动态排序AppendTo

jQuery Dynamically Order AppendTo

本文关键字:AppendTo 排序 动态      更新时间:2023-09-26

我有以下代码:

HTML:

<ul id="main-menu">
    <li><a href="#page-1" class="slide-item selected">page 1</a></li>
    <li><a href="#page-2" class="slide-item">page 2</a></li>
    <li><a href="#page-3" class="slide-item">page 3</a></li>
    <li><a href="#page-4" class="slide-item">page 4</a></li>
</ul>
<div class="test">
    <div id="page-1" class="page">
    <div class="page-container">
        <h3>page 1</h3>
        <p>
            Lorem ipsum dolor sit amet, consectetur adipisicing elit. Commodi consequatur deleniti eum illo itaque
            iusto officia soluta, veritatis? Ab aliquam autem cum doloribus eaque eum in itaque natus rem, vero.
            Lorem ipsum dolor sit amet, consectetur adipisicing elit. Commodi consequatur deleniti eum illo itaque
            iusto officia soluta, veritatis? Ab aliquam autem cum doloribus eaque eum in itaque natus rem, vero.
            Lorem ipsum dolor sit amet, consectetur adipisicing elit. Commodi consequatur deleniti eum illo itaque
            iusto officia soluta, veritatis? Ab aliquam autem cum doloribus eaque eum in itaque natus rem, vero.
            Lorem ipsum dolor sit amet, consectetur adipisicing elit. Commodi consequatur deleniti eum illo itaque
        </p>
        </div>
    </div>
</div>
JQUERY:

    $.fn.insertAt = function(index, elements){
    var children = this.children();
    if(index >= children.size()){
        console.log(index+'>='+children.size());
        this.append(elements);
        return this;
    }
    var before = children.eq(index);
    $(elements).insertBefore(before);
    return this;
}; //http://upshots.org/javascript/jquery-insert-element-at-index
jQuery('.slide-item').on('click', function(){
        var item = jQuery('a[href="'+jQuery(this).attr('href')+'"]').parent();
        var index = jQuery("ul li").index(item);
        //console.log(index);
        var target = jQuery(this).attr('href').substr(1);
        if(jQuery(jQuery(this).attr('href')).length){
            console.log('loaded');
        }else {
            jQuery.get("pages/"+target+".html", function(data){
                jQuery('.test').insertAt(index, data);
            });
        }
        return false;
    });

基本上你可以看到,根据你点击的链接它会加载一个页面,现在我的实际问题是:

有办法让他们保持秩序吗?

例如,如果我按以下顺序点击链接1,4,2,3那么这就是页面附加到页面的顺序:

<div id="page-1" class="page">
<div id="page-4" class="page">
<div id="page-2" class="page">
<div id="page-3" class="page">

但是我需要它独立于你点击链接的顺序…例如,如果我点击1,3,2,4那么我需要页面按顺序(1,2,3,4)追加:

<div id="page-1" class="page">
<div id="page-2" class="page">
<div id="page-3" class="page">
<div id="page-4" class="page">

我最近试图通过索引做到这一点,通过获得点击项li的索引,然后尝试使用insertAt函数,我在这里找到插入div在该索引…但它不能完全工作,例如,如果我点击4,然后3被附加在4之后。

我建议您通过为每个页面创建空占位符div来简化整个系统。那么订单就已经到位了。

JSFiddle: http://jsfiddle.net/TrueBlueAussie/R2T4Z/4/

// Use wrapped DOM ready event to provide local $ for jQuery
jQuery(function ($) {
    $('.slide-item').on('click', function () {
        var $link = $(this);
        var target = $link.attr('href').substr(1);
        // If the div has any content it is "loaded" (if you know the page has child elements use children().length as it will be faster)
        if ($('#' + target).html().length) {
            console.log('loaded');
        } else {
            // Dummy test code - REMOVE THIS
            $('#' + target).html("I AM LOADED:" + target);
            // End dummy test code
            $.get("pages/" + target + ".html", function (data) {
                $('#' + target).html(data);
            });
        }
        return false;
    }).each(function (index) {
        // create an empty placeholder DIV (in order) with unique matching id for each new entry
        var $link = $(this);
        var id = $link.attr("href").substr(1);
        // If page not already present...
        if (!$('#' + id).length) {
            $('.test').append($('<div>').attr("id", id));
        }
    });
});

*注意:jQuery(function ($) {YOU CODE HERE});jQuery(document).ready($){YOUR CODE HERE});的快捷方式,并提供了一个局部作用域的$,所以你的jQuery代码更短。

更新:http://jsfiddle.net/TrueBlueAussie/ugZST/12/

经过多次讨论,要求还需要与水平滑块一起工作。现有的是一次性类型,与动态内容不兼容,因此我也使用slideToPage函数替换了它,该函数使用绝对动画将页面带入和退出视图:

function slideToPage($page){
    var $wrapper = $('.wrapper');
    var width = $wrapper.outerWidth();
    var height = $wrapper.outerWidth();
    // Set size of all children and stop previous animations
    $wrapper.children().css({width: width, height: height}).stop();
    // Find the current page (positioned at 0)
    var $currentpage = $wrapper.find('.currentpage');
    if ($page.is($currentpage)){
        console.log("Stay on current page");
        return;
    }
    console.log("$currentpage.index() " + $currentpage.index());
    console.log("$page.index() " + $page.index());
    // Is the new page index before or after (left or right scroll)
    var slideRight = $page.index() > $currentpage.index();
    var delta = slideRight ? 1 : -1;
    // Position offscreen (to left or right of the screen)
    $page.css({left: delta * width});
    // Animate new panel to positon 0
    $page.animate({left: 0}, 1000).show();
    // Animation old panels offscreen (left or right) then hide
    $currentpage.animate({left: -delta * width}, 1000, function(){
        $currentpage.hide();
    });
    $currentpage.removeClass('currentpage');
    $page.addClass('currentpage');
    // hide all other pages (just to be sure)
    $wrapper.children().not($currentpage).not($page).hide();
}
// Use wrapped DOM ready event to provide local $ for jQuery
jQuery(function ($) {
    $('.scrollitem').on('click', function () {
        var $link = $(this);
        var target = $link.attr('href').substr(1);
        // If the div has any content it is "loaded" (if you know the page has child elements use children().length as it will be faster)
        var $page = $('#' + target);
        var $target = $page.find('.page-container');
        if ($target.html().length) {
            console.log('loaded');
            slideToPage($page);
        } else {
            // Dummy test code - REMOVE THIS
            $target.html("I AM LOADED:" + target + "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Commodi consequatur deleniti eum illo itaque Lorem ipsum dolor sit amet, consectetur adipisicing elit. Commodi consequatur deleniti eum illo itaque Lorem ipsum dolor sit amet, consectetur adipisicing elit. Commodi consequatur deleniti eum illo itaque");
            slideToPage($page);
            $page.css('display', '');
            // End dummy test code
            $.get("pages/" + target + ".html", function (data) {
                $target.html(data);
                slideToPage($page);
                $page.css('display', '');
            });
        }
        return false;
    }).each(function (index) {
        // create an empty placeholder DIV (in order) with unique matching id for each new entry
        var $link = $(this);
        var id = $link.attr("href").substr(1);
        // If page not already present...
        if (!$('#' + id).length) {
            $('.wrapper').append($('<div class="page"><div class="page-container"></div></div>').attr("id", id).css('display', 'none'));
        }
    });
});

您的insert-at函数在这里不起作用。正如您所发现的,单击第4页然后单击第3页并不能正确排序,因为insert-at函数根据子元素的索引插入dom元素。这意味着,如果您有一个像[page3, page5]这样的列表,那么在索引n处插入任何后续页n显然会失败。

这个问题有很多解决方案,很难确定哪一个是你用例的最佳选择,但一个简单的解决方案是简单地遍历当前列表,直到第n个索引的页码大于n,然后将其插入到n处。在计算机科学中,我们称之为在线插入排序。你可以在这里阅读:http://en.wikipedia.org/wiki/Insertion_sort

这里有一个演示:

$.fn.insertAt = function(index, elements){
    var children = this.children();
    if(index >= children.size()){
        console.log(index+'>='+children.size());
        this.append(elements);
        return this;
    }
    var before = children.eq(index);
    $(elements).insertBefore(before);
    return this;
}; //http://upshots.org/javascript/jquery-insert-element-at-index
jQuery('.slide-item').on('click', function(){
    var item = jQuery('a[href="'+jQuery(this).attr('href')+'"]').parent();
    var index = jQuery("ul li").index(item);
    //console.log(index);
    var target = jQuery(this).attr('href').substr(1);
    if(jQuery(jQuery(this).attr('href')).length){
        console.log('loaded');
    }else {
        //jQuery.get("pages/"+target+".html", function(data){
        //    jQuery('.test').insertAt(index, data);
        //});
        // the insert page number happens to be the index
        var data = '<div id="' + target + '" class="page">' + target + ' content</div>';
        var toInsertPageNumber = index;
        var didInsert = false;
        jQuery('.test').children().each(function(k, v) {
            var currentPageNumber = parseInt($(v).attr('id').replace('page-', ''), 10);
            if (currentPageNumber > index) {
                jQuery('.test').insertAt(k, data);      
                didInsert = true;
                return false;
            }
        });
        // if we didn't insert anything, then it goes to the end of the list.
        if (!didInsert) {
            jQuery('.test').append(data);
        }
    }
    return false;
});

下面是一个包含上述代码的页面:http://jsfiddle.net/aDtV5/

这里有一个函数可以做到这一点:

//check by comparing order number
function insert(page){
    //extract order number from element to be inserted
    var placeId = parseInt($(page).attr('id').substr($(page).attr('id').length - 1));
    //loop through each existing page
    $('.page').each(function(){
        //extract order number of current loop iteration
        var id = parseInt($(this).attr("id"));
        //if currently existing item has higher ID than the one to be inserted
        //insert new page before(this works because we can assume order)
        if(id > placeId){
            $([NEW_PAGE]).insertBefore($(this));
            return;
        }
        //in case your trying to load an existing page
        if(id === placeId){return;}
    });
    //page to be loaded is bigger than any already loaded
    $([NEW_PAGE]).insertAfter($('.page').last());
}

不需要占位符。

jsfiddle: http://jsfiddle.net/Neverever/43gn9/

function insertData(id, data){
    // locate next 'div' and insert before it
    var found = $("li:has(a[href='" + id + "']) ~ li a").get().some(function(elm, idx) {
        var nextDiv = $($(elm).attr('href'));
        return nextDiv.length && nextDiv.before(data);
    });
    // if not found, append to .test
    if(!found)
        $(".test").append(data);
}
jQuery(function($) {
    $('.slide-item').on('click', function(){
        var self = $(this),
            id = self.attr('href'),
            target = id.substring(1);
        if($(id).length) {
            console.log('loaded');
        } else {
            // use jsFiddle ajax api call to return dummy HTML
            $.post("/echo/html/", { html : '<div id="'+target+'">'+target+'</div>'}, function(data) {
                insertData(id, data);
            });
            // uncomment the following for your actual ajax request
            /*
            $.get("pages/"+target+".html", function(data){
                insertData(id, data);
            });
            */
        }
        return false;
    });
});

如果这是你正在寻找的…也许你可以试试这个…

 <style>
 .hidden{
   display:none;
 }
</style>
<ul id="main-menu">
<li><a href="#page-1" class="slide-item selected">page 1</a></li>
<li><a href="#page-2" class="slide-item">page 2</a></li>
<li><a href="#page-3" class="slide-item">page 3</a></li>
<li><a href="#page-4" class="slide-item">page 4</a></li>
</ul>

<div id="page-1" class="page hidden">
<div id="page-2" class="page hidden">
<div id="page-3" class="page hidden">
<div id="page-4" class="page hidden">

<script>
 var content = "Content of ";
 $("#main-menu li").on("click",function(e){
   var id = e.target.hash.substring(1);
   $("#"+id).removeClass('hidden')
   .append("div")
   .addClass("page-container")
   .append("h3").text(id)
   .append("p")
   .text(content);
});
</script>

将"content"替换为要在text方法中显示的内容

可以用一个函数调用.filter(),该函数查找id小于要插入的页面的元素。然后在最后找到的div之后插入该页。

function addPage(id, page) {
    if (!$('#' + id).length) {
        // find the last page div with id smaller than target id
        $prevDiv = $('div.page', '.test').filter(function () {
            return $(this).attr('id') < id;
        }).last();
        // and append the new page after it
        $prevDiv.after(page);
    }
}

看到JSFiddle

由于DOM节点列表实现了类似数组的结构,因此可以对它们进行排序。你可以很容易地把它变成一个jQuery"插件":

function sortNodes(nodes, compare) {
    if(nodes instanceof jQuery) nodes = nodes.get();
    nodes.sort(compare);
    jQuery.each(nodes, function(i, node) {
        node.parentNode.appendChild(node);
    });
}

然后你可以这样使用:

// replace this line in your code:
jQuery('.test').insertAt(index, data);
// with this code:
var $test = jQuery('.test');
$test.append( data );
sortNodes( $test.children(), function(a, b) {
    return a.id > b.id;
});

说明:将节点列表传递给sortNodes方法。在您的示例中,传递一个页面列表。你的HTML结构是这样的:

<div class="test">
   <div id="page-4" class="page"></div>
   <div id="page-1" class="page"></div>
   <div id="page-3" class="page"></div>
   <div id="page-2" class="page"></div>
</div>

所以我们用这一行传递页面列表:

jQuery('.test').children();

然后根据'compare'函数对每个节点进行排序(请自己阅读有关排序数组的内容)。在本例中,我们比较节点ID,以便节点按其ID(例如'page-2' > 'page-1')的字母顺序排序。

…还有小提琴:

http://jsfiddle.net/ryanwheale/FpkgH/

您可以将已单击的索引作为URL参数发送,并将其与数据一起(从服务器)发送回客户端。然后可以将接收到的数据附加到正确的位置。另一件事是,如果你按这个顺序点击链接1、4、2、3,你不能期望结果以相同的顺序,因为ajax调用是异步执行的。

jQuery('.slide-item').on('click', function(){
var target = jQuery(this).attr('href').substr(1);
jQuery.get("pages/"+target+".html", function(data){
    if($('.test').length == 0 )
    {
        $('.test').append(data);
    }
    else
    {
        $('.test').each(function(key,val){
          var id = $(val).attr("id");
          var index = id.split("-")[1];
          if(index <= newIndex)
          {
            //here newIndex is clicked link should come from server
            jQuery(data).insertAfter($(this));
          }
        });
    }
});
return false;
});