PageRenderTime 59ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/edittools/ubb/images/vbulletin_global.js

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