2008-11-12 27 views
41

अगर मैं इस तरह एक सूची है:डोम नोड्स को सॉर्ट करने का सबसे आसान तरीका?

<ul id="mylist"> 
    <li id="list-item1">text 1</li> 
    <li id="list-item2">text 2</li> 
    <li id="list-item3">text 3</li> 
    <li id="list-item4">text 4</li> 
</ul> 

सबसे आसान तरीका करने के लिए अपने पसंद के डोम नोड्स फिर से व्यवस्थित क्या है? (पेज लोड होने पर इसे स्वचालित रूप से होने की आवश्यकता होती है, कुकी से सूची-क्रम वरीयता प्राप्त होती है)

उदा।

<ul id="mylist"> 
    <li id="list-item3">text 3</li> 
    <li id="list-item4">text 4</li> 
    <li id="list-item2">text 2</li> 
    <li id="list-item1">text 1</li> 
</ul> 
+0

मैं अगर यह आपकी मदद करेंगे यकीन नहीं है, लेकिन आप इस पर एक सर्वर साइड प्रौद्योगिकी (PHP) की तरह उपयोग कर रहे हैं पेज, तो यह कुकीज़ तक पहुंच भी होनी चाहिए। PHP में, यह वैश्विक $ _COOKIE सरणी में है। – nickf

उत्तर

62

वहाँ शायद यह करने के लिए एक आसान तरीका एक जे एस लाइब्रेरी का उपयोग है हालांकि, यहां एक काम कर समाधान वेनिला js का उपयोग कर रहा है।

var list = document.getElementById('mylist'); 

var items = list.childNodes; 
var itemsArr = []; 
for (var i in items) { 
    if (items[i].nodeType == 1) { // get rid of the whitespace text nodes 
     itemsArr.push(items[i]); 
    } 
} 

itemsArr.sort(function(a, b) { 
    return a.innerHTML == b.innerHTML 
      ? 0 
      : (a.innerHTML > b.innerHTML ? 1 : -1); 
}); 

for (i = 0; i < itemsArr.length; ++i) { 
    list.appendChild(itemsArr[i]); 
} 
+0

आपके समाधान निकफ़ के लिए धन्यवाद, मैं इसे थोड़ा सा अनुकूलित कर रहा हूं क्योंकि मैं jQuery का उपयोग कर रहा हूं लेकिन मुझे लगता है कि मुझे अब यह कैसे करना है इसका विचार है, धन्यवाद! :) – James

+27

'list.childNodes' के बजाय' list.children' का उपयोग करके, आप टेक्स्ट नोड्स के चेक से बच सकते हैं। –

+0

जब मैंने पहली बार यह जवाब पढ़ा, तो मैंने वैनिला जेएस सोचा? [Vanilla.js] (http://vanilla-js.com/) क्यों आवश्यक है? : ^) – zipzit

14

आपको लगता है कि डीओएम नोड्स को सॉर्ट करने से अच्छा प्रदर्शन नहीं होता है। आपके जावास्क्रिप्ट में एक अलग दृष्टिकोण होगा जो उस डेटा का प्रतिनिधित्व करता है जो डीओएम नोड्स में जाता है, उस डेटा को सॉर्ट करता है, और उसके बाद डीओएम नोड्स वाले div को पुन: उत्पन्न करता है।

हो सकता है कि आपके पास ऐसे कई नोड्स क्रमबद्ध न हों, इसलिए इससे कोई फर्क नहीं पड़ता। मेरा अनुभव डीओएम में हेरफेर करके एचटीएमएल टेबल को सॉर्ट करने की कोशिश करने पर आधारित है, जिसमें सैकड़ों पंक्तियों और दो दर्जन कॉलम वाले टेबल शामिल हैं।

9

आप पहले से ही jQuery का उपयोग कर रहे हैं, मैं सलाह देते हैं tinysort: http://tinysort.sjeiti.com/

$("li").tsort({order:"asc"}); 
$("li").tsort({order:"desc"}); 
+2

टिनिसोर्ट कोड की 13 लाइनों की तुलना में धीमी गति से कई गुना है, जो jQuery चयन परिणाम को सॉर्ट करने और इसे वापस जोड़ने के आधार पर - http: // jsperf।com/attr-vs-getattribute/12 –

+0

TinySort एक jQuery प्लगइन होता था लेकिन jQuery निर्भरता को हटाने के लिए फिर से लिखा गया था। अब यह छोटा और तेज –

1

बहुत ज्यादा विश्लेषण करने के लिए इस तालिका में कुछ भी नया लाता है, तो बिना, मैं आम तौर पर इस का उपयोग करें:

function forEach(ar, func){ if(ar){for(var i=ar.length; i--;){ func(ar[i], i); }} } 
function removeElement(node){ return node.parentNode.removeChild(node); } 
function insertBefore(ref){ return function(node){ return ref.parentNode.insertBefore(node, ref); }; } 

function sort(items, greater){ 
    var marker = insertBefore(items[0])(document.createElement("div")); //in case there is stuff before/after the sortees 
    forEach(items, removeElement); 
    items.sort(greater); 
    items.reverse(); //because the last will be first when reappending 
    forEach(items, insertBefore(marker)); 
    removeElement(marker); 
} 

जहां आइटम एक ही माता पिता के बच्चों की एक सरणी है। हम आखिरी बार से शुरू करते हैं और शीर्ष पर शुरू होने वाले शीर्ष भाग में झिलमिलाहट से बचने के लिए पहले से शुरू करते हैं। मैं आम तौर पर इस तरह मेरे आइटम सरणी मिल:

forEachSnapshot(document.evaluate(..., 6, null), function(n, i){ items[i] = n; }); 
13

यह देखें कार्रवाई में: http://jsfiddle.net/stefek99/y7JyT/

jQuery.fn.sortDomElements = (function() { 
     return function(comparator) { 
      return Array.prototype.sort.call(this, comparator).each(function(i) { 
        this.parentNode.appendChild(this); 
      }); 
     }; 
    })(); 

संक्षिप्त

+0

अच्छा है! मुझे चीजों को भी पसंद है, इसलिए उस पर आधारित, मैं एक [बहुत ही सरल jQuery फ़ंक्शन] (http://jsfiddle.net/mindplay/H2mrp/) के साथ आया था जो आपको कॉलबैक-फ़ंक्शन प्रदान करने देता है जो कि सॉर्ट करने के लिए मूल्य की गणना करता है द्वारा। (मैंने दो उदाहरणों को शामिल किया: वर्णमाला में एक सूची क्रमबद्ध करना, और पहले कॉलम में एक संख्यात्मक मान द्वारा तालिका को सॉर्ट करना - अनिवार्य रूप से एक-लाइनर दोनों।) –

+0

मुझे पता है कि यह एक पुरानी पोस्ट है, लेकिन क्या मैं पूछ सकता हूं, इसका क्या फायदा है एक स्व निष्पादन समारोह का उपयोग कर sortDomElements समारोह वापस? JQuery.fn.sortDomElements = function (comparitor) कहने के लिए यह और अधिक terse नहीं होगा ...? इस तरह http://jsfiddle.net/y7JyT/77/ – Julian

5

मेरे संस्करण, आशा उपयोगी दूसरों के लिए होगा:

var p = document.getElementById('mylist'); 
Array.prototype.slice.call(p.children) 
    .map(function (x) { return p.removeChild(x); }) 
    .sort(function (x, y) { return /* sort logic */; }) 
    .forEach(function (x) { p.appendChild(x); }); 
+0

आपका मतलब क्या है '/ * सॉर्ट तर्क */'? :/कोड अच्छा दिखता है, लेकिन मेरा सॉर्ट तर्क थोड़ा कमजोर है –

+1

इसका मतलब है कि आपको अपना सॉर्ट तर्क रखना चाहिए, https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/ पर एक नज़र डालें Global_Objects/Array/इसे मूल रूप से वही क्रमबद्ध करें, केवल एक्स और वाई डोम नोड्स हैं। –

2

यहां डीओएम नोड्स को क्रमबद्ध करने के लिए एक ES6 फ़ंक्शन है:

const sortChildren = ({ container, childSelector, getScore }) => { 
    const items = [...container.querySelectorAll(childSelector)]; 

    items 
    .sort((a, b) => getScore(b) - getScore(a)) 
    .forEach(item => container.appendChild(item)); 
}; 

यहाँ कैसे आप क्रमबद्ध करना Untapped user reviews by score इसका इस्तेमाल करेंगे:

sortChildren({ 
    container: document.querySelector("#main-stream"), 
    childSelector: ".item", 
    getScore: item => { 
    const rating = item.querySelector(".rating"); 
    if (!rating) return 0; 
    const scoreString = [...rating.classList].find(c => /r\d+/.test(c)); 
    const score = parseInt(scoreString.slice(1)); 
    return score; 
    } 
}); 
संबंधित मुद्दे