chore(load) es2015-ify

This commit is contained in:
coderaiser 2017-02-16 13:26:22 +02:00
parent 750ab79d4c
commit 4acbab01b6

View file

@ -1,381 +1,368 @@
'use strict';
/* global Util */
const rendy = require('rendy');
const itype = require('itype/legacy');
const jonny = require('jonny');
const Emitify = require('emitify');
const exec = require('execon');
const {Images} = require('./dom');
const Events = require('./events');
module.exports = new LoaderProto(Util, Images, Events);
const {getExt} = require('../common/util');
function LoaderProto(Util, Images, Events) {
/**
* Функция создаёт элемент и загружает файл с src.
*
* @param pParams_o = {
* name, - название тэга
* src', - путь к файлу
* func, - обьект, содержаий одну из функций
* или сразу две onload и onerror
* {onload: function() {}, onerror: function();}
* style,
* id,
* element,
* async, - true by default
* inner: 'id{color:red, },
* class,
* notAppend - false by default
module.exports = load;
module.exports.getIdBySrc = getIdBySrc;
module.exports.ext = ext;
/**
* Функция создаёт элемент и загружает файл с src.
*
* @param params = {
* name, - название тэга
* src', - путь к файлу
* func, - обьект, содержаий одну из функций
* или сразу две onload и onerror
* {onload: function() {}, onerror: function();}
* style,
* id,
* element,
* async, - true by default
* inner: 'id{color:red, },
* class,
* notAppend - false by default
*
*/
function load(params) {
const {
src,
id = getIdBySrc(src),
func,
name,
async,
inner,
style,
parent = document.body,
className,
attribute,
notAppend,
} = params;
/*
* if passed arguments function
* then it's onload by default
*
* if object - then onload and onerror
*/
function load(params) {
var element, type,
p = params,
func = p.func,
name = p.name,
parent = p.parent || document.body,
/*
* if passed arguments function
* then it's onload by default
*
* if object - then onload and onerror
*/
funcLoad = function() {
var callback = func && func.onload || func;
Events.remove('error', element, funcError);
Util.exec(callback);
},
funcError = function() {
var callback,
template = 'file {{ src }} could not be loaded',
msg = rendy(template, {
src: p.src
}),
error = new Error(msg);
if (func)
callback = func.onerror || func.onload || func;
parent.removeChild(element);
Images.show.error(msg);
Util.exec(callback, error);
};
const funcLoad = () => {
const callback = func && func.onload || func;
/* убираем путь к файлу, оставляя только название файла */
if (!p.id && p.src)
p.id = load.getIdBySrc(p.src);
element = document.getElementById(p.id);
Events.remove('error', element, funcError);
if (element) {
Util.exec(func);
} else {
element = document.createElement(name);
if (name === 'script' || name === 'link')
Events.addOnce('load', element, funcLoad)
.addError(element, funcError);
if (p.id)
element.id = p.id;
if (p.className)
element.className = p.className;
if (p.src) {
/* if work with css use href */
if (name === 'link') {
element.href = p.src;
element.rel = 'stylesheet';
} else
element.src = p.src;
}
if (p.attribute) {
type = itype(p.attribute);
switch(type) {
case 'string':
element.setAttribute(p.attribute, '');
break;
case 'object':
Object.keys(p.attribute).forEach(function(name) {
element.setAttribute(name, p.attribute[name]);
});
break;
}
}
if (p.style)
element.style.cssText = p.style;
if (p.async && name === 'script' || p.async === undefined)
element.async = true;
if (!p.notAppend)
parent.appendChild(element);
if (p.inner)
element.innerHTML = p.inner;
}
exec(callback);
};
const funcError = () => {
const msg = `file ${src} could not be loaded`;
const error = new Error(msg);
parent.removeChild(element);
Images.show.error(msg);
const callback = func && func.onerror || func.onload || func;
exec(callback, error);
};
let element = document.getElementById(id);
if (element) {
exec(func);
return element;
}
/**
* Function gets id by src
* @param pSrc
*
* Example: http://domain.com/1.js -> 1_js
*/
load.getIdBySrc = function(src) {
var num, sub, id,
isStr = itype.string(src);
if (isStr) {
if (~src.indexOf(':'))
src += '-join';
num = src.lastIndexOf('/') + 1,
sub = src.substr(src, num),
id = src.replace(sub, '');
/* убираем точки */
id = id.replace(/\./g, '-');
element = document.createElement(name);
if (/^(script|link)$/.test(name))
Events.addOnce('load', element, funcLoad)
.addError(element, funcError);
if (id)
element.id = id;
if (className)
element.className = className;
if (src) {
if (name !== 'link') {
element.src = src;
} else {
element.href = src;
element.rel = 'stylesheet';
}
return id;
};
}
/**
* load file countent via ajax
*
* @param pParams
*/
load.ajax = function(params) {
var data,
p = params,
isObject = itype.object(p.data),
isArray = itype.array(p.data),
isArrayBuf = itype(p.data) === 'arraybuffer',
type = p.type || p.method || 'GET',
headers = p.headers || {},
xhr = new XMLHttpRequest();
if (attribute) {
const type = itype(attribute);
xhr.open(type, p.url, true);
Object.keys(headers).forEach(function(name) {
var value = headers[name];
xhr.setRequestHeader(name, value);
});
if (p.responseType)
xhr.responseType = p.responseType;
if (!isArrayBuf && isObject || isArray)
data = Util.json.stringify(p.data);
else
data = p.data;
xhr.onreadystatechange = function(event) {
var TYPE_JSON, type, data, isContain, notText,
xhr = event.target,
OK = 200;
if (xhr.readyState === xhr.DONE) {
Images.clearProgress();
TYPE_JSON = 'application/json';
type = xhr.getResponseHeader('content-type');
if (xhr.status !== OK) {
Util.exec(p.error, xhr);
} else {
data = xhr.response;
notText = p.dataType !== 'text',
isContain = ~type.indexOf(TYPE_JSON);
if (type && isContain && notText)
data = Util.json.parse(xhr.response) || xhr.response;
Util.exec(p.success, data, xhr.statusText, xhr);
}
}
};
xhr.send(data);
};
load.put = function(url, body) {
var emitter = Emitify(),
xhr = new XMLHttpRequest();
url = encodeURI(url);
url = url.replace('#', '%23');
xhr.open('put', url, true);
xhr.upload.onprogress = function(event) {
var percent, count;
if (event.lengthComputable) {
percent = (event.loaded / event.total) * 100;
count = Math.round(percent);
emitter.emit('progress', count);
}
};
xhr.onreadystatechange = function() {
var error,
over = xhr.readyState === xhr.DONE,
OK = 200;
if (over)
if (xhr.status === OK) {
emitter.emit('end');
} else {
error = Error(xhr.responseText);
emitter.emit('error', error);
}
};
xhr.send(body);
return emitter;
};
load.ext = function(src, func) {
var element,
ext = Util.getExt(src);
switch (ext) {
case '.js':
element = load.js(src, func);
switch(type) {
case 'string':
element.setAttribute(attribute, '');
break;
case '.css':
element = load.css(src, func);
case 'object':
Object.keys(attribute).forEach((name) => {
element.setAttribute(name, attribute[name]);
});
break;
default:
element = load({
src,
func,
});
}
return element;
};
}
/**
* create elements and load them to DOM-tree
* one-by-one
*
* @param params
* @param callback
*/
load.series = function(params, callback) {
var funcs = [];
if (style)
element.style.cssText = style;
if (async && name === 'script' || async === undefined)
element.async = true;
if (!notAppend)
parent.appendChild(element);
if (inner)
element.innerHTML = inner;
return element;
}
/**
* Function gets id by src
* @param src
*
* Example: http://domain.com/1.js -> 1_js
*/
function getIdBySrc(src) {
const isStr = itype.string(src);
if (!isStr)
return;
if (~src.indexOf(':'))
src += '-join';
const num = src.lastIndexOf('/') + 1;
const sub = src.substr(src, num);
const id = src
.replace(sub, '')
.replace(/\./g, '-');
return id;
}
/**
* load file countent via ajax
*
* @param params
*/
module.exports.ajax = (params) => {
const p = params;
const isObject = itype.object(p.data);
const isArray = itype.array(p.data);
const isArrayBuf = itype(p.data) === 'arraybuffer';
const type = p.type || p.method || 'GET';
const headers = p.headers || {};
const xhr = new XMLHttpRequest();
xhr.open(type, p.url, true);
Object.keys(headers).forEach((name) => {
const value = headers[name];
xhr.setRequestHeader(name, value);
});
if (p.responseType)
xhr.responseType = p.responseType;
let data;
if (!isArrayBuf && isObject || isArray)
data = jonny.stringify(p.data);
else
data = p.data;
xhr.onreadystatechange = (event) => {
const xhr = event.target;
const OK = 200;
if (params) {
funcs = params.map(function(url) {
return load.ext.bind(null, url);
})
.concat(callback);
if (xhr.readyState !== xhr.DONE)
return;
Images.clearProgress();
const TYPE_JSON = 'application/json';
const type = xhr.getResponseHeader('content-type');
if (xhr.status !== OK)
return exec(p.error, xhr);
const notText = p.dataType !== 'text';
const isContain = ~type.indexOf(TYPE_JSON);
let data = xhr.response;
if (type && isContain && notText)
data = jonny.parse(xhr.response) || xhr.response;
Util.exec.series(funcs);
}
return load;
exec(p.success, data, xhr.statusText, xhr);
};
/**
* improve callback of funcs so
* we pop number of function and
* if it's last we call pCallBack
*
* @param params
* @param callback - onload function
*/
load.parallel = function(params, callback) {
var funcs = [];
xhr.send(data);
};
module.exports.put = (url, body) => {
const emitter = Emitify();
const xhr = new XMLHttpRequest();
url = encodeURI(url)
.replace('#', '%23');
xhr.open('put', url, true);
xhr.upload.onprogress = (event) => {
var percent, count;
if (params) {
funcs = params.map(function(url) {
return load.ext.bind(null, url);
});
if (event.lengthComputable) {
percent = (event.loaded / event.total) * 100;
count = Math.round(percent);
Util.exec.parallel(funcs, callback);
emitter.emit('progress', count);
}
};
xhr.onreadystatechange = () => {
const over = xhr.readyState === xhr.DONE;
const OK = 200;
if (!over)
return;
if (xhr.status === OK)
return emitter.emit('end');
const error = Error(xhr.responseText);
emitter.emit('error', error);
};
xhr.send(body);
return emitter;
};
function ext(src, func) {
switch (getExt(src)) {
case '.js':
return load.js(src, func);
case '.css':
return load.css(src, func);
default:
return load({
src,
func,
});
}
}
/**
* create elements and load them to DOM-tree
* one-by-one
*
* @param params
* @param callback
*/
load.series = (params, callback) => {
if (!params)
return load;
};
/**
* Функция загружает js-файл
*
* @param src
* @param func
*/
load.js = (src, func) => {
const name = 'script';
return load({
name,
src,
func,
});
},
const funcs = params
.map((url) => ext.bind(null, url))
.concat(callback);
load.css = (src, func) => {
const name = 'link';
const {head:parent} = document;
return load({
name,
src,
parent,
func
});
};
/**
* Функция создаёт елемент style и записывает туда стили
* @param params - структура параметров, заполняеться таким
* образом: {src: ' ',func: '', id: '', element: '', inner: ''}
* все параметры опциональны
*/
load.style = (params) => {
const {
id,
src,
name = 'style',
func,
inner,
parent = document.head,
element,
} = params;
return load({
id,
src,
func,
name,
inner,
parent,
element,
});
};
exec.series(funcs);
return load;
}
};
/**
* improve callback of funcs so
* we pop number of function and
* if it's last we call pCallBack
*
* @param params
* @param callback - onload function
*/
load.parallel = (params, callback) => {
if (!params)
return load;
const funcs = params.map((url) => {
return ext.bind(null, url);
});
exec.parallel(funcs, callback);
return load;
};
/**
* Функция загружает js-файл
*
* @param src
* @param func
*/
load.js = (src, func) => {
const name = 'script';
return load({
name,
src,
func,
});
},
load.css = (src, func) => {
const name = 'link';
const {head:parent} = document;
return load({
name,
src,
parent,
func
});
};
/**
* Функция создаёт елемент style и записывает туда стили
* @param params - структура параметров, заполняеться таким
* образом: {src: ' ',func: '', id: '', element: '', inner: ''}
* все параметры опциональны
*/
load.style = (params) => {
const {
id,
src,
name = 'style',
func,
inner,
parent = document.head,
element,
} = params;
return load({
id,
src,
func,
name,
inner,
parent,
element,
});
};