From 4acbab01b6588ac832063bdfe7083231aac4971c Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 16 Feb 2017 13:26:22 +0200 Subject: [PATCH] chore(load) es2015-ify --- client/load.js | 675 ++++++++++++++++++++++++------------------------- 1 file changed, 331 insertions(+), 344 deletions(-) diff --git a/client/load.js b/client/load.js index 2f999573..28a9b4d6 100644 --- a/client/load.js +++ b/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, + }); +};