/* bind.js * * Author: nanto_vi (TOYAMA Nao) * Lisence: Public Domain */ Object.extend = function (dest, src, onlyMissing) { for (var i in src) if (!onlyMissing || !(i in dest)) dest[i] = src[i]; return dest; }; Object.extend(Function.prototype, { genericize: function () { var self = this; return function () { var thisObject = Array.prototype.shift.apply(arguments); return self.apply(thisObject, arguments); }; }, genericizeMethods: function () { for (var i = 0; i < arguments.length; i++) { var name = arguments[i]; this[name] = this.prototype[name].genericize(); } }, bindThis: function (thisObject) { var self = this; return function () { return self.apply(thisObject, arguments); }; }, bind: function () { var self = this; var argHints = arguments; var func = function () { var args = []; for (var i = 0; i < argHints.length; i++) { var argHint = argHints[i]; args[i] = (argHint instanceof Function && argHint._isBound) ? argHint.apply(null, arguments) : (argHint instanceof Function.Argument) ? arguments[argHint.index] : (argHint instanceof Function.Literal) ? argHint.value : argHint; } return self.apply(this, args); }; func._isBound = true; return func; }, literal: function () { return new Function.Literal(this); }, delay: function (delay) { var self = this; return function () { var args = arguments; window.setTimeout(function () {self.apply(null, args);}, delay); }; } }); Function.genericizeMethods("apply", "call", "genericize", "genericizeMethods", "bindThis", "bind", "literal", "delay"); Object.extend(Function, { Argument: function (n) { this.index = n - 1; }, Literal: function (value) { this.value = value; }, get: function (object, method, argLength) { if (object[method] instanceof Function) return object[method]; var jsMethod = "_" + method + argLength; if (jsMethod in arguments.callee) return arguments.callee[jsMethod]; var args = []; for (var i = 0; i < argLength; i++) args[i] = "arguments[" + i + "]"; return arguments.callee[jsMethod] = new Function("return this." + method + "(" + args.join(", ") + ");"); } }); (function () { for (var i = 1; i <= 12; i++) this["_" + i] = new Function.Argument(i); })(); Object.extend(String.prototype, { toFunction: function () { return arguments.callee[this]; }, call: function () { return this.toFunction().apply(null, arguments); }, bind: function () { return Function.prototype.bind.apply(this.toFunction(), arguments); } }); String.genericizeMethods("toFunction", "call", "bind"); Object.extend(String.prototype.toFunction, { "+": function () { if (arguments.length == 1) return +arguments[0]; var result = arguments[0]; for (var i = 1; i < arguments.length; i++) result += arguments[i]; return result; }, "-": function () { if (arguments.length == 1) return -arguments[0]; var result = arguments[0]; for (var i = 1; i < arguments.length; i++) result -= arguments[i]; return result; }, "*": function () { var result = arguments[0]; for (var i = 1; i < arguments.length; i++) result *= arguments[i]; return result; }, "/": function () { var result = arguments[0]; for (var i = 1; i < arguments.length; i++) result /= arguments[i]; return result; }, "<": function (a, b) {return a < b;}, ">": function (a, b) {return a > b;}, "<=": function (a, b) {return a <= b;}, ">=": function (a, b) {return a >= b;}, "==": function (a, b) {return a == b;}, "!=": function (a, b) {return a != b;}, "&&": function () { for (var i = 0; i < arguments.length; i++) if (!arguments[i]) return arguments[i]; return arguments[arguments.length - 1]; }, "||": function () { for (var i = 0; i < arguments.length; i++) if (argumens[i]) return arguments[i]; return arguments[arguments.length - 1]; }, "?:": function (condition, truePart, falsePart) { return condition ? truePart : falsePart; }, ",": function () { return arguments[arguments.length - 1]; }, "[]": function () { return Array.from(arguments); }, "!": function (condition) {return !condition;}, "true": function () {return true;}, "false": function () {return false;}, "null": function () {return null;}, "void": function () {return undefined;}, "typeof": function (x) {return typeof x;}, "in": function (member, object) {return member in object;}, "new": function (Class) { var argLength = arguments.length - 1; var constructor = arguments.callee[argLength]; if (!constructor) { var args = []; for (var i = 0; i < argLength; i++) args[i] = "arguments[" + i + "]"; constructor = arguments.callee[argLength] = new Function("return new this(" + args.join(", ") + ");"); } return constructor.apply(Class, Array.slice(arguments, 1)); }, "": String, "get": function (object, property) { return object[property]; }, "set": function (object, property, value) { return object[property] = value; }, "call": function (object, method) { return Function.get(object, method, arguments.length - 2) .apply(object, Array.slice(arguments, 2)); }, "invoke": function (func) { return func.apply(null, Array.slice(arguments, 1)); }, "k": function (k) {return k;} }); Object.extend(Array.prototype, { forEach: function (callback, thisObject) { for (var i = 0, length = this.length; i < length; i++) callback.call(thisObject, this[i], i, this); }, map: function (callback, thisObject) { var length = this.length; var result = new Array(length); for (var i = 0; i < length; i++) result[i] = callback.call(thisObject, this[i], i, this); return result; }, filter: function (callback, thisObject) { var result = []; for (var i = 0, length = this.length; i < length; i++) { var element = this[i]; if (callback.call(thisObject, element, i, this)) result.push(element); } return result; }, some: function (callback, thisObject) { for (var i = 0, length = this.length; i < length; i++) if (callback.call(thisObject, this[i], i, this)) return true; return false; }, every: function (callback, thisObject) { for (var i = 0, length = this.length; i < length; i++) if (!callback.call(thisObject, this[i], i, this)) return false; return true; }, indexOf: function (searchElement, fromIndex) { var length = this.length; if (arguments.length < 2 || (fromIndex < 0 && (fromIndex += length) < 0)) fromIndex = 0 for (var i = fromIndex; i < length; i++) if (this[i] === searchElement) return i; return -1; }, lastIndexOf: function (searchElement, fromIndex) { var length = this.length; if (arguments.length < 2 || fromIndex >= length) fromIndex = length - 1; else if (fromIndex < 0) fromIndex += length; for (var i = fromIndex; i >= 0; i--) if (this[i] === searchElement) return i; return -1; } }, true); if (!Array.forEach) { Array.genericizeMethods("forEach", "map", "filter", "some", "every", "indexOf", "lastIndexOf", "concat", "join", "slice", "pop", "push", "shift", "unshift", "reverse", "sort", "splice"); String.genericizeMethods("charAt", "charCodeAt", "concat", "indexOf", "lastIndexOf", "match", "replace", "search", "slice", "split", "substring", "toUpperCase", "toLowerCase"); } Array.from = Array.map.bind(_1, "k".toFunction()); if (!Date.now) Date.now = function () {return +(new Date());}; // Date.now = "+".bind("new".bind(Date));