1/*======================================================================*\ 2|| #################################################################### || 3|| # vBulletin 3.6.8 Patch Level 2 4|| # ---------------------------------------------------------------- # || 5|| # Copyright ©2000-2008 Jelsoft Enterprises Ltd. All Rights Reserved. || 6|| # This file may not be redistributed in whole or significant part. # || 7|| # ---------------- VBULLETIN IS NOT FREE SOFTWARE ---------------- # || 8|| # http://www.vbulletin.com | http://www.vbulletin.com/license.html # || 9|| #################################################################### || 10\*======================================================================*/ 11 12/** 13* Handle Firebug calls when Firebug is not available (getfirebug.com) 14*/ 15if (!window.console || !console.firebug) 16{ 17 window.console = {}; 18 var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; 19 for (var i = 0; i < names.length; ++i) window.console[names[i]] = function() {}; 20} 21 22/** 23* Handle YUI custom event calls when YUI is not available (clientscript/yui/yahoo-dom-event.js) 24*/ 25if (typeof YAHOO == "undefined") 26{ 27 function null_event() { this.fire = function() {}; this.subscribe = function() {}; }; 28} 29 30/** 31* Setup Variables 32* 33* @var string SESSIONURL - stores the session URL 34* @var array vbphrase - stores text phrases 35* @var array vB_Editor - array of vB_Text_Editor objects 36* @var boolean ignorequotechars - ignore characters inside [quote] tags for message length check 37* @var integer pagenavcounter - counts the number of pagenav instances encountered so far 38* @var boolean is_regexp - does window.regExp exist? - Catch errors with less capable browsers 39* @var boolean AJAX_Compatible - does the current browser support AJAX? 40* @var string pointer_cursor - help out old versions of IE that don't understand style.cursor = pointer 41*/ 42var SESSIONURL = (typeof(SESSIONURL) == "undefined" ? "" : SESSIONURL); 43var vbphrase = (typeof(vbphrase) == "undefined" ? new Array() : vbphrase); 44var vB_Editor = new Array(); 45var ignorequotechars = false; 46var pagenavcounter = 0; 47var is_regexp = (window.RegExp) ? true : false; 48var AJAX_Compatible = false; 49var pointer_cursor = (is_ie ? 'hand' : 'pointer'); 50 51/** 52* Define the browser loading the page 53* 54* @var string userAgent Useragent string 55* @var boolean is_opera Opera 56* @var boolean is_saf Safari 57* @var boolean is_webtv WebTV 58* @var boolean is_ie Internet Explorer 59* @var boolean is_ie4 Internet Explorer 4 60* @var boolean is_ie7 Internet Explorer 7 61* @var boolean is_ps3 Playstation 3 62* @var boolean is_moz Mozilla / Firefox / Camino 63* @var boolean is_kon Konqueror 64* @var boolean is_ns Netscape 65* @var boolean is_ns4 Netscape 4 66* @var boolean is_mac Client is running MacOS 67*/ 68var userAgent = navigator.userAgent.toLowerCase(); 69var is_opera = ((userAgent.indexOf('opera') != -1) || (typeof(window.opera) != 'undefined')); 70var is_saf = ((userAgent.indexOf('applewebkit') != -1) || (navigator.vendor == 'Apple Computer, Inc.')); 71var is_webtv = (userAgent.indexOf('webtv') != -1); 72var is_ie = ((userAgent.indexOf('msie') != -1) && (!is_opera) && (!is_saf) && (!is_webtv)); 73var is_ie4 = ((is_ie) && (userAgent.indexOf('msie 4.') != -1)); 74var is_ie7 = ((is_ie) && (userAgent.indexOf('msie 7.') != -1)); 75var is_ps3 = (userAgent.indexOf('playstation 3') != -1); 76var is_moz = ((navigator.product == 'Gecko') && (!is_saf)); 77var is_kon = (userAgent.indexOf('konqueror') != -1); 78var is_ns = ((userAgent.indexOf('compatible') == -1) && (userAgent.indexOf('mozilla') != -1) && (!is_opera) && (!is_webtv) && (!is_saf)); 79var is_ns4 = ((is_ns) && (parseInt(navigator.appVersion) == 4)); 80var is_mac = (userAgent.indexOf('mac') != -1); 81 82/** 83* Workaround for heinous IE bug - add special vBlength property to all strings 84* This method is applied to ALL string objects automatically 85* 86* @return integer 87*/ 88String.prototype.vBlength = function() 89{ 90 return (is_ie && this.indexOf("\n") != -1) ? this.replace(/\r?\n/g, "_").length : this.length; 91} 92 93/**
94* Overrides IE's original String.prototype.substr to accept negative values 95* 96* @param integer Substring start position 97* @param integer Substring length 98* 99* @return string 100*/ 101if ("1234".substr(-2, 2) == "12") // (which would be incorrect) 102{ 103 String.prototype.substr_orig = String.prototype.substr; 104 105 String.prototype.substr = function(start, length) 106 { 107 if (typeof(length) == "undefined") 108 { 109 return this.substr_orig((start < 0 ? this.length + start : start)); 110 } 111 else 112 { 113 return this.substr_orig((start < 0 ? this.length + start : start), length); 114 } 115 }; 116} 117 118/** 119* Define Array.shift() for browsers that don't have it 120*/ 121if (typeof Array.prototype.shift === 'undefined') 122{ 123 Array.prototype.shift = function() 124 { 125 for(var i = 0, b = this[0], l = this.length-1; i < l; i++) 126 { 127 this[i] = this[i + 1]; 128 } 129 this.length--; 130 return b; 131 }; 132} 133 134/** 135* Function to emulate document.getElementById 136* 137* @param string Object ID 138* 139* @return mixed null if not found, object if found 140*/ 141function fetch_object(idname) 142{ 143 if (document.getElementById) 144 { 145 return document.getElementById(idname); 146 } 147 else if (document.all) 148 { 149 return document.all[idname]; 150 } 151 else if (document.layers) 152 { 153 return document.layers[idname]; 154 } 155 else 156 { 157 return null; 158 } 159} 160 161/** 162* Function to emulate document.getElementsByTagName 163* 164* @param object Parent object (eg: document) 165* @param string Tag type (eg: 'td') 166* 167* @return array 168*/ 169function fetch_tags(parentobj, tag) 170{ 171 if (parentobj == null) 172 { 173 return new Array(); 174 } 175 else if (typeof parentobj.getElementsByTagName != 'undefined') 176 { 177 return parentobj.getElementsByTagName(tag); 178 } 179 else if (parentobj.all && parentobj.all.tags) 180 { 181 return parentobj.all.tags(tag); 182 } 183 else 184 { 185 return new Array(); 186 } 187} 188 189/** 190* Function to count the number of tags in an object 191* 192* @param object Parent object (eg: document) 193* @param string Tag type (eg: 'td') 194* 195* @return integer 196*/ 197function fetch_tag_count(parentobj, tag) 198{ 199 return fetch_tags(parentobj, tag).length; 200} 201 202// ############################################################################# 203// Event handlers 204 205/** 206* Handles the different event models of different browsers and prevents event bubbling 207* 208* @param event Event object 209* 210* @return event 211*/ 212function do_an_e(eventobj) 213{ 214 if (!eventobj || is_ie) 215 { 216 window.event.returnValue = false; 217 window.event.cancelBubble = true; 218 return window.event; 219 } 220 else 221 { 222 eventobj.stopPropagation(); 223 eventobj.preventDefault(); 224 return eventobj; 225 } 226} 227 228/** 229* Handles the different event models of different browsers and prevents event bubbling in a lesser way than do_an_e() 230* 231* @param event Event object 232* 233* @return event 234*/ 235function e_by_gum(eventobj) 236{ 237 if (!eventobj || is_ie) 238 { 239 window.event.cancelBubble = true; 240 return window.event; 241 } 242 else 243 { 244 if (eventobj.target.type == 'submit') 245 { 246 // naughty safari 247 eventobj.target.form.submit(); 248 } 249 eventobj.stopPropagation(); 250 return eventobj; 251 } 252} 253 254// ############################################################################# 255// Message manipulation and validation 256 257/** 258* Checks that a message is valid for submission to PHP 259* 260* @param string Message text 261* @param mixed Either subject text (if you want to make sure it exists) or 0 if you don't care 262* @param integer Minimum acceptable character limit for the message 263* 264* @return boolean 265*/ 266function validatemessage(messagetext, subjecttext, minchars) 267{ 268 if (is_kon || is_saf || is_webtv) 269 { 270 // ignore less-than-capable browsers 271 return true; 272 } 273 else if (subjecttext.length < 1) 274 { 275 // subject not specified 276 alert(vbphrase['must_enter_subject']); 277 return false; 278 } 279 else 280 { 281 var stripped = PHP.trim(stripcode(messagetext, false, ignorequotechars)); 282 283 if (stripped.length < minchars) 284 { 285 // minimum message length not met 286 alert(construct_phrase(vbphrase['message_too_short'], minchars)); 287 return false; 288 } 289 else if (typeof(document.forms.vbform) != 'undefined' && typeof(document.forms.vbform.imagestamp) != 'undefined') 290 { 291 // This form has image verification enabled 292 document.forms.vbform.imagestamp.failed = false;
293 294 if (document.forms.vbform.imagestamp.value.length != 6) 295 { 296 alert(vbphrase['complete_image_verification']); 297 document.forms.vbform.imagestamp.failed = true; 298 document.forms.vbform.imagestamp.focus(); 299 return false; 300 } 301 else 302 { 303 return true; 304 } 305 } 306 else 307 { 308 // everything seems ok 309 return true; 310 } 311 } 312} 313 314 315/** 316* Strips quotes and bbcode tags from text 317* 318* @param string Text to manipulate 319* @param boolean If true, strip <x> otherwise strip [x] 320* @param boolean If true, strip all [quote]...contents...[/quote] 321* 322* @return string 323*/ 324function stripcode(str, ishtml, stripquotes) 325{ 326 if (!is_regexp) 327 { 328 return str; 329 } 330 331 if (stripquotes) 332 { 333 var start_time = new Date().getTime(); 334 335 while ((startindex = PHP.stripos(str, '[quote')) !== false) 336 { 337 if (new Date().getTime() - start_time > 2000) 338 { 339 // while loop has been running for over 2 seconds and has probably gone infinite 340 break; 341 } 342 343 if ((stopindex = PHP.stripos(str, '[/quote]')) !== false) 344 { 345 fragment = str.substr(startindex, stopindex - startindex + 8); 346 str = str.replace(fragment, ''); 347 } 348 else 349 { 350 break; 351 } 352 str = PHP.trim(str); 353 } 354 } 355 356 if (ishtml) 357 { 358 // exempt image tags -- they need to count as characters in the string 359 // as the do as BB codes 360 str = str.replace(/<img[^>]+src="([^"]+)"[^>]*>/gi, '$1'); 361 362 var html1 = new RegExp("<(\\w+)[^>]*>", 'gi'); 363 var html2 = new RegExp("<\\/\\w+>", 'gi'); 364 365 str = str.replace(html1, ''); 366 str = str.replace(html2, ''); 367 368 var html3 = new RegExp('( )', 'gi'); 369 str = str.replace(html3, ' '); 370 } 371 else 372 { 373 var bbcode1 = new RegExp("\\[(\\w+)(=[^\\]]*)?\\]", 'gi'); 374 var bbcode2 = new RegExp("\\[\\/(\\w+)\\]", 'gi'); 375 376 str = str.replace(bbcode1, ''); 377 str = str.replace(bbcode2, ''); 378 } 379 380 return str; 381} 382 383// ############################################################################# 384// vB_PHP_Emulator class 385// ############################################################################# 386 387/** 388* PHP Function Emulator Class 389*/ 390function vB_PHP_Emulator() 391{ 392} 393 394// ============================================================================= 395// vB_PHP_Emulator Methods 396 397/** 398* Find a string within a string (case insensitive) 399* 400* @param string Haystack 401* @param string Needle 402* @param integer Offset 403* 404* @return mixed Not found: false / Found: integer position 405*/ 406vB_PHP_Emulator.prototype.stripos = function(haystack, needle, offset) 407{ 408 if (typeof offset == 'undefined') 409 { 410 offset = 0; 411 } 412 413 index = haystack.toLowerCase().indexOf(needle.toLowerCase(), offset); 414 415 return (index == -1 ? false : index); 416} 417 418/** 419* Trims leading whitespace 420* 421* @param string String to trim 422* 423* @return string 424*/ 425vB_PHP_Emulator.prototype.ltrim = function(str) 426{ 427 return str.replace(/^\s+/g, ''); 428} 429 430/** 431* Trims trailing whitespace 432* 433* @param string String to trim 434* 435* @return string 436*/ 437vB_PHP_Emulator.prototype.rtrim = function(str) 438{ 439 return str.replace(/(\s+)$/g, ''); 440} 441 442/** 443* Trims leading and trailing whitespace 444* 445* @param string String to trim 446* 447* @return string 448*/ 449vB_PHP_Emulator.prototype.trim = function(str) 450{ 451 return this.ltrim(this.rtrim(str)); 452} 453 454/** 455* Emulation of PHP's preg_quote() 456* 457* @param string String to process 458* 459* @return string 460*/ 461vB_PHP_Emulator.prototype.preg_quote = function(str) 462{ 463 // replace + { } ( ) [ ] | / ? ^ $ \ . = ! < > : * with backslash+character 464 return str.replace(/(\+|\{|\}|\(|\)|\[|\]|\||\/|\?|\^|\$|\\|\.|\=|\!|\<|\>|\:|\*)/g, "\\$1"); 465} 466 467/** 468* Emulates PHP's preg_match_all()... sort of 469* 470* @param string Haystack 471* @param string Regular expression - to be inserted into RegExp(x) 472* 473* @return mixed Array on match, false on no match 474*/ 475vB_PHP_Emulator.prototype.match_all = function(string, regex) 476{ 477 var gmatch = string.match(RegExp(regex, "gim")); 478 if (gmatch) 479 { 480 var matches = new Array(); 481 482 var iregex = new RegExp(regex, "im"); 483 for (var i = 0; i < gmatch.length; i++) 484 { 485 matches[matches.length] = gmatch[i].match(iregex); 486 } 487 488 return matches; 489 } 490 else 491 { 492 return false; 493 } 494} 495 496/** 497* Emulates unhtmlspecialchars in vBulletin 498* 499* @param string String to process 500* 501* @return string 502*/ 503vB_PHP_Emulator.prototype.unhtmlspecialchars = function(str) 504{ 505 f = new Array(/</g, />/g, /"/g, /&/g); 506 r = new Array('<', '>', '"', '&'); 507 508 for (var i in f) 509 { 510 str = str.replace(f[i], r[i]); 511 } 512 513 return str; 514} 515 516/** 517* Unescape CDATA from vB_AJAX_XML_Builder PHP class 518* 519* @param string Escaped CDATA 520* 521* @return string 522*/ 523vB_PHP_Emulator.prototype.unescape_cdata = function(str) 524{ 525 var r1 = /<\=\!\=\[\=C\=D\=A\=T\=A\=\[/g; 526 var r2 = /\]\=\]\=>/g; 527 528 return str.replace(r1, '<![CDATA[').replace(r2, ']]>'); 529} 530 531/** 532* Emulates PHP's htmlspecialchars() 533* 534* @param string String to process 535* 536* @return string 537*/ 538vB_PHP_Emulator.prototype.htmlspecialchars = function(str) 539{ 540 //var f = new Array(/&(?!#[0-9]+;)/g, /</g, />/g, /"/g); 541 var f = new Array( 542 (is_mac && is_ie ? new RegExp('&', 'g') : new RegExp('&(?!#[0-9]+;)', 'g')), 543 new RegExp('<', 'g'), 544 new RegExp('>', 'g'), 545 new RegExp('"', 'g') 546 ); 547 var r = new Array( 548 '&', 549 '<', 550 '>', 551 '"' 552 ); 553 554 for (var i = 0; i < f.length; i++) 555 { 556 str = str.replace(f[i], r[i]); 557 } 558 559 return str; 560} 561 562/** 563* Searches an array for a value 564* 565* @param string Needle 566* @param array Haystack 567* @param boolean Case insensitive 568* 569* @return integer Not found: -1 / Found: integer index 570*/ 571vB_PHP_Emulator.prototype.in_array = function(ineedle, haystack, caseinsensitive) 572{ 573 var needle = new String(ineedle); 574 575 if (caseinsensitive) 576 { 577 needle = needle.toLowerCase(); 578 for (var i in haystack) 579 { 580 if (haystack[i].toLowerCase() == needle) 581 { 582 return i; 583 } 584 } 585 } 586 else 587 { 588 for (var i in haystack) 589 { 590 if (haystack[i] == needle) 591 { 592 return i; 593 } 594 } 595 } 596 return -1; 597} 598 599/** 600* Emulates PHP's strpad() 601* 602* @param string Text to pad 603* @param integer Length to pad 604* @param string String with which to pad 605* 606* @return string 607*/ 608vB_PHP_Emulator.prototype.str_pad = function(text, length, padstring) 609{ 610 text = new String(text); 611 padstring = new String(padstring); 612 613 if (text.length < length) 614 { 615 padtext = new String(padstring); 616 617 while (padtext.length < (length - text.length)) 618 { 619 padtext += padstring; 620 } 621 622 text = padtext.substr(0, (length - text.length)) + text; 623 } 624 625 return text; 626} 627 628/**
629* A sort of emulation of PHP's urlencode - not 100% the same, but accomplishes the same thing 630* 631* @param string String to encode 632* 633* @return string 634*/ 635vB_PHP_Emulator.prototype.urlencode = function(text) 636{ 637 text = escape(text.toString()).replace(/\+/g, "%2B"); 638 639 // this escapes 128 - 255, as JS uses the unicode code points for them. 640 // This causes problems with submitting text via AJAX with the UTF-8 charset. 641 var matches = text.match(/(%([0-9A-F]{2}))/gi); 642 if (matches) 643 { 644 for (var matchid = 0; matchid < matches.length; matchid++) 645 { 646 var code = matches[matchid].substring(1,3); 647 if (parseInt(code, 16) >= 128) 648 { 649 text = text.replace(matches[matchid], '%u00' + code); 650 } 651 } 652 } 653 654 // %25 gets translated to % by PHP, so if you have %25u1234, 655 // we see it as %u1234 and it gets translated. So make it %u0025u1234, 656 // which will print as %u1234! 657 text = text.replace('%25', '%u0025'); 658 659 return text; 660} 661 662/** 663* Works a bit like ucfirst, but with some extra options 664* 665* @param string String with which to work 666* @param string Cut off string before first occurence of this string 667* 668* @return string 669*/ 670vB_PHP_Emulator.prototype.ucfirst = function(str, cutoff) 671{ 672 if (typeof cutoff != 'undefined') 673 { 674 var cutpos = str.indexOf(cutoff); 675 if (cutpos > 0) 676 { 677 str = str.substr(0, cutpos); 678 } 679 } 680 681 str = str.split(' '); 682 for (var i = 0; i < str.length; i++) 683 { 684 str[i] = str[i].substr(0, 1).toUpperCase() + str[i].substr(1); 685 } 686 return str.join(' '); 687} 688 689// ############################################################################# 690// vB_AJAX_Handler 691// ############################################################################# 692 693/** 694* XML Sender Class 695* 696* @param boolean Should connections be asyncronous? 697*/ 698function vB_AJAX_Handler(async) 699{ 700 /** 701 * Should connections be asynchronous? 702 * 703 * @var boolean 704 */ 705 this.async = async ? true : false; 706} 707 708// ============================================================================= 709// vB_AJAX_Handler methods 710 711/** 712* Initializes the XML handler 713* 714* @return boolean True if handler created OK 715*/ 716vB_AJAX_Handler.prototype.init = function() 717{ 718 if (typeof vb_disable_ajax != 'undefined' && vb_disable_ajax == 2) 719 { 720 // disable all ajax features 721 return false; 722 } 723 724 if (typeof XMLHttpRequest != "undefined") 725 { 726 this.handler = new XMLHttpRequest(); 727 return (this.handler.setRequestHeader ? true : false); 728 } 729 else if (is_ie && !is_ie7) 730 { 731 this.handler = eval("new A" + "ctiv" + "eX" + "Ob" + "ject('Micr" + "osoft.XM" + "LHTTP');"); 732 return true; 733 } 734 else 735 { 736 return false; 737 } 738} 739 740/** 741* Detects if the browser is fully compatible 742* 743* @return boolean 744*/ 745vB_AJAX_Handler.prototype.is_compatible = function() 746{ 747 if (typeof vb_disable_ajax != 'undefined' && vb_disable_ajax == 2) 748 { 749 // disable all ajax features 750 return false; 751 } 752 753 if (is_ie && !is_ie4) { return true; } 754 else if (typeof XMLHttpRequest != 'undefined') 755 { 756 try { return XMLHttpRequest.prototype.setRequestHeader ? true : false; } 757 catch(e) 758 { 759 try { var tester = new XMLHttpRequest(); return tester.setRequestHeader ? true : false; } 760 catch(e) { return false; } 761 } 762 } 763 else { return false; } 764} 765 766/** 767* Checks if the system is ready 768* 769* @return boolean False if ready 770*/ 771vB_AJAX_Handler.prototype.not_ready = function() 772{ 773 return (this.handler.readyState && (this.handler.readyState < 4)); 774} 775 776/** 777* OnReadyStateChange event handler 778* 779* @param function 780*/ 781vB_AJAX_Handler.prototype.onreadystatechange = function(event) 782{ 783 if (!this.handler) 784 { 785 if (!this.init()) 786 { 787 return false; 788 } 789 } 790 if (typeof event == 'function') 791 { 792 this.handler.onreadystatechange = event; 793 } 794 else 795 { 796 alert('XML Sender OnReadyState event is not a function'); 797 } 798 799 return false; 800} 801 802/** 803* Sends data 804* 805* @param string Destination URL 806* @param string Request Data 807* 808* @return mixed Return message 809*/ 810vB_AJAX_Handler.prototype.send = function(desturl, datastream) 811{ 812 if (!this.handler) 813 { 814 if (!this.init()) 815 { 816 return false; 817 } 818 } 819 if (!this.not_ready()) 820 { 821 this.handler.open('POST', desturl, this.async); 822 this.handler.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 823 this.handler.send(datastream + '&s=' + fetch_sessionhash()); 824 825 if (!this.async && this.handler.readyState == 4 && this.handler.status == 200) 826 { 827 return true; 828 } 829 } 830 return false;
831} 832 833/** 834* Fetches the contents of an XML node 835* 836* @param object XML node 837* 838* @return string XML node contents 839*/ 840vB_AJAX_Handler.prototype.fetch_data = function(xml_node) 841{ 842 if (xml_node && xml_node.firstChild && xml_node.firstChild.nodeValue) 843 { 844 return PHP.unescape_cdata(xml_node.firstChild.nodeValue); 845 } 846 else 847 { 848 return ''; 849 } 850} 851 852// we can check this variable to see if browser is AJAX compatible 853AJAX_Compatible = vB_AJAX_Handler.prototype.is_compatible(); 854console.info("Browser is%s AJAX compatible", AJAX_Compatible ? "" : " NOT"); 855 856// ############################################################################# 857// vB_Hidden_Form 858// ############################################################################# 859 860/** 861* Form Generator Class 862* 863* Builds a form filled with hidden fields for invisible submit via POST 864* 865* @param string Script (my_target_script.php) 866*/ 867function vB_Hidden_Form(script) 868{ 869 this.action = script; 870 this.variables = new Array(); 871} 872 873// ============================================================================= 874// vB_Hidden_Form methods 875 876/** 877* Adds a hidden input field to the form object 878* 879* @param string Name attribute 880* @param string Value attribute 881*/ 882vB_Hidden_Form.prototype.add_variable = function(name, value) 883{ 884 this.variables[this.variables.length] = new Array(name, value); 885 console.log("vB_Hidden_Form :: add_variable(%s)", name); 886}; 887 888/** 889* Fetches all form elements inside an HTML element and performs 'add_input()' on them 890* 891* @param object HTML element to search 892*/ 893vB_Hidden_Form.prototype.add_variables_from_object = function(obj) 894{ 895 if (!obj) 896 { 897 return; 898 } 899 console.info("vB_Hidden_Form :: add_variables_from_object(%s)", obj.id); 900 var inputs = fetch_tags(obj, 'input'); 901 for (var i = 0; i < inputs.length; i++) 902 { 903 switch (inputs[i].type) 904 { 905 case 'checkbox': 906 case 'radio': 907 if (inputs[i].checked) 908 { 909 this.add_variable(inputs[i].name, inputs[i].value); 910 } 911 break; 912 case 'text': 913 case 'hidden': 914 case 'password': 915 this.add_variable(inputs[i].name, inputs[i].value); 916 break; 917 default: 918 continue; 919 } 920 } 921 922 var textareas = fetch_tags(obj, 'textarea'); 923 for (var i = 0; i < textareas.length; i++) 924 { 925 this.add_variable(textareas[i].name, textareas[i].value); 926 } 927 928 var selects = fetch_tags(obj, 'select'); 929 for (var i = 0; i < selects.length; i++) 930 { 931 if (selects[i].multiple) 932 { 933 for (var j = 0; j < selects[i].options.length; j++) 934 { 935 if (selects[i].options[j].selected) 936 { 937 this.add_variable(selects[i].name, selects[i].options[j].value); 938 } 939 } 940 } 941 else 942 { 943 this.add_variable(selects[i].name, selects[i].options[selects[i].selectedIndex].value); 944 } 945 } 946}; 947 948/** 949* Fetches a variable value 950* 951* @param string Variable name 952* 953* @return mixed Variable value 954*/ 955vB_Hidden_Form.prototype.fetch_variable = function(varname) 956{ 957 for (var i = 0; i < this.variables.length; i++) 958 { 959 if (this.variables[i][0] == varname) 960 { 961 return this.variables[i][1]; 962 } 963 } 964 965 return null; 966}; 967 968/** 969* Submits the hidden form object 970*/ 971vB_Hidden_Form.prototype.submit_form = function() 972{ 973 this.form = document.createElement('form'); 974 this.form.method = 'post'; 975 this.form.action = this.action; 976 977 for (var i = 0; i < this.variables.length; i++) 978 { 979 var inputobj = document.createElement('input'); 980 981 inputobj.type = 'hidden'; 982 inputobj.name = this.variables[i][0]; 983 inputobj.value = this.variables[i][1]; 984 985 this.form.appendChild(inputobj); 986 } 987 988 console.info("vB_Hidden_Form :: submit_form() -> %s", this.action); 989 document.body.appendChild(this.form).submit(); 990}; 991 992/** 993* Builds a URI query string from the given variables 994*/ 995vB_Hidden_Form.prototype.build_query_string = function() 996{ 997 var query_string = ''; 998 999 for (var i = 0; i < this.variables.length; i++) 1000 { 1001 query_string += this.variables[i][0] + '=' + PHP.urlencode(this.variables[i][1]) + '&'; 1002 } 1003 1004 console.info("vB_Hidden_Form :: Query String = %s", query_string); 1005 return query_string; 1006} 1007 1008/** 1009* Legacy functions for backward compatability 1010*/ 1011vB_Hidden_Form.prototype.add_input = vB_Hidden_Form.prototype.add_variable;
1012vB_Hidden_Form.prototype.add_inputs_from_object = vB_Hidden_Form.prototype.add_variables_from_object; 1013 1014// ############################################################################# 1015// Window openers and instant messenger wrappers 1016 1017/** 1018* Opens a generic browser window 1019* 1020* @param string URL 1021* @param integer Width 1022* @param integer Height 1023* @param string Optional Window ID 1024*/ 1025function openWindow(url, width, height, windowid) 1026{ 1027 return window.open( 1028 url, 1029 (typeof windowid == 'undefined' ? 'vBPopup' : windowid), 1030 'statusbar=no,menubar=no,toolbar=no,scrollbars=yes,resizable=yes' 1031 + (typeof width != 'undefined' ? (',width=' + width) : '') + (typeof height != 'undefined' ? (',height=' + height) : '') 1032 ); 1033} 1034 1035/** 1036* Opens control panel help window 1037* 1038* @param string Script name 1039* @param string Action type 1040* @param string Option value 1041* 1042* @return window 1043*/ 1044function js_open_help(scriptname, actiontype, optionval) 1045{ 1046 return openWindow( 1047 'help.php?s=' + SESSIONHASH + '&do=answer&page=' + scriptname + '&pageaction=' + actiontype + '&option=' + optionval, 1048 600, 450, 'helpwindow' 1049 ); 1050} 1051 1052/** 1053* Opens a window to show a list of attachments in a thread (misc.php?do=showattachments) 1054* 1055* @param integer Thread ID 1056* 1057* @return window 1058*/ 1059function attachments(threadid) 1060{ 1061 return openWindow( 1062 'misc.php?' + SESSIONURL + 'do=showattachments&t=' + threadid, 1063 480, 300 1064 ); 1065} 1066 1067/** 1068* Opens a window to show a list of posters in a thread (misc.php?do=whoposted) 1069* 1070* @param integer Thread ID 1071* 1072* @return window 1073*/ 1074function who(threadid) 1075{ 1076 return openWindow( 1077 'misc.php?' + SESSIONURL + 'do=whoposted&t=' + threadid, 1078 230, 300 1079 ); 1080} 1081 1082/** 1083* Opens an IM Window 1084* 1085* @param string IM type 1086* @param integer User ID 1087* @param integer Width of window 1088* @param integer Height of window 1089* 1090* @return window 1091*/ 1092function imwindow(imtype, userid, width, height) 1093{ 1094 return openWindow( 1095 'sendmessage.php?' + SESSIONURL + 'do=im&type=' + imtype + '&u=' + userid, 1096 width, height 1097 ); 1098} 1099 1100/** 1101* Sends an MSN message 1102* 1103* @param string Target MSN handle 1104* 1105* @return boolean false 1106*/ 1107function SendMSNMessage(name) 1108{ 1109 if (!is_ie) 1110 { 1111 alert(vbphrase['msn_functions_only_work_in_ie']); 1112 return false; 1113 } 1114 else 1115 { 1116 MsgrObj.InstantMessage(name); 1117 return false; 1118 } 1119} 1120 1121/** 1122* Adds an MSN Contact (requires MSN) 1123* 1124* @param string MSN handle 1125* 1126* @return boolean false 1127*/ 1128function AddMSNContact(name) 1129{ 1130 if (!is_ie) 1131 { 1132 alert(vbphrase['msn_functions_only_work_in_ie']); 1133 return false; 1134 } 1135 else 1136 { 1137 MsgrObj.AddContact(0, name); 1138 return false; 1139 } 1140} 1141 1142/** 1143* Detects Caps-Lock when a key is pressed 1144* 1145* @param event 1146* 1147* @return boolean True if Caps-Lock is on 1148*/ 1149function detect_caps_lock(e) 1150{ 1151 e = (e ? e : window.event); 1152 1153 var keycode = (e.which ? e.which : (e.keyCode ? e.keyCode : (e.charCode ? e.charCode : 0))); 1154 var shifted = (e.shiftKey || (e.modifiers && (e.modifiers & 4))); 1155 var ctrled = (e.ctrlKey || (e.modifiers && (e.modifiers & 2))); 1156 1157 // if characters are uppercase without shift, or lowercase with shift, caps-lock is on. 1158 return (keycode >= 65 && keycode <= 90 && !shifted && !ctrled) || (keycode >= 97 && keycode <= 122 && shifted); 1159} 1160 1161/** 1162* Confirms log-out request 1163* 1164* @param string Log-out confirmation message 1165* 1166* @return boolean 1167*/ 1168function log_out(confirmation_message) 1169{ 1170 var ht = document.getElementsByTagName("html")[0]; 1171 ht.style.filter = "progid:DXImageTransform.Microsoft.BasicImage(grayscale=1)"; 1172 if (confirm(confirmation_message)) 1173 { 1174 return true; 1175 } 1176 else 1177 { 1178 ht.style.filter = ""; 1179 return false; 1180 } 1181} 1182 1183// ############################################################################# 1184// Cookie handlers 1185 1186/** 1187* Sets a cookie 1188* 1189* @param string Cookie name 1190* @param string Cookie value 1191* @param date Cookie expiry date 1192*/ 1193function set_cookie(name, value, expires) 1194{ 1195 console.log("Set Cookie :: %s = '%s'", name, value); 1196 document.cookie = name + '=' + escape(value) + '; path=/' + (typeof expires != 'undefined' ? '; expires=' + expires.toGMTString() : ''); 1197} 1198 1199/** 1200* Deletes a cookie 1201* 1202* @param string Cookie name 1203*/ 1204function delete_cookie(name) 1205{ 1206 console.log("Delete Cookie :: %s", name); 1207 document.cookie = name + '=' + '; expires=Thu, 01-Jan-70 00:00:01 GMT' + '; path=/'; 1208} 1209
1210/** 1211* Fetches the value of a cookie 1212* 1213* @param string Cookie name 1214* 1215* @return string 1216*/ 1217function fetch_cookie(name) 1218{ 1219 cookie_name = name + '='; 1220 cookie_length = document.cookie.length; 1221 cookie_begin = 0; 1222 while (cookie_begin < cookie_length) 1223 { 1224 value_begin = cookie_begin + cookie_name.length; 1225 if (document.cookie.substring(cookie_begin, value_begin) == cookie_name) 1226 { 1227 var value_end = document.cookie.indexOf (';', value_begin); 1228 if (value_end == -1) 1229 { 1230 value_end = cookie_length; 1231 } 1232 var cookie_value = unescape(document.cookie.substring(value_begin, value_end)); 1233 console.log("Fetch Cookie :: %s = '%s'", name, cookie_value); 1234 return cookie_value; 1235 } 1236 cookie_begin = document.cookie.indexOf(' ', cookie_begin) + 1; 1237 if (cookie_begin == 0) 1238 { 1239 break; 1240 } 1241 } 1242 console.log("Fetch Cookie :: %s (null)", name); 1243 return null; 1244} 1245 1246// ############################################################################# 1247// Form element managers (used for 'check all' type systems) 1248 1249/** 1250* Sets all checkboxes, radio buttons or selects in a given form to a given state, with exceptions 1251* 1252* @param object Form object 1253* @param string Target element type (one of 'radio', 'select-one', 'checkbox') 1254* @param string Selected option in case of 'radio' 1255* @param array Array of element names to be excluded 1256* @param mixed Value to give to found elements 1257*/ 1258function js_toggle_all(formobj, formtype, option, exclude, setto) 1259{ 1260 for (var i =0; i < formobj.elements.length; i++) 1261 { 1262 var elm = formobj.elements[i]; 1263 if (elm.type == formtype && PHP.in_array(elm.name, exclude, false) == -1) 1264 { 1265 switch (formtype) 1266 { 1267 case 'radio': 1268 if (elm.value == option) // option == '' evaluates true when option = 0 1269 { 1270 elm.checked = setto; 1271 } 1272 break; 1273 case 'select-one': 1274 elm.selectedIndex = setto; 1275 break; 1276 default: 1277 elm.checked = setto; 1278 break; 1279 } 1280 } 1281 } 1282} 1283 1284/** 1285* Sets all <select> elements to the selectedIndex specified by the 'selectall' element 1286* 1287* @param object Form object 1288*/ 1289function js_select_all(formobj) 1290{ 1291 exclude = new Array(); 1292 exclude[0] = 'selectall'; 1293 js_toggle_all(formobj, 'select-one', '', exclude, formobj.selectall.selectedIndex); 1294} 1295 1296/** 1297* Sets all <input type="checkbox" /> elements to have the same checked status as 'allbox' 1298* 1299* @param object Form object 1300*/ 1301function js_check_all(formobj) 1302{ 1303 exclude = new Array(); 1304 exclude[0] = 'keepattachments'; 1305 exclude[1] = 'allbox'; 1306 exclude[2] = 'removeall'; 1307 js_toggle_all(formobj, 'checkbox', '', exclude, formobj.allbox.checked); 1308} 1309 1310/** 1311* Sets all <input type="radio" /> groups to have a particular option checked 1312* 1313* @param object Form object 1314* @param mixed Selected option 1315*/ 1316function js_check_all_option(formobj, option) 1317{ 1318 exclude = new Array(); 1319 exclude[0] = 'useusergroup'; 1320 js_toggle_all(formobj, 'radio', option, exclude, true); 1321} 1322 1323/** 1324* Alias to js_check_all 1325*/ 1326function checkall(formobj) 1327{ 1328 js_check_all(formobj); 1329} 1330 1331/** 1332* Alias to js_check_all_option 1333*/ 1334function checkall_option(formobj, option) 1335{ 1336 js_check_all_option(formobj, option); 1337} 1338 1339/** 1340* Resize function for CP textareas 1341* 1342* @param integer If positive, size up, otherwise size down 1343* @param string ID of the textarea 1344* 1345* @return boolean false 1346*/ 1347function resize_textarea(to, id) 1348{ 1349 if (to < 0) 1350 { 1351 var rows = -5; 1352 var cols = -10; 1353 } 1354 else 1355 { 1356 var rows = 5; 1357 var cols = 10; 1358 } 1359 1360 var textarea = fetch_object(id); 1361 if (typeof textarea.orig_rows == 'undefined') 1362 { 1363 textarea.orig_rows = textarea.rows; 1364 textarea.orig_cols = textarea.cols; 1365 } 1366 1367 var newrows = textarea.rows + rows; 1368 var newcols = textarea.cols + cols; 1369 1370 if (newrows >= textarea.orig_rows && newcols >= textarea.orig_cols) 1371 { 1372 textarea.rows = newrows; 1373 textarea.cols = newcols; 1374 } 1375 1376 return false; 1377} 1378 1379// ############################################################################# 1380// Collapsible element handlers 1381 1382/** 1383* Toggles the collapse state of an object, and saves state to 'vbulletin_collapse' cookie 1384* 1385* @param string Unique ID for the collapse group 1386* 1387* @return boolean false 1388*/ 1389function toggle_collapse(objid) 1390{ 1391 if (!is_regexp) 1392 { 1393 return false;
1394 } 1395 1396 obj = fetch_object('collapseobj_' + objid); 1397 img = fetch_object('collapseimg_' + objid); 1398 cel = fetch_object('collapsecel_' + objid); 1399 1400 if (!obj) 1401 { 1402 // nothing to collapse! 1403 if (img) 1404 { 1405 // hide the clicky image if there is one 1406 img.style.display = 'none'; 1407 } 1408 return false; 1409 } 1410 1411 if (obj.style.display == 'none') 1412 { 1413 obj.style.display = ''; 1414 save_collapsed(objid, false); 1415 if (img) 1416 { 1417 img_re = new RegExp("_collapsed\\.gif$"); 1418 img.src = img.src.replace(img_re, '.gif'); 1419 } 1420 if (cel) 1421 { 1422 cel_re = new RegExp("^(thead|tcat)(_collapsed)$"); 1423 cel.className = cel.className.replace(cel_re, '$1'); 1424 } 1425 } 1426 else 1427 { 1428 obj.style.display = 'none'; 1429 save_collapsed(objid, true); 1430 if (img) 1431 { 1432 img_re = new RegExp("\\.gif$"); 1433 img.src = img.src.replace(img_re, '_collapsed.gif'); 1434 } 1435 if (cel) 1436 { 1437 cel_re = new RegExp("^(thead|tcat)$"); 1438 cel.className = cel.className.replace(cel_re, '$1_collapsed'); 1439 } 1440 } 1441 return false; 1442} 1443 1444/** 1445* Updates vbulletin_collapse cookie with collapse preferences 1446* 1447* @param string Unique ID for the collapse group 1448* @param boolean Add a cookie 1449*/ 1450function save_collapsed(objid, addcollapsed) 1451{ 1452 var collapsed = fetch_cookie('vbulletin_collapse'); 1453 var tmp = new Array(); 1454 1455 if (collapsed != null) 1456 { 1457 collapsed = collapsed.split('\n'); 1458 1459 for (var i in collapsed) 1460 { 1461 if (collapsed[i] != objid && collapsed[i] != '') 1462 { 1463 tmp[tmp.length] = collapsed[i]; 1464 } 1465 } 1466 } 1467 1468 if (addcollapsed) 1469 { 1470 tmp[tmp.length] = objid; 1471 } 1472 1473 expires = new Date(); 1474 expires.setTime(expires.getTime() + (1000 * 86400 * 365)); 1475 set_cookie('vbulletin_collapse', tmp.join('\n'), expires); 1476} 1477 1478// ############################################################################# 1479// Event Handlers for PageNav menus 1480 1481/** 1482* Class to handle pagenav events 1483*/ 1484function vBpagenav() 1485{ 1486} 1487 1488/** 1489* Handles clicks on pagenav menu control objects 1490*/ 1491vBpagenav.prototype.controlobj_onclick = function(e) 1492{ 1493 this._onclick(e); 1494 var inputs = fetch_tags(this.menu.menuobj, 'input'); 1495 for (var i = 0; i < inputs.length; i++) 1496 { 1497 if (inputs[i].type == 'text') 1498 { 1499 inputs[i].focus(); 1500 break; 1501 } 1502 } 1503}; 1504 1505/** 1506* Submits the pagenav form... sort of 1507*/ 1508vBpagenav.prototype.form_gotopage = function(e) 1509{ 1510 if ((pagenum = parseInt(fetch_object('pagenav_itxt').value, 10)) > 0) 1511 { 1512 window.location = this.addr + '&page=' + pagenum; 1513 } 1514 return false; 1515}; 1516 1517/** 1518* Handles clicks on the 'Go' button in pagenav popups 1519*/ 1520vBpagenav.prototype.ibtn_onclick = function(e) 1521{ 1522 return this.form.gotopage(); 1523}; 1524 1525/** 1526* Handles keypresses in the text input of pagenav popups 1527*/ 1528vBpagenav.prototype.itxt_onkeypress = function(e) 1529{ 1530 return ((e ? e : window.event).keyCode == 13 ? this.form.gotopage() : true); 1531}; 1532 1533// ############################################################################# 1534// DHTML Popup Menu Handling (complements vbulletin_menu.js) 1535 1536/** 1537* Wrapper for vBmenu.register 1538* 1539* @param string Control ID 1540* @param boolean No image (true) 1541* @param boolean Does nothing any more 1542*/ 1543function vbmenu_register(controlid, noimage, datefield) 1544{ 1545 if (typeof(vBmenu) == "object") 1546 { 1547 return vBmenu.register(controlid, noimage); 1548 } 1549 else 1550 { 1551 return false; 1552 } 1553} 1554 1555// ############################################################################# 1556// Stuff that really doesn't fit anywhere else 1557 1558/** 1559* Sets an element and all its children to be 'unselectable' 1560* 1561* @param object Object to be made unselectable 1562*/
1563function set_unselectable(obj) 1564{ 1565 if (!is_ie4 && typeof obj.tagName != 'undefined') 1566 { 1567 if (obj.hasChildNodes()) 1568 { 1569 for (var i = 0; i < obj.childNodes.length; i++) 1570 { 1571 set_unselectable(obj.childNodes[i]); 1572 } 1573 } 1574 obj.unselectable = 'on'; 1575 } 1576} 1577 1578/** 1579* Fetches the sessionhash from the SESSIONURL variable 1580* 1581* @return string 1582*/ 1583function fetch_sessionhash() 1584{ 1585 return (SESSIONURL == '' ? '' : SESSIONURL.substr(2, 32)); 1586} 1587 1588/** 1589* Emulates the PHP version of vBulletin's construct_phrase() sprintf wrapper 1590* 1591* @param string String containing %1$s type replacement markers 1592* @param string First replacement 1593* @param string Nth replacement 1594* 1595* @return string 1596*/ 1597function construct_phrase() 1598{ 1599 if (!arguments || arguments.length < 1 || !is_regexp) 1600 { 1601 return false; 1602 } 1603 1604 var args = arguments; 1605 var str = args[0]; 1606 var re; 1607 1608 for (var i = 1; i < args.length; i++) 1609 { 1610 re = new RegExp("%" + i + "\\$s", 'gi'); 1611 str = str.replace(re, args[i]); 1612 } 1613 return str; 1614} 1615 1616/** 1617* Handles the quick style/language options in the footer 1618* 1619* @param object Select object 1620* @param string Type (style or language) 1621*/ 1622function switch_id(selectobj, type) 1623{ 1624 var id = selectobj.options[selectobj.selectedIndex].value; 1625 1626 if (id == '') 1627 { 1628 return; 1629 } 1630 1631 var url = new String(window.location); 1632 var fragment = new String(''); 1633 1634 // get rid of fragment 1635 url = url.split('#'); 1636 1637 // deal with the fragment first 1638 if (url[1]) 1639 { 1640 fragment = '#' + url[1]; 1641 } 1642 1643 // deal with the main url 1644 url = url[0]; 1645 1646 // remove id=x& from main bit 1647 if (url.indexOf(type + 'id=') != -1 && is_regexp) 1648 { 1649 re = new RegExp(type + "id=\\d+&?"); 1650 url = url.replace(re, ''); 1651 } 1652 1653 // add the ? to the url if needed 1654 if (url.indexOf('?') == -1) 1655 { 1656 url += '?'; 1657 } 1658 else 1659 { 1660 // make sure that we have a valid character to join our id bit 1661 lastchar = url.substr(url.length - 1); 1662 if (lastchar != '&' && lastchar != '?') 1663 { 1664 url += '&'; 1665 } 1666 } 1667 1668 window.location = url + type + 'id=' + id + fragment; 1669} 1670 1671/** 1672* Takes the 'alt' attribute for an image and attaches it to the 'title' attribute 1673* 1674* @param object Image object 1675*/ 1676function img_alt_2_title(img) 1677{ 1678 if (!img.title && img.alt != '') 1679 { 1680 img.title = img.alt; 1681 } 1682} 1683 1684// ############################################################################# 1685// Initialize a PostBit 1686 1687/** 1688* This function runs all the necessary Javascript code on a PostBit 1689* after it has been loaded via AJAX. Don't use this method before a 1690* complete page load or you'll have problems. 1691* 1692* @param object Object containing postbits 1693*/ 1694function PostBit_Init(obj, postid) 1695{ 1696 console.log("PostBit Init: %d", postid); 1697 1698 if (typeof vBmenu != 'undefined') 1699 { 1700 // init profile menu(s) 1701 var divs = fetch_tags(obj, 'div'); 1702 for (var i = 0; i < divs.length; i++) 1703 { 1704 if (divs[i].id && divs[i].id.substr(0, 9) == 'postmenu_') 1705 { 1706 vBmenu.register(divs[i].id, true); 1707 } 1708 } 1709 } 1710 1711 if (typeof vB_QuickEditor != 'undefined') 1712 { 1713 // init quick edit controls 1714 vB_AJAX_QuickEdit_Init(obj); 1715 } 1716 1717 if (typeof vB_QuickReply != 'undefined') 1718 { 1719 // init quick reply button 1720 qr_init_buttons(obj); 1721 } 1722 1723 if (typeof mq_init != 'undefined') 1724 { 1725 // init quick reply button 1726 mq_init(obj); 1727 } 1728 1729 if (typeof vBrep != 'undefined') 1730 { 1731 if (typeof postid != 'undefined' && typeof postid != 'null') 1732 { 1733 vbrep_register(postid); 1734 } 1735 } 1736 1737 if (typeof inlineMod != 'undefined') 1738 { 1739 im_init(obj); 1740 } 1741} 1742 1743// ############################################################################# 1744// Main vBulletin Javascript Initialization 1745 1746/** 1747* This function runs (almost) at the end of script loading on most vBulletin pages 1748* 1749* It sets up things like image alt->title tags, turns on the popup menu system etc. 1750* 1751* @return boolean 1752*/ 1753function vBulletin_init() 1754{ 1755 // don't bother doing any exciting stuff for WebTV 1756 if (is_webtv) 1757 { 1758 return false; 1759 } 1760 1761 // set 'title' tags for image elements 1762 var imgs = fetch_tags(document, 'img'); 1763 for (var i = 0; i < imgs.length; i++) 1764 { 1765 img_alt_2_title(imgs[i]); 1766 } 1767 1768 // finalize popup menus 1769 if (typeof vBmenu == 'object') 1770 { 1771 // close all menus on document click or resize 1772 if (typeof(YAHOO) != "undefined") 1773 { 1774 YAHOO.util.Event.on(document, "click", vbmenu_hide); 1775 YAHOO.util.Event.on(window, "resize", vbmenu_hide); 1776 } 1777 else if (window.attachEvent && !is_saf) 1778 { 1779 document.attachEvent('onclick', vbmenu_hide); 1780 window.attachEvent('onresize', vbmenu_hide); 1781 } 1782 else if (document.addEventListener && !is_saf) 1783 { 1784 document.addEventListener('click', vbmenu_hide, false); 1785 window.addEventListener('resize', vbmenu_hide, false); 1786 } 1787 else 1788 { 1789 window.onclick = vbmenu_hide; 1790 window.onresize = vbmenu_hide; 1791 } 1792 1793 // add popups to pagenav elements 1794 var pagenavs = fetch_tags(document, 'td'); 1795 for (var n = 0; n < pagenavs.length; n++) 1796 { 1797 if (pagenavs[n].hasChildNodes() && pagenavs[n].firstChild.name && pagenavs[n].firstChild.name.indexOf('PageNav') != -1) 1798 { 1799 var addr = pagenavs[n].title; 1800 pagenavs[n].title = ''; 1801 pagenavs[n].innerHTML = ''; 1802 pagenavs[n].id = 'pagenav.' + n; 1803 var pn = vBmenu.register(pagenavs[n].id); 1804 if (is_saf) 1805 { 1806 pn.controlobj._onclick = pn.controlobj.onclick; 1807 pn.controlobj.onclick = vBpagenav.prototype.controlobj_onclick; 1808 } 1809 } 1810 } 1811 1812 // process the pagenavs popup form 1813 if (typeof addr != 'undefined') 1814 { 1815 fetch_object('pagenav_form').addr = addr; 1816 fetch_object('pagenav_form').gotopage = vBpagenav.prototype.form_gotopage; 1817 fetch_object('pagenav_ibtn').onclick = vBpagenav.prototype.ibtn_onclick; 1818 fetch_object('pagenav_itxt').onkeypress = vBpagenav.prototype.itxt_onkeypress; 1819 } 1820 1821 // activate the menu system 1822 vBmenu.activate(true); 1823 } 1824 1825 // the new init system 1826 vBulletin.init(); 1827 1828 return true; 1829} 1830 1831// ############################################################################# 1832// vBulletin Javascript Framework 1833 1834/** 1835* General class for handling custom events and custom controls 1836*/ 1837function vBulletin_Framework() 1838{ 1839 /** 1840 * @var array Array of elements to be passed to control init functions 1841 * @var array Array of AJAX load/save URLs 1842 * @var array Array of YUI custom events 1843 * @var date Current time 1844 */ 1845 this.elements = new Array(); 1846 this.ajaxurls = new Array(); 1847 this.events = new Array(); 1848 this.time = new Date(); 1849 1850 // custom event to fire during class init 1851 this.add_event("systemInit"); 1852} 1853 1854/** 1855* Initializes the object - usually called at end of footer template 1856*/ 1857vBulletin_Framework.prototype.init = function() 1858{ 1859 this.events.systemInit.fire(); 1860 console.info("System Init Fired"); 1861} 1862 1863/** 1864* Emulates OOP class extension 1865* 1866* @param object Extended class 1867* @param object Base class 1868*/ 1869vBulletin_Framework.prototype.extend = function(subClass, baseClass) 1870{ 1871 function inheritance() {} 1872 inheritance.prototype = baseClass.prototype; 1873 1874 subClass.prototype = new inheritance(); 1875 subClass.prototype.constructor = subClass; 1876 subClass.baseConstructor = baseClass; 1877 subClass.superClass = baseClass.prototype; 1878} 1879 1880/** 1881* Registers a custom control for later initialization 1882* Arguments 1-n are stored for later use 1883* 1884* @param string Control type (vB_DatePicker etc.) 1885* @param string HTML element ID 1886*/ 1887vBulletin_Framework.prototype.register_control = function(controltype, element) 1888{ 1889 var args = new Array(); 1890 for (var i = 1; i < arguments.length; i++) 1891 { 1892 args.push(arguments[i]); 1893 } 1894 if (!this.elements[controltype]) 1895 { 1896 console.info("Creating array vBulletin.elements[\"%s\"]", controltype); 1897 this.elements[controltype] = new Array(); 1898 } 1899 var x = this.elements[controltype].push(args); 1900 console.log("vBulletin.elements[\"%s\"][%d] = %s", controltype, x-1, args.join(", ")); 1901} 1902 1903/** 1904* Registers AJAX load/save urls for a control 1905* 1906* @param Fetch URL 1907* @param Save URL 1908* @param List of elements to which these URLs apply 1909*/ 1910vBulletin_Framework.prototype.register_ajax_urls = function(fetch, save, elements) 1911{ 1912 var fetch = fetch.split("?"); fetch[1] = SESSIONURL + "ajax=1&" + fetch[1].replace(/\{(\d+)(:\w+)?\}/gi, '%$1$s'); 1913 var save = save.split("?"); save[1] = SESSIONURL + "ajax=1&" + save[1].replace(/\{(\d+)(:\w+)?\}/gi, '%$1$s'); 1914 1915 console.log("Register AJAX URLs for %s", elements); 1916 1917 for (var i = 0; i < elements.length; i++) 1918 { 1919 this.ajaxurls[elements[i]] = new Array(fetch, save); 1920 } 1921} 1922 1923/** 1924* Register a custom event 1925* 1926* @param string Event name 1927*/ 1928vBulletin_Framework.prototype.add_event = function(eventname) 1929{ 1930 this.events[eventname] = (typeof YAHOO != 'undefined' ? new YAHOO.util.CustomEvent(eventname) : new null_event()); 1931} 1932 1933/** 1934* BC: Pass console calls to Firebug if it's available 1935*/ 1936vBulletin_Framework.prototype.console = console.log; 1937 1938// ############################################################################# 1939 1940// initialize the PHP function emulator 1941var PHP = new vB_PHP_Emulator(); 1942 1943// Create an instance of the vBulletin Framework object 1944var vBulletin = new vBulletin_Framework(); 1945 1946/*======================================================================*\ 1947|| #################################################################### 1948|| # Downloaded: 00:43, Mon Jan 28th 2008 1949|| # CVS: $RCSfile$ - $Revision: 17556 $ 1950|| #################################################################### 1951\*======================================================================*/
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.