Aliexpress Plus

Sorts search results by item price properly with shipping costs included, enhances item pages

Ajankohdalta 2.5.2020. Katso uusin versio.

// ==UserScript==
// @name         Aliexpress Plus
// @namespace    http://www.facebook.com/Tophness
// @version      2.5
// @description  Sorts search results by item price properly with shipping costs included, enhances item pages
// @author       Tophness
// @match        https://*.aliexpress.com/w/wholesale?*
// @match        https://*.aliexpress.com/wholesale?*
// @match        https://*.aliexpress.com/af/*
// @match        https://*.aliexpress.com/item/*
// @require      https://cdnjs.cloudflare.com/ajax/libs/tinysort/2.3.6/tinysort.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/tinysort/2.3.6/tinysort.charorder.min.js
// @license MIT
// @run-at document-idle
// ==/UserScript==

var sortmethod = 2;
var count = 0;

var elh = {
    'sortchange1' : 'Cheapest Unit Price',
    'sortchange2' : 'Cheapest Total Price',
    'sortchange3' : 'Cheapest Total Price (Max Price)',
    'sortchange4' : 'Cheapest Price',
    'sortchange5' : 'Max Price',
};

var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        if(mutation.type == 'childList'){
            for (var j = 0; j < mutation.addedNodes.length; j++) {
                processall(mutation.addedNodes[j].childNodes);
            }
        }
    });
});

function waitForEl(){
    var observera = new MutationObserver(function (mutations, me) {
        if(document.querySelector("ul.list-items")) {
            me.disconnect();
            if(document.location.href.indexOf('g=y') == -1){
                observer.observe(document.querySelector("ul.list-items"), { childList: true, subtree: true });
            }
            else{
                observer.observe(document.querySelector("ul.list-items"), { childList: true });
            }
            return;
        }
    });

    observera.observe(document, {
        childList: true,
        subtree: true
    });
}

function process(listitem){
    if(listitem.querySelector){
        var pricerow = listitem.querySelector('div.item-price-row');
        if(pricerow){
            var price = pricerow.querySelector('.price-current');
            var shipping = listitem.querySelector('.shipping-value');
            if(price && price.innerText.indexOf('$') != -1 && listitem.className != "moved" && listitem.className.indexOf('product-card') == -1){
                var pricefixed = price.innerText.substring(price.innerText.indexOf('$')+1);
                var shippingfixed;
                if(shipping.innerText.indexOf('Free Shipping') != -1 || shipping.innerText == ''){
                    shippingfixed = "0.00";
                }
                else{
                    shippingfixed = shipping.innerText.substring(shipping.innerText.indexOf('$')+1);
                }
                var pricepretext = price.innerText.substring(0, price.innerText.indexOf('$')+1);
                var finalcost = "";
                var pricesplit;
                if(pricefixed.indexOf(' - ') != -1){
                    pricesplit = pricefixed.split(' - ');
                    if(sortmethod == 3){
                        finalcost = (parseFloat(pricesplit[1]) + parseFloat(shippingfixed)).toFixed(2) + " - " + (parseFloat(pricesplit[0]) + parseFloat(shippingfixed)).toFixed(2);
                    }
                    else{
                        finalcost = (parseFloat(pricesplit[0]) + parseFloat(shippingfixed)).toFixed(2) + " - " + (parseFloat(pricesplit[1]) + parseFloat(shippingfixed)).toFixed(2);
                    }
                }
                else{
                    finalcost = (parseFloat(pricefixed) + parseFloat(shippingfixed)).toFixed(2);
                }
                var finalcostpost;
                var finalcostpostwhole;
                var priceunitparttemp;
                var priceunitel = pricerow.querySelector('span.price-unit');
                var packagingsale = listitem.querySelector('div.item-price-row.packaging-sale')
                if(packagingsale){
                    priceunitel = packagingsale.querySelector('span.price-unit');
                }
                if(priceunitel){
                    var priceuniteltext = priceunitel.innerText;
                    var priceunit = priceuniteltext.substring(0, priceuniteltext.indexOf(' '));
                    var priceunitposttext = priceuniteltext.substring(priceuniteltext.indexOf(' '));
                    var finalcostpart;
                    if(pricefixed.indexOf(' - ') != -1){
                        if(sortmethod == 3){
                            finalcostpart = (parseFloat(pricesplit[1]) / parseFloat(priceunit)).toFixed(2);
                        }
                        else{
                            finalcostpart = (parseFloat(pricesplit[0]) / parseFloat(priceunit)).toFixed(2);
                        }
                    }
                    else{
                        finalcostpart = (finalcost / parseFloat(priceunit)).toFixed(2);
                    }
                    if(priceunitposttext.indexOf('/') != -1){
                        var priceunitsplit = priceunitposttext.split('/');
                        var priceunitpart = priceunitsplit[0];
                        var priceunitwhole = priceunitsplit[1];
                        finalcostpostwhole = finalcost + " / " + priceunitwhole;
                        finalcost = finalcostpart + " / " + priceunitpart;
                        priceunitparttemp = priceunitpart;
                    }
                }
                var finalcostdiv = document.createElement('div');
                finalcostdiv.className = 'item-total-wrap';
                if(finalcostpostwhole){
                    var finalcostpretext = document.createElement('span');
                    finalcostpretext.className = 'total-pretext';
                    finalcostpretext.innerHTML = "Total: " + pricepretext;
                    var finalcostspan = document.createElement('span');
                    finalcostspan.className = 'total-current';
                    finalcostspan.innerHTML = finalcostpostwhole;
                    if(packagingsale){
                        pricerow.querySelector('span.price-unit').innerHTML = " / " + priceunitparttemp;
                    }
                    else{
                        listitem.querySelector('div.item-price-row.packaging-sale').querySelector('span.price-unit').innerHTML = " / " + priceunitparttemp;
                    }
                    price.innerHTML = pricepretext + finalcostpart;
                    finalcostdiv.appendChild(finalcostpretext);
                    if(sortmethod == 1){
                        finalcostspan.className = 'total-posttext';
                        var finalcostbr = document.createElement('br');
                        finalcostbr.style.display = "none";
                        var finalcostspan2 = document.createElement('span');
                        finalcostspan2.className = 'total-current';
                        finalcostspan2.innerHTML = finalcost;
                        finalcostspan2.style.display = "none";
                        finalcostdiv.appendChild(finalcostspan2);
                        finalcostdiv.appendChild(finalcostbr);
                    }
                    finalcostdiv.appendChild(finalcostspan);
                }
                else{
                    var finalcostpretext = document.createElement('span');
                    finalcostpretext.className = 'total-pretext';
                    finalcostpretext.innerHTML = "Total: " + pricepretext;
                    var finalcostspan = document.createElement('span');
                    finalcostspan.className = 'total-current';
                    finalcostspan.innerHTML = finalcost;
                    finalcostdiv.appendChild(finalcostpretext);
                    finalcostdiv.appendChild(finalcostspan);
                }
                if(shipping.parentNode.nextSibling.className != finalcostdiv.className){
                    price.parentNode.parentNode.parentNode.insertBefore(finalcostdiv, shipping.parentNode.nextSibling);
                }
                if(count >= 3){
                    sortall(document.querySelectorAll("li.list-item"));
                    count = 0;
                }
                else{
                    count++;
                }
            }
        }
    }
}

function processall(list){
    for (var i = 0; i < list.length; i++) {
        process(list[i]);
    }
}

function sortall(listitems){
    if(sortmethod == 1){
        tinysort(listitems,{selector:'span.total-current', natural:true});
    }
    else if(sortmethod == 2){
        tinysort(listitems,{selector:'span.total-current', natural:true});
    }
    else if(sortmethod == 3){
        tinysort(listitems,{selector:'span.price-current', natural:true});
    }
    if(sortmethod == 4){
        tinysort(listitems,{selector:'span.total-current', natural:true});
    }
    else if(sortmethod == 5){
        tinysort(listitems,{selector:'span.price-current', natural:true, order: 'desc'});
    }
}

function SortRows(mode){
    sortmethod = mode;
    sortall(document.querySelectorAll("li.list-item"));
    fakeScrollDown();
}
function insertsearch(){
    var sortdiv = document.createElement('div');
    sortdiv.className = 'sort-item';
    var sortspan = document.createElement('div');
    sortspan.className = 'sort-item';
    var sortspan2 = document.createElement('div');
    sortspan2.className = 'sort-item';
    var sortspan3 = document.createElement('div');
    sortspan3.className = 'sort-item';
    var sortspan4 = document.createElement('div');
    sortspan4.className = 'sort-item';
    var sortspan5 = document.createElement('div');
    sortspan5.className = 'sort-item';
    var sortchange = document.createElement('div');
    sortchange.id = 'sortchange1';
    sortchange.innerHTML = elh[sortchange.id];
    sortchange.addEventListener("click", function () {
        SortRows(0)
    }, false);
    var sortchange2 = document.createElement('div');
    sortchange2.id = 'sortchange2';
    sortchange2.innerHTML = elh[sortchange2.id];
    sortchange2.addEventListener("click", function () {
        SortRows(1)
    }, false);
    var sortchange3 = document.createElement('div');
    sortchange3.id = 'sortchange3';
    sortchange3.innerHTML = elh[sortchange3.id];
    sortchange3.addEventListener("click", function () {
        SortRows(2)
    }, false);
    var sortchange4 = document.createElement('div');
    sortchange4.id = 'sortchange4';
    sortchange4.innerHTML = elh[sortchange4.id];
    sortchange4.addEventListener("click", function () {
        SortRows(3)
    }, false);
    var sortchange5 = document.createElement('label');
    sortchange5.id = 'sortchange5';
    sortchange5.innerHTML = elh[sortchange5.id] + ': ';
    var sortchange5t = document.createElement('input');
    sortchange5t.id = 'sortchange5t';
    sortchange5t.addEventListener("keydown", function () {
        SortRows(4)
    }, false);
    sortspan.appendChild(sortchange);
    sortspan2.appendChild(sortchange2);
    sortspan3.appendChild(sortchange3);
    sortspan4.appendChild(sortchange4);
    sortspan5.appendChild(sortchange5);
    sortspan5.appendChild(sortchange5t);
    sortdiv.appendChild(sortspan);
    sortdiv.appendChild(sortspan2);
    sortdiv.appendChild(sortspan3);
    sortdiv.appendChild(sortspan4);
    sortdiv.appendChild(sortspan5);
    var searchbox = document.querySelector(".sort-by-wrapper");
    if(searchbox){
        searchbox.appendChild(sortdiv);
        document.getElementById('sortchange' + sortmethod).setAttribute('style', 'font-weight: bold');
    }
}

function process2(item){
    if(item.className == "item-info"){
        if(item.querySelector("div.item-title.line-limit-length")){
            item.querySelector("div.item-title.line-limit-length").classList.remove('line-limit-length');
            //item.parentNode.parentNode.style.marginBottom = "88px";
            item.parentNode.parentNode.style.height = "auto";
        }
    }
}

function checkall(list){
    for (var i = 0; i < list.length; i++) {
        process2(list[i]);
    }
}

var observer2 = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        if(mutation.type == 'childList'){
            for (var j = 0; j < mutation.addedNodes.length; j++) {
                checkall(mutation.addedNodes[j].childNodes);
            }
        }
    });
});

function waitForEl2(){
    var observerb = new MutationObserver(function (mutations, me) {
        if(document.querySelector(".item-title-block")) {
            me.disconnect();
            observer2.observe(document.querySelector(".bottom-recommendation"), { childList: true, subtree: true });
            return;
        }
    });

    observerb.observe(document, {
        childList: true,
        subtree: true
    });
}

function fakeScrollDown(){
    setTimeout((function(){
        window.scrollByPages(1);;
        if(window.scrollY < window.scrollMaxY){
            fakeScrollDown();
        }
        else{
            window.scrollTo(0,0);
        }
    }),100);
}

function docalctotal(){
    var itempageshipping = document.querySelector('.product-shipping-price');
    if(itempageshipping){
        itempageshipping = itempageshipping.innerText;
        if(itempageshipping.indexOf('Free Shipping') != -1){
            itempageshipping = '0.00';
        }
        itempageshipping = parseFloat(itempageshipping.substring(itempageshipping.indexOf('$')+1).trimEnd());
        var itempageprice = document.querySelector('.product-price-value');
        if(itempageprice){
            itempageprice = itempageprice.innerText;
            var preprice = itempageprice.substring(itempageprice.indexOf(':')+1, itempageprice.indexOf('$')+1);
            itempageprice = parseFloat(itempageprice.substring(itempageprice.indexOf('$')+1).trimEnd());
            var itempagetotal = parseFloat(itempageshipping + itempageprice).toFixed(2).toString();
            var finalcostpretext = document.createElement('span');
            finalcostpretext.className = 'total-pretext';
            finalcostpretext.innerHTML = "Total: " + preprice + itempagetotal;
            finalcostpretext.style.fontSize = "24px";
            finalcostpretext.style.fontWeight = "700";
            var finalcostdiv = document.createElement('div');
            finalcostdiv.className = 'total-current';
            finalcostdiv.appendChild(finalcostpretext);
            var insertitemtotal = document.querySelector('.product-action');
            if(insertitemtotal){
                var pretextitem = document.querySelector('.total-pretext');
                if(pretextitem){
                    pretextitem.innerHTML = "Total: " + preprice + itempagetotal;
                }
                else{
                    insertitemtotal.parentNode.insertBefore(finalcostdiv, insertitemtotal);
                }
            }
        }
    }
}

function calctotal(){
    var proplist = document.querySelector('.sku-wrap');
    if(proplist && proplist.childNodes.length > 0){
        var proplistall = proplist.querySelectorAll('.sku-property');
        for (var i = 0; i < proplistall.length; i++) {
            var propitem = proplistall[i].querySelectorAll('.sku-property-item');
            if(!propitem[0].classList.contains('selected')){
                propitem[0].click();
            }
            for (var i2 = 0; i2 < propitem.length; i2++) {
                propitem[i2].addEventListener('click', function() {
                    setTimeout((function(){
                        docalctotal();
                    }),1000);
                });
            }
        }
        setTimeout((function(){
            docalctotal();
        }),1000);
    }
    else{
        docalctotal();
    }
}

if(document.location.href.indexOf('/wholesale') != -1 || document.location.href.indexOf('/af') != -1){
    waitForEl();
    processall(document.querySelectorAll("li.list-item"));
    //sortall(document.querySelectorAll("li.list-item"));
    insertsearch();
    fakeScrollDown();
}
else if(document.location.href.indexOf('/item') != -1){
    waitForEl2();
    setTimeout((function(){
        checkall(document.querySelectorAll(".item-info"));
        calctotal();
    }),2000);
}