동적으로 <select>
요소를 생성 하고 jQuery로 전환 할 수 있어야합니다 .combobox()
. 이것은 jQuery를 사용할 수있는 일부 “클릭”이벤트와는 반대로 요소 생성 이벤트 여야합니다 .on()
.
그렇다면 이와 같은 것이 존재합니까?
$(document).on("create", "select", function() {
$(this).combobox();
}
나는 매우 구식이기 때문에 livequery를 사용하기를 꺼립니다.
업데이트 언급 한 select / combobox는 ajax를 통해 jQuery colorbox (모달 창)에로드되므로 문제는 colorbox를 사용하여 combobox 만 시작할 수 onComplete
있지만 하나의 콤보 박스를 변경하면 다른 선택 / 콤보 박스를 동적으로 생성해야합니다. 요소 생성을 감지하는보다 일반적인 방법 ( select
이 경우).
UPDATE2 문제를 더 시도하고 설명하기 위해- select/combobox
재귀 적으로 생성 된 요소가 있고 내부에 많은 시작 코드가 .combobox()
있으므로 @bipen의 답변 과 같은 고전적인 접근 방식을 사용하면 코드가 미친 수준으로 부 풀릴 것입니다. 이것이 문제를 더 잘 설명하기를 바랍니다.
UPDATE3 모두에게 감사합니다. 이제 사용 중단 이후 DOMNodeInserted
DOM 변이에 공백이 남아 있으며이 문제에 대한 해결책이 없다는 것을 이해합니다. 내 응용 프로그램을 다시 생각해야 할 것입니다.
답변
당신은 할 수 이벤트는이 코드가 문서에 추가되는 경우에 대한 이벤트를 얻을 수 있습니다.on
DOMNodeInserted
$('body').on('DOMNodeInserted', 'select', function () {
//$(this).combobox();
});
$('<select>').appendTo('body');
$('<select>').appendTo('body');
여기에 Fiddled : http://jsfiddle.net/Codesleuth/qLAB2/3/
편집 : 주변을 읽은 후 DOMNodeInserted
브라우저에서 문제가 발생하지 않는지 다시 확인해야 합니다. 2010 년 의이 질문 은 IE가 이벤트를 지원하지 않는다는 것을 암시하므로 가능하면 테스트하십시오.
여기를보십시오 : [link] 경고! DOMNodeInserted 이벤트 유형은 참조 및 완전성을 위해이 사양에 정의되어 있지만이 사양 은이 이벤트 유형의 사용을 중단 합니다.
답변
DOMNodeInserted
돌연변이 이벤트 를 사용할 수 있습니다 (위임 필요 없음).
$('body').on('DOMNodeInserted', function(e) {
var target = e.target; //inserted element;
});
답변
다른 여러 답변에서 언급했듯이 돌연변이 이벤트 는 더 이상 사용되지 않으므로 MutationObserver 를 사용해야합니다. 대신 를 합니다. 아직 아무도 그것에 대해 자세히 설명하지 않았기 때문에 여기에 간다 …
기본 JavaScript API
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 });
이렇게하면 관찰자가 시작됩니다. 첫 번째 인수는 관찰자가 변경 사항을 감시 할 노드입니다. 두 번째 인수는 감시 대상에 대한 옵션입니다 .
childList
추가되거나 제거되는 자식 요소를보고 싶다는 의미입니다.subtree
이 요소의 하위 트리 어디에서나 변경 사항을 감시 하도록 확장 되는 수정 자입니다childList
(그렇지 않으면에서 직접 변경 사항을 확인합니다targetNode
).
그 외의 다른 두 가지 주요 옵션 childList
은 attributes
및 characterData
입니다. 이 세 가지 중 하나를 사용해야합니다.
function callback(records) {
records.forEach(function (record) {
콜백 내부에서 상황이 조금 까다로워집니다. 콜백은 MutationRecord 배열을 수신합니다 . 각 MutationRecord 한 유형의 몇 가지 변화를 설명 할 수 있습니다 ( childList
, attributes
또는 characterData
). 관찰자에게를 보라고 만 말 childList
했으므로 유형을 확인하지 않겠습니다.
var list = record.addedNodes;
여기에서 추가 된 모든 자식 노드의 NodeList를 가져옵니다. 노드가 추가되지 않은 모든 레코드에 대해 비어 있습니다 (이러한 레코드가 많을 수 있음).
거기에서 추가 된 노드를 반복하고 <select>
요소 인 .
여기에 정말 복잡한 것은 없습니다.
jQuery
…하지만 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 에서 라이브로 볼 수 있습니다 .
노트
이 jQuery 코드는 상당히 기본적인 구현입니다. 다른 곳에서 수정하여 선택기를 유효하게 만드는 경우에는 트리거되지 않습니다.
예를 들어 선택기가이고 .test select
문서에 이미 <select>
. 에 클래스 test
를 추가하면 <body>
선택기가 유효하지만 record.target
및 만 확인하기 때문에 record.addedNodes
이벤트가 발생하지 않습니다. 선택하려는 요소가 변경되어야합니다.
이것은 변이가 발생할 때마다 선택자를 쿼리하여 피할 수 있습니다. 이미 처리 된 요소에 대해 중복 이벤트가 발생하지 않도록하기 위해 그렇게하지 않기로 결정했습니다. 인접 하거나 일반적인 형제 결합 자를 올바르게 처리 하면 상황이 더욱 까다로워집니다.
보다 포괄적 인 솔루션 은 Damien Ó Ceallaigh 의 답변 에서 언급했듯이 https://github.com/pie6k/jquery.initialize를 참조 하십시오 . 그러나 해당 라이브러리의 작성자는 라이브러리가 오래되었다고 발표했으며이를 위해 jQuery를 사용하지 말 것을 제안했습니다.
답변
내 모든 아약스 문제를 해결할 수있는이 솔루션을 생각해 냈습니다.
준비된 이벤트의 경우 이제 다음을 사용합니다.
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');
});
답변
플러그인 adampietrasiak / jquery.initialize가 있으며 ,이를 기반으로 MutationObserver
간단하게 수행 할 수 있습니다.
$.initialize(".some-element", function() {
$(this).css("color", "blue");
});
답변
이 DOM4 MutationObservers
작업은 가능하지만 Firefox 14 + / Chrome 18+ (현재)에서만 작동합니다.
그러나 IE10, Firefox 5+, Chrome 3+, Opera 12, Android 2.0+, Safari 4+와 같은 CSS3 애니메이션을 지원하는 모든 브라우저에서 작동 하는 ” 장대 한 해킹 “(저자의 말이 아닙니다!)이 있습니다. 블로그 에서 데모 를 참조하십시오 . 해킹은 JavaScript에서 관찰되고 실행되는 주어진 이름의 CSS3 애니메이션 이벤트를 사용하는 것입니다.
답변
한 가지 방법은, 같다 (단지 파이어 폭스와 크롬에서 테스트하지만) 신뢰성은 수신 자바 스크립트를 사용하는 것입니다 animationend
(또는 낙타 표기법, 그리고 형제, 접두사 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에 있지만 축약 된 접두사 버전 제거됨) 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
참조 :