<select>
要素を動的に作成し、jQuery .combobox()
に変換できるようにする必要があります。これは、jQuery .on()
を使用できる「クリック」イベントではなく、要素作成イベントである必要があります。
それで、このようなものは存在しますか?
$(document).on("create", "select", function() {
$(this).combobox();
}
Livequeryは非常に時代遅れなので、使用することに消極的です。
UPDATE前述の選択/コンボボックスは、ajaxを介してjQueryカラーボックス(モーダルウィンドウ)にロードされるため、問題-カラーボックスを使用してコンボボックスのみを開始できますonComplete
ただし、1つのコンボボックスを変更すると、別のselect/comboboxを動的に作成する必要があるため、要素の作成を検出するより一般的な方法が必要です(この場合はselect
)。
UPDATE2さらに問題を説明するために-select/combobox
要素を再帰的に作成しました。また、.combobox()
内に多くの開始コードがあります。 @ bipen's answer のような古典的なアプローチを使用した場合、私のコードは非常識なレベルに膨らみます。これが問題をよりよく説明することを願っています。
UPDATE3皆さん、ありがとうございます。DOMNodeInserted
が非推奨になったため、DOMミューテーションにボイドが残っており、この問題の解決策がないことを理解しました。アプリケーションを再考する必要があります。
on
DOMNodeInserted
イベントを使用すると、コードによってドキュメントに追加されたときのイベントを取得できます。
$('body').on('DOMNodeInserted', 'select', function () {
//$(this).combobox();
});
$('<select>').appendTo('body');
$('<select>').appendTo('body');
ここで調整: http://jsfiddle.net/Codesleuth/qLAB2/3/
編集:DOMNodeInserted
を再確認するだけで、ブラウザ間で問題が発生することはありません。 この質問 2010年からIEはイベントをサポートしていないことが示唆されているため、可能であればテストしてください。
こちらをご覧ください: [link]警告! DOMNodeInsertedイベントタイプは、参照と完全性のためにこの仕様で定義されていますが、この仕様 deprecates このイベントタイプの使用
DOMNodeInserted
突然変異イベントを使用できます(委任は不要です):
$('body').on('DOMNodeInserted',function(e){ var target = e.target; //inserted element; });
編集: 突然変異イベント aredeprecated、代わりに mutation observer を使用
他のいくつかの回答で述べたように、 mutation events は廃止されているため、代わりに MutationObserver を使用する必要があります。まだ誰も詳細を教えていないので、ここに行きます...
MutationObserverのAPIは非常にシンプルです。突然変異イベントほど単純ではありませんが、それでも大丈夫です。
function callback(records) {
records.forEach(function (record) {
var list = record.addedNodes;
var i = list.length - 1;
for ( ; i > -1; i-- ) {
if (list[i].nodeName === 'SELECT') {
// Insert code here...
console.log(list[i]);
}
}
});
}
var observer = new MutationObserver(callback);
var targetNode = document.body;
observer.observe(targetNode, { childList: true, subtree: true });
<script>
// For testing
setTimeout(function() {
var $el = document.createElement('select');
document.body.appendChild($el);
}, 500);
</script>
それを分解しましょう。
var observer = new MutationObserver(callback);
これにより、オブザーバーが作成されます。オブザーバーはまだ何も見ていません。これは、イベントリスナーが接続される場所です。
observer.observe(targetNode, { childList: true, subtree: true });
これにより、オブザーバーが起動します。最初の引数は、オブザーバーが変更を監視するノードです。 2番目の引数は、 監視対象のオプション です。 childList
は、追加または削除される子要素を監視することを意味します。 subtree
はchildList
を拡張した修飾子であり、この要素のサブツリーの任意の場所の変更を監視します(そうでない場合は、<body>
内で直接変更を確認します)。他の2つの重要な可能性はattributes
とcharacterData
です。これは、それらがどのように聞こえるかを意味します。
function callback(records) {
records.forEach(function (record) {
コールバック内では、少し注意が必要です。コールバックは MutationRecord sの配列を受け取ります。各MutationRecordは、1つのタイプ(childList
、attributes
、またはcharacterData
)のいくつかの変更を記述することができます。オブザーバーにchildList
を監視するように指示しただけなので、タイプの確認は気にしません。
var list = record.addedNodes;
ここで、追加されたすべての子ノードのNodeListを取得します。これは、ノードが追加されていないすべてのレコードで空になります(そのようなレコードが多数ある場合があります)。
そこから、追加されたノードをループし、<select>
要素であるものを見つけます。
ここでは本当に複雑なことは何もありません。
...しかし、jQueryを要求しました。いいよ.
(function($) {
var observers = [];
$.event.special.domNodeInserted = {
setup: function setup(data, namespaces) {
var observer = new MutationObserver(checkObservers);
observers.Push([this, observer, []]);
},
teardown: function teardown(namespaces) {
var obs = getObserverData(this);
obs[1].disconnect();
observers = $.grep(observers, function(item) {
return item !== obs;
});
},
remove: function remove(handleObj) {
var obs = getObserverData(this);
obs[2] = obs[2].filter(function(event) {
return event[0] !== handleObj.selector && event[1] !== handleObj.handler;
});
},
add: function add(handleObj) {
var obs = getObserverData(this);
var opts = $.extend({}, {
childList: true,
subtree: true
}, handleObj.data);
obs[1].observe(this, opts);
obs[2].Push([handleObj.selector, handleObj.handler]);
}
};
function getObserverData(element) {
var $el = $(element);
return $.grep(observers, function(item) {
return $el.is(item[0]);
})[0];
}
function checkObservers(records, observer) {
var obs = $.grep(observers, function(item) {
return item[1] === observer;
})[0];
var triggers = obs[2];
var changes = [];
records.forEach(function(record) {
if (record.type === 'attributes') {
if (changes.indexOf(record.target) === -1) {
changes.Push(record.target);
}
return;
}
$(record.addedNodes).toArray().forEach(function(el) {
if (changes.indexOf(el) === -1) {
changes.Push(el);
}
})
});
triggers.forEach(function checkTrigger(item) {
changes.forEach(function(el) {
var $el = $(el);
if ($el.is(item[0])) {
$el.trigger('domNodeInserted');
}
});
});
}
})(jQuery);
これにより、 jQuery特殊イベントAPI を使用して、domNodeInserted
という新しいイベントが作成されます。次のように使用できます。
$(document).on("domNodeInserted", "select", function () {
$(this).combobox();
});
一部のライブラリはテスト目的でselect
要素を作成するため、個人的にクラスを探すことをお勧めします。
当然、.off("domNodeInserted", ...)
を使用するか、次のようなデータを渡すことで監視を微調整することもできます。
$(document.body).on("domNodeInserted", "select.test", {
attributes: true,
subtree: false
}, function () {
$(this).combobox();
});
これにより、本体内の要素の属性が直接変更されるたびに、select.test
要素の外観のチェックがトリガーされます。
下または jsFiddle でライブで確認できます。
(function($) {
$(document).on("domNodeInserted", "select", function() {
console.log(this);
//$(this).combobox();
});
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
// For testing
setTimeout(function() {
var $el = document.createElement('select');
document.body.appendChild($el);
}, 500);
</script>
<script>
(function($) {
var observers = [];
$.event.special.domNodeInserted = {
setup: function setup(data, namespaces) {
var observer = new MutationObserver(checkObservers);
observers.Push([this, observer, []]);
},
teardown: function teardown(namespaces) {
var obs = getObserverData(this);
obs[1].disconnect();
observers = $.grep(observers, function(item) {
return item !== obs;
});
},
remove: function remove(handleObj) {
var obs = getObserverData(this);
obs[2] = obs[2].filter(function(event) {
return event[0] !== handleObj.selector && event[1] !== handleObj.handler;
});
},
add: function add(handleObj) {
var obs = getObserverData(this);
var opts = $.extend({}, {
childList: true,
subtree: true
}, handleObj.data);
obs[1].observe(this, opts);
obs[2].Push([handleObj.selector, handleObj.handler]);
}
};
function getObserverData(element) {
var $el = $(element);
return $.grep(observers, function(item) {
return $el.is(item[0]);
})[0];
}
function checkObservers(records, observer) {
var obs = $.grep(observers, function(item) {
return item[1] === observer;
})[0];
var triggers = obs[2];
var changes = [];
records.forEach(function(record) {
if (record.type === 'attributes') {
if (changes.indexOf(record.target) === -1) {
changes.Push(record.target);
}
return;
}
$(record.addedNodes).toArray().forEach(function(el) {
if (changes.indexOf(el) === -1) {
changes.Push(el);
}
})
});
triggers.forEach(function checkTrigger(item) {
changes.forEach(function(el) {
var $el = $(el);
if ($el.is(item[0])) {
$el.trigger('domNodeInserted');
}
});
});
}
})(jQuery);
</script>
このjQueryコードは、かなり基本的な実装です。他の場所での変更によりセレクタが有効になった場合はトリガーされません。
たとえば、セレクタが.test select
であり、ドキュメントに既に<select>
があるとします。クラスtest
を<body>
に追加すると、セレクターが有効になりますが、record.target
およびrecord.addedNodes
のみをチェックするため、イベントは発生しません。変更は、それ自体を選択する要素に発生する必要があります。
これは、突然変異が発生するたびにセレクターを照会することで回避できます。既に処理された要素に対してイベントが重複することを避けるために、私はそうしないことを選択しました。 隣接 または 一般的な兄弟コンビネータ を適切に処理すると、事態はさらに複雑になります。
より包括的なソリューションについては、 https://github.com/pie6k/jquery.initialize を参照してください DamienÓCeallaigh の answer =。
私のすべてのajaxの問題を解決するように思われるこのソリューションを思いついた。
準備完了のイベントでは、これを使用します。
function loaded(selector, callback){
//trigger after page load.
$(function () {
callback($(selector));
});
//trigger after page update eg ajax event or jquery insert.
$(document).on('DOMNodeInserted', selector, function () {
callback($(this));
});
}
loaded('.foo', function(el){
//some action
el.css('background', 'black');
});
そして、通常のトリガーイベントには、これを使用します。
$(document).on('click', '.foo', function () {
//some action
$(this).css('background', 'pink');
});
これは DOM4 MutationObservers
で実行できますが、Firefox 14 +/Chrome 18+(現在)でのみ機能します。
ただし、IE10、Firefox 5以降、Chrome 3以降のCSS3アニメーションをサポートするすべてのブラウザで機能する「 epic hack 」(著者の言葉は私のものではありません!) Opera 12、Android 2.0 +、Safari 4+。ブログの demo を参照してください。このハッキングは、JavaScriptで監視および実行される特定の名前のCSS3アニメーションイベントを使用することです。
プラグイン adampietrasiak/jquery.initialize があり、これは単純にこれを実現するMutationObserver
に基づいています。
$.initialize(".some-element", function() {
$(this).css("color", "blue");
});
seems信頼できる(FirefoxとChromeでのみテストされています)1つの方法は、JavaScriptを使用してanimationend
(またはそのcamelCased 、接頭辞付きの兄弟animationEnd
)イベント、追加する予定の要素タイプに短命(デモでは0.01秒)のアニメーションを適用します。もちろん、これはonCreate
イベントではなく、(準拠ブラウザーで)onInsertion
タイプのイベントに近似しています。以下は概念実証です。
$(document).on('webkitAnimationEnd animationend MSAnimationEnd oanimationend', function(e){
var eTarget = e.target;
console.log(eTarget.tagName.toLowerCase() + ' added to ' + eTarget.parentNode.tagName.toLowerCase());
$(eTarget).draggable(); // or whatever other method you'd prefer
});
次のHTMLを使用します。
<div class="wrapper">
<button class="add">add a div element</button>
</div>
そして(以下のFiddleに存在するものの、省略された、prefixed-versions-removed)CSS:
/* vendor-prefixed alternatives removed for brevity */
@keyframes added {
0% {
color: #fff;
}
}
div {
color: #000;
/* vendor-prefixed properties removed for brevity */
animation: added 0.01s linear;
animation-iteration-count: 1;
}
明らかに、CSSは、jQueryで使用されるセレクターと同様に、関連する要素の配置に合わせて調整することができます(実際には、可能な限り挿入ポイントに近いはずです)。
イベント名のドキュメント:
Mozilla | animationend
Microsoft | MSAnimationEnd
Opera | oanimationend
Webkit | webkitAnimationEnd
W3C | animationend
参照:
私にとって、体への結合は機能しません。 jQuery.bind()を使用してドキュメントにバインドします。
$(document).bind('DOMNodeInserted',function(e){
var target = e.target;
});
idで<select>
を作成し、ドキュメントに追加し、.combobox
を呼び出します
var dynamicScript='<select id="selectid"><option value="1">...</option>.....</select>'
$('body').append(dynamicScript); //append this to the place your wanted.
$('#selectid').combobox(); //get the id and add .combobox();
これでうまくいくはずです..必要に応じて選択を非表示にし、.combobox
を表示した後、またはfindを使用してください。
$(document).find('select').combobox() //though this is not good performancewise