2014-02-16 38 views
1

我正在嘗試基本的Jquery插件和原型概念,但結束了一個不尋常的行爲。Jquery插件與原型

HTML:

<div> 
    <span> 
     <textarea>Text Area with 500 characters. Adding Some text.</textarea> 
     <span class="cl"></span> 
    </span> 
    <span> 
     <textarea>Text Area with 100 characters</textarea> 
     <span class="cl"></span> 
    </span> 
</div> 

JQuery的:

(function ($) { 
    var tisCharsLeftCntxt = null; 

    function fnCharsLeft(ele, genStngs) { 
     this.jqe = $(ele); 
     this.maxChars = genStngs.maxChars; 
     tisCharsLeftCntxt = this; 
     this.fnInit(); 
    } 
    fnCharsLeft.prototype = { 
     fnInit: function() { 
      tisCharsLeftCntxt.fnUpdateRemainingChars(); 
      tisCharsLeftCntxt.jqe.keyup(function (event) { 
       key = event.keyCode ? event.keyCode : event.which; 
       if ((37 != key) && (38 != key) && (39 != key) && (40 != key)) { 
        tisCharsLeftCntxt.fnUpdateRemainingChars(); 
       } 
      }); 
     }, 
     fnUpdateRemainingChars: function() { 
      var charsLft = tisCharsLeftCntxt.maxChars - tisCharsLeftCntxt.jqe.val().length, 
       jqeDestToUpdt = tisCharsLeftCntxt.jqe.siblings('.cl'); 
      charsLft = (charsLft < 0) ? 0 : charsLft; 
      if (charsLft) { 
       jqeDestToUpdt.text(charsLft + ' more of ' + tisCharsLeftCntxt.maxChars + ' characters'); 
      } else { 
       tisCharsLeftCntxt.jqe.val(tisCharsLeftCntxt.jqe.val() 
        .substring(0, tisCharsLeftCntxt.maxChars)); 
       tisCharsLeftCntxt.jqe.scrollTop(tisCharsLeftCntxt.jqe[0].scrollHeight); 
       jqeDestToUpdt.text("Maximum limit of " + tisCharsLeftCntxt.maxChars + " characters reached"); 
       return false; 
      } 
     } 
    }; 
    $.fn.fnCharsLeftPlgn = function (genStngs) { 
     return $(this).data("charsleft", new fnCharsLeft(this, genStngs)); 
    }; 
})(window.jQuery); 
$('div span:nth-child(1) textarea').fnCharsLeftPlgn({maxChars: 500}); 
$('div span:nth-child(2) textarea').fnCharsLeftPlgn({maxChars: 100}); 

小提琴: http://jsfiddle.net/5UQ4D/ & http://jsfiddle.net/5UQ4D/1/

的要求是,該插件應該表明,可以在文本中添加的字符數-區。如果在一個頁面中只有一個文本區域,那麼這個工作就很好。但是,如果有多個,只有最後一個與該插件關聯的文本區域正常工作。

關於這裏的代碼,在左側的文本區域中的字符數都是在初始化期間正確更新(僅限於第一次)。但稍後當文本區域內容發生變化時,只有第100個字符(或與插件關聯的最新文本區域)才能正常工作。

似乎,我無法將插件上下文獨立限制在文本區域。請指點,..

+0

'$ .jQuery.fn.fnCharsLeftPlgn'應該是'$ .fn.fnCharsLeftPlgn'('$'是作爲'window.jQuery'傳遞的參數) – JAAulde

+0

對不起,這是一個複製錯誤。正如你所提到的,檢查JS小提琴,那裏的代碼是正確的。這裏也更新了代碼。 – NEB

+2

你有全局var tisCharsLeftCntxt = null;通過它訪問你的方法內的元素...這就是爲什麼只有最後一個textarea是活躍的 –

回答

1

問題1:

正如評論所說,你要創建一個名爲tisCharsLeftCntxt外的其他情況下的變量,然後在你的構造函數分配this它。每次運行插件時,您都會在tisCharsLeftCntxt上踩一個新的this

沒有理由在你有批發的時尚中使用對this的引用。您的代碼中只有一個地方會更改範圍,以致this不再是您的實例。這個地方在keyup事件處理函數中。您應該將您的別名this本地化爲包含該事件處理程序的方法。

問題2:

我相信你的問題的另一部分(如果你跑了反對其匹配多個元素的選擇器的插件,這將被視爲)是插件功能的內側(其中一個生活在$.fn)。

$.fn.fnCharsLeftPlgn = function (genStngs) { 
    return $(this).data("charsleft", new fnCharsLeft(this, genStngs)); 
}; 

它應該是:

$.fn.fnCharsLeftPlgn = function (genStngs) { 
    return this.each(function() { 
     $(this).data("charsleft", new fnCharsLeft(this, genStngs)); 
    }); 
}; 

當直接已加入了jQuery原型($.fn)的方法的內部,this指當前集合,而不是元素的全部。一個插件本身應該是each,以便針對其各個成員運行元素特定的邏輯。

沒有使用.each()您打電話給.data()針對整個集合,將其所有charsleft數據屬性設置爲fnCharsLeft的一個實例。通過使用.each(),您將爲集合中的每個元素創建一個新的fnCharsLeft實例。

由於.each()然後返回集合,並且插件應該是可鏈接的,您只需返回它。

經驗法則是,如果您將this直接傳遞到插件中的jQuery工廠($()),那麼函數會因爲它已經是集合而出錯。根據經驗,第二個規則,幾乎是其意圖除了那些所有插件定義返回有關元素的信息(如.val().html(),或.text()沒有給出PARAM時)應與return this.each(function() {...

解決方案啓動:

把這些變化共同作用的結果在這個小提琴:http://jsfiddle.net/5UQ4D/4/

而這種代碼:

(function ($) { 
    var fnCharsLeft = function (ele, genStngs) { 
     this.jqe = $(ele); 
     this.maxChars = genStngs.maxChars; 
     this.fnInit(); 
    }; 
    fnCharsLeft.prototype = { 
     fnInit: function() { 
      var instance = this; 

      this.fnUpdateRemainingChars(); 
      this.jqe.on('keyup', function (e) { 
       key = e.keyCode ? e.keyCode : e.which; 

       if (37 != key && 38 != key && 39 != key && 40 != key) { 
        instance.fnUpdateRemainingChars(); 
       } 
      }); 
     }, 
     fnUpdateRemainingChars: function() { 
      var charsLft = this.maxChars - this.jqe.val().length, 
       jqeDestToUpdt = this.jqe.siblings('.cl'); 

      charsLft = charsLft < 0 ? 0 : charsLft; 

      if (charsLft) { 
       jqeDestToUpdt.text(charsLft + ' more of ' + this.maxChars + ' characters'); 
      } else { 
       this.jqe 
        .val(this.jqe.val().substring(0, this.maxChars)) 
        .scrollTop(this.jqe[0].scrollHeight); 

       jqeDestToUpdt.text("Maximum limit of " + this.maxChars + " characters reached"); 

       return false; 
      } 
     } 
    }; 

    $.fn.fnCharsLeftPlgn = function (genStngs) { 
     return this.each(function() { 
      $(this).data('charsleft', new fnCharsLeft(this, genStngs)); 
     }); 
    }; 
}(window.jQuery)); 
+0

感謝解決方案和信息。對「tisCharsLeftCntxt」有一種奇怪的感覺,不知道是什麼,但評論「踐踏tisCharsLeftCntxt與一個**新的**」和「**全球**變種」 是有道理的。它也可以解決我與其他插件不一致的問題。這可能與主題不符,但是,您是否仍然可以告訴從另一個插件(p2)更改插件(p1)中參數的最佳方法。用例是選擇選項(p1)和搜索輸入(p2)。當輸入(P2)給出時,它應該觸發P1的清除/重置UI。爲了解決這個問題,我使用了全局變量var,結果很糟糕。 – NEB

+0

沒問題,很高興幫助。我不確定自己完全理解你的後續問題,但我會說,對於你在這裏做的事情,我會使用jQuery UI小部件而不是jQuery插件。您可以像插件一樣調用小部件,但它提供了設置選項,處理事件和銷燬的狀態和框架。將插件想象成無狀態 - 運行它們以實現效果,然後它們消失 - 並將小部件作爲有狀態的插件 - 運行它們,實例將繼續進行交互和管理。 – JAAulde