mirror of
https://github.com/atlanticbiomedical/biomedjs.git
synced 2025-07-02 00:47:26 -04:00
Added a bunch of stuff
This commit is contained in:
352
public/js/lib/hashids.js
Normal file
352
public/js/lib/hashids.js
Normal file
@ -0,0 +1,352 @@
|
||||
|
||||
/*
|
||||
|
||||
Hashids
|
||||
http://hashids.org/javascript
|
||||
(c) 2013 Ivan Akimov
|
||||
|
||||
https://github.com/ivanakimov/hashids.js
|
||||
hashids may be freely distributed under the MIT license.
|
||||
|
||||
*/
|
||||
|
||||
/*jslint plusplus: true, nomen: true, browser: true */
|
||||
/*global define */
|
||||
|
||||
var Hashids = (function () {
|
||||
|
||||
"use strict";
|
||||
|
||||
function Hashids(salt, minHashLength, alphabet) {
|
||||
|
||||
var uniqueAlphabet, i, j, len, sepsLength, diff, guardCount;
|
||||
|
||||
this.version = "1.0.2";
|
||||
|
||||
/* internal settings */
|
||||
|
||||
this.minAlphabetLength = 16;
|
||||
this.sepDiv = 3.5;
|
||||
this.guardDiv = 12;
|
||||
|
||||
/* error messages */
|
||||
|
||||
this.errorAlphabetLength = "error: alphabet must contain at least X unique characters";
|
||||
this.errorAlphabetSpace = "error: alphabet cannot contain spaces";
|
||||
|
||||
/* alphabet vars */
|
||||
|
||||
this.alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
|
||||
this.seps = "cfhistuCFHISTU";
|
||||
this.minHashLength = parseInt(minHashLength, 10) > 0 ? minHashLength : 0;
|
||||
this.salt = (typeof salt === "string") ? salt : "";
|
||||
|
||||
if (typeof alphabet === "string") {
|
||||
this.alphabet = alphabet;
|
||||
}
|
||||
|
||||
for (uniqueAlphabet = "", i = 0, len = this.alphabet.length; i !== len; i++) {
|
||||
if (uniqueAlphabet.indexOf(this.alphabet.charAt(i)) === -1) {
|
||||
uniqueAlphabet += this.alphabet.charAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
this.alphabet = uniqueAlphabet;
|
||||
|
||||
if (this.alphabet.length < this.minAlphabetLength) {
|
||||
throw this.errorAlphabetLength.replace("X", this.minAlphabetLength);
|
||||
}
|
||||
|
||||
if (this.alphabet.search(" ") !== -1) {
|
||||
throw this.errorAlphabetSpace;
|
||||
}
|
||||
|
||||
/* seps should contain only characters present in alphabet; alphabet should not contains seps */
|
||||
|
||||
for (i = 0, len = this.seps.length; i !== len; i++) {
|
||||
|
||||
j = this.alphabet.indexOf(this.seps.charAt(i));
|
||||
if (j === -1) {
|
||||
this.seps = this.seps.substr(0, i) + " " + this.seps.substr(i + 1);
|
||||
} else {
|
||||
this.alphabet = this.alphabet.substr(0, j) + " " + this.alphabet.substr(j + 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.alphabet = this.alphabet.replace(/ /g, "");
|
||||
|
||||
this.seps = this.seps.replace(/ /g, "");
|
||||
this.seps = this.consistentShuffle(this.seps, this.salt);
|
||||
|
||||
if (!this.seps.length || (this.alphabet.length / this.seps.length) > this.sepDiv) {
|
||||
|
||||
sepsLength = Math.ceil(this.alphabet.length / this.sepDiv);
|
||||
|
||||
if (sepsLength === 1) {
|
||||
sepsLength++;
|
||||
}
|
||||
|
||||
if (sepsLength > this.seps.length) {
|
||||
|
||||
diff = sepsLength - this.seps.length;
|
||||
this.seps += this.alphabet.substr(0, diff);
|
||||
this.alphabet = this.alphabet.substr(diff);
|
||||
|
||||
} else {
|
||||
this.seps = this.seps.substr(0, sepsLength);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.alphabet = this.consistentShuffle(this.alphabet, this.salt);
|
||||
guardCount = Math.ceil(this.alphabet.length / this.guardDiv);
|
||||
|
||||
if (this.alphabet.length < 3) {
|
||||
this.guards = this.seps.substr(0, guardCount);
|
||||
this.seps = this.seps.substr(guardCount);
|
||||
} else {
|
||||
this.guards = this.alphabet.substr(0, guardCount);
|
||||
this.alphabet = this.alphabet.substr(guardCount);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Hashids.prototype.encode = function () {
|
||||
|
||||
var ret = "", i, len,
|
||||
numbers = Array.prototype.slice.call(arguments);
|
||||
|
||||
if (!numbers.length) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (numbers[0] instanceof Array) {
|
||||
numbers = numbers[0];
|
||||
}
|
||||
|
||||
for (i = 0, len = numbers.length; i !== len; i++) {
|
||||
if (typeof numbers[i] !== "number" || numbers[i] % 1 !== 0 || numbers[i] < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return this._encode(numbers);
|
||||
|
||||
};
|
||||
|
||||
Hashids.prototype.decode = function (hash) {
|
||||
|
||||
var ret = [];
|
||||
|
||||
if (!hash.length || typeof hash !== "string") {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return this._decode(hash, this.alphabet);
|
||||
|
||||
};
|
||||
|
||||
Hashids.prototype.encodeHex = function (str) {
|
||||
|
||||
var i, len, numbers;
|
||||
|
||||
str = str.toString();
|
||||
if (!/^[0-9a-fA-F]+$/.test(str)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
numbers = str.match(/[\w\W]{1,12}/g);
|
||||
|
||||
for (i = 0, len = numbers.length; i !== len; i++) {
|
||||
numbers[i] = parseInt("1" + numbers[i], 16);
|
||||
}
|
||||
|
||||
return this.encode.apply(this, numbers);
|
||||
|
||||
};
|
||||
|
||||
Hashids.prototype.decodeHex = function (hash) {
|
||||
|
||||
var ret = [], i, len,
|
||||
numbers = this.decode(hash);
|
||||
|
||||
for (i = 0, len = numbers.length; i !== len; i++) {
|
||||
ret += (numbers[i]).toString(16).substr(1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
};
|
||||
|
||||
Hashids.prototype._encode = function (numbers) {
|
||||
|
||||
var ret, lottery, i, len, number, buffer, last, sepsIndex, guardIndex, guard, halfLength, excess,
|
||||
alphabet = this.alphabet,
|
||||
numbersSize = numbers.length,
|
||||
numbersHashInt = 0;
|
||||
|
||||
for (i = 0, len = numbers.length; i !== len; i++) {
|
||||
numbersHashInt += (numbers[i] % (i + 100));
|
||||
}
|
||||
|
||||
lottery = ret = alphabet.charAt(numbersHashInt % alphabet.length);
|
||||
for (i = 0, len = numbers.length; i !== len; i++) {
|
||||
|
||||
number = numbers[i];
|
||||
buffer = lottery + this.salt + alphabet;
|
||||
|
||||
alphabet = this.consistentShuffle(alphabet, buffer.substr(0, alphabet.length));
|
||||
last = this.hash(number, alphabet);
|
||||
|
||||
ret += last;
|
||||
|
||||
if (i + 1 < numbersSize) {
|
||||
number %= (last.charCodeAt(0) + i);
|
||||
sepsIndex = number % this.seps.length;
|
||||
ret += this.seps.charAt(sepsIndex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (ret.length < this.minHashLength) {
|
||||
|
||||
guardIndex = (numbersHashInt + ret[0].charCodeAt(0)) % this.guards.length;
|
||||
guard = this.guards[guardIndex];
|
||||
|
||||
ret = guard + ret;
|
||||
|
||||
if (ret.length < this.minHashLength) {
|
||||
|
||||
guardIndex = (numbersHashInt + ret[2].charCodeAt(0)) % this.guards.length;
|
||||
guard = this.guards[guardIndex];
|
||||
|
||||
ret += guard;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
halfLength = parseInt(alphabet.length / 2, 10);
|
||||
while (ret.length < this.minHashLength) {
|
||||
|
||||
alphabet = this.consistentShuffle(alphabet, alphabet);
|
||||
ret = alphabet.substr(halfLength) + ret + alphabet.substr(0, halfLength);
|
||||
|
||||
excess = ret.length - this.minHashLength;
|
||||
if (excess > 0) {
|
||||
ret = ret.substr(excess / 2, this.minHashLength);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
};
|
||||
|
||||
Hashids.prototype._decode = function (hash, alphabet) {
|
||||
|
||||
var ret = [], i = 0,
|
||||
lottery, len, subHash, buffer,
|
||||
r = new RegExp("[" + this.guards + "]", "g"),
|
||||
hashBreakdown = hash.replace(r, " "),
|
||||
hashArray = hashBreakdown.split(" ");
|
||||
|
||||
if (hashArray.length === 3 || hashArray.length === 2) {
|
||||
i = 1;
|
||||
}
|
||||
|
||||
hashBreakdown = hashArray[i];
|
||||
if (typeof hashBreakdown[0] !== "undefined") {
|
||||
|
||||
lottery = hashBreakdown[0];
|
||||
hashBreakdown = hashBreakdown.substr(1);
|
||||
|
||||
r = new RegExp("[" + this.seps + "]", "g");
|
||||
hashBreakdown = hashBreakdown.replace(r, " ");
|
||||
hashArray = hashBreakdown.split(" ");
|
||||
|
||||
for (i = 0, len = hashArray.length; i !== len; i++) {
|
||||
|
||||
subHash = hashArray[i];
|
||||
buffer = lottery + this.salt + alphabet;
|
||||
|
||||
alphabet = this.consistentShuffle(alphabet, buffer.substr(0, alphabet.length));
|
||||
ret.push(this.unhash(subHash, alphabet));
|
||||
|
||||
}
|
||||
|
||||
if (this._encode(ret) !== hash) {
|
||||
ret = [];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
};
|
||||
|
||||
Hashids.prototype.consistentShuffle = function (alphabet, salt) {
|
||||
|
||||
var integer, j, temp, i, v, p;
|
||||
|
||||
if (!salt.length) {
|
||||
return alphabet;
|
||||
}
|
||||
|
||||
for (i = alphabet.length - 1, v = 0, p = 0; i > 0; i--, v++) {
|
||||
|
||||
v %= salt.length;
|
||||
p += integer = salt.charAt(v).charCodeAt(0);
|
||||
j = (integer + v + p) % i;
|
||||
|
||||
temp = alphabet.charAt(j);
|
||||
alphabet = alphabet.substr(0, j) + alphabet.charAt(i) + alphabet.substr(j + 1);
|
||||
alphabet = alphabet.substr(0, i) + temp + alphabet.substr(i + 1);
|
||||
|
||||
}
|
||||
|
||||
return alphabet;
|
||||
|
||||
};
|
||||
|
||||
Hashids.prototype.hash = function (input, alphabet) {
|
||||
|
||||
var hash = "",
|
||||
alphabetLength = alphabet.length;
|
||||
|
||||
do {
|
||||
hash = alphabet.charAt(input % alphabetLength) + hash;
|
||||
input = parseInt(input / alphabetLength, 10);
|
||||
} while (input);
|
||||
|
||||
return hash;
|
||||
|
||||
};
|
||||
|
||||
Hashids.prototype.unhash = function (input, alphabet) {
|
||||
|
||||
var number = 0, pos, i;
|
||||
|
||||
for (i = 0; i < input.length; i++) {
|
||||
pos = alphabet.indexOf(input[i]);
|
||||
number += pos * Math.pow(alphabet.length, input.length - i - 1);
|
||||
}
|
||||
|
||||
return number;
|
||||
|
||||
};
|
||||
|
||||
/* require.js bit */
|
||||
|
||||
if (typeof define === "function" && typeof define.amd === "object" && define.amd) {
|
||||
|
||||
define(function () {
|
||||
return Hashids;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return Hashids;
|
||||
|
||||
}());
|
Reference in New Issue
Block a user