You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

4026 lines
104 KiB

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