2017-06-23 5 views
0

基本オプションチェーンの親子関係を使って選択メニューを表示したり非表示にする次のコードがあります。変更があったら、私は関数を呼び出す必要があります。複数の変更イベントでjQuery約束を使用する方法

現在、私は以下のようにして、<select>ごとにイベントが発生したときにそれを呼び出して、その関数を呼び出します。実際の生活では、これはアヤックスコールですが、それは質問には関係ありません。

以下のコードは、です。私が解決したい問題は、関数が複数回不必要にトリガされるため、変更イベントに頼らずにこれをどのように達成できるかということです。親が変更されたときに$.each()ループの最後に関数呼び出しを配置するだけですが、アニメーションが関係しているため、問題の要素が表示/非表示になることがあるため失敗します。私はそれぞれslideUp()slideDown()の中にコールバックを置くことでこれを解決しましたが、これが私が何度も何度もトリガを引き起こす正確な理由です。

.promise()メソッドは、一度バウンド特定のタイプのすべてのアクションを解決され、動的に生成された約束を返します。

は私が探しています答えは述べてjQueryの promise()を使用して強い気持ちを持っていますキューに入れられたかどうかのコレクションは、終了しました。

これはまさに私がやりたいことですが、私は完全にpromise()で混乱していて、それは正しい使い方です。私はコンセプトを得ましたが、どのようにすべての変更イベントを1つのpromise()にキューイングして、すべてが完了したら私の関数を呼び出すことができるかを理解するのに役立ちます。

$('select[data-parent="true"]').change(function() { 
 
    var parentValue = +this.value; 
 
    var parentId = $(this).data('parent_id'); 
 
    $('div[data-parent_id="' + parentId + '"]').each(function() { 
 
    var parentValues = $(this).data('parent_values'); 
 
    if (parentValues.indexOf(parentValue) !== -1) { 
 
     $(this).slideDown(1000, function() { 
 
     $(this).find('select').change(); 
 
     }); 
 
    } else { 
 
     $(this).slideUp(1000, function() { 
 
     $(this).find('select').change(); 
 
     }); 
 
    } 
 
    }); 
 
}); 
 
$('select').on('change', function() { 
 
    var results = ''; 
 
    $('div.option').each(function() { 
 
    results += $(this).find('select').prop('name') + ' IS VISIBLE: ' + +$(this).is(':visible') + '<br>'; 
 
    }); 
 
    $('#results').html(results); 
 
});
div { 
 
    padding: 5px 10px; 
 
} 
 

 
div.child { 
 
    display: none 
 
} 
 

 
select { 
 
    width: 200px; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> 
 
<div class="option"> 
 
    <select name="container" data-parent="true" data-parent_id="10"> 
 
    <option value="">--- Select a container---</option> 
 
\t \t <option value="1">Box</option> 
 
\t \t <option value="2">Bag</option> 
 
\t \t <option value="3">Pallet</option> 
 
\t </select> 
 
</div> 
 
<div class="child option" data-parent_id="10" data-parent_values="[1]"> 
 
    <select name="box color"> 
 
\t \t <option value="100">Red</option> 
 
\t \t <option value="200">Blue</option> 
 
\t </select> 
 
</div> 
 
<div class="child option" data-parent_id="10" data-parent_values="[2]"> 
 
    <select name="bag color"> 
 
\t \t <option value="300">Green</option> 
 
\t \t <option value="400">Yellow</option> 
 
\t </select> 
 
</div> 
 
<div class="child option" data-parent_id="10" data-parent_values="[3]"> 
 
    <select name="pallet color"> 
 
\t \t <option value="500">Black</option> 
 
\t \t <option value="600">Yellow</option> 
 
\t </select> 
 
</div> 
 
<div id="results"> 
 
</div>

答えて

1

jQueryのアニメーションが約束.promise().map代わりの.eachを使用して返すことができたよう - コードは単純になります

$('select[data-parent="true"]').change(function() { 
 
    var parentValue = +this.value; 
 
    var parentId = $(this).data('parent_id'); 
 
    $.when.apply($, $('div[data-parent_id="' + parentId + '"]').map(function(i, v) { 
 
     var parentValues = $(this).data('parent_values'); 
 
     if (parentValues.indexOf(parentValue) !== -1) { 
 
      return $(this).slideDown(1000).promise(); 
 
     } else { 
 
      return $(this).slideUp(1000).promise(); 
 
     } 
 
    })).done(function() { 
 
     var results = ''; 
 
     $('div.option').each(function() { 
 
      results += $(this).find('select').prop('name') + ' IS VISIBLE: ' + +$(this).is(':visible') + '<br>'; 
 
     }); 
 
     $('#results').html(results); 
 
    }); 
 
});
div { 
 
    padding: 5px 10px; 
 
} 
 

 
div.child { 
 
    display: none 
 
} 
 

 
select { 
 
    width: 200px; 
 
    margin: 4px; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> 
 
<div class="option"> 
 
    <select name="container" data-parent="true" data-parent_id="10"> 
 
    <option value="">--- Select a container---</option> 
 
\t \t <option value="1">Box</option> 
 
\t \t <option value="2">Bag</option> 
 
\t \t <option value="3">Pallet</option> 
 
\t </select> 
 
</div> 
 
<div class="child option" data-parent_id="10" data-parent_values="[1]"> 
 
    <select name="box color"> 
 
\t \t <option value="100">Red</option> 
 
\t \t <option value="200">Blue</option> 
 
\t </select> 
 
</div> 
 
<div class="child option" data-parent_id="10" data-parent_values="[2]"> 
 
    <select name="bag color"> 
 
\t \t <option value="300">Green</option> 
 
\t \t <option value="400">Yellow</option> 
 
\t </select> 
 
</div> 
 
<div class="child option" data-parent_id="10" data-parent_values="[3]"> 
 
    <select name="pallet color"> 
 
\t \t <option value="500">Black</option> 
 
\t \t <option value="600">Yellow</option> 
 
\t </select> 
 
</div> 
 
<div id="results"> 
 
</div>

+0

ありがとうございます - 私はいつも 'map()'のファンであり、これは適切で、これは私が思いついたよりもエレガントで直感的です私自身。 – billynoah

+0

私はこのトピックについてのQ&Aはもっと一般的ではないことに驚いています。私はカップル良いスレッドを見つけたが、これはおそらくすべての時間が来るという事実を考えると、私が期待するほど多くはない。私は、多くの人がそれが動作し、20イベントが必要なときにトリガーされることを気にしないという内容のコンテンツだと思います。 – billynoah

0

実験の時間は、以下の溶液を得ました。 $.Deferred()オブジェクトの配列を作成し、$.whenを使用してそれらを解決します。複雑な部分はthis answerにあり、配列を$.whenに渡す方法が説明されています。これは私がしたようにjQueryの繰延オブジェクトに苦しんで誰かを助けホープ:

$('select[data-parent="true"]').change(function() { 
 
    var deferred = []; 
 
    var parentValue = +this.value; 
 
    var parentId = $(this).data('parent_id'); 
 
    $('div[data-parent_id="' + parentId + '"]').each(function(i, v) { 
 
    deferred[i] = $.Deferred(); 
 
    var parentValues = $(this).data('parent_values'); 
 
    if (parentValues.indexOf(parentValue) !== -1) { 
 
     $(this).slideDown(1000, function() { 
 
     deferred[i].resolve(); 
 
     }); 
 
    } else { 
 
     $(this).slideUp(1000, function() { 
 
     deferred[i].resolve(); 
 
     }); 
 
    } 
 
    }); 
 
    $.when.apply($, deferred).done(function() { 
 
    var results = ''; 
 
    $('div.option').each(function() { 
 
     results += $(this).find('select').prop('name') + ' IS VISIBLE: ' + +$(this).is(':visible') + '<br>'; 
 
    }); 
 
    $('#results').html(results); 
 
    }); 
 
});
div { 
 
    padding: 5px 10px; 
 
} 
 

 
div.child { 
 
    display: none 
 
} 
 

 
select { 
 
    width: 200px; 
 
    margin: 4px; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> 
 
<div class="option"> 
 
    <select name="container" data-parent="true" data-parent_id="10"> 
 
    <option value="">--- Select a container---</option> 
 
\t \t <option value="1">Box</option> 
 
\t \t <option value="2">Bag</option> 
 
\t \t <option value="3">Pallet</option> 
 
\t </select> 
 
</div> 
 
<div class="child option" data-parent_id="10" data-parent_values="[1]"> 
 
    <select name="box color"> 
 
\t \t <option value="100">Red</option> 
 
\t \t <option value="200">Blue</option> 
 
\t </select> 
 
</div> 
 
<div class="child option" data-parent_id="10" data-parent_values="[2]"> 
 
    <select name="bag color"> 
 
\t \t <option value="300">Green</option> 
 
\t \t <option value="400">Yellow</option> 
 
\t </select> 
 
</div> 
 
<div class="child option" data-parent_id="10" data-parent_values="[3]"> 
 
    <select name="pallet color"> 
 
\t \t <option value="500">Black</option> 
 
\t \t <option value="600">Yellow</option> 
 
\t </select> 
 
</div> 
 
<div id="results"> 
 
</div>

+1

もちろん、jQueryアニメーションが "ネイティブ"な約束を返すことができることを知っていて、.eachの代わりに.mapを使うと、コードはさらに簡素化できます。https://jsfiddle.net/0ruud9xL/ –

+0

これはまさに最もクールなことです私は終日見た。あなたはそれを別の答えとして掲示し、私はそれを喜んで受け入れたものとしてマークします。ありがとう! – billynoah

+0

答えが追加されました - 私はそれをテストしませんでしたが、今すぐテストしました –

関連する問題