第7章 jQuery插件的使用和寫法


第7章 jQuery插件的使用和寫法

插件又稱擴展,是一種遵循一定規范的應用程序接口寫出來的程序。
插件的編寫思想基於面向對象。

獲取最新的插件可以查看jquery官網:http://plugins.jquery.com/
本章將從幾個基本的例子來介紹jquery插件的使用。


一. 表單驗證插件Validation

jquery最常用的場合就是表單驗證。Validation則是歷史最悠久的jquery插件之一。分為內置驗證規則,和自定義驗證規則。信息提示明確——可以通過keyUp,focus等方式完成實時驗證。
本筆記跟隨原書采用Validation 1.9版

1.快速上手

Validation基本規則如下:(相關內容可通過ctrl+F查找源文件得到)

資料來源:</http://www.cnblogs.com/si-shaohua/p/3760286.html>

# 語句表述
校驗規則
1 required:true
必輸字段
2 remote:"check.php"
使用ajax方法調用check.php驗證輸入值
3 email:true
必須輸入正確格式的電子郵件
4 url:true
必須輸入正確格式的網址
5 date:true
必須輸入正確格式的日期 日期校驗ie6出錯,慎用
6 dateISO:true
必須輸入正確格式的日期(ISO),例如:2009-06-23,1998/01/22 只驗證格式,不驗證有效性
7 number:true
必須輸入合法的數字(負數,小數)
8 digits:true
必須輸入整數
9 creditcard:
必須輸入合法的信用卡號
10 equalTo:"#field"
輸入值必須和#field相同
11 accept:
輸入擁有合法后綴名的字符串(上傳文件的后綴)
12 maxlength:5
輸入長度最多是5的字符串(漢字算一個字符)
13 minlength:10
輸入長度最小是10的字符串(漢字算一個字符)
14 rangelength:[5,10]
輸入長度必須介於 5 和 10 之間的字符串")(漢字算一個字符)
15 range:[5,10]
輸入值必須介於 5 和 10 之間
16 max:5
輸入值不能大於5
17 min:10
輸入值不能小於10

【例7.1】

制作一個表單,包括用戶名,郵箱,網址(非必填),和評論。要求能夠輸入驗證。
思路:

(1)對於姓名一欄中長度至少為2位(minlength="2"
(2)電子郵件一欄需要加上.email
(3)網址加上.url
(4)對於必填字段全部加上class="required";

html

    <form class="cxmform" id="commentForm" method="get" action="#">
        <fieldset>
            <lengend>一個簡單帶驗證提示的評論</lengend>
            <p>
                <label for="cursername">Name</label><em>*</em>
                <input type="text" id="cuesername" name="username" size="25" class="required" minlength="2">
            </p>
            <p>
                <label for="cemail">Email</label><em>*</em>
                <input type="text" id="cemail" name="email" size="25" class="required email">
            </p>
            <p>
                <label for="curl">WebCite</label><em>&nbsp;&nbsp;</em>
                <input type="text" id="curl" name="url" size="25" class="url">
            </p>
            <p>
                <label for="ccomment">Comment</label><em>*</em>
                <textarea id="ccomment" name="comment" cols="22" class="required"></textarea>
            </p>
            <p>
                <input type="submit" value="Submit" class="submit">
            </p>
        </fieldset>
    </form>

補充css樣式(對功能無影響)

* { font-family: Verdana; font-size: 96%; }
label { width: 10em; float: left; }
label.error { float: none; color: red; padding-left: .5em; vertical-align: top; }
p { clear: both; }
.submit { margin-left: 12em; }
em { font-weight: bold; padding-right: 1em; vertical-align: top; }

最后還不要忘記對插件庫的調用,

<script type="text/javascript" src="js/jquery.validate.js"></script>

jq調用

$(document).ready(function(){
    $("#commentForm").validate();
});

效果如下:

【初步小結插件的使用方法】
(1)引入插件
(2)確定需求:哪些需要用才加
(3)指定驗證規則。
(4)如果我們想漢化這個插件,只需要修改插件中的message消息(注意和驗證規則對應):

jQuery.extend(jQuery.validator.messages, {
  required: "必選字段",
  remote: "請修正該字段",
  email: "請輸入正確格式的電子郵件",
  url: "請輸入合法的網址",
  date: "請輸入合法的日期",
  dateISO: "請輸入合法的日期 (ISO).",
  number: "請輸入合法的數字",
  digits: "只能輸入整數",
  creditcard: "請輸入合法的信用卡號",
  equalTo: "請再次輸入相同的值",
  accept: "請輸入擁有合法后綴名的字符串",
  maxlength: jQuery.validator.format("請輸入一個 長度最多是 {0} 的字符串"),
  minlength: jQuery.validator.format("請輸入一個 長度最少是 {0} 的字符串"),
  rangelength: jQuery.validator.format("請輸入 一個長度介於 {0} 和 {1} 之間的字符串"),
  range: jQuery.validator.format("請輸入一個介於 {0} 和 {1} 之間的值"),
  max: jQuery.validator.format("請輸入一個最大為{0} 的值"),
  min: jQuery.validator.format("請輸入一個最小為{0} 的值")
});

2.改進

上面的例子對於最短字段采用了minlength="2"這樣的屬性方法。而對開發者來說最友好的事情,應該是把所有的驗證規則要么全放class要么全放屬性中。

(1)再引一個插件——jquery.metadata.js

(從這個插件能查到的資料來看,大多數都是和表單驗證一起用)

(2)改變jq的調用方法:
$(document).ready(function(){
    $("#commentForm").validate({meta:'validate'});
});
(3)驗證規則全部寫到class屬性里去!

比如說:
class="required" minlength="2"寫成:class="{validate:{required:true,minlength:2}}".只要是插件相關的,全部改成復合對象的形式:

    <form class="cxmform" id="commentForm" method="get" action="#">
        <fieldset>
            <lengend>一個簡單帶驗證提示的評論</lengend>
            <p>
                <label for="cursername">Name</label><em>*</em>
                <input type="text" id="cuesername" name="username" size="25" class="{validate:{required:true,minlength:2}}">
            </p>
            <p>
                <label for="cemail">Email</label><em>*</em>
                <input type="text" id="cemail" name="email" size="25" class="{validate:{required:true, email:true}}">
            </p>
            <p>
                <label for="curl">WebCite</label><em>&nbsp;&nbsp;</em>
                <input type="text" id="curl" name="url" size="25" class="{validate:{url:true}}">
            </p>
            <p>
                <label for="ccomment">Comment</label><em>*</em>
                <textarea id="ccomment" name="comment" cols="22" class="{validate:{required:true}}"></textarea>
            </p>
            <p>
                <input type="submit" value="Submit" class="submit">
            </p>
        </fieldset>
    </form>

效果和之前完全一致。

3.改進(第二種):通過name來驗證

鍵入繁瑣的class是多數人不喜歡的。下面從js層面研究如何實現一樣的效果。把class都刪了:

$(function(){
    $('#commentForm).validate({
        rules:{//定義rules屬性
            username:{//通過name來匹配驗證屬性規則
                required:true;
                minlength:2;
            },email{
                required:true;
                email:true;
            },url:"url",
            comment:required;
        }
    })
})

4.自定義插件

(1)更推薦的方法

除了從源碼上漢化之外,更推薦在調用class時完成一整套規則。比如姓名驗證一欄中,class改寫為:

class="{validate:{required:true,minlength:2,messages:{required:'請輸入姓名',minlength:'請至少輸入兩個字符'}}}"
(2)如果需要在驗證信息中添加圖片

在js文件中鍵入代碼:

  $(document).ready(function(){

    $("#commentForm").validate({
        rules: {
            username: {
                required: true,
                minlength: 2
            },
            email: {
                required: true,
                email: true
            },
            url:"url",
            comment: "required"
        },
        
        messages: {
            username: {
                required: '請輸入姓名',
                minlength: '請至少輸入兩個字符'
            },
            email: {
                required: '請輸入電子郵件',
                email: '請檢查電子郵件的格式'
            },
            url: '請檢查網址的格式',
            comment: '請輸入您的評論'
        },  
        
        errorElement: "em", //可以用其他標簽,記住把樣式也對應修改
        success: function(label) {
            //label指向上面那個錯誤提示信息標簽em
            label.text(" ")             //清空錯誤提示消息
                .addClass("success");   //加上自定義的success類
        }

      });

  });

同時在css中追加樣式:

em.error {
  background:url("../images/unchecked.gif") no-repeat 0px 0px;
  padding-left: 16px;
}
em.success {
  background:url("../images/checked.gif") no-repeat 0px 0px;
  padding-left: 16px;
}

效果圖:

(3)規則的自定義

評論功能還有一個重要部分是驗證碼,驗證碼通常有后台生成,在這里直接模擬。
在html的表現是:

<p>
    <label for="cvalcode">驗證碼</label>
    <input id="cvalcode" name="valcode" size="25"  value="" />=1+1
</p>

$("#commentForm").validate()方法上面定義驗證規則:
使用 $.validator.addMethod('方法名',function(值,對象,param))定義

    //自定義一個驗證方法
    $.validator.addMethod(
    "formula", //驗證方法名稱
    function(value, element, param) {//驗證規則
        return value == eval(param);
    }, 
    '請正確輸入數學公式計算后的結果'//不成功則出現驗證提示信息
    );

跟其他規則一樣,在rules里面,根據name調用對象:

valcode: {
    formula: "1+1"  
}

效果如下:

代碼清單
jq

  $(document).ready(function(){

    //自定義一個驗證方法
    $.validator.addMethod(
    "formula", //驗證方法名稱
    function(value, element, param) {//驗證規則
        return value == eval(param);
    }, 
    '請正確輸入數學公式計算后的結果'//驗證提示信息
    );

    $("#commentForm").validate({
        rules: {
            username: {
                required: true,
                minlength: 2
            },
            email: {
                required: true,
                email: true
            },
            url:"url",
            comment: "required",
            valcode: {
                formula: "1+1"  
            }
        },
        
        messages: {
            username: {
                required: '請輸入姓名',
                minlength: '請至少輸入兩個字符'
            },
            email: {
                required: '請輸入電子郵件',
                email: '請檢查電子郵件的格式'
            },
            url: '請檢查網址的格式',
            comment: '請輸入您的評論'
        },  
        
        errorElement: "em",             //用來創建錯誤提示信息標簽
        success: function(label) {          //驗證成功后的執行的回調函數
            //label指向上面那個錯誤提示信息標簽em
            label.text(" ")             //清空錯誤提示消息
                .addClass("success");   //加上自定義的success類
        }


      });

  });

二. jQuery表單插件——form

jQuery Form插件是一個優秀的Ajax表單插件,可以非常容易地、無侵入地升級HTML表單以支持Ajax。jQuery Form有兩個核心方法 -- ajaxForm() 和 ajaxSubmit(), 它們集合了從控制表單元素到決定如何管理提交進程的功能。另外,插件還包括其他的一些方法: formToArray()、formSerialize()、fieldSerialize()、fieldValue()、clearForm()、clearFields() 和 resetForm()等。

調試需要服務器環境的支持。筆記跟隨原書使用2.95版

1.快速上手

【例7.2】

一個表單,包括名字,地址,自我介紹,被提交時傳送到demo.php中,如果返回成功則收到“提交成功!”的信息。
————准備工作
在頁面引入插件:
<script type="text/javascript" src="js/jquery.form.js"></script>
html結構為:

    <form id="myForm" action="demo.php" method="post">
        名稱:<input type="text" name="name"><br>
        地址:<input type="text" name="address"><br>
        自我介紹:<input type="text" name="introduction"><br>
        <div id="output1" style="display:none"></div>
    </form>

demo.php初始化內容為:

<?php 
    header("Content-Type:text/html; charset=utf-8");
    echo "<h6>{$_REQUEST['name']}</h6>";
?>

在js文件中:

$(function(){
    //綁定一個id為myForm的表單並提供一個回調函數
    $('#myForm').ajaxForm(function(){
        $('#output1').html('提交成功!').show();
    });
    return false;//阻止表單默認提交
})

通過Form插件的兩個核心方法,都可以在不修改表單的HTML代碼結構的情況下,輕易地將表單的提交方式升級為Ajax提交方式。另一個核心方法ajaxSubmit()也能完成同樣的功能。

$(function(){
    //綁定一個id為myForm的表單並提供一個回調函數
    $('#myForm').ajaxSubmit(function(){
        $('#output1').html('提交成功!').show();
    });
    return false;//阻止表單默認提交
})

2.兩個核心方法的參數

ajaxForm() 和 ajaxSubmit() 都能接受0個或1個參數,當為單個參數時,該參數既可以是一個回調函數,也可以是一個options對象,上面的例子就是回調函數,下面介紹options對象,使得它們對表單擁有更多的控制權。

1.  var options = {  
2.  target: '#output',          //把服務器返回的內容放入id為output的元素中      
3.  beforeSubmit: showRequest,  //提交前的回調函數  
4.  success: showResponse,      //提交后的回調函數  
5.  //url: url,                 //默認是form的action, 如果申明,則會覆蓋  
6.  //type: type,               //默認是form的method(get or post),如果申明,則會覆蓋  
7.  //dataType: null,           //html(默認), xml, script, json...接受服務端返回的類型  
8.  //clearForm: true,          //成功提交后,清除所有表單元素的值  
9.  //resetForm: true,          //成功提交后,重置所有表單元素的值  
10.  timeout: 3000               //限制請求的時間,當請求大於3秒后,跳出請求  
11.  }  

13.  function showRequest(formData, jqForm, options){  
14.  //formData: 數組對象,提交表單時,Form插件會以Ajax方式自動提交這些數據,格式如:[{name:user,value:val },{name:pwd,value:pwd}]  
15.  //jqForm:   jQuery對象,封裝了表單的元素     
16.  //options:  options對象  
17.  var queryString = $.param(formData);   //name=1&address=2  
18.  var formElement = jqForm[0];              //將jqForm轉換為DOM對象  
19.  var address = formElement.address.value;  //訪問jqForm的DOM元素  
20.  return true;  //只要不返回false,表單都會提交,在這里可以對表單元素進行驗證  
21.  };  

23.  function showResponse(responseText, statusText){  
24.  //dataType=xml  
25.  var name = $('name', responseXML).text();  
26.  var address = $('address', responseXML).text();  
27.  $("#xmlout").html(name + "  " + address);  
28.  //dataType=json  
29.  $("#jsonout").html(data.name + "  " + data.address);  
30.  };  

32.  $("#myForm").ajaxForm(options);  

34.  $("#myForm2").submit(funtion(){  
35.  $(this).ajaxSubmit(options);  
36.  return false;   //阻止表單默認提交  
37.  });

表單提交之前進行驗證: beforeSubmit會在表單提交前被調用,如果beforeSubmit返回false,則會阻止表單提交。

3.表單提交之前的驗證

利用beforeSubmit的特性,當返回為false時,阻止提交。可以定義一個validate函數,作為beforeSubmit的值:

1.  beforeSubmit: validate  
2.  function validate(formData, jqForm, options) { //在這里對表單進行驗證,如果不符合規則,將返回false來阻止表單提交,直到符合規則為止  
3.  //方式一:利用formData參數  
4.  for (var i=0; i < formData.length; i++) {  
5.  if (!formData[i].value) {  
6.  alert('用戶名,地址和自我介紹都不能為空!');  
7.  return false;  
8.  }  
9.  }   

11.  //方式二:利用jqForm對象  
12.  var form = jqForm[0]; //把表單轉化為dom對象  
13.  if (!form.name.value || !form.address.value) {  
14.  alert('用戶名和地址不能為空,自我介紹可以為空!');  
15.  return false;  
16.  }  

18.  //方式三:利用fieldValue()方法,fieldValue 是表單插件的一個方法,它能找出表單中的元素的值,返回一個集合。  
19.  var usernameValue = $('input[name=name]').fieldValue();  
20.  var addressValue = $('input[name=address]').fieldValue();  
21.  if (!usernameValue[0] || !addressValue[0]) {  
22.  alert('用戶名和地址不能為空,自我介紹可以為空!');  
23.  return false;  
24.  }  

26.  var queryString = $.param(formData); //組裝數據  
27.  //alert(queryString); //類似 : name=1&add=2    
28.  return true;  
29.  }

三.模態窗口插件——SimpleModal

補白:

  • 模態窗口就是在該窗口關閉之前,其父窗口不可能成為活動窗口的那種窗口。
    例如:窗口A彈出窗口B,如果窗口B是模態的,在窗口B關閉前就不可能切換到窗口A;如果B是非模態的,那可以在這兩個窗口之間任意切換。
    更簡單地說alert彈出框就是一個模態窗口。
  • 模態對話框 和 非模態對話框區別
    模態對話框在顯示之后,就不能對同一個程序中的其它窗口進行操作。
    非模態對話框在顯示之后,還可以對同一個程序的其它窗口進行操作

SimpleModal為模態窗口的開發提供了強有力的接口。
本筆記采用SimpleModal 1.4.4版

1.快速上手



彈出的內容是需要css規范化的,因此css文件不可少。可以根據規則自定義css。本例用的是box.css。直接復制來用就好。

.simplemodal-container .ico-ok, .simplemodal-container .ico-error, .simplemodal-container .ico-info, .simplemodal-container .ico-question, .simplemodal-container .ico-warn, .simplemodal-container .ico-wait,.simplemodal-container .modalCloseImg,.simplemodal-container .btn-close, .simplemodal-container .btn-close-b{background:url(../img/box.png) no-repeat;display:inline-block;width:32px;height:32px;}
.simplemodal-container .ico-ok{background-position:-66px 0;}
.simplemodal-container .ico-error{background-position:0 0;}
.simplemodal-container .ico-info{background-position:-33px 0;}
.simplemodal-container .ico-question{background-position:-99px 0;}
.simplemodal-container .ico-warn{background-position:-165px 0;}
.simplemodal-container .ico-wait{background-position:-132px 0;}

.simplemodal-container .tips{padding:34px 0 0;}
.simplemodal-container .tips-ico{float:left;position:relative;top:-9px;width:auto;padding-left:5%;margin-right:16px;_margin-right:13px;text-align:right;}
.simplemodal-container .tips-content{overflow:hidden;height:1%;padding-right:5%;}
.simplemodal-container .tips-title, .simplemodal-container .tips-line{padding:0 0 8px;}
.simplemodal-container .tips-title{font-weight:700;font-size:14px;}
.simplemodal-container .tips-line{line-height:20px;}
.simplemodal-container .font-red{color:#c00;}
.simplemodal-container .tips-buttons{margin-top:23px;text-align:right;}
.simplemodal-container .tips-buttons .btn-blue, .simplemodal-container .tips-buttons .btn-blue-s, .simplemodal-container .tips-buttons .btn-white, .simplemodal-container .tips-buttons .btn-white-s{margin-right:16px;}

.simplemodal-container{position:relative;height:100%;*width:100%;margin:-9px;padding:9px;font-size:12px;line-height:1.5;background-color:rgba(0,0,0,0.2);filter:progid:DXImageTransform.Microsoft.Gradient(startColorstr=#30000000, endColorstr=#30000000);}
.simplemodal-container .btn-close{background-position:-286px 0;position:absolute;z-index:1;right:13px;top:13px;width:16px;height:16px;overflow:hidden;text-indent:-99em;text-decoration:none;}
.simplemodal-container .btn-close:hover{background-position:-302px 0;}
.simplemodal-container .btn-close-b{background-position:-249px 0;position:absolute;z-index:1;right:17px;_right:19px;top:19px;width:18px;height:18px;overflow:hidden;text-indent:-99em;text-decoration:none;}
.simplemodal-container .btn-close-b:hover{background-position:-267px 0;}

.box-title{position:relative;border:1px solid #369;border-bottom:none;margin:-1px -1px 0;background-color:#EBF2FA;padding:1px 0;}
.box-title h2{height:2em;line-height:2em;color:#666;font-size:100%;text-indent:12px;}
.simplemodal-data{height:100%;overflow:hidden;}
.box-main{position:relative;background-color:#fff;border:1px solid #369;margin:0 -1px -1px;border-top:none;zoom:1;}
.box-buttons{margin-top:23px;padding:0 9px 9px 0;text-align:right;}
.box-buttons button{margin-left:8px;min-width:68px;min-width:52px\9;*min-width:auto;height:24px;padding:0 5px 1px;*padding:0 10px 1px;}
.simplemodal-container iframe.box-iframe{position:relative;height:100%;width:100%;margin:-1px;overflow:hidden;border:1px solid #6685A2;background-color:#fff;}

.simplemodal-container .modalCloseImg{
    background-position:-286px 0;
    position:absolute;
    right:13px;
    top:13px;
    width:16px;
    height:16px;
    overflow:hidden;
    text-indent:-99em;
    text-decoration:none;
    cursor:pointer; 
    display:inline;
    z-index:3200;
}
.simplemodal-container .modalCloseImg:hover{background-position:-302px 0;}

有兩種調用方法。

(1)獲取一個jquery對象,然后對其使用Modal()方法。然后就可以用該元素的內容來顯示模態窗口。
$(elem).modal({options})
(2)作為一個單獨的函數使用

通過傳遞一個jq對象,通過dom元素來創建一個模態窗口

$.modal('<div><h1>HELLO WORLD!</h1></div>'),({options});

options參數為以上兩個方法提供了可能需要的css樣式信息。

(3)如何關閉——使用.simplemodal-close

你可以在button按鈕或是a標記上使用此類。

【例7.3】制作一個模態提示框和模態的iframe。

注意:原書案例中,simpleModal版本是1.4.2。用的是jquery1.7.1,不支持筆者的jquery-1.11版。經過測試,最新的1.4.4版可以支持jquery1.9。jq1.11.3版運行demo沒問題,但是firebug會報錯。除了基礎版本之外,還有登陸窗,聯系方式等其它的用法。可到作者官網http://www.ericmmartin.com/projects/下載更多demo。(需要FQ)


    <link rel="stylesheet" type="text/css" href="css/box.css"/>
    
    <link rel="stylesheet" type="text/css" href="css/css.css"/>
    <script type="text/javascript" src="js/jquery-1.9.js"></script>
    <script type="text/javascript" src="js/jquery.simplemodal-1.4.4.js"></script>
    <script type="text/javascript" src="js/js.js"></script>
    <div id='container'>

    <div id='content'>
        <div id='basic-modal'>
            <p>提示框-ok:<input type='button' name='basic' value='Demo' class='open-basic-dialog-ok'/></p>
            <p>警告框-warn:<input type='button' name='basic' value='Demo' class='open-basic-dialog-warn'/></p>
            <p>彈出iframe:<input type='button' name='basic' value='Demo' class='open-basic-ifr'/></p>
        </div>
    </div>
    
    <!-- 彈出內容 -->

    <div id="basic-dialog-ok">
        <!-- 普通彈出層 [[ -->  
        <p><h3>已完成!</h3></p>
        <button type="button" class="simplemodal-close">關 閉</button>
         
        <!-- 普通彈出層 ]] -->
    </div>

    <div id="basic-dialog-warn">
        <!-- 普通彈出層 [[ -->  
        <div class="box-title show"><h2>提示</h2></div>  
        <div class="box-main">
            <div class="tips">      
                <span class="tips-ico">
                    <span class="ico-warn"><!-- 圖標 --></span>
                </span>      
                <div class="tips-content">        
                    <div class="tips-title">系統繁忙,請稍候重試</div>        
                    <div class="tips-line"></div>     
                </div>    
            </div>
            <div class="box-buttons"><button type="button" class="simplemodal-close">關 閉</button></div>
        </div>  
        <!-- 普通彈出層 ]] -->
    </div>

    <div id="ifr-dialog" >
        <!-- iframe彈出層 [[ -->  
        <iframe frameborder="0" scrolling="no" id="ifr-dialog-container" src="javascript:;" class="box-iframe"></iframe>
        <!-- iframe彈出層 ]] -->
    </div>

</div>

主要css

body {
    background:#fff; color:#333;
    font: 12px/22px verdana, arial, sans-serif; 
    height:100%; margin:0 auto; width:100%;
}

#container {
    margin:0 auto; 
    padding-top:20px; 
    width:800px;
}
#content {
    border-bottom:1px dotted #999; 
    border-top:1px dotted #999; 
    padding:20px 0;
}

*{margin:0;padding:0;}

/* element全部消失為none */
#basic-dialog-ok,#basic-dialog-warn,#ifr-dialog{
    display:none;
    background: url('../images/logo.png') no-repeat center 90px;
    background-size: 50px 50px;

}
.dialog-param{
    color: #fff;
}

/* 定義彈出窗口時其它區域的顏色*/
#simplemodal-overlay {
    background-color:#000;
}
/*定義彈出窗口的背景色*/
.simplemodal-wrap{background-color:#fff;}

/* 彈出窗寬高 */
#simplemodal-container {
    height:150px; 
    width:500px;
}
/*彈出iframe的寬高*/
#ifr-dialog-content{
    height:300px; 
    width:700px;
}

效果:

四. 管理cookie的插件——Cookie

關於cookie的知識補白

  • cookie是網站放在客戶端的一個小文本文件,比如下回自動登陸,記住用戶名。就是典型的cookie應用。
  • 和網頁緩存沒有任何關系。緩存無法用js控制,而cookie可以。
  • 所有網站共享同一套cookie——數量和總的體積有限(以Kb為單位)數量幾十個。
  • 會有過期時間,由js來控制。
  • 完全由客戶來控制。敏感數據不能放cookie。

測試cookie,要么搭建本地服務器,要么在火狐。其它都不行。

1.快速上手

此插件需要用到$.cookie()方法。其中有三個參數

$.cookie('表單控件的name值',cookie字符串的來源比如value值,過期天數)
【例7.4】

一個表單,有用戶名。當點擊“記住用戶名”時,下回登陸就會記住用戶名。

    用戶名:<input type="text" name="username" id="username"/> <br/>
   <input type="checkbox" name="check" id="check"/>記住用戶名

根據上述思想很快寫出

$(function(){
    var COOKIE_NAME='username';
    if($.cookie(COOKIE_NAME)){
        $('#username').val($.cookie(COOKIE_NAME));
    }
    $('#check').click(function(){
        if(this.checked){
            $.cookie(COOKIE_NAME,$('#username').val(),{path:'/',expires:10});
        }else{
            $.cookie(COOKIE_NAME,null,{path:'/'});
        }
    })
    alert(document.cookie);//驗證cookie狀況
})

在輸入框中寫入djtao,點擊關閉,重新打開網頁。
彈出cookie信息為:

過期時間可以在火狐選項-隱私中查看最近的cookie發現。過期時間在10天后。

2.其它方法

(1)寫入cookie
$.cookie('待寫入的cookie名','cookie值')
(2)讀取:根據已有的cookie名來讀取已有的cookie值
$.cookie('待讀取的cookie名')
(3)刪除cookie

把一個空字符串或是空對象存進第二個參數就行了。

$.cookie('待刪除的cookie名','null')
(4)第三個參數

所謂第三個參數其實是一個集合。

$.cookie(cookieName,cookieValue,{
    expires:7;//有效期,如果時間已過,則自動刪除。
    path:'/';//cookie路徑
    domain:xxx.com;//域名,頁面cookie都會在此站點下歸類。
    secure:true;//如果設置為true,會要求一個安全協議。
})

五. jquery UI插件

如果說jquery是javascript的一個庫。那么jquery UI就是jquery的庫。原書認為,jquery UI很可能是未來jquery的重點。但從幾年之后網絡上的討論來看,是落伍了。另一方面,作為一個官方插件,jquery還是有它值得研究的地方。或許可以借鑒該代碼思想。

jQuery UI 主要分為3個部分:交互、微件和效果庫。

  • 交互(Interactions)
    交互部件是一些與鼠標交互相關的內容,包括縮放(Resizable) , 拖動(Draggable) , 放置(Droppable) , 選擇(Selectable) , 排序(Sortable)等。
  • 小部件(Widgets)
    主要是一些界面的擴展,包括折疊面板(Accordion) , 自動完成(Autocomplete) , 按鈕(Button) , 日期選擇器(Datepicker) , 對話框(Dialog) , 菜單(Menu) , 進度條(Progressbar) , 滑塊(Slider) , 旋轉器(Spinner) , 標簽頁(Tabs) , 工具提示框(Tooltip)等,新版本的UI將包含更多的微件。
  • 效果庫(Effects)
    用於提供豐富的動畫效果,讓動畫不再局限於jQuery的animate()方法。包括特效(Effect) , 顯示(Show) , 隱藏(Hide) , 切換(Toggle) , 添加 Class(Add Class) , 移除 Class(Remove Class) , 切換 Class(Toggle Class) , 轉換 Class(Switch Class) , 顏色動畫(Color Animation)等。

在此闡述深入的使用方法非本筆記原意。但是為了學習思想,不妨把jqueryUI基本原理陳列如下。

安裝

當小部件安裝時,生命周期開始。我們只需要在一個或多個元素上調用插件,即安裝了小部件。

 $(  "#elem"  ).progressbar();

這將會初始化 jQuery 對象中的每個元素,在本例中,元素 id 為 "elem"。因為我們調用無參數的 .progressbar() 方法,小部件則會按照它的默認選項進行初始化。我們可以在安裝時傳遞一組選項,這樣既可重寫默認選項。

$(  "#elem"  ).progressbar({ value:  20  });

安裝時傳遞的選項數目多少可根據我們的需要而定。任何我們未傳遞的選項則都使用它們的默認值。

選項是小部件狀態的組成部分,所以我們也可以在安裝后再進行設置選項。我們將在后續的 option 方法中介紹這部分內容。

方法

既然小部件已經初始化,我們就可以查詢它的狀態,或者在小部件上執行動作。所有初始化后的動作都以方法調用的形式進行。為了在小部件上調用一個方法,我們可以向 jQuery 插件傳遞方法的名稱。例如,為了在進度條(progressbar)小部件上調用 value 方法,我們應該使用:

$(  "#elem"  ).progressbar(  "value"  );

如果方法接受參數,我們可以在方法名后傳遞參數。例如,為了傳遞參數 40value 方法,我們可以使用:

$(  "#elem"  ).progressbar(  "value",  40  );

就像 jQuery 中的其他方法一樣,大部分的小部件方法為鏈接返回 jQuery 對象。

$(  "#elem"  )
  .progressbar(  "value",  90  )
  .addClass(  "almost-done"  );
公共的方法

每個小部件都有它自己的一套基於小部件所提供功能的方法。然而,有一些方法是所有小部件都共同具有的。

option

正如我們前面所提到的,我們可以在初始化之后通過 option 方法改變選項。例如,我們可以通過調用 option 方法改變 progressbar(進度條)的 value 為 30。

$(  "#elem"  ).progressbar(  "option",  "value",  30  );

請注意,這與之前我們調用 value 方法的實例有所不同。在本實例中,我們調用 option 方法,改變 value 選項為 30。

我們也可以為某個選項獲取當前的值。

$(  "#elem"  ).progressbar(  "option",  "value"  );

另外,我們可以通過給 option 方法傳遞一個對象,一次更新多個選項。

$(  "#elem"  ).progressbar(  "option",  {
  value:  100,
  disabled:  true
});

您也許注意到 option 方法有着與 jQuery 代碼中取值器和設置器相同的標志,就像 .css().attr()。唯一的不同就是您必須傳遞字符串 "option" 作為第一個參數。

disable

disable 方法禁用小部件。在進度條(progressbar)實例中,這會改變樣式讓進度條顯示為禁用狀態。

1.  $(  "#elem"  ).progressbar(  "disable"  );

調用 disable 方法等同於設置 disabled 選項為 true

enable

enable 方法是 disable 方法的對立面。

1.  $(  "#elem"  ).progressbar(  "enable"  );

調用 enable 方法等同於設置 disabled 選項為 false

destroy

如果您不再需要小部件,那么可以銷毀它,返回到最初的標記。這意味着小部件生命周期的終止。

1.  $(  "#elem"  ).progressbar(  "destroy"  );

一旦您銷毀了一個小部件,您就不能在該部件上調用任何方法,除非您再次初始化這個小部件。如果您要移除元素,可以直接通過 .remove(),也可以通過 .html().empty() 修改祖先,小部件會自動銷毀。

widget

一些小部件生成包裝器元素,或與原始元素斷開連接的元素。在下面的實例中,widget 將返回生成的元素。在進度條(progressbar)實例中,沒有生成的包裝器,widget 方法返回原始的元素。

1.  $(  "#elem"  ).progressbar(  "widget"  );
事件

所有的小部件都有跟他們各種行為相關的事件,用於在狀態改變時通知您。對於大多數的小部件,當事件被觸發時,名稱以小部件名稱為前綴。例如,我們可以綁定進度條()的 change 事件,一旦值發生變化時就觸發。

$(  "#elem"  ).bind(  "progressbarchange",  function()  {
  alert(  "The value has changed!"  );
});

每個事件都有一個相對應的回調,作為選項進行呈現。我們可以使用進度條(progressbar)的 change 回調,這等同於綁定 progressbarchange 事件。

 $(  "#elem"  ).progressbar({
  change:  function()  {
  alert(  "The value has changed!"  );
  }
});
公共的事件

大多數事件是針對特定的小部件,所有的小部件都有一個公共的 create 事件。該事件在小部件被創建時即被觸發。

1.快速上手

【例7.5】拖動排序的使用

拖動方法調用的是sortable()方法。
html

    <ul id="ul1">
        <li class="list-item">1</li>
        <li class="list-item">2</li>
        <li class="list-item">3</li>
        <li class="list-item">4</li>
    </ul>

css

.list-item{
    width: 200px;line-height: 50px;
    border: 1px solid black;
    text-align: center;
    margin-top: 20px;
    list-style: none;
    cursor: pointer;
}

jq

$(function(){
    $( "#ul1" ).sortable();
    $( "#ul1" ).disableSelection();
})

然后一個簡單到令人發指的拖動排序效果就做出來了。

2. 結合后台

sortable方法在參數中可以插入回調函數。比如說我想知道拖動后的排序,可以采用:

$('selector').sortable{
    stop:function(){
        do something;
    }
}

六.jquery插件的編寫

插件編寫的目的是封裝方法或函數,以便下次調用。插件分為三個類型:

  • 封裝對象方法:
    最常見的類型,通過選擇器來進行對象操作:
  • 封裝全局函數
    獨立的全局函數。
  • 選擇器插件
    更為豐富的選擇邏輯。

1.要點

  • 命名:建議命名為jquery.xxx.js
  • 所有的對象方法應該加到jquery.fn對象上,全局函數加到jquery對象本身
  • 注意this:內部指向的是選擇器
  • 允許遍歷(this.each)
  • 分號結尾:(否則壓縮會出問題)
  • 插件返回的是一個jquery對象,保證鏈式操作
  • 不建議簡寫,可以允許閉包方法。

2.閉包方法

所謂閉包:允許使用其它函數內部定義的函數。
插件的標准寫法是:

//前面加分號為了更好的兼容性。
;(function($){//$是這個匿名函數的形參
    /*代碼,允許簡寫如$*/
})(jQuery);//將jquery作為實參傳遞給匿名函數。后面括弧表示立即執行。

3. 插件機制——jQuery.extend()和jQuery.fn.extend()

前者用於擴展對象方法,后者用於擴展全局函數或者選擇器。

4. 編寫實例

(1)對象方法
【例7.6】編寫獲取顏色方法的插件color()

實現兩個功能:A.設置匹配元素的顏色;B.獲取匹配元素的顏色
網頁中有一個#div1,字體顏色為紅色

;(function ($) {
    jQuery.fn.extend({
        "color":function(value){
            if(value==undefined){
                return this.css('color');//當前返回字體的顏色
            }else{
                return this.css('color',value);//如果value參數為空,返回字體顏色
            }
        }
    })
})(jQuery);//立即調用!

再寫一段調用的測試:

$(function(){
    alert($('#div1').color());
    $('#div1').color('blue');
})

成功將字體設置為藍色。

進一步改造:因為color的css方法中已經包含了參數為空的情況,可以省略判斷,直接返回this.css('color',value)。根據設置color的思想還可以設置background,border等方法:

;(function ($) {
    jQuery.fn.extend({
        'color':function(value){
            return this.css('color',value);
        },
        'backgroundColor':function(value){
            return this.css('background-color',value);
        },
        'border':function(value){
            return this.css('border',value);
        }
    })
})(jQuery);

成功通過測試。

【例7.7】表格隔行變色:

第五章表格隔行變色的代碼是:

.even{
    background: #fff38f;
}
.odd{
    background: #ffffee;
}
.selected{ background:#FF6500;color:#fff;}

jq:

$(function(){
    $('tbody>tr:odd').addClass('odd');
    $('tbody>tr:even').addClass('even');
    $('tbody>tr').click(function(){
        if($(this).hasClass('selected')){
            return false;
        }else{
            $(this).siblings().removeClass('selected');
            $(this).addClass('selected');
        }
    })
})

試用插件的寫法實現上述功能。插件方法取名為tableStriped

思路:要通過`對象.tableStriped()方法應該有一個參數options,options參數是一個對象。你可以通過設置參數的屬性來規定你要給它加上那種class,表述為options.odd,options.even,options.selected。

;(function ($) {
    jQuery.fn.extend({
        'tableStriped':function(options){
            options=$.extend({
                odd:'odd',
                even:'even',
                selected:'selected'
            },options);
        }
    })
})(jQuery);//立即調用!

框架已經打好,接下來就是選擇元素,應該使用$(選擇器,this)表述只在匹配與元素內進行操作。函數應該是可鏈的,所以最后應該返回this。

;(function ($) {
    jQuery.fn.extend({
        'tableStriped':function(options){
            //參數框架
            options=$.extend({
                odd:'odd',
                even:'even',
                selected:'selected'
            },options);
        //具體方法:
            $('tbody>tr:odd',this).addClass(options.odd);
            $('tbody>tr:even',this).addClass(options.even);
            $('tbody>tr',this).click(function(){
                if($(this).hasClass(options.selected)){
                    return false;
                }else{
                    $(this).siblings().removeClass(options.selected);
                    $(this).addClass(options.selected);
                }
            })
            return this;//使方法可鏈
        }
    })
})(jQuery);//立即調用!

在驗證中,可以通過$('table').tableStriped(參數)來實現題目的效果。如果我不想使用.odd.even。selected這種名稱的樣式,可以重新傳入一個對象:

$('table').tableStriped({odd:'haha',even:'hehe',selected:'hoho'});

上述代碼表示在所有table中,對奇數序列odd的行(2,4,6...)使用.haha樣式,...一次類推。

注意:在前面提到的幾個要點里,元素應該是允許遍歷的。簡單的說,就是內部對象可能不是一個單獨的對象,也有可能是多個。

;(function ($) {
    jQuery.fn.extend({
        'somePlugin':function(options){
            return this.each(function(){
                //代碼
            })
        }
    })
})(jQuery);//立即調用!
(2)怎樣封裝全局函數插件

因為全局函數之前已經經過封裝,因改起來很簡單,把函數放到jquery命名空間下就可以。

;(function($){
    $.extand({
         屬性名:function(){
            //待封裝函數代碼
    })
})(jQuery)

寫插件時注意不要把內容寫死。

(3)自定義選擇器

想自定義選擇器,首先得了解jquery選擇器的機制:通過正則表達式來解析,然后針對解析出來的選擇符執行一個函數。——稱為選擇器函數。現在以:lt()為例說明jquery選擇器函數的特性。
$('div:lt(3)')表示選取div索引值小於3的所有div元素(大於用:gt())。分析:lt()jquery源碼:

gt:function(a,i,m){
    return i<m[3]-0;
}
  • a表示當前遍歷到的dom元素
  • i表示當前遍歷到dom的索引值
  • m是一個數組,也是選擇器函數的最重要部分。拿$('div:lt(3)')來說:
    • m[0]表示:lt(3)這部分。
    • m[1]表示冒號
    • m[2]決定了用那個選擇器函數,在例子只帶lt
    • m[3]指代括號內的數字。
【例7.8】在jquery的空間內寫一個between選擇器,選取目標元素索引值在一定范圍之間的所有元素。
;function($){
    $.extend($.expr[':'],{
        between:function(a,i,m){
            var tmp=m[3].split(',');
            return tmp[0]-0<i&&tmp[1]<tmp[1]-0;
        }
    })
}

解釋:在自定義選擇器between,中m[3]表述為x,y表示數字x,和數字y之間的索引值范圍。因此,需要用split方法把它分割為數組tmp,所以tmp有兩個元素。其中tmp[0]代表數字較大的數組元素(本質上還是字符串)。
接下來依樣畫葫蘆,把i的取值范圍返回出去就行了。(tmp-0表示通過一個簡單運算把字符串轉換為數字。)
選擇器僅僅是$.expr[':']的一部分,不能獨立存在。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM