2012年3月14日 星期三

[jQuery] 在plugin內加入function

今天再寫plugin的時候,發現在要把一些區塊獨立出來,但是又不知道如何在plugin內再獨立使用function,然後我就自己測試看看,發現這樣子可行。

範例程式碼

(function($){
    var helps = {
        question: function(){
            ...
        }.
        answers: function(){
            ...
        }
    };
   
    $.fn.qa = function(){
        helps.question();
        helps.answers();
    }
})(jQuery);

這樣就可以使用了

2012年3月12日 星期一

[jQuery] textarea auto expand(文字區塊自動延展)

jQuery plugin: autoResize

其實之前一直有再找類似的套件,facebook樣式的textarea auto expand,不過一直沒有找到不錯的,今天在尋找的時候找到一個不錯的plugin「autoResize」

自己選擇下載喜歡的檔案格式

Script

$('textarea#comment').autoResize({
    // On resize:
    onResize : function() {
        $(this).css({opacity:0.8});
    },
    // After resize:
    animateCallback : function() {
        $(this).css({opacity:1});
    },
    // Quite slow animation:
    animateDuration : 300,
    // More extra space:
    extraSpace : 40
});

HTML


這樣就可以使用了 :)

不過他還有一些選項可以選擇使用,日後有用到再介紹。

來源網站

2012年3月10日 星期六

[jQuery] jQuery Plugin 寫法

由於網頁設計目前用到jQuery的機率越來越高,常常寫了一段程式碼需要重複使用,於是決定把它製作成模組使用

建立一個Plugin

(function($){
    $.fn.helloworld = function(){
        alert('Hello World');
    }
})(jQuery);

照jQuery文件說明,是可以這樣寫

jQuery.fn.helloworld = function(){
    alert('Hello World');
}

不過一方面為了方便使用「$」字號,且不與其他函式庫衝突,所以就使用外層包著,這樣就可以在裡面使用「$」字號,不會衝突。

this代表的意義

假設我們這麼寫了一段程式碼

(function($){
    $.fn.showbox = function(){
        this.fadeIn('slow');
    }
})(jQuery);

然後我們只要這樣使用

$('div').showbox();

div就會依照Plugin內的程式碼去執行,this就等於div這個物件,不需再另外再去指定。

保持鏈結(Maintaing Chainability)

下面有個範例<取自jQuery網站>

(function( $ ){

  $.fn.lockDimensions = function( type ) {  

    return this.each(function() {

      var $this = $(this);

      if ( !type || type == 'width' ) {
        $this.width( $this.width() );
      }

      if ( !type || type == 'height' ) {
        $this.height( $this.height() );
      }

    });

  };
})( jQuery );
$('div').lockDimensions('width').css('color', 'red');

照上面的範例,因為這個物件必須接著下面繼續的動作,所以在lockDimensions這個plugin必須回傳this,才能繼續接著.css()這類其他jQuery的函式,要是沒有回傳this的話,就會接不到物件,而後面動作都沒有效果。

設定預設值和選項(Defaults and Options)

許多功能性較複雜的plugin,會給予使用者很多選項去選擇所需的功能,來符合自己的需求,而這些選項必然需要預設值來確保plugin的運作正常,當使用者忘記給予一些參數時,預設值能自動替補上去,來讓程式運行正常。

(function( $ ){

  $.fn.box = function( options ) {  

    //設定選項和預設值
    var settings = $.extend( {
      'width'         : '200px',
      'height'        : '200px',
      'background-color' : 'blue'
    }, options);

    return this.each(function() {        
       alert(settings.width);
    });

  };
})( jQuery );

$("div").box();
//200px


$("div").box(
    {
        'width': 300px
    }
};
//300px                   

在沒有給予選項狀態下,plugin預設會使用程式碼編寫時的預設值。

預設值是一個非常重要的東西,常常再編寫程式碼時忘記給予參數造成程式掛點,如果有設定預設值,就算忘記給予參數,也可以讓程式順利執行。

命名(Namespacing)

這段是jQuery文件中提到的,我也非常認同好的且正確的命名plugin是應該做的事情,其實這也不也僅限於jQuery Plugin而已,在任何程式碼中正確的命名都是必須的,最好用幫自己小孩取名子的心態下去取,總不會把自己的小孩叫a,b,c這類的名稱吧,文件中提到正確的命名可以將名稱衝突的機率降到最低,避免太多隻plugin一起引入時,因為不好的命名結果造成覆蓋,程式無法正確執行,另一方面,正確的命名可以方便開發者快速的追蹤問題,這是非常重要的,畢竟時間就是金錢,因為今天自己的命名不小心結果造成要花更大的成本去檢查錯誤,最後發現命名衝突,這該有多嘔。

多種方法(Plugin Methods)

有的時候我們在寫一隻plugin,會有許多方法可以讓使用者可以選擇,但是每種方法都寫一隻plugin又太多餘,且難以維護管理,且互相都有相依性,這時候就可以這樣寫。

(function($){
    var methods = {
        init : function( options ) { 
            var settings = $.extend({
                'width': '200px'
            },options);
            this.css('width', settings.width); 
        },
        show : function( ) {
            this.show();
        },
        hide : function( ) { 
            this.hide();
        },
        spin : function( content ) { 
            alert(content);
        }
     };

     $.fn.box = function( method ) {
         // Method calling logic
         if ( methods[method] ) {
             return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
         }else if( typeof method === 'object' || ! method ) {
             return methods.init.apply( this, arguments );
         }else{
             $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
         }    
     };
})(jQuery);

然後可以這樣使用

$("div").box();
//call init function;
//set box width 200px.

$("div").box({width: '377px'});
//call init function with options
//set box width 377px.

$("div").box('hide');
//call hide funtion
//div hide

$("div").box('spin', 'This is box.');
//call spin function with argument
//This is box.

這樣就可以依照參數的不同去執行不同的動作,然後又屬於同一隻plugin內,不需要為每種動作都建立一個plugin,我覺得很方便。

事件(Events)

在寫plugin時,一定會用到許多事件問題,常常要綁定一些事件,例如:「click」「blur」這類的事件要處理,在有些情況下,必須要讓這些事件停止動作,我們就必須「unbind」這些事件。所以我們常常會這樣:

(function($){
    var methods = {
        init: function() {  
            return this.each(function(){
                 $(window).bind('click', methods.start);
                 //未加入namespacing
            );  
        },  
        stop: function() {  
            return this.each(function(){
                 $(window).unbind('click');
                 //有可能干擾到其他相同類型事件
            });  
        },
        start: function(){
             ..........
        }  
    }

    $.fn.runner = function( method ) {   
        if ( methods[method] ) {
            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
        }     
    };
})(jQuery);

如果照上面那樣寫的話,在初始化runner這個物件時,會綁定click事件,這沒有甚麼太大問題,但是當執行stop時,避免unbind「click」時干擾到其他事件,所以我們可以這樣寫:

    var methods = {
        init: function() {  
            return this.each(function(){
                 $(window).bind('click.runner', methods.start);
                 //加入了namespacing
            );  
        },  
        stop: function() {  
            return this.each(function(){
                 $(window).unbind('click.runner');
                 //或是 $(window).unbind('.runner');
                 //這樣就不會影響其他的事件
            });  
        },
        start: function(){
             ..........
        }  
    }

    $.fn.runner = function( method ) {   
        if ( methods[method] ) {
            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
            return methods.init.apply( this, arguments );
        } else {
            $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
        }     
    };

這樣寫的話就可以緊限於這個物件的事件,而不去影響到其他plugin物件的運作。

2012年3月8日 星期四

[javascript] 多檔上傳 - 使用SWFUpload

最近因為工作需求而必須使用到多檔上傳的工具,雖然說jQuery有個 jQuery File Upload 的Plugin但是『file[]』這個多檔選擇必須在HTML支援的瀏覽器下才能作用,結果就在(爛)IE不完全支援HTML 5的情況下,只好放棄使用 jQuery File Upload 這個工具,另尋其他的多檔上傳工具, SWFUpload 這套工具我想應該也是行之有年(不過我就是不是很喜歡Flash),整個事件處理也算是完整,為了工作的順暢,就來用 SWFUpload 來執行多檔上傳的工作吧。

1.首先我們要先下載SWFUpload 的核心檔案[ 點此進入下載頁面 ]

未完待續

2012年3月4日 星期日

[CSS] 子物件置底

今天為了這個問題google了好久,原來是這樣子用阿,之前一直不知道只會用padding來控制,現在終於了解了。

CSS

.father{position:relative;}
.child{position:absolute; bottom: 0;}

HTML

父系物件的position必須設定為relative,子物件position設定為relative

使用這樣的方式,就可以使「child」類別的物件置於「father」的底部。

[PHP] 正規表示法驗證密碼

驗證密碼

  • 至少有一個數字
  • 至少有一個小寫英文字母
  • 至少有一個大寫英文字母
  • 字串長度在 6 ~ 30 個字母之間
function valid_password($password)
{
    if(preg_match("/^(?=.*\d)(?=.*[a-z]).{32,64}$/", $string))
        return TRUE;
    else
        return FALSE;
}