|
|
- /*
- Kube UI Framework
- Version 7.2.1
- Updated: November 10, 2018
-
- http://imperavi.com/kube/
-
- Copyright (c) 2009-2018, Imperavi LLC.
- License: MIT
- */
- (function() {
- var Ajax = {};
-
- Ajax.settings = {};
- Ajax.post = function(options) { return new AjaxRequest('post', options); };
- Ajax.get = function(options) { return new AjaxRequest('get', options); };
-
- var AjaxRequest = function(method, options)
- {
- var defaults = {
- method: method,
- url: '',
- before: function() {},
- success: function() {},
- error: function() {},
- data: false,
- async: true,
- headers: {}
- };
-
- this.p = this.extend(defaults, options);
- this.p = this.extend(this.p, Ajax.settings);
- this.p.method = this.p.method.toUpperCase();
-
- this.prepareData();
-
- this.xhr = new XMLHttpRequest();
- this.xhr.open(this.p.method, this.p.url, this.p.async);
-
- this.setHeaders();
-
- var before = (typeof this.p.before === 'function') ? this.p.before(this.xhr) : true;
- if (before !== false)
- {
- this.send();
- }
- };
-
- AjaxRequest.prototype = {
- extend: function(obj1, obj2)
- {
- if (obj2) for (var name in obj2) { obj1[name] = obj2[name]; }
- return obj1;
- },
- prepareData: function()
- {
- if (this.p.method === 'POST' && !this.isFormData()) this.p.headers['Content-Type'] = 'application/x-www-form-urlencoded';
- if (typeof this.p.data === 'object' && !this.isFormData()) this.p.data = this.toParams(this.p.data);
- if (this.p.method === 'GET') this.p.url = (this.p.data) ? this.p.url + '?' + this.p.data : this.p.url;
- },
- setHeaders: function()
- {
- this.xhr.setRequestHeader('X-Requested-With', this.p.headers['X-Requested-With'] || 'XMLHttpRequest');
- for (var name in this.p.headers)
- {
- this.xhr.setRequestHeader(name, this.p.headers[name]);
- }
- },
- isFormData: function()
- {
- return (typeof window.FormData !== 'undefined' && this.p.data instanceof window.FormData);
- },
- isComplete: function()
- {
- return !(this.xhr.status < 200 || this.xhr.status >= 300 && this.xhr.status !== 304);
- },
- send: function()
- {
- if (this.p.async)
- {
- this.xhr.onload = this.loaded.bind(this);
- this.xhr.send(this.p.data);
- }
- else
- {
- this.xhr.send(this.p.data);
- this.loaded.call(this);
- }
- },
- loaded: function()
- {
- if (this.isComplete())
- {
- var response = this.xhr.response;
- var json = this.parseJson(response);
- response = (json) ? json : response;
-
- if (typeof this.p.success === 'function') this.p.success(response, this.xhr);
- }
- else
- {
- if (typeof this.p.error === 'function') this.p.error(this.xhr.statusText);
- }
- },
- parseJson: function(str)
- {
- try {
- var o = JSON.parse(str);
- if (o && typeof o === 'object')
- {
- return o;
- }
-
- } catch (e) {}
-
- return false;
- },
- toParams: function (obj)
- {
- return Object.keys(obj).map(
- function(k){ return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]); }
- ).join('&');
- }
- };
- var DomCache = [0];
- var DomExpando = 'data' + +new Date();
- var DomHClass = 'is-hidden';
- var DomHMClass = 'is-hidden-mobile';
-
- var Dom = function(selector, context)
- {
- return this.parse(selector, context);
- };
-
- Dom.ready = function(fn)
- {
- if (document.readyState != 'loading') fn();
- else document.addEventListener('DOMContentLoaded', fn);
- };
-
- Dom.prototype = {
- get dom()
- {
- return true;
- },
- get length()
- {
- return this.nodes.length;
- },
- parse: function(selector, context)
- {
- var nodes;
- var reHtmlTest = /^\s*<(\w+|!)[^>]*>/;
-
- if (!selector)
- {
- nodes = [];
- }
- else if (selector.dom)
- {
- this.nodes = selector.nodes;
- return selector;
- }
- else if (typeof selector !== 'string')
- {
- if (selector.nodeType && selector.nodeType === 11)
- {
- nodes = selector.childNodes;
- }
- else
- {
- nodes = (selector.nodeType || selector === window) ? [selector] : selector;
- }
- }
- else if (reHtmlTest.test(selector))
- {
- nodes = this.create(selector);
- }
- else
- {
- nodes = this._query(selector, context);
- }
-
- this.nodes = this._slice(nodes);
- },
- create: function(html)
- {
- if (/^<(\w+)\s*\/?>(?:<\/\1>|)$/.test(html))
- {
- return [document.createElement(RegExp.$1)];
- }
-
- var elements = [];
- var container = document.createElement('div');
- var children = container.childNodes;
-
- container.innerHTML = html;
-
- for (var i = 0, l = children.length; i < l; i++)
- {
- elements.push(children[i]);
- }
-
- return elements;
- },
-
- // add
- add: function(nodes)
- {
- this.nodes = this.nodes.concat(this._toArray(nodes));
- },
-
- // get
- get: function(index)
- {
- return this.nodes[(index || 0)] || false;
- },
- getAll: function()
- {
- return this.nodes;
- },
- eq: function(index)
- {
- return new Dom(this.nodes[index]);
- },
- first: function()
- {
- return new Dom(this.nodes[0]);
- },
- last: function()
- {
- return new Dom(this.nodes[this.nodes.length - 1]);
- },
- contents: function()
- {
- return this.get().childNodes;
- },
-
- // loop
- each: function(callback)
- {
- var len = this.nodes.length;
- for (var i = 0; i < len; i++)
- {
- callback.call(this, (this.nodes[i].dom) ? this.nodes[i].get() : this.nodes[i], i);
- }
-
- return this;
- },
-
- // traversing
- is: function(selector)
- {
- return (this.filter(selector).length > 0);
- },
- filter: function (selector)
- {
- var callback;
- if (selector === undefined)
- {
- return this;
- }
- else if (typeof selector === 'function')
- {
- callback = selector;
- }
- else
- {
- callback = function(node)
- {
- if (selector instanceof Node)
- {
- return (selector === node);
- }
- else if (selector && selector.dom)
- {
- return ((selector.nodes).indexOf(node) !== -1);
- }
- else
- {
- node.matches = node.matches || node.msMatchesSelector || node.webkitMatchesSelector;
- return (node.nodeType === 1) ? node.matches(selector || '*') : false;
- }
- };
- }
-
- return new Dom(this.nodes.filter(callback));
- },
- not: function(filter)
- {
- return this.filter(function(node)
- {
- return !new Dom(node).is(filter || true);
- });
- },
- find: function(selector)
- {
- var nodes = [];
- this.each(function(node)
- {
- var ns = this._query(selector || '*', node);
- for (var i = 0; i < ns.length; i++)
- {
- nodes.push(ns[i]);
- }
- });
-
- return new Dom(nodes);
- },
- children: function(selector)
- {
- var nodes = [];
- this.each(function(node)
- {
- if (node.children)
- {
- var ns = node.children;
- for (var i = 0; i < ns.length; i++)
- {
- nodes.push(ns[i]);
- }
- }
- });
-
- return new Dom(nodes).filter(selector);
- },
- parent: function(selector)
- {
- var nodes = [];
- this.each(function(node)
- {
- if (node.parentNode) nodes.push(node.parentNode);
- });
-
- return new Dom(nodes).filter(selector);
- },
- parents: function(selector, context)
- {
- context = this._getContext(context);
-
- var nodes = [];
- this.each(function(node)
- {
- var parent = node.parentNode;
- while (parent && parent !== context)
- {
- if (selector)
- {
- if (new Dom(parent).is(selector)) { nodes.push(parent); }
- }
- else
- {
- nodes.push(parent);
- }
-
- parent = parent.parentNode;
- }
- });
-
- return new Dom(nodes);
- },
- closest: function(selector, context)
- {
- context = this._getContext(context);
- selector = (selector.dom) ? selector.get() : selector;
-
- var nodes = [];
- var isNode = (selector && selector.nodeType);
- this.each(function(node)
- {
- do {
- if ((isNode && node === selector) || new Dom(node).is(selector)) return nodes.push(node);
- } while ((node = node.parentNode) && node !== context);
- });
-
- return new Dom(nodes);
- },
- next: function(selector)
- {
- return this._getSibling(selector, 'nextSibling');
- },
- nextElement: function(selector)
- {
- return this._getSibling(selector, 'nextElementSibling');
- },
- prev: function(selector)
- {
- return this._getSibling(selector, 'previousSibling');
- },
- prevElement: function(selector)
- {
- return this._getSibling(selector, 'previousElementSibling');
- },
-
- // css
- css: function(name, value)
- {
- if (value === undefined && (typeof name !== 'object'))
- {
- var node = this.get();
- if (name === 'width' || name === 'height')
- {
- return (node.style) ? this._getHeightOrWidth(name, node, false) + 'px' : undefined;
- }
- else
- {
- return (node.style) ? getComputedStyle(node, null)[name] : undefined;
- }
- }
-
- // set
- return this.each(function(node)
- {
- var obj = {};
- if (typeof name === 'object') obj = name;
- else obj[name] = value;
-
- for (var key in obj)
- {
- if (node.style) node.style[key] = obj[key];
- }
- });
- },
-
- // attr
- attr: function(name, value, data)
- {
- data = (data) ? 'data-' : '';
-
- if (value === undefined && (typeof name !== 'object'))
- {
- var node = this.get();
- if (node && node.nodeType !== 3)
- {
- return (name === 'checked') ? node.checked : this._getBooleanFromStr(node.getAttribute(data + name));
- }
- else return;
- }
-
- // set
- return this.each(function(node)
- {
- var obj = {};
- if (typeof name === 'object') obj = name;
- else obj[name] = value;
-
- for (var key in obj)
- {
- if (node.nodeType !== 3)
- {
- if (key === 'checked') node.checked = obj[key];
- else node.setAttribute(data + key, obj[key]);
- }
- }
- });
- },
- data: function(name, value)
- {
- if (name === undefined)
- {
- var reDataAttr = /^data\-(.+)$/;
- var attrs = this.get().attributes;
-
- var data = {};
- var replacer = function (g) { return g[1].toUpperCase(); };
-
- for (var key in attrs)
- {
- if (attrs[key] && reDataAttr.test(attrs[key].nodeName))
- {
- var dataName = attrs[key].nodeName.match(reDataAttr)[1];
- var val = attrs[key].value;
- dataName = dataName.replace(/-([a-z])/g, replacer);
-
- if (this._isObjectString(val)) val = this._toObject(val);
- else val = (this._isNumber(val)) ? parseFloat(val) : this._getBooleanFromStr(val);
-
- data[dataName] = val;
- }
- }
-
- return data;
- }
-
- return this.attr(name, value, true);
- },
- val: function(value)
- {
- if (value === undefined)
- {
- var el = this.get();
- if (el.type && el.type === 'checkbox') return el.checked;
- else return el.value;
- }
-
- return this.each(function(node)
- {
- node.value = value;
- });
- },
- removeAttr: function(value)
- {
- return this.each(function(node)
- {
- var rmAttr = function(name) { if (node.nodeType !== 3) node.removeAttribute(name); };
- value.split(' ').forEach(rmAttr);
- });
- },
- removeData: function(value)
- {
- return this.each(function(node)
- {
- var rmData = function(name) { if (node.nodeType !== 3) node.removeAttribute('data-' + name); };
- value.split(' ').forEach(rmData);
- });
- },
-
- // dataset/dataget
- dataset: function(key, value)
- {
- return this.each(function(node)
- {
- DomCache[this.dataindex(node)][key] = value;
- });
- },
- dataget: function(key)
- {
- return DomCache[this.dataindex(this.get())][key];
- },
- dataindex: function(el)
- {
- var cacheIndex = el[DomExpando];
- var nextCacheIndex = DomCache.length;
-
- if (!cacheIndex)
- {
- cacheIndex = el[DomExpando] = nextCacheIndex;
- DomCache[cacheIndex] = {};
- }
-
- return cacheIndex;
- },
-
-
- // class
- addClass: function(value)
- {
- return this._eachClass(value, 'add');
- },
- removeClass: function(value)
- {
- return this._eachClass(value, 'remove');
- },
- toggleClass: function(value)
- {
- return this._eachClass(value, 'toggle');
- },
- hasClass: function(value)
- {
- return this.nodes.some(function(node)
- {
- return (node.classList) ? node.classList.contains(value) : false;
- });
- },
-
- // html & text
- empty: function()
- {
- return this.each(function(node)
- {
- node.innerHTML = '';
- });
- },
- html: function(html)
- {
- return (html === undefined) ? (this.get().innerHTML || '') : this.empty().append(html);
- },
- text: function(text)
- {
- return (text === undefined) ? (this.get().textContent || '') : this.each(function(node) { node.textContent = text; });
- },
-
- // manipulation
- after: function(html)
- {
- return this._inject(html, function(frag, node)
- {
- if (typeof frag === 'string')
- {
- node.insertAdjacentHTML('afterend', frag);
- }
- else
- {
- var elms = (frag instanceof Node) ? [frag] : this._toArray(frag).reverse();
- for (var i = 0; i < elms.length; i++)
- {
- node.parentNode.insertBefore(elms[i], node.nextSibling);
- }
- }
-
- return node;
-
- });
- },
- before: function(html)
- {
- return this._inject(html, function(frag, node)
- {
- if (typeof frag === 'string')
- {
- node.insertAdjacentHTML('beforebegin', frag);
- }
- else
- {
- var elms = (frag instanceof Node) ? [frag] : this._toArray(frag);
- for (var i = 0; i < elms.length; i++)
- {
- node.parentNode.insertBefore(elms[i], node);
- }
- }
-
- return node;
- });
- },
- append: function(html)
- {
- return this._inject(html, function(frag, node)
- {
- if (typeof frag === 'string' || typeof frag === 'number')
- {
- node.insertAdjacentHTML('beforeend', frag);
- }
- else
- {
- var elms = (frag instanceof Node) ? [frag] : this._toArray(frag);
- for (var i = 0; i < elms.length; i++)
- {
- node.appendChild(elms[i]);
- }
- }
-
- return node;
- });
- },
- prepend: function(html)
- {
- return this._inject(html, function(frag, node)
- {
- if (typeof frag === 'string' || typeof frag === 'number')
- {
- node.insertAdjacentHTML('afterbegin', frag);
- }
- else
- {
- var elms = (frag instanceof Node) ? [frag] : this._toArray(frag).reverse();
- for (var i = 0; i < elms.length; i++)
- {
- node.insertBefore(elms[i], node.firstChild);
- }
- }
-
- return node;
- });
- },
- wrap: function(html)
- {
- return this._inject(html, function(frag, node)
- {
- var wrapper = (typeof frag === 'string' || typeof frag === 'number') ? this.create(frag)[0] : (frag instanceof Node) ? frag : this._toArray(frag)[0];
-
- if (node.parentNode)
- {
- node.parentNode.insertBefore(wrapper, node);
- }
-
- wrapper.appendChild(node);
-
- return new Dom(wrapper);
-
- });
- },
- unwrap: function()
- {
- return this.each(function(node)
- {
- var $node = new Dom(node);
-
- return $node.replaceWith($node.contents());
- });
- },
- replaceWith: function(html)
- {
- return this._inject(html, function(frag, node)
- {
- var docFrag = document.createDocumentFragment();
- var elms = (typeof frag === 'string' || typeof frag === 'number') ? this.create(frag) : (frag instanceof Node) ? [frag] : this._toArray(frag);
-
- for (var i = 0; i < elms.length; i++)
- {
- docFrag.appendChild(elms[i]);
- }
-
- var result = docFrag.childNodes[0];
- node.parentNode.replaceChild(docFrag, node);
-
- return result;
-
- });
- },
- remove: function()
- {
- return this.each(function(node)
- {
- if (node.parentNode) node.parentNode.removeChild(node);
- });
- },
- clone: function(events)
- {
- var nodes = [];
- this.each(function(node)
- {
- var copy = this._clone(node);
- if (events) copy = this._cloneEvents(node, copy);
- nodes.push(copy);
- });
-
- return new Dom(nodes);
- },
-
- // show/hide
- show: function()
- {
- return this.each(function(node)
- {
- if (!node.style || !this._hasDisplayNone(node)) return;
-
- var target = node.getAttribute('domTargetShow');
- var isHidden = (node.classList) ? node.classList.contains(DomHClass) : false;
- var isHiddenMobile = (node.classList) ? node.classList.contains(DomHMClass) : false;
- var type;
-
- if (isHidden)
- {
- type = DomHClass;
- node.classList.remove(DomHClass);
- }
- else if (isHiddenMobile)
- {
- type = DomHMClass;
- node.classList.remove(DomHMClass);
- }
- else
- {
- node.style.display = (target) ? target : 'block';
- }
-
- if (type) node.setAttribute('domTargetHide', type);
- node.removeAttribute('domTargetShow');
-
- }.bind(this));
- },
- hide: function()
- {
- return this.each(function(node)
- {
- if (!node.style || this._hasDisplayNone(node)) return;
-
- var display = node.style.display;
- var target = node.getAttribute('domTargetHide');
-
- if (target === DomHClass)
- {
- node.classList.add(DomHClass);
- }
- else if (target === DomHMClass)
- {
- node.classList.add(DomHMClass);
- }
- else
- {
- if (display !== 'block') node.setAttribute('domTargetShow', display);
- node.style.display = 'none';
- }
-
- node.removeAttribute('domTargetHide');
-
- });
- },
-
- // dimensions
- scrollTop: function(value)
- {
- var node = this.get();
- var isWindow = (node === window);
- var isDocument = (node.nodeType === 9);
- var el = (isDocument) ? (document.scrollingElement || document.body.parentNode || document.body || document.documentElement) : node;
-
- if (value !== undefined)
- {
- if (isWindow) window.scrollTo(0, value);
- else el.scrollTop = value;
- return;
- }
-
- if (isDocument)
- {
- return (typeof window.pageYOffset != 'undefined') ? window.pageYOffset : ((document.documentElement.scrollTop) ? document.documentElement.scrollTop : ((document.body.scrollTop) ? document.body.scrollTop : 0));
- }
- else
- {
- return (isWindow) ? window.pageYOffset : el.scrollTop;
- }
- },
- offset: function()
- {
- return this._getDim('Offset');
- },
- position: function()
- {
- return this._getDim('Position');
- },
- width: function(value, adjust)
- {
- return this._getSize('width', 'Width', value, adjust);
- },
- height: function(value, adjust)
- {
- return this._getSize('height', 'Height', value, adjust);
- },
- outerWidth: function()
- {
- return this._getInnerOrOuter('width', 'outer');
- },
- outerHeight: function()
- {
- return this._getInnerOrOuter('height', 'outer');
- },
- innerWidth: function()
- {
- return this._getInnerOrOuter('width', 'inner');
- },
- innerHeight: function()
- {
- return this._getInnerOrOuter('height', 'inner');
- },
-
- // events
- click: function()
- {
- return this._triggerEvent('click');
- },
- focus: function()
- {
- return this._triggerEvent('focus');
- },
- trigger: function(names)
- {
- return this.each(function(node)
- {
- var events = names.split(' ');
- for (var i = 0; i < events.length; i++)
- {
- var ev;
- var opts = { bubbles: true, cancelable: true };
-
- try {
- ev = new window.CustomEvent(events[i], opts);
- } catch(e) {
- ev = document.createEvent('CustomEvent');
- ev.initCustomEvent(events[i], true, true);
- }
-
- node.dispatchEvent(ev);
- }
- });
- },
- on: function(names, handler, one)
- {
- return this.each(function(node)
- {
- var events = names.split(' ');
- for (var i = 0; i < events.length; i++)
- {
- var event = this._getEventName(events[i]);
- var namespace = this._getEventNamespace(events[i]);
-
- handler = (one) ? this._getOneHandler(handler, names) : handler;
- node.addEventListener(event, handler);
-
- node._e = node._e || {};
- node._e[namespace] = node._e[namespace] || {};
- node._e[namespace][event] = node._e[namespace][event] || [];
- node._e[namespace][event].push(handler);
- }
-
- });
- },
- one: function(events, handler)
- {
- return this.on(events, handler, true);
- },
- off: function(names, handler)
- {
- var testEvent = function(name, key, event) { return (name === event); };
- var testNamespace = function(name, key, event, namespace) { return (key === namespace); };
- var testEventNamespace = function(name, key, event, namespace) { return (name === event && key === namespace); };
- var testPositive = function() { return true; };
-
- if (names === undefined)
- {
- // ALL
- return this.each(function(node)
- {
- this._offEvent(node, false, false, handler, testPositive);
- });
- }
-
- return this.each(function(node)
- {
- var events = names.split(' ');
-
- for (var i = 0; i < events.length; i++)
- {
- var event = this._getEventName(events[i]);
- var namespace = this._getEventNamespace(events[i]);
-
- // 1) event without namespace
- if (namespace === '_events') this._offEvent(node, event, namespace, handler, testEvent);
- // 2) only namespace
- else if (!event && namespace !== '_events') this._offEvent(node, event, namespace, handler, testNamespace);
- // 3) event + namespace
- else this._offEvent(node, event, namespace, handler, testEventNamespace);
- }
- });
- },
-
- // form
- serialize: function(asObject)
- {
- var obj = {};
- var elms = this.get().elements;
- for (var i = 0; i < elms.length; i++)
- {
- var el = elms[i];
- if (/(checkbox|radio)/.test(el.type) && !el.checked) continue;
- if (!el.name || el.disabled || el.type === 'file') continue;
-
- if (el.type === 'select-multiple')
- {
- for (var z = 0; z < el.options.length; z++)
- {
- var opt = el.options[z];
- if (opt.selected) obj[el.name] = opt.value;
- }
- }
-
- obj[el.name] = (this._isNumber(el.value)) ? parseFloat(el.value) : this._getBooleanFromStr(el.value);
- }
-
- return (asObject) ? obj : this._toParams(obj);
- },
- ajax: function(success, error)
- {
- if (typeof AjaxRequest !== 'undefined')
- {
- var method = this.attr('method') || 'post';
- var options = {
- url: this.attr('action'),
- data: this.serialize(),
- success: success,
- error: error
- };
-
- return new AjaxRequest(method, options);
- }
- },
-
- // private
- _queryContext: function(selector, context)
- {
- context = this._getContext(context);
-
- return (context.nodeType !== 3 && typeof context.querySelectorAll === 'function') ? context.querySelectorAll(selector) : [];
- },
- _query: function(selector, context)
- {
- if (context)
- {
- return this._queryContext(selector, context);
- }
- else if (/^[.#]?[\w-]*$/.test(selector))
- {
- if (selector[0] === '#')
- {
- var element = document.getElementById(selector.slice(1));
- return element ? [element] : [];
- }
-
- if (selector[0] === '.')
- {
- return document.getElementsByClassName(selector.slice(1));
- }
-
- return document.getElementsByTagName(selector);
- }
-
- return document.querySelectorAll(selector);
- },
- _getContext: function(context)
- {
- context = (typeof context === 'string') ? document.querySelector(context) : context;
-
- return (context && context.dom) ? context.get() : (context || document);
- },
- _inject: function(html, fn)
- {
- var len = this.nodes.length;
- var nodes = [];
- while (len--)
- {
- var res = (typeof html === 'function') ? html.call(this, this.nodes[len]) : html;
- var el = (len === 0) ? res : this._clone(res);
- var node = fn.call(this, el, this.nodes[len]);
-
- if (node)
- {
- if (node.dom) nodes.push(node.get());
- else nodes.push(node);
- }
- }
-
- return new Dom(nodes);
- },
- _cloneEvents: function(node, copy)
- {
- var events = node._e;
- if (events)
- {
- copy._e = events;
- for (var name in events._events)
- {
- for (var i = 0; i < events._events[name].length; i++)
- {
- copy.addEventListener(name, events._events[name][i]);
- }
- }
- }
-
- return copy;
- },
- _clone: function(node)
- {
- if (typeof node === 'undefined') return;
- if (typeof node === 'string') return node;
- else if (node instanceof Node || node.nodeType) return node.cloneNode(true);
- else if ('length' in node)
- {
- return [].map.call(this._toArray(node), function(el) { return el.cloneNode(true); });
- }
- },
- _slice: function(obj)
- {
- return (!obj || obj.length === 0) ? [] : (obj.length) ? [].slice.call(obj.nodes || obj) : [obj];
- },
- _eachClass: function(value, type)
- {
- return this.each(function(node)
- {
- if (value)
- {
- var setClass = function(name) { if (node.classList) node.classList[type](name); };
- value.split(' ').forEach(setClass);
- }
- });
- },
- _triggerEvent: function(name)
- {
- var node = this.get();
- if (node && node.nodeType !== 3) node[name]();
- return this;
- },
- _getOneHandler: function(handler, events)
- {
- var self = this;
- return function()
- {
- handler.apply(this, arguments);
- self.off(events);
- };
- },
- _getEventNamespace: function(event)
- {
- var arr = event.split('.');
- var namespace = (arr[1]) ? arr[1] : '_events';
- return (arr[2]) ? namespace + arr[2] : namespace;
- },
- _getEventName: function(event)
- {
- return event.split('.')[0];
- },
- _offEvent: function(node, event, namespace, handler, condition)
- {
- for (var key in node._e)
- {
- for (var name in node._e[key])
- {
- if (condition(name, key, event, namespace))
- {
- var handlers = node._e[key][name];
- for (var i = 0; i < handlers.length; i++)
- {
- if (typeof handler !== 'undefined' && handlers[i].toString() !== handler.toString())
- {
- continue;
- }
-
- node.removeEventListener(name, handlers[i]);
- node._e[key][name].splice(i, 1);
-
- if (node._e[key][name].length === 0) delete node._e[key][name];
- if (Object.keys(node._e[key]).length === 0) delete node._e[key];
- }
- }
- }
- }
- },
- _getInnerOrOuter: function(method, type)
- {
- return this[method](undefined, type);
- },
- _getDocSize: function(node, type)
- {
- var body = node.body, html = node.documentElement;
- return Math.max(body['scroll' + type], body['offset' + type], html['client' + type], html['scroll' + type], html['offset' + type]);
- },
- _getSize: function(type, captype, value, adjust)
- {
- if (value === undefined)
- {
- var el = this.get();
- if (el.nodeType === 3) value = 0;
- else if (el.nodeType === 9) value = this._getDocSize(el, captype);
- else if (el === window) value = window['inner' + captype];
- else value = this._getHeightOrWidth(type, el, adjust || 'normal');
-
- return Math.round(value);
- }
-
- return this.each(function(node)
- {
- value = parseFloat(value);
- value = value + this._adjustResultHeightOrWidth(type, node, adjust || 'normal');
-
- new Dom(node).css(type, value + 'px');
-
- }.bind(this));
- },
- _getHeightOrWidth: function(type, el, adjust)
- {
- if (!el) return 0;
-
- var name = type.charAt(0).toUpperCase() + type.slice(1);
- var result = 0;
- var style = getComputedStyle(el, null);
- var $el = new Dom(el);
- var $targets = $el.parents().filter(function(node)
- {
- return (node.nodeType === 1 && getComputedStyle(node, null).display === 'none') ? node : false;
- });
-
- if (style.display === 'none') $targets.add(el);
- if ($targets.length !== 0)
- {
- var fixStyle = 'visibility: hidden !important; display: block !important;';
- var tmp = [];
-
- $targets.each(function(node)
- {
- var $node = new Dom(node);
- var thisStyle = $node.attr('style');
- if (thisStyle !== null) tmp.push(thisStyle);
- $node.attr('style', (thisStyle !== null) ? thisStyle + ';' + fixStyle : fixStyle);
- });
-
- result = $el.get()['offset' + name] - this._adjustResultHeightOrWidth(type, el, adjust);
-
- $targets.each(function(node, i)
- {
- var $node = new Dom(node);
- if (tmp[i] === undefined) $node.removeAttr('style');
- else $node.attr('style', tmp[i]);
- });
- }
- else
- {
- result = el['offset' + name] - this._adjustResultHeightOrWidth(type, el, adjust);
- }
-
- return result;
- },
- _adjustResultHeightOrWidth: function(type, el, adjust)
- {
- if (!el || adjust === false) return 0;
-
- var fix = 0;
- var style = getComputedStyle(el, null);
- var isBorderBox = (style.boxSizing === "border-box");
-
- if (type === 'height')
- {
- if (adjust === 'inner' || (adjust === 'normal' && isBorderBox))
- {
- fix += (parseFloat(style.borderTopWidth) || 0) + (parseFloat(style.borderBottomWidth) || 0);
- }
-
- if (adjust === 'outer') fix -= (parseFloat(style.marginTop) || 0) + (parseFloat(style.marginBottom) || 0);
- }
- else
- {
- if (adjust === 'inner' || (adjust === 'normal' && isBorderBox))
- {
- fix += (parseFloat(style.borderLeftWidth) || 0) + (parseFloat(style.borderRightWidth) || 0);
- }
-
- if (adjust === 'outer') fix -= (parseFloat(style.marginLeft) || 0) + (parseFloat(style.marginRight) || 0);
- }
-
- return fix;
- },
- _getDim: function(type)
- {
- var node = this.get();
- return (node.nodeType === 3) ? { top: 0, left: 0 } : this['_get' + type](node);
- },
- _getPosition: function(node)
- {
- return { top: node.offsetTop, left: node.offsetLeft };
- },
- _getOffset: function(node)
- {
- var rect = node.getBoundingClientRect();
- var doc = node.ownerDocument;
- var docElem = doc.documentElement;
- var win = doc.defaultView;
-
- return {
- top: rect.top + win.pageYOffset - docElem.clientTop,
- left: rect.left + win.pageXOffset - docElem.clientLeft
- };
- },
- _getSibling: function(selector, method)
- {
- selector = (selector && selector.dom) ? selector.get() : selector;
-
- var isNode = (selector && selector.nodeType);
- var sibling;
-
- this.each(function(node)
- {
- while (node = node[method])
- {
- if ((isNode && node === selector) || new Dom(node).is(selector))
- {
- sibling = node;
- return;
- }
- }
- });
-
- return new Dom(sibling);
- },
- _toArray: function(obj)
- {
- if (obj instanceof NodeList)
- {
- var arr = [];
- for (var i = 0; i < obj.length; i++)
- {
- arr[i] = obj[i];
- }
-
- return arr;
- }
- else if (obj === undefined) return [];
- else
- {
- return (obj.dom) ? obj.nodes : obj;
- }
- },
- _toParams: function(obj)
- {
- var params = '';
- for (var key in obj)
- {
- params += '&' + this._encodeUri(key) + '=' + this._encodeUri(obj[key]);
- }
-
- return params.replace(/^&/, '');
- },
- _toObject: function(str)
- {
- return (new Function("return " + str))();
- },
- _encodeUri: function(str)
- {
- return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+');
- },
- _isNumber: function(str)
- {
- return !isNaN(str) && !isNaN(parseFloat(str));
- },
- _isObjectString: function(str)
- {
- return (str.search(/^{/) !== -1);
- },
- _getBooleanFromStr: function(str)
- {
- if (str === 'true') return true;
- else if (str === 'false') return false;
-
- return str;
- },
- _hasDisplayNone: function(el)
- {
- return (el.style.display === 'none') || ((el.currentStyle) ? el.currentStyle.display : getComputedStyle(el, null).display) === 'none';
- }
- };
- // Wrapper
- var $K = {};
-
- // Globals
- $K.app = [];
- $K.version = '7.2.1';
- $K.options = {};
- $K.modules = {};
- $K.services = {};
- $K.plugins = {};
- $K.classes = {};
- $K.extends = {};
- $K.lang = {};
- $K.dom = function(selector, context) { return new Dom(selector, context); };
- $K.ajax = Ajax;
- $K.Dom = Dom;
- $K.env = {
- 'module': 'modules',
- 'service': 'services',
- 'plugin': 'plugins',
- 'class': 'classes',
- 'extend': 'extends'
- };
-
- // init class
- var KubeApp = function(options, args)
- {
- return ($K.app = new App(options));
- };
-
- // init
- $K.init = function(options)
- {
- return new KubeApp(options, [].slice.call(arguments, 1));
- };
-
- // api
- $K.api = function(name)
- {
- var app = $K.app;
- var args = [].slice.call(arguments, 1);
-
- if (app)
- {
- args.unshift(name);
- app.api.apply(app, args);
- }
- };
-
- // add
- $K.add = function(type, name, obj)
- {
- if (typeof $K.env[type] === 'undefined') return;
-
- // translations
- if (obj.translations)
- {
- $K.lang = $K.extend(true, {}, $K.lang, obj.translations);
- }
-
- // extend
- if (type === 'extend')
- {
- $K[$K.env[type]][name] = obj;
- }
- else
- {
- // prototype
- var F = function() {};
- F.prototype = obj;
-
- // extends
- if (obj.extends)
- {
- for (var i = 0; i < obj.extends.length; i++)
- {
- $K.inherit(F, $K.extends[obj.extends[i]]);
- }
- }
-
- $K[$K.env[type]][name] = F;
- }
- };
-
- // add lang
- $K.addLang = function(lang, obj)
- {
- if (typeof $K.lang[lang] === 'undefined')
- {
- $K.lang[lang] = {};
- }
-
- $K.lang[lang] = $K.extend($K.lang[lang], obj);
- };
-
- // create
- $K.create = function(name)
- {
- var arr = name.split('.');
- var args = [].slice.call(arguments, 1);
-
- var type = 'classes';
- if (typeof $K.env[arr[0]] !== 'undefined')
- {
- type = $K.env[arr[0]];
- name = arr.slice(1).join('.');
- }
-
- // construct
- var instance = new $K[type][name]();
-
- instance._type = arr[0];
- instance._name = name;
-
- // init
- if (instance.init)
- {
- var res = instance.init.apply(instance, args);
-
- return (res) ? res : instance;
- }
-
- return instance;
- };
-
- // inherit
- $K.inherit = function(current, parent)
- {
- var F = function () {};
- F.prototype = parent;
- var f = new F();
-
- for (var prop in current.prototype)
- {
- if (current.prototype.__lookupGetter__(prop)) f.__defineGetter__(prop, current.prototype.__lookupGetter__(prop));
- else f[prop] = current.prototype[prop];
- }
-
- current.prototype = f;
- current.prototype.super = parent;
-
- return current;
- };
-
- // error
- $K.error = function(exception)
- {
- throw exception;
- };
-
- // extend
- $K.extend = function()
- {
- var extended = {};
- var deep = false;
- var i = 0;
- var length = arguments.length;
-
- if (Object.prototype.toString.call( arguments[0] ) === '[object Boolean]')
- {
- deep = arguments[0];
- i++;
- }
-
- var merge = function(obj)
- {
- for (var prop in obj)
- {
- if (Object.prototype.hasOwnProperty.call(obj, prop))
- {
- if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') extended[prop] = $K.extend(true, extended[prop], obj[prop]);
- else extended[prop] = obj[prop];
- }
- }
- };
-
- for (; i < length; i++ )
- {
- var obj = arguments[i];
- merge(obj);
- }
-
- return extended;
- };
- var App = function(options)
- {
- this.modules = {};
- this.services = [];
- this.queueStart = { 'service': {}, 'module': {} };
- this.queueStop = { 'service': {}, 'module': {} };
- this.started = false;
- this.stopped = false;
-
- // environment
- this.namespace = 'kube';
- this.dataNamespace = 'data-kube';
- this.instancePrefix = 'kube-instance-';
- this.rootOpts = options;
- this.$win = $K.dom(window);
- this.$doc = $K.dom(document);
- this.$body = $K.dom('body');
-
- // core services
- this.coreServices = ['options', 'lang', 'utils'];
- this.bindableServices = ['opts', 'lang', 'utils', '$win', '$doc', '$body']
-
- this.utils = $K.create('service.utils', this);
- this.opts = $K.create('service.options', this, 'global', options);
- this.lang = $K.create('service.lang', this);
-
- this.appcallback = new App.Callback(this);
- this.appstarter = new App.Starter(this);
- this.appbuilder = new App.Builder(this);
- this.appbroadcast = new App.Broadcast(this);
- this.appapi = new App.Api(this);
-
- this.build();
- this.start();
- };
-
- App.prototype = {
-
- // build
- build: function()
- {
- this.appbuilder.build();
- },
-
- // start & stop
- start: function()
- {
- // start
- this.stopped = false;
- this.broadcast('start', this);
-
- // starter
- this.appstarter.start();
-
- // started
- this.broadcast('started', this);
- this.started = true;
- },
- stop: function()
- {
- this.started = false;
- this.stopped = true;
-
- // stop
- this.broadcast('stop', this);
-
- // stopper
- this.appstarter.stop();
-
- // stopped
- this.broadcast('stopped', this);
- },
-
- // starter & stopper
- starter: function(instance, priority)
- {
- var type = (instance._type !== 'service') ? 'module' : instance._type;
- this.queueStart[type][priority] = instance._name;
- },
- stopper: function(instance, priority)
- {
- var type = (instance._type !== 'service') ? 'module' : instance._type;
- this.queueStop[type][priority] = instance._name;
- },
-
- // started & stopped
- isStarted: function()
- {
- return this.started;
- },
- isStopped: function()
- {
- return this.stopped;
- },
-
- // broadcast
- broadcast: function(name, sender)
- {
- this.appbroadcast.trigger(name, sender, [].slice.call(arguments, 2));
- },
-
- // callback
- on: function(name, func)
- {
- this.appcallback.add(name, func);
- },
- off: function(name, func)
- {
- this.appcallback.remove(name, func);
- },
-
- // api
- api: function(name)
- {
- return this.appapi.trigger(name, [].slice.call(arguments, 1));
- }
- };
- App.Module = function(app, $el, name, id)
- {
- this.app = app;
- this.instancePrefix = app.instancePrefix;
-
- // local
- this.eventTypes = ['click', 'mouseover', 'mouseout', 'mousedown', 'mouseup', 'mousemove',
- 'keydown', 'keyup', 'focus', 'submit', 'change', 'contextmenu', 'input'];
-
- // build
- return this._build($el, name, id);
- };
-
- App.Module.prototype = {
- _build: function($el, name, id)
- {
- var instance = $el.dataget(this.instancePrefix + name);
- if (!instance && typeof $K.modules[name] !== 'undefined')
- {
- var context = new App.Context(this.app, $el, id);
- var $target = context.getTarget();
-
- instance = $K.create('module.' + name, this.app, context);
- instance._id = id;
-
- $el.dataset(this.instancePrefix + name, instance);
- $el.attr('data-loaded', true);
-
- // delegate events
- this._delegateModuleEvents(instance, $el, name);
-
- // delegate commands
- this._delegateModuleCommands(instance, $el);
-
- if ($target.is())
- {
- this._delegateModuleCommands(instance, $target);
- }
- }
-
- return instance;
- },
-
- _delegateModuleCommands: function(instance, $el)
- {
- $el.find('[data-command]').each(function(node)
- {
- this._delegateCommand(instance, node, node.getAttribute('data-command'));
-
- }.bind(this));
- },
- _delegateCommand: function(instance, node, command)
- {
- if (typeof instance._eventCommands === 'undefined') instance._eventCommands = [];
-
- var self = this;
- var $node = $K.dom(node);
-
- instance._eventCommands.push($node);
-
- $node.on('click.generatedcommand', function(e)
- {
- e.preventDefault();
-
- var args = $node.data();
- args.event = e;
-
- self.app.broadcast(command, instance, $node, args);
- });
- },
- _delegateModuleEvents: function(instance, $el, name)
- {
- $el.find('[data-type]').each(function(node)
- {
- var arr = node.getAttribute('data-type').split('.');
- var type = arr[0];
- var scope = name;
-
- if (arr.length === 2)
- {
- scope = arr[0];
- type = arr[1];
- }
-
- if (scope === name)
- {
- this._delegateEvent(instance, name, node, type);
- }
-
- }.bind(this));
- },
- _delegateEvent: function(instance, name, node, type)
- {
- if (typeof instance._eventNodes === 'undefined') instance._eventNodes = [];
-
- var $node = $K.dom(node);
- var callback = function(e, eventType, element, type, args)
- {
- return instance['on' + eventType].call(instance, e, element, type, args);
- };
-
- instance._eventNodes.push($node);
-
- for (var i = 0; i < this.eventTypes.length; i++)
- {
- var event = 'on' + this.eventTypes[i];
- if (typeof instance[event] === 'function')
- {
- $node.on(this.eventTypes[i] + '.generatedevent', function(e)
- {
- var args = $node.data();
- callback(e, e.type, this, type, args);
- });
- }
- }
- }
- };
- App.Context = function(app, $el, name)
- {
- this.app = app;
- this.opts = app.opts;
-
- // build
- this.$element = this._buildElement($el);
- this.params = this._buildParams();
- this.name = this._buildName(name);
- this.$target = this._buildTarget();
- };
-
- App.Context.prototype = {
-
- // public
- getElement: function()
- {
- return this.$element;
- },
- getTarget: function()
- {
- return this.$target;
- },
- getParams: function(defaults)
- {
- return (defaults) ? $K.extend({}, defaults, this.params) : this.params;
- },
- getName: function()
- {
- return this.name;
- },
-
- // private
- _buildName: function(name)
- {
- return (this.params.name) ? this.params.name : name;
- },
- _buildParams: function()
- {
- return $K.create('service.options', this.app, 'element', this.$element);
- },
- _buildElement: function($el)
- {
- return new App.Element(this.app, $el);
- },
- _buildTarget: function()
- {
- return new App.Target(this.app, this.params.target);
- }
- };
- App.Callback = function(app)
- {
- this.app = app;
- this.opts = app.opts;
-
- // local
- this.callbacks = {};
-
- // build
- this._build();
- };
-
- App.Callback.prototype = {
- stop: function()
- {
- this.callbacks = {};
- },
- add: function(name, handler)
- {
- if (typeof this.callbacks[name] === 'undefined') this.callbacks[name] = [];
-
- this.callbacks[name].push(handler);
- },
- remove: function(name, handler)
- {
- if (handler === undefined)
- {
- delete this.callbacks[name];
- }
- else
- {
- for (var i = 0; i < this.callbacks[name].length; i++)
- {
- this.callbacks[name].splice(i, 1);
- }
-
- if (this.callbacks[name].length === 0)
- {
- delete this.callbacks[name];
- }
- }
- },
- trigger: function(name, args)
- {
- if (typeof this.callbacks[name] === 'undefined') return;
-
- for (var i = 0; i < this.callbacks[name].length; i++)
- {
- this.callbacks[name][i].apply(this.app, args);
- }
- },
-
- // private
- _build: function()
- {
- if (this.opts.callbacks)
- {
- for (var name in this.opts.callbacks)
- {
- if (typeof this.opts.callbacks[name] === 'function')
- {
- if (typeof this.callbacks[name] === 'undefined') this.callbacks[name] = [];
- this.callbacks[name].push(this.opts.callbacks[name]);
- }
- else
- {
- for (var key in this.opts.callbacks[name])
- {
- if (typeof this.callbacks[name + '.' + key] === 'undefined') this.callbacks[name + '.' + key] = [];
- this.callbacks[name + '.' + key].push(this.opts.callbacks[name][key]);
- }
-
- }
- }
- }
- }
- };
- App.Element = function(app, $el)
- {
- this.app = app;
- this.parse($el);
- };
-
- App.Element.prototype = {
- isOpened: function()
- {
- return !this.isClosed();
- },
- isClosed: function()
- {
- return (this.hasClass('is-hidden') || this.css('display') === 'none');
- }
- };
-
- $K.inherit(App.Element, Dom.prototype);
- App.Target = function(app, selector)
- {
- this.app = app;
- this.parse(selector);
- };
-
- App.Target.prototype = {
- isOpened: function()
- {
- return !this.isClosed();
- },
- isClosed: function()
- {
- var self = this;
- var count = 0;
- var len = this.length;
- this.each(function(node)
- {
- var $node = $K.dom(node);
- if ($node.hasClass('is-hidden') || $node.css('display') === 'none')
- {
- count++;
- }
- });
-
- return (count === len);
- }
- };
-
- $K.inherit(App.Target, Dom.prototype);
- App.Api = function(app)
- {
- this.app = app;
- this.modules = app.modules;
- };
-
- App.Api.prototype = {
- trigger: function(name, args)
- {
- var arr = name.split('.');
- var isNamed = (arr.length === 3);
- var isApp = (arr.length === 1);
- var isCallback = (arr[0] === 'on' || arr[0] === 'off');
-
- var module = arr[0];
- var method = arr[1];
- var id = false;
-
- if (isApp)
- {
- module = false;
- method = arr[0];
- }
- else if (isNamed)
- {
- method = arr[2];
- id = arr[1];
- }
-
- // app
- if (isApp)
- {
- if (typeof this.app[method] === 'function')
- {
- return this._call(this.app, method, args);
- }
- }
- // callback
- else if (isCallback)
- {
- return (module === 'on') ? this.app.on(module, args[0]) : this.app.off(module, args[0] || undefined);
- }
- else
- {
- // service
- if (this._isInstanceExists(this.app, module))
- {
- return this._call(this.app[module], method, args);
- }
- // module / plugin / addon
- else if (this._isInstanceExists(this.modules, module))
- {
- this._doApi(module, method, id, args)
- }
- }
- },
-
- // private
- _isInstanceExists: function(obj, name)
- {
- return (typeof obj[name] !== 'undefined');
- },
- _doApi: function(module, method, id, args)
- {
- for (var key in this.modules[module])
- {
- if (id === false || id === key)
- {
- var instance = this.modules[module][key];
- this._call(instance, method, args);
- }
- }
- },
- _call: function(instance, method, args)
- {
- if (typeof instance[method] === 'function')
- {
- return instance[method].apply(instance, args);
- }
- }
- };
- App.Broadcast = function(app)
- {
- this.app = app;
- this.modules = app.modules;
- this.callback = app.appcallback;
- };
-
- App.Broadcast.prototype = {
- trigger: function(name, sender, args)
- {
- if (Array.isArray(name))
- {
- sender._id = name[0];
- name = name[1];
- }
- else if (sender && typeof sender.context !== 'undefined')
- {
- sender._id = sender.context.getName();
- }
-
- args.unshift(sender);
-
- for (var moduleName in this.modules)
- {
- for (var key in this.modules[moduleName])
- {
- var instance = this.modules[moduleName][key];
- this._call(instance, name, args, sender);
- }
- }
-
- this.callback.trigger(name, args);
- },
-
-
- // private
- _call: function(instance, name, args, sender)
- {
- // new
- if (typeof instance['onmessage'] !== 'undefined')
- {
- var arr = name.split('.');
- var func = instance['onmessage'][arr[0]];
-
- if (arr.length === 1 && typeof func === 'function')
- {
- func.apply(instance, args);
- }
- else if (arr.length === 2 && typeof func !== 'undefined' && typeof func[arr[1]] === 'function')
- {
- func[arr[1]].apply(instance, args);
- }
- }
-
- // 7.1.1 compatibility
- var arr = name.split('.');
- if (arr.length === 1)
- {
- if (typeof instance['on' + name] === 'function')
- {
- instance['on' + name].apply(instance, args);
- }
- }
- else
- {
- arr[0] = 'on' + arr[0];
-
- // without id
- var func = this.app.utils.checkProperty(instance, arr);
- if (typeof func === 'function')
- {
- func.apply(instance, args);
- }
-
- // with id
- if (sender && sender._id)
- {
- var idArr = [arr[0], sender._id, arr[1]];
- var func = this.app.utils.checkProperty(instance, idArr);
- if (typeof func === 'function')
- {
- func.apply(instance, args);
- }
- }
- }
- }
- };
- App.Builder = function(app)
- {
- this.app = app;
- this.opts = app.opts;
- this.$doc = app.$doc;
- this.dataNamespace = app.dataNamespace;
- };
-
- App.Builder.prototype = {
- build: function()
- {
- this._buildServices();
- this._buildModules();
- },
-
- // private
- _buildServices: function()
- {
- var services = [];
- var startableServices = [];
- for (var name in $K.services)
- {
- if (this.app.coreServices.indexOf(name) === -1)
- {
- this.app[name] = $K.create('service.' + name, this.app);
- this.app.bindableServices.push(name);
- services.push(name);
- startableServices.push(name);
- }
- }
-
- // make core services to use another services
- for (var i = 0; i < this.app.coreServices.length; i++)
- {
- var name = this.app.coreServices[i];
- if (name !== 'options') services.push(name);
- }
-
- // binding
- for (var i = 0; i < services.length; i++)
- {
- var service = services[i];
- for (var z = 0; z < this.app.bindableServices.length; z++)
- {
- var inj = this.app.bindableServices[z];
- if (service !== inj)
- {
- this.app[service][inj] = this.app[inj];
- }
- }
- }
-
- this.app.services = startableServices;
- },
- _buildModules: function()
- {
- this.$doc.find('[' + this.dataNamespace + ']').each(function(node, i)
- {
- var $el = $K.dom(node);
- var name = $el.attr(this.dataNamespace);
- var id = ($el.attr('id')) ? $el.attr('id') : name + '-' + i;
- id = ($el.attr('data-name')) ? $el.attr('data-name') : id;
- var instance = new App.Module(this.app, $el, name, id);
-
- this._storeElementModule(instance, name, id);
-
- }.bind(this));
- },
- _storeElementModule: function(instance, name, id)
- {
- if (instance)
- {
- if (typeof this.app.modules[name] === 'undefined')
- {
- this.app.modules[name] = {};
- }
-
- this.app.modules[name][id] = instance;
- }
- }
- };
- App.Starter = function(app)
- {
- this.app = app;
- this.queue = {
- 'start': app.queueStart,
- 'stop': app.queueStop
- };
- this.priority = {
- 'start': { 'service': [], 'module': [] },
- 'stop': { 'service': [], 'module': [] }
- };
- };
-
- App.Starter.prototype = {
- start: function()
- {
- this._stopStart('service', 'start');
- this._stopStart('module', 'start');
- },
- stop: function()
- {
- this._stopStart('service', 'stop');
- this._stopStart('module', 'stop');
- },
-
- // private
- _stopStart: function(type, method)
- {
- // priority
- var queue = this.queue[method][type];
- for (var key in queue)
- {
- var name = queue[key];
- var instance = (type === 'service') ? this.app[name] : this.app.modules[name];
-
- this._callInstances(type, method, instance);
- this.priority[method][type].push(name);
- }
-
- // common
- var modules = (type === 'service') ? this.app.services : this.app.modules;
- for (var key in modules)
- {
- var name = (type === 'service') ? modules[key] : key;
-
- if (this.priority[method][type].indexOf(name) === -1)
- {
- var instance = (type === 'service') ? this.app[name] : modules[name];
- this._callInstances(type, method, instance);
- }
- }
- },
- _stopModuleEvents: function(method, instance)
- {
- if (method === 'stop')
- {
- if (typeof instance._eventNodes !== 'undefined')
- {
- for (var i = 0; i < instance._eventNodes.length; i++)
- {
- instance._eventNodes[i].off('.generatedevent');
- }
- }
-
- if (typeof instance._eventCommands !== 'undefined')
- {
- for (var i = 0; i < instance._eventCommands.length; i++)
- {
- instance._eventCommands[i].off('.generatedcommand');
- }
- }
- }
- },
- _callInstances: function(type, method, instance)
- {
- if (type === 'service')
- {
- this._call(instance, method);
- }
- else
- {
- for (var key in instance)
- {
- this._call(instance[key], method);
- this._stopModuleEvents(method, instance[key]);
- }
- }
- },
- _call: function(instance, method, args)
- {
- if (typeof instance[method] === 'function')
- {
- return instance[method].apply(instance, args);
- }
- }
- };
- $K.add('extend', 'dom', $K.Dom.prototype);
- $K.add('service', 'animate', {
- init: function(app)
- {
- this.app = app;
-
- // local
- this.animationOpt = true;
- },
- run: function(element, animation, callback)
- {
- return new $K.AnimatePlay(this.app, element, animation, callback, this.animationOpt);
- },
- remove: function(element)
- {
- this.$el = $K.dom(element);
- var effect = this.$el.attr('kube-animate-effect');
-
- this.$el.hide();
- this.$el.removeClass(effect);
- this.$el.off('animationend webkitAnimationEnd');
- }
- });
-
- $K.AnimatePlay = function(app, element, animation, callback, animationOpt)
- {
- this.hidableEffects = ['fadeOut', 'flipOut', 'slideUp', 'zoomOut', 'slideOutUp', 'slideOutRight', 'slideOutLeft'];
- this.prefix = 'kube-';
- this.prefixes = ['', '-webkit-'];
-
- this.utils = app.utils;
- this.$el = $K.dom(element);
- this.$body = $K.dom('body');
- this.callback = callback;
- this.animation = (!animationOpt) ? this._buildAnimationOff(animation) : animation;
-
- this._setHeight();
-
- // animate
- if (this._isAnimate()) this._animate();
- else this._toggle();
- };
-
- $K.AnimatePlay.prototype = {
- _setHeight: function()
- {
- if (this.animation === 'slideUp' || this.animation === 'slideDown')
- {
- this.$el.height(this.$el.height());
- }
- },
- _buildAnimationOff: function(animation)
- {
- return (this._isHidable(animation)) ? 'hide' : 'show';
- },
- _isAnimate: function()
- {
- return (this.animation !== 'show' && this.animation !== 'hide');
- },
- _isHidable: function(effect)
- {
- return (this.hidableEffects.indexOf(effect) !== -1);
- },
- _clean: function()
- {
- this.$body.removeClass('is-no-scroll-x');
- this.$el.removeClass(this.prefix + this.animation);
- this.$el.removeAttr('kube-animate-effect');
- },
- _toggle: function()
- {
- if (this.animation === 'show') this.$el.show();
- else this.$el.hide();
-
- if (typeof this.callback === 'function') this.callback(this);
- },
- _animate: function()
- {
- this.$body.addClass('is-no-scroll-x');
- this.$el.show();
-
- this.$el.addClass(this.prefix + this.animation);
- this.$el.attr('kube-animate-effect', this.prefix + this.animation);
- this._complete();
- },
- _complete: function()
- {
-
- this.$el.one('animationend webkitAnimationEnd', function(e)
- {
- if (this.$el.hasClass(this.prefix + this.animation)) this._clean();
- if (this._isHidable(this.animation)) this.$el.hide();
-
- if (this.animation === 'slideUp' || this.animation === 'slideDown') this.$el.css('height', '');
- if (typeof this.callback === 'function') this.callback(this.$el);
-
- }.bind(this));
- }
- };
- $K.add('service', 'transition', {
- init: function(app)
- {
- this.transitionOpt = true;
- },
- run: function(element, params)
- {
- return new $K.TransitionPlay(params, element, this.transitionOpt);
-
- },
- remove: function(element)
- {
- this.$el = $K.dom(element);
-
- var classname = this.$el.attr('kube-transition-class');
- if (classname)
- {
- this.$el.removeClass(classname);
- this.$el.removeAttr('kube-transition-class');
- }
-
- var css = this.$el.attr('kube-transition-css');
- if (css)
- {
- var names = css.split(',');
- for (var i = 0; i < names.length; i++)
- {
- this.$el.css(names[i], '');
- }
-
- this.$el.removeAttr('kube-transition-css');
- }
-
- this.$el.off('transitionend webkitTransitionEnd');
- }
- });
-
-
- $K.TransitionPlay = function(params, element, transitionOpt)
- {
- this.$el = $K.dom(element);
- this.params = params;
-
- this._transition();
- };
-
- $K.TransitionPlay.prototype = {
- _transition: function()
- {
- if (this.params.classname)
- {
- this.$el.addClass(this.params.classname);
- this.$el.attr('kube-transition-class', this.params.classname);
- }
-
- if (this.params.css)
- {
- this.$el.css(this.params.css);
-
- var names = [];
- for (var key in this.params.css)
- {
- names.push(key);
- }
-
- this.$el.attr('kube-transition-css', names.join(','))
- }
-
- this._complete();
- },
- _complete: function()
- {
- this.$el.one('transitionend webkitTransitionEnd', function(e)
- {
- if (typeof this.params.callback === 'function') this.params.callback(this.$el);
-
- }.bind(this));
- }
- };
- $K.add('service', 'lang', {
- init: function(app)
- {
- this.app = app;
- this.opts = app.opts;
-
- var lang = (this.opts.lang) ? this.opts.lang : 'en';
-
- // build
- this.vars = this.build(lang);
- },
- build: function(lang)
- {
- lang = ($K.lang[lang] === undefined) ? 'en' : lang;
-
- return ($K.lang[lang] !== undefined) ? $K.lang[lang] : [];
- },
- rebuild: function(lang)
- {
- this.opts.lang = lang;
- this.vars = this.build(lang);
- },
- extend: function(obj)
- {
- this.vars = $K.extend(this.vars, obj);
- },
- parse: function(str)
- {
- if (str === undefined)
- {
- return '';
- }
-
- var matches = str.match(/## (.*?) ##/g);
- if (matches)
- {
- for (var i = 0; i < matches.length; i++)
- {
- var key = matches[i].replace(/^##\s/g, '').replace(/\s##$/g, '');
- str = str.replace(matches[i], this.get(key));
- }
- }
-
- return str;
- },
- get: function(name)
- {
- return (typeof this.vars[name] !== 'undefined') ? this.vars[name] : '';
- }
- });
- $K.add('service', 'options', {
- init: function(app, type, opts)
- {
- this.app = app;
- this.utils = app.utils;
-
- return (type === 'global') ? this._build(opts) : this._buildElement(opts);
- },
- _build: function(opts)
- {
- return (opts) ? this._extendFromElements(opts) : {};
- },
- _buildElement: function($el)
- {
- return $K.extend(
- {},
- $el.data()
- );
- },
- _extendFromElements: function(options)
- {
- return (options.hasOwnProperty('append')) ? this.utils.extendData(options, options['append']) : options;
- }
- });
- $K.add('service', 'response', {
- init: function(app)
- {
- this.app = app;
- },
- // public
- parse: function(str)
- {
- if (str === '') return false;
-
- var obj = (typeof str === 'object') ? str : JSON.parse(str);
- if (obj[0] !== undefined)
- {
- for (var item in obj)
- {
- this._parseItem(obj[item]);
- }
- }
- else
- {
- this._parseItem(obj);
- }
-
- return obj;
- },
- // private
- _parseItem: function(item)
- {
- if (item.type === 'location')
- {
- top.location.href = item.data;
- }
- else if (item.type === 'message')
- {
- this.message.show(item.data);
- }
- else
- {
- for (var key in item.data)
- {
- var val = item.data[key];
- var $el = $K.dom(key);
-
- if (item.type === 'value')
- {
- val = (val === null || val === false) ? 0 : val;
- val = (val === true) ? 1 : val;
-
- $el.val(val);
- }
- else if (item.type === 'html')
- {
- val = (val === null || val === false) ? '' : val;
-
- $el.html(this._stripslashes(val));
- }
- else if (item.type === 'addClass')
- {
- $el.addClass(val);
- }
- else if (item.type === 'removeClass')
- {
- $el.removeClass(val);
- }
- else if (item.type === 'show')
- {
- $el.removeClass('is-hidden');
- }
- else if (item.type === 'hide')
- {
- $el.addClass('is-hidden');
- }
- else if (item.type === 'animate')
- {
- this.animate.run($el, val);
- }
- }
- }
-
- return item;
- },
- _stripslashes: function(str)
- {
- return (str+'').replace(/\0/g, '0').replace(/\\([\\'"])/g, '$1');
- }
- });
- $K.add('service', 'progress', {
- init: function(app)
- {
- this.app = app;
- this.$body = app.$body;
-
- // defaults
- this.defaults = {
- selector: 'kube-progress',
- target: false,
- value: 100
- }
-
- // local
- this.$progress = false;
- this.$progressBar = false;
- },
- // public
- stop: function()
- {
- this.$progress = false;
- this.$progressBar = false;
-
- $K.dom('#' + this.params.selector).remove();
-
- if (this.params.target)
- {
- var $target = $K.dom(this.params.target);
- $target.removeClass('is-relative');
- }
- },
- show: function(params)
- {
- this._buildDefaults(params);
- this._build();
- },
- hide: function(params)
- {
- if (this.$progress)
- {
- this._buildDefaults(params);
- this.animate.run(this.$progress, 'fadeOut', this.stop.bind(this));
- }
- },
- update: function(params)
- {
- this._buildDefaults(params);
-
- if (!this.$progress) this._build();
- this._setValue();
- },
-
- // private
- _buildDefaults: function(data)
- {
- this.params = $K.extend({}, this.defaults, data);
- },
- _build: function()
- {
- this.stop();
-
- this.$progress = $K.dom('<div>');
- this.$progress.attr('id', this.params.selector);
- this.$progress.addClass(this.params.selector);
-
- this.$progressBar = $K.dom('<span>');
- this.$progress.append(this.$progressBar);
-
- if (this.params.target)
- {
- var $target = $K.dom(this.params.target);
- if ($target.css('position') === 'static')
- {
- $target.addClass('is-relative');
- }
-
- $target.append(this.$progress);
- }
- else
- {
- this.$progress.addClass('is-fixed');
- this.$body.append(this.$progress);
- }
- },
- _setValue: function()
- {
- this.$progressBar.css('width', this.params.value + '%');
- }
- });
- $K.add('service', 'message', {
- init: function(app)
- {
- this.app = app;
-
- // defaults
- this.defaults = {
- name: false,
- delay: 7, // seconds
- message: '',
- position: 'right', // left, centered, line
- positions: ['is-left', 'is-right', 'is-center', 'is-centered', 'is-line'],
- type: false,
- types: ['is-error', 'is-success', 'is-focus', 'is-black'],
- selector: 'kube-message'
- };
-
- // animation
- this.currentAnimation = [];
- this.animation = {
- line: ['slideInDown', 'slideOutUp'],
- centered: ['slideInDown', 'slideOutUp'],
- left: ['slideInLeft', 'slideOutLeft'],
- right: ['slideInRight', 'slideOutRight']
- };
-
- // local
- this.$message = false;
- this.timeout = false;
- },
- // public
- stop: function()
- {
- clearTimeout(this.timeout);
-
- $K.dom('#' + this.params.selector).remove();
-
- this.$message = false;
- this.$doc.off('.kube.message');
- },
- show: function(params)
- {
- this._buildDefaults(params);
-
- // stop
- this.stop();
-
- // build
- this._build();
- this._open();
- },
- hide: function(params)
- {
- this._buildDefaults(params);
- this._close();
- },
- // private
- _broadcast: function(message)
- {
- message = 'message.' + message;
- message = (this.params.name !== false ) ? [this.params.name, message] : message;
-
- this.app.broadcast(message, this);
- },
- _buildDefaults: function(data)
- {
- this.params = $K.extend({}, this.defaults, data);
- },
- _buildAnimation: function()
- {
- this.currentAnimation = this.animation[this.params.position];
- },
- _buildClose: function()
- {
- this.$message.on('click.kube.message', this._close.bind(this));
- },
- _buildType: function()
- {
- if (this.params.type)
- {
- this.$message.removeClass(this.params.types.join(' '));
- this.$message.addClass(this.params.type);
- }
- },
- _buildPosition: function()
- {
- this.$message.removeClass(this.params.positions.join(' '));
- this.$message.addClass('is-' + this.params.position);
- },
- _buildMessage: function()
- {
- this.$message.html(this.params.message);
- },
- _build: function()
- {
- this.$message = $K.dom('<div>');
- this.$message.attr('id', this.params.selector);
- this.$message.addClass('message is-hidden');
-
- this.$body.append(this.$message);
- },
- _handleKeyboard: function(e)
- {
- if (e.which === 27) this._close();
- },
- _open: function()
- {
- this._broadcast('open');
-
- this._buildClose();
- this._buildType();
- this._buildPosition();
- this._buildAnimation();
- this._buildMessage();
-
- this.animate.run(this.$message, this.currentAnimation[0], this._opened.bind(this));
- },
- _close: function(e)
- {
- if (this.$message)
- {
- this._broadcast('close');
- this.animate.run(this.$message, this.currentAnimation[1], this._closed.bind(this));
- }
- },
- _opened: function()
- {
- this.$doc.on('keyup.kube.message', this._handleKeyboard.bind(this));
- this.timeout = setTimeout(this._close.bind(this), this.params.delay * 1000);
-
- this._broadcast('opened');
- },
- _closed: function()
- {
- this.stop();
- this._broadcast('closed');
- }
- });
- $K.add('service', 'modal', {
- init: function(app)
- {
- this.app = app;
-
- // defaults
- this.defaults = {
- target: false,
- name: false,
- url: false,
- title: false,
- width: '600px',
- height: false,
- handle: false,
- commands: false
- };
-
- // local
- this.$box = false;
- this.$modal = false;
-
- },
- // public
- stop: function()
- {
- if (this.$box)
- {
- this.$box.remove();
- this.$box = false;
- this.$modal = false;
-
- this.$doc.off('.kube.modal');
- this.$win.off('.kube.modal');
- }
-
- if (this.$overlay)
- {
- this.$overlay.remove();
- }
- },
- open: function(params)
- {
- this._buildDefaults(params);
-
- if (this.params.url)
- {
- this._openUrl();
- }
- else if (this.params.target)
- {
- this._openTarget();
- }
- },
- close: function()
- {
- this._close();
- },
- resize: function()
- {
- this.$modal.setWidth(this.params.width);
- this.$modal.updatePosition();
- },
-
- // private
- _broadcast: function(message)
- {
- message = 'modal.' + message;
-
- this.app.broadcast([this.params.name, message], this, this.$modal, this.$modalForm);
- },
- _isOpened: function()
- {
- return (this.$modal && this.$modal.hasClass('is-open'));
- },
- _openUrl: function()
- {
- $K.ajax.post({
- url: this.params.url,
- success: this._doOpen.bind(this)
- });
- },
- _openTarget: function()
- {
- var template = $K.dom(this.params.target).clone().html();
- this._doOpen(template);
- },
- _doOpen: function(template)
- {
- this.stop();
-
- if (!this._isDesktop())
- {
- document.activeElement.blur();
- }
-
-
- this._createModal(template);
-
- this._buildModalBox();
- this._buildOverlay();
- this._buildModal();
- this._buildModalForm();
- this._buildModalCommands();
-
- this.$modal.updatePosition();
- this._broadcast('open');
-
- this.animate.run(this.$box, 'fadeIn', this._opened.bind(this));
- this.animate.run(this.$overlay, 'fadeIn');
- },
- _opened: function()
- {
- this.$modal.addClass('is-open');
- this.$box.on('mousedown.kube.modal', this._close.bind(this));
- this.$doc.on('keyup.kube.modal', this._handleEscape.bind(this));
- this.$win.on('resize.kube.modal', this.resize.bind(this));
- this.$modal.getBody().find('input[type=text],input[type=url],input[type=email]').on('keydown.kube.modal', this._handleEnter.bind(this));
-
- this._broadcast('opened');
- },
- _close: function(e)
- {
- if (!this.$box || !this._isOpened()) return;
-
- if (e)
- {
- if (!this._needToClose(e.target))
- {
- return;
- }
-
- e.stopPropagation();
- e.preventDefault();
- }
-
- this._broadcast('close');
-
- this.animate.run(this.$box, 'fadeOut', this._closed.bind(this));
- this.animate.run(this.$overlay, 'fadeOut');
- },
- _closed: function()
- {
- this.$modal.removeClass('is-open');
- this.$box.off('.kube.modal');
- this.$doc.off('.kube.modal');
- this.$win.off('.kube.modal');
-
- this._broadcast('closed');
- },
- _createModal: function(template)
- {
- this.$modal = $K.create('class.modal.element', this.app, template);
- },
- _buildDefaults: function(data)
- {
- this.params = $K.extend({}, this.defaults, data);
- },
- _buildModalBox: function()
- {
- this.$box = $K.dom('<div>');
- this.$box.attr('id', 'kube-modal');
- this.$box.addClass('modal-box is-hidden');
- this.$box.html('');
- this.$body.append(this.$box);
- },
- _buildOverlay: function()
- {
- this.$overlay = $K.dom('#kube-overlay');
- if (this.$overlay.length === 0)
- {
- this.$overlay = $K.dom('<div>');
- this.$overlay.attr('id', 'kube-overlay');
- this.$overlay.addClass('overlay is-hidden');
- this.$body.prepend(this.$overlay);
- }
- },
- _buildModal: function()
- {
- this.$box.append(this.$modal);
-
- this.$modal.setTitle(this.params.title);
- this.$modal.setHeight(this.params.height);
- this.$modal.setWidth(this.params.width);
- },
- _buildModalCommands: function()
- {
- if (this.params.commands)
- {
- var commands = this.params.commands;
- var $footer = this.$modal.getFooter();
- for (var key in commands)
- {
- var $btn = $K.dom('<button>');
-
- $btn.addClass('button');
- $btn.html(commands[key].title);
- $btn.attr('data-command', key);
-
- if (typeof commands[key].classname !== 'undefined')
- {
- $btn.addClass(commands[key].classname);
- }
-
- if (typeof commands[key].close !== 'undefined')
- {
- $btn.attr('data-action', 'close');
- $btn.on('click', this._close.bind(this));
- }
- else
- {
- $btn.on('click', this._handleCommand.bind(this));
- }
-
- $footer.append($btn);
- }
- }
- },
- _buildModalForm: function()
- {
- this.$modalForm = $K.create('modal.form', this.app, this.$modal.getForm());
- },
- _needToClose: function(el)
- {
- var $target = $K.dom(el);
- if ($target.attr('data-action') === 'close' || this.$modal.isCloseNode(el) || $target.closest('.modal').length === 0)
- {
- return true;
- }
-
- return false;
- },
- _handleCommand: function(e)
- {
- var $btn = $K.dom(e.target).closest('button');
- var command = $btn.attr('data-command');
-
- if (command !== 'cancel') e.preventDefault();
-
- this._broadcast(command);
- },
- _handleEnter: function(e)
- {
- if (e.which === 13)
- {
- if (this.params.handle)
- {
- e.preventDefault();
- this._broadcast(this.params.handle);
- }
- }
- },
- _handleEscape: function(e)
- {
- if (e.which === 27) this._close();
- },
- _isDesktop: function()
- {
- return !/(iPhone|iPod|iPad|Android)/.test(navigator.userAgent);
- }
- });
-
- $K.add('class', 'modal.form', {
- extends: ['dom'],
- init: function(app, element)
- {
- this.app = app;
-
- // build
- this.build(element);
- },
-
- // public
- build: function(element)
- {
- this.parse(element);
- },
- getData: function()
- {
- var data = {};
- this.find('[name]').each(function(node)
- {
- var $node = $K.dom(node);
- data[$node.attr('name')] = $node.val();
- });
-
- return data;
- },
- setData: function(data)
- {
- this.find('[name]').each(function(node)
- {
- var $node = $K.dom(node);
- var name = $node.attr('name');
- if (data.hasOwnProperty(name))
- {
- if (node.type && node.type === 'checkbox') node.checked = data[name];
- else $node.val(data[name]);
- }
- });
- },
- getItem: function(name)
- {
- return this.find('[name=' + name + ']');
- }
- });
- $K.add('class', 'modal.element', {
- extends: ['dom'],
- init: function(app, template)
- {
- this.app = app;
- this.opts = app.opts;
- this.$win = app.$win;
-
- // init
- this._init(template);
- },
-
- // get
- getForm: function()
- {
- return this.find('form');
- },
- getHeader: function()
- {
- return this.$modalHeader;
- },
- getBody: function()
- {
- return this.$modalBody;
- },
- getFooter: function()
- {
- return this.$modalFooter;
- },
-
- // set
- setTitle: function(title)
- {
- if (title) this.$modalHeader.html(title);
- },
- setWidth: function(width)
- {
- width = (parseInt(width) >= this.$win.width()) ? '96%' : width;
-
- this.css('max-width', width);
- },
- setHeight: function(height)
- {
- if (height !== false) this.$modalBody.css('height', height);
- },
-
- // update
- updatePosition: function()
- {
- var width = this.width();
- this.css({ 'left': '50%', 'margin-left': '-' + (width/2) + 'px' });
-
- var windowHeight = this.$win.height();
- var height = this.height();
- var marginTop = (windowHeight/2 - height/2);
-
- if (height < windowHeight && marginTop !== 0)
- {
- this.css('margin-top', marginTop + 'px');
- }
- },
-
- // is
- isCloseNode: function(el)
- {
- return (el === this.$modalClose.get());
- },
-
- // private
- _init: function(template)
- {
- this._build();
- this._buildClose();
- this._buildHeader();
- this._buildBody();
- this._buildFooter();
- this._buildTemplate(template);
- },
- _build: function()
- {
- this.parse('<div>');
- this.addClass('modal');
- this.attr('dir', this.opts.direction);
- },
- _buildClose: function()
- {
- this.$modalClose = $K.dom('<span>');
- this.$modalClose.addClass('close');
-
- this.append(this.$modalClose);
- },
- _buildHeader: function()
- {
- this.$modalHeader = $K.dom('<div>');
- this.$modalHeader.addClass('modal-header');
-
- this.append(this.$modalHeader);
- },
- _buildBody: function()
- {
- this.$modalBody = $K.dom('<div>');
- this.$modalBody.addClass('modal-body');
-
- this.append(this.$modalBody);
- },
- _buildFooter: function()
- {
- this.$modalFooter = $K.dom('<div>');
- this.$modalFooter.addClass('modal-footer');
-
- this.append(this.$modalFooter);
- },
- _buildTemplate: function(template)
- {
- this.$modalBody.html(template);
- }
- });
- $K.add('service', 'observer', {
- init: function(app)
- {
- this.app = app;
- this.opts = app.opts;
-
- if (this._isObserve())
- {
- this._build();
- }
- },
-
- // private
- _isObserve: function()
- {
- return (typeof this.opts.observer !== 'undefined' && window.MutationObserver);
- },
- _build: function()
- {
- var self = this;
- var observer = new MutationObserver(function(mutations)
- {
- mutations.forEach(function(mutation)
- {
- var newNodes = mutation.addedNodes;
- if (newNodes.length === 0 || (newNodes.length === 1 && newNodes.nodeType === 3))
- {
- return;
- }
-
- self._iterate();
- });
- });
-
- // pass in the target node, as well as the observer options
- observer.observe(document, {
- subtree: true,
- childList: true
- });
- },
- _iterate: function()
- {
- var self = this;
- var $nodes = $K.dom('[data-kube]').not('[data-loaded]');
- $nodes.each(function(node, i)
- {
- var $el = $K.dom(node);
- var name = $el.attr('data-kube');
- var id = ($el.attr('id')) ? $el.attr('id') : name + '-' + (self.app.servicesIndex + i);
- var instance = new App.Module(self.app, $el, name, id);
-
- self._storeElementModule(instance, name, id)
- self._call(instance, 'start');
- });
-
- // $R
- if (typeof $R !== 'undefined')
- {
- $R('[data-redactor]');
- }
- },
- _call: function(instance, method, args)
- {
- if (typeof instance[method] === 'function')
- {
- return instance[method].apply(instance, args);
- }
- },
- _storeElementModule: function(instance, name, id)
- {
- if (instance)
- {
- if (typeof this.app.modules[name] === 'undefined')
- {
- this.app.modules[name] = {};
- }
-
- this.app.modules[name][id] = instance;
- }
- }
- });
- $K.add('service', 'utils', {
- init: function(app)
- {
- this.app = app;
- },
-
- // string
- parseOptsString: function(str)
- {
- var properties = str.replace('{', '').replace('}', '').trim().replace(/;$/, '').split(';');
- var obj = {};
- properties.forEach(function(property) {
- var tup = property.split(':');
- obj[tup[0].trim()] = tup[1].trim().replace(/'/g, '');
- });
-
- return obj;
- },
- ucfirst: function(str)
- {
- return str.charAt(0).toUpperCase() + str.slice(1);
- },
-
- // object
- checkProperty: function(obj)
- {
- var args = (arguments[1] && Array.isArray(arguments[1])) ? arguments[1] : [].slice.call(arguments, 1);
-
- for (var i = 0; i < args.length; i++)
- {
- if (!obj || (typeof obj[args[i]] === 'undefined'))
- {
- return false;
- }
-
- obj = obj[args[i]];
- }
-
- return obj;
- },
-
- // data
- extendData: function(data, elements)
- {
- if (typeof elements === 'object')
- {
- data = $K.extend({}, data, elements);
- }
- else if (typeof elements === 'string')
- {
- var $elms = $K.dom(elements);
- $elms.each(function(node)
- {
- var $node = $K.dom(node);
- if (node.tagName === 'FORM')
- {
- data = $K.extend({}, data, $node.serialize(true));
- }
- else
- {
- var name = ($node.attr('name')) ? $node.attr('name') : $node.attr('id');
- var val = $node.val();
- data[name] = (this._isNumber(val)) ? parseFloat(val) : this._getBooleanFromStr(val);
- }
- });
- }
-
- return data;
- },
- _isNumber: function(str)
- {
- return !isNaN(str) && !isNaN(parseFloat(str));
- },
- _getBooleanFromStr: function(str)
- {
- if (str === 'true') return true;
- else if (str === 'false') return false;
-
- return str;
- }
- });
-
- window.Kube = window.$K = $K;
- }());
- (function($K)
- {
- $K.add('module', 'alert', {
- init: function(app, context)
- {
- this.app = app;
- this.animate = app.animate;
-
- // context
- this.context = context;
- this.$element = context.getElement();
- },
- // events
- onclick: function(e, element, type)
- {
- if (type === 'close')
- {
- this.close(e);
- }
- },
- // public
- open: function(e)
- {
- if (this.$element.isOpened()) return;
- if (e) e.preventDefault();
-
- this.app.broadcast('alert.open', this);
- this.animate.run(this.$element, 'fadeIn', this._opened.bind(this));
- },
- close: function(e)
- {
- if (this.$element.isClosed()) return;
- if (e) e.preventDefault();
-
- this.app.broadcast('alert.close', this);
- this.animate.run(this.$element, 'fadeOut', this._closed.bind(this));
- },
- // private
- _opened: function()
- {
- this.app.broadcast('alert.opened', this);
- },
- _closed: function()
- {
- this.app.broadcast('alert.closed', this);
- }
- });
- })(Kube);
- (function($K)
- {
- $K.add('module', 'toggle', {
- init: function(app, context)
- {
- this.app = app;
- this.animate = app.animate;
-
- // defaults
- var defaults = {
- target: false
- };
-
- // context
- this.context = context;
- this.params = context.getParams(defaults);
- this.$element = context.getElement();
- this.$target = context.getTarget();
- },
- // public
- start: function()
- {
- this.$element.on('click.kube.toggle', this.toggle.bind(this));
- },
- stop: function()
- {
- this.$element.off('.kube.toggle');
- },
- toggle: function(e)
- {
- return (this.$target.isOpened()) ? this.close(e) : this.open(e);
- },
- open: function(e)
- {
- if (this.$target.isOpened()) return;
- if (e) e.preventDefault();
-
- this.app.broadcast('toggle.open', this);
- this.animate.run(this.$target, 'slideDown', this._opened.bind(this));
- },
- close: function(e)
- {
- if (this.$target.isClosed()) return;
- if (e) e.preventDefault();
-
- this.app.broadcast('toggle.close', this);
- this.animate.run(this.$target, 'slideUp', this._closed.bind(this));
- },
-
- // private
- _opened: function()
- {
- this.app.broadcast('toggle.opened', this);
- },
- _closed: function()
- {
- this.app.broadcast('toggle.closed', this);
- }
- });
- })(Kube);
- (function($K)
- {
- $K.add('module', 'sticky', {
- init: function(app, context)
- {
- this.app = app;
- this.$win = app.$win;
-
- // defaults
- var defaults = {
- offset: 0 // string in pixels
- };
-
- // context
- this.context = context;
- this.params = context.getParams(defaults);
- this.$element = context.getElement();
- },
- start: function()
- {
- this.offsetTop = this._getOffsetTop();
-
- this._load();
- this.$win.on('scroll.kube.sticky', this._load.bind(this));
- },
- stop: function()
- {
- this.$win.off('scroll.kube.sticky');
- this.$element.removeClass('fixed').css('top', '');
- },
- // private
- _load: function()
- {
- return (this._isFix()) ? this._setFixed() : this._setUnfixed();
- },
- _isFix: function()
- {
- return (this.$win.scrollTop() > (this.offsetTop + parseInt(this.params.offset, 10)));
- },
- _setFixed: function()
- {
- this.$element.addClass('is-fixed').css('top', this.params.offset);
- this.app.broadcast('sticky.fixed', this);
- },
- _setUnfixed: function()
- {
- this.$element.removeClass('is-fixed').css('top', '');
- this.app.broadcast('sticky.unfixed', this);
- },
- _getOffsetTop: function()
- {
- return this.$element.offset().top;
- }
- });
- })(Kube);
- (function($K)
- {
- $K.add('module', 'offcanvas', {
- init: function(app, context)
- {
- this.app = app;
- this.$doc = app.$doc;
- this.$body = app.$body;
- this.utils = app.utils;
- this.animate = app.animate;
- this.transition = app.transition;
-
- // defaults
- var defaults = {
- clickOutside: true,
- target: false
- };
-
- // context
- this.context = context;
- this.params = context.getParams(defaults);
- this.$element = context.getElement();
- this.$target = context.getTarget();
-
- // build
- this._build();
- },
- start: function()
- {
- this.$element.on('click.kube.offcanvas', this.toggle.bind(this));
- },
- stop: function()
- {
- this._clear();
- },
- toggle: function(e)
- {
- return (this.$target.isOpened()) ? this.close(e) : this.open(e);
- },
- open: function(e)
- {
- if (e)
- {
- e.stopPropagation();
- e.preventDefault();
- }
-
- this._clear();
-
- this.$body.addClass('is-no-scroll-x');
- this.$target.addClass('is-offcanvas');
-
- this.targetWidth = this.$target.width();
-
- this._resize();
- this.app.broadcast('offcanvas.open', this);
-
- return (this.isSlide) ? this._openSlide() : this._openPush();
- },
- close: function(e)
- {
- if (this.eventScroll) return;
- if (e)
- {
- var $el = $K.dom(e.target);
- var el = $el.get();
- var isClickable = (el.tagName === 'A' ||el.tagName === 'BUTTON');
- if (!isClickable || el === this.$element.get())
- {
- e.stopPropagation();
- e.preventDefault();
- }
- }
-
- this.app.broadcast('offcanvas.close', this);
-
- return (this.isSlide) ? this._closeSlide() : this._closePush();
- },
- // private
- _build: function()
- {
- this.isSlide = !(this.$target.hasClass('is-offcanvas-push'));
- this.slideDirection = (this.$target.hasClass('is-offcanvas-right')) ? 'Right' : 'Left';
- this.pushSign = (this.slideDirection === 'Left') ? '' : '-';
- this.eventScroll = false;
- },
- _handleKeyboard: function(e)
- {
- if (e.which === 27) this.close();
- },
-
- _openSlide: function()
- {
- this.animate.run(this.$target, 'slideIn' + this.slideDirection, this._opened.bind(this));
- },
- _openPush: function()
- {
- this.$target.show();
- this._pushBody(this.pushSign + this.targetWidth + 'px', this._opened.bind(this));
- },
- _opened: function()
- {
- this.$doc.on('touchmove.kube.offcanvas', function() { this.eventScroll = true; }.bind(this));
- this.$doc.on('touchstart.kube.offcanvas', function() { this.eventScroll = false; }.bind(this));
- this.$doc.on('keyup.kube.offcanvas', this._handleKeyboard.bind(this));
-
- if (this.params.clickOutside)
- {
- this.$doc.on('click.kube.offcanvas touchend.kube.offcanvas', this.close.bind(this));
- }
-
- this.app.broadcast('offcanvas.opened', this);
- },
- _closeSlide: function()
- {
- this.animate.run(this.$target, 'slideOut' + this.slideDirection, this._closed.bind(this));
- },
- _closePush: function()
- {
- this._pushBody('0', this._closed.bind(this));
- },
- _closed: function()
- {
- this.$doc.off('.kube.offcanvas');
- this.$body.removeClass('is-no-scroll-x');
- this.transition.remove(this.$body);
- this.$target.removeClass('is-offcanvas');
- this.$target.hide();
-
- this.app.broadcast('offcanvas.closed', this);
- },
- _pushBody: function(transform, callback)
- {
- var params = {
- classname: 'is-offcanvasTransition',
- css: { transform: 'translateX(' + transform + ')' },
- callback: callback
- };
-
- this.transition.run(this.$body, params, callback);
- },
- _resize: function()
- {
- var resize = function()
- {
- this.$target.height(this.$doc.height());
- }.bind(this);
-
- resize();
- this.$doc.on('resize.kube.offcanvas', resize);
- },
- _clear: function()
- {
- this.$doc.off('.kube.offcanvas');
- this.transition.remove(this.$body);
-
- $K.dom('.is-offcanvas').each(function(node)
- {
- var $el = $K.dom(node);
-
- this.animate.remove($el);
-
- $el.hide();
- $el.removeClass('is-offcanvas');
-
- }.bind(this));
- }
- });
- })(Kube);
- (function($K)
- {
- $K.add('module', 'tabs', {
- init: function(app, context)
- {
- this.app = app;
- this.$body = app.$body;
-
- // defaults
- var defaults = {
- equal: false
- };
-
- // context
- this.context = context;
- this.params = context.getParams(defaults);
- this.$element = context.getElement();
-
- // local
- this.$boxes = $K.dom([]);
- this.$tabActive = false;
- this.$boxActive = false;
- },
- start: function()
- {
- this._buildControls();
- this._buildBoxes();
- this._setEqualBoxes();
-
- this._open();
- },
- stop: function()
- {
- this.$tabsControls.off('.kube.tabs');
- },
- // api
- getActiveTab: function()
- {
- return this.$tabActive;
- },
- getActiveBox: function()
- {
- return this.$boxActive;
- },
- // private
- _toggle: function(e)
- {
- if (e)
- {
- e.stopPropagation();
- e.preventDefault();
- }
-
- var $tab = $K.dom(e.target);
- var $box = this._getBox($tab);
-
- if ($tab.hasClass('is-active')) return;
-
- this._open($tab);
- this.app.broadcast('tabs.opened', this);
- },
- _buildControls: function()
- {
- this.$tabsControls = this.$element.find('a');
- this.$tabsControls.on('click.kube.tabs', this._toggle.bind(this));
- },
- _buildBoxes: function()
- {
- this.$tabsControls.each(function(node, i)
- {
- var $tab = $K.dom(node);
- var $box = this._getBox($tab);
-
- this.$boxes.add($box);
-
- if (i === 0) this.$tabActive = $tab;
- if ($tab.hasClass('is-active')) this.$tabActive = $tab;
-
- }.bind(this));
- },
- _open: function($tab)
- {
- this.$tabActive = ($tab) ? $tab : this.$tabActive;
-
- this.$tabsControls.removeClass('is-active');
- this.$tabActive.addClass('is-active');
- this.$boxActive = this._getBox(this.$tabActive);
-
- this.$boxes.addClass('is-hidden').removeClass('is-open');
- this.$boxActive.removeClass('is-hidden').addClass('is-open');
- },
- _getBox: function($tab)
- {
- return $K.dom($tab.attr('href'));
- },
- _setEqualBoxes: function()
- {
- if (!this.params.equal) return;
-
- var minHeight = this._getItemMaxHeight() + 'px';
-
- this.$boxes.css('min-height', minHeight);
- },
- _getItemMaxHeight: function()
- {
- var max = 0;
- this.$boxes.each(function(node)
- {
- var $node = $K.dom(node);
- var h = $node.height();
- max = (h > max) ? h : max;
- });
-
- return max;
- }
- });
- })(Kube);
- (function($K)
- {
- $K.add('module', 'dropdown', {
- init: function(app, context)
- {
- this.app = app;
- this.$doc = app.$doc;
- this.$win = app.$win;
- this.$body = app.$body;
- this.utils = app.utils;
- this.animate = app.animate;
-
- // defaults
- var defaults = {
- target: false
- };
-
- // context
- this.context = context;
- this.params = context.getParams(defaults);
- this.$element = context.getElement();
- this.$target = context.getTarget();
-
- // local
- this.animationOpen = 'slideDown';
- this.animationClose = 'slideUp';
- },
- // public
- start: function()
- {
- this.$element.on('click.kube.dropdown', this.toggle.bind(this));
- },
- stop: function()
- {
- this.animate.clear(this.$target);
- this.$target.hide();
-
- this.$element.off('.kube.dropdown');
- this.$doc.off('.kube.dropdown');
- this.$win.off('.kube.dropdown');
- },
- toggle: function(e)
- {
- return (this.$target.isOpened()) ? this.close(e) : this.open(e);
- },
- open: function(e)
- {
- if (this.$target.isOpened()) return;
- if (e)
- {
- e.stopPropagation();
- e.preventDefault();
- }
-
- this.$doc.off('.kube.dropdown');
- this.$win.off('.kube.dropdown');
-
- // hide all
- this.$body.find('.dropdown').each(function(node)
- {
- var $el = $K.dom(node);
-
- this.animate.remove($el);
- $el.hide();
-
- }.bind(this));
-
- this._openCaret();
- this._setPosition();
-
- this.$element.addClass('dropdown-in');
- this.app.broadcast('dropdown.open', this);
- this.animate.run(this.$target, this.animationOpen, this._opened.bind(this));
- },
- close: function(e)
- {
- if (this.$target.isClosed()) return;
- if (e)
- {
- var el = e.target;
- var $el = $K.dom(el);
- var isClickable = (el.tagName === 'A' || el.tagName === 'BUTTON');
- if (!isClickable || el === this.$element.get() || (el.tagName === 'A' && $el.hasClass('is-active')))
- {
- e.stopPropagation();
- e.preventDefault();
- }
- }
-
- this.app.broadcast('dropdown.close', this);
- this.animate.run(this.$target, this.animationClose, this._closed.bind(this));
- },
-
- // private
- _getPlacement: function()
- {
- var pos = this.$element.position();
- var height = parseFloat(this.$element.css('height')) + pos.top + parseFloat(this.$target.css('height'));
- return (this.$doc.height() < height) ? 'top' : 'bottom';
- },
- _setPosition: function()
- {
- var elHeight = parseFloat(this.$element.css('height'));
- var pos = this.$element.offset();
- var top = pos.top + elHeight;
- var left = pos.left;
- var height = parseFloat(this.$target.css('height'));
- var placement = this._getPlacement();
- var width = parseFloat(this.$target.css('width'));
- var borderWidth = parseFloat(this.$element.css('border-left-width')) + parseFloat(this.$element.css('border-right-width'));
- var leftFix = (this.$win.width() < (left + width)) ? (width - this.$element.width() - borderWidth) : 0;
-
- if (placement === 'top')
- {
- top = top - height - elHeight;
- this.animationOpen = 'show';
- this.animationClose = 'hide';
- }
- else
- {
- this.animationOpen = 'slideDown';
- this.animationClose = 'slideUp';
- }
-
- this.$target.css({ 'top': top + 'px', 'left': (left - leftFix) + 'px' });
- },
- _handleKeyboard: function(e)
- {
- if (e.which === 27) this.close();
- },
- _opened: function()
- {
- this.$doc.on('keyup.kube.dropdown', this._handleKeyboard.bind(this));
- this.$doc.on('click.kube.dropdown touchstart.kube.dropdown', this.close.bind(this));
- this.$doc.on('scroll.kube.dropdown', this._setPosition.bind(this));
- this.$win.on('resize.kube.dropdown', this._setPosition.bind(this));
-
- this.app.broadcast('dropdown.opened', this);
- },
- _closed: function()
- {
- this.$doc.off('.kube.dropdown');
- this.$win.off('.kube.dropdown');
-
- this._closeCaret();
- this.$element.removeClass('dropdown-in');
- this.app.broadcast('dropdown.closed', this);
- },
- _openCaret: function()
- {
- var $caret = this.$element.find('.caret');
- $caret.removeClass('is-down').addClass('is-left');
- },
- _closeCaret: function()
- {
- var $caret = this.$element.find('.caret');
- $caret.removeClass('is-left').addClass('is-down');
- }
- });
- })(Kube);
|