Reputation: 26281
I wish to clone the innerhtml
of an element (#clone
) and insert it into another element (#newLocation
).
The problem with using clone()
is that I will have first delete the elements (if any) currently in #newLocation
, then iterate over each element in #clone
and append it to #newLocation
. It's not the end of the world, but I'm hoping for a simpler way.
Instead, I thought I'd use html()
. Since this won't preserve events, I would have to delegate the even using ON
. I had thought this would work, however, it doesn't.
Any suggestions what I am doing wrong? Also, think it would be more efficient to use the clone()
solution even if I can get html()
solution working?
EDIT: Just wrote my very first plugin: http://jsfiddle.net/Wnr65/ which seems to work. Good idea to use? Sure it could be written better.
$(document).ready(function(){
$("#cloneIt").click(function(){$('#newLocation').cloneInnerHtml('clone').css('color', 'red');});
$("#clone a").click(function(){alert("click");});
$("#clone select").change(function(){alert("change");});
});
(function( $ ){
$.fn.cloneInnerHtml = function( id ) {
this.empty();
var $t=this;
$('#'+id).each(function() {$t.append($(this).clone(true));});
return this;
};
})( jQuery );
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Clone INNERHTML</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js" language="javascript"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#cloneIt").click(function(){$('#newLocation').html($('#clone').html());});
//Only works on original clone
$("#clone a").on("click", function(){alert("click");});
$("#clone select").on("change", function(){alert("change");});
//Doesn't work at all
$("#newLocation a").on("click", function(){alert("click");});
$("#newLocation select").on("change", function(){alert("change");});
});
</script>
</head>
<body>
<input type="button" value="Clone it" id="cloneIt" />
<p>Original clone is shown below</p>
<div id="clone">
<a href="#">Click Me</a>
<select><option>Hello</option><option>Goodby</option></select>
</div>
<hr />
<p>Insert new clones below.</p>
<div id="newLocation">
<p class="someOldElement">someOldElement</p>
</div>
</body>
</html>
Upvotes: 1
Views: 4616
Reputation: 4912
It is normal that your code doesn't react as you want. When you do
$("#clone a").on("click", function() {
alert("click");
});
it will bind click
event to the elements which match the #clone a
selector. Those elements are determined at the moment of the execution. In your case, this line bind the event to the first and only link present in the page.
The same rule apply for the code
$("#newLocation a").on("click", function() {
alert("click");
});
but the difference here is that, at the moment of execution, there is no a
element inside #newLocation
, so the selection is empty and the handler is not bound at all.
Then, when you do
$('#newLocation').html( $('#clone').html() );
it will get the HTML content from one element and copy it into another element, but it's only about HTML content, so the event binding still the same as before the "copy operation".
The on method has different syntax, and only one allow the event delegation:
// get all current "a" elements inside the "#clone"
// and bind the click event
$( "#clone a" ).on( "click", handler );
// get the "#clone" element, bind a click event to it
// BUT trigger the event only when the origin of the event is an "a" element
// here the event delegation is enabled
// it means that future "a" elements will trigger the handler
$( "#clone" ).on( "click", "a", handler );
// if you want it to work with your code
// you could do something like below
// this add a click handler to all present and future "a" elements
// which are inside "#clone" or "#newLocation"
// but this is not the recommended way to do this, check below the clone method
$("#clone, #newLocation").on("click", "a", handler);
clone
method doesn't remove the elements, here is a working demo http://jsfiddle.net/pomeh/G34SE/
HTML code
<div class="source">
<a href="#">Some link</a>
</div>
<div class="target">
</div>
CSS code
div {
width: 100px;
height: 25px;
}
.source {
border: solid red 1px;
}
.target {
border: solid blue 1px;
}
Javascript code
var $element = $("a"),
$target = $(".target"),
$clone;
$element.on("click", function( ev ) {
ev.preventDefault();
console.log("click");
});
$clone = $element.clone( true );
$clone.appendTo( $target );
The method also receive a parameter indicating whether event handlers should be copied along with the elements http://api.jquery.com/clone/
Upvotes: 2
Reputation: 1981
Edit: I got it to work with .on
Here's a fiddle. Also check out the jQuery API for .on and take a look at the "Direct and delegated events" section
$("#clone a").on("click", function(){alert("click");});
$("#clone select").on("change", function(){alert("change");});
$("#newLocation").on("click", "a", function(){alert("click");});
$("#newLocation").on("change", "select", function(){alert("change");});
Upvotes: 1