|
Overview
|
Coverage100.00
SLOC9846
LOC2708
Missed0
|
|
base/array.js
|
Coverage100.00
SLOC668
LOC194
Missed0
|
- 1
var obj = require("./object"), misc = require("./misc"), string = require("./string"), isString = string.isString, number = require("./number.js");- 1
var argsToArray = misc.argsToArray;- 1
var isArray = exports.isArray = function (obj) {- 318
return Array.isArray(obj);};- 1
var cross = function (num, cross) {- 7
var ret = cross.reduceRight(function (a, b) {- 38
if (!isArray(b)) b = [b];- 19
b.unshift(num)- 19
a.unshift(b);- 19
return a;}, []);- 7
return ret;};- 1
var permute = function (num, cross, length) {- 6
var ret = [];- 6
for (var i = 0; i < cross.length; i++) {- 12
ret.push([num].concat(array.rotate(cross, i)).slice(0, length));}- 6
return ret;};- 1
var intersection = function (a, b) {- 45
var ret = [];- 45
if (isArray(a) && isArray(b)) {- 45
if (a.length && b.length) {- 35
var aOne = a[0];- 35
if (b.indexOf(aOne) != -1) {- 28
ret = [aOne].concat(intersection(a.slice(1), b));} else {- 7
ret = intersection(a.slice(1), b);}}}- 45
return ret;};- 1
var _sort = (function () {- 1
var isAll = function (arr, test) {- 12
return arr.every(test);};- 1
var defaultCmp = function (a, b) {- 39
return a - b;};- 1
return function _sort(arr, property) {- 22
var ret = [];- 22
if (isArray(arr)) {- 22
ret = arr.slice();- 22
if (property) {- 10
if (typeof property == "function") {- 1
ret.sort(property);} else {- 9
ret.sort(function (a, b) {- 27
var aProp = a[property], bProp = b[property];- 27
if (isString(aProp) && isString(bProp)) {- 9
return aProp > bProp ? 1 : aProp < bProp ? -1 : 0;} else {- 18
return aProp - bProp;}});}} else {- 12
if (isAll(ret, isString)) {- 3
ret.sort();} else {- 9
ret.sort(defaultCmp);}}}- 22
return ret;};})();- 1
var comb = exports, array;/*** @namespace Utilities for Arrays*/- 1
comb.array = {/**@lends comb.array*//*** converts anything to an array** @example* comb.array.toArray({a : "b", b : "c"}) => [["a","b"], ["b","c"]];* comb.array.toArray("a") => ["a"]* comb.array.toArray(["a"]) => ["a"];* comb.array.toArray() => [];* comb.array.toArray("a", {a : "b"}) => ["a", ["a", "b"]];*/toArray:function (o) {- 21
var ret = [];- 21
if (o != null) {- 20
var args = argsToArray(arguments);- 20
if (args.length == 1) {- 19
if (isArray(o)) {- 12
ret = o;- 7
} else if (obj.isHash(o)) {- 2
for (var i in o) {- 3
if (o.hasOwnProperty(i)) {- 3
ret.push([i, o[i]]);}}} else {- 5
ret.push(o);}} else {- 1
args.forEach(function (a) {- 2
ret = ret.concat(array.toArray(a));})}}- 21
return ret;},/*** Sums all items in an array** @example** comb.array.sum([1,2,3]) => 6* comb.array.sum(["A","B","C"]) => "ABC";* var d1 = new Date(1999), d2 = new Date(2000), d3 = new Date(3000);* comb.array.sum([d1,d2,d3]) => "Wed Dec 31 1969 18:00:01 GMT-0600 (CST)"* + "Wed Dec 31 1969" 18:00:02 GMT-0600 (CST)"* + "Wed Dec 31 1969 18:00:03 GMT-0600 (CST)"* comb.array.sum([{},{},{}]) => "[object Object][object Object][object Object]";** @param {Number[]} array the array of numbers to sum*/sum:function (array) {- 10
array = array || [];- 10
if (array.length) {- 8
return array.reduce(function (a, b) {- 16
return a + b;});} else {- 2
return 0;}},/*** Averages an array of numbers.* @example** comb.array.avg([1,2,3]); //2** @param {Number[]} array - an array of numbers* @return {Number} the average of all the numbers in the array.* @throws {Error} if the array is not all numbers.*/avg:function (arr) {- 6
arr = arr || [];- 6
if (arr.length) {- 4
var sum = array.sum(arr);- 4
if (number.isNumber(sum)) {- 1
return sum / arr.length;} else {- 3
throw new Error("Cannot average an array of non numbers.");}} else {- 2
return 0;}},/*** Allows the sorting of an array based on a property name instead. This can also* act as a sort that does not change the original array.** <b>NOTE:</b> this does not change the original array!** @example* comb.array.sort([{a : 1}, {a : 2}, {a : -2}], "a"); //[{a : -2}, {a : 1}, {a : 2}];* @param {Array} arr the array to sort* @param {String|Function} cmp the property to sort on. Or a function used to compare.* @return {Array} a copy of the original array that is sorted.*/sort:function (arr, cmp) {- 8
return _sort(arr, cmp);},/*** Finds that min value of an array. If a second argument is provided and it is a function* it will be used as a comparator function. If the second argument is a string then it will be used* as a property look up on each item.** @example* comb.array.min([{a : 1}, {a : 2}, {a : -2}], "a"); //{a : -2}* comb.array.min([{a : 1}, {a : 2}, {a : -2}], function(a,b){* return a.a - b.a* }); //{a : -2}** @param {Array} arr the array to find the min value on* @param {String|Function} cmp the property to sort on. Or a function used to compare.* @return {*}*/min:function (arr, cmp) {- 7
return _sort(arr, cmp)[0];},/*** Finds that max value of an array. If a second argument is provided and it is a function* it will be used as a comparator function. If the second argument is a string then it will be used* as a property look up on each item.** @example* comb.array.max([{a : 1}, {a : 2}, {a : -2}], "a"); //{a : 2}* comb.array.max([{a : 1}, {a : 2}, {a : -2}], function(a,b){* return a.a - b.a* }); //{a : 2}** @param arr the array to find the max value on* @param {String|Function} cmp the property to sort on. Or a function used to compare.* @return {*} the maximum value of the array based on the provided cmp.*/max:function (arr, cmp) {- 7
return _sort(arr, cmp)[arr.length - 1];},/*** Finds the difference of the two arrays.** @example** comb.array.difference([1,2,3], [2,3]); //[1]* comb.array.difference(["a","b",3], [3]); //["a","b"]** @param {Array} arr1 the array we are subtracting from* @param {Array} arr2 the array we are subtracting from arr1* @return {*} the difference of the arrays.*/difference:function (arr1, arr2) {- 5
var ret = arr1, args = array.flatten(misc.argsToArray(arguments).slice(1));- 5
if (isArray(arr1)) {- 5
ret = arr1.filter(function (a) {- 14
return args.indexOf(a) === -1;});}- 5
return ret;},/*** Removes duplicates from an array** @example** comb.array.removeDuplicates([1,1,1]) => [1]* comb.array.removeDuplicates([1,2,3,2]) => [1,2,3]** @param {Aray} array the array of elements to remove duplicates from*/removeDuplicates:function (arr) {- 11
if (isArray(arr)) {- 11
var ret = arr.reduce(function (a, b) {- 47
if (a.indexOf(b) === -1) {- 32
return a.concat(b);} else {- 15
return a;}}, []);- 11
return ret;}},unique:function (arr) {- 2
return array.removeDuplicates(arr);},/*** Rotates an array the number of specified positions** @example* var arr = ["a", "b", "c", "d"];* comb.array.rotate(arr) => ["b", "c", "d", "a"]* comb.array.rotate(arr, 2) => ["c", "d", "a", "b"]);* comb.array.rotate(arr, 3) => ["d", "a", "b", "c"]);* comb.array.rotate(arr, 4) => ["a", "b", "c", "d"]);* comb.array.rotate(arr, -1) => ["d", "a", "b", "c"]);* comb.array.rotate(arr, -2) => ["c", "d", "a", "b"]);* comb.array.rotate(arr, -3) => ["b", "c", "d", "a"]);* comb.array.rotate(arr, -4) => ["a", "b", "c", "d"]);** @param {Array} array the array of elements to remove duplicates from* @param {Number} numberOfTimes the number of times to rotate the array*/rotate:function (arr, numberOfTimes) {- 58
var ret = arr.slice();- 58
if (typeof numberOfTimes != "number") {- 1
numberOfTimes = 1;}- 58
if (numberOfTimes && isArray(arr)) {- 32
if (numberOfTimes > 0) {- 22
ret.push(ret.shift());- 22
numberOfTimes--;} else {- 10
ret.unshift(ret.pop());- 10
numberOfTimes++;}- 32
return array.rotate(ret, numberOfTimes);} else {- 26
return ret;}},/*** Finds all permutations of an array** @example* var arr = [1,2,3];* comb.array.permutations(arr) => [[ 1, 2, 3 ],[ 1, 3, 2 ],[ 2, 3, 1 ],* [ 2, 1, 3 ],[ 3, 1, 2 ],[ 3, 2, 1 ]]* comb.array.permutations(arr, 2) => [[ 1, 2],[ 1, 3],[ 2, 3],[ 2, 1],[ 3, 1],[ 3, 2]]* comb.array.permutations(arr, 1) => [[1],[2],[3]]* comb.array.permutations(arr, 0) => [[]]* comb.array.permutations(arr, 4) => []** @param {Array} arr the array to permute.* @param {Number} length the number of elements to permute.*/permutations:function (arr, length) {- 5
var ret = [];- 5
if (isArray(arr)) {- 5
var copy = arr.slice(0);- 5
if (typeof length != "number") {- 1
length = arr.length;}- 5
if (!length) {- 1
ret = [[]];- 4
} else if (length <= arr.length) {- 3
ret = arr.reduce(function (a, b, i) {- 9
if (length > 1) {- 6
var ret = permute(b, array.rotate(copy, i).slice(1), length);} else {- 3
ret = [[b]];}- 9
return a.concat(ret);}, [])}}- 5
return ret;},/*** Zips to arrays together** @example* var a = [ 4, 5, 6 ], b = [ 7, 8, 9 ]* comb.array.zip([1], [2], [3]) => [[ 1, 2, 3 ]]);* comb.array.zip([1,2], [2], [3]) => [[ 1, 2, 3 ],[2, null, null]]* comb.array.zip([1,2,3], a, b) => [[1, 4, 7],[2, 5, 8],[3, 6, 9]]* comb.array.zip([1,2], a, b) => [[1, 4, 7],[2, 5, 8]]* comb.array.zip(a, [1,2], [8]) => [[4,1,8],[5,2,null],[6,null,null]]** @param arrays variable number of arrays to zip together*/zip:function () {- 5
var ret = [];- 5
var arrs = argsToArray(arguments);- 5
if (arrs.length > 1) {- 5
var arr1 = arrs.shift();- 5
if (isArray(arr1)) {- 5
ret = arr1.reduce(function (a, b, i) {- 11
var curr = [b];- 11
for (var j = 0; j < arrs.length; j++) {- 22
var currArr = arrs[j];- 22
if (isArray(currArr) && !misc.isUndefined(currArr[i])) {- 17
curr.push(currArr[i]);} else {- 5
curr.push(null);}}- 11
a.push(curr)- 11
return a;}, []);}}- 5
return ret;},/*** Transposes an array of arrays* @example** comb.array.transpose([[1,2,3], [4,5,6]]) => [ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]* comb.array.transpose([[1,2], [3,4], [5,6]]) => [ [ 1, 3, 5 ], [ 2, 4, 6 ] ]* comb.array.transpose([[1], [3,4], [5,6]]) => [[1]])** @param [Array[Array[]]] arr Array of arrays*/transpose:function (arr) {- 3
var ret = [];- 3
if (isArray(arr) && arr.length) {- 3
var last;- 3
arr.forEach(function (a) {- 8
if (isArray(a) && (!last || a.length == last.length)) {- 6
a.forEach(function (b, i) {- 13
!ret[i] && (ret[i] = []);- 13
ret[i].push(b);});- 6
last = a;}});}- 3
return ret;},/*** Retrieves values at specified indexes in the array** @example** var arr =["a", "b", "c", "d"]* comb.array.valuesAt(arr, 1,2,3) => ["b", "c", "d"];* comb.array.valuesAt(arr, 1,2,3, 4) => ["b", "c", "d", null];* comb.array.valuesAt(arr, 0,3) => ["a", "d"];** @param {Array} arr the array to retrieve values from* @index {Number} index variable number of indexes to retrieve*/valuesAt:function (arr, indexes) {- 3
var ret = [];- 3
var indexes = argsToArray(arguments);- 3
var arr = indexes.shift(), l = arr.length;- 3
if (isArray(arr) && indexes.length) {- 3
for (var i = 0; i < indexes.length; i++) {- 9
ret.push(arr[indexes[i]] || null);}}- 3
return ret;},/*** Union a variable number of arrays together** @example** comb.array.union(['a','b','c'], ['b','c', 'd']) => ["a", "b", "c", "d"]* comb.array.union(["a"], ["b"], ["c"], ["d"], ["c"]) => ["a", "b", "c", "d"]** @param arrs variable number of arrays to union*/union:function () {- 2
var ret = [];- 2
var arrs = argsToArray(arguments);- 2
if (arrs.length > 1) {- 2
ret = array.removeDuplicates(arrs.reduce(function (a, b) {- 7
return a.concat(b);}, []));}- 2
return ret;},/*** Finds the intersection of arrays* NOTE : this function accepts an arbitrary number of arrays** @example* comb.array.intersect([1,2], [2,3], [2,3,5]) => [2]* comb.array.intersect([1,2,3], [2,3,4,5], [2,3,5]) => [2,3]* comb.array.intersect([1,2,3,4], [2,3,4,5], [2,3,4,5]) => [2,3,4]* comb.array.intersect([1,2,3,4,5], [1,2,3,4,5], [1,2,3]) => [1,2,3]* comb.array.intersect([[1,2,3,4,5],[1,2,3,4,5],[1,2,3]]) => [1,2,3]** @param {Array} a* @param {Array} b*/intersect:function (a, b) {- 5
var collect = [], set;- 5
var args = argsToArray(arguments);- 5
if (args.length > 1) {//assume we are intersections all the lists in the array- 4
set = args;} else {- 1
set = args[0];}- 5
if (isArray(set)) {- 5
var x = set.shift();- 5
var collect = set.reduce(function (a, b) {- 10
return intersection(a, b);}, x);}- 5
return array.removeDuplicates(collect);},/*** Finds the powerset of an array** @example** comb.array.powerSet([1,2]) => [* [],* [ 1 ],* [ 2 ],* [ 1, 2 ]* ]* comb.array.powerSet([1,2,3]) => [* [],* [ 1 ],* [ 2 ],* [ 1, 2 ],* [ 3 ],* [ 1, 3 ],* [ 2, 3 ],* [ 1, 2, 3 ]* ]* comb.array.powerSet([1,2,3,4]) => [* [],* [ 1 ],* [ 2 ],* [ 1, 2 ],* [ 3 ],* [ 1, 3 ],* [ 2, 3 ],* [ 1, 2, 3 ],* [ 4 ],* [ 1, 4 ],* [ 2, 4 ],* [ 1, 2, 4 ],* [ 3, 4 ],* [ 1, 3, 4 ],* [ 2, 3, 4 ],* [ 1, 2, 3, 4 ]* ]** @param {Array} arr the array to find the powerset of*/powerSet:function (arr) {- 3
var ret = [];- 3
if (isArray(arr) && arr.length) {- 3
var ret = arr.reduce(function (a, b) {- 9
var ret = a.map(function (c) {- 25
return c.concat(b);})- 9
return a.concat(ret);}, [[]]);}- 3
return ret;},/*** Find the cartesian product of two arrays** @example** comb.array.cartesian([1,2], [2,3]) => [* [1,2],* [1,3],* [2,2],* [2,3]* ]* comb.array.cartesian([1,2], [2,3,4]) => [* [1,2],* [1,3],* [1,4] ,* [2,2],* [2,3],* [2,4]* ]* comb.array.cartesian([1,2,3], [2,3,4]) => [* [1,2],* [1,3],* [1,4] ,* [2,2],* [2,3],* [2,4] ,* [3,2],* [3,3],* [3,4]* ]** @param {Array} a* @param {Array} b*/cartesian:function (a, b) {- 10
var ret = [];- 10
if (isArray(a) && isArray(b) && a.length && b.length)- 7
ret = cross(a[0], b).concat(array.cartesian(a.slice(1), b));- 10
return ret;},/*** Compacts an array removing null or undefined objects from the array.** @example** var x;* comb.array.compact([1,null,null,x,2]) => [1,2]* comb.array.compact([1,2]) => [1,2]** @param {Array} arr*/compact:function (arr) {- 2
var ret = [];- 2
if (isArray(arr) && arr.length) {- 2
ret = arr.filter(function (item) {- 7
return !misc.isUndefinedOrNull(item);})}- 2
return ret;},/*** Creates a new array that is the result of the array concated the number of* times. If times is not specified or it equals 0 then it defaults to 1.* @param {Array} arr the array to multiply.* @param {Number} [times=1] the number of times to multiple the array.* @return {Array} a new array that is the result of the array multiplied the number of times specified.*/multiply:function (arr, times) {- 4
times = number.isNumber(times) ? times : 1;- 4
if (!times) {//make sure times is greater than zero if it is zero then dont multiply it- 1
times = 1;}- 4
arr = array.toArray(arr || []);- 4
var ret = [], i = 0;- 4
while (++i <= times) {- 5
ret = ret.concat(arr);}- 4
return ret;},/*** Flatten multiple arrays into a single array** @example** comb.array.flatten([1,2], [2,3], [3,4]) => [1,2,2,3,3,4]* comb.array.flatten([1,"A"], [2,"B"], [3,"C"]) => [1,"A",2,"B",3,"C"]** @param array*/flatten:function (arr) {- 10
var set;- 10
var args = argsToArray(arguments);- 10
if (args.length > 1) {//assume we are intersections all the lists in the array- 3
set = args;} else {- 7
set = array.toArray(arr);}- 10
return set.reduce(function (a, b) {- 19
return a.concat(b);}, []);}};- 1
array = comb.array;
|
base/broadcast.js
|
Coverage100.00
SLOC171
LOC63
Missed0
|
- 1
var func = require("./functions"),obj = require("./object");- 1
var comb = exports;- 1
var wrapper = function() {- 8
return function() {- 31
var c = arguments.callee, listeners = c.__listeners, func = c.func, r;- 31
if (func) {- 31
r = func.apply(this, arguments);}- 31
for (var i = 0; i < listeners.length; i++) {- 39
var lis = listeners[i];- 39
if (lis) {- 30
lis.apply(this, arguments);}}- 31
return r;}};- 1
var listeners = {};- 1
obj.merge(comb, {/**@lends comb*//*** Disconnects a listener to a function* @param {handle} A handle returned from comb.connect*/disconnect : function(handle) {- 10
if (handle && handle.length == 3) {- 9
var obj = handle[0], method = handle[1], cb = handle[2];- 9
if (typeof method != "string") throw "comb.disconnect : When calling disconnect the method must be string";- 9
var scope = obj || global, ls;- 9
if (typeof scope[method] == "function") {- 8
ls = scope[method].__listeners;- 8
if (ls && cb-- > 0) {//we dont want to splice it because our indexing will get off- 8
ls[cb] = null;}} else {- 1
throw new Error("unknown method " + method + " in object " + obj);}} else {- 1
throw "comb.disconnect : invalid handle"}},/*** Function to listen when other functions are called** @example** comb.connect(obj, "event", myfunc);* comb.connect(obj, "event", "log", console);** @param {Object} obj the object in which the method you are connecting to resides* @param {String} method the name of the method to connect to* @param {Function} cb the function to callback* @param {Object} [scope] the scope to call the specified cb in** @returns {Array} handle to pass to {@link comb.disconnect}*/connect : function(obj, method, cb, scope) {- 14
var index;- 14
if (typeof method != "string") throw new Error("When calling connect the method must be string");- 14
if (!func.isFunction(cb)) throw new Error("When calling connect callback must be a string");- 14
var scope = obj || global, listeners, newMethod;- 14
if (typeof scope[method] == "function") {- 13
listeners = scope[method].__listeners;- 13
if (!listeners) {- 8
newMethod = wrapper();- 8
newMethod.func = obj[method];- 8
listeners = (newMethod.__listeners = []);- 8
scope[method] = newMethod;}- 13
index = listeners.push(cb);} else {- 1
throw new Error("unknow method " + method + " in object " + obj);}- 13
return [obj, method, index];},/*** Broadcasts an event to all listeners* NOTE : the function takes a variable number of arguments* i.e. all arguments after the topic will be passed to the listeners** @example*** comb.broadcast("hello", "hello world");* //the args "hello" and "world" will be passed to any listener of the topic* //"hello"* comb.broadcast("hello", "hello", "world");** @param {String} topic the topic to brodcast* @param params the information to bradcast*/broadcast : function() {- 4
var args = Array.prototype.slice.call(arguments);- 4
var topic = args.splice(0, 1)[0];- 4
if (topic) {- 4
var list = listeners[topic];- 4
if (list) {- 4
for (var i = list.length - 1; i >= 0; i--) {- 4
var han = list[i], cb = han.cb;- 4
if (cb) {- 4
cb.apply(this, args);}}}}},/*** Listen for the broadcast of certain events** @example* comb.listen("hello", function(arg1, arg2){* console.log(arg1);* console.log(arg2);* });** @param {String} topic the topic to listen for* @param {Function} callback the funciton to call when the topic is published** @returns a handle to pass to {@link comb.unListen}*/listen : function(topic, callback) {- 3
if (!func.isFunction(callback)) throw new Error("callback must be a function");- 3
var handle = {topic : topic,cb : callback,pos : null};- 3
var list = listeners[topic];- 3
if (!list) {- 3
list = (listeners[topic] = []);}- 3
list.push(handle);- 3
handle.pos = list.length - 1;- 3
return handle;},/*** Disconnects a listener** @param handle a handle returned from {@link comb.listen}*/unListen : function(handle) {- 2
if (handle) {- 2
var topic = handle.topic, list = listeners[topic];- 2
if (list) {- 2
for (var i = list.length - 1; i >= 0; i--) {- 2
if (list[i] == handle) {- 2
list.splice(i, 1);}}- 2
if (!list.length) {- 2
delete listeners[topic];}}}}});
|
base/date.js
|
Coverage100.00
SLOC1106
LOC356
Missed0
|
- 1
var string = require("./string").string;/*** @ignore* Based on DOJO Date Implementation** Dojo is available under *either* the terms of the modified BSD license *or* the* Academic Free License version 2.1. As a recipient of Dojo, you may choose which* license to receive this code under (except as noted in per-module LICENSE* files). Some modules may not be the copyright of the Dojo Foundation. These* modules contain explicit declarations of copyright in both the LICENSE files in* the directories in which they reside and in the code itself. No external* contributions are allowed under licenses which are fundamentally incompatible* with the AFL or BSD licenses that Dojo is distributed under.**/- 1
var floor = Math.floor, round = Math.round, min = Math.min, pow = Math.pow, ceil = Math.ceil, abs = Math.abs;- 1
var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];- 1
var monthAbbr = ["Jan.", "Feb.", "Mar.", "Apr.", "May.", "Jun.", "Jul.", "Aug.", "Sep.", "Oct.", "Nov.", "Dec."];- 1
var monthLetter = ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"];- 1
var dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];- 1
var dayAbbr = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];- 1
var dayLetter = ["S", "M", "T", "W", "T", "F", "S"];- 1
var eraNames = ["Before Christ", "Anno Domini"];- 1
var eraAbbr = ["BC", "AD"];- 1
var eraLetter = ["B", "A"];- 1
var comb = exports, date;/*** Determines if obj is a Date** @param {Anything} obj the thing to test if it is a Date* @memberOf comb* @returns {Boolean} true if it is a Date false otherwise*/- 1
comb.isDate = function (obj) {- 36
var undef;- 36
return (obj !== undef && typeof obj === "object" && obj instanceof Date);};- 1
function getDayOfYear(/*Date*/dateObject, utc) {// summary: gets the day of the year as represented by dateObject- 6
return date.difference(new Date(dateObject.getFullYear(), 0, 1, dateObject.getHours()), dateObject, null, utc) + 1; // Number}- 1
function getWeekOfYear(/*Date*/dateObject, /*Number*/firstDayOfWeek, utc) {- 4
firstDayOfWeek = firstDayOfWeek || 0;- 4
var fullYear = dateObject[utc ? "getUTCFullYear" : "getFullYear"]();- 4
var firstDayOfYear = new Date(fullYear, 0, 1).getDay(),adj = (firstDayOfYear - firstDayOfWeek + 7) % 7,week = floor((getDayOfYear(dateObject) + adj - 1) / 7);// if year starts on the specified day, start counting weeks at 1- 4
if (firstDayOfYear == firstDayOfWeek) {- 4
week++;}- 4
return week; // Number}- 1
function buildDateEXP(pattern, tokens) {- 28
return pattern.replace(/([a-z])\1*/ig,function (match) {// Build a simple regexp. Avoid captures, which would ruin the tokens list- 100
var s,c = match.charAt(0),l = match.length,p2 = '', p3 = '';- 100
p2 = '0?';- 100
p3 = '0{0,2}';- 100
switch (c) {case 'y':- 17
s = '\\d{2,4}';- 17
break;case 'M':- 17
s = (l > 2) ? '\\S+?' : '1[0-2]|' + p2 + '[1-9]';- 17
break;case 'D':- 2
s = '[12][0-9][0-9]|3[0-5][0-9]|36[0-6]|' + p3 + '[1-9][0-9]|' + p2 + '[1-9]';- 2
break;case 'd':- 16
s = '3[01]|[12]\\d|' + p2 + '[1-9]';- 16
break;case 'w':- 2
s = '[1-4][0-9]|5[0-3]|' + p2 + '[1-9]';- 2
break;case 'E':- 6
s = '\\S+';- 6
break;case 'h': //hour (1-12)- 5
s = '1[0-2]|' + p2 + '[1-9]';- 5
break;case 'K': //hour (1-24)- 2
s = '1[01]|' + p2 + '\\d';- 2
break;case 'H': //hour (0-23)- 1
s = '1\\d|2[0-3]|' + p2 + '\\d';- 1
break;case 'k': //hour (1-24)- 1
s = '1\\d|2[0-4]|' + p2 + '[1-9]';- 1
break;case 'm':case 's':- 15
s = '[0-5]\\d';- 15
break;case 'S':- 5
s = '\\d{' + l + '}';- 5
break;case 'a':- 3
var am = 'AM', pm = 'PM';- 3
s = am + '|' + pm;- 3
if (am != am.toLowerCase()) {- 3
s += '|' + am.toLowerCase();}- 3
if (pm != pm.toLowerCase()) {- 3
s += '|' + pm.toLowerCase();}- 3
s = s.replace(/\./g, "\\.");- 3
break;case 'v':case 'z':case 'Z':case 'G':case 'q':case 'Q':- 6
s = ".*";- 6
break;default:- 2
s = c == " " ? "\\s*" : c + "*";// console.log("parse of date format, pattern=" + pattern);}- 100
if (tokens) {- 100
tokens.push(match);}- 100
return "(" + s + ")"; // add capture}).replace(/[\xa0 ]/g, "[\\s\\xa0]"); // normalize whitespace. Need explicit handling of \xa0 for IE.}/*** @namespace Utilities for Dates*/- 1
comb.date = {/**@lends comb.date*//*** Returns the number of days in the month of a date** @example** comb.date.getDaysInMonth(new Date(2006, 1, 1)); //28* comb.date.getDaysInMonth(new Date(2004, 1, 1)); //29* comb.date.getDaysInMonth(new Date(2006, 2, 1)); //31* comb.date.getDaysInMonth(new Date(2006, 3, 1)); //30* comb.date.getDaysInMonth(new Date(2006, 4, 1)); //31* comb.date.getDaysInMonth(new Date(2006, 5, 1)); //30* comb.date.getDaysInMonth(new Date(2006, 6, 1)); //31* @param {Date} dateObject the date containing the month* @return {Number} the number of days in the month*/getDaysInMonth:function (/*Date*/dateObject) {// summary:// Returns the number of days in the month used by dateObject- 18
var month = dateObject.getMonth();- 18
var days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];- 18
if (month == 1 && date.isLeapYear(dateObject)) {- 3
return 29;} // Number- 15
return days[month]; // Number},/*** Determines if a date is a leap year** @example** comb.date.isLeapYear(new Date(1600, 0, 1)); //true* comb.date.isLeapYear(new Date(2004, 0, 1)); //true* comb.date.isLeapYear(new Date(2000, 0, 1)); //true* comb.date.isLeapYear(new Date(2006, 0, 1)); //false* comb.date.isLeapYear(new Date(1900, 0, 1)); //false* comb.date.isLeapYear(new Date(1800, 0, 1)); //false* comb.date.isLeapYear(new Date(1700, 0, 1)); //false** @param {Date} dateObject* @returns {Boolean} true if it is a leap year false otherwise*/isLeapYear:function (/*Date*/dateObject, utc) {- 14
var year = dateObject[utc ? "getUTCFullYear" : "getFullYear"]();- 14
return !(year % 400) || (!(year % 4) && !!(year % 100)); // Boolean},/*** Determines if a date is on a weekend** @example** var thursday = new Date(2006, 8, 21);* var saturday = new Date(2006, 8, 23);* var sunday = new Date(2006, 8, 24);* var monday = new Date(2006, 8, 25);* comb.date.isWeekend(thursday)); //false* comb.date.isWeekend(saturday); //true* comb.date.isWeekend(sunday); //true* comb.date.isWeekend(monday)); //false** @param {Date} dateObject the date to test** @returns {Boolean} true if the date is a weekend*/isWeekend:function (/*Date?*/dateObject, utc) {// summary:// Determines if the date falls on a weekend, according to local custom.- 4
var day = (dateObject || new Date())[utc ? "getUTCDay" : "getDay"]();- 4
return day == 0 || day == 6;},/*** Get the timezone of a date** @example* //just setting the strLocal to simulate the toString() of a date* dt.str = 'Sun Sep 17 2006 22:25:51 GMT-0500 (CDT)';* //just setting the strLocal to simulate the locale* dt.strLocale = 'Sun 17 Sep 2006 10:25:51 PM CDT';* comb.date.getTimezoneName(dt); //'CDT'* dt.str = 'Sun Sep 17 2006 22:57:18 GMT-0500 (CDT)';* dt.strLocale = 'Sun Sep 17 22:57:18 2006';* comb.date.getTimezoneName(dt); //'CDT'* @param dateObject the date to get the timezone from** @returns {String} the timezone of the date*/getTimezoneName:function (/*Date*/dateObject) {- 33
var str = dateObject.toString();- 33
var tz = '';- 33
var pos = str.indexOf('(');- 33
if (pos > -1) {- 29
tz = str.substring(++pos, str.indexOf(')'));}- 33
return tz; // String},/*** Compares two dates** @example** var d1 = new Date();* d1.setHours(0);* comb.date.compare(d1, d1); // 0** var d1 = new Date();* d1.setHours(0);* var d2 = new Date();* d2.setFullYear(2005);* d2.setHours(12);* comb.date.compare(d1, d2, "date"); // 1* comb.date.compare(d1, d2, "datetime"); // 1** var d1 = new Date();* d1.setHours(0);* var d2 = new Date();* d2.setFullYear(2005);* d2.setHours(12);* comb.date.compare(d2, d1, "date"); // -1* comb.date.compare(d1, d2, "time"); //-1** @param {Date|String} date1 the date to comapare* @param {Date|String} [date2=new Date()] the date to compare date1 againse* @param {"date"|"time"|"datetime"} portion compares the portion specified** @returns -1 if date1 is < date2 0 if date1 === date2 1 if date1 > date2*/compare:function (/*Date*/date1, /*Date*/date2, /*String*/portion) {- 5
date1 = new Date(date1);- 5
date2 = new Date((date2 || new Date()));- 5
if (portion == "date") {// Ignore times and compare dates.- 2
date1.setHours(0, 0, 0, 0);- 2
date2.setHours(0, 0, 0, 0);- 3
} else if (portion == "time") {// Ignore dates and compare times.- 1
date1.setFullYear(0, 0, 0);- 1
date2.setFullYear(0, 0, 0);}- 5
var ret = 0;- 5
date1 > date2 && (ret = 1);- 5
date1 < date2 && (ret = -1);- 5
return ret; // int},/*** Adds a specified interval and amount to a date** @example* var dtA = new Date(2005, 11, 27);* comb.date.add(dtA, "year", 1); //new Date(2006, 11, 27);* comb.date.add(dtA, "years", 1); //new Date(2006, 11, 27);** dtA = new Date(2000, 0, 1);* comb.date.add(dtA, "quarter", 1); //new Date(2000, 3, 1);* comb.date.add(dtA, "quarters", 1); //new Date(2000, 3, 1);** dtA = new Date(2000, 0, 1);* comb.date.add(dtA, "month", 1); //new Date(2000, 1, 1);* comb.date.add(dtA, "months", 1); //new Date(2000, 1, 1);** dtA = new Date(2000, 0, 31);* comb.date.add(dtA, "month", 1); //new Date(2000, 1, 29);* comb.date.add(dtA, "months", 1); //new Date(2000, 1, 29);** dtA = new Date(2000, 0, 1);* comb.date.add(dtA, "week", 1); //new Date(2000, 0, 8);* comb.date.add(dtA, "weeks", 1); //new Date(2000, 0, 8);** dtA = new Date(2000, 0, 1);* comb.date.add(dtA, "day", 1); //new Date(2000, 0, 2);** dtA = new Date(2000, 0, 1);* comb.date.add(dtA, "weekday", 1); //new Date(2000, 0, 3);** dtA = new Date(2000, 0, 1, 11);* comb.date.add(dtA, "hour", 1); //new Date(2000, 0, 1, 12);** dtA = new Date(2000, 11, 31, 23, 59);* comb.date.add(dtA, "minute", 1); //new Date(2001, 0, 1, 0, 0);** dtA = new Date(2000, 11, 31, 23, 59, 59);* comb.date.add(dtA, "second", 1); //new Date(2001, 0, 1, 0, 0, 0);** dtA = new Date(2000, 11, 31, 23, 59, 59, 999);* comb.date.add(dtA, "millisecond", 1); //new Date(2001, 0, 1, 0, 0, 0, 0);** @param {Date} date* @param {String} interval the interval to add* <ul>* <li>day | days</li>* <li>weekday | weekdays</li>* <li>year | years</li>* <li>week | weeks</li>* <li>quarter | quarters</li>* <li>months | months</li>* <li>hour | hours</li>* <li>minute | minutes</li>* <li>second | seconds</li>* <li>millisecond | milliseconds</li>* </ul>* @param {Number} [amount=0] the amount to add*/add:function (/*Date*/date, /*String*/interval, /*int*/amount) {- 126
amount = amount | 0- 126
var sum = new Date(date);- 126
var fixOvershoot = false;- 126
var property = "Date";//noinspection FallthroughInSwitchStatementJS- 126
switch (interval) {case "day":case "days" :- 33
break;case "weekday":case "weekdays":// Divide the increment time span into weekspans plus leftover days// e.g., 8 days is one 5-day weekspan / and two leftover days// Can't have zero leftover days, so numbers divisible by 5 get// a days value of 5, and the remaining days make up the number of weeks- 16
var days, weeks, mod = amount % 5, strt = date.getDay(), adj = 0;- 16
if (!mod) {- 6
days = (amount > 0) ? 5 : -5;- 6
weeks = (amount > 0) ? ((amount - 5) / 5) : ((amount + 5) / 5);} else {- 10
days = mod;- 10
weeks = parseInt(amount / 5);}- 16
if (strt == 6 && amount > 0) {- 2
adj = 1;- 14
} else if (strt == 0 && amount < 0) {// Orig date is Sun / negative increment// Jump back over Sat- 4
adj = -1;}// Get weekday val for the new date- 16
var trgt = strt + days;// New date is on Sat or Sun- 16
if (trgt == 0 || trgt == 6) {- 2
adj = (amount > 0) ? 2 : -2;}// Increment by number of weeks plus leftover days plus// weekend adjustments- 16
amount = (7 * weeks) + days + adj;- 16
break;case "year":case "years":- 20
property = "FullYear";- 20
fixOvershoot = true;- 20
break;case "week":case "weeks":- 3
amount *= 7;- 3
break;case "quarter":case "quarters" :// Naive quarter is just three months- 9
amount *= 3;case "month":case "months":// Reset to last day of month if you overshoot- 22
fixOvershoot = true;- 22
property = "Month";- 22
break;default:- 32
interval = interval.replace(/s$/, "");- 32
property = "UTC" + interval.charAt(0).toUpperCase() + interval.substring(1) + "s";}- 126
if (property) {- 126
sum["set" + property](sum["get" + property]() + amount);}- 126
if (fixOvershoot && (sum.getDate() < date.getDate())) {- 13
sum.setDate(0);}- 126
return sum; // Date},/*** Finds the difference between two dates based on the specified interval** @example** var dtA, dtB;** dtA = new Date(2005, 11, 27);* dtB = new Date(2006, 11, 27);* comb.date.difference(dtA, dtB, "year"); //1** dtA = new Date(2000, 1, 29);* dtB = new Date(2001, 2, 1);* comb.date.difference(dtA, dtB, "quarter"); //4* comb.date.difference(dtA, dtB, "month"); //13** dtA = new Date(2000, 1, 1);* dtB = new Date(2000, 1, 8);* comb.date.difference(dtA, dtB, "week"); //1** dtA = new Date(2000, 1, 29);* dtB = new Date(2000, 2, 1);* comb.date.difference(dtA, dtB, "day"); //1** dtA = new Date(2006, 7, 3);* dtB = new Date(2006, 7, 11);* comb.date.difference(dtA, dtB, "weekday"); //6** dtA = new Date(2000, 11, 31, 23);* dtB = new Date(2001, 0, 1, 0);* comb.date.difference(dtA, dtB, "hour"); //1** dtA = new Date(2000, 11, 31, 23, 59);* dtB = new Date(2001, 0, 1, 0, 0);* comb.date.difference(dtA, dtB, "minute"); //1** dtA = new Date(2000, 11, 31, 23, 59, 59);* dtB = new Date(2001, 0, 1, 0, 0, 0);* comb.date.difference(dtA, dtB, "second"); //1** dtA = new Date(2000, 11, 31, 23, 59, 59, 999);* dtB = new Date(2001, 0, 1, 0, 0, 0, 0);* comb.date.difference(dtA, dtB, "millisecond"); //1*** @param {Date} date1* @param {Date} [date2 = new Date()]* @param {String} [interval = "day"] the intercal to find the difference of.* <ul>* <li>day | days</li>* <li>weekday | weekdays</li>* <li>year | years</li>* <li>week | weeks</li>* <li>quarter | quarters</li>* <li>months | months</li>* <li>hour | hours</li>* <li>minute | minutes</li>* <li>second | seconds</li>* <li>millisecond | milliseconds</li>* </ul>*/difference:function (/*Date*/date1, /*Date?*/date2, /*String*/interval, utc) {- 172
date2 = date2 || new Date();- 172
interval = interval || "day";- 172
var yearDiff = date2.getFullYear() - date1.getFullYear();- 172
var delta = 1; // Integer return value- 172
switch (interval) {case "quarter":case "quarters":- 5
var m1 = date1[utc ? "getUTCMonth" : "getMonth"]();- 5
var m2 = date2[utc ? "getUTCMonth" : "getMonth"]();// Figure out which quarter the months are in- 5
var q1 = floor(m1 / 3) + 1;- 5
var q2 = floor(m2 / 3) + 1;// Add quarters for any year difference between the dates- 5
q2 += (yearDiff * 4);- 5
delta = q2 - q1;- 5
break;case "weekday":case "weekdays":- 28
var days = round(date.difference(date1, date2, "day", utc));- 28
var weeks = parseInt(date.difference(date1, date2, "week", utc));- 28
var mod = days % 7;// Even number of weeks- 28
if (mod == 0) {- 7
days = weeks * 5;} else {// Weeks plus spare change (< 7 days)- 21
var adj = 0;- 21
var aDay = date1[utc ? "getUTCDay" : "getDay"]();- 21
var bDay = date2[utc ? "getUTCDay" : "getDay"]();- 21
weeks = parseInt(days / 7);- 21
mod = days % 7;// Mark the date advanced by the number of// round weeks (may be zero)- 21
var dtMark = new Date(date1);- 21
dtMark.setDate(dtMark[utc ? "getUTCDate" : "getDate"]() + (weeks * 7));- 21
var dayMark = dtMark[utc ? "getUTCDay" : "getDay"]();// Spare change days -- 6 or less- 21
if (days > 0) {- 12
switch (true) {// Range starts on Satcase (aDay == 6 || bDay == 6):- 3
adj = -1;- 3
break;// Range starts on Suncase aDay == 0:- 4
adj = 0;- 4
break;// Range ends on Suncase bDay == 0:- 1
adj = -2;- 1
break;// Range contains weekendcase (dayMark + mod) > 5:- 1
adj = -2;}- 9
} else if (days < 0) {- 9
switch (true) {// Range starts on Satcase aDay == 6:- 1
adj = 0;- 1
break;// Range starts on Suncase aDay == 0:- 3
adj = 1;- 3
break;// Range ends on Satcase bDay == 6:- 1
adj = 2;- 1
break;// Range ends on Suncase bDay == 0:- 1
adj = 1;- 1
break;// Range contains weekendcase (dayMark + mod) < 0:- 1
adj = 2;}}- 21
days += adj;- 21
days -= (weeks * 2);}- 28
delta = days;- 28
break;case "year":case "years":- 8
delta = yearDiff;- 8
break;case "month":case "months":- 5
var m1 = date1[utc ? "getUTCMonth" : "getMonth"]();- 5
var m2 = date2[utc ? "getUTCMonth" : "getMonth"]();- 5
delta = (m2 - m1) + (yearDiff * 12);- 5
break;case "week":case "weeks":- 32
delta = parseInt(date.difference(date1, date2, "day", utc) / 7);- 32
break;case "day":case "days":- 77
delta /= 24;case "hour":case "hours":- 83
delta /= 60;case "minute":case "minutes":- 87
delta /= 60;case "second":case "seconds":- 90
delta /= 1000;case "millisecond":case "milliseconds":- 94
delta *= date2.getTime() - date1.getTime();}// Round for fractional values and DST leaps- 172
return round(delta); // Number (integer)},/*** Parses a date string into a date object** @example* var aug_11_2006 = new Date(2006, 7, 11, 0);* comb.date.parse("08/11/06", "MM/dd/yy"); //aug_11_2006* comb.date.parse("11Aug2006", 'ddMMMyyyy'); //aug_11_2006* comb.date.parse("Aug2006", 'MMMyyyy'); //new Date(2006, 7, 1)* comb.date.parse("Aug 11, 2006", "MMM dd, yyyy"); //aug_11_2006* comb.date.parse("August 11, 2006", "MMMM dd, yyyy"); //aug_11_2006* comb.date.parse("Friday, August 11, 2006", "EEEE, MMMM dd, yyyy"); //aug_11_2006** @param {String} dateStr The string to parse* @param {String} format the format of the date composed of the following options* <ul>* <li> G Era designator Text AD</li>* <li> y Year Year 1996; 96</li>* <li> M Month in year Month July; Jul; 07</li>* <li> w Week in year Number 27</li>* <li> W Week in month Number 2</li>* <li> D Day in year Number 189</li>* <li> d Day in month Number 10</li>* <li> E Day in week Text Tuesday; Tue</li>* <li> a Am/pm marker Text PM</li>* <li> H Hour in day (0-23) Number 0</li>* <li> k Hour in day (1-24) Number 24</li>* <li> K Hour in am/pm (0-11) Number 0</li>* <li> h Hour in am/pm (1-12) Number 12</li>* <li> m Minute in hour Number 30</li>* <li> s Second in minute Number 55</li>* <li> S Millisecond Number 978</li>* <li> z Time zone General time zone Pacific Standard Time; PST; GMT-08:00</li>* <li> Z Time zone RFC 822 time zone -0800 </li>* </ul>** @returns {Date} the parsed date***/parse:function (dateStr, format) {- 28
if (!format) throw new Error('format required when calling comb.date.parse');- 28
var tokens = [], regexp = buildDateEXP(format, tokens),re = new RegExp("^" + regexp + "$", "i"),match = re.exec(dateStr);- 28
if (!match) {- 4
return null;} // null- 24
var result = [1970, 0, 1, 0, 0, 0, 0], // will get converted to a Date at the endamPm = "",valid = match.every(function (v, i) {- 106
if (!i) {- 24
return true;}- 82
var token = tokens[i - 1];- 82
var l = token.length;- 82
switch (token.charAt(0)) {case 'y':- 13
if (v < 100) {- 3
v = parseInt(v, 10);//choose century to apply, according to a sliding window//of 80 years before and 20 years after present year- 3
var year = '' + new Date().getFullYear(),century = year.substring(0, 2) * 100,cutoff = min(year.substring(2, 4) + 20, 99);- 3
result[0] = (v < cutoff) ? century + v : century - 100 + v;} else {- 10
result[0] = v;}- 13
break;case 'M':- 14
if (l > 2) {- 10
var months = monthNames;- 10
if (l === 3) {- 4
months = monthAbbr;}//Tolerate abbreviating period in month part//Case-insensitive comparison- 10
v = v.replace(".", "").toLowerCase();- 10
months = months.map(function (s) {- 120
return s.replace(".", "").toLowerCase();});- 10
if ((v = months.indexOf(v)) == -1) {- 1
return false;}} else {- 4
v--;}- 13
result[1] = v;- 13
break;case 'E':case 'e':- 6
var days = dayNames;- 6
if (l == 3) {- 2
days = dayAbbr;}//Case-insensitive comparison- 6
v = v.toLowerCase();- 6
days = days.map(function (d) {- 42
return d.toLowerCase();});- 6
var d = days.indexOf(v);- 6
if (d == -1) {- 2
v = parseInt(v);- 2
if (isNaN(v) || v > days.length) {- 1
return false;}} else {- 4
v = d;}- 5
break;case 'D':- 2
result[1] = 0;case 'd':- 15
result[2] = v;- 15
break;case 'a': //am/pm- 2
var am = "am";- 2
var pm = "pm";- 2
var period = /\./g;- 2
v = v.replace(period, '').toLowerCase();// we might not have seen the hours field yet, so store the state and apply hour change later- 2
amPm = (v == pm) ? 'p' : (v == am) ? 'a' : '';- 2
break;case 'k': //hour (0-11)- 1
if (v == 24) {- 1
v = 0;}// fallthrough...case 'h': //hour (1-12)case 'H': //hour (0-23)case 'K': //hour (0-11)//in the 12-hour case, adjusting for am/pm requires the 'a' part//which could come before or after the hour, so we will adjust later- 7
result[3] = v;- 7
break;case 'm': //minutes- 7
result[4] = v;- 7
break;case 's': //seconds- 5
result[5] = v;- 5
break;case 'S': //milliseconds- 4
result[6] = v;- 4
break;}- 80
return true;});- 24
if (valid) {- 22
var hours = +result[3];//account for am/pm- 22
if (amPm === 'p' && hours < 12) {- 1
result[3] = hours + 12; //e.g., 3pm -> 15- 21
} else if (amPm === 'a' && hours == 12) {- 1
result[3] = 0; //12am -> 0}- 22
var dateObject = new Date(result[0], result[1], result[2], result[3], result[4], result[5], result[6]); // Date- 22
var dateToken = (tokens.indexOf('d') != -1),monthToken = (tokens.indexOf('M') != -1),month = result[1],day = result[2],dateMonth = dateObject.getMonth(),dateDay = dateObject.getDate();- 22
if ((monthToken && dateMonth > month) || (dateToken && dateDay > day)) {- 1
return null;}- 21
return dateObject; // Date} else {- 2
return null;}},/*** Formats a date to the specidifed format string** @example** var date = new Date(2006, 7, 11, 0, 55, 12, 345);* comb.date.format(date, "EEEE, MMMM dd, yyyy"); //"Friday, August 11, 2006"* comb.date.format(date, "M/dd/yy"); //"8/11/06"* comb.date.format(date, "E"); //"6"* comb.date.format(date, "h:m a"); //"12:55 AM"* comb.date.format(date, 'h:m:s'); //"12:55:12"* comb.date.format(date, 'h:m:s.SS'); //"12:55:12.35"* comb.date.format(date, 'k:m:s.SS'); //"24:55:12.35"* comb.date.format(date, 'H:m:s.SS'); //"0:55:12.35"* comb.date.format(date, "ddMMyyyy"); //"11082006"** @param date the date to format* @param {String} format the format of the date composed of the following options* <ul>* <li> G Era designator Text AD</li>* <li> y Year Year 1996; 96</li>* <li> M Month in year Month July; Jul; 07</li>* <li> w Week in year Number 27</li>* <li> W Week in month Number 2</li>* <li> D Day in year Number 189</li>* <li> d Day in month Number 10</li>* <li> E Day in week Text Tuesday; Tue</li>* <li> a Am/pm marker Text PM</li>* <li> H Hour in day (0-23) Number 0</li>* <li> k Hour in day (1-24) Number 24</li>* <li> K Hour in am/pm (0-11) Number 0</li>* <li> h Hour in am/pm (1-12) Number 12</li>* <li> m Minute in hour Number 30</li>* <li> s Second in minute Number 55</li>* <li> S Millisecond Number 978</li>* <li> z Time zone General time zone Pacific Standard Time; PST; GMT-08:00</li>* <li> Z Time zone RFC 822 time zone -0800 </li>* </ul>*/format:function (date, format, utc) {- 70
utc = utc || false;- 70
var fullYear, month, day, d, hour, minute, second, millisecond;- 70
if (utc) {- 22
fullYear = date.getUTCFullYear(),month = date.getUTCMonth(),day = date.getUTCDay(),d = date.getUTCDate(),hour = date.getUTCHours(),minute = date.getUTCMinutes(),second = date.getUTCSeconds(),millisecond = date.getUTCMilliseconds();} else {- 48
fullYear = date.getFullYear(),month = date.getMonth(),d = date.getDate(),day = date.getDay(),hour = date.getHours(),minute = date.getMinutes(),second = date.getSeconds(),millisecond = date.getMilliseconds();}- 70
return format.replace(/([a-z])\1*/ig, function (match, options) {- 356
var s, pad, h,c = match.charAt(0),l = match.length;- 356
switch (c) {case 'd':- 39
s = "" + d;case 'H':- 68
!s && (s = "" + hour);case 'm':- 107
!s && (s = "" + minute);case 's':- 144
!s && (s = "" + second);- 144
pad = true;- 144
break;case 'G':- 4
s = ((l < 4) ? eraAbbr : eraNames)[fullYear < 0 ? 0 : 1];- 4
break;case 'y':- 42
s = fullYear;- 42
if (l > 1) {- 42
l == 2 ? s = string.truncate("" + s, 2, true) : pad = true;}- 42
break;case 'Q':case 'q':- 6
s = ceil((month + 1) / 3);- 6
pad = true;- 6
break;case 'M':- 39
if (l < 3) {- 31
s = month + 1;- 31
pad = true;} else {- 8
s = (l == 3 ? monthAbbr : monthNames)[month];}- 39
break;case 'w':- 4
s = getWeekOfYear(date, 0, utc), pad = true;- 4
break;case 'D':- 2
s = getDayOfYear(date, utc), pad = true;- 2
break;case 'E':- 10
if (l < 3) {- 2
s = day + 1;- 2
pad = true;} else {- 8
s = (l == 3 ? dayAbbr : dayNames)[day];}- 10
break;case 'a':- 2
s = (hour < 12) ? 'AM' : 'PM';- 2
break;case 'h':- 6
s = (hour % 12) || 12, pad = true;- 6
break;case 'K':- 2
s = (hour % 12), pad = true;- 2
break;case 'k':- 2
s = hour || 24, pad = true;- 2
break;case 'S':- 35
s = round(millisecond * pow(10, l - 3)), pad = true;- 35
break;case 'v':case 'z':- 31
s = comb.date.getTimezoneName(date);- 31
if (s) {- 27
break;}- 4
l = 4;// fallthrough... use GMT if tz not availablecase 'Z':- 4
var offset = date.getTimezoneOffset();- 4
var tz = [(offset >= 0 ? "-" : "+"),string.pad(floor(abs(offset) / 60), 2, "0"),string.pad(abs(offset) % 60, 2, "0")];- 4
if (l == 4) {- 4
tz.splice(0, 0, "GMT");- 4
tz.splice(3, 0, ":");}- 4
s = tz.join("");- 4
break;// case 'Y': case 'u': case 'W': case 'F': case 'g': case 'A': case 'e':// console.log(match+" modifier unimplemented");default:- 27
s = match;// throw new Error("comb.date.format: invalid pattern char: " + match);}- 356
if (pad) {- 272
s = string.pad(s, l, '0');}- 356
return s;});}};- 1
date = comb.date;/*** Adds the specified year/s to the current date.** @example** //assuming that current year is 2012* comb.yearsFromNow(1); //2013-mm-dd hh:MM:ss** @param {Number} val the number of years to add** @return {Date} a date with the number of years added*/- 1
comb.yearsFromNow = function (val) {- 1
return date.add(new Date(), "years", val);};/*** Subtracts the specified year/s from the current date.** @param {Number} val the number of years to subtract** @return {Date} a date with the number of years subtracted*/- 1
comb.yearsAgo = function (val) {- 1
return date.add(new Date(), "years", -val);};/*** Adds the specified month/s to the current date.** @example** //assuming that current month is february* comb.yearsFromNow(2); //yyyy-04-dd hh:MM:ss** @param {Number} val the number of months to add** @return {Date} a date with the number of years added*/- 1
comb.monthsFromNow = function (val) {- 1
return date.add(new Date(), "months", val);};/*** Subtracts the specified month/s from the current date.** @param {Number} val the number of months to subtract** @return {Date} a date with the number of months subtracted*/- 1
comb.monthsAgo = function (val) {- 1
return date.add(new Date(), "months", -val);};/*** Adds the specified day/s to the current date.** @param {Number} val the number of days to add** @return {Date} a date with the number of days added*/- 1
comb.daysFromNow = function (val) {- 14
return date.add(new Date(), "days", val);};/*** Subtracts the specified day/s from the current date.** @param {Number} val the number of days to subtract** @return {Date} a date with the number of days subtracted*/- 1
comb.daysAgo = function (val) {- 1
return date.add(new Date(), "days", -val);};/*** Adds the specified hour/s to the current date.** @param {Number} val the number of hours to add** @return {Date} a date with the number of hours added*/- 1
comb.hoursFromNow = function (val) {- 1
return date.add(new Date(), "hours", val);};/*** Subtracts the specified hour/s from the current date.** @param {Number} val the number of hours to subtract** @return {Date} a date with the number of hours subtracted*/- 1
comb.hoursAgo = function (val) {- 1
return date.add(new Date(), "hours", -val);};/*** Adds the specified minute/s to the current date.** @param {Number} val the number of minutes to add** @return {Date} a date with the number of minutes added*/- 1
comb.minutesFromNow = function (val) {- 1
return date.add(new Date(), "minutes", val);};/*** Subtracts the specified minute/s from the current date.** @param {Number} val the number of minutes to subtract** @return {Date} a date with the number of minutes subtracted*/- 1
comb.minutesAgo = function (val) {- 1
return date.add(new Date(), "minutes", -val);};/*** Adds the specified second/s to the current date.** @param {Number} val the number of seconds to add** @return {Date} a date with the number of seconds added*/- 1
comb.secondsFromNow = function (val) {- 1
return date.add(new Date(), "seconds", val);};/*** Subtracts the specified second/s from the current date.** @param {Number} val the number of seconds to subtract** @return {Date} a date with the number of seconds subtracted*/- 1
comb.secondsAgo = function (val) {- 1
return date.add(new Date(), "seconds", -val);};
|
base/functions.js
|
Coverage100.00
SLOC157
LOC44
Missed0
|
- 1
var comb = exports;/*** Determines if something is a function* @param {Anything} obj the thing to test if it is a function** @returns {Boolean} true if the obj is a function false otherwise*/- 1
comb.isFunction = function (obj) {- 885
return typeof obj == "function";};/*** Binds a method to a particular scope** @param {Object} scope the scope to bind the callback to* @param {String|Function} method the method to callback* @param [args] optional args to pass to the callback** @returns {Function} the hitched function*/- 1
comb.hitch = function (scope, method, args) {- 447
var args = Array.prototype.slice.call(arguments).slice(2);- 447
if (typeof method == "string") {- 187
method = scope[method];}- 447
if (method) {- 445
return function () {- 621
var scopeArgs = args.concat(Array.prototype.slice.call(arguments));- 621
return method.apply(scope, scopeArgs);};} else {- 2
throw new Error(method + "Method not defined");}};/*** @function* Binds a method to a particular scope** @param {Object} scope the scope to bind the callback to* @param {String|Function} method the method to callback* @param [args] optional args to pass to the callback** @returns {Function} the hitched function*/- 1
comb.bind = comb.hitch;/*** Binds a method to a particular scope ignoring any new arguments passed* into the function. This is useful if you want to force particular arguments and* ignore any new ones** @param {Object} scope the scope to bind the callback to* @param {String|Function} method the method to callback* @param [args] optional args to pass to the callback** @returns {Function} the hitched function*/- 1
comb.hitchIgnore = function (scope, method, args) {- 16
var args = Array.prototype.slice.call(arguments).slice(2);- 16
if (typeof method == "string") {- 14
method = scope[method];}- 16
if (method) {- 14
return function () {- 14
return method.apply(scope, args);};} else {- 2
throw new Error(method + "Method not defined");}};/*** @function* Binds a method to a particular scope ignoring any new arguments passed* into the function. This is useful if you want to force particular arguments and* ignore any new ones** @param {Object} scope the scope to bind the callback to* @param {String|Function} method the method to callback* @param [args] optional args to pass to the callback** @returns {Function} the hitched function*/- 1
comb.bindIgnore = comb.hitchIgnore;/*** Allows the passing of additional arguments to a function when it is called* especially useful for callbacks that you want to provide additional parameters to** @param {String|Function} method the method to callback* @param {Anything} [args] variable number of arguments to pass** @returns {Function} partially hitched function*/- 1
comb.partial = function (method, args) {- 103
var args = Array.prototype.slice.call(arguments).slice(1);- 103
if (typeof method == "function") {- 102
return function () {- 81
var scopeArgs = args.concat(Array.prototype.slice.call(arguments));- 81
return method.apply(this, scopeArgs);};} else {- 1
throw new Error(method + "Method not defined");}};- 1
var curry = function (f, execute) {- 8
return function (arg) {- 8
var args = Array.prototype.slice.call(arguments);- 8
return execute ? f.apply(this, arguments) : function (arg) {- 6
return f.apply(this, args.concat(Array.prototype.slice.call(arguments)));};}};/*** Curries a function* @example* var curried = comb.curry(4, function(a,b,c,d){* return [a,b,c,d].join(",");* }* curried("a");* curried("b");* curried("c");* curried("d") => "a,b,c,d"** //OR** curried("a")("b")("c")("d") => "a,b,c,d"*** @param {Number} depth the number of args you expect* @param {Function} cb the function to call once all args are gathered* @param {Object} [scope] what scope to call the function in** @returns {Function} the curried version of the function* */- 1
comb.curry = function (depth, cb, scope) {- 2
var f;- 2
if (scope) {- 1
f = comb.hitch(scope, cb);} else {- 1
f = cb;}- 2
if (depth) {- 2
var len = depth - 1;- 2
for (var i = len; i >= 0; i--) {- 8
f = curry(f, i == len);}}- 2
return f;};
|
base/index.js
|
Coverage100.00
SLOC12
LOC2
Missed0
|
- 1
var objectBase = require("./object");- 1
objectBase.merge(exports, objectBase,require("./broadcast"),require("./functions"),require("./string"),require("./number"),require("./misc"),require("./date"),require("./array"),require("./regexp"),require("./inflections"));
|
base/inflections.js
|
Coverage100.00
SLOC215
LOC93
Missed0
|
/** A port of the Rails/Sequel inflections class* http://sequel.rubyforge.org/rdoc/classes/Sequel/Inflections.html*/- 1
var array = require("./array").array, misc = require("./misc");- 1
var comb = exports;- 1
var CAMELIZE_CONVERT_REGEXP = /_(.)/g;- 1
var DASH = '-';- 1
var UNDERSCORE = '_';- 1
var UNDERSCORE_CONVERT_REGEXP1 = /([A-Z]+)(\d+|[A-Z][a-z])/g;- 1
var UNDERSCORE_CONVERT_REGEXP2 = /(\d+|[a-z])(\d+|[A-Z])/g;- 1
var UNDERSCORE_CONVERT_REPLACE = '$1_$2';- 1
var PLURALS = [], SINGULARS = [], UNCOUNTABLES = [];- 1
var _plural = function (rule, replacement) {- 20
PLURALS.unshift([rule, replacement])};- 1
var _singular = function (rule, replacement) {- 23
SINGULARS.unshift([rule, replacement])};/*** Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used# for strings, not regular expressions. You simply pass the irregular in singular and plural form.## Examples:# irregular 'octopus', 'octopi'# irregular 'person', 'people'* @param singular the singular version* @param plural the plural version*/- 1
var _irregular = function (singular, plural) {- 7
_plural(new RegExp("(" + singular.substr(0, 1) + ")" + singular.substr(1) + "$"), "$1" + plural.substr(1));- 7
_singular(new RegExp("(" + plural.substr(0, 1) + ")" + plural.substr(1) + "$"), "$1" + singular.substr(1));};- 1
var _uncountable = function (words) {- 1
UNCOUNTABLES.push(misc.argsToArray(arguments))- 1
UNCOUNTABLES = array.flatten(UNCOUNTABLES);};- 1
_plural(/$/, 's');- 1
_plural(/s$/i, 's');- 1
_plural(/(alias|(?:stat|octop|vir|b)us)$/i, '$1es');- 1
_plural(/(buffal|tomat)o$/i, '$1oes');- 1
_plural(/([ti])um$/i, '$1a');- 1
_plural(/sis$/i, 'ses');- 1
_plural(/(?:([^f])fe|([lr])f)$/i, '$1$2ves');- 1
_plural(/(hive)$/i, '$1s');- 1
_plural(/([^aeiouy]|qu)y$/i, '$1ies');- 1
_plural(/(x|ch|ss|sh)$/i, '$1es');- 1
_plural(/(matr|vert|ind)ix|ex$/i, '$1ices');- 1
_plural(/([m|l])ouse$/i, '$1ice');- 1
_plural(/^(ox)$/i, "$1en");- 1
_singular(/s$/i, '');- 1
_singular(/([ti])a$/i, '$1um');- 1
_singular(/(analy|ba|cri|diagno|parenthe|progno|synop|the)ses$/i, '$1sis');- 1
_singular(/([^f])ves$/i, '$1fe');- 1
_singular(/([h|t]ive)s$/i, '$1');- 1
_singular(/([lr])ves$/i, '$1f');- 1
_singular(/([^aeiouy]|qu)ies$/i, '$1y');- 1
_singular(/(m)ovies$/i, '$1ovie');- 1
_singular(/(x|ch|ss|sh)es$/i, '$1');- 1
_singular(/([m|l])ice$/i, '$1ouse');- 1
_singular(/buses$/i, 'bus');- 1
_singular(/oes$/i, 'o');- 1
_singular(/shoes$/i, 'shoe');- 1
_singular(/(alias|(?:stat|octop|vir|b)us)es$/i, '$1');- 1
_singular(/(vert|ind)ices$/i, '$1ex');- 1
_singular(/matrices$/i, 'matrix');- 1
_irregular('person', 'people');- 1
_irregular('man', 'men');- 1
_irregular('child', 'children');- 1
_irregular('sex', 'sexes');- 1
_irregular('move', 'moves');- 1
_irregular('quiz', 'quizzes');- 1
_irregular('testis', 'testes');- 1
_uncountable("equipment", "information", "rice", "money", "species", "series", "fish", "sheep", "news");- 1
exports.singular = _singular;- 1
exports.plural = _plural;- 1
exports.uncountable = _uncountable;/*** Converts a string to camelcase** @example* comb.camelize('hello_world') => helloWorld* comb.camelize('column_name') => columnName* comb.camelize('columnName') => columnName* comb.camelize(null) => null* comb.camelize() => undefined** @param {String} str the string to camelize* @memberOf comb* @returns {String} the camelized version of the string*/- 1
comb.camelize = function (str) {- 8
var ret = str;- 8
if (!misc.isUndefinedOrNull(str)) {- 6
ret = str.replace(CAMELIZE_CONVERT_REGEXP, function (a, b) {- 4
return b.toUpperCase();});}- 8
return ret;};/*** The reverse of camelize. Makes an underscored form from the expression in the string.** @example* comb.underscore('helloWorld') => hello_world* comb.underscore('column_name') => column_name* comb.underscore('columnName') => column_name* comb.underscore(null) => null* comb.underscore() => undefined* @param {String} str The string to underscore* @memberOf comb* @returns {String} the underscored version of the string* */- 1
comb.underscore = function (str) {- 7
var ret = str;- 7
if (!misc.isUndefinedOrNull(str)) {- 5
ret = str.replace(UNDERSCORE_CONVERT_REGEXP1, UNDERSCORE_CONVERT_REPLACE).replace(UNDERSCORE_CONVERT_REGEXP2, UNDERSCORE_CONVERT_REPLACE).replace(DASH, UNDERSCORE).toLowerCase();}- 7
return ret;};/*** Singularizes and camelizes the string. Also strips out all characters preceding* and including a period (".").** @example* comb.classify('egg_and_hams') => "eggAndHam"* comb.classify('post') => "post"* comb.classify('schema.post') => "post"** @param {String} str the string to classify* @memberOf comb* @returns {String} the classified version of the string**/- 1
comb.classify = function (str) {- 5
var ret = str;- 5
if (!misc.isUndefinedOrNull(str)) {- 3
ret = comb.camelize(comb.singularize(str.replace(/.*\./g, '')));}- 5
return ret;};/*** Returns the plural form of the word in the string.** @example* comb.pluralize("post") => "posts"* comb.pluralize("octopus") => "octopi"* comb.pluralize("sheep") => "sheep"* comb.pluralize("words") => "words"* comb.pluralize("the blue mailman") => "the blue mailmen"* comb.pluralize("CamelOctopus") => "CamelOctopi"** @param {String} str the string to pluralize* @memberOf comb* @returns {String} the pluralized version of the string**/- 1
comb.pluralize = function (str) {- 51
var ret = str;- 51
if (!misc.isUndefinedOrNull(str)) {- 49
if (UNCOUNTABLES.indexOf(str) == -1) {- 48
for (var i in PLURALS) {- 641
var s = PLURALS[i], rule = s[0], replacement = s[1];- 641
if ((ret = ret.replace(rule, replacement)) != str) {- 48
break;}}}}- 51
return ret;};/*** The reverse of pluralize, returns the singular form of a word in a string.** @example* comb.singularize("posts") => "post"* comb.singularize("octopi")=> "octopus"* comb.singularize("sheep") => "sheep"* comb.singularize("word") => "word"* comb.singularize("the blue mailmen") => "the blue mailman"* comb.singularize("CamelOctopi") => "CamelOctopus"** @param {String} str the string to singularize* @memberOf comb* @returns {String} the singularized version of the string* */- 1
comb.singularize = function (str) {- 54
var ret = str;- 54
if (!misc.isUndefinedOrNull(str)) {- 52
if (UNCOUNTABLES.indexOf(str) == -1) {- 51
for (var i in SINGULARS) {- 785
var s = SINGULARS[i], rule = s[0], replacement = s[1];- 785
if ((ret = ret.replace(rule, replacement)) != str) {- 49
break;}}}}- 54
return ret;};
|
base/misc.js
|
Coverage100.00
SLOC187
LOC51
Missed0
|
- 1
var comb = exports,arraySlice = Array.prototype.slice;/**** Converts an arguments object to an array** @example** function test(){* return comb.argsToArray(arguments);* }** function testSlice(){* return comb.argsToArray(arguments, 3);* }** console.log(test(1,2,3)); //[1,2,3]* console.log(test(1,2,3,4,5,6)); //[4,5,6]** @function* @param {Arguments} args the arguments object to convert* @param {Number} [slice=0] the number of arguments to slice.* @memberOf comb* @static* @returns {Array} array version of the arguments object*/- 1
function argsToArray(args, slice) {- 1688
slice = slice || 0;- 1688
return arraySlice.call(args, slice);}/*** Determines if obj is a boolean** @param {Anything} obj the thing to test if it is a boolean** @returns {Boolean} true if it is a boolean false otherwise* @memberOf comb* @static*/- 1
function isBoolean(obj) {- 24
var undef, type = typeof obj;- 24
return obj != undef && type == "boolean" || type == "Boolean";}/*** Determines if obj is undefined** @param {Anything} obj the thing to test if it is undefined* @returns {Boolean} true if it is undefined false otherwise* @memberOf comb* @static*/- 1
function isUndefined(obj) {- 1254
var undef;- 1254
return obj !== null && obj === undef;}/*** Determins if the obj is not undefined** @param obj the thing to test if it is not undefined** @return {Boolean} true if it is defined false otherwise* @memberOf comb* @static*/- 1
function isDefined(obj) {- 8
return !isUndefined(obj);}/*** Determines if obj is undefined or null** @param {Anything} obj the thing to test if it is undefined or null* @returns {Boolean} true if it is undefined or null false otherwise* @memberOf comb* @static*/- 1
function isUndefinedOrNull(obj) {- 1044
return isUndefined(obj) || isNull(obj);}/*** Determines if obj is null** @param {Anything} obj the thing to test if it is null** @returns {Boolean} true if it is null false otherwise* @memberOf comb* @static*/- 1
function isNull(obj) {- 1042
var undef;- 1042
return obj !== undef && obj == null;}/*** Determines if obj is an Arguments object;** @param {Anything} obj the thing to test if it is null** @returns {Boolean} true if it is an Arguments Object false otherwise* @memberOf comb* @static*/- 1
function isArguments(object) {- 23
return !isUndefinedOrNull(object) && Object.prototype.toString.call(object) == '[object Arguments]';}- 1
function isInstance(obj, clazz) {- 693
if (typeof clazz == "function") {- 692
return obj instanceof clazz;} else {- 1
return false;}}/*** Determines if obj is an instance of a particular class** @param {Anything} obj the thing to test if it and instance of a class* @param {Object} Clazz used to determine if the object is an instance of** @returns {Boolean} true if it is an instance of the clazz false otherwise* @memberOf comb* @static*/- 1
function isInstanceOf(obj, clazz) {- 693
return argsToArray(arguments, 1).some(function (c) {- 693
return isInstance(obj, c);});}- 1
(function () {- 1
var listeners = [];- 1
var setup = false;- 1
function setupListener() {- 13
if (!setup) {- 1
var orig = process.emit;- 1
process.emit = function (event) {- 680
try {- 680
if (event === 'exit') {- 1
listeners.forEach(function (cb) {- 13
cb();});}} finally {- 680
orig.apply(this, arguments);}};- 1
setup = true;}}/*** Adds listeners to process.exit without having to change setMaxListeners useful if you* are writing a library and do not want to change core setting.** @param {Funciton} cb funciton to call when process is exiting* @memberOf comb* @static*/- 1
function listenForExit(cb) {- 13
setupListener();- 13
listeners.push(cb);}- 1
comb.listenForExit = listenForExit;})();- 1
comb.argsToArray = argsToArray;- 1
comb.isBoolean = isBoolean;- 1
comb.isUndefined = isUndefined;- 1
comb.isDefined = isDefined;- 1
comb.isUndefinedOrNull = isUndefinedOrNull;- 1
comb.isNull = isNull;- 1
comb.isArguments = isArguments;- 1
comb.isInstanceOf = isInstanceOf;
|
base/number.js
|
Coverage100.00
SLOC66
LOC10
Missed0
|
- 1
var comb = exports;/*** Determines if obj is a number** @param {Anything} obj the thing to test if it is a Number** @returns {Boolean} true if it is a number false otherwise*/- 1
comb.isNumber = function(obj) {- 729
var undef;- 729
return obj !== undef && obj != null && (typeof obj == "number" || obj instanceof Number);};/*** @private*/- 1
var round = Math.round, pow = Math.pow;/*** @namespace Utilities for numbers*/- 1
comb.number = {/**@lends comb.number*//*** Rounds a number to the specified places.** @example** comb.number.round(10.000009, 2); //10* comb.number.round(10.000009, 5); //10.00001* comb.number.round(10.0009, 3); //10.001* comb.number.round(10.0009, 2); //10* comb.number.round(10.0009, 3); //10.001** @param {Number} num the number to round.* @param {Number} places the number of places to round to.*/round : function(number, places, increment) {- 6
increment = increment || 1e-20;- 6
var factor = 10 / (10 * (increment || 10));- 6
return (Math.ceil(factor * +number) / factor).toFixed(places) * 1; // Number},/*** Rounds a number to the specified places, rounding up.** @example** comb.number.roundCeil(10.000001, 2); //10.01* comb.number.roundCeil(10.000002, 5); //10.00001* comb.number.roundCeil(10.0003, 3); //10.001* comb.number.roundCeil(10.0004, 2); //10.01* comb.number.roundCeil(10.0005, 3); //10.001* comb.number.roundCeil(10.0002, 2); //10.01** @param {Number} num the number to round.* @param {Number} places the number of places to round to.*/roundCeil : function(number, places){- 6
return Math.ceil(number * Math.pow(10, places))/Math.pow(10, places);}};
|
base/object.js
|
Coverage100.00
SLOC300
LOC87
Missed0
|
- 1
var comb = exports,misc = require("./misc.js"),isUndefinedOrNull = misc.isUndefined,isArguments = misc.isArguments,pSlice = Array.prototype.slice;//taken from node js assert.js//https://github.com/joyent/node/blob/master/lib/assert.js- 1
var _deepEqual = function (actual, expected) {// 7.1. All identical values are equivalent, as determined by ===.- 43
if (actual === expected) {- 3
return true;- 40
} else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {- 1
if (actual.length != expected.length) return false;- 1
for (var i = 0; i < actual.length; i++) {- 3
if (actual[i] !== expected[i]) return false;}- 1
return true;// 7.2. If the expected value is a Date object, the actual value is// equivalent if it is also a Date object that refers to the same time.- 39
} else if (actual instanceof Date && expected instanceof Date) {- 2
return actual.getTime() === expected.getTime();// 7.3 If the expected value is a RegExp object, the actual value is// equivalent if it is also a RegExp object with the same source and// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).- 37
} else if (actual instanceof RegExp && expected instanceof RegExp) {- 2
return actual.source === expected.source &&actual.global === expected.global &&actual.multiline === expected.multiline &&actual.lastIndex === expected.lastIndex &&actual.ignoreCase === expected.ignoreCase;// 7.4. Other pairs that do not both pass typeof value == 'object',// equivalence is determined by ==.- 35
} else if (typeof actual != 'object' && typeof expected != 'object') {- 13
return actual == expected;// 7.5 For all other Object pairs, including Array objects, equivalence is// determined by having the same number of owned properties (as verified// with Object.prototype.hasOwnProperty.call), the same set of keys// (although not necessarily the same order), equivalent values for every// corresponding key, and an identical 'prototype' property. Note: this// accounts for both named and indexed properties on Arrays.} else {- 22
return objEquiv(actual, expected);}};- 1
var objEquiv = function (a, b) {- 22
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))- 7
return false;// an identical 'prototype' property.- 15
if (a.prototype !== b.prototype) return false;//~~~I've managed to break Object.keys through screwy arguments passing.// Converting to array solves the problem.- 15
if (isArguments(a)) {- 2
if (!isArguments(b)) {- 1
return false;}- 1
a = pSlice.call(a);- 1
b = pSlice.call(b);- 1
return _deepEqual(a, b);}- 13
try {- 13
var ka = Object.keys(a),kb = Object.keys(b),key, i;} catch (e) {//happens when one is a string literal and the other isn't- 1
return false;}// having the same number of owned properties (keys incorporates// hasOwnProperty)- 12
if (ka.length != kb.length)- 2
return false;//the same set of keys (although not necessarily the same order),- 10
ka.sort();- 10
kb.sort();//~~~cheap key test- 10
for (i = ka.length - 1; i >= 0; i--) {- 10
if (ka[i] != kb[i])- 2
return false;}//equivalent values for every corresponding key, and//~~~possibly expensive deep test- 8
for (i = ka.length - 1; i >= 0; i--) {- 8
key = ka[i];- 11
if (!_deepEqual(a[key], b[key])) return false;}- 5
return true;}- 1
var merge = function (target, source) {- 49
var name, s;- 49
for (name in source) {- 207
s = source[name];- 207
if (!(name in target) || (target[name] !== s)) {- 206
target[name] = s;}}- 49
return target;};- 1
var deepMerge = function (target, source) {- 16
var name, s, t;- 16
for (name in source) {- 22
s = source[name], t = target[name];- 22
if (!_deepEqual(t, s)) {- 22
if (comb.isHash(t) && comb.isHash(s)) {- 4
target[name] = deepMerge(t, s);- 18
} else if (comb.isHash(s)) {- 5
target[name] = deepMerge({}, s);} else {- 13
target[name] = s;}}}- 16
return target;};/*** Merges objects together* NOTE: this function takes a variable number of objects to merge** @example** var myObj = {};* comb.merge(myObj, {test : true});** myObj.test => true** comb.merge(myObj, {test : false}, {test2 : false}, {test3 : "hello", test4 : "world"});* myObj.test => false* myObj.test2 => false* myObj.test3 => "hello"* myObj.test4 => "world"*** @param {Object} obj the object to merge into* @param {Object} props variable number of objects to merge into the obj** @returns {Object} the merged object*/- 1
comb.merge = function (obj, props) {- 31
if (!obj) {- 1
obj = {};}- 31
for (var i = 1, l = arguments.length; i < l; i++) {- 49
merge(obj, arguments[i]);}- 31
return obj; // Object};/*** Merges objects together only overriding properties that are different.* NOTE: this function takes a variable number of objects to merge** @example** var myObj = {my : {cool : {property1 : 1, property2 : 2}}};* comb.deepMerge(myObj, {my : {cool : {property3 : 3}}});** myObj.my.cool.property1 => 1* myObj.my.cool.property2 => 2* myObj.my.cool.property3 => 3*** @param {Object} obj the object to merge into* @param {Object} props variable number of objects to merge into the obj** @returns {Object} the merged object*/- 1
comb.deepMerge = function (obj, props) {- 4
if (!obj) {- 1
obj = {};}- 4
for (var i = 1, l = arguments.length; i < l; i++) {- 7
deepMerge(obj, arguments[i]);}- 4
return obj; // Object};/*** Extends the prototype of an object if it exists otherwise it extends the object.** @example** var MyObj = function(){};* MyObj.prototype.test = true;* comb.extend(MyObj, {test2 : false, test3 : "hello", test4 : "world"});** var myObj = new MyObj();** myObj.test => true* myObj.test2 => false* myObj.test3 => "hello"* myObj.test4 => "world"** var myObj2 = {};* myObj2.test = true;* comb.extend(myObj2, {test2 : false, test3 : "hello", test4 : "world"});** myObj2.test => true* myObj2.test2 => false* myObj2.test3 => "hello"* myObj2.test4 => "world"*** @param {Object} parent the parent object to extend* @param {Object} extend the extension object to mixin to the parent** @returns {Object} returns the extended object*/- 1
comb.extend = function (parent, extend) {- 2
var proto = parent.prototype || parent;- 2
return exports.merge(proto, extend);};/*** Determines if obj is an object** @param {Anything} obj the thing to test if it is an object** @returns {Boolean} true if it is an object false otherwise*/- 1
comb.isObject = function (obj) {- 87
var undef;- 87
return obj != null && obj != undef && typeof obj == "object";};/*** Determines if an object is just a hash and not a qualified Object such as Number** @example* comb.isHash({}) => true* comb.isHash({1 : 2, a : "b"}) => true* comb.isHash(new Date()) => false* comb.isHash(new String()) => false* comb.isHash(new Number()) => false* comb.isHash(new Boolean()) => false* comb.isHash() => false* comb.isHash("") => false* comb.isHash(1) => false* comb.isHash(false) => false* comb.isHash(true) => false* @param {Anything} obj the thing to test if it is a hash** @returns {Boolean} true if it is a hash false otherwise*/- 1
comb.isHash = function (obj) {- 72
var ret = comb.isObject(obj);- 72
return ret && obj.constructor === Object;}/*** Determines if an object is empty** @example** comb.isEmpty({}) => true* comb.isEmpty({a : 1}) => false** @param object the object to test* @returns {Boolean} true if the object is empty;*/- 1
comb.isEmpty = function (object) {- 5
if (comb.isObject(object)) {- 4
for (var i in object) {- 2
if (object.hasOwnProperty(i)) {- 2
return false;}}}- 3
return true;};/*** Determines if two things are deep equal.** @example** comb.deepEqual({a : 1, b : 2}, {a : 1, b : 2}) => true* comb.deepEqual({a : 1}, {a : 1, b : 2}) => false** @param o1 the first thing to compare* @param o3 the second thing to compare* @return {Boolean}*/- 1
comb.deepEqual = function (o1, o2) {- 12
return _deepEqual(o1, o2);}
|
base/regexp.js
|
Coverage100.00
SLOC48
LOC11
Missed0
|
- 1
var comb = exports;/*** Tests if something is a regular expression.** @example** comb.isRegExp(/hello/); //true* comb.isRegExp("hello"); //false** @param obj the thing to test.* @return {Boolean}* @static* @memberOf comb**/- 1
function isRegExp(obj) {- 7
var undef;- 7
return obj !== undef && obj != null && (obj instanceof RegExp);}- 1
comb.isRexExp = isRegExp;- 1
comb.isRegExp = isRegExp;/*** @namespace Regeular expression utilities**/- 1
comb.regexp = {/**@lends comb.regexp*//*** Escapes a string** @param {String} str the string to escape* @param {String} [except] characters to ignore** @returns {String} the escaped string*/escapeString:function (str, except) {- 31
return str.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, function (ch) {- 31
if (except && except.indexOf(ch) != -1) {- 15
return ch;}- 16
return "\\" + ch;}); // String}};
|
base/string.js
|
Coverage100.00
SLOC1184
LOC131
Missed0
|
- 1
var comb = exports, date, misc = require("./misc");/*** Tests if something is a string.** @example** comb.isString("true") //true* comb.isString(true) //false** @param obj the thing to test* @return {Boolean} returns true if the argument is a string.* @static* @memberOf comb*/- 1
function isString(obj) {- 924
var undef;- 924
return obj != undef && (typeof obj == "string" || obj instanceof String);}- 1
comb.isString = isString;- 1
var FORMAT_REGEX = /%((?:-?\+?.?\d*)?|(?:\[[^\[|\]]*\]))?([sjdDZ])/g;- 1
var INTERP_REGEX = /{(?:\[([^\[|\]]*)\])?(\w+)}/g;- 1
var STR_FORMAT = /(-?)(\+?)([A-Z|a-z|\W]?)([1-9][0-9]*)?$/;- 1
var OBJECT_FORMAT = /([1-9][0-9]*)$/g;- 1
var formatString = function (string, format) {- 58
var match = format.match(STR_FORMAT), ret = string, cString = comb.string;- 58
if (match) {- 58
var isLeftJustified = match[1], padChar = match[3], width = match[4];- 58
if (width) {- 58
width = parseInt(width);- 58
if (ret.length < width) {- 30
ret = cString.pad(ret, width, padChar, isLeftJustified);} else {- 28
ret = cString.truncate(ret, width);}}}- 58
return ret;};- 1
var formatNumber = function (number, format) {- 8
if (typeof number == "number") {- 7
var cString = comb.string, ret = "" + number;- 7
var match = format.match(STR_FORMAT);- 7
if (match) {- 7
var isLeftJustified = match[1], signed = match[2], padChar = match[3], width = match[4];- 7
if (signed) {- 3
ret = (number > 0 ? "+" : "") + ret;}- 7
if (width) {- 5
width = parseInt(width);- 5
if (ret.length < width) {- 4
ret = cString.pad(ret, width, padChar || "0", isLeftJustified);} else {- 1
ret = cString.truncate(ret, width);}}}} else {- 1
throw new Error("comb.string.format : when using %d the parameter must be a number!");}- 7
return ret;};- 1
var formatObject = function (object, format) {- 4
var ret, match = format.match(OBJECT_FORMAT), spacing = 0;- 4
if (match) {- 4
spacing = parseInt(match[0]);- 4
if (isNaN(spacing)) spacing = 0;}- 4
try {- 4
ret = JSON.stringify(object, null, spacing);} catch (e) {- 1
throw new Error("comb.string.format : Unable to parse json from ", object);}- 3
return ret;};- 1
var styles = {//stylesbold:1,bright:1,italic:3,underline:4,blink:5,inverse:7,crossedOut:9,red:31,green:32,yellow:33,blue:34,magenta:35,cyan:36,white:37,redBackground:41,greenBackground:42,yellowBackground:43,blueBackground:44,magentaBackground:45,cyanBackground:46,whiteBackground:47,encircled:52,overlined:53,grey:90,black:90};/**@namespace comb characters*/- 1
comb.characters = {/**@lends comb.characters*//*** âº*/SMILEY:"âº",/*** â»*/SOLID_SMILEY:"â»",/*** â¥*/HEART:"â¥",/*** â¦*/DIAMOND:"â¦",/*** â£*/CLOVE:"â£",/*** â*/SPADE:"â ",/*** â¢*/DOT:"â¢",/*** â*/SQUARE_CIRCLE:"â",/*** â*/CIRCLE:"â",/*** â*/FILLED_SQUARE_CIRCLE:"â",/*** â*/MALE:"â",/*** â*/FEMALE:"â",/*** âª*/EIGHT_NOTE:"âª",/*** â«*/DOUBLE_EIGHT_NOTE:"â«",/*** â¼*/SUN:"â¼",/*** âº*/PLAY:"âº",/*** â*/REWIND:"â",/*** â*/UP_DOWN:"â",/*** ¶*/PILCROW:"¶",/*** §*/SECTION:"§",/*** â¬*/THICK_MINUS:"â¬",/*** â¨*/SMALL_UP_DOWN:"â¨",/*** â*/UP_ARROW:"â",/*** â*/DOWN_ARROW:"â",/*** â*/RIGHT_ARROW:"â",/*** â*/LEFT_ARROW:"â",/*** â*/RIGHT_ANGLE:"â",/*** â*/LEFT_RIGHT_ARROW:"â",/*** â²*/TRIANGLE:"â²",/*** â¼*/DOWN_TRIANGLE:"â¼",/*** â*/HOUSE:"â",/*** Ã*/C_CEDILLA:"Ã",/*** ü*/U_UMLAUT:"ü",/*** é*/E_ACCENT:"é",/*** â*/A_LOWER_CIRCUMFLEX:"â",/*** ä*/A_LOWER_UMLAUT:"ä",/*** Ã*/A_LOWER_GRAVE_ACCENT:"à ",/*** Ã¥*/A_LOWER_CIRCLE_OVER:"Ã¥",/*** ç*/C_LOWER_CIRCUMFLEX:"ç",/*** ê*/E_LOWER_CIRCUMFLEX:"ê",/*** ë*/E_LOWER_UMLAUT:"ë",/*** è*/E_LOWER_GRAVE_ACCENT:"è",/*** ï*/I_LOWER_UMLAUT:"ï",/*** î*/I_LOWER_CIRCUMFLEX:"î",/*** ì*/I_LOWER_GRAVE_ACCENT:"ì",/*** Ã*/A_UPPER_UMLAUT:"Ã",/*** Ã*/A_UPPER_CIRCLE:"à ",/*** Ã*/E_UPPER_ACCENT:"Ã",/*** æ*/A_E_LOWER:"æ",/*** Ã*/A_E_UPPER:"Ã",/*** ô*/O_LOWER_CIRCUMFLEX:"ô",/*** ö*/O_LOWER_UMLAUT:"ö",/*** ò*/O_LOWER_GRAVE_ACCENT:"ò",/*** û*/U_LOWER_CIRCUMFLEX:"û",/*** ù*/U_LOWER_GRAVE_ACCENT:"ù",/*** ÿ*/Y_LOWER_UMLAUT:"ÿ",/*** Ã*/O_UPPER_UMLAUT:"Ã",/*** Ã*/U_UPPER_UMLAUT:"Ã",/*** ¢*/CENTS:"¢",/*** £*/POUND:"£",/*** Â¥*/YEN:"Â¥",/*** ¤*/CURRENCY:"¤",/*** â§*/PTS:"â§",/*** Æ*/FUNCTION:"Æ",/*** á*/A_LOWER_ACCENT:"á",/*** Ã*/I_LOWER_ACCENT:"Ã",/*** ó*/O_LOWER_ACCENT:"ó",/*** ú*/U_LOWER_ACCENT:"ú",/*** ñ*/N_LOWER_TILDE:"ñ",/*** Ã*/N_UPPER_TILDE:"Ã",/*** ª*/A_SUPER:"ª",/*** º*/O_SUPER:"º",/*** ¿*/UPSIDEDOWN_QUESTION:"¿",/*** â*/SIDEWAYS_L:"â",/*** ¬*/NEGATION:"¬",/*** ½*/ONE_HALF:"½",/*** ¼*/ONE_FOURTH:"¼",/*** ¡*/UPSIDEDOWN_EXCLAMATION:"¡",/*** «*/DOUBLE_LEFT:"«",/*** »*/DOUBLE_RIGHT:"»",/*** â*/LIGHT_SHADED_BOX:"â",/*** â*/MEDIUM_SHADED_BOX:"â",/*** â*/DARK_SHADED_BOX:"â",/*** â*/VERTICAL_LINE:"â",/*** â¤*/MAZE__SINGLE_RIGHT_T:"â¤",/*** â*/MAZE_SINGLE_RIGHT_TOP:"â",/*** â*/MAZE_SINGLE_RIGHT_BOTTOM_SMALL:"â",/*** â*/MAZE_SINGLE_LEFT_TOP_SMALL:"â",/*** â*/MAZE_SINGLE_LEFT_BOTTOM_SMALL:"â",/*** â*/MAZE_SINGLE_LEFT_T:"â",/*** â´*/MAZE_SINGLE_BOTTOM_T:"â´",/*** â¬*/MAZE_SINGLE_TOP_T:"â¬",/*** â¼*/MAZE_SINGLE_CENTER:"â¼",/*** â*/MAZE_SINGLE_HORIZONTAL_LINE:"â",/*** â¡*/MAZE_SINGLE_RIGHT_DOUBLECENTER_T:"â¡",/*** â*/MAZE_SINGLE_RIGHT_DOUBLE_BL:"â",/*** â¢*/MAZE_SINGLE_RIGHT_DOUBLE_T:"â¢",/*** â*/MAZE_SINGLE_RIGHT_DOUBLEBOTTOM_TOP:"â",/*** â*/MAZE_SINGLE_RIGHT_DOUBLELEFT_TOP:"â",/*** â*/MAZE_SINGLE_LEFT_DOUBLE_T:"â",/*** â§*/MAZE_SINGLE_BOTTOM_DOUBLE_T:"â§",/*** â¤*/MAZE_SINGLE_TOP_DOUBLE_T:"â¤",/*** â¥*/MAZE_SINGLE_TOP_DOUBLECENTER_T:"â¥",/*** â¨*/MAZE_SINGLE_BOTTOM_DOUBLECENTER_T:"â¨",/*** â*/MAZE_SINGLE_LEFT_DOUBLERIGHT_BOTTOM:"â",/*** â*/MAZE_SINGLE_LEFT_DOUBLERIGHT_TOP:"â",/*** â*/MAZE_SINGLE_LEFT_DOUBLEBOTTOM_TOP:"â",/*** â*/MAZE_SINGLE_LEFT_DOUBLETOP_BOTTOM:"â",/*** Î*/MAZE_SINGLE_LEFT_TOP:"Î",/*** â*/MAZE_SINGLE_RIGHT_BOTTOM:"â",/*** â*/MAZE_SINGLE_LEFT_CENTER:"â",/*** â«*/MAZE_SINGLE_DOUBLECENTER_CENTER:"â«",/*** âª*/MAZE_SINGLE_DOUBLECROSS_CENTER:"âª",/*** â£*/MAZE_DOUBLE_LEFT_CENTER:"â£",/*** â*/MAZE_DOUBLE_VERTICAL:"â",/*** â*/MAZE_DOUBLE_RIGHT_TOP:"â",/*** â*/MAZE_DOUBLE_RIGHT_BOTTOM:"â",/*** â*/MAZE_DOUBLE_LEFT_BOTTOM:"â",/*** â*/MAZE_DOUBLE_LEFT_TOP:"â",/*** â©*/MAZE_DOUBLE_BOTTOM_T:"â©",/*** â¦*/MAZE_DOUBLE_TOP_T:"â¦",/*** â*/MAZE_DOUBLE_LEFT_T:"â ",/*** â*/MAZE_DOUBLE_HORIZONTAL:"â",/*** â¬*/MAZE_DOUBLE_CROSS:"â¬",/*** â*/SOLID_RECTANGLE:"â",/*** â*/THICK_LEFT_VERTICAL:"â",/*** â*/THICK_RIGHT_VERTICAL:"â",/*** â*/SOLID_SMALL_RECTANGLE_BOTTOM:"â",/*** â*/SOLID_SMALL_RECTANGLE_TOP:"â",/*** Φ*/PHI_UPPER:"Φ",/*** â*/INFINITY:"â",/*** â©*/INTERSECTION:"â©",/*** â¡*/DEFINITION:"â¡",/*** ±*/PLUS_MINUS:"±",/*** â¥*/GT_EQ:"â¥",/*** â¤*/LT_EQ:"â¤",/*** â*/THEREFORE:"â ",/*** âµ*/SINCE:"âµ",/*** â*/DOESNOT_EXIST:"â",/*** â*/EXISTS:"â",/*** â*/FOR_ALL:"â",/*** â*/EXCLUSIVE_OR:"â",/*** â¡*/BECAUSE:"â¡",/*** ÷*/DIVIDE:"÷",/*** â*/APPROX:"â",/*** °*/DEGREE:"°",/*** â*/BOLD_DOT:"â",/*** ·*/DOT_SMALL:"·",/*** â*/CHECK:"â",/*** â*/ITALIC_X:"â",/*** â¿*/SUPER_N:"â¿",/*** ²*/SQUARED:"²",/*** ³*/CUBED:"³",/*** â*/SOLID_BOX:"â ",/*** â°*/PERMILE:"â°",/*** ®*/REGISTERED_TM:"®",/*** ©*/COPYRIGHT:"©",/*** â¢*/TRADEMARK:"â¢",/*** β*/BETA:"β",/*** γ*/GAMMA:"γ",/*** ζ*/ZETA:"ζ",/*** η*/ETA:"η",/*** ι*/IOTA:"ι",/*** κ*/KAPPA:"κ",/*** λ*/LAMBDA:"λ",/*** ν*/NU:"ν",/*** ξ*/XI:"ξ",/*** ο*/OMICRON:"ο",/*** Ï*/RHO:"Ï",/*** Ï*/UPSILON:"Ï ",/*** Ï*/CHI_LOWER:"Ï",/*** Ï*/CHI_UPPER:"Ï",/*** Ï*/PSI:"Ï",/*** α*/ALPHA:"α",/*** Ã*/ESZETT:"Ã",/*** Ï*/PI:"Ï",/*** Σ*/SIGMA_UPPER:"Σ",/*** Ï*/SIGMA_LOWER:"Ï",/*** µ*/MU:"µ",/*** Ï*/TAU:"Ï",/*** Î*/THETA:"Î",/*** Ω*/OMEGA:"Ω",/*** δ*/DELTA:"δ",/*** Ï*/PHI_LOWER:"Ï",/*** ε*/EPSILON:"ε"}/**@namespace String utilities*/- 1
comb.string = {/**@lends comb.string*//*** Pads a string** @example** comb.string.pad("STR", 5, " ", true) => "STR "* comb.string.pad("STR", 5, "$") => "$$STR"** @param {String} string the string to pad* @param {Number} length the length of the string when padded* @param {String} [ch= " "] character to pad the string with* @param {Boolean} [end=false] if true then the padding is added to the end** @returns {String} the padded string*/pad:function (string, length, ch, end) {- 318
string = "" + string; //check for numbers- 318
ch = ch || " ";- 318
var strLen = string.length;- 318
while (strLen < length) {- 204
if (end) {- 117
string += ch;} else {- 87
string = ch + string;}- 204
strLen++;}- 318
return string;},/*** Truncates a string to the specified length.* @example** //from the beginning* comb.string.truncate("abcdefg", 3) => "abc";* //from the end* comb.string.truncate("abcdefg", 3,true) => "efg"* //omit the length* comb.string.truncate("abcdefg") => "abcdefg"** @param {String} string the string to truncate* @param {Number} [length = -1] the max length of the string, if the string is* shorter than the length then the string is returned.* @param {Boolean} [end=false] truncate starting at the end of the string** @return {String} the truncated string.*/truncate:function (string, length, end) {- 39
var ret = string;- 39
if (comb.isString(ret)) {- 37
if (string.length > length) {- 20
if (end) {- 5
var l = string.length;- 5
ret = string.substring(l - length, l);} else {- 15
ret = string.substring(0, length);}}} else {- 2
ret = comb.string.truncate("" + ret, length);}- 39
return ret;},/*** Formats a string with the specified format** @example** var format = comb.string.format;** format("%s, %s", ["Hello", "World"]) => "Hello, World";* format("%[ 10]s, %[- 10]s", ["Hello", "World"])* => " Hello, World ";* format("%-!10s, %#10s, %10s and %-10s",* "apple", "orange", "bananas", "watermelons")* => "apple!!!!!, ####orange, bananas and watermelon"* format("%+d, %+d, %10d, %-10d, %-+#10d, %10d",* 1,-2, 1, 2, 3, 100000000000)* => "+1, -2, 0000000001, 2000000000, +3########, 1000000000"* format("%[h:mm a]D", [date]) => 7:32 PM - local -* format("%[h:mm a]Z", [date]) => 12:32 PM - UTC* //When using object formats they must be in an array otherwise* //format will try to interpolate the properties into the string.* format("%j", [{a : "b"}])* => '{"a":"b"}'* format("%1j, %4j", [{a : "b"}, {a : "b"}])* => '{\n "a": "b"\n},\n{\n "a": "b"\n}'* format("{hello}, {world}", {hello : "Hello", world : "World")* => "Hello, World";* format({[-s10]apple}, {[%#10]orange}, {[10]banana} and {[-10]watermelons}",* {* apple : "apple",* orange : "orange",* banana : "bananas",* watermelons : "watermelons"* });* => applesssss, ####orange, bananas and watermelon** @param {String} str the string to format, if you want to use a spacing character as padding (other than \\s) then put your format in brackets.* <ol>* <li>String Formats %[options]s</li>* <ul>* <li>- : left justified</li>* <li>Char : padding character <b>Excludes d,j,s</b></li>* <li>Number : width</li>* </ul>* </li>* <li>Number Formats %[options]d</li>* <ul>* <li>- : left justified</li>* <li>+ : signed number</li>* <li>Char : padding character <b>Excludes d,j,s</b></li>* <li>Number : width</li>* </ul>* </li>* <li>Object Formats %[options]j</li>* <ul>* <li>Number : spacing for object properties.</li>* </ul>* </li>* </ol>*** @param {Object|Array|Arguments...} obj the parameters to replace in the string* if an array is passed then the array is used sequentially* if an object is passed then the object keys are used* if a variable number of args are passed then they are used like an array** @returns {String} the formatted string*/format:function (str, obj) {- 90
!date && (date = require("./date"));- 90
if (obj instanceof Array) {- 33
var i = 0, len = obj.length;//find the matches- 33
return str.replace(FORMAT_REGEX, function (m, format, type) {- 53
var replacer, ret;- 53
if (i < len) {- 52
replacer = obj[i++];} else {//we are out of things to replace with so//just return the match?- 1
return m;}- 52
if (m == "%s" || m == "%d" || m == "%D") {//fast path!- 27
ret = replacer;- 25
} else if (m == "%Z") {- 1
ret = replacer.toUTCString();- 24
} else if (m == "%j") {- 2
try {- 2
ret = JSON.stringify(replacer);} catch (e) {- 1
throw new Error("comb.string.format : Unable to parse json from ", replacer);}} else {- 22
format = format.replace(/^\[|\]$/g, "");- 22
switch (type) {case "s":- 4
ret = formatString(replacer, format);- 4
break;case "d":- 7
ret = formatNumber(replacer, format);- 6
break;case "j":- 3
ret = formatObject(replacer, format);- 2
break;case "D":- 4
ret = date.date.format(replacer, format);- 4
break;case "Z":- 4
ret = date.date.format(replacer, format, true);- 4
break;}}- 49
return ret;});- 57
} else if (typeof obj == "object") {- 34
return str.replace(INTERP_REGEX, function (m, format, value) {- 135
value = obj[value];- 135
if (!misc.isUndefined(value)) {- 134
if (format) {- 82
if (comb.isString(value)) {- 54
return formatString(value, format);- 28
} else if (typeof value == "number") {- 1
return formatNumber(value, format);- 27
} else if (date.isDate(value)) {- 26
return date.date.format(value, format);- 1
} else if (typeof value == "object") {- 1
return formatObject(value, format);}} else {- 52
return "" + value;}}- 1
return m;});} else {- 23
var args = Array.prototype.slice.call(arguments).slice(1);- 23
return exports.string.format(str, args);}},/*** Converts a string to an array** @example** comb.string.toArray("a|b|c|d", "|") => ["a","b","c","d"]* comb.string.toArray("a", "|") => ["a"]* comb.string.toArray("", "|") => []** @param {String} str the string to parse* @param {String} delimeter the delimeter to use*/toArray:function (testStr, delim) {- 3
var ret = [];- 3
if (testStr) {- 3
if (testStr.indexOf(delim) > 0) return testStr.replace(/\s+/g, "").split(delim);- 1
else return [testStr];}- 1
return ret;},/*** Returns a string duplicated n times;** @example** comb.string.multiply("HELLO", 5) => "HELLOHELLOHELLOHELLOHELLO"***/multiply:function (str, times) {- 152
var ret = [];- 152
if (times) {- 147
for (var i = 0; i < times; i++) {- 562
ret.push(str);}}- 152
return ret.join("");},/*** Styles a string according to the specified styles.** @example* //style a string red* comb.string.style('myStr', 'red');* //style a string red and bold* comb.string.style('myStr', ['red', bold]);** @param {String} str The string to style.* @param {String|Array} styles the style or styles to apply to a string.* options include :* <ul>* <li>bold</li>* <li>bright</li>* <li>italic</li>* <li>underline</li>* <li>inverse</li>* <li>crossedOut</li>* <li>blink</li>* <li>red</li>* <li>green</li>* <li>yellow</li>* <li>blue</li>* <li>magenta</li>* <li>cyan</li>* <li>white</li>* <li>redBackground</li>* <li>greenBackground</li>* <li>yellowBackground</li>* <li>blueBackground</li>* <li>magentaBackground</li>* <li>cyanBackground</li>* <li>whiteBackground</li>* <li>grey</li>* <li>black</li>** </ul>*/style:function (str, options) {- 48
var ret = str;- 48
if (options) {- 48
if (ret instanceof Array) {- 1
ret = ret.map(function (s) {- 3
return comb.string.style(s, options);})- 47
} else if (options instanceof Array) {- 4
options.forEach(function (option) {- 12
ret = comb.string.style(ret, option);});- 43
} else if (options in styles) {- 43
ret = '\x1B[' + styles[options] + 'm' + str + '\x1B[0m';}}- 48
return ret;}};
|
collections/AVLTree.js
|
Coverage100.00
SLOC203
LOC100
Missed0
|
- 1
var define = require("../define").define,Tree = require("./Tree"),base = require("../base"),multiply = base.string.multiply;- 1
var abs = Math.abs;- 1
var makeNode = function(data) {- 122
return {data : data,balance : 0,left : null,right : null}};- 1
var rotateSingle = function(root, dir, otherDir) {- 80
var save = root[otherDir];- 80
root[otherDir] = save[dir];- 80
save[dir] = root;- 80
return save;};- 1
var rotateDouble = function(root, dir, otherDir) {- 15
root[otherDir] = rotateSingle(root[otherDir], otherDir, dir);- 15
return rotateSingle(root, dir, otherDir);};- 1
var adjustBalance = function(root, dir, bal) {- 15
var otherDir = dir == "left" ? "right" : "left";- 15
var n = root[dir], nn = n[otherDir];- 15
if (nn.balance == 0)- 11
root.balance = n.balance = 0;- 4
else if (nn.balance == bal) {- 2
root.balance = -bal;- 2
n.balance = 0;}else { /* nn.balance == -bal */- 2
root.balance = 0;- 2
n.balance = bal;}- 15
nn.balance = 0;};- 1
var insertAdjustBalance = function(root, dir) {- 60
var otherDir = dir == "left" ? "right" : "left";- 60
var n = root[dir];- 60
var bal = dir == "left" ? -1 : +1;- 60
if (n.balance == bal) {- 46
root.balance = n.balance = 0;- 46
root = rotateSingle(root, otherDir, dir);}else {- 14
adjustBalance(root, dir, bal);- 14
root = rotateDouble(root, otherDir, dir);}- 60
return root;};- 1
var removeAdjustBalance = function(root, dir, done) {- 5
var otherDir = dir == "left" ? "right" : "left";- 5
var n = root[otherDir];- 5
var bal = dir == "left" ? -1 : 1;- 5
if (n.balance == -bal) {- 1
root.balance = n.balance = 0;- 1
root = rotateSingle(root, dir, otherDir);}- 4
else if (n.balance == bal) {- 1
adjustBalance(root, otherDir, -bal);- 1
root = rotateDouble(root, dir, otherDir);}else { /* n.balance == 0 */- 3
root.balance = -bal;- 3
n.balance = bal;- 3
root = rotateSingle(root, dir, otherDir);- 3
done.done = true;}- 5
return root;};- 1
var insert = function(root, data, done, compare) {- 472
if (root == null || root == undefined)- 122
root = makeNode(data);else {- 350
var dir = compare(data, root.data) == -1 ? "left" : "right";- 350
root[dir] = insert(root[dir], data, done, compare);- 350
if (!done.done) {/* Update balance factors */- 255
root.balance += dir == "left" ? -1 : 1;/* Rebalance as necessary and terminate */- 255
if (root.balance == 0)- 21
done.done = true;- 234
else if (abs(root.balance) > 1) {- 60
root = insertAdjustBalance(root, dir);- 60
done.done = true;}}}- 472
return root;};- 1
var remove = function(root, data, done, compare) {- 57
var dir, cmp, save, b;- 57
if (root) {//Remove node- 57
cmp = compare(data, root.data);- 57
if (cmp === 0) {// Unlink and fix parent- 26
var l = root.left, r = root.right;- 26
if (!l || !r) {- 18
dir = !l ? "right" : "left";- 18
save = root[dir];- 18
return save;}else {- 8
var heir = l, r;- 8
while ((r = heir.right) != null) {- 3
heir = r;}- 8
root.data = heir.data;//reset and start searching- 8
data = heir.data;}}- 39
dir = compare(root.data, data) == -1 ? "right" : "left";- 39
root[dir] = remove(root[dir], data, done, compare);- 39
if (!done.done) {/* Update balance factors */- 24
b = (root.balance += (dir == "left" ? 1 : -1));/* Terminate or rebalance as necessary */- 24
var a = abs(b);- 24
if (a === 1)- 10
done.done = true;- 14
else if (a > 1)- 5
root = removeAdjustBalance(root, dir, done);}}- 39
return root;};/*** @ignoreCode* @class <p>An AVL tree is a self-balancing binary search tree.* In an AVL tree, the heights of the two child subtrees of any node differ by at most one.* Lookup, insertion, and deletion all take O(log n) time in both the average and worst cases,* where n is the number of nodes in the tree prior to the operation.* Insertions and deletions may require the tree to be rebalanced by one or more tree rotations.</p>* <p>AVL trees are more rigidly balanced than red-black trees, leading to slower insertion and removal but faster retrieval</p>** <b>Performance</b>* <table>* <tr><td></td><td>Best</td><td>Worst</td></tr>* <tr><td>Space</td><td>O(n)</td><td>O(n)</td></tr>* <tr><td>Search</td><td>O(log n)</td><td>O(log n)</td></tr>* <tr><td>Insert</td><td>O(log n)</td><td>O(log n)</td></tr>* <tr><td>Delete</td><td>O(log n)</td><td>O(log n)</td></tr>* <table>* @name AVLTree* @augments comb.collections.Tree* @memberOf comb.collections*/- 1
module.exports = exports = define(Tree, {instance : {/**@lends comb.collections.AVLTree.prototype*/insert : function(data) {- 122
var done = {done : false};- 122
this.__root = insert(this.__root, data, done, this.compare);},remove : function(data) {- 18
this.__root = remove(this.__root, data, {done : false}, this.compare);},__printNode : function(node, level) {- 37
var str = [];- 37
if (node == null) {- 19
str.push(multiply('\t', level));- 19
str.push("~");- 19
console.log(str.join(""));} else {- 18
this.__printNode(node.right, level + 1);- 18
str.push(multiply('\t', level));- 18
str.push(node.data + ":" + node.balance + "\n");- 18
console.log(str.join(""));- 18
this.__printNode(node.left, level + 1);}}}});
|
collections/AnderssonTree.js
|
Coverage100.00
SLOC165
LOC76
Missed0
|
- 1
var define = require("../define").define,Tree = require("./Tree"),base = require("../base"),multiply = base.string.multiply;- 1
var RED = "red", BLACK = "black";- 1
var nil = {level:0, data:null};- 1
var makeNode = function (data, level) {- 122
return {data:data,level:level,left:nil,right:nil}};- 1
var skew = function (root) {- 384
if (root.level != 0 && root.left.level == root.level) {- 66
var save = root.left;- 66
root.left = save.right;- 66
save.right = root;- 66
root = save;}- 384
return root;};- 1
var split = function (root) {- 384
if (root.level != 0 && root.right.right.level == root.level) {- 79
var save = root.right;- 79
root.right = save.left;- 79
save.left = root;- 79
root = save;- 79
++root.level;}- 384
return root;};- 1
var insert = function (root, data, compare) {- 492
if (root == nil) {- 122
root = makeNode(data, 1);}else {- 370
var dir = compare(data, root.data) == -1 ? "left" : "right";- 370
root[dir] = insert(root[dir], data, compare);- 370
root = skew(root);- 370
root = split(root);}- 492
return root;};- 1
var remove = function (root, data, compare) {- 59
var rLeft, rRight;- 59
if (root != nil) {- 59
var cmp = compare(data, root.data);- 59
if (cmp == 0) {- 26
rLeft = root.left, rRight = root.right;- 26
if (rLeft != nil && rRight != nil) {- 8
var heir = rLeft;- 8
while (heir.right != nil)- 3
heir = heir.right;- 8
root.data = heir.data;- 8
root.left = remove(rLeft, heir.data, compare);} else {- 18
root = root[rLeft == nil ? "right" : "left"];}} else {- 33
var dir = cmp == -1 ? "left" : "right";- 33
root[dir] = remove(root[dir], data, compare);}}- 59
if (root != nil) {- 42
var rLevel = root.level;- 42
var rLeftLevel = root.left.level, rRightLevel = root.right.level;- 42
if (rLeftLevel < rLevel - 1 || rRightLevel < rLevel - 1) {- 14
if (rRightLevel > --root.level)- 2
root.right.level = root.level;- 14
root = skew(root);- 14
root = split(root);}}- 59
return root;};/**** @ignoreCode* @class <p>Andersson Trees are a version of a balanced Binary tree, while similar to RedBlack Trees the balancing is not as strict.</p>** <b>Performance</b>* <table>* <tr><td></td><td>Best</td><td>Worst</td></tr>* <tr><td>space</td><td>O(n)</td><td>O(n)</td></tr>* <tr><td>Search</td><td>O(log n)</td><td>O(log n)</td></tr>* <tr><td>Insert</td><td>O(log n)</td><td>O(log n)</td></tr>* <tr><td>Delete</td><td>O(log n)</td><td>O(log n)</td></tr>* <table>* @name AnderssonTree* @augments comb.collections.Tree* @memberOf comb.collections*/- 1
module.exports = exports = define(Tree, {instance:{/**@lends comb.collections.AnderssonTree.prototype*/isEmpty:function () {- 4
return this.__root == nil || this._super(arguments);},insert:function (data) {- 130
if (this.__root == null) this.__root = nil;- 122
this.__root = insert(this.__root, data, this.compare);},remove:function (data) {- 18
this.__root = remove(this.__root, data, this.compare);},traverseWithCondition:function (node, order, callback) {- 614
var cont = true;- 614
if (node != nil) {- 317
return this._super(arguments);}- 297
return cont;},traverse:function (node, order, callback) {- 989
if (node != nil) {- 482
this._super(arguments);}},contains:function (value) {- 44
if (this.__root != nil) {- 26
return this._super(arguments);}- 18
return false;},__printNode:function (node, level) {- 37
var str = [];- 37
if (node.data == null || node == null) {- 19
str.push(multiply('\t', level));- 19
str.push("~");- 19
console.log(str.join(""));} else {- 18
this.__printNode(node.right, level + 1);- 18
str.push(multiply('\t', level));- 18
str.push(node.data + ":" + node.level + "\n");- 18
console.log(str.join(""));- 18
this.__printNode(node.left, level + 1);}}}});
|
collections/BinaryTree.js
|
Coverage100.00
SLOC83
LOC30
Missed0
|
- 1
var define = require("../define").define,Tree = require("./Tree"),base = require("../base");/**** @ignoreCode* @class <p>A Search tree that maintains the following properties</p>* <ul>* <li>The left subtree of a node contains only nodes with keys less than the node's key.* <li>The right subtree of a node contains only nodes with keys greater than the node's key.* <li>Both the left and right subtrees must also be binary search trees.* </ul>** <b>Performance</b>* <table>* <tr><td></td><td>Best</td><td>Worst</td></tr>* <tr><td>Space</td><td>O(n)</td><td>O(n)</td></tr>* <tr><td>Search</td><td>O(log n)</td><td>O(n)</td></tr>* <tr><td>Insert</td><td>O(log n)</td><td>O(n)</td></tr>* <tr><td>Delete</td><td>O(log n)</td><td>O(n)</td></tr>* <table>* @name BinaryTree* @augments comb.collections.Tree* @memberOf comb.collections*/- 1
module.exports = exports = define(Tree, {instance : {/**@lends comb.collections.BinaryTree.prototype*/insert : function(data) {- 124
if (this.__root == null) {- 9
return (this.__root = {data : data,parent : null,left : null,right : null});}- 115
var compare = this.compare;- 115
var root = this.__root;- 115
while (root != null) {- 505
var cmp = compare(data, root.data);- 505
if (cmp) {- 503
var leaf = (cmp == -1) ? "left" : "right";- 503
var next = root[leaf];- 503
if (next == null) {- 113
return (root[leaf] = {data : data, parent : root, left : null, right : null});} else {- 390
root = next;}} else {- 2
return;}}},remove : function(data) {- 19
if (this.__root != null) {- 19
var head = {right : this.__root}, it = head;- 19
var p, f = null;- 19
var dir = "right";- 19
while (it[dir] != null) {- 51
p = it;- 51
it = it[dir];- 51
var cmp = this.compare(data, it.data);- 51
if (!cmp) {- 18
f = it;}- 51
dir = (cmp == -1 ? "left" : "right");}- 19
if (f != null) {- 18
f.data = it.data;- 18
p[p.right == it ? "right" : "left"] = it[it.left == null ? "right" : "left"];}- 19
this.__root = head.right;}}}});
|
collections/Collection.js
|
Coverage100.00
SLOC56
LOC8
Missed0
|
- 1
var define = require("../define").define,base = require("../base");/*** @ignoreCode* @class Base class for all collections* @name Collection* @memberOf comb.collections*/- 1
define(null, {instance:{/**@lends comb.collections.Collection.prototype*//*** Concats two collections*/concat:function () {- 1
throw new Error("Not Implemented");},/*** Joins two collections*/join:function () {- 1
throw new Error("Not Implemented");},/*** Slice a portion from a collection*/slice:function () {- 1
throw new Error("Not Implemented");},/*** Convert a collection to a string*/toString:function () {- 1
throw new Error("Not Implemented");},/*** Find the index of an item in a collection*/indexOf:function () {- 1
throw new Error("Not Implemented");},/*** Find the last index of an item in a collection*/lastIndexOf:function () {- 1
throw new Error("Not Implemented");}}}).as(module);
|
collections/HashTable.js
|
Coverage100.00
SLOC378
LOC126
Missed0
|
- 1
var define = require("../define").define,Collection = require("./Collection"),Iterable = require("./Iterable"),base = require("../base");- 1
var hashFunction = function (key) {- 100
if (typeof key == "string") {- 26
return key;- 74
} else if (typeof key == "object") {- 44
return key.hashCode ? key.hashCode() : "" + key;} else {- 30
return "" + key;}};- 1
var Bucket = define(null, {instance:{constructor:function () {- 32
this.__entries = [];},pushValue:function (key, value) {- 36
this.__entries.push({key:key, value:value});- 36
return value;},remove:function (key) {- 14
var ret = null, map = this.__entries, val;- 14
var i = map.length - 1;- 14
for (; i >= 0; i--) {- 16
if ((val = map[i]) != null && val.key === key) {- 12
map[i] = null;- 12
return val.value;}}- 2
return ret;},"set":function (key, value) {- 14
var ret = null, map = this.__entries;- 14
var i = map.length - 1;- 14
for (; i >= 0; i--) {- 18
var val = map[i];- 18
if (val && key === val.key) {- 6
val.value = value;- 6
ret = value;- 6
break;}}- 14
if (!ret) {- 8
map.push({key:key, value:value});}- 14
return ret;},find:function (key) {- 34
var ret = null, map = this.__entries, val;- 34
var i = map.length - 1;- 34
for (; i >= 0; i--) {- 43
val = map[i];- 43
if (val && key === val.key) {- 26
ret = val.value;- 26
break;}}- 34
return ret;},getEntrySet:function (arr) {- 78
var map = this.__entries, l = map.length;- 78
if (l) {- 78
for (var i = 0; i < l; i++) {- 88
var e = map[i];- 88
if (e) {- 80
arr.push(e);}}}},getKeys:function (arr) {- 21
var map = this.__entries, l = map.length;- 21
if (l) {- 21
for (var i = 0; i < l; i++) {- 24
var e = map[i];- 24
if (e) {- 8
arr.push(e.key);}}}- 21
return arr;},getValues:function (arr) {- 14
var map = this.__entries, l = map.length;- 14
if (l) {- 14
for (var i = 0; i < l; i++) {- 16
var e = map[i];- 16
if (e) {- 8
arr.push(e.value);}}}- 14
return arr;}}});/*** @ignoreCode* @class <p>Implementation of a HashTable for javascript.* This HashTable implementation allows one to use anything as a key.* </p>* <b>NOTE: THIS IS ~ 3 times slower than javascript native objects</b>** <p> A use case for this collection is when one needs to store items in which the key will not be a string, or number</p>** @name HashTable* @augments comb.collections.Collection* @memberOf comb.collections** @property {Array} keys all keys contained in the table* @property {Array} values all values contained in the table* @property {Array} entrySet an array of objects. Each object contains a key, and value property.*/- 1
define([Collection, Iterable], {instance:{/**@lends comb.collections.HashTable.prototype*/constructor:function () {- 13
this.__map = {};},__entrySet:function () {- 14
var ret = [], es = [];- 14
for (var i in this.__map) {- 78
this.__map[i].getEntrySet(ret);}- 14
return ret;},/*** Put a key, value pair into the table** <b>NOTE :</b> the collection will not check if the key previously existed.** @param {Anything} key the key to look up the object.* @param {Anything} value the value that corresponds to the key.** @returns the value*/put:function (key, value) {- 29
var hash = hashFunction(key);- 29
var bucket = null;- 29
if ((bucket = this.__map[hash]) == null) {- 25
bucket = (this.__map[hash] = new Bucket());}- 29
bucket.pushValue(key, value);- 29
return value;},/*** Remove a key value pair from the table.** @param key the key of the key value pair to remove.** @returns the removed value.*/remove:function (key) {- 16
var hash = hashFunction(key), ret = null;- 16
var bucket = this.__map[hash];- 16
if (bucket) {- 14
ret = bucket.remove(key);}- 16
return ret;},/*** Get the value corresponding to the key.** @param key the key used to look up the value** @returns null if not found, or the value.*/"get":function (key) {- 26
var hash = hashFunction(key), ret = null;- 26
var bucket = null;- 26
if ((bucket = this.__map[hash]) != null) {- 26
ret = bucket.find(key);}- 26
return ret;},/*** Set the value of a previously existing key,value pair or create a new entry.** @param key the key to be be used* @param value the value to be set** @returns the value.*/"set":function (key, value) {- 21
var hash = hashFunction(key), ret = null, bucket = null, map = this.__map;- 21
if ((bucket = map[hash]) != null) {- 14
ret = bucket.set(key, value);} else {- 7
ret = (map[hash] = new Bucket()).pushValue(key, value);}- 21
return ret;},/*** Tests if the table contains a particular key* @param key the key to test** @returns {Boolean} true if it exitsts false otherwise.*/contains:function (key) {- 8
var hash = hashFunction(key), ret = false;- 8
var bucket = null;- 8
if ((bucket = this.__map[hash]) != null) {- 8
ret = bucket.find(key) != null;}- 8
return ret;},/*** Returns a new HashTable containing the values of this HashTable, and the other table.* </br>* <b> DOES NOT CHANGE THE ORIGINAL!</b>* @param {comb.collections.HashTable} hashTable the hash table to concat with this.** @returns {comb.collections.HashTable} a new HashTable containing all values from both tables.*/concat:function (hashTable) {- 2
if (hashTable instanceof this._static) {- 1
var ret = new this._static();- 1
var otherEntrySet = hashTable.entrySet.concat(this.entrySet);- 1
for (var i = otherEntrySet.length - 1; i >= 0; i--) {- 4
var e = otherEntrySet[i];- 4
ret.put(e.key, e.value);}- 1
return ret;} else {- 1
throw new TypeError("When joining hashtables the joining arg must be a HashTable");}},/*** Creates a new HashTable containg values that passed the filtering function.** @param {Function} cb Function to callback with each item, the first aruguments is an object containing a key and value field* @param {Object} scope the scope to call the function.** @returns {comb.collections.HashTable} the HashTable containing the values that passed the filter.*/filter:function (cb, scope) {- 1
var es = this.__entrySet(), ret = new this._static();- 1
es = es.filter.apply(es, arguments);- 1
for (var i = es.length - 1; i >= 0; i--) {- 4
var e = es[i];- 4
ret.put(e.key, e.value);}- 1
return ret;},/*** Loop through each value in the hashtable** @param {Function} cb the function to call with an object containing a key and value field* @param {Object} scope the scope to call the funciton in*/forEach:function (cb, scope) {- 1
var es = this.__entrySet(), l = es.length, f = cb.bind(scope || this);- 1
es.forEach.apply(es, arguments);},/*** Determines if every item meets the condition returned by the callback.** @param {Function} cb Function to callback with each item, the first aruguments is an object containing a key and value field* @param {Object} [scope=this] scope to call the function in** @returns {Boolean} True if every item passed false otherwise*/every:function () {- 2
var es = this.__entrySet();- 2
return es.every.apply(es, arguments);},/*** Loop through each value in the hashtable, collecting the value returned by the callback function.* @param {Function} cb Function to callback with each item, the first aruguments is an object containing a key and value field* @param {Object} [scope=this] scope to call the function in** @returns {Array} an array containing the mapped values.*/map:function () {- 1
var es = this.__entrySet(), ret = new this._static();- 1
return es.map.apply(es, arguments);},/*** Determines if some items meet the condition returned by the callback.** @param {Function} cb Function to callback with each item, the first aruguments is an object containing a key and value field* @param {Object} [scope=this] scope to call the function in** @returns {Boolean} True if some items passed false otherwise*/some:function () {- 2
var es = this.__entrySet();- 2
return es.some.apply(es, arguments);},/*** Apply a function against an accumulator and each value of the array (from left-to-right) as to reduce it to a single value.** @param {Function} callback Function to execute on each value in the array.* @param initialValue Value to use as the first argument to the first call of the callback..*/reduce:function () {- 1
var es = this.__entrySet();- 1
return es.reduce.apply(es, arguments);},/*** Apply a function against an accumulator and each value of the array (from right-to-left) as to reduce it to a single value.** @param {Function} callback Function to execute on each value in the array.* @param initialValue Value to use as the first argument to the first call of the callback..*/reduceRight:function () {- 1
var es = this.__entrySet();- 1
return es.reduceRight.apply(es, arguments);},/*** Clears out all items from the table.*/clear:function () {- 1
this.__map = {};},getters:{keys:function () {- 8
var ret = [], es = [];- 8
for (var i in this.__map) {- 21
this.__map[i].getKeys(ret);}- 8
return ret;},values:function () {- 6
var ret = [], es = [];- 6
for (var i in this.__map) {- 14
this.__map[i].getValues(ret);}- 6
return ret;},entrySet:function () {- 5
return this.__entrySet();},isEmpty:function () {- 2
return this.keys.length == 0;}}}}).as(module);
|
collections/Heap.js
|
Coverage100.00
SLOC218
LOC62
Missed0
|
- 1
var define = require("../define").define,Collection = require("./Collection"),base = require("../base");- 1
var padding = function(char, numSpaces) {- 9
var ret = [];- 9
for (var i = 0; i < numSpaces; i++)- 16
ret.push(char);- 9
return ret.join("");};- 1
module.exports = exports = define(Collection, {instance : {/**@lends comb.collections.Heap.prototype*/__getParentIndex : function(index) {- 192
return Math.floor((index - 1) / 2);},__getLeftChildIndex : function(index) {- 28
return (index * 2) + 1;},__getRightChildIndex : function(index) {- 28
return (index * 2) + 2;},__makeNode : function(key, value) {- 137
return {key : key, value : value};},/*** Base class for Heap Implementations.*** @constructs* @augments comb.collections.Collection* @memberOf comb.collections** @property {Number} count the current number of elements.* @property {Array} keys the keys of all items in the heap.* @property {Array} values the values contained in the heap.* @property {Boolean} isEmpty true if the Heap is empty.*/constructor : function() {- 32
this.__heap = [];},/*** Insert a key value into the key* @param key* @param value*/insert : function(key, value) {- 138
if (!base.isString(key)) {- 137
var l = this.__heap.push(this.__makeNode(key, value));- 137
this.__upHeap(l - 1);} else {- 1
throw TypeError("Invalid key");}},/*** Removes the root from the heap** @returns the value of the root*/remove : function() {- 48
var ret = undefined, heap = this.__heap, l = heap.length;- 48
if (l) {- 48
ret = heap[0];- 48
if (l == 1) {- 12
heap.length = 0;} else {- 36
heap[0] = heap.pop();- 36
this.__downHeap(0);}}- 48
return ret ? ret.value : ret;},/*** Gets he value of the root node with out removing it.** @returns the value of the root*/peek : function() {- 33
var ret = undefined, heap = this.__heap, l = heap.length;- 33
if (l) {- 30
ret = heap[0];}- 33
return ret ? ret.value : ret;},/*** Gets the key of the root node without removing it.** @returns the key of the root*/peekKey : function() {- 6
var ret = undefined, heap = this.__heap, l = heap.length;- 6
if (l) {- 4
ret = heap[0];}- 6
return ret ? ret.key : ret;},/*** Perform the heapify operation after the an* item as been added to the bottom of the heap.** @param index the index in which the new item was added*/__upHeap : function(index) {- 1
throw Error("NOT IMPLEMENTED");},/*** Heapify the heap after the root has been removed** @param index the index of the root*/__downHeap : function(index) {- 1
throw Error("NOT IMPLEMENTED");},/**** Determine if the heap contains a particular key.** @param key key to test.** @returns {Boolean} true if the key is contained in this heap.*/containsKey : function(key) {- 15
var heap = this.__heap;- 15
for (var i = heap.length - 1; i >= 0; i--) {- 42
if (heap[i].key == key) {- 12
return true;}}- 3
return false;},/**** Determine if the heap contains a particular value.** @param value value to test.** @returns {Boolean} true if the value is contained in this heap.*/containsValue : function(value) {- 15
var heap = this.__heap;- 15
for (var i = heap.length - 1; i >= 0; i--) {- 42
if (heap[i].value == value) {- 12
return true;}}- 3
return false;},/*** Empty the heap.*/clear : function() {- 9
this.__heap.length = 0;},__printNode : function(index, level) {//console.log(level);- 9
var str = [], node = this.__heap[index];- 9
if (node == null || node == undefined) {- 5
str.push(padding('\t', level));- 5
str.push("~");- 5
console.log(str.join(""));} else {- 4
this.__printNode(this.__getRightChildIndex(index), level + 1);- 4
str.push(padding('\t', level));- 4
str.push(node.key + " : " + node.value + "\n");- 4
console.log(str.join(""));- 4
this.__printNode(this.__getLeftChildIndex(index), level + 1);}},/*** Print the heap.*/print : function() {- 1
this.__printNode(0, 0);},getters : {count : function() {- 12
return this.__heap.length;},keys : function() {- 3
return this.__heap.map(function(n) {- 12
return n.key;});},values : function() {- 3
return this.__heap.map(function(n) {- 12
return n.value;});},isEmpty : function() {- 18
return this.__heap.length == 0;}}}});
|
collections/Iterable.js
|
Coverage100.00
SLOC63
LOC9
Missed0
|
- 1
var define = require("../define").define,base = require("../base");/*** @ignoreCode* @class Base class for all collections* @name Iterable* @memberOf comb.collections*/- 1
define(null, {instance:{/**@lends comb.collections.Iterable.prototype*//*** Filter items from a collection*/filter:function () {- 1
throw new Error("Not Implemented");},/*** Loop through the items in a collection*/forEach:function () {- 1
throw new Error("Not Implemented");},/*** Determine if every item in a collection meets the criteria*/every:function () {- 1
throw new Error("Not Implemented");},/*** Map every item in a collection*/map:function () {- 1
throw new Error("Not Implemented");},/*** Determing if some items in a colleciton meet the criteria*/some:function () {- 1
throw new Error("Not Implemented");},/*** Reduce a collection*/reduce:function () {- 1
throw new Error("Not Implemented");},/*** Reduce a collection starting from the right most position*/reduceRight:function () {- 1
throw new Error("Not Implemented");}}}).as(module);
|
collections/MaxHeap.js
|
Coverage100.00
SLOC66
LOC25
Missed0
|
- 1
var define = require("../define").define,Heap = require("./Heap"),base = require("../base");/*** @ignoreCode** @class <p> Max Heap implementation, lowest value in heap is always at the root.</p>* </br>* <b>Performance</b>* <table>* <tr><td></td><td>Best</td><td>Worst</td></tr>* <tr><td>Insert</td><td>O(log n)</td><td>O(log n)</td></tr>* <tr><td>Remove</td><td>O(log n)</td><td>O(log n)</td></tr>* <tr><td>Peek</td><td>O(1)</td><td>O(1)</td></tr>* <tr><td>Contains</td><td>O(n)</td><td>O(n)</td></tr>* <table>* @name MaxHeap* @augments comb.collections.Heap* @memberOf comb.collections*/- 1
exports = module.exports = define(Heap, {instance : {__upHeap : function(index) {- 48
var heap = this.__heap;- 48
var node = heap[index];- 48
while (index >= 0) {- 84
var parentIndex = this.__getParentIndex(index), parent = heap[parentIndex];- 84
if (parent && parent.key < node.key) {- 36
heap[index] = parent;- 36
index = parentIndex;} else {- 48
break;}}- 48
heap[index] = node;},__downHeap : function(index) {- 12
var heap = this.__heap;- 12
var node = heap[index], length = heap.length;- 12
while (index < Math.floor(length / 2)) {- 8
var leftIndex = this.__getLeftChildIndex(index),rightIndex = this.__getRightChildIndex(index), left = heap[leftIndex], right = heap[rightIndex], child, childIndex;- 8
if (rightIndex < length && right.key < left.key) {- 4
childIndex = leftIndex;- 4
child = left} else {- 4
childIndex = leftIndex;- 4
child = heap[leftIndex];}- 8
if(child.key > node.key){- 5
heap[index] = child;- 5
index = childIndex;}else{- 3
break;}}- 12
heap[index] = node;}}});
|
collections/MinHeap.js
|
Coverage100.00
SLOC65
LOC26
Missed0
|
- 1
var define = require("../define").define,Heap = require("./Heap"),base = require("../base");- 1
var floor = Math.floor, MinHeap;/*** @class <p> Min Heap implementation, lowest value in heap is always at the root.</p>* </br>* <b>Performance</b>* <table>* <tr><td></td><td>Best</td><td>Worst</td></tr>* <tr><td>Insert</td><td>O(log n)</td><td>O(log n)</td></tr>* <tr><td>Remove</td><td>O(log n)</td><td>O(log n)</td></tr>* <tr><td>Peek</td><td>O(1)</td><td>O(1)</td></tr>* <tr><td>Contains</td><td>O(n)</td><td>O(n)</td></tr>* <table>* @name MinHeap* @augments comb.collections.Heap* @memberOf comb.collections* @ignoreCode*/- 1
module.exports = exports = define(Heap, {instance : {__upHeap : function(index) {- 88
var heap = this.__heap;- 88
var node = heap[index], key = node.key, gpi = this.__getParentIndex;- 88
while (index >= 0) {- 108
var parentIndex = gpi(index), parent = heap[parentIndex];- 108
if (parent && parent.key > key) {- 20
heap[index] = parent;- 20
index = parentIndex;} else {- 88
break;}}- 88
heap[index] = node;},__downHeap : function(index) {- 24
var heap = this.__heap;- 24
var node = heap[index], key = node.key, length = heap.length, max = floor(length / 2), glci = this.__getLeftChildIndex, grci = this.__getRightChildIndex;- 24
while (index < max) {- 16
var leftIndex = glci(index),rightIndex = grci(index), left = heap[leftIndex], right = heap[rightIndex], child, childIndex;- 16
if (rightIndex < length && right.key < left.key) {- 2
childIndex = rightIndex;- 2
child = right;} else {- 14
childIndex = leftIndex;- 14
child = left;}- 16
if (child.key < key) {- 10
heap[index] = child;- 10
index = childIndex;} else {- 6
break;}}- 24
heap[index] = node;}}});
|
collections/Pool.js
|
Coverage100.00
SLOC162
LOC51
Missed0
|
- 1
var define = require("../define").define,Collection = require("./Collection"),Queue = require("./Queue"),base = require("../base");/*** @class Base class for a pool.** @name Pool* @memberOf comb.collections** @property {Number} count the total number of objects in the pool, including free and in use objects.* @property {Number} freeCount the number of free objects in this pool.* @property {Number} inUseCount the number of objects in use in this pool.* @property {Number} [minObjects=0] the minimum number of objects this pool should contain.* @property {Number} [maxObjects=1] the maximum number of objects this pool should contain* @ignoreCode*/- 1
exports = module.exports = define(null, {instance : {/**@lends comb.collections.Pool.prototype*/__minObjects : 0,__maxObjects : 1,constructor : function(options) {- 5
options = options || {};- 5
this.__freeObjects = new Queue();- 5
this.__inUseObjects = [];- 5
this.__minObjects = options.minObjects || 0;- 5
this.__maxObjects = options.maxObjects || 1;- 5
this.minObjects = this.__minObjects;- 4
this.maxObjects = this.__maxObjects;},/*** Retrieves an object from this pool.* `* @return {*} an object to contained in this pool*/getObject : function() {- 19
var ret = undefined;- 19
if (this.freeCount > 0) {- 2
ret = this.__freeObjects.dequeue();- 2
this.__inUseObjects.push(ret);- 17
} else if (this.__maxObjects > this.count) {- 12
ret = this.createObject();- 12
this.__inUseObjects.push(ret);}- 19
return ret;},/*** Returns an object to this pool. The object is validated before it is returned to the pool,* if the validation fails then it is removed from the pool;* @param {*} obj the object to return to the pool*/returnObject : function(obj) {- 8
if (this.validate(obj) && this.count <= this.__maxObjects) {- 7
this.__freeObjects.enqueue(obj);- 7
var index;- 7
if ((index = this.__inUseObjects.indexOf(obj)) > -1)- 7
this.__inUseObjects.splice(index, 1);} else {- 1
this.removeObject(obj);}},/*** Removes an object from the pool, this can be overriden to provide any* teardown of objects that needs to take place.** @param {*} obj the object that needs to be removed.** @return {*} the object removed.*/removeObject : function(obj) {- 2
var index;- 2
if (this.__freeObjects.contains(obj)) {- 1
this.__freeObjects.remove(obj);- 1
} else if ((index = this.__inUseObjects.indexOf(obj)) > -1) {- 1
this.__inUseObjects.splice(index, 1);}//otherwise its not contained in this pool;- 2
return obj;},/*** Validates an object in this pool.* </br>* <b>THIS SHOULD BE OVERRIDDEN TO VALIDATE</b>** @param {*} obj the object to validate.*/validate : function(obj) {- 8
return true;},/*** Creates a new object for this pool.* * </br>* <b>THIS SHOULD BE OVERRIDDEN TO ADD THE CORRECT TYPE OF OBJECT</b>** @return {Object} be default just creates an object.*/createObject : function() {- 16
return {};},setters : {minObjects : function(l) {- 6
if (l <= this.__maxObjects) {- 5
this.__minObjects = l;- 5
var i;- 5
if ((i = this.count) < l) {- 1
while (i++ < l) {- 4
this.__freeObjects.enqueue(this.createObject());}}} else {- 1
throw "comb.collections.Pool : minObjects cannot be greater than maxObjects.";}},maxObjects : function(l) {- 9
if (l >= this.__minObjects) {- 8
this.__maxObjects = l;- 8
var i = this.count, j = this.freeCount, fo = this.__freeObjects;- 8
while (i > l && j >= 0) {- 1
this.removeObject(fo.dequeue());- 1
j--;- 1
i--;}} else {- 1
throw "comb.collections.Pool : maxObjects cannot be less than maxObjects.";}}},getters : {freeCount : function() {- 41
return this.__freeObjects.count;},inUseCount : function() {- 14
return this.__inUseObjects.length;},count : function() {- 52
return this.__freeObjects.count + this.__inUseObjects.length;},minObjects : function() {- 2
return this.__minObjects;},maxObjects : function() {- 1
return this.__maxObjects;}}}})
|
collections/PriorityQueue.js
|
Coverage100.00
SLOC41
LOC6
Missed0
|
- 1
var define = require("../define").define,MinHeap = require("./MinHeap"),base = require("../base");- 1
var PriorityQueue;/*** @class PriorityQueue Implementation where the value with the highest priority moves to the front* Priority starts at 0, and the greatest value being the lowest priority;* @name PriorityQueue* @augments comb.collections.MinHeap* @memberOf comb.collections* @ignoreCode*/- 1
PriorityQueue = define(MinHeap, {instance : {/**@lends comb.collections.PriorityQueue.prototype*//*** Adds the value with the specified priority to the queue** @param {Number} priority the priority of the item* </br>* <b>0 = Highest, n = lowest</b>* @param value*/enqueue : function(priority, value) {- 44
return this.insert(priority, value);},/*** Removes the item with the highest priority from the queue** @returns the value of the item*/dequeue : function() {- 16
return this.remove();}}});- 1
module.exports = exports = PriorityQueue;
|
collections/Queue.js
|
Coverage100.00
SLOC119
LOC32
Missed0
|
- 1
var define = require("../define").define,Collection = require("./Collection"),base = require("../base");/*** @class <p>FIFO Data structure</p>* @name Queue* @augments comb.collections.Collection* @memberOf comb.collections** @property {Number} count the current number of elements in this queue* @property {Boolean} isEmpty true if this queue is empty* @property {Array} values a copy of the values contained in this queue* @ignoreCode*/- 1
module.exports = exports = define(Collection, {instance : {/**@lends comb.collections.Queue.prototype*/constructor : function() {- 6
this.__queue = [];- 6
this.__next = 0;- 6
this.__last = 0;},/*** Add data to this queue* @param {*} data element to add*/enqueue : function(data) {- 27
this.__queue[this.__last++] = data;},/*** Removes first item from the head of the queue** @return {*} The element removed from this queue. Returns undefined if the queue is empty.*/dequeue : function() {- 7
var ret = undefined,next = this.__next, queue;- 7
if (next != this.__last) {- 5
queue = this.__queue;- 5
ret = queue[next];- 5
queue[this.__next++] = undefined;}- 7
return ret;},/*** Retrieves the item at the head of the queue without removing it** @return {*} The element at the head of the queue. Returns undefined if the queue is empty.*/peek : function() {- 1
var ret = undefined, next = this.__next;- 1
if (next != this.__last) {- 1
ret = this.__queue[next];}- 1
return ret;},/*** Removes all items from this queue*/clear : function() {- 1
this.__queue.length = 0;- 1
this.__next = 0;- 1
this.__last = 0;},/*** Determine if this queue contains the element* @param {*} obj the object to find** @return {Boolean} true if this queue contains the element*/contains : function(obj) {- 5
return this.__queue.indexOf(obj) != -1;},/*** Removes an element from this queue.* @param {*} obj the data to remove.** @return {Boolean} true if the element was removed, false otherwise.*/remove : function(obj) {- 8
var index = this.__queue.indexOf(obj), ret = false;- 8
if (index != -1) {- 8
if (index == this.__next) {- 1
this.dequeue();} else {- 7
this.__queue.splice(index, 1);- 7
this.__last--;}- 8
ret = true;}- 8
return ret;},toString : function(){- 3
return this.__queue.toString();},getters : {count : function() {- 95
return this.__last - this.__next;},isEmpty : function() {- 5
return this.__last - this.__next == 0;},values : function() {- 1
return this.__queue.slice(this.__next, this.__last);}}}});
|
collections/RedBlackTree.js
|
Coverage100.00
SLOC188
LOC101
Missed0
|
- 1
var define = require("../define").define,Tree = require("./Tree"),base = require("../base"),multiply = base.string.multiply;- 1
var RED = "red", BLACK = "black";- 1
var isRed = function(node) {- 1156
return node != null && node.red;};- 1
var makeNode = function(data, parent) {- 122
return {data : data,red : true,left : null,right : null}};- 1
var insert = function(root, data, compare) {- 503
if (root == null) {- 122
return makeNode(data, null);} else {- 381
var cmp = compare(data, root.data);- 381
if (cmp) {- 381
var dir = cmp == -1 ? "left" : "right";- 381
var otherDir = dir == "left" ? "right" : "left";- 381
root[dir] = insert(root[dir], data, compare);- 381
var node = root[dir];- 381
if (isRed(node)) {- 294
var sibling = root[otherDir];- 294
if (isRed(sibling)) {/* Case 1 */- 68
root.red = true;- 68
node.red = false;- 68
sibling.red = false;} else {- 226
if (isRed(node[dir])) {- 43
root = rotateSingle(root, otherDir);- 183
} else if (isRed(node[otherDir])) {- 11
root = rotateDouble(root, otherDir);}}}}}- 381
return root;};- 1
var rotateSingle = function(root, dir) {- 70
var otherDir = dir == "left" ? "right" : "left";- 70
var save = root[otherDir];- 70
root[otherDir] = save[dir];- 70
save[dir] = root;- 70
root.red = true;- 70
save.red = false;- 70
return save;};- 1
var rotateDouble = function(root, dir) {- 12
var otherDir = dir == "left" ? "right" : "left";- 12
root[otherDir] = rotateSingle(root[otherDir], otherDir);- 12
return rotateSingle(root, dir);};- 1
var remove = function (root, data, done, compare) {- 52
if (root == null) {- 2
done.done = true;} else {- 50
var dir;- 50
if (compare(data, root.data) == 0) {- 22
if (root.left == null || root.right == null) {- 16
var save = root[root.left == null ? "right" : "left"];/* Case 0 */- 16
if (isRed(root)) {- 2
done.done = true;- 14
} else if (isRed(save)) {- 5
save.red = false;- 5
done.done = true;}- 16
return save;}else {- 6
var heir = root.right, p;- 6
while (heir.left != null) {- 2
p = heir;- 2
heir = heir.left;}- 6
p && (p.left = null);- 6
root.data = heir.data;- 6
data = heir.data;}}- 34
dir = compare(data, root.data) == -1 ? "left" : "right";- 34
root[dir] = remove(root[dir], data, done, compare);- 34
!done.done && (root = removeBalance(root, dir, done));}- 36
return root;};- 1
var removeBalance = function(root, dir, done) {- 11
var notDir = dir == "left" ? "right" : "left";- 11
var p = root, s = p[notDir];- 11
if (isRed(s)) {- 2
root = rotateSingle(root, dir);- 2
s = p[notDir];}- 11
if (s != null) {- 11
if (!isRed(s.left) && !isRed(s.right)) {- 9
isRed(p) && (done.done = true);- 9
p.red = 0;- 9
s.red = 1;} else {- 2
var save = p.red, newRoot = ( root === p );- 2
p = (isRed(s[notDir]) ? rotateSingle : rotateDouble)(p, dir);- 2
p.red = save;- 2
p.left.red = p.right.red = 0;- 2
if (newRoot) {- 1
root = p;} else {- 1
root[dir] = p;}- 2
done.done = true;}}- 11
return root;};- 1
var RedBlackTree;/*** @class <p>A RedBlack tree is a form of a self balancing binary tree.</p>** <b>Performance</b>* <table>* <tr><td></td><td>Best</td><td>Worst</td></tr>* <tr><td>Space</td><td>O(n)</td><td>O(n)</td></tr>* <tr><td>Search</td><td>O(log n)</td><td>O(log n)</td></tr>* <tr><td>Insert</td><td>O(log n)</td><td>O(log n)</td></tr>* <tr><td>Delete</td><td>O(log n)</td><td>O(log n)</td></tr>* <table>* @name RedBlackTree* @augments comb.collections.Tree* @memberOf comb.collections* @ignoreCode*/- 1
module.exports = exports = define(Tree, {instance : {/**@lends comb.collections.RedBlackTree.prototype*/insert : function(data) {- 122
this.__root = insert(this.__root, data, this.compare);- 122
this.__root.red = false;},remove : function(data) {- 18
var done = {done : false};- 18
var root = remove(this.__root, data, done, this.compare);- 18
if (root != null)- 17
root.red = 0;- 18
this.__root = root;},__printNode : function(node, level) {- 37
var str = [];- 37
if (node == null || node == undefined) {- 19
str.push(multiply('\t', level));- 19
str.push("~");- 19
console.log(str.join(""));} else {- 18
this.__printNode(node.right, level + 1);- 18
str.push(multiply('\t', level));- 18
str.push((node.red ? "RED" : "BLACK") + ":" + node.data + "\n");- 18
console.log(str.join(""));- 18
this.__printNode(node.left, level + 1);}}}});
|
collections/Stack.js
|
Coverage100.00
SLOC117
LOC30
Missed0
|
- 1
var define = require("../define").define,Collection = require("./Collection"),base = require("../base");/*** @class <p>LIFO Data structure</p>* @name Stack* @augments comb.collections.Collection* @memberOf comb.collections** @property {Number} count the current number of elements in this queue* @property {Boolean} isEmpty true if this queue is empty* @property {Array} values a copy of the values contained in this queue* @ignoreCode*/- 1
module.exports = exports = define(Collection, {instance : {/**@lends comb.collections.Stack.prototype*/constructor : function() {- 1
this.__stack = [];- 1
this.__next = -1;},/*** Add an item to the tail of this stack* @param {*} data item to qppend to this stack**/push : function(data) {- 23
this.__stack[++this.__next] = data;},/*** Removes the tail of this static* @return {*} the data at the tail of this stack*/pop : function() {- 11
var ret = undefined, stack, next = this.__next;- 11
if (next >= 0) {- 10
stack = this.__stack;- 10
ret = stack[next];- 10
stack[this.__next--] = undefined;}- 11
return ret;},/*** Retrieves the item at the tail of the stack without removing it** @return {*} The element at the tail of the stack. Returns undefined if the stack is empty.*/peek : function() {- 1
var ret = undefined,next = this.__next;- 1
if (next >= 0) {- 1
ret = this.__stack[next];}- 1
return ret;},/*** Removes all items from this stack.*/clear : function() {- 1
this.__stack.length = 0;- 1
this.__next = -1;},/*** Determine if this stack contains the element* @param {*} obj the object to find** @return {Boolean} true if this stack contains the element*/contains : function(obj) {- 3
return this.__stack.indexOf(obj) != -1;},/*** Removes an element from this stack.* @param {*} obj the data to remove.** @return {Boolean} true if the element was removed, false otherwise.*/remove : function(obj) {- 7
var index = this.__stack.indexOf(obj), ret = false;- 7
if (index != -1) {- 7
if (index == this.__next) {- 1
this.pop();} else {- 6
this.__stack.splice(index, 1);- 6
this.__next--;}- 7
ret = true;}- 7
return ret;},toString : function(){- 3
return this.__stack.toString();},getters : {count : function() {- 3
return this.__next + 1;},isEmpty : function() {- 5
return this.__next < 0;},values : function() {- 1
return this.__stack.slice(0, this.__next + 1).reverse();}}}});
|
collections/Tree.js
|
Coverage100.00
SLOC457
LOC160
Missed0
|
- 1
var define = require("../define").define,Collection = require("./Collection"),Iterable = require("./Iterable"),base = require("../base"),multiply = base.string.multiply;- 1
var compare = function(a, b) {- 2757
var ret = 0;- 2757
if (a > b) {- 1571
return 1;- 1186
} else if (a < b) {- 936
return -1;- 250
}else if(!b){- 1
return 1;}- 249
return ret;};- 1
var Tree = define([Collection, Iterable], {instance : {/**@lends comb.collections.Tree.prototype*//*** Prints a node* @param node node to print* @param level the current level the node is at, Used for formatting*/__printNode : function(node, level) {//console.log(level);- 37
var str = [];- 37
if (node == null || node == undefined) {- 19
str.push(multiply('\t', level));- 19
str.push("~");- 19
console.log(str.join(""));} else {- 18
this.__printNode(node.right, level + 1);- 18
str.push(multiply('\t', level));- 18
str.push(node.data + "\n");- 18
console.log(str.join(""));- 18
this.__printNode(node.left, level + 1);}},/*** Base Class for all tree implementations* @constructs* @augments comb.collections.Collection* @augments comb.collections.Iterable* @memberOf comb.collections** @param {Object} options options to initialize the tree* @param {Function} options.compare function used to compare items in a tree must return an integer* <ul>* </li>-1 for less than</li>* </li>0 for equal</li>* </li>1 for greater than</li>* </ul>**/constructor : function(options) {- 45
options = options || {};- 45
this.compare = options.compare || compare;- 45
this.__root = null;},/*** Inserts an item into the tree* @param {Anything} data the item to insert*/insert : function(data) {- 1
throw new Error("Not Implemented");},/*** Removes an item from the tree* @param {Anything} data the item to insert*/remove : function(data) {- 1
throw new Error("Not Implemented");},/*** Clear all items from a tree*/clear : function() {- 4
this.__root = null;},/*** Test if a tree is empty** @return {Boolean} true if empty false otherwise*/isEmpty : function() {- 15
return this.__root == null;},/*** Traverse a tree until the callback function returns false** <p><b>Not typically used directly</b></p>** @param {Object} node the node to start at* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme* @param {Function} callback called for each item, traversal continues until the function returns false**/traverseWithCondition : function(node, order, callback) {- 2172
var cont = true;- 2172
if (node) {- 1270
order = order || Tree.PRE_ORDER;- 1270
if (order === Tree.PRE_ORDER) {- 152
cont = callback(node.data);- 152
if (cont) {- 144
cont = this.traverseWithCondition(node.left, order, callback);- 144
cont && (cont = this.traverseWithCondition(node.right, order, callback));}- 1118
} else if (order === Tree.IN_ORDER) {- 510
cont = this.traverseWithCondition(node.left, order, callback);- 510
if (cont) {- 444
cont = callback(node.data);- 444
cont && (cont = this.traverseWithCondition(node.right, order, callback));}- 608
} else if (order === Tree.POST_ORDER) {- 178
cont = this.traverseWithCondition(node.left, order, callback);- 178
if (cont) {- 158
cont && (cont = this.traverseWithCondition(node.right, order, callback));- 158
cont && (cont = callback(node.data));}- 430
} else if (order === Tree.REVERSE_ORDER) {- 430
cont = this.traverseWithCondition(node.right, order, callback);- 430
if (cont) {- 384
cont = callback(node.data);- 384
cont && (cont = this.traverseWithCondition(node.left, order, callback));}}}- 2172
return cont;},/*** Traverse a tree** <p><b>Not typically used directly</b></p>** @param {Object} node the node to start at* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme* @param {Function} callback called for each item**/traverse : function(node, order, callback) {- 3449
if (node) {- 1928
order = order || Tree.PRE_ORDER;- 1928
if (order === Tree.PRE_ORDER) {- 632
callback(node.data);- 632
this.traverse(node.left, order, callback);- 632
this.traverse(node.right, order, callback);- 1296
} else if (order === Tree.IN_ORDER) {- 632
this.traverse(node.left, order, callback);- 632
callback(node.data);- 632
this.traverse(node.right, order, callback);- 664
} else if (order === Tree.POST_ORDER) {- 632
this.traverse(node.left, order, callback);- 632
this.traverse(node.right, order, callback);- 632
callback(node.data);- 32
} else if (order === Tree.REVERSE_ORDER) {- 32
this.traverseWithCondition(node.right, order, callback);- 32
callback(node.data);- 32
this.traverseWithCondition(node.left, order, callback);}}},/*** Loop through each item in the tree* @param {Function} cb called for each item in the tree* @param {Object} [scope=this] scope to call the function in* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme*/forEach : function(cb, scope, order) {- 28
if (typeof cb !== "function")- 4
throw new TypeError();- 24
order = order || Tree.IN_ORDER;- 24
scope = scope || this;- 24
this.traverse(this.__root, order, function(node) {- 312
cb.call(scope, node, this);});},/*** Loop through each item in the tree, collecting the value returned by the callback funciton.* @param {Function} cb called for each item in the tree.* Whatever the function returns is inserted into the return tree* @param {Object} [scope=this] scope to call the function in* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme** @return {comb.collections.Tree} the tree with the mapped items*/map : function(cb, scope, order) {- 28
if (typeof cb !== "function")- 4
throw new TypeError();- 24
order = order || Tree.IN_ORDER;- 24
scope = scope || this;- 24
var construct = this._static;- 24
var ret = new this._static();- 24
this.traverse(this.__root, order, function(node) {- 312
ret.insert(cb.call(scope, node, this));});- 24
return ret;},/*** Filters a tree, only returning items that result in true being returned from the callback** @param {Function} cb called for each item in the tree* @param {Object} [scope=this] scope to call the function in* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme** @return {comb.collections.Tree} the tree with items that resulted in true being returned from the callback*/filter : function(cb, scope, order) {- 16
if (typeof cb !== "function")- 4
throw new TypeError();- 12
order = order || Tree.IN_ORDER;- 12
scope = scope || this;- 12
var ret = new this._static();- 12
this.traverse(this.__root, order, function(node) {- 216
var include = cb.call(scope, node, this);- 216
include && ret.insert(node);});- 12
return ret;},/*** Reduces a tree** @param {Function} fun called for each item in the tree* @param [accumulator=First item in tree(Order dependant)] scope to call the function in* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme** @return the result of the reduce function*/reduce : function(fun, accumulator, order) {- 36
var arr = this.toArray(order);- 36
var args = [fun];- 36
!base.isUndefinedOrNull(accumulator) && args.push(accumulator)- 36
return arr.reduce.apply(arr, args);},/*** Reduces from right to left** @param {Function} fun called for each item in the tree* @param [accumulator=First item in tree(Order dependant)] scope to call the function in* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme** @return the result of the reduce function*/reduceRight : function(fun, accumulator, order) {- 12
var arr = this.toArray(order);- 12
var args = [fun];- 12
!base.isUndefinedOrNull(accumulator) && args.push(accumulator)- 12
return arr.reduceRight.apply(arr, args);},/*** Determines if every item meets the condition returned by the callback.** @param {Function} cb called for each item in the tree* @param {Object} [scope=this] scope to call the function in* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme** @return {Boolean} True if every item passed false otherwise*/every : function(cb, scope, order) {- 36
if (typeof cb !== "function")- 4
throw new TypeError();- 32
order = order || Tree.IN_ORDER;- 32
scope = scope || this;- 32
var ret = false;- 32
this.traverseWithCondition(this.__root, order, function(node) {- 264
return (ret = cb.call(scope, node, this));});- 32
return ret;},/*** Determines if some item meet the condition returned by the callback. Traversal ends the first time true is found.** @param {Function} cb called for each item in the tree* @param {Object} [scope=this] scope to call the function in* @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme** @return {Boolean} True if every item passed false otherwise*/some : function(cb, scope, order) {- 36
if (typeof cb !== "function")- 4
throw new TypeError();- 32
order = order || Tree.IN_ORDER;- 32
scope = scope || this;- 32
var ret;- 32
this.traverseWithCondition(this.__root, order, function(node) {- 284
ret = cb.call(scope, node, this);- 284
return !ret;});- 32
return ret;},/*** Converts a tree into an array based on the specified order** @param {Tree.PRE_ORDER|Tree.POST_ORDER|Tree.IN_ORDER|Tree.REVERSE_ORDER} [order=Tree.IN_ORDER] the traversal scheme** @return {Array} array of all items in the order specified.*/toArray : function(order) {- 72
order = order || Tree.IN_ORDER;- 72
var arr = [];- 72
this.traverse(this.__root, order, function(node) {- 1056
arr.push(node);});- 72
return arr;},/*** Determines if a value is contained in the tree* @param {*} value the value to find** @return {Boolean} true if the tree contains the item false otherwise.*/contains : function(value) {- 160
var ret = false;- 160
var root = this.__root;- 160
while (root != null) {- 376
var cmp = this.compare(value, root.data);- 376
if (cmp) {- 271
root = root[(cmp == -1) ? "left" : "right"];} else {- 105
ret = true;- 105
root = null;}}- 160
return ret;},/*** Finds a value in the tree* @param {*} value the value to find** @return the value of the node that matched*/find : function(value) {- 8
var ret;- 8
var root = this.__root;- 8
while (root != null) {- 35
var cmp = this.compare(value, root.data);- 35
if (cmp) {- 31
root = root[(cmp == -1) ? "left" : "right"];} else {- 4
ret = root.data;- 4
break;}}- 8
return ret;},/*** Find all values less than a value* @param {*} value the value to find nodes less than* @param {Boolean} [exclusive=false] if true the value will NOT be included in the return array** @return {Array} the array containing all values less than*/findLessThan : function(value, exclusive) {//find a better way!!!!- 32
var ret = [], compare = this.compare;- 32
this.traverseWithCondition(this.__root, exports.IN_ORDER, function(v) {- 200
var cmp = compare(value, v);- 200
if ((!exclusive && cmp == 0) || cmp == 1) {- 168
ret.push(v);- 168
return true;} else {- 32
return false;}});- 32
return ret;},/*** Find all greater than a value* @param {*} value the value to find nodes greater than* @param {Boolean} [exclusive=false] if true the value will NOT be included in the return array** @return {Array} the array containing all values greater than*/findGreaterThan : function(value, exclusive) {//find a better way!!!!- 32
var ret = [], compare = this.compare;- 32
this.traverse(this.__root, exports.REVERSE_ORDER, function(v) {- 416
var cmp = compare(value, v);- 416
if ((!exclusive && cmp == 0) || cmp == -1) {- 372
ret.push(v);- 372
return true;} else {- 44
return false;}});- 32
return ret;},/*** Prints a tree to the console.*/print : function() {- 4
this.__printNode(this.__root, 0);}},static : {/** @lends comb.collections.Tree *//*** Pre Order*/PRE_ORDER : "pre_order",/*** In Order*/IN_ORDER : "in_order",/*** Post Order*/POST_ORDER:"post_order",/*** Reverse Order*/REVERSE_ORDER : "reverse_order"}});/**@ignore*/- 1
module.exports = exports = Tree;
|
collections/index.js
|
Coverage100.00
SLOC21
LOC2
Missed0
|
- 1
var comb = exports;/*** @ignore* @namespace Various collections*/- 1
comb.collections = {Collection : require("./Collection"),Iterable : require("./Iterable"),Tree : require("./Tree"),BinaryTree : require("./BinaryTree"),RedBlackTree : require("./RedBlackTree"),AnderssonTree : require("./AnderssonTree"),AVLTree : require("./AVLTree"),HashTable : require("./HashTable"),Queue : require("./Queue"),Stack : require("./Stack"),Heap : require("./Heap"),MinHeap : require("./MinHeap"),MaxHeap : require("./MaxHeap"),PriorityQueue : require("./PriorityQueue"),Pool : require("./Pool")};
|
define.js
|
Coverage100.00
SLOC505
LOC138
Missed0
|
/*** Used to keep track of classes and to create unique ids* @ignore*/- 1
var classCounter = 0;- 1
var callSuper = function (args, a) {- 1121
var meta = this.__meta,supers = meta.supers,l = supers.length, superMeta = meta.superMeta, pos = superMeta.pos;- 1121
if (l > pos) {- 976
a && (args = a);- 976
var name = superMeta.name, f = superMeta.f, m;- 976
do {- 976
m = supers[pos][name];- 976
if ("function" === typeof m && (m = m._f || m) !== f) {- 976
superMeta.pos = 1 + pos;- 976
return m.apply(this, args);}} while (l > ++pos);}- 145
return null;};- 1
var defaultFunction = function () {- 140
var meta = this.__meta || {},supers = meta.supers,l = supers.length, superMeta = meta.superMeta, pos = superMeta.pos;- 140
if (l > pos) {- 123
var name = superMeta.name, f = superMeta.f, m;- 123
do {- 173
m = supers[pos][name];- 173
if ("function" === typeof m && (m = m._f || m) !== f) {- 94
superMeta.pos = 1 + pos;- 94
return m.apply(this, arguments);}} while (l > ++pos);}- 46
return null;};- 1
var functionWrapper = function (f, name) {- 306
var wrapper = function () {- 13911
var ret, meta = this.__meta || {};- 13911
var orig = meta.superMeta;- 13911
meta.superMeta = {f:f, pos:0, name:name};- 13911
ret = f.apply(this, arguments);- 13862
meta.superMeta = orig;- 13862
return ret;};- 306
wrapper._f = f;- 306
return wrapper;};/*** @ignore*/- 1
var defineMixinProps = function (child, proto) {- 34
var operations = proto.setters || {};- 34
for (var i in operations) {- 15
if (!child.__lookupSetter__(i)) { //make sure that the setter isnt already there- 15
child.__defineSetter__(i, operations[i]);}}- 34
operations = proto.getters || {};- 34
for (i in operations) {- 15
if (!child.__lookupGetter__(i)) {//define the getter if the child does not already have it- 15
child.__defineGetter__(i, operations[i]);}}- 34
for (var j in proto) {- 103
if (j != "getters" && j != "setters") {- 83
var p = proto[j];- 83
if ("function" === typeof p) {- 78
if (!child.hasOwnProperty(j)) {- 10
child[j] = functionWrapper(defaultFunction, j);}} else {- 5
child[j] = p;}}}};/*** @ignore*/- 1
var mixin = function () {- 7
var args = Array.prototype.slice.call(arguments), l = args.length;- 7
var child = this.prototype, childMeta = child.__meta, thisMeta = this.__meta, bases = child.__meta.bases, staticBases = bases.slice(),staticSupers = thisMeta.supers || [], supers = childMeta.supers|| [];- 7
for (var i = 0; i < l; i++) {- 17
var m = args[i], mProto = m.prototype;- 17
var protoMeta = mProto.__meta, meta = m.__meta;- 17
!protoMeta && (protoMeta = (mProto.__meta = {proto :mProto || {}}));- 17
!meta && (meta = (m.__meta = {proto :m.__proto__ || {}}));- 17
defineMixinProps(child, protoMeta.proto || {});- 17
defineMixinProps(this, meta.proto || {});//copy the bases for static,- 17
mixinSupers(m.prototype, supers, bases);- 17
mixinSupers(m, staticSupers, staticBases);}- 7
return this;};/*** @ignore*/- 1
var mixinSupers = function (sup, arr, bases) {- 214
var meta = sup.__meta;- 214
!meta && (meta = (sup.__meta = {}));- 214
var unique = sup.__meta.unique;- 214
!unique && (meta.unique = "define" + ++classCounter);//check it we already have this super mixed into our prototype chain//if true then we have already looped their supers!- 214
if (bases.indexOf(unique) == -1) {//add their id to our bases- 138
bases.push(unique);- 138
var supers = sup.__meta.supers || [], i = supers.length - 1 || 0;- 138
while (i >= 0) {- 118
mixinSupers(supers[i--], arr, bases);}- 138
arr.unshift(sup);}};/*** @ignore*/- 1
var defineProps = function (child, proto) {- 88
var operations = proto.setters;- 88
if (operations) {- 8
for (var i in operations) {- 13
child.__defineSetter__(i, operations[i]);}}- 88
operations = proto.getters || {};- 88
if (operations) {- 88
for (i in operations) {- 47
child.__defineGetter__(i, operations[i]);}}- 88
for (i in proto) {- 347
if (i != "getters" && i != "setters") {- 326
var f = proto[i];- 326
if ("function" === typeof f) {- 293
var meta = f.__meta || {};- 293
if (!meta.isConstructor) {- 292
child[i] = functionWrapper(f, i);} else {- 1
child[i] = f;}} else {- 33
child[i] = f;}}}};- 1
var _export = function (obj, name) {- 11
if (obj && name) {- 2
obj[name] = this;} else {- 9
obj.exports = obj = this;}- 11
return this;};/*** @ignore*/- 1
var __define = function (child, sup, proto) {- 46
var childProto = child.prototype, supers = [];- 46
var unique = "define" + ++classCounter, bases = [], staticBases = [];- 46
var instanceSupers = [], staticSupers = [];- 46
var meta = childProto.__meta = {supers:instanceSupers,unique:unique,bases:bases,superMeta:{f:null,pos:0,name:null}};- 46
var childMeta = child.__meta = {supers:staticSupers,unique:unique,bases:staticBases,isConstructor:true,superMeta:{f:null,pos:0,name:null}};- 46
if (sup) {- 31
supers = Array.isArray(sup) ? sup : [sup];- 31
sup = supers.shift();- 31
child.__proto__ = sup;- 31
childProto.__proto__ = sup.prototype;- 31
mixinSupers(sup.prototype, instanceSupers, bases),mixinSupers(sup, staticSupers, staticBases);}- 46
if (proto) {- 44
var instance = meta.proto = proto.instance || {};- 44
!instance.hasOwnProperty("constructor") && (instance.constructor = defaultFunction);- 44
var stat = childMeta.proto = proto.static || {};- 44
stat.init = stat.init || defaultFunction;- 44
defineProps(childProto, instance, false);- 44
defineProps(child, stat, true);} else {- 2
meta.proto = {};- 2
childMeta.proto = {};- 2
child.init = functionWrapper(defaultFunction, "init");- 2
childProto.constructor = functionWrapper(defaultFunction, "constructor");}- 46
if (supers.length) {- 7
mixin.apply(child, supers);}- 46
child.mixin = mixin;- 46
childProto._super = child._super = callSuper;- 46
child.as = _export;- 46
childProto._static = child;};/*** Defines a new class to be used** <p>* Class methods* <ul>* <li>as(module | object, name): exports the object to module or the object with the name</li>* <li>mixin(mixin) : mixes in an object</li>* </ul>* </br>* Instance methods* <ul>* <li>_super(argumnents, [?newargs]): calls the super of the current method</li>* </ul>** </br>* Instance properties* <ul>* <li>_static: use to reference class properties and methods</li>* </ul>** </p>*** @example* //Class without a super class* var Mammal = comb.define(null, {* instance : {** constructor: function(options) {* options = options || {};* this._super(arguments);* this._type = options.type || "mammal";* },** speak : function() {* return "A mammal of type " + this._type + " sounds like";* },** //Define your getters* getters : {* type : function() {* return this._type;* }* },** //Define your setters* setters : {* type : function(t) {* this._type = t;* }* }* },** //Define your static methods* static : {* soundOff : function() {* return "Im a mammal!!";* }* }* });** //Show singular inheritance*var Wolf = comb.define(Mammal, {* instance: {* constructor: function(options) {* options = options || {};* //You can call your super constructor, or you may not* //call it to prevent the super initializing parameters* this._super(arguments);* this._sound = "growl";* this._color = options.color || "grey";* },** speak : function() {* //override my super classes speak* //Should return "A mammal of type mammal sounds like a growl"* return this._super(arguments) + " a " + this._sound;* },** //add new getters for sound and color* getters : {** color : function() {* return this._color;* },** sound : function() {* return this._sound;* }* },** setters : {** //NOTE color is read only except on initialization** sound : function(s) {* this._sound = s;* }* }** },** static : {* //override my satic soundOff* soundOff : function() {* //You can even call super in your statics!!!* //should return "I'm a mammal!! that growls"* return this._super(arguments) + " that growls";* }* }*});*** //Typical hierarchical inheritance* // Mammal->Wolf->Dog* var Dog = comb.define(Wolf, {* instance: {* constructor: function(options) {* options = options || {};* this._super(arguments);* //override Wolfs initialization of sound to woof.* this._sound = "woof";** },** speak : function() {* //Should return "A mammal of type mammal sounds like a growl thats domesticated"* return this._super(arguments) + " thats domesticated";* }* },** static : {* soundOff : function() {* //should return "I'm a mammal!! that growls but now barks"* return this._super(arguments) + " but now barks";* }* }*});**** dog instanceof Wolf => true* dog instanceof Mammal => true* dog.speak() => "A mammal of type mammal sounds like a woof thats domesticated"* dog.type => "mammal"* dog.color => "gold"* dog.sound => "woof"* Dog.soundOff() => "Im a mammal!! that growls but now barks"** // Mammal->Wolf->Dog->Breed*var Breed = comb.define(Dog, {* instance: {** //initialize outside of constructor* _pitch : "high",** constructor: function(options) {* options = options || {};* this._super(arguments);* this.breed = options.breed || "lab";* },** speak : function() {* //Should return "A mammal of type mammal sounds like a* //growl thats domesticated with a high pitch!"* return this._super(arguments) + " with a " + this._pitch + " pitch!";* },** getters : {* pitch : function() {* return this._pitch;* }* }* },** static : {* soundOff : function() {* //should return "I'M A MAMMAL!! THAT GROWLS BUT NOW BARKS!"* return this._super(arguments).toUpperCase() + "!";* }* }* });*** var breed = new Breed({color : "gold", type : "lab"}),**** breed instanceof Dog => true* breed instanceof Wolf => true* breed instanceof Mammal => true* breed.speak() => "A mammal of type lab sounds like a woof "* + "thats domesticated with a high pitch!"* breed.type => "lab"* breed.color => "gold"* breed.sound => "woof"* breed.soundOff() => "IM A MAMMAL!! THAT GROWLS BUT NOW BARKS!"*** //Example of multiple inheritance* //NOTE proto is optional** //Mammal is super class* //Wolf Dog and Breed inject functionality into the prototype* var Lab = comb.define([Mammal, Wolf, Dog, Breed]);** var lab = new Lab();* lab instanceof Wolf => false* lab instanceof Dog => false* lab instanceof Breed => false* lab instanceof Mammal => true* lab.speak() => "A mammal of type mammal sounds like a"* + " woof thats domesticated with a high pitch!"* Lab.soundOff() => "IM A MAMMAL!! THAT GROWLS BUT NOW BARKS!"** @name define* @memberOf comb** @param {Array|Class} super the supers of this class* @param {Object} [proto] the object used to define this class* @param {Object} [proto.instance] the instance methods of the class* @param {Object} [proto.instance.getters] the getters for the class* @param {Object} [proto.instance.setters] the setters for the class* @param {Object} [proto.static] the Class level methods of this class* @param {Object} [proto.static.getters] static getters for the object* @param {Object} [proto.static.setters] static setters for the object** @returns {Object} the constructor of the class to be used with new keyword*/- 1
exports.define = function (sup, proto) {- 43
var child = function () {- 596
this.constructor.apply(this, arguments);};- 43
__define(child, sup, proto);- 43
return child.init() || child;};/*** Defines a singleton instance of a Class. See {@link define}* @example* var MyLab = comb.singleton([Mammal, Wolf, Dog, Breed]);* var myLab1 = new MyLab();* myLab1.type = "collie"* var myLab2 = new MyLab();* myLab1 === myLab2 => true* myLab1.type => "collie"* myLab2.type => "collie"*** @name singleton* @memberOf comb*/- 1
exports.singleton = function (sup, proto) {- 3
var retInstance;- 3
var child = function () {- 6
if (!retInstance) {- 2
this.constructor.apply(this, arguments);- 2
retInstance = this;}- 6
return retInstance;};- 3
__define(child, sup, proto);- 3
return child.init() || child;};
|
index.js
|
Coverage100.00
SLOC101
LOC7
Missed0
|
- 1
var base = require("./base");/*** @projectName comb** @github https://github.com/Pollenware/comb** @includeDoc [OO] ../docs-md/define.md* @includeDoc [Promises] ../docs-md/promise.md* @includeDoc [Logging] ../docs-md/logging.md* @includeDoc [Utilities] ../docs-md/utilities.md* @includeDoc [Test Coverage] [../docs-md/coverage.html]*** @header** #Comb** ##Overview** Framework for node that provides a one stop shop for frequently needed utilities, including:** * [OO utilties](./define.html)* * Collections* * [Logging](./logging.html)* * [String & date formatting](./utilities)* * [Flow control](./promise.html)*** ##Installation** `npm install comb`** ##Highlights** * 100% test coverage!* * comb([define](./comb.html#.define)|[singleton](./comb.html#.singleton))* * The backbone of comb.* * Options for classical inheritance models as well as mixins(pseudo multi-inheritance)* * You can call this._super from any method. Including statically defined ones!* * Access to your class level properties within an instance* * Logging* * Logger inheritance through name spaces* * Predefined [level](./comb_logging_Level.html) level definition along with the ability to define your own.* * Multiple appenders including* * [FileAppender](./comb_logging_appenders_FileAppender.html) - log it to a file* * [RollingFileAppender](./comb_logging_appenders_RollingFileAppender.html) - log it to a file up to a customizable size then create a new one.* * [JSONAppender](./comb_logging_appenders_JSONAppender.html) - write it out as JSON to a file.* * [ConsoleAppender](./comb_logging_appenders_ConsoleAppender.html)- log it to the console* * Configurable with [files OR programatically](./comb_logger.html#.configure)* * Collections* * [RedBlackTree](./comb_collections_RedBlackTree.html)* * [AVLTree](./comb_collections_AVLTree.html)* * [AnderssonTree](./comb_collections_AnderssonTree.html)* * [BinaryTree](./comb_collections_BinaryTree.html)* * [HashTable](./comb_collections_HashTable.html)* * [MaxHeap](./comb_collections_MaxHeap.html)* * [MinHeap](./comb_collections_MinHeap.html)* * [Pool](./comb_collections_Pool.html)* * [PriorityQueue](./comb_collections_PriorityQueue.html)* * [Queue](./comb_collections_Queue.html)* * [Stack](./comb_collections_Stack.html)** * [Flow control](./promise.html)* * [Promises](./comb_Promise.html)* * [PromiseList](./comb_PromiseList.html)* * [comb.when](./comb.html#.when)* * [comb.serial](./comb.html#.serial)** @footer* ##License** MIT <https://github.com/Pollenware/comb/raw/master/LICENSE>** ##Meta* * Code: `git clone git://github.com/Pollenware/comb.git`* * Website: <http://pollenware.com>* * Twitter: [http://twitter.com/pollenware](http://twitter.com/pollenware) - 877.465.4045*//*** Utilities for javascript, optimized for the server environment.*** @namespace*/- 1
var comb = exports;- 1
base.merge(exports, base, require("./define"), require("./promise"), require("./plugins"), require("./collections"), require("./logging"));- 1
comb.definePlugin = function (obj) {- 1
if (comb.isHash(obj)) {- 1
comb.deepMerge(comb, obj);}- 1
return comb;};
|
logging/appenders/appender.js
|
Coverage100.00
SLOC167
LOC30
Missed0
|
- 1
var define = require("../../define.js").define, base = require("../../base"), Level = require("../level");- 1
var APPENDER_TYPES = {};/*** @class Base class for all appenders** @name Appender* @memberOf comb.logging.appenders** @param {Object} [options] options to assign to this Appender* @param {String} [options.name="appender"] the name of this Appender. If you want two of the same type of appender* on a logger it must have a different name.* @param {String} [options.pattern="[{[yyyy-MM-ddTHH:mm:ss:SSS (z)]timeStamp}] {[- 5]levelName} {[-20]name} - {message}"]* <p>Available Options for formatting see {@link comb.string.format} for formatting options</p>* <ul>* <li>timeStamp - the timestamp of the event being logged</li>* <li>level - the {@link comb.logging.Level} of the event</li>* <li>levelName - the name of the level being logged</li>* <li>name - the name of the logger logging the event</li>* <li>message - the message being logged</li>* </ul>* @param {comb.logging.Level|String} [options.level=comb.logging.Level.INFO] the logging level of this appender* <p><b>Note:</b> the level can be different from the logger in the case that you want a particular logger* to only log particular event of a level. For example an appender that only logs errors. BEWARE that if the* appenders level is lower than the logger is will not receive any messages.</p>** @property {String} name the name of this Appender.* @property {String} pattern the pattern for this Appender.* @property {comb.logging.Level} level the level of this Appender.* @ignoreCode*/- 1
define(null, {instance:{/**@lends comb.logging.appenders.Appender.prototype*/constructor:function (options) {- 21
options = options || {};- 21
this.name = options.name || "appender";- 21
this.pattern = options.pattern || "[{[yyyy-MM-ddTHH:mm:ss:SSS (z)]timeStamp}] {[- 5]levelName} {[-20]name} - {message}";- 21
var level = options.level;- 21
if (options.level && (level = Level.toLevel(level))) {- 3
this.__level = level;}},/*** Appends a message to a log.* <b>This method is abstract and must be implemented in subclasses</b>* @param {Object} event the logging event to log.* @param {Date} event.timeStamp the timeStamp of the event.* @param {comb.logging.Level} level the level of the event.* @param {String} name the name of the logger the event was emitted from.* @param {String} message the message that is being logged.**/append:function (event) {- 1
throw new Error("abstract method");},_canAppend:function (event) {- 76
return !base.isUndefinedOrNull(this.__level) && event.level.isGreaterOrEqualToo(this.__level);},/**@ignore*/setters:{/**@ignore*/level:function (level) {- 59
if (level && level instanceof Level) {- 52
this.__level = level;} else {//try to get the level- 7
level = Level.toLevel(level);- 7
if (level) {- 4
this.__level = level;}}},pattern:function (patt) {- 22
if (base.isString(patt)) {- 22
this.__pattern = patt;}},name:function (name) {- 27
if (base.isString(name)) {- 27
this.__name = name;}}},/**@ignore*/getters:{/**@ignore*/level:function () {- 92
return this.__level;},name:function () {- 112
return this.__name;},pattern:function () {- 3
return this.__pattern;}}},"static":{/**@lends comb.logging.appenders.Appender*//*** Register an appender so it can be used with {@link comb.logging.PropertyConfigurator}** @example** var Appender = comb.logging.appenders.Appender;* comb.define(Appender, {* instance : {* append : function(event){* //log the message* }* }* }).registerType("MyAppender").as(module);** @param {String} type the identifier for your appender type.* @return returns the Appender class for chaining.*/registerType:function (type) {- 5
if (base.isString(type)) {- 5
APPENDER_TYPES[type.toLowerCase()] = this;}- 5
return this;},/*** Acts as a factory for appenders.** @example** var logging = comb.logging,* Logger = logging.Logger,* Appender = logging.appenders.Appender;** var logger = comb.logging.Logger.getLogger("my.logger");* logger.addAppender(Appender.createAppender("consoleAppender"));** @param {String} type the type of appender to create.* @param {Object} [options={}] additional options to pass to the appender.* @return {comb.logging.appenders.Appender} an appender to add to a logger.*/createAppender:function (type, options) {- 14
var caseType = type.toLowerCase();- 14
if (caseType in APPENDER_TYPES) {- 13
return new APPENDER_TYPES[caseType](options);} else {- 1
throw new Error(type + " appender is not registered!");}}}}).as(module);
|
logging/appenders/consoleAppender.js
|
Coverage100.00
SLOC37
LOC17
Missed0
|
- 1
var define = require("../../define.js").define, base = require("../../base"), string = base.string, style = string.style, format = string.format, Appender = require("./appender"), Level = require("../level");/*** @class Appends messages to the console.** @name ConsoleAppender* @augments comb.logging.appenders.Appender* @memberOf comb.logging.appenders*/- 1
define(Appender, {instance:{constructor:function (options) {- 9
options = options || {};- 9
!options.name && (options.name = "consoleAppender");- 9
this._super(arguments, [options]);},append:function (event) {- 7
if (this._canAppend(event)) {- 7
var message = format(this.__pattern, event);- 7
var level = event.level;- 7
if (Level.ERROR.equals(level) || Level.FATAL.equals(level)) {- 3
console.log(style(message, "red"));- 4
} else if (Level.WARN.equals(level)) {- 1
console.log(style(message, "yellow"));- 3
} else if (Level.DEBUG.equals(level)) {- 1
console.log(style(message, "magenta"));- 2
} else if (Level.TRACE.equals(level)) {- 1
console.log(style(message, "cyan"));} else {- 1
console.log(message);}}}}}).registerType("ConsoleAppender").as(module);
|
logging/appenders/fileAppender.js
|
Coverage100.00
SLOC83
LOC22
Missed0
|
- 1
var define = require("../../define.js").define,base = require("../../base"),promise = require("../../promise"),string = base.string,Promise = promise.Promise,PromiseList = promise.PromiseList,style = string.style,format = string.format,Appender = require("./appender"),Level = require("../level"),fs = require("fs");/*** @class Appends messages to a file.** @example* var fileAppender = new comb.logging.appenders.FileAppender({* file : "/var/log/myLog.log"* });*** @name FileAppender* @augments comb.logging.appenders.Appender* @memberOf comb.logging.appenders** @param {Object} [options] options to assign to this Appender* @param {String} [options.name="appender"] the name of this Appender. If you want two of the same type of appender* on a logger it must have a different name.* @param {String} [options.pattern="[{[yyyy-MM-ddTHH:mm:ss:SSS (z)]timeStamp}] {[- 5]levelName} {[-20]name} - {message}"]* <p>Available Options for formatting see {@link comb.string.format} for formatting options</p>* <ul>* <li>timeStamp - the timestamp of the event being logged</li>* <li>level - the {@link comb.logging.Level} of the event</li>* <li>levelName - the name of the level being logged</li>* <li>name - the name of the logger logging the event</li>* <li>message - the message being logged</li>* </ul>* @param {comb.logging.Level|String} [options.level=comb.logging.Level.INFO] the logging level of this appender* <p><b>Note:</b> the level can be different from the logger in the case that you want a particular logger* to only log particular event of a level. For example an appender that only logs errors. BEWARE that if the* appenders level is lower than the logger is will not recieve any messages.</p>** @param {String} [options.file="./log.log"] the file to log events to.* @param {String} [options.encoding="utf8"] the encoding of the file.* @param {Boolean} [options.overwrite=false] if true the log file is overwritten otherwise it is appended to.* @ignoreCode*/- 1
define(Appender, {instance:{constructor:function (options) {- 8
options = options || {};- 8
!options.name && (options.name = "fileAppender");- 8
this.__file = options.file || "./log.log";- 8
this.__encoding = options.encoding || "utf8";- 8
this.__overwrite = options.overwrite || false;- 8
this.__writeStream = options.writeStream || fs.createWriteStream(this.__file, { flags:this.__overwrite ? "w" : 'a', encoding:this.__encoding});- 8
this._super([options]);- 8
this.__pattern += "\n";- 8
base.listenForExit(base.hitch(this, "__onExit"));},__onExit:function () {- 14
var ret = new Promise();- 14
var ws = this.__writeStream;- 14
this.__writeStream = null;- 14
ws.on("close", base.hitch(ret, "callback"));- 14
ws.destroySoon();- 14
return ret.promise();},append:function (event) {- 15
var ws = this.__writeStream;- 15
if (this._canAppend(event) && ws && ws.writable) {- 15
var message = format(this.__pattern, event);- 15
var level = event.level;- 15
ws.write(message);}}}}).registerType("FileAppender").as(module);
|
logging/appenders/index.js
|
Coverage100.00
SLOC11
LOC5
Missed0
|
/**@ignore*/- 1
exports.Appender = require("./appender");/**@ignore*/- 1
exports.ConsoleAppender = require("./consoleAppender");/**@ignore*/- 1
exports.FileAppender = require("./fileAppender");/**@ignore*/- 1
exports.JSONAppender = require("./jsonAppender");/**@ignore*/- 1
exports.RollingFileAppender = require("./rollingFileAppender");
|
logging/appenders/jsonAppender.js
|
Coverage100.00
SLOC85
LOC19
Missed0
|
- 1
var define = require("../../define.js").define,base = require("../../base"),string = base.string,escape = base.regexp.escapeString,FileAppender = require("./fileAppender"),format = string.format,Level = require("../level"),fs = require("fs");/*** @class Appends messages to a file in JSON format. The messages are logged to an array in a JSON file* <b>The file is always overwritten</b>** @example* //example log.json* [* {* "timestamp" : "Wed Jun 08 2011 11:16:20 GMT-0500 (CDT)",* "level" : "INFO",* "name" : "comb",* "message" : "INFO MESSAGE!!!!"* }* ]*** @name JSONAppender* @augments comb.logging.appenders.FileAppender* @memberOf comb.logging.appenders** @param {Object} [options] options to assign to this Appender* @param {String} [options.name="appender"] the name of this Appender. If you want two of the same type of appender* on a logger it must have a different name.* @param {String} [options.pattern="{"timestamp" : "{timeStamp}", "level" : "{levelName}", "name" : "{name}", "message" : "{message}"}"]* <p>Available Options for formatting see {@link comb.string.format} for formatting options</p>* <ul>* <li>timeStamp - the timestamp of the event being logged</li>* <li>level - the {@link comb.logging.Level} of the event</li>* <li>levelName - the name of the level being logged</li>* <li>name - the name of the logger logging the event</li>* <li>message - the message being logged</li>* </ul>* @param {comb.logging.Level|String} [options.level=comb.logging.Level.INFO] the logging level of this appender* <p><b>Note:</b> the level can be different from the logger in the case that you want a particular logger* to only log particular event of a level. For example an appender that only logs errors. BEWARE that if the* appenders level is lower than the logger is will not recieve any messages.</p>** @param {String} [options.file="./log.json"] the file to log events to.* @param {String} [options.encoding="utf8"] the encoding of the file.** @ignoreCode*/- 1
define(FileAppender, {instance:{constructor:function (options) {- 5
options = options || {};- 5
this.name = options.name || "JSONAppender";- 5
this.__count = 0;- 5
this.__file = options.file || "./log.json";- 5
this.__encoding = options.encoding || "utf8";- 5
this.__writeStream = options.writeStream || fs.createWriteStream(this.__file, { flags:"w", encoding:this.__encoding});- 5
this.__writeStream.write("[\n");- 5
this.level = options.level;//explicit overwrite of patter- 5
this.__pattern = '{"timestamp" : "{timeStamp}", "level" : "{levelName}", "name" : "{name}", "message" : "{message}"}';- 5
base.listenForExit(base.hitch(this, "__onExit"));},append:function (event) {- 6
if (this._canAppend(event)) {- 6
event.message = event.message.replace(/\n+/g, "\\n");- 6
var message = (this.__count ? ",\n" : "\n") + format(this.__pattern, event);- 6
this.__writeStream.write(message);- 6
this.__count++;}},__onExit:function () {- 5
this.__writeStream.write("]");- 5
this._super(arguments);}}}).registerType("JSONAppender").as(module);
|
logging/appenders/rollingFileAppender.js
|
Coverage100.00
SLOC211
LOC79
Missed0
|
- 1
var define = require("../../define.js").define,promise = require("../../promise"),Promise = promise.Promise,PromiseList = promise.PromiseList,base = require("../../base"),hitch = base.hitch,string = base.string,escape = base.regexp.escapeString,style = string.style,format = string.format,FileAppender = require("./fileAppender"),Level = require("../level"),fs = require("fs"),path = require("path");- 1
var conversion = {MB:1048576,KB:1024,GB:1073741824};- 1
var DEFAULT_SIZE = "10MB";- 1
var convertToBytes = function (str) {- 3
var ret = DEFAULT_SIZE;- 3
var match = str.match(/(\d+)(MB|KB|GB)$/);- 3
if (match && match.length == 3) {- 3
var size = parseInt(match[1], 10);- 3
ret = size * conversion[match[2]];}- 3
return ret;}/*** @class Appends messages to a file. Rolls files over when a size limit has been reached. Once the max file size has* been reached it is rolled over to a file called <logName>.log.n where n is a number.* </br></br>* <p>Example. RollingFileAppender is current writing to myLog.log, the log reaches is max size to it is* renamed to myLog.log.1 and a new myLog.log is created.</p>* </br>* If maxBackupIndex is reached then the log at that index is deleted. If maxBackupIndex is set to 0 then no log is* rolled over.</p>** @name RollingFileAppender* @augments comb.logging.appenders.FileAppender* @memberOf comb.logging.appenders** @param {Object} [options] options to assign to this Appender* @param {String} [options.name="appender"] the name of this Appender. If you want two of the same type of appender* on a logger it must have a different name.* @param {String} [options.pattern="[{[yyyy-MM-ddTHH:mm:ss:SSS (z)]timeStamp}] {[- 5]levelName} {[-20]name} - {message}"]* <p>Available Options for formatting see {@link comb.string.format} for formatting options</p>* <ul>* <li>timeStamp - the timestamp of the event being logged</li>* <li>level - the {@link comb.logging.Level} of the event</li>* <li>levelName - the name of the level being logged</li>* <li>name - the name of the logger logging the event</li>* <li>message - the message being logged</li>* </ul>* @param {comb.logging.Level|String} [options.level=comb.logging.Level.INFO] the logging level of this appender* <p><b>Note:</b> the level can be different from the logger in the case that you want a particular logger* to only log particular event of a level. For example an appender that only logs errors. BEWARE that if the* appenders level is lower than the logger is will not recieve any messages.</p>** @param {String} [options.file="./log.log"] the file to log events to.* @param {String} [options.encoding="utf8"] the encoding of the file.* @param {Boolean} [options.overwrite=false] if true the log file is overwritten otherwise it is appended to.* @param {String} [options.maxSize="10MB"] the maxSize of a file. Valid options include "KB", "MB", or "GB"** <pre class="code">* maxSize = "100MB"* //or* maxSize = "100KB"* //or* maxSize = "1GB"* </pre>** @param {Number} [options.maxBackupIndex=10] the maximum number of files to rollOver.*/- 1
define(FileAppender, {instance:{__watching:false,constructor:function (options) {- 3
options = options || {};- 3
this.maxSize = options.maxSize || DEFAULT_SIZE;- 3
!options.name && (options.name = "rollingFileAppender");- 3
this.maxBackupIndex = options.maxBackupIndex || 10;- 3
this.__queue = [];- 3
this.__inRollover = false;- 3
this._super([options]);},__startCheck:function () {- 1
if (!this.__watching) {- 1
this.__watching = true;- 1
fs.watchFile(this.__file, hitch(this, "__checkFile"));- 1
fs.stat(this.__file, hitch(this, function (err, stat) {- 1
this.__checkFile(stat);}));}},__checkFile:function (stats) {- 5
var ret = new Promise();- 5
if (!this.__inRollover) {- 3
if (stats.size >= this.maxSize) {- 2
if (this.maxBackupIndex > 0) {- 1
this.__inRollover = true;- 1
this.__onExit().chain(hitch(this, "__rollover")).then(hitch(this, function () {- 1
var ws = fs.createWriteStream(this.__file, { flags:"w", encoding:this.__encoding});- 1
ws.on("open", hitch(this, function () {- 1
this.__writeStream = ws;- 1
this.__inRollover = false;- 1
this.__checkQueue();- 1
ret.callback();}));}), hitch(ret, "errback", new Error("comb.logging.appenders.RollingFileAppender : error rolling over files")));} else {- 1
this.__writeStream = fs.createWriteStream(this.__file, { flags:"w", encoding:this.__encoding});- 1
ret.callback();}} else {- 1
ret.callback();}} else {- 2
ret.callback();}- 5
return ret.promise();},append:function (event) {- 12
if (this._canAppend(event)) {- 12
!this.__watching && this.__startCheck();- 12
var ws = this.__writeStream;- 12
if (!this.__inRollover && ws && ws.writable) {- 9
this._super(arguments);} else {- 3
this.__queue.push(event);}}},__checkQueue:function () {- 1
this.__queue.forEach(this.append, this);- 1
this.__queue.length = 0;},__rollover:function () {- 1
var ret = new Promise(), file = this.__file;- 1
var dir = path.dirname(file), baseName = new RegExp("(" + escape(path.basename(path.basename(file))) + ")(?:\\.(\\d*))*");- 1
fs.readdir(dir, hitch(this, function (err, files) {- 1
files = files.filter(function (f) {- 5
var match = f.match(baseName);- 5
if (match) {- 4
return true;} else {- 1
return false;}});- 1
files = files.sort(function (a, b) {- 6
var ret = 0;- 6
if (a > b) {- 3
ret = 0;- 3
} else if (a < b) {- 3
ret = 1;}- 6
return ret;});- 1
var count = files.length, i = 0;- 1
var checkFile = hitch(this, function () {- 5
if (count > 0) {- 4
var f = dir + "/" + files[i++];- 4
if (count > this.maxBackupIndex) {//drop the file;- 1
count--;- 1
fs.unlink(f, function (err) {- 1
err ? ret.errback(err) : checkFile();});} else {//rename the file- 3
var rn = this.__file + "." + count--;- 3
fs.rename(f, rn, function (err) {- 3
err ? ret.errback(err) : checkFile();});}} else {- 1
ret.callback();}});- 1
checkFile();}));- 1
return ret.promise();},getters:{maxSize:function () {- 3
return this.__maxSize;}},setters:{maxSize:function (size) {- 3
this.__maxSize = size ? convertToBytes(size) : DEFAULT_SIZE;}}}}).registerType("RollingFileAppender").as(module);
|
logging/config.js
|
Coverage100.00
SLOC213
LOC50
Missed0
|
- 1
var define = require("../define.js").define, base = require("../base"), fs = require('fs'), Appender = require("./appenders/appender.js");- 1
var logging, Logger, Level, appenders;- 1
var checkProcessUncaughtException = (function () {- 1
var isProcessUnCaaughtEception = false;- 1
return function _checkProcessUncaughtException() {//if (!isProcessUnCaaughtEception) {- 10
var rootLogger = Logger.getRootLogger();- 10
if (!isProcessUnCaaughtEception) {- 1
process.on("uncaughtException", function (err) {- 2
if (rootLogger.appenders.length) {- 1
rootLogger.error(err);} else {- 1
console.error(err.stack);}});- 1
isProcessUnCaaughtEception = true;}//}};})();- 1
var parseProperties = function (properties) {- 4
for (var i in properties) {- 4
var logger = Logger.getLogger(i);- 4
var props = properties[i], level = props.level, appenderArr = props.appenders;- 4
if (level) {- 4
level = Level.toLevel(level);- 4
if (level) {- 4
logger.level = level;}}- 4
if (appenderArr && base.isArray(appenderArr)) {- 4
for (var j = appenderArr.length - 1; j >= 0; j--) {- 14
var appenderProps = base.merge({}, appenderArr[j]), type = appenderProps.type;- 14
appenderProps.type = null;- 14
if (type) {- 12
logger.addAppender(type, appenderProps);}}}}- 4
checkProcessUncaughtException();};/*** @class default configurator for logging** @name BasicConfigurator* @memberOf comb.logging* @ignoreCode**/- 1
var BasicConfigurator = (exports.BasicConfigurator = define(null, {instance:{/**@lends comb.logging.BasicConfigurator.prototype*/constructor:function () {- 6
if (!Logger) {- 1
logging = require("./index").logging;- 1
Logger = logging.Logger;- 1
Level = logging.Level;- 1
appenders = logging.appenders;}},/*** Configure logging.** @param {comb.logging.Appender} [appender=null] appender to add to the root logger, by default a console logger is added.*/configure:function (appender) {- 6
var rootLogger = Logger.getRootLogger();- 6
rootLogger.removeAllAppenders();- 6
if (base.isInstanceOf(appender, appenders.Appender)) {- 2
rootLogger.addAppender(appender);} else {- 4
rootLogger.addAppender(new appenders.ConsoleAppender());}- 6
checkProcessUncaughtException();}}}));/*** @class Configures comb.Logger with the properties or properties contained within a file** @example** var propertyConfigurator = new comb.logging.PropertyConfigurator();** propertyConfigurator.configure("/location/of/combLogger.json");** //or** var config = {* "my.logger" : {* level : "INFO",* appenders : [* {* //default file appender* type : "FileAppender",* file : "/var/log/myApp.log",* },* {* //default JSON appender* type : "JSONAppender",* file : "/var/log/myApp.JSON",* },* {* type : "FileAppender",* //override default patter* pattern : "{[EEEE, MMMM dd, yyyy h:m a]timeStamp} {[5]level}"* + " {[- 5]levelName} {[-20]name} : {message}",* //location of my log file* file : "/var/log/myApp-errors.log",* //override name so it will get added to the log* name : "errorFileAppender",* //overwrite each time* overwrite : true,* //explicity set the appender to only accept errors* level : "ERROR"* },* {* type : "JSONAppender",* file : "/var/log/myApp-error.json",* //explicity set the appender to only accept errors* level : "ERROR"* }* ]* }* //repeat for more loggers** propertyConfigurator.configure(config);* }** @name PropertyConfigurator* @augments comb.logging.BasicConfigurator* @memberOf comb.logging* @ignoreCode**/- 1
exports.PropertyConfigurator = define(BasicConfigurator, {instance:{/**@lends comb.logging.PropertyConfigurator.prototype*//*** Call to configure logging** @example** //Example configuration* {* "my.logger" : {* level : "INFO",* appenders : [* {* //default file appender* type : "FileAppender",* file : "/var/log/myApp.log",* },* {* //default JSON appender* type : "JSONAppender",* file : "/var/log/myApp.JSON",* },* {* type : "FileAppender",* //override default patter* pattern : "{[EEEE, MMMM dd, yyyy h:m a]timeStamp} {[5]level}"* + " {[- 5]levelName} {[-20]name} : {message}",* //location of my log file* file : "/var/log/myApp-errors.log",* //override name so it will get added to the log* name : "errorFileAppender",* //overwrite each time* overwrite : true,* //explicity set the appender to only accept errors* level : "ERROR"* },* {* type : "JSONAppender",* file : "/var/log/myApp-error.json",* //explicity set the appender to only accept errors* level : "ERROR"* }* ]* }** @param {Object|String} properties Object containing configuration or string containing a file name with the configuration.*/configure:function (properties) {- 6
var rootLogger = Logger.getRootLogger();- 6
rootLogger.removeAllAppenders();- 6
if (base.isHash(properties)) {- 2
parseProperties(base.deepMerge({}, properties));} else {- 4
fs.readFile(properties, function (err, res) {- 4
if (err) {- 1
throw err;} else {- 3
try {- 3
parseProperties(JSON.parse(res));} catch (e) {- 1
throw e;}}});}}}});
|
logging/index.js
|
Coverage100.00
SLOC662
LOC162
Missed0
|
- 1
var define = require("../define.js"),base = require("../base"),isString = base.isString,merge = base.merge,isUndefinedOrNull = base.isUndefinedOrNull,isHash = base.isHash,isInstanceOf = base.isInstanceOf,argsToArray = base.argsToArray,format = base.string.format,Level = require("./level"),appenders = require("./appenders"),Appender = appenders.Appender,configurators = require("./config");- 1
var rootTree;- 1
var LoggerTree = define.define(null, {instance:{constructor:function (root) {- 14
this.__root = root;- 14
this.__name = root.name;- 14
this.__level = root.level;- 14
this.__parent = root._parent;- 14
this.__map = {};},__getSubLoggers:function () {- 6
var map = this.__map, ret = [], n;- 6
for (var i in map) {- 2
n = map[i];- 2
if (n) {- 2
ret = ret.concat(n.tree.getCurrentLoggers());}}- 6
return ret;},__getLoggers:function () {- 4
return [this.__root].concat(this.__getSubLoggers())},getCurrentLoggers:function () {- 4
return this.__getLoggers();},getSubLoggers:function () {- 2
return this.__getSubLoggers();},getLogger:function (name) {- 31
var ret;- 31
if (name) {- 29
var parts = name.split(".");- 29
if (parts.length) {- 29
var category = parts.shift();- 29
var lNode = this.__map[category];- 29
if (!lNode) {- 13
lNode = this.__map[category] = new Logger(category, this);- 13
lNode.addAppenders(this.__root.appenders);}- 29
ret = lNode;- 29
if (parts.length) {//keep searching- 10
name = parts.join(".");- 10
ret = lNode.tree.getLogger(name);}}} else {- 2
ret = this.__root;}- 31
return ret;},getRootLogger:function () {- 23
return this.__root;},isDisabled:function (level) {},resetConfiguration:function () {},/*** level = string|Level*/addAppender:function (appender) {- 85
var map = this.__map;- 85
for (var i in map) {- 61
map[i].addAppender(appender);}},removeAppender:function (name) {- 68
var map = this.__map;- 68
for (var i in map) {- 59
map[i].removeAppender(name);}},setters:{level:function (level) {- 45
this.__level = level;- 45
if (level && level instanceof Level) {- 45
var map = this.__map;- 45
for (var i in map) {- 2
map[i].level = level;}}}},getters:{categories:function () {- 2
return this.getCurrentLoggers().map(function (l) {- 3
return l.fullName;});},name:function () {- 35
var ret = this.__name;- 35
if (this.__parent) {- 21
var pName = this.__parent.name;- 21
if (pName) {- 8
ret = pName + "." + ret;}}- 35
return ret;},level:function () {- 13
return this.__level;},additive:function () {- 13
return this.__root.additive;}}}});- 1
var comb = exports;/*** @ignore* @namespace logging package*/- 1
comb.logging = merge({Level:Level}, configurators);/*** @ignore* @namespace appenders for logging*/- 1
comb.logging.appenders = appenders;- 1
var logging = comb.logging;/*** @class This class is the entry point for all logging actions in comb.* <p><b>Logger should be retrieved by calling Logger.getLogger() NOT through the new keyword</b><p>* <p>* All loggers in comb follow a heirarchy of inheritance based on a dot notation.* <pre class="code">* rootLogger - ""* / \* "my" "myOther"* / \* "my.logger" "myOther.logger"* / \* "my.logger.Log" "myOther.logger.Log"** </pre>* In the above Tree the rootLogger is the base for all logger. my and myOther inherit from rootLogger* my.logger inherits from my, and myOther.logger inherits from myOther. The logs do not have to be retrieved in* order. If I set rootLogger to ERROR level and added a console appender to it the appender and level will be* added to all logs. However if I set my to INFO level and add a fileAppender to it the level and appender will* only be added to logs in "my" subtree. If you set my.logger to not be additive then levels, and appenders will not* propogate down to the rest of the tree.** </p>** <p>For information on levels see {@link comb.logging.Level}.</p>* <p>For information on appenders see* <ul>* <li>{@link comb.logging.appenders.Appender}</li>* <li>{@link comb.logging.appenders.ConsoleAppender}</li>* <li>{@link comb.logging.appenders.FileAppender}</li>* <li>{@link comb.logging.appenders.JSONAppender}</li>* <li>{@link comb.logging.appenders.RollingFileAppender}</li>* </ul>* </p>* <p>For information on configurators see {@link comb.logging.BasicConfigurator} or {@link comb.logging.PropertyConfigurator}.</p>** @example** var logger = comb.logger;** //configure you logging environement* logger.configure();** //add a file appender to all loggers* logger.configure(logger.appender("FileAppender", {file : "/var/log/myLog.log"});** //Retreiving a logger.* var combLogger = logger("comb");* var combCollectionLogger = logger("comb.collections");* var treeLogger = logger("comb.collections.Tree")* //add a JSON appender to tree logger just for fun!* .addAppender("JSONAppender", {file : "/var/log/myTreeLogger.json"})** //set my treeLogger to DEBUG Level* treeLogger.level = "DEBUG";*** @name Logger* @memberOf comb.logging** @property {Array<comb.logging.Logger>} subLoggers all loggers this logger is the parent of.* @property {comb.logging.Level} level the level of this Logger* @property {Boolean} additive set to false to prevent changes to this logger from propogating down.* @property {Boolean} isDebug true if this Loggers level is DEBUG* @property {Boolean} isTrace true if this Loggers level is TRACE* @property {Boolean} isInfo true if this Loggers level is INFO* @property {Boolean} isWarn true if this Loggers level is WARN* @property {Boolean} isError true if this Loggers level is ERROR* @property {Boolean} isFatal true if this Loggers level is FATAL* @property {Boolean} isOff true if this Loggers level is OFF* @property {String} name the name of this logger this <b>does not</b> include the dot notated name* @property {String} fullName the full path name of this Logger.* @property {comb.logging.appenders.Appender} appenders list of appenders this logger currently contains.* @ignoreCode*/- 1
var Logger = (logging.Logger = define.define(null, {instance:{/**@lends comb.logging.Logger.prototype*/constructor:function (name, parent) {- 14
this.__additive = true;- 14
this.__name = name;- 14
this._parent = parent;- 14
this._tree = new LoggerTree(this);- 14
this.fullName = this._tree.name;- 14
if (!parent || !parent.additive) {- 1
this.level = Level.ALL;} else {- 13
this.level = parent.level;}- 14
this.__appenders = {};},/*** Log an info level message** @param {String} message the message to log.** @return {comb.logging.Logger} for chaining.*/info:function (message) {- 17
return this.log.apply(this, [Level.INFO].concat(argsToArray(arguments)));},/*** Log an debug level message** @param {String} message the message to log.** @return {comb.logging.Logger} for chaining.*/debug:function (message) {- 14
return this.log.apply(this, [Level.DEBUG].concat(argsToArray(arguments)));},/*** Log an error level message** @param {String} message the message to log.** @return {comb.logging.Logger} for chaining.*/error:function (message) {- 15
return this.log.apply(this, [Level.ERROR].concat(argsToArray(arguments)));},/*** Log an warn level message** @param {String} message the message to log.** @return {comb.logging.Logger} for chaining.*/warn:function (message) {- 14
return this.log.apply(this, [Level.WARN].concat(argsToArray(arguments)));},/*** Log an trace level message** @param {String} message the message to log.** @return {comb.logging.Logger} for chaining.*/trace:function (message) {- 14
return this.log.apply(this, [Level.TRACE].concat(argsToArray(arguments)));},/*** Log an fatal level message** @param {String} message the message to log.** @return {comb.logging.Logger} for chaining.*/fatal:function (message) {- 14
return this.log.apply(this, [Level.FATAL].concat(argsToArray(arguments)));},/*** Log a message** @param {comb.logging.Level} level the level the message is* @param {String} message the message to log.** @return {comb.logging.Logger} for chaining.*/log:function (level, message) {- 94
var args = argsToArray(arguments, 1);- 94
level = Level.toLevel(level);- 94
if (args.length > 1) {- 18
message = format.apply(null, args);}- 94
if (level.isGreaterOrEqualToo(this.level)) {- 64
if (Level.TRACE.equals(level)) {- 10
var err = new Error;- 10
err.name = "Trace";- 10
err.message = message || '';- 10
Error.captureStackTrace(err, arguments.callee);- 10
message = err.stack;- 54
} else if (Level.ERROR.equals(level) && isInstanceOf(message, Error)) {- 1
message = message.stack;}- 64
var type = level.name.toLowerCase(), appenders = this.__appenders;- 64
var event = {level:level,levelName:level.name,message:message,timeStamp:new Date(),name:this.fullName};- 64
Object.keys(appenders).forEach(function (i) {- 64
appenders[i].append(event);});}- 94
return this;},/*** Add an appender to this logger. If this is additive then the appender is added to all subloggers.** @example* comb.logger("my.logger")* .addAppender("ConsoleAppender")* .addAppender("FileAppender", {file:'/var/log/my.log'})* .addAppender("RollingFileAppender", {file:'/var/log/myRolling.log'})* .addAppender("JSONAppender", {file:'/var/log/myJson.log'});** @param {comb.logging.Appender|String} If the appender is an {@link comb.logging.appenders.Appender} then it is added.* If the appender is a string then {@link comb.logging.appenders.Appender.createAppender} will be called to create it.** @param {Object} [opts = null] If the first argument is a string then the opts will be used as constructor arguments for* creating the appender.** @return {comb.logging.Logger} for chaining.*/addAppender:function (appender, opts) {- 104
var args = argsToArray(arguments);- 104
if (isString(appender)) {- 12
this.addAppender(Appender.createAppender(appender, opts));} else {- 92
if (!isUndefinedOrNull(appender)) {- 92
var name = appender.name;- 92
if (!(name in this.__appenders)) {- 85
this.__appenders[name] = appender;- 85
if (!appender.level) {- 17
appender.level = this.level;}- 85
this._tree.addAppender(appender);}}}- 104
return this;},/*** Short cut to add a list of appenders to this Logger* @param {Array<comb.logging.Appender>} appenders** @return {comb.logging.Logger} for chaining.*/addAppenders:function (appenders) {- 14
appenders.forEach(this.addAppender.bind(this));- 14
return this;},/*** Removes and appender from this logger.* @param {String} name the name of the appender* @return {comb.logging.Logger} for chaining.*/removeAppender:function (name) {- 68
if (name in this.__appenders) {- 68
delete this.__appenders[name];- 68
this._tree.removeAppender(name);}- 68
return this;},/*** Removes a list of appenders from this logger.** @param {String[]} appenders a list of names of appenders to remove* @return {comb.logging.Logger} for chaining.*/removeAppenders:function (appenders) {- 1
appenders.forEach(this.removeAppender, this);- 1
return this;},/*** Removes all appenders from this logger and sub loggers if this Logger is additive.** @return {comb.logging.Logger} for chaining.*/removeAllAppenders:function () {- 16
Object.keys(this.__appenders).forEach(this.removeAppender.bind(this));- 16
return this;},/*** Determines if an appender is attached.** @param {String} name the name of the appender.*/isAppenderAttached:function (name) {- 38
return (name in this.__appenders);},/*** Gets an appender from this logger** @param {String} name the name of the appender.** @return {comb.logging.Appender|undefined} returns the appender with the specified name or* undefined if it is not found.*/getAppender:function (name) {- 8
var ret;- 8
if (name in this.__appenders) {- 8
ret = this.__appenders[name];}- 8
return ret;},/*** @ignore* */setters:{level:function (level) {- 46
level = Level.toLevel(level);- 46
if (this.__additive) {- 45
this.__level = level;- 45
var appenders = this.__appenders;- 45
for (var i in appenders) {- 35
appenders[i].level = level;}- 45
this._tree.level = level;} else {- 1
this.__level = level;}},additive:function (additive) {- 2
this.__additive = additive;}},/**@ignore*/getters:{/**@ignore*//**@ignore*/subLoggers:function () {- 2
return this._tree.getSubLoggers();},/**@ignore*/level:function () {- 202
return this.__level;},/**@ignore*/additive:function () {- 15
return this.__additive;},isAll:function () {- 8
return Level.ALL.isGreaterOrEqualToo(this.level);},/**@ignore*/isDebug:function () {- 8
return Level.DEBUG.isGreaterOrEqualToo(this.level);},/**@ignore*/isTrace:function () {- 8
return Level.TRACE.isGreaterOrEqualToo(this.level);},/**@ignore*/isInfo:function () {- 8
return Level.INFO.isGreaterOrEqualToo(this.level);},/**@ignore*/isWarn:function () {- 8
return Level.WARN.isGreaterOrEqualToo(this.level);},/**@ignore*/isError:function () {- 8
return Level.ERROR.isGreaterOrEqualToo(this.level);},/**@ignore*/isFatal:function () {- 8
return Level.FATAL.isGreaterOrEqualToo(this.level);},/**@ignore*/isOff:function () {- 9
return Level.OFF.equals(this.level);},/**@ignore*/name:function () {- 14
return this.__name;},/**@ignore*/tree:function () {- 13
return this._tree;},/**@ignore*/appenders:function () {- 20
var ret = [];- 20
for (var i in this.__appenders) {- 9
ret.push(this.__appenders[i]);}- 20
return ret;},categories:function () {- 2
return this._tree.categories;}}},static:{/**@lends comb.logging.Logger*//*** Return the root of all loggers*/getRootLogger:function () {- 23
return rootTree.getRootLogger();},/*** Retrieves/Creates a logger based on the name passed in** @param {String} name the name of the logger*/getLogger:function (name) {- 21
return rootTree.getLogger(name);}}}));/**** @function* @description Alias to {@link comb.logging.Logger.getLogger}. See {@link comb.logging.Logger} for more information.** @example** comb.logger("my.logger");** @memberOf comb* @namespace*/- 1
exports.logger = Logger.getLogger.bind(Logger);/*** @function* @description Shortcut to configure loggers.** @example** //same as new comb.logging.BasicConfigurator().configure();* comb.logger.configure();** //new comb.logging.PropertyConfigurator().configure("/location/to/logger/configuration.json");* comb.logger.configure("/location/to/logger/configuration.json");** @memberOf comb.logger*/- 1
exports.logger.configure = function configure() {- 4
var args = argsToArray(arguments), configurator;- 4
if (!args.length) {- 1
configurator = new configurators.BasicConfigurator();} else {- 3
var first = args[0];- 3
if (isHash(first) || isString(first)) {- 2
configurator = new configurators.PropertyConfigurator();} else {- 1
configurator = new configurators.BasicConfigurator();}}- 4
configurator.configure.apply(configurator, args);- 4
return this;};/*** @function* @description Factory method for creating appenders. See {@link comb.logging.appenders.Appender.createAppender} for* arguments.** @example** var appender = comb.logger.appender("ConsoleAppender");* comb.logger("my.logger").addAppender(appender);** @memberOf comb.logger**/- 1
exports.logger.appender = Appender.createAppender.bind(Appender);- 1
var rootLogger = new Logger("");- 1
rootTree = rootLogger._tree;/*** The root for all loggers.* @memberOf comb.logger* @type comb.logging.Logger*/- 1
exports.logger.rootLogger = rootLogger;
|
logging/level.js
|
Coverage100.00
SLOC188
LOC33
Missed0
|
- 1
var define = require("../define.js").define, base = require("../base");- 1
var LEVELS = {ALL:-100000,DEBUG:1,TRACE:2,INFO:3,WARN:4,ERROR:5,FATAL:6,OFF:100000};- 1
var LEVELS_REVERSE = {"-100000":"ALL","1":"DEBUG","2":"TRACE","3":"INFO","4":"WARN","5":"ERROR","6":"FATAL","100000":"OFF"};/*** @class Level class used to describe logging levels. The levels determine what types of events are logged to the appenders* for example the if Level.ALL is used then all event will be logged, however if Level.INFO was used then <b>ONLY</b>* INFO, WARN, ERROR, and FATAL events will be logged. To turn off logging for a logger use Level.OFF.** <p><b>Not typically instantiated directly, but through staticly defined levels</b></p>* @example* //Levels in ascending order* comb.logging.Level.ALL* comb.logging.Level.DEBUG* comb.logging.Level.TRACE* comb.logging.Level.INFO* comb.logging.Level.WARN* comb.logging.Level.ERROR* comb.logging.Level.FATAL* comb.logging.Level.OFF** //or* Level.getLevel("INFO");** @name Level* @memberOf comb.logging** @property {Number} level the numerical representation of this level.* @property {String} name the name of level.* @ignoreCode*/- 1
var Level = (exports = module.exports = define(null, {instance:{/**@lends comb.logging.Level.prototype*/constructor:function (level, name) {- 9
this.level = level;- 9
this.name = name;},/*** Determing if this level is >= another level* @param {comb.logging.Level} level the level to test against** @returns {Boolean} true if this is >= false otherwise.*/isGreaterOrEqualToo:function (level) {- 290
var ret = false;- 290
if (level && base.isNumber(level.level)) {- 290
if (this.level >= level.level) {- 189
ret = true;}}- 290
return ret;},/*** Determing if this level is equal to another level based off of the numerical rank.** @param {comb.logging.Level} level the level to compare** @returns {Boolean} true if this is equal to that false otherwise.*/equals:function (level) {- 148
return level.level == this.level;}},static:{/**@lends comb.logging.Level*//*** Converts a numerical or string representation of a level, if a default level is provided,* then if a level cannot be determined then the default level is used.** @param {Number|String|comb.logging.Level} level the level to try to convert* @param {comb.logging.Level} [defaultLevel] default level to use if one cannot be determined,** @returns {comb.logging.Level|null} returns a level if one can be determined null otherwise.*/toLevel:function (level, defaultLevel) {- 194
var ret = null;- 194
var args = base.argsToArray(arguments);- 194
if (args.length === 1) {- 192
var level = args[0];- 192
if (base.isNumber(level)) {- 11
var strLevel = LEVELS_REVERSE[level];- 11
ret = Level[strLevel];- 181
} else if (base.isString(level)) {- 48
ret = Level[level.toUpperCase()];} else {- 133
ret = level;}} else {- 2
ret = (Level.toLevel(args[0]) || args[1]);}- 194
return ret;},/*** Adds a new level to the Level object.** @example** logger = Logger.getLogger("my.logger");** //create the custom level* Level.addLevel("custom_Level", 20);** //now set the level on a logger* logger.level = Level.CUSTOM_LEVEL;** @param {string} label the label of the level, <b>Note:</b> the label will be coverted to uppercase.* @param {number} level the level of the level** @return {undefined|comb.logging.Level} the level that was created.**/addLevel:function (label, level) {- 1
var ret;- 1
if (base.isString(label) && base.isNumber(level)) {- 1
label = label.toUpperCase();- 1
LEVELS_REVERSE[level] = label;- 1
LEVELS[label] = level;- 1
ret = (this[label] = new Level(level, label));}- 1
return ret;},/*** Level to allow logging of all events.*/ALL:null,/*** Logs only events debug or greater.*/DEBUG:null,/*** Like debug but provides a finer level of detail*/TRACE:null,/*** Only info, or error related events*/INFO:null,/*** Only warn or error related events*/WARN:null,/*** Error or fatal events*/ERROR:null,/*** Only fatal events*/FATAL:null,/*** No events will be logged.*/OFF:null}}));- 1
for (var i in LEVELS_REVERSE) {- 8
Level[LEVELS_REVERSE[i]] = new Level(parseInt(i, 10), LEVELS_REVERSE[i]);}
|
plugins/Broadcaster.js
|
Coverage100.00
SLOC113
LOC26
Missed0
|
- 1
var func = require("../base/functions"),define = require("../define").define;- 1
var Broadcaster = define(null, {instance : {/** @lends comb.plugins.Broadcaster.prototype *//*** Plugin to allow a class to easily broadcast events** @example** var Mammal = define(comb.plugins.Broadcaster, {* instance : {** constructor: function(options) {* options = options || {};* this._super(arguments);* this._type = options.type || "mammal";* },** speak : function() {* var str = "A mammal of type " + this._type + " sounds like";* this.broadcast("speak", str);* this.onSpeak(str);* return str;* },** onSpeak : function(){}* }* });*** var m = new Mammal({color : "gold"});* m.listen("speak", function(str){* //called back from the broadcast event* console.log(str);* });* m.speak();** @constructs*/constructor : function() {- 2
this.__listeners = {};},/*** Broadcasts an event from an object** @param name the name of the event to broadcast* @param {Object|String|Function|Date|Number} [args] variable number of arguments to pass to listeners, can be anything*/broadcast : function(topic, args) {- 2
var args = Array.prototype.slice.call(arguments, 0), topic = args.shift();- 2
if (topic && topic in this.__listeners) {- 2
var list = this.__listeners[topic], i = list.length - 1;- 2
while (i >= 0) {- 2
list[i--].cb.apply(this, args);}}},/*** Listens to a broadcasted event* Simimlar to {@link comb.listen}** @param {String} topic the topic to listen to* @param {Function} callback the function to callback on event publish** @returns {Array} handle to disconnect a topic*/listen : function(topic, callback) {- 3
if (!func.isFunction(callback)) throw new Error("callback must be a function");- 3
var handle = {topic : topic,cb : callback};- 3
var list = this.__listeners[topic];- 3
if (!list) {- 2
list = (this.__listeners[topic] = [handle]);- 2
handle.pos = 0;} else {- 1
handle.pos = list.push(handle);}- 3
return handle;},/*** Disconnects a listener* Similar to {@link comb.unListen}** @param handle disconnect a handle returned from Broadcaster.listen*/unListen : function(handle) {- 1
if (handle) {- 1
var topic = handle.topic;- 1
if (topic in this.__listeners) {- 1
var listeners = this.__listeners, list = listeners[topic];- 1
if (list) {- 1
for (var i = list.length - 1; i >= 0; i--) {- 1
if (list[i] == handle) {- 1
list.splice(i, 1);- 1
break;}}}}}}}});- 1
exports = module.exports = Broadcaster;
|
plugins/Middleware.js
|
Coverage100.00
SLOC212
LOC40
Missed0
|
- 1
var func = require("../base/functions"),obj = require("../base/object"),Promise = require("../promise").Promise,define = require("../define").define;- 1
var Middleware = define(null, {instance:{/** @lends comb.plugins.Middleware.prototype */__hooks:{pre:{}, post:{}},/*** @class Plugin to enable middleware on a class** @example** var Mammal = define(comb.plugins.Middleware, {* instance : {** constructor: function(options) {* options = options || {};* this.super(arguments);* this._type = options.type || "mammal";* },** speak : function() {* var ret = new comb.Promise();* this._hook("pre", "speak")* .then(comb.hitch(this, "_hook", "post", "speak"), hitch(ret, "errback"))* .then(comb.hitch(ret, "callback"), comb.hitch(ret, "errback"));* return ret;* }* }*});** Mammal.pre('speak', function(next){* //do something meaningful* next();* });* var m = new Mammal({color : "gold"});* m.speak();** @constructs*/constructor:function () {- 6
this.__hooks = obj.merge({}, this.__hooks);- 6
this._super(arguments);},/*** <p>Protected!</p>** <p>Call to initiate middleware for the topic</p>* <p><b>NOTE:</b> this function takes a variable number of arguments* whatever comes after the op param will be passed into* the listening function, with the last argument to the listenting* function being the next function</p>*** @public* @param {"pre"|"post"} state the state in which the hook should be called* @param {String} op the operation that is being acted upong* @param args arguments to be passed into the listening functions.* @returns {comb.Promise} a promise to use after middleware chain completes**/_hook:function (state, op, args) {- 11
args = args || [];- 11
var promise = new Promise();- 11
var funcs, length;- 11
if (this.__hooks[state] && (funcs = this.__hooks[state][op]) != null && (length = funcs.length) > 0) {- 7
var count = 0;- 7
var next = func.hitch(this, function (err) {- 15
if (err) {- 1
promise.errback(err);} else {- 14
process.nextTick(func.hitch(this, function () {//if Ive looped through all of them callback- 14
if (count == length) {- 6
promise.callback();} else {//call next- 8
var nextArgs = args.slice(0);- 8
nextArgs.unshift(next);- 8
funcs[count++].apply(this, nextArgs);}}));}});- 7
next();} else {- 4
promise.callback();}- 11
return promise.promise();},/*** Use to listen to before an event occurred i.e. pre save** <b>NOTE:</b></br>* <ul>* <li>You must call next in order for the middleware chain to complete</li>* <li>This connects to events on the instance of an object, not all instances!</li>* <li>Hooks are called in the order they are received!</li>* <li> When connecting your callback will be called in the scope of the class</br>if you want a certain scope use {@link comb.hitch}</li>* </ul>** @example* instance.pre("save", function(args,...., next){* //do something...* //you have to call next!!!!!* next();* });** */pre:function (fun, callback) {- 1
var hook = this.__hooks.pre[fun];- 1
if (!hook) {- 1
hook = this.__hooks.pre[fun] = [];}- 1
hook.push(callback);},/*** <p>Use to listen to after an event has occurred i.e. post save</p>* <b>NOTE:</b></br>* <ul>* <li>You must call next in order for the middleware chain to complete</li>* <li>This connects to events on the instance of an object, NOT all instances!</li>* <li>Hooks are called in the order they are received!</li>* <li>When connecting your callback will be called in the scope of the class</br>if you want a certain scope use {@link comb.hitch}</li>* </ul>* @example** instance.post("save", function(next){* //do something...* //you have to call next!!!!!* next();* });* */post:function (fun, callback) {- 1
var hook = this.__hooks.post[fun];//if I havent initialized it create it;- 1
if (hook == undefined) {- 1
hook = this.__hooks.post[fun] = [];}- 1
hook.push(callback);}},static:{/** @lends comb.plugins.Middleware *//***<p> Use to listen to after an event has occurred i.e. post save</p>** <b>NOTE:</b></br>* <ul>* <li>You must call next in order for the middleware chain to complete</li>* <li>This connects to events on ALL instances of an object</li>* <li>Hooks are called in the order they are received!</li>* <li>When connecting your callback will be called in the scope of the class</br>if you want a certain scope use {@link comb.hitch}</li>* </ul>** @example* Class.pre("save", function(next){* ...* //you must call next* });* */pre:function (name, cb) {- 2
var hooks = this.prototype.__hooks;- 2
var hook = hooks.pre[name];- 2
if (!hook) {- 1
hook = hooks.pre[name] = [];}- 2
hook.push(cb);},/***<p>Use to listen to after an event has occurred i.e. post save</p>**<b>NOTE:</b></br>* <ul>* <li>You must call next in order for the middleware chain to complete</li>* <li>This connects to events on ALL instances of an object</li>* <li>Hooks are called in the order they are received!</li>* <li>When connecting your callback will be called in the scope of the class</br>if you want a certain scope use {@link comb.hitch}</li>* </ul>** @example* Class.post("save", function(next){* ...* //you must call next* });* */post:function (name, cb) {- 1
var hooks = this.prototype.__hooks;- 1
var hook = hooks.post[name];- 1
if (!hook) {- 1
hook = hooks.post[name] = [];}- 1
hook.push(cb);}}});- 1
module.exports = exports = Middleware;
|
plugins/index.js
|
Coverage100.00
SLOC6
LOC2
Missed0
|
- 1
var comb = exports;/**@namespace plugins for classes using {@link comb.define}*/- 1
comb.plugins = {Broadcaster : require("./Broadcaster"),Middleware : require("./Middleware")};
|
promise.js
|
Coverage100.00
SLOC736
LOC192
Missed0
|
- 1
var hitch = require("./base/functions").hitch,define = require("./define").define,base = require("./base"),argsToArray = base.argsToArray,isUndefinedOrNull = base.isUndefinedOrNull,isArray = base.isArray,isFunction = base.isFunction,isInstanceOf = base.isInstanceOf;- 1
var Promise = define(null, {instance:{/** @lends comb.Promise.prototype */__fired:false,__results:null,__error:null,__errorCbs:null,__cbs:null,/*** Promise object used to provide seperation of success and error resolution paths for async operations.** @example* var myFunc = function(){* var promise = new Promise();* //callback the promise after 10 Secs* setTimeout(hitch(promise, "callback"), 10000);* return promise.promise();* }* var myFunc2 = function(){* var promises =[];* for(var i = 0; i < 10; i++){* promises.push(myFunc);* }* //create a new promise list with all 10 promises* return new PromiseList(promises).promise();* }** myFunc.then(function(success){}, function(error){})* //chain promise operations* myFunc.chain(myfunc).then(function(success){}, function(error){})** myFunc2.then(function(success){}, function(error){})* //chain promise operations* myFunc2.chain(myfunc).then(function(success){}, function(error){})* @constructs*/constructor:function () {- 246
this.__errorCbs = [];- 246
this.__cbs = [];},/*** @private*/__resolve:function () {- 216
if (!this.__fired) {- 216
this.__fired = true;- 216
var cbs = this.__error ? this.__errorCbs : this.__cbs,len = cbs.length, i,results = this.__error || this.__results;- 216
for (i = 0; i < len; i++) {- 127
this.__callNextTick(cbs[i], results);}}},__callNextTick:function (cb, results) {- 127
process.nextTick(hitch(this, function () {- 127
cb.apply(this, results);}));},/*** Add a callback to the callback chain of the promise*** @param {Function|comb.Promise} cb the function or promise to callback when the promise is resolved.** @return {comb.Promise} this promise for chaining*/addCallback:function (cb) {- 209
if (cb) {- 206
if (exports.isPromiseLike(cb)) {- 30
cb = hitch(cb, "callback");}- 206
if (this.__fired && this.__results) {- 72
cb.apply(this, this.__results);} else {- 134
this.__cbs.push(cb);}}- 209
return this;},/*** Add a callback to the errback chain of the promise** @param {Function|comb.Promise} cb the function or promise to callback when the promise errors** @return {comb.Promise} this promise for chaining*/addErrback:function (cb) {- 207
if (cb) {- 198
if (exports.isPromiseLike(cb)) {- 44
cb = hitch(cb, "errback");}- 198
if (this.__fired && this.__error) {- 9
cb.apply(this, this.__error);} else {- 189
this.__errorCbs.push(cb);}}- 207
return this;},/**** Adds a callback or promise to be resolved for both success* and error.** @param {Function|comb.Promise} cb callback or promise to be resolved for both success* and error.* @return {comb.Promise} this promise for chaining*/both:function (cb) {- 6
this.addCallback(cb);- 6
if (exports.isPromiseLike(cb)) {- 2
this.addErrback(hitch(cb, "callback"));} else {- 4
this.addErrback(cb);}- 6
return this;},/*** When called all functions registered as callbacks are called with the passed in results.** @param {*} args variable number of results to pass back to listeners of the promise*/callback:function (args) {- 180
args = argsToArray(arguments);- 180
if (this.__fired) {- 1
throw new Error("Already fired!");}- 179
this.__results = args;- 179
this.__resolve();- 179
return this.promise();},/*** When called all functions registered as errbacks are called with the passed in error(s)** @param {*} args number of errors to pass back to listeners of the promise*/errback:function (args) {- 38
if (this.__fired) {- 1
throw args || new Error("Already fired");}- 37
this.__error = argsToArray(arguments);- 37
this.__resolve();- 37
return this.promise();},/*** Resolved a promise using the node style callback.** @example** var promise = new Promise();* fs.readFile("file.txt", "utf8", promise.resolve.bind(promise));* promise.then(function(file){* console.log(file);* });** @param {Error} [err=null] If specified then the promise will error out* @param {...} [args] if err is null then the aruments will be used to resolve the promise.** @return {comb.Promise} for chaining.*/resolve:function (err, args) {- 2
if (err) {- 1
this.errback(err);} else {- 1
this.callback.apply(this, argsToArray(arguments, 1));}- 2
return this;},/*** Call to specify action to take after promise completes or errors** @param {Function} [callback=null] function to call after the promise completes successfully* @param {Function} [errback=null] function to call if the promise errors** @return {comb.Promise} this promise for chaining*/then:function (callback, errback) {- 128
if (exports.isPromiseLike(callback)) {- 28
this.addCallback(callback);- 28
this.addErrback(callback);} else {- 100
this.addCallback(callback);- 100
this.addErrback(errback);}- 128
return this;},/*** Call this function as a classic node callback where the first argument* will be an error, or null if no error occured. The other arugments will* be the result from the promise.** @example** promise.classic(function(err, res){* if(err){* console.log(err);* }else{* console.log(res);* }* });** @param cb callback where the first argument* will be an error, or null if no error occured. The other arugments will* be the result from the promise.* @return {comb.Promise} the promise to chain*/classic:function (cb) {- 3
if ("function" === typeof cb) {- 3
this.addErrback(function (err) {- 1
cb(err);});- 3
this.addCallback(function () {- 2
cb.apply(this, [null].concat(argsToArray(arguments)));});}- 3
return this;},/*** Call to chaining of promises** @example** var p = new Promise();** p* .chain(function(previousPromiseResults){* return previousPromiseResults + " world";* }, errorHandler)* .chain(function(previousPromiseResults){* return when(dbCall());* }).classic(function(err, results){* //all promises are done* });** p.callback("Hello");** @param callback method to call this one completes. If you return a promise the execution will delay until the returned promise has resolved.* @param [errback=null] method to call if this promise errors. If errback is not specified then the returned promises* errback method will be used.** @return {comb.Promise} A new that wraps the promise for chaining*/chain:function (callback, errback) {- 23
var promise = new Promise();- 23
this.addCallback(function (results) {- 20
when(isFunction(callback) ? callback.call(this, results) : callback).then(promise);});// If no errback passed, then invoke our promise's errback to pass// on to next link in the chain.- 23
this.addErrback(errback || promise);- 23
return promise.promise();},/*** Applies the same function that returns a promise to both the callback and errback.** @param {Function} callback function to call. This function must return a Promise** @return {comb.Promise} a promise to continue chaining or to resolve with.**/chainBoth:function (callback) {- 6
var promise = new Promise();- 6
this.addCallback(function (results) {- 4
when(isFunction(callback) ? callback.call(this, results) : callback).then(promise);});- 6
this.addErrback(function (results) {- 2
when(isFunction(callback) ? callback.call(this, results) : callback).then(promise);});- 6
return promise.promise();},/*** Creates an object to that contains methods to listen to resolution but not the "callback" or "errback" methods.** @example** var asyncMethod = function(){* var ret = new comb.Promise();* process.nextTick(ret.callback.bind(ret, "hello"));* return ret.promise();* }** asyncMethod().callback() //throws error** @return {Object} an object containing "chain", "chainBoth", "promise", "addCallback", "addErrback", "then", "both".*/promise:function () {- 436
var ret = {chain:this.chain.bind(this),chainBoth:this.chainBoth.bind(this),promise:function () {- 57
return ret;}};- 436
["addCallback", "addErrback", "then", "both", "classic"].forEach(function (action) {- 2180
ret[action] = function () {- 150
this[action].apply(this, arguments);- 150
return ret;}.bind(this);}, this);- 436
return ret;}}});- 1
var PromiseList = define(Promise, {instance:{/** @lends comb.PromiseList.prototype *//*@private*/__results:null,/*@private*/__errors:null,/*@private*/__promiseLength:0,/*@private*/__defLength:0,/*@private*/__firedLength:0,normalizeResults:false,/*** PromiseList object used for handling a list of Promises** @example* var myFunc = function(){* var promise = new Promise();* //callback the promise after 10 Secs* setTimeout(hitch(promise, "callback"), 10000);* return promise.promise();* }* var myFunc2 = function(){* var promises =[];* for(var i = 0; i < 10; i++){* promises.push(myFunc);* }* //create a new promise list with all 10 promises* return new PromiseList(promises).promise();* }** myFunc.then(function(success){}, function(error){})* //chain promise operations* myFunc.chain(myfunc).then(function(success){}, function(error){})** myFunc2.then(function(success){}, function(error){})* //chain promise operations* myFunc2.chain(myfunc).then(function(success){}, function(error){})** @param {comb.Promise[]} [defs=[]] the list of promises* @constructs* @augments comb.Promise* @memberOf comb* */constructor:function (defs, normalizeResults) {- 18
this.__errors = [];- 18
this.__results = [];- 18
this.normalizeResults = base.isBoolean(normalizeResults) ? normalizeResults : false;- 18
this._super(arguments);- 18
if (defs && defs.length) {- 16
this.__defLength = defs.length;- 16
defs.forEach(this.__addPromise, this);} else {- 2
this.__resolve();}},/*** Add a promise to our chain* @private* @param promise the promise to add to our chain* @param i the index of the promise in our chain*/__addPromise:function (promise, i) {- 42
promise.addCallback(hitch(this, function () {- 37
var args = argsToArray(arguments);- 37
args.unshift(i);- 37
this.callback.apply(this, args);}));- 42
promise.addErrback(hitch(this, function () {- 5
var args = argsToArray(arguments);- 5
args.unshift(i);- 5
this.errback.apply(this, args);}));},/*** Resolves the promise* @private*/__resolve:function () {- 18
if (!this.__fired) {- 18
this.__fired = true;- 18
var cbs = this.__errors.length ? this.__errorCbs : this.__cbs,len = cbs.length, i,results = this.__errors.length ? this.__errors : this.__results;- 18
for (i = 0; i < len; i++) {- 5
this.__callNextTick(cbs[i], results);}}},__callNextTick:function (cb, results) {- 5
process.nextTick(hitch(this, function () {- 5
cb.apply(this, [results]);}));},addCallback:function (cb) {- 16
if (cb) {- 16
if (exports.isPromiseLike(cb)) {- 1
cb = hitch(cb, "callback");}- 16
if (this.__fired && !this.__errors.length) {- 7
cb.call(this, this.__results);} else {- 9
this.__cbs.push(cb);}}- 16
return this;},addErrback:function (cb) {- 16
if (cb) {- 16
if (exports.isPromiseLike(cb)) {- 2
cb = hitch(cb, "errback");}- 16
if (this.__fired && this.__errors.length) {- 4
cb.call(this, this.__errors);} else {- 12
this.__errorCbs.push(cb);}}- 16
return this;},callback:function (i) {- 38
if (this.__fired) {- 1
throw new Error("Already fired!");}- 37
var args = argsToArray(arguments);- 37
if (this.normalizeResults) {- 20
args = args.slice(1);- 20
args = args.length == 1 ? args.pop() : args;}- 37
this.__results[i] = args;- 37
this.__firedLength++;- 37
if (this.__firedLength == this.__defLength) {- 11
this.__resolve();}- 37
return this.promise();},errback:function (i) {- 6
if (this.__fired) {- 1
throw new Error("Already fired!");}- 5
var args = argsToArray(arguments);- 5
if (this.normalizeResults) {- 4
args = args.slice(1);- 4
args = args.length == 1 ? args.pop() : args;}- 5
this.__errors[i] = args;- 5
this.__firedLength++;- 5
if (this.__firedLength == this.__defLength) {- 5
this.__resolve();}- 5
return this.promise();}}});- 1
exports.Promise = Promise;- 1
exports.PromiseList = PromiseList;- 1
function isPromiseLike(obj) {- 673
return !isUndefinedOrNull(obj) && (isInstanceOf(obj, Promise) || (isFunction(obj.then)&& isFunction(obj.addCallback) && isFunction(obj.addErrback)));}- 1
base.merge(exports, {/*** @lends comb*//*** Tests if an object is like a promise (i.e. it contains then, addCallback, addErrback)* @param obj object to test* @function*/isPromiseLike:isPromiseLike,/*** Waits for promise and non promise values to resolve and fires callback or errback appropriately. If you pass in an array of promises* then it will wait for all promises in the list to resolve.** @example* var a = "hello";* var b = new comb.Promise().callback(world);* comb.when(a, b) => called back with ["hello", "world"];** @param {Anything...} args variable number of arguments to wait for.* @param {Function} cb the callback function* @param {Function} eb the errback function* @returns {comb.Promise} a promise that is fired when all values have resolved*/when:function (args, cb, eb) {- 97
var args = argsToArray(arguments), p;- 97
eb = base.isFunction(args[args.length - 1]) ? args.pop() : null;- 97
cb = base.isFunction(args[args.length - 1]) ? args.pop() : null;- 97
if (eb && !cb) {- 5
cb = eb;- 5
eb = null;}- 97
if (!args.length) {- 3
p = new Promise().callback(args);- 94
} else if (args.length == 1) {- 88
args = args.pop();- 88
if (isPromiseLike(args)) {- 57
p = args;- 31
} else if (isArray(args) && args.every(isPromiseLike)) {- 1
p = new PromiseList(args, true);} else {- 30
p = new Promise().callback(args);}} else {- 6
p = new PromiseList(args.map(function (a) {- 12
return exports.isPromiseLike(a) ? a : new Promise().callback(a);}), true);}- 97
if (cb) {- 11
p.addCallback(cb);}- 97
if (eb) {- 6
p.addErrback(eb);}- 97
return p.promise();},/*** Wraps traditional node style functions with a promise.* @example** var fs = require("fs");* var readFile = comb.wrap(fs.readFile, fs);* readFile(__dirname + "/test.json").then(* function(buffer){* console.log(contents);* },* funciton(err){** } console.error(err);* );*** @param {Function} fn function to wrap* @param {Object} scope scope to call the function in** @return {Funciton} a wrapped function*/wrap:function (fn, scope) {- 2
return function () {- 2
var ret = new Promise();- 2
var args = argsToArray(arguments);- 2
args.push(ret.resolve.bind(ret));- 2
fn.apply(scope || this, args);- 2
return ret.promise();}},/*** Executes a list of items in a serial manner. If the list contains promises then each promise* will be executed in a serial manner, if the list contains non async items then the next item in the list* is called.** @example** var asyncAction = function(item, timeout){* var ret = new comb.Promise();* setTimeout(comb.hitchIgnore(ret, "callback", item), timeout);* return ret.promise();* };** comb.serial([* comb.partial(asyncAction, 1, 1000),* comb.partial(asyncAction, 2, 900),* comb.partial(asyncAction, 3, 800),* comb.partial(asyncAction, 4, 700),* comb.partial(asyncAction, 5, 600),* comb.partial(asyncAction, 6, 500)* ]).then(function(results){* console.log(results); // [1,2,3,4,5,6];* });**** @param list* @param callback* @param errback*/serial:function (list, callback, errback) {- 4
if (base.isArray(list)) {- 3
return callNext(list, 0, [], false, new Promise().then(callback, errback), false)} else {- 1
throw new Error("When calling comb.serial the first argument must be an array");}},/*** Works just like {@link comb.Promise#chain} method, allowing you to propogate results from one funciton to another.* This is different than {@link comb.serial} in that it propogates results from one promise to the next, where* {@link comb.serial} does not.** @example** function asyncAction(add, timeout) {* return function (num) {* num = num || 0;* var ret = new comb.Promise();* setTimeout(function () {* ret.callback(num + add);* }, timeout);* return ret;* }* }** comb.chain([* asyncAction(1, 100),* asyncAction(2, 100),* asyncAction(3, 100),* asyncAction(4, 100),* asyncAction(5, 100),* ]).then(function(results){* console.log(results); //15* });** @param {function[]} list an array of function to call.* @return {comb.Promise} a promise that will resolve with the results of the last function in the list.*/chain:function (list) {- 5
if (base.isArray(list)) {- 4
return callNext(list, 0, null, false, new Promise(), true);} else {- 1
throw new Error("When calling comb.serial the first argument must be an array");}}});- 1
var when = exports.when;- 1
function callNextSuccess(list, index, results, isErrored, ret, propogate) {//store results- 51
var args = argsToArray(arguments, 6);- 51
if (propogate) {- 31
process.nextTick(base.partial(callNext, list, index + 1, args, isErrored, ret, propogate));} else {- 20
results.push(args.length == 1 ? args[0] : args);- 20
process.nextTick(base.partial(callNext, list, index + 1, results, isErrored, ret, propogate));}}- 1
function callNextError(index, results, isErrored, ret, propogate) {//store results- 2
var args = argsToArray(arguments, 5);- 2
ret.errback.apply(ret, args);}- 1
function callNext(list, index, results, isErrored, ret, propogate) {- 58
if (index < list.length) {- 55
var item = list[index];- 55
try {- 55
when(base.isFunction(item) ? propogate ? item.apply(null, results) : item() : item).then(callNextSuccess.bind(null, list, index, results, isErrored, ret, propogate),callNextError.bind(null, index, results, isErrored, ret, propogate));} catch (e) {- 2
ret.errback(e);}} else {- 3
propogate ? ret.callback.apply(ret, results) : ret.callback(results);}- 58
return ret.promise();}