7449


お世話になってます  
初心者ですがなにとぞよろしくお願いします。

`<select>` 要素の値が変わったことをトリガーに見栄えが変わるjQueryのプラグインを作成中です。

`<select>`
の選択が「他のスクリプト」によって変更されたときにjQueryでそのイベントを取得したいと考えています。「他のスクリプト」は不特定です。

jQueryにおいて

[code]

    $('select').change(myFnc);
    
[/code]

ですがスクリプトによる操作では、myFncは呼び出されません。  
（スクリプトによる変更は発火しない、と解釈しています）。

「他のスクリプト」で値が変更された場合にもイベントをとりたいので、

[code]

    $('select').val('hoge').trigger('change');
    
[/code]

としたいところですが、当然「他のスクリプト」は不特定なのでそれはできません。

なにとぞアドバイスをお願いします。


CC BY-SA 3.0
2015-03-04T14:45:44.370
7446
2015-03-12T08:53:08.983
2015-03-05T17:14:47.437
30
8013
question
javascript jquery
select 要素の値が他のスクリプトによって変更された場合にイベントを受け取りたい


かなり強引ですが、`setTimeout`を使えば擬似的な`change`トリガを作れます。

ただ、`select`を選択中(確定前)にも値が変わってしまいます。  
この動作が許容できれば`.val()`で値取得していれば良いと思います。

[code]

    $(document).ready(function() {
        checkSelect();
    });
    
    var selectValue = 1;
    function checkSelect(){
    
        if(selectValue != $("select").val()){
            // changeイベントと同等
            $("div").text($("select").val());
        }
    
        selectValue = $("select").val();
    
        // 250msec後に再チェック
        setTimeout(function(){checkSelect();}, 250);
    }
[/code]

[code]

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div></div>
    
    <select>
        <option value="1" selected>aaa</option>
        <option value="2">bbb</option>
        <option value="3">ccc</option>
    </select>
[/code]


CC BY-SA 3.0
2015-03-04T15:29:28.337
7449
2015-03-05T00:33:40.627
2015-03-05T00:33:40.627
7214
7214
7446
answer


いろんな意味で良くない方法だと思いますが…  
スクリプトでselectedを設定すると仮定してこれって出来るかな？

[code]

    function sss(a,b){ //値変更時用
      delete a.selected;
      a.selected = b;
      a.__defineSetter__("selected", function(y) { 
      alert('chenge!');//実行したいfunction
      sss(a,y) });
    }
    
    //個別にoptionタグにsetterを設定
    var xxx = document.getElementsByTagName('option')[0];
    xxx.__defineSetter__("selected", function(y) { 
      alert('chenge!');//実行したいfunction
      sss(xxx,y); });
    
[/code]

※適当に書いたコードです。  
※__defineSetter__は非推奨です。

* * *

** 2015/03/12 追記**

少し調べて書いてみました。

「他のスクリプト」によってプロパティに代入される時に  
発火するイベント自体を作ってしまうという発想です。

set/getを使った方が良いかもしれませんね。  
<https://stackoverflow.com/questions/10592753/how-to-define-setter-getter-on-
prototype>

[code]

    var useSetter = true;
    
    //emulate legacy getter/setter API using ES5 APIs より抜粋
    //http://blogs.msdn.com/b/ie/archive/2010/09/07/transitioning-existing-code-to-the-es5-getter-setter-apis.aspx
    try {
       if (!Object.prototype.__defineGetter__ &&
        Object.defineProperty({},"x",{get: function(){return true}}).x) {
      Object.defineProperty(Object.prototype, "__defineGetter__",
         {enumerable: false, configurable: true,
          value: function(name,func)
             {Object.defineProperty(this,name,
                 {get:func,enumerable: true,configurable: true});
      }});
      Object.defineProperty(Object.prototype, "__defineSetter__",
         {enumerable: false, configurable: true,
          value: function(name,func)
             {Object.defineProperty(this,name,
                 {set:func,enumerable: true,configurable: true});
      }});
       }
    } catch(defPropException) {
     alert(' "__defineGetter__" & "defineProperty" 非対応です。');
     useSetter = false;
    /*Do nothing if an exception occurs*/
    };
    
    
    if (useSetter){//初期設定
     var opts = document.getElementsByTagName('option');
     for (var i = 0; i < opts.length;i++) {
       (function (i) {
     opts[i].__defineSetter__('selected', function (y) {
       alert('chenge! :'+i); //実行したいfunction
       seta_sel(opts[i], y);
     });
       })(i);
     }
    }
    
    function seta_sel(a,b){ //値変更時の処理
      delete a.selected; // 自身が代入の邪魔をするのでselectedを消して作り直す
      a.selected = b;
      a.__defineSetter__("selected", function(y) {  //setterを設定 
      alert('chenge! :'+(a.value-1));//実行したいfunction
      seta_sel(a,y) });
    }
    
    //選択変更スクリプト
    function check(x){
     var opts = document.getElementsByTagName('option')[x-1].selected=true;
    }
    
    function check2(x){ //jquery版
      $("select#sel1").val(x);
    }
[/code]

[code]

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div></div>
    
    <select id="sel1" name="seln1">
        <option value="1" selected>aaa</option>
        <option value="2">bbb</option>
        <option value="3">ccc</option>
    </select>
    
    <br><input type="button" onclick="check('1');" value="リストaaaを選択">
    <br><input type="button" onclick="check('2');" value="リストbbbを選択">
    <br><input type="button" onclick="check('3');" value="リストcccを選択">
    
    <br>jqueryだと他のoptionを初期化するからそれも発火してしまいます…
    <br><input type="button" onclick="check2('3');" value="リストcccをjqueryで選択">
[/code]

もっとスマートに出来る方法無いかしら…


CC BY-SA 3.0
2015-03-05T10:51:00.953
7485
2015-03-12T08:53:08.983
2017-05-23T12:38:56.467
-1
5479
7446
answer