基于页面元素动态构建菜单结构

时间:2014-06-22 16:40:40

标签: javascript jquery html

我在根据页面元素创建动态菜单时遇到了一些问题。如何从中创建一个菜单?:

<div class="parent">
    <div class="one child" id="first"></div>
</div>
<div class="parent">
      <div class="one child" id="second"></div>
</div>
<div class="parent">
      <div class="one child" id="third"></div>
</div>
<div class="parent">
      <div class="one child" id="fourth"></div>
      <div class="one child" id="fifth"></div>
      <div class="one child" id="sixth"></div>
      <div class="one child" id="seventh"></div>
</div>
<div class="parent">
      <div class="one child" id="eight"></div>
</div>

因此,我希望jquery能够像这样构建一个菜单结构:

<ul class="navigation">
      <li><a href="#first"></a></li>
      <li><a href="#second"></a></li>
      <li><a href="#third"></a></li>
      <li>
            <ul class="sub-navigation">
                  <li><a href="#fourth"></a></li>
                  <li><a href="#fifth"></a></li>
                  <li><a href="#sixth"></a></li>
                  <li><a href="#seventh"></a></li>
            </ul>
      </li>
      <li><a href="#eight"></a></li>
</ul>

这是我一直在干预的小提琴(我试图让它发挥作用):http://jsfiddle.net/rt9Pm/

在某个地方,我失去了我的焦点,我无法完成这个小涂鸦。

2 个答案:

答案 0 :(得分:0)

var $parents = $('.parent'),
    $ul = $('<ul>'),
    $li = $('<li>'),
    $a = $('<a>'),
    $nav = $('<nav>'),
    $navul = $ul.clone().attr('class', 'navigation');

$nav.append($navul);

$parents.each(function ea(){
    var $parent = $(this),
        $children = $parent.children('.one.child'),
        $anchor = $a.clone(),
        $subul,
        id;

    if ($children.length == 1) {
        id = $children.attr('id');

        $anchor
            .attr('href', '#' + id)
            .text($children.attr('id'));

        $navul.append($li.clone().append($anchor));
    } else if ($children.length > 1) {
        $subul = $ul.clone().attr('class', 'sub-navigation');

        $children.each(function ea(){
            var $child = $(this),
                $anchor = $a.clone(),
                id = $child.attr('id');

            $anchor
                .attr('href', '#' + id)
                .text($child.attr('id'));

            $subul.append($li.clone().append($anchor));
        });

        $navul.append($subul);
    }
});

$parents.filter(':eq(0)').before($nav);

http://jsfiddle.net/sPJPr/1

答案 1 :(得分:0)

我有一段时间,并认为这可能对您有用:

(function($){
    $.fn.createMenu = function (opts){
        var s = $.extend({
            'menuID' : 'menu',
            'navigationID' : 'navigation',
            'navigationClass' : 'navigation',
            'attachTo' : 'body'
        }, opts),
            nav = $('<nav />', {
                'id' : s.navigationID
            }),
            menu = $('<ul />', {
                'id' : s.menuID
            }),
            textProp = 'textContent' in document.body ? 'textContent' : 'innerText',
            ulWrap = document.createElement('ul'),
            liWrap = document.createElement('li'),
            aWrap = document.createElement('a'),
            liTmp,aTmp,
            // defining a function to create the li-wrapped links:
            createLinks = function (el, par, prefix) {
                // if the 'par' is a jQuery object we'll use that,
                // otherwise we assume it's a DOM node and we wrap that with jQuery:
                var parent = par instanceof jQuery ? par : $(par);
                // cloning created elements rather than re-creating elements:
                aTmp = aWrap.cloneNode();
                // creating the 'href' to link to the id:
                aTmp.href = '#' + el.id;
                aTmp[textProp] = el.id;
                liTmp = liWrap.cloneNode();
                // appending the cloned a element to the li element:
                liTmp.appendChild(aTmp);
                // adding the appropriate class to the parent 'ul' element,
                // and appending the 'li':
                parent.addClass(('undefined' === typeof prefix ? '' : prefix) + s.navigationClass).append(liTmp);
            };

        // appending the 'menu' to the 'nav':
        nav.append(menu);

        // prepending the nav to the specified element (from the options/defaults):
        nav.prependTo(s.attachTo);

        // iterating over the elements matched by the selector:
        this.each(function(i,e){
            // using this twice, so caching:
            var $e = $(e);
            // if there are no siblings:
            if ($e.siblings().length === 0) {
                // we create the links:
                createLinks(e, menu);
            }
            // if there are previous siblings we do nothing:
            else if ($e.prev().length) {
                // do nothing, this is inelegant
                // but I couldn't think of a better way
            }
            else {
                // there are siblings (this should only be matched by the first
                // sibling of a group.
                // clone a new 'li' and 'ul' element:
                var li = liWrap.cloneNode(),
                    ul = ulWrap.cloneNode(),
                // find all childNodes of the element's parent:
                    items = e.parentNode.childNodes;
                // append the cloned 'ul' to the cloned 'li':
                li.appendChild(ul);
                // iterate over the childNodes:
                for (var i = 0, len = items.length; i < len; i++) {
                    // if the node has a nodeType *and* that nodeType is exactly 1
                    // (therefore the node is an HTMLElement):
                    if (items[i].nodeType && items[i].nodeType === 1) {
                        // create links from those elements:
                        createLinks(items[i], ul, 'sub-');
                    }
                }
                // append the created 'li' (above,  before the for loop) to the menu:
                menu.append(li);
            }
        });
        // I tend to return the created elements, jQuery often, however, returns
        // the elements of the original selector (which would be 'return this'):
        return nav;
    };
})(jQuery);

$('.one').createMenu();

JS Fiddle demo

参考文献: