Comparing version 0.0.0 to 0.0.2
1931
cute.js
@@ -1,7 +0,1930 @@ | ||
var api = module.exports; | ||
/** ___ _ __ __ _ | ||
* / __| _| |_ ___ __ __/ \ / \ / | | ||
* | (_| || | _/ -_) \ V / () | () || | | ||
* \___\_,_|\__\___| \_/ \__(_)__(_)_| | ||
* | ||
* http://lighter.io/cute | ||
* | ||
* Source: | ||
* https://github.com/lighterio/cute/blob/master/scripts/ajax.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/charts.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/collections.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/cookies.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/crypto.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/dates.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/dom.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/events.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/forms.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/functions.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/history.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/i18n.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/json.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/logging.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/numbers.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/page.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/ready.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/regexp.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/storage.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/strings.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/style.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/timing.js | ||
* https://github.com/lighterio/cute/blob/master/scripts/types.js | ||
*/ | ||
var Cute = {} | ||
Cute.version = '0.0.1' | ||
/* istanbul ignore next */ | ||
//+env:commonjs | ||
if (typeof exports === 'object') { | ||
module.exports = Cute | ||
} | ||
//-env:commonjs | ||
//+env:amd | ||
else if (typeof define === 'function' && define.amd) { | ||
define(function () { | ||
return Cute | ||
}); | ||
} | ||
//-env:amd | ||
//+env:window | ||
else { | ||
this.Cute = Cute | ||
} | ||
//-env:window | ||
/** | ||
* Expose the version to module users. | ||
* @type {string} | ||
* Get an XMLHttpRequest object (or ActiveX object in old IE). | ||
* | ||
* @return {XMLHttpRequest} The request object. | ||
*/ | ||
api.version = require('./package.json').version; | ||
Cute._xhr = function () { | ||
return new XMLHttpRequest() | ||
} | ||
/** | ||
* Get an XMLHttpRequest upload object. | ||
* | ||
* @return {XMLHttpRequestUpload} The request upload object. | ||
*/ | ||
Cute.upload = function () { | ||
return Cute._xhr().upload | ||
} | ||
/** | ||
* Make an AJAX request, and handle it with success or failure. | ||
* | ||
* @param {String} url A URL from which to request a response. | ||
* @param {String} data An optional query, which if provided, makes the request a POST. | ||
* @param {Function} fn An optional function which takes (data, status) arguments. | ||
*/ | ||
Cute.get = function (url, data, fn) { | ||
// If the optional data argument is omitted, zero it. | ||
if (Cute.isFunction(data)) { | ||
fn = data | ||
data = 0 | ||
} | ||
var request = Cute._xhr() | ||
request.onreadystatechange = function (event) { | ||
if (request.readyState === 4) { | ||
var status = request.status | ||
var text = request.responseText | ||
var data = Cute.parse(text, 0) | ||
fn(data, status) | ||
} | ||
} | ||
var method = data ? 'POST' : 'GET' | ||
request.open(method, url, true) | ||
if (data) { | ||
request.setRequestHeader('content-type', 'application/x-www-form-urlencoded') | ||
if (Cute.isObject(data)) { | ||
data = 'json=' + Cute.encode(Cute.stringify(data)) | ||
} | ||
} | ||
request.send(data || null) | ||
return request | ||
} | ||
/** | ||
* Get 100 consistent colors for charting. | ||
* These colors are designed to maximize visual distance. | ||
* | ||
* @return {Array} The request object. | ||
*/ | ||
Cute.colors = function () { | ||
var colors = Cute.colors._cache | ||
if (!colors) { | ||
var map = {} | ||
var string = | ||
'03f290c00eb0b0f0cbe6000605090307bf0c740f7a07f' + | ||
'686f97a098a0748f05a200a772d6332300b1708014dc0' + | ||
'c89f7a0ff045faf78304ab9798eb804020fcfd5600089' + | ||
'9f574be6f0f7f6405' | ||
colors = [] | ||
for (var i = 0; i < 3; i++) { | ||
for (var j = 0; j < 35; j++) { | ||
var color = string.substr(j * 3 + i, 3) | ||
if (!map[color]) { | ||
map[color] = 1 | ||
colors.push('#' + color) | ||
} | ||
} | ||
} | ||
Cute.colors._cache = colors | ||
} | ||
return colors | ||
} | ||
/** | ||
* Iterate over a string, array or object. | ||
* Call a function on each value. | ||
* If the function returns zero, stop iterating. | ||
* | ||
* - For strings, the function arguments are: (character, index, collection). | ||
* - For arrays, the function arguments are: (value, index, collection). | ||
* - For objects, the arguments are: (value, key, collection). | ||
* | ||
* @param {String|Array|Object} collection A collection of items. | ||
* @param {Function} fn A function to call on each item. | ||
* @return {Number} Index or key that returned false. | ||
*/ | ||
Cute.each = function (collection, fn) { | ||
if (collection) { | ||
var length = collection.length | ||
var key, result | ||
if (Cute.isNumber(length)) { | ||
for (key = 0; key < length; key++) { | ||
result = fn(collection[key], key, collection) | ||
if (result === 0) { | ||
break | ||
} | ||
} | ||
} else { | ||
for (key in collection) { | ||
result = fn(collection[key], key, collection) | ||
if (result === 0) { | ||
break | ||
} | ||
} | ||
} | ||
return key | ||
} | ||
} | ||
/** | ||
* Decorate an object with properties from another object. | ||
* | ||
* @param {Object} object An object to decorate. | ||
* @param {Object} decorations An object whose properties will be used as decorations. | ||
* @return {Object} The decorated object. | ||
*/ | ||
Cute.decorate = function (object, decorations) { | ||
if (object) { | ||
Cute.each(decorations, function (value, key) { | ||
object[key] = value | ||
}) | ||
} | ||
return object | ||
} | ||
/** | ||
* Get the value of an object property, and optionally set it to a default | ||
* value if it's not defined. | ||
* | ||
* @param {Object} object An object to get/set a property on. | ||
* @param {String} property The property name. | ||
* @param {Any} defaultValue An optional default value for the property. | ||
* @return {Any} The resulting property value. | ||
*/ | ||
Cute.prop = function (object, property, defaultValue) { | ||
var value = object[property] | ||
if (Cute.isUndefined(value)) { | ||
value = object[property] = defaultValue | ||
} | ||
return value | ||
} | ||
/** | ||
* Return the subset of a collection for which a filter function returns truthy. | ||
* | ||
* @param {Array|Object} collection A collection to filter. | ||
* @param {Function} fn A filter function. | ||
* @return {Array|Object} The filtered subset. | ||
*/ | ||
Cute.filter = function (collection, fn) { | ||
var isArray = Cute.isArray(collection) | ||
var filtered = isArray ? [] : {} | ||
Cute.each(collection, function (value, key) { | ||
if (fn(value)) { | ||
if (isArray) { | ||
filtered.push(value) | ||
} else { | ||
filtered[key] = value | ||
} | ||
} | ||
}) | ||
return filtered | ||
} | ||
/** | ||
* Merge one or more arrays into an array. | ||
* | ||
* @param {Array} array An array to merge into. | ||
* @param {Array...} Items to merge into the array. | ||
* @return {Array} The first array argument, with new items merged in. | ||
*/ | ||
Cute.merge = function (array) { | ||
Cute.each(arguments, function (items, index) { | ||
if (index) { | ||
[].push.apply(array, items) | ||
} | ||
}) | ||
return array | ||
} | ||
/** | ||
* Read cookies, and optionally get or set one. | ||
* | ||
* @param {String} name An optional cookie name to get or set. If not provided, return a map. | ||
* @param {Object} value A value to be set as a string, or null if the cookie is to be deleted. | ||
* @param {Object} options Optional cookie settings, including "maxAge", "expires", "path", "domain" and "secure". | ||
* @return {Object} A cookie, or a map of cookie names and values. | ||
*/ | ||
Cute.cookie = function (name, value, options) { | ||
// Initialize a cookie map. | ||
var map = Cute.cookie.map | ||
if (!map) { | ||
map = Cute.cookie.map = {} | ||
var parts = document.cookie.split(/; |=/) | ||
for (var i = 0, l = parts.length; i < l; i++) { | ||
map[Cute.decode(parts[i])] = Cute.decode(parts[++i]) | ||
} | ||
} | ||
// If no cookie is named, return the map. | ||
if (!name) { | ||
value = map | ||
// Otherwise, get or set one. | ||
} else { | ||
// If no value is provided, return the existing value. | ||
if (Cute.isUndefined(value)) { | ||
value = map[name] | ||
// If a value is provided, set the cookie to that value. | ||
} else { | ||
options = options || {} | ||
var pair = Cute.encode(name) + '=' + Cute.encode(value) | ||
var path = options.path | ||
var domain = options.domain | ||
var secure = options.secure | ||
// If the value is null, expire it as of one millisecond ago. | ||
var maxAge = Cute.isNull(value) ? -1 : options.maxAge | ||
var expires = maxAge ? new Date(Date.now() + maxAge) : 0 | ||
document.cookie = pair + | ||
(path ? ';path=' + path : '') + | ||
(domain ? ';domain=' + domain : '') + | ||
(expires ? ';expires=' + expires.toUTCString() : '') + | ||
(secure ? ';secure' : '') | ||
map[name] = value | ||
} | ||
} | ||
return value | ||
} | ||
/** | ||
* Calculate an MD5 hash for a string (useful for things like Gravatars). | ||
* | ||
* @param {String} s A string to hash. | ||
* @return {String} The MD5 hash for the given string. | ||
*/ | ||
Cute.md5 = function (str) { | ||
// Encode as UTF-8. | ||
str = decodeURIComponent(encodeURIComponent(str)) | ||
// Build an array of little-endian words. | ||
var arr = new Array(str.length >> 2) | ||
for (var idx = 0, len = arr.length; idx < len; idx += 1) { | ||
arr[idx] = 0 | ||
} | ||
for (idx = 0, len = str.length * 8; idx < len; idx += 8) { | ||
arr[idx >> 5] |= (str.charCodeAt(idx / 8) & 0xFF) << (idx % 32) | ||
} | ||
// Calculate the MD5 of an array of little-endian words. | ||
arr[len >> 5] |= 0x80 << (len % 32) | ||
arr[(((len + 64) >>> 9) << 4) + 14] = len | ||
var a = 1732584193 | ||
var b = -271733879 | ||
var c = -1732584194 | ||
var d = 271733878 | ||
len = arr.length | ||
idx = 0 | ||
while (idx < len) { | ||
var olda = a | ||
var oldb = b | ||
var oldc = c | ||
var oldd = d | ||
var e = arr[idx++] | ||
var f = arr[idx++] | ||
var g = arr[idx++] | ||
var h = arr[idx++] | ||
var i = arr[idx++] | ||
var j = arr[idx++] | ||
var k = arr[idx++] | ||
var l = arr[idx++] | ||
var m = arr[idx++] | ||
var n = arr[idx++] | ||
var o = arr[idx++] | ||
var p = arr[idx++] | ||
var q = arr[idx++] | ||
var r = arr[idx++] | ||
var s = arr[idx++] | ||
var t = arr[idx++] | ||
a = ff(a, b, c, d, e, 7, -680876936) | ||
d = ff(d, a, b, c, f, 12, -389564586) | ||
c = ff(c, d, a, b, g, 17, 606105819) | ||
b = ff(b, c, d, a, h, 22, -1044525330) | ||
a = ff(a, b, c, d, i, 7, -176418897) | ||
d = ff(d, a, b, c, j, 12, 1200080426) | ||
c = ff(c, d, a, b, k, 17, -1473231341) | ||
b = ff(b, c, d, a, l, 22, -45705983) | ||
a = ff(a, b, c, d, m, 7, 1770035416) | ||
d = ff(d, a, b, c, n, 12, -1958414417) | ||
c = ff(c, d, a, b, o, 17, -42063) | ||
b = ff(b, c, d, a, p, 22, -1990404162) | ||
a = ff(a, b, c, d, q, 7, 1804603682) | ||
d = ff(d, a, b, c, r, 12, -40341101) | ||
c = ff(c, d, a, b, s, 17, -1502002290) | ||
b = ff(b, c, d, a, t, 22, 1236535329) | ||
a = gg(a, b, c, d, f, 5, -165796510) | ||
d = gg(d, a, b, c, k, 9, -1069501632) | ||
c = gg(c, d, a, b, p, 14, 643717713) | ||
b = gg(b, c, d, a, e, 20, -373897302) | ||
a = gg(a, b, c, d, j, 5, -701558691) | ||
d = gg(d, a, b, c, o, 9, 38016083) | ||
c = gg(c, d, a, b, t, 14, -660478335) | ||
b = gg(b, c, d, a, i, 20, -405537848) | ||
a = gg(a, b, c, d, n, 5, 568446438) | ||
d = gg(d, a, b, c, s, 9, -1019803690) | ||
c = gg(c, d, a, b, h, 14, -187363961) | ||
b = gg(b, c, d, a, m, 20, 1163531501) | ||
a = gg(a, b, c, d, r, 5, -1444681467) | ||
d = gg(d, a, b, c, g, 9, -51403784) | ||
c = gg(c, d, a, b, l, 14, 1735328473) | ||
b = gg(b, c, d, a, q, 20, -1926607734) | ||
a = hh(a, b, c, d, j, 4, -378558) | ||
d = hh(d, a, b, c, m, 11, -2022574463) | ||
c = hh(c, d, a, b, p, 16, 1839030562) | ||
b = hh(b, c, d, a, s, 23, -35309556) | ||
a = hh(a, b, c, d, f, 4, -1530992060) | ||
d = hh(d, a, b, c, i, 11, 1272893353) | ||
c = hh(c, d, a, b, l, 16, -155497632) | ||
b = hh(b, c, d, a, o, 23, -1094730640) | ||
a = hh(a, b, c, d, r, 4, 681279174) | ||
d = hh(d, a, b, c, e, 11, -358537222) | ||
c = hh(c, d, a, b, h, 16, -722521979) | ||
b = hh(b, c, d, a, k, 23, 76029189) | ||
a = hh(a, b, c, d, n, 4, -640364487) | ||
d = hh(d, a, b, c, q, 11, -421815835) | ||
c = hh(c, d, a, b, t, 16, 530742520) | ||
b = hh(b, c, d, a, g, 23, -995338651) | ||
a = ii(a, b, c, d, e, 6, -198630844) | ||
d = ii(d, a, b, c, l, 10, 1126891415) | ||
c = ii(c, d, a, b, s, 15, -1416354905) | ||
b = ii(b, c, d, a, j, 21, -57434055) | ||
a = ii(a, b, c, d, q, 6, 1700485571) | ||
d = ii(d, a, b, c, h, 10, -1894986606) | ||
c = ii(c, d, a, b, o, 15, -1051523) | ||
b = ii(b, c, d, a, f, 21, -2054922799) | ||
a = ii(a, b, c, d, m, 6, 1873313359) | ||
d = ii(d, a, b, c, t, 10, -30611744) | ||
c = ii(c, d, a, b, k, 15, -1560198380) | ||
b = ii(b, c, d, a, r, 21, 1309151649) | ||
a = ii(a, b, c, d, i, 6, -145523070) | ||
d = ii(d, a, b, c, p, 10, -1120210379) | ||
c = ii(c, d, a, b, g, 15, 718787259) | ||
b = ii(b, c, d, a, n, 21, -343485551) | ||
a = add(a, olda) | ||
b = add(b, oldb) | ||
c = add(c, oldc) | ||
d = add(d, oldd) | ||
} | ||
arr = [a, b, c, d] | ||
// Build a string. | ||
var hex = '0123456789abcdef' | ||
str = '' | ||
for (idx = 0, len = arr.length * 32; idx < len; idx += 8) { | ||
var code = (arr[idx >> 5] >>> (idx % 32)) & 0xFF | ||
str += hex.charAt((code >>> 4) & 0x0F) + hex.charAt(code & 0x0F) | ||
} | ||
return str | ||
/** | ||
* Add 32-bit integers, using 16-bit operations to mitigate JS interpreter bugs. | ||
*/ | ||
function add (a, b) { | ||
var lsw = (a & 0xFFFF) + (b & 0xFFFF) | ||
var msw = (a >> 16) + (b >> 16) + (lsw >> 16) | ||
return (msw << 16) | (lsw & 0xFFFF) | ||
} | ||
function cmn (q, a, b, x, s, t) { | ||
a = add(add(a, q), add(x, t)) | ||
return add((a << s) | (a >>> (32 - s)), b) | ||
} | ||
function ff (a, b, c, d, x, s, t) { | ||
return cmn((b & c) | ((~b) & d), a, b, x, s, t) | ||
} | ||
function gg (a, b, c, d, x, s, t) { | ||
return cmn((b & d) | (c & (~d)), a, b, x, s, t) | ||
} | ||
function hh (a, b, c, d, x, s, t) { | ||
return cmn(b ^ c ^ d, a, b, x, s, t) | ||
} | ||
function ii (a, b, c, d, x, s, t) { | ||
return cmn(c ^ (b | (~d)), a, b, x, s, t) | ||
} | ||
} | ||
/** | ||
* Returns a Date object. | ||
* | ||
* @param {Date|Number|String} date An optional Date or Date constructor | ||
* argument (default: now). | ||
* @return {Date} A Date object. | ||
*/ | ||
Cute.getDate = function (date) { | ||
return Cute.isDate(date) ? date : date ? new Date(date) : new Date() | ||
} | ||
/** | ||
* Get Unix epoch milliseconds from a date. | ||
* | ||
* @param {Date} date An optional Date object (default: now). | ||
* @return {Number} Epoch milliseconds. | ||
*/ | ||
Cute.ms = function (date) { | ||
return date ? Cute.getDate(date).getTime() : Date.now() | ||
} | ||
/** | ||
* Get an ISO-standard date string. | ||
* | ||
* @param {Date} date Date object (default: now). | ||
* @return {String} ISO date string. | ||
*/ | ||
Cute.stamp = function (date) { | ||
date = Cute.getDate(date) | ||
return date.toISOString() | ||
} | ||
/** | ||
* Take a date and return a formatted date string in long or short format: | ||
* - Short: "8/26/14 7:42pm" | ||
* - Long: "August 26, 2014 at 7:42pm" | ||
* | ||
* @param {Object} date An optional Date object or argument for the | ||
* Date constructor. | ||
* @param {Boolean} isLong Whether to output the short or long format. | ||
* @param {Boolean} includeTime Whether to append the time. | ||
* @return {String} The formatted date string. | ||
*/ | ||
Cute.formatDate = function (date, isLong, includeTime) { | ||
date = Cute.getDate(date) | ||
var month = date.getMonth() | ||
var day = date.getDate() | ||
var year = date.getFullYear() | ||
if (isLong) { | ||
month = Cute.i18n.months[month] | ||
} else { | ||
month++ | ||
year = ('' + year).substr(2) | ||
} | ||
var string | ||
if (!Cute.i18n.monthDay) { | ||
string = month | ||
month = day | ||
day = string | ||
} | ||
if (isLong) { | ||
string = month + ' ' + day + ', ' + year | ||
} else { | ||
string = month + '/' + day + '/' + year | ||
} | ||
if (includeTime) { | ||
if (isLong) { | ||
string += ' ' + Cute.i18n.at | ||
} | ||
string += ' ' + Cute.formatTime(date) | ||
} | ||
return string | ||
} | ||
/** | ||
* Take a date object and return a formatted time string. | ||
* | ||
* @param {Object} date An optional Date object or constructor argument. | ||
* @return {String} A formatted time value. | ||
*/ | ||
Cute.formatTime = function (date) { | ||
date = Cute.getDate(date) | ||
var hour = +date.getHours() | ||
var minute = +date.getMinutes() | ||
var isAm = 1 | ||
minute = minute > 9 ? minute : '0' + minute | ||
if (Cute.i18n.twelveHour) { | ||
if (hour > 11) { | ||
isAm = 0 | ||
if (hour > 12) { | ||
hour -= 12 | ||
} | ||
} else if (!hour) { | ||
hour = 12 | ||
} | ||
} else { | ||
hour = hour > 9 ? hour : '0' + hour | ||
} | ||
var string = hour + ':' + minute | ||
if (Cute.i18n.twelveHour) { | ||
string += (isAm ? 'am' : 'pm') | ||
} | ||
return string | ||
} | ||
/** | ||
* Get an element by its ID (if the argument is an ID). | ||
* If you pass in an element, it just returns it. | ||
* This can be used to ensure that you have an element. | ||
* | ||
* @param {DOMElement} parent Optional element to call getElementById on (default: document). | ||
* @param {string|DOMElement} idOrElement ID of an element, or the element itself. | ||
* @return {DOMElement} The matching element, or undefined. | ||
*/ | ||
Cute.id = function (parent, idOrElement) { | ||
if (!idOrElement) { | ||
idOrElement = parent | ||
parent = document | ||
} | ||
return Cute.isString(idOrElement) ? parent.getElementById(idOrElement) : idOrElement | ||
} | ||
/** | ||
* Get or set the parent of an element. | ||
* | ||
* @param {DOMElement} element A element whose parent we want to get/set. | ||
* @param {String} parent An optional parent to add the element to. | ||
* @param {String} before An optional child to insert the element before. | ||
* @return {DOMElement} The parent of the element. | ||
*/ | ||
Cute.parent = function (element, parent, before) { | ||
if (parent) { | ||
parent.insertBefore(element, before || null) | ||
} else { | ||
parent = element.parentNode | ||
} | ||
return parent | ||
} | ||
/** | ||
* Get an element's ancestors, optionally filtered by a selector. | ||
* | ||
* @param {DOMElement} element An element to start from. | ||
* @param {String} selector An optional selector to filter ancestors. | ||
* @return {Array} The array of ancestors. | ||
*/ | ||
Cute.up = function (element, selector) { | ||
var ancestors = [] | ||
while (element = Cute.parent(element)) { // eslint-disable-line | ||
ancestors.push(element) | ||
} | ||
ancestors = Cute.filter(ancestors, function (element) { | ||
return Cute.matches(element, selector) | ||
}) | ||
return ancestors | ||
} | ||
/** | ||
* Get the child nodes of a parent element. | ||
* | ||
* @param {DOMElement} element A parent element who might have child nodes. | ||
* @return {HTMLCollection} The collection of child nodes. | ||
*/ | ||
Cute.nodes = function (element) { | ||
return element.childNodes | ||
} | ||
/** | ||
* Get an element's index with respect to its parent. | ||
* | ||
* @param {DOMElement} element An element with a parent, and potentially siblings. | ||
* @return {Number} The element's index, or -1 if there's no matching element. | ||
*/ | ||
Cute.index = function (element) { | ||
var index = -1 | ||
while (element) { | ||
++index | ||
element = element.previousSibling | ||
} | ||
return index | ||
} | ||
/** | ||
* Create an element, given a specified tag identifier. | ||
* | ||
* Identifiers are of the form: | ||
* tagName#id.class1.class2?attr1=value1&attr2=value2 | ||
* | ||
* Each part of the identifier is optional. | ||
* | ||
* @param {DOMElement|String} elementOrString An element or a string used to create an element (default: div). | ||
* @return {DOMElement} The existing or created element. | ||
*/ | ||
Cute.create = function (elementOrString) { | ||
var element = elementOrString | ||
if (Cute.isString(elementOrString)) { | ||
var tagAndAttributes = elementOrString.split('?') | ||
var tagAndClass = tagAndAttributes[0].split('.') | ||
var className = tagAndClass.slice(1).join(' ') | ||
var tagAndId = tagAndClass[0].split('#') | ||
var tagName = tagAndId[0] || 'div' | ||
var id = tagAndId[1] | ||
var attributes = tagAndAttributes[1] | ||
var isSvg = /^(svg|g|path|circle|line)$/.test(tagName) | ||
var uri = 'http://www.w3.org/' + (isSvg ? '2000/svg' : '1999/xhtml') | ||
element = document.createElementNS(uri, tagName) | ||
if (id) { | ||
element.id = id | ||
} | ||
if (className) { | ||
element.className = className | ||
} | ||
// TODO: Do something less janky than using query string syntax (Maybe like Ltl?). | ||
if (attributes) { | ||
attributes = attributes.split('&') | ||
Cute.each(attributes, function (attribute) { | ||
var keyAndValue = attribute.split('=') | ||
var key = keyAndValue[0] | ||
var value = keyAndValue[1] | ||
element[key] = value | ||
Cute.attr(element, key, value) | ||
}) | ||
} | ||
} | ||
return element | ||
} | ||
/** | ||
* Add a child element under a parent element, optionally before another element. | ||
* | ||
* @param {DOMElement} parent An optional parent element (default: document). | ||
* @param {DOMElement|String} elementOrString An element or a string used to create an element (default: div). | ||
* @param {DOMElement} beforeSibling An optional child to insert the element before. | ||
* @return {DOMElement} The element that was inserted. | ||
*/ | ||
Cute.add = function (parent, elementOrString, beforeSibling) { | ||
if (Cute.isString(parent)) { | ||
beforeSibling = elementOrString | ||
elementOrString = parent | ||
parent = document.body | ||
} | ||
var element = Cute.create(elementOrString) | ||
// If the beforeSibling value is a number, get the (future) sibling at that index. | ||
if (Cute.isNumber(beforeSibling)) { | ||
beforeSibling = Cute.nodes(parent)[beforeSibling] | ||
} | ||
// Insert the element, optionally before an existing sibling. | ||
if (beforeSibling) { | ||
parent.insertBefore(element, beforeSibling) | ||
} else { | ||
parent.appendChild(element) | ||
} | ||
return element | ||
} | ||
/** | ||
* Remove an element from its parent. | ||
* | ||
* @param {DOMElement} element An element to remove. | ||
*/ | ||
Cute.remove = function (element) { | ||
// Remove the element from its parent, provided that it has a parent. | ||
var parent = Cute.parent(element) | ||
if (parent) { | ||
parent.removeChild(element) | ||
} | ||
} | ||
/** | ||
* Get or set an element's inner HTML. | ||
* | ||
* @param {DOMElement} element An element. | ||
* @param {String} html An optional string of HTML to set as the innerHTML. | ||
* @return {String} The element's HTML. | ||
*/ | ||
Cute.html = function (element, html) { | ||
if (!Cute.isUndefined(html)) { | ||
element.innerHTML = html | ||
} | ||
return element.innerHTML | ||
} | ||
/** | ||
* Get an element's lowercase tag name. | ||
* | ||
* @param {DOMElement} element An element. | ||
* @return {String} The element's tag name. | ||
*/ | ||
Cute.tag = function (element) { | ||
return Cute.lower(element.tagName) | ||
} | ||
/** | ||
* Get or set the text of an element. | ||
* | ||
* @param {DOMElement} element An optional element. | ||
* @return {String} text A text string to set. | ||
*/ | ||
Cute.text = function (element, text) { | ||
if (!Cute.isUndefined(text)) { | ||
Cute.html(element, '') | ||
Cute.addText(element, text) | ||
} | ||
// Get the full text, but fall back to visible text for older browsers. | ||
return element.textContent || element.innerText | ||
} | ||
/** | ||
* Add text to an element. | ||
* | ||
* @param {DOMElement} element An element. | ||
* @return {String} text A text string to add. | ||
*/ | ||
Cute.addText = function (element, text, beforeSibling) { | ||
Cute.add(element, document.createTextNode(text), beforeSibling) | ||
} | ||
/** | ||
* Get, set, or delete an attribute of an element. | ||
* | ||
* @param {DOMElement} element An element. | ||
* @param {String} name An attribute name. | ||
* @param {String} value A value to set the attribute to. | ||
* @return {String} The value of the attribute. | ||
*/ | ||
Cute.attr = function (element, name, value) { | ||
if (Cute.isNull(value)) { | ||
element.removeAttribute(name) | ||
} else if (Cute.isUndefined(value)) { | ||
value = element.getAttribute(name) | ||
} else { | ||
var old = Cute.attr(element, name) | ||
if (value !== old) { | ||
element.setAttribute(name, value) | ||
} | ||
} | ||
return value | ||
} | ||
/** | ||
* Add, remove or check classes on an element. | ||
* | ||
* @param {DOMElement} element An element to change or read classes from. | ||
* @param {String} operations Space-delimited operations to perform on | ||
* an element's className. | ||
* * "!name" adds the "name" class if not | ||
* present, or removes it if present. | ||
* * "+name" adds the "name" class. | ||
* * "-name" removes the "name" class. | ||
* * "name" returns 1 if the "name" class | ||
* is present, or undefined if it isn't. | ||
* @return {Object} The map of all classes in the element's | ||
* className, or 1 or undefined if the last queried class was found. | ||
*/ | ||
Cute.classes = function (element, operations) { | ||
var map = {} | ||
var result = map | ||
var list = Cute.string(element.className).match(/\S+/g) | ||
Cute.each(list, function (key) { | ||
map[key] = 1 | ||
}) | ||
if (operations) { | ||
operations.replace(/([!\+-]*)?(\S+)/g, function (match, op, key) { | ||
var value = map[key] | ||
if (op === '!') { | ||
value = !value | ||
} else if (op === '+') { | ||
value = 1 | ||
} else if (op === '-') { | ||
value = 0 | ||
} else { | ||
result = value ? 1 : 0 | ||
} | ||
map[key] = value | ||
}) | ||
list = [] | ||
Cute.each(map, function (value, key) { | ||
if (value) { | ||
list.push(key) | ||
} | ||
}) | ||
element.className = list.join(' ') | ||
} | ||
return result | ||
} | ||
/** | ||
* Find elements matching a selector, and return or run a function on them. | ||
* | ||
* Selectors are not fully querySelector compatible. | ||
* Selectors only support commas, spaces, IDs, tags & classes. | ||
* | ||
* @param {DOMElement} parent An optional element under which to find elements. | ||
* @param {String} selector A simple selector for finding elements. | ||
* @param {Function} fn An optional function to run on matching elements. | ||
* @return {HTMLCollection} The matching elements (if any). | ||
*/ | ||
Cute.all = function (parent, selector, fn) { | ||
if (!selector || Cute.isFunction(selector)) { | ||
fn = selector | ||
selector = parent | ||
parent = document | ||
} | ||
var elements = parent.querySelectorAll(selector) | ||
if (fn) { | ||
Cute.each(elements, fn) | ||
} | ||
return elements | ||
} | ||
/** | ||
* Find an element matching a selector, optionally run a function on it, and return it. | ||
* | ||
* @param {DOMElement} parent An optional element under which to find an element. | ||
* @param {String} selector A simple selector for finding an element. | ||
* @param {Function} fn An optional function to run on a matching element. | ||
* @return {DOMElement} The matching element (if any). | ||
*/ | ||
Cute.one = function (parent, selector, fn) { | ||
if (!selector || Cute.isFunction(selector)) { | ||
fn = selector | ||
selector = parent | ||
parent = document | ||
} | ||
var element = parent.querySelector(selector) | ||
if (element && fn) { | ||
fn(element) | ||
} | ||
return element | ||
} | ||
/** | ||
* Update a DOM node based on the contents of another. | ||
* | ||
* @param {DOMElement} domNode The DOM node to merge into. | ||
* @param {DOMElement} newNode The virtual DOM to merge from. | ||
*/ | ||
Cute.update = function (domNode, newNode) { | ||
var domChild = domNode.firstChild || 0 | ||
var newChild = newNode.firstChild || 0 | ||
while (newChild) { | ||
var domTag = domChild.tagName | ||
var newTag = newChild.tagName | ||
var domNext = domChild.nextSibling || 0 | ||
var newNext = newChild.nextSibling || 0 | ||
if ((domTag !== newTag) || Cute.lower(newTag) === 'svg') { | ||
domNode.insertBefore(newChild, domChild || null) | ||
if (domChild) { | ||
domNode.removeChild(domChild) | ||
} | ||
domChild = domNext | ||
} else { | ||
if (newTag) { | ||
Cute.update(domChild, newChild) | ||
} else if (domChild) { | ||
domChild.textContent = newChild.textContent | ||
} else { | ||
domNode.appendChild(newChild) | ||
} | ||
domChild = domNext | ||
} | ||
newChild = newNext | ||
} | ||
while (domChild) { | ||
domNext = domChild.nextSibling | ||
domNode.removeChild(domChild) | ||
domChild = domNext | ||
} | ||
var map = {} | ||
function mapAttributes (element, index) { | ||
Cute.each(element.attributes, function (attribute) { | ||
map[attribute.name] = index ? attribute.value : null | ||
}) | ||
} | ||
mapAttributes(domNode, 0) | ||
mapAttributes(newNode, 1) | ||
Cute.each(map, function (value, name) { | ||
Cute.attr(domNode, name, value) | ||
}) | ||
} | ||
/** | ||
* Event Handlers | ||
* @type {Object} | ||
*/ | ||
Cute._handlers = {} | ||
/** | ||
* Listen for one or more events, optionally on a given element. | ||
* | ||
* @param {String|DOMElement} target An optional selector or element. | ||
* @param {String|Array} types A list of events to listen for. | ||
* @param {Function} listener A callback function. | ||
*/ | ||
Cute.on = function (target, types, listener) { | ||
if (!listener) { | ||
listener = types | ||
types = target | ||
target = document | ||
} | ||
var element = Cute.isString(target) ? document : target | ||
types = types.split(/\s+/) | ||
Cute.each(types, function (type) { | ||
var handlers = Cute._handlers[type] | ||
if (!handlers) { | ||
handlers = Cute._handlers[type] = [] | ||
if (element.addEventListener) { | ||
element.addEventListener(type, Cute._propagate) | ||
} else if (element.attachEvent) { | ||
element.attachEvent('on' + type, Cute._propagate) | ||
} else { | ||
element['on' + type] = Cute._propagate | ||
} | ||
} | ||
handlers.push({t: target, f: listener}) | ||
}) | ||
} | ||
/** | ||
* Remove a listener for one event type. | ||
* | ||
* @param {String} types Types of event to stop listening for. | ||
* @param {Function} listener A listener function to remove. | ||
*/ | ||
Cute.off = function (types, listener) { | ||
types = types.split(/\s+/) | ||
Cute.each(types, function (type) { | ||
var handlers = Cute._handlers[type] | ||
Cute.each(handlers, function (item, index) { | ||
if (item && (item.f === listener)) { | ||
delete handlers[index] | ||
} | ||
}) | ||
}) | ||
} | ||
/** | ||
* Listen for one or more events, optionally on a given element, and ensure that the | ||
* listener will only be executed once. | ||
* | ||
* @param {String|DOMElement} target An optional selector or element. | ||
* @param {String|Array} types A list of events to listen for. | ||
* @param {Function} listener A function to execute when an event occurs. | ||
*/ | ||
Cute.once = function (target, types, listener) { | ||
var onceFn = function (target, type, event) { | ||
Cute.off(types, onceFn) | ||
listener.apply(target, arguments) | ||
} | ||
Cute.on(target, types, onceFn) | ||
} | ||
/** | ||
* Simulate an event. | ||
* | ||
* @param {DOMElement} target A target to start propagation from. | ||
* @param {String} event A type of event. | ||
* @param {Object} data Optional data to report with the event. | ||
*/ | ||
Cute.emit = function (target, type, data) { | ||
Cute._propagate({ | ||
type: type, | ||
target: target, | ||
data: data | ||
}) | ||
} | ||
/** | ||
* Propagate an event from a target element up to the DOM root. | ||
* | ||
* @param {Object} event An event to propagate: | ||
* { | ||
* type: String, // An event type (e.g.) "click". | ||
* target: Object, // The element where the event occurred. | ||
* data: Object // Optional event data. | ||
* } | ||
*/ | ||
Cute._propagate = function (event) { | ||
// Get the window-level event if an event isn't passed. | ||
event = event || window.event | ||
// Reference the event target. | ||
var eventTarget = event.target || event.srcElement || document | ||
// Extract the event type. | ||
var type = event.type | ||
// Propagate the event up through the target's DOM parents. | ||
var element = eventTarget | ||
var handlers = Cute._handlers[type] | ||
while (element && !event.stop) { | ||
Cute.each(handlers, function (handler) { | ||
if (handler) { | ||
var target = handler.t | ||
var fn = handler.f | ||
var isMatch = Cute.isString(target) | ||
? Cute.matches(element, target) | ||
: (element === target) | ||
if (isMatch) { | ||
fn(eventTarget, type, event) | ||
} | ||
return !event.stop | ||
} | ||
}) | ||
if (element === document) { | ||
break | ||
} | ||
element = Cute.parent(element) | ||
} | ||
} | ||
/** | ||
* Find out if an element matches a given selector. | ||
* | ||
* @param {DOMElement} element An element to pretend the event occurred on. | ||
* @param {String} selector A CSS selector to check against an element. | ||
* @return {Boolean} True if the element (this) matches the selector. | ||
*/ | ||
Cute.matches = function (element, selector) { | ||
var matches = | ||
element.webkitMatchesSelector || | ||
element.msMatchesSelector || | ||
element.mozMatchesSelector || | ||
element.oMatchesSelector || | ||
element.matchesSelector || | ||
element.matches || Cute.no | ||
var isMatch = matches.call(element, selector) | ||
return isMatch | ||
} | ||
/** | ||
* Prevent the default action for this event. | ||
* | ||
* @param {Event} event Event to prevent from doing its default action. | ||
*/ | ||
Cute.prevent = function (event) { | ||
Cute.apply(event, 'preventDefault') | ||
} | ||
/** | ||
* Stop an event from bubbling or performing its default action. | ||
* | ||
* @param {Event} event Event to stop. | ||
*/ | ||
Cute.stop = function (event) { | ||
event.stop = 1 | ||
Cute.prevent(event) | ||
} | ||
/** | ||
* Focus on a specified element. | ||
* | ||
* @param {DOMElement} element The element to focus on. | ||
*/ | ||
Cute.focus = function (element) { | ||
Cute.apply(element, 'focus') | ||
} | ||
/** | ||
* Get or set the value of a form element. | ||
* | ||
* @param {DOMElement} input A form element. | ||
* @param {String|Array} newValue An optional new value for the element. | ||
* @return {String|Array} The current or new value. | ||
*/ | ||
Cute.value = function (input, newValue) { | ||
if (!input) { | ||
return | ||
} | ||
var type = input.type[0] | ||
var value = input.value | ||
var options = input.options | ||
var setNew = arguments.length > 1 | ||
var items, isMulti, flag | ||
if (type === 'c' || type === 'r') { | ||
var form = input.form || document | ||
var selector = 'input[name=' + input.name + ']' | ||
items = Cute.all(form, selector) | ||
isMulti = (type === 'c' && items.length > 1) | ||
flag = 'checked' | ||
} else if (options) { | ||
items = options | ||
isMulti = input.multiple | ||
flag = 'selected' | ||
} | ||
if (items) { | ||
var matches = {} | ||
var array = Cute.array(newValue) | ||
Cute.each(array, function (value) { | ||
matches[value] = 1 | ||
}) | ||
value = [] | ||
Cute.each(items, function (input) { | ||
var isMatch = !!matches[input.value] | ||
if (setNew) { | ||
input[flag] = isMatch | ||
} else if (input[flag]) { | ||
value.push(input.value) | ||
} | ||
}) | ||
if (!isMulti) { | ||
value = value[0] | ||
} | ||
} else if (setNew) { | ||
input.value = newValue | ||
} | ||
return setNew ? newValue : value | ||
} | ||
/** | ||
* Empty handler. | ||
* @type {Function} | ||
*/ | ||
Cute.no = function () {} | ||
/** | ||
* Apply arguments to an object method. | ||
* | ||
* @param {Object} object An object with methods. | ||
* @param {String} methodName A method name, which may exist on the object. | ||
* @param {Array} args An array to apply to the method. | ||
* @return {Object} The result returned by the object method. | ||
*/ | ||
Cute.apply = function (object, methodName, args) { | ||
return ((object || 0)[methodName] || Cute.no).apply(object, args) | ||
} | ||
/** | ||
* Try to apply arguments to an object method. | ||
* | ||
* @param {Object} object An object with methods. | ||
* @param {String} methodName A method name, which may exist on the object. | ||
* @param {Array} args An array to apply to the method. | ||
* @return {Object} The result returned by the object method. | ||
*/ | ||
Cute.attempt = function (object, methodName, args) { | ||
try { | ||
Cute.apply(object, methodName, args) | ||
} catch (ignore) { | ||
} | ||
} | ||
/** | ||
* Push, replace or pop a history item. | ||
* | ||
* @param {String} href An optional href to visit (or falsy to go back). | ||
* @param {Boolean} inPlace Whether to just replace the current state. | ||
*/ | ||
Cute.go = function (href, inPlace) { | ||
var history = window.history | ||
var method = | ||
href === -1 ? 'back' | ||
: href === 1 ? 'forward' | ||
: (inPlace ? 'replace' : 'push') + 'State' | ||
Cute.attempt(history, method, [undefined, undefined, href]) | ||
return history | ||
} | ||
/** | ||
* The values in this file can be overridden externally. | ||
* The default locale is US. Sorry, World. | ||
*/ | ||
Cute.i18n = { | ||
// Names of months. | ||
months: [ | ||
'January', 'February', 'March', 'April', 'May', 'June', | ||
'July', 'August', 'September', 'October', 'November', 'December' | ||
], | ||
// A word for separating date & time in long format. | ||
at: 'at', | ||
// Whether to use American-style MM/DD/YY. | ||
monthDay: 1, | ||
// Whether to use 12-hour instead of 24-hour times. | ||
twelveHour: 1, | ||
// Whether to use Fahrenheit. | ||
fahrenheit: 1 | ||
} | ||
/** | ||
* Creates a JSON string. | ||
* | ||
* @param {Any} data Data to stringify. | ||
* @return {String} A JSON string. | ||
*/ | ||
Cute.stringify = function (data, _stack) { | ||
if (Cute.isDate(data) || | ||
data && Cute.isFunction(data.toJSON) || | ||
Cute.isString(data)) { | ||
data = JSON.stringify(data) | ||
} else if (Cute.isFunction(data) || Cute.isUndefined(data)) { | ||
return _stack ? 'null' : undefined | ||
} else if (data && Cute.isObject(data) && !(data instanceof Boolean) && !(data instanceof Number)) { | ||
_stack = _stack || [] | ||
var isCircular | ||
Cute.each(_stack, function (item) { | ||
if (item === data) { | ||
isCircular = 1 | ||
} | ||
}) | ||
if (isCircular) { | ||
return '"[Circular ' + (_stack.length) + ']"' | ||
} | ||
_stack.push(data) | ||
var isArray = Cute.isArray(data) | ||
var parts = [] | ||
Cute.each(data, function (value, key) { | ||
value = Cute.stringify(value, _stack) | ||
parts.push(isArray ? value : Cute.stringify(key) + ':' + value) | ||
}) | ||
_stack.pop() | ||
data = (isArray ? '[' : '{') + parts.join(',') + (isArray ? ']' : '}') | ||
} else { | ||
data = Cute.string(data) | ||
} | ||
return data | ||
} | ||
/** | ||
* Create a JSON string with its double quotes escaped. | ||
* | ||
* @param {Any} data Data to stringify. | ||
* @return {String} A JSON string with escaped quotes. | ||
*/ | ||
Cute.attrify = function (data) { | ||
return Cute.stringify(data).replace(/"/g, '"') | ||
} | ||
/** | ||
* Parse JSON (or JavaScript) and return a value. | ||
* | ||
* @param {String} js JSON (or JavaScript). | ||
* @param {Any} alternative Fallback value if an error occurs. | ||
* @return {Any} Value of the JSON/JS or fallback. | ||
*/ | ||
Cute.parse = function (js, alternative) { | ||
try { | ||
/* eslint-disable */ | ||
eval('eval.J=' + js) | ||
js = eval.J | ||
/* eslint-enable */ | ||
} catch (ignore) { | ||
//+env:debug | ||
Cute.error('[Cute] Could not parse JS: ' + js) | ||
//-env:debug | ||
js = alternative | ||
} | ||
return js | ||
} | ||
/** | ||
* Run some JavaScript. | ||
* | ||
* @param {String} js JavaScript code to run. | ||
*/ | ||
Cute.run = function (js) { | ||
Cute.parse('0;' + js) | ||
} | ||
// When not in debug mode, make the logging functions do nothing. | ||
Cute.error = Cute.no | ||
Cute.warn = Cute.no | ||
Cute.info = Cute.no | ||
Cute.log = Cute.no | ||
Cute.trace = Cute.no | ||
//+env:debug | ||
/** | ||
* Log values to the console, if it's available. | ||
*/ | ||
Cute.error = function () { | ||
Cute.apply(window.console, 'error', arguments) | ||
} | ||
/** | ||
* Log values to the console, if it's available. | ||
*/ | ||
Cute.warn = function () { | ||
Cute.apply(window.console, 'warn', arguments) | ||
} | ||
/** | ||
* Log values to the console, if it's available. | ||
*/ | ||
Cute.info = function () { | ||
Cute.apply(window.console, 'info', arguments) | ||
} | ||
/** | ||
* Log values to the console, if it's available. | ||
*/ | ||
Cute.log = function () { | ||
Cute.apply(window.console, 'log', arguments) | ||
} | ||
/** | ||
* Log values to the console, if it's available. | ||
*/ | ||
Cute.trace = function () { | ||
Cute.apply(window.console, 'trace', arguments) | ||
} | ||
//-env:debug | ||
/** | ||
* If the argument is numeric, return a number, otherwise return zero. | ||
* | ||
* @param {Any} value A value to convert to a number, if necessary. | ||
* @return {Number} The number, or zero. | ||
*/ | ||
Cute.number = function (value) { | ||
return isNaN(value *= 1) ? 0 : (value || 0) | ||
} | ||
/** | ||
* Repeat a string a specified number of times. | ||
* | ||
* @param {String} string A string to repeat. | ||
* @param {Number} times A number of times to repeat the string. | ||
* @return {String} The resulting string. | ||
*/ | ||
Cute.repeat = function (string, times) { | ||
return (new Array(times + 1)).join(string) | ||
} | ||
/** | ||
* Pad a number with zeros or a string with spaces. | ||
* | ||
* @param {Number|String} value A value to pad. | ||
* @param {Number} length A length to pad to. | ||
* @return {String} The padded value. | ||
*/ | ||
Cute.pad = function (value, length) { | ||
// Repurpose the length variable to count how much padding we need. | ||
length = Math.max(length - Cute.string(value).length, 0) | ||
// Pad based on type. | ||
if (Cute.isNumber(value)) { | ||
value = Cute.repeat('0', length) + value | ||
} else { | ||
value = value + Cute.repeat(' ', length) | ||
} | ||
return value | ||
} | ||
/** | ||
* Get the <head> element from the document. | ||
* | ||
* @return {DOMElement} The <head> element. | ||
*/ | ||
Cute.head = function () { | ||
return Cute.one('head') | ||
} | ||
/** | ||
* Get the <head> element from the document. | ||
* | ||
* @return {DOMElement} The <head> element. | ||
*/ | ||
Cute.body = function () { | ||
return Cute.one('body') | ||
} | ||
/** | ||
* Insert an external JavaScript file. | ||
* | ||
* @param {String} src A source URL of a script to insert. | ||
* @param {Function} fn An optional function to run when the script loads. | ||
*/ | ||
Cute.js = function (src, fn) { | ||
var head = Cute.head() | ||
var script = Cute.add(head, 'script') | ||
if (fn) { | ||
Cute.ready(script, fn) | ||
} | ||
script.async = true | ||
script.src = src | ||
} | ||
/** | ||
* Insert CSS text to the page. | ||
* | ||
* @param {String} css CSS text to be inserted. | ||
*/ | ||
Cute.css = function (css) { | ||
var head = Cute.head() | ||
var style = Cute.add(head, 'style') | ||
Cute.text(style, css) | ||
var sheet = style.styleSheet | ||
if (sheet) { | ||
sheet.cssText = css | ||
} | ||
} | ||
/** | ||
* Scale CSS pixel sizes using a window property. | ||
* | ||
* @param {String} css CSS text to be zoomed. | ||
*/ | ||
Cute.zoom = function (css) { | ||
var zoom = window._zoom || 1 | ||
return css.replace(/([\.\d]+)px\b/g, function (match, n) { | ||
return Math.floor(n * zoom) + 'px' | ||
}) | ||
} | ||
/** | ||
* Execute a function when the page loads or new content is added. | ||
* | ||
* @param {Function} listener A function which will receive a ready element. | ||
*/ | ||
Cute.ready = function (object, listener) { | ||
if (!listener) { | ||
listener = object | ||
object = document | ||
} | ||
// If the object is alreay ready, run the function now. | ||
if (Cute.isReady(object)) { | ||
listener(object) | ||
} else { | ||
// Create a function that replaces itself so it will only run once. | ||
var fn = function () { | ||
if (Cute.isReady(object)) { | ||
Cute.isReady(object, 1) | ||
listener(object) | ||
listener = Cute.no | ||
} | ||
} | ||
// Bind using multiple methods for a variety of browsers. | ||
Cute.on(object, 'readystatechange DOMContentLoaded', fn) | ||
Cute.on(object === document ? window : object, 'load', fn) | ||
// Bind to the Cute-triggered ready event. | ||
Cute.on(object, '_ready', fn) | ||
} | ||
} | ||
/** | ||
* Get or set the readiness status of an object. | ||
* | ||
* @param {Object} object The object that might be ready. | ||
* @param {Boolean} setReady Whether to . | ||
* @return {Boolean} Whether the object is currently ready. | ||
*/ | ||
Cute.isReady = function (object, setReady) { | ||
// Declare an object to be ready, and run events that have been bound to it. | ||
if (setReady && !object._ready) { | ||
object._ready = 1 | ||
Cute.emit(object, '_ready') | ||
} | ||
// AJAX requests have readyState 4 when loaded. | ||
// All documents will reach readyState=="complete". | ||
// In IE, scripts can reach readyState=="loaded" or readyState=="complete". | ||
return object._ready || /(4|complete|scriptloaded)$/.test('' + object.tagName + object.readyState) | ||
} | ||
/** | ||
* Get the contents of a specified type of tag within a string of HTML. | ||
* | ||
* @param {String} html A string of HTML. | ||
* @param {String} tagName The type of tag to find. | ||
* @param {Function} fn A function to call on each content block. | ||
* @return {Array} The array of contents. | ||
*/ | ||
Cute.tagContents = function (html, tagName, fn) { | ||
var pattern = Cute.tagPatterns[tagName] | ||
if (!pattern) { | ||
var flags = /^(html|head|title|body)$/.test(tagName) ? 'i' : 'gi' | ||
pattern = new RegExp('<' + tagName + '.*?>([\\s\\S]*?)<\\/' + tagName + '>', flags) | ||
Cute.tagPatterns[tagName] = pattern | ||
} | ||
var contents = [] | ||
html.replace(pattern, function (match, content) { | ||
contents.push(content) | ||
if (fn) { | ||
fn(content) | ||
} | ||
}) | ||
return contents | ||
} | ||
Cute.tagPatterns = {} | ||
/** | ||
* Get or set an item in local storage. | ||
* | ||
* @param {String} key A key to fetch an object by. | ||
* @param {Any} value A value to be stringified and stored. | ||
* @return {Any} The object that was fetched and deserialized | ||
*/ | ||
Cute.item = function (key, value) { | ||
var storage = window.localStorage | ||
// If no value is passed in, get a value. | ||
if (Cute.isUndefined(value)) { | ||
value = storage.getItem(key) | ||
value = Cute.parse(value, value) | ||
// A null value indicates that we want the actual value to be removed. | ||
} else if (Cute.isNull(value)) { | ||
storage.removeItem(key) | ||
value = undefined | ||
// If a non-null value is passed in, store it. | ||
} else { | ||
storage.setItem(key, Cute.stringify(value)) | ||
} | ||
return value | ||
} | ||
/** | ||
* Return true if the string contains the given substring. | ||
* | ||
* @param {String} string A string to search within. | ||
* @param {String} substring A substring to search for. | ||
* @return {Boolean} True if the string contains the substring. | ||
*/ | ||
Cute.contains = function (string, substring) { | ||
return Cute.string(string).indexOf(substring) > -1 | ||
} | ||
/** | ||
* Return true if the string starts with the given substring. | ||
* | ||
* @param {String} string A string to search within. | ||
* @param {String} beginning A substring to search for. | ||
* @return {Boolean} True if the string starts with the substring. | ||
*/ | ||
Cute.startsWith = function (string, beginning) { | ||
return Cute.string(string).indexOf(beginning) === 0 | ||
} | ||
/** | ||
* Returns true if the string end with the given substring. | ||
* | ||
* @param {String} string A string to search within. | ||
* @param {String} ending A substring to search for. | ||
* @return {Boolean} True if the string ends with the substring. | ||
*/ | ||
Cute.endsWith = function (string, ending) { | ||
string = Cute.string(string) | ||
return string.indexOf(ending) === (string.length - ending.length) | ||
} | ||
/** | ||
* Trim the whitespace from a string. | ||
* | ||
* @param {String} string A string to trim. | ||
* @return {String} The trimmed string. | ||
*/ | ||
Cute.trim = function (string) { | ||
return Cute.string(string).replace(/^\s+|\s+$/g, '') | ||
} | ||
/** | ||
* Split a string by commas. | ||
* | ||
* @param {String} string A string to split. | ||
* @return {Array} The comma-delimited contents of the string. | ||
*/ | ||
Cute.split = function (string) { | ||
return Cute.string(string).split(',') | ||
} | ||
/** | ||
* Convert a string to lower case. | ||
* | ||
* @param {String} string A string to convert to lower case. | ||
* @return {String} The lowercase string. | ||
*/ | ||
Cute.lower = function (string) { | ||
return Cute.string(string).toLowerCase() | ||
} | ||
/** | ||
* Convert a string to an upper case. | ||
* | ||
* @param {String} string A string to convert to upper case. | ||
* @return {String} The uppercase string. | ||
*/ | ||
Cute.upper = function (string) { | ||
return Cute.string(string).toUpperCase() | ||
} | ||
/** | ||
* Measure the length of a string. | ||
* | ||
* @param {String} string A string to measure. | ||
* @return {Number} The string length. | ||
*/ | ||
Cute.length = function (string) { | ||
return Cute.string(string).length | ||
} | ||
/** | ||
* Return an encoded string for URLs. | ||
* | ||
* @param {String} string A string to escape. | ||
* @return {String} The escaped string. | ||
*/ | ||
Cute.encode = function (string) { | ||
return encodeURIComponent(Cute.string(string)) | ||
} | ||
/** | ||
* Return the decoded version of an encoded URL component. | ||
* | ||
* @param {String} string A string to decode. | ||
* @return {String} The decoded string. | ||
*/ | ||
Cute.decode = function (string) { | ||
return decodeURIComponent(Cute.string(string)) | ||
} | ||
/** | ||
* Set style properties on a given element. | ||
* | ||
* @param {DOMElement} element Element to set style properties on. | ||
* @param {Object} map Optional style property map. | ||
* @return {Object} Style property of the element. | ||
*/ | ||
Cute.style = function (element, map) { | ||
var style = Cute.prop(element, 'style', 0) | ||
Cute.each(map, function (value, key) { | ||
style[key] = value | ||
}) | ||
return style | ||
} | ||
/** | ||
* Scroll a page to a position or element. | ||
* | ||
* @param {Integer|String|Object} to A name, ID, element or Top/Left. | ||
* @param {String} direction Default: "Top". | ||
*/ | ||
Cute.scroll = function (to, direction) { | ||
direction = direction || 'Top' | ||
if (Cute.isString(to)) { | ||
to = Cute.one('a[name=' + to + '],#' + to) | ||
} | ||
if (to && Cute.isObject(to)) { | ||
var element = to | ||
to = 0 | ||
while (element) { | ||
to += element['offset' + direction] || 0 | ||
element = element.offsetParent | ||
} | ||
} | ||
var body = Cute.body() | ||
var key = 'scroll' + direction | ||
if (Cute.isNumber(to)) { | ||
body[key] = document.documentElement[key] = to | ||
} | ||
return body[key] | ||
} | ||
/** | ||
* Get or set the width and height of an element. | ||
* | ||
* @param {DOMElement} element Element to measure or resize. | ||
* @param {Array} size Optional width and height. | ||
* @return {Array} Width and height. | ||
*/ | ||
Cute.size = function (element, size) { | ||
element = element || 0 | ||
if (size) { | ||
Cute.style(element, {width: size[0], height: size[1]}) | ||
} else { | ||
size = [element.offsetWidth || 0, element.offsetHeight || 0] | ||
} | ||
return size | ||
} | ||
/** | ||
* Get or set the left and top of an element. | ||
* | ||
* @param {DOMElement} element Element to measure or resize. | ||
* @param {Array} position Optional left and top. | ||
* @return {Array} Left and top. | ||
*/ | ||
Cute.position = function (element, position) { | ||
element = element || 0 | ||
if (position) { | ||
Cute.style(element, {left: position[0], top: position[1]}) | ||
} else { | ||
position = [element.offsetLeft || 0, element.offsetTop || 0] | ||
} | ||
return position | ||
} | ||
/** | ||
* Get the width and height of the viewport as an array. | ||
* | ||
* @return {Array} [width, height] | ||
*/ | ||
Cute.viewport = function () { | ||
function dim (key) { | ||
return Math.max(document.documentElement['client' + key] || 0, window['inner' + key] || 0) | ||
} | ||
return [dim('Width'), dim('Height')] | ||
} | ||
/** | ||
* Set or clear a timeout or interval. If set, save it for possible clearing. | ||
* | ||
* @param {Object} object An object to bind a timer to. | ||
* @param (String) name A name for the timer. | ||
* @param {Function} fn A function to run if the timer is reached. | ||
* @param {Integer} delay An optional delay in milliseconds. | ||
* @param {Boolean} recur Whether to occur regularly (i.e. setInterval). | ||
*/ | ||
Cute.wait = function (object, name, fn, delay, recur) { | ||
var map = Cute.prop(object, '_wait', {}) | ||
clearTimeout(map[name]) | ||
if (fn) { | ||
if (Cute.isUndefined(delay)) { | ||
delay = 9 | ||
} | ||
map[name] = (recur ? setInterval : setTimeout)(fn, delay) | ||
} | ||
} | ||
Cute._times = {} | ||
Cute.t = function () { | ||
return (window.performance || Date).now() | ||
} | ||
Cute.start = function (label) { | ||
Cute._times[label] = Cute.t() | ||
} | ||
Cute.end = function (label) { | ||
Cute._times[label] = Cute.t() - Cute._times[label] | ||
} | ||
Cute.logTimes = function () { | ||
var times = [] | ||
Cute.each(Cute._times, function (value, key) { | ||
times.push(key + ' ' + value.toFixed(3) + 'ms') | ||
}) | ||
Cute.log(times.join(', ')) | ||
} | ||
/** | ||
* Check whether a value is undefined. | ||
* | ||
* @param {Any} value A value to check. | ||
* @return {Boolean} True if the value is undefined. | ||
*/ | ||
Cute.isUndefined = function (value) { | ||
return typeof value === 'undefined' | ||
} | ||
/** | ||
* Check whether a value is a boolean. | ||
* | ||
* @param {Any} value A value to check. | ||
* @return {Boolean} True if the value is a boolean. | ||
*/ | ||
Cute.isBoolean = function (value) { | ||
return typeof value === 'boolean' || value instanceof Boolean | ||
} | ||
/** | ||
* Check whether a value is a number. | ||
* | ||
* @param {Any} value A value to check. | ||
* @return {Boolean} True if the value is a number. | ||
*/ | ||
Cute.isNumber = function (value) { | ||
return typeof value === 'number' || value instanceof Number | ||
} | ||
/** | ||
* Check whether a value is a string. | ||
* | ||
* @param {Any} value A value to check. | ||
* @return {Boolean} True if the value is a string. | ||
*/ | ||
Cute.isString = function (value) { | ||
return typeof value === 'string' || value instanceof String | ||
} | ||
/** | ||
* Check whether a value is a function. | ||
* | ||
* @param {Any} value A value to check. | ||
* @return {Boolean} True if the value is a function. | ||
*/ | ||
Cute.isFunction = function (value) { | ||
return typeof value === 'function' | ||
} | ||
/** | ||
* Check whether a value is an object. | ||
* | ||
* @param {Any} value A value to check. | ||
* @return {Boolean} True if the value is an object. | ||
*/ | ||
Cute.isObject = function (value) { | ||
return typeof value === 'object' | ||
} | ||
/** | ||
* Check whether a value is null. | ||
* | ||
* @param {Any} value A value to check. | ||
* @return {Boolean} True if the value is null. | ||
*/ | ||
Cute.isNull = function (value) { | ||
return value === null | ||
} | ||
/** | ||
* Check whether a value is an array. | ||
* | ||
* @param {Any} value A value to check. | ||
* @return {Boolean} True if the value is an array. | ||
*/ | ||
Cute.isArray = function (value) { | ||
return value instanceof Array | ||
} | ||
/** | ||
* Check whether a value is a date. | ||
* | ||
* @param {Any} value A value to check. | ||
* @return {Boolean} True if the value is a date. | ||
*/ | ||
Cute.isDate = function (value) { | ||
return value instanceof Date | ||
} | ||
/** | ||
* Turn a value into a string if it isn't already. | ||
* | ||
* @param {Any} value A value that might be a string. | ||
* @return {String} A string made from appending the given value to the | ||
* empty string. | ||
*/ | ||
Cute.string = function (value) { | ||
return Cute.isString(value) ? value : '' + value | ||
} | ||
/** | ||
* Turn a value into an array if it isn't already. | ||
* | ||
* @param {Any} value A value that might be an array. | ||
* @return {Array} An array that is or contains the value passed in. | ||
*/ | ||
Cute.array = function (value) { | ||
return Cute.isArray(value) ? value : (Cute.isUndefined(value) ? [] : [value]) | ||
} | ||
{ | ||
"name": "cute", | ||
"description": "Web components", | ||
"version": "0.0.2", | ||
"description": "Minifier-friendly JavaScript built for speed and power.", | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"chug": "^0.4.1", | ||
"exam": "^1.4.5", | ||
"figlet": "1.0.9", | ||
"jsdom": "7.2.2" | ||
}, | ||
"keywords": [ | ||
"cute", | ||
"web", | ||
"components" | ||
"jymin", | ||
"javascript", | ||
"you", | ||
"minify", | ||
"fast", | ||
"minifiable", | ||
"lightweight", | ||
"speed", | ||
"power", | ||
"uglify", | ||
"closure", | ||
"compiler", | ||
"jquery", | ||
"zepto", | ||
"alternative", | ||
"angular", | ||
"react", | ||
"ember", | ||
"frontend", | ||
"ui", | ||
"ux", | ||
"lodash" | ||
], | ||
"version": "0.0.0", | ||
"main": "cute.js", | ||
"homepage": "https://github.com/lighterio/cute", | ||
"engines": { | ||
"node": ">=0.8.28" | ||
}, | ||
"scripts": { | ||
"build": "node .chug.js", | ||
"test": "./node_modules/exam/exam.js", | ||
"cover": "./node_modules/exam/exam-cover.js", | ||
"report": "open coverage/lcov-report/index.html", | ||
"bench": "./node_modules/exam/exam.js test/bench" | ||
}, | ||
"repository": "https://github.com/lighterio/cute.git", | ||
"bugs": { | ||
"url": "https://github.com/lighterio/cute/issues" | ||
}, | ||
"bugs": "https://github.com/lighterio/cute/issues", | ||
"homepage": "http://lighter.io/cute", | ||
"author": "Sam Eubank <sameubank@gmail.com>", | ||
@@ -21,13 +56,12 @@ "contributors": [ | ||
"license": "MIT", | ||
"engines": [ | ||
"node >= 0.2.6" | ||
], | ||
"scripts": { | ||
"test": "./node_modules/exam/exam.js", | ||
"cover": "istanbul cover ./node_modules/exam/exam.js", | ||
"report": "open coverage/lcov-report/index.html", | ||
"coveralls": "istanbul cover ./node_modules/exam/exam.js --report lcovonly -- -R spec && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage" | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": {} | ||
"standard": { | ||
"globals": [ | ||
"Cute", | ||
"window", | ||
"document", | ||
"location", | ||
"XMLHttpRequest", | ||
"ActiveXObject" | ||
] | ||
} | ||
} |
278
README.md
@@ -1,106 +0,192 @@ | ||
# <a href="http://lighter.io/cute" style="font-size:40px;text-decoration:none;color:#000"><img src="https://cdn.rawgit.com/lighterio/lighter.io/master/public/cute.svg" style="width:90px;height:90px"> Cute</a> | ||
[![NPM Version](https://img.shields.io/npm/v/cute.svg)](https://npmjs.org/package/cute) | ||
[![Downloads](https://img.shields.io/npm/dm/cute.svg)](https://npmjs.org/package/cute) | ||
[![Build Status](https://img.shields.io/travis/lighterio/cute.svg)](https://travis-ci.org/lighterio/cute) | ||
[![Code Coverage](https://img.shields.io/coveralls/lighterio/cute/master.svg)](https://coveralls.io/r/lighterio/cute) | ||
[![Dependencies](https://img.shields.io/david/lighterio/cute.svg)](https://david-dm.org/lighterio/cute) | ||
[![Support](https://img.shields.io/gratipay/Lighter.io.svg)](https://gratipay.com/Lighter.io/) | ||
# <a href="http://lighter.io/cute" style="font-size:40px;text-decoration:none"><img src="https://cdn.rawgit.com/lighterio/lighter.io/master/public/cute.svg" style="width:90px;height:90px"> Cute</a> | ||
[![Chat](https://badges.gitter.im/chat.svg)](//gitter.im/lighterio/public) | ||
[![Version](https://img.shields.io/npm/v/cute.svg)](//www.npmjs.com/package/cute) | ||
[![Downloads](https://img.shields.io/npm/dm/cute.svg)](//www.npmjs.com/package/cute) | ||
[![Build](https://img.shields.io/travis/lighterio/cute.svg)](//travis-ci.org/lighterio/cute) | ||
[![Coverage](https://img.shields.io/codecov/c/github/lighterio/cute/master.svg)](//codecov.io/gh/lighterio/cute) | ||
[![Support](https://img.shields.io/gittip/zerious.png)](https://www.gittip.com/lighterio/) | ||
Cute is a web components library. | ||
Cute is "JavaScript You Minify", meaning Cute scripts can be concatenated | ||
with your application code and minfied together. Functions you use will | ||
remain intact, and functions you don't use will minify out. The end result | ||
is that browsers will download and run your code quickly, enabling the fastest | ||
experiences possible. | ||
### Quick Start | ||
# Understanding Latency | ||
Install `cute` in your project: | ||
```bash | ||
npm install --save cute | ||
``` | ||
Browser experiences are affected by three main causes of latency, which can | ||
roughly be categorized as **hops**, **size** and **speed**. | ||
* **Hops** to servers and back can be very latent, depending on distance to | ||
servers and number of subsequent hops. | ||
* **Size** of downloads affect bandwidth usage, and large assets can cause | ||
long delays. | ||
* **Speed** of browser rendering is affected by how fast a CPU is and how much | ||
work it needs to do. | ||
The relationship between | ||
[Moore's Law](http://www.nngroup.com/articles/law-of-bandwidth/) and | ||
[Nielsen's Law](http://en.wikipedia.org/wiki/Moore%27s_law) means CPU speeds | ||
can be expected to increase at a greater rate than bandwidth, so over time, | ||
size becomes more important than speed. Additionally, caching is a | ||
common solution for mitigating latency from hops, and small sizes are better | ||
for caching, both on CDNs (saving cost) and browsers (saving space). | ||
## Acknowledgements | ||
We would like to thank all of the amazing people who use, support, | ||
promote, enhance, document, patch, and submit comments & issues. | ||
Cute couldn't exist without you. | ||
<!-- | ||
doNothing | ||
responseSuccessFn | ||
responseFailureFn | ||
getXhr | ||
getUpload | ||
getResponse | ||
forEach | ||
each | ||
getLength | ||
getFirst | ||
getLast | ||
hasMany | ||
push | ||
pop | ||
merge | ||
padArray | ||
getAllCookies | ||
getCookie | ||
setCookie | ||
deleteCookie | ||
getTime | ||
getIsoDate | ||
formatLongDate | ||
formatShortDate | ||
getElement | ||
getElementsByTagName | ||
getElementsByTagAndClass | ||
getParent | ||
createTag | ||
createElement | ||
addElement | ||
appendElement | ||
prependElement | ||
wrapElement | ||
getChildren | ||
getIndex | ||
insertElement | ||
removeElement | ||
clearElement | ||
getHtml | ||
setHtml | ||
getText | ||
setText | ||
getAttribute | ||
setAttribute | ||
getData | ||
setData | ||
getClass | ||
getClasses | ||
setClass | ||
getFirstChild | ||
getPreviousSibling | ||
getNextSibling | ||
hasClass | ||
addClass | ||
removeClass | ||
flipClass | ||
toggleClass | ||
insertScript | ||
all | ||
one | ||
Emitter | ||
EmitterPrototype | ||
CLICK | ||
MOUSEDOWN | ||
MOUSEUP | ||
KEYDOWN | ||
KEYUP | ||
KEYPRESS | ||
bind | ||
on | ||
trigger | ||
stopPropagation | ||
preventDefault | ||
bindFocusChange | ||
bindHover | ||
onHover | ||
bindClick | ||
bindWindowLoad | ||
isReady | ||
focusElement | ||
doOnce | ||
setTimer | ||
removeTimeout | ||
getType | ||
getValue | ||
setValue | ||
getHistory | ||
historyPush | ||
historyReplace | ||
historyPop | ||
onHistoryPop | ||
reservedWordPattern | ||
stringify | ||
parse | ||
execute | ||
parseBoolean | ||
parseNumber | ||
parseString | ||
parseObject | ||
parseArray | ||
error | ||
warn | ||
info | ||
log | ||
trace | ||
ifConsole | ||
ensureNumber | ||
zeroFill | ||
forIn | ||
forOf | ||
decorateObject | ||
ensureProperty | ||
getStorage | ||
fetch | ||
store | ||
ensureString | ||
contains | ||
startsWith | ||
trim | ||
splitByCommas | ||
splitBySpaces | ||
decorateString | ||
match | ||
extractLetters | ||
extractNumbers | ||
lower | ||
upper | ||
escape | ||
unescape | ||
buildQueryString | ||
getBrowserVersionOrZero | ||
isType | ||
isUndefined | ||
isBoolean | ||
isNumber | ||
isString | ||
isFunction | ||
isObject | ||
isInstance | ||
isArray | ||
isDate | ||
getHost | ||
getBaseUrl | ||
getQueryParams | ||
getHashParams | ||
onReady | ||
--> | ||
Additionally, huge thanks go to [TUNE](http://www.tune.com) for employing | ||
and supporting [Cute](http://lighter.io/cute) project maintainers, | ||
and for being an epically awesome place to work (and play). | ||
## MIT License | ||
Copyright (c) 2014 Sam Eubank | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. | ||
## How to Contribute | ||
We welcome contributions from the community and are happy to have them. | ||
Please follow this guide when logging issues or making code changes. | ||
### Logging Issues | ||
All issues should be created using the | ||
[new issue form](https://github.com/lighterio/cute/issues/new). | ||
Please describe the issue including steps to reproduce. Also, make sure | ||
to indicate the version that has the issue. | ||
### Changing Code | ||
Code changes are welcome and encouraged! Please follow our process: | ||
1. Fork the repository on GitHub. | ||
2. Fix the issue ensuring that your code follows the | ||
[style guide](http://lighter.io/style-guide). | ||
3. Add tests for your new code, ensuring that you have 100% code coverage. | ||
(If necessary, we can help you reach 100% prior to merging.) | ||
* Run `npm test` to run tests quickly, without testing coverage. | ||
* Run `npm run cover` to test coverage and generate a report. | ||
* Run `npm run report` to open the coverage report you generated. | ||
4. [Pull requests](http://help.github.com/send-pull-requests/) should be made | ||
to the [master branch](https://github.com/lighterio/cute/tree/master). | ||
### Contributor Code of Conduct | ||
As contributors and maintainers of Cute, we pledge to respect all | ||
people who contribute through reporting issues, posting feature requests, | ||
updating documentation, submitting pull requests or patches, and other | ||
activities. | ||
If any participant in this project has issues or takes exception with a | ||
contribution, they are obligated to provide constructive feedback and never | ||
resort to personal attacks, trolling, public or private harassment, insults, or | ||
other unprofessional conduct. | ||
Project maintainers have the right and responsibility to remove, edit, or | ||
reject comments, commits, code, edits, issues, and other contributions | ||
that are not aligned with this Code of Conduct. Project maintainers who do | ||
not follow the Code of Conduct may be removed from the project team. | ||
Instances of abusive, harassing, or otherwise unacceptable behavior may be | ||
reported by opening an issue or contacting one or more of the project | ||
maintainers. | ||
We promise to extend courtesy and respect to everyone involved in this project | ||
regardless of gender, gender identity, sexual orientation, ability or | ||
disability, ethnicity, religion, age, location, native language, or level of | ||
experience. | ||
## More on Cute... | ||
* [Contributing](//github.com/lighterio/cute/blob/master/CONTRIBUTING.md) | ||
* [License (ISC)](//github.com/lighterio/cute/blob/master/LICENSE.md) | ||
* [Change Log](//github.com/lighterio/cute/blob/master/CHANGELOG.md) | ||
* [Roadmap](//github.com/lighterio/cute/blob/master/ROADMAP.md) |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
Trivial Package
Supply chain riskPackages less than 10 lines of code are easily copied into your own project and may not warrant the additional supply chain risk of an external dependency.
Found 1 instance in 1 package
124690
37
3802
193
4
2
2
4