var Util, DOM; (function (Util, DOM) { 'use strict'; /* global rendy */ var DOMProto = Object.getPrototypeOf(DOM); DOMProto.load = new LoaderProto(Util, DOM.Images, DOM.Events); 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 * */ 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); }; /* убираем путь к файлу, оставляя только название файла */ if (!p.id && p.src) p.id = load.getIdBySrc(p.src); element = document.getElementById(p.id); 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 = Util.type(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; } 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 = Util.type.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, '-'); } return id; }; /** * load file countent via ajax * * @param pParams */ load.ajax = function(params) { var data, p = params, countProgress, isObject = Util.type.object(p.data), isArray = Util.type.array(p.data), isArrayBuf = Util.type(p.data) === 'arraybuffer', type = p.type || p.method || 'GET', xhr = new XMLHttpRequest(); xhr.open(type, p.url, true); if (p.responseType) xhr.responseType = p.responseType; if (!isArrayBuf && isObject || isArray) data = Util.json.stringify(p.data); else data = p.data; Events.add('progress', xhr.upload, function(event) { var percent, count; if (event.lengthComputable) { percent = (event.loaded / event.total) * 100; count = Math.round(percent); if (countProgress) Images.setProgress(count); countProgress = true; } }); Events.add('readystatechange', xhr, function(event) { var TYPE_JSON, type, data, isContain, notText, xhr = event.target, OK = 200; if (xhr.readyState === 4 /* Complete */) { 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.ext = function(src, func) { var element, ext = Util.getExt(src); switch (ext) { case '.js': element = load.js(src, func); break; case '.css': element = load.css(src, func); break; default: element = load({ src : src, func : 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 (params) { funcs = params.map(function(url) { return load.ext.bind(null, url); }) .concat(callback); Util.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 = function(params, callback) { var funcs = []; if (params) { funcs = params.map(function(url) { return load.ext.bind(null, url); }); Util.exec.parallel(funcs, callback); } return load; }; /** * Функция загружает js-файл * * @param pSrc * @param pFunc */ load.js = function(src, func) { var element = load({ name : 'script', src : src, func : func }); return element; }, load.css = function(src, callback) { var element = load({ name : 'link', src : src, parent : document.head, func : callback }); return element; }; /** * Функция создаёт елемент style и записывает туда стили * @param pParams_o - структура параметров, заполняеться таким * образом: {src: ' ',func: '', id: '', element: '', inner: ''} * все параметры опциональны */ load.style = function(params) { if (!params.name) params.name = 'style'; if (!params.parent) params.parent = document.head; return load(params); }; return load; } })(Util, DOM);