1/*======================================================================*\ 2|| #################################################################### || 3|| # vBulletin 3.5.4 4|| # ---------------------------------------------------------------- # || 5|| # Copyright ©2000-2006 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// Initial setup 14 15// ensure SESSIONURL exists 16if (typeof SESSIONURL == 'undefined') 17{ 18 SESSIONURL = ''; 19} 20 21// ensure vbphrase exists 22if (typeof vbphrase == 'undefined') 23{ 24 vbphrase = new Array(); 25} 26 27// Array of message editor objects 28var vB_Editor = new Array(); 29 30// Ignore characters within [quote] tags in messages for length check 31var ignorequotechars = false; 32 33// Number of pagenav items dealt with so far 34var pagenavcounter = 0; 35 36// ############################################################################# 37// Browser detection and limitation workarounds 38 39// Define the browser we have instead of multiple calls throughout the file 40var userAgent = navigator.userAgent.toLowerCase(); 41var is_opera = (userAgent.indexOf('opera') != -1); 42var is_saf = ((userAgent.indexOf('applewebkit') != -1) || (navigator.vendor == 'Apple Computer, Inc.')); 43var is_webtv = (userAgent.indexOf('webtv') != -1); 44var is_ie = ((userAgent.indexOf('msie') != -1) && (!is_opera) && (!is_saf) && (!is_webtv)); 45var is_ie4 = ((is_ie) && (userAgent.indexOf('msie 4.') != -1)); 46var is_moz = ((navigator.product == 'Gecko') && (!is_saf)); 47var is_kon = (userAgent.indexOf('konqueror') != -1); 48var is_ns = ((userAgent.indexOf('compatible') == -1) && (userAgent.indexOf('mozilla') != -1) && (!is_opera) && (!is_webtv) && (!is_saf)); 49var is_ns4 = ((is_ns) && (parseInt(navigator.appVersion) == 4)); 50var is_mac = (userAgent.indexOf('mac') != -1); 51 52// Catch possible bugs with WebTV and other older browsers 53var is_regexp = (window.RegExp) ? true : false; 54 55// Is the visiting browser compatible with AJAX? 56var AJAX_Compatible = false; 57 58// Help out old versions of IE that don't understand element.style.cursor = 'pointer' 59var pointer_cursor = (is_ie ? 'hand' : 'pointer'); 60 61/** 62* Workaround for heinous IE bug - add special vBlength property to all strings 63* This method is applied to ALL string objects automatically 64* 65* @return integer 66*/ 67String.prototype.vBlength = function() 68{ 69 return (is_ie && this.indexOf('\n') != -1) ? this.replace(/\r?\n/g, '_').length : this.length; 70} 71 72/** 73* Pop function for browsers that don't have it built in 74* 75* @param array Array from which to pop 76* 77* @return mixed null on empty, value on success 78*/ 79function array_pop(a) 80{ 81 if (typeof a != 'object' || !a.length) 82 { 83 return null; 84 } 85 else 86 { 87 var response = a[a.length - 1]; 88 a.length--; 89 return response; 90 } 91} 92 93/** 94* Push function for browsers that don't have it built in 95* 96* @param array Array onto which to push 97* @param mixed Value to push onto array 98* 99* @return integer Length of array 100*/ 101function array_push(a, value) 102{ 103 a[a.length] = value; 104 return a.length; 105} 106 107/** 108* Function to emulate document.getElementById 109* 110* @param string Object ID 111* 112* @return mixed null if not found, object if found 113*/ 114function fetch_object(idname) 115{ 116 if (document.getElementById) 117 { 118 return document.getElementById(idname); 119 } 120 else if (document.all) 121 { 122 return document.all[idname]; 123 } 124 else if (document.layers) 125 { 126 return document.layers[idname]; 127 } 128 else 129 { 130 return null; 131 } 132} 133 134/** 135* Function to emulate document.getElementsByTagName 136* 137* @param object Parent tag (eg: document) 138* @param string Tag type (eg: 'td') 139* 140* @return array 141*/ 142function fetch_tags(parentobj, tag) 143{ 144 if (typeof parentobj.getElementsByTagName != 'undefined') 145 { 146 return parentobj.getElementsByTagName(tag); 147 } 148 else if (parentobj.all && parentobj.all.tags) 149 { 150 return parentobj.all.tags(tag); 151 } 152 else 153 { 154 return null; 155 } 156} 157 158// ############################################################################# 159// Event handlers 160 161/** 162* Handles the different event models of different browsers and prevents event bubbling 163* 164* @param event Event object 165* 166* @return event 167*/ 168function do_an_e(eventobj) 169{ 170 if (!eventobj || is_ie) 171 { 172 window.event.returnValue = false;
173 window.event.cancelBubble = true; 174 return window.event; 175 } 176 else 177 { 178 eventobj.stopPropagation(); 179 eventobj.preventDefault(); 180 return eventobj; 181 } 182} 183 184/** 185* Handles the different event models of different browsers and prevents event bubbling in a lesser way than do_an_e() 186* 187* @param event Event object 188* 189* @return event 190*/ 191function e_by_gum(eventobj) 192{ 193 if (!eventobj || is_ie) 194 { 195 window.event.cancelBubble = true; 196 return window.event; 197 } 198 else 199 { 200 if (eventobj.target.type == 'submit') 201 { 202 // naughty safari 203 eventobj.target.form.submit(); 204 } 205 eventobj.stopPropagation(); 206 return eventobj; 207 } 208} 209 210// ############################################################################# 211// Message manipulation and validation 212 213/** 214* Checks that a message is valid for submission to PHP 215* 216* @param string Message text 217* @param mixed Either subject text (if you want to make sure it exists) or 0 if you don't care 218* @param integer Minimum acceptable character limit for the message 219* 220* @return boolean 221*/ 222function validatemessage(messagetext, subjecttext, minchars) 223{ 224 if (is_kon || is_saf || is_webtv) 225 { 226 // ignore less-than-capable browsers 227 return true; 228 } 229 else if (subjecttext.length < 1) 230 { 231 // subject not specified 232 alert(vbphrase['must_enter_subject']); 233 return false; 234 } 235 else 236 { 237 var stripped = PHP.trim(stripcode(messagetext, false, ignorequotechars)); 238 239 if (stripped.length < minchars) 240 { 241 // minimum message length not met 242 alert(construct_phrase(vbphrase['message_too_short'], minchars)); 243 return false; 244 } 245 else 246 { 247 // everything seems ok 248 return true; 249 } 250 } 251} 252 253/** 254* Strips quotes and bbcode tags from text 255* 256* @param string Text to manipulate 257* @param boolean If true, strip <x> otherwise strip [x] 258* @param boolean If true, strip all [quote]...contents...[/quote] 259* 260* @return string 261*/ 262function stripcode(str, ishtml, stripquotes) 263{ 264 if (!is_regexp) 265 { 266 return str; 267 } 268 269 if (stripquotes) 270 { 271 var start_time = new Date().getTime(); 272 273 while ((startindex = PHP.stripos(str, '[quote')) !== false) 274 { 275 if (new Date().getTime() - start_time > 2000) 276 { 277 // while loop has been running for over 2 seconds and has probably gone infinite 278 break; 279 } 280 281 if ((stopindex = PHP.stripos(str, '[/quote]')) !== false) 282 { 283 fragment = str.substr(startindex, stopindex - startindex + 8); 284 str = str.replace(fragment, ''); 285 } 286 else 287 { 288 break; 289 } 290 str = PHP.trim(str); 291 } 292 } 293 294 if (ishtml) 295 { 296 // exempt image tags -- they need to count as characters in the string 297 // as the do as BB codes 298 str = str.replace(/<img[^>]+src="([^"]+)"[^>]*>/gi, '$1'); 299 300 var html1 = new RegExp("<(\\w+)[^>]*>", 'gi'); 301 var html2 = new RegExp("<\\/\\w+>", 'gi'); 302 303 str = str.replace(html1, ''); 304 str = str.replace(html2, ''); 305 306 var html3 = new RegExp('( )', 'gi'); 307 str = str.replace(html3, ' '); 308 } 309 else 310 { 311 var bbcode1 = new RegExp("\\[(\\w+)[^\\]]*\\]", 'gi'); 312 var bbcode2 = new RegExp("\\[\\/(\\w+)\\]", 'gi'); 313 314 str = str.replace(bbcode1, ''); 315 str = str.replace(bbcode2, ''); 316 } 317 318 return str; 319} 320 321// ############################################################################# 322// vB_PHP_Emulator class 323// ############################################################################# 324 325/** 326* PHP Function Emulator Class 327*/ 328function vB_PHP_Emulator() 329{ 330} 331 332// ============================================================================= 333// vB_PHP_Emulator Methods 334 335/** 336* Find a string within a string (case insensitive) 337* 338* @param string Haystack 339* @param string Needle 340* @param integer Offset 341* 342* @return mixed Not found: false / Found: integer position 343*/ 344vB_PHP_Emulator.prototype.stripos = function(haystack, needle, offset) 345{ 346 if (typeof offset == 'undefined') 347 { 348 offset = 0; 349 } 350 351 index = haystack.toLowerCase().indexOf(needle.toLowerCase(), offset); 352 353 return (index == -1 ? false : index); 354} 355 356/** 357* Trims leading whitespace 358* 359* @param string String to trim 360* 361* @return string 362*/ 363vB_PHP_Emulator.prototype.ltrim = function(str) 364{ 365 return str.replace(/^\s+/g, ''); 366} 367 368/** 369* Trims trailing whitespace 370* 371* @param string String to trim 372* 373* @return string 374*/ 375vB_PHP_Emulator.prototype.rtrim = function(str) 376{ 377 return str.replace(/(\s+)$/g, ''); 378} 379 380/** 381* Trims leading and trailing whitespace 382* 383* @param string String to trim 384* 385* @return string 386*/ 387vB_PHP_Emulator.prototype.trim = function(str) 388{ 389 return this.ltrim(this.rtrim(str)); 390} 391 392/** 393* Emulation of PHP's preg_quote() 394* 395* @param string String to process 396* 397* @return string 398*/ 399vB_PHP_Emulator.prototype.preg_quote = function(str) 400{ 401 // replace + { } ( ) [ ] | / ? ^ $ \ . = ! < > : * with backslash+character 402 return str.replace(/(\+|\{|\}|\(|\)|\[|\]|\||\/|\?|\^|\$|\\|\.|\=|\!|\<|\>|\:|\*)/g, "\\$1"); 403} 404 405/** 406* Emulates unhtmlspecialchars in vBulletin 407* 408* @param string String to process 409* 410* @return string 411*/ 412vB_PHP_Emulator.prototype.unhtmlspecialchars = function(str) 413{ 414 f = new Array(/</g, />/g, /"/g, /&/g); 415 r = new Array('<', '>', '"', '&'); 416 417 for (var i in f) 418 { 419 str = str.replace(f[i], r[i]); 420 } 421 422 return str; 423} 424 425/** 426* Emulates PHP's htmlspecialchars() 427* 428* @param string String to process 429* 430* @return string 431*/ 432vB_PHP_Emulator.prototype.htmlspecialchars = function(str) 433{ 434 //var f = new Array(/&(?!#[0-9]+;)/g, /</g, />/g, /"/g); 435 var f = new Array( 436 (is_mac && is_ie ? new RegExp('&', 'g') : new RegExp('&(?!#[0-9]+;)', 'g')), 437 new RegExp('<', 'g'), 438 new RegExp('>', 'g'), 439 new RegExp('"', 'g') 440 ); 441 var r = new Array( 442 '&', 443 '<', 444 '>', 445 '"' 446 ); 447 448 for (var i = 0; i < f.length; i++) 449 { 450 str = str.replace(f[i], r[i]); 451 } 452 453 return str; 454} 455 456/** 457* Searches an array for a value 458* 459* @param string Needle 460* @param array Haystack 461* @param boolean Case insensitive 462* 463* @return integer Not found: -1 / Found: integer index 464*/ 465vB_PHP_Emulator.prototype.in_array = function(ineedle, haystack, caseinsensitive) 466{ 467 var needle = new String(ineedle); 468 469 if (caseinsensitive) 470 { 471 needle = needle.toLowerCase(); 472 for (var i in haystack) 473 { 474 if (haystack[i].toLowerCase() == needle) 475 { 476 return i; 477 } 478 } 479 } 480 else 481 { 482 for (var i in haystack) 483 { 484 if (haystack[i] == needle) 485 { 486 return i; 487 } 488 } 489 } 490 return -1; 491} 492 493/** 494* Emulates PHP's strpad() 495* 496* @param string Text to pad 497* @param integer Length to pad 498* @param string String with which to pad 499* 500* @return string 501*/ 502vB_PHP_Emulator.prototype.str_pad = function(text, length, padstring) 503{ 504 text = new String(text); 505 padstring = new String(padstring); 506 507 if (text.length < length) 508 { 509 padtext = new String(padstring); 510 511 while (padtext.length < (length - text.length)) 512 { 513 padtext += padstring; 514 } 515 516 text = padtext.substr(0, (length - text.length)) + text; 517 } 518 519 return text; 520} 521 522/**
523* A sort of emulation of PHP's urlencode - not 100% the same, but accomplishes the same thing 524* 525* @param string String to encode 526* 527* @return string 528*/ 529vB_PHP_Emulator.prototype.urlencode = function(text) 530{ 531 text = text.toString(); 532 533 // this escapes 128 - 255, as JS uses the unicode code points for them. 534 // This causes problems with submitting text via AJAX with the UTF-8 charset. 535 var matches = text.match(/[\x90-\xFF]/g); 536 if (matches) 537 { 538 for (var matchid = 0; matchid < matches.length; matchid++) 539 { 540 var char_code = matches[matchid].charCodeAt(0); 541 text = text.replace(matches[matchid], '%u00' + (char_code & 0xFF).toString(16).toUpperCase()); 542 } 543 } 544 545 return escape(text).replace(/\+/g, "%2B"); 546} 547 548/** 549* Works a bit like ucfirst, but with some extra options 550* 551* @param string String with which to work 552* @param string Cut off string before first occurence of this string 553* 554* @return string 555*/ 556vB_PHP_Emulator.prototype.ucfirst = function(str, cutoff) 557{ 558 if (typeof cutoff != 'undefined') 559 { 560 var cutpos = str.indexOf(cutoff); 561 if (cutpos > 0) 562 { 563 str = str.substr(0, cutpos); 564 } 565 } 566 567 str = str.split(' '); 568 for (var i = 0; i < str.length; i++) 569 { 570 str[i] = str[i].substr(0, 1).toUpperCase() + str[i].substr(1); 571 } 572 return str.join(' '); 573} 574 575// initialize the PHP emulator 576var PHP = new vB_PHP_Emulator(); 577 578// ############################################################################# 579// vB_AJAX_Handler 580// ############################################################################# 581 582/** 583* XML Sender Class 584* 585* @param boolean Should connections be asyncronous? 586*/ 587function vB_AJAX_Handler(async) 588{ 589 /** 590 * Should connections be asynchronous? 591 * 592 * @var boolean 593 */ 594 this.async = async ? true : false; 595} 596 597// ============================================================================= 598// vB_AJAX_Handler methods 599 600/** 601* Initializes the XML handler 602* 603* @return boolean True if handler created OK 604*/ 605vB_AJAX_Handler.prototype.init = function() 606{ 607 if (typeof vb_disable_ajax != 'undefined' && vb_disable_ajax == 2) 608 { 609 // disable all ajax features 610 return false; 611 } 612 613 try 614 { 615 this.handler = new XMLHttpRequest(); 616 return (this.handler.setRequestHeader ? true : false); 617 } 618 catch(e) 619 { 620 try 621 { 622 this.handler = eval("new A" + "ctiv" + "eX" + "Ob" + "ject('Micr" + "osoft.XM" + "LHTTP');"); 623 return true; 624 } 625 catch(e) 626 { 627 return false; 628 } 629 } 630} 631 632/** 633* Detects if the browser is fully compatible 634* 635* @return boolean 636*/ 637vB_AJAX_Handler.prototype.is_compatible = function() 638{ 639 if (typeof vb_disable_ajax != 'undefined' && vb_disable_ajax == 2) 640 { 641 // disable all ajax features 642 return false; 643 } 644 645 if (is_ie && !is_ie4) { return true; } 646 else if (XMLHttpRequest) 647 { 648 try { return XMLHttpRequest.prototype.setRequestHeader ? true : false; } 649 catch(e) 650 { 651 try { var tester = new XMLHttpRequest(); return tester.setRequestHeader ? true : false; } 652 catch(e) { return false; } 653 } 654 } 655 else { return false; } 656} 657 658/** 659* Checks if the system is ready 660* 661* @return boolean False if ready 662*/ 663vB_AJAX_Handler.prototype.not_ready = function() 664{ 665 return (this.handler.readyState && (this.handler.readyState < 4)); 666} 667 668/** 669* OnReadyStateChange event handler 670* 671* @param function 672*/ 673vB_AJAX_Handler.prototype.onreadystatechange = function(event) 674{ 675 if (!this.handler) 676 { 677 if (!this.init()) 678 { 679 return false; 680 } 681 } 682 if (typeof event == 'function') 683 { 684 this.handler.onreadystatechange = event; 685 } 686 else 687 { 688 alert('XML Sender OnReadyState event is not a function'); 689 } 690} 691 692/** 693* Sends data 694* 695* @param string Destination URL 696* @param string Request Data 697* 698* @return mixed Return message 699*/ 700vB_AJAX_Handler.prototype.send = function(desturl, datastream) 701{ 702 if (!this.handler) 703 { 704 if (!this.init()) 705 { 706 return false; 707 } 708 } 709 if (!this.not_ready()) 710 { 711 this.handler.open('POST', desturl, this.async); 712 this.handler.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 713 this.handler.send(datastream + '&s=' + fetch_sessionhash()); 714 715 if (!this.async && this.handler.readyState == 4 && this.handler.status == 200) 716 { 717 return true; 718 } 719 } 720 return false;
721} 722 723// we can check this variable to see if browser is AJAX compatible 724var AJAX_Compatible = vB_AJAX_Handler.prototype.is_compatible(); 725 726// ############################################################################# 727// vB_Hidden_Form 728// ############################################################################# 729 730/** 731* Form Generator Class 732* 733* Builds a form filled with hidden fields for invisible submit via POST 734* 735* @param string Script (my_target_script.php) 736*/ 737function vB_Hidden_Form(script) 738{ 739 this.form = document.createElement('form'); 740 this.form.method = 'post'; 741 this.form.action = script; 742} 743 744// ============================================================================= 745// vB_Hidden_Form methods 746 747/** 748* Adds a hidden input field to the form object 749* 750* @param string Name attribute 751* @param string Value attribute 752*/ 753vB_Hidden_Form.prototype.add_input = function(name, value) 754{ 755 var inputobj = document.createElement('input'); 756 757 inputobj.type = 'hidden'; 758 inputobj.name = name; 759 inputobj.value = value; 760 761 this.form.appendChild(inputobj); 762}; 763 764/** 765* Fetches all form elements inside an HTML element and performs 'add_input()' on them 766* 767* @param object HTML element to search 768*/ 769vB_Hidden_Form.prototype.add_inputs_from_object = function(obj) 770{ 771 var inputs = fetch_tags(obj, 'input'); 772 for (var i = 0; i < inputs.length; i++) 773 { 774 switch (inputs[i].type) 775 { 776 case 'checkbox': 777 case 'radio': 778 if (inputs[i].checked) 779 { 780 this.add_input(inputs[i].name, inputs[i].value); 781 } 782 break; 783 case 'text': 784 case 'hidden': 785 case 'password': 786 this.add_input(inputs[i].name, inputs[i].value); 787 break; 788 default: 789 continue; 790 } 791 } 792 793 var textareas = fetch_tags(obj, 'textarea'); 794 for (var i = 0; i < textareas.length; i++) 795 { 796 this.add_input(textareas[i].name, textareas[i].value); 797 } 798 799 var selects = fetch_tags(obj, 'select'); 800 for (var i = 0; i < selects.length; i++) 801 { 802 if (selects[i].multiple) 803 { 804 for (var j = 0; j < selects[i].options.length; j++) 805 { 806 if (selects[i].options[j].selected) 807 { 808 this.add_input(selects[i].name, selects[i].options[j].value); 809 } 810 } 811 } 812 else 813 { 814 this.add_input(selects[i].name, selects[i].options[selects[i].selectedIndex].value); 815 } 816 } 817} 818 819/** 820* Submits the hidden form object 821*/ 822vB_Hidden_Form.prototype.submit_form = function() 823{ 824 document.body.appendChild(this.form).submit(); 825}; 826 827// ############################################################################# 828// Window openers and instant messenger wrappers 829 830/** 831* Opens a generic browser window 832* 833* @param string URL 834* @param integer Width 835* @param integer Height 836* @param string Optional Window ID 837*/ 838function openWindow(url, width, height, windowid) 839{ 840 return window.open( 841 url, 842 (typeof windowid == 'undefined' ? 'vBPopup' : windowid), 843 'statusbar=no,menubar=no,toolbar=no,scrollbars=yes,resizable=yes' 844 + (typeof width != 'undefined' ? (',width=' + width) : '') + (typeof height != 'undefined' ? (',height=' + height) : '') 845 ); 846} 847 848/** 849* Opens control panel help window 850* 851* @param string Script name 852* @param string Action type 853* @param string Option value 854* 855* @return window 856*/ 857function js_open_help(scriptname, actiontype, optionval) 858{ 859 return openWindow( 860 'help.php?s=' + SESSIONHASH + '&do=answer&page=' + scriptname + '&pageaction=' + actiontype + '&option=' + optionval, 861 600, 450, 'helpwindow' 862 ); 863} 864 865/** 866* Opens a window to show a list of posters in a thread (misc.php?do=whoposted) 867* 868* @param integer Thread ID 869* 870* @return window 871*/ 872function who(threadid) 873{ 874 return openWindow( 875 'misc.php?' + SESSIONURL + 'do=whoposted&t=' + threadid, 876 230, 300 877 ); 878} 879 880/** 881* Opens an IM Window 882* 883* @param string IM type 884* @param integer User ID 885* @param integer Width of window 886* @param integer Height of window 887* 888* @return window 889*/ 890function imwindow(imtype, userid, width, height) 891{ 892 return openWindow( 893 'sendmessage.php?' + SESSIONURL + 'do=im&type=' + imtype + '&u=' + userid, 894 width, height 895 ); 896} 897 898/** 899* Sends an MSN message 900* 901* @param string Target MSN handle 902* 903* @return boolean false 904*/ 905function SendMSNMessage(name) 906{ 907 if (!is_ie) 908 { 909 alert(vbphrase['msn_functions_only_work_in_ie']); 910 return false;
911 } 912 else 913 { 914 MsgrObj.InstantMessage(name); 915 return false; 916 } 917} 918 919/** 920* Adds an MSN Contact (requires MSN) 921* 922* @param string MSN handle 923* 924* @return boolean false 925*/ 926function AddMSNContact(name) 927{ 928 if (!is_ie) 929 { 930 alert(vbphrase['msn_functions_only_work_in_ie']); 931 return false; 932 } 933 else 934 { 935 MsgrObj.AddContact(0, name); 936 return false; 937 } 938} 939 940// ############################################################################# 941// Cookie handlers 942 943/** 944* Sets a cookie 945* 946* @param string Cookie name 947* @param string Cookie value 948* @param date Cookie expiry date 949*/ 950function set_cookie(name, value, expires) 951{ 952 document.cookie = name + '=' + escape(value) + '; path=/' + (typeof expires != 'undefined' ? '; expires=' + expires.toGMTString() : ''); 953} 954 955/** 956* Deletes a cookie 957* 958* @param string Cookie name 959*/ 960function delete_cookie(name) 961{ 962 document.cookie = name + '=' + '; expires=Thu, 01-Jan-70 00:00:01 GMT' + '; path=/'; 963} 964 965/** 966* Fetches the value of a cookie 967* 968* @param string Cookie name 969* 970* @return string 971*/ 972function fetch_cookie(name) 973{ 974 cookie_name = name + '='; 975 cookie_length = document.cookie.length; 976 cookie_begin = 0; 977 while (cookie_begin < cookie_length) 978 { 979 value_begin = cookie_begin + cookie_name.length; 980 if (document.cookie.substring(cookie_begin, value_begin) == cookie_name) 981 { 982 var value_end = document.cookie.indexOf (';', value_begin); 983 if (value_end == -1) 984 { 985 value_end = cookie_length; 986 } 987 return unescape(document.cookie.substring(value_begin, value_end)); 988 } 989 cookie_begin = document.cookie.indexOf(' ', cookie_begin) + 1; 990 if (cookie_begin == 0) 991 { 992 break; 993 } 994 } 995 return null; 996} 997 998// ############################################################################# 999// Form element managers (used for 'check all' type systems 1000 1001/** 1002* Sets all checkboxes, radio buttons or selects in a given form to a given state, with exceptions 1003* 1004* @param object Form object 1005* @param string Target element type (one of 'radio', 'select-one', 'checkbox') 1006* @param string Selected option in case of 'radio' 1007* @param array Array of element names to be excluded 1008* @param mixed Value to give to found elements 1009*/ 1010function js_toggle_all(formobj, formtype, option, exclude, setto) 1011{ 1012 for (var i =0; i < formobj.elements.length; i++) 1013 { 1014 var elm = formobj.elements[i]; 1015 if (elm.type == formtype && PHP.in_array(elm.name, exclude, false) == -1) 1016 { 1017 switch (formtype) 1018 { 1019 case 'radio': 1020 if (elm.value == option) // option == '' evaluates true when option = 0 1021 { 1022 elm.checked = setto; 1023 } 1024 break; 1025 case 'select-one': 1026 elm.selectedIndex = setto; 1027 break; 1028 default: 1029 elm.checked = setto; 1030 break; 1031 } 1032 } 1033 } 1034} 1035 1036/** 1037* Sets all <select> elements to the selectedIndex specified by the 'selectall' element 1038* 1039* @param object Form object 1040*/ 1041function js_select_all(formobj) 1042{ 1043 exclude = new Array(); 1044 exclude[0] = 'selectall'; 1045 js_toggle_all(formobj, 'select-one', '', exclude, formobj.selectall.selectedIndex); 1046} 1047 1048/** 1049* Sets all <input type="checkbox" /> elements to have the same checked status as 'allbox' 1050* 1051* @param object Form object 1052*/ 1053function js_check_all(formobj) 1054{ 1055 exclude = new Array(); 1056 exclude[0] = 'keepattachments'; 1057 exclude[1] = 'allbox'; 1058 exclude[2] = 'removeall'; 1059 js_toggle_all(formobj, 'checkbox', '', exclude, formobj.allbox.checked); 1060} 1061 1062/** 1063* Sets all <input type="radio" /> groups to have a particular option checked 1064* 1065* @param object Form object 1066* @param mixed Selected option 1067*/ 1068function js_check_all_option(formobj, option) 1069{ 1070 exclude = new Array(); 1071 exclude[0] = 'useusergroup'; 1072 js_toggle_all(formobj, 'radio', option, exclude, true); 1073} 1074 1075/** 1076* Alias to js_check_all 1077*/ 1078function checkall(formobj) { js_check_all(formobj); } 1079 1080/** 1081* Alias to js_check_all_option 1082*/ 1083function checkall_option(formobj, option) { js_check_all_option(formobj, option); } 1084 1085/** 1086* Resize function for CP textareas 1087* 1088* @param integer If positive, size up, otherwise size down 1089* @param string ID of the textarea 1090* 1091* @return boolean false 1092*/ 1093function resize_textarea(to, id) 1094{ 1095 if (to < 0) 1096 { 1097 var rows = -5; 1098 var cols = -10; 1099 } 1100 else 1101 { 1102 var rows = 5; 1103 var cols = 10; 1104 } 1105 1106 var textarea = fetch_object(id); 1107 if (typeof textarea.orig_rows == 'undefined') 1108 { 1109 textarea.orig_rows = textarea.rows; 1110 textarea.orig_cols = textarea.cols; 1111 } 1112 1113 var newrows = textarea.rows + rows; 1114 var newcols = textarea.cols + cols; 1115 1116 if (newrows >= textarea.orig_rows && newcols >= textarea.orig_cols) 1117 { 1118 textarea.rows = newrows; 1119 textarea.cols = newcols; 1120 } 1121 1122 return false;
1123} 1124 1125// ############################################################################# 1126// Collapsible element handlers 1127 1128/** 1129* Toggles the collapse state of an object, and saves state to 'vbulletin_collapse' cookie 1130* 1131* @param string Unique ID for the collapse group 1132* 1133* @return boolean false 1134*/ 1135function toggle_collapse(objid) 1136{ 1137 if (!is_regexp) 1138 { 1139 return false; 1140 } 1141 1142 obj = fetch_object('collapseobj_' + objid); 1143 img = fetch_object('collapseimg_' + objid); 1144 cel = fetch_object('collapsecel_' + objid); 1145 1146 if (!obj) 1147 { 1148 // nothing to collapse! 1149 if (img) 1150 { 1151 // hide the clicky image if there is one 1152 img.style.display = 'none'; 1153 } 1154 return false; 1155 } 1156 1157 if (obj.style.display == 'none') 1158 { 1159 obj.style.display = ''; 1160 save_collapsed(objid, false); 1161 if (img) 1162 { 1163 img_re = new RegExp("_collapsed\\.gif$"); 1164 img.src = img.src.replace(img_re, '.gif'); 1165 } 1166 if (cel) 1167 { 1168 cel_re = new RegExp("^(thead|tcat)(_collapsed)$"); 1169 cel.className = cel.className.replace(cel_re, '$1'); 1170 } 1171 } 1172 else 1173 { 1174 obj.style.display = 'none'; 1175 save_collapsed(objid, true); 1176 if (img) 1177 { 1178 img_re = new RegExp("\\.gif$"); 1179 img.src = img.src.replace(img_re, '_collapsed.gif'); 1180 } 1181 if (cel) 1182 { 1183 cel_re = new RegExp("^(thead|tcat)$"); 1184 cel.className = cel.className.replace(cel_re, '$1_collapsed'); 1185 } 1186 } 1187 return false; 1188} 1189 1190/** 1191* Updates vbulletin_collapse cookie with collapse preferences 1192* 1193* @param string Unique ID for the collapse group 1194* @param boolean Add a cookie 1195*/ 1196function save_collapsed(objid, addcollapsed) 1197{ 1198 var collapsed = fetch_cookie('vbulletin_collapse'); 1199 var tmp = new Array(); 1200 1201 if (collapsed != null) 1202 { 1203 collapsed = collapsed.split('\n'); 1204 1205 for (var i in collapsed) 1206 { 1207 if (collapsed[i] != objid && collapsed[i] != '') 1208 { 1209 tmp[tmp.length] = collapsed[i]; 1210 } 1211 } 1212 } 1213 1214 if (addcollapsed) 1215 { 1216 tmp[tmp.length] = objid; 1217 } 1218 1219 expires = new Date(); 1220 expires.setTime(expires.getTime() + (1000 * 86400 * 365)); 1221 set_cookie('vbulletin_collapse', tmp.join('\n'), expires); 1222} 1223 1224// ############################################################################# 1225// Event Handlers for PageNav menus 1226 1227/** 1228* Class to handle pagenav events 1229*/ 1230function vBpagenav() 1231{ 1232} 1233 1234/** 1235* Handles clicks on pagenav menu control objects 1236*/ 1237vBpagenav.prototype.controlobj_onclick = function(e) 1238{ 1239 this._onclick(e); 1240 var inputs = fetch_tags(this.menu.menuobj, 'input'); 1241 for (var i = 0; i < inputs.length; i++) 1242 { 1243 if (inputs[i].type == 'text') 1244 { 1245 inputs[i].focus(); 1246 break; 1247 } 1248 } 1249}; 1250 1251/** 1252* Submits the pagenav form... sort of 1253*/ 1254vBpagenav.prototype.form_gotopage = function(e) 1255{ 1256 if ((pagenum = parseInt(fetch_object('pagenav_itxt').value, 10)) > 0) 1257 { 1258 window.location = this.addr + '&page=' + pagenum; 1259 } 1260 return false; 1261}; 1262 1263/** 1264* Handles clicks on the 'Go' button in pagenav popups 1265*/ 1266vBpagenav.prototype.ibtn_onclick = function(e) 1267{ 1268 return this.form.gotopage(); 1269}; 1270 1271/** 1272* Handles keypresses in the text input of pagenav popups 1273*/ 1274vBpagenav.prototype.itxt_onkeypress = function(e) 1275{ 1276 return ((e ? e : window.event).keyCode == 13 ? this.form.gotopage() : true); 1277}; 1278 1279// ############################################################################# 1280// DHTML Popup Menu Handling (complements vbulletin_menu.js) 1281 1282/** 1283* Wrapper for vBmenu.register 1284* 1285* @param string Control ID 1286* @param boolean No image (true) 1287* @param boolean Does nothing any more 1288*/ 1289function vbmenu_register(controlid, noimage, datefield) 1290{ 1291 if (typeof vBmenu == 'object') 1292 { 1293 vBmenu.register(controlid, noimage); 1294 } 1295} 1296 1297// ############################################################################# 1298// Stuff that really doesn't fit anywhere else 1299 1300/** 1301* Sets an element and all its children to be 'unselectable' 1302* 1303* @param object Object to be made unselectable 1304*/
1305function set_unselectable(obj) 1306{ 1307 if (!is_ie4 && typeof obj.tagName != 'undefined') 1308 { 1309 if (obj.hasChildNodes()) 1310 { 1311 for (var i = 0; i < obj.childNodes.length; i++) 1312 { 1313 set_unselectable(obj.childNodes[i]); 1314 } 1315 } 1316 obj.unselectable = 'on'; 1317 } 1318} 1319 1320/** 1321* Fetches the sessionhash from the SESSIONURL variable 1322* 1323* @return string 1324*/ 1325function fetch_sessionhash() 1326{ 1327 return (SESSIONURL == '' ? '' : SESSIONURL.substr(2, 32)); 1328} 1329 1330/** 1331* Emulates the PHP version of vBulletin's construct_phrase() sprintf wrapper 1332* 1333* @param string String containing %1$s type replacement markers 1334* @param string First replacement 1335* @param string Nth replacement 1336* 1337* @return string 1338*/ 1339function construct_phrase() 1340{ 1341 if (!arguments || arguments.length < 1 || !is_regexp) 1342 { 1343 return false; 1344 } 1345 1346 var args = arguments; 1347 var str = args[0]; 1348 var re; 1349 1350 for (var i = 1; i < args.length; i++) 1351 { 1352 re = new RegExp("%" + i + "\\$s", 'gi'); 1353 str = str.replace(re, args[i]); 1354 } 1355 return str; 1356} 1357 1358/** 1359* Handles the quick style/language options in the footer 1360* 1361* @param object Select object 1362* @param string Type (style or language) 1363*/ 1364function switch_id(selectobj, type) 1365{ 1366 var id = selectobj.options[selectobj.selectedIndex].value; 1367 1368 if (id == '') 1369 { 1370 return; 1371 } 1372 1373 var url = new String(window.location); 1374 var fragment = new String(''); 1375 1376 // get rid of fragment 1377 url = url.split('#'); 1378 1379 // deal with the fragment first 1380 if (url[1]) 1381 { 1382 fragment = '#' + url[1]; 1383 } 1384 1385 // deal with the main url 1386 url = url[0]; 1387 1388 // remove id=x& from main bit 1389 if (url.indexOf(type + 'id=') != -1 && is_regexp) 1390 { 1391 re = new RegExp(type + "id=\\d+&?"); 1392 url = url.replace(re, ''); 1393 } 1394 1395 // add the ? to the url if needed 1396 if (url.indexOf('?') == -1) 1397 { 1398 url += '?'; 1399 } 1400 else 1401 { 1402 // make sure that we have a valid character to join our id bit 1403 lastchar = url.substr(url.length - 1); 1404 if (lastchar != '&' && lastchar != '?') 1405 { 1406 url += '&'; 1407 } 1408 } 1409 1410 window.location = url + type + 'id=' + id + fragment; 1411} 1412 1413// ############################################################################# 1414// Initialize a PostBit 1415 1416/** 1417* This function runs all the necessary Javascript code on a PostBit 1418* after it has been loaded via AJAX. Don't use this method before a 1419* complete page load or you'll have problems. 1420* 1421* @param object Object containing postbits 1422*/ 1423function PostBit_Init(obj) 1424{ 1425 if (typeof vBmenu != 'undefined') 1426 { 1427 // init profile menu(s) 1428 var divs = fetch_tags(obj, 'div'); 1429 for (var i = 0; i < divs.length; i++) 1430 { 1431 if (divs[i].id && divs[i].id.substr(0, 9) == 'postmenu_') 1432 { 1433 vBmenu.register(divs[i].id, true); 1434 } 1435 } 1436 } 1437 1438 if (typeof vB_QuickEditor != 'undefined') 1439 { 1440 // init quick edit controls 1441 vB_AJAX_QuickEdit_Init(obj); 1442 } 1443 1444 if (typeof vB_QuickReply != 'undefined') 1445 { 1446 // init quick reply button 1447 qr_init_buttons(obj); 1448 } 1449} 1450 1451// ############################################################################# 1452// Main vBulletin Javascript Initialization 1453 1454/** 1455* This function runs (almost) at the end of script loading on most vBulletin pages 1456* 1457* It sets up things like image alt->title tags, turns on the popup menu system etc. 1458* 1459* @return boolean 1460*/ 1461function vBulletin_init() 1462{ 1463 // don't bother doing any exciting stuff for WebTV 1464 if (is_webtv) 1465 { 1466 return false; 1467 } 1468 1469 // set 'title' tags for image elements 1470 var imgs = fetch_tags(document, 'img'); 1471 for (var i = 0; i < imgs.length; i++) 1472 { 1473 if (!imgs[i].title && imgs[i].alt != '') 1474 { 1475 imgs[i].title = imgs[i].alt; 1476 } 1477 } 1478 1479 // finalize popup menus 1480 if (typeof vBmenu == 'object') 1481 { 1482 // close all menus on document click 1483 if (window.attachEvent && !is_saf) 1484 { 1485 document.attachEvent('onclick', vbmenu_hide); 1486 window.attachEvent('onresize', vbmenu_hide); 1487 } 1488 else if (document.addEventListener && !is_saf) 1489 { 1490 document.addEventListener('click', vbmenu_hide, false); 1491 window.addEventListener('resize', vbmenu_hide, false); 1492 } 1493 else 1494 { 1495 window.onclick = vbmenu_hide; 1496 window.onresize = vbmenu_hide; 1497 } 1498 1499 // add popups to pagenav elements 1500 var pagenavs = fetch_tags(document, 'td'); 1501 for (var n = 0; n < pagenavs.length; n++) 1502 { 1503 if (pagenavs[n].hasChildNodes() && pagenavs[n].firstChild.name && pagenavs[n].firstChild.name.indexOf('PageNav') != -1) 1504 { 1505 var addr = pagenavs[n].title; 1506 pagenavs[n].title = ''; 1507 pagenavs[n].innerHTML = ''; 1508 pagenavs[n].id = 'pagenav.' + n; 1509 var pn = vBmenu.register(pagenavs[n].id); 1510 if (is_saf) 1511 { 1512 pn.controlobj._onclick = pn.controlobj.onclick; 1513 pn.controlobj.onclick = vBpagenav.prototype.controlobj_onclick; 1514 } 1515 } 1516 } 1517 1518 // process the pagenavs popup form 1519 if (typeof addr != 'undefined') 1520 { 1521 fetch_object('pagenav_form').addr = addr; 1522 fetch_object('pagenav_form').gotopage = vBpagenav.prototype.form_gotopage; 1523 fetch_object('pagenav_ibtn').onclick = vBpagenav.prototype.ibtn_onclick; 1524 fetch_object('pagenav_itxt').onkeypress = vBpagenav.prototype.itxt_onkeypress; 1525 } 1526 1527 // activate the menu system 1528 vBmenu.activate(true); 1529 } 1530 1531 return true; 1532} 1533 1534/*======================================================================*\ 1535|| #################################################################### 1536|| # Downloaded: 13:29, Wed Mar 22nd 2006 1537|| # CVS: $RCSfile: vbulletin_global.js,v $ - $Revision: 1.151 $ 1538|| #################################################################### 1539\*======================================================================*/
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.