// Underscore-contrib (underscore.function.predicates.js 0.3.0) // (c) 2013 Michael Fogus, DocumentCloud and Investigative Reporters & Editors // Underscore-contrib may be freely distributed under the MIT license. // Establish the root object, `window` in the browser, or `require` it on the server. if (typeof exports === 'object') { _ = module.exports = require('underscore'); } // Helpers // ------- // Mixing in the predicate functions // --------------------------------- _.mixin({ // A wrapper around instanceof isInstanceOf: function(x, t) { return (x instanceof t); }, // An associative object is one where its elements are // accessed via a key or index. (i.e. array and object) isAssociative: function(x) { return _.isArray(x) || _.isObject(x) || _.isArguments(x); }, // An indexed object is anything that allows numerical index for // accessing its elements (e.g. arrays and strings). NOTE: Underscore // does not support cross-browser consistent use of strings as array-like // objects, so be wary in IE 8 when using String objects and IE<8. // on string literals & objects. isIndexed: function(x) { return _.isArray(x) || _.isString(x) || _.isArguments(x); }, // A seq is something considered a sequential composite type (i.e. arrays and `arguments`). isSequential: function(x) { return (_.isArray(x)) || (_.isArguments(x)); }, // Check if an object is an object literal, since _.isObject(function() {}) === _.isObject([]) === true isPlainObject: function(x) { return _.isObject(x) && x.constructor === Object; }, // These do what you think that they do isZero: function(x) { return 0 === x; }, isEven: function(x) { return _.isFinite(x) && (x & 1) === 0; }, isOdd: function(x) { return _.isFinite(x) && !_.isEven(x); }, isPositive: function(x) { return x > 0; }, isNegative: function(x) { return x < 0; }, isValidDate: function(x) { return _.isDate(x) && !_.isNaN(x.getTime()); }, // A numeric is a variable that contains a numeric value, regardless its type // It can be a String containing a numeric value, exponential notation, or a Number object // See here for more discussion: http://stackoverflow.com/questions/18082/validate-numbers-in-javascript-isnumeric/1830844#1830844 isNumeric: function(n) { return !isNaN(parseFloat(n)) && isFinite(n); }, // An integer contains an optional minus sign to begin and only the digits 0-9 // Objects that can be parsed that way are also considered ints, e.g. "123" // Floats that are mathematically equal to integers are considered integers, e.g. 1.0 // See here for more discussion: http://stackoverflow.com/questions/1019515/javascript-test-for-an-integer isInteger: function(i) { return _.isNumeric(i) && i % 1 === 0; }, // A float is a numbr that is not an integer. isFloat: function(n) { return _.isNumeric(n) && !_.isInteger(n); }, // checks if a string is a valid JSON isJSON: function(str) { try { JSON.parse(str); } catch (e) { return false; } return true; }, // Returns true if its arguments are monotonically // increaing values; false otherwise. isIncreasing: function() { var count = _.size(arguments); if (count === 1) return true; if (count === 2) return arguments[0] < arguments[1]; for (var i = 1; i < count; i++) { if (arguments[i-1] >= arguments[i]) { return false; } } return true; }, // Returns true if its arguments are monotonically // decreaing values; false otherwise. isDecreasing: function() { var count = _.size(arguments); if (count === 1) return true; if (count === 2) return arguments[0] > arguments[1]; for (var i = 1; i < count; i++) { if (arguments[i-1] <= arguments[i]) { return false; } } return true; } });