js/Mobilizing/core/util/Misc.js
/**
* Simple object check.
* @param {any} item - The item
* @return {boolean} True if object, false otherwise.
*/
export function isObject(item) {
return (item && typeof item === 'object' && !Array.isArray(item) && item !== null);
}
import cloneDeep from "lodash/cloneDeep";
export function cloneObject(object) {
return cloneDeep(object);
}
/**
* Method to convert a string to Base64. Used internally to convert loaded raw data to img. Wrote by phil@philten.com - http://www.philten.com
*
* @author phil@philten.com - http://www.philten.com
* Date: 2010/12/15
* version: 1.0
* url french: http://www.philten.com/fr-xmlhttprequest-image
* url english: http://www.philten.com/us-xmlhttprequest-image
* @param inputStr the string to encode
*/
export function encode64(inputStr) {
const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
let outputStr = "";
let i = 0;
while (i < inputStr.length) {
//all three "& 0xff" added below are there to fix a known bug
//with bytes returned by xhr.responseText
const byte1 = inputStr.charCodeAt(i++) & 0xff;
const byte2 = inputStr.charCodeAt(i++) & 0xff;
const byte3 = inputStr.charCodeAt(i++) & 0xff;
const enc1 = byte1 >> 2;
const enc2 = ((byte1 & 3) << 4) | (byte2 >> 4);
var enc3, enc4;
if (isNaN(byte2)) {
enc3 = enc4 = 64;
}
else {
enc3 = ((byte2 & 15) << 2) | (byte3 >> 6);
if (isNaN(byte3)) {
enc4 = 64;
}
else {
enc4 = byte3 & 63;
}
}
outputStr += b64.charAt(enc1) + b64.charAt(enc2) + b64.charAt(enc3) + b64.charAt(enc4);
}
return outputStr;
}
/**
* Converts a DOMString to an ArrayBuffer (raw data binary).
*
* @param {DOMString} str a string returned by a XMLHTTPRequest (responseText)
* @return {ArrayBuffer} the resulting ArrayBuffer
*/
export function stringToArrayBuffer(str) {
const buffer = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buffer);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buffer;
}
export function getFileExtension(url){
if (url.lastIndexOf(".") > 0) {
return url.substr(url.lastIndexOf(".")).toLowerCase();
}
return null;
}
/**
* Extract the MimeType from the URL string of image files. Used internally for texture loading
*
* @param {String} url
* @return {String} mimeType from the url
*/
export function getMimeType(url) {
let mimeType = null;
const extension = getFileExtension(url);
if (extension === ".jpg" || extension === ".jpeg") {
mimeType = "jpeg";
}
else if (extension === ".tiff" || extension === ".tif") {
mimeType = "tiff";
}
else if (extension === ".png") {
mimeType = "png";
}
else if (extension === ".gif") {
mimeType = "gif";
}
console.log(`extension ${extension}`, `mimeType ${mimeType}`);
return mimeType;
}
/**
* Returns a throttled version of a function
* The returned function will only call the original function at most once per the specified threshhold
*
* @param {Function} fn The function to throttle
* @param {Number} threshhold The threshhold in milliseconds
* @param {Object} scope The scope in which the original function will be called
* @return {Function} The throttled function
*/
export function throttle(fn, threshhold, scope = null) {
let inThrottle;
return function () {
const args = arguments;
if (!inThrottle) {
fn.apply(scope, args);
inThrottle = true;
setTimeout(() => {
inThrottle = false
}, threshhold);
}
}
}
/**
* A function that return null as a value
*
* @return {null} null
*/
export function noop() {
return null;
}
/**
* function to get the parameters of the url
*
* @param sParam the string of the parameter to get from the url
* @return {String} the parameter if found, undefined elsewhere
*/
export function getUrlParameter(sParam) {
const sPageURL = decodeURIComponent(window.location.search.substring(1));
const sURLVariables = sPageURL.split('&');
for (let i = 0; i < sURLVariables.length; i++) {
const sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] === sParam) {
return (typeof sParameterName[1] === "undefined") ? true : sParameterName[1];
}
}
return undefined;
}
/**
* Generate a random uuid
*
* @author Broofa <robert@broofa.com> (http://www.broofa.com/2008/09/javascript-uuid-function/)
* @param {Integer} [len] The desired number of characters
* @param {Integer} [radix] The number of allowable values for each character
* @return {String} The generated uuid
*
* @example
* let id = uuid();
* // "66209871-857D-4A12-AC7E-E9EEBC2A6AC3"
*
* @example
* let id = uuid(5);
* // "kryIh"
*
* @example
* let id = uuid(5, 2);
* // "10100"
*/
export function uuid(len, radix) {
const chars = [
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
];
const _radix = radix || chars.length;
const id = [];
if (len) {
// Compact form
for (let i = 0; i < len; i++) {
id[i] = chars[0 | Math.random() * _radix];
}
}
else {
// rfc4122 requires these characters
id[8] = id[13] = id[18] = id[23] = '-';
id[14] = '4';
// Fill in random data. At i==19 set the high bits of clock sequence as per rfc4122, sec. 4.1.5
for (let i = 0; i < 36; i++) {
if (!id[i]) {
const r = 0 | Math.random() * 16;
id[i] = chars[(i === 19) ? (r & 0x3) | 0x8 : r];
}
}
}
return id.join('');
}
/**
Copyright (c) 2011, Daniel Guerrero
All rights reserved.
* Uses the new array typed in javascript to binary base64 encode/decode
* at the moment just decodes a binary base64 encoded
* into either an ArrayBuffer (decodeArrayBuffer)
* or into an Uint8Array (decode)
*
* References:
* https://developer.mozilla.org/en/JavaScript_typed_arrays/ArrayBuffer
* https://developer.mozilla.org/en/JavaScript_typed_arrays/Uint8Array
*/
export class Base64Binary {
constructor() {
this._keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
}
/* will return a Uint8Array type */
decodeArrayBuffer(input) {
const bytes = (input.length / 4) * 3;
const ab = new ArrayBuffer(bytes);
this.decode(input, ab);
return ab;
}
removePaddingChars(input) {
const lkey = this._keyStr.indexOf(input.charAt(input.length - 1));
if (lkey === 64) {
return input.substring(0, input.length - 1);
}
return input;
}
decode(input, arrayBuffer) {
//get last chars to see if are valid
input = this.removePaddingChars(input);
input = this.removePaddingChars(input);
const bytes = parseInt((input.length / 4) * 3, 10);
let uarray;
let chr1, chr2, chr3;
let enc1, enc2, enc3, enc4;
let i = 0;
let j = 0;
if (arrayBuffer) {
uarray = new Uint8Array(arrayBuffer);
}
else {
uarray = new Uint8Array(bytes);
}
const regex = /[^A-Za-z0-9\+\/\=]/g;
input = input.replace(regex, "");
for (i = 0; i < bytes; i += 3) {
//get the 3 octects in 4 ascii chars
enc1 = this._keyStr.indexOf(input.charAt(j++));
enc2 = this._keyStr.indexOf(input.charAt(j++));
enc3 = this._keyStr.indexOf(input.charAt(j++));
enc4 = this._keyStr.indexOf(input.charAt(j++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
uarray[i] = chr1;
if (enc3 !== 64) {
uarray[i + 1] = chr2;
}
if (enc4 !== 64) {
uarray[i + 2] = chr3;
}
}
return uarray;
}
}