Wish
Wish

Reputation: 1614

jquery making html

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

Answers (3)

Rain Diao
Rain Diao

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

Denys S&#233;guret
Denys S&#233;guret

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

Rune FS
Rune FS

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

Related Questions