1 /** Licensed Materials - Property of IBM, 5724-E76 and 5724-E77, (C) Copyright IBM Corp. 2011, 2012 - All Rights reserved. **/ 2 (function(){ 3 /** 4 * START main 5 */ 6 7 /** 8 * The global namespace of the IBM Client API 9 * @name i$ 10 * @namespace The global namespace of the IBM Client API 11 */ 12 13 var w=window, 14 i$=function(){ 15 if(i$.qel){ 16 return i$.qel.apply(this,arguments); 17 } 18 }; 19 w.i$ = i$; 20 21 /** 22 * Refers to the global namespace, by default the window object. 23 * @field global 24 * @type Window 25 */ 26 i$.global = w; 27 //i$.doc = document; 28 29 /** 30 * Native console normalization 31 */ 32 if(typeof(console) == "undefined"){ 33 /** 34 * @ignore 35 */ 36 var f = function(){}; 37 console = { 38 log:f, 39 debug:f, 40 info:f, 41 warn:f, 42 error:f, 43 assert:f 44 }; 45 } 46 47 /** 48 * Generates a partial function based on an existing function. The first argument denotes the 49 * function to create a new partial for. All subsequent arguments after that are used to 50 * prefill the original function's parameters with fixed values whenever the partial is 51 * called. Any undefined values in the arguments list will be used as a placeholder to 52 * shift in the actual calling arguments. Any calling arguments that are left over after 53 * shifting into placeholder locations will be concatenated to the end of the resulting 54 * arguments that are passed to the original function as if they were default placeholders. 55 * @type Function 56 * @param {Function} func Function to create a partial from. Must not be null. 57 * @param {Mixed} [args] Values to set at fixed positions in the calling context's 58 * actual arguments. 59 * @return {Function} A new partial function based on f. Never null. 60 * 61 * @example 62 * Example 1 63 * var f = i$.partial(function(a, b, c){ 64 * alert(a + " - " + b + " - " + c); 65 * }, 1, 5); // fixes the first 2 parameters a and b 66 * f(10); // alerts "1 - 5 - 10" 67 * 68 * @example 69 * Example 2 70 * var f = i$.partial(function(a, b, c){ 71 * alert(a + " - " + b + " - " + c); 72 * }, 1, undefined, 5); // fixes parameter a and c, and marks b as a placeholder 73 * f(3); // alerts "1 - 3 - 5" 74 * 75 * @example 76 * Example 3 77 * var f = i$.partial(function(a, b, c){ 78 * alert(a + " - " + b + " - " + c); 79 * }, undefined, 10); // fixes parameter b 80 * f(1, 100); // alerts "1 - 10 - 100" 81 */ 82 i$.partial = function(/*Function*/f) { 83 var factoryArgs = i$.toArray(arguments).slice(1); 84 return function() { 85 var args = factoryArgs.slice(0), // copy factory args 86 cArgs = i$.toArray(arguments), // calling args 87 i=0; 88 for(;i<args.length;i++){ 89 if(args[i] === undefined){ 90 args[i] = cArgs.shift(); // shift calling args into placeholders 91 } 92 } 93 args.push.apply(args, cArgs); // push the left over onto args 94 return f.apply(this, args); // call the original function 95 }; 96 }; 97 /** 98 * Generates a partial function based on an existing function but fixes the scope in which the 99 * partial function is called regardless of the eventual calling scope. 100 * @see i$.partial 101 * @type Function 102 * @param {Object} obj Object to scope the function to so that the returned 103 * function always calls func in context of this scope object. Must not be null. 104 * @param {Function} func Function to scope. Must not be null. 105 * @param {Mixed} [args] Arguments with same semantics as {@link i$.partial} 106 * 107 * @return {Function} 108 * A new function like {@link i$.partial} but fixes the function's scope permanently. 109 * Calling this without additional arguments besides obj and func simply creates a new function 110 * of the same arity whose scope is fixed to obj. 111 * 112 * @example 113 * Example 1: 114 * var obj = {a: 1}; 115 * var f = i$.scope(obj, function(b, c){ 116 * alert(this.a + " - " + b + " - " + c); 117 * }); 118 * f(3, 5); // alerts "1 - 3 - 5" 119 * 120 * @example 121 * Example 2: 122 * var obj = {a: 1}; 123 * var f = i$.scope(obj, function(b, c){ 124 * alert(this.a + " - " + b + " - " + c); 125 * }, undefined, 5); 126 * f(3); // alerts "1 - 3 - 5" 127 */ 128 i$.scope = function(/*Object*/s,/*Function|String*/f) { 129 var of = f; 130 f = function(){ 131 return (i$.isString(of) ? s[of] : of).apply(s, arguments); 132 }; 133 return i$.partial.apply(this, i$.toArray(arguments).slice(1)); 134 }; 135 /** 136 * Logs an error to the console.error function. Entry point for extensions to capture logged 137 * errors. 138 * 139 * @private 140 * @param {String} message Message to be logged out as error 141 * @param {Error} [err] Error object to be logged 142 * @type void 143 */ 144 i$.error = function(/*String*/message, /*Error?*/err){ 145 console.error(err || new Error(message)); 146 }; 147 148 /** 149 * Enumerates over all items in an array or an object that is like an array as defined 150 * by {@link i$.isLikeArray}, calling function func for each enumerated value. 151 * 152 * @private 153 * @param {Array} arr Array to enumerate. Must not be null. 154 * @param {Function} func Function with signature function(value, index, originalArray) to 155 * call for each property or index. Must not be null. 156 * @param {Number} [start] optional start count 157 * @type void 158 */ 159 i$.forEach = function(arr,f,start) { 160 if(start==null){start=0;} 161 for(var i=(start>=0)?start:0;i<arr.length;i++){ 162 f(arr[i],i,arr); 163 } 164 }; 165 /** 166 * Enumerates over all properties of obj, calling function func for each enumerated value. 167 * 168 * @private 169 * @param {Object} obj Object whose properties should be enumerated 170 * @param {Function} func Function with signature function(value, propName, originalObject) to 171 * call for each property or index. 172 */ 173 i$.forIn = function(o,f){ 174 for(var i in o) { 175 if (Object.prototype.hasOwnProperty.call(o,i)) { 176 f(o[i],i,o); 177 } 178 } 179 }; 180 /** 181 * Enumerates over all properties of obj if obj is an object, or all items in obj if it is an array or is 182 * like an array (see {@link i$.isLikeArray}), calling function func in optional scope (defaulting to the global scope) 183 * for each enumerated value. 184 * 185 * @param {Object|Array} obj Object or Array to enumerate. Must not be null 186 * @param {Function} func Function with signature function(value, index|propName, originalObject) to 187 * call for each property or index. Must not be null 188 * @param {Object} [scope=i$.global] Object optional scope to call func in 189 * @type void 190 */ 191 i$.each = function(o,f,s){ 192 if(s){f = i$.scope(s,f);} 193 if(o) { 194 if(o instanceof Array || typeof o.length === "number") { 195 i$.forEach(o,f); 196 } 197 else { 198 i$.forIn(o,f); 199 } 200 } 201 }; 202 /** 203 * Tests whether some element in the array passes the test implemented by the provided function. 204 * 205 * @return {Boolean} Returns true if calling function func on each of the items in arr ever returns true; false otherwise. 206 * @type Boolean 207 * @param {Array|ArrayLike} arr Array to search; may simply be like an array. Must not be null. 208 * @param {Function} func Function with signature function(value) to 209 * call for each property or index. Must not be null. 210 * @param {Object} [scope=i$.global] Object optional scope to call func in 211 */ 212 i$.some = function(a,f,s){ 213 if(s){f = i$.scope(s,f);} 214 for(var i=0;i<a.length;i++){ 215 if(f(a[i])){ 216 return true; 217 } 218 } 219 return false; 220 }; 221 /** 222 * Tests whether all elements in the array pass the test implemented by the provided function. 223 * 224 * @return {Boolean} Returns true if calling function func on each of the items in arr never returns false; false otherwise. 225 * @type Boolean 226 * @param {Array|ArrayLike} arr Array to search; may simply be like an array. Must not be null. 227 * @param {Function} func Function with signature function(value) to 228 * call for each property or index. Must not be null. 229 * @param {Object} [scope=i$.global] Object optional scope to call func in 230 */ 231 i$.every = function(o,f,s){ 232 if(s){f = i$.scope(s,f);} 233 return !i$.some(o,function(val){ 234 return !f(val); 235 }); 236 }; 237 238 239 /** 240 * Provides light-weight AOP-style programming with around advice semantics. 241 * Overrides the function at obj[name] with a new function that effectively wraps the previous 242 * one and that has this signature: function(originalFn, arguments) 243 * Normal processing can be continued by returning the return value from calling 244 * originalFn.apply(this, arguments). 245 * The modified object property is tagged such that it can be unwrapped to restore its 246 * original form using {@link i$.unwrap}. 247 * <p>Note: A function property may be wrapped multiple times, but is modeled as a stack 248 * such that {@link i$.unwrap} will only unwrap the top wrapping layer at that point 249 * in time.</p> 250 * 251 * @example 252 * Example: 253 * var car = { 254 * drive: function(){ 255 * console.log("Driving"); 256 * } 257 * }; 258 * i$.wrap(car, "drive", function(originalFn, args) { 259 * if(!isIcy) { 260 * return originalFn.apply(this, args); 261 * } 262 * else { 263 * console.warn("It is too icy!"); 264 * } 265 * }); 266 * @param {Object} obj object to wrap a function property on. Must not be null. 267 * @param {String} name name of the object property that references a function to wrap. Must not be null. 268 * @param {Function} func function to replace the original with that has the signature 269 * function(originalFn, args). Must not be null. 270 * @type Function 271 * @return {Function} the wrapped function. Never null. 272 */ 273 i$.wrap = function(o,n,f){ 274 var fn = o[n]; 275 o[n] = function(){ 276 return f.call(this,fn,arguments); 277 }; 278 o[n]._wrapped = fn; 279 return o[n]; 280 }; 281 /** 282 * Unwraps a previously wrapped function at obj[name] from {@link i$.wrap} to its original form and 283 * resets it back. 284 * @param {Object} obj object to unwrap a function property on. Must not be null. 285 * @param {String} name name of the object property that references a function to unwrap. Must not be null. 286 * @type Function 287 * @return {Function} the unwrapped function or if no unwrapping possible, the original function again. Never null. 288 */ 289 i$.unwrap = function(o,n){ 290 var fn = o[n]; 291 if(fn && fn._wrapped){o[n] = fn._wrapped;} 292 return o[n]; 293 }; 294 295 i$.copyShallow = function(o){ 296 var r = i$.isArrayLike(o)?[]:{}; 297 i$.forIn(o, function(v,k){ 298 r[k]=v; 299 }); 300 return r; 301 }; 302 303 /**#@+ @ignore */ 304 var shadowPropFn = function(propName,target,overwrite,name){ 305 if(overwrite || target[name] === undefined){ 306 target[name] = function(){ 307 return this[propName][name].apply(this[propName], arguments); 308 }; 309 } 310 }, shadowObjFn = function(obj,target,overwrite, name){ 311 if(overwrite || target[name] === undefined){ 312 target[name] = function(){ 313 return obj[name].apply(obj, arguments); 314 }; 315 } 316 }; 317 /**#@-*/ 318 319 /** 320 * Creates shadowing functions on target that call the underlying functions on the shadowed source referred 321 * to by source. Those functions are called in the source's scope instead of the target's. This allows 322 * building up functions with less code that provide passthroughs to other objects as well as hiding 323 * APIs (Example: read-only). 324 * 325 * @param {String|Object} source String|Object refers to the source to delegate functions to. If it is a string, it refers 326 * to the name of the property on the scope of the function's execution context. If it is an object, it is 327 * accessed directly as a property on that object. 328 * @param {Object} target Object the target to create new functions on which shadow functions on the source. 329 * @param {Array} names Array of string names to create function properties for. 330 * @param {Boolean} [overwrite=false] Boolean property to specify whether or not the shadowing 331 * process should overwrite existing functions on the target with the same name. 332 * @type void 333 * 334 * @example 335 * Example 1: 336 * 337 * var source = { 338 * say: function(){ 339 * alert("I am " + this.name); 340 * }, 341 * name: "Sam" 342 * }; 343 * var target = { 344 * name: "Mouse" 345 * }; 346 * i$.shadow(source, target, ["say"]); // creates a "say" function on target 347 * target.say(); // alerts "I am Mouse" 348 * source.say = function(){ alert(this.name + " I am"); }; 349 * target.say(); // alerts "Mouse I am" 350 * 351 * @example 352 * Example 2: 353 * 354 * var target = { 355 * name: "Mouse", 356 * sourceProp: { 357 * say: function(){ 358 * alert("I am " + this.name); 359 * }, 360 * name: "Sam" 361 * } 362 * }; 363 * i$.shadow("sourceProp", target, ["say"]); // creates a "say" function on target 364 * target.say(); // alerts "I am Mouse" 365 * target.sourceProp.say = function(){ alert(this.name + " I am"); }; 366 * target.say(); // alerts "Mouse I am" 367 */ 368 i$.shadow = function(s,t,names,over){ 369 i$.each(names, i$.partial(i$.isString(s) ? shadowPropFn : shadowObjFn, s, t, over)); 370 }; 371 372 /**#@+ 373 @ignore 374 */ 375 var objFromPath = function(path, c, s){ 376 var i, p, ts = s||i$.global; 377 for(i=0;ts!=null,i<path.length,p=path[i];i++){ 378 if(ts[p]==null) { 379 if(c){ts[p]={};} 380 else{ts=null;break;} 381 } 382 ts = ts[p]; 383 } 384 return ts; 385 }; 386 /**#@-*/ 387 388 /** 389 * Gets whatever value is resolved by the dot-delimited namepath in the property chain of the scope object, 390 * which defaults to the global scope if none is provided. Conditionally creates the path if any 391 * part of it does not exist, setting empty objects at each null or undefined segment in the path. 392 * 393 * @param {String} namepath String with dot-delimited segments that refer to a name path to an object. Must not be null. 394 * @param {Boolean} [create=false] Boolean value that instructs the function to create the name path if it 395 * does not exist completely. 396 * @param {Object} [scope=i$.global] Object to begin the lookup for the name path resolution. 397 * @type Object 398 * @return {Object} the path object or null. 399 * 400 * @example 401 * Example 1: 402 * 403 * var obj = i$.fromPath("com.ibm.theme.feature"); 404 * alert(obj); // alerts "null" 405 * 406 * @example 407 * Example 2: 408 * 409 * var obj = i$.fromPath("com.ibm.theme.feature", true); 410 * alert(obj===com.ibm.theme.feature); // alerts "true" 411 * 412 * @example 413 * Example 3: 414 * 415 * var obj1 = i$.fromPath("com.ibm.theme", true); 416 * var obj2 = i$.fromPath("feature", true, obj1); 417 * alert(obj2===com.ibm.theme.feature); // alerts "true" 418 */ 419 i$.fromPath = function(n, c, s) { 420 var path = n.split("."); 421 return objFromPath(path, c, s); 422 }; 423 /** 424 * Sets a value to the dot-delimited path namepath in the property chain of the scope object, 425 * which defaults to the global scope if none is provided. 426 * 427 * @param {String} namepath String with dot-delimited parts that refer to a name path to an object. Must not be null. 428 * Any null or undefined segments in the path will be initialized to empty objects. 429 * @param {Mixed} value Any value to set at the last part of the objects resolved by the name path. Must not be null. 430 * @param {Object} [scope=i$.global] Object to begin the lookup for the name path resolution. 431 * @type Mixed 432 * @return {Mixed} the passed in value. 433 * 434 * @example 435 * Example 1: 436 * 437 * i$.toPath("com.ibm.theme.feature", { 438 * say: function() { 439 * alert("hello"); 440 * } 441 * }); 442 * com.ibm.theme.feature.say(); // alerts "hello" 443 * 444 * @example 445 * Example 2: 446 * 447 * var ibm = i$.fromPath("com.ibm", true); 448 * i$.toPath("theme.feature", { 449 * say: function() { 450 * alert("hello"); 451 * } 452 * }, ibm); 453 * com.ibm.theme.feature.say(); // alerts "hello" 454 */ 455 i$.toPath = function(n, v, s) { 456 var path = n.split("."), 457 p = path.pop(), 458 o = objFromPath(path, true, s); 459 o[p] = v; 460 return v; 461 }; 462 463 /** 464 * Wraps a function into a singleton-factory builder such that on the first function call, 465 * it calls the wrapped function and stores its return value then returns it. On subsequent 466 * calls, it just returns the original value. 467 * 468 * @param {Function} func the function to be called the first time. Must not be null. 469 * @param {Object} [scope] Object optional scope to call func in 470 * @type Function 471 * @returns {Function} Returns the singleton factory function. Never null. 472 * 473 * @example 474 * var singleton = i$.cachedFn(function() { 475 * alert("hello"); 476 * return true; 477 * }); 478 * singleton(); // alerts "hello" 479 * singleton(); // does not alert anything, just returns true 480 */ 481 i$.cachedFn = function(f,s){ 482 var val; 483 var fn = function(){ 484 if(!fn.called){ // expose for backdoor uncaching 485 fn.called = true; 486 val = f.apply(s, arguments); 487 } 488 return val; 489 } 490 return fn; 491 }; 492 493 i$.xhrFmts = { 494 text: function(xhr){ 495 return xhr.responseText; 496 }, 497 json: function(xhr) { 498 return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test( 499 xhr.responseText.replace(/"(\\.|[^"\\])*"/g, ''))) && 500 eval('(' + xhr.responseText + ')'); 501 }, 502 xml: function(xhr) { 503 return xhr.responseXML; 504 }, 505 javascript: function(xhr) { 506 if ((/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test( 507 str.replace(/"(\\.|[^"\\])*"/g, '')))) { 508 throw new SyntaxError("Invalid characters in javascript object"); 509 } 510 else { 511 return eval('(' + xhr.responseText + ')'); 512 } 513 } 514 }; 515 516 /** 517 * END main 518 */ 519 })();(function(){ 520 /** 521 * START of i$/core_ext 522 */ 523 /** 524 * Support for frames 525 */ 526 var i$ = window.i$; 527 528 /** 529 * This module defines APIs that are directly defined here but may also 530 * be reimplemented by some compat or adapter module. Such implementations 531 * may use another framework to do so. The overrides may be applied after 532 * this is loaded or in place of it. 533 */ 534 535 // doclets for client detection properties 536 /** 537 * Value indicating the version of Internet Explorer being used; undefined 538 * otherwise. 539 * @property 540 * @type Number 541 * @name i$.isIE 542 */ 543 544 /** 545 * Value indicating the version of Firefox being used; undefined 546 * otherwise. 547 * @property 548 * @type Number 549 * @name i$.isFF 550 */ 551 552 /** 553 * Value indicating the version of Opera being used; undefined 554 * otherwise. 555 * @property 556 * @type Number 557 * @name i$.isOpera 558 */ 559 560 /** 561 * Value indicating the version of Safari being used; undefined 562 * otherwise. 563 * @property 564 * @type Number 565 * @name i$.isSafari 566 */ 567 568 /** 569 * Value indicating the version of Chrome being used; undefined 570 * otherwise. 571 * @property 572 * @type Number 573 * @name i$.isChrome 574 */ 575 576 /** 577 * Value indicating the version of WebKit being used; undefined 578 * otherwise. 579 * @property 580 * @type Number 581 * @name i$.isWebKit 582 */ 583 584 /**#@+ @ignore */ 585 // client detection 586 (function(ua){ 587 var toVer = function(verStr){ 588 return parseFloat(verStr); // return type Number 589 /* 590 var p = verStr.split("."); 591 return {major:p[0],minor:p[1],rev:p[2],toString: function(){return p.join(".");}}; 592 */ 593 }, 594 list=[ 595 ["IE", /MSIE\s*([\S]+)*/], 596 ["FF", /Firefox\/([\S]+)*/], 597 ["Opera", /Opera[\s\/]([\S]+)*/], 598 ["Safari", /Version\/([\S]+)*[\s\S]*Safari/], 599 ["Chrome", /Chrome\/([\S]+)*/], 600 ["WebKit", /AppleWebKit\/([\S]+)*/]]; 601 i$.each(list, function(test){ 602 var m = test[1].exec(ua); 603 if(m && m.length > 1) { 604 i$["is"+test[0]] = toVer(m[1]); 605 }; 606 }); 607 })(navigator.userAgent); 608 // check if IE is in compatibility mode, update i$.isIE if it is different than what was retrieved from the user agent 609 var compatMode = document.documentMode; 610 if(compatMode && compatMode != 5 && Math.floor(i$.isIE) != compatMode){ 611 i$.isIE = compatMode; 612 } 613 /**#@- */ 614 615 616 /** 617 * Determines if an object is a DOM node or not. 618 * 619 * @param {Object} obj Object to be tested. Must not be null. 620 * @type Boolean 621 * @return {Boolean} Returns true if obj is a DOM node, false otherwise. 622 */ 623 i$.isNode = function(o){ 624 return typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName === "string"; 625 }; 626 /** 627 * Determines if an object is a function or not. 628 * 629 * @param {Object} obj Object to be tested. Must not be null. 630 * @type Boolean 631 * @return {Boolean} Returns true if obj is a function, false otherwise. 632 */ 633 i$.isFunction = function(o){ 634 return typeof o === "function" || o instanceof Function; 635 }; 636 /** 637 * Determines if an object is an object or not. 638 * 639 * @param {Object} obj Object to be tested. Must not be null. 640 * @type Boolean 641 * @return {Boolean} Returns true if obj is an object, false otherwise. 642 */ 643 i$.isObject = function(o){ 644 return typeof o === "object"; 645 }; 646 /** 647 * Determines if an object is an array or not. 648 * 649 * @param {Object} obj Object to be tested. Must not be null. 650 * @type Boolean 651 * @return {Boolean} Returns true if obj is an array, false otherwise. 652 */ 653 i$.isArray = function(o){ 654 if (typeof Array.isArray === "function") { 655 return Array.isArray(o); 656 } else { 657 return Object.prototype.toString.call(o) === "[object Array]"; 658 } 659 }; 660 /** 661 * Determines if an object is a string or not. 662 * 663 * @param {Object} obj Object to be tested. Must not be null. 664 * @type Boolean 665 * @return {Boolean} Returns true if obj is a string, false otherwise. 666 */ 667 i$.isString = function(o){ 668 return typeof o === "string"; 669 }; 670 /** 671 * Determines if an object is a number or not. 672 * 673 * @param {Object} obj Object to be tested. Must not be null. 674 * @type Boolean 675 * @return {Boolean} Returns true if obj is a number, false otherwise. 676 */ 677 i$.isNumber = function(o){ 678 return typeof o === "number"; 679 }; 680 /** 681 * Determines if an object is a boolean or not. 682 * 683 * @param {Object} obj Object to be tested. Must not be null. 684 * @type Boolean 685 * @return {Boolean} Returns true if obj is a boolean, false otherwise. 686 */ 687 i$.isBoolean = function(o){ 688 return typeof o === "boolean"; 689 }; 690 /** 691 * Determines if an object is array like or not. 692 * 693 * @param {Object} obj Object to be tested. Must not be null. 694 * @type Boolean 695 * @return {Boolean} Returns true if obj is like an array, namely that it at least has a length property of type number; 696 * false otherwise. 697 */ 698 i$.isLikeArray = function(o){ 699 return o instanceof Array || typeof o.length === "number"; 700 }; 701 702 /** 703 * Returns a true array from obj, creating a copy if obj is already an array. Useful for 704 * coercing array-like structures into true arrays safely. 705 * 706 * @param {Object|Array} obj Array or array-like object to convert into a new array. Must not be null. 707 * @type Array 708 * @return {Array} A new array. Never null. 709 */ 710 i$.toArray = function(o){ 711 return Array.prototype.slice.call(o); 712 }; 713 714 /**#@+ @ignore */ 715 if(i$.isIE) { 716 var fast = i$.toArray; 717 i$.toArray = function(o) { 718 try { // fast toArray 719 return fast(o); 720 } catch(err) { // slow toArray 721 var a = new Array(o.length); 722 for(var i=0;i<o.length;i++) { 723 a[i]=o[i]; 724 } 725 return a; 726 } 727 }; 728 } 729 730 // window/document onload and onunload handling 731 var pageLoaded = (document.readyState === "complete"), 732 loadFns = [], 733 unloadFns = [], 734 unloadSet = false; 735 736 i$._initPage = function() { 737 // fires all the loaders 738 var fn; 739 pageLoaded = true; 740 if(window.detachEvent) { 741 // leak protection 742 window.detachEvent("onload", i$._initPage); 743 } 744 745 while(loadFns.length>0){ 746 if(fn = loadFns.shift()) { 747 try { 748 fn(); 749 } 750 catch (err) { 751 console.log(err); 752 } 753 } 754 } 755 }; 756 i$._exitPage = function() { 757 // fires all the unloaders 758 var fn; 759 while(unloadFns.length>0){ 760 if(fn = unloadFns.shift()) { 761 try { 762 fn(); 763 } 764 catch (err) { 765 console.log(err); 766 } 767 } 768 } 769 }; 770 i$._addEvent = function(e,f,o){ 771 // adds an event to given object 772 // e: the event name, must have "on" as the first two characters 773 // f: the function to run when the event fires, fired on o 774 // o: the object on which to attach the event, window if unspecified 775 var w = o ? o : window; 776 var s = w.attachEvent ? e : e.substring(2); // chop off the "on" part 777 var a = w.attachEvent || w.addEventListener; 778 a(s, function(){ f.apply(w, arguments); }, false); 779 }; 780 // add init and exit page handlers 781 if(!pageLoaded) { 782 i$._addEvent("onload", i$._initPage); 783 if (document.addEventListener) { // browser compatibility 784 document.addEventListener("DOMContentLoaded", i$._initPage, false); // fires before onload, is sufficient and faster 785 } 786 } 787 /**#@-*/ 788 789 /** 790 * Adds a function to call on page load 791 * 792 * @param {Function|String} func The function to call, either a function or name of a function on 793 * scope object. Must not be null 794 * @param {Object} [scope=i$.global] The scope in which to call the function, i.e. the 'this' keyword within the function represents the scope object 795 * @type void 796 */ 797 i$.addOnLoad = function(f,o) { 798 if(o) { f = i$.scope(o,f); } 799 if(pageLoaded) { // fire immediately if page is loaded 800 f(); 801 } else { 802 loadFns.push(f); 803 } 804 }; 805 /** 806 * Adds a function to call on page unload. Not supported on Opera. 807 * 808 * @param {Function|String} func The function to call, either a function or name of a function on 809 * scope object. Must not be null. 810 * @param {Object} [scope=i$.global] The scope in which to call the function 811 * @type void 812 */ 813 i$.addOnUnload = function(f,o) { 814 // please note: Opera does not support the onunload event 815 if(!unloadSet) { i$._addEvent("onunload", i$._exitPage); unloadSet = true; } 816 if(o) { f = i$.scope(o,f); } 817 unloadFns.push(f); 818 }; 819 820 /**#@+ 821 @ignore 822 */ 823 var mx = function(o,m){ 824 for(var p in m) { 825 if(m.hasOwnProperty(p)){o[p]=m[p];} 826 } 827 }, mxn = function(o,m,names) { 828 i$.forEach(names, function(p){ 829 if(m.hasOwnProperty(p)){o[p]=m[p];} 830 }); 831 }; 832 /**#@-*/ 833 834 /** 835 * Enumerates over arguments, mashing all the native properties of each argument 836 * object into the first argument object, returning the first. Properties with the 837 * same name are resolved by using the last argument that contains that property. 838 * 839 * @param {Object} obj Target object to get new property values from subsequent arguments. Must not be null. 840 * @param {Object} props Objects to mash properties into the prototype. Must not be null. 841 * @type Function 842 * @return {Function} Returns obj again which has been passed into the mash function 843 * 844 * @example 845 * var bag1 = { 846 * prop1: "value", 847 * prop2: "Pass" 848 * }; 849 * var bag2 = { 850 * prop2: 15 851 * }; 852 * i$.mash(stash, bag1, bag2); 853 * 854 * is functionally equivalent to: 855 * 856 * stash.prop1 = "value"; 857 * stash.prop2 = "Pass"; 858 * stash.prop2 = 15; 859 */ 860 i$.mash = function(o) { 861 i$.forEach(arguments, function(v){ 862 mx(o,v); 863 },1); // start at index 1 of arguments 864 return o; 865 }; 866 /** 867 * Like {@link i$.mash} but only mashes properties whose names are in the names array first 868 * argument. The same semantics as {@link i$.mash} are applied except that the arguments 869 * are shifted by one to accommodate the names argument. This is useful for only mashing 870 * certain known properties from various objects into a target. 871 * 872 * @param {String[]} names An array of property names to mash. Must not be null. 873 * @param {Object} obj Target object to get new property values from subsequent arguments. Must not be null. 874 * @param {Object} props Objects to mash properties from. Must not be null. 875 * @type Function 876 * @return {Function} Returns obj again which has been passed into the mashSpec function 877 */ 878 i$.mashSpec = function(n,o) { 879 i$.forEach(arguments, function(v){ 880 mxn(o,v,n); 881 },2); // start at index 2 of arguments 882 return o; 883 }; 884 /** 885 * Like {@link i$.mash} but mashes properties into the function's prototype. 886 * Properties with the same name are resolved by using the last 887 * argument that contains that property. 888 * 889 * @param {Function} func Function whose prototype should be augmented. Must not be null. 890 * @param {Object} props Objects to mash properties into the prototype. Must not be null. 891 * @type Function 892 * @return {Function} Returns func again which has been passed into the augment function 893 * 894 * @example 895 * var visuals = { 896 * color: "white" 897 * }; 898 * var structural = { 899 * make: "sedan" 900 * }; 901 * i$.augment(Car, visuals, structural); 902 * 903 * is functionally equivalent to: 904 * 905 * Car.prototype.color = "white"; 906 * Car.prototype.make = "sedan"; 907 */ 908 i$.augment = function(f) { 909 var r = f; 910 if(f && f.prototype) { 911 f = f.prototype; 912 i$.mash.apply(i$, arguments); 913 } 914 return r; 915 }; 916 /** 917 * Creates and returns a new object whose prototype is the proto argument. This provides 918 * a light-weight API for building prototypal inheritance structures without 919 * constructing instances of the o argument. All arguments after the proto argument 920 * are used to mash properties into the new object just like {@link i$.mash}. 921 * 922 * @function 923 * @param {Object} proto Object to use as the prototype of the returned object. Must not be null. 924 * @param {Object} props Objects to mash properties into the prototype. Must not be null. 925 * @type Object 926 * @return {Object} A new object. Never null. 927 */ 928 i$.make = (function(){ 929 var l = function(){}; 930 return function(o) { 931 l.prototype = o; 932 o = new l(); 933 return i$.mash.apply(i$, arguments); 934 }; 935 })(); 936 937 var frontTrim = /^\s+/g; 938 /** 939 * The trim function removes all newlines, spaces (including non-breaking spaces), and tabs 940 * from the beginning and end of the supplied string. If these whitespace characters occur 941 * in the middle of the string, they are preserved. 942 * 943 * @param {String} str String to be trimmed. Must not be null. 944 * @type String 945 * @return {String} The trimmed string 946 */ 947 i$.trim = function(str){ 948 str = str.replace(frontTrim, ""); 949 var i = str.length-1; 950 while(str.charAt(i)==" " || str.charAt(i)=="\t" || str.charAt(i)=="\n" || str.charAt(i)=="\r") { 951 i--; 952 } 953 return str.substring(0,i+1); 954 }; 955 956 // alias for perf 957 var isArray = i$.isArray, 958 isObject = i$.isObject; 959 960 /** 961 * Merges a value object's properties into the target object. If value and target are both 962 * arrays then a resulting merged array is created, otherwise all object properties are 963 * merged from value into target. 964 * 965 * @param {Object|Array} obj Either object or array/array-like object to merge into the target object. Must not be null. 966 * @param {Object|Array} [target=i$.global] The target object or array 967 * @type Object|Array 968 * @return {Object|Array} Returns the merged object target. Same type as the target object that was passed in. 969 * 970 * @example 971 * Example 1: 972 * 973 * var visuals = { 974 * color: "white" 975 * }; 976 * var structural = { 977 * make: "sedan" 978 * }; 979 * var car = {}; 980 * i$.merge(visuals, car); 981 * i$.merge(structural, car); 982 * 983 * Result: 984 * car = { 985 * color: "white", 986 * make: "sedan" 987 * }; 988 * 989 * @example 990 * Example 2: 991 * 992 * var car = ["4 doors"]; 993 * i$.merge(["white","sedan"], car); 994 * 995 * Result: 996 * car = ["4 doors", "white", "sedan"] 997 */ 998 i$.merge = function(value, target, path){ 999 var path = path || [], v, c; 1000 // if target is null, then someone called with i$.merge(obj) defaulting target to the global obj 1001 target = target || i$.global; 1002 1003 if(isArray(value) && isArray(target)) { 1004 target.push.apply(target, value); 1005 } 1006 else { 1007 for(var x in value){ 1008 if(value.hasOwnProperty(x)){ 1009 v = value[x], c = target[x]; 1010 if(c != null && ((isArray(v) && isArray(c)) || (isObject(v) && isObject(c)))) { 1011 // c is not null or undefined, so we won't be calling merge against null 1012 target[x] = i$.merge(v, c, path.concat(x)); 1013 } 1014 else { 1015 // if all else fails, just override 1016 target[x] = v; 1017 } 1018 } 1019 } 1020 } 1021 return target; 1022 }; 1023 1024 var RTLMap; 1025 /** 1026 * Determines whether a certain locale is a right to left language. 1027 * 1028 * @param {String} locale The locale to be tested. Must not be null. 1029 * @type Boolean 1030 * @return {Boolean} Returns true if locale is right to left, false otherwise. 1031 */ 1032 i$.isRTL = function(locale) { 1033 if(!RTLMap){ 1034 RTLMap = i$.fromPath("ibmCfg.themeConfig.RTLMap"); 1035 } 1036 var _rtl_locales = RTLMap || {"iw":1,"he":1,"ar":1}; 1037 return (locale.substring(0,2) in _rtl_locales); 1038 }; 1039 1040 /** 1041 * END of i$/core_ext 1042 */ 1043 })(); 1044