/* * Cylon - Utils * cylonjs.com * * Copyright (c) 2013-2015 The Hybrid Group * Licensed under the Apache 2.0 license. */ "use strict"; var _ = require("./utils/helpers"); var monkeyPatches = require("./utils/monkey-patches"); var Utils = module.exports = { // Public: Alias to setInterval, combined with Number monkeypatches below to // create an artoo-like syntax. // // interval - interval to run action on // action - action to perform at interval // // Examples // // every((5).seconds(), function() { // console.log("Hello world (and again in 5 seconds)!"); // }); // // Returns an interval every: function every(interval, action) { return setInterval(action, interval); }, // Public: Alias to setTimeout, combined with Number monkeypatches below to // create an artoo-like syntax. // // interval - interval to run action on // action - action to perform at interval // // Examples // // after((10).seconds(), function() { // console.log("Hello world from ten seconds ago!"); // }); // // Returns an interval after: function after(delay, action) { return setTimeout(action, delay); }, // Public: Alias to the `every` function, but passing 0 // Examples // // constantly(function() { // console.log("hello world (and again and again)!"); // }); // // Returns an interval constantly: function constantly(action) { return every(0, action); }, // Public: Sleep - do nothing for some duration of time. // // ms - number of ms to sleep for // // Examples // // sleep((1).second()); // // Returns a function sleep: function sleep(ms) { var start = Date.now(), i; while(Date.now() < start + ms) { i = 0; } }, // Public: Function to use for class inheritance. // Based on CoffeeScript's implementation. // // Example // // var Sphero = function Sphero() {}; // // subclass(Sphero, ParentClass); // // // Sphero is now a subclass of Parent, and can access parent methods // // through Sphero.__super__ // // Returns subclass subclass: function subclass(child, parent) { var Ctor = function() { this.constructor = child; }; for (var key in parent) { if (parent.hasOwnProperty(key)) { child[key] = parent[key]; } } Ctor.prototype = parent.prototype; child.prototype = new Ctor(); child.__super__ = parent.prototype; return child; }, proxyFunctions: function proxyFunctions(source, target) { _.each(source, function(prop, key) { if (_.isFunction(prop) && !target[key]) { target[key] = prop.bind(source); } }); }, // Public: Proxies a list of methods from one object to another. It will not // overwrite existing methods unless told to. // // methods - array of functions to proxy // target - object to proxy the functions to // base - (optional) object that proxied functions will be declared on. // Defaults to 'this'. // force - (optional) boolean - whether or not to force method assignment // // Returns base proxyFunctionsToObject: function(methods, target, base, force) { if (base == null) { base = this; } force = force || false; methods.forEach(function(method) { if (_.isFunction(base[method]) && !force) { return; } base[method] = function() { return target[method].apply(target, arguments); }; }); return base; }, // Public: Analogue to Ruby"s Hash#fetch method for looking up object // properties. // // obj - object to do property lookup on // property - string property name to attempt to look up // fallback - either: // - a fallback value to return if `property` can"t be found // - a function to be executed if `property` can"t be found. The function // will be passed `property` as an argument. // // Examples // // var object = { property: "hello world" }; // fetch(object, "property"); // //=> "hello world" // // fetch(object, "notaproperty", "default value"); // //=> "default value" // // var notFound = function(prop) { return prop + " not found!" }; // fetch(object, "notaproperty", notFound) // // "notaproperty not found!" // // var badFallback = function(prop) { prop + " not found!" }; // fetch(object, "notaproperty", badFallback) // // Error: no return value from provided callback function // // fetch(object, "notaproperty"); // // Error: key not found: "notaproperty" // // Returns the value of obj[property], a fallback value, or the results of // running "fallback". If the property isn"t found, and "fallback" hasn"t been // provided, will throw an error. fetch: function(obj, property, fallback) { if (obj.hasOwnProperty(property)) { return obj[property]; } if (fallback === void 0) { throw new Error("key not found: \"" + property + "\""); } if (_.isFunction(fallback)) { var value = fallback(property); if (value === void 0) { throw new Error("no return value from provided fallback function"); } return value; } return fallback; }, // Public: Given a name, and an array of existing names, returns a unique // name. // // name - name that"s colliding with existing names // arr - array of existing names // // Returns the new name as a string makeUnique: function(name, arr) { var newName; if (!~arr.indexOf(name)) { return name; } for (var n = 1; ; n++) { newName = name + "-" + n; if (!~arr.indexOf(newName)) { return newName; } } }, // Public: Adds necessary utils to global namespace, along with base class // extensions. // // Examples // // Number.prototype.seconds // undefined // after // undefined // // Utils.bootstrap(); // // Number.prototype.seconds // [function] // (after === Utils.after) // true // // Returns Cylon.Utils bootstrap: function bootstrap() { global.every = this.every; global.after = this.after; global.constantly = this.constantly; monkeyPatches.install(); return this; } }; Utils.bootstrap();