iT邦幫忙

DAY 7
3

jQuery 套件開發之我可不可以跳著說系列 第 7

jQuery套件開發之(七),實作套件。

寫一個套件。符合如下操作的pattern

$('#id1').ryTooltip() ;  //沒參數
$('#id1').ryTooltip({xxx: ooo}) ;  //有參數地執行套件
$('#id1').ryTooltip('method', arguments obj) ;  //執行套件method

<文章列表>
IT人生組文章
--9/22 : 不要在電梯裡面討論HTML
http://ithelp.ithome.com.tw/question/10128407
--9/21 : IT人的人生觀
http://ithelp.ithome.com.tw/question/10128168
--9/20 : IT人的創意
http://ithelp.ithome.com.tw/question/10127866
--9/19 : 程式設計師的成就感
http://ithelp.ithome.com.tw/question/10127573
--9/18 : 你的職業是甚麼?
http://ithelp.ithome.com.tw/question/10127308

開發技術組文章
--9/22 : jQuery套件開發(七),實作套件。
http://ithelp.ithome.com.tw/question/10128406
--9/21 : jQuery套件開發(六),套件的整個流程的小構思。
http://ithelp.ithome.com.tw/question/10128176
--9/20 : jQuery套件開發(五),套件的定義
http://ithelp.ithome.com.tw/question/10127881
--9/19 : jQuery套件開發(四),預設值與設定值的差別
http://ithelp.ithome.com.tw/question/10127575
--9/18 : jQuery套件開發(三),true false的判斷
http://ithelp.ithome.com.tw/question/10127297

全列表
http://ithelp.ithome.com.tw/ironman6/player/sheephead081/alll/1
寫套件嚕

各位觀眾..

我今天要推出的套件就是~~~tooltip!

你沒看錯,我就是那麼無恥。

對了,程式碼還超長的,神~吧~!

但是我們主要是為了探討寫套件的一些流程

還有,希望能夠有一個小小的架構適應我們大部分寫套件的需求

當你滑鼠滑過SPAN會顯示提示文字( 我恥力真高阿! )

我們先來回想一下上一次我們提到寫套件大概會遇到哪些程序

第一個,套件初始化。( 先把要用到的元素放到畫面中,當然是隱形的嚕 )
第二個,套件觸發。( 悠~碰到了SPAN )
第三個,邏輯計算。( 算出觸發元素的相關資訊用來決定tooltop要顯示在哪裡 )
第四個,畫面改變。( 畫面上顯示一個DIV )
第五個,事件綁定。( 綁定mouseleave事件,滑鼠移開DIV元素就消失。 )

其中,事件綁定的部分要看你元素是在哪裡生成的。

像我是初始化的時候就把元素append到 body 裡面了。

所以,我那時候事件就已經綁定好了。

首先,先來定義我的套件想怎樣使用

$(function()
{
    $.ryTooltip('init') ;
    $.ryTooltip('testMode') ;
    $('#id1').ryTooltip() ;
}) ;

我是習慣套件使用前都要先初始化。

畢竟不見得你的套件是那麼的輕快。

另外有一點很重要就是這樣有助於把畫面跟程式做分割。

舉例而言,如果你做的是一個月曆的套件。

你可以在開發的時候 用$.calender('init')的時候把月曆漂漂亮亮的弄在畫面上。

你還不用想接下來的事件呢~你只要把套件美美的弄出來就好了。

有人會說,我可以套件載入的時候利用立即函式來處理

的確沒錯,但這樣一來你就錯失設定預設值的時機了。

當然你也可以打開程式碼改程式。這沒甚麼大不了的。

;(function ( $, W, D, undefined ) {
    var pluginName = 'ryTooltip' ;
    
    $.pg = $[pluginName] = function()
    {     
        if ($.isFunction( $.pg[arguments[0]] ))
        {
            $.pg[arguments[0]](arguments[1]) ;
        }
    }
    
    $.pg.defaults = 
    {
        testMode: false,
        ttBorder: '1px solid red',  //tt means tooltop
        ttBgColor: 'blue',
        ttPadding: '8px',
        ttColor: 'yellow',
        ttClass: 'ryttClass',
    } ;

    $.pg.init = function()
    {
        $[pluginName].createHero() ;
    }
    
    $.pg.createHero = function()
    {
        $.pg.hero = $('<span />')
            //set some would not be changed by settings or defaults
            .css(
            {
                display: 'none',  //invisible is important.
                position: 'absolute',
            })
            .appendTo('body') ;
    }
    
    $.pg.log = function()
    {
        if ($[pluginName].defaults.testMode) 
        {
            console.log(arguments) ;
        }

    }
    
    $.pg.testMode = function(mode)
    {
        var _flag = true ;
        if (mode === false)
        {
            _flag = false ;
        }
        $[pluginName].defaults.testMode = _flag ;
        if (_flag) 
        {
            console.log('testMode is opened') ;
        }
    }      
    
})( jQuery, window, document );

然後我習慣打開$.ryTooltip('testMode') ;

這會把測試模式打開,這個模式會把一些設定的log顯示出來

這通常是要修改套件的時候還滿有用的

然後最後才是我們一般使用套件的方法

$('#id1').ryTooltip() ;

那因為我們在初始化的時候早就把套件元素放在文件裡了

所以套件變得超好寫的!只是綁定事件,然後在某個時間點把套件.show()而已。

這部分我有學一些文章。

文章一
http://coding.smashingmagazine.com/2011/10/11/essential-jquery-plugin-patterns/
文章二
http://www.learningjquery.com/2007/10/a-plugin-development-pattern

剛剛,我們是在設定套件的預設值以及一些檢查機制

接下來,再針對這個套件設計內容

    function Plugin(element, args)
    {  
        this.element = element ;
        this.ele$    = $(element) ;
        this.args    = args[0] ;
        this.hero    = $.pg.hero ;  
        //如果套件很簡單,只會產生一個元素(巢狀也算在內)。
        //那我大部會會取名叫做hero
        
        //這裡的順序,越後面代表越重要。所以是以傳進來的參數為主
        this.settings = $.extend({}, defaults, $.pg.defaults, this.args) ;      
        
        this.init() ;
    }

    Plugin.prototype =
    {
          init: function()
        {
            var self = this ;     
            self.hero
                .addClass(self.settings.ttClass)  //
                .html( self.ele$.attr('data-tooltip') ) ;
            
            self.bindEvent() ;
        }
        
        , bindEvent: function()
        {
            var self = this ;
            
            self.ele$
                .on('mouseenter', function(e)
                {               
                    self.hero
                        .css(
                        {                 
                            border: self.settings.ttBorder,
                            'background-color': self.settings.ttBgColor,
                            padding: self.settings.ttPadding,
                            color: self.settings.ttColor,
                            top: e.clientY,
                            left: e.clientX,
                        })
                        .show() ;
                })
                .on('mouseleave', function()
                {
                    self.hero.hide() ;
                }) ;
        }
    }

    $.fn[pluginName] = function() {
        //處裡套件全域設定       
        args = Array.prototype.slice.call(arguments) ;
        return this.each(function() {
            if (!$.data(this, 'plugin_' + pluginName)) {
                $.data(this, 'plugin_' + pluginName, new Plugin(this, args));  //吃參數
            }
            else if ($.isFunction(Plugin.prototype[args[0]]))
            {
                $.data(this, 'plugin_' + pluginName)[args[0]](args[1]);  //吃參數
            }
            else
            {
                console.log('wrong way to use this method:' + args[0]) ;
            }
        });
    }

這樣寫雖然看起來很麻煩

但是擴充功能的時候你就會覺得他很方便。

完全就是物件導向,所以當你的套件生出來的物件很多也不怕。

而且完全支援以下的用法

$('#id1').ryTooltip() ;  //沒參數
$('#id1').ryTooltip({xxx: ooo}) ;  //有參數地執行套件
$('#id1').ryTooltip('method', arguments obj) ;  //執行套件method

另外就是,假如套件產生出來的元素只有一組

我會把它叫做hero

如果是那種產生很多組同階層的元素

那我會取一個soldiers or troops

還滿符合語意的。

最後是DEMO頁面。
http://ry.url.tw/wp/doc/a2.htm

不過當然,現在我們的進度,還很前面。

慢慢地,我們會讓我們的套件設計越發合理。

下一次,我們來寫寫看

如果沒有觸發的元素怎麼辦? 例如說這樣使用: $.showLocation() ;

假如我的套件是一個DIV,上面顯示滑鼠當前座標位置!

除此之外,目前的

1.參數控管也不太好

老是用arguments,到時候真正的參數已經巢狀到不知道第幾層去了。

2.事件的綁定,也是有點問題。

這些我們都會慢慢解決。

期待明天的相會喔


上一篇
jQuery套件開發之(六),對觸發套件的整個流程的小構思。
下一篇
jQuery套件開發(八),怎麼樣把element 放進DOM中才好呢。
系列文
jQuery 套件開發之我可不可以跳著說26

1 則留言

0
老鷹(eagle)
iT邦高手 1 級 ‧ 2013-09-22 13:14:23

沙發

簽名簽名

我要留言

立即登入留言