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 for (var i = 0, length = this.length; i < length; i++) { 194 //this.each(function(object) { 195 var value = Object.toJSON(this[i]); 196 if (!Object.isUndefined(value)) results.push(value); 197 }; 198 return '[' + results.join(', ') + ']'; 199 } 200 }); 201 Object.extend(Date.prototype, { 202 // TODO Fix UTC 203 toJSON: function() { 204 return '"' + this.getUTCFullYear() + '-' + 205 (this.getUTCMonth() + 1).toPaddedString(2) + '-' + 206 this.getUTCDate().toPaddedString(2) + 'T' + 207 this.getUTCHours().toPaddedString(2) + ':' + 208 this.getUTCMinutes().toPaddedString(2) + ':' + 209 this.getUTCSeconds().toPaddedString(2) + 'Z"'; 210 } 211 }); 212 /** 213 * @class Class like creation with inheritance. Based on Alex Arnell's inheritance implementation. 214 */ 215 jls.lang.Class = {/** @lends jls.lang.Class */ 216 /** 217 * Creates a new class. 218 * 219 * @param {Object} declaration An object containing the class declaration. 220 * @returns {Object} The new class. 221 */ 222 create: function() { 223 var parent = null, properties = Array.from(arguments); 224 if (typeof properties[0] == "function") 225 parent = properties.shift(); 226 227 function klass() { 228 this.initialize.apply(this, arguments); 229 } 230 231 Object.extend(klass, jls.lang.Class.Methods); 232 klass.superclass = parent; 233 klass.subclasses = []; 234 235 if (parent) { 236 var subclass = function() { }; 237 subclass.prototype = parent.prototype; 238 klass.prototype = new subclass; 239 parent.subclasses.push(klass); 240 } 241 242 for (var i = 0; i < properties.length; i++) 243 klass.addMethods(properties[i]); 244 245 if (!klass.prototype.initialize) 246 klass.prototype.initialize = jls.lang.Class.emptyFunction; 247 248 klass.prototype.constructor = klass; 249 250 return klass; 251 }, 252 emptyFunction: function() { }, 253 notAvailableFunction: function() { 254 throw new jls.lang.Exception('Function not available'); 255 }, 256 abstractMethod: function() { 257 throw new jls.lang.Exception('Abstract method'); 258 }, 259 // instantiate 260 newInstance: function(object) { 261 if (!(object && object.classname)) { 262 throw new jls.lang.Exception('Invalid object, the classname property is required'); 263 } 264 var classname = object.classname; 265 jls.loader.require(classname); 266 /*var properties = Array.from(arguments); 267 var args = ''; 268 for (var i = 0; i < properties.length; i++) { 269 if (i > 0) args += ', '; 270 args += 'properties[' + i + ']'; 271 }*/ 272 var args = 'object'; 273 for (var i = 1; i < arguments.length; i++) { 274 args += ', arguments[' + i + ']'; 275 } 276 //jls.logger.info('newInstance() : eval(\'new ' + classname + '(' + args + ')\')'); 277 return eval('new ' + classname + '(' + args + ')'); 278 } 279 }; 280 /** 281 * @class Class helper. 282 */ 283 jls.lang.Class.Methods = /** @lends jls.lang.Class.Methods */ 284 { 285 addMethods: function(source) { 286 var ancestor = this.superclass && this.superclass.prototype; 287 var properties = Object.keys(source); 288 289 if (!Object.keys({ toString: true }).length) 290 properties.push("toString", "valueOf"); 291 292 for (var i = 0, length = properties.length; i < length; i++) { 293 var property = properties[i], value = source[property]; 294 if (ancestor && (typeof value == 'function') && 295 value.argumentNames()[0] == "$super") { 296 var method = value; 297 value = (function(m) { 298 return function() { return ancestor[m].apply(this, arguments) }; 299 })(property).wrap(method); 300 301 value.valueOf = method.valueOf.bind(method); 302 value.toString = method.toString.bind(method); 303 } 304 this.prototype[property] = value; 305 } 306 307 return this; 308 } 309 }; 310