1 /* 2 * prototype.js light 3 */ 4 Array.prototype.clone = function() { 5 return [].concat(this); 6 }; 7 Array.prototype.toArray = Array.prototype.clone; 8 // The primary use of Array.from() is to obtain an actual Array object based on anything that could pass as an array. 9 // the predefined arguments reference within your functions 10 Array.from = function(iterable) { 11 if (!iterable) return []; 12 if (iterable.toArray) return iterable.toArray(); 13 var length = iterable.length || 0, results = new Array(length); 14 while (length--) results[length] = iterable[length]; 15 return results; 16 } 17 // extend Object 18 Object.extend = function(destination, source) { 19 for (var property in source) 20 destination[property] = source[property]; 21 return destination; 22 }; 23 Object.extend(Object, { 24 toJSON: function(object) { 25 var type = typeof object; 26 switch (type) { 27 case 'undefined': 28 case 'function': 29 case 'unknown': return; 30 case 'boolean': return object.toString(); 31 } 32 if (object === null) return 'null'; 33 if (object.toJSON) return object.toJSON(); 34 var results = []; 35 for (var property in object) { 36 var value = Object.toJSON(object[property]); 37 if (!Object.isUndefined(value)) 38 results.push(property.toJSON() + ': ' + value); 39 } 40 return '{' + results.join(', ') + '}'; 41 }, 42 keys: function(object) { 43 var keys = []; 44 for (var property in object) 45 keys.push(property); 46 return keys; 47 }, 48 values: function(object) { 49 var values = []; 50 for (var property in object) 51 values.push(object[property]); 52 return values; 53 }, 54 isArray: function(object) { 55 return object != null && typeof object == "object" && 56 'splice' in object && 'join' in object; 57 }, 58 isHash: function(object) { 59 return object instanceof Hash; 60 }, 61 isFunction: function(object) { 62 return typeof object == "function"; 63 }, 64 isString: function(object) { 65 return typeof object == "string"; 66 }, 67 isNumber: function(object) { 68 return typeof object == "number"; 69 }, 70 isUndefined: function(object) { 71 return typeof object == "undefined"; 72 }, 73 inheritConstants: function(destination, source) { 74 for (var property in source) { 75 if ((typeof source[property] == "string") || (typeof source[property] == "number")) { 76 destination[property] = source[property]; 77 } 78 } 79 return destination; 80 } 81 }); 82 // extend Function 83 Object.extend(Function.prototype, { 84 argumentNames: function() { 85 var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1] 86 .replace(/\s+/g, '').split(','); 87 return names.length == 1 && !names[0] ? [] : names; 88 }, 89 bind: function() { 90 if (arguments.length < 2 && (typeof arguments[0] == "undefined")) return this; 91 var __method = this, args = Array.from(arguments), object = args.shift(); 92 return function() { 93 return __method.apply(object, args.concat(Array.from(arguments))); 94 } 95 }, 96 curry: function() { 97 if (!arguments.length) return this; 98 var __method = this, args = Array.from(arguments); 99 return function() { 100 return __method.apply(this, args.concat(Array.from(arguments))); 101 } 102 }, 103 wrap: function(wrapper) { 104 var __method = this; 105 return function() { 106 return wrapper.apply(this, [__method.bind(this)].concat(Array.from(arguments))); 107 } 108 }, 109 methodize: function() { 110 if (this._methodized) return this._methodized; 111 var __method = this; 112 return this._methodized = function() { 113 return __method.apply(null, [this].concat(Array.from(arguments))); 114 }; 115 } 116 }); 117 Object.extend(String.prototype, { 118 camelize: function(prefix, suffix) { 119 var parts = this.split('-'); 120 if (prefix) parts.unshift(prefix); 121 if (suffix) parts.push(suffix); 122 var len = parts.length; 123 if (len == 1) return parts[0]; 124 125 var camelized = this.charAt(0) == '-' 126 ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) 127 : parts[0]; 128 129 for (var i = 1; i < len; i++) 130 camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); 131 132 return camelized; 133 }, 134 capitalize: function() { 135 return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); 136 }, 137 startsWith: function(pattern) { 138 return this.indexOf(pattern) === 0; 139 }, 140 endsWith: function(pattern) { 141 var d = this.length - pattern.length; 142 return d >= 0 && this.lastIndexOf(pattern) === d; 143 }, 144 empty: function() { 145 return this == ''; 146 }, 147 strip: function() { 148 return this.replace(/^\s+/, '').replace(/\s+$/, ''); 149 }, 150 // TODO Remove this 151 times: function(count) { 152 return count < 1 ? '' : new Array(count + 1).join(this); 153 }, 154 toJSON: function() { 155 // TODO Fix quotes... 156 return '\'' + this.toString().replace(/([\\'])/g, '\\$1') + '\''; 157 } 158 }); 159 Object.extend(Number.prototype, { 160 toPaddedString: function(length, radix) { 161 var string = this.toString(radix || 10); 162 return '0'.times(length - string.length) + string; 163 }, 164 toJSON: function() { 165 return isFinite(this) ? this.toString() : 'null'; 166 } 167 }); 168 Object.extend(Array.prototype, { 169 indexOf: function(object, from) { 170 var len = this.length; 171 from = from || 0; 172 for (var i = from; i < len; i++) { 173 if (this[i] === object) { 174 return i; 175 } 176 } 177 return -1; 178 }, 179 remove: function(object) { 180 var index = 0; 181 if (typeof object == 'number') { 182 index = object; 183 } else { 184 index = this.indexOf(object); 185 if (index < 0) { 186 return null; 187 } 188 } 189 return this.splice(index, 1)[0]; 190 }, 191 toJSON: function() { 192 var results = []; 193 this.each(function(object) { 194 var value = Object.toJSON(object); 195 if (!Object.isUndefined(value)) results.push(value); 196 }); 197 return '[' + results.join(', ') + ']'; 198 } 199 }); 200 Object.extend(Date.prototype, { 201 // TODO Fix UTC 202 toJSON: function() { 203 return '"' + this.getUTCFullYear() + '-' + 204 (this.getUTCMonth() + 1).toPaddedString(2) + '-' + 205 this.getUTCDate().toPaddedString(2) + 'T' + 206 this.getUTCHours().toPaddedString(2) + ':' + 207 this.getUTCMinutes().toPaddedString(2) + ':' + 208 this.getUTCSeconds().toPaddedString(2) + 'Z"'; 209 } 210 }); 211 /** 212 * @class Class like creation with inheritance. Based on Alex Arnell's inheritance implementation. 213 */ 214 jls.lang.Class = {/** @lends jls.lang.Class */ 215 /** 216 * Creates a new class. 217 * 218 * @param {Object} declaration An object containing the class declaration. 219 * @returns {Object} The new class. 220 */ 221 create: function() { 222 var parent = null, properties = Array.from(arguments); 223 if (typeof properties[0] == "function") 224 parent = properties.shift(); 225 226 function klass() { 227 this.initialize.apply(this, arguments); 228 } 229 230 Object.extend(klass, jls.lang.Class.Methods); 231 klass.superclass = parent; 232 klass.subclasses = []; 233 234 if (parent) { 235 var subclass = function() { }; 236 subclass.prototype = parent.prototype; 237 klass.prototype = new subclass; 238 parent.subclasses.push(klass); 239 } 240 241 for (var i = 0; i < properties.length; i++) 242 klass.addMethods(properties[i]); 243 244 if (!klass.prototype.initialize) 245 klass.prototype.initialize = jls.lang.Class.emptyFunction; 246 247 klass.prototype.constructor = klass; 248 249 return klass; 250 }, 251 emptyFunction: function() { }, 252 notAvailableFunction: function() { 253 throw new jls.lang.Exception('Function not available'); 254 }, 255 abstractMethod: function() { 256 throw new jls.lang.Exception('Abstract method'); 257 }, 258 // instantiate 259 newInstance: function(object) { 260 if (!(object && object.classname)) { 261 throw new jls.lang.Exception('Invalid object, the classname property is required'); 262 } 263 var classname = object.classname; 264 jls.loader.require(classname); 265 /*var properties = Array.from(arguments); 266 var args = ''; 267 for (var i = 0; i < properties.length; i++) { 268 if (i > 0) args += ', '; 269 args += 'properties[' + i + ']'; 270 }*/ 271 var args = 'object'; 272 for (var i = 1; i < arguments.length; i++) { 273 args += ', arguments[' + i + ']'; 274 } 275 //jls.logger.info('newInstance() : eval(\'new ' + classname + '(' + args + ')\')'); 276 return eval('new ' + classname + '(' + args + ')'); 277 } 278 }; 279 /** 280 * @class Class helper. 281 */ 282 jls.lang.Class.Methods = /** @lends jls.lang.Class.Methods */ 283 { 284 addMethods: function(source) { 285 var ancestor = this.superclass && this.superclass.prototype; 286 var properties = Object.keys(source); 287 288 if (!Object.keys({ toString: true }).length) 289 properties.push("toString", "valueOf"); 290 291 for (var i = 0, length = properties.length; i < length; i++) { 292 var property = properties[i], value = source[property]; 293 if (ancestor && (typeof value == 'function') && 294 value.argumentNames()[0] == "$super") { 295 var method = value; 296 value = (function(m) { 297 return function() { return ancestor[m].apply(this, arguments) }; 298 })(property).wrap(method); 299 300 value.valueOf = method.valueOf.bind(method); 301 value.toString = method.toString.bind(method); 302 } 303 this.prototype[property] = value; 304 } 305 306 return this; 307 } 308 }; 309