/*jshint esversion: 6*/
var Cluster = {
'version': '0.0.1',
'versiontype': 'alpha',
'className': 'cluster',
'path': 'cluster/',
'mainFileName': 'cluster.js',
'Utils': {
uppath(path, level) {
var r = path.split('/'), f='';
r.forEach( (e, i) => {
if(i<level){
f+=e;
}
});
return f;
},
downpath(path, level) {
var r = path.split('/').reverse(), f='';
r.forEach( (e, i) => {
if(i<level){
f=e+'/'+f;
}
});
return f;
},
goodTime(ms){
if(ms >= 1000) return (ms/1000).toFixed(3)+'s';
else if(ms < 1 && ms > 0.001) return (ms*1000).toFixed(3)+'µs';
else if(ms <= 0.001) return (ms*1000000).toFixed(3)+'ns';
else return ms.toFixed(3)+'ms';
}
}
};
Cluster.whereShouldBe = function(needed){
var parsed_propertie, result='', ppath;
parsed_propertie = needed.split('.');
var last = Cluster[parsed_propertie[0]];
if(last){
parsed_propertie.forEach( (e) => {
if(last){
ppath = (last.path + last.mainFileName )|| e;
result+= '/'+ppath;
last = last[e];
} else return false;
});
} else return false;
return result;
};
Cluster.Benchmark = class Benchmark{
constructor(options={}){
this.iterations = options.iterations;
this.ms_start = options.start;
this.ms_end = options.end;
this.ms_delta = options.end-options.start;
this.ms_average = this.ms_delta/this.iterations;
this.delta = Cluster.Utils.goodTime(this.ms_delta);
this.average = Cluster.Utils.goodTime(this.ms_average);
this.mode = options.mode;
}
};
Cluster.randomHash = function(len=32, security=true){
var saltAlpha = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"abcdefghijklmnopqrstuvwxyz"+ (security ? './-+_%*£\\ç^äâëêùàèé$§!()[]{}:,?\'"' : '');
var salt = 'rh$';
for(var i = 0; i < len; ++i) {
salt += saltAlpha.charAt(
Math.floor(Math.random() * saltAlpha.length));
}
return salt;
};
Cluster.benchmark = function (callback, options={}) {
var dc = // default config
{
iterations: 1,
mode: 'simple'
};
var it=1, bt=0, at=0, mode ;
if(typeof options == 'number'){
it = options;
mode = dc.mode;
}
else{
if(typeof options.iterations == 'number') it = options.iterations;
else it = dc.iterations;
if(typeof options.mode == 'string') mode = options.mode;
else mode = dc.mode;
}
if(mode == 'simple'){
bt = performance.now();
for(let i = 0; i < it ; i++){
callback();
}
at = performance.now();
}
return new Cluster.Benchmark({
iterations: it,
start: bt,
end: at,
mode: mode
});
};
Cluster.NeedError = class NeedError extends Error{
constructor(needed='some unknow', message=''){
super(message);
this.name = 'ClusterNeedError';
this.splittedStack = this.stack.split('\n');
this.fileOriginPath = this.splittedStack[this.splittedStack.length-1].replace(/at | /g,'');
this.fileOriginName = Cluster.Utils.downpath(this.fileOriginPath, 2).replace(/:[0-9]+:[0-9]+/,'');
this.stack = this.splittedStack[this.splittedStack.length-1];
this.needed = needed;
var whereis = needed+" should be in \'"+Cluster.whereShouldBe(needed)+"\'\n";
this.message = 'A cluster object in \''+this.fileOriginName+'\' need '+this.needed+' element...\n'+whereis+message;
}
};
Cluster.need = function(needed, message){
var parsed_propertie;
parsed_propertie = needed.split('.');
if(parsed_propertie.length == 1){
if(!Cluster[parsed_propertie[0]]) throw new Cluster.NeedError(needed, message);
}
else if(parsed_propertie.length == 2){
if(Cluster[parsed_propertie[0]]){
if(!Cluster[parsed_propertie[0]][parsed_propertie[1]]) throw new Cluster.NeedError(needed, message);
}
else{
throw new Cluster.NeedError(parsed_propertie[0], message);
}
}
};
Cluster.Ui = {
'classSuffix': 'ui',
'path': Cluster.path+"cluster-ui/",
'mainFileName': "component.js",
'define': function (object){
if(window.customElements){
window.customElements.define('cluster-'+object.tag, object);
}
else{
document.registerElement('cluster-'+object.tag, object);
}
},
/**
* hiddenProperty - Get an inaccessible property if the item had a none display or if is no-present to the document.
* @description
* NOTE: This property is accessible from the prototype of HTMLElement
* Cluster Benchmark for this function:
* average: "598.427µs"
delta: "2.992s"
iterations: 5000
mode: "simple"
NOTE: Very slow performance ~ 0.6ms per iteration
NOTE: Use this method moderately, for example the use of element.hiddenProperty('offsetWidth') is 1000 times slower than element.offsetWidth
*
* @param {string} prop The property name
* @param {HTMLElement} [element] If the method is not called from a prototype, specify an element in the second argument.
* @param {bool} profond Indicate if the cloneNode should be profond
* @return {type} The return value of the property specified
*/
'hiddenProperty': function(prop, element, profond=true){
let el = (this instanceof HTMLElement) ? this : element;
let nel = el.cloneNode(profond);
nel.style.visibility = "hidden";
nel.style.display = 'block';
document.documentElement.appendChild(nel);
let w = nel[prop];
nel.remove();
return w;
}
};
HTMLElement.prototype.hiddenProperty = Cluster.Ui.hiddenProperty;
Cluster.cssList = [];
/**
* css - Add css file to header dynamicly.
*
* @param {string} filename The file name
* @return {bool}
*/
Cluster.css = function(filename){
var fileref=document.createElement("style");
fileref.setAttribute("type", "text/css");
var path = "";
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function()
{
if(xhr.readyState == 4){
if(xhr.status == 200) {
fileref.textContent = xhr.responseText;
document.getElementsByTagName("head")[0].appendChild(fileref);
}
}
};
xhr.open("GET", path+filename, true);
xhr.send();
}
Cluster.Ui.className = Cluster.className+'-'+Cluster.Ui.classSuffix;
export default Cluster;