Reputation: 1614
for given tag I need to wrap it with quite a few elements. So that user can put
<img src="img.gif" >
but outcome would be
<div class="total">
<div class="cover">
<div class="crop">
<img src="img.gif" alt>
</div>
<div class="hover">
<div class="peel">
<div class="links">
<a href="#">FB</a>
</div>
</div>
</div>
</div>
</div>
So i decided to make it into jQuery plugin. And here is piece of it
(function($) {
$.fn.peel = function(options) {
var defaults = {};
var settings = $.extend({},defaults, options);
return this.each(function() {
$(this).load(function() {
var image = $(this);
var total = $('<div />', {'class' : 'total'});
var cover = $('<div />', {'class' : 'cover'});
var crop = $('<div />', {'class': 'crop'});
var hover = $('<div />', {'class' : 'hover'});
var peel = $('<div />', {'class' : 'peel'});
var links = $('<div />', {'class' : 'links'});
var a = $('<a>', {'href' : '#', 'text' : 'FB'});
//Chaining begins here
image.wrap(crop);
crop.after(hover);
});
});
};
})(jQuery);
At first i make variables with divs i will use. But i am having hard time making it all together this time.. I left 2 lines which doesnt want to work with chaining. At first i am wrapping image with crop, and then i am adding hover div after crop div. But... 2nd line doesn't work. I tried in numerous ways. No luck so far. Seems like it is impossible to add something that is added with "wrap". Maybe I am doing wrong, so maybe someone of you could help ? :)
Thanks.
Upvotes: 3
Views: 134
Reputation: 926
you can achieve that in this way:
image.wrap(total).wrap(cover).wrap(crop)
.closest('.crop')
.after(a.wrap(hover).wrap(peel).wrap(links).closest('.hover'));
@dystroy's answer is not totally correct: you can insert thing after a node in memory
cover.append(crop).append(hover).appendTo('body');
you'll find all the 3 nodes were appended to DOM
the key point is $.wrap
. when you wrap something, not like other operation, jQuery will create a new copy, at this time, the wrapper in the dom is not the same reference with the one created in memory any more.
take the first line as example:
var domCrop = image.wrap(total).wrap(cover).wrap(crop)
.closest('.crop');
console.log(domCrop.is(crop)); //false, domCrop and the corp in mem not point to the same ref
the last but not least, in actually, I don't like this way to extend the dom node. it made the code hard to write and maintain.
here's my solution:
(function($) {
$.fn.peel = function(options) {
var defaults = {};
var settings = $.extend({},defaults, options);
var html = '<div class="total">'
+ ' <div class="cover">'
+ ' <div class="crop"></div>'
+ ' <div class="hover">'
+ ' <div class="peel">'
+ ' <div class="links">'
+ ' <a href="#">FB</a>'
+ ' </div>'
+ ' </div>'
+ ' </div>'
+ ' </div>'
+ '</div>';
return this.each(function() {
$(this).load(function() {
var $image = $(this);
//introduced a placeholder.
//not to replace the $image directly, just for keeping all the event handler bound to $image.
var $placeholder = $('<span/>').insertAfter($image);
$(html).find('.crop').append($image)
.end()
.replaceAll($placeholder);
});
});
};
})(jQuery);
jsFiddle Demo: http://jsfiddle.net/vF4QH/1/
Upvotes: 1
Reputation: 382160
DOM manipulations on elements not inserted in the page might be a little tricky.
after
, for example, can only work on an element having a parent. Here is its implementation :
after: function() {
return this.domManip( arguments, false, function( elem ) {
if ( this.parentNode ) {
this.parentNode.insertBefore( elem, this.nextSibling );
}
});
},
Similarly, wrap
will call before
which has a symmetric implementation.
What works is to build your tree by using append
and starting from the most external element :
cover.append(crop);
crop.append(image);
cover.append(hover);
Upvotes: 2
Reputation: 21742
Why not simply build a tempalte once and for all like this
var htmlTemplate = '<div class="total">'
htmlTemplate += ' <div class="cover">';
htmlTemplate += ' <div class="crop"></div>';
htmlTemplate += ' <div class="hover">';
htmlTemplate += ' <div class="peel">';
htmlTemplate += ' <div class="links">';
htmlTemplate += ' <a href="#">FB</a>';
htmlTemplate += ' </div>';
htmlTemplate += ' </div>';
htmlTemplate += ' </div>';
htmlTemplate += ' </div>';
htmlTemplate += '</div>';
Then when you need it you can do something like the below code to insert the image tag
var selection = $(htmlTemplate);
selection.find('.crop').html('<img src="img.gif" alt>');
and finally append it somewhere in the DOM
//substitute body for where you wish to place the result
$("body").append(selection)
Upvotes: 0