简体   繁体   中英

Sort a list of products with JavaScript change event listener

I have to sort a list of products added dynamically in page with JavaScript. The criteria are in the HTML value option tag and i need to sort them with JavaScript change event listener.

List of products:

const data = {
    items: [
        {
            name: "Soup",
            price: 10.45,
            image: "soup.jpg"
        },
        {
            name: "Stake",
            price: 11.35,
            image: "stake.jpg"
        },

        {
            name: "Salmon",
            price: 45.85,
            image: "salmon.jpg"
        },
        {
            name: "Banana cake",
            price: 12.85,
            image: "banana_cake.jpg"
        },
        {
            name: "Brioche",
            price: 9.55,
            image: "brioche.jpg"
        },
        {
            name: "Fruit cake",
            price: 32.55,
            image: "fruit_cake.jpg"
        }                
    ]
};

HTML:

<select name="sort" id="sort">
     <option value="cmpAscendingName">Ascending Name</option>
     <option value="cmpDescendingName">Descending Name</option>
     <option value="cmpPriceUp" selected>Price Up</option>
     <option value="cmpPriceDown">Price Down</option>
</select>

My JavaScript code:

let sorting = document.querySelector('#sort');
let criteria = sorting.valueOf('option');

sorting.addEventListener('change', (event) => {
    function c(a, b){
        return a.items.price - b.items.price;
    }

});

You have a couple of options. If you want to keep the HTML as is, you can have an object that tells you what each of those values means (the "style" of the sort):

const sortInformation = {
     cmpAscendingName: {
         prop: "name",
         direction: 1
     },
     cmpDescendingName: {
         prop: "name",
         direction: -1
     },
     cmpPriceUp: {
         prop: "price",
         direction: 1
     },
     cmpPriceDown: {
         prop: "price",
         direction: -1
     }
};

That tells you what property you're sorting on, and whether it's ascending ( direction = 1 ) or descending ( direction = -1 ).

Then to get the sort info for a particular style (eg, for "cmpAscendingName" ), you do:

const sort = sortInformation[style];

With that information, you can sort like this:

data.items.sort((a, b) => {
    // Get the values for the property
    const avalue = a[sort.prop];
    const bvalue = b[sort.prop];
    // Compare them
    let result;
    if (typeof avalue === "number") {
        result = avalue - bvalue;
    } else {
        result = String(avalue).localeCompare(bvalue);
    }
    // Return the result, adjusting for ascending/descending
    return sort.direction * result;
});

Live Example:

 const data = { items: [ { name: "Soup", price: 10.45, image: "soup.jpg" }, { name: "Stake", price: 11.35, image: "stake.jpg" }, { name: "Salmon", price: 45.85, image: "salmon.jpg" }, { name: "Banana cake", price: 12.85, image: "banana_cake.jpg" }, { name: "Brioche", price: 9.55, image: "brioche.jpg" }, { name: "Fruit cake", price: 32.55, image: "fruit_cake.jpg" } ] }; const sortInformation = { cmpAscendingName: { prop: "name", direction: 1 }, cmpDescendingName: { prop: "name", direction: -1 }, cmpPriceUp: { prop: "price", direction: 1 }, cmpPriceDown: { prop: "price", direction: -1 } }; let sorting = document.querySelector('#sort'); sortData(data, sorting.value); showData(data); sorting.addEventListener('change', (event) => { sortData(data, event.currentTarget.value); }); function sortData(data, style) { // Get the information for the style const sort = sortInformation[style]; if (sort) { data.items.sort((a, b) => { // Get the values for the property const avalue = a[sort.prop]; const bvalue = b[sort.prop]; // Compare them let result; if (typeof avalue === "number") { result = avalue - bvalue; } else { result = String(avalue).localeCompare(bvalue); } // Return the result, adjusting for ascending/descending return sort.direction * result; }); showData(data); } } function showData(data) { const div = document.getElementById("display"); div.innerHTML = "<ul>" + data.items.map(entry => { return `<li>${entry.name.replace(/&/g, "&amp;").replace(/</g, "&lt;")} - ${entry.price}</li>`; }).join("") "</ul>"; }
 <select name="sort" id="sort"> <option value="cmpAscendingName">Ascending Name</option> <option value="cmpDescendingName">Descending Name</option> <option value="cmpPriceUp" selected>Price Up</option> <option value="cmpPriceDown">Price Down</option> </select> <div id="display"></div>

Another option would be to sort the property name and direction on the option element directly, which I was originally thinking you'd want to do, but doing it with a "style" of sort grew on me. :-)


In a comment you said:

...i forgot to say that after the sort i need to update an attribute "data-index' with the current index of the product

You didn't say what element you want to put that attribute on, but after sorting the array, you can loop through it with

data.items.forEach((item, index) => {
    // ...use `item` and/or `index` here...
});

...and use that index to create any attribute you may need.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM