jQueryのone関数の作成方法と注意点

このQ&Aのポイント
  • jQueryのone関数は便利な関数ですが、正しく作成するにはいくつかの注意点があります。
  • one関数を作成するためには、addOneという関数を使用します。addOne関数は、指定した要素に対して一度だけ実行されるイベントを追加します。
  • また、addOne関数を使用する際には、nameとelementの引数を指定することで、要素に名前を付けることができます。しかし、同じ名前を指定した場合には上書きされてしまうので注意が必要です。
回答を見る
  • ベストアンサー

jQuery の one 関数について

jQuery の one 関数は便利だと思い、是非作ってみようと思いましたが、全然出来ません>< 一応以下のように作ってありますが、正しく動作しない上に、name を指定して、 Listener.data オブジェクトにname で保存をするようになっていて、同じnameを渡したら上書きされてしまいます。 どうしたら、jQueryのような、one関数を作れるでしょうか?;; var Listener={ addEvent:function(element,type,callback,useCapture){ if(element.addEventListener){ return element.addEventListener(type,callback,useCapture); } else if(element.attachEvent){ return element.attachEvent('on'+type,callback); } else{ return element['on'+type]=callback; } }, removeEvent:function(element,type,callback,useCapture){ if(element.removeEventListener){ element.removeEventListener(type,callback,useCapture); } else if(element.detachEvent){ element.detachEvent('on'+type,callback); } else{ return false; } return true; }, addOne:function(name,element,type,callback,useCapture){ Listener.addEvent(element,type,callback,useCapture); Listener.addEvent(element,type,function(){ Listener.removeEvent(element,type,); },useCapture); this.data[name]=new Function("Listener.removeEvent("+element+",'"+type+"',Listener.data['"+name+"'],"+useCapture+");+callback); this.addEvent(element,type,this.data[name],useCapture); }, data:{ } }; addEventとremoveEventは正常動作しています。 現在は、 Listener.addOne('name'/*指定しなくてもいいようにしたい*/,'document'/*オブジェクトを渡すと、elementがobjectになり、未定義エラーに*/,function(){alert('OK');},true); となっていますが、目指すは以下のような書き方です。 //仮関数定義 function test(str){ alert(str); } var str='test'; Listener.addOne(document,function(str){test(str);},true); です。 一応、jQueryのone関数を見てみましたが、jQueryは使ったことが無く、あまり分かりませんでした;; 御回答宜しくお願いしますm(_ _)m

質問者が選んだベストアンサー

  • ベストアンサー
  • fujillin
  • ベストアンサー率61% (1594/2576)
回答No.1

よくわかってませんが… ・質問文中「callback」と書いてあるのは、function(←このままじゃまずいけど)のことでは? ・addEventで値をreturnしていますが、戻り値は常にtrueみたいなので、意味があるのだろうか?(未確認です) ・addEventに『element['on'+type]=callback;』があるけれど、removeEventのほうにはこれに対応したものがないのはなぜ?(そもそもこの部分は必要なのかどうか・・・?) などという揚げ足取りは置いておいて・・・ addOne : function(element, type, func, useCapture) としたときに addEventで並列にイベントのバインドとデタッチを定義しようとしているみたいですが、定義の順序と実行順って(同じと)保証されているんでしたっけ?(不確定だったような・・・未確認です) なので、『 func実行後にremoveする 』関数をaddEventするのがよいのでは? addOne : function(element, type, func, useCapture){  Listener.addEvent(element, type, function(){   func();   Listener.removeEvent(element, type, arguments.callee, useCapture);  }, useCapture); } あと、蛇足ですが >var str='test'; >Listener.addOne(document,function(str){test(str);},true); strがグローバルで、それを参照するなら function(){ test(str): } では? 任意の引数を渡したいのなら  (function(a){return function(){test(a)};})("other value") とか?

gorusura
質問者

お礼

arguments.call!! こんなんがあったんですねb 初めて知りました;; おかげで、完成しました^^ また、ご指摘くださった部分も修正して、完成しました^^ 本当にありがとうございましたm(_ _);

関連するQ&A

  • 循環参照とメモリリークに関して

    次のスクリプトはメモリリークを起こしているでしょうか。 function process(listener){ return function(evt){ listener.call(evt.target,evt); }; } function addEvent(element,type,listener,useCapture){ element.addEventListener(element,type,process(listener),useCapture); } var div=document.getElementsByTagName('div')[0]; //存在するものとして addEvent(div,'click',function(){;},false); //いかにも起こしそう div.parentNode.removeChild(div); //親も存在するものとして 工夫してみたものの、やはりメモリリークするんでしょうか。 実際にaddEventListenerのlistener引数に渡されるのは、element変数を参照しない function(evt){ listener.call(evt.target,evt); }; ですが、listener変数は参照します。 そして、そのlistener変数はdiv変数(DOM)を参照するので、ここで循環するのでしょうか。 そして、以下の場合はどうなのでしょうか。。 var elements=[document.getElementsByTagName('div')[0]]; elements[0].addEventListener('click',function(){;},false); elements[0].parentNode.removeChild(elements[0]);

  • jQuery mobileのイベントについて

    jQuery mobile 1.0で使えていたイベントが1.1.1で使えなくなりました。 何か仕様が変わったのでしょうか? よろしくお願いします。 例: $("div:jqmData(role='collapsible')").each(function(){  // ここが機能しなくなった bindEventTouch($(this)); }); function bindEventTouch(element) { element.bind('tap', function(event, ui) { if(element.hasClass('ui-collapsible-collapsed')) { } else { $('#' + element.attr('id') + 'l li').remove(); $('#' + element.attr('id') + 'l').append("<li>I'm Header #FF</li>"); } }); }

  • jQueryが読み込めない

    下記のようにサンプルコードを入力し、同一ファイル内にjsファイルを設置しているのですが、機能せず、ただのテキストボックスが表示されるのみです。 大変初歩的な質問ですが、よろしくお願いします。 ■phpファイル <body> <form action="" method=""> <label for="user-name">お名前</label><input type="text" id="user-name"><br> <label for="user-kana">フリガナ</label><input type="text" id="user-kana"> </form> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <script src="jquery.autoKana.js"></script> <script> $(document).ready(function(){ $.fn.autoKana('#user-name', '#user-kana', {katakana:true}); }); </script> </body> ■jquery.autoKana.js (function ($) { $.fn.autoKana = function (element1, element2, passedOptions) { var options = $.extend( { 'katakana': false }, passedOptions); var kana_extraction_pattern = new RegExp('[^  ぁあ-んー]', 'g'); var kana_compacting_pattern = new RegExp('[ぁぃぅぇぉっゃゅょ]', 'g'); var elName, elKana, active = false, timer = null, flagConvert = true, input; elName = $(element1); elKana = $(element2); active = true; _stateClear(); elName.blur(_eventBlur); elName.focus(_eventFocus); elName.keydown(_eventKeyDown); function start() { active = true; }; function stop() { active = false; }; function toggle(event) { var ev = event || window.event; if (event) { var el = Event.element(event); if (el.checked) { active = true; } else { active = false; } } else { active = !active; } }; function _checkConvert(new_values) { if (!flagConvert) { if (Math.abs(values.length - new_values.length) > 1) { var tmp_values = new_values.join('').replace(kana_compacting_pattern, '').split(''); if (Math.abs(values.length - tmp_values.length) > 1) { _stateConvert(); } } else { if (values.length == input.length && values.join('') != input) { _stateConvert(); } } } }; function _checkValue() { var new_input, new_values; new_input = elName.val() if (new_input == '') { _stateClear(); _setKana(); } else { new_input = _removeString(new_input); if (input == new_input) { return; } else { input = new_input; if (!flagConvert) { new_values = new_input.replace(kana_extraction_pattern, '').split(''); _checkConvert(new_values); _setKana(new_values); } } } }; function _clearInterval() { clearInterval(timer); }; function _eventBlur(event) { _clearInterval(); }; function _eventFocus(event) { _stateInput(); _setInterval(); }; function _eventKeyDown(event) { if (flagConvert) { _stateInput(); } }; function _isHiragana(chara) { return ((chara >= 12353 && chara <= 12435) || chara == 12445 || chara == 12446); }; function _removeString(new_input) { if (new_input.match(ignoreString)) { return new_input.replace(ignoreString, ''); } else { var i, ignoreArray, inputArray; ignoreArray = ignoreString.split(''); inputArray = new_input.split(''); for (i

  • jQueryのload()を使用して外部のhtmlの特定の箇所を、別の

    jQueryのload()を使用して外部のhtmlの特定の箇所を、別のhtmlの特定のセレクに読み込んでいます。ただ、読み込む先のURLが動的に変わるので、変数で扱えたらと考えています。 jQueryの中身の該当する部分と思われる箇所を見てみたのですが、引数で指定されているurlを変数で扱う方法などありませんでしょうか?未熟な知識で申し訳ないのですが、どなた教えていただけませんでしょうか? jqueryのload()を使用しなくても、同じような挙動をする他のおすすめなどもあれば教えていただけると非常に助かります。 【ソース】 $(document).ready(function(){ $("#box_A").load("[URL]←(このurlを変数で扱いたい) #box_B"); }); 【jQueryの中味】 jQuery.fn.extend({ // Keep a copy of the old load _load: jQuery.fn.load, load: function( url, params, callback ) { if ( typeof url !== "string" ) return this._load( url ); var off = url.indexOf(" "); if ( off >= 0 ) { var selector = url.slice(off, url.length); url = url.slice(0, off); } // Default to a GET request var type = "GET"; // If the second parameter was provided if ( params ) // If it's a function if ( jQuery.isFunction( params ) ) { // We assume that it's the callback callback = params; params = null; // Otherwise, build a param string } else if( typeof params === "object" ) { params = jQuery.param( params ); type = "POST"; } var self = this; // Request the remote document jQuery.ajax({ url: url, type: type, dataType: "html", data: params, complete: function(res, status){ // If successful, inject the HTML into all the matched elements if ( status == "success" || status == "notmodified" ) // See if a selector was specified self.html( selector ? // Create a dummy div to hold the results jQuery("<div/>") // inject the contents of the document in, removing the scripts // to avoid any 'Permission Denied' errors in IE .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, "")) // Locate the specified elements .find(selector) : // If not, just inject the full result res.responseText ); if( callback ) self.each( callback, [res.responseText, status, res] ); } }); return this; },  【中略】 });

  • [jQuery] クリックで連番関数を順番に実行

    ボタンをクリックする度に連番で作成した関数を順番に実行したいのですが、スマートな書き方がわかりません。 下記のコードで一応動くのですが、関数が100個とかに増えた場合すごくコードが長くなってしまいます。 もっとスマートに書く方法はないものでしょうか? ▼サンプルコード <html> <head> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <script> $(function(){ function s1(){alert('s1');}; function s2(){alert('s2');}; function s3(){alert('s3');}; var num = 1; $('p').click(function() { if(num == 1){s1();} else if(num == 2){s2();} else if(num == 3){s3();} num++; return false; }); }); </script> </head> <body> <p>click</p> </body> </html>

  • jQueryのfocus,blurが機能しません。

    初めまして。jquery初心者です。宜しくお願いします。 フォームの入力項目に『検索したい言葉を入力してください』だとか、『お名前を入力してください』というテキストが薄い色で入っていて、テキスト内をクリックして入力状態になると、中のテキストが消えるというしくみをjQueryでやっているのですが、上手く行きません。 <HTML> <form name="form1" method="post" action="https://www.rescue.ne.jp/form/mail.cgi"> <p> <label for="namae">お名前</label> <input class="guideText" type="text" name="namae" id="namae" value="お名前を入力してください。"> </p> <p> <label for="email">メールアドレス</label> <input class="guideText" type="text" name="email" id="email" value="メールアドレスを入力してください。"> </p> <p> <label for="comment">お問い合わせ内容</label> <textarea class="guidetext" name="comment" id="comment">メッセージを入力してください。</textarea> </p> <p> <input type="submit" name="button" id="button" value="お問い合わせ送信"> </p> </form> 一番上の『お名前を入力してください。』の部分だけ機能しますが、文字の色が 最初サイトを開くと黒になり、テキストをクリックすると文字が消え、フォーカスを外すと薄いグレーになります。これを、最初から薄いグレーで表示させたいのと、『メールアドレス』『お問い合わせ内容』も同じようにfocus,blurを適用させたいです。 // JavaScript Document $(function(){ $('.guideText').each(function(){ var guideText = this.defaultValue; var element = $(this); element.focus(function(){ if(element.val()===guideText){ element.val(''); element.removeClass('guide'); } }); element.blur(function(){ if(element.val()===''){ element.val(guideText); element.addClass('guide') } }); if(element.val()===guidetext){ element.addClass('guide'); } }); }); <HTML>では、class="guidetext"とすべて適用させてるのに上手く機能しません。 自分では限界なので相談させていただきました。 どうか、宜しくお願い致します。

  • jQueryで要素を取得した後の使い方について

    jQueryでグローバル変数に要素を代入した後にその変数を利用したいのですが記述方法がわかりません。 var element; // クリックしたinputの要素をelementに代入 $(function(){  $("input").click(function(){   element = $(this);  }); }); // elementを利用する function alertEx(){  alert($(element).val()); } alertEx関数を実行するとクリックしたinputの値を表示するようにしたいです。 alertEx関数でのelementの使い方が間違っていると思うのですが、どのように記述すればinputの値をalert表示できるのでしょうか? 知りたいのは、あくまでも要素をelementに代入した後の利用の仕方です。 表示方法とかではないです(上記コードは例です)。 どうぞよろしくお願い致します。

  • チェックしなくても、確認のウインドウがでる

    チェックしなくても、確認のウインドウがでてしまうのですが、どこがいけないのでしょうか <SCRIPT language=JavaScript> function SubmitCheck() } if (document.Order.elements[kiyaku_fn].value == ""){ return false; } else if (document.Order.elements[kiyaku_fn].value == "同意"){ alert("規約に同意して下さい"); return false; } var confirm_str = ""; confirm_str = "下記の事項をご確認ください。\n" + "正しければ、OKを押してください。\n" + "--------------------------------\n" + "規約:" + document.Order.elements[kiyaku_fn].value + "\n\n"; temp = 0; confirm_str += "--------------------------------\n"; if(confirm(confirm_str)){ return true; } else return false; return true; } </SCRIPT> <INPUT id=checkbox1 type=checkbox value="同意" name=checkbox1>規約

  • DOMを使ったjavascript「続きを読む」(表示/非表示 切替え)初期値変更について

    以下は拾ってきたもので、 長い文章の途中に「続きを読む」などと入れて 内容を隠しておくのに使えるものだと思いますが、 設置してみたところ初期値で表示状態になっています。 これを非表示にするには どの値を変更すれば良いでしょうか。 javascriptの知識がないので、教えて下さい。 // イベントリスナーの追加 function addEvent(node, evt, func) { if (node.addEventListener) { node.addEventListener(evt, func, false); } else if (node.attachEvent) { node.attachEvent("on" + evt, func); } } // イベントがあった要素を得る function getTarget(e) { if (e.target) { return e.target; } else if (e.srcElement) { return e.srcElement; } } // イベントリスナーの割り当て function setHandler() { // 文書内のdiv要素を列挙する var divElements = document.getElementsByTagName('div'); for (var i = 0; i < divElements.length; i++) { // div要素の直下の階層にあるh4要素を得る var h4Element = divElements[i].getElementsByTagName('h4')[0]; // h4要素のclickイベントにイベントリスナーを割り当てる addEvent(h4Element, "click", showHide); } } // h4要素と同じ階層にあるp要素の表示/非表示を切り替える function showHide(e) { // クリックされたh4要素を得る var h4Element = getTarget(e); // h4要素と同じ階層にあるp要素を得る var parent = h4Element.parentNode; var pElement = parent.getElementsByTagName('p')[0]; // p要素の表示/非表示を切り替える pElement.style.display = (pElement.style.display == 'none') ? '' : 'none'; } // イベントリスナーを割り当てる addEvent(window, "load", setHandler);

  • jquery,ajaxによるphp通信でnull

    初めまして。 現在jqueryを勉強中の学生です。 いろいろなサイトを参考にしつつ、試しににjquery・ajaxを使ったphpとの通信を試みているのですが、文字列のやりとりがうまくいきません。 数字ではうまくいくのですが、文字になるとalertの部分でnullと返されてしまいます。 アドバイス等頂ければと思います。 よろしくお願いいたします。 以下部分的ではありますがコードを示します。 (jqueryはjquery-1.11.1.min.jsを使用) [js] $.ajax({ type: "POST", url: "step1.php", data: send_data, success: function(receive_data) { var parseAr = JSON.parse(receive_data); alert(parseAr[0]['name']); }, error: function(XMLHttpRequest, textStatus, errorThrown) {alert('Error: ' + errorThrown); } }); return false; [php側] <?php if(isset($_POST['name'])) { $result = array(); $result[] = array('name'=>'織田', 'age'=>'33'); $result[] = array('name'=>'織田', 'age'=>'33'); echo json_encode($result); } else { echo json_encode('The parameter of "name" is not found.'); } exit; ?>

専門家に質問してみよう