2010-12-28 14 views
2

私はかなりの数ヶ月間JS(主にjQuery)を書いてきましたが、今日は最初の抽象化をjQueryメソッドとして作成することにしました。私はすでに作業コードを持っていますが、私は正しい方法でやっていないと感じているので、私はここにいくつかの啓発のために来ます。宣言時にjQueryメソッドを呼び出し、次にonEvent

注:私が既に知っているように、そのトリックを行う何かがすでにあると返答しないでください。この問題に対する私の関心はむしろ教育的です。私のコードを実行するためのもの(とし)は何

:テキストフィールドの文字と、ユーザが終わりに近づいているとき、カウンターの色を変更

リミット。

そして、ここで私が持っているものです。

HTMLで
$(function(){ 

    $('#bio textarea').keyup(function(){ 
    $(this).char_length_validation({ 
     maxlength: 500, 
     warning: 50, 
     validationSelector: '#bio .note' 
    }) 
    }) 

    $('#bio textarea').trigger('keyup'); 

}) 


jQuery.fn.char_length_validation = function(opts){ 

    chars_left = opts.maxlength - this.val().length; 

    if(chars_left >= 0){ 
    $(opts.validationSelector + ' .value').text(chars_left); 

    if(chars_left < opts.warning){ 
     $(opts.validationSelector).addClass('invalid'); 
    } 
    else{ 
     $(opts.validationSelector).removeClass('invalid'); 
    } 
    } 
    else{ 
    this.value = this.value.substring(0, opts.maxlength); 
    } 
} 

<div id="bio"> 
    <textarea>Some text</textarea> 
    <p class="note> 
    <span class="value">XX</span> 
    <span> characters left</span> 
    </p> 
</div> 

特に私は、それぞれからkeyupに各イベントを結合の代わりに、一度結合し、後でメソッドを呼び出して、本当に不快に感じます。

また、(したがってタイトルも)最初に(ページがレンダリングされるとき)メソッドを呼び出す必要があり、ユーザーが文字を入力するたびに呼び出す必要があります。あなたの時間:)

答えて

1

を事前に

おかげであなたが行うことができます方法でトリガ結合し、初期:

jQuery.fn.charLengthValidation = function(opts) { 
    return this.keyup(function() { 
     var charsLeft = opts.maxLength - $(this).val().length; 
     if (charsLeft >= 0) { 
      $(opts.validationSelector + ' .value').text(charsLeft); 
      $(opts.validationSelector).toggleClass('invalid', charsLeft < opts.warning); 
     } else { 
      $(this).val($(this).val().substring(0, opts.maxLength)); 
     } 
    }).trigger('keyup'); 
} 

$(function() { 
    $('#bio textarea').charLengthValidation({ 
     maxLength: 25, 
     warning: 10, 
     validationSelector: '#bio .note' 
    }); 
}); 
+0

'this'はすでにjQueryオブジェクトです。 –

+0

私は知っている:)。ちょうどそれについて読んでいた。 – Heikki

+0

とてもエレガントです。それは有り難いです! – cesarsalazar

2

chars_leftは全然良くないグローバル変数です。ここには、より良い(わずかに変更された)バージョンがあります:

jQuery.fn.char_length_validation = function(opts) { 
    this.each(function() { 
     var chars_left = opts.maxlength - $(this).val().length; 
     $(this).keyup(function() { 
      chars_left = opts.maxlength - $(this).val().length; 
      if (chars_left >= 0) { 
       $(opts.validationSelector).text(chars_left); 
       if (chars_left < opts.warning) { 
        $(opts.validationSelector).addClass('invalid'); 
       } 
       else { 
        $(opts.validationSelector).removeClass('invalid'); 
       } 
      } 
      else { 
       $(this).val($(this).val().substring(0, opts.maxlength)); 
      } 
     }); 
    }); 
    this.keyup(); // makes the "initial" execution 
    return this; 
}; 

DEMOを参照してください。

いくつかの説明:関数でjQueryプラグインで

  • thisは、セレクタによって選択された要素を指します。 this.each()を使用してこれらのすべてをループし、それに応じてすべての要素を設定する必要があります。
  • この例では、すべての要素がchars_leftという変数になります。 keyup()に渡されたイベントハンドラは、クロージャであるため、そのイベントハンドラにアクセスできます。 更新:既にここでは非常に遅いです;)とにかく毎回値を再計算するので、ここで宣言する必要はありません。それでも、それはあなたが私的変数をどのように時間の経過とともに持続するかという考えを与えるべきです。
  • 連鎖をサポートするには、常にreturn thisにする必要があります。

さらに思考:

  • あなたはそれが(すなわち、あなたが検証セレクタについて考える必要が)いくつかのテキストエリアのために働く作ることができるかを考えることもできます。それを特定の構造に結びつけないでください。
  • デフォルトのオプションが必要です。
  • 更新:もちろん、(jQuery関数のように)1つのテキストエリアでのみプラグインを動作させることができます。
+0

この例では、 'this.each()'ループは本当に必要ではありませんが、そうですか?そして、各要素は実際に 'chars_left'変数を必要としません。なぜなら、それはkeyupイベントハンドラにもスコープできるからです。 – Heikki

+0

非常に有用な答えは、Heikkiのものと組み合わせて、それは私にその主題のより良い理解を与えました。あまりにも悪い私は1つしか受け入れることができません。ありがとうございました! – cesarsalazar

+0

@Heikki:普遍的なものにしたいのであれば、 'this.each'を使うことをお勧めします。 * I *がプラグインを作成している場合は、複数の要素が選択されている場合でもプラグインが機能することを確認します。しかし、はい、イベントハンドラに 'chars_left'を置くことができますが、それは非常に時間を要するからです。それでも、私的変数を持つ方法を示しています。 –

関連する問題