/* 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);