Reputation: 7808
So I know about jQuery's .on() function to give dynamically added element's event handlers.
E.g I've used it this way
$(document).on("change",Items,function(){/*Code here*/});
But is there a way to use this .on() function (or something else) to call a function once an object has been appended into the document? I ask this because I'm using a jquery plugin called Chosen which creates better select boxes, and it works by using the line
$(selector).chosen();
However that line doesn't work if it's used before an element is appended into the document, and for the sake of the cleanliness of my code it would be nice if I could call a function to run that line when the element has been appended, instead of adding that line after I've appended the element.
Edit: The problem isn't that I can't use .chosen() after I've appended the element. Because I can! I just want to be able to keep my code better organised by not having the $(selector).chosen() line hidden all the way at the bottom of my code unnoticed.
My code:
//Create the dropdown box for the items
var Items = document.createElement("select");
$(Items).attr( {"id":"Items"} );
$(document).on("change",Items,
function(){
updateHolder(true);
$(InfoBox).trigger("chosen:updated");
setTimeout(
function(){
$(Items).data('chosen').input_blur();
}, 100
);
}
);
//Add items from ED.listOfItems to HTML Items dropdown box
for(var it in ED.listOfItems){
var iKey = ED.listOfItems[it];
var itemOption = document.createElement("option");
if(!Array.isArray(iKey)){
$(itemOption).val(iKey);
$(itemOption).html(iKey.split("_")[0]);
}
else{
$(itemOption).val(iKey[0]);
$(itemOption).html(iKey[1]);
}
$(Items).append( itemOption );
}
/*******Set default to spawn*******/
/**/ ED.objectType = "Spawn"; /**/
/**/ ED.infoType = ""; /**/
/**/ $(Items).val("Spawn"); /**/
/**********************************/
$(MenuBar).append(Items);
$(Items).chosen({disable_search_threshold: 100});
$("#Items_chosen").css({"width":"100px","position":"absolute","left":"5px","top":"20px"});
As you can see, the 2nd to last line is the chosen line, but it just seems to be in an illogical place to me. I'm very OCD with my code :P
Upvotes: 2
Views: 9615
Reputation: 2824
I had the problem of add a class to an element i've created and appended, since this class have transition, css transitions doesn't work if element is not in the DOM tree, all solutions i've tried didn't work for me so i ended up with this workaround:
elementParent.append(elementToAdd);
setTimeout(() => {
$(elementToAdd).addClass("show");
}, 0);
In this way the class will be added only after the element has been added in the DOM.
Upvotes: 0
Reputation: 7808
I just found the answer I needed on another question, but it was never accepted. The answer is by Mario Bellart, Fire OnAppend event for jQuery element when it gets appended to the DOM
How I adapted his code
//Create the dropdown box for the items
var Items = document.createElement("select");
$(Items).attr( {"id":"Items"} );
$(document).on("append", Items,
function(){
$(Items).chosen({disable_search_threshold: 100});
$("#Items_chosen").css({"width":"100px","position":"absolute","left":"5px","top":"20px"});
}
);
$(document).on("change",Items,
function(){
updateHolder(true);
$(InfoBox).trigger("chosen:updated");
setTimeout(
function(){
$(Items).data('chosen').input_blur();
}, 100
);
}
);
//Add items from ED.listOfItems to HTML Items dropdown box
for(var it in ED.listOfItems){
var iKey = ED.listOfItems[it];
var itemOption = document.createElement("option");
if(!Array.isArray(iKey)){
$(itemOption).val(iKey);
$(itemOption).html(iKey.split("_")[0]);
}
else{
$(itemOption).val(iKey[0]);
$(itemOption).html(iKey[1]);
}
$(Items).append( itemOption );
}
/*******Set default to spawn*******/
/**/ ED.objectType = "Spawn"; /**/
/**/ ED.infoType = ""; /**/
/**/ $(Items).val("Spawn"); /**/
/**********************************/
$(MenuBar).append(Items).trigger("append");
I did not know about .trigger() and creating custom events. Maybe I should do some more reading up.
Upvotes: 1
Reputation: 54
You can use livequery plugin https://github.com/brandonaaron/livequery, the best solution would be absolutely https://developer.mozilla.org/en-US/docs/Web/Guide/DOM/Events/Mutation_events ,but browser support is really poor.
Upvotes: 1
Reputation: 21758
(Edit OP is delegating document
doesn't fire a change
event.change
)
If you cannot manually bind .chosen()
after you append
, then you may want to look into MutationObserver
, though the browser support is fairly bleeding edge.
Upvotes: 1
Reputation: 8376
Maybe there's a better way, but I usually add a class like "to_replace" to newly created elements, and then use:
$(".to_replace").each(function() {
$(this).removeClass("to_replace").choosen();
})
each time I changed anything.
Upvotes: 3