동적으로 생성 된 요소에 대한 jQuery "생성시"이벤트
동적으로 <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
(그렇지 않으면 그냥 직접 내 변화에 보일 것이다 어느 곳이 요소의 하위 트리의 변화를보고 <body>
). 다른 두 가지 중요한 가능성은 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 에서 라이브로 볼 수 있습니다 .
(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
이벤트가 발생하지 않습니다. 선택하려는 요소가 변경되어야합니다.
이것은 변이가 발생할 때마다 선택자를 쿼리하여 피할 수 있습니다. 이미 처리 된 요소에 대해 중복 이벤트가 발생하지 않도록하기 위해 그렇게하지 않기로 결정했습니다. 인접 하거나 일반적인 형제 결합 자를 올바르게 처리 하면 상황이 더욱 까다로워집니다.
보다 포괄적 인 솔루션 은 Damien Ó Ceallaigh 의 답변 에서 언급했듯이 https://github.com/pie6k/jquery.initialize를 참조 하십시오 .
내 모든 아약스 문제를 해결하는 것 같은이 솔루션을 생각해 냈습니다.
준비된 이벤트의 경우 이제 다음을 사용합니다.
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+, Opera 12, Android 2.0+, Safari 4+와 같은 CSS3 애니메이션을 지원하는 모든 브라우저에서 작동 하는 " 장대 한 해킹 "(저자의 말이 아닙니다!)이 있습니다. 블로그 에서 데모 를 참조하십시오 . 해킹은 JavaScript에서 관찰되고 실행되는 주어진 이름의 CSS3 애니메이션 이벤트를 사용하는 것입니다.
One way, which seems reliable (though tested only in Firefox and Chrome) is to use JavaScript to listen for the animationend
(or its camelCased, and prefixed, sibling animationEnd
) event, and apply a short-lived (in the demo 0.01 second) animation to the element-type you plan to add. This, of course, is not an onCreate
event, but approximates (in compliant browsers) an onInsertion
type of event; the following is a proof-of-concept:
$(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
});
With the following HTML:
<div class="wrapper">
<button class="add">add a div element</button>
</div>
And (abbreviated, prefixed-versions-removed though present in the Fiddle, below) 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;
}
Obviously the CSS can be adjusted to suit the placement of the relevant elements, as well as the selector used in the jQuery (it should really be as close to the point of insertion as possible).
Documentation of the event-names:
Mozilla | animationend
Microsoft | MSAnimationEnd
Opera | oanimationend
Webkit | webkitAnimationEnd
W3C | animationend
References:
- caniuse.com summary of compatibility of CSS Animations.
- CSS AnimationEvent Interface (W3C).
- JavaScript
animationend
vendor-support.
For me binding to the body does not work. Binding to the document using jQuery.bind() does.
$(document).bind('DOMNodeInserted',function(e){
var target = e.target;
});
There is a plugin, adampietrasiak/jquery.initialize, which is based on MutationObserver
that achieves this simply.
$.initialize(".some-element", function() {
$(this).css("color", "blue");
});
create a <select>
with id , append it to document.. and call .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();
this should do the trick.. you can hide the select if you want and after .combobox
show it..or else use find..
$(document).find('select').combobox() //though this is not good performancewise
if you are using angularjs you can write your own directive. I had the same problem whith bootstrapSwitch. I have to call $("[name='my-checkbox']").bootstrapSwitch();
in javascript but my html input object was not created at that time. So I write an own directive and create the input element with <input type="checkbox" checkbox-switch>
In the directive I compile the element to get access via javascript an execute the jquery command (like your .combobox()
command). Very important is to remove the attribute. Otherwise this directive will call itself and you have build a loop
app.directive("checkboxSwitch", function($compile) {
return {
link: function($scope, element) {
var input = element[0];
input.removeAttribute("checkbox-switch");
var inputCompiled = $compile(input)($scope.$parent);
inputCompiled.bootstrapSwitch();
}
}
});
참고URL : https://stackoverflow.com/questions/15268661/jquery-on-create-event-for-dynamically-created-elements
'programing tip' 카테고리의 다른 글
싱글 톤이 안티 패턴으로 간주되는 이유는 무엇입니까? (0) | 2020.11.02 |
---|---|
Pandas DataFrame에 메타 정보 / 메타 데이터 추가 (0) | 2020.11.02 |
단편화 여부-활동에 대한 중첩 단편. (0) | 2020.11.02 |
Swift #selector 구문으로 "모호한 사용"컴파일 오류를 해결하려면 어떻게해야합니까? (0) | 2020.11.02 |
Python 및 Django와 함께 사용할 HAML 구현이 있습니까? (0) | 2020.11.02 |