mirror of
https://github.com/coderaiser/cloudcmd.git
synced 2026-07-24 08:29:53 +00:00
chore(load) es2015-ify
This commit is contained in:
parent
750ab79d4c
commit
4acbab01b6
1 changed files with 331 additions and 344 deletions
675
client/load.js
675
client/load.js
|
|
@ -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,
|
||||
});
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue