Amazon units converter

Convert Amazon units to normal units that all normal countries uses. It's check only 2 rows in a Specs table, so it's very perfomance-friendly.

As of 2021-08-24. See the latest version.

// ==UserScript==
// @name			Amazon units converter
// @name:ru			Amazon конвертер величин
// @namespace		https://greasyfork.org/ru/users/303426-титан
// @version				1.0.1
// @description		Convert Amazon units to normal units that all normal countries uses. It's check only 2 rows in a Specs table, so it's very perfomance-friendly.
// @description:ru	Конвертирует единицы измерения Амазона из Американских в нормальные. Он проверяет только 2 строчки в Характеристиках, поэтому этот скрипт не оказывает практически никакого влияния на производительность
// @author			Титан
// @include			http://www.amazon.com/*
// @include			https://www.amazon.com/*
// @include			http://www.amazon.co.uk/*
// @include			https://www.amazon.co.uk/*
// @include			http://www.amazon.fr/*
// @include			https://www.amazon.fr/*
// @include			http://www.amazon.de/*
// @include			https://www.amazon.de/*
// @include			http://www.amazon.es/*
// @include			https://www.amazon.es/*
// @include			http://www.amazon.ca/*
// @include			https://www.amazon.ca/*
// @include			http://www.amazon.in/*
// @include			https://www.amazon.in/*
// @include			http://www.amazon.it/*
// @include			https://www.amazon.it/*
// @include			http://www.amazon.co.jp/*
// @include			https://www.amazon.co.jp/*
// @include			http://www.amazon.com.mx/*
// @include			https://www.amazon.com.mx/*
// @include			http://www.amazon.com.au/*
// @include			https://www.amazon.com.au/*
// @icon			https://www.google.com/s2/favicons?domain=amazon.com
// @grant			none
// ==/UserScript==

(function() {
	'use strict';
	let DebugText = ":::Amazon American units to normal units extension::: ";
	let Debug = false;

	window.onload = () => {
		let specsTable = document.getElementById("productDetails_detailBullets_sections1").firstElementChild;

		for(let tr of specsTable.children) {
			//if (tr.nodeName !="TR") continue; //if it's not tr
			//if the tr contains
			//console.log(tr.firstElementChild.textContent.toLowerCase());
			if (tr.firstElementChild.textContent.toLowerCase().indexOf("dimensions")>=0) {
				let packageDimentions = tr.lastElementChild;
				packageDimentions.textContent = ReplaceUnit(packageDimentions.textContent,"inches","cm",ConvertInchesToSm);
					/*=ReplaceUnit(
					ReplaceUnit(packageDimentions.textContent,"inches","cm",ConvertInchesToSm),
					"pounds", "kg", ConvertPoundsToKg);*/
			} else if (tr.firstElementChild.textContent.toLowerCase().indexOf("weight")>=0) {
				let weight = tr.lastElementChild;
				weight.textContent = ReplaceUnit(weight.textContent,"pounds","kg",ConvertPoundsToKg);
				}
			}
		}




	/**
	 * Converts all numbers in text from old unit to new unit
	 *
	 * @param {string} Text Text that will be converted
	 * @param {string} UnitName Name of current unit
	 * @param {string} NewUnitName Name of the new unit
	 * @param {function} UnitConvertFunc Function that takes current unit float and returns new unit float
	 * @return {string} Text with all old unit floats replaced by new unit floats
	 */
	function ReplaceUnit(Text,UnitName,NewUnitName,UnitConvertFunc) {
		let NewText = "";
		let offset = 0;
		let lastUnitTextIndex = -UnitName.length;

		let unitTextIndex = Text.toLowerCase().indexOf(UnitName);
		if (unitTextIndex===-1) return Text;

		let unitTextFragment = Text.slice(lastUnitTextIndex+UnitName.length, unitTextIndex)
		lastUnitTextIndex = unitTextIndex;

		while (unitTextIndex!==-1) { //while there IS a UnitName text in a string untouched
			let i = 0;

			console.log("original fragment: " + unitTextFragment);
			LfragmentLoop:
			while (i < unitTextFragment.length)
			{ //Перебор внутри фрагмента
				let firstDigitPos;
				let lastDigitPos;
				for (i; ;i++) { //Searches for first digit symbol
					if (i === unitTextFragment.length) { //if first digit not found, exit circle
						if(Debug) console.log(`${DebugText}no Number found before \"${UnitName}\" text: ${NormalizeString( unitTextFragment)}`);
						break LfragmentLoop;
					}
					if (isFloatNumber(unitTextFragment[i])) break;  //if first digit found, break
				}

				lastDigitPos = firstDigitPos = i;

				for (i+=1;i < unitTextFragment.length; i++) {//searches for last digit position
					if (isFloatNumber(unitTextFragment[i])) lastDigitPos = i;
					else break;
				}

				let UnitNumber = unitTextFragment.slice(firstDigitPos,lastDigitPos+1);
				let NewUnitNumber = UnitConvertFunc(UnitNumber).toFixed(2);
				unitTextFragment = unitTextFragment.slice(0,firstDigitPos) + NewUnitNumber + unitTextFragment.slice(lastDigitPos+1);
				let offset = NewUnitNumber.length - UnitNumber.length
				i+= offset+1;
				if(Debug) console.log("fragment: "+ NormalizeString(unitTextFragment)+"\nCursorpos:"+CreateSpaces(i)+"↑");
			}

			NewText+=unitTextFragment + NewUnitName;
			unitTextIndex = Text.toLowerCase().indexOf(UnitName, lastUnitTextIndex+UnitName.length);
			if (unitTextIndex===-1) break;
			unitTextFragment = Text.slice(lastUnitTextIndex+UnitName.length, unitTextIndex)
			lastUnitTextIndex = unitTextIndex;
		}

		if (lastUnitTextIndex<Text.length)
			NewText+=Text.slice(lastUnitTextIndex+UnitName.length)
		return NewText;
	}

	function ConvertInchesToSm(Inches) {
		return Inches*2.54;
	}

	function ConvertPoundsToKg(Pounds) {
		return Pounds*0.45359237;
	}

	function isFloatNumber(c) {
		return c >= '0' && c <= '9' || c === '.';
	}

	function CreateSpaces(Count){
		let Spaces = "";
		for (let i=Count;i--; i>0) Spaces+= " ";
		return Spaces;
	}

	function NormalizeString(inputString){
		let normalizedString = "";
		for (let i=0; i<inputString.length;i++) {
			switch (inputString[i]) {
				case '\n': normalizedString+="↵"; break;
				case '\t': normalizedString+="⇥"; break;
				case '\r': normalizedString+="␍"; break;
				case '\b': normalizedString+="␈"; break;
				case '\f': normalizedString+="↡"; break;
				case '\v': normalizedString+="⭳"; break;
				case '\0': normalizedString+="␀"; break;
				default: normalizedString+= inputString[i]; break;
			}
		}
		return normalizedString;
	}
})();