build/hilo.js
// # Hilo
// `0.1.0-pre-dev-beta-10`<br/>
// Built on: 2015-05-06<br/>
// Project started before 2 years and 28 months and 6 days<br/>
// http://erikroyall.github.com/hilo<br/>
// Copyright (c) 2013 Erik Royall<br/>
// Licensed under MIT (see LICENSE-MIT)
(function (A, M, D) {
/* Register Hilo as an AMD module */
/*globals YUI: false, module: false, define: false*/
if (typeof module !== "undefined" && module.exports) {
module.exports = D;
} else if (typeof define === "function" && define.amd) {
define(D);
} else if (typeof YUI === "function") {
YUI.add(A, D);
} else {
M[A] = D();
}
}("Hilo", this, function () {
/*jshint -W083, -W064, -W061, -W030*/
/* JSHint escapes:
- W083 - Don't make function within a loop (Evts)
- W064 - Eval can be harmful (JSON)
- W064 - Missing new prefix when invoking constructor (Sizzle)
- W030 - Saw an expression (Sizzle, Me) */
"use strict";
var hilo /* Public API */
/* Used to measure performace (Hilo.perf) */
, start
/* References to browser objects */
, win = window // Reference to window
, doc = win.document // Reference to document
/* Used for storing detected features */
, detected
/* Key mappings (Hilo.keys) */
, key
/*Array of callbacks to be exec.ed on DOMReady */
, callbacks = [] // Array of functions to be executed on DOMReady
/* Private Selector Function */
, select
/* Feature Detection (Hilo.feature) */
, feature
/* Main AJAX function (Hilo.ajax) */
, hiloAjax
/* hasOwnProperty helper */
, own = function (obj, prop) {
return obj.hasOwnProperty(prop);
}
/* Loop Variable */
, _i;
/* Start performace testing */
start = new Date().getTime();
// ## Feature Detection
feature = (function () {
var c = function (tagName) {
return doc.createElement(tagName);
}
, i = c("input")
, d = c("div")
, cn = c("canvas")
, fr = c("iframe")
, is = function (i, attr, val) {
return !!(i.setAttribute (attr, val));
}
, a = c("audio")
, s = c("span")
, v = c("video")
, xr = new XMLHttpRequest();
return {
// addEventListener()
addEventListener: (function () {
return typeof win.addEventListener === "function";
}()),
// Application Cache (or Offline Web Apps)
applicationCache: (function () {
return !!win.applicationCache;
}()),
// Audio (tag)
audio: (function () {
return !!a.canPlayType;
}()),
// Preload audio (hmm.. background music?)
audioPreload: (function () {
return "preload" in a;
}()),
// Audio Types
audioType: {
// MP3 audio format
mp3: (function () {
return !!(a.canPlayType && a.canPlayType("audio/mpeg;").replace(/no/, ""));
}()),
// Vorbis audio format
vorbis: (function () {
return !!(a.canPlayType && a.canPlayType("audio/ogg; codecs='vorbis'").replace(/no/, ""));
}()),
// MS WAV audio format
wav: (function () {
return !!(a.canPlayType && a.canPlayType("audio/wav; codecs='1'").replace(/no/, ""));
}()),
// AAC audio format
aac: (function () {
return !!(a.canPlayType && a.canPlayType("audio/mp4; codecs='mp4a.40.2'").replace(/no/, ""));
}())
},
// Canvas API
canvas: (function () {
return !!cn.getContext;
}()),
// Canvas Text
canvasText: (function () {
return !!cn.getContext && typeof cn.getContext("2d").fillText === "function";
}()),
// classList prop. in HTMLElement
classList: (function () {
return "classList" in s;
}()),
// Command
command: (function () {
return "type" in c("command");
}()),
// Form Constraint Validation
consval: (function () {
return "noValidate" in c("form");
}()),
// contentEditable attribute
contentEditable: (function () {
return "isContentEditable" in s;
}()),
// Datalist (tag)
datalist: (function () {
return "options" in c("datalist");
}()),
// Details (tag)
details: (function () {
return "open" in c("details");
}()),
// Drag & Drop
dragdrop: (function () {
return "draggable" in s;
}()),
// ECMAScript 6
es6: (function () {
return typeof String.prototype.contains === "function";
}()),
// File system API
fileapi: (function () {
return typeof FileReader !== "undefined";
}()),
// 5th Generation Rendering Engine
gen5: (function () {
return parseInt(win.navigator.appVersion, 10) === 5;
}()),
// Geolocation
geolocation: (function () {
return "geolocation" in win.navigator;
}()),
// window.getSelection() method
getSelection: (function () {
return typeof win.getSelection === "function";
}()),
// History API
history: (function () {
return !!(win.history && history.pushState);
}()),
// IFrame
iframe: {
sandbox: (function () {
return "sandbox" in fr;
}()),
srdoc: (function () {
return "srcdoc" in fr;
}())
},
// IndexedDB (use this instead of WebSQL)
indexeddb: (function () {
return !!(win.indexedDB && win.IDBKeyRange && win.IDBTransaction);
}()),
// Input
input: {
// Input Auto Focus
autofocus: (function () {
return "autofocus" in i;
}()),
// Placeholder
placeholder: (function () {
return "placeholder" in i;
}()),
// Input Types (they are pretty self-explanatory)
type: {
color: (function () {
is(i, "type", "color");
return i.type !== "text";
}()),
date: (function () {
is(i, "type", "date");
return i.type !== "text";
}()),
datetime: (function () {
is(i, "type", "datetime");
return i.type !== "text";
}()),
datetimeLocal: (function () {
is(i, "type", "datetime-local");
return i.type !== "text";
}()),
email: (function () {
is(i, "type", "email");
return i.type !== "text";
}()),
month: (function () {
is(i, "type", "month");
return i.type !== "text";
}()),
number: (function () {
is(i, "type", "number");
return i.type !== "text";
}()),
range: (function () {
is(i, "type", "range");
return i.type !== "text";
}()),
search: (function () {
is(i, "type", "search");
return i.type !== "text";
}()),
tel: (function () {
is(i, "type", "tel");
return i.type !== "text";
}()),
time: (function () {
is(i, "type", "time");
return i.type !== "text";
}()),
week: (function () {
is(i, "type", "week");
return i.type !== "text";
}())
}
},
// Local Storage
localStorage: (function () {
try {
return "localStorage" in win && win["localStorage"] !== null && !!win.localStorage.setItem;
} catch(e){
return false;
}
}()),
// Meter (tag)
meter: (function () {
return "value" in c("meter");
}()),
// Microdata
microdata: (function () {
return "getItems" in doc;
}()),
// Offline (App Cache)
offline: (function () {
return !!win.applicationCache;
}()),
// Output (tag)
output: (function () {
return "value" in c("output");
}()),
// Progress (tag)
progress: (function () {
return "value" in c("progress");
}()),
// querySelector & querySelectorAll
qsa: (function () {
return "querySelector" in doc && "querySelectorAll" in doc;
}()),
// CSS3 Selectors in querySelectorAll
qsa3: (function () {
try {
return doc.querySelectorAll(":root").length > 0;
} catch (e) {
return false;
}
}()),
// requestAnimationFrame
requestAnimationFrame: (function () {
if (typeof requestAnimationFrame === "function") {
return true;
} else if (typeof msRequestAnimationFrame === "function") {
return "ms";
} else if (typeof webkitRequestAnimationFrame === "function") {
return "webkit";
} else if (typeof mozRequestAnimationFrame === "function") {
return "moz";
} else {
return false;
}
}()),
// Server-sent Events
serverEvt: (function () {
return typeof EventSource !== "undefined";
}()),
// Session Storage
sessionStorage: (function () {
try {
return "sessionStorage" in win && win["sessionStorage"] !== null;
} catch(e) {
return false;
}
}()),
// Modal Dialog (showModalDialog)
showModalDialog: (function () {
return typeof win.showModalDialog === "function";
}()),
// SVG (Scalable Vector Graphics)
svg: (function () {
return !!(doc.createElementNS && doc.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGRect);
}()),
// SVG in text/html
svginhtml:(function () {
d.innerHTML = "<svg></svg>";
return !!(win.SVGSVGElement && d.firstChild instanceof win.SVGSVGElement);
}()),
// Template (tag)
template: (function () {
return "content" in c("template");
}()),
// Time (tag)
time: (function () {
return "datetime" in c("time");
}()),
// Undo (not just Ctrl + Z)
undo: (function () {
return typeof UndoManager !== "undefined";
}()),
// Video
video: (function () {
try {
return !!v.canPlayType;
} catch (e) {
return false;
}
}()),
// Video Captions
videoCaptions: (function () {
return "src" in c("track");
}()),
// Video Formats
videoFormats: {
// H264 Video Format (MP4)
h264: (function () {
try {
return v.canPlayType("video/mp4; codecs='avc1.42E01E, mp4a.40.2'");
} catch (e) {
return false;
}
}()),
// WebM Video Format
webm: (function () {
try {
return v.canPlayType("video/webm; codecs='vp8, vorbis'");
} catch (e) {
return false;
}
}()),
// OGG Theora Video Format
ogg: (function () {
try {
return v.canPlayType("video/ogg; codecs='theora, vorbis'");
} catch (e) {
return false;
}
}())
},
// Video Poster
videoPoster: (function () {
return "poster" in c("video");
}()),
// Web Audio API (NOT the <audio> tag)
webAudio: (function () {
// return !!(win.webkitAudioContext || win.AudioContext);
if (win.AudioContext) {
return true;
} else if (win.webkitAudioContext) {
return "webkit";
}
return false;
}()),
// WebSockets
webSockets: (function () {
return !!win.webSocket;
}()),
// WebSQL (a deprecated specification; use IndexedDB instead)
websql: (function () {
return !!win.openDatabase;
}()),
// Web Workers
webWorkers: (function () {
return !!win.Worker;
}()),
// Widgets
widgets: (function () {
return typeof widget !== "undefined";
}()),
// Cross-document messaging
xdocmsg: (function () {
return !!win.postMessage;
}()),
// XML HTTP Request
xhr: {
// Cross-domain requests
xdr: (function () {
return "withCredentials" in xr;
}()),
// Send as form data
formdata: (function () {
return !!win.FormData;
}()),
// Upload progress events
upe: (function () {
return "upload" in xr;
}())
}
};
}());
// ## Browser, Engine, Platform Detection
detected = (function () {
var engine
, browser
, system
, ua = win.navigator.userAgent
, safariVersion
, p;
// Browser
browser = {
ie: 0,
firefox: 0,
safari: 0,
konq: 0,
opera: 0,
chrome: 0,
// Specific Version
ver: null
};
// System
system = {
win: false,
mac: false,
x11: false,
/* Mobile Devices */
iphone: false,
ipod: false,
ipad: false,
ios: false,
android: false,
nokiaN: false,
winMobile: false,
/* Game Consoles */
wii: false,
ps: false
};
// Redering engine
engine = {
ie: 0,
gecko: 0,
webkit: 0,
khtml: 0,
opera: 0,
/* Complete version*/
ver: null
};
if(window.opera) {
engine.ver = browser.ver = window.opera.version();
engine.opera = browser.opera = parseFloat(engine.ver);
} else if (/AppleWebKit\/(\S+)/.test(ua)) {
engine.ver = RegExp.$1;
engine.webkit = parseFloat(engine.ver);
/* Figures out if chrome or Safari */
if (/Chrome\/(\S+)/.test(ua)) {
browser.ver = RegExp.$1;
browser.chrome = parseFloat(browser.ver);
} else if (/Version\/(\S+)/.test(ua)) {
browser.ver = RegExp.$1;
browser.safari = parseFloat(browser.ver);
} else {
/* Approximate version */
safariVersion = 1;
if (engine.webkit < 100) {
safariVersion = 1;
} else if (engine.webkit < 312) {
safariVersion = 1.2;
} else if (engine.webkit < 412) {
safariVersion = 1.3;
} else {
safariVersion = 2;
}
browser.safari = browser.ver = safariVersion;
}
} else if (/KHTML\/(\S+)/.test(ua) || /Konqueror\/([^;]+)/.test(ua)) {
engine.ver = browser.ver = RegExp.$1;
engine.khtml = browser.konq = parseFloat(engine.ver);
} else if (/rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)) {
engine.ver = RegExp.$1;
engine.gecko = parseFloat(engine.ver);
/* Determine if it's firefox */
if (/Firefox\/(\S+)/.test(ua)) {
browser.ver = RegExp.$1;
browser.firefox = parseFloat(browser.ver);
}
} else if (/MSIE ([^;]+)/.test(ua)) {
engine.ver = browser.ver = RegExp.$1;
engine.ie = browser.ie = parseFloat(engine.ver);
}
/* Detect browsers */
browser.ie = engine.ie;
browser.opera = engine.opera;
/* Detect platform */
p = navigator.platform;
system.win = p.indexOf("Win") === 0;
system.mac = p.indexOf("Mac") === 0;
system.x11 = (p === "X11") || (p.indexOf("Linux") === 0);
/* Detecting Windows OSs */
if (system.win) {
if (/Win(?:dows )?([^do]{2})\s?(\d+\.\d+)?/.test(ua)) {
if (RegExp.$1 === "NT") {
switch(RegExp["$2"]) {
case "5.0":
system.win = "2000";
break;
case "5.1":
system.win = "XP";
break;
case "6.0":
system.win = "Vista";
break;
case "6.1":
system.win = "7";
break;
default:
system.win = "NT";
break;
}
} else if (RegExp.$1 === "9x") {
system.win = "ME";
} else {
system.win = RegExp.$1;
}
}
}
/* Mobile Devices */
system.iphone = ua.indexOf("iPhone") > -1;
system.ipod = ua.indexOf("iPod") > -1;
system.ipad = ua.indexOf("iPad") > -1;
system.nokiaN = ua.indexOf("NokiaN") > -1;
/* Windows Mobile */
if (system.win === "CE") {
system.winMobile = system.win;
} else if (system.win === "Ph") {
if (/Windows Phone OS(\d+.\d+)/.test(ua)) {
system.win = "Phone";
system.winMobile = parseFloat(RegExp.$1);
}
}
/* Determine iOS Version */
if (system.mac && ua.indexOf("Mobile") > -1) {
if (/CPU (?:iPhone )?OS (\d+_\d+)/.test(ua)) {
system.ios = parseFloat(RegExp.$1.replace("_", "."));
} else {
system.ios = 2; // Can't really detect - so guess
}
}
/* Determine Android Version */
if (/Android (\d+\.\d+)/.test(ua)) {
system.android = parseFloat(RegExp.$1);
}
/* Gaming Consoles */
system.wii = ua.indexOf("Wii") > -1;
system.ps = /playstation/i.test(ua);
/* Name and Version */
if (system.win) {
system.name = "Windows";
system.version = system.win;
} else if (system.mac) {
system.name = "Mac";
} else if (system.x11) {
system.name = "Linux";
} else {
system.name = "Some other";
}
/* Engines */
if (browser.ie) {
browser.name = "IE";
browser.version = browser.ie;
} else if (browser.chrome) {
browser.name = "Chrome";
browser.version = browser.chrome;
} else if (browser.safari) {
browser.name = "Safari";
browser.version = browser.safari;
} else if (browser.konq) {
browser.name = "Konqueror";
browser.version = browser.konq;
} else if (browser.opera) {
browser.name = "Opera";
browser.version = browser.opera;
} else if (browser.firefox) {
browser.name = "Firefox";
browser.version = browser.firefox;
}
/* return them */
return {
engine: engine,
browser: browser,
system: system
};
}());
// --------------------------------------------------
// JSON
// --------------------------------------------------
/*!
* JSON Parser (Public Domain)
* by Douglas Crockford
* http://javascript.crockford.com/
*/
// Create a json object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.
var json = {};
(function () {
if (typeof window.JSON === "object" && typeof window.JSON.parse === "function") {
json = window.JSON;
return;
}
function f (n) {
// Format integers to have at least two digits.
return n < 10 ? "0" + n : n;
}
if (typeof Date.prototype.tojson !== "function") {
Date.prototype.tojson = function () {
return isFinite(this.valueOf()) ?
this.getUTCFullYear() + "-" +
f(this.getUTCMonth() + 1) + "-" +
f(this.getUTCDate()) + "T" +
f(this.getUTCHours()) + ":" +
f(this.getUTCMinutes()) + ":" +
f(this.getUTCSeconds()) + "Z"
: null;
};
String.prototype.tojson =
Number.prototype.tojson =
Boolean.prototype.tojson = function () {
return this.valueOf();
};
}
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
gap,
indent,
meta = { // table of character substitutions
"\b": "\\b",
"\t": "\\t",
"\n": "\\n",
"\f": "\\f",
"\r": "\\r",
"\"" : "\\\"",
"\\": "\\\\"
},
rep;
function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
escapable.lastIndex = 0;
return escapable.test(string) ? "\"" + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === "string" ? c
: "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
}) + "\"" : "\"" + string + "\"";
}
function str(key, holder) {
// Produce a string from holder[key].
var i, // The loop counter.
k, // The member key.
v, // The member value.
length,
mind = gap,
partial,
value = holder[key];
// If the value has a tojson method, call it to obtain a replacement value.
if (value && typeof value === "object" &&
typeof value.tojson === "function") {
value = value.tojson(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === "function") {
value = rep.call(holder, key, value);
}
// What happens next depends on the value"s type.
switch (typeof value) {
case "string":
return quote(value);
case "number":
// json numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : "null";
case "boolean":
case "null":
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce "null". The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is "object", we might be dealing with an object or an array or
// null.
case "object":
// Due to a specification blunder in ECMAScript, typeof null is "object",
// so watch out for that case.
if (!value) {
return "null";
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === "[object Array]") {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-json values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || "null";
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0 ? "[]"
: gap ? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]"
: "[" + partial.join(",") + "]";
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === "object") {
length = rep.length;
for (i = 0; i < length; i += 1) {
if (typeof rep[i] === "string") {
k = rep[i];
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ": " : ":") + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ": " : ":") + v);
}
}
}
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0 ? "{}"
: gap ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}"
: "{" + partial.join(",") + "}";
gap = mind;
return v;
}
}
// If the json object does not yet have a stringify method, give it one.
if (typeof json.stringify !== "function") {
json.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a json text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i;
gap = "";
indent = "";
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === "number") {
for (i = 0; i < space; i += 1) {
indent += " ";
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === "string") {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== "function" &&
(typeof replacer !== "object" ||
typeof replacer.length !== "number")) {
throw new Error("json.stringify");
}
// Make a fake root object containing our value under the key of "".
// Return the result of stringifying the value.
return str("", {"": value});
};
}
// If the json object does not yet have a parse method, give it one.
if (typeof json.parse !== "function") {
json.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid json text.
var j;
function walk(holder, key) {
// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
var k, v, value = holder[key];
if (value && typeof value === "object") {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
text = String(text);
cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return "\\u" +
("0000" + a.charCodeAt(0).toString(16)).slice(-4);
});
}
// In the second stage, we run the text against regular expressions that look
// for non-json patterns. We are especially concerned with "()" and "new"
// because they can cause invocation, and "=" because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the json backslash pairs with "@" (a non-json character). Second, we
// replace all simple value tokens with "]" characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or "]" or
// "," or ":" or "{" or "}". If that is so, then the text is safe for eval.
if (/^[\],:{}\s]*$/
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
.replace(/(?:^|:|,)(?:\s*\[)+/g, ""))) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The "{" operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval("(" + text + ")");
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === "function" ? walk({"": j}, "") : j;
}
// If the text is not json parseable, then a SyntaxError is thrown.
throw new SyntaxError("json.parse");
};
}
}());
// --------------------------------------------------
// Utilities
// --------------------------------------------------
var boxedString = Object("a")
, splitString = boxedString[0] !== "a" || !(0 in boxedString);
var toObject = function toObject (o) {
if (typeof o === "undefined") { // this matches both null and undefined
throw new TypeError("can't convert "+o+" to object");
}
return Object(o);
};
var toInteger = function toInteger (value) {
var number = +value;
if (Number.isNaN(number)) {
return 0;
}
if (number === 0 || !isFinite(number)) {
return number;
}
return sign(number) * Math.floor(Math.abs(number));
};
var isPrimitive = function isPrimitive(input) {
var type = typeof input;
return (
input === null ||
type === "undefined" ||
type === "boolean" ||
type === "number" ||
type === "string"
);
};
var toPrimitive = function toPrimitive (input) {
var val, valueOf, toString;
if (isPrimitive(input)) {
return input;
}
valueOf = input.valueOf;
if (typeof valueOf === "function") {
val = valueOf.call(input);
if (isPrimitive(val)) {
return val;
}
}
toString = input.toString;
if (typeof toString === "function") {
val = toString.call(input);
if (isPrimitive(val)) {
return val;
}
}
throw new TypeError();
};
var sign = function sign(value) {
var number = +value;
if (number === 0) {
return number;
}
if (Number.isNaN(number)) {
return number;
}
return number < 0 ? -1 : 1;
};
// --------------------------------------------------
// Array Utilities
// --------------------------------------------------
// Executes a function on each of the element
// in the array
var each = function each (arr, fn, thisRef) {
var _i, _l;
// Use Array.prototype.forEach if available
if (Array.prototype.forEach) {
return Array.prototype.forEach.call(arr, fn);
}
// Throw an error if array and function are not provided
if (!(arr && fn)) {
throw new Error (
"Not enough arguments provided for each()"
);
}
// Make the this variable the array itself if not provided
thisRef = thisRef || arr;
for (_i = 0, _l = arr.length; _i < _l; _i += 1) {
fn.call(thisRef, arr[_i]);
}
};
// Iterate over an object and execute a function on each 'value'
// of it
var forIn = function forIn (obj, fn, thisRef) {
var _i;
// Throw an error if object and function are not provided
if (!(obj && fn)) {
throw new Error (
"Not enough arguments provided for forIn()"
);
}
// Make the given object as the `this` value if one is not provided
thisRef = thisRef || obj;
for (_i in obj) {
if (own(obj, _i)) {
fn.call(thisRef, _i);
}
}
};
// Append all the properties of the second object to the first
var extend = function extend (obj, ext) {
var _i;
// Throw an error if object and extension are not provided
if (!(obj && ext)) {
throw new Error (
"Not enough arguments provided for extend()"
);
}
for (_i in ext) {
if (own(ext, _i)) {
obj[_i] = ext[_i];
}
}
return obj;
};
// Check if every element in the object passes the test
var every = function every (o, fun) {
var t, len, thisp, _i;
if (o === null) {
throw new TypeError();
}
t = Object(o);
len = t.length >>> 0;
if (typeof fun !== "function") {
throw new TypeError();
}
thisp = arguments[1];
for (_i = 0; _i < len; _i++) {
if (_i in t && !fun.call(thisp, t[_i], _i, t)) {
return false;
}
}
return true;
};
// --------------------------------------------------
// String Utilities
// --------------------------------------------------
// Remove whitespace at the start and end of a string
var trim = function trim (str) {
var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" +
"\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
"\u2029\uFEFF";
ws = "[" + ws + "]";
var trimBeginRegexp = new RegExp("^" + ws + ws + "*"),
trimEndRegexp = new RegExp(ws + ws + "*$");
if (str === void 0 || str === null) {
throw new TypeError("can't convert "+ str +" to object");
}
return String(str).replace(trimBeginRegexp, "").replace(trimEndRegexp, "");
};
// Check if a string contains another string in it
var contains = function contains (haystack, needle) {
var position = arguments[1];
return haystack.indexOf(needle, position) !== -1;
};
var indexOf = function indexOf(arr, sought /*, fromIndex */ ) {
var self = splitString && arr.toString() === "[object String]" ?
this.split("") :
toObject(this)
, length = self.length >>> 0;
if (!length) {
return -1;
}
var i = 0;
if (arguments.length > 1) {
i = toInteger(arguments[1]);
}
// handle negative indices
i = i >= 0 ? i : Math.max(0, length + i);
for (; i < length; i++) {
if (i in self && self[i] === sought) {
return i;
}
}
return -1;
};
// --------------------------------------------------
// Core Library
// --------------------------------------------------
// If there is a select function (sizzle), use it
// or use the native querySelectorAll()
select = select || function (selector, root) {
// Set root to given root or document
root = root || doc;
// Use the native querySelectorAll
return root.querySelectorAll(selector);
};
/**
* The main Hilo Object / function
*
* @module Hilo
* @static
* @class hilo
* @author Erik Royall
*/
hilo = function (input, root, en) {
if (typeof input === "undefined") {
// It's better than not returning anything
return win.Hilo;
} else if (typeof input === "number") {
return new NumberObject(input);
} else if (typeof input === "string") {
if (trim(input) === "") {
// Can't pass empty string to querySelectorAll()
return new Dom({length:0});
}
// Most common, return based on selector
return new Dom(select(input, root, en), input);
} else if (typeof input === "function") {
if (document.readyState === "complete") {
input();
} else {
callbacks.push(input);
}
// Allows to immediately start executing more code
// It's better than not returning anything!
return win.Hilo;
} else if (input.length) { // DOM Node List | Hilo DOM Object
return new Dom(input);
} else { // DOM Node
input = [input];
return new Dom(input);
}
};
// Enable Selector Caching
hilo.temp = {};
// Version info
hilo.version = "0.1.0-pre-dev-beta-9";
// Detections
hilo.feature = feature;
hilo.browser = detected.browser;
hilo.engine = detected.engine;
hilo.platform = detected.system;
// ES Utils
extend(hilo, {
each: each,
extend: extend,
every: every,
trim: trim,
contains: contains,
indexOf: indexOf,
isPrimitive: isPrimitive,
toObject: toObject,
toInteger: toInteger,
toPrimitive: toPrimitive
});
// JSON
hilo.json = {
parse: json.parse,
stringify: json.stringify
};
// Legacy
hilo.legacy = typeof sizzle === "function";
// --------------------------------------------------
// Testing
// --------------------------------------------------
extend(hilo, {
/**
* Public test function
*
* @for hilo
* @method test
* @param con
* @return {Test}
* @example
* <div class="code"><pre class="prettyprint">
* $.test("hello");
* </pre></div>
*
* <div class="code"><pre class="prettyprint">
* $.test({
* name: "Erik Royall",
* age: 14,
* projects: ["hilo", "helio"]
* });
* </pre></div>
* @since 0.1.0
*/
test: function (con) {
return new Test(con);
}
});
/**
* Main Test Class
*
* @constructor
* @class Test
* @param {Any} con To compare
* @param {boolean} neg Whether to inverse the result
* @return void
* @example
* <div class="code"><pre class="prettyprint">
* new Test({});
* new Test("Hilo", true);
* </pre></div>
* @since 0.1.0
*/
function Test (con, neg) {
this.con = con;
if (neg) {
this.neg = true;
}
}
// --------------------------------------------------
// Test Comparisions
// --------------------------------------------------
extend(Test.prototype, {
/**
* Test if equal
*
* @for Test
* @method ifEquals
* @param {Any} tw Comparision object
* @return {boolean}
* @example
* <div class="code"><pre class="prettyprint">
* var isIt = $.test(hilo.version).ifEquals("v0.1.0-pre-dev-beta-9");
* </pre></div>
* @since 0.1.0
*/
ifEquals: function (tw) {
var val = this.con === tw;
return this.neg ? !val : val;
},
/**
* Test if contains
*
* @for Test
* @method ifContains
* @param {Any} tw Comparision object
* @return {boolean}
* @example
* <div class="code"><pre class="prettyprint">
* var isHiloBeta = $.test(hilo.version).ifContains("beta");
* </pre></div>
* @since 0.1.0
*/
ifContains: function (tw) {
var ifString = this.con.split(tw).length === 1 ? false : true;
if (typeof tw === "string" && typeof this.con === "object" && this.con.length) {
} else if (typeof tw === "string" && typeof this.con === "string") {
return this.neg ? !ifString : ifString;
}
},
/**
* Inverse a test
*
* @for Test
* @method not
* @return {Test}
* @example
* <div class="code"><pre class="prettyprint">
* $("Hilo.js").not().ifEquals("Hilo");
* </pre></div>
* @since 0.1.0
*/
not: function () {
return new Test(this, true);
}
});
//
// ** `hiloAjax` **
//
// Makes an AJAX request
//
// Param:
//
// `config // {Object} Configuration Options`
//
// For the list of all config opts, see below.
//
// Example:
//
// ```
// Hilo.ajax({
// url: "requestHandler.php",
// success: function (data, xhr) {
// console.log(data, xhr);
// },
// method: "GET"
// });
// ```
//
hiloAjax = function (config) {
// ```
// config.
// method // HTTP Method (default: "POST")
// url // The file to send request
// async // Whether to perform an asynchronous request (default: true)
// data // Data to be sent to the server
// response // HTTP Response type
// callback // function to be executed on readystatechange
// complete // {Function} (xhr.readyState = 4) To be triggered when request is complete
// error // {Function} To be triggered when request fails with an error
// timeout // {Function} To be triggered when request time's out
// success // {Function} (200) To be triggered when request is successfully made (Commonly registered event)
// notfound // {Function} (404) To be triggered when there has been a 4oh4 NotFound exception
// forbidden // {Function} (403) To be triggered when making the request is forbidden
// username // {String} Username to be provided, if authentication is required
// password // {String} Password to be provided, if...
// contentType // HTTP Content-Type
// ```
var xhr;
/* Use the `XMLHttpRequest` object if available
or use `ActiveXObject` */
if (win.XMLHttpRequest) {
xhr = new win.XMLHttpRequest();
} else if (win.ActiveXObject) {
xhr = new win.ActiveXObject("Microsoft.XMLHTTP");
}
/* Throw an error if a URL hasn't been provided
Seriously, wth can this do without a target url? */
if (!config.url) {
throw new TypeError("url parameter not provided to hilo.ajax");
}
/* Perform an asynchronous request by default */
config.async = config.async || true;
/* Authentication params */
config.username = config.username || null;
config.password = config.password || null;
/* contentType.. "application/x-www-form-urlencoded; charset=UTF-8" is preferred */
config.contentType = config.contentType || "application/x-www-form-urlencoded; charset=UTF-8";
xhr.onreadystatechange = function () {
if (config.callback) {
config.callback(xhr);
}
if (xhr.readyState === 4) { // Request is completed
typeof config.complete ? config.complete.call(this, xhr) : null;
switch (xhr.status) {
case 200: // Success
typeof config.success ? config.success.call(this, xhr) : null;
typeof config.error ? config.error.call(this, xhr) : null;
break;
case 404: // Not Found
typeof config.notfound ? config.notfound.call(this, xhr) : null;
typeof config.error ? config.error.call(this, xhr) : null;
break;
case 403: // Forbidden
typeof config.forbidden ? config.forbidden.call(this, xhr) : null;
typeof config.error ? config.error.call(this, xhr) : null;
break;
default: // Some Error
typeof config.error ? config.error.call(this, xhr) : null;
break;
}
} else if (xhr.readyState === 3) {
typeof config.sent ? config.sent.call(this, xhr) : null;
}
};
/* Run this function when the request has timed out :'( */
xhr.timeout = config.timeout;
/* Open the request (Could've been more verbose) */
xhr.open(
config.method.trim().toUpperCase() || "POST",
config.url,
config.async,
config.username,
config.password
);
/* If config.data is an object, JSON.encode it */
if (typeof config.data === "object") {
config.data = JSON.encode(config.data);
}
/* Lauch the request */
xhr.send(typeof config.data === "string" ? config.data : null);
};
hilo.ajax = hiloAjax;
//
// `ajaxRequest` _Internal_
//
// Param:
//
// * `method`: {String} HTTP Method
// * `strOpt`: {String} URL, or options object (see above)
// * `callback`: {Function} To be executed on `success`
// * `oOpt`: {Object} For providing more options
//
function ajaxRequest (method, strOpt, callback, oOpt) {
oOpt = (typeof oOpt === "object" ? oOpt : undefined);
if (typeof strOpt === "string" && typeof callback === "function") {
hiloAjax(extend({
method: method,
url: strOpt,
success: callback
}, oOpt));
} else {
hiloAjax(extend({
method: method
}, strOpt));
}
}
//
// ### Make an asynchronous GET Request
//
// Params are similar to those of the internal `ajaxRequest` method (see above)
//
// ```
// $.get({
// url: "path/to/file.js",
// success: function (data) {
// console.log(data);
// }
// }); // Long form
// ```
//
// ```
// $.get("path/to/file.js", function (data) {
// console.log(data);
// }); // This does the exact same function as above
// ```
//
// ```
// $.get("path/to/file.js", function (data) {
// console.log(data);
// }, {
// error: function (err) {
// console.error(err);
// }
// }); // Short form, with more options
// ```
//
hilo.get = function (strOpt, callback, oOpt) {
ajaxRequest("GET", strOpt, callback, oOpt);
};
//
// ### Make an asynchronous POST Request
//
// Params are similar to those of the internal `ajaxRequest` method (see above)
//
// ```
// $.post({
// url: "path/to/file.js",
// success: function (data) {
// console.log(data);
// },
// data: JSON.encode(obj)
// }); // Long form
// ```
//
// ```
// $.post("path/to/file.js", function (data) {
// console.log(data);
// }, {
// data: JSON.encode(obj),
// error: function (err) {
// console.error(err);
// }
// }); // Short form, with more options
// ```
//
hilo.post = function (strOpt, callback, oOpt) {
ajaxRequest("POST", strOpt, callback, oOpt);
};
//
// ### Main DOM Class
//
// ** Params: **
// - `els` {Array} The elements to manipulate
// - `sel` {String} The selector used
//
// ** Examples **
//
// ```
// new Dom (document.querySelectorAll(p:first-child);
// ```
// ```
// new Dom ([document.createElement("div")]);
// ```
// ```
// new Dom ([document.getElementByid("box")]);
// ```
// ```
// new Dom (document.getElementsByClassName("hidden"));
// ```
// ```
// new Dom (document.getElementsByTagName("mark"));
// ```
//
function Dom (els, sel) {
var _i, _l;
/* Note that `this` is an object and NOT an Array */
/* Loop thorugh the NodeList and set `this[index]` for `els[index]` */
for (_i = 0, _l = els.length; _i < _l; _i += 1) {
this[_i] = els[_i];
}
/* Useful for looping through as ours is an object and not an array */
this.length = els.length;
/* Know what selector is used to select the elements */
this.sel = sel;
}
/* Make it _look_ like an array */
Dom.prototype = Array.prototype;
extend(Dom.prototype, {
/* Set the constructor to Dom. It defaults to Array. We don't that */
constructor: Dom
});
// ### Hilo CSS Helper Methods
//
// **_unhyph_** *Internal*
//
// Return a string repacing all `-`s with `""` and making the letter
// next to every `-` uppercase
//
// **Param**:
// - `prop`: {String} CSS Property Name
//
// **Examples**:
// ```
// unhyph("background-color"); // backgroundColor
// unhyph("color"); // color
// ```
//
function unhyph (prop) {
return prop.toLowerCase().replace(/-(.)/g, function (m, m1) {
return m1.toUpperCase();
});
}
//
// **_unitize_** *Internal*
//
// Add necessary suffix to the number for certain CSS properties
// _This will later be used by .css() and a number of other methods_
//
// **Param**:
// - `unit`: {String|Number} Valid CSS Unit (`unitize()` Returns the same thing if {String})
// - `prop`: {String} CSS Property Name
//
// **Examples**:
// ```
// unitize("background-color"); // backgroundColor
// unhyph("color"); // color
// ```
//
function unitize (unit, prop) {
/* All the CSS props. that are to be defaulted to px values */
var pixel = {
"width": true,
"maxWidth": true,
"minWidth": true,
"height": true,
"maxHeight": true,
"minHeight": true,
"borderWidth": true,
"borderTopWidth": true,
"borderLeftWidth": true,
"borderBottomWidth": true,
"borderRightWidth": true,
"borderRadius": true,
"outlineWidth": true,
"outlineOffset": true,
"strokeWidth": true,
"fontSize": true,
"lineHeight": true,
"letterSpacing": true,
"textIndent": true,
"textUnderlineWidth": true,
"margin": true,
"marginTop": true,
"marginLeft": true,
"marginBottom": true,
"marginRight": true,
"padding": true,
"paddingTop": true,
"paddingLeft": true,
"paddingBottom": true,
"paddingRight": true,
"top": true,
"left": true,
"bottom": true,
"right": true
};
/* String values are not be unitized no matter what */
if (typeof unit === "string") {
return unit;
}
/* If the property is present in the previously mentioned
object, the unit is suffixed with "px" */
if (pixel[prop] === true) {
return unit + "px";
}
return unit;
}
//
// **_hilo.create_**
//
// Create an element
//
// **Params**:
// - `tagName`: {String} Tag Name or Node name of element
// - `attrs`: {Object} An object containing the attributes and values
//
// **Example**:
// ```
// $.create("div", {
// class: "post",
// "data-id": 2
// });
// ```
//
hilo.create = function (tagName, attrs) {
var el = new Dom([document.createElement(tagName)]), key;
if (attrs) {
/* Add Class if the `className` is set */
if (attrs.className) {
el.addClass(attrs.className);
delete attrs.className;
}
/* Set html to if `text` content is given */
if (attrs.text) {
el.html(attrs.text);
delete attrs.text;
}
/* Set other attributes */
for (key in attrs) {
if(attrs.hasOwnProperty(key)) {
el.attr(key, attrs[key]);
}
}
}
return el;
};
extend(Dom.prototype, {
// ## Helper Functions
//
// **_Hilo.Dom.prototype.each_**
//
// Execute a function on selected elements
//
// **Param**:
// - `fn`: {Function} The function to be called
//
// **Example**:
// ```
// $("p").each(function (el) {
// doSomethingWith(e);
// });
// ```
//
each: function (fn) {
this.map(fn);
return this; /* return the current Dom instance */
},
//
// **_Hilo.Dom.prototype.map_**
//
// Return the results of executing a function
// on all the selected elements
//
// **Param**:
// - `fn`: {Function} The function to be called
//
// **Example**:
// ```
// $("div.need-cf").map(function (e) {
// doSomethingWith(e);
// });
// ```
//
map: function (fn) {
var results = []
, _i
, _l;
for (_i = 0, _l = this.length; _i < _l; _i += 1) {
results.push(fn.call(this, this[_i], _i));
}
return results;
},
//
// **_Hilo.Dom.prototype.one_**
//
// Map on selected elements and return them based
// on the number of selected elements
//
// **Param**:
// - `fn`: {Function} The function to be called
//
one: function (fn) {
var m = this.map(fn);
return m.length > 1 ? m : m[0];
},
//
// **_Hilo.Dom.prototype.first_**
//
// Execute a function on the first selected element
//
// **Param**:
// - `fn`: {Function} The function to be called
//
// **Example**:
// ```
// $("div").first(function (e) {
// console.log(e + " is the first div");
// });
// ```
//
first: function (fn) {
return fn(this[0]);
},
//
// **_Hilo.Dom.prototype.filter_**
//
// Filter the selected element and return the
// elements that pass the test (or return true)
//
// **Param**:
// - `fn`: {Function} The function to be called
//
// **Example**:
// ```
// $("div").filter(function (el) {
// return el.className.split("hidden").length > 1;
// });
// ```
//
filter: function (fn) {
var len = this.length >>> 0
, _i
, t = Object(this)
, res = []
, val;
for (_i = 0; _i < len; _i++) {
if (_i in t) {
val = t[_i];
if (fn.call(this, val, _i, t)) {
res.push(val);
}
}
}
return new Dom(res);
},
// ## Element Selections, etc.
//
// **_Hilo.Dom.prototype.get_**
//
// Get a JavaScript Array containing selected elements
//
// **Example**:
// ```
// $("script").get();
// ```
//
get: function () {
var els = [];
this.each(function (el) {
els.push(el);
});
return els;
},
//
// **_Hilo.Dom.prototype.firstEl_**
//
// Return first element of the selected elements
//
// **Example**:
// ```
// $("p.hidden").firstEl().show();
// ```
//
firstEl: function () {
return new Dom([this[0]]);
},
//
// **_Hilo.Dom.prototype.lastEl_**
//
// Return last element of the selected elements
//
// **Example**:
// ```
// $("p.hidden").lastEl().show();
// ```
//
lastEl: function () {
return new Dom([this[this.length - 1]]);
},
//
// **_Hilo.Dom.prototype.el_**
//
// Return nth element of the selected elements
//
// **Param**:
// - `place`: {Number} The index of the element (Starts from 1)
//
// **Example**:
// ```
// $("p.hidden").el(3).show();
// ```
//
el: function (place) {
return new Dom([this[place - 1]]);
},
//
// **_Hilo.Dom.prototype.children_**
//
// Return the children of selected elements
//
// **Param**:
// - `sel`: {String} Optional filtering selector
//
// **Example**:
// ```
// var childrenOfContainer = $("div.container").children();
// $("div.container").children(":not(.hidden)").addClass("me");
// ```
//
children: function (sel) {
var children = [], _i, _l;
this.each(function (el) {
var childNodes = select(sel ? sel : "*", el);
for (_i = 0, _l = childNodes.length; _i < _l; _i += 1) {
children = children.concat(childNodes[_i]);
}
});
return children;
},
//
// **_Hilo.Dom.prototype.parents_**
//
// Return the parents of selected elements
//
// **Example**:
// ```
// $("div#editor").parent().hide()
// ```
//
parents: function () {
var pars = [];
this.each(function (el) {
pars = pars.concat(el.parentElement);
});
return new Dom(pars);
},
//
// **_Hilo.Dom.prototype.parent_**
//
// Return the parent of the first selected element
//
// **Example**:
// ```
// $("div#editor").parent().hide()
// ```
//
parent: function () {
return this.first(function (el) {
return new Dom([el.parentElement]);
});
},
//
// **_Hilo.Dom.prototype.rel_**
//
// Return relatives of selected elements based
// on the given relation
//
// **Param**:
// - `sul`: {String} Relation
//
// **Example**:
// ```
// $("div#editor").rel("nextSibling").addClass("next-to-editor");
// ```
//
rel: function (sul) {
var els = [];
this.each(function (el) {
els.push(el[sul]);
});
return els;
},
//
// **_Hilo.Dom.prototype.next_**
//
// Return next sibling elements of selected elements
//
// **Example**:
// ```
// $("div#editor").next().addClass("next-to-editor");
// ```
//
next: function () {
return this.rel("nextElementSibling");
},
//
// **_Hilo.Dom.prototype.prev_**
//
// Return next sibling elements of selected elements
//
// **Example**:
// ```
// $("div#editor").prev().addClass("prev-to-editor");
// ```
//
prev: function () {
return this.rel("previousElementSibling");
},
//
// **_Hilo.Dom.prototype.html_**
//
// Set or return innerHTML of selected elements
//
// **Param**:
// - `html`: {String} HTML Code to be inserted
//
// **Example**:
// ```
// $("p:first-child").html("first-p");
// var html = $("span").html();
// ```
//
html: function (htmlCode) {
if (typeof htmlCode !== "undefined") {
return this.each(function(el) {
el.innerHTML = htmlCode;
});
} else {
return this.first(function(el) {
return el.innerHTML;
});
}
},
//
// **_Hilo.Dom.prototype.empty_**
//
// Empty the selected elements
//
// **Example**:
// ```
// $("#todo-list").empty();
// ```
//
empty: function () {
return this.html("");
},
//
// **_Hilo.Dom.prototype.append_**
//
// Append html to selected elements
//
// **Param**:
// - `html`: {String} HTML Code to be appeneded
//
// **Example**:
// ```
// $("p:first-child").append(" - From the first p child")
// ```
//
append: function (html) {
return this.each(function (el) {
el.innerHTML += html;
});
},
//
// **_Hilo.Dom.prototype.prepend_**
//
// Prepend html to selected elements
//
// **Param**:
// - `html`: {String} HTML Code to be appeneded
//
// **Example**:
// ```
// $("p:first-child").append(" - From the first p child")
// ```
//
prepend: function (html) {
return this.each(function (el) {
el.innerHTML = html + el.innerHTML;
});
},
//
// **_Hilo.Dom.prototype.value_**
//
// Get or set the value attribute of the selected element
//
// **Param**:
// - `val`: {String} Value to set to
//
// **Example**:
// ```
// $("#my-form").children("input#name").value();
// ```
//
value: function (val) {
if (val) {
return this.each(function (el) {
el.value = val;
});
} else {
this.first(function (el) {
return el.value;
});
}
},
//
// **_Hilo.Dom.prototype.id_**
//
// Get or set the ID of first element
//
// **Param**:
// - `id`: {String} ID to set
//
// **Example**:
// ```
// $("p.rect").first().id("square");
// ```
//
id: function (id) {
if (id) {
// Setting id of only one element because
// id is intended to be an unique identifier
return this.first(function(el) {
el.id = id;
});
} else {
return this.first(function (el) {
return el.id;
});
}
},
// ### Classes and IDs
//
// **_Hilo.Dom.prototype.class_**
//
// Add, remove, or check class(es)
//
// **Param**:
// - `action`: {String} Action to take ("add", "remove", "has")
// - `className`: {String|Array} Class(es) to add or remove
//
// **Examples**:
// ```
// $("div#editor").class("add", "no-js");
// ```
// ```
// $("div#editor").class("remove", "no-js");
// ```
// ```
// var isHidden = $("p").class("has", "hidden");
// ```
//
"class": feature.classList === true ? function (action, className) {
return this.each(function (el) {
var _i, parts, contains, res = [];
if (typeof className === "string") { // A String
parts = className.split(" ");
if (parts.length === 1) { // String, one class
contains = el.classList.contains(className);
switch (action) {
case "add": {
if (!contains) {
el.classList.add(className);
}
} break;
case "remove": {
if (contains) {
el.classList.remove(className);
}
} break;
case "has": {
res = true;
} break;
case "toggle": {
for (_i = 0; _i < parts.length; _i += 1) {
if (contains) {
el.classList.remove(parts[_i]);
} else {
el.classList.add(parts[_i]);
}
}
} break;
}
} else { // String, many classes
contains = function (className) {
return el.classList.contains(className);
};
switch (action) {
case "add": {
for (_i = 0; _i < parts.length; _i += 1) {
if (!contains(parts[_i])) {
el.classList.add(parts[_i]);
}
}
} break;
case "remove": {
for (_i = 0; _i < parts.length; _i += 1) {
if (contains(parts[_i])) {
el.classList.remove(parts[_i]);
}
}
} break;
case "has": {
for (_i = 0; _i < parts.length; _i += 1) {
res.push(contains(parts[_i]));
}
} break;
case "toggle": {
for (_i = 0; _i < parts.length; _i += 1) {
if (contains(parts[_i])) {
el.classList.remove(parts[_i]);
} else {
el.classList.add(parts[_i]);
}
}
} break;
}
}
} else if (className.length) { // Array
parts = className;
contains = function (className) {
return el.classList.contains(className);
};
switch (action) {
case "add": {
for (_i = 0; _i < parts.length; _i += 1) {
if (!contains(parts[_i])) {
el.classList.add(parts[_i]);
}
}
} break;
case "remove": {
for (_i = 0; _i < parts.length; _i += 1) {
if (contains(parts[_i])) {
el.classList.remove(parts[_i]);
}
}
} break;
case "has": {
for (_i = 0; _i < parts.length; _i += 1) {
res.push(contains(parts[_i]));
}
} break;
case "toggle": {
for (_i = 0; _i < parts.length; _i += 1) {
if (contains(parts[_i])) {
el.classList.remove(parts[_i]);
} else {
el.classList.add(parts[_i]);
}
}
} break;
}
}
return typeof res === "boolean" ? res : res.every(function (el) {
return el === true;
});
});
} : function (action, className) {
return this.each(function (el) {
var _i, parts, contains, res = [];
if (typeof className === "string") {
parts = className.split(" ");
if (parts.length === 1) {
contains = el.className.split(className).length > 1;
switch (action) {
case "add": {
if (!contains) {
el.className += " " + (className);
}
} break;
case "remove": {
if (contains) {
el.className.replace(className, "");
}
} break;
case "has": {
res = contains;
} break;
case "toggle": {
for (_i = 0; _i < parts.length; _i += 1) {
if (contains) {
el.className.replace(className, "");
} else {
el.className += " " + className;
}
}
} break;
}
} else {
contains = function (className) {
return el.className.split(className).length > 1;
};
switch (action) {
case "add": {
for (_i = 0; _i < parts.length; _i += 1) {
if (!contains(parts[_i])) {
el.className += " " + parts[_i];
}
}
} break;
case "remove": {
for (_i = 0; _i < parts.length; _i += 1) {
if (contains(parts[_i])) {
el.className.replace(parts[_i], "");
}
}
} break;
case "has": {
for (_i = 0; _i < parts.length; _i += 1) {
res.push(contains(parts[_i]));
}
} break;
case "toggle": {
for (_i = 0; _i < parts.length; _i += 1) {
if (contains(parts[_i])) {
el.className.replace(parts[_i], "");
} else {
el.className += " " + parts[_i];
}
}
} break;
}
}
} else if (className.length) {
parts = className;
contains = function (className) {
return el.className.split(className).length > 1;
};
switch (action) {
case "add": {
for (_i = 0; _i < parts.length; _i += 1) {
if (!contains(parts[_i])) {
el.className += " " + parts[_i];
}
}
} break;
case "remove": {
for (_i = 0; _i < parts.length; _i += 1) {
if (contains(parts[_i])) {
el.className.replace(parts[_i], "");
}
}
} break;
case "has": {
for (_i = 0; _i < parts.length; _i += 1) {
res.push(contains(parts[_i]));
}
} break;
case "toggle": {
for (_i = 0; _i < parts.length; _i += 1) {
if (contains(parts[_i])) {
el.className.replace(parts[_i], "");
} else {
el.className += " " + parts[_i];
}
}
} break;
}
}
return typeof res === "boolean" ? res : res.every(function (el) {
return el === true;
});
});
},
//
// **_Hilo.Dom.prototype.addClass_**
//
// Adds class(es) to selected elements
//
// **Param**:
// - `className`: {String|Array} The class(es) to add
//
// **Example**:
// ```
// $("p").addClass("paragraph");
// ```
//
addClass: function (className) {
return this["class"]("add", className);
},
//
// **_Hilo.Dom.prototype.removeClass_**
//
// Remove class(es) from selected elements
//
// **Param**:
// - `className`: {String|Array} The class(es) to remove
//
// **Example**:
// ```
// $("p.hidden").removeClass("hidden");
// ```
//
removeClass: function (className) {
return this["class"]("remove", className);
},
//
// **_Hilo.Dom.prototype.hasClass_**
//
// Check if selected elements have the specified class(es)
//
// **Param**:
// - `className`: {String|Array} The class(es) to check if exists
//
// **Example**:
// ```
// $("pre").hasClass("prettyprint");
// ```
//
hasClass: function (className) {
return this["class"]("has", className);
},
//
// **_Hilo.Dom.prototype.toggleClass_**
//
// Add class(es) if it/they do(es) not exist(s),
// remove if exist(s)
//
// **Param**:
// - `className`: {String|Array} The class(es) to toggle
//
// **Example**:
// ```
// $(".someClass").on("click", function () {
// $(this).toggleClass("opaque");
// });
// ```
//
toggleClass: function (className) {
return this["class"]("toggle", className);
},
//
// **_Hilo.Dom.prototype.attr_**
//
// Set or return attribute values
//
// **Param**:
// - `name`: {String} Name of attribute
// - `val`: {String} Value of attribute
//
// **Example**:
// ```
// $("p.hidden").attr("hidden");
// ```
// ```
// $("div.edit").attr("contentEditable", "true");
// ```
// ```
// $("body").attr("hilo", "0.1.0");
// ```
//
attr: function (name, val) {
if(val) {
return this.each(function(el) {
el.setAttribute(name, val);
});
} else {
return this.first(function (el) {
return el.getAttribute(name);
});
}
},
// ### Hilo CSS
//
// **_Hilo.Dom.prototype.css_**
//
// Set or return css property values
//
// **Param**:
// - `prop`: {String|Object} Name of the propety | Properties
// - `value`: {String} Value of property
//
// **Example**:
// ```
// $("p").css("margin-left", "10em");
// ```
// ```
// $("p.round").css({
// "border-radius": 10,
// width: 100
// });
// ```
//
css: function (prop, value) {
var unhyphed;
if (typeof prop === "string") {
unhyphed = unhyph(prop);
if (value) {
return this.each(function (el) {
el.style[unhyphed] = unitize(value, unhyphed);
});
} else {
return this.first(function (el) {
return el.style[unhyphed];
});
}
} else if (typeof prop === "object") {
forIn(prop, function (pr) {
unhyphed = unhyph(pr);
this.each(function (el) {
el.style[unhyphed] = unitize(prop[pr], unhyphed);
});
}, this);
}
},
//
// **_Hilo.Dom.prototype.computed_**
//
// Get computed property
//
// **Param**:
// - `prop`: {String|Object} Name of property
//
// **Example**:
// ```
// $("#box").computed("width");
// ```
//
computed: function (prop) {
return this.first(function (el) {
return win.getComputedStyle(el)[prop];
});
},
// Get outer width
outerWidth: function () {
return parseFloat(this.computed("width")) +
parseFloat(this.computed("paddingLeft")) +
parseFloat(this.computed("paddingRight")) +
parseFloat(this.computed("borderLeft")) +
parseFloat(this.computed("borderRight")) + "px";
},
// Get inner width
innerWidth: function () {
return parseFloat(this.computed("width")) +
parseFloat(this.computed("paddingLeft")) +
parseFloat(this.computed("paddingRight")) + "px";
},
// Get outer height
outerHeight: function () {
return parseFloat(this.computed("height")) +
parseFloat(this.computed("paddingTop")) +
parseFloat(this.computed("paddingBottom")) +
parseFloat(this.computed("borderTop")) +
parseFloat(this.computed("borderBottom")) + "px";
},
// Get inner height
innerHeight: function () {
return parseFloat(this.computed("height")) +
parseFloat(this.computed("paddingTop")) +
parseFloat(this.computed("paddingBottom")) + "px";
}
});
// --------------------------------------------------
// Events
// --------------------------------------------------
extend(Dom.prototype, {
// Listen to an event and execute a function when that event happend
/**
* Listen to an event and execute a function when that event happend
*
* @for Dom
* @method on
* @param {String} evt Name of event
* @param {Function} fn Function to be executed when the event is fired
* @return {Dom}
* @example
* <div class="code"><pre class="prettyprint">
* $("#box").on("click", function (e) {
* console.log("#box was clicked");
* });
* </pre></div>
* @since 0.1.0
*/
on: (function () {
// Check if `document.addEventListener` method
// is available and use it if it is
if (document.addEventListener) {
return function (evt, fn) {
return this.each(function (el) {
el.addEventListener(evt, fn, false);
});
};
// Otherwise check if `document.attachEvent`
// legacy method is available and use it if it is
} else if (document.attachEvent) {
return function (evt, fn) {
return this.each(function (el) {
el.attachEvent("on" + evt, fn);
});
};
// Add event the DOM Level 0 Style
} else {
return function (evt, fn) {
return this.each(function (el) {
el["on" + evt] = fn;
});
};
}
}()),
// Stop listening to an event
/**
* Stop listening to an event
*
* @for Dom
* @method on
* @param {String} evt Name of event
* @param {Function} fn Function to stop listening to
* @return {Dom}
* @example
* <div class="code"><pre class="prettyprint">
* $("#box").off("click", fn);
* </pre></div>
* @since 0.1.0
*/
off: (function () {
if (document.removeEventListener) {
return function (evt, fn) {
return this.each(function (el) {
el.removeEventListener(evt, fn, false);
});
};
} else if (document.detachEvent) {
return function (evt, fn) {
return this.each(function (el) {
el.detachEvent("on" + evt, fn);
});
};
} else {
return function (evt) {
return this.each(function (el) {
el["on" + evt] = null;
});
};
}
}()),
/**
* Trigger or fire an event
*
* @for Dom
* @method fire
* @param {String} evt Name of event to fire
* @return {Dom}
* @example
* <div class="code"><pre class="prettyprint">
* $("#uploadForm").fire("overload");
* </pre></div>
* @since 0.1.0
*/
fire: (function () {
if (document.dispatchEvent) {
return function (event) {
var evt;
try {
evt = document.createEvent("Events");
} catch (e) {
evt = document.createEvent("UIEvents");
}
evt.initUIEvent(event, true, true, window, 1);
return this.each(function (el) {
el.dispatchEvent(evt);
});
};
} else if (document.fireEvent) {
return function (event) {
var evt = document.createEventObject();
evt.button = 1;
return this.each(function(el) {
el.fireEvent("on" + event, evt);
});
};
} else {
return function (event) {
return this.each(function (el) {
el["on" + event].call();
});
};
}
}())
});
// --------------------------------------------------
// Events (imp.)
// --------------------------------------------------
extend(Dom.prototype, {
ready: function (fn) {
this.each(function (el) {
el.onreadystatechange = function () {
if (el.readyState = "complete") {
fn();
}
};
});
}
});
(function () {
var evtObj = {}
, impEvts;
impEvts = [
"blur",
"click",
"change",
"dblclick",
"drag",
"dragstart",
"dragend",
"dragenter",
"dragleave",
"dragover",
"drop",
"error",
"focus",
"keyup",
"keydown",
"keypress",
"load",
"mousedown",
"mouseleave",
"mouseenter",
"mouseover",
"mousemove",
"mouseout",
"submit"
];
for (_i = 0; _i < impEvts.length; _i += 1) {
evtObj[impEvts[_i]] = function (fn) {
if (typeof fn === "function") {
return this.on(impEvts[_i], fn);
}
return this.fire(impEvts[_i]);
};
}
extend(Dom.prototype, evtObj);
}());
// These keyborad key mappings will be later used
// to enable use of shortcut keys or the like
key = {
// Numbers
"0": 48,
"1": 49,
"2": 50,
"3": 51,
"4": 52,
"5": 53,
"6": 54,
"7": 55,
"8": 56,
"9": 57,
// Uppercase letters
A: 65,
B: 66,
C: 67,
D: 68,
E: 69,
F: 70,
G: 71,
H: 72,
I: 73,
J: 74,
K: 75,
L: 76,
M: 77,
N: 78,
O: 79,
P: 80,
Q: 81,
R: 82,
S: 83,
T: 84,
U: 85,
V: 86,
W: 87,
X: 88,
Y: 89,
Z: 90,
// Lowecase letters
a: 97,
b: 98,
c: 99,
d: 100,
e: 101,
f: 102,
g: 103,
h: 104,
i: 105,
j: 106,
k: 107,
l: 108,
m: 109,
n: 110,
o: 111,
p: 112,
q: 113,
r: 114,
s: 115,
t: 116,
u: 117,
v: 118,
w: 119,
x: 120,
y: 121,
z: 122,
// Other Important Keys
alt: 18,
caps: 20,
ctrl: 17,
cmd: 17,
enter: 13,
esc: 27,
del: 46,
end: 35,
back: 8,
// Arrows
left: 37,
up: 38,
right: 39,
down: 40,
// F-keys
f1: 112,
f2: 113,
f3: 114,
f4: 115,
f5: 116,
f6: 117,
f7: 118,
f8: 119,
f9: 120,
f10: 121,
f11: 122,
f12: 123,
// Less-used keys
home: 36,
insert: 45,
numlock: 144,
// Symbols
"`": 222,
"-": 189,
",": 188,
".": 190,
"/": 191,
";": 186,
"[": 219,
"\\": 220,
"]": 221,
"=": 187
};
hilo.keys = key;
// --------------------------------------------------
// Effects (fx)
// --------------------------------------------------
extend(Dom.prototype, {
/**
* Sets the display property of sel.els. to "" or given value
*
* @for Dom
* @method show
* @param {string} display Value of display prop.
* @return {Dom}
* @example
* <div class="code"><pre class="prettyprint">
* $("p").show();
* </pre></div>
* @since 0.1.0
*/
show: function (display) {
display = display || "";
return this.each(function (el) {
el.style.display = display;
el.setAttribute("aria-hidden", false);
});
},
/**
* Sets the display property of sel.els. to "none"
*
* @for Dom
* @method hide
* @return {Dom}
* @example
* <div class="code"><pre class="prettyprint">
* $("p").hide();
* </pre></div>
* @since 0.1.0
*/
hide: function () {
return this.each(function (el) {
el.style.display = "none";
// ARIA
el.setAttribute("aria-hidden", true);
});
},
/**
* Shows hidden elements, hides shown elements
*
* @for Dom
* @method toggle
* @return {Dom}
* @example
* <div class="code"><pre class="prettyprint">
* $("p").toggle();
* </pre></div>
* @since 0.1.0
*/
toggle: function (display) {
return this.each(function (el) {
if (el.style.display === "none") {
el.style.display = display ? display : "";
// ARIA
el.setAttribute("aria-hidden", false);
} else {
el.style.display = "none";
// ARIA
el.setAttribute("aria-hidden", true);
}
});
},
/**
* Sets visibility to "visible"
*
* @for Dom
* @method appear
* @return {Dom}
* @example
* <div class="code"><pre class="prettyprint">
* $("p").appear();
* </pre></div>
* @since 0.1.0
*/
appear: function () {
return this.each(function (el) {
el.style.visibility = "visible";
// ARIA
el.setAttribute("aria-hidden", false);
});
},
/**
* Sets visiblity to "hidden"
*
* @for Dom
* @method disappear
* @return {Dom}
* @example
* <div class="code"><pre class="prettyprint">
* $("p").disappear();
* </pre></div>
* @since 0.1.0
*/
disappear: function () {
return this.each(function (el) {
el.style.visibility = "hidden";
// ARIA
el.setAttribute("aria-hidden", true);
});
},
/**
* Appears a disappeared element, disappears an appeared element
*
* @for Dom
* @method toggleVisibility
* @return {Dom}
* @example
* <div class="code"><pre class="prettyprint">
* $("p").toggleVisibility();
* </pre></div>
* @since 0.1.0
*/
toggleVisibility: function () {
return this.each(function (el) {
if (el.style.opacity === "0") {
el.style.visibility = "visible";
// ARIA
el.setAttribute("aria-hidden", true);
} else {
el.style.visibility = "hidden";
// ARIA
el.setAttribute("aria-hidden", true);
}
});
},
/**
* Animates opacity prop. from 0 to 1 or 1 to 0
*
* @for Dom
* @method fade
* @param {string} inOut Whether "in" or "out"
* @param {number|string} "fast", "slow", "normal" or a number
* @return {Dom}
* @example
* <div class="code"><pre class="prettyprint">
* $("p").fade("in");
* $("p").fade("out");
* $("p").fade("in", 140);
* $("p").fade("out", 100);
* </pre></div>
* @since 0.1.0
*/
fade: function (inOut, timing) {
if (inOut === "in") {
this.show();
}
return this.each(function (el) {
var time;
switch(timing) {
case "slow":
time = 200;
break;
case "normal":
time = 120;
break;
case "fast":
time = 80;
break;
default:
time = time || 120;
break;
}
function animate () {
var val = 0.3
, end = 1;
if (parseFloat(el.style.opacity) === (inOut === "in" ? 1 : 0)) {
// Stop the animation if the opacity is set to the final value
clearInterval(win.Hilo.temp.anim);
} else {
if (inOut === "out") {
val = -val;
end = 0;
}
el.style.opacity = parseFloat(el.style.opacity || end) + val;
}
}
win.Hilo.temp.anim = setInterval(animate, timing);
});
},
/**
* Animates opacity prop. from 0 to 1
*
* @for Dom
* @method fadeIn
* @param {number|string} "fast", "slow", "normal" or a number
* @return {Dom}
* @example
* <div class="code"><pre class="prettyprint">
* $("p").fadeIn();
* $("p").fadeIn(140);
* </pre></div>
* @since 0.1.0
*/
fadeIn: function (timing) {
this.fade("in", timing);
},
/**
* Animates opacity prop. from 1 to 0
*
* @for Dom
* @method fadeOut
* @param {number|string} "fast", "slow", "normal" or a number
* @return {Dom}
* @example
* <div class="code"><pre class="prettyprint">
* $("p").fadeOut();
* $("p").fadeOut(140);
* </pre></div>
* @since 0.1.0
*/
fadeOut: function (timing) {
this.fade("out", timing);
}
});
hilo.classify = function () {
var body = win.Hilo("body")
, classes = ["js"]
, _i;
// Remove the default no-js class
body.removeClass("no-js");
if (hilo.browser.chrome) {
classes.push("chrome");
} else if (hilo.browser.firefox) {
classes.push("firefox");
} else if (hilo.browser.safari) {
classes.push("safari");
} else if (hilo.browser.ie) {
for (_i = 6; _i <= 11; _i++) {
if (hilo.browser.ie <= _i) {
classes.push("lte-ie" + _i);
if (hilo.browser.ie < _i) {
classes.push("lt-ie" + _i);
}
}
if (hilo.browser.ie >= _i) {
classes.push("gte-ie" + _i);
if (hilo.browser.ie > _i) {
classes.push("gt-ie" + _i);
}
}
if (hilo.browser.ie === _i) {
classes.push("ie" + _i);
}
}
classes.push("ie");
} else if (hilo.browser.opera) {
classes.push("opera");
} else if (hilo.browser.konq) {
classes.push("konqueror");
}
classes.push((function () {
switch (hilo.platform.name) {
case "Windows":
return "windows";
case "Mac":
return "mac";
case "Linux":
return "linux";
}
})());
if (hilo.engine.webkit) {
classes.push("webkit");
} else if (hilo.engine.ie) {
classes.push("trident");
} else if (hilo.engine.opera) {
classes.push("presto");
} else if (hilo.engine.gecko) {
classes.push("gecko");
}
classes.push(hilo.browser.name.toLowerCase() + parseInt(hilo.browser.version, 10));
function getBrowserVersion () {
return String(hilo.browser.version).replace(".", "-");
}
if (getBrowserVersion() !== parseInt(hilo.browser.version, 10)) {
classes.push(hilo.browser.name.toLowerCase() + getBrowserVersion());
}
for (_i in hilo.feature) {
if (hilo.feature.hasOwnProperty(_i)) {
if (hilo.feature[_i] === true) {
classes.push(_i.toLowerCase());
} else if (hilo.feature[_i] === false) {
classes.push("no-" + _i.toLowerCase());
}
}
}
body.addClass(classes);
return classes;
};
// --------------------------------------------------
// More Functionality
// --------------------------------------------------
/**
* NumberObject Class
*
* @constructor
* @class NumberObject
* @param {Number} num Number
* @example
* <div class="code"><pre class="prettyprint">
* new NumberObject(2);
* </pre></div>
* <div class="code"><pre class="prettyprint">
* new NumberObject(Math.PI);
* </pre></div>
* @since 0.1.0
*/
function NumberObject (num) {
this.num = num;
}
extend(NumberObject.prototype, {
/**
* NumberObject.MAX_INTEGER = 9007199254740991
* The maximum value of a JavaScript integer
*
* @for NumberObject
* @property MAX_INTEGER
* @type Number
* @since 0.1.0
*/
MAX_INTEGER: 9007199254740991,
/**
* Epsilon
*
* @for NumberObject
* @property EPSILON
* @type Number
* @since 0.1.0
*/
EPSILON: 2.220446049250313e-16,
/**
* Parses integer value from a string or number
*
* @for NumberObject
* @method parseInt
* @return {Number}
* @example
* <div class="code"><pre class="prettyprint">
* new NumberObject(3.5).parseInt() // 3
* </pre></div>
* @since 0.1.0
*/
parseInt: function () {
parseInt.call(this, this.num);
},
/**
* Parses float point number value from a string or number
*
* @for NumberObject
* @method parseFloat
* @return {Number}
* @example
* <div class="code"><pre class="prettyprint">
* new NumberObject("5.3").parseFloat() // 5.3
* </pre></div>
* @since 0.1.0
*/
parseFloat: function () {
parseFloat.call(this, this.num);
},
/**
* Returns true if a number is a finite value
*
* @for NumberObject
* @method isFinite
* @return {Bolean} Whether the number is finite
* @example
* <div class="code"><pre class="prettyprint">
* new NumberObject(NaN).isFinite() // false
* new NumberObject(3).isFinite() // true
* </pre></div>
* @since 0.1.0
*/
isFinite: function() {
return typeof this.num === 'number' && isFinite(this.num);
},
/**
* If the number is an integer
*
* @for NumberObject
* @method isInteger
* @return {Number} Whether the number is an integer
* @example
* <div class="code"><pre class="prettyprint">
* new NumberObject(5.3).isInteger() // false
* new NumberObject(4).isInteger() // true
* </pre></div>
* @since 0.1.0
*/
isInteger: function() {
return typeof this.num === 'number' &&
!isNaN(this.num) &&
isFinite(this.num) &&
parseInt(this.num, 10) === this.num;
},
/**
* Returns if the number is NaN (Not a number)
*
* @for NumberObject
* @method isNan
* @return {Number} Whether the number is not a number (NaN)
* @example
* <div class="code"><pre class="prettyprint">
* new NumberObject(5).isNan() // false
* new NumberObject(NaN).isNan() // true
* </pre></div>
* @since 0.1.0
*/
isNaN: function() {
// NaN !== NaN, but they are identical.
// NaNs are the only non-reflexive value, i.e., if x !== x,
// then x is NaN.
// isNaN is broken: it converts its argument to number, so
// isNaN('foo') => true
return this.num !== this.num;
},
/**
* Converts ant value to an integer
*
* @for NumberObject
* @method toInteger
* @return {Number} The converted integer
* @example
* <div class="code"><pre class="prettyprint">
* new NumberObject(5).toInteger() // 5
* new NumberObject(NaN).toInteger() // 0
* </pre></div>
* @since 0.1.0
*/
toInteger: function() {
var number = +this.num;
if (isNaN(number)) {
return 0;
}
if (number === 0 || !isFinite(number)) {
return number;
}
return sign.call(this, number) * Math.floor(Math.abs(number));
},
sign: function (value) {
sign.call(this, this.num, value);
},
/**
* Call a function n times
*
* @for NumberObject
* @method times
* @param {Function} fn The function to be called
* @param {Array} args The arguments to be passed
* @return {Number} The converted integer
* @example
* <div class="code"><pre class="prettyprint">
* var i = 0;
* new NumberObject(100).times(function () {
* console.log(i++);
* });
* </pre></div>
* <div class="code"><pre class="prettyprint">
* new NumberObject(100).times(function () {
* consolee.log
* });
* </pre></div>
* @since 0.1.0
*/
times: function (fn, args) {
var _i = 0;
while (_i < this.num) {
fn.apply(this, args);
_i += 1;
}
}
});
// ## Hilo Extension API
/* Provide Extension API */
extend(hilo, {
Dom: Dom.prototype,
Test: Test.prototype
});
/* Set event handler for triggering DOM Events */
doc.onreadystatechange = function () {
if (doc.readyState === "complete") {
for (_i = 0; _i < callbacks.length; _i += 1) {
callbacks[_i]();
}
}
};
/* Get the total time took to execute the script */
hilo.perf = new Date().getTime() - start;
// Finally return Hilo
return hilo;
}));