I have a Javascript code, which I use to bring Night Mode effect on an HTML page...
The code goes something like this-
javascript: (function () {
function RGBtoHSL(RGBColor) {
with(Math) {
var R, G, B;
var cMax, cMin;
var sum, diff;
var Rdelta, Gdelta, Bdelta;
var H, L, S;
R = RGBColor[0];
G = RGBColor[1];
B = RGBColor[2];
cMax = max(max(R, G), B);
cMin = min(min(R, G), B);
sum = cMax + cMin;
diff = cMax - cMin;
L = sum / 2;
if (cMax == cMin) {
S = 0;
H = 0;
} else {
if (L <= (1 / 2)) S = diff / sum;
else S = diff / (2 - sum);
Rdelta = R / 6 / diff;
Gdelta = G / 6 / diff;
Bdelta = B / 6 / diff;
if (R == cMax) H = Gdelta - Bdelta;
else if (G == cMax) H = (1 / 3) + Bdelta - Rdelta;
else H = (2 / 3) + Rdelta - Gdelta; if (H < 0) H += 1;
if (H > 1) H -= 1;
}
return [H, S, L];
}
}
function getRGBColor(node, prop) {
var rgb = getComputedStyle(node, null).getPropertyValue(prop);
var r, g, b;
if (/rgb\((\d+),\s(\d+),\s(\d+)\)/.exec(rgb)) {
r = parseInt(RegExp.$1, 10);
g = parseInt(RegExp.$2, 10);
b = parseInt(RegExp.$3, 10);
return [r / 255, g / 255, b / 255];
}
return rgb;
}
function hslToCSS(hsl) {
return "hsl(" + Math.round(hsl[0] * 360) + ", " + Math.round(hsl[1] * 100) + "%, " + Math.round(hsl[2] * 100) + "%)";
}
var props = ["color", "background-color", "border-left-color", "border-right-color", "border-top-color", "border-bottom-color"];
var props2 = ["color", "backgroundColor", "borderLeftColor", "borderRightColor", "borderTopColor", "borderBottomColor"];
if (typeof getRGBColor(document.documentElement, "background-color") == "string") document.documentElement.style.backgroundColor = "white";
revl(document.documentElement);
function revl(n) {
var i, x, color, hsl;
if (n.nodeType == Node.ELEMENT_NODE) {
for (i = 0; x = n.childNodes[i]; ++i) revl(x);
for (i = 0; x = props[i]; ++i) {
color = getRGBColor(n, x);
if (typeof (color) != "string") {
hsl = RGBtoHSL(color);
hsl[2] = 1 - hsl[2];
n.style[props2[i]] = hslToCSS(hsl);
}
}
}
}
})()
I have saved this as a Bookmarklet in my Bookmark Bar on Google Chrome, but I want this to be automatically applied to every page I load. What should I do to achieve this?
You should write this as a userscript and run it with something like tampermonkey
Related
Lets say I have the following array of strings, var = array_of_strings["abc","abcd"]
My goal is to run a function and have this return roughly 75% (0.75). Implying that the results are roughly 75% in common. Roughly being defined as within a certain error range, let us say 5% or some settable number.
I'm currently using the the Levenshtein algorithm to compute differences in the strings, however, this is extremely slow and taxing on the CPU in my situation as the strings I'm using are thousands and thousands of lines long.
Levenshtein gives me what the differences are; and while useful in certain situations, my particular use case is simply looking to see what percentage the strings are roughly different from each other and not what each difference actually is necessarily.
The current levenshtein algorithm I'm using is below (which I borrowed from another answer here on stackoverflow). It will return how many differences it found which I can then use to calculate a percentage difference, but it's very slow! Sometimes taking a couple of seconds to run and freezes up the computer as well.
async function levenshtein(s, t) {
return new Promise((resolve, reject) => {
console.log("levenshtein active");
if (s === t) {
return 0;
}
var n = s.length, m = t.length;
if (n === 0 || m === 0) {
return n + m;
}
var x = 0, y, a, b, c, d, g, h, k;
var p = new Array(n);
for (y = 0; y < n;) {
p[y] = ++y;
}
for (; (x + 3) < m; x += 4) {
var e1 = t.charCodeAt(x);
var e2 = t.charCodeAt(x + 1);
var e3 = t.charCodeAt(x + 2);
var e4 = t.charCodeAt(x + 3);
c = x;
b = x + 1;
d = x + 2;
g = x + 3;
h = x + 4;
for (y = 0; y < n; y++) {
k = s.charCodeAt(y);
a = p[y];
if (a < c || b < c) {
c = (a > b ? b + 1 : a + 1);
}
else {
if (e1 !== k) {
c++;
}
}
if (c < b || d < b) {
b = (c > d ? d + 1 : c + 1);
}
else {
if (e2 !== k) {
b++;
}
}
if (b < d || g < d) {
d = (b > g ? g + 1 : b + 1);
}
else {
if (e3 !== k) {
d++;
}
}
if (d < g || h < g) {
g = (d > h ? h + 1 : d + 1);
}
else {
if (e4 !== k) {
g++;
}
}
p[y] = h = g;
g = d;
d = b;
b = c;
c = a;
}
}
for (; x < m;) {
var e = t.charCodeAt(x);
c = x;
d = ++x;
for (y = 0; y < n; y++) {
a = p[y];
if (a < c || d < c) {
d = (a > d ? d + 1 : a + 1);
}
else {
if (e !== s.charCodeAt(y)) {
d = c + 1;
}
else {
d = c;
}
}
p[y] = d;
c = a;
}
h = d;
}
resolve(h);
})
}
My question is, is there a way to calculate the difference faster when large string sets are used? In my case accuracy is not too important just as long as a rough difference is known of a certain percentage.
For example, if a research paper was published and I have the original paper and the students paper I want to know if roughly 10% of the students paper is plagiarized.
Maybe if I cut a random parts out of the strings this can help to save on time but this feels very dirty/inefficient.
I have a for loop like this:
var speed = 100;
var curve = [];
for (var i = 0; i < 5; i++) {
curve.push(i*speed);
}
So for the last loop its 400, the question is how do i implement ease in and out in the for loop? roughly in the end the result should be like this? [0,52,200,348,400]
EDIT:
var defaultSpin = 24;
var totalSlices = 12;
for (var i = 0; i < defaultSpin; i++) {
highlight(divs[i%totalSlices], i*100, 100);
}
function highlight(el, delay, duration) {
setTimeout(function() {
el.className += ' active';
setTimeout(function() {
el.className = 'pie';
}, duration)
}, delay)
}
It is a spin wheel with highlight instead of actually spinning it. I'm calling the above function with the loop. for now it only has constant speed because each loop difference is only 100 so the 1st hightlight delay is 0 and it start immediately. 2nd is 100, 3rd is 200 and so on.
Lots of common easing functions are shown here:
http://gizma.com/easing/
Here is an example of how to use one:
// from http://gizma.com/easing/
var easeInOutQuad = function (t, b, c, d) {
t /= d/2;
if (t < 1) return c/2*t*t + b;
t--;
return -c/2 * (t*(t-2) - 1) + b;
};
var steps = 4
var speed = 100
var curve = []
for (var i = 0; i < steps+1; i++) {
var stepValue = easeInOutQuad(i, 0, speed*steps, steps);
curve.push(stepValue);
}
console.log(curve); // [0, 50, 200, 350, 400]
Hey take a note of this snippet
/*\
* Raphael.easing_formulas
[ property ]
**
* Object that contains easing formulas for animation. You could extend it with your own. By default it has following list of easing:
# <ul>
# <li>“linear”</li>
# <li>“<” or “easeIn” or “ease-in”</li>
# <li>“>” or “easeOut” or “ease-out”</li>
# <li>“<>” or “easeInOut” or “ease-in-out”</li>
# <li>“backIn” or “back-in”</li>
# <li>“backOut” or “back-out”</li>
# <li>“elastic”</li>
# <li>“bounce”</li>
# </ul>
# <p>See also Easing demo.</p>
\*/
var ef = R.easing_formulas = {
linear: function (n) {
return n;
},
"<": function (n) {
return pow(n, 1.7);
},
">": function (n) {
return pow(n, .48);
},
"<>": function (n) {
var q = .48 - n / 1.04,
Q = math.sqrt(.1734 + q * q),
x = Q - q,
X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1),
y = -Q - q,
Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1),
t = X + Y + .5;
return (1 - t) * 3 * t * t + t * t * t;
},
backIn: function (n) {
var s = 1.70158;
return n * n * ((s + 1) * n - s);
},
backOut: function (n) {
n = n - 1;
var s = 1.70158;
return n * n * ((s + 1) * n + s) + 1;
},
elastic: function (n) {
if (n == !!n) {
return n;
}
return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1;
},
bounce: function (n) {
var s = 7.5625,
p = 2.75,
l;
if (n < (1 / p)) {
l = s * n * n;
} else {
if (n < (2 / p)) {
n -= (1.5 / p);
l = s * n * n + .75;
} else {
if (n < (2.5 / p)) {
n -= (2.25 / p);
l = s * n * n + .9375;
} else {
n -= (2.625 / p);
l = s * n * n + .984375;
}
}
}
return l;
}
};
ef.easeIn = ef["ease-in"] = ef["<"];
ef.easeOut = ef["ease-out"] = ef[">"];
ef.easeInOut = ef["ease-in-out"] = ef["<>"];
ef["back-in"] = ef.backIn;
ef["back-out"] = ef.backOut;
This is a snippet from Raphael. Here you see you have a list of animation ease-in formulas.
Lets try one of them, e.g. ease-in
var pow = Math.pow;
function easeIn(n) {
return pow(n, 1.7);
}
function easeOut(n) {
return pow(n, .48);
}
function process(min, max, intervals, fN) {
var diff = 1 / intervals,
difference = max - min,
curve = [];
for (i = diff; i <= 1; i += diff) {
curve.push(min + (difference * fN(i)));
}
return curve;
}
console.log('easeIn: \n', process(0, 400, 5, easeIn));
console.log('easeOut: \n', process(0, 400, 5, easeOut));
This might not be in sync with the output you have expected. But these are the formulas a renowned JS SVG library like Rapahel uses. You would love this demo
I have translated the following C++ code:
#include <iostream>
using namespace std;
#define NDIGITS 100
#define LEN (NDIGITS/4+1)*14
long a[LEN];
long b;
long c = LEN;
long d;
long e = 0;
long f = 10000;
long g;
long h = 0;
int main(void) {
cout<<b<<endl;
for(; (b=c-=14) > 0 ;){
for(; --b > 0 ;){
d *= b;
if( h == 0 )
d += 2000*f;
else
d += a[b]*f;
g=b+b-1;
a[b] = d % g;
d /= g;
}
h = printf("%ld",e+d/f);
d = e = d % f;
}
getchar();
return 0;
}
Into JavaScript:
function mod(n, m) {
return ((m % n) + n) % n;
} // mod function to fix javascript modulo bug
function calculate(NDIGITS){
var LEN = (NDIGITS / 4 + 1) * 14,
out = "",
a = [],
b = 0,
c = LEN,
d = 0,
e = 0,
f = 10000,
g = 0,
h = 0;
for( ; a.length != LEN; a.push(0));
for( ; (b=c-=14) > 0 ; ){
for(; --b > 0 ;){
d *= b;
if(h == 0)
d += 2000*f;
else
d += a[b]*f;
g=b+b-1;
a[b] = mod(d, g);
d /= g;
};
h = 4;
out += e + d / f;
d = e = mod(d, f);
};
return out;
};
calculate(100);
The problem is, the C++ (which is correct) output looks like this:
314159265358979323846264338327952884197169399375105820974944592307816406286208998628034825342117067
But the JavaScript (which is wrong) output looks like this:
3141.59265358979345928.3358757688158002.0385670499462603.1996016540431161.44919092773639662.2465149363658988.6127837844255865.38922090756173.61883094848226189.6324225085448150.3443440509899223.2179589088062808.1943642437717982.8973948575671840.86646781354151140.38694447211833938.5632867441137341.458720505086448.7384444661472807.14448220310268936.5521832735086764.9290682040381301.76585926509928223.4135991546457438.115065010927
Where did I mess up in my coding? Thanks for the help.
JavaScript does floating point division.
Arguments exchanged in modulo calculation function.
Here is code that produces the same result as the C++ code provided for the given sample (100) digits:
function mod(m, n) {
return ((m % n) + n) % n;
} // mod function to fix javascript modulo bug
function calculate(NDIGITS) {
var LEN = (NDIGITS / 4 + 1) * 14,
out = "",
a = [],
b = 0,
c = LEN,
d = 0,
e = 0,
f = 10000,
g = 0,
h = 0;
for (; a.length !== LEN; a.push(0));
for (; (b = c -= 14) > 0;) {
for (; --b > 0;) {
d *= b;
if (h === 0) {
d += 2000 * f;
} else {
d += a[b] * f;
}
g = b + b - 1;
a[b] = mod(d, g);
d = Math.floor(d / g);
}
h = Math.floor(e + d / f);
out += h;
h = h.length;
d = e = mod(d, f);
}
return out;
}
console.log(calculate(100));
I want to build a Thunderbird addon for encryption/decryption of email. I have the JavaScript code but I don't know how to use XUL to make it work.
Here is the JavaScript code in HTML: Fiddle.
var Alphabet = "!\"#$%&'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ \n𮃩∆";
Alphabet = Alphabet.split("");
var Crypto = function (alpha, gen, C) {
var p, B, encrypt, decrypt, f, g, modInv, modPow, toAlpha, to10;
toAlpha = function (x) {
var y, p, l, n;
if (x === 0) {
return "!!!!";
}
y = [];
n = 4;
n = Math.ceil(n);
while (n--) {
p = Math.pow(alpha.length, n);
l = Math.floor(x / p);
y.push(alpha[l]);
x -= l * p;
}
y = y.join("");
return y;
};
to10 = function (x) {
var y, p, n;
y = 0;
p = 1;
x = x.split("");
n = x.length;
while (n--) {
y += alpha.indexOf(x[n]) * p;
p *= alpha.length;
}
return y;
};
modInv = function (gen, mod) {
var v, d, u, t, c, q;
v = 1;
d = gen;
t = 1;
c = mod % gen;
u = Math.floor(mod / gen);
while (d > 1) {
q = Math.floor(d / c);
d = d % c;
v = v + q * u;
if (d) {
q = Math.floor(c / d);
c = c % d;
u = u + q * v;
}
}
return d ? v : mod - u;
};
modPow = function (base, exp, mod) {
var c, x;
if (exp === 0) {
return 1;
} else if (exp < 0) {
exp = -exp;
base = modInv(base, mod);
}
c = 1;
while (exp > 0) {
if (exp % 2 === 0) {
base = (base * base) % mod;
exp /= 2;
} else {
c = (c * base) % mod;
exp--;
}
}
return c;
};
p = 91744613;
C = parseInt(C, 10);
if (isNaN(C)) {
C = Math.round(Math.sqrt(Math.random() * Math.random()) * (p - 2) + 2);
alert("Your new private key is "+C);
}
B = modPow(gen, C, p);
decrypt = function (a) {
var d, x, y;
x = a[1];
y = modPow(a[0], -C, p);
d = (x * y) % p;
d = Math.round(d) % p;
return alpha[d - 2];
};
encrypt = function (key, d) {
var k, a;
k = Math.ceil(Math.sqrt(Math.random() * Math.random()) * 1E10);
d = alpha.indexOf(d) + 2;
a = [];
a[0] = modPow(key[1], k, key[0]);
a[1] = (d * modPow(key[2], k, key[0])) % key[0];
return a;
};
f = function (message, key) {
var n, x, y, w;
y = [];
message = message.split("");
n = message.length;
while (n--) {
x = encrypt(key, message[n]);
y.push(toAlpha(x[0]));
y.push(toAlpha(x[1]));
}
y = y.join("");
return y;
};
g = function (message) {
var n, m, d, x;
m = [];
n = message.length / 8;
while (n--) {
x = message[8 * n + 4];
x += message[8 * n + 5];
x += message[8 * n + 6];
x += message[8 * n + 7];
m.unshift(x);
x = message[8 * n];
x += message[8 * n + 1];
x += message[8 * n + 2];
x += message[8 * n + 3];
m.unshift(x);
}
x = [];
d = [];
n = m.length / 2;
while (n--) {
x[0] = m[2 * n];
x[1] = m[2 * n + 1];
x[0] = to10(x[0]);
x[1] = to10(x[1]);
d.push(decrypt(x));
}
message = d.join("");
return message;
};
return {
pubKey: [p, gen, B],
priKey: C,
decrypt: g,
encrypt: f
};
};
var key = prompt("Do you already have a private key? If so, enter it here. Otherwise, a new one will be generated for you.");
var user = Crypto(Alphabet, 62, key);
var dataBox = document.getElementById("inputBox");
document.getElementById("userPriKeyBox").innerHTML = user.priKey;
document.getElementById("userPubKeyBox").innerHTML = user.pubKey.join(" ");
document.getElementById("encryptBox").onclick = function () {
var x, y, z;
x = dataBox.value;
if (x === "") {
alert("Please enter some data in the input box.");
return false;
}
y = document.getElementById("recPubKeyBox").value;
if (y === "") {
alert("Please enter a valid public key into the public key box.");
return false;
}
y = y.split(" ");
if (y.length != 3) {
alert("Please enter a valid public key into the public key box.");
return false;
}
y[0] = parseInt(y[0], 10);
y[1] = parseInt(y[1], 10);
y[2] = parseInt(y[2], 10);
if (isNaN(y[0]) || y[0] < 1 || isNaN(y[1]) || y[1] < 1 || isNaN(y[2]) || y[2] < 1) {
alert("Please enter a valid public key into the public key box.");
return false;
}
z = user.encrypt(x, y);
dataBox.value = z;
};
document.getElementById("decryptBox").onclick = function () {
var x, z;
x = dataBox.value;
if (x === "") {
alert("Please enter some data in the input box.");
return false;
}
z = user.decrypt(x);
dataBox.value = z;
};
<div style="font-family:monospace">Your private key:
<span id="userPriKeyBox"></span>
<br/>Your public key:
<span id="userPubKeyBox"></span>
<br/>Recipient's public key:
<input id="recPubKeyBox" style="font-family:monospace">
<br/>
<textarea id="inputBox" rows="15" cols="50" style="font-family:monospace"></textarea>
<br/>
<input type="button" value="Encrypt" id="encryptBox" />
<input type="button" value="Decrypt" id="decryptBox" />
<br/>
</div>
How can I use that JavaScript code in a Thunderbird addon?
This tutorial helped me a lot.
I hope it will help you to succeed with your extension, too.
I am looking for a good general purpose Levenshtein implementation in Javascript. It must be fast and be useful for short and long strings. It should also be used many times (hence the caching). The most important thing is that it calculates a plain simple Levenshtein distance. I came up with this:
var levenshtein = (function() {
var row2 = [];
return function(s1, s2) {
if (s1 === s2) {
return 0;
} else {
var s1_len = s1.length, s2_len = s2.length;
if (s1_len && s2_len) {
var i1 = 0, i2 = 0, a, b, c, c2, row = row2;
while (i1 < s1_len)
row[i1] = ++i1;
while (i2 < s2_len) {
c2 = s2.charCodeAt(i2);
a = i2;
++i2;
b = i2;
for (i1 = 0; i1 < s1_len; ++i1) {
c = a + (s1.charCodeAt(i1) === c2 ? 0 : 1);
a = row[i1];
b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
row[i1] = b;
}
}
return b;
} else {
return s1_len + s2_len;
}
}
};
})();
Now I have two questions:
Can this be faster? I know by writing out the first iteration of each loop one can gain about 20%.
Is this code well written to serve as general purpose code, to be used in a library for instance?
We had a competition for fun at work about making the fastest levenshtein implementation and I came up with a faster one. First of all, I must say that it was not easy to beat your solution which was the fastest to find "out there". :)
This is tested with node.js and it my benchmarks results indicates that this implementation is ~15% faster on small texts (random words size 2-10 characters) and over twice as fast on longer texts (with lengths 30+ containing random characters)
Note: I removed array caching of all implementations
function levenshtein(s, t) {
if (s === t) {
return 0;
}
var n = s.length, m = t.length;
if (n === 0 || m === 0) {
return n + m;
}
var x = 0, y, a, b, c, d, g, h, k;
var p = new Array(n);
for (y = 0; y < n;) {
p[y] = ++y;
}
for (; (x + 3) < m; x += 4) {
var e1 = t.charCodeAt(x);
var e2 = t.charCodeAt(x + 1);
var e3 = t.charCodeAt(x + 2);
var e4 = t.charCodeAt(x + 3);
c = x;
b = x + 1;
d = x + 2;
g = x + 3;
h = x + 4;
for (y = 0; y < n; y++) {
k = s.charCodeAt(y);
a = p[y];
if (a < c || b < c) {
c = (a > b ? b + 1 : a + 1);
}
else {
if (e1 !== k) {
c++;
}
}
if (c < b || d < b) {
b = (c > d ? d + 1 : c + 1);
}
else {
if (e2 !== k) {
b++;
}
}
if (b < d || g < d) {
d = (b > g ? g + 1 : b + 1);
}
else {
if (e3 !== k) {
d++;
}
}
if (d < g || h < g) {
g = (d > h ? h + 1 : d + 1);
}
else {
if (e4 !== k) {
g++;
}
}
p[y] = h = g;
g = d;
d = b;
b = c;
c = a;
}
}
for (; x < m;) {
var e = t.charCodeAt(x);
c = x;
d = ++x;
for (y = 0; y < n; y++) {
a = p[y];
if (a < c || d < c) {
d = (a > d ? d + 1 : a + 1);
}
else {
if (e !== s.charCodeAt(y)) {
d = c + 1;
}
else {
d = c;
}
}
p[y] = d;
c = a;
}
h = d;
}
return h;
}
On longer texts it will get almost up to 3 times the speed of your implementation if it initially cache the inner loop's s.charCodeAt(y) in an Uint32Array. Longer texts also seemed to benefit from using a Uint16Array as a the distance cost array. Here is the code for that solution
function levenshtein(s, t) {
if (s === t) {
return 0;
}
var n = s.length, m = t.length;
if (n === 0 || m === 0) {
return n + m;
}
var x = 0, y, a, b, c, d, g, h;
var p = new Uint16Array(n);
var u = new Uint32Array(n);
for (y = 0; y < n;) {
u[y] = s.charCodeAt(y);
p[y] = ++y;
}
for (; (x + 3) < m; x += 4) {
var e1 = t.charCodeAt(x);
var e2 = t.charCodeAt(x + 1);
var e3 = t.charCodeAt(x + 2);
var e4 = t.charCodeAt(x + 3);
c = x;
b = x + 1;
d = x + 2;
g = x + 3;
h = x + 4;
for (y = 0; y < n; y++) {
a = p[y];
if (a < c || b < c) {
c = (a > b ? b + 1 : a + 1);
}
else {
if (e1 !== u[y]) {
c++;
}
}
if (c < b || d < b) {
b = (c > d ? d + 1 : c + 1);
}
else {
if (e2 !== u[y]) {
b++;
}
}
if (b < d || g < d) {
d = (b > g ? g + 1 : b + 1);
}
else {
if (e3 !== u[y]) {
d++;
}
}
if (d < g || h < g) {
g = (d > h ? h + 1 : d + 1);
}
else {
if (e4 !== u[y]) {
g++;
}
}
p[y] = h = g;
g = d;
d = b;
b = c;
c = a;
}
}
for (; x < m;) {
var e = t.charCodeAt(x);
c = x;
d = ++x;
for (y = 0; y < n; y++) {
a = p[y];
if (a < c || d < c) {
d = (a > d ? d + 1 : a + 1);
}
else {
if (e !== u[y]) {
d = c + 1;
}
else {
d = c;
}
}
p[y] = d;
c = a;
}
h = d;
}
return h;
}
All benchmark results is from my tests and test-data might be different with your test-data.
The main 2 difference in this solution than to yours (and some other fast ones) I think is
Not always do compare of the characters in the inner loop if not necessary.
Sort of "Loop unrolling" in the outer loop doing 4 rows at a time in the levenshtein "matrix". This was a major performance win.
http://jsperf.com/levenshtein-distance/24
I will put this solution on github when I find the time :)
Update:
Finally, I put the solution on github
https://github.com/gustf/js-levenshtein. Its a bit modified/optimized but it is the same base algorithm.