1var ccms = window.ccms || {}; 2 3ccms.hasOwnProperty = (Object.prototype.hasOwnProperty) ? function(o, prop) {return o && o.hasOwnProperty(prop);} 4 : function(o, prop) {return typeof o[prop] !== 'undefined' && o.constructor.prototype[prop] !== o[prop];}; 5 6// object inheritance/extension utility function. http://javascript.crockford.com/prototypal.html 7ccms.object = function(o) { 8 function F() {} 9 F.prototype = o; 10 return new F(); 11}; 12 13// array update / merge function 14ccms.extend = ccms.update = function(destination, source) { 15 for (var property in source) { 16 if (ccms.hasOwnProperty(source, property)) { 17 destination[property] = source[property]; 18 } 19 } 20 return destination; 21}; 22 23// clone an object (shallow clone). usage: var clone = ccms.cloneOf(thing); 24ccms.cloneOf = function(what) { 25 var i, o; 26 if (typeof what.prototype == 'undefined') { 27 o = {}; 28 for (i in what) { 29 o[i] = what[i]; 30 } 31 } 32 else { 33 o = ccms.object(what.prototype); 34 for (i in what) { 35 if (ccms.hasOwnProperty(what, i)) { 36 o[i] = what[i]; 37 } 38 } 39 } 40 return o; 41}; 42 43ccms.namespace = function(name) { 44 if (!name || !name.length) { 45 return null; 46 } 47 var parts = name.split("."); 48 var ns = window; 49 for (var i = 0; i < parts.length; ++i) { 50 ns[parts[i]] = ns[parts[i]] || {}; 51 ns = ns[parts[i]]; 52 } 53 return ns; 54}; 55 56// Asynchronous operations (http, timed events) 57ccms.namespace('ccms.async'); 58// Configuration 59ccms.namespace('ccms.config'); 60// DOM helper functions 61ccms.namespace('ccms.dom'); 62// Event library 63ccms.namespace('ccms.event'); 64// Logging / Messages 65ccms.namespace('ccms.log'); 66// CSS helper functions 67ccms.namespace('ccms.css'); 68// Date utilities 69ccms.namespace('ccms.date'); 70 71ccms.extend(ccms, (function() { 72 var scripts = []; 73 return { 74 75 detectScripts: function(evt) { 76 var src; 77 var stags = ccms.arrayOf(document.getElementsByTagName('script')); 78 for (var t = 0; t < stags.length; ++t) { 79 if ((src = stags[t].getAttribute('src')) && src.length) { 80 src = src.replace(/\?v=[0-9]+/,''); 81 scripts[src] = true; 82 } 83 } 84 }, 85 86 // jscombo'd scripts call this with each contained url 87 addScript: function(url) { 88 url = url.replace(/\?v=[0-9]+/,''); 89 scripts[url] = true; 90 }, 91 92 // import an external script 93 require: function(url, callback) { 94 if (!url) return false; 95 var s = false; 96 var src = url.replace(/\?v=[0-9]+/,''); 97 if (typeof scripts[src] === 'undefined') { 98 scripts[src] = true; 99 if (navigator.userAgent.indexOf('MSIE') > 0) { 100 ccms.require_sync(url); 101 } 102 else { 103 s = document.createElement('script'); 104 s.setAttribute('type', 'text/javascript'); 105 s.setAttribute('src', url); 106 document.getElementsByTagName('head')[0].appendChild(s); 107 } 108 } 109 110 if (typeof callback === 'function') { 111 if (s) { 112 // Tested: 113 // - Firefox (y) 114 // - Safari (n) 115 ccms.event.attach(s, 'load', function() { callback(); }); 116 } 117 else { 118 callback(); 119 } 120 } 121 122 return scripts[url]; 123 }, 124 125 require_sync: function(url) { 126 var script = ccms.async.http({ 127 url:url 128 }); 129 window.eval(script); 130 }, 131 132 browser: { 133 isIE: /*@cc_on!@*/false, 134 isSafari: /webkit/gi.test(navigator.userAgent), 135 isWebKit: /webkit/gi.test(navigator.userAgent), 136 isGecko: !(/webkit/gi.test(navigator.userAgent)) && (/Gecko/.test(navigator.userAgent)) 137 }, 138 139 140 push: function(a, value) {a[a.length] = value;}, 141 142 indexOf: function(a, item) { 143 for (var i = 0; i < a.length; ++i) { 144 if (a[i] === item) { 145 return i; 146 } 147 } 148 return -1; 149 }, 150 151 // array filter function 152 filter: function(a, callback) { 153 if (!callback) { 154 callback = function(e) {return e;}; 155 } 156 var out = []; 157 for (var i = 0; i < a.length; ++i) { 158 if (callback(a[i])) { 159 out[out.length] = a[i]; 160 } 161 } 162 return out; 163 }, 164 // array map function 165 map: function(a, callback) { 166 if (!callback) { 167 callback = function(e) {return e;}; 168 } 169 var out = []; 170 for (var i in a) { 171 if (ccms.hasOwnProperty(a, i)) { 172 out[i] = callback(a[i]); 173 } 174 } 175 return out; 176 }, 177 // array membership function 178 contains: function(a, value) { 179 for (var i in a) { 180 if (ccms.hasOwnProperty(a, i) && a[i] === value) { 181 return true; 182 } 183 } 184 return false;
185 }, 186 187 containsi: function(a, value) { 188 var valuei = value.toLowerCase(); 189 for (var i in a) { 190 if (ccms.hasOwnProperty(a, i) && (((typeof a[i] === 'string') && (a[i].toLowerCase() === valuei)) || (a[i] === value))) { 191 return true; 192 } 193 } 194 return false; 195 }, 196 197 remove: function(a, value) { 198 for (var i in a) { 199 if (ccms.hasOwnProperty(a, i) && a[i] === value) { 200 delete a[i]; 201 } 202 } 203 return a; 204 }, 205 206 removei: function(a, value) { 207 var valuei = value.toLowerCase(); 208 for (var i in a) { 209 if (ccms.hasOwnProperty(a, i) && (((typeof a[i] === 'string') && (a[i].toLowerCase() === valuei)) || (a[i] === value))) { 210 delete a[i]; 211 } 212 } 213 return a; 214 }, 215 216 flip: function(a) { 217 var b = []; 218 for(var i in a) { 219 if (ccms.hasOwnProperty(a, i)) { 220 b[a[i]] = i; 221 } 222 } 223 return b; 224 }, 225 226 shift: function(a) { 227 var result = a[0]; 228 for (var i = 0; i < a.length - 1; ++i) { 229 a[i] = a[i + 1]; 230 } 231 --a.length; 232 return result; 233 }, 234 235 keysOf: function(object) { 236 var r = []; 237 for (var i in object) { 238 if (ccms.hasOwnProperty(object, i)) { 239 r[r.length] = i; 240 } 241 } 242 return r; 243 }, 244 245 valuesOf: function(object) { 246 var r = []; 247 for (var i in object) { 248 if (ccms.hasOwnProperty(object, i)) { 249 r[r.length] = object[i]; 250 } 251 } 252 return r; 253 }, 254 255 arrayOf: function(iterable) { 256 var results = []; 257 if (!iterable) {return results;} 258 if (iterable.toArray) { 259 return iterable.toArray(); 260 } 261 else { 262 for (var i = 0; i < iterable.length; i++) { 263 results[results.length] = iterable[i]; 264 } 265 return results; 266 } 267 }, 268 269 isCollection: function(o) { 270 return ( 271 o && // o is something 272 o.length && // o is indexed 273 (typeof o !== "string") && // o is not a string 274 !o.tagName && // o is not an HTML element 275 !o.alert && // o is not a window 276 (typeof o[0] !== "undefined") 277 ); 278 }, 279 280 bind: function(obj, method) { 281 return function() { 282 var args = arguments; 283 return method.apply(obj, args); 284 }; 285 }, 286 287 chain: function(f1, f2) { 288 if (f1) { 289 if (f2) { 290 return function() {f1(); return f2();}; 291 } 292 return f1; 293 } 294 return f2; 295 }, 296 297 html: { 298 isAvailable: false, 299 isWanted: false, 300 use: function() { 301 ccms.html.isAvailable = true; 302 ccms.html.isWanted = true; 303 ccms.html = ccms.DomBuilder.apply(ccms.html); 304 ccms.html.use = function() {}; 305 } 306 }, 307 308 widgets: { 309 widgetlist: [], 310 installers: {}, 311 add: function(widget, id) { 312 if (typeof id !== 'string' || id === '') { 313 id = ccms.widgets.widgetlist.length; 314 } 315 if (ccms.widgets.widgetlist[id]) { 316 id = ccms.dom.generateId(); 317 } 318 ccms.widgets.widgetlist[id] = widget; 319 }, 320 get: function(id) { 321 return ccms.widgets.widgetlist[id]; 322 }, 323 remove: function(id) { 324 delete ccms.widgets.widgetlist[id]; 325 }, 326 each: function(callback) { 327 for(var i in ccms.widgets.widgetlist) { 328 if (ccms.hasOwnProperty(ccms.widgets.widgetlist, i)) { 329 callback(ccms.widgets.widgetlist[i]); 330 } 331 } 332 }, 333 addInstaller: function(name, callback, condition) { 334 ccms.widgets.installers[name] = callback; 335 336 if (condition !== false) { 337 if (typeof condition === 'undefined') { 338 if (ccms.dom.ready) { 339 callback(); 340 } 341 else { 342 ccms.event.onDOMReady(function() {callback();}); // wrap function cos onDOMReady passes parameters 343 } 344 return; 345 } 346 if (!ccms.dom.ready) { // Queue for later 347 ccms.event.addLoadEvent(function() { ccms.async.when(condition, callback); }); 348 } 349 else { // Call Now 350 ccms.async.when(condition, callback); 351 } 352 } 353 },
354 runInstallers: function(block, optional_data) { 355 if (typeof block === 'undefined') { 356 block = document; 357 } 358 else if (block.target || block.srcElement) { 359 // Event Got This 360 block = document; 361 } 362 363 var funx = ccms.widgets.installers; 364 for (var name in funx) { 365 if (ccms.hasOwnProperty(funx, name)) { 366 funx[name](block, optional_data); 367 } 368 } 369 370 return block; 371 }, 372 373 addClassInstaller: function(WidgetConstructor, classname, tagname) { 374 var name = classname; 375 var i = 1; 376 while (name in ccms.widgets.installers) { 377 name = classname + (++i); 378 } 379 ccms.widgets.addInstaller(name, 380 ccms.widgets.installNow.partial(WidgetConstructor, classname, tagname) 381 ); 382 }, 383 384 removeInstaller: function(name) { 385 delete ccms.widgets.installers[name]; 386 }, 387 388 installNow: function(WidgetConstructor, classname, tagname, rootelement) { 389 if (typeof rootelement === 'undefined' && window.opera) { 390 rootelement = document.body; 391 } 392 var elts = ccms.dom.getElementsByClassName(classname, tagname, rootelement); 393 for (var i = 0; i < elts.length; ++i) { 394 var v = new WidgetConstructor(elts[i]); 395 if (!WidgetConstructor.anonymouswidget) { 396 ccms.widgets.add(v, elts[i].id); 397 } 398 } 399 }, 400 401 install: function(WidgetConstructor, classname, tagname, rootelement) { 402 ccms.log.debug('Replace Me... ccms.widgets.install: ' + classname + ', ' + tagname + ', ' + rootelement); 403 ccms.log.debug(WidgetConstructor); 404 if (typeof rootelement === 'undefined') { 405 if (window.opera) { 406 rootelement = document.body; 407 } 408 else { 409 rootelement = document; 410 } 411 } 412 if (typeof tagname === 'undefined') {tagname = '*';} 413 ccms.event.onDOMReady(function() { 414 var elts = ccms.dom.getElementsByClassName(classname, tagname, rootelement); 415 for (var i = 0; i < elts.length; ++i) { 416 var id = elts[i].id; 417 if (id === '') {id = ccms.dom.generateId(); elts[i].setAttribute('id', id);} 418 ccms.widgets.add(new WidgetConstructor(elts[i]), id); 419 } 420 }); 421 } 422 }, 423 424 repr: function() { 425 var i; 426 var out = ''; 427 if (arguments.length === 1) { 428 var a = arguments[0]; 429 out += a + "\r\n"; 430 if (typeof a === 'object') { 431 for (i in a) { 432 if (ccms.hasOwnProperty(a, i)) { 433 out += i + ": " + a[i] + "\r\n"; 434 } 435 } 436 } 437 } 438 else { 439 for (i in arguments) { 440 if (ccms.hasOwnProperty(arguments, i)) { 441 out += ccms.repr(arguments[i]); 442 } 443 } 444 } 445 return out; 446 } 447 448 }; 449})()); 450 451ccms.extend(ccms.config, { 452 get: function(name, default_value) { 453 return (typeof ccms.config[name] === 'undefined') ? default_value : ccms.config[name]; 454 }, 455 set: function(name, value) { 456 if (name !== 'set' && name !== 'get') { 457 return ccms.config[name] = value; 458 } 459 } 460}); 461 462if (typeof jQuery !== 'undefined') { 463 464 (function($) { 465 466 $.cf = $.cf || {}; 467 468 if (typeof $.cf.installer === 'undefined') { 469 var installers = []; 470 471 $.cf.installer = function(/*(func | selector, func)*/) { 472 if (arguments.length === 1) { 473 installers.push(arguments[0]); 474 } 475 else { 476 var sel = arguments[0], func = arguments[1]; 477 installers.push(function($root) { 478 var $el = $root.find(sel); 479 if ($el.size()) { 480 return func($el); 481 } 482 }); 483 } 484 }; 485 486 $.fn.cf_install = function() { 487 this.each(function() { 488 var $this = $(this); 489 $.each(installers, function(i, func) { 490 func($this); 491 }); 492 }); 493 }; 494 } 495 496 $(document).ready(function() { 497 setTimeout(function() { 498 if (typeof $.cf.installer.version === 'undefined') { 499 $('body').cf_install(); 500 } 501 }, 1); 502 }); 503 504 })(jQuery); 505 506} 507 508 509/* 510 create an html module. 511 all options are optional :) 512 { 513 'className': 'element', // additional classes to give module 514 'header': '<h3>title</h3>', // html string or false to skip creating header 515 'body': '<p>something interesting</p>', // html string or false to skip creating body 516 'footer': '<p>footer stuff</p>', // html string or false to skip creating footer 517 } 518*/ 519ccms.html.Module = function(options) { 520 if (!ccms.html.isAvailable) ccms.html.use(); 521 522 if (typeof options === 'undefined') options = {}; 523 524 if (typeof options.className === 'undefined') {options.className = 'module';} 525 else {options.className = 'module ' + options.className;} 526 527 if (typeof options.id === 'undefined') {options.id = ccms.dom.generateId();} 528 529 var module = ccms.html.DIV({'class':options.className, 'id':options.id}); 530 531 if (options.header !== false) { 532 if (typeof options.css_hd === 'undefined') {options.css_hd = 'header';} 533 var head = ccms.html.DIV({'class':options.css_hd}); 534 head = module.appendChild(head); 535 if (typeof options.header === 'string') {head.innerHTML = options.header;} 536 else if (typeof options.header === 'object') {head.appendChild(options.header);} 537 } 538 if (options.body !== false) { 539 if (typeof options.css_bd === 'undefined') {options.css_bd = 'body';} 540 var body = ccms.html.DIV({'class':options.css_bd}); 541 body = module.appendChild(body); 542 if (typeof options.body === 'string') {body.innerHTML = options.body;} 543 else if (typeof options.body === 'object') {body.appendChild(options.body);} 544 } 545 if (options.footer !== false) { 546 if (typeof options.css_ft === 'undefined') {options.css_ft = 'footer';} 547 var foot = ccms.html.DIV({'class':options.css_ft}); 548 foot = module.appendChild(foot); 549 if (typeof options.footer === 'string') {foot.innerHTML = options.footer;} 550 else if (typeof options.footer === 'object') {foot.appendChild(options.footer);} 551 } 552 553 return module; 554}; 555 556ccms.html.MessageBox = function(options) { 557 if (typeof YAHOO === 'object' && typeof YAHOO.widget === 'object' && typeof YAHOO.widget.SimpleDialog === 'function') { 558 var p = ccms.update({ 559 width: "300px", 560 fixedcenter: true, 561 visible: false, 562 draggable: true, 563 close: options.close, 564 text: options.body, 565 icon: options.icon, 566 constraintoviewport: true, 567 buttons: [] 568 }, options); 569 p.buttons = []; 570 for (var k in options.buttons) { 571 if (ccms.hasOwnProperty(options.buttons, k)) { 572 var button = options.buttons[k]; 573 var callback = null; 574 var isDefault = false;
575 if (button !== null) { 576 if (typeof button === 'object') { 577 if (ccms.hasOwnProperty(button, 'label')) { 578 k = button.label; 579 } 580 if (ccms.hasOwnProperty(button, 'onclick')) { 581 callback = button.onclick; 582 } 583 if (ccms.hasOwnProperty(button, 'isDefault')) { 584 isDefault = button.isDefault; 585 } 586 } 587 else if (typeof button === 'function') { 588 callback = button; 589 } 590 } 591 if (callback === null) { 592 callback = function() {this.hide();}; 593 } 594 p.buttons.push({ 595 text:k, 596 handler:callback, 597 isDefault:isDefault 598 }); 599 } 600 } 601 var id = options.id || "MessageBox"; 602 var dlg = new YAHOO.widget.SimpleDialog(id, p); 603 if (options.header) dlg.setHeader(options.header); 604 if (options['class']) ccms.dom.addClass(dlg.element, options['class']); 605 dlg.render('content'); 606 return dlg; 607 } 608 else { 609 610 ccms.html.MessageBox.close = function(e) { 611 this.parentNode.removeChild(this); 612 }; 613 ccms.html.MessageBox.show = function() { 614 var parent = document.body; 615 if (typeof this.options.parent !== 'undefined') { 616 parent = $(this.options.parent); 617 } 618 parent.appendChild(this); 619 if (typeof this.options.center === 'string') { 620 var w = ccms.dom.getViewportWidth(); 621 var h = ccms.dom.getViewportHeight(); 622 var box = this; 623 if (this.options.backing) { 624 ccms.dom.setStyleObject(this, { 625 position:'absolute', 626 top:0, right:0, bottom:0, left:0 627 }); 628 box = box.firstChild; 629 } 630 if (this.options.center.indexOf('x') > -1) { 631 ccms.dom.setX(box, (w - box.offsetWidth) / 2); 632 } 633 if (this.options.center.indexOf('y') > -1) { 634 ccms.dom.setY(box, window.scrollY + ((h - box.offsetHeight) / 2) - 64); 635 } 636 if (this.options.shadow) { 637 ccms.dom.setStyle(box, 'height', '' + box.firstChild.offsetHeight + 'px'); 638 } 639 } 640 }; 641 642 if (!ccms.html.isAvailable) {ccms.html.use();} 643 644 if (typeof options === 'undefined') {options = {};} 645 646 if (typeof options.className === 'undefined') {options.className = 'ccmsMessageBox';} 647 if (typeof options.buttons === 'undefined') { 648 options.buttons = { 649 'Ok': null 650 }; 651 } 652 653 var callback; 654 var buttons = []; 655 var ul = ccms.html.UL({'class':'buttons'}), li; 656 for (var k in options.buttons) { 657 if (ccms.hasOwnProperty(options.buttons, k)) { 658 var klass = 'button'; 659 var button = options.buttons[k]; 660 callback = null; 661 if (button !== null) { 662 if (typeof button === 'object') { 663 if (ccms.hasOwnProperty(button, 'class')) { 664 klass += ' ' + button['class']; 665 } 666 if (ccms.hasOwnProperty(button, 'onclick')) { 667 callback = button.onclick; 668 } 669 } 670 else if (typeof button === 'function') 671 callback = button; 672 } 673 li = ccms.html.LI({'class':klass}, ccms.html.SPAN(k)); 674 ul.appendChild(li); 675 buttons.push([li, callback]); 676 } 677 } 678 679 options.footer = ccms.html.DIV(ul, ccms.html.DIV({'class':'clear'})); 680 var module = ccms.html.Module(options); 681 if (options.shadow) { 682 module = ccms.html.DIV({'class':'ccmsMessageBoxShadow'}, module); 683 } 684 if (options.backing) { 685 module = ccms.html.DIV({'class':'ccmsMessageBoxBacking'}, module); 686 } 687 if (options['class']) ccms.dom.addClass(module, options['class']); 688 var close = ccms.html.MessageBox.close.bind(module); 689 for (var i = 0; i < buttons.length; ++i) { 690 li = buttons[i][0]; 691 callback = buttons[i][1]; 692 if (callback === null) {callback = close;} 693 else if (typeof callback === 'function') {callback = callback.chain(close);} 694 ccms.event.attach(li, 'click', callback); 695 } 696 module.show = ccms.html.MessageBox.show.bind(module); 697 module.options = options; 698 return module; 699 700 } 701}; 702 703 704 705ccms.DomBuilder = { 706 IE_TRANSLATIONS : { 707 'class' : 'className', 708 'for' : 'htmlFor' 709 }, 710 ieAttrSet : function(a, i, el) { 711 var trans; 712 if ((trans = this.IE_TRANSLATIONS[i])) el[trans] = a[i]; 713 else if (i === 'style') el.style.cssText = a[i]; 714 else if (i.match(/^on/)) el[i] = new Function(a[i]); 715 else el.setAttribute(i, a[i]); 716 }, 717 apply : function(o) { 718 o = o || {}; 719 var els = ("p|div|span|strong|em|img|table|tr|td|th|thead|tbody|tfoot|pre|code|" + 720 "h1|h2|h3|h4|h5|h6|ul|ol|li|form|input|textarea|legend|fieldset|" + 721 "select|option|blockquote|cite|br|hr|dd|dl|dt|address|a|button|abbr|acronym|" + 722 "script|link|style|bdo|ins|del|object|param|
722col|colgroup|optgroup|caption|" + 723 "label|dfn|kbd|samp|var").split("|"); 724 var el, i=0; 725 while ((el = els[i++])) { 726 o[el.toUpperCase()] = ccms.DomBuilder.tagFunc(el); 727 } 728 return o; 729 }, 730 tagFunc : function(tag) { 731 return function() { 732 var a = arguments, at, ch; a.slice = [].slice; if (a.length>0) { 733 if (a[0].nodeName || typeof a[0] === "string") ch = a; 734 else { at = a[0]; ch = a.slice(1); } } 735 return ccms.DomBuilder.elem(tag, at, ch); 736 }; 737 }, 738 elem : function(e, a, c) { 739 a = a || {}; c = c || []; 740 var i, el = document.createElement(e), isIE = navigator.userAgent.match(/MSIE/); 741 for (i in a) { 742 if (typeof a[i] !== 'function') { 743 if (isIE) this.ieAttrSet(a, i, el); 744 else el.setAttribute(i, a[i]); 745 } 746 } 747 for (i=0; i<c.length; i++) { 748 if (typeof c[i] === 'string') c[i] = document.createTextNode(c[i]); 749 el.appendChild(c[i]); 750 } 751 return el; 752 } 753}; 754 755ccms.extend(ccms.log, (function() { 756 var responders = {}; 757 return { 758 debugging: false, 759 760 levels: { 761 FATAL: 50, 762 ERROR: 40, 763 WARNING: 30, 764 INFO: 20, 765 DEBUG: 10 766 }, 767 768 output: function() { 769 var args = ccms.arrayOf(arguments); 770 var level = ccms.shift(args); 771 if (typeof(responders[level]) === 'function') { 772 responders[level].apply(this, args); 773 } 774 }, 775 setup: function() { 776 for(var id in this.levels) { 777 var level = this.levels[id]; 778 responders[level] = this._debug; 779 this[id.toLowerCase()] = this.output.partial(level); 780 } 781 }, 782 addListener: function(level, responder) { 783 responders[level] = responder; 784 }, 785 _debug: function() { 786 if (this.debugging) { 787 var body = document.getElementsByTagName('body'); 788 if (body.length) { 789 body = body[0]; 790 } 791 else { 792 if (typeof console !== 'undefined' && console.debug) {console.debug('%o', arguments);} 793 else if (typeof opera !== 'undefined' && opera.postError) {opera.postError(ccms.repr(arguments));} 794 else {alert(ccms.repr(arguments));} 795 return; 796 } 797 if (!this._debug.output) { 798 this._debug.output = document.createElement('pre'); 799 this._debug.output.className = 'debugoutput'; 800 body.appendChild(this._debug.output); 801 } 802 this._debug.output.innerHTML += this.stringify.apply(this, arguments); 803 } 804 }, 805 stringify: function() { 806 var s = ''; 807 for (var i = 0; i < arguments.length; ++i) { 808 if (typeof arguments[i] === 'object') { 809 s += ccms.repr(arguments[i]) + "\r\n"; 810 } 811 else { 812 s += arguments[i] + "\n"; 813 } 814 } 815 return s; 816 } 817 }; 818})()); 819 820// convert a value to an integer, also returning zero if NaN (like PHP does). This is useful for more 821// than just strings, so it's not a method on String prototype. 822function intval(value) { 823 value = parseInt(value, 10); 824 if (isNaN(value)) { 825 value = 0; 826 } 827 return value; 828} 829 830// convert a value to a float, also returning zero if NaN (like PHP does). This is useful for more 831// than just strings, so it's not a method on String prototype. 832function floatval(value) { 833 value = parseFloat(value); 834 if (isNaN(value)) { 835 value = 0.0; 836 } 837 return value; 838} 839 840// Sugar! 841Function.prototype.method = function(name,fn) { 842 if (typeof this.prototype[name] == 'undefined') { 843 this.prototype[name] = fn; 844 } 845 return this; 846}; 847 848// callback fn can take these arguments, all optional: (propertyName, propertyValue) 849ccms.forEachProperty = function(thisObj, fn) { 850 for (var i in thisObj) { 851 if (ccms.hasOwnProperty(thisObj, i)) { 852 fn.call(thisObj, i, thisObj[i]); 853 } 854 } 855}; 856 857Array.method('forEach', function(fn, thisObj) { 858 var scope = thisObj || window; 859 for (var i = 0, j = this.length; i < j; ++i) { 860 fn.call(scope, this[i], i, this); 861 } 862}) 863.method('every', function(fn, thisObj) { 864 var scope = thisObj || window; 865 for (var i = 0, j = this.length; i < j; ++i) { 866 if (!fn.call(scope, this[i], i, this)) { 867 return false; 868 } 869 } 870 return true; 871}) 872.method('some', function(fn, thisObj) { 873 var scope = thisObj || window; 874 for (var i = 0, j = this.length; i < j; ++i) { 875 if (fn.call(scope, this[i], i, this)) { 876 return true; 877 } 878 } 879 return false;
880}) 881.method('map', function(fn, thisObj) { 882 var scope = thisObj || window; 883 var a = []; 884 for (var i = 0, j = this.length; i < j; ++i) { 885 a.push(fn.call(scope, this[i], i, this)); 886 } 887 return a; 888}) 889.method('filter', function(fn, thisObj) { 890 var scope = thisObj || window; 891 var a = []; 892 for (var i = 0, j = this.length; i < j; ++i) { 893 if (!fn.call(scope, this[i], i, this)) { 894 continue; 895 } 896 a.push(this[i]); 897 } 898 return a; 899}) 900.method('indexOf', function(el, start) { 901 start = start || 0; 902 for (var i = start, j = this.length; i < j; ++i) { 903 if (this[i] === el) { 904 return i; 905 } 906 } 907 return -1; 908}) 909.method('lastIndexOf', function(el, start) { 910 start = start || this.length; 911 if (start >= this.length) { 912 start = this.length; 913 } 914 if (start < 0) { 915 start = this.length + start; 916 } 917 for (var i = start; i >= 0; --i) { 918 if (this[i] === el) { 919 return i; 920 } 921 } 922 return -1; 923}); 924 925Array.prototype.foreach = Array.prototype.forEach; 926 927if (!Array.prototype.reduce) { 928 Array.method('reduce', function(fn, initial) { 929 var i = 0, r = initial; 930 if (typeof initial === 'undefined') r = this[i++]; 931 while (i < this.length) { 932 r = fn(r, this[i++]); 933 } 934 return r; 935 }); 936} 937 938// like indexOf but uses a callback test instead of equality test 939if (!Array.prototype.findBy) { 940 Array.method('findBy', function(fn, start) { 941 start = start || 0; 942 for (var i = start, j = this.length; i < j; ++i) { 943 if (fn(this[i])) { 944 return i; 945 } 946 } 947 return -1; 948 }); 949} 950 951if (!Array.prototype.unique) { 952 Array.method('unique', function() { 953 var a = []; 954 var l = this.length; 955 for (var i = 0; i < l; ++i) { 956 for (var j = i + 1; j < l; ++j) { 957 // If this[i] is found later in the array 958 if (this[i] === this[j]) 959 j = ++i; 960 } 961 a.push(this[i]); 962 } 963 return a; 964 }); 965} 966 967/* 968 * We add some useful methods to the String object 969 */ 970 971String.prototype.startswith = function(text) { 972 return this.substring(0, text.length) === text; 973}; 974String.prototype.endswith = function(text) { 975 return this.substring(this.length - text.length) === text; 976}; 977String.prototype.trim = function(chars) { 978 if (typeof chars === 'undefined') 979 chars = '\\s'; 980 return this.ltrim(chars).rtrim(chars); 981}; 982String.prototype.ltrim = function(chars) { 983 if (typeof chars === 'undefined') 984 chars = '\\s'; 985 var rx = new RegExp('^[' + chars + ']*(.*?)$', 'm'); 986 return this.replace(rx, '$1'); 987}; 988String.prototype.rtrim = function(chars) { 989 if (typeof chars === 'undefined') 990 chars = '\\s'; 991 var rx = new RegExp('^(.*?)[' + chars + ']*$', 'm'); 992 return this.replace(rx, '$1'); 993}; 994 995String.prototype.stripTags = function() { 996 return this.replace(/<\/?[^>]+>/gi, ''); 997}; 998 999String.prototype.escapeHTML = function() { 1000 var div = document.createElement('div'); 1001 var text = document.createTextNode(this); 1002 div.appendChild(text); 1003 return div.innerHTML; 1004}; 1005 1006String.prototype.unescapeHTML = function() { 1007 var div = document.createElement('div'); 1008 div.innerHTML = this.stripTags(); 1009 return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; 1010}; 1011 1012String.prototype.parseHTML = function() { 1013 var div = document.createElement('div'); 1014 div.innerHTML = this.trim(); 1015 return div.firstChild; 1016}; 1017 1018String.prototype.parseJSON = function () { 1019 if (JSON) return JSON.parse(this.toString()); 1020 return eval('(' + this + ')'); 1021}; 1022 1023// Function.prototype.bind = function() { 1024// var __method = this; 1025// var args = ccms.arrayOf(arguments); 1026// var object = ccms.shift(args); 1027// return function() { 1028// return __method.apply(object, args.concat(ccms.arrayOf(arguments))); 1029// }; 1030// }; 1031Function.prototype.partial = function() { 1032 var __method = this; 1033 var args = ccms.arrayOf(arguments); 1034 return function() { 1035 return __method.apply(this, args.concat(ccms.arrayOf(arguments))); 1036 }; 1037}; 1038Function.prototype.rpartial = function() { 1039 var __method = this; 1040 var args = ccms.arrayOf(arguments); 1041 return function() { 1042 return __method.apply(this, ccms.arrayOf(arguments).concat(args)); 1043 }; 1044}; 1045Function.prototype.chain = function() { 1046 var __method = this; 1047 var funcs = ccms.arrayOf(arguments); 1048 funcs.unshift(__method); 1049 return function() { 1050 var rv; 1051 var args = ccms.arrayOf(arguments); 1052 for (var i = 0; i < funcs.length; ++i) { 1053 rv = funcs[i].apply(this, args); 1054 if (false === rv) return false;
1055 } 1056 return rv; 1057 }; 1058}; 1059 1060// from: http://beppu.lbox.org/articles/2006/09/06/actsasaspect 1061function actsAsAspect(object) { 1062 object.yield = null; 1063 object.rv = {}; 1064 object.before = function(method, f) { 1065 var original = eval("this." + method); 1066 this[method] = function() { 1067 f.apply(this, arguments); 1068 return original.apply(this, arguments); 1069 }; 1070 }; 1071 object.after = function(method, f) { 1072 var original = eval("this." + method); 1073 this[method] = function() { 1074 this.rv[method] = original.apply(this, arguments); 1075 return f.apply(this, arguments); 1076 }; 1077 }; 1078 object.around = function(method, f) { 1079 var original = eval("this." + method); 1080 this[method] = function() { 1081 this.yield = original; 1082 return f.apply(this, arguments); 1083 }; 1084 }; 1085 return object; 1086} 1087 1088String.prototype.camelize = function() { 1089 var oStringList = this.split('-'); 1090 if (oStringList.length === 1) return oStringList[0]; 1091 1092 var camelizedString = this.indexOf('-') === 0 1093 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) 1094 : oStringList[0]; 1095 1096 for (var i = 1, len = oStringList.length; i < len; i++) { 1097 var s = oStringList[i]; 1098 camelizedString += s.charAt(0).toUpperCase() + s.substring(1); 1099 } 1100 1101 return camelizedString; 1102}; 1103 1104 1105ccms.URL = function(url) { 1106 this._fields = {'username' : 4, 'password' : 5, 'port' : 7, 'protocol' : 2, 'scheme': 2, 'host' : 6, 'path' : 8, 'url' : 0, 'query' : 9, 'fragment' : 10}; 1107 this._regex = /^((\w+):\/\/)?((\w+):?(\w+)?@)?([^\/\?:]+):?(\d+)?(\/?[^\?#]+)?\??([^#]+)?#?(\w*)/; 1108 if (typeof url !== 'undefined') 1109 this.parse(url); 1110}; 1111 1112ccms.URL.prototype.parse = function(url) { 1113 var r = this._regex.exec(url); 1114 if (!r) throw "ccms.URL::parse -> Invalid URL"; 1115 for (var f in this._fields) { 1116 if (typeof r[this._fields[f]] === 'undefined') this[f] = ''; 1117 else this[f] = r[this._fields[f]]; 1118 } 1119 this.parseQuery(this.query); 1120}; 1121ccms.URL.prototype.parseQuery = function(qs) { 1122 this.query = {}; 1123 var params = qs.split('&'); 1124 for (var i = 0; i < params.length; ++i) { 1125 if (params[i].length) { 1126 var kv = params[i].split("="); 1127 if (kv.length) this.query[kv[0]] = kv[1]; 1128 } 1129 } 1130}; 1131ccms.URL.prototype.appendPath = function(path) { 1132 this.path = this.path.rtrim('/') + '/' + path.ltrim('/'); 1133 return this.path; 1134}; 1135ccms.URL.prototype.prependPath = function(path) { 1136 this.path = '/' + path.trim('/') + '/' + this.path.ltrim('/'); 1137 return this.path; 1138}; 1139ccms.URL.prototype.pop = function() { 1140 this.path = this.path.replace(/\/[^\/]+\/?$/, ''); 1141}; 1142ccms.URL.prototype.localURL = function() { 1143 var s = ''; 1144 if (this.path) s += this.path; 1145 if (ccms.keysOf(this.query).length > 0) s += '?' + urlencode(this.query); 1146 if (this.fragment !== '') s += '#' + this.fragment; 1147 return s; 1148}; 1149ccms.URL.prototype.toString = function() { 1150 var s = ''; 1151 if (this.protocol) s += this.protocol + '://'; 1152 if (this.username || this.password) s += this.username + ':' + this.password + '@'; 1153 if (this.host) s += this.host; 1154 if (this.port) s += ':' + this.port; 1155 return s + this.localURL(); 1156}; 1157 1158ccms.URL.open = function(url, new_window /*=false*/) { 1159 if (typeof new_window === 'undefined') new_window = false; 1160 if (typeof url === 'object') url = url.toString(); 1161 if (!url.match(/^(\w+:\/\/|[\/\.])/)) url = 'http://' + url; 1162 if (new_window) return window.open(url); 1163 document.location.href = url; 1164 return true; 1165}; 1166 1167ccms.URL.stripHost = function(url) { 1168 return url.replace(/^(\w+:\/\/[^\/]+)(.+)$/, '$2'); 1169}; 1170 1171// url encode all function arguments. if argument is an object, encode it's properties. e.g: 1172// urlencode({a:1, b:"this/thing"}, c, d, {e:3}) returns 'a=1&b=this%2Fthing&c&d&e=3' 1173function urlencode() { 1174 var output = []; 1175 for (var i = 0; i < arguments.length; ++i) { 1176 var arg = arguments[i]; 1177 if (typeof arg === 'object') { 1178 for (var j in arg) { 1179 if (ccms.hasOwnProperty(arg, j)) { 1180 if (typeof arg[j] === 'object') { 1181 for (var k in arg[j]) { 1182 if (ccms.hasOwnProperty(arg[j], k)) { 1183 output[output.length] = encodeURIComponent(j) + '=' + encodeURIComponent(arg[j][k]); 1184 } 1185 } 1186 } 1187 else { 1188 output[output.length] = encodeURIComponent(j) + '=' + encodeURIComponent(arg[j]); 1189 } 1190 } 1191 } 1192 } 1193 else { 1194 output[output.length] = encodeURIComponent(arg); 1195 } 1196 } 1197 return output.join('&'); 1198} 1199 1200// make a query string using the urlencode function 1201function ccmsQS(args) { 1202 return '?' + urlencode(args); 1203} 1204function ccmsQSAppend(url, args) { 1205 return url + (url.indexOf('?') > 0 ? '&' : '?') + urlencode(args); 1206} 1207 1208function ccmsFormData(formId, return_these_too) { 1209 var oForm = $(formId); 1210 if (!oForm) return false;
1211 var oElement, oName, oValue, oDisabled; 1212 var hasSubmit = false; 1213 var out, i, j; 1214 if (typeof return_these_too === 'undefined') out = {}; 1215 else out = ccms.cloneOf(return_these_too); 1216 // Iterate over the form elements collection to construct the label-value pairs. 1217 for (i=0; i<oForm.elements.length; i++){ 1218 oDisabled = oForm.elements[i].disabled; 1219 // If the name attribute is not populated, the form field's 1220 // value will not be submitted. 1221 if(oForm.elements[i].name !== ''){ 1222 oElement = oForm.elements[i]; 1223 oName = oForm.elements[i].name; 1224 oValue = oForm.elements[i].value; 1225 } 1226 // Do not submit fields that are disabled. 1227 if(!oDisabled && oElement) 1228 { 1229 switch (oElement.type) 1230 { 1231 case 'select-one': 1232 for(j=0; j<oElement.options.length; j++){ 1233 if(oElement.options[j].selected){ 1234 // out[oName] = oElement.options[j].value || oElement.options[j].text; 1235 out[oName] = oElement.options[j].value; 1236 break; 1237 } 1238 } 1239 break; 1240 case 'select-multiple': 1241 for(j=0; j<oElement.options.length; j++){ 1242 if(oElement.options[j].selected){ 1243 if (typeof out[oName] === 'undefined') out[oName] = []; 1244 // out[oName][out[oName].length] = oElement.options[j].value || oElement.options[j].text; 1245 out[oName][out[oName].length] = oElement.options[j].value; 1246 } 1247 } 1248 break; 1249 case 'radio': 1250 case 'checkbox': 1251 if(oElement.checked){ 1252 out[oName] = oValue; 1253 } 1254 break; 1255 case 'file': 1256 // this.sFormData += encodeURIComponent(oName) + '=' + encodeURIComponent(oValue) + '&'; 1257 // stub case as XMLHttpRequest will only send the file path as a string. 1258 case undefined: 1259 // stub case for fieldset element which returns undefined. 1260 case 'reset': 1261 // stub case for input type reset button. 1262 case 'button': 1263 // stub case for input type button elements. 1264 break; 1265 case 'submit': 1266 if(hasSubmit === false){ 1267 hasSubmit = true; 1268 out[oName] = oValue; 1269 } 1270 break; 1271 default: 1272 if (oName.substring(oName.length - 2) === '[]') { 1273 if (typeof out[oName] === 'undefined') out[oName] = []; 1274 out[oName][out[oName].length] = oValue; 1275 } 1276 else 1277 out[oName] = oValue; 1278 break; 1279 } 1280 } 1281 } 1282 return out; 1283} 1284 1285ccms.async.when = function(condition, callback, timeout) { 1286 return new ccms.async.Poller(condition, callback, timeout); 1287}; 1288 1289ccms.async.Poller = ccmsWaiter = function(condition, callback, timeout) { 1290 timeout = timeout || 500; 1291 var interval = false; 1292 1293 function test() { 1294 if (condition()) { 1295 window.clearInterval(interval); 1296 interval = false; 1297 callback(); 1298 } 1299 } 1300 1301 self.start = function() { 1302 if (interval === false) 1303 interval = window.setInterval(test, timeout); 1304 }; 1305 1306 self.cancel = function() { 1307 if (interval !== false) { 1308 window.clearInterval(interval); 1309 interval = false; 1310 } 1311 }; 1312 1313 self.start(); 1314}; 1315 1316// Asynchronous stuff (ajax wrappers, timed events) 1317ccms.extend(ccms.async, { 1318 1319 // create an XMLHttpRequest object 1320 getXMLHttpRequest: function () { 1321 var self = arguments.callee; 1322 if (!self.XMLHttpRequest) { 1323 var tryThese = [ 1324 function () {return new XMLHttpRequest();}, 1325 function () {return new ActiveXObject('Msxml2.XMLHTTP.6.0');}, 1326 function () {return new ActiveXObject('Msxml2.XMLHTTP');}, 1327 function () {return new ActiveXObject('Microsoft.XMLHTTP');}, 1328 function () {return new ActiveXObject('Msxml2.XMLHTTP.4.0');}, 1329 function () {throw new Exception("Browser does not support XMLHttpRequest");} 1330 ]; 1331 for (var i = 0; i < tryThese.length; i++) { 1332 var func = tryThese[i]; 1333 try { 1334 self.XMLHttpRequest = func; 1335 return func(); 1336 } catch (e) { 1337 // pass 1338 } 1339 } 1340 } 1341 return self.XMLHttpRequest(); 1342 }, 1343 1344 // to use, set {..., HttpFactory:ccms.async.CachingXMLHttpRequest} in http() args 1345 CachingXMLHttpRequest: function() { 1346 return new ccms.async._CachingXMLHttpRequest(); 1347 }, 1348 1349 // begin an async HTTP call. args should be a configuration object, e.g: 1350 // {method:'GET', url:'/fetch/this', onSuccess: successcallback, onFailure: failcallback, parameters:{userid:1234}} 1351 // method, onFailure, and parameters are optional, they default to GET, console.log, and {}. 1352 // call .cancel() on the return value to abort the request (doesn't work in all browsers). 1353 http: function(args) { 1354 var settings = ccms.extend({method:'GET', async:(args.onSuccess?true:false), onFailure:ccms.async.onHTTPError}, args); 1355 settings.cancelled = false;
1356 settings.cancel = function() {settings.cancelled = true;}; 1357 settings.method = settings.method.toUpperCase(); 1358 var http; 1359 if (typeof settings.HttpFactory === 'function') http = settings.HttpFactory(); 1360 else http = this.getXMLHttpRequest(); 1361 var postdata = null; 1362 1363 // If there's a fragment, remove it 1364 var p; 1365 if ((p = settings.url.indexOf('#')) !== -1) { 1366 settings.url = settings.url.substring(0, p); 1367 } 1368 1369 if (settings.parameters) { 1370 if (settings.method === 'POST') { 1371 postdata = urlencode(settings.parameters); 1372 } 1373 else if (settings.method === 'GET' || settings.method === 'HEAD') { 1374 settings.url += (settings.url.indexOf('?') > 0 ? '&' : '?') + urlencode(settings.parameters); 1375 } 1376 } 1377 if (settings.method === 'GET' && settings.url.length > 2048) { 1378 // ie max path length is 2048 characters. use post instead in that case with ccms workaround hack 1379 settings.method = 'POST'; 1380 1381 if (typeof settings.HttpFactory === 'function') 1382 // require normal http request for now, until CachingXMLHttpRequest supports POST 1383 http = this.getXMLHttpRequest(); 1384 1385 p = settings.url.indexOf('?'); 1386 postdata = urlencode({'X-CCMS-TUNNELLED-GET':settings.url.substring(p + 1)}); 1387 1388 http.open(settings.method, settings.url.substring(0, p), settings.async); 1389 } 1390 else { 1391 http.open(settings.method, settings.url, settings.async); 1392 } 1393 if (postdata) { 1394 http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 1395 } 1396 http.send(postdata); 1397 if (settings.async) { 1398 http.onreadystatechange = function() { 1399 if (settings.cancelled) { 1400 try { 1401 // unset this to fix a firefox memleak - inside try/catch cos i.e. throws type mismatch... 1402 http.onreadystatechange = null; 1403 } catch(e) {;} 1404 return; 1405 } 1406 if (http.readyState === 4){ 1407 if (http.status === 200 || http.status === 304) { 1408 if (settings.onSuccess) { 1409 if (settings.parseJSON) settings.onSuccess.bind(settings)(http.responseText.parseJSON()); 1410 else settings.onSuccess.bind(settings)(http); 1411 } 1412 } 1413 else { 1414 if (settings.onFailure) { 1415 if (settings.parseJSON) settings.onFailure.bind(settings)(http.responseText.parseJSON()); 1416 else settings.onFailure.bind(settings)(http); 1417 } 1418 } 1419 try { 1420 http.onreadystatechange = null; 1421 } catch(e) {;} 1422 } 1423 }; 1424 } 1425 else { 1426 return http.responseText; 1427 } 1428 return settings; 1429 }, 1430 1431 submitForm: function(formid, args) { 1432 var oForm = $(formid); 1433 if (typeof args === 'undefined') args = {}; 1434 if (typeof jQuery !== 'undefined' && jQuery.fn.ajaxSubmit && jQuery(oForm).find('input[type="file"]').size()) { 1435 var p = { 1436 data: args.parameters, 1437 success: function(resp, status) { 1438 if (status == 'success') args.onSuccess && args.onSuccess(resp); 1439 else args.onHTTPError && args.onHTTPError(resp); 1440 } 1441 }; 1442 jQuery(oForm).ajaxSubmit(p); 1443 } 1444 else { 1445 if (typeof args.parameters === 'object') 1446 args.parameters = ccms.extend(args.parameters, ccmsFormData(oForm)); 1447 else 1448 args.parameters = ccmsFormData(oForm); 1449 ccms.extend(args, { 1450 'url' : oForm.action, 1451 'method' : oForm.method 1452 }); 1453 ccms.async.http(args); 1454 } 1455 }, 1456 1457 onHTTPError: function(req) { 1458 ccms.log.debug('HTTP Error: ' + req.status + ' ' + req.statusText + "\n" + req.responseText); 1459 }, 1460 1461 after: function(timeout, callback) { 1462 return setTimeout(callback, timeout); 1463 }, 1464 cancelTimeout: function(timeout_id) { 1465 return clearTimeout(timeout_id); 1466 }, 1467 1468 1469 _cache: {}, 1470 1471 _CachingXMLHttpRequest: function() { 1472 var http = null, cache = null, asynchronous = false, key; 1473 var self = this; 1474 1475 this.onreadystatechange = null; 1476 1477 this.open = function(method, url, async) { 1478 asynchronous = async; 1479 key = null; 1480 if (method === 'GET') { 1481 key = method + url + async; 1482 if (typeof ccms.async._cache[key] === 'object') { 1483 cache = ccms.async._cache[key]; 1484 if (typeof console === 'object' && typeof console.log === 'function') { 1485 if (typeof console.group === 'function') console.group("GET (ccms cached) " + url); 1486 console.log(cache); 1487 if (typeof console.groupEnd === 'function') console.groupEnd(); 1488 } 1489 return; 1490 } 1491 } 1492 if (/*@cc_on!@*/false) { 1493 url = ccmsQSAppend(url, {'cachebust':(new Date()).getTime()}); 1494 } 1495 http = ccms.async.getXMLHttpRequest(); 1496 http.open(method, url, async); 1497 }; 1498
1499 this.send = function(data) { 1500 if (cache === null) { 1501 if (asynchronous) { 1502 http.onreadystatechange = _onreadystatechange.bind(this); 1503 http.send(data); 1504 return null; 1505 } 1506 else { 1507 cache = http.send(data); 1508 ccms.async._cache[key] = cache; 1509 return cache; 1510 } 1511 } 1512 else if (asynchronous) { 1513 ccms.async.after(1, _cached_onreadystatechange.bind(this)); 1514 return null; 1515 } 1516 else { 1517 return cache; 1518 } 1519 }; 1520 1521 function _cached_onreadystatechange() { 1522 ccms.extend(self, cache); 1523 self.onreadystatechange(cache); 1524 } 1525 1526 function _onreadystatechange() { 1527 self.readyState = http.readyState; 1528 if (http.readyState === 4 && http.status === 200) { 1529 self.status = http.status; 1530 try { 1531 http.onreadystatechange = null; 1532 } 1533 catch(e) {;} 1534 cache = { 1535 status: http.status, 1536 statusText: http.statusText, 1537 readyState: http.readyState, 1538 responseText: http.responseText 1539 }; 1540 ccms.extend(self, cache); 1541 ccms.async._cache[key] = cache; 1542 self.onreadystatechange(cache); 1543 } 1544 else if (http.readyState === 4 && self.onreadystatechange !== null) { 1545 self.responseText = http.responseText; 1546 self.onreadystatechange(http); 1547 } 1548 } 1549 } 1550 1551 1552}); 1553 1554ccms.async.jsr = (function() { 1555 var count = 0; 1556 var head = document.getElementsByTagName("head").item(0); 1557 return { 1558 callbacks: {}, 1559 create_cb: function(onSuccess) { 1560 var c = count; 1561 this.callbacks[count] = function(json) { 1562 var s = $("ccmsjsr" + c); 1563 s.parentNode.removeChild(s); // can't remove from head here cos IE6 inserts the script tags into base tag! 1564 delete ccms.async.jsr.callbacks[c]; 1565 return onSuccess(json); 1566 }; 1567 return this.callbacks[count]; 1568 }, 1569 call: function(settings) { 1570 if (settings.parameters) { 1571 settings.url += (settings.url.indexOf('?') > 0 ? '&' : '?') + urlencode(settings.parameters); 1572 } 1573 this.create_cb(settings.onSuccess); 1574 settings.url += (settings.url.indexOf('?') > 0 ? '&' : '?') + urlencode({callback: 'ccms.async.jsr.callbacks[' + count + ']'}); 1575 if (!settings.allow_cache) settings.url += '&noCacheIE=' + (new Date()).getTime(); 1576 var scriptObj = document.createElement("script"); 1577 scriptObj.setAttribute("type", "text/javascript"); 1578 scriptObj.setAttribute("src", settings.url); 1579 scriptObj.setAttribute("id", "ccmsjsr" + count); 1580 head.appendChild(scriptObj); 1581 ++count; 1582 if (typeof console !== 'undefined' && typeof console.log === 'function') console.log(settings.url); 1583 } 1584 }; 1585})(); 1586 1587ccms.async.processJSON = function(json) { 1588 ccms.ApiLinks.addMany(json.links); 1589 if (typeof json.js !== 'undefined') { 1590 json.js.foreach(ccms.require); 1591 } 1592}; 1593 1594ccms.async.trapMultipleSubmits = function(root_element) { 1595 ccms.event.attach(root_element, 'click', function(e) { 1596 var target = ccms.event.getTarget(e); 1597 if (target.type === 'submit') { 1598 ccms.dom.getElementsBy(function(node) { 1599 return node.type === 'submit' && node.name !== target.name; 1600 }, 'input', root_element).foreach(function(node) {node.value = ''; node.name = '';}); 1601 } 1602 }); 1603}; 1604 1605ccms.async.searchBox = (function() { 1606 return { 1607 config: { 1608 AJAX_KEYPRESS_DELAY: 0.5 1609 }, 1610 1611 isIgnoreKey: function(nKeyCode) { 1612 if ((nKeyCode == 9) || (nKeyCode == 13) || // tab, enter 1613 (nKeyCode == 16) || (nKeyCode == 17) || // shift, ctl 1614 (nKeyCode >= 18 && nKeyCode <= 20) || // alt,pause/break,caps lock 1615 (nKeyCode == 27) || // esc 1616 (nKeyCode >= 33 && nKeyCode <= 35) || // page up,page down,end 1617 (nKeyCode >= 36 && nKeyCode <= 40) || // home,left,up, right, down 1618 (nKeyCode >= 44 && nKeyCode <= 45)) { // print screen,insert 1619 return true; 1620 } 1621 return false; 1622 }, 1623 1624 KeyMonitor: function(handler) { 1625 var _timer_id = -1; 1626 this.onKey = function(e) { 1627 alert(1); 1628 if (_timer_id != -1) { 1629 ccms.async.cancelTimeout(_timer_id); 1630 _timer_id = -1; 1631 } 1632 if (e.keyCode == 13 || !ccms.async.searchBox.isIgnoreKey(e.keyCode)) { 1633 _timer_id = ccms.async.after(ccms.async.searchBox.config.AJAX_KEYPRESS_DELAY * 1000, function() { 1634 _timer_id = -1; 1635 handler.startSearch(); 1636 }); 1637 if (e.keyCode == 13) return ccms.event.killEvent(e); 1638 } 1639 }; 1640 //ccms.event.attach(handler.getInputField(), 'keydown', this.onKey); 1641 }, 1642 1643 SimpleHandler: function(text_input, api_settings) { 1644 this.getInputField = function() {return text_input;}; 1645 this.startSearch = function() { 1646 if (text_input.value != '') { 1647 if (typeof api_settings.parameters != 'object') api_settings.parameters = {}; 1648 api_settings.parameters.q = text_input.value; 1649 ccms.async.http(api_settings); 1650 } 1651 }; 1652 this.mon = new ccms.async.searchBox.KeyMonitor(this); 1653 } 1654 }; 1655})(); 1656 1657 1658/* 1659 * Event manager - register events in a x-browser fashion, with workarounds for IE memory leaks. 1660 */ 1661if (typeof YAHOO !== 'undefined' && typeof YAHOO.util !== 'undefined') { 1662 if (typeof YAHOO.util.Event !== 'undefined') { 1663 ccms.event = YAHOO.util.Event; 1664 ccms.event.CustomEvent = YAHOO.util.CustomEvent; 1665 ccms.event.addLoadEvent = function(handler, oScope, bOverride) {return YAHOO.util.Event.addListener(window, 'load', handler, oScope, bOverride);}; 1666 ccms.event.attach = ccms.event.addListener; 1667 ccms.event.detach = ccms.event.removeListener; 1668 ccms.event.killEvent = function(e) {ccms.event.stopEvent(e); return false;}; 1669 ccms.event.YAHOO_onDOMReady = ccms.event.onDOMReady; 1670 ccms.event.onDOMReady = function(callback, data, scope) { 1671 // wrap callback function cos onDOMReady eats exceptions 1672 return YAHOO.util.Event.YAHOO_onDOMReady(function() { 1673 try { 1674 callback.apply(this, arguments); 1675 } 1676 catch(ex) { 1677 if (typeof console === 'object' && typeof console.error === 'function') { 1678 if (typeof ex.stack !== 'undefined') { 1679 console.error(ex.message, ex.stack); 1680 } 1681 else { 1682 console.error(ex); 1683 } 1684 } 1685 else ccms.debug.error(ex); 1686 throw ex; 1687 } 1688 }, data, scope); 1689 }; 1690 } 1691 else {
1692 document.write('<b>ccms.event unavailable, because the YAHOO Event library has not been included before ccms.js</b>'); 1693 } 1694 if (typeof YAHOO.util.Dom !== 'undefined') { 1695 ccms.dom = YAHOO.util.Dom; 1696 } 1697} 1698else { 1699 document.write('<b>ccms.dom and ccms.event unavailable, because the YAHOO libraries have not been included</b>'); 1700} 1701 1702ccms.event.onDOMReady(function() { 1703 if (typeof jQuery !== 'undefined') jQuery.noConflict(); 1704 ccms.dom.ready = true; 1705}); 1706 1707 1708 1709/* 1710 global events system, allows decoupled notifications between different components. 1711 basic example: 1712 1713 ccms.events.subscribe('video.play', function(ev_name, ev_args) {alert('Playing!');}); 1714 1715 in "video" component: 1716 ccms.events.add('video.play'); 1717 when play pressed: 1718 ccms.events.fire('video.play'); 1719*/ 1720ccms.events = (function() { 1721 var events = {}; 1722 var subs = {}; 1723 1724 return { 1725 subscribe: function(p_type, op_fn, p_obj, p_override) { 1726 var p_fn = function() { 1727 try { 1728 return op_fn.apply(this, arguments); 1729 } 1730 catch(e) { 1731 console.log(e); 1732 } 1733 return null; 1734 }; 1735 var ce = events[p_type]; 1736 if (ce) { 1737 ce.subscribe(p_fn, p_obj, p_override); 1738 } 1739 else { 1740 if (!subs[p_type]) { 1741 subs[p_type] = []; 1742 } 1743 subs[p_type].push({ 1744 fn: p_fn, 1745 obj: p_obj, 1746 override: p_override 1747 }); 1748 } 1749 }, 1750 unsubscribe: function(p_type, p_fn, p_obj) { 1751 var ce = events[p_type]; 1752 if (ce) { 1753 return ce.unsubscribe(p_fn, p_obj); 1754 } 1755 else { 1756 return false; 1757 } 1758 }, 1759 add: function(p_type, p_config) { 1760 var opts = p_config || {}; 1761
1762 if (events[p_type]) { 1763 ; 1764 } 1765 else { 1766 var scope = opts.scope || this; 1767 var silent = opts.silent || null; 1768 var ce = new ccms.event.CustomEvent(p_type, scope, silent); 1769 events[p_type] = ce; 1770 if (opts.onSubscribeCallback) { 1771 ce.subscribeEvent.subscribe(opts.onSubscribeCallback); 1772 } 1773 var qs = subs[p_type]; 1774 if (qs) { 1775 for (var i=0; i<qs.length; ++i) { 1776 ce.subscribe(qs[i].fn, qs[i].obj, qs[i].override); 1777 } 1778 } 1779 } 1780 1781 return events[p_type]; 1782 }, 1783 fire: function(p_type, arg1, arg2, etc) { 1784 var ce = events[p_type]; 1785 if (ce) { 1786 var args = []; 1787 for (var i=1; i<arguments.length; ++i) { 1788 args.push(arguments[i]); 1789 } 1790 return ce.fire.apply(ce, args); 1791 } 1792 else { 1793 return null; 1794 } 1795 } 1796 }; 1797})(); 1798 1799 1800// The MAGIC $ function :) 1801// usage: 1802// $('foo') returns the node with id='foo' 1803// $('foo', 'bar', 'oof') returns an array of the elements with specified ids 1804// if parameter(s) is (are) already objects they're just returned. 1805function $() { 1806 var elements = []; 1807 for (var i = 0; i < arguments.length; i++) { 1808 var element = arguments[i]; 1809 if (typeof element === 'string') 1810 element = document.getElementById(element); 1811 if (arguments.length === 1) 1812 return element; 1813 elements[elements.length] = element; 1814 } 1815 return elements; 1816}; 1817 1818/* 1819 * ccms DOM helpers: 1820 */ 1821 1822if (!window.Node || !window.Node.ELEMENT_NODE) { 1823 var Node = { 1824 ELEMENT_NODE: 1, ATTRIBUTE_NODE: 2, TEXT_NODE: 3, CDATA_SECTION_NODE: 4, ENTITY_REFERENCE_NODE: 5, 1825 ENTITY_NODE: 6, PROCESSING_INSTRUCTION_NODE: 7, COMMENT_NODE: 8, DOCUMENT_NODE: 9, DOCUMENT_TYPE_NODE: 10, 1826 DOCUMENT_FRAGMENT_NODE: 11, NOTATION_NODE: 12 1827 }; 1828} 1829 1830ccms.extend(ccms.dom, { 1831 // toggle a nodes visibility 1832 toggle: function(e, style) { 1833 if (typeof e === 'string') 1834 e = $(e); 1835 if (e.style.display !== 'none' ) { 1836 e.style.display = 'none'; 1837 } 1838 else if (style) e.style.display = style; 1839 else { 1840 e.style.display = ''; 1841 } 1842 }, 1843 isHidden: function(e) { 1844 if (typeof e === 'string') e = $(e); 1845 return (e.style.display === 'none'); 1846 }, 1847 // hide a node 1848 hide: function(e) { 1849 if (typeof e === 'string') 1850 e = $(e); 1851 e.style.display = 'none'; 1852 }, 1853 // show a node 1854 show: function(e, style) { 1855 if (typeof e === 'string') 1856 e = $(e); 1857 if (style) e.style.display = style; 1858 else e.style.display = ''; 1859 }, 1860 refresh: function(e) { 1861 if (typeof e === 'undefined') 1862 e = document.body; 1863 else if (typeof e === 'string') 1864 e = $(e); 1865 1866 ccms.dom.hide(e); 1867 ccms.dom.show(e); 1868 }, 1869 // check a node is visible by checking visbility / display of self and ancestors 1870 isVisible: function(el, root) { 1871 if (typeof root == 'undefined') root = document.body; 1872 while (el && el !== root) { 1873 if (ccms.dom.getStyle(el, 'display') == 'none' || ccms.dom.getStyle(el, 'visibility') == 'hidden') { 1874 return false; 1875 } 1876 el = el.parentNode; 1877 } 1878 return true; 1879 }, 1880 // swap two nodes 1881 swapNode: function(n1, n2) { 1882 if (n1.swapNode) { // ie has native swapNode support 1883 n1.swapNode(n2); 1884 } 1885 else { 1886 var p = n2.parentNode; 1887 var s = n2.nextSibling; 1888 1889 if (s == n1) { 1890 p.insertBefore(n1, n2); 1891 } 1892 else if (n2 == n1.nextSibling) { 1893 p.insertBefore(n2, n1); 1894 } 1895 else { 1896 n1.parentNode.replaceChild(n2, n1); 1897 p.insertBefore(n1, s); 1898 } 1899 } 1900 }, 1901 // insert a node after another 1902 insertAfter: function(nInsert, nPrevious) { 1903 var nParent = nPrevious.parentNode; 1904 if (nPrevious.nextSibling) { 1905 nInsert = nParent.insertBefore(nInsert, nPrevious.nextSibling); 1906 } 1907 else { 1908 nInsert = nParent.appendChild(nInsert); 1909 } 1910 return nInsert; 1911 }, 1912 // get an element's ancestor by tag and/or class name 1913 getParentByClassName: function(oElm, strTagName, strClassName) { 1914 var tf = ccms.dom.hasTagName.rpartial(strTagName.toLowerCase()); 1915 var f; 1916 if (typeof strClassName === 'string') { 1917 var cf = ccms.dom.hasClass.rpartial(strClassName); 1918 f = function(n) {return tf(n) && cf(n);}; 1919 } 1920 else { 1921 f = function(n) {return tf(n);}; 1922 } 1923 return ccms.dom.getAncestor(oElm, f); 1924 }, 1925 1926 getSelfOrAncestorBy: function(callback, node) { 1927 while(node) { 1928 if (node.nodeType === Node.ELEMENT_NODE) { 1929 if (callback(node)) 1930 break; 1931 } 1932 node = node.parentNode; 1933 } 1934 return node; 1935 }, 1936 1937 getElementsByClassNameRE: function(regex, strTagName, oElm) { 1938 if (typeof(regex) == 'string') regex = RegExp(regex); 1939 return ccms.dom.getElementsBy(function(node) {return node.className.match(regex);}, strTagName, oElm); 1940 }, 1941 1942 getElementByClassName: function(strClassName, strTagName, oElm) { 1943 if (window.opera) { 1944 if (typeof oElm === 'undefined') oElm = document; 1945 if (oElm.nodeType === Node.DOCUMENT_NODE) oElm = oElm.body; 1946 } 1947 return ccms.dom.getElementsByClassName(strClassName, strTagName, oElm)[0]; 1948 }, 1949 1950 getLabelFor: function(oElm) { 1951 var oLabel = null; 1952 1953 if (typeof oElm === 'string') 1954 oElm = $(oElm); 1955 1956 if ((oLabel = ccms.dom.getParentByClassName(oElm, 'label'))) 1957 return oLabel; 1958 else if (oElm.getAttribute('id')) 1959 return ccms.dom.getElementsBy(function(node) { 1960 return node.htmlFor == oElm.getAttribute('id'); 1961 })[0]; 1962 else 1963 return null; 1964 }, 1965 1966 getChildrenBy: function(callback, parent, elements_only/*=true*/) { 1967 if (typeof elements_only === 'undefined') elements_only = true; 1968 var kids = []; 1969 var n = parent.firstChild; 1970 while(n) { 1971 if ((!elements_only || ccms.dom.isElementNode(n)) && callback(n)) 1972 kids.push(n); 1973 n = n.nextSibling; 1974 } 1975 return kids; 1976 }, 1977 1978 getChildrenByTagName: function(tagName, parent) { 1979 return ccms.dom.getChildrenBy(ccms.dom.hasTagName.rpartial(tagName), parent); 1980 }, 1981 1982 getChildrenByClassName: function(className, tagName, parent) { 1983 var cf = ccms.dom.hasClass.rpartial(className); 1984 var f; 1985 if (typeof tagName === 'string') { 1986 var tf = ccms.dom.hasTagName.rpartial(strTagName.toLowerCase()); 1987 f = function(n) {return tf(n) && cf(n);}; 1988 } 1989 else { 1990 f = function(n) {return cf(n);}; 1991 } 1992 return ccms.dom.getChildrenBy(f, parent); 1993 }, 1994 1995 getElementPosition: function(element) { 1996 if (element.offsetParent) { 1997 for (var posX = 0, posY = 0; element.offsetParent; element = element.offsetParent) { 1998 posX += element.offsetLeft; 1999 posY += element.offsetTop; 2000 } 2001 return [posX, posY]; 2002 } 2003 else { 2004 return [element.x, element.y]; 2005 } 2006 }, 2007 2008 getDocumentScroll: function() { 2009 return [ccms.dom.getDocumentScrollLeft, ccms.dom.getDocumentScrollTop]; 2010 }, 2011 2012 getWidth: function(o) { 2013 if (typeof o.innerWidth === 'number') { 2014 return o.innerWidth; 2015 } 2016 else if (o.clientWidth) { 2017 return o.clientWidth; 2018 } 2019 return 0; 2020 }, 2021 getHeight: function(o) { 2022 if (typeof o.innerHeight === 'number') { 2023 return o.innerHeight; 2024 } 2025 else if (o.clientHeight) { 2026 return o.clientHeight; 2027 } 2028 return 0; 2029 }, 2030
2031 isSubnodeOf: function(parent, subnode) { 2032 if (subnode) { 2033 var n = subnode.parentNode; 2034 while (n) { 2035 if (n === parent) { 2036 return true; 2037 } 2038 n = n.parentNode; 2039 } 2040 } 2041 return false; 2042 }, 2043 2044 hasMovedOutOf: function(eventobj, element) { 2045 var src = ccms.event.getTarget(eventobj); 2046 if (element !== src && src && !ccms.dom.isSubnodeOf(element, src)) {return true;} 2047 var rel = ccms.event.getRelatedTarget(eventobj); 2048 return rel !== element && !ccms.dom.isSubnodeOf(element, rel); 2049 }, 2050 getStyleObject: function(element, style_names) { 2051 element = $(element); 2052 var styles; 2053 if (element) { 2054 styles = {}; 2055 style_names.foreach(function(name) {styles[name] = ccms.dom.getStyle(element, name);}); 2056 } 2057 return styles; 2058 }, 2059 setStyleObject: function(element, styles) { 2060 element = $(element); 2061 if (element) {for (var name in styles) {ccms.dom.setStyle(element, name, styles[name]);}} 2062 }, 2063 setStyleByClass: function(t,c,p,v, root) { // tag, class, property, value, optional root element 2064 ccms.dom.getElementsByClassName(c, t, root).foreach(function(node) {ccms.dom.setStyle(node, p, v);}); 2065 }, 2066 2067 toggleClass: function(element, className) { 2068 if (ccms.dom.hasClass(element, className)) 2069 ccms.dom.removeClass(element, className); 2070 else 2071 ccms.dom.addClass(element, className); 2072 }, 2073 2074 swapClass: function(element, removeClass, addClass) { 2075 if (ccms.dom.hasClass(element, removeClass)) 2076 ccms.dom.removeClass(element, removeClass); 2077 ccms.dom.addClass(element, addClass); 2078 }, 2079 2080 getElementIndex: function(node, includeNonElementNodes) { 2081 var n = node.parentNode.firstChild; 2082 var i = 0; 2083 if (typeof includeNonElementNodes === 'undefined') 2084 includeNonElementNodes = false; 2085 while(n) { 2086 if (n === node) return i; 2087 if (includeNonElementNodes || n.nodeType === Node.ELEMENT_NODE) 2088 ++i; 2089 n = n.nextSibling; 2090 } 2091 return -1; 2092 }, 2093 2094 removeChildren: function(el) { 2095 var prev; 2096 var node = el.lastChild; 2097 while(node) { 2098 prev = node.previousSibling; 2099 el.removeChild(node); 2100 node = prev; 2101 } 2102 }, 2103 2104 getNext: function(node, callback, oData) { 2105 var cb = callback; 2106 if (!cb) cb = ccms.dom.isElementNode; 2107 var n = node.nextSibling; 2108 while(n && !cb(n, oData)) { 2109 n = n.nextSibling; 2110 } 2111 return n; 2112 }, 2113 getPrevious: function(node, callback, oData) { 2114 var cb = callback; 2115 if (!cb) cb = ccms.dom.isElementNode; 2116 var n = node.previousSibling; 2117 while(n && !cb(n, oData)) { 2118 n = n.previousSibling; 2119 } 2120 return n; 2121 }, 2122 getAncestor: function(node, callback, oData) { 2123 var cb = callback; 2124 if (!cb) cb = ccms.dom.isElementNode; 2125 var n = node.parentNode; 2126 while(n && !cb(n, oData)) { 2127 n = n.parentNode; 2128 } 2129 return n; 2130 }, 2131 getChild: function(node, callback, oData) { 2132 var cb = callback; 2133 if (!cb) cb = ccms.dom.isElementNode; 2134 var n = node.firstChild; 2135 while(n && !cb(n, oData)) { 2136 n = n.nextSibling; 2137 } 2138 return n; 2139 }, 2140 2141 isElementNode: function(node) {return node.nodeType === Node.ELEMENT_NODE;}, 2142 //hasClass: function(node, sClassName) {return !sClassName || ccms.contains(node.className.split(' '), sClassName);}, 2143 hasTagName: function(node, sTagName) {return sTagName === '*' || (typeof node.tagName !== 'undefined' && node.tagName.toUpperCase() === sTagName.toUpperCase());}, 2144 2145 hasRel: function(node, sRel) { return !sRel || (node.getAttribute('rel') && ccms.contains(node.getAttribute('rel').split(' '), sRel));}, 2146 2147 _waiting: 0, 2148 pushWaitingClass: function() { 2149 ++ccms.dom._waiting; 2150 ccms.dom.addClass(document.body, 'waiting'); 2151 }, 2152 popWaitingClass: function() { 2153 if (--ccms.dom._waiting <= 0) { 2154 ccms.dom.removeClass(document.body, 'waiting'); 2155 } 2156 }, 2157 2158 // replace id attributes in html string with a generated one if the id already exists 2159 fixDuplicateIDs: function(html) { 2160 var bits = html.match(/id=('.+?'|".+?")/g); 2161 bits.foreach(function(attr) { 2162 var id = attr.match(/('.+?'|".+?")/); 2163 id = id[1].substring(1, id[1].length - 1); 2164 if ($(id)) { 2165 var new_attr = 'id="' + id + '-' + ccms.dom.generateId() + '"'; 2166 html = html.replace(attr, new_attr); 2167 } 2168 }); 2169 return html; 2170 }, 2171 2172 // set option with specified value to selected 2173 setSelectedIndexByValue: function(select, value) { 2174 for(var i = 0; i < select.options.length; ++i) { 2175 if (value == select.options[i].value) { 2176 select.selectedIndex = i; 2177 break; 2178 } 2179 } 2180 }, 2181 2182 ready: false 2183}); 2184 2185ccms.dom.updatePopupLinks = function(root) { 2186 ccms.dom.getElementsByClassName('external', 'a', document.body).foreach(ccms.dom.setExternalLink); 2187 ccms.dom.getElementsByClassName('external', 'form', document.body).foreach(ccms.dom.setExternalLink); 2188}; 2189ccms.dom.updateRelExternalLinks = function(root) { 2190 var queryfunc = function(node) {return ccms.dom.hasRel(node, 'external');};
2191 ccms.dom.getElementsBy(queryfunc, 'a', document.body).forEach(ccms.dom.setExternalLink); 2192}; 2193ccms.dom.updateExternalLinks = function(root, subdomains) { 2194 subdomains = subdomains || []; 2195 var re = subdomains.length ? new RegExp('^(' + subdomains.join('|') + ')\.') : ''; 2196 var queryfunc = function(node) { 2197 return node.href.startswith('http') && (window.location.hostname.replace(re, '') != node.hostname.replace(re, '') || ccms.dom.hasRel(node, 'external')); 2198 }; 2199 ccms.dom.getElementsBy(queryfunc, 'a', document.body).forEach(ccms.dom.setExternalLink); 2200}; 2201ccms.dom.updateHumanoids = function (root) { 2202 var humanoids = document.getElementsByTagName('input'); 2203 var d = new Date(); 2204 for (var i = 0; i < humanoids.length; i++) { 2205 if (humanoids[i].name == 'humanoid') { 2206 humanoids[i].value = d.getTime(); 2207 } 2208 } 2209} 2210 2211/* Override me if you want to do something different/more */ 2212ccms.dom.setExternalLink = function(node) { 2213 node.setAttribute('target', '_blank'); 2214} 2215 2216ccms.dom.updateHumanoids = function(root) { 2217 var d = new Date(); 2218 var humanoids = document.getElementsByTagName('input'); 2219 for (var i = 0; i < humanoids.length; i++) { 2220 if (humanoids[i].name == 'humanoid') { 2221 humanoids[i].value = d.getTime(); 2222 } 2223 } 2224}; 2225 2226ccms.extend(ccms.css, { 2227 styleSheets: [], 2228 require: function(url) 2229 { 2230 if (this.styleSheets[url]) return; 2231 this.styleSheets[url] = true; 2232 if (navigator.userAgent.indexOf('MSIE') > 0) 2233 {
2234 document.write('<link rel="stylesheet" type="text/css" href="' + url + '" />'); 2235 } 2236 else 2237 { 2238 var s = document.createElement('link'); 2239 s.setAttribute('rel', 'stylesheet'); 2240 s.setAttribute('type', 'text/css'); 2241 s.setAttribute('href', url); 2242 document.getElementsByTagName('head')[0].appendChild(s); 2243 } 2244 } 2245}); 2246 2247ccms.namespace('ccms.screen'); 2248ccms.extend(ccms.screen, (function() { 2249 var classes = []; 2250 var widths = []; 2251 var current_class = ''; 2252 2253 return { 2254 setScreenClass: function() { 2255 var width = document.documentElement.clientWidth; 2256 var new_class = classes[widths[0]]; 2257 2258 for (var i in widths) { 2259 var w = widths[i]; 2260 2261 if (w <= width) new_class = classes[w]; 2262 } 2263 2264 if (current_class !== new_class) { 2265 if (current_class !== '') 2266 ccms.dom.removeClass(document.body, current_class); 2267 ccms.dom.addClass(document.body, current_class = new_class); 2268 2269 ccms.require('/js/ccmsBrowserCapabilities.js'); 2270 2271 ccms.async.when(function() {return (typeof ccms.browser.getCapabilities === 'function');}, function() { 2272 ccms.async.http({ 2273 url: '/browsercaps', 2274 method: 'POST', 2275 parameters: {'json': JSON.stringify(ccms.browser.getCapabilities())}, 2276 onSuccess: function(req) {}, 2277 onFailure: function(req) {ccms.log.debugging = true; ccms.log.debug('ccmsBrowserCapabilities: ' + req.status + ' ' + req.statusText + "\n" + req.responseText);} 2278 }); 2279 }); 2280 } 2281 }, 2282 setupMonitor: function(dat, current) { 2283 var sorter = function sortNumber(a, b) { return a - b; }; 2284 2285 if (current) current_class = current; 2286 2287 var i = 0; 2288 for (var w in dat) { 2289 widths[i++] = w; 2290 classes[w] = dat[w]; 2291 } 2292 widths.sort(sorter); 2293 2294 if (widths.length > 0) { 2295 ccms.event.addLoadEvent(ccms.screen.setScreenClass); 2296 ccms.event.addListener(window, 'resize', ccms.screen.setScreenClass); 2297 } 2298 } 2299 }; 2300})()); 2301 2302ccms.cookie = { 2303 get: function(cookieName, default_value) { 2304 var cookieNameStart,valueStart,valueEnd,value; 2305 cookieNameStart = document.cookie.indexOf(cookieName+'='); 2306 if (cookieNameStart < 0) { 2307 if (typeof default_value === 'undefined') return null; 2308 return default_value; 2309 } 2310 valueStart = document.cookie.indexOf(cookieName+'=') + cookieName.length + 1; 2311 valueEnd = document.cookie.indexOf(";",valueStart); 2312 if (valueEnd === -1){valueEnd = document.cookie.length;} 2313 value = document.cookie.substring(valueStart,valueEnd ); 2314 value = unescape(value); 2315 if (value === '') { 2316 if (typeof default_value === 'undefined') return null; 2317 return default_value; 2318 } 2319 return value; 2320 }, 2321 set: function(cookieName,value,hoursToLive,path,domain,secure) { 2322 var expireString,timerObj,expireAt,pathString,domainString,secureString,setCookieString; 2323 /* If no hoursToLive argument, or it is not numeric, do not set expiration */ 2324 if (!hoursToLive || typeof hoursToLive !== 'number' || parseInt(hoursToLive, 10) === 'NaN'){ 2325 expireString = ''; 2326 } 2327 else { 2328 timerObj = new Date(); 2329 timerObj.setTime(timerObj.getTime()+(parseInt(hoursToLive, 10)*60*60*1000)); 2330 expireAt = timerObj.toGMTString(); 2331 expireString = ";expires="+expireAt; 2332 } 2333 /* If no path argument, or argument is empty string, set path to default of / */ 2334 pathString = ";path="; 2335 (!path || path === '') ? pathString += "/" : pathString += path; 2336 /* If no domain argument, or argument is empty string, set domain to default of window.location.hostname */ 2337 domainString = "; domain="; 2338 (!domain || domain === '') ? domainString += window.location.hostname : domainString += domain; 2339 /* If secure argument is the BOOL true, set SSL string accordingly. Otherwise, do not set it. */ 2340 (secure === true) ? secureString = ";secure" : secureString = ''; 2341 value = escape(value); 2342 setCookieString = cookieName+"="+(value)+expireString+pathString+domainString; 2343 document.cookie = setCookieString; 2344 }, 2345 del: function(cookieName,path,domain){ 2346 (!path || !path.length) ? path='' : path=path; 2347 (!domain || !domain.length) ? domain='' : domain=domain; 2348 ccms.cookie.set(cookieName,'',-8760,path,domain); 2349 }, 2350 test: function(){ 2351 ccms.cookie.set('cT','acc'); 2352 var runTest = ccms.cookie.get('cT'); 2353 if (runTest === 'acc'){ 2354 ccms.cookies.del('cT'); 2355 testStatus = true; 2356 } 2357 else { 2358 testStatus = false;
2359 } 2360 return testStatus; 2361 } 2362}; 2363 2364/* Add a flash message from JavaScript */ 2365ccms.flash = function(html) 2366{ 2367 /* If there's a message, turn it into html add it to the document */ 2368 if (typeof html !== 'undefined') { 2369 var block = html, content; 2370 if (html.constructor.prototype === String.prototype) /* Assume this is an HTML snippit */ 2371 { 2372 if (html === '') { 2373 block = false; 2374 } 2375 else { 2376 /* A cheeky way of getting the HTML as a DOM object */ 2377 block = document.createElement('div'); 2378 block.innerHTML = html; 2379 block = block.childNodes[0]; 2380 } 2381 } 2382 if (block) { 2383 if ((content = $('content'))) { 2384 if (content.childNodes.length > 0) { 2385 content.insertBefore(block, content.childNodes.item(0)); 2386 } 2387 else { 2388 content.appendChild(block); 2389 } 2390 } 2391 } 2392 } 2393 2394 /* Find all of the flash divs, if there's more than one then consolidate them */ 2395 var flashes = ccms.arrayOf(ccms.dom.getElementsByClassName('flash', 'div')); 2396 if (flashes.length > 0) { 2397 flash = flashes[0]; 2398 if (flashes.length > 1) { 2399 for (var f = 1; f < flashes.length; ++f) { 2400 var kids = ccms.arrayOf(flashes[f].getElementsByTagName('p')); 2401 for (var k = 0; k < kids.length; ++k) { 2402 flash.appendChild(kids[k]); 2403 } 2404 flashes[f].parentNode.removeChild(flashes[f]); 2405 } 2406 } 2407 ccms.flash.attachFlash(flash); 2408 } 2409}; 2410 2411ccms.flash.attachFlash = function(root_element) { 2412 /* Override me to setup animations */ 2413}; 2414 2415ccms.event.attach(window, 'load', function(e) {ccms.flash();}); 2416 2417ccms.log.setup(); 2418 2419ccms.event.addLoadEvent(ccms.detectScripts); 2420ccms.event.addLoadEvent(ccms.dom.updateHumanoids); 2421 2422ccms.widgets.addInstaller('updatePopupLinks', ccms.dom.updatePopupLinks); 2423ccms.widgets.addInstaller('updateHumanoids', ccms.dom.updateHumanoids); 2424 2425(function() { 2426 var f = document.createElement('input'); 2427 // Run through HTML5's new input attributes to see if the UA understands any. 2428 // Mike Taylr has created a comprehensive resource for testing these attributes 2429 // when applied to all input types: 2430 // http://miketaylr.com/code/input-type-attr.html 2431 // spec: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary 2432 var input = (function(props) { 2433 var attrs = {}; 2434 for ( var i in props ) { 2435 attrs[ props[i] ] = !!(props[i] in f); 2436 } 2437 return attrs; 2438 })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' ')); 2439 2440})(); 2441 2442 2443ccms.ApiLinks = (function() { 2444 var links = []; 2445 var have_document = false; 2446 2447 var _boundcall = function(config) { 2448 config.api = this; 2449 return ccms.ApiLinks.call(config); 2450 }; 2451 2452 ccms.event.onDOMReady(function() {ccms.ApiLinks.extract();}); 2453 2454 return { 2455 2456 extract: function(root_element) { 2457 if (typeof root_element === 'undefined') { 2458 if (have_document) return true; 2459 have_document = true; 2460 root_element = document; 2461 } 2462 ccms.arrayOf(root_element.getElementsByTagName('link')).foreach(function(node) { 2463 links.push({ 2464 'href':node.getAttribute('href'), 2465 'rel':node.getAttribute('rel'), 2466 'title':node.getAttribute('title'), 2467 'type':node.getAttribute('type'), 2468 'parameters': {}, 2469 'call': _boundcall 2470 }); 2471 }); 2472 return true; 2473 }, 2474 2475 add: function(link) { 2476 if (typeof link.parameters === 'undefined') link.parameters = {}; 2477 link.call = _boundcall; 2478 if (link.rel) ccms.ApiLinks.removeWithRel(link.rel); 2479 links.push(link); 2480 }, 2481 2482 addMany: function(links) { 2483 if (typeof links === 'object' && typeof links.foreach === 'function') 2484 links.foreach(this.add); 2485 }, 2486 2487 findByRel: function(rel) { 2488 return links[links.findBy(function(link) { 2489 if (typeof rel == 'string') return link.rel == rel; 2490 return link.rel.match(rel); 2491 })]; 2492 }, 2493 2494 findWithRel: function(rel) { 2495 if (typeof rel == 'string') 2496 return links.filter(function(link) {return link.rel == rel;}); 2497 else 2498 return links.filter(function(link) {return link.rel.match(rel);}); 2499 }, 2500 2501 removeWithRel: function(rel) { 2502 if (typeof rel == 'string') 2503 links = links.filter(function(link) {return link.rel != rel;}); 2504 else 2505 links = links.filter(function(link) {return !link.rel.match(rel);}); 2506 }, 2507 2508 call: function(config) { 2509 var api; 2510 if (YAHOO.lang.isObject(api = config.api) || (api = this.findByRel(config.api))) { 2511 config.parseJSON = api.type.match('json'); 2512 if (typeof config.url === 'undefined') config.url = api.href; 2513 if (typeof config.parameters === 'undefined') config.parameters = api.parameters; 2514 else if (typeof api.parameters === 'object') config.parameters = ccms.update(ccms.cloneOf(api.parameters), config.parameters); 2515 if (typeof config.parameters.jsi !== 'string') config.parameters.jsi = 'content'; 2516 if (!config.url.match(/:\/\//) || -1 < config.url.indexOf(document.location.host)) { 2517 return ccms.async.http(config); 2518 } 2519 return ccms.async.jsr.call(config); 2520 } 2521 } 2522 2523 }; 2524})(); 2525 2526/* 2527 http://www.JSON.org/json2.js 2528 2008-05-25 2529 2530 Public Domain. 2531 2532 NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. 2533 2534 See http://www.JSON.org/js.html 2535
2536 This file creates a global JSON object containing two methods: stringify 2537 and parse. 2538 2539 JSON.stringify(value, replacer, space) 2540 value any JavaScript value, usually an object or array. 2541 2542 replacer an optional parameter that determines how object 2543 values are stringified for objects without a toJSON 2544 method. It can be a function or an array. 2545 2546 space an optional parameter that specifies the indentation 2547 of nested structures. If it is omitted, the text will 2548 be packed without extra whitespace. If it is a number, 2549 it will specify the number of spaces to indent at each 2550 level. If it is a string (such as '\t' or ' '), 2551 it contains the characters used to indent at each level. 2552 2553 This method produces a JSON text from a JavaScript value. 2554 2555 When an object value is found, if the object contains a toJSON 2556 method, its toJSON method will be called and the result will be 2557 stringified. A toJSON method does not serialize: it returns the 2558 value represented by the name/value pair that should be serialized, 2559 or undefined if nothing should be serialized. The toJSON method 2560 will be passed the key associated with the value, and this will be 2561 bound to the object holding the key. 2562 2563 For example, this would serialize Dates as ISO strings. 2564 2565 Date.prototype.toJSON = function (key) { 2566 function f(n) { 2567 // Format integers to have at least two digits. 2568 return n < 10 ? '0' + n : n; 2569 } 2570 2571 return this.getUTCFullYear() + '-' + 2572 f(this.getUTCMonth() + 1) + '-' + 2573 f(this.getUTCDate()) + 'T' + 2574 f(this.getUTCHours()) + ':' + 2575 f(this.getUTCMinutes()) + ':' + 2576 f(this.getUTCSeconds()) + 'Z'; 2577 }; 2578 2579 You can provide an optional replacer method. It will be passed the 2580 key and value of each member, with this bound to the containing 2581 object. The value that is returned from your method will be 2582 serialized. If your method returns undefined, then the member will 2583 be excluded from the serialization. 2584 2585 If the replacer parameter is an array, then it will be used to 2586 select the members to be serialized. It filters the results such 2587 that only members with keys listed in the replacer array are 2588 stringified. 2589 2590 Values that do not have JSON representations, such as undefined or 2591 functions, will not be serialized. Such values in objects will be 2592 dropped; in arrays they will be replaced with null. You can use 2593 a replacer function to replace those with JSON values. 2594 JSON.stringify(undefined) returns undefined. 2595 2596 The optional space parameter produces a stringification of the 2597 value that is filled with line breaks and indentation to make it 2598 easier to read. 2599 2600 If the space parameter is a non-empty string, then that string will 2601 be used for indentation. If the space parameter is a number, then 2602 the indentation will be that many spaces. 2603 2604 Example: 2605 2606 text = JSON.stringify(['e', {pluribus: 'unum'}]); 2607 // text is '["e",{"pluribus":"unum"}]' 2608 2609 2610 text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); 2611 // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' 2612 2613 text = JSON.stringify([new Date()], function (key, value) { 2614 return this[key] instanceof Date ? 2615 'Date(' + this[key] + ')' : value; 2616 }); 2617 // text is '["Date(---current time---)"]' 2618 2619 2620 JSON.parse(text, reviver) 2621 This method parses a JSON text to produce an object or array. 2622 It can throw a SyntaxError exception. 2623 2624 The optional reviver parameter is a function that can filter and 2625 transform the results. It receives each of the keys and values, 2626 and its return value is used instead of the original value. 2627 If it returns what it received, then the structure is not modified. 2628 If it returns undefined then the member is deleted. 2629 2630 Example: 2631 2632 // Parse the text. Values that look like ISO date strings will 2633 // be converted to Date objects. 2634 2635 myData = JSON.parse(text, function (key, value) { 2636 var a; 2637 if (typeof value === 'string') { 2638 a = 2639/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); 2640 if (a) { 2641 return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], 2642 +a[5], +a[6])); 2643 } 2644 } 2645 return value; 2646 }); 2647 2648 myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { 2649 var d; 2650 if (typeof value === 'string' && 2651 value.slice(0, 5) === 'Date(' && 2652 value.slice(-1) === ')') { 2653 d = new Date(value.slice(5, -1)); 2654 if (d) { 2655 return d; 2656 } 2657 } 2658 return value; 2659 }); 2660 2661 2662 This is a reference implementation. You are free to copy, modify, or 2663 redistribute. 2664 2665 This code should be minified before deployment. 2666 See http://javascript.crockford.com/jsmin.html 2667 2668 USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO 2669 NOT CONTROL. 2670*/ 2671 2672/*jslint evil: true */ 2673 2674/*global JSON */ 2675 2676/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", call,
2677 charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, getUTCMinutes, 2678 getUTCMonth, getUTCSeconds, hasOwnProperty, join, lastIndex, length, 2679 parse, propertyIsEnumerable, prototype, push, replace, slice, stringify, 2680 test, toJSON, toString 2681*/ 2682 2683if (!this.JSON) { 2684 2685// Create a JSON object only if one does not already exist. We create the 2686// object in a closure to avoid creating global variables. 2687 2688 JSON = function () { 2689 2690 function f(n) { 2691 // Format integers to have at least two digits. 2692 return n < 10 ? '0' + n : n; 2693 } 2694 2695 Date.prototype.toJSON = function (key) { 2696 2697 return this.getUTCFullYear() + '-' + 2698 f(this.getUTCMonth() + 1) + '-' + 2699 f(this.getUTCDate()) + 'T' + 2700 f(this.getUTCHours()) + ':' + 2701 f(this.getUTCMinutes()) + ':' + 2702 f(this.getUTCSeconds()) + 'Z'; 2703 }; 2704 2705 var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, 2706 escapeable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, 2707 gap, 2708 indent, 2709 meta = { // table of character substitutions 2710 '\b': '\\b', 2711 '\t': '\\t', 2712 '\n': '\\n', 2713 '\f': '\\f', 2714 '\r': '\\r', 2715 '"' : '\\"', 2716 '\\': '\\\\' 2717 }, 2718 rep; 2719 2720 2721 function quote(string) { 2722 2723// If the string contains no control characters, no quote characters, and no 2724// backslash characters, then we can safely slap some quotes around it. 2725// Otherwise we must also replace the offending characters with safe escape 2726// sequences. 2727 2728 escapeable.lastIndex = 0; 2729 return escapeable.test(string) ? 2730 '"' + string.replace(escapeable, function (a) { 2731 var c = meta[a]; 2732 if (typeof c === 'string') { 2733 return c; 2734 } 2735 return '\\u' + ('0000' + 2736 (+(a.charCodeAt(0))).toString(16)).slice(-4); 2737 }) + '"' : 2738 '"' + string + '"'; 2739 } 2740 2741 2742 function str(key, holder) { 2743 2744// Produce a string from holder[key]. 2745 2746 var i, // The loop counter. 2747 k, // The member key. 2748 v, // The member value. 2749 length, 2750 mind = gap, 2751 partial, 2752 value = holder[key]; 2753 2754// If the value has a toJSON method, call it to obtain a replacement value. 2755 2756 if (value && typeof value === 'object' && 2757 typeof value.toJSON === 'function') { 2758 value = value.toJSON(key); 2759 } 2760 2761// If we were called with a replacer function, then call the replacer to 2762// obtain a replacement value. 2763 2764 if (typeof rep === 'function') { 2765 value = rep.call(holder, key, value); 2766 } 2767 2768// What happens next depends on the value's type. 2769 2770 switch (typeof value) { 2771 case 'string': 2772 return quote(value); 2773 2774 case 'number': 2775 2776// JSON numbers must be finite. Encode non-finite numbers as null. 2777 2778 return isFinite(value) ? String(value) : 'null'; 2779 2780 case 'boolean': 2781 case 'null': 2782 2783// If the value is a boolean or null, convert it to a string. Note: 2784// typeof null does not produce 'null'. The case is included here in 2785// the remote chance that this gets fixed someday. 2786 2787 return String(value); 2788 2789// If the type is 'object', we might be dealing with an object or an array or 2790// null. 2791 2792 case 'object': 2793 2794// Due to a specification blunder in ECMAScript, typeof null is 'object', 2795// so watch out for that case. 2796 2797 if (!value) { 2798 return 'null'; 2799 } 2800 2801// Make an array to hold the partial results of stringifying this object value. 2802 2803 gap += indent; 2804 partial = []; 2805 2806// If the object has a dontEnum length property, we'll treat it as an array.
2807 2808 if (typeof value.length === 'number' && 2809 !(value.propertyIsEnumerable('length'))) { 2810 2811// The object is an array. Stringify every element. Use null as a placeholder 2812// for non-JSON values. 2813 2814 length = value.length; 2815 for (i = 0; i < length; i += 1) { 2816 partial[i] = str(i, value) || 'null'; 2817 } 2818 2819// Join all of the elements together, separated with commas, and wrap them in 2820// brackets. 2821 2822 v = partial.length === 0 ? '[]' : 2823 gap ? '[\n' + gap + 2824 partial.join(',\n' + gap) + '\n' + 2825 mind + ']' : 2826 '[' + partial.join(',') + ']'; 2827 gap = mind; 2828 return v; 2829 } 2830 2831// If the replacer is an array, use it to select the members to be stringified. 2832 2833 if (rep && typeof rep === 'object') { 2834 length = rep.length; 2835 for (i = 0; i < length; i += 1) { 2836 k = rep[i]; 2837 if (typeof k === 'string') { 2838 v = str(k, value, rep); 2839 if (v) { 2840 partial.push(quote(k) + (gap ? ': ' : ':') + v); 2841 } 2842 } 2843 } 2844 } else { 2845 2846// Otherwise, iterate through all of the keys in the object. 2847 2848 for (k in value) { 2849 if (Object.hasOwnProperty.call(value, k)) { 2850 v = str(k, value, rep); 2851 if (v) { 2852 partial.push(quote(k) + (gap ? ': ' : ':') + v); 2853 } 2854 } 2855 } 2856 } 2857 2858// Join all of the member texts together, separated with commas, 2859// and wrap them in braces. 2860 2861 v = partial.length === 0 ? '{}' : 2862 gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + 2863 mind + '}' : '{' + partial.join(',') + '}'; 2864 gap = mind; 2865 return v; 2866 } 2867 } 2868 2869// Return the JSON object containing the stringify and parse methods. 2870 2871 return { 2872 stringify: function (value, replacer, space) { 2873 2874// The stringify method takes a value and an optional replacer, and an optional 2875// space parameter, and returns a JSON text. The replacer can be a function 2876// that can replace values, or an array of strings that will select the keys. 2877// A default replacer method can be provided. Use of the space parameter can 2878// produce text that is more easily readable. 2879 2880 var i; 2881 gap = ''; 2882 indent = ''; 2883 2884// If the space parameter is a number, make an indent string containing that 2885// many spaces. 2886 2887 if (typeof space === 'number') { 2888 for (i = 0; i < space; i += 1) { 2889 indent += ' '; 2890 } 2891 2892// If the space parameter is a string, it will be used as the indent string. 2893 2894 } else if (typeof space === 'string') { 2895 indent = space; 2896 } 2897 2898// If there is a replacer, it must be a function or an array. 2899// Otherwise, throw an error. 2900 2901 rep = replacer; 2902 if (replacer && typeof replacer !== 'function' && 2903 (typeof replacer !== 'object' || 2904 typeof replacer.length !== 'number')) { 2905 throw new Error('JSON.stringify'); 2906 } 2907 2908// Make a fake root object containing our value under the key of ''. 2909// Return the result of stringifying the value. 2910 2911 return str('', {'': value}); 2912 }, 2913 2914 2915 parse: function (text, reviver) { 2916 2917// The parse method takes a text and an optional reviver function, and returns 2918// a JavaScript value if the text is a valid JSON text. 2919 2920 var j; 2921 2922 function walk(holder, key) { 2923 2924// The walk method is used to recursively walk the resulting structure so 2925// that modifications can be made. 2926 2927 var k, v, value = holder[key]; 2928 if (value && typeof value === 'object') { 2929 for (k in value) { 2930 if (Object.hasOwnProperty.call(value, k)) { 2931 v = walk(value, k); 2932 if (v !== undefined) { 2933 value[k] = v; 2934 } else { 2935 delete value[k]; 2936 } 2937 } 2938 } 2939 } 2940 return reviver.call(holder, key, value); 2941 } 2942 2943 2944// Parsing happens in four stages. In the first stage, we replace certain 2945// Unicode characters with escape sequences. JavaScript handles many characters 2946// incorrectly, either silently deleting them, or treating them as line endings. 2947 2948 cx.lastIndex = 0; 2949 if (cx.test(text)) { 2950 text = text.replace(cx, function (a) {
2951 return '\\u' + ('0000' + 2952 (+(a.charCodeAt(0))).toString(16)).slice(-4); 2953 }); 2954 } 2955 2956// In the second stage, we run the text against regular expressions that look 2957// for non-JSON patterns. We are especially concerned with '()' and 'new' 2958// because they can cause invocation, and '=' because it can cause mutation. 2959// But just to be safe, we want to reject all unexpected forms. 2960 2961// We split the second stage into 4 regexp operations in order to work around 2962// crippling inefficiencies in IE's and Safari's regexp engines. First we 2963// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we 2964// replace all simple value tokens with ']' characters. Third, we delete all 2965// open brackets that follow a colon or comma or that begin the text. Finally, 2966// we look to see that the remaining characters are only whitespace or ']' or 2967// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. 2968 2969 if (/^[\],:{}\s]*$/. 2970test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). 2971replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). 2972replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { 2973 2974// In the third stage we use the eval function to compile the text into a 2975// JavaScript structure. The '{' operator is subject to a syntactic ambiguity 2976// in JavaScript: it can begin a block or an object literal. We wrap the text 2977// in parens to eliminate the ambiguity. 2978 2979 j = eval('(' + text + ')'); 2980 2981// In the optional fourth stage, we recursively walk the new structure, passing 2982// each name/value pair to a reviver function for possible transformation. 2983 2984 return typeof reviver === 'function' ? 2985 walk({'': j}, '') : j; 2986 } 2987 2988// If the text is not JSON parseable, then a SyntaxError is thrown. 2989 2990 throw new SyntaxError('JSON.parse'); 2991 } 2992 }; 2993 }(); 2994} 2995 2996ccms.extend(ccms.date, { 2997 monthNames: "January February March April May June July August September October November December".split(" "), 2998 weekdayNames: "Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" ") 2999}); 3000 3001 3002/* http://delete.me.uk/2005/03/iso8601.html */ 3003Date.prototype.setISO8601 = function (string) { 3004 var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" + 3005 "(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" + 3006 "(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?"; 3007 var d = string.match(new RegExp(regexp)); 3008 3009 var offset = 0; 3010 var date = new Date(d[1], 0, 1); 3011 3012 if (d[3]) { date.setMonth(d[3] - 1); } 3013 if (d[5]) { date.setDate(d[5]); } 3014 if (d[7]) { date.setHours(d[7]); } 3015 if (d[8]) { date.setMinutes(d[8]); } 3016 if (d[10]) { date.setSeconds(d[10]); } 3017 if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); } 3018 if (d[14]) { 3019 offset = (Number(d[16]) * 60) + Number(d[17]); 3020 offset *= ((d[15] == '-') ? 1 : -1); 3021 } 3022 3023 offset -= date.getTimezoneOffset(); 3024 time = (Number(date) + (offset * 60 * 1000)); 3025 this.setTime(Number(time)); 3026}; 3027Date.parseISO8601 = function(string) { 3028 var d = new Date(); 3029 d.setISO8601(string); 3030 return d; 3031};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.