On 28/02/2007, at 8:17 AM, Joel Birch wrote:
> On 28/02/2007, at 12:29 AM, Klaus Hartl wrote:
>> Joel Birch schrieb:
>>> Hi jQuerivites,
>>>
>>> I'd like to offer up my humble plugin (humble is the key word here)
>>> to get a sense of if something this basic is of any worth to the
>>> community.
>>
>> I think its useful! Here's some work for you ;-)
>>
>> * Instead of doing two appends you could do:
>>
>> $('<div class="'+o.divClass+'"></div>').append([o.head,
>> $list]).insertBefore(this.eq(0));
>>
>> * Instead of using this.innerHtml you should use $(this).text() to
>> avoid
>> nested links for example. Imagine article headlines that are links as
>> well but should also serve as content navigation hook.
>>
>> Another useful option would be to specify where to append the created
>> navigation. I could imagine appending it to the body and apply a  
>> fixed
>> positioning, so that it is always in the viewport...
>>

Hi Klaus, I've done my homework :D

Firstly, I reduced those two appends to one. I found that .append 
(o.head,$list) works - you must have made a typo with the square  
brackets but that was easy to figure out anyway.

Secondly, inspired by your prompt to reduce function calls, I rewrote  
how the list was compiled by creating a string of the whole list  
before appending that to the list. This made the whole plugin run  
more than twice as fast as before (~30ms for 19 list items instead of  
~80ms).

Finally, I made it so you can target where the list is inserted as  
you suggested. There is a new option called "insertMethod" that takes  
one of "insertBefore", "insertAfter", "append" or "prepend", and  
another new option called "insertTarget" which takes a jQuery object.

So now if you want to append the list to the body you can do:
$("h2").contentMenu({"insertMethod":"append","insertTarget":$("body")});

The default is to .insertBefore(this.eq(0));

Obviously the code has grown larger, mainly due to the switch used to  
parse the insertMethod option. Can you think of a better way of doing  
that whilst avoiding eval()?

I have learnt a lot doing this so thanks for humouring me Klaus - I  
know you are very busy at the moment. Oh, here's the new code:

(function($) {
$.fn.contentMenu = function(o){
        o = $.extend({  "head" : "<h3>Some handy links to help you navigate  
this page:</h3>",
                                        "divClass" : "contentMenu",
                                        "aClass"        : "inPage",
                                        "insertMethod" : "insertBefore",
                                        "insertTarget" : this.eq(0) }, o || {});
        $.cmCount = $.cmCount+1 || 0;
        var $list = $("<ul>");
        var lastInd = this.length-1;
        var lis = '';
        var menu = $('<div class="'+o.divClass+'"></div>').append(o.head, 
$list);
        switch (o.insertMethod){
                case "insertBefore":
                        menu.insertBefore(o.insertTarget);
                        break;
                case "insertAfter":
                        menu.insertAfter(o.insertTarget);
                        break;
                case "append":
                        o.insertTarget.append(menu);
                        break;
                case "prepend":
                        o.insertTarget.prepend(menu);
                        break;
                default :
                        menu.insertBefore(o.insertTarget);
        }
        return this.each(function(i){
                this.id = this.id || "menu"+$.cmCount+"-el"+i;
                lis += '<li><a href="#'+this.id+'" class="'+o.aClass+'">Skip to 
 
<em>'+$(this).text()+'</em></a></li>';
                if (i==lastInd){ $list.append(lis); }
        });
};
)(jQuery);

Cheers
Joel.


_______________________________________________
jQuery mailing list
discuss@jquery.com
http://jquery.com/discuss/

Reply via email to