chicago
Version:
A front-end JavaScript library for user-interface developers.
1,700 lines (1,692 loc) • 49.3 kB
JavaScript
/*!
* Chicago - A front-end JavaScript library for user-interface developers.
*
* Copyright (c) 2015 Erik Nielsen
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Project home:
* https://nielse63.github.io/Chicago/
*
* Version: 1.1.0
*
*/
Array.prototype.diff = function(a) {
return this.filter(function(i) {
return a.indexOf(i) < 0;
});
};
/*!
* Chicago - Core
* Base core of the Chicago library
*
* Copyright (c) 2015 Erik Nielsen
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Project home:
* https://nielse63.github.io/Chicago/
*
* Version: 1.1.0
*
*/
(function(global, factory) {
if(typeof window === "undefined" && global.window) {
global = global.window;
}
if(typeof define === "function" && define.amd) {
define("chicago", function() {
var chicago = global.Chicago || factory(global.jQuery, global, global.document);
chicago.load = function(res, req, onload, config) {
var resources = res.split(','),
load = [],
i, base = (config.config && config.config.chicago && config.config.chicago.base ? config.config.chicago.base : "").replace(/\/+$/g, "");
if(!base) {
throw new Error("Please define base path to Chicago in the requirejs config.");
}
for(i = 0; i < resources.length; i += 1) {
var resource = resources[i].replace(/\./g, '/');
load.push(base + '/modules/' + resource);
}
req(load, function() {
onload(chicago);
});
};
return chicago;
});
}
if(!global.jQuery) {
throw new Error('Chicago requires jQuery');
}
global.Chicago = factory(global.jQuery, global, global.document);
return global.Chicago;
})(typeof window !== "undefined" ? window : this, function($, win, doc) {
var _cTemp = win.Chicago;
var eventnames = {
beforeready : 'beforeready.chicago.dom',
ready : 'ready.chicago.dom',
load : 'reloaded.chicago.dom',
init : 'init.chicago.module'
};
var _c = {
version : '1.1.0',
doc : doc,
win : win,
$ : $,
$doc : $(doc),
$win : $(win),
$html : $('html'),
$head : $('html head'),
$body : $('body'),
utils : {},
support : {},
modules : {},
create : {},
css : {},
elements : {},
deprecated : {},
domReady : false,
langdirection : $('html').attr('dir') ? $('html').attr('dir') : 'ltr',
extend : function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
if(_c.utils.is.boolean(target)) {
deep = target;
target = arguments[i] || {};
i++;
}
if(typeof target !== "object" && !_c.utils.is.function(target)) {
target = {};
}
for(; i < length; i++) {
if((options = arguments[i]) !== null) {
for(name in options) {
src = target[name];
copy = options[name];
if(target === copy) {
continue;
}
if(deep && copy && (_c.utils.is.object(copy) || (copyIsArray = _c.utils.is.array(copy)))) {
if(copyIsArray) {
copyIsArray = false;
clone = src && _c.utils.is.array(src) ? src : [];
} else {
clone = src && _c.utils.is.object(src) ? src : {};
}
target[name] = _c.extend(deep, clone, copy);
} else if(copy !== undefined) {
target[name] = copy;
}
}
}
}
return target;
},
noConflict : function() {
if(_cTemp) {
win.Chicago = _cTemp;
$.Chicago = _cTemp;
$.fn.chicago = _cTemp.fn;
return _cTemp;
}
return this;
},
fn : function(command, options) {
var args = arguments,
cmd = command.match(/^([a-z\-]+)(?:\.([a-z]+))?/i),
module = cmd[1],
method = cmd[2];
if(!method && typeof options === 'string') {
method = options;
}
if(!_c[module]) {
$.error('Chicago module [' + module + '] does not exist.');
return this;
}
return this.each(function() {
var $this = _c.$(this);
var data = $this.data(module);
if(!data) {
$this.data(module, data = _c[module](this, (method ? void 0 : options)));
}
if(method) {
data[method].apply(data, Array.prototype.slice.call(args, 1));
}
});
},
on : function(evt, handler, data) {
if(evt && evt.indexOf(eventnames.ready) > -1 && _c.domReady) {
return handler.apply(_c.$doc);
}
return _c.$doc.on(evt, handler, data);
},
trigger : function(evt, params) {
return _c.$doc.trigger(evt, params);
},
};
_c.ready = function(fn) {
if(_c.domReady) {
return fn(doc);
}
return _c.on(eventnames.ready);
};
_c.module = function(name, methods) {
if(!this.create[name]) {
this.create[name] = function(_this) {
return function(options) {
return _this.factory.make(name, options);
};
}(this);
}
var dataKey = 'chicago.data.' + name,
fn = function(element, options) {
this.element = element ? _c.$(element) : null;
this.options = _c.extend(true, {}, this.defaults, options);
if(this.element) {
this.element.data(dataKey, this);
if(!_c.elements[name]) {
_c.elements[name] = null;
}
}
this.init();
this.trigger(eventnames.init, [name, this]);
return this;
};
this.extend(true, fn.prototype, {
defaults : {},
boot : function() {},
init : function() {},
destroy : function() {},
on : function(evt, data, handler) {
return _c.$(this.element || this).on(evt, data, handler);
},
one : function(evt, data, handler) {
return _c.$(this.element || this).one(evt, data, handler);
},
off : function(evt) {
return _c.$(this.element || this).off(evt);
},
trigger : function(evt, params) {
return _c.$(this.element || this).trigger(evt, params);
},
proxy : function(obj, methods) {
return methods.split(' ').forEach(function(_this) {
return function(method) {
if(!_this[method]) {
_this[method] = function() {
return obj[method].apply(obj, arguments);
};
}
};
}(this));
},
}, methods);
this.modules[name] = fn;
this[name] = function() {
var args = arguments,
ele,
options;
if(args.length) {
switch(args.length) {
case 1:
if(_c.utils.is.string(args[0]) || args[0].nodeType || _c.utils.is.jQueryObject(args[0])) {
ele = $(args[0]);
} else {
options = args[0];
}
break;
case 2:
ele = _c.$(args[0]);
options = args[1];
break;
}
}
if(ele && ele.data(dataKey)) {
return ele.data(dataKey);
}
return new _c.modules[name](ele, options);
};
if(!this[name].template) {
this[name].template = {};
}
this[name].template = _c.extend(this[name].template, methods.template);
if(_c.domReady) {
_c.module.boot(name);
}
return fn;
};
_c.module.boot = function(name) {
if(_c.modules[name] && _c.modules[name].prototype && _c.modules[name].prototype.boot && !_c.modules[name].booted) {
_c.modules[name].booted = true;
_c.modules[name].prototype.boot.apply(_c, []);
}
};
_c.bootComponents = function() {
for(var module in _c.modules) {
_c.module.boot(module);
}
};
_c.on(eventnames.ready, function() {
if(_c.domReady) {
return;
}
_c.domReady = true;
});
_c.support = _c.$.extend(_c.support, {
requestAnimationFrame : win.requestAnimationFrame ||
win.webkitRequestAnimationFrame ||
win.mozRequestAnimationFrame ||
win.msRequestAnimationFrame ||
win.oRequestAnimationFrame ||
function(callback) {
win.setTimeout(callback, 1e3 / 60);
},
touch : 'ontouchstart' in win ||
win.DocumentTouch && win.document instanceof win.DocumentTouch ||
win.navigator.msPointerEnabled && win.navigator.msMaxTouchPoints > 0 ||
win.navigator.pointerEnabled && win.navigator.maxTouchPoints > 0 ||
false,
mutationobserver : win.MutationObserver ||
win.WebKitMutationObserver ||
null,
transition : {
end : (function() {
var ele = doc.body || doc.documentElement,
eventNames = {
WebkitTransition : 'webkitTransitionEnd',
MozTransition : 'transitionend',
OTransition : 'oTransitionEnd otransitionend',
transition : 'transitionend',
};
for(var name in eventNames) {
if(ele.style[name] !== undefined) {
return eventNames[name];
}
}
})()
},
animation : {
start : (function() {
var ele = doc.body || doc.documentElement,
eventNames = {
WebkitAnimation : 'webkitAnimationStart',
MozAnimation : 'animationstart',
OAnimation : 'oAnimationStart oanimationstart',
MSAnimation : 'MSAnimationStart',
animation : 'animationstart',
};
for(var name in eventNames) {
if(ele.style[name] !== undefined) {
return eventNames[name];
}
}
})(),
iteration : (function() {
var ele = doc.body || doc.documentElement,
eventNames = {
WebkitAnimation : 'webkitAnimationIteration',
MozTransition : 'animationiteration',
OTransition : 'oAnimationIteration oanimationiteration',
MSAnimation : 'MSAnimationIteration',
transition : 'animationiteration',
};
for(var name in eventNames) {
if(ele.style[name] !== undefined) {
return eventNames[name];
}
}
})(),
end : (function() {
var ele = doc.body || doc.documentElement,
eventNames = {
WebkitAnimation : 'webkitAnimationEnd',
MozAnimation : 'animationend',
OAnimation : 'oAnimationEnd oanimationend',
MSAnimation : 'MSAnimationEnd',
transition : 'animationend',
};
for(var name in eventNames) {
if(ele.style[name] !== undefined) {
return eventNames[name];
}
}
})()
}
});
_c.utils = _c.$.extend(_c.utils, {
is : {
undefined : function(obj) {
return obj === undefined || typeof obj === 'undefined';
},
null : function(obj) {
return Object.prototype.toString.call(obj) === '[object Null]';
},
boolean : function(obj) {
return typeof obj === 'boolean';
},
string : function(obj) {
return typeof obj === 'string' || Object.prototype.toString.call(obj) === '[object String]';
},
numeric : function(obj) {
return !isNaN(parseFloat(obj)) && isFinite(obj);
},
integer : function(obj) {
return obj && Number(obj) === obj && obj % 1 === 0;
},
float : function(obj) {
return obj && Number(obj) === obj && obj % 1 !== 0;
},
date : function(obj) {
var d = new Date(obj);
return d !== 'Invalid Date' && d.toString() !== 'Invalid Date' && !isNaN(d);
},
jQueryObject : function(obj) {
return obj instanceof win.jQuery;
},
element : function(obj) {
var ele = this.jQueryObject(obj) ? obj[0] : obj;
return(typeof HTMLElement === 'object' ? ele instanceof HTMLElement : (ele && typeof ele === 'object' && ele.nodeType === 1 && typeof ele.nodeName === 'string'));
},
function : function(obj) {
return typeof obj === 'function';
},
array : function(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
},
object : function(obj) {
return Object.prototype.toString.call(obj) === '[object Object]';
},
},
now : Date.now || function() {
return new Date().getTime();
},
inArray : function(array, item) {
return array.indexOf(item) > -1;
},
debounce : function(fn, wait, immediate) {
var timeout;
return function() {
var context = this,
args = arguments,
later = function() {
timeout = null;
if(!immediate) {
fn.apply(context, args);
}
},
callNow = immediate && !timeout;
win.clearTimeout(timeout);
timeout = win.setTimeout(later, wait);
if(callNow) {
fn.apply(context, args);
}
};
},
toCamelCase : function(string) {
if(string === null || string === undefined) {
return '';
}
string = String(string).trim();
return string.replace(/(\-[a-z])/g, function(letter) {
return letter.toUpperCase().replace('-', '');
});
},
uid : function(prefix) {
var d = _c.utils.now();
prefix = prefix || '';
return prefix + 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return(c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
},
watch : function(object, property, callback) {
var watch = Object.prototype.watch || Object.defineProperty(Object.prototype, "watch", {
enumerable : false,
configurable : true,
writable : false,
value : function(prop, handler) {
var oldval = this[prop],
newval = oldval,
getter = function() {
return this.__clones[prop];
},
setter = function(val) {
if(newval !== val) {
oldval = newval;
newval = this.__clones[prop] = val;
return handler.call(this, prop, oldval, val);
}
};
if(delete this[prop]) {
Object.defineProperty(this, prop, {
get : getter,
set : setter,
enumerable : true,
configurable : true
});
}
}
});
if(!object.hasOwnProperty('__clones')) {
object.__clones = {};
}
object.__clones[property] = object[property];
object.watch(property, callback);
},
unwatch : function(object, property) {
var unwatch = Object.prototype.unwatch || Object.defineProperty(Object.prototype, "unwatch", {
enumerable : false,
configurable : true,
writable : false,
value : function(prop) {
var val = this[prop];
delete this[prop];
this[prop] = val;
}
});
function applyUnwatch(prop) {
object.unwatch(prop);
if(object.__clones && object.__clones[prop]) {
delete object.__clones[prop];
}
if(!Object.keys(object.__clones).length) {
delete object.__clones;
}
}
if(property === undefined) {
for(var key in object) {
applyUnwatch(key);
}
} else {
applyUnwatch(property);
}
},
getCSSValue : function(ele, property) {
var value = ele.css(property).replace(/px/gi, '');
if(_c.utils.is.numeric(value)) {
value = parseFloat(value);
if(_c.utils.is.float(value)) {
value = parseFloat(value.toFixed(2));
}
}
return value;
},
stringToMilliseconds : function(string) {
if(!_c.utils.is.string(string)) {
string = String(string);
}
return parseInt(parseFloat(string.replace('s', '')) * 1000, 10);
},
stringToSlug : function(string) {
string = String(string) || '';
return string
.replace(/[^a-zA-Z0-9]/g, ' ')
.replace(/\s+/g, '-')
.toLowerCase();
},
str2json : function(str, notevil) {
try {
if(notevil) {
return JSON.parse(str.replace(/([\$\w]+)\s* :/g, function(_, $1) {
return '"' + $1 + '" :';
}).replace(/'([^']+)'/g, function(_, $1) {
return '"' + $1 + '"';
}));
} else {
var newFN = Function;
return new newFN('', 'var json = ' + str + '; return JSON.parse(JSON.stringify(json));')();
}
} catch(e) {
return false;
}
},
options : function(string) {
if(_c.utils.is.object(string)) {
return string;
}
var start = string ? string.indexOf('{') : -1;
var options = {};
if(start !== -1) {
try {
options = _c.utils.str2json(string.substr(start));
} catch(_error) {}
}
return options;
},
});
var shouldVendorize = [
'box-sizing',
'transition',
'transform',
'perspective',
'calc',
'border-radius',
'background-clip',
];
_c.factory = {
template : function(str, data) {
var tokens = str.replace(/\n/g, '\\n').replace(/\{\{\{\s*(.+?)\s*\}\}\}/g, "{{!$1}}").split(/(\{\{\s*(.+?)\s*\}\})/g),
i = 0,
toc,
cmd,
prop,
val,
fn,
output = [],
openblocks = 0;
while(i < tokens.length) {
toc = tokens[i];
if(toc.match(/\{\{\s*(.+?)\s*\}\}/)) {
i = i + 1;
toc = tokens[i];
cmd = toc[0];
prop = toc.substring(toc.match(/^(\^|\#|\!|\~|\:)/) ? 1 : 0);
switch(cmd) {
case '#':
output.push("if(" + prop + ") {");
openblocks++;
break;
case '/':
output.push("}");
openblocks--;
break;
case '!':
output.push("__ret.push(" + prop + ");");
break;
default:
output.push("__ret.push(" + prop + ");");
break;
}
} else {
output.push("__ret.push('" + toc.replace(/\'/g, "\\'") + "');");
}
i = i + 1;
}
fn = new Function('$data', [
'var __ret = [];',
'try {',
'with($data){', (!openblocks ? output.join('') : '__ret = ["Not all blocks are closed correctly."]'), '};',
'}catch(e){__ret = [e.message];}',
'return __ret.join("").replace(/\\n\\n/g, "\\n");',
'function escape(html) { return String(html).replace(/&/g, \'&\').replace(/\"/g, \'"\').replace(/</g, \'<\').replace(/>/g, \'>\');}'
].join("\n"));
return data ? fn(data) : fn;
},
make : function(name, options) {
if(!_c[name] || !_c[name].template) {
return;
}
options = options || {};
var templateOptions = {},
ele;
if(_c[name].template.options) {
for(var prop in options) {
if(!_c.utils.is.undefined(_c[name].template.options[prop])) {
if(prop === 'id') {
options[prop] = _c.utils.stringToSlug(options[prop]);
}
templateOptions[prop] = options[prop];
}
}
templateOptions = _c.extend(true, {}, _c[name].template.options, templateOptions);
}
if(_c[name].template.css && !_c.css[name]) {
_c.css[name] = true;
var css = _c.factory.css(_c[name].template.css, name);
_c.$head.prepend(css);
}
if(_c[name].template.html) {
var html = _c.factory.template(_c[name].template.html, templateOptions);
ele = _c.$(html);
_c.$body.append(ele);
} else {
ele = _c.$doc;
}
return _c[name](ele, options);
},
vendorize : function(property, value) {
if(_c.utils.is.numeric(value)) {
return property + ':' + value + ';';
}
property = String(property);
value = String(value);
var prefixes = [
'-webkit-',
'-moz-',
],
output = property + ':' + value + ';\n';
for(var i = 0; i < shouldVendorize.length; i++) {
var prop = shouldVendorize[i];
if(output.indexOf(prop) > -1) {
var prefix = _c.browser.getPrefix(prop);
output = output.replace(new RegExp(prop, 'g'), prefix + prop);
}
}
return output;
},
needsUnit : function(property) {
var needsUnit = [
'width',
'height',
'top',
'left',
'bottom',
'right',
'margin',
'padding',
'font-size',
];
return _c.utils.inArray(needsUnit, property)
},
css : function(object, name) {
name = name || 'module';
if(!_c.utils.is.object(object)) {
throw new Error('_c.factory.css requires an object');
}
var output = ['<style data-css="' + name + '-css">', '</style>'];
for(var selector in object) {
var len = output.length,
index = len - 1,
set = object[selector];
if(!_c.utils.is.object(set)) {
continue;
}
output.splice(index, 0, selector);
var setString = '{';
for(var prop in set) {
var value = set[prop];
if(value && _c.utils.is.numeric(value)) {
value = _c.factory.needsUnit(prop) ? value += 'px' : value;
}
setString += _c.factory.vendorize(prop, value);
}
len = output.length;
index = len - 1;
output.splice(index, 0, setString + '}');
}
return output.join('');
},
};
_c.factory.make.css = function(name) {
if(_c[name] && _c[name].template.css && !_c.css[name]) {
_c.css[name] = true;
var css = _c.factory.css(_c[name].template.css, name);
_c.$head.prepend(css);
}
};
(function() {
_c.$doc.on('ready', function() {
_c.$body = _c.$('body');
_c.trigger(eventnames.beforeready);
_c.bootComponents();
_c.$win.on('load resizeend orientationchange', _c.utils.debounce(function() {
_c.$doc.trigger(eventnames.load);
}, 100));
_c.trigger(eventnames.ready);
});
})();
return _c;
});
/*!
* Chicago - Browser
* A collection of browser capability methods
*
* Copyright (c) 2015 Erik Nielsen
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Project home:
* https://nielse63.github.io/Chicago/
*
* Version: 1.1.0
*
*/
(function(global, factory) {
var module;
var Chicago = global.Chicago || null;
if(Chicago) {
module = factory(Chicago, global, global.document);
}
if(typeof define === 'function' && define.amd) {
define('chicago-browser', ['chicago'], function() {
return module || factory(Chicago, global, global.document);
});
}
})(typeof window !== "undefined" ? window : (typeof this.window !== "undefined" ? this.window : this), function(_c, win, doc) {
var test = function(rgx) {
var ua = win.navigator.userAgent;
return rgx.test(ua) || rgx.test(ua.toLowerCase());
};
var exec = function(rgx) {
var ua = win.navigator.userAgent;
return rgx.exec(ua) || rgx.exec(ua.toLowerCase());
};
var uamatches = function(key) {
var ua = win.navigator.userAgent;
return ua.indexOf(key) > -1 || ua.toLowerCase().indexOf(key) > -1;
};
var match = function(key) {
var matches = win.navigator.userAgent.match(key);
return !!matches ? matches[0] : null;
};
var version = function(obj, string) {
var returnObj = {
version : {
full : string
}
};
var versionArray = string.split('.');
if(versionArray.length > 0) {
versionArray = versionArray.reverse();
returnObj.version.major = parseFloat(versionArray.pop());
if(versionArray.length > 0) {
returnObj.version.minor = parseFloat(versionArray.pop());
if(versionArray.length > 0) {
versionArray = versionArray.reverse();
returnObj.version.patch = parseFloat(versionArray.join('.'));
} else {
returnObj.version.patch = 0;
}
} else {
returnObj.version.minor = 0;
}
} else {
returnObj.version.major = 0;
}
return _c.$.extend(obj, returnObj);
};
var objectHasKey = function(search, obj) {
if(!_c.utils.is.object(obj)) {
return false;
}
if(_c.utils.is.string(search)) {
search = search.toLowerCase();
}
for(var k in obj) {
var val = obj[k];
if(_c.utils.is.string(val)) {
val = val.toLowerCase();
}
if(_c.utils.is.object(val)) {
var contains = objectHasKey(search, val);
if(contains) {
return true;
}
}
if(val === search) {
return true;
}
}
return false;
};
var defs = {
device : {
types : ['TV', 'Tablet', 'Mobile', 'Desktop'],
},
screens : {
mini : 0,
small : 480,
medium : 768,
large : 960,
xlarge : 1220
},
};
_c.browser = {
is : function(string) {
return objectHasKey(string, this);
},
can : function(style) {
var supports = (function() {
var div = doc.createElement('div');
var vendors = 'Khtml Ms ms O Moz Webkit'.split(' ');
return function(prop) {
if(!_c.utils.is.undefined(div.style[prop])) {
return true;
}
prop = prop.replace(/^[a-z]/, function(val) {
return val.toUpperCase();
});
for(var i = 0; i < vendors.length; i++) {
var vendor = vendors[i];
if(!_c.utils.is.undefined(div.style[vendor + prop])) {
return true;
}
}
return false;
};
})();
return supports(style);
},
getPrefix : function(prop) {
var div = doc.createElement('div'),
vendors = 'Khtml Ms ms O Moz Webkit'.split(' ');
prop = _c.utils.toCamelCase(prop);
if(!_c.utils.is.undefined(div.style[prop])) {
return '';
}
for(var i = 0; i < vendors.length; i++) {
var vendor = vendors[i];
if(!_c.utils.is.undefined(div.style[vendor + prop])) {
return '-' + vendor.toLowerCase() + '-';
}
}
return '';
},
};
return _c.module('browserProxy', {
defaults : {
check : {
borwser : true,
device : true,
language : true,
os : true,
plugins : true,
screen : true,
touch : true,
},
addHTMLClasses : true,
},
classes : [],
boot : function() {
return _c.ready(function() {
var ele = _c.$doc;
if(!ele.data('chicago.data.browserProxy')) {
_c.browserProxy(ele);
}
});
},
init : function() {
_c.$doc.on('ready.chicago.dom reloaded.chicago.dom', function(_this) {
return function(e) {
_this.setBrowserData();
};
}(this));
},
setBrowserData : function() {
if(this.options.check.touch) {
_c.browser.touch = this.getTouch();
}
if(this.options.check.device) {
_c.browser.device = this.getDevice();
}
if(this.options.check.screen) {
_c.browser.screen = this.getScreen();
}
if(this.options.check.os) {
_c.browser.os = this.getOS();
}
if(this.options.check.borwser) {
_c.browser.browser = this.getBrowser();
}
if(this.options.check.language) {
_c.browser.language = this.getLanguage();
}
if(this.options.check.plugins) {
_c.browser.plugins = this.getPlugins();
}
if(this.options.addHTMLClasses) {
this.addHTMLClasses();
}
win.setTimeout(function() {
_c.$doc.trigger('updated.chicago.browser');
});
},
getTouch : function() {
var touch = 'ontouchstart' in win && win.navigator.userAgent.toLowerCase().match(/mobile|tablet/) ||
win.DocumentTouch && doc instanceof win.DocumentTouch ||
win.navigator.msPointerEnabled && win.navigator.msMaxTouchPoints > 0 ||
win.navigator.pointerEnabled && win.navigator.maxTouchPoints > 0 ||
false;
return !!touch;
},
getDevice : function() {
var device = {
type : null,
model : null
};
if(test(/GoogleTV|SmartTV|SMART-TV|Internet.TV|NetCast|NetTV|AppleTV|Boxee|Kylo|Roku|dlnadoc|Roku|POV_TV|HbbTV|ce\-html/)) {
device.type = defs.device.types[0];
device.model = 'SmartTV';
} else if(test(/Xbox|PLAYSTATION 3|Wii/)) {
device.type = defs.device.types[0];
device.model = 'Game Console';
} else if(test(/ip(a|ro)d/)) {
device.type = defs.device.types[1];
device.model = 'iPad';
} else if((test(/tablet/) && !test(/rx-34/)) || test(/folio/)) {
device.type = defs.device.types[1];
device.model = String(exec(/PlayBook/) || '');
} else if(test(/linux/) && test(/Android/) && !test(/Fennec|mobi|htc.magic|htcX06ht|nexus.one|sc-02b|fone.945/)) {
device.type = defs.device.types[1];
device.model = 'Android';
} else if(test(/Kindle/) || (test(/mac.os/) && test(/silk/))) {
device.type = defs.device.types[1];
device.model = 'Kindle';
} else if(test(/gt-p10|sc-01c|shw-m180s|sgh-t849|sch-i800|shw-m180l|sph-p100|sgh-i987|zt180|htc(.flyer|\_flyer)|sprint.atp51|viewpad7|pandigital(sprnova|nova)|ideos.s7|dell.streak.7|advent.vega|a101it|a70bht|mid7015|next2|nook/) || (test(/mb511/) && test(/rutem/))) {
device.type = defs.device.types[1];
device.model = 'Android';
} else if(test(/bb10/)) {
device.type = defs.device.types[1];
device.model = 'BlackBerry';
} else {
device.model = exec(/iPhone|iPod|Android|BlackBerry|Opera Mini|Opera Mobi|Skyfire|Maemo|Windows Phone|Palm|IEMobile|Symbian|SymbianOS|Fennec|J2ME/);
if(device.model !== null) {
device.type = defs.device.types[2];
device.model = match(String(device.model));
} else {
device.model = '';
if(test(/Bolt|Fennec|Iris|Maemo|minimo|mobi|mowser|netfront|novarra|prism|rx-34|Skyfire|tear|xv6875|xv6975|google.wireless.transcoder/)) {
device.type = defs.device.types[2];
} else if(test(/opera/) && test(/windows.nt.5/) && test(/htc|xda|mini|vario|samsung\-gt\-i8000|samsung\-sgh\-i9/)) {
device.type = defs.device.types[2];
} else if((test(/windows.(nt|xp|me|9)/) && !test(/phone/)) || test(/win(9|.9|nt)/) || test(/\(windows 8\)/)) {
device.type = defs.device.types[3];
} else if(test(/macintosh|powerpc/) && !test(/silk/)) {
device.type = defs.device.types[3];
device.model = 'Mac';
} else if(test(/linux/) && test(/x11/)) {
device.type = defs.device.types[3];
} else if(test(/solaris|sunos|bsd/)) {
device.type = defs.device.types[3];
} else if(test(/cros/)) {
device.type = defs.device.types[3];
} else if(test(/bot|crawler|spider|yahoo|ia_archiver|covario-ids|findlinks|dataparksearch|larbin|mediapartners-google|ng-search|snappy|teoma|jeeves|tineye/) && !test(/mobile/)) {
device.type = defs.device.types[3];
device.model = 'Crawler';
} else {
device.type = defs.device.types[3];
}
}
}
if(device.type !== 'Desktop' && device.type !== 'TV') {
device.orientation = 'landscape';
if(win.innerHeight > win.innerWidth) {
device.orientation = 'portrait';
}
}
return device;
},
getScreen : function() {
var keys = Object.keys(defs.screens).reverse();
for(var i = 0; i < keys.length; i++) {
var size = keys[i];
var width = defs.screens[size];
if(win.innerWidth > (width - 1)) {
return size;
}
}
},
getOS : function() {
var os = {
name : null,
addressRegisterSize : null,
};
if(_c.browser.device.model !== '') {
if(_c.browser.device.model === 'iPad' || _c.browser.device.model === 'iPhone' || _c.browser.device.model === 'iPod') {
os.name = 'iOS';
os = version(os, (test(/os\s([\d_]+)/) ? RegExp.$1 : '').replace(/_/g, '.'));
} else if(_c.browser.device.model === 'Android') {
os.name = 'Android';
os = version(os, (test(/Android\s([\d\.]+)/) ? RegExp.$1 : ''));
} else if(_c.browser.device.model === 'BlackBerry') {
os.name = 'BlackBerry';
os = version(os, (test(/version\/([^\s]+)/) ? RegExp.$1 : ''));
} else if(_c.browser.device.model === 'PlayBook') {
os.name = 'BlackBerry';
os = version(os, (test(/os ([^\s]+)/) ? RegExp.$1.replace(';', '') : ''));
}
}
if(!os.name) {
var options = [
'iOS',
'Android',
'BlackBerry',
'Opera Mini',
'Windows',
'Mac OS',
'OS X',
'AIX',
'Amiga',
'AROS',
'Bada',
'BeOS',
'Brew',
'Chrome OS',
'COS',
'Danger Hiptop',
'DragonFly BSD',
'Fire OS',
'Firefox OS',
'FreeBSD',
'GNU OS',
'Haiku OS',
'HP-UX',
'Inferno OS',
'IRIX',
'Joli OS',
'JVM (Java)',
'JVM',
'KIN OS',
'Linux',
'LiveArea',
'Maemo',
'MeeGo',
'MINIX 3',
'MorphOS',
'MSN TV (WebTV)',
'NetBSD',
'Nintendo 3DS',
'Nintendo DS',
'OpenBSD',
'OpenVM',
'Orbis OS',
'OS/2',
'OS/2 Warp',
'Palm OS',
'PClinuxOS',
'Plan 9',
'QNX x86pc',
'RISK OS',
'Sailfish',
'SCO OpenServer',
'SkyOS',
'Solaris',
'Syllable',
'Symbian OS',
'Tizen',
'Ubuntu Touch',
'webOS',
'Wii OS',
'Wii U OS',
'Xbox',
'XrossMediaBar (XMB)',
'Yun OS',
'unknown',
];
for(var i = 0; i < options.length; i++) {
var option = options[i];
if(uamatches(option)) {
os.name = option;
break;
}
}
}
if(!os.name) {
if(_c.browser.device.model !== '') {
if(_c.browser.device.model === 'ipad' || _c.browser.device.model === 'iphone' || _c.browser.device.model === 'ipod') {
os.name = 'ios';
version(os, (test(/os\s([\d_]+)/) ? RegExp.$1 : '').replace(/_/g, '.'));
} else if(_c.browser.device.model === 'Android') {
os.name = 'Android';
version(os, (test(/Android\s([\d\.]+)/) ? RegExp.$1 : ''));
} else if(_c.browser.device.model === 'BlackBerry') {
os.name = 'BlackBerry';
version(os, (test(/version\/([^\s]+)/) ? RegExp.$1 : ''));
} else if(_c.browser.device.model === 'PlayBook') {
os.name = 'BlackBerry';
version(os, (test(/os ([^\s]+)/) ? RegExp.$1.replace(';', '') : ''));
}
}
}
if(!os.name) {
if(uamatches('win') || uamatches('16bit')) {
os.name = 'windows';
if(uamatches('windows nt 6.3')) {
os = version(os, '8.1');
} else if(uamatches('windows nt 6.2') || test(/\(windows 8\)/)) {
os = version(os, '8');
} else if(uamatches('windows nt 6.1')) {
os = version(os, '7');
} else if(uamatches('windows nt 6.0')) {
os = version(os, 'vista');
} else if(uamatches('windows nt 5.2') || uamatches('windows nt 5.1') || uamatches('windows xp')) {
os = version(os, 'xp');
} else if(uamatches('windows nt 5.0') || uamatches('windows 2000')) {
os = version(os, '2k');
} else if(uamatches('winnt') || uamatches('windows nt')) {
os = version(os, 'nt');
} else if(uamatches('win98') || uamatches('windows 98')) {
os = version(os, '98');
} else {
if(uamatches('win95') || uamatches('windows 95')) {
os = version(os, '95');
}
}
} else if(uamatches('mac') || uamatches('darwin')) {
os.name = 'mac';
if(uamatches('68k') || uamatches('68000')) {
os = version(os, '68k');
} else if(uamatches('ppc') || uamatches('powerpc')) {
os = version(os, 'ppc');
} else {
if(uamatches('os x')) {
os = version(os, (test(/os\sx\s([\d_]+)/) ? RegExp.$1 : 'os x').replace(/_/g, '.'));
}
}
} else if(uamatches('webtv')) {
os.name = 'webtv';
} else if(uamatches('x11') || uamatches('inux')) {
os.name = 'linux';
} else if(uamatches('sunos')) {
os.name = 'sun';
} else if(uamatches('irix')) {
os.name = 'irix';
} else if(uamatches('freebsd')) {
os.name = 'freebsd';
} else {
if(uamatches('bsd')) {
os.name = 'bsd';
}
}
}
if(test(/\sx64|\sx86|\swin64|\swow64|\samd64/)) {
os.addressRegisterSize = '64bit';
} else {
os.addressRegisterSize = '32bit';
}
return os;
},
getBrowser : function() {
var browser = {
name : null,
engine : null,
};
if(!test(/opera|webtv/) && (test(/msie\s([\d\w\.]+)/) || uamatches('trident'))) {
browser.engine = 'trident';
browser.name = 'ie';
if(!win.addEventListener && doc.documentMode && doc.documentMode === 7) {
browser = version(browser, '8.compat');
} else if(test(/trident.*rv[ :](\d+)\./)) {
browser = version(browser, RegExp.$1);
} else {
browser = version(browser, (test(/trident\/4\.0/) ? '8' : RegExp.$1));
}
} else if(uamatches('firefox')) {
browser.engine = 'gecko';
browser.name = 'firefox';
browser = version(browser, (test(/firefox\/([\d\w\.]+)/) ? RegExp.$1 : ''));
} else if(uamatches('gecko/')) {
browser.engine = 'gecko';
} else if(uamatches('opera') || uamatches('opr')) {
browser.name = 'opera';
browser.engine = 'presto';
browser = version(browser, (test(/version\/([\d\.]+)/) ? RegExp.$1 : (test(/opera(\s|\/)([\d\.]+)/) ? RegExp.$2 : '')));
} else if(uamatches('konqueror')) {
browser.name = 'konqueror';
} else if(uamatches('chrome')) {
browser.engine = 'webkit';
browser.name = 'chrome';
browser = version(browser, (test(/chrome\/([\d\.]+)/) ? RegExp.$1 : ''));
} else if(uamatches('iron')) {
browser.engine = 'webkit';
browser.name = 'iron';
} else if(uamatches('crios')) {
browser.name = 'chrome';
browser.engine = 'webkit';
browser = version(browser, (test(/crios\/([\d\.]+)/) ? RegExp.$1 : ''));
} else if(uamatches('applewebkit/')) {
browser.name = 'safari';
browser.engine = 'webkit';
browser = version(browser, (test(/version\/([\d\.]+)/) ? RegExp.$1 : ''));
} else if(uamatches('mozilla/')) {
browser.engine = 'gecko';
}
return browser;
},
getLanguage : function() {
return {
direction : _c.$html.attr('dir') || win.getComputedStyle(doc.body || doc.documentElement).direction || 'ltr',
code : win.navigator.userLanguage || win.navigator.language,
};
},
getPlugins : function() {
var output = [];
if(!_c.utils.is.undefined(win.navigator.plugins)) {
for(var i = 0; i < win.navigator.plugins.length; i++) {
output.push(win.navigator.plugins[i]);
}
}
return output;
},
addHTMLClasses : function() {
var classes = [];
if(_c.browser.screen) {
classes.push('screen-' + _c.browser.screen);
}
if(!_c.utils.is.undefined(_c.browser.touch)) {
classes.push(_c.browser.touch ? 'touch' : 'notouch');
}
if(classes.diff(this.classes).length) {
_c.$html.removeClass(this.classes.join(' '));
_c.$html.addClass(classes.join(' '));
this.classes = classes;
}
}
});
});
/*!
* Chicago - Events
* Creates custom event bindings
*
* Copyright (c) 2015 Erik Nielsen
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Project home:
* https://nielse63.github.io/Chicago/
*
* Version: 1.1.0
*
*/
(function(global, factory) {
if(typeof window === "undefined" && global.window) {
global = global.window;
}
var component;
if(global.Chicago) {
component = factory(global.Chicago, global, global.document);
}
if(typeof define === 'function' && define.amd) {
define('chicago-events', ['chicago'], function() {
return component || factory(global.Chicago, global, global.document);
});
}
})(typeof window !== "undefined" ? window : this, function(_c, win, doc) {
_c.events = {
scrollend : {
latency : 150,
setup : function(data) {
data = _c.$.extend({
latency : _c.$.event.special.scrollend.latency
}, data);
var uid = _c.utils.uid('scrollend'),
timer = null,
handler = function(e) {
if(timer) {
win.clearTimeout(timer);
}
timer = win.setTimeout(function() {
timer = null;
var target = _c.$(e.target);
return target.trigger('scrollend', [{
top : target.scrollTop(),
left : target.scrollLeft(),
}]);
}, data.latency);
};
_c.$(this).data('chicago.event.scrolltop.uid', uid);
return _c.$(this).on('scroll', _c.utils.debounce(handler, 100)).data(uid, handler);
},
teardown : function() {
var uid = _c.$(this).data('chicago.event.scrolltop.uid');
_c.$(this).off('scroll', _c.$(this).data(uid));
_c.$(this).removeData(uid);
return _c.$(this).removeData('chicago.event.scrolltop.uid');
}
},
scrollstart : {
setup : function(data) {
var uid = _c.utils.uid('scrollstart'),
handler = function(e) {
e.type = 'scrollstart.chicago.dom';
_c.$(e.target).trigger('scrollstart', [{
top : _c.$(e.target).scrollTop(),
left : _c.$(e.target).scrollLeft(),
}]);
};
_c.$(this).on('scrollstart', function() {
return _c.$(this).off('scroll', handler);
});
_c.$(this).on('scrollend', function() {
return _c.$(this).on('scroll', handler).data(uid, handler);
});
_c.$(this).data('chicago.event.scrollstart.uid', uid);
return _c.$(this).on('scroll', handler).data(uid, handler);
},
teardown : function() {
var uid = _c.$(this).data('chicago.event.scrollstart.uid');
_c.$(this).off('scroll', _c.$(this).data(uid));
_c.$(this).removeData(uid);
return _c.$(this).removeData('chicago.event.scrollstart.uid');
}
},
resizeend : {
latency : 250,
setup : function(data) {
var uid = _c.utils.uid('resizeend'),
_data = _c.$.extend({
latency : _c.$.event.special.resizeend.latency
}, data),
timer,
handler = function(e) {
if(timer) {
win.clearTimeout(timer);
}
timer = win.setTimeout(function() {
timer = null;
var target = _c.$(e.target);
return target.trigger('resizeend', [{
width : target.width(),
height : target.height(),
}]);
}, _data.latency);
};
_c.$(this).data('chicago.event.resizeend.uid', uid);
_c.$(this).on('resizeend', function() {
return _c.$(this).off('resize', _c.utils.debounce(handler, 100));
});
return _c.$(this).on('resizestart', function() {
return _c.$(this).on('resize', _c.utils.debounce(handler, 100)).data(uid, handler);
});
},
teardown : function() {
var uid = _c.$(this).data('chicago.event.resizeend.uid');
_c.$(this).off('resize', _c.$(this).data(uid));
_c.$(this).removeData(uid);
return _c.$(this).removeData('chicago.event.resizeend.uid');
}
},
resizestart : {
setup : function() {
var ele = _c.$(this),
uid = _c.utils.uid('resizestart'),
handler = function(e) {
var target = _c.$(e.target);
return target.trigger('resizestart', [{
width : target.width(),
height : target.height(),
}]);
};
ele.data('chicago.event.resizestart.uid', uid);
ele.on('resizestart', function(e) {
return _c.$(this).off('resize', handler);
});
ele.on('resizeend', function(e) {
return _c.$(this).on('resize', handler).data(uid, handler);
});
return ele.on('resize', handler).data(uid, handler);
},
teardown : function() {
var uid = _c.$(this).data('chicago.event.resizestart.uid');
_c.$(this).off('resize', _c.$(this).data(uid));
_c.$(this).removeData(uid);
return _c.$(this).removeData('chicago.event.resizestart.uid');
}
},
transition : {
defaults : {
start : function(property) {},
progress : function(property, duration, value) {},
complete : function(property) {},
},
setup : function(data, namespaces, eventHandle) {
var uid = _c.utils.uid('transition'),
ele = _c.$(this),
keys = {
uid : 'chicago.event.transition.uid',
base : 'chicago.event.' + uid,
event : 'chicago.event.' + uid + '.event',
info : 'chicago.event.' + uid + '.info',
},
intervalCount = 15,
_event = {
initalValues : {}
},
tracker = _c.win.performace ? _c.win.performace.now : _c.utils.now;
data = _c.extend({}, _c.$.event.special.transition.defaults, data);
function getTransitionData() {
var info = ele.data(keys.info);
if(info) {
return info;
}
info = {};
var transition = ele.css('transition').split(',');
for(var i = 0; i < transition.length; i++) {
var values = transition[i].trim().split(' '),
property = values[0];
if(!info.hasOwnProperty(property)) {
info[property] = {
duration : _c.utils.stringToMilliseconds(values[1]),
function : values[2],
delay : _c.utils.stringToMilliseconds(values[3]),
value : _c.utils.getCSSValue(ele, property)
};
}
}
ele.data(keys.info, info);
return info;
}
function removeDataForProperty(property) {
var keyBase = keys.base + '.' + property,
_keys = {
bindStart : keyBase + '.did.bind.start',
didStart : keyBase + '.did.start',
didStartAt : keyBase + '.did.start.at',
progressValue : keyBase + '.progress.value'
};
for(var key in _keys) {
var string = _keys[key];
ele.removeData(string);
}
}
function setInitialValues(property) {
if(!property) {
for(var prop in getTransitionData()) {
_event.initalValues[prop] = _c.utils.getCSSValue(ele, prop);
}
} else {
_event.initalValues[property] = _c.utils.getCSSValue(ele, property);
}
}
ele.data(keys.uid, uid);
if(!ele.data(keys.event)) {
var did = {
begin : {},
end : {}
},
diff = 0;
function completeCallback(property, cssValue, elapsedTime) {
diff = 0;
did.end[property] = {
time : tracker()
};
setInitialValues(property);
delete did.begin[property];
data.complete.call(ele[0], property, cssValue, elapsedTime);
ele.trigger('transition');
}
setInitialValues();
ele.on(_c.support.transition.end, function(e) {
var property = e.originalEvent.propertyName,
cssValue = _c.utils.getCSSValue(ele, property),
info = getTransitionData(),
elapsedTime = info[property].duration;
completeCallback(property, cssValue, elapsedTime);
});
_event.interval = win.setInterval(function() {
info = getTransitionData();
for(var property in info) {
var initialValue = _event.initalValues[property],
currentValue = _c.utils.getCSSValue(ele, property),
obj = info[property];
if(diff && did.begin[property]) {
diff = tracker() - did.begin[property].time;
}
if(!did.begin[property] && currentValue !== initialValue) {
did.begin[property] = {
time : tracker()
};
if(did.end[property]) {
delete did.end[property];
}
data.start.call(ele[0], property, initialValue);
} else if(did.begin[property] && !did.end[property] && diff < (obj.duration + 1)) {
data.progress.call(ele[0], property, currentValue, diff);
}
}
}, intervalCount);
ele.data(keys.event, _event);
}
return true;
},
teardown : function() {
var uid = _c.$(this).data('chicago.event.transition.uid'),
keys = {
uid : 'chicago.event.transition.uid',
base : 'chicago.event.' + uid,
event : 'chicago.event.' + uid + '.event',
info : 'chicago.event.' + uid + '.info',
};
for(var k in keys) {
var key = keys[k],
value = _c.$(this).data(key);
if(k === 'event' && value && value.interval) {
win.clearInterval(value.interval);
}
if(value) {
_c.$(this).removeData(key);
}
}
}
},
animation : {
defaults : {
start : function(name) {},
iteration : function(name, iterationCount) {},
complete : function(name, elapsedTime) {},
},
setup : function(data, namespaces, eventHandle) {
var uid = _c.utils.uid('animation'),
ele = _c.$(this),
keys = {
uid : 'chicago.event.animation.uid',
base : 'chicago.event.' + uid,
iterations : 'chicago.event.' + uid + '.iterations',
event : 'chicago.event.' + uid + '.event',
},
intervalCount = 15;
data = _c.$.extend({}, _c.$.event.special.animation.defaults, data);
ele.data(keys.uid, uid);
if(!ele.data(keys.event)) {
function iterationHandler(e) {
var name = e.originalEvent.animationName,
count = ele.data(keys.iterations);
count++;
ele.data(keys.iterations, count);
data.iteration.call(ele, name, count);
}
ele.data(keys.event, {
start : ele.on(_c.support.animation.start, function(e) {
data.start.call(ele, e.originalEvent.animationName);
ele.data(keys.iterations, 0);
}),
iteration : ele.on(_c.support.animation.iteration, iterationHandler),
end : ele.on(_c.support.animation.end, function(e) {
iterationHandler(e);
var name = e.originalEvent.animationName;
var time = _c.utils.stringToMilliseconds(e.originalEvent.elapsedTime);
data.complete.call(ele, name, time);
ele.trigger('animation');
})
});
}
return true;
},
teardown : function() {
var uid = _c.$(this).data('chicago.event.animation.uid'),
keys = {
uid : 'chicago.event.animation.uid',
base : 'chicago.event.' + uid,
iterations : 'chicago.event.' + uid + '.iterations',
event : 'chicago.event.' + uid + '.event',
};
for(var k in keys) {
var key = keys[k],
value = _c.$(this).data(key);
if(value) {
_c.$(this).removeData(key);
}
}
}
},
swipe : {
setup : function(data) {
var uid = _c.utils.uid('scrollstart'),
target = _c.$(this),
events = {
down : 'touchstart MSPointerDown pointerdown mousedown',
move : 'touchmove MSPointerMove pointermove mousemove',
up : 'touchend MSPointerUp pointerup mouseup mouseleave'
},
memory = {
down : {
x : 0,
y : 0,
},
up : {
x : 0,
y : 0,
},
};
function swipeDirection(x1, x2, y1, y2) {
return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'left' : 'right') : (y1 - y2 > 0 ? 'up' : 'down');
}
function unbind(string, handler) {
string.split(' ').forEach(function(evt) {
target.off(evt, handler);
});
}
function downHandler(e) {
memory.down = {
x : e.screenX,
y : e.screenY,
};
target.on(events.move, moveHanlder);
}
function moveHanlder(e) {
unbind(events.up, upHandler);
target.one(events.up, upHandler);
}
function upHandler(e) {
unbind(events.move, moveHanlder);
unbind(events.up, upHandler);
memory.up = {
x : e.screenX,
y : e.screenY,
};
var dir = swipeDirection(memory.down.x, memory.up.x, memory.down.y, memory.up.y);
target.trigger('swipe', [dir]);
target.trigger('swipe' + dir);
}
target.on(events.down, downHandler);
_c.$(this).data('chicago.event.swipe.uid', uid).data(uid, downHandler);
},
teardown : function() {
var uid = _c.$(this).data('chicago.event.scrollstart.uid');
return _c.$(this).removeData(uid).removeData('chicago.event.scrollstart.uid');
}
},
};
(function() {
for(var k in _c.events) {
var v = _c.events[k];
if(_c.utils.is.object(v)) {
_c.$.event.special[k] = v;
var fn = function(options, callback) {
return this.each(function() {
return _c.$(this).on(k, options, callback);
});
};
_c.$.fn[k] = fn;
}
}
})();
});