QA@IT

フォームに入力された値をリアルタイムに取得しクッキーに書き込む処理について

5102 PV

質問失礼いたします。

表題の挙動を実現すべく下記のコードを書いてみました。Emailを入力するテキストフィールドに入力された値をkeyupイベントをバインドしてクッキーに書き込もうとしています。

しかし実際の挙動は、2文字以上を入力した際にはクッキーに書き込まれるようですが、1文字だけ入力した際にはクッキーに書き込まれず意図した挙動となりません。

どうすれば1文字だけ入力した際にもクッキーに書き込むことができるのかが今の自分の知識では分かりませんでしたので、こちらで質問させていただいた次第です。

初歩的な質問で恐縮ですがご教示いただけますと幸いです。よろしくお願いいたします。

function FormManager(data) {  
  this.cookieData = data.cookieData;
};
FormManager.prototype = {
  writeCookie : function (CurrentField, eventName) {
    var form = this.cookieData;
    for (var key in form) {
      if (form[key] === CurrentField) {
        $(CurrentField).each(function() {
          $(this).bind(eventName, writeCookieCoreProcess(key))
        });
      }
    }
  }
};

function writeCookieCoreProcess(cookieName) {
  return function() {
    var value = $(this).val();
    setCookie(cookieName, value);
  }
}

function setCookie(name, value, expires, domain, path, secure) {
  var cookie = '';
  cookie += name + '=' + encodeURIComponent(value);

  if (expires) {
    var exp = new Data();
    exp.setData(exp.getData() + expires);
    cookie += '; expires=' + exp.toGMTString();
  }
  if(domain) {cookie += '; domain=' + domain;}
  if(path) {cookie += '; path =' + path;}
  if(secure) {cookie += '; secure';}

  document.cookie = cookie;
}

function addressFormCookieNameData() {
  cookieNameData = {
    "email":document.getElementById('text-field-email')
  };
}

// イベント処理
addListener(window, 'load', init);

function init() {  
  var email = document.getElementById('text-field-email');
  addListener(email, 'keyup', function() {whenTextFieldKeyupped(this)});
}
function whenTextFieldKeyupped(CurrentField) {
  var addressForm = new FormManager({cookieData:addressFormCookieNameData()});
  addressForm.writeCookie(CurrentField, "keyup");  
}

【追記】お礼を誤って投稿してしまったままだったので、投稿削除に伴いお礼の内容を質問に記載します

2013/08/27 1:37

flied_onionさん

ご回答いただき誠にあがとうございます。

お教えいただいた方法

まずはwhenTextFieldKeyuppedでFormManager使わずに
setCookie("email",$(CurrentField).val()); などして
動くようにしてからFormManagerを適用する様にしたほうが良いでしょう。

を試したところ1文字の取得に成功いたしました。質問した段階ではイベントのバインドについての理解が曖昧だったようで、大変助かりました。ありがとうございました。

FormManagerのfor (var key in form) { で何がしたいのか

これはaddressFormCookieNameData()関数で設定したDataが複数存在する場合に、Dataとアクティブなフォームオブジェクトを比較して処理を適用するオブジェクトを指定するためのもので、今回質問に記載したコードにおいては不要となっています。

「キー押すたびにbindされ続け」ている気がする

本件については、まだ試行していませんが、都度unbindを呼んで対応しようと思います。ご指摘いただきありがとうございました。

これでようやく満足できるコードが実装できそうです。この度は、ご丁寧にご教示いただきまして誠にありがとうございました。

またご縁がございましたらよろしくお願いいたします。

【追記】「都度unbindを呼んで対応」について、不要であることが分かりました

2013/08/27 1:37

「都度unbindを呼んで対応」について、不要であることが分かりましたので情報共有いたします。

▼EventTarget.addEventListener - Web API リファレンス | MDN
https://developer.mozilla.org/ja/docs/Web/API/EventTarget.addEventListener?redirectlocale=ja&redirectslug=DOM%2FEventTarget.addEventListener

上記リンクにて、

複数の同一のイベントリスナー 複数の同一の EventListener が、同じ EventTarget に同じ引数で登録された場合、重複するインスタンスは反映されません。EventListener が 2 度呼び出されることはなく、重複するインスタンスは反映されないので、removeEventListener で手動で削除する必要はありません。

という内容を確認しました。

  • そもそもそのsetCookieという関数で1文字をクッキーに登録できますか? -
  • コメントいただきありがとうございます。ご指摘いただいたsetCookie関数を記載し忘れておりました。失礼いたしました…。こちらの関数で、クッキーに登録はできております。 -
  • setCookie関数で1文字がクッキーにセットできているかについて、onloadイベントが発生した際にcookieの値をdivタグのテキストにセットするようにして確認したところ、1回目のリロードでは登録されておらず2回目のリロードにより登録されているようです。keyupイベントについても同様に1回目のイベント発生をバインドできていない可能性があります。引き続き検証してみます。 -
  • 追記ありがとうございます、参考になります。 -
  • とんでもないです。いつもご丁寧にコメントいただき、ありがとうございます。 -

回答

ざっと見た感じでは初回のイベント時は
FormManagerの

for (var key in form) {
  if (form[key] === CurrentField) {
    $(CurrentField).each(function() {
      $(this).bind(eventName, writeCookieCoreProcess(key))
    });
  }
}

で、イベントがバインドされるのみで writeCookieCoreProcessは呼び出されないからじゃないでしょうか。

それとは別で、これだとキー押すたびにbindされ続けたりはしないのですか?
実際に動作で確認してないので特に自信はないですが。

編集 履歴 (0)
  • ご返信いただきありがとうございます。そして、回答が遅れまして申し訳ございません。

    ご指摘の箇所を例えば
    for (var key in form) {
    if (form[key] === CurrentField) {
    writeCookieCoreProcess(key)
    }
    }
    -
  • のようにしてみましたが、上手く値が取得できず苦慮しております…。さらに、ご指摘の通り「キー押すたびにbindされ続け」ている気がするのですが、やはり別の方法が浮かばず対応できていません。どのような方法で表題の挙動を実装できるのか本日も行き詰まっている状況です…。また何かございましたらアドバイスなどよろしくお願いいたします。 -
  • コメントがないので、どこでどういう事がしたいのかわからないですね。FormManagerのfor (var key in form) { で何がしたいのかわからないです。 setCookieはちゃんと動きそうですから、まずはwhenTextFieldKeyuppedでFormManager使わずにsetCookie("email",$(CurrentField).val()); などして -
  • 動くようにしてからFormManagerを適用する様にしたほうが良いでしょう。 -
  • ご回答いただきありがとうございます。いただいた内容につきまして、火曜日以降に時間を取ってご返答&試行してみたいと思います。恐れ入りますが今しばらくお待ちくださいますようお願いいたします。 -
  • ご回答いただき誠にありがとうございます。お教えいただいた方法を試したところ1文字の取得に成功いたしました。質問した段階ではイベントのバインドについての理解が曖昧だったようで、大変助かりました。ありがとうございました。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。