[JavaScript]map取代push取得Json裡的資料問題紀錄

map取代push實例

今天跟一起寫code的群組討論到JS世界裡盡量不要去使用直接改變變數的function,例如這邊的push,雖然我還不太懂切確的觀念是什麼不過還是分享一下朋友教的寫法,這種方法似乎比較精簡也直觀。

先紀錄我原本的寫法,在接取api的資料經常會碰到這種Json格式,我想要取得每個物件的name:

var apiArray = [
{
    name: 'Kurt',
    age: 25
},
{
    name: 'Andy',
    age: 40
},
{
    name: 'Maggie',
    age: 20
},
{
    name: 'Mary',
    age: 35
}]; 
var nameArray = [];
for (var key in apiArray) {
    nameArray.push(apiArray[key].name);
}
console.log(nameArray); //["Kurt", "Andy", "Maggie", "Mary"]

朋友教我使用map去擷取:

var apiArray = [
{
    name: 'Kurt',
    age: 25
},
{
    name: 'Andy',
    age: 40
},
{
    name: 'Maggie',
    age: 20
},
{
    name: 'Mary',
    age: 35
}]; 
var nameArray = apiArray.map(function(obj){
    return obj.name;
});
console.log(nameArray); //["Kurt", "Andy", "Maggie", "Mary"]

兩種方法在這種小地方或許看不出來,但就直觀維護上這種方法看到return obj.name就大略知道在做什麼事情了。

[JavaScript] split 分割字串

split(分割字串)

Syntax(語法):

str.split([separator[, limit]]);

參考文章:Mozilla Developer Network(MDN)

字串分割完會變成陣列

直接看範例:

var stringToSplit = 'apple and banana are my favorite fruits.';
var arrayAfterSplit = stringToSplit.split(' ');
console.log(arrayAfterSplit); //["apple", "and", "banana", "are", "my", "favorite", "fruits."]

這時候要取得哪一個想要的字串只需要使用separator[index]就行囉!

當然我們可以分割再分割

var stringToSplit = "?id=12345678&passwd=00000000";
//在這裡我只要12345678這個字串時要做兩次分割

var arrayAfterSplit = stringToSplit.split('=');
console.log(arrayAfterSplit); //["?id", "12345678&passwd", "00000000"]

//這時候做第二次切割

var theIdNumber = arrayAfterSplit[1].split('&')[0];
console.log(theIdNumber); //"12345678"

選擇切出幾塊字串

使用方法:
split(separator, number);
直接看範例:

var stringToSplit = 'apple and banana are my favorite fruits.';
var arrayAfterSplit = stringToSplit.split(' ', 3); //只取三塊

console.log(arrayAfterSplit); //["apple", "and", "banana"]

搭配.join()更換字元

在MDN的範例裡面我發現有趣的東西是搭配.join()可以做到更換字元的效果:

var stringToSplit = 'apple and banana are my favorite fruits.';
var arrayAfterSplit = stringToSplit.split(' ').join('/');
console.log(arrayAfterSplit); //"apple/and/banana/are/my/favorite/fruits."

要注意這裡console.log出來的不是陣列又變回字串了!
join裡的東西會自動填入剛剛split的切割位置。

小記

會遇到這個問題是因為我遇到要利用網址(URL)取得使用者的id,這樣讓使用者在點進去網址的時候可以利用這個id得到他的資料,所以會搭配到var currentLocation = window.location;這個方法,例如網址為:
https://somecompany.com/somepage?id=123456
此時一進去這個連結我要用123456這個id去接取api初始化屬於該使用者的頁面資料:

var currentLocation = window.location;
console.log(currentLocation); //https://somecompany.com/somepage?id=123456

var arrayAfterSplit = stringToSplit.split('='); 
console.log(arrayAfterSplit[1]); //"123456"

這樣就可以取得id囉,當然window.location取得的狀況有很多種所以一開始一定要先console.log下來看一下。

HTML Email(電子郵件內網頁) 問題紀錄

麻煩的outlook電子郵件網頁

上一篇文章後續還是踩到了一些雷,再來紀錄一下。

line-height

上篇文章有提到這個屬性還被大多數瀏覽器和信箱支持,但在用程式開啟的outlook裡面它不是不支持,而是如果寫在<table>這個tag裡的話他不支持(囧)。

也就是說瀏覽器打開的話下面例子是ok的:

<table style="line-height:20px;">
    <tr>
        <td>element</td>
        <td>element</td>
    </tr>
</table>

但在程式打開的outlook不支持寫在<table>裡所以我們要改寫成:

<table>
    <tr>
        <td style="line-height:10px;">element</td>
        <td style="line-height:10px;">element</td>
    </tr>
</table>

可不可以寫在<tr>上我還沒測試過,因為每一次測試都是要從主管那更新所以我不好意思一直測試XD,再來在同一個<tr>的tag裡面是否只需要寫一個<\td>就好也不得知,總之照著個方式寫是ok的哦!

超連結<a>的文字顏色

如果想要改變點下超連結之後的顏色,也就是做到Visited的動作以前我們可以用選擇器來辦到:

.somelink:visited {
    color: #fff;
}

但是inline style卻沒有這種寫法,我們只能在tag裡面使用!important強制讓他一直維持一種顏色:

<a style="text-decoration:none; color: #fff !important;" href="#">element</a>

參考這篇Stack overflow

當然在遊覽器上看都沒問題,只不過問題又出在程式上開啟的outlook....,我用線上產生的html可行(國外有網站是可以線上排版後幫你產生html)但自己做的html卻失敗,於是我直接把按鈕做成一個圖片檔放上去了。

總之最後終於把html email告一段落了~

HTML Email(電子郵件內網頁)

HTML Email

這陣子第一次碰到要做一個可以當Email發送的HTML檔案,感覺有中文解說的網站不多(也許是我關鍵字下得不好),總之如果打HTML Email是可以找尋到國外不少資源,再來介紹我當中遇到的每個地雷。

完全使用inline style控制style

第一次遇到這個工作時我天真的以為不就跟平常瀏覽器用的HTML一樣把HTML和CSS做分離,設計師還出圖的很簡單應該一下做完了。

沒錯是一下就做完了,但是完全不能使用!!!

因為在每個個大郵件他們都有自己的CSS,所以會把你傳送檔案裡有CSS的屬性大多都會擋掉,所以要考慮各大瀏覽器的相容度之外,每個郵件的相容度是不一樣的(gmail, outlook打開的效果不一樣),所以要回歸最原始最基本的做法:

<div style="width: 100px;height: 100px;border: 1px solid black;"></div>

以上就是inline style的寫法,記得完全避諱使用class,雖然網路上有些人似乎有成功使用選擇器去input(就是寫class的做法),但我自己試過幾個是失敗的。

盡量完全使用table

為什麼要用table呢?因為在email中很多的CSS屬性是不相容的,像是position, float等竟然不能使用啊!變成說我們的切版只能實實在在地用table硬刻出來了,雖然我們的padding, margin在大部分的郵件還是有效的,但如果是要寄給outlook的郵件就不建議使用了!待會會解釋。

特殊的形狀一律使用圖片取代

什麼意思呢?
因為我們的border-radius, rotate等等也都不太能使用了,所以有什麼特殊的圖形盡量上傳到網路上用<img src="#">這個tag去實現吧!

重新認識基本的table屬性

雖然table可以稍微切版,形狀可以直接使用圖片,但平常我們要把東西調精準的話table一定不夠啊!一定要搭配margin和padding甚至position等等,為什麼不能使用呢?

剛剛提過position是完全不用考慮了,但如果要寄給outlook的話margin和padding也是不建議的哦!那怎麼辦?我們還有原始的table屬性可以使用!

  • cellpadding
  • cellspacing
  • border
  • line-height
  • align
  • valign
  • colspan 這幾個原生屬性要好好利用哦,可以把內文位置再加以調整的工具不多了啊! 所以說HTML Email的版面也不要太複雜了

大部分前四個屬性我都會直接灌在table上面了

<table style="width: 100%;font-size:14px;line-height:30px;" cellpadding="0" cellspacing="0" border="0">
</table>

再搭配chrome的開發者工具就很好先做初始調整了。

非瀏覽器開啟的outlook不吃<div>這個tag

非瀏覽器開啟的outlook不吃<div>這個tag
非瀏覽器開啟的outlook不吃<div>這個tag
非瀏覽器開啟的outlook不吃<div>這個tag
這個太哭夭了我要講三遍,如果有在用公司郵件的大多都會接觸到這個工具,就是outlook不一定在瀏覽器上開啟,他本身就有一個程式是打開郵件的,這個程式不吃<div>這個tag!!!
也就是說在<div>裡面加上的style會完全忽略!千萬要小心!

總結

所以如果要做大部份郵件、瀏覽器甚至是程式打開的outlook都正常的HTML Email,照著上面的步驟應該就不會出太大的問題摟!

至於有沒有更多的屬性可以用或更好的做法那肯定是有的,只是我就沒再多做研究下去囉!這是我第一次遇到的HTML Email功課,希望能幫大家能避開一些地雷。XD

還有續集~請點我看文章

3/22補充:感謝FB上Front-End Developers Taiwan社團有人分享的HTML Email適應表網站

[Angular-1]ng-class問題紀錄1

ng-class
這次我遇到的情況是想再controller控制一個變數,讓ng-class去判斷這個變數的內容改變他的CSS,但是是用Jquery的Listener去觸發。

先參考一些我在網路上查到的用法:
Angular官方網站
Day22- 入門AngularJS筆記-AngularJS指令(19) ng-class

第一件事情是我想說ng-class如果成立的話能否直接蓋掉原本本的class:
設定html

<table>
  <tr>
    <td class="inputTd" ng-class="{'InputTooShort': tableInputTooShort}">
        <input id="userInput" model="tableInput" />
    <td>
  </tr>
</table>

設定JS

$scope.tableInputTooShort = false;
$('#userInput').bind('focusout', function ($scope) {
    if(tableInput.length < 3) {
        $scope.tableInputTooShort = true;
    }else {
        $scope.tableInputTooShort = true;
    }
});

設定CSS

.inputTd {
   border: 1px solid #999;
}
.InputTooShort {
    border: 2px solid red !important;
}

此時出現很神奇的Bug,每當我輸入的字串小於三個字元並且滑鼠點出input去觸發他的focusout,$scope.tableInputTooShort這個變數會變成true沒錯,但是這個tag的class並沒有更新,反而是我再點入input輸入格隨意輸入換刪除一個字元他的class才會更新為InputTooShort這個CSS,反之,當他被InputTooShort這個CSS更新後我把字元輸入到三個以上後點出input讓focusout把$scope.tableInputTooShort這個變數會變成false時class依然沒有更新,也是要再我重新點回input刪除或輸入任意字元才會更新為inputTd,但這不是我要的效果,我希望的是觸發focusout之後,的CSS就應該要更新了。

起初以為是判斷式的關係,但我試了很多判斷式還是都一樣,目前功力太淺也還找不出原因,只好再直接求助Angular的驗證式:
設定html

<table ng-form="form">
  <tr>
    <td class="inputTd" ng-class="form.pathDepartAddr$error.minlength ? 'InputTooShort' : 'inputTd'">
      <input id="userInput" model="tableInput"
      name="pathDepartAddr"
      ng-minlength="3" />
    <td>
  </tr>
</table>

其實這樣就直接也省下JS的程式碼了,雖然是成功有效果但我最初的希望會是點出格子外後才觸發更新CSS,但如果使用這個方法的話會比較像onchange一樣的效果,只要輸入或刪除任意字元就會一直觸發和刷新這個CSS。

form.pathDepartAddr$error.minlength可以參考我之前文章的解釋,值得注意的是雖然在input裡面我是寫ng-minlength="3",但是在ng-class裡面只有寫minlength不用加上ng-這串。

[JavaScript]淺談this

這幾天從研究apply和call之類的函示,突然發現JavaScript的觀念差得可以,建構子、this等等方法十分陌生,這些東西在我工作其實使用的場合真的很少,加上現在框架和語法糖的發展讓很多事情語意化的很理所當然,但我認為站在前端的場合上面還是要多懂得一些JavaScript的精神和觀念。

這篇主要討論基本的this,建議可以先了解我前一篇的文章初探建構子,雖然不懂也沒關係,但他們確實是息息相關。

this指向於調用該函式之物件

這個經常看到卻又很模糊的東西是什麼呢?
有的人說是執行『此次』時的屬性,有人說他像免洗餐具每次都會像是重新使用,第二次使用的人會是拿到一副新碗筷跟上次使用的人是完全不一樣的東西,網路上我有找到一篇解釋得蠻好的文章。

他解釋為:this指向於調用該函式之物件

簡單的公式就是物件.函式(),此函式裡有我們自創的this。
使用以上公式觀察下面例子:

var singer = {
    words: '摩擦!摩擦!',
    say: function(){ console.log(this.words); }
};
singer.say();  //"摩擦!摩擦!"


var singer = {
    words: '似魔鬼的步伐',
    say: function(){ console.log(this.words); }
};
singer.say();  //"似魔鬼的步伐"

所以函示接在哪個物件的後面this就是指向該物件的內容囉!!

這邊菜鳥提醒一下this一定是在『方法』裡面,我之前實在對類別和方法的用法感到很困惑,沒想到還是工作兩個月後才有顯著的理解XD,詳情可以參考上一篇初探建構子

再來當函式前面沒有接物件的話,this會指向全域物件
像這樣子獨立出現:函式

var words = '原來你是我最想留住的幸運';
var sing = function () {
    console.log(this.words);
}
sing();  //'原來你是我最想留住的幸運'

當sing()這個函式前面沒有接著物件的話程式會判斷是接取最外面的東西。

接下來比較常見的小問題

var words = '你存在我深深的腦海裡';
var obj = {
    words: '我心裡有針要喊煞嘸聲',
    sing: function(){
        console.log(this.words);
        var sing = function(){
          console.log(this.words);
        }
        sing(); //'你存在我深深的腦海裡'

    }
};
obj.sing();  //'我心裡有針要喊煞嘸聲'

主要都是看接什麼物件而唱出什麼歌詞,那有一個有趣的玩法可以讓this保留下來。

延續上面的例子:

var words = '你存在我深深的腦海裡';
var obj = {
    words: '我心裡有針要喊煞嘸聲',
    sing: function(){
        console.log(this.words);
        var that = this;  //我把這個this存到變數that裡面了!

        console.log(that);  //出現完整的obj物件

        var sing = function(){
          console.log(that.words);  //這裡的that帶著

        }
        sing(); //'我心裡有針要喊煞嘸聲'

    }
};
obj.sing();  //'我心裡有針要喊煞嘸聲'

JavaScript有個有趣的小地方是存到變數that的那行程式碼裡的this,會是指向本身物件的this唷!
所以再來我使用它的時候他會是指向obj這個物件的。
下面的那行console.log也可以顯示出這個this是指哪個物件。

參考文章:#Javascript:this用法整理
我只是用比較有趣的例子敘述XD。

[JavaScript]初探建構子(Constructor)

學JS這麼久了一直對建構子的觀念很模糊,剛好前陣子尋找技術文章又有提到,自己再來深入了解終於比較理解了,網路上很許多非常好的解釋,但為了防範老人痴呆自己也想來下手寫一篇分享。

MDN的介紹就已經非常不錯,趕時間的直接參考這篇吧XD。

在原生的JS世界,我們經常創造很多物件,即使是超級簡單的:

var Person = {
    name: 'Kurt',
    age: 18,
    skill: 'Keep cool'
}
console.log(Person);  //print出Person這個東西骨子裡到底裝了些什麼

這樣我定義了一個Person名叫Kurt有年齡和一個可以裝酷的技能,但是我想做二十個人組成一個棒球隊,我就必須宣告二十次這種物件,那有沒有更好的方法呢?

我們請小叮噹幫我們做出一個人類製造機吧!!

function makePerson (name) {
    console.log(name + '出生惹!');
}

var Kurt = new makePerson ('Kurt');  //Kurt出生惹!

var Maggie = new makePerson ('Maggie');  //Maggie出生惹!

console.log(Kurt);  //Object {}

console.log(Maggie);  //Object {}

我做了一個人類製造機(function)叫makePerson,這個就是大家所謂的『類別』,他可以拿來製造真實的人類(先不要討論Kurt也可以是一隻狗的名字,這樣我會很困擾)。
但是!!這個人類製造機(function)並不是一個實體的人類(物件)唷!!有注意到我在使用這個人類製造機的時候前面加了new嗎?這時候的Kurt才是一個真正的人類(物件),你才可以對他做修改,賦予他彩色或是黑白的人生,因為到目前為止他是一個什麼都沒有的人類(全空的物件),最後兩行console後print出來的結果是Object {}。

好,身為一個良好的棒球隊要年齡適中,各有各的特長使之各司其職,所以我們要來給我們製造出來的人類(物件)一些特長了(屬性)。

我們針對Kurt延續程式碼:

function makePerson (name) {
    console.log(name + '出生惹!');
}

var Player1 = new makePerson ('Player1');  //Kurt出生惹!

Kurt.name = 'Kurt';
Kurt.age = 18;
Kurt.skill = 'keep cool';
console.log(Player1);  //Object {age: 18, name: "Kurt", skill: "keep cool"}

這邊可以看到我先製造Player1的人類(物件),我後天訓練讓大家要叫他Kurt(name),給了他現在很適合打棒球的18歲年齡(age),還有讓他在球場上一直保持冷靜的技能(skill),剛剛後天訓練的東西我們稱之為『屬性』

可是這邊有個問題,慣老闆不會喜歡我們花這麼多力氣去後天訓練這些球員(每個物件都要一個一個去定義是很麻煩的事情),我們希望他一加入棒球隊就是個適合打棒球的人,那最棒的事情就是他打從娘胎出來就會打棒球了,沒錯,慣老闆就是這麼任性。

所以我們要改良人類製造機,讓一出廠的人類就有他的名字,年齡和技能,於是乎....:

function makePerson (name, age, skill) {
    this.name = name;
    this.age = age;
    this.skill = skill;
}

var Player1 = new makePerson ('Kurt', 18, 'Keep cool');
console.log(Player1);  //Object {age: 18, name: "Kurt", skill: "keep cool"}

新型的人類製造機如上,只要我們製造(new)人類(物件)的時候把後面的參數填正確位置,一出生的人類馬上就可以上場打棒球囉!

好,現在你可以先製造個二十位未成年少女組成一個棒球隊了?

言歸正傳,慣老闆覺得這樣可以直接製作適合打棒球的人還不夠有競爭力,所以他希望從第一棒到第九棒,救援投手到候補球員,甚至是打掃棒球茶水間的大嬸都有擊出全壘打的能力,畢竟還沒做到這一步之前球隊都是有進步空間的,阿只要球隊還有進步空間在慣老闆的眼裡都是一隻還不夠有競爭力的球隊,所以我們要想個『方法』。

再延續之前的程式碼:

function makePerson (name, age, skill) {
    this.name = name;
    this.age = age;
    this.skill = skill;
}

makePerson.prototype.yesBoss = function() {
    console.log('擊出全壘打,得分!');
};

var Player1 = new makePerson ('Kurt', 18, 'Keep cool');
Player1.yesBoss();  //擊出全壘打,得分!

console.log(Player1);  
/*Object {
  age: 18,
  name: "Kurt",
  skill: "Keep cool",
  yesBoss: function () {
        console.log('擊出全壘打\uFF0C得分\uFF01');
    }
}*/

撰寫新的程式碼,在人類製造機(類別)後面加上.prototype就可以打造製造機專屬的『方法』,方法的名稱也是自己定義的,在這邊我取名為yesBoss(是的老闆)。

只要以後由這個人類製造機製造出來的人類使用這個方法就可以打出全壘打了,但一定要是此製造機(類別)製造出來的人類(物件)唷!

接下來只要慣老闆不斷的使用yesBoss就可以讓自己旗下的未成年少女和茶水間大嬸得分到對手不要不要的,每場屌打對手二十幾分,金錢,名聲,地位和權利全部都接收,那這些肯定都是慣老闆的功勞啊!!

[Angular-1]ng-key鍵盤事件

今天想要做一個按下Enter就可以執行Submit的事件,最常見到的地方就是登入的時候,我們帥氣快速的打完帳號密碼一定會Combo接Enter鍵登入吧!其實這是JS的事件唷!

沒想到這麼簡單的東西我會卡了四個小時,滿滿的大心得記錄一下吧XD。

原生Javascript的onkey事件

JS的原生事件有三種:
onkeyup:釋放鍵盤觸發
onkeydown:按下鍵盤觸發
onkeypress:按下鍵盤後釋放觸發

我並沒有很深入研究使用情況,我在想onkeydown和onkeypress使用場合在一次要按多顆鍵(onkeydown)或者是單顆鍵(onkeypress),今天主要用登入表單的例子示範最基本的實作就好。

index.html
<form action="#" method="post">
    請輸入帳號<input type="text" name="username" onkeypress="goLogin(evt);">
    請輸入密碼<input type="text" name="password" onkeypress="goLogin(evt);">
    <input type="submit" value="登入">
</form>

以上就是最簡單的登入表格囉,並且我直接在input裡面加入inline function,也就是說當使用者游標正在那兩個input裡面的時候只要按下鍵盤再放開會一直不斷執行goLogin()這個function,然後千萬不要忘記要給他一個變數讓等等的JS去判斷我們按下什麼鍵。

app.js
function (evt) {
    if (evt.keyCode == 13) {
        dosomething...
    }
};

JS的function裡面要給他一個變數讓外部的直帶進去,而keyCode則是用onkeypress產生出來的東西的原生屬性,Enter鍵的這個值會是13,鍵盤對應表在網路上有很多資源,例如這篇

onkeypress當然也可以從外部呼叫,例如我在JS做一個事件:

app.js
var userinput = document.GetElementById("username");
userinput.onkeypress = function (evt) {
    dosomething...
};

AngularJs的onkey事件

AngularJs的方法其實大同小異,只是官網寫的三種教學竟然不一致讓我少看最重要的那一篇,他把我最想知道的用法寫在ng-keyup而已太扯了。

總之剛剛上面原生講的三種事件換寫為下面三種:
onkeyupng-keyup
onkeydownng-keydown
onkeypressng-keypress

再來直接用剛剛基本的登入頁面做示範:

index.html
<form>
    請輸入帳號<input type="text" ng-model="count.username" onkeypress="goLogin($event);">
    請輸入密碼<input type="text" ng-model="count.password" onkeypress="goLogin($event);">
    <input type="submit" value="登入">
</form>

而JS裡面則差不多一樣

app.js
$scope.goLogin = function (keyValue) {
    if (keyValue.keyCode == 13) {
        dosomething...
    }
};

Angular的ng-model方便之處在這邊就不多談,最重要要注意的是goLogin(\$event)我裡面待的變數是Angular原生的$event唷!!!!!!!!!

總之他們兩個一定要搭配就是了,而鍵盤的直也一樣用keyCode就叫得出來囉!

雖然這其實有人帶的話簡單的要命,但有時候真的鬼打牆卡住就真的是卡很久XD,今天真的是有撞牆到啦,但搞定就是很開心!

[RegExp]正則表示式

會接觸正則表達式(RegExp)是因為前一篇的文章ng-pattern,但正則似乎是所有語言通用的,所以學起來絕對不吃虧。

網路上有太多太多的資源可以查詢了,我也比較會用基本的數字判斷而已,所以這篇主要分享我學習上的一些小地雷觀念。

一次只能設定一個字

一次只能設定一個字

一次只能設定一個字

為什麼重複三次標題,因為這是我踩的一個很大的雷,網路上有很多資源,其中我的需求是要限制一個範圍的數字,例如只能輸入0~1500之間的數字,這時候其中一個網站給我一個很猛的寫法是^[0-1500]$,我在那邊試老半天一值給我很奇怪的數字範圍。

後來很不爽直接關鍵字全打英文想找國外的說明,發現有個頗棒的外文網站解釋得真的很好,參考此連結,老實說我覺得英文的資源說明真的比較明白,中文的資源真的沒有在解釋比較完整的觀念。

大中小括號各司其職{}[]()

首先在JS的正則會用兩條斜線包起來,像這樣/Some RegExp/,而想要限制什麼樣的文字照著打即可(例如/9453/,/helloworld/,/taiwanNo1),RegExp是很精明的所以大小寫全形半形都不可以不同。

中括號[]--一個單字的象徵

但我們不可能像上面的例子量身定做,我們需要一個單字的範圍值,例如我要單個任意數字,這邊的單個只的真的是一個數字,不能是0.1或01這種有單個以上的數字,是最基本的0,1,2,3,4,5,6,7,8,9,這時候我們要的那個單字範圍是0~9,在正則的規則裡面我們可以用最基本的^[0-9]$表達,注意中間是-哦。

那英文怎麼辦?英文也可以用範圍來表示,順序為字母序有分大小寫
例如[a-z]為可以輸入小寫a~z任一個字母,而[A-Z]則是可以輸入大寫,那如果想要大小寫都可以呢?
[a-zA-Z]可以表達出來,中間不用加任何符號,因為-只會認左右邊的第一個單字!!所以如果不小心寫錯如[aA-Z]他只會認得A~Z這個範圍哦!

所以最基本範圍是任意大小寫英文和數字的單字表達為[a-zA-Z0-9],這樣我們知道中括號是做什麼事情的囉!

大括號{}--象徵必須使用次數

大括號是緊緊黏在一個單字後面的,他做的事情例如{m,n}代表的是使用最少m次最多n次,看幾個最簡單的範例:
^[a-z]{1,5}$
a~z任意單字出現一到五次。
符合的有:apple,cat,dog
不符合的:Dog,and1,hellowworld,0
^B[0-9]{5}$
一個B後面接任意數字五個。
符合的有:B12345,B12,B999
不符合的:C12345,12345,BB123
^0{3}AC{1,}$
三個0一個A和一到無限次的C
符合的有:000AC,000ACCCCCCCCCCC
不符合的:111AC,000A,000C,000ACC
^7{,3}$
最多三個7
符合的有:7,77,777
不符合的:07,7777,a7

大括號的工作就是限制次數囉!

小括號()--合併為一個敘述

跟數學運算符號一樣用法,就是先執行括號內的東西,小括號也經常跟tube|搭配在一起,用一個簡單的例子:
^([a-z]|[0-9]){1,3}[A-Z]{,3}$
小括號內先執行,所以是任意單字a~z或者任意數字0~9,兩個其中一個出現一到三次,緊接著出現三次以內的大寫英文單字A~Z。

綜合三大括號我們再舉一個例子:
^([A-Z][a-z]{,10})|(09[0-9]{8})$
看出來了嗎?請填寫英文名字或者手機號碼,因為我的設定為開頭為一個大寫英文字母後面緊接著最多十個的小寫字母或者開頭為09後面緊接著八次任意數字。

但這有個弊案,會不會有人的英文名字真的只有一個大寫字母?抑或者名字真的超過十一個字母單字?這時候我們就可以用符號來表示了!

常用符號^$?*+

要維持著正則的穩定性,一定要加上最常用的^符號,^緊接著一個單字代表開頭,一個單字後面緊接著$代表結尾,直接看例子:
^[a-z]331$
代表開頭一個小寫a~z的單字後面接33並最後是接1,但為什麼還要特別指定開頭和尾巴?

正則是可以去匹配一整篇文章(例如新聞)的方式,不斷重複尋找符合條件的單字,所以如果再使用者輸入的欄位不加上^和$只要中間有夾雜著符合條件的單字也許是可以輸入的上去的哦!不過這邊我是沒驗證過XD。

也就是說如果單純[a-z]331的話a331也符合bbba33111也會有符合條件,所以在製作給使用者的欄位最好是嚴謹一點,多加點符號吧!

其他的常用符號?*+都是緊接在單字後面
?代表需要出現零次會一次
*代表需要出現零次或無限次
+代表需要出現一次或者無限次
這些東西都可以在網路上輕易找到,可以參考這篇

其他跳脫符號的使用方法就不在贅述了,懂得剛剛說的觀念其實要學習正則表示式不會是很困難的事情囉!

[Angular-1]自製驗證式ng-pattern

其實Angular的其中一個精華是已經可以在HTML裡面做很多事情和判斷,也就是說Angular可以寫到幾乎已經不用寫太多JS了,但這是一個雙面刃,畢竟JS是前端很重要的命根之一。

或說回來,Angular在製作表單可以把引導性做的很高,立即的判斷該欄位是否是正確的輸入值(例如電子信箱不會有中文字),許多內建基本的驗證式(例如信箱格式,文字長短等等)上網都可以輕鬆找尋到就不多介紹。

這次的主題是可以自定義條件的ng-pattern,那想要善用ng-pattern就不得不學習一下燒翻腦袋的正則表示式(RegExp)啦!正則表示式就請參考我的另外一篇文章囉!

ng-pattern的用法

先來討論ng-pattern使用方式,最基本的使用方式是把他放入一個input的tag裡面,其實就跟表達式(ng-show等等)的方法一樣,但只有他單獨出現的話是沒有意義的,簡單的例子如下:

<div ng-form name="demoform">
    <input type="text"
    name="identify"
    placeholder="請輸入身分證"
    class="style"
    ng-model="user.identify"
    ng-pattern="/[A-Z][0-9]{9}/" />
    <span ng-show="demoform.identify.$error.pattern">輸入的格式不正確</span>
</div> 

第一個規則是驗證式(如這次的例子ng-pattern)都需要被包在form的tag裡面喔!

Angular有自己的ng-form,與原生的HTML的form差異在哪這邊不多做探討,總之直接用一套Angular的表達式也比較有優點,不要忘記幫ng-form取上名字name="demoform"

input的原聲屬性全部都可以使用,ng-model是Angular處理資歷的表達式不多做探討,ng-pattern為驗證式,當然不能忘記要幫他取名子name="identify"

再來先不要探討ng-pattern裡面的東西,ng-pattern本身是驗證式,所以當使用者輸入的欄位不符合我自訂的條件(/[A-Z][0-9]{9}/)的話會激活一個內建$error的屬性,所以我span的表達式ng-show會為true而顯示

這裡可以很語意化的看成表單(demoform)的(.)某個input(identify)的(.)錯誤($error)的(.)某個驗證式(pattern)為真,所以span這個tag就會出現輸入的格式不正確這行字。

這就是驗證式基本的用法,當然可以配上CSS和其他手法玩得讓表單更有引導性,但這裡就不在深入討論了,至於基本的驗證式介紹也可以直接參考Angular的官方網站

ng-pattern可以外部帶入

直接看範例:

index.html
<input type="text"
    name="identify"
    placeholder="請輸入身分證"
    class="style"
    ng-model="user.identify"
    ng-pattern="identifyRegExp" />
app.js
angular.module('app',[])
    .controller('contrl',[finction(){
        this.identifyRegExp = /[A-Z][0-9]{9}/;
    }])

當然也可以自己製作一些function讓他動態產生,這裡就不多討論了,接下來正則表示式就請參考我的另外一篇文章囉!