Greasy Fork

来自缓存

Greasy Fork is available in English.

Aliexpress Plus FiZ

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

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Aliexpress Plus FiZ
// @namespace    http://www.zaoios.ru/
// @version      2.5.5
// @description  Sorts search results by item price properly with shipping costs included, enhances item pages for Google Chrome
// @author       FiZ, 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==
// known bug: after windows resize sometimes need to revert original sort order

var SortTimeoutID;
var CurPageGoods = 0;
var BottomLinksRewritten = false;
var sortmethod = 3;
var showUnitPrice = false;

var elh = {
    'sortchange1' : 'Cheapest Unit',
    'sortchange2' : 'Cheapest Total',
    'sortchange3' : 'Cheapest Total (Max Price)',
    'sortchange4' : 'Cheapest',
    '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++) {
                //console.log("mutcn: "+ mutation.addedNodes[j].className);
                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 CleanPriceText(pricefixed){
    pricefixed=pricefixed.replace("US $","");
    pricefixed=pricefixed.replace(" руб.","");
    //pricefixed=pricefixed.split(" ").join(""); //pricefixed=pricefixed.replaceAll(" ","");
    pricefixed=pricefixed.split("\u00a0").join(""); //pricefixed=pricefixed.replaceAll(/\u00a0/g, ""); //.replace("\&nbsp;","");
    pricefixed=pricefixed.split(",").join("."); //pricefixed=pricefixed.replaceAll(",",".");
    return(pricefixed);
}

function process(listitem){
    if(!listitem.querySelector)
        return(0);

    var pricerow = listitem.querySelector('div.item-price-row');
    if(!pricerow)
        return(0);

    if(listitem.querySelector('span.orig-ord'))
        return(0);

    var price = pricerow.querySelector('.price-current');
    var shipping = listitem.querySelector('.shipping-value');
    var shippingtext = (shipping)? shipping.innerText : "";
    if(!price || listitem.className == "moved")// && listitem.className.indexOf('product-card') == -1 //&& price.innerText.indexOf('$') != -1
        return(0);
    //var pricefixed = price.innerText.substring(price.innerText.indexOf('$')+1);
    var pricefixed = CleanPriceText(price.innerText);
    //console.log("pricefixed: "+pricefixed);

    var shippingfixed;
    if(shippingtext.indexOf('Free Shipping') != -1 || shippingtext == ''){
        shippingfixed = "0.00";
    }
    else{
        shippingfixed = CleanPriceText(shippingtext.substring(shippingtext.indexOf(' ')+1));
    }
    var pricepretext = price.innerText.substring(0, price.innerText.indexOf('$')+1);
    var finalcosttext = "", finalmaxcost = "";
    var pricesplit;
    if(pricefixed.indexOf(' - ') != -1){
        pricesplit = pricefixed.split(' - ');
        //if(sortmethod == 3){
        //    finalcosttext = (parseFloat(pricesplit[1]) + parseFloat(shippingfixed)).toFixed(2) + " - " + (parseFloat(pricesplit[0]) + parseFloat(shippingfixed)).toFixed(2);
        //}
        //else{
        finalcosttext = (parseFloat(pricesplit[0]) + parseFloat(shippingfixed)).toFixed(2) + " - " + (parseFloat(pricesplit[1]) + parseFloat(shippingfixed)).toFixed(2);
        finalmaxcost =(parseFloat(pricesplit[1]) + parseFloat(shippingfixed)).toFixed(2);

        //}
    }
    else{
        finalcosttext = (parseFloat(pricefixed) + parseFloat(shippingfixed)).toFixed(2);
        finalmaxcost = finalcosttext;
    }
    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(showUnitPrice && 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 = (finalcosttext / parseFloat(priceunit)).toFixed(2);
        }
        if(priceunitposttext.indexOf('/') != -1){
            var priceunitsplit = priceunitposttext.split('/');
            var priceunitpart = priceunitsplit[0];
            var priceunitwhole = priceunitsplit[1];
            finalcostpostwhole = finalcosttext + " / " + priceunitwhole;
            finalcosttext = finalcostpart + " / " + priceunitpart;
            priceunitparttemp = priceunitpart;
        }
    }
    var finalcostdiv = document.createElement('div');
    finalcostdiv.className = 'item-total-wrap';
    var finalcostpretext = document.createElement('span');
    finalcostpretext.className = 'total-pretext';
    finalcostpretext.innerHTML = "Total: " + pricepretext;
    var finalcostspan = document.createElement('span');
    finalcostspan.className = 'total-current';
    if(finalcostpostwhole){
        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 = finalcosttext;
            finalcostspan2.style.display = "none";
            finalcostdiv.appendChild(finalcostspan2);
            finalcostdiv.appendChild(finalcostbr);
        }
        finalcostdiv.appendChild(finalcostspan);
    }
    else{
        finalcostspan.innerHTML = finalcosttext;
        var finalmaxcostspan = document.createElement('span');
        finalmaxcostspan.className = 'total-max';
        finalmaxcostspan.innerHTML = finalmaxcost;
        finalmaxcostspan.style.display = "none";
        var origOrderspan = document.createElement('span');
        origOrderspan.className = 'orig-ord';
        origOrderspan.innerHTML = CurPageGoods++;
        origOrderspan.style.display = "none";
        finalcostdiv.appendChild(finalcostpretext);
        finalcostdiv.appendChild(finalcostspan);
        finalcostdiv.appendChild(finalmaxcostspan);
        finalcostdiv.appendChild(origOrderspan);
    }
    if(shipping && shipping.parentNode.nextSibling.className != finalcostdiv.className){
        price.parentNode.parentNode.parentNode.insertBefore(finalcostdiv, shipping.parentNode.nextSibling);
    }else
        price.parentNode.parentNode.parentNode.insertBefore(finalcostdiv, price.parentNode.parentNode.nextSibling);

    PlanToSortall();
}

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

function PlanToSortall(){
    if(SortTimeoutID)
        clearTimeout(SortTimeoutID);

    SortTimeoutID=setTimeout((function(){
        sortall(document.querySelectorAll("li.list-item"), sortmethod);
    }),100);

}

function sortall(listitems, sortmethod){
    //console.log("Sorting");
    //return(0);
    SortTimeoutID=0;

    if(sortmethod == 0){
        tinysort(listitems,{selector:'span.orig-ord', natural:true});// Original sort order, //our new span
    }else if(sortmethod == 1){
        tinysort(listitems,{selector:'span.tsotal-current', natural:true}); //Cheapest Unit',
    }
    else if(sortmethod == 2){
        tinysort(listitems,{selector:'span.total-current', natural:true}); // Cheapest Total', //our new span
    }
    else if(sortmethod == 3){
        tinysort(listitems,{selector:'span.total-max', natural:true}); //'Cheapest Total (Max Price)', //our new span
    }
    else if(sortmethod == 4){
        tinysort(listitems,{selector:'span.price-current', natural:true}); // 'Cheapest', //ali present
    }
    else if(sortmethod == 5){
        tinysort(listitems,{selector:'span.price-current', natural:true, order: 'desc'}); // 'Max Price', //ali present
    }
    return(0);
}

function SortRows(mode){
    if (sortmethod != mode){
        if(mode>0){
            document.getElementById('sortchange' + sortmethod).setAttribute('style', 'font-weight: regular');
            document.getElementById('sortchange' + mode).setAttribute('style', 'font-weight: bold');
            sortmethod = mode;
        }
    }
    sortall(document.querySelectorAll("li.list-item"), mode);
    fakeScrollDown();
}


function doalilink(){
//    console.log("Start Revert sorting");
    SortRows(0);
}

function rewriteAliLinks(){
    var proplist = document.querySelector('.sort-by-wrapper');
    if(proplist && proplist.childNodes.length > 0){
        var proplistall = proplist.querySelectorAll('.sort-item');
        for (var i = 0; i < proplistall.length; i++) {
            proplistall[i].addEventListener('click', function () {doalilink()}, false);
        }
    }

}

document.body.onscroll = function() {
    if(!BottomLinksRewritten)
        rewriteAliBottomLinks();
      };

function rewriteAliBottomLinks(){
    var proplist, i, proplistall;

    proplist = document.querySelector('.next-pagination-pages');
    if(proplist && proplist.childNodes.length > 0){
        BottomLinksRewritten=true;
        //console.log("pl ");
        proplistall = proplist.querySelectorAll('.next-btn');
        for (i = 0; i < proplistall.length; i++) {
            //console.log("ib: "+i);
            proplistall[i].addEventListener('click', function () {doalilink()}, false);
        }
    }
}

function insertsearch(){
    rewriteAliLinks();

    var sortdiv = document.createElement('span');
    sortdiv.className = 'sort-item';
    var sortspan = document.createElement('span');
    sortspan.className = 'sort-item';
    var sortspan2 = document.createElement('span');
    sortspan2.className = 'sort-item';
    var sortspan3 = document.createElement('span');
    sortspan3.className = 'sort-item';
    var sortspan4 = document.createElement('span');
    sortspan4.className = 'sort-item';
    var sortspan5 = document.createElement('span');
    sortspan5.className = 'sort-item';
    var sortchange = document.createElement('span');
    sortchange.id = 'sortchange1';
    sortchange.innerHTML = elh[sortchange.id];
    sortchange.addEventListener("click", function () {
        SortRows(1) //'Cheapest Unit',
    }, false);
    var sortchange2 = document.createElement('span');
    sortchange2.id = 'sortchange2';
    sortchange2.innerHTML = elh[sortchange2.id];
    sortchange2.addEventListener("click", function () {
        SortRows(2) // 'Cheapest Total',
    }, false);
    var sortchange3 = document.createElement('span');
    sortchange3.id = 'sortchange3';
    sortchange3.innerHTML = elh[sortchange3.id];
    sortchange3.addEventListener("click", function () {
        SortRows(3) //'Cheapest Total (Max Price)',
    }, false);
    var sortchange4 = document.createElement('span');
    sortchange4.id = 'sortchange4';
    sortchange4.innerHTML = elh[sortchange4.id];
    sortchange4.addEventListener("click", function () {
        SortRows(4) //'Cheapest',
    }, 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(5) //'Max Price',
    }, 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);
        searchbox.appendChild(sortspan);
        searchbox.appendChild(sortspan2);
        searchbox.appendChild(sortspan3);
        searchbox.appendChild(sortspan4);
        searchbox.appendChild(sortspan5);
        if(sortmethod>0)
            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(){
    window.scrollBy(0, window.innerHeight);
    setTimeout((function(){
        //window.scrollByPages(1);;
        //window.scrollBy(0, window.innerHeight);;
       // console.log("height: "+(window.scrollY+ window.innerHeight) +"from "+ document.body.scrollHeight + "wh "+ window.innerHeight);
        if((window.scrollY+ window.innerHeight) < document.body.scrollHeight){ //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 = itempageshipping.substring(itempageshipping.indexOf(':')+2);
        itempageshipping = parseFloat(CleanPriceText(itempageshipping)); //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());
            itempageprice = parseFloat(CleanPriceText(itempageprice));
            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);
}