1if (typeof(BS) == 'undefined') { 2 BS = {}; 3 BS.com = {}; 4 BS.utl = {}; 5 6 function is_array(v) 7 { 8 if (!isset(v) || v === null) return false; 9 return v.constructor == Array; 10 } 11 function isset(v) { return (typeof v == 'undefined') ? false : true; } 12 13 function empty (obj) 14 { 15 if (obj === null) return true; 16 17 switch (typeof obj) { 18 case 'number': return (obj == 0); 19 case 'string': return (!obj || obj== ''); 20 case 'boolean': return obj !== true; 21 case 'undefined': return true; 22 case 'object': 23 if (is_array(obj)) { 24 for (var i in obj) { 25 if (obj.hasOwnProperty(i)) return false; 26 } 27 return true; 28 } 29 case 'function': 30 default: return false; 31 } 32 } 33} 34 35/*!\brief Callback class that represents a callback function, optional 36 * data object, and optional bind to data scope. 37 * \param f function 38 * \param bind bind scope (optional) 39 * \param d data (optional) 40 */ 41BS.com.Callback = function (f, bind, d) 42{ 43 this.f = f; 44 this.bind = bind; 45 this.d = d; 46}; 47 48BS.com.Browser = function () 49{ 50 this.agent = this._getAgent(this.dataBrowser) || 'unknown'; 51 this.version = this._getVersion(navigator.userAgent) 52 || this._getVersion(navigator.appVersion) 53 || 'unknown'; 54 this.OS = this._getAgent(this.dataOS) || 'an unknown OS'; 55 56 this.isIE = (this.agent == 'Explorer'); 57 this.isSafari = (this.agent == 'Safari' || this.agent == 'Konqueror'); 58 this.isOpera = (this.agent == 'Opera'); 59 this.isChrome = (this.agent == 'Chrome'); 60}; 61 62BS.com.Browser.prototype = { 63 _getAgent: function (data) 64 { 65 for (var i=0; i<data.length; i++) { 66 var dataStr = data[i].str; 67 var dataProp = data[i].prop; 68 this.verSrchStr = data[i].verSrch || data[i].id; 69 if (dataStr) { 70 if (dataStr.indexOf(data[i].substr) != -1) 71 return data[i].id; 72 } 73 else if (dataProp) return data[i].id; 74 } 75 }, 76 77 _getVersion: function (dataStr) 78 { 79 var index = dataStr.indexOf(this.verSrchStr); 80 if (index == -1) return; 81 return parseFloat(dataStr.substring(index+this.verSrchStr.length+1)); 82 }, 83 84 isValid: function (mode) 85 { 86 if (mode == 'Java' && this.OS == 'Mac') { 87 switch (this.agent) { 88 case 'Chrome': return true; 89 case 'Safari': return (this.version > 400); 90 case 'Firefox': return (this.version >= 1.5); 91 default: return false; 92 } 93 } 94 95 switch (this.agent) { 96 case 'Safari': return (this.version > 300); 97 case 'Chrome': return (this.version >= 0.2); 98 case 'Mozilla': return (this.version > 1.6); 99 case 'Firefox': return (this.version >= 1); 100 case 'Explorer': return (this.version > 5); 101 case 'Opera': return (this.version >= 9); 102 default: return false; 103 } 104 }, 105 106 dataBrowser: [ 107 { 108 str: navigator.vendor, 109 substr: 'Apple', 110 id: 'Safari' 111 }, 112 { 113 str: navigator.vendor, 114 substr: 'Google', 115 id: 'Chrome' 116 }, 117 { 118 prop: window.opera, 119 id: 'Opera' 120 }, 121 { 122 str: navigator.vendor, 123 substr: 'iCab', 124 id: 'iCab' 125 }, 126 { 127 str: navigator.vendor, 128 substr: 'KDE', 129 id: 'Konqueror' 130 }, 131 { 132 str: navigator.userAgent, 133 substr: 'Firefox', 134 id: 'Firefox' 135 }, 136 { // for newer Netscapes (6+) 137 str: navigator.userAgent, 138 substr: 'Netscape', 139 id: 'Netscape' 140 }, 141 { 142 str: navigator.userAgent, 143 substr: 'MSIE', 144 id: 'Explorer', 145 verSrch: 'MSIE' 146 }, 147 { 148 str: navigator.userAgent, 149 substr: 'Gecko', 150 id: 'Mozilla', 151 verSrch: 'rv' 152 }, 153 { // for older Netscapes (4-) 154 str: navigator.userAgent, 155 substr: 'Mozilla', 156 id: 'Netscape', 157 verSrch: 'Mozilla' 158 } 159 ], 160 161 dataOS : [ 162 { 163 str: navigator.platform, 164 substr: 'Win', 165 id: 'Windows' 166 }, 167 { 168 str: navigator.platform, 169 substr: 'Mac', 170 id: 'Mac' 171 }, 172 { 173 str: navigator.platform, 174 substr: 'Linux', 175 id: 'Linux' 176 } 177 ] 178}; 179 180BS.com.Dom = function () 181{ 182 BS.utl.globalEvent.addCB('load', this._onLoad, this); 183}; 184 185BS.com.Dom.mkidCnt = 0; 186 187BS.com.Dom.prototype = { 188 isLoaded: false, 189 190 _onLoad: function () { this.isLoaded = true; }, 191 192 mkid: function () { return 'BSDomID' + BS.com.Dom.mkidCnt++; }, 193 194 get: function (id, doc) 195 { 196 if (id.nodeName) return id; 197 198 if (!doc) doc = document; 199 200 if (!doc.all && !document.getElementById) 201 throw 'AssertErr Dom.get'; 202 203 if (doc.getElementById) return doc.getElementById(id); 204 else if (doc.all && doc.all[id]) return doc.all[id]; 205 else return null; 206 }, 207 208 textNode: function (obj, str) 209 { 210 var node = document.createTextNode(str); 211 obj.appendChild(node); 212 return node; 213 }, 214 215 parentByNodeName: function (node, name) 216 { 217 name = name.toUpperCase(); 218 for (; node && (node.nodeName != name); node=node.parentNode); 219 return node; 220 }, 221 222 size: function (obj) 223 { 224 switch (this.getStyle(obj, 'overflow')) { 225 case 'scroll': return [obj.scrollWidth, obj.scrollHeight]; 226 default: return [obj.offsetWidth, obj.offsetHeight]; 227 } 228 }, 229 230 //returns size, ignoring scroll attributes ... should probably 231 // be folded into size() 232 fullsize: function (obj) 233 { 234 return [obj.offsetWidth, obj.offsetHeight]; 235 }, 236 237 setSize: function (obj, dim) 238 { 239 _bsDom.setStyle(obj, 'width', dim[0] + 'px'); 240 _bsDom.setStyle(obj, 'height', dim[1] + 'px'); 241 }, 242 243 ofs: function (obj) { return [obj.offsetLeft, obj.offsetTop]; }, 244 245 outerOfs: function (obj) 246 { 247 var t = this.ofs(obj); 248 return BS.utl.xy.add(t, this.size(obj)); 249 }, 250 251 pos: function (obj) 252 { 253 var left = parseInt(this.getStyle(obj, 'left')); 254 var top = parseInt(this.getStyle(obj, 'top')); 255 var isRel = (this.getStyle(obj, 'position') == 'relative'); 256 257 if (isNaN(left)) left = (isRel) ? 0 : obj.offsetLeft; 258 if (isNaN(top)) top = (isRel) ? 0 : obj.offsetTop; 259 260 var r = [left, top]; 261 262 /* 263 if (BS.utl.browser.isIE &&
264 this.getStyle(obj, 'position') == 'absolute') 265 BS.utl.xy.add(r, this.scrollOfs()); 266 */ 267 268 return r; 269 }, 270 271 outerPos: function (obj) 272 { 273 var t = this.pos(obj); 274 return BS.utl.xy.add(t, this.size(obj)); 275 }, 276 277 objOfs: function (obj, top) 278 { 279 var ofs = this.ofs(obj); 280 var parent; 281 282 for (parent = obj.offsetParent; parent && parent != top; 283 parent = parent.offsetParent) 284 BS.utl.xy.add(ofs, this.ofs(parent)); 285 286 return ofs; 287 }, 288 289 docOfs: function (obj, top) 290 { 291 var ofs = this.ofs(obj); 292 var parent; 293 294 for (parent = obj.offsetParent; parent && parent != top; 295 parent = parent.offsetParent) 296 BS.utl.xy.add(ofs, this.ofs(parent)); 297 298 return ofs; 299 }, 300 301 outerDocOfs: function (obj) 302 { 303 var t = this.pageOfs(obj); 304 return BS.utl.xy.add(t, this.size(obj)); 305 }, 306 307 pageOfs: function (obj) 308 { 309 // must be part of document object 310 if (obj.parentNode === null || 311 this.getStyle(obj, 'display') == 'none') 312 return false; 313 314 var parent; 315 var pos = []; 316 var box; 317 318 if (obj.getBoundingClientRect) { 319 // IE 320 box = obj.getBoundingClientRect(); 321 pos = [box.left, box.top]; 322 var scroll = [Math.max(document.documentElement.scrollLeft, document.body.scrollLeft), 323 Math.max(document.documentElement.scrollTop, document.body.scrollTop)]; 324 return BS.utl.xy.add(pos, scroll); 325 } 326 else if (document.getBoxObjectFor) { 327 // gecko 328 box = document.getBoxObjectFor(obj); 329 pos = [box.x, box.y]; 330 var border = [parseInt(this.getStyle(obj, 'borderLeftWidth')), 331 parseInt(this.getStyle(obj, 'borderTopWidth'))]; 332 BS.utl.xy.add(pos, border); 333 } 334 else { 335 // safari & opera 336 pos = [obj.offsetLeft, obj.offsetTop]; 337 if ((parent = obj.offsetParent) != obj) { 338 for (; parent; parent = parent.offsetParent) { 339 pos[0] += parent.offsetLeft; 340 pos[1] += parent.offsetTop; 341 } 342 } 343 if (BS.utl.browser.isOpera || 344 (BS.utl.browser.isSafari &&
345 this.getStyle(obj, 'position') == 'absolute')) { 346 pos[0] -= document.body.offsetLeft; 347 pos[1] -= document.body.offsetTop; 348 } 349 } 350 351 for (parent = obj.parentNode; 352 parent && parent.nodeName != 'BODY' && 353 parent.nodeName != 'HTML'; 354 parent = parent.parentNode) { 355 pos[0] -= parent.scrollLeft; 356 pos[1] -= parent.scrollTop; 357 } 358 359 return pos; 360 }, 361 362 outerPageOfs: function (obj) 363 { 364 var t = this.pageOfs(obj); 365 return BS.utl.xy.add(t, this.size(obj)); 366 }, 367 368 isInside: function (a, b, p, ofs) 369 { 370 var pt = (ofs) ? BS.utl.xy.add(p, ofs) : p; 371 372 if (pt[0] < a[0] || pt[1] < a[1]) return false; 373 if (pt[0] > b[0] || pt[1] > b[1]) return false; 374 375 return true; 376 }, 377 378 scrollOfs: function () 379 { 380 if (window.pageXOffset) 381 return [window.pageXOffset, window.pageYOffset]; 382 else if (document.documentElement) 383 return [document.body.scrollLeft + 384 document.documentElement.scrollLeft, 385 document.body.scrollTop + 386 document.documentElement.scrollTop]; 387 else if (document.body.scrollLeft >= 0) 388 return [document.body.scrollLeft, 389 document.body.scrollTop]; 390 else return [0, 0]; 391 }, 392 393 clientSize: function () 394 { 395 if (window.innerHeight >= 0) 396 return [window.innerWidth, window.innerHeight]; 397 else if (document.documentElement && document.documentElement.clientHeight) 398 return [document.documentElement.clientWidth, 399 document.documentElement.clientHeight]; 400 else if (document.body.clientHeight >= 0) 401 return [document.body.clientWidth, 402 document.body.clientHeight]; 403 else return [0, 0]; 404 }, 405 406 docSize: function () 407 { 408 if (!document.body) return [0, 0]; 409 410 var scrollH = -1, winH = -1, bodyH = -1; 411 var marginTop = parseInt(this.getStyle(document.body, 412 'marginTop'), 10); 413 var marginBot = parseInt(this.getStyle(document.body, 414 'marginBottom'), 10); 415 var docW = -1, bodyW = -1, winW = -1; 416 var marginR = parseInt(this.getStyle(document.body, 417 'marginRight'), 10); 418 var marginL = parseInt(this.getStyle(document.body, 419 'marginLeft'), 10); 420 421 var mode = document.compatMode; 422 423 if ((mode || BS.utl.browser.isIE) && !BS.utl.browser.isOpera ) { 424 // (IE, Gecko) 425 switch (mode) { 426 case 'CSS1Compat': 427 // Standards mode 428 scrollH = ((window.innerHeight && window.scrollMaxY) ? window.innerHeight+window.scrollMaxY : -1); 429 winH = Math.max(document.documentElement.clientHeight, self.innerHeight||-1); 430 bodyH = document.body.offsetHeight + marginTop + marginBot; 431 432 docW = document.documentElement.clientWidth; 433 bodyW = document.body.offsetWidth + marginL + marginR; 434 winW = self.innerWidth || -1; 435 break; 436 437 default: 438 // Quirks mode 439 scrollH = document.body.scrollHeight; 440 bodyH = document.body.clientHeight; 441 442 bodyW = document.body.clientWidth; 443 winWidth = document.body.scrollWidth; 444 } 445 } 446 else { 447 // Safari & Opera 448 scrollH = document.documentElement.scrollHeight; 449 winH = self.innerHeight; 450 bodyH = document.documentElement.clientHeight; 451 docW = document.documentElement.clientWidth; 452 bodyW = document.body.offsetWidth + marginL + marginR; 453 winW = self.innerWidth; 454 } 455 456 return [Math.max(bodyW, docW, winW), 457 Math.max(bodyH, scrollH, winH)]; 458 }, 459 460 setPos: function (obj, pt) 461 { 462 this.setStyle(obj, 'left', pt[0] + 'px'); 463 this.setStyle(obj, 'top', pt[1] + 'px'); 464 }, 465 466 clrPos: function (obj) 467 { 468 this.setStyle(obj, 'position', 'static'); 469 this.setStyle(obj, 'left', 'auto'); 470 this.setStyle(obj, 'top', 'auto'); 471 }, 472 473 setPageOfs: function (obj, pos, flag) 474 { 475 // change static to relative positioning 476 if (this.getStyle(obj, 'position') == 'static') 477 this.setStyle(obj, 'position', 'relative'); 478 479 var curPos = this.pageOfs(obj); 480 if (curPos === false) return false; 481 482 var cssPos = this.pos(obj); 483 484 if (pos[0] !== null) 485 this.setStyle(obj, 'left', 486 pos[0] - curPos[0] + cssPos[0] + 'px'); 487 if (pos[1] !== null) 488 this.setStyle(obj, 'top', 489 pos[1] - curPos[1] + cssPos[1] + 'px'); 490 }, 491 492 clientCenter: function (obj, min, f_no_ofs) 493 { 494 min = (min) ? min : [10,10]; 495 var size = this.size(obj); 496 var client = this.clientSize(); 497 var scroll = this.scrollOfs(); 498 var pos = [0, 0]; 499 500 pos[0] = Math.round((client[0] - size[0])/2) + scroll[0]; 501 pos[1] = Math.round((client[1] - size[1])/2); 502 503 pos[1] += scroll[1]; 504 505 if (!f_no_ofs) pos[1] -= Math.round(client[1]/20); 506 507 if (pos[0] < min[0]) pos[0] = min[0]; 508 if (pos[1] < min[1]) pos[1] = min[1]; 509 510 this.setPageOfs(obj, pos); 511 }, 512 513 /*!\brief Executes function on the argument. Supports array of 514 * arguments or single argument. 515 * \param a argument (can be array of arguments) 516 * \param f function 517 * \param bind bind scope (optional) 518 */ 519 _batch: function (a, f, bind) 520 { 521 if (is_array(a)) return BS.utl.array.foreach(a, f, bind); 522 else return f.call(bind, a); 523 }, 524 525 /*!\brief Get style. 526 * \param obj object 527 * \param property property 528 */ 529 getStyle: function (obj, property) 530 { 531 var val = null; 532 var dv = document.defaultView; 533 534 if (property == 'opacity' && obj.filters) { 535 // IE opacity 536 val = 1; 537 try { 538 val = obj.filters.item('DXImageTransform.Microsoft.Alpha').opacity / 100; 539 } 540 catch(e) { 541 try { val = obj.filters.item('alpha').opacity / 100; } 542 catch(e) {} 543 } 544 } 545 else if (obj.style[property]) val = obj.style[property]; 546 else if (obj.currentStyle && obj.currentStyle[property]) 547 val = obj.currentStyle[property]; 548 else if (dv && dv.getComputedStyle) { 549 // convert camelCase to hyphen-case 550 var str = ''; 551 for (var i=0, l=property.length; i < l; i++) { 552 if (property.charAt(i) == property.charAt(i).toUpperCase()) 553 str += '-' + property.charAt(i).toLowerCase(); 554 else str += property.charAt(i); 555 } 556 557 if (dv.getComputedStyle(obj, '') && 558 dv.getComputedStyle(obj, '').getPropertyValue(str)) 559 val = dv.getComputedStyle(obj, '').getPropertyValue(str); 560 } 561 562 return val; 563 }, 564 565 /*!\brief Set style. 566 * \param obj object 567 * \param property property 568 * \param val value 569 */ 570 setStyle: function (obj, property, val) 571 { 572 if (!obj) throw 'BS.com.setStyle: null object'; 573 574 switch (property) { 575 case 'opacity': 576 if (BS.utl.browser.isIE && 577 typeof obj.style.filter == 'string') { 578 obj.style.filter = 'alpha(opacity=' + 579 (val * 100) + ')'; 580 if (!obj.currentStyle || 581 !obj.currentStyle.hasLayout) 582 obj.style.zoom = 1; 583 } 584 else { 585 obj.style.opacity = val; 586 obj.style['-moz-opacity'] = val; 587 obj.style['-khtml-opacity'] = val; 588 } 589 break; 590 // IE scroll compatibility 591 case 'position': if (BS.utl.browser.isIE) obj.style.zoom = 1; 592 default: try { obj.style[property] = val } catch (e) { }; 593 } 594 }, 595 596 setDisplay: function (obj, f) 597 { 598 BS.utl.dom.setStyle(obj, 'display', (f) ? 'block' : 'none'); 599 }, 600 601 setVis: function (obj, f) 602 { 603 BS.utl.dom.setStyle(obj, 'visibility', (f) ? 604 'visible' : 'hidden'); 605 }, 606 607 toggleDisplay: function (obj) 608 { 609 obj = _bsDom.get(obj); 610 var f = (_bsDom.getStyle(obj, 'display') == 'none'); 611 this.setDisplay(obj, f); 612 }, 613
614 /*!\brief Returns true if DOM object contains class name. 615 * \param obj object 616 * \param cnm class name 617 * \return boolean 618 */ 619 hasClass: function (obj, cnm) 620 { 621 var f = function (obj) 622 { 623 var re = new RegExp('(?:^|\\s+)' + cnm + '(?:\\s+|$)'); 624 return re.test(obj['className']); 625 }; 626 627 return this._batch(obj, f, this); 628 }, 629 630 /*!\brief Adds class name to DOM object if it does not exist. 631 * \param obj object 632 * \param cnm class name 633 */ 634 addClass: function (obj, cnm) 635 { 636 var f = function (obj) 637 { 638 if (this.hasClass(obj, cnm)) return; 639 if (!empty(obj['className'])) cnm = ' ' + cnm; 640 obj['className'] += cnm; 641 }; 642 643 this._batch(obj, f, this); 644 }, 645 646 /*!\brief Adds class name array to DOM object (wrapper). 647 * \param obj object 648 * \param cnmA class name array 649 */ 650 addClassArr: function (obj, cnmA) 651 { 652 for (var i=0, l=cnmA.length; i<l; i++) 653 this.addClass(obj, cnmA[i]); 654 }, 655 656 /*!\brief Delete class name from DOM object if it exists. 657 * \param obj object 658 * \param cnm class name 659 */ 660 delClass: function (obj, cnm) 661 { 662 var f = function (obj) 663 { 664 if (!this.hasClass(obj, cnm)) return; 665 var a = obj['className'].split(' '); 666 var str = ''; 667 for (var i = 0; i < a.length; i++) { 668 if (a[i] == cnm) continue; 669 if (!empty(str)) str += ' '; 670 str += a[i]; 671 } 672 obj['className'] = str; 673 }; 674 675 this._batch(obj, f, this); 676 }, 677 678 setClass: function (obj, cnm, f) 679 { 680 if (f) this.addClass(obj, cnm); 681 else this.delClass(obj, cnm); 682 }, 683 684 /*!\brief Checks whether p is inside of the area of the node 685 * \param p point 686 * \param node dom object 687 */ 688 inNode: function (p, node) 689 { 690 var pos = this.pageOfs(node); 691 var size = this.size(node); 692 693 return pos[0] <= p[0] && p[0] <= pos[0] + size[0] && 694 pos[1] <= p[1] && p[1] <= pos[1] + size[1]; 695 } 696}; 697 698/*!\brief Event class that provides a portability layer. 699 * \note single instantiation only 700 */ 701BS.com.Event = function () 702{ 703 // function array for attach/detach 704 this.fA = []; 705}; 706 707BS.com.Event.prototype = { 708 /*!\brief Destructor (pseudo) */ 709 _delete: function () 710 { 711 this.detachAll(); 712 delete this.fA; 713 }, 714 715 /*!\brief Attach an event handler to an object. A caching layer 716 * is in place for the detach method (to locate funcT). 717 * \param obj DOM object 718 * \param type event type 719 * \param func function to attach 720 * \param bind bind scope (optional) 721 * \param d data (optional) 722 */ 723 attach: function (obj, type, func, bind, d) 724 { 725 var scope = bind ? bind : obj; 726 var funcT = function (e) 727 { 728 return func.call(scope, BS.com.Event.getEvent(e), d); 729 }; 730 731 this.fA[this.fA.length] = [obj, type, func, funcT, scope, d]; 732 733 // HACK: fix for stupid IE; there's probably a loop 734 // using the "for i in" syntax somewhere upstream 735 if (!obj) return; 736 737 if (obj.addEventListener) 738 obj.addEventListener(type, funcT, false); 739 else if (obj.attachEvent) obj.attachEvent('on' + type, funcT); 740 else throw 'AssertErr Event.attach'; 741 }, 742 743 /*!\brief Detach event handler based on offset. 744 * \param i offset 745 */ 746 _detach: function (i) 747 { 748 var obj = this.fA[i][0]; 749 750 // HACK: fix for stupid IE; there's probably a loop 751 // using the "for i in" syntax somewhere upstream 752 if (!obj) return; 753 754 if (obj.removeEventListener) 755 obj.removeEventListener(this.fA[i][1], this.fA[i][3], 756 false); 757 else if (obj.detachEvent) 758 obj.detachEvent('on' + this.fA[i][1], this.fA[i][3]); 759 else throw 'AssertErr Event.detach'; 760 761 this.fA[i][0] = this.fA[i][3] = this.fA[i][4] = null; 762 this.fA.splice(i, 1); 763 }, 764 765 /*!\brief Detach an event handler from an object. 766 * \param obj DOM object 767 * \param type event type 768 * \param func function to detach 769 */ 770 detach: function (obj, type, func) 771 { 772 var t; 773 for (i=0, l=this.fA.length; i<l; i++) { 774 t = this.fA[i]; 775 if (t[0] != obj || t[1] != type || t[2] != func) 776 continue; 777 break; 778 } 779 780 if (i == l) return false; 781 782 this._detach(i); 783 784 return true; 785 }, 786 787 /*!\brief Detach all event handlers. */ 788 detachAll: function () 789 { 790 var t; 791 for (var i=0, l=this.fA.length; i<l; i++) { 792 t = this.fA[i]; 793 794 // HACK: for stupid IE 795 if (!t[0]) continue; 796 797 if (t[0].removeEventListener) 798 t[0].removeEventListener(t[1], t[3], false); 799 else if (t[0].detachEvent) 800 t[0].detachEvent('on' + t[1], t[3]); 801 else throw 'AssertErr Event.detachAll'; 802 803 delete this.fA[i][3]; 804 } 805 delete this.fA; 806 this.fA = []; 807 }, 808 809 /*!\brief Detach multiple event handlers based on matching data. 810 * \param data data 811 */ 812 detachData: function (data) 813 { 814 var i, l, t = []; 815 816 for (i=0, l=this.fA.length; i<l; i++) { 817 if (this.fA[i][4] != data) continue; 818 t.push(i); 819 } 820 821 for (i=0, l=t.length; i<l; i++) this._detach(t[i] - i); 822 }, 823 824 /*!\brief Executes setInterval() with object support. 825 * \param ms milliseconds 826 * \param func function 827 * \param bind bind scope (optional) 828 * \param d data (optional) 829 */
830 setInterval: function (ms, func, bind, d) 831 { 832 var t = function () { return func.call(bind, d); }; 833 return setInterval(t, ms); 834 }, 835 836 /*!\brief Executes setTimeout() with object support. 837 * \param ms milliseconds 838 * \param func function 839 * \param bind bind scope (optional) 840 * \param d data (optional) 841 */ 842 setTimeout: function (ms, func, bind, d) 843 { 844 var t = function () { return func.call(bind, d); }; 845 return setTimeout(t, ms); 846 }, 847 848 /*!\brief Returns KEY code for a key press event. 849 * \param e event 850 * \return key code 851 */ 852 getKeyCode: function (e) 853 { 854 var code = e.keyCode || e.which; 855 856 // map unicode cursor codes in safari 857 if (e.type == 'keypress' && BS.utl.browser.isSafari) { 858 switch (code) { 859 case 63232: return 38; 860 case 63233: return 40; 861 case 63234: return 37; 862 case 63235: return 39; 863 } 864 } 865 866 // ignore function keys 867 if ((code >= 112 && code <= 123) && !e.charCode) 868 return null; 869 870 return code; 871 }, 872 873 /*!\brief Returns CHARACTER code for a key press event. 874 * \param e event 875 * \return character code 876 */ 877 getCharCode: function (e) 878 { 879 return e.charCode || 880 ((e.type == 'keypress' || e.type == 'keydown' || 881 e.type == 'keyup') ? e.keyCode : 0) || 882 e.which; 883 }, 884 885 /*!\brief Returns scroll position as an array. 886 * \return [ scrollLeft, scrollTop ] 887 */ 888 _getScroll: function () 889 { 890 var dd = document.documentElement, db = document.body; 891 if (dd && dd.scrollTop) return [dd.scrollLeft, dd.scrollTop]; 892 else if (db) return [db.scrollLeft, db.scrollTop]; 893 else return [0, 0]; 894 }, 895 896 /*!\brief Returns page X coordinate for event. 897 * \param e event 898 */ 899 getX: function (e) 900 { 901 var x = e.pageX; 902 903 if (!x && x !== 0) { 904 x = e.clientX || 0; 905 } 906 907 return x; 908 }, 909
910 /*!\brief Returns page Y coordinate for event. 911 * \param e event 912 */ 913 getY: function (e) 914 { 915 var y = e.pageY; 916 917 if (!y && y !== 0) { 918 y = e.clientY || 0; 919 } 920 921 return y; 922 }, 923 924 /*!\brief Return page X, Y cordinates for an event. 925 * \param e event 926 */ 927 getXY: function (e) 928 { 929 return [this.getX(e), this.getY(e)]; 930 }, 931 932 /*!\brief Returns event target. 933 * \param e event 934 * \param textParent parent if text (default false) 935 * \return element 936 */ 937 getTarget: function (e, textParent) 938 { 939 var t = e.target || e.srcElement; 940 if (textParent && t && t.nodeName == '#text') 941 return t.parentNode; 942 return t; 943 }, 944 945 /*!\brief Return event related target. 946 * \param e event 947 * \return element (related target) 948 */ 949 getRelatedTarget: function (e) 950 { 951 var t = e.relatedTarget; 952 953 if (!t) { 954 if (e.type == 'mouseout') t = e.toElement; 955 else if (e.type == 'mouseover') t = e.fromElement; 956 } 957 958 return t; 959 }, 960 961 /*!\brief Prevent default action of browser for event. 962 * \param e event 963 */ 964 preventDefault: function (e) 965 { 966 if (e.preventDefault) e.preventDefault(); 967 else e.returnValue = false; 968 }, 969 970 /*!\brief Stop bubble phase for event. 971 * \param e event 972 */ 973 stopPropagation: function (e) 974 { 975 if (e.stopPropagation) e.stopPropagation(); 976 else e.cancelBubble = true; 977 }, 978 979 disableSelect: function (obj) 980 { 981 if (BS.utl.browser.isIE || _bsBrowser.isSafari) 982 obj.onselectstart=function(){return false}; 983 else if (BS.utl.browser.agent == 'Firefox') 984 BS.utl.dom.setStyle(obj, 'MozUserSelect', 'none'); 985 else 986 obj.onmousedown=function(){return false}; 987 988 BS.utl.dom.setStyle(obj, 'cursor', 'default'); 989 } 990}; 991 992/*!\brief Returns event in a consistent manner. 993 * \param e event 994 * \return event 995 */ 996BS.com.Event.getEvent = function (e) 997{ 998 if (!e) e = window.event; 999 1000 if (e.target) { 1001 if (e.target.nodeType == 3) e.target = e.target.parentNode; 1002 } 1003 else if (e.srcElement) e.target = e.srcElement; 1004 1005 return e; 1006}; 1007 1008/*!\brief CustomEvent class that represents a custom event type and can 1009 * be associated with one or more Callback. 1010 * \param type event type 1011 * \param bind bind scope (default window) 1012 */ 1013BS.com.CustomEvent = function (type, bind) 1014{ 1015 this.type = type; 1016 this.scope = bind || window; 1017 this.cbA = []; 1018}; 1019 1020BS.com.CustomEvent.prototype = { 1021 intvlID: null, 1022 1023 /*!\brief Add callback function. 1024 * \param f function 1025 * \param bind bind scope (optional) 1026 * \param d data (optional) 1027 */ 1028 addCB: function (f, bind, d) 1029 { 1030 this.cbA.push(new BS.com.Callback(f, bind, d)); 1031 }, 1032 1033 /*!\brief Delete callback function based on function and data. 1034 * \param f function 1035 * \param bind bind scope (optional) 1036 * \param d data (optional) 1037 */ 1038 delCB: function (f, bind, d) 1039 { 1040 var cb, found = false; 1041 1042 for (var i=0, l=this.cbA.length; i<l; i++) { 1043 cb = this.cbA[i]; 1044 if (cb.f != f || cb.bind != bind || cb.d != d) 1045 continue; 1046 1047 cb.bind = cb.d = cb.f = null; 1048 this.cbA.splice(i, 1); 1049 found = true; 1050 i--; 1051 l--; 1052 } 1053 1054 return found; 1055 }, 1056 1057 /*!\brief Delete all callback functions. */ 1058 delCBAll: function () 1059 { 1060 BS.utl.event.detachData(this); 1061 1062 var t; 1063 for (var i=0, l=this.cbA.length; i<l; i++) { 1064 t = this.cbA[i]; 1065 t.bind = t.d = t.f = null; 1066 delete this.cbA[i]; 1067 } 1068 this.cbA = []; 1069 }, 1070 1071 /*!\brief Destructor (pseudo) */ 1072 _delete: function () { this.delCBAll(); }, 1073 1074 /*!\brief Execute callback functions. The callback is executed 1075 * in the Callback::bind scope if not null otherwise, the 1076 * scope is CustomEvent::scope. The callback function is 1077 * effectively called as follows: 1078 * 1079 * cb(CustomEvent::type, Callback::d, arguments) 1080 * arguments[0] target 1081 * arguments[1] attach data (optional) 1082 */ 1083 exec: function () 1084 { 1085 var cb, r, scope; 1086 for (var i=0, l=this.cbA.length; i<l; i++) { 1087 cb = this.cbA[i]; 1088 scope = cb.bind ? cb.bind : this.scope; 1089 r = cb.f.call(scope, this.type, cb.d, arguments); 1090 } 1091 1092 return r; 1093 }, 1094 1095 /*!\brief Attach to an event handler of an object. 1096 * \param obj DOM object 1097 * \param type event type 1098 * \param d data (optional) 1099 */ 1100 attach: function (obj, type, d) 1101 { 1102 return BS.utl.event.attach(obj, type, this.exec, this, d); 1103 }, 1104 1105 /*!\brief Detach from an event handler of an object. 1106 * \param obj DOM object 1107 * \param type event type 1108 */ 1109 detach: function (obj, type) 1110 { 1111 return BS.utl.event.detach(obj, type, this.exec); 1112 }, 1113 1114 /*!\brief Attach to setInterval(). 1115 * \param ms milliseconds 1116 * \param d data (optional) 1117 */
1118 setInterval: function (ms, d) 1119 { 1120 this.clearInterval(); 1121 this.intID = BS.utl.event.setInterval(ms, this.exec, this, d); 1122 return this.intID; 1123 }, 1124 1125 /*!\brief Attach to setTimeout(). 1126 * \param ms milliseconds 1127 * \param d data (optional) 1128 */ 1129 setTimeout: function (ms, d) 1130 { 1131 return BS.utl.event.setTimeout(ms, this.exec, this, d); 1132 }, 1133 1134 /*!\brief Detach from setInterval(). */ 1135 clearInterval: function () 1136 { 1137 if (!this.intID) return; 1138 window.clearInterval(this.intID); 1139 this.intID = null; 1140 }, 1141 1142 toString: function () { return 'CustomEvent: ' + this.type; } 1143}; 1144 1145BS.com.Debug = function () {}; 1146 1147BS.com.Debug.prototype = { 1148 _logOpt: function (opt, c) 1149 { 1150 if (!opt || typeof(opt) != 'string') return false; 1151 return (opt.indexOf(c) != -1) 1152 }, 1153 1154 /*!\brief Log message if textarea is set. 1155 * \param s message 1156 * \param opt option string 1157 * c: clear textarea 1158 * n: no newline 1159 */ 1160 log: function (s, opt) 1161 { 1162 if (!this._ta) this.setTextarea(); 1163 1164 var t; 1165 1166 if (s && typeof s == 'object') t = BS.utl.array.toString(s); 1167 else t = s; 1168 1169 if (this._logOpt(opt, 'c')) this._ta.value = ''; 1170 1171 if (typeof(t) != 'undefined') { 1172 this._ta.value += t; 1173 if (!this._logOpt(opt, 'n')) this._ta.value += '\n'; 1174 } 1175 }, 1176 1177 /*!\brief Set textarea. If null, create textarea. 1178 * \param taID textarea ID 1179 * \note requires document.body 1180 */ 1181 setTextarea: function (taID) 1182 { 1183 if (taID) this._ta = BS.utl.dom.get(taID); 1184 else { 1185 this._ta = BS.utl.mm.domNew(document.body, 'form'); 1186 this._ta.innerHTML = '<input type=reset><br>' + 1187 '<textarea id=' + 1188 (this._ta = BS.utl.dom.mkid()) + 1189 ' cols=80 rows=20></textarea>'; 1190 this._ta = BS.utl.dom.get(this._ta); 1191 } 1192 this._ta.value = ''; 1193 } 1194}; 1195 1196/*!\brief Memory management class that implements a pseudo destructor 1197 * mechanism. If the object is a DOM node, it is automatically 1198 * removed from the parentNode. Precedence is given to non DOM 1199 * node objects in the delete phase. 1200 * \param cnm CSS class name 1201 */ 1202BS.com.Delete = function (cnm) 1203{ 1204 this._cnm = cnm; 1205 this._delA = []; 1206 this._param = []; 1207}; 1208 1209/*!\brief Hover compatibility callback. */ 1210BS.com.Delete._hoverCB = function () 1211{ 1212 var t = BS.utl.event.getTarget(arguments[0]); 1213 if (arguments[0].type == 'mouseover') 1214 BS.utl.dom.addClass(t, 'bsHover'); 1215 else BS.utl.dom.delClass(t, 'bsHover'); 1216}; 1217 1218BS.com.Delete.prototype = { 1219 /*!\brief Add item for later cleanup. 1220 * \param i item 1221 */ 1222 add: function (i) { this._delA.push(i); }, 1223 1224 _del: function (i) 1225 { 1226 if (!i || !i._delete) return; 1227 1228 i._delete(); 1229 i._delete = null; 1230 1231 delete i; 1232 }, 1233 1234 /*!\brief Execute pseudo-destructor and delete for item. 1235 * \param obj item 1236 */ 1237 del: function (obj) 1238 { 1239 var i, l; 1240 1241 this._del(obj); 1242 1243 for (i=0, l=this._delA.length; i<l; i++) { 1244 if (this._delA[i] != obj) continue; 1245 this._delA.splice(i, 1); 1246 return; 1247 } 1248 1249 for (i=0, l=this._domA.length; i<l; i++) { 1250 if (this._domA[i] != obj) continue; 1251 this._domA.splice(i, 1); 1252 return; 1253 } 1254 }, 1255 1256 /*!\brief Execute pseudo-destructor and delete for 1257 * all items in the specified array. 1258 * \param iA item array 1259 */ 1260 delArr: function (iA) 1261 { 1262 if (iA) 1263 for (var i=0, l=iA.length; i<l; i++) this._del(iA[i]); 1264 //for (var i in iA) this._del(iA[i]); 1265 1266 delete iA; 1267 }, 1268 1269 /*!\brief Returns object for specified object type (variable 1270 * arguments) and caches in this._delA. 1271 * \param obj object constructor 1272 * \return object 1273 */ 1274 oNew: function (obj) 1275 { 1276 var t = []; 1277 for (var i=1, l=arguments.length; i<l; i++) 1278 t.push(arguments[i]); 1279 t = BS.utl.object.create(obj, t); 1280 this.add(t); 1281 return t; 1282 }, 1283 1284 /*!\brief Returns new CustomEvent and caches the object in 1285 * this._delA. 1286 * \param type event type 1287 * \param oScope object scope (default window) 1288 */ 1289 ceNew: function () 1290 { 1291 var t = BS.utl.object.create(BS.com.CustomEvent, arguments); 1292 this.add(t); 1293 return t; 1294 }, 1295 1296 /*!\brief Returns DOM object for specified object id, sets 1297 * primary class name and appends optional class name. 1298 * \param e object or object id 1299 * \param cnm class name (optional) 1300 * \return DOM object 1301 */ 1302 domGet: function (e, cnm) 1303 { 1304 e = BS.utl.dom.get(e); 1305 1306 if (!e.nodeName) throw 'AssertErr BS.com.Delete.domGet'; 1307 1308 if (this._cnm) BS.utl.dom.addClass(e, this._cnm); 1309 1310 if (this._param['className']) 1311 BS.utl.dom.addClass(e, this._param['className']); 1312 1313 if (cnm) BS.utl.dom.addClass(e, cnm); 1314 1315 return e; 1316 }, 1317 1318 /*!\brief Appends DOM object for specified node name, sets
1319 * primary class name and appends optional class name. 1320 * \param node append node 1321 * \param name node name 1322 * \param cnm class name (optional) 1323 * \return DOM object 1324 */ 1325 domNew: function (node, name, cnm) 1326 { 1327 var e = document.createElement(name); 1328 1329 if (this._cnm) BS.utl.dom.addClass(e, this._cnm); 1330 1331 if (this._param['className']) 1332 BS.utl.dom.addClass(e, this._param['className']); 1333 1334 if (cnm) BS.utl.dom.addClass(e, cnm); 1335 1336 if (node) node.appendChild(e); 1337 1338 return e; 1339 }, 1340 1341 /*!\brief Hover wrapper for this.domNew(). */ 1342 domNewHover: function (node, name, cnm) 1343 { 1344 var e = this.domNew(node, name, cnm); 1345 BS.utl.event.attach(e, 'mouseover', BS.com.Delete._hoverCB); 1346 BS.utl.event.attach(e, 'mouseout', BS.com.Delete._hoverCB); 1347 return e; 1348 }, 1349 1350 /*!\brief Sets parameter value for specified name. 1351 * className CSS class name 1352 * \param name name 1353 * \param value value 1354 */ 1355 setParam: function (name, value) 1356 { 1357 this._param[name] = value; 1358 }, 1359 1360 /*!\brief Pseudo destructor. */ 1361 _delete: function () 1362 { 1363 this._delA.reverse(); 1364 this.delArr(this._delA); 1365 delete this._param; 1366 } 1367}; 1368 1369/*!\brief Global event handler that attaches to root-most elements. 1370 * \note single instantiation only 1371 */ 1372BS.com.GlobalEvent = function () { this.ceA = []; }; 1373 1374BS.com.GlobalEvent.prototype = { 1375 _delete: function () 1376 { 1377 //for (var i in this.ceA) { 1378 for (var i=0, l=this.ceA.length; i<l; i++) { 1379 if (this.ceA[i]._delete) 1380 this.ceA[i]._delete(); 1381 delete this.ceA[i]; 1382 } 1383 }, 1384 1385 /*!\brief Returns cached CustomEvent for specified type. 1386 * \param type event type 1387 * \return CustomEvent 1388 */ 1389 _getCE: function (type) 1390 { 1391 if (!this.ceA[type]) { 1392 this.ceA[type] = new BS.com.CustomEvent(type + 'Evt'); 1393 1394 var obj; 1395 switch (type) { 1396 case 'load': 1397 case 'resize': 1398 case 'unload': obj = window; break; 1399 case 'keydown': 1400 case 'keyup': 1401 case 'keypress': 1402 obj = document; break; 1403 default: obj = document.body; break; 1404 } 1405 1406 this.ceA[type].attach(obj, type); 1407 } 1408 1409 return this.ceA[type]; 1410 }, 1411 1412 /*!\brief Adds callback for specified type. 1413 * \param type event type 1414 * \param f function 1415 * \param bind bind scope (optional) 1416 * \param data data (optional) 1417 */ 1418 addCB: function (type, f, bind, d) 1419 { 1420 this._getCE(type).addCB(f, bind, d); 1421 }, 1422 1423 /*!\brief Deletes callback for specified type. 1424 * \param type event type 1425 * \param f function 1426 * \param data data (optional) 1427 */ 1428 delCB: function (type, f, d) 1429 { 1430 this._getCE(type).delCB(f, d); 1431 } 1432}; 1433 1434BS.com.Location = function () { this.location = document.location; }; 1435 1436BS.com.Location.prototype = { 1437 /*!\brief Returns array of the location path components. */ 1438 getPathnameArr: function () 1439 { 1440 if (!this.pathnameA) { 1441 this.pathnameA = this.location.pathname.split('/'); 1442 this.pathnameA.shift(); 1443 } 1444 1445 return this.pathnameA; 1446 }, 1447 1448 /*!\brief Returns the location search string. */ 1449 getSearch: function () 1450 { 1451 return (this.location.search) ? 1452 this.location.search.substr(1) : null; 1453 }, 1454 1455 /*!\brief Returns array of the location search string components 1456 * URL decoded. 1457 * \note no array support for multi form vars 1458 */ 1459 getSearchArr: function () 1460 { 1461 var s; 1462 if (!(s = this.getSearch())) return null; 1463 return BS.utl.array.urldecode(s); 1464 }, 1465 1466 getHash: function () 1467 { 1468 return (this.location.hash) ? 1469 this.location.hash.substr(1) : null; 1470 }, 1471 1472 getHashArr: function () 1473 { 1474 var s; 1475 if (!(s = this.getHash())) return null; 1476 return BS.utl.array.urldecode(s); 1477 } 1478}; 1479 1480BS.com.Window = function () {}; 1481 1482BS.com.Window.prototype = { 1483 open: function (url, dim, attr, name) 1484 { 1485 var args = "width=" + dim[0] + ",height=" + dim[1]; 1486 1487 if (attr && ((typeof attr) == "string")) { 1488 args += (attr.indexOf("menubar") != -1 ) ? 1489 ",menubar=yes" : ",menubar=no"; 1490 args += (attr.indexOf("noscroll") != -1 ) ? 1491 ",scrollbars=no" : ",scrollbars=yes"; 1492 args += (attr.indexOf("resize") != -1) ? 1493 ",resizable=yes" : ",resizeable=no"; 1494 args += (attr.indexOf("tool") != -1) ? 1495 ",toolbar=yes" : ",toolbar=no"; 1496 args += (attr.indexOf("loc") != -1) ? 1497 ",location=yes" : ",location=no"; 1498 args += (attr.indexOf("status") != -1) ? 1499 ",status=yes" : ",status=no"; 1500 } 1501 else args += ",menubar=no,scrollbars=yes,resizeable=no,toolbar=no,location=no,status=no"; 1502 1503 if (name === true) 1504 name = 'Window' + Math.floor(100000*Math.random()); 1505 else if (!name) name = 'Window'; 1506 1507 var w = window.open(url, name, args); 1508 w.focus(); 1509 return w; 1510 }, 1511 1512 openLink: function(url, dim, attr, name) 1513 { 1514 this.open(url, dim, attr, name); 1515 } 1516}; 1517 1518BS.com.Form = {}; 1519 1520BS.com.Form.Select = function (obj, name, first, className) 1521{ 1522 if (!obj) obj = null; 1523 1524 if (!className) className = null; 1525 1526 this.mm = new BS.com.Delete(); 1527 this.sel = this.mm.domNew(obj, 'select', className); 1528 this.sel.setAttribute('name', name); 1529 1530 if (first) { 1531 this.optMM = new BS.com.Delete(); 1532 tmp = this.optMM.domNew(this.sel, 'option'); 1533 tmp.value = first[0]; tmp.text = first[1]; 1534 } 1535}; 1536 1537BS.com.Form.Select.prototype = { 1538 _delete: function () { this.mm._delete(); }, 1539 1540 clear: function () 1541 { 1542 if (this.optMM) { 1543 for (var t=this.sel; t.hasChildNodes(); 1544 t.removeChild(t.firstChild)); 1545 this.optMM._delete(); 1546 delete this.optMM; 1547 } 1548 1549 this.optMM = new BS.com.Delete(); 1550 }, 1551
1552 load: function (arr, f_concat) 1553 { 1554 var tmp; 1555 1556 if (!this.optMM || !f_concat) { 1557 this.clear(); 1558 } 1559 1560 for (var i = 0, l = arr.length; i<l; i++) { 1561 tmp = this.optMM.domNew(this.sel, 'option', (arr[i][2] ? arr[i][2] : null)); 1562 tmp.value = arr[i][0]; 1563 tmp.text = arr[i][1]; 1564 } 1565 1566 this.sel.selectedIndex = 0; 1567 }, 1568 1569 setVal: function (val) { BS.utl.form.setValue(this.sel, val); }, 1570 1571 getVal: function () { return BS.utl.form.getValue(this.sel); }, 1572 getText: function () 1573 { 1574 return this.sel.options[this.sel.selectedIndex].text; 1575 }, 1576 1577 setStyle: function (prop, val) 1578 { 1579 BS.utl.dom.setStyle(this.sel, prop, val); 1580 }, 1581 1582 addClass: function (cn) { BS.utl.dom.addClass(this.sel, cn); }, 1583 1584 disable: function (flag) { this.sel.disabled = flag; }, 1585 1586 reset: function () { this.sel.selectedIndex = 0; } 1587}; 1588 1589BS.com.Button = function (rootObj, cls, txt) 1590{ 1591 this.obj = _bsMm.domNew(null, "input", cls); 1592 this.obj.setAttribute('type', 'button'); 1593 this.obj.setAttribute('value', txt); 1594 rootObj.appendChild(this.obj); 1595 this.ceA = []; 1596} 1597 1598BS.com.Button.prototype = { 1599 _delete: function () 1600 { 1601 _bsMm.delArr(this.ceA); 1602 }, 1603 1604 attach: function (type, func, scope, data) 1605 { 1606 var ce = _bsMm.ceNew(); 1607 ce.addCB(func, scope, data); 1608 ce.attach(this.obj, type); 1609 this.ceA.push({ce:ce, type:type}); 1610 }, 1611 1612 disable: function (val) 1613 { 1614 if (val) this.obj.setAttribute('disabled', true); 1615 else this.obj.removeAttribute('disabled'); 1616 }, 1617 1618 setLabel: function (str) 1619 { 1620 this.obj.setAttribute('value', str); 1621 } 1622}; 1623 1624BS.utl.gvA = []; 1625BS.utl.gvAi = 0; 1626BS.utl.mkGvId = function () { return BS.utl.gvAi++; }; 1627 1628BS.utl.mkGvStr = function (obj) 1629{ 1630 var gvid = BS.utl.mkGvId(); 1631 BS.utl.gvA[gvid] = obj; 1632 return 'BS.utl.gvA[' + gvid + ']'; 1633} 1634 1635BS.utl.object = {}; 1636 1637BS.utl.object.clone = function (obj, noRecursion) 1638{ 1639 if (!obj || typeof obj != 'object') return obj; 1640 1641 var newObj = (obj.constructor == Array) ? [] : {}; 1642 1643 for (var i in obj) 1644 newObj[i] = noRecursion ? obj[i] : BS.utl.object.clone(obj[i]); 1645 1646 return newObj; 1647}; 1648 1649/*!\brief New object creation using argument array. 1650 * \param obj object 1651 * \param argA argument array 1652 */ 1653BS.utl.object.create = function (obj, argA) 1654{ 1655 var t = function (tA) { obj.apply(this, tA); }; 1656 t.prototype = obj.prototype; 1657 return new t(argA); 1658}; 1659 1660/*!\brief Inherit class definition. This function must be run after the 1661 * definition of the parent/child constructors and prototypes. 1662 * The child constructor uses the Function.call(this, ...) 1663 * method to call the parent constructor. 1664 * \param parent parent class 1665 * \param child child class 1666 */ 1667BS.utl.object.inherit = function (parent, child) 1668{ 1669 if (!parent) throw 'BS.utl.object.inherit missing parent class'; 1670 var tmp = function () {}; 1671 tmp.prototype = parent.prototype; 1672 var old = function () {}; 1673 old.prototype = child.prototype; 1674 child.prototype = new tmp; 1675 old.prototype = new old; 1676 for (var i in old.prototype) child.prototype[i] = old.prototype[i]; 1677}; 1678 1679BS.utl.object._cacheA = []; 1680BS.utl.object.cache = function (oName) 1681{ 1682 var a = BS.utl.object._cacheA; 1683 1684 if (!isset(a[oName])) 1685 a[oName] = BS.utl.mm.oNew(eval(oName)); 1686 1687 return a[oName]; 1688} 1689 1690BS.utl.mm = new BS.com.Delete; 1691BS.utl.event = BS.utl.mm.oNew(BS.com.Event); 1692BS.utl.browser = BS.utl.mm.oNew(BS.com.Browser); 1693 1694BS.utl.array = {}; 1695 1696/*!\brief Copy array. 1697 * \param a Array 1698 */ 1699BS.utl.array.copy = function (a) 1700{ 1701 var r = []; 1702 1703 if (a.constructor == arguments.constructor) 1704 a = Array.prototype.slice.call(a); 1705 1706 for (var i in a) r[i] = a[i]; 1707 1708 return r; 1709}; 1710 1711/*!\brief Calls callback function for each member of the array with an 1712 * optional data variable. The callback is called with a single 1713 * element of the array and the optional data. 1714 * \param a Array 1715 * \param cb callback 1716 * \param d data (optional) 1717 * \param bind bind scope (optional) 1718 */ 1719BS.utl.array.foreach = function (a, cb, bind) 1720{ 1721 if (bind) f = function (aT, dT) { cb.call(bind, aT, dT); }; 1722 else f = cb; 1723 1724 for (var d=null, i=0, l=a.length; i<l; i++) d = f(a[i], d); 1725 1726 if (bind) delete f; 1727 1728 return d; 1729}; 1730 1731/*!\brief Returns length of associative array or object 1732 * \param a Array 1733 */ 1734BS.utl.array.length = function (a) 1735{ 1736 var n = 0; 1737 for (var i in a) n++; 1738 return n; 1739}; 1740 1741/*!\brief Reduces Array by removing [0] only elements. Accepts an 1742 * optional max depth parameter. 1743 * \param arr Array 1744 * \param d max depth (optional) 1745 * \return Array 1746 */ 1747BS.utl.array.reduce = function (arr, d) 1748{ 1749 var arF = BS.utl.array.reduce, i; 1750 1751 if (typeof d == 'undefined') d = -1; 1752 1753 if (!d) return arr; 1754 else if (d > 0) d--; 1755 1756 if (typeof arr != 'object') return arr; 1757 if (arr.length == 1) return arr = arF(arr[0], d); 1758 1759 for (i in arr) arr[i] = arF(arr[i], d); 1760 1761 return arr; 1762}; 1763 1764/*!\brief Calls BS.utl.array.reduce() for every member of array. 1765 * \param arr Array 1766 * \return Array 1767 */ 1768BS.utl.array.reduceArr = function (arr) 1769{ 1770 for (var i in arr) arr[i] = BS.utl.array.reduce(arr[i]); 1771 return arr; 1772}; 1773 1774/*!\brief Converts Array to a String. 1775 * \param arr Array 1776 * \param d depth (internal) 1777 * \return String 1778 */ 1779BS.utl.array.toString = function (arr, d) 1780{ 1781 var i, j = 0, s = '', t; 1782 1783 if (typeof d == 'undefined') d = 0; 1784 1785 if (arr === null || arr.constructor == String) 1786 return (arr === null ? 'null' : '"' + arr + '"') + '\n'; 1787 1788 for (i in arr) j++; 1789 if (!j && arr.length) arr = Array.prototype.slice.call(arr); 1790 1791 if (d && arr.constructor != Array) return arr.constructor.toString(); 1792 1793 for (i in arr) { 1794 for (j=0; j<d; j++) s += '. '; 1795 s += '[' + i + ']'; 1796 t = arr[i]; 1797 if (t !== null && typeof t == 'object') 1798 s += '\n' + BS.utl.array.toString(t, d+1); 1799 else { 1800 s += ' '; 1801 if (t === null) s += 'null\n'; 1802 else if (typeof(t) == 'string') s += '"' + t + '"\n'; 1803 else s += t + '\n'; 1804 } 1805 } 1806 1807 return s; 1808}; 1809 1810/*!\brief Deletes empty members. 1811 * \param a Array 1812 */ 1813BS.utl.array.trim = function (a) 1814{ 1815 for (var i in a) { if (empty(a[i])) delete a[i]; } 1816 return a; 1817}; 1818 1819/*!\brief Returns an array representation of the URL encoded string of 1820 * name/value pairs. The form variable array representation 1821 * is based on the PHP interpretation. 1822 * \param s URL string 1823 * \return array 1824 */ 1825BS.utl.array.urldecode = function (s) 1826{ 1827 var a = s.split('&'), r = [], t = []; 1828 var i, l, nA, nI, nL; 1829 var de = BS.utl.string.urldecode; 1830 var na = BS.utl.form._getNameArr; 1831 1832 for (i=0, l=a.length; i<l; i++) { 1833 t = a[i].split('=', 2); 1834 for (nA=na(de(t[0])), nI=0, nL=nA.length, nT=r; nI<nL-1; 1835 nI++) { 1836 if (typeof(nT[nA[nI]]) == 'undefined' || 1837 nT[nA[nI]].constructor != Array) 1838 nT[nA[nI]] = []; 1839 nT = nT[nA[nI]]; 1840 } 1841 1842 nT[nA[nI]] = de(t[1]); 1843 } 1844 1845 return r; 1846}; 1847 1848/*!\brief Returns a string representing the specified array as a form 1849 * URL encoded string. The form variable array representation 1850 * is based on the PHP interpretation. 1851 * \param arr array 1852 * \param name name (optional for array recursion) 1853 * \return URL string 1854 */ 1855BS.utl.array.urlencode = function (arr, name) 1856{ 1857 var s = null, t; 1858 var aeF = BS.utl.array.urlencode; 1859 var seF = BS.utl.string.urlencode; 1860 1861 for (var i in arr) { 1862 if (s) s += '&'; 1863 else s = ''; 1864 1865 t = name ? (name + '[' + i + ']') : i; 1866 1867 if (typeof arr[i] == 'object') 1868 s += !empty(arr[i]) ? aeF(arr[i], t) : (seF(t) + '='); 1869 else s += (seF(t) + '=' + seF(arr[i])); 1870 } 1871 1872 return s; 1873}; 1874 1875/*!\brief Tests if array contains specified element 1876 * \param array array 1877 * \param obj element 1878 * \return boolean 1879 */ 1880BS.utl.array.inArray = function (arr, obj) 1881{ 1882 if (empty(arr)) return false;
1883 1884 for (var i=0, l=arr.length; i < l; i++) if (arr[i] == obj) return true; 1885 return false; 1886}; 1887 1888BS.utl.debug = new BS.com.Debug; 1889var log = function (a, b) { BS.utl.debug.log(a, b); }; 1890 1891BS.utl.globalEvent = BS.utl.mm.oNew(BS.com.GlobalEvent); 1892BS.utl.globalEvent.addCB('unload', BS.utl.mm._delete, BS.utl.mm); 1893 1894BS.utl.dom = new BS.com.Dom; 1895 1896BS.utl.cookie = {}; 1897 1898BS.utl.cookie.get = function (n) 1899{ 1900 var c = document.cookie, i, j; 1901 n = escape(n); 1902 1903 if ((i = c.indexOf(n + '=')) < 0) return null; 1904 1905 i += n.length + 1; 1906 1907 if ((j = c.indexOf(';', i)) < 0) j = c.length; 1908 1909 return unescape(c.substring(i, j)); 1910}; 1911 1912BS.utl.form = {}; 1913 1914/*!\brief Return the form element of the specified name. Needed to get 1915 * around a stupid IE problem with dynamically-generated form 1916 * elements. 1917 * \param fObj form object 1918 * \param n element name 1919 */ 1920BS.utl.form.getElem = function (fObj, n) 1921{ 1922 if (BS.utl.browser.isIE) { 1923 var el = []; 1924 for (var e, i=0, l=fObj.elements.length; i<l; i++) { 1925 e = fObj.elements[i]; 1926 if (e.name == n) el.push(e); 1927 } 1928 switch (el.length) { 1929 case 0: return null; 1930 case 1: return el[0]; 1931 default: return el; 1932 } 1933 } 1934 else { 1935 if (isset(fObj.elements[n])) return fObj.elements[n]; 1936 return null; 1937 } 1938}; 1939 1940/*!\brief Return the value of the specified form element. 1941 * \param fe form element 1942 */ 1943BS.utl.form.getValue = function (fe) 1944{ 1945 switch (fe.type) { 1946 case 'hidden': 1947 case 'text': 1948 case 'password': 1949 case 'file': 1950 case 'textarea': return fe.value; 1951 case 'checkbox': 1952 case 'radio': 1953 if (fe.checked) return fe.value; 1954 break; 1955 case 'select-one': 1956 if (fe.selectedIndex < 0) fe.selectedIndex = 0; 1957 if (fe.length) return fe[fe.selectedIndex].value; 1958 break; 1959 case 'select-multiple': 1960 var r = null; 1961 for (var i=0, l=fe.length; i<l; i++) { 1962 if (!fe[i].selected) continue; 1963 if (!r) r = []; 1964 r.push(fe[i].value); 1965 } 1966 return r; 1967 case 'button': 1968 case 'submit': 1969 break; 1970 default: throw 'AssertErr: unimplemented form element: ' + fe.type; 1971 } 1972 1973 return null; 1974}; 1975 1976/*!\brief Set the value of the specified form element. 1977 * \param fe form element 1978 * \param v value 1979 * \param s skip IE setTimeout() workaround (default false) 1980 */ 1981BS.utl.form.setValue = function (fe, v, s) 1982{ 1983 var i, l, t; 1984 1985 try { 1986 t = fe.type; 1987 if (!isset(t) && isset(fe.length)) t = fe[0].type; 1988 1989 switch (t) { 1990 case 'checkbox': 1991 if (v.constructor == Array) { 1992 fe.checked = false; 1993 for (i in v) { 1994 if (fe.value == v[i]) { 1995 fe.checked = true; 1996 break; 1997 } 1998 } 1999 } 2000 else fe.checked = (fe.value == v); 2001 break; 2002 case 'hidden': 2003 case 'text': 2004 case 'textarea': 2005 fe.value = v; 2006 break; 2007 case 'radio': 2008 if (fe.length) { 2009 for (i=0, l=fe.length; i<l; i++) 2010 fe[i].checked = (fe[i].value == v); 2011 } 2012 else fe.checked = (fe.value == v); 2013 break; 2014 case 'select-one': 2015 case 'select-multiple': 2016 for (i=0, l=fe.length; i<l; i++) { 2017 if (fe[i].value != v) { 2018 if (fe.type == 'select-one') 2019 fe[i].selected = false; 2020 continue; 2021 } 2022 fe[i].selected = true; 2023 break; 2024 } 2025 break; 2026 default: throw 'AssertErr: unimplemented form element'; 2027 } 2028 } 2029 catch (e) { 2030 if (!s) BS.utl.event.setTimeout(0, 2031 function () { BS.utl.form.setValue(fe, v, true); }); 2032 } 2033}; 2034 2035/*!\brief Returns an array representing the array components in the 2036 * string representation of an array. 2037 * \param s string array representation 2038 */ 2039BS.utl.form._getNameArr = function (s) 2040{ 2041 for (var a = s.split('['), i=0, l=a.length, n, t; i<l; i++) { 2042 n = a[i]; 2043 t = n.indexOf(']'); 2044 2045 if ((!i && (!n.length || t != -1)) || 2046 (i && (t == -1 || t != n.lastIndexOf(']')))) 2047 throw 'AssertErr: invalid name format'; 2048 2049 if (i) a[i] = n.substr(0, n.length - 1); 2050 } 2051 2052 return a; 2053} 2054 2055/*!\brief Sets form to match any existing members in the specified 2056 * array. 2057 * \param f form object 2058 * \param a array 2059 * \param s skip IE setTimeout() workaround (default false) 2060 */ 2061BS.utl.form.fromArray = function (f, a, s) 2062{ 2063 var sF = BS.utl.form.setValue; 2064 var vF = BS.utl.form.fromArray._g; 2065 2066 for (var i=0, t=f.elements, l=t.length, v; i<l; i++) { 2067 if (!t[i].name) continue; 2068 2069 if ((v = vF(t[i].name, a)) === null) continue; 2070 2071 sF(t[i], v, s); 2072 } 2073} 2074 2075/*!\brief Returns value from array based on string representation of the 2076 * desired array value. 2077 * \param s string array representation 2078 * \param dA array 2079 */ 2080BS.utl.form.fromArray._g = function (s, dA) 2081{ 2082 var a = BS.utl.form._getNameArr(s); 2083 2084 for (var i=0, l=a.length, n, tA = dA; i<l; i++) { 2085 n = a[i]; 2086 2087 if (!isset(tA[n])) return null; 2088 else if (tA[n].constructor != Array && 2089 tA[n].constructor != Object) { 2090 if (i == l - 1) return tA[n]; 2091 return null; 2092 } 2093 else if (i == l - 2 && a[i+1] === '' && 2094 (tA[n].constructor == Array || 2095 tA[n].constructor == Object)) 2096 return tA[n]; 2097 2098 tA = tA[n]; 2099 } 2100 return null; 2101} 2102 2103/*!\brief Returns an array representing the elements in the form object 2104 * optionally skipping blank entries. 2105 * \param f form object 2106 * \param s skip blank (default false) 2107 * \return array 2108 */ 2109BS.utl.form.toArray = function (f, s) 2110{ 2111 var sF = BS.utl.form.toArray._s; 2112 var vF = BS.utl.form.getValue; 2113 2114 for (var i=0, t=f.elements, l=t.length, rA=[], v; i<l; i++) { 2115 if (!t[i].name) continue; 2116 2117 if ((v = vF(t[i])) === null || (s && !v)) continue; 2118 2119 sF(t[i].name, v, rA); 2120 } 2121 return rA; 2122}; 2123 2124/*!\brief Sets value into array creating all necessary elements in the 2125 * string representation of the destination in the array. 2126 * \param s string array represenation 2127 * \param v value 2128 * \param rA array (return) 2129 */ 2130BS.utl.form.toArray._s = function (s, v, rA) 2131{ 2132 var a = BS.utl.form._getNameArr(s); 2133 2134 for (var i=0, l=a.length-1, n, t, tA=rA; i<l; i++) { 2135 n = a[i]; 2136 2137 if (!n.length) { 2138 tA.push(t = []); 2139 tA = t;
2140 continue; 2141 } 2142 2143 if (!isset(tA[n]) || tA[n].constructor != Array) tA[n] = []; 2144 2145 tA = tA[n]; 2146 } 2147 2148 n = a[a.length - 1]; 2149 2150 if (!n.length) tA.push(v); 2151 else if (typeof(tA[n]) == 'undefined') tA[n] = v; 2152 else if (tA[n].constructor == Array) tA[n].push(v); 2153 else tA[n] = [tA[n], v]; 2154 2155 return rA; 2156} 2157 2158BS.utl.form.post = function (d, action) 2159{ 2160 var f = BS.utl.mm.domNew(null, 'form'); 2161 f.setAttribute('method', 'post'); 2162 if (action) f.setAttribute('action', action); 2163 2164 var str = ''; 2165 for (var k in d) { 2166 str += '<input type="hidden" name="' + k + '" value="' + d[k] + '">'; 2167 } 2168 2169 f.innerHTML = str; 2170 document.body.appendChild(f); 2171 f.submit(); 2172} 2173 2174BS.utl.func = {}; 2175 2176BS.utl.func.bind = function (f, scope) 2177{ 2178 return function () { return f.apply(scope, arguments); }; 2179}; 2180 2181BS.utl.img = {}; 2182 2183/*!\brief Returns a single Image or an array of Images based on the 2184 * number of image src strings supplied to the function. 2185 * \param variable arguments image src string(s) 2186 * \return Image or array of Image 2187 */ 2188BS.utl.img.create = function() 2189{ 2190 var r; 2191 2192 if (arguments.length == 1) { 2193 r = new Image; 2194 r.src = arguments[0]; 2195 return r; 2196 } 2197 2198 r = []; 2199 for (var i=0, l=arguments.length; i<l; i++) { 2200 r[i] = new Image; 2201 r[i].src = arguments[i]; 2202 } 2203 2204 return r; 2205}; 2206 2207BS.utl.location = new BS.com.Location; 2208 2209BS.utl.mouse = {}; 2210 2211/*!\brief Return offset of mouse based on event. 2212 * \param evt event 2213 */ 2214BS.utl.mouse.ofs = function (evt) 2215{ 2216 var r = BS.utl.event.getXY(BS.com.Event.getEvent(evt)); 2217 if (BS.utl.browser.isIE) BS.utl.xy.add(r, BS.utl.dom.scrollOfs()); 2218 return r; 2219}; 2220 2221/*!\brief Return position of mouse based on event. 2222 * \param evt event 2223 */ 2224BS.utl.mouse.pos = function (evt) 2225{ 2226 evt = BS.com.Event.getEvent(evt); 2227 return [evt.clientX, evt.clientY]; 2228}; 2229 2230BS.utl.string = {}; 2231 2232/*!\brief Returns a URL decoded string based on the provided string. 2233 * \param s string 2234 * \return URL encoded string 2235 */ 2236BS.utl.string.urldecode = function (s) { return decodeURIComponent(s); }; 2237 2238/*!\brief Returns a URL encoded string based on the provided string. 2239 * \param s string 2240 * \return URL encoded string 2241 */ 2242BS.utl.string.urlencode = function (s) { return encodeURIComponent(s); }; 2243 2244BS.utl.string.fmtBytes = function (bytes) 2245{ 2246 var unit; 2247 var n; 2248 2249 bytes = parseInt(bytes); 2250 if (isNaN(bytes)) return '-'; 2251 2252 if (bytes/(1024) < 1) { 2253 unit = 'bytes'; 2254 n = Math.floor(bytes); 2255 } 2256 else if (bytes/(1024*1024) < 1) { 2257 unit = 'KB'; 2258 n = Math.floor(10*bytes/(1024))/10; 2259 } 2260 else if (bytes/(1024*1024*1024) < 1) { 2261 unit = 'MB'; 2262 n = Math.floor(10*bytes/(1024*1024))/10; 2263 } 2264 else { 2265 unit = 'GB'; 2266 n = Math.floor(10*bytes/(1024*1024*1024))/10; 2267 } 2268 2269 n = n.toString(); 2270 if (n.indexOf('.') < 0) n += '.0'; 2271 2272 return n + unit; 2273}; 2274 2275BS.utl.string.truncate = function (str, n) 2276{ 2277 if (str.length >= n) return (str.substr(0, n-3) + '...'); 2278 else return str; 2279}; 2280 2281BS.utl.string.fmtMoney = function (mnt) 2282{ 2283 mnt -= 0; 2284 mnt = (Math.round(mnt*100))/100; 2285 return (mnt == Math.floor(mnt)) ? mnt + '.00' 2286 : ( (mnt*10 == Math.floor(mnt*10)) ? 2287 mnt + '0' : mnt); 2288} 2289 2290BS.utl.xy = {}; 2291 2292/*!\brief Add source XY to destination XY (destructive). 2293 * \param d destination XY 2294 * \param s source XY 2295 */ 2296BS.utl.xy.add = function (d, s) 2297{ 2298 d[0] += s[0]; 2299 d[1] += s[1]; 2300 return d; 2301}; 2302 2303/*!\brief Subtract source XY from destination XY (destructive). 2304 * \param d destination XY 2305 * \param s source XY 2306 */ 2307BS.utl.xy.sub = function (d, s) 2308{ 2309 d[0] -= s[0]; 2310 d[1] -= s[1]; 2311 return d; 2312}; 2313 2314/*!\brief Return distance between two XY points. 2315 * \param p0 point XY 2316 * \param p1 point XY 2317 */ 2318BS.utl.xy.distance = function (p0, p1) 2319{ 2320 return Math.sqrt(Math.pow(p0[0] - p1[0], 2) + 2321 Math.pow(p0[1] - p1[1], 2)); 2322}; 2323 2324/*!\brief Constrain point XY in bounding box. 2325 * \param p point XY 2326 * \param b0 bounding box XY 2327 * \param b1 bounding box XY 2328 */ 2329BS.utl.xy.constrain = function (p, b0, b1) 2330{ 2331 var t; 2332 2333 if (p[0] > (t = Math.max(b0[0], b1[0]))) p[0] = t; 2334 else if (p[0] < (t = Math.min(b0[0], b1[0]))) p[0] = t; 2335 2336 if (p[1] > (t = Math.max(b0[1], b1[1]))) p[1] = t; 2337 else if (p[1] < (t = Math.min(b0[1], b1[1]))) p[1] = t; 2338 2339 return p; 2340}; 2341 2342BS.utl.ieHoverNav = function (id) 2343{ 2344 if (!_bsBrowser.isIE) return; 2345 _bsMm.oNew(BS.com.HoverMenuUplifter, id); 2346}; 2347 2348BS.com.HoverMenuUplifter = function (id) 2349{ 2350 this.mm = new BS.com.Delete(); 2351 2352 this.rootUL = _bsDom.get(id); 2353 2354 if (!this.rootUL) return; 2355 2356 this.mEvt = this.mm.ceNew('mouse', this); 2357 this.mEvt.addCB(this._mouseCB); 2358 this.uplift(); 2359}; 2360 2361BS.com.HoverMenuUplifter.prototype = { 2362 HOVER_CLASS: 'ieHover', 2363 2364 _delete: function () 2365 { 2366 this.rootUL = null; 2367 this.mm._delete(); 2368 }, 2369 2370 uplift: function () 2371 { 2372 var el = this.rootUL.getElementsByTagName('li'); 2373 delete this.cArr; this.cArr = []; 2374 2375 for (var i=0, l=el.length; i<l; i++) { 2376 this.cArr[i] = ''; 2377 if (empty(el[i].className)) continue; 2378 2379 if (el[i].className != '') 2380 this.cArr[i] = '_' + el[i].className; 2381 this.mEvt.attach(el[i], 'mouseover', i); 2382 this.mEvt.attach(el[i], 'mouseout', i); 2383 } 2384 }, 2385 2386 _mouseCB: function (type, data, args) 2387 { 2388 var e = args[0]; 2389 var elindx = args[1]; 2390 var type = e.type; 2391 var target = _bsEvt.getTarget(e); 2392 var hc = this.HOVER_CLASS; 2393 2394 var node = _bsDom.parentByNodeName(target, 'LI'); 2395 2396 switch(type) { 2397 case 'mouseover':
2398 if (node.className == '' /*!_bsDom.hasClass(node, hc)*/) { 2399 var pNode = _bsDom.parentByNodeName(node.parentNode, 'LI'); 2400 //log(node.className + ' ' + node.tagName); 2401 _bsDom.addClass(pNode, hc); 2402 } else 2403 _bsDom.addClass(node, hc + this.cArr[elindx]); 2404 _bsDom.addClass(node, hc); 2405 break; 2406 case 'mouseout': 2407 _bsDom.delClass(node, hc + this.cArr[elindx]); 2408 _bsDom.delClass(node, hc); 2409 if (node.className == '' /*!_bsDom.hasClass(node, hc)*/) { 2410 node = _bsDom.parentByNodeName(node.parentNode, 'LI'); 2411 _bsDom.delClass(node, hc); 2412 } 2413 break; 2414 } 2415 2416 _bsEvt.stopPropagation(e); 2417 } 2418}; 2419 2420BS.utl.window = new BS.com.Window; 2421 2422// shortcuts 2423_bsArr = BS.utl.array; 2424_bsBrowser = BS.utl.browser; 2425_bsCookie = BS.utl.cookie; 2426_bsDom = BS.utl.dom; 2427_bsEvt = BS.utl.event; 2428_bsForm = BS.utl.form; 2429_bsGlobalEvt = BS.utl.globalEvent; 2430_bsMm = BS.utl.mm; 2431_bsMouse = BS.utl.mouse; 2432_bsObj = BS.utl.object; 2433_bsStr = BS.utl.string; 2434_bsWin = BS.utl.window; 2435_bsXy = BS.utl.xy; 2436BS.com.Prompt = function (obj, parent, className, zindex) 2437{ 2438 this.mm = new BS.com.Delete; 2439 2440 this.parent = (parent) ? parent : document.body; 2441 this.wobj = (obj) ? 2442 obj : this.mm.domNew(this.parent, 'div', 'BsPrompt'); 2443 2444 this.obj = this.mm.domNew(this.wobj, 'div', null); 2445 2446 if (className) _bsDom.addClass(this.wobj, className); 2447 2448 _bsDom.setStyle(this.wobj, 'position', 'absolute'); 2449 _bsDom.setStyle(this.wobj, 'visibility', 'hidden'); 2450 _bsDom.setStyle(this.wobj, 'zIndex', (zindex) ? zindex : '5000'); 2451 _bsDom.setStyle(this.wobj, 'display', 'block'); 2452 _bsDom.setStyle(this.obj, 'overflow', 'auto'); 2453}; 2454 2455BS.com.Prompt.prototype = { 2456 _delete: function () { this.mm._delete(); }, 2457 2458 setPageOfs: function (pos) 2459 { 2460 _bsDom.setPageOfs(this.wobj, pos); 2461 }, 2462 2463 setObjOfs: function (obj, ofs) 2464 { 2465 if (!obj) return; 2466 var pos = _bsDom.pageOfs(obj); 2467 _bsDom.setPageOfs(this.wobj, _bsXy.add(pos, ofs)); 2468 }, 2469 2470 clientCenter: function (min) { _bsDom.clientCenter(this.wobj, min); }, 2471 2472 _resize: function () { this.clientCenter([25,25]); }, 2473 2474 show: function (mode) 2475 { 2476 _bsDom.setVis(this.wobj, mode); 2477 _bsDom.setDisplay(this.wobj, mode); 2478 if (mode) { 2479 this._resize(); 2480 _bsGlobalEvt.addCB('resize', this._resize, this); 2481 } else { 2482 _bsGlobalEvt.delCB('resize', this._resize, this); 2483 } 2484 } 2485}; 2486 2487BS.com.BusyPrompt = function (title, msg, mask) 2488{ 2489 BS.com.Prompt.call(this, null, null, 'BsBusyPrompt', '8000'); 2490 this.mask = (mask) ? mask : this.mm.oNew(BS.com.Mask, null, 0.25, '7999'); 2491 2492 this.titleH = this.mm.domNew(this.obj, 'h1'); 2493 this.msgDIV = this.mm.domNew(this.obj, 'div', 'bsBpMsg'); 2494 this.titleH.innerHTML = title; 2495 this.msgDIV.innerHTML = msg; 2496}; 2497 2498BS.com.BusyPrompt.prototype = { 2499 _delete: function () 2500 { 2501 BS.com.Prompt.prototype._delete.call(this); 2502 this.mask = null; 2503 }, 2504 2505 show: function (mode) 2506 { 2507 this.mask.show(mode); 2508 BS.com.Prompt.prototype.show.call(this, mode); 2509 2510 if (mode) 2511 _bsDom.clientCenter(this.wobj); 2512 } 2513}; 2514 2515if (BS.com.Prompt) _bsObj.inherit(BS.com.Prompt, BS.com.BusyPrompt); 2516 2517BS.com.Balloon = function (delay, fade) 2518{ 2519 this.mm = new BS.com.Delete('BsBalloon'); 2520 this.delay = isset(delay) ? delay : 500; 2521 2522 this.f_fade = fade ? true : false; 2523 2524 this.obj = this.mm.domNew(document.body, 'div'); 2525 with (_bsDom) { 2526 setPageOfs(this.obj, [0,0]); 2527 setStyle(this.obj, 'visibility', 'hidden'); 2528 } 2529 2530 this.tailTopDIV = this.mm.domNew(this.obj, 'div'); 2531 _bsDom.setStyle(this.tailTopDIV, 'display', 'none'); 2532 2533 this.bodyDIV = this.mm.domNew(this.obj, 'div', 'bsbBody'); 2534 2535 this.tailBottomDIV = this.mm.domNew(this.obj, 'div', 'downleft'); 2536 2537 this.stayE = this.mm.ceNew('stay', this); 2538 this.stayE.addCB(this.hoverE); 2539 this.stayE.attach(this.obj, 'mouseover'); 2540 this.stayE.attach(this.obj, 'mouseout'); 2541 2542 this.hovE = this.mm.ceNew('hov', this); 2543 this.hovE.addCB(this.hoverE); 2544 2545 if (this.f_fade) { 2546 this.fxCE = this.mm.ceNew('animate', this); 2547 this.fxCE.addCB(this._setVis); 2548 2549 this.fx = this.mm.oNew(BS.com.Animate, this.obj); 2550 this.fx.setCE(this.fxCE); 2551 2552 _bsDom.setStyle(this.obj, 'opacity', 0); 2553 } 2554 2555 this.htmlA = []; 2556 this.relObjA = []; 2557 this.widthA = []; 2558 this.objA = []; 2559}; 2560 2561BS.com.Balloon.prototype = { 2562 f_show: false, 2563 f_stat: false, 2564 f_fade: false, 2565 f_enabled: true, 2566 2567 _delete: function () 2568 { 2569 this.stayE.detach(this.obj, 'mouseover'); 2570 this.stayE.detach(this.obj, 'mouseout'); 2571 2572 for (var i in this.objA) { 2573 this.hovE.detach(this.objA[i], 'mouseover'); 2574 this.hovE.detach(this.objA[i], 'mouseout'); 2575 // this.hovE.detach(this.objA[i], 'mousedown'); 2576 } 2577 2578 delete this.relObjA; 2579 delete this.htmlA; 2580 delete this.widthA; 2581 delete this.objA; 2582 this.mm._delete(); 2583 }, 2584 2585 hoverE: function (type, data, args) 2586 { 2587 var evt = args[0]; 2588 2589 switch (evt.type) { 2590 case 'mouseover': 2591 if (!this.f_enabled) { 2592 if (this.f_show) { 2593 this.f_show = false;
2594 this._show(); 2595 } 2596 return; 2597 } 2598 this.f_show = true; 2599 var caller = _bsEvt.getTarget(evt); 2600 2601 if (type == 'hov' && 2602 (!this.lastPos || this.bodyDIV.innerHTML != this.htmlA[caller.id])) { 2603 if (this.lastPos) this.f_stat = false; 2604 _bsDom.setStyle(this.obj, 'width', this.widthA[caller.id] + 'px'); 2605 this.bodyDIV.innerHTML = this.htmlA[caller.id]; 2606 this.lastPos = this.relObjA[caller.id] ? 2607 _bsDom.pageOfs(caller) : BS.utl.mouse.ofs(evt); 2608 2609 var mult = this.relObjA[caller.id] ? .5 : 0; 2610 2611 this.lastPos[0] += mult*caller.offsetWidth; 2612 2613 this._setArrow('down'); 2614 this._setArrow('left'); 2615 2616 if (this.lastPos[1] - _bsDom.scrollOfs()[1] 2617 - this.obj.offsetHeight > 0) { 2618 this.lastPos[1] -= this.obj.offsetHeight; 2619 } else { 2620 if (this.relObjA[caller.id]) 2621 this.lastPos[1] += caller.offsetHeight; 2622 this._setArrow('up'); 2623 } 2624 2625 if (_bsDom.clientSize()[0] + 2626 _bsDom.scrollOfs()[0] - 2627 this.lastPos[0] - this.obj.offsetWidth < 0) { 2628 if (this.lastPos[0] - this.obj.offsetWidth >= 0) { 2629 this.lastPos[0] -= this.obj.offsetWidth; 2630 this._setArrow('right'); 2631 } 2632 } 2633 } 2634 _bsEvt.setTimeout(this.delay, this._show, this); 2635 break; 2636 case 'mouseout': 2637 this.f_show = false; 2638 _bsEvt.setTimeout(50, this._show, this); 2639 break; 2640 case 'mousedown': 2641 this.f_show = false; 2642 this._show(); 2643 break; 2644 } 2645 }, 2646 2647 attach: function (obj, html, width, f_relObj) 2648 { 2649 if (!obj) return; 2650 if (!obj.id) obj.id = _bsDom.mkid(); 2651 2652 this.relObjA[obj.id] = f_relObj; 2653 this.htmlA[obj.id] = html; 2654 this.widthA[obj.id] = isset(width) ? width : 158; 2655 this.objA[obj.id] = obj; 2656 2657 this.hovE.attach(obj, 'mouseover'); 2658 this.hovE.attach(obj, 'mouseout'); 2659 // this.hovE.attach(obj, 'mousedown'); 2660 }, 2661 2662 setEnabled: function (enabled) { this.f_enabled = enabled; }, 2663 2664 setStyle: function (prop, val) { _bsDom.setStyle(this.obj, prop, val); }, 2665 2666 setContent: function (html, id) { this.htmlA[id] = html; }, 2667 2668 _setArrow: function (direction) 2669 { 2670 switch (direction) { 2671 case 'left': 2672 _bsDom.delClass(this.tailTopDIV, 'upright'); 2673 _bsDom.delClass(this.tailBottomDIV, 'downright'); 2674 _bsDom.addClass(this.tailTopDIV, 'upleft'); 2675 _bsDom.addClass(this.tailBottomDIV, 'downleft'); 2676 break; 2677 case 'right': 2678 _bsDom.delClass(this.tailTopDIV, 'upleft'); 2679 _bsDom.delClass(this.tailBottomDIV, 'downleft'); 2680 _bsDom.addClass(this.tailTopDIV, 'upright'); 2681 _bsDom.addClass(this.tailBottomDIV, 'downright'); 2682 break; 2683 case 'down': 2684 _bsDom.setStyle(this.tailTopDIV, 'display', 'none'); 2685 _bsDom.setStyle(this.tailBottomDIV, 'display', 'block'); 2686 break; 2687 case 'up': 2688 _bsDom.setStyle(this.tailBottomDIV, 'display', 'none'); 2689 _bsDom.setStyle(this.tailTopDIV, 'display', 'block'); 2690 break; 2691 } 2692 }, 2693 2694 _show: function () 2695 { 2696 if (this.f_show) { 2697 if (this.f_stat) return; 2698 _bsDom.setPageOfs(this.obj, this.lastPos); 2699 if (this.f_fade) this.fx.fadein(50); 2700 else this._setVis(null, null, ['start', 'fadein']); 2701 this.f_stat = true; 2702 } else { 2703 if (!this.f_stat) return; 2704 if (this.f_fade) this.fx.fadeout(200); 2705 else this._setVis(null, null, ['end', 'fadeout']); 2706 this.lastPos = null; 2707 this.orgiPos = null; 2708 this.f_stat = false; 2709 } 2710 }, 2711 2712 _setVis: function (type, data, args) 2713 { 2714 var state = args[0]; 2715 var effect = args[1]; 2716 2717 if (state == 'start' && effect == 'fadein') 2718 _bsDom.setStyle(this.obj, 'visibility', 'visible'); 2719 else if (state == 'end' && effect == 'fadeout') 2720 _bsDom.setStyle(this.obj, 'visibility', 'hidden'); 2721 } 2722}; 2723 2724BS.com.Mask = function (parent, opacity, zindex, color) 2725{ 2726 var isIE = _bsBrowser.isIE; 2727 2728 if (!zindex) zindex = '1000'; 2729 if (!color) color = '#000'; 2730 if (!opacity) opacity = 0.4; 2731 2732 this.mm = new BS.com.Delete('Mask'); 2733 this.parent = (parent) ? parent : document.body; 2734 2735 if (isIE) { 2736 this.obj = this.mm.domNew(null, 'iframe', 'BsMask'); 2737 this.obj.src = '/com/mask?color=' + _bsStr.urlencode(color); 2738 document.body.appendChild(this.obj); 2739 } else this.obj = this.mm.domNew(document.body, 'div', 'BsMask'); 2740 2741 _bsDom.setStyle(this.obj, 'position', 'absolute'); 2742 _bsDom.setStyle(this.obj, 'visibility', 'hidden'); 2743 _bsDom.setStyle(this.obj, 'zIndex', zindex); 2744 _bsDom.setStyle(this.obj, 'opacity', opacity); 2745 2746 if (!isIE) { 2747 _bsDom.setStyle(this.obj, 'backgroundColor', color); 2748 this.obj.innerHTML = ' '; 2749 } 2750 2751 // weird firefox bug! setting the 'height' style in _resize() 2752 // causes excessive CPU usage in firefox... should not call 2753 // _resize() in the constructor. 2754 // this._resize(); 2755}; 2756 2757BS.com.Mask.prototype = { 2758 f_show: false, 2759 2760 _delete: function () 2761 { 2762 this.mm._delete(); 2763 this.parent = null; 2764 }, 2765 2766 _resize: function () 2767 { 2768 var pos, size; 2769 2770 if (this.parent == document.body) { 2771 size = _bsDom.docSize(); 2772 pos = [0,0]; 2773 } 2774 else { 2775 size = _bsDom.size(this.parent); 2776 pos = _bsDom.pageOfs(this.parent); 2777 2778 } 2779 2780 if (isNaN(size[0]) || isNaN(size[1]) || !pos) return; 2781 2782 _bsDom.setPageOfs(this.obj, pos); 2783 _bsDom.setSize(this.obj, size); 2784 }, 2785 2786 show: function (mode) 2787 { 2788 if (mode == this.f_show) return; 2789 this.f_show = mode; 2790 2791 if (mode) { 2792 this._resize(); 2793 _bsGlobalEvt.addCB('resize', this._resize, this, 2794 true); 2795 } 2796 else { 2797 _bsDom.setStyle(this.obj, 'height', '1px'); 2798 _bsGlobalEvt.delCB('resize', this._resize, this); 2799 } 2800 2801 _bsDom.setStyle(this.obj, 'visibility', 2802 mode ? 'visible' : 'hidden'); 2803 } 2804}; 2805 2806BS.com.Alert = function () 2807{
2808 BS.com.Prompt.call(this, null, null, 'BsAlert', '9999'); 2809 2810 this.mask = _bsMm.oNew(BS.com.Mask, null, 0.3, '9998'); 2811 2812 this.msgA = []; 2813 2814 this.titleH = this.mm.domNew(this.obj, 'h1'); 2815 this.bodyDIV = this.mm.domNew(this.obj, 'div', 'body'); 2816 this.footerDIV = this.mm.domNew(this.obj, 'div', 'footer') 2817 this.okINP = this.mm.domNew(null, 'input', 'button') 2818 this.okINP.setAttribute('type', 'button'); 2819 this.okINP.value = " OK "; 2820 this.footerDIV.appendChild(this.okINP); 2821 2822 this.okE = _bsMm.ceNew('ok', this); 2823 this.okE.addCB(this._clear, this); 2824 this.okE.attach(this.okINP, 'click'); 2825}; 2826 2827BS.com.Alert.prototype = { 2828 f_show: false, 2829 msgA: null, 2830 ce: null, 2831 DEBUG: false, 2832 2833 _delete: function () 2834 { 2835 BS.com.Prompt.prototype._delete.call(this); 2836 this.ce = null; 2837 delete this.msgA; 2838 }, 2839 2840 _closeWin: function (type, data, args) 2841 { 2842 window.close(); 2843 }, 2844 2845 _clear: function (type, data, args) 2846 { 2847 if (!this.f_show) return; 2848 this.f_show = false; 2849 2850 _bsGlobalEvt.delCB('resize', this._resize, this); 2851 this.bodyDIV.innerHTML = this.titleH.innerHTML = ''; 2852 BS.com.Prompt.prototype.show.call(this, false); 2853 2854 if (this.msgA.length) { 2855 _bsEvt.setTimeout(100, this._showA, this); 2856 return; 2857 } 2858 2859 if (this.ce) 2860 if (!this.ce.exec()) return; 2861 2862 this.ce = null; 2863 this.mask.show(false); 2864 }, 2865 2866 _showA: function (type, data, args) 2867 { 2868 if (!this.msgA.length) return; 2869 var msg = this.msgA.shift(); 2870 this.show(msg[0], msg[1], msg[2]) 2871 }, 2872 2873 _focus: function () { this.okINP.focus(); }, 2874 2875 close: function (clearCe) 2876 { 2877 if (clearCe) this.ce = null; 2878 this._clear(); 2879 }, 2880 2881 setCloseWin: function (flag) 2882 { 2883 if (flag) this.okE.addCB(this._closeWin, this); 2884 else this.okE.delCB(this._closeWin); 2885 }, 2886 2887 show: function (title, html, ce) 2888 { 2889 // check if a "false" error was thrown - 2890 // e.g. used by PS.utl.responseErr() 2891 if (html === false) return; 2892 2893 if (this.f_show) { 2894 this.msgA.push([title, html, ce]); 2895 _bsEvt.setTimeout(0, this._focus, this); 2896 return; 2897 } 2898 this.f_show = true; 2899 2900 if (ce) this.ce = ce; 2901 this.mask.show(true); 2902 if (title) this.titleH.innerHTML = title; 2903 if (html) { 2904 if (typeof(html) == 'object' && html.length) { 2905 var str = '<ul>'; 2906 for (var i = 0; i < html.length; i++) 2907 str += '<li>' + html[i] + '</li>'; 2908 str += '</ul>'; 2909 this.bodyDIV.innerHTML = str; 2910 2911 } 2912 else this.bodyDIV.innerHTML = html; 2913 2914 if (this.DEBUG && html.stack) 2915 this.bodyDIV.innerHTML += '\n' + html.stack; 2916 } 2917 2918 BS.com.Prompt.prototype.show.call(this, true); 2919 _bsEvt.setTimeout(0, this._focus, this); 2920 } 2921}; 2922 2923_bsObj.inherit(BS.com.Prompt, BS.com.Alert); 2924 2925_bsGlobalEvt.addCB('load', 2926 function () { _bsAlert = BS.utl.alert = _bsMm.oNew(BS.com.Alert); }); 2927 2928// shortcuts 2929var _bsAlert;
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.