pafisc / Matsmart Product Sorter

// ==UserScript==
// @namespace   https://openuserjs.org/user/pafisc
// @name        Matsmart Product Sorter
// @version     1.1.0
// @description Sort products by highest discount or lowest price
// @copyright   2018, pafisc (https://openuserjs.org/user/pafisc)
// @license     MIT
// @updateURL   https://openuserjs.org/meta/pafisc/Matsmart_Product_Sorter.meta.js
// @include     http://*.matsmart.se*
// @include     https://*.matsmart.se*
// @grant none
// ==/UserScript==

// ==OpenUserJS==
// @author      pafisc, Patrik Fischer
// ==/OpenUserJS==

// Settings
var sortByDiscount = true; //Set false for lowest price

//Element classes
var productContainerIdName = 'block-product-list';
var productClassName = 'prd';
var productDiscountClassName = 'prd-discount-oldprice';
var productPriceClassName = 'prd-price-num';

// Sorts products contained in productContainer
var sortProducts = function (productContainer) {

  // Don't bother if there's no container
  if (productContainer) {

    // Collection of all products element
    var productEls = productContainer.getElementsByClassName(productClassName);

    if (productEls == null || productEls.length == 0) {
      return;
    }

    // Function returning discount for product
    var getDiscount = function (item) {

      var saveEl = item.getElementsByClassName(productDiscountClassName)[0];
      var saveText = saveEl.getElementsByTagName('span')[0].textContent;

      var regExp = /\(([^)]+)\)/;
      var matches = regExp.exec(saveText);
      var discount = matches[1]; //contains the value between the parentheses

      return discount;

    };

    // Function returning price for product
    var getPrice = function (item) {

      var priceEl = item.getElementsByClassName(productPriceClassName)[0];
      var priceText = priceEl.textContent;
      var price = parseInt(priceText);

      return price;

    };

    // Array in which LIs are to be sorted in proper order
    var sortedItems = [];

    // Filling array with product references
    for (var i = 0; i < productEls.length; i++) {
      sortedItems.push(productEls[i]);
    }

    // Sorting products in newly initialized array
    sortedItems.sort(function (itemA, itemB) {
      if (sortByDiscount) {
        return getDiscount(itemB).localeCompare(getDiscount(itemA)); //highest discount first
      }
      else {
        return getPrice(itemB) < getPrice(itemA); //lowest price first
      }
    });

    // Placing products in proper order within the product container
    for (var i = 0; i < sortedItems.length; i++) {
      if (!productEls[i]) {
        break;
      }
      productEls[i].replaceWith(sortedItems[i]);
    }
  }

};

var productContainersDone = 0;

// Polls for products containers and once it's found it sorts its elements.
// As new containers show, they are handled
// Number of milliseconds between polls is given as delay parameter.
var pollForProductsContainer = function (delay) {

  var productContainers = document.querySelectorAll("#block-product-list"); //support multiple product lists on page

  if (productContainers == null) {
    setTimeout(pollForProductsContainer, delay);
  }
  else {
    for (var i = productContainersDone; i < productContainers.length; i++) {
      sortProducts(productContainers[i]);
    }
    productContainersDone = productContainers.length;
    //setTimeout(pollForProductsContainer, delay); //seams that all is included in first loop
  }

};

// If necessary, delay can be made longer to lessen the strain on the CPU
pollForProductsContainer(1e3);