开发者

Best plugin development practices to avoid polluting jQuery namespace?

I have created a jQuery plugin that allows the user to interact with a tree (creating, updating, deleting nodes). There are at least a dozen methods for interacting with the tree. Ideally, I don’t want to pollute the jQuery namespace with all of these tree-specific methods as I am doing now as each methods presents an additional opportunity for a namespace collision. I just want the one method for activating the plug开发者_运维百科in itself and so I am looking to refactor.

$('ol#tree').tree(options) // just a single jQuery method for my plugin is fine…
$('li#item4').moveNode('li#item6') // …however, we also have this supporting method
$('ol#tree').appendNode(node) // …and this one
$('li#item2').expandBranch() // …and this one, etc.

What are some practices for exposing an interface to the activated DOM element and its sub-elements that don’t pollute the jQuery namespace?

I have toyed with saving jQuery object that comes back when I create the tree.

var tree =  $('ol#tree').tree();

This tree object itself would be extended to include the methods. Unfortunately, as the tree itself is being regularly manipulated, this runs the risk of having the state of that object fall out of sync with the state of the parent DOM element and its sub-elements. I’m not sure trying to maintain state in that object is worth it, since the DOM itself will always have the current state.

I have also considered using a namespace (via John Resig’s Space plugin):

$('ol#tree').tree()
$('ol#tree').tree.appendNode(node)
$('ol#tree').tree.item('li#item2').expandBranch()

How do you handle this problem? Could you point me to some existing plugins that address this issue from whose code I could learn?


Use a short and crisp name! Not the boring tree, but for example nicetree (Hey, this is just an idea)! Put the interface into the name. Like this:

$("ol#tree").nicetree.appendNode(node);
$("ol#tree").nicetree.item("li#item2").expandBranch();

Another idea is the object that comes back as you proposed, but don't update this object. This object is only a reference to the real object or DOM. This adds a layer of indirection and this might or might not be acceptable to you.

I as a plugin user would like both solutions, but prefer the first one slightly.


Here's what I came up with since I asked:

MarioWare = {
  Tree: {
    Methods: {
      nodes: function(){
        var selected = null;
        var context = this[0];
        if (selector === undefined) // tree.nodes();
          selected = $('li', context);
        else if (typeof selector == 'string') // tree.nodes('li:first,li:last');
          selected = $(selector, context);
        else if (typeof selector == 'number') // tree.nodes(2);
          selected = $('li', context).eq(selector);
        return MarioWare.$node(selected);
      },
      appendNode: function(){...}
    }
  },
  $tree: function(selector){
    return $.extend($(selector), MarioWare.Tree.Methods);
  },
  Node: {
    Methods: {
      select: function(multiSelect) {...}
    }
  },
  $node: function(selector){
    return $.extend($(selector), MarioWare.Node.Methods);
  }
}

In this way it works like some of the utility methods found in Prototype.js:

var $tree = MarioWare.$tree; //shortcut
var $node = MarioWare.$node; //shortcut
var tree = $tree('ul:first');
var nodes = tree.nodes();
nodes.eq(0).select();

It always requires a utility accessor (e.g $tree, $node), but it prevents the jQuery namespace from getting polluted. I like that the accessor clarifies the context of what we're working with--a tree or a node, for example.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜