annotate forum/Themes/Vamp/scripts/script.js @ 76:e3e11437ecea website

Add forum code
author Chris Cannam
date Sun, 07 Jul 2013 11:25:48 +0200
parents
children
rev   line source
Chris@76 1 var smf_formSubmitted = false;
Chris@76 2 var lastKeepAliveCheck = new Date().getTime();
Chris@76 3 var smf_editorArray = new Array();
Chris@76 4
Chris@76 5 // Some very basic browser detection - from Mozilla's sniffer page.
Chris@76 6 var ua = navigator.userAgent.toLowerCase();
Chris@76 7
Chris@76 8 var is_opera = ua.indexOf('opera') != -1;
Chris@76 9 var is_opera5 = ua.indexOf('opera/5') != -1 || ua.indexOf('opera 5') != -1;
Chris@76 10 var is_opera6 = ua.indexOf('opera/6') != -1 || ua.indexOf('opera 6') != -1;
Chris@76 11 var is_opera7 = ua.indexOf('opera/7') != -1 || ua.indexOf('opera 7') != -1;
Chris@76 12 var is_opera8 = ua.indexOf('opera/8') != -1 || ua.indexOf('opera 8') != -1;
Chris@76 13 var is_opera9 = ua.indexOf('opera/9') != -1 || ua.indexOf('opera 9') != -1;
Chris@76 14 var is_opera95 = ua.indexOf('opera/9.5') != -1 || ua.indexOf('opera 9.5') != -1;
Chris@76 15 var is_opera96 = ua.indexOf('opera/9.6') != -1 || ua.indexOf('opera 9.6') != -1;
Chris@76 16 var is_opera10 = (ua.indexOf('opera/9.8') != -1 || ua.indexOf('opera 9.8') != -1 || ua.indexOf('opera/10.') != -1 || ua.indexOf('opera 10.') != -1) || ua.indexOf('version/10.') != -1;
Chris@76 17 var is_opera95up = is_opera95 || is_opera96 || is_opera10;
Chris@76 18
Chris@76 19 var is_ff = (ua.indexOf('firefox') != -1 || ua.indexOf('iceweasel') != -1 || ua.indexOf('icecat') != -1 || ua.indexOf('shiretoko') != -1 || ua.indexOf('minefield') != -1) && !is_opera;
Chris@76 20 var is_gecko = ua.indexOf('gecko') != -1 && !is_opera;
Chris@76 21
Chris@76 22 var is_chrome = ua.indexOf('chrome') != -1;
Chris@76 23 var is_safari = ua.indexOf('applewebkit') != -1 && !is_chrome;
Chris@76 24 var is_webkit = ua.indexOf('applewebkit') != -1;
Chris@76 25
Chris@76 26 var is_ie = ua.indexOf('msie') != -1 && !is_opera;
Chris@76 27 var is_ie4 = is_ie && ua.indexOf('msie 4') != -1;
Chris@76 28 var is_ie5 = is_ie && ua.indexOf('msie 5') != -1;
Chris@76 29 var is_ie50 = is_ie && ua.indexOf('msie 5.0') != -1;
Chris@76 30 var is_ie55 = is_ie && ua.indexOf('msie 5.5') != -1;
Chris@76 31 var is_ie5up = is_ie && !is_ie4;
Chris@76 32 var is_ie6 = is_ie && ua.indexOf('msie 6') != -1;
Chris@76 33 var is_ie6up = is_ie5up && !is_ie55 && !is_ie5;
Chris@76 34 var is_ie6down = is_ie6 || is_ie5 || is_ie4;
Chris@76 35 var is_ie7 = is_ie && ua.indexOf('msie 7') != -1;
Chris@76 36 var is_ie7up = is_ie6up && !is_ie6;
Chris@76 37 var is_ie7down = is_ie7 || is_ie6 || is_ie5 || is_ie4;
Chris@76 38
Chris@76 39 var is_ie8 = is_ie && ua.indexOf('msie 8') != -1;
Chris@76 40 var is_ie8up = is_ie8 && !is_ie7down;
Chris@76 41
Chris@76 42 var is_iphone = ua.indexOf('iphone') != -1 || ua.indexOf('ipod') != -1;
Chris@76 43 var is_android = ua.indexOf('android') != -1;
Chris@76 44
Chris@76 45 var ajax_indicator_ele = null;
Chris@76 46
Chris@76 47 // Define document.getElementById for Internet Explorer 4.
Chris@76 48 if (!('getElementById' in document) && 'all' in document)
Chris@76 49 document.getElementById = function (sId) {
Chris@76 50 return document.all[sId];
Chris@76 51 }
Chris@76 52
Chris@76 53 // Define XMLHttpRequest for IE 5 and above. (don't bother for IE 4 :/.... works in Opera 7.6 and Safari 1.2!)
Chris@76 54 else if (!('XMLHttpRequest' in window) && 'ActiveXObject' in window)
Chris@76 55 window.XMLHttpRequest = function () {
Chris@76 56 return new ActiveXObject(is_ie5 ? 'Microsoft.XMLHTTP' : 'MSXML2.XMLHTTP');
Chris@76 57 };
Chris@76 58
Chris@76 59 // Ensure the getElementsByTagName exists.
Chris@76 60 if (!'getElementsByTagName' in document && 'all' in document)
Chris@76 61 document.getElementsByTagName = function (sName) {
Chris@76 62 return document.all.tags[sName];
Chris@76 63 }
Chris@76 64
Chris@76 65 // Some older versions of Mozilla don't have this, for some reason.
Chris@76 66 if (!('forms' in document))
Chris@76 67 document.forms = document.getElementsByTagName('form');
Chris@76 68
Chris@76 69 // Load an XML document using XMLHttpRequest.
Chris@76 70 function getXMLDocument(sUrl, funcCallback)
Chris@76 71 {
Chris@76 72 if (!window.XMLHttpRequest)
Chris@76 73 return null;
Chris@76 74
Chris@76 75 var oMyDoc = new XMLHttpRequest();
Chris@76 76 var bAsync = typeof(funcCallback) != 'undefined';
Chris@76 77 var oCaller = this;
Chris@76 78 if (bAsync)
Chris@76 79 {
Chris@76 80 oMyDoc.onreadystatechange = function () {
Chris@76 81 if (oMyDoc.readyState != 4)
Chris@76 82 return;
Chris@76 83
Chris@76 84 if (oMyDoc.responseXML != null && oMyDoc.status == 200)
Chris@76 85 {
Chris@76 86 if (funcCallback.call)
Chris@76 87 {
Chris@76 88 funcCallback.call(oCaller, oMyDoc.responseXML);
Chris@76 89 }
Chris@76 90 // A primitive substitute for the call method to support IE 5.0.
Chris@76 91 else
Chris@76 92 {
Chris@76 93 oCaller.tmpMethod = funcCallback;
Chris@76 94 oCaller.tmpMethod(oMyDoc.responseXML);
Chris@76 95 delete oCaller.tmpMethod;
Chris@76 96 }
Chris@76 97 }
Chris@76 98 };
Chris@76 99 }
Chris@76 100 oMyDoc.open('GET', sUrl, bAsync);
Chris@76 101 oMyDoc.send(null);
Chris@76 102
Chris@76 103 return oMyDoc;
Chris@76 104 }
Chris@76 105
Chris@76 106 // Send a post form to the server using XMLHttpRequest.
Chris@76 107 function sendXMLDocument(sUrl, sContent, funcCallback)
Chris@76 108 {
Chris@76 109 if (!window.XMLHttpRequest)
Chris@76 110 return false;
Chris@76 111
Chris@76 112 var oSendDoc = new window.XMLHttpRequest();
Chris@76 113 var oCaller = this;
Chris@76 114 if (typeof(funcCallback) != 'undefined')
Chris@76 115 {
Chris@76 116 oSendDoc.onreadystatechange = function () {
Chris@76 117 if (oSendDoc.readyState != 4)
Chris@76 118 return;
Chris@76 119
Chris@76 120 if (oSendDoc.responseXML != null && oSendDoc.status == 200)
Chris@76 121 funcCallback.call(oCaller, oSendDoc.responseXML);
Chris@76 122 else
Chris@76 123 funcCallback.call(oCaller, false);
Chris@76 124 };
Chris@76 125 }
Chris@76 126 oSendDoc.open('POST', sUrl, true);
Chris@76 127 if ('setRequestHeader' in oSendDoc)
Chris@76 128 oSendDoc.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
Chris@76 129 oSendDoc.send(sContent);
Chris@76 130
Chris@76 131 return true;
Chris@76 132 }
Chris@76 133
Chris@76 134 // A property we'll be needing for php_to8bit.
Chris@76 135 String.prototype.oCharsetConversion = {
Chris@76 136 from: '',
Chris@76 137 to: ''
Chris@76 138 };
Chris@76 139
Chris@76 140 // Convert a string to an 8 bit representation (like in PHP).
Chris@76 141 String.prototype.php_to8bit = function ()
Chris@76 142 {
Chris@76 143 if (smf_charset == 'UTF-8')
Chris@76 144 {
Chris@76 145 var n, sReturn = '';
Chris@76 146
Chris@76 147 for (var i = 0, iTextLen = this.length; i < iTextLen; i++)
Chris@76 148 {
Chris@76 149 n = this.charCodeAt(i);
Chris@76 150 if (n < 128)
Chris@76 151 sReturn += String.fromCharCode(n)
Chris@76 152 else if (n < 2048)
Chris@76 153 sReturn += String.fromCharCode(192 | n >> 6) + String.fromCharCode(128 | n & 63);
Chris@76 154 else if (n < 65536)
Chris@76 155 sReturn += String.fromCharCode(224 | n >> 12) + String.fromCharCode(128 | n >> 6 & 63) + String.fromCharCode(128 | n & 63);
Chris@76 156 else
Chris@76 157 sReturn += String.fromCharCode(240 | n >> 18) + String.fromCharCode(128 | n >> 12 & 63) + String.fromCharCode(128 | n >> 6 & 63) + String.fromCharCode(128 | n & 63);
Chris@76 158 }
Chris@76 159
Chris@76 160 return sReturn;
Chris@76 161 }
Chris@76 162
Chris@76 163 else if (this.oCharsetConversion.from.length == 0)
Chris@76 164 {
Chris@76 165 switch (smf_charset)
Chris@76 166 {
Chris@76 167 case 'ISO-8859-1':
Chris@76 168 this.oCharsetConversion = {
Chris@76 169 from: '\xa0-\xff',
Chris@76 170 to: '\xa0-\xff'
Chris@76 171 };
Chris@76 172 break;
Chris@76 173
Chris@76 174 case 'ISO-8859-2':
Chris@76 175 this.oCharsetConversion = {
Chris@76 176 from: '\xa0\u0104\u02d8\u0141\xa4\u013d\u015a\xa7\xa8\u0160\u015e\u0164\u0179\xad\u017d\u017b\xb0\u0105\u02db\u0142\xb4\u013e\u015b\u02c7\xb8\u0161\u015f\u0165\u017a\u02dd\u017e\u017c\u0154\xc1\xc2\u0102\xc4\u0139\u0106\xc7\u010c\xc9\u0118\xcb\u011a\xcd\xce\u010e\u0110\u0143\u0147\xd3\xd4\u0150\xd6\xd7\u0158\u016e\xda\u0170\xdc\xdd\u0162\xdf\u0155\xe1\xe2\u0103\xe4\u013a\u0107\xe7\u010d\xe9\u0119\xeb\u011b\xed\xee\u010f\u0111\u0144\u0148\xf3\xf4\u0151\xf6\xf7\u0159\u016f\xfa\u0171\xfc\xfd\u0163\u02d9',
Chris@76 177 to: '\xa0-\xff'
Chris@76 178 };
Chris@76 179 break;
Chris@76 180
Chris@76 181 case 'ISO-8859-5':
Chris@76 182 this.oCharsetConversion = {
Chris@76 183 from: '\xa0\u0401-\u040c\xad\u040e-\u044f\u2116\u0451-\u045c\xa7\u045e\u045f',
Chris@76 184 to: '\xa0-\xff'
Chris@76 185 };
Chris@76 186 break;
Chris@76 187
Chris@76 188 case 'ISO-8859-9':
Chris@76 189 this.oCharsetConversion = {
Chris@76 190 from: '\xa0-\xcf\u011e\xd1-\xdc\u0130\u015e\xdf-\xef\u011f\xf1-\xfc\u0131\u015f\xff',
Chris@76 191 to: '\xa0-\xff'
Chris@76 192 };
Chris@76 193 break;
Chris@76 194
Chris@76 195 case 'ISO-8859-15':
Chris@76 196 this.oCharsetConversion = {
Chris@76 197 from: '\xa0-\xa3\u20ac\xa5\u0160\xa7\u0161\xa9-\xb3\u017d\xb5-\xb7\u017e\xb9-\xbb\u0152\u0153\u0178\xbf-\xff',
Chris@76 198 to: '\xa0-\xff'
Chris@76 199 };
Chris@76 200 break;
Chris@76 201
Chris@76 202 case 'tis-620':
Chris@76 203 this.oCharsetConversion = {
Chris@76 204 from: '\u20ac\u2026\u2018\u2019\u201c\u201d\u2022\u2013\u2014\xa0\u0e01-\u0e3a\u0e3f-\u0e5b',
Chris@76 205 to: '\x80\x85\x91-\x97\xa0-\xda\xdf-\xfb'
Chris@76 206 };
Chris@76 207 break;
Chris@76 208
Chris@76 209 case 'windows-1251':
Chris@76 210 this.oCharsetConversion = {
Chris@76 211 from: '\u0402\u0403\u201a\u0453\u201e\u2026\u2020\u2021\u20ac\u2030\u0409\u2039\u040a\u040c\u040b\u040f\u0452\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u2122\u0459\u203a\u045a\u045c\u045b\u045f\xa0\u040e\u045e\u0408\xa4\u0490\xa6\xa7\u0401\xa9\u0404\xab-\xae\u0407\xb0\xb1\u0406\u0456\u0491\xb5-\xb7\u0451\u2116\u0454\xbb\u0458\u0405\u0455\u0457\u0410-\u044f',
Chris@76 212 to: '\x80-\x97\x99-\xff'
Chris@76 213 };
Chris@76 214 break;
Chris@76 215
Chris@76 216 case 'windows-1253':
Chris@76 217 this.oCharsetConversion = {
Chris@76 218 from: '\u20ac\u201a\u0192\u201e\u2026\u2020\u2021\u2030\u2039\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u2122\u203a\xa0\u0385\u0386\xa3-\xa9\xab-\xae\u2015\xb0-\xb3\u0384\xb5-\xb7\u0388-\u038a\xbb\u038c\xbd\u038e-\u03a1\u03a3-\u03ce',
Chris@76 219 to: '\x80\x82-\x87\x89\x8b\x91-\x97\x99\x9b\xa0-\xa9\xab-\xd1\xd3-\xfe'
Chris@76 220 };
Chris@76 221 break;
Chris@76 222
Chris@76 223 case 'windows-1255':
Chris@76 224 this.oCharsetConversion = {
Chris@76 225 from: '\u20ac\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\u2039\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u02dc\u2122\u203a\xa0-\xa3\u20aa\xa5-\xa9\xd7\xab-\xb9\xf7\xbb-\xbf\u05b0-\u05b9\u05bb-\u05c3\u05f0-\u05f4\u05d0-\u05ea\u200e\u200f',
Chris@76 226 to: '\x80\x82-\x89\x8b\x91-\x99\x9b\xa0-\xc9\xcb-\xd8\xe0-\xfa\xfd\xfe'
Chris@76 227 };
Chris@76 228 break;
Chris@76 229
Chris@76 230 case 'windows-1256':
Chris@76 231 this.oCharsetConversion = {
Chris@76 232 from: '\u20ac\u067e\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\u0679\u2039\u0152\u0686\u0698\u0688\u06af\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u06a9\u2122\u0691\u203a\u0153\u200c\u200d\u06ba\xa0\u060c\xa2-\xa9\u06be\xab-\xb9\u061b\xbb-\xbe\u061f\u06c1\u0621-\u0636\xd7\u0637-\u063a\u0640-\u0643\xe0\u0644\xe2\u0645-\u0648\xe7-\xeb\u0649\u064a\xee\xef\u064b-\u064e\xf4\u064f\u0650\xf7\u0651\xf9\u0652\xfb\xfc\u200e\u200f\u06d2',
Chris@76 233 to: '\x80-\xff'
Chris@76 234 };
Chris@76 235 break;
Chris@76 236
Chris@76 237 default:
Chris@76 238 this.oCharsetConversion = {
Chris@76 239 from: '',
Chris@76 240 to: ''
Chris@76 241 };
Chris@76 242 break;
Chris@76 243 }
Chris@76 244 var funcExpandString = function (sSearch) {
Chris@76 245 var sInsert = '';
Chris@76 246 for (var i = sSearch.charCodeAt(0), n = sSearch.charCodeAt(2); i <= n; i++)
Chris@76 247 sInsert += String.fromCharCode(i);
Chris@76 248 return sInsert;
Chris@76 249 };
Chris@76 250 this.oCharsetConversion.from = this.oCharsetConversion.from.replace(/.\-./g, funcExpandString);
Chris@76 251 this.oCharsetConversion.to = this.oCharsetConversion.to.replace(/.\-./g, funcExpandString);
Chris@76 252 }
Chris@76 253
Chris@76 254 var sReturn = '', iOffsetFrom = 0;
Chris@76 255 for (var i = 0, n = this.length; i < n; i++)
Chris@76 256 {
Chris@76 257 iOffsetFrom = this.oCharsetConversion.from.indexOf(this.charAt(i));
Chris@76 258 sReturn += iOffsetFrom > -1 ? this.oCharsetConversion.to.charAt(iOffsetFrom) : (this.charCodeAt(i) > 127 ? '&#' + this.charCodeAt(i) + ';' : this.charAt(i));
Chris@76 259 }
Chris@76 260
Chris@76 261 return sReturn
Chris@76 262 }
Chris@76 263
Chris@76 264 // Character-level replacement function.
Chris@76 265 String.prototype.php_strtr = function (sFrom, sTo)
Chris@76 266 {
Chris@76 267 return this.replace(new RegExp('[' + sFrom + ']', 'g'), function (sMatch) {
Chris@76 268 return sTo.charAt(sFrom.indexOf(sMatch));
Chris@76 269 });
Chris@76 270 }
Chris@76 271
Chris@76 272 // Simulate PHP's strtolower (in SOME cases PHP uses ISO-8859-1 case folding).
Chris@76 273 String.prototype.php_strtolower = function ()
Chris@76 274 {
Chris@76 275 return typeof(smf_iso_case_folding) == 'boolean' && smf_iso_case_folding == true ? this.php_strtr(
Chris@76 276 'ABCDEFGHIJKLMNOPQRSTUVWXYZ\x8a\x8c\x8e\x9f\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde',
Chris@76 277 'abcdefghijklmnopqrstuvwxyz\x9a\x9c\x9e\xff\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe'
Chris@76 278 ) : this.php_strtr('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');
Chris@76 279 }
Chris@76 280
Chris@76 281 String.prototype.php_urlencode = function()
Chris@76 282 {
Chris@76 283 return escape(this).replace(/\+/g, '%2b').replace('*', '%2a').replace('/', '%2f').replace('@', '%40');
Chris@76 284 }
Chris@76 285
Chris@76 286 String.prototype.php_htmlspecialchars = function()
Chris@76 287 {
Chris@76 288 return this.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
Chris@76 289 }
Chris@76 290
Chris@76 291 String.prototype.php_unhtmlspecialchars = function()
Chris@76 292 {
Chris@76 293 return this.replace(/&quot;/g, '"').replace(/&gt;/g, '>').replace(/&lt;/g, '<').replace(/&amp;/g, '&');
Chris@76 294 }
Chris@76 295
Chris@76 296 String.prototype.php_addslashes = function()
Chris@76 297 {
Chris@76 298 return this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'');
Chris@76 299 }
Chris@76 300
Chris@76 301 String.prototype._replaceEntities = function(sInput, sDummy, sNum)
Chris@76 302 {
Chris@76 303 return String.fromCharCode(parseInt(sNum));
Chris@76 304 }
Chris@76 305
Chris@76 306 String.prototype.removeEntities = function()
Chris@76 307 {
Chris@76 308 return this.replace(/&(amp;)?#(\d+);/g, this._replaceEntities);
Chris@76 309 }
Chris@76 310
Chris@76 311 String.prototype.easyReplace = function (oReplacements)
Chris@76 312 {
Chris@76 313 var sResult = this;
Chris@76 314 for (var sSearch in oReplacements)
Chris@76 315 sResult = sResult.replace(new RegExp('%' + sSearch + '%', 'g'), oReplacements[sSearch]);
Chris@76 316
Chris@76 317 return sResult;
Chris@76 318 }
Chris@76 319
Chris@76 320
Chris@76 321 // Open a new window.
Chris@76 322 function reqWin(desktopURL, alternateWidth, alternateHeight, noScrollbars)
Chris@76 323 {
Chris@76 324 if ((alternateWidth && self.screen.availWidth * 0.8 < alternateWidth) || (alternateHeight && self.screen.availHeight * 0.8 < alternateHeight))
Chris@76 325 {
Chris@76 326 noScrollbars = false;
Chris@76 327 alternateWidth = Math.min(alternateWidth, self.screen.availWidth * 0.8);
Chris@76 328 alternateHeight = Math.min(alternateHeight, self.screen.availHeight * 0.8);
Chris@76 329 }
Chris@76 330 else
Chris@76 331 noScrollbars = typeof(noScrollbars) == 'boolean' && noScrollbars == true;
Chris@76 332
Chris@76 333 window.open(desktopURL, 'requested_popup', 'toolbar=no,location=no,status=no,menubar=no,scrollbars=' + (noScrollbars ? 'no' : 'yes') + ',width=' + (alternateWidth ? alternateWidth : 480) + ',height=' + (alternateHeight ? alternateHeight : 220) + ',resizable=no');
Chris@76 334
Chris@76 335 // Return false so the click won't follow the link ;).
Chris@76 336 return false;
Chris@76 337 }
Chris@76 338
Chris@76 339 // Remember the current position.
Chris@76 340 function storeCaret(oTextHandle)
Chris@76 341 {
Chris@76 342 // Only bother if it will be useful.
Chris@76 343 if ('createTextRange' in oTextHandle)
Chris@76 344 oTextHandle.caretPos = document.selection.createRange().duplicate();
Chris@76 345 }
Chris@76 346
Chris@76 347 // Replaces the currently selected text with the passed text.
Chris@76 348 function replaceText(text, oTextHandle)
Chris@76 349 {
Chris@76 350 // Attempt to create a text range (IE).
Chris@76 351 if ('caretPos' in oTextHandle && 'createTextRange' in oTextHandle)
Chris@76 352 {
Chris@76 353 var caretPos = oTextHandle.caretPos;
Chris@76 354
Chris@76 355 caretPos.text = caretPos.text.charAt(caretPos.text.length - 1) == ' ' ? text + ' ' : text;
Chris@76 356 caretPos.select();
Chris@76 357 }
Chris@76 358 // Mozilla text range replace.
Chris@76 359 else if ('selectionStart' in oTextHandle)
Chris@76 360 {
Chris@76 361 var begin = oTextHandle.value.substr(0, oTextHandle.selectionStart);
Chris@76 362 var end = oTextHandle.value.substr(oTextHandle.selectionEnd);
Chris@76 363 var scrollPos = oTextHandle.scrollTop;
Chris@76 364
Chris@76 365 oTextHandle.value = begin + text + end;
Chris@76 366
Chris@76 367 if (oTextHandle.setSelectionRange)
Chris@76 368 {
Chris@76 369 oTextHandle.focus();
Chris@76 370 var goForward = is_opera ? text.match(/\n/g).length : 0;
Chris@76 371 oTextHandle.setSelectionRange(begin.length + text.length + goForward, begin.length + text.length + goForward);
Chris@76 372 }
Chris@76 373 oTextHandle.scrollTop = scrollPos;
Chris@76 374 }
Chris@76 375 // Just put it on the end.
Chris@76 376 else
Chris@76 377 {
Chris@76 378 oTextHandle.value += text;
Chris@76 379 oTextHandle.focus(oTextHandle.value.length - 1);
Chris@76 380 }
Chris@76 381 }
Chris@76 382
Chris@76 383 // Surrounds the selected text with text1 and text2.
Chris@76 384 function surroundText(text1, text2, oTextHandle)
Chris@76 385 {
Chris@76 386 // Can a text range be created?
Chris@76 387 if ('caretPos' in oTextHandle && 'createTextRange' in oTextHandle)
Chris@76 388 {
Chris@76 389 var caretPos = oTextHandle.caretPos, temp_length = caretPos.text.length;
Chris@76 390
Chris@76 391 caretPos.text = caretPos.text.charAt(caretPos.text.length - 1) == ' ' ? text1 + caretPos.text + text2 + ' ' : text1 + caretPos.text + text2;
Chris@76 392
Chris@76 393 if (temp_length == 0)
Chris@76 394 {
Chris@76 395 caretPos.moveStart('character', -text2.length);
Chris@76 396 caretPos.moveEnd('character', -text2.length);
Chris@76 397 caretPos.select();
Chris@76 398 }
Chris@76 399 else
Chris@76 400 oTextHandle.focus(caretPos);
Chris@76 401 }
Chris@76 402 // Mozilla text range wrap.
Chris@76 403 else if ('selectionStart' in oTextHandle)
Chris@76 404 {
Chris@76 405 var begin = oTextHandle.value.substr(0, oTextHandle.selectionStart);
Chris@76 406 var selection = oTextHandle.value.substr(oTextHandle.selectionStart, oTextHandle.selectionEnd - oTextHandle.selectionStart);
Chris@76 407 var end = oTextHandle.value.substr(oTextHandle.selectionEnd);
Chris@76 408 var newCursorPos = oTextHandle.selectionStart;
Chris@76 409 var scrollPos = oTextHandle.scrollTop;
Chris@76 410
Chris@76 411 oTextHandle.value = begin + text1 + selection + text2 + end;
Chris@76 412
Chris@76 413 if (oTextHandle.setSelectionRange)
Chris@76 414 {
Chris@76 415 var goForward = is_opera ? text1.match(/\n/g).length : 0, goForwardAll = is_opera ? (text1 + text2).match(/\n/g).length : 0;
Chris@76 416 if (selection.length == 0)
Chris@76 417 oTextHandle.setSelectionRange(newCursorPos + text1.length + goForward, newCursorPos + text1.length + goForward);
Chris@76 418 else
Chris@76 419 oTextHandle.setSelectionRange(newCursorPos, newCursorPos + text1.length + selection.length + text2.length + goForwardAll);
Chris@76 420 oTextHandle.focus();
Chris@76 421 }
Chris@76 422 oTextHandle.scrollTop = scrollPos;
Chris@76 423 }
Chris@76 424 // Just put them on the end, then.
Chris@76 425 else
Chris@76 426 {
Chris@76 427 oTextHandle.value += text1 + text2;
Chris@76 428 oTextHandle.focus(oTextHandle.value.length - 1);
Chris@76 429 }
Chris@76 430 }
Chris@76 431
Chris@76 432 // Checks if the passed input's value is nothing.
Chris@76 433 function isEmptyText(theField)
Chris@76 434 {
Chris@76 435 // Copy the value so changes can be made..
Chris@76 436 var theValue = theField.value;
Chris@76 437
Chris@76 438 // Strip whitespace off the left side.
Chris@76 439 while (theValue.length > 0 && (theValue.charAt(0) == ' ' || theValue.charAt(0) == '\t'))
Chris@76 440 theValue = theValue.substring(1, theValue.length);
Chris@76 441 // Strip whitespace off the right side.
Chris@76 442 while (theValue.length > 0 && (theValue.charAt(theValue.length - 1) == ' ' || theValue.charAt(theValue.length - 1) == '\t'))
Chris@76 443 theValue = theValue.substring(0, theValue.length - 1);
Chris@76 444
Chris@76 445 if (theValue == '')
Chris@76 446 return true;
Chris@76 447 else
Chris@76 448 return false;
Chris@76 449 }
Chris@76 450
Chris@76 451 // Only allow form submission ONCE.
Chris@76 452 function submitonce(theform)
Chris@76 453 {
Chris@76 454 smf_formSubmitted = true;
Chris@76 455
Chris@76 456 // If there are any editors warn them submit is coming!
Chris@76 457 for (var i = 0; i < smf_editorArray.length; i++)
Chris@76 458 smf_editorArray[i].doSubmit();
Chris@76 459 }
Chris@76 460 function submitThisOnce(oControl)
Chris@76 461 {
Chris@76 462 // Hateful, hateful fix for Safari 1.3 beta.
Chris@76 463 if (is_safari)
Chris@76 464 return !smf_formSubmitted;
Chris@76 465
Chris@76 466 // oControl might also be a form.
Chris@76 467 var oForm = 'form' in oControl ? oControl.form : oControl;
Chris@76 468
Chris@76 469 var aTextareas = oForm.getElementsByTagName('textarea');
Chris@76 470 for (var i = 0, n = aTextareas.length; i < n; i++)
Chris@76 471 aTextareas[i].readOnly = true;
Chris@76 472
Chris@76 473 return !smf_formSubmitted;
Chris@76 474 }
Chris@76 475
Chris@76 476 // Deprecated, as innerHTML is supported everywhere.
Chris@76 477 function setInnerHTML(oElement, sToValue)
Chris@76 478 {
Chris@76 479 oElement.innerHTML = sToValue;
Chris@76 480 }
Chris@76 481
Chris@76 482 function getInnerHTML(oElement)
Chris@76 483 {
Chris@76 484 return oElement.innerHTML;
Chris@76 485 }
Chris@76 486
Chris@76 487 // Set the "outer" HTML of an element.
Chris@76 488 function setOuterHTML(oElement, sToValue)
Chris@76 489 {
Chris@76 490 if ('outerHTML' in oElement)
Chris@76 491 oElement.outerHTML = sToValue;
Chris@76 492 else
Chris@76 493 {
Chris@76 494 var range = document.createRange();
Chris@76 495 range.setStartBefore(oElement);
Chris@76 496 oElement.parentNode.replaceChild(range.createContextualFragment(sToValue), oElement);
Chris@76 497 }
Chris@76 498 }
Chris@76 499
Chris@76 500 // Checks for variable in theArray.
Chris@76 501 function in_array(variable, theArray)
Chris@76 502 {
Chris@76 503 for (var i in theArray)
Chris@76 504 if (theArray[i] == variable)
Chris@76 505 return true;
Chris@76 506
Chris@76 507 return false;
Chris@76 508 }
Chris@76 509
Chris@76 510 // Checks for variable in theArray.
Chris@76 511 function array_search(variable, theArray)
Chris@76 512 {
Chris@76 513 for (var i in theArray)
Chris@76 514 if (theArray[i] == variable)
Chris@76 515 return i;
Chris@76 516
Chris@76 517 return null;
Chris@76 518 }
Chris@76 519
Chris@76 520 // Find a specific radio button in its group and select it.
Chris@76 521 function selectRadioByName(oRadioGroup, sName)
Chris@76 522 {
Chris@76 523 if (!('length' in oRadioGroup))
Chris@76 524 return oRadioGroup.checked = true;
Chris@76 525
Chris@76 526 for (var i = 0, n = oRadioGroup.length; i < n; i++)
Chris@76 527 if (oRadioGroup[i].value == sName)
Chris@76 528 return oRadioGroup[i].checked = true;
Chris@76 529
Chris@76 530 return false;
Chris@76 531 }
Chris@76 532
Chris@76 533 // Invert all checkboxes at once by clicking a single checkbox.
Chris@76 534 function invertAll(oInvertCheckbox, oForm, sMask, bIgnoreDisabled)
Chris@76 535 {
Chris@76 536 for (var i = 0; i < oForm.length; i++)
Chris@76 537 {
Chris@76 538 if (!('name' in oForm[i]) || (typeof(sMask) == 'string' && oForm[i].name.substr(0, sMask.length) != sMask && oForm[i].id.substr(0, sMask.length) != sMask))
Chris@76 539 continue;
Chris@76 540
Chris@76 541 if (!oForm[i].disabled || (typeof(bIgnoreDisabled) == 'boolean' && bIgnoreDisabled))
Chris@76 542 oForm[i].checked = oInvertCheckbox.checked;
Chris@76 543 }
Chris@76 544 }
Chris@76 545
Chris@76 546 // Keep the session alive - always!
Chris@76 547 var lastKeepAliveCheck = new Date().getTime();
Chris@76 548 function smf_sessionKeepAlive()
Chris@76 549 {
Chris@76 550 var curTime = new Date().getTime();
Chris@76 551
Chris@76 552 // Prevent a Firefox bug from hammering the server.
Chris@76 553 if (smf_scripturl && curTime - lastKeepAliveCheck > 900000)
Chris@76 554 {
Chris@76 555 var tempImage = new Image();
Chris@76 556 tempImage.src = smf_prepareScriptUrl(smf_scripturl) + 'action=keepalive;time=' + curTime;
Chris@76 557 lastKeepAliveCheck = curTime;
Chris@76 558 }
Chris@76 559
Chris@76 560 window.setTimeout('smf_sessionKeepAlive();', 1200000);
Chris@76 561 }
Chris@76 562 window.setTimeout('smf_sessionKeepAlive();', 1200000);
Chris@76 563
Chris@76 564 // Set a theme option through javascript.
Chris@76 565 function smf_setThemeOption(option, value, theme, cur_session_id, cur_session_var, additional_vars)
Chris@76 566 {
Chris@76 567 // Compatibility.
Chris@76 568 if (cur_session_id == null)
Chris@76 569 cur_session_id = smf_session_id;
Chris@76 570 if (typeof(cur_session_var) == 'undefined')
Chris@76 571 cur_session_var = 'sesc';
Chris@76 572
Chris@76 573 if (additional_vars == null)
Chris@76 574 additional_vars = '';
Chris@76 575
Chris@76 576 var tempImage = new Image();
Chris@76 577 tempImage.src = smf_prepareScriptUrl(smf_scripturl) + 'action=jsoption;var=' + option + ';val=' + value + ';' + cur_session_var + '=' + cur_session_id + additional_vars + (theme == null ? '' : '&th=' + theme) + ';time=' + (new Date().getTime());
Chris@76 578 }
Chris@76 579
Chris@76 580 function smf_avatarResize()
Chris@76 581 {
Chris@76 582 var possibleAvatars = document.getElementsByTagName('img');
Chris@76 583
Chris@76 584 for (var i = 0; i < possibleAvatars.length; i++)
Chris@76 585 {
Chris@76 586 var tempAvatars = []; j = 0;
Chris@76 587 if (possibleAvatars[i].className != 'avatar')
Chris@76 588 continue;
Chris@76 589
Chris@76 590 // Image.prototype.avatar = possibleAvatars[i];
Chris@76 591 tempAvatars[j] = new Image();
Chris@76 592 tempAvatars[j].avatar = possibleAvatars[i];
Chris@76 593
Chris@76 594 tempAvatars[j].onload = function()
Chris@76 595 {
Chris@76 596 this.avatar.width = this.width;
Chris@76 597 this.avatar.height = this.height;
Chris@76 598 if (smf_avatarMaxWidth != 0 && this.width > smf_avatarMaxWidth)
Chris@76 599 {
Chris@76 600 this.avatar.height = (smf_avatarMaxWidth * this.height) / this.width;
Chris@76 601 this.avatar.width = smf_avatarMaxWidth;
Chris@76 602 }
Chris@76 603 if (smf_avatarMaxHeight != 0 && this.avatar.height > smf_avatarMaxHeight)
Chris@76 604 {
Chris@76 605 this.avatar.width = (smf_avatarMaxHeight * this.avatar.width) / this.avatar.height;
Chris@76 606 this.avatar.height = smf_avatarMaxHeight;
Chris@76 607 }
Chris@76 608 }
Chris@76 609 tempAvatars[j].src = possibleAvatars[i].src;
Chris@76 610 j++;
Chris@76 611 }
Chris@76 612
Chris@76 613 if (typeof(window_oldAvatarOnload) != 'undefined' && window_oldAvatarOnload)
Chris@76 614 {
Chris@76 615 window_oldAvatarOnload();
Chris@76 616 window_oldAvatarOnload = null;
Chris@76 617 }
Chris@76 618 }
Chris@76 619
Chris@76 620
Chris@76 621 function hashLoginPassword(doForm, cur_session_id)
Chris@76 622 {
Chris@76 623 // Compatibility.
Chris@76 624 if (cur_session_id == null)
Chris@76 625 cur_session_id = smf_session_id;
Chris@76 626
Chris@76 627 if (typeof(hex_sha1) == 'undefined')
Chris@76 628 return;
Chris@76 629 // Are they using an email address?
Chris@76 630 if (doForm.user.value.indexOf('@') != -1)
Chris@76 631 return;
Chris@76 632
Chris@76 633 // Unless the browser is Opera, the password will not save properly.
Chris@76 634 if (!('opera' in window))
Chris@76 635 doForm.passwrd.autocomplete = 'off';
Chris@76 636
Chris@76 637 doForm.hash_passwrd.value = hex_sha1(hex_sha1(doForm.user.value.php_to8bit().php_strtolower() + doForm.passwrd.value.php_to8bit()) + cur_session_id);
Chris@76 638
Chris@76 639 // It looks nicer to fill it with asterisks, but Firefox will try to save that.
Chris@76 640 if (is_ff != -1)
Chris@76 641 doForm.passwrd.value = '';
Chris@76 642 else
Chris@76 643 doForm.passwrd.value = doForm.passwrd.value.replace(/./g, '*');
Chris@76 644 }
Chris@76 645
Chris@76 646 function hashAdminPassword(doForm, username, cur_session_id)
Chris@76 647 {
Chris@76 648 // Compatibility.
Chris@76 649 if (cur_session_id == null)
Chris@76 650 cur_session_id = smf_session_id;
Chris@76 651
Chris@76 652 if (typeof(hex_sha1) == 'undefined')
Chris@76 653 return;
Chris@76 654
Chris@76 655 doForm.admin_hash_pass.value = hex_sha1(hex_sha1(username.php_to8bit().php_strtolower() + doForm.admin_pass.value.php_to8bit()) + cur_session_id);
Chris@76 656 doForm.admin_pass.value = doForm.admin_pass.value.replace(/./g, '*');
Chris@76 657 }
Chris@76 658
Chris@76 659 // Shows the page numbers by clicking the dots (in compact view).
Chris@76 660 function expandPages(spanNode, baseURL, firstPage, lastPage, perPage)
Chris@76 661 {
Chris@76 662 var replacement = '', i, oldLastPage = 0;
Chris@76 663 var perPageLimit = 50;
Chris@76 664
Chris@76 665 // The dots were bold, the page numbers are not (in most cases).
Chris@76 666 spanNode.style.fontWeight = 'normal';
Chris@76 667 spanNode.onclick = '';
Chris@76 668
Chris@76 669 // Prevent too many pages to be loaded at once.
Chris@76 670 if ((lastPage - firstPage) / perPage > perPageLimit)
Chris@76 671 {
Chris@76 672 oldLastPage = lastPage;
Chris@76 673 lastPage = firstPage + perPageLimit * perPage;
Chris@76 674 }
Chris@76 675
Chris@76 676 // Calculate the new pages.
Chris@76 677 for (i = firstPage; i < lastPage; i += perPage)
Chris@76 678 replacement += '<a class="navPages" href="' + baseURL.replace(/%1\$d/, i).replace(/%%/g, '%') + '">' + (1 + i / perPage) + '</a> ';
Chris@76 679
Chris@76 680 if (oldLastPage > 0)
Chris@76 681 replacement += '<span style="font-weight: bold; cursor: ' + (is_ie && !is_ie6up ? 'hand' : 'pointer') + ';" onclick="expandPages(this, \'' + baseURL + '\', ' + lastPage + ', ' + oldLastPage + ', ' + perPage + ');"> ... </span> ';
Chris@76 682
Chris@76 683 // Replace the dots by the new page links.
Chris@76 684 setInnerHTML(spanNode, replacement);
Chris@76 685 }
Chris@76 686
Chris@76 687 function smc_preCacheImage(sSrc)
Chris@76 688 {
Chris@76 689 if (!('smc_aCachedImages' in window))
Chris@76 690 window.smc_aCachedImages = [];
Chris@76 691
Chris@76 692 if (!in_array(sSrc, window.smc_aCachedImages))
Chris@76 693 {
Chris@76 694 var oImage = new Image();
Chris@76 695 oImage.src = sSrc;
Chris@76 696 }
Chris@76 697 }
Chris@76 698
Chris@76 699
Chris@76 700 // *** smc_Cookie class.
Chris@76 701 function smc_Cookie(oOptions)
Chris@76 702 {
Chris@76 703 this.opt = oOptions;
Chris@76 704 this.oCookies = {};
Chris@76 705 this.init();
Chris@76 706 }
Chris@76 707
Chris@76 708 smc_Cookie.prototype.init = function()
Chris@76 709 {
Chris@76 710 if ('cookie' in document && document.cookie != '')
Chris@76 711 {
Chris@76 712 var aCookieList = document.cookie.split(';');
Chris@76 713 for (var i = 0, n = aCookieList.length; i < n; i++)
Chris@76 714 {
Chris@76 715 var aNameValuePair = aCookieList[i].split('=');
Chris@76 716 this.oCookies[aNameValuePair[0].replace(/^\s+|\s+$/g, '')] = decodeURIComponent(aNameValuePair[1]);
Chris@76 717 }
Chris@76 718 }
Chris@76 719 }
Chris@76 720
Chris@76 721 smc_Cookie.prototype.get = function(sKey)
Chris@76 722 {
Chris@76 723 return sKey in this.oCookies ? this.oCookies[sKey] : null;
Chris@76 724 }
Chris@76 725
Chris@76 726 smc_Cookie.prototype.set = function(sKey, sValue)
Chris@76 727 {
Chris@76 728 document.cookie = sKey + '=' + encodeURIComponent(sValue);
Chris@76 729 }
Chris@76 730
Chris@76 731
Chris@76 732 // *** smc_Toggle class.
Chris@76 733 function smc_Toggle(oOptions)
Chris@76 734 {
Chris@76 735 this.opt = oOptions;
Chris@76 736 this.bCollapsed = false;
Chris@76 737 this.oCookie = null;
Chris@76 738 this.init();
Chris@76 739 }
Chris@76 740
Chris@76 741 smc_Toggle.prototype.init = function ()
Chris@76 742 {
Chris@76 743 // The master switch can disable this toggle fully.
Chris@76 744 if ('bToggleEnabled' in this.opt && !this.opt.bToggleEnabled)
Chris@76 745 return;
Chris@76 746
Chris@76 747 // If cookies are enabled and they were set, override the initial state.
Chris@76 748 if ('oCookieOptions' in this.opt && this.opt.oCookieOptions.bUseCookie)
Chris@76 749 {
Chris@76 750 // Initialize the cookie handler.
Chris@76 751 this.oCookie = new smc_Cookie({});
Chris@76 752
Chris@76 753 // Check if the cookie is set.
Chris@76 754 var cookieValue = this.oCookie.get(this.opt.oCookieOptions.sCookieName)
Chris@76 755 if (cookieValue != null)
Chris@76 756 this.opt.bCurrentlyCollapsed = cookieValue == '1';
Chris@76 757 }
Chris@76 758
Chris@76 759 // If the init state is set to be collapsed, collapse it.
Chris@76 760 if (this.opt.bCurrentlyCollapsed)
Chris@76 761 this.changeState(true, true);
Chris@76 762
Chris@76 763 // Initialize the images to be clickable.
Chris@76 764 if ('aSwapImages' in this.opt)
Chris@76 765 {
Chris@76 766 for (var i = 0, n = this.opt.aSwapImages.length; i < n; i++)
Chris@76 767 {
Chris@76 768 var oImage = document.getElementById(this.opt.aSwapImages[i].sId);
Chris@76 769 if (typeof(oImage) == 'object' && oImage != null)
Chris@76 770 {
Chris@76 771 // Display the image in case it was hidden.
Chris@76 772 if (oImage.style.display == 'none')
Chris@76 773 oImage.style.display = '';
Chris@76 774
Chris@76 775 oImage.instanceRef = this;
Chris@76 776 oImage.onclick = function () {
Chris@76 777 this.instanceRef.toggle();
Chris@76 778 this.blur();
Chris@76 779 }
Chris@76 780 oImage.style.cursor = 'pointer';
Chris@76 781
Chris@76 782 // Preload the collapsed image.
Chris@76 783 smc_preCacheImage(this.opt.aSwapImages[i].srcCollapsed);
Chris@76 784 }
Chris@76 785 }
Chris@76 786 }
Chris@76 787
Chris@76 788 // Initialize links.
Chris@76 789 if ('aSwapLinks' in this.opt)
Chris@76 790 {
Chris@76 791 for (var i = 0, n = this.opt.aSwapLinks.length; i < n; i++)
Chris@76 792 {
Chris@76 793 var oLink = document.getElementById(this.opt.aSwapLinks[i].sId);
Chris@76 794 if (typeof(oLink) == 'object' && oLink != null)
Chris@76 795 {
Chris@76 796 // Display the link in case it was hidden.
Chris@76 797 if (oLink.style.display == 'none')
Chris@76 798 oLink.style.display = '';
Chris@76 799
Chris@76 800 oLink.instanceRef = this;
Chris@76 801 oLink.onclick = function () {
Chris@76 802 this.instanceRef.toggle();
Chris@76 803 this.blur();
Chris@76 804 return false;
Chris@76 805 }
Chris@76 806 }
Chris@76 807 }
Chris@76 808 }
Chris@76 809 }
Chris@76 810
Chris@76 811 // Collapse or expand the section.
Chris@76 812 smc_Toggle.prototype.changeState = function(bCollapse, bInit)
Chris@76 813 {
Chris@76 814 // Default bInit to false.
Chris@76 815 bInit = typeof(bInit) == 'undefined' ? false : true;
Chris@76 816
Chris@76 817 // Handle custom function hook before collapse.
Chris@76 818 if (!bInit && bCollapse && 'funcOnBeforeCollapse' in this.opt)
Chris@76 819 {
Chris@76 820 this.tmpMethod = this.opt.funcOnBeforeCollapse;
Chris@76 821 this.tmpMethod();
Chris@76 822 delete this.tmpMethod;
Chris@76 823 }
Chris@76 824
Chris@76 825 // Handle custom function hook before expand.
Chris@76 826 else if (!bInit && !bCollapse && 'funcOnBeforeExpand' in this.opt)
Chris@76 827 {
Chris@76 828 this.tmpMethod = this.opt.funcOnBeforeExpand;
Chris@76 829 this.tmpMethod();
Chris@76 830 delete this.tmpMethod;
Chris@76 831 }
Chris@76 832
Chris@76 833 // Loop through all the images that need to be toggled.
Chris@76 834 if ('aSwapImages' in this.opt)
Chris@76 835 {
Chris@76 836 for (var i = 0, n = this.opt.aSwapImages.length; i < n; i++)
Chris@76 837 {
Chris@76 838 var oImage = document.getElementById(this.opt.aSwapImages[i].sId);
Chris@76 839 if (typeof(oImage) == 'object' && oImage != null)
Chris@76 840 {
Chris@76 841 // Only (re)load the image if it's changed.
Chris@76 842 var sTargetSource = bCollapse ? this.opt.aSwapImages[i].srcCollapsed : this.opt.aSwapImages[i].srcExpanded;
Chris@76 843 if (oImage.src != sTargetSource)
Chris@76 844 oImage.src = sTargetSource;
Chris@76 845
Chris@76 846 oImage.alt = oImage.title = bCollapse ? this.opt.aSwapImages[i].altCollapsed : this.opt.aSwapImages[i].altExpanded;
Chris@76 847 }
Chris@76 848 }
Chris@76 849 }
Chris@76 850
Chris@76 851 // Loop through all the links that need to be toggled.
Chris@76 852 if ('aSwapLinks' in this.opt)
Chris@76 853 {
Chris@76 854 for (var i = 0, n = this.opt.aSwapLinks.length; i < n; i++)
Chris@76 855 {
Chris@76 856 var oLink = document.getElementById(this.opt.aSwapLinks[i].sId);
Chris@76 857 if (typeof(oLink) == 'object' && oLink != null)
Chris@76 858 setInnerHTML(oLink, bCollapse ? this.opt.aSwapLinks[i].msgCollapsed : this.opt.aSwapLinks[i].msgExpanded);
Chris@76 859 }
Chris@76 860 }
Chris@76 861
Chris@76 862 // Now go through all the sections to be collapsed.
Chris@76 863 for (var i = 0, n = this.opt.aSwappableContainers.length; i < n; i++)
Chris@76 864 {
Chris@76 865 if (this.opt.aSwappableContainers[i] == null)
Chris@76 866 continue;
Chris@76 867
Chris@76 868 var oContainer = document.getElementById(this.opt.aSwappableContainers[i]);
Chris@76 869 if (typeof(oContainer) == 'object' && oContainer != null)
Chris@76 870 oContainer.style.display = bCollapse ? 'none' : '';
Chris@76 871 }
Chris@76 872
Chris@76 873 // Update the new state.
Chris@76 874 this.bCollapsed = bCollapse;
Chris@76 875
Chris@76 876 // Update the cookie, if desired.
Chris@76 877 if ('oCookieOptions' in this.opt && this.opt.oCookieOptions.bUseCookie)
Chris@76 878 this.oCookie.set(this.opt.oCookieOptions.sCookieName, this.bCollapsed ? '1' : '0');
Chris@76 879
Chris@76 880 if ('oThemeOptions' in this.opt && this.opt.oThemeOptions.bUseThemeSettings)
Chris@76 881 smf_setThemeOption(this.opt.oThemeOptions.sOptionName, this.bCollapsed ? '1' : '0', 'sThemeId' in this.opt.oThemeOptions ? this.opt.oThemeOptions.sThemeId : null, this.opt.oThemeOptions.sSessionId, this.opt.oThemeOptions.sSessionVar, 'sAdditionalVars' in this.opt.oThemeOptions ? this.opt.oThemeOptions.sAdditionalVars : null);
Chris@76 882 }
Chris@76 883
Chris@76 884 smc_Toggle.prototype.toggle = function()
Chris@76 885 {
Chris@76 886 // Change the state by reversing the current state.
Chris@76 887 this.changeState(!this.bCollapsed);
Chris@76 888 }
Chris@76 889
Chris@76 890
Chris@76 891 function ajax_indicator(turn_on)
Chris@76 892 {
Chris@76 893 if (ajax_indicator_ele == null)
Chris@76 894 {
Chris@76 895 ajax_indicator_ele = document.getElementById('ajax_in_progress');
Chris@76 896
Chris@76 897 if (ajax_indicator_ele == null && typeof(ajax_notification_text) != null)
Chris@76 898 {
Chris@76 899 create_ajax_indicator_ele();
Chris@76 900 }
Chris@76 901 }
Chris@76 902
Chris@76 903 if (ajax_indicator_ele != null)
Chris@76 904 {
Chris@76 905 if (navigator.appName == 'Microsoft Internet Explorer' && !is_ie7up)
Chris@76 906 {
Chris@76 907 ajax_indicator_ele.style.position = 'absolute';
Chris@76 908 ajax_indicator_ele.style.top = document.documentElement.scrollTop;
Chris@76 909 }
Chris@76 910
Chris@76 911 ajax_indicator_ele.style.display = turn_on ? 'block' : 'none';
Chris@76 912 }
Chris@76 913 }
Chris@76 914
Chris@76 915 function create_ajax_indicator_ele()
Chris@76 916 {
Chris@76 917 // Create the div for the indicator.
Chris@76 918 ajax_indicator_ele = document.createElement('div');
Chris@76 919
Chris@76 920 // Set the id so it'll load the style properly.
Chris@76 921 ajax_indicator_ele.id = 'ajax_in_progress';
Chris@76 922
Chris@76 923 // Add the image in and link to turn it off.
Chris@76 924 var cancel_link = document.createElement('a');
Chris@76 925 cancel_link.href = 'javascript:ajax_indicator(false)';
Chris@76 926 var cancel_img = document.createElement('img');
Chris@76 927 cancel_img.src = smf_images_url + '/icons/quick_remove.gif';
Chris@76 928
Chris@76 929 if (typeof(ajax_notification_cancel_text) != 'undefined')
Chris@76 930 {
Chris@76 931 cancel_img.alt = ajax_notification_cancel_text;
Chris@76 932 cancel_img.title = ajax_notification_cancel_text;
Chris@76 933 }
Chris@76 934
Chris@76 935 // Add the cancel link and image to the indicator.
Chris@76 936 cancel_link.appendChild(cancel_img);
Chris@76 937 ajax_indicator_ele.appendChild(cancel_link);
Chris@76 938
Chris@76 939 // Set the text. (Note: You MUST append here and not overwrite.)
Chris@76 940 ajax_indicator_ele.innerHTML += ajax_notification_text;
Chris@76 941
Chris@76 942 // Finally attach the element to the body.
Chris@76 943 document.body.appendChild(ajax_indicator_ele);
Chris@76 944 }
Chris@76 945
Chris@76 946 function createEventListener(oTarget)
Chris@76 947 {
Chris@76 948 if (!('addEventListener' in oTarget))
Chris@76 949 {
Chris@76 950 if (oTarget.attachEvent)
Chris@76 951 {
Chris@76 952 oTarget.addEventListener = function (sEvent, funcHandler, bCapture) {
Chris@76 953 oTarget.attachEvent('on' + sEvent, funcHandler);
Chris@76 954 }
Chris@76 955 oTarget.removeEventListener = function (sEvent, funcHandler, bCapture) {
Chris@76 956 oTarget.detachEvent('on' + sEvent, funcHandler);
Chris@76 957 }
Chris@76 958 }
Chris@76 959 else
Chris@76 960 {
Chris@76 961 oTarget.addEventListener = function (sEvent, funcHandler, bCapture) {
Chris@76 962 oTarget['on' + sEvent] = funcHandler;
Chris@76 963 }
Chris@76 964 oTarget.removeEventListener = function (sEvent, funcHandler, bCapture) {
Chris@76 965 oTarget['on' + sEvent] = null;
Chris@76 966 }
Chris@76 967 }
Chris@76 968 }
Chris@76 969 }
Chris@76 970
Chris@76 971 // This function will retrieve the contents needed for the jump to boxes.
Chris@76 972 function grabJumpToContent()
Chris@76 973 {
Chris@76 974 var oXMLDoc = getXMLDocument(smf_prepareScriptUrl(smf_scripturl) + 'action=xmlhttp;sa=jumpto;xml');
Chris@76 975 var aBoardsAndCategories = new Array();
Chris@76 976
Chris@76 977 ajax_indicator(true);
Chris@76 978
Chris@76 979 if (oXMLDoc.responseXML)
Chris@76 980 {
Chris@76 981 var items = oXMLDoc.responseXML.getElementsByTagName('smf')[0].getElementsByTagName('item');
Chris@76 982 for (var i = 0, n = items.length; i < n; i++)
Chris@76 983 {
Chris@76 984 aBoardsAndCategories[aBoardsAndCategories.length] = {
Chris@76 985 id: parseInt(items[i].getAttribute('id')),
Chris@76 986 isCategory: items[i].getAttribute('type') == 'category',
Chris@76 987 name: items[i].firstChild.nodeValue.removeEntities(),
Chris@76 988 is_current: false,
Chris@76 989 childLevel: parseInt(items[i].getAttribute('childlevel'))
Chris@76 990 }
Chris@76 991 }
Chris@76 992 }
Chris@76 993
Chris@76 994 ajax_indicator(false);
Chris@76 995
Chris@76 996 for (var i = 0, n = aJumpTo.length; i < n; i++)
Chris@76 997 aJumpTo[i].fillSelect(aBoardsAndCategories);
Chris@76 998 }
Chris@76 999
Chris@76 1000 // This'll contain all JumpTo objects on the page.
Chris@76 1001 var aJumpTo = new Array();
Chris@76 1002
Chris@76 1003 // *** JumpTo class.
Chris@76 1004 function JumpTo(oJumpToOptions)
Chris@76 1005 {
Chris@76 1006 this.opt = oJumpToOptions;
Chris@76 1007 this.dropdownList = null;
Chris@76 1008 this.showSelect();
Chris@76 1009 }
Chris@76 1010
Chris@76 1011 // Show the initial select box (onload). Method of the JumpTo class.
Chris@76 1012 JumpTo.prototype.showSelect = function ()
Chris@76 1013 {
Chris@76 1014 var sChildLevelPrefix = '';
Chris@76 1015 for (var i = this.opt.iCurBoardChildLevel; i > 0; i--)
Chris@76 1016 sChildLevelPrefix += this.opt.sBoardChildLevelIndicator;
Chris@76 1017 setInnerHTML(document.getElementById(this.opt.sContainerId), this.opt.sJumpToTemplate.replace(/%select_id%/, this.opt.sContainerId + '_select').replace(/%dropdown_list%/, '<select name="' + this.opt.sContainerId + '_select" id="' + this.opt.sContainerId + '_select" ' + ('implementation' in document ? '' : 'onmouseover="grabJumpToContent();" ') + ('onbeforeactivate' in document ? 'onbeforeactivate' : 'onfocus') + '="grabJumpToContent();"><option value="?board=' + this.opt.iCurBoardId + '.0">' + sChildLevelPrefix + this.opt.sBoardPrefix + this.opt.sCurBoardName.removeEntities() + '</option></select>&nbsp;<input type="button" value="' + this.opt.sGoButtonLabel + '" onclick="window.location.href = \'' + smf_prepareScriptUrl(smf_scripturl) + 'board=' + this.opt.iCurBoardId + '.0\';" />'));
Chris@76 1018 this.dropdownList = document.getElementById(this.opt.sContainerId + '_select');
Chris@76 1019 }
Chris@76 1020
Chris@76 1021 // Fill the jump to box with entries. Method of the JumpTo class.
Chris@76 1022 JumpTo.prototype.fillSelect = function (aBoardsAndCategories)
Chris@76 1023 {
Chris@76 1024 var bIE5x = !('implementation' in document);
Chris@76 1025 var iIndexPointer = 0;
Chris@76 1026
Chris@76 1027 // Create an option that'll be above and below the category.
Chris@76 1028 var oDashOption = document.createElement('option');
Chris@76 1029 oDashOption.appendChild(document.createTextNode(this.opt.sCatSeparator));
Chris@76 1030 oDashOption.disabled = 'disabled';
Chris@76 1031 oDashOption.value = '';
Chris@76 1032
Chris@76 1033 // Reset the events and clear the list (IE5.x only).
Chris@76 1034 if (bIE5x)
Chris@76 1035 {
Chris@76 1036 this.dropdownList.onmouseover = null;
Chris@76 1037 this.dropdownList.remove(0);
Chris@76 1038 }
Chris@76 1039 if ('onbeforeactivate' in document)
Chris@76 1040 this.dropdownList.onbeforeactivate = null;
Chris@76 1041 else
Chris@76 1042 this.dropdownList.onfocus = null;
Chris@76 1043
Chris@76 1044 // Create a document fragment that'll allowing inserting big parts at once.
Chris@76 1045 var oListFragment = bIE5x ? this.dropdownList : document.createDocumentFragment();
Chris@76 1046
Chris@76 1047 // Loop through all items to be added.
Chris@76 1048 for (var i = 0, n = aBoardsAndCategories.length; i < n; i++)
Chris@76 1049 {
Chris@76 1050 var j, sChildLevelPrefix, oOption;
Chris@76 1051
Chris@76 1052 // If we've reached the currently selected board add all items so far.
Chris@76 1053 if (!aBoardsAndCategories[i].isCategory && aBoardsAndCategories[i].id == this.opt.iCurBoardId)
Chris@76 1054 {
Chris@76 1055 if (bIE5x)
Chris@76 1056 iIndexPointer = this.dropdownList.options.length;
Chris@76 1057 else
Chris@76 1058 {
Chris@76 1059 this.dropdownList.insertBefore(oListFragment, this.dropdownList.options[0]);
Chris@76 1060 oListFragment = document.createDocumentFragment();
Chris@76 1061 continue;
Chris@76 1062 }
Chris@76 1063 }
Chris@76 1064
Chris@76 1065 if (aBoardsAndCategories[i].isCategory)
Chris@76 1066 oListFragment.appendChild(oDashOption.cloneNode(true));
Chris@76 1067 else
Chris@76 1068 for (j = aBoardsAndCategories[i].childLevel, sChildLevelPrefix = ''; j > 0; j--)
Chris@76 1069 sChildLevelPrefix += this.opt.sBoardChildLevelIndicator;
Chris@76 1070
Chris@76 1071 oOption = document.createElement('option');
Chris@76 1072 oOption.appendChild(document.createTextNode((aBoardsAndCategories[i].isCategory ? this.opt.sCatPrefix : sChildLevelPrefix + this.opt.sBoardPrefix) + aBoardsAndCategories[i].name));
Chris@76 1073 oOption.value = aBoardsAndCategories[i].isCategory ? '#c' + aBoardsAndCategories[i].id : '?board=' + aBoardsAndCategories[i].id + '.0';
Chris@76 1074 oListFragment.appendChild(oOption);
Chris@76 1075
Chris@76 1076 if (aBoardsAndCategories[i].isCategory)
Chris@76 1077 oListFragment.appendChild(oDashOption.cloneNode(true));
Chris@76 1078 }
Chris@76 1079
Chris@76 1080 // Add the remaining items after the currently selected item.
Chris@76 1081 this.dropdownList.appendChild(oListFragment);
Chris@76 1082
Chris@76 1083 if (bIE5x)
Chris@76 1084 this.dropdownList.options[iIndexPointer].selected = true;
Chris@76 1085
Chris@76 1086 // Internet Explorer needs this to keep the box dropped down.
Chris@76 1087 this.dropdownList.style.width = 'auto';
Chris@76 1088 this.dropdownList.focus();
Chris@76 1089
Chris@76 1090 // Add an onchange action
Chris@76 1091 this.dropdownList.onchange = function() {
Chris@76 1092 if (this.selectedIndex > 0 && this.options[this.selectedIndex].value)
Chris@76 1093 window.location.href = smf_scripturl + this.options[this.selectedIndex].value.substr(smf_scripturl.indexOf('?') == -1 || this.options[this.selectedIndex].value.substr(0, 1) != '?' ? 0 : 1);
Chris@76 1094 }
Chris@76 1095 }
Chris@76 1096
Chris@76 1097 // A global array containing all IconList objects.
Chris@76 1098 var aIconLists = new Array();
Chris@76 1099
Chris@76 1100 // *** IconList object.
Chris@76 1101 function IconList(oOptions)
Chris@76 1102 {
Chris@76 1103 if (!window.XMLHttpRequest)
Chris@76 1104 return;
Chris@76 1105
Chris@76 1106 this.opt = oOptions;
Chris@76 1107 this.bListLoaded = false;
Chris@76 1108 this.oContainerDiv = null;
Chris@76 1109 this.funcMousedownHandler = null;
Chris@76 1110 this.funcParent = this;
Chris@76 1111 this.iCurMessageId = 0;
Chris@76 1112 this.iCurTimeout = 0;
Chris@76 1113
Chris@76 1114 // Add backwards compatibility with old themes.
Chris@76 1115 if (!('sSessionVar' in this.opt))
Chris@76 1116 this.opt.sSessionVar = 'sesc';
Chris@76 1117
Chris@76 1118 this.initIcons();
Chris@76 1119 }
Chris@76 1120
Chris@76 1121 // Replace all message icons by icons with hoverable and clickable div's.
Chris@76 1122 IconList.prototype.initIcons = function ()
Chris@76 1123 {
Chris@76 1124 for (var i = document.images.length - 1, iPrefixLength = this.opt.sIconIdPrefix.length; i >= 0; i--)
Chris@76 1125 if (document.images[i].id.substr(0, iPrefixLength) == this.opt.sIconIdPrefix)
Chris@76 1126 setOuterHTML(document.images[i], '<div title="' + this.opt.sLabelIconList + '" onclick="' + this.opt.sBackReference + '.openPopup(this, ' + document.images[i].id.substr(iPrefixLength) + ')" onmouseover="' + this.opt.sBackReference + '.onBoxHover(this, true)" onmouseout="' + this.opt.sBackReference + '.onBoxHover(this, false)" style="background: ' + this.opt.sBoxBackground + '; cursor: ' + (is_ie && !is_ie6up ? 'hand' : 'pointer') + '; padding: 3px; text-align: center;"><img src="' + document.images[i].src + '" alt="' + document.images[i].alt + '" id="' + document.images[i].id + '" style="margin: 0px; padding: ' + (is_ie ? '3px' : '3px 0px 3px 0px') + ';" /></div>');
Chris@76 1127 }
Chris@76 1128
Chris@76 1129 // Event for the mouse hovering over the original icon.
Chris@76 1130 IconList.prototype.onBoxHover = function (oDiv, bMouseOver)
Chris@76 1131 {
Chris@76 1132 oDiv.style.border = bMouseOver ? this.opt.iBoxBorderWidthHover + 'px solid ' + this.opt.sBoxBorderColorHover : '';
Chris@76 1133 oDiv.style.background = bMouseOver ? this.opt.sBoxBackgroundHover : this.opt.sBoxBackground;
Chris@76 1134 oDiv.style.padding = bMouseOver ? (3 - this.opt.iBoxBorderWidthHover) + 'px' : '3px'
Chris@76 1135 }
Chris@76 1136
Chris@76 1137 // Show the list of icons after the user clicked the original icon.
Chris@76 1138 IconList.prototype.openPopup = function (oDiv, iMessageId)
Chris@76 1139 {
Chris@76 1140 this.iCurMessageId = iMessageId;
Chris@76 1141
Chris@76 1142 if (!this.bListLoaded && this.oContainerDiv == null)
Chris@76 1143 {
Chris@76 1144 // Create a container div.
Chris@76 1145 this.oContainerDiv = document.createElement('div');
Chris@76 1146 this.oContainerDiv.id = 'iconList';
Chris@76 1147 this.oContainerDiv.style.display = 'none';
Chris@76 1148 this.oContainerDiv.style.cursor = is_ie && !is_ie6up ? 'hand' : 'pointer';
Chris@76 1149 this.oContainerDiv.style.position = 'absolute';
Chris@76 1150 this.oContainerDiv.style.width = oDiv.offsetWidth + 'px';
Chris@76 1151 this.oContainerDiv.style.background = this.opt.sContainerBackground;
Chris@76 1152 this.oContainerDiv.style.border = this.opt.sContainerBorder;
Chris@76 1153 this.oContainerDiv.style.padding = '1px';
Chris@76 1154 this.oContainerDiv.style.textAlign = 'center';
Chris@76 1155 document.body.appendChild(this.oContainerDiv);
Chris@76 1156
Chris@76 1157 // Start to fetch its contents.
Chris@76 1158 ajax_indicator(true);
Chris@76 1159 this.tmpMethod = getXMLDocument;
Chris@76 1160 this.tmpMethod(smf_prepareScriptUrl(this.opt.sScriptUrl) + 'action=xmlhttp;sa=messageicons;board=' + this.opt.iBoardId + ';xml', this.onIconsReceived);
Chris@76 1161 delete this.tmpMethod;
Chris@76 1162
Chris@76 1163 createEventListener(document.body);
Chris@76 1164 }
Chris@76 1165
Chris@76 1166 // Set the position of the container.
Chris@76 1167 var aPos = smf_itemPos(oDiv);
Chris@76 1168 if (is_ie50)
Chris@76 1169 aPos[1] += 4;
Chris@76 1170
Chris@76 1171 this.oContainerDiv.style.top = (aPos[1] + oDiv.offsetHeight) + 'px';
Chris@76 1172 this.oContainerDiv.style.left = (aPos[0] - 1) + 'px';
Chris@76 1173 this.oClickedIcon = oDiv;
Chris@76 1174
Chris@76 1175 if (this.bListLoaded)
Chris@76 1176 this.oContainerDiv.style.display = 'block';
Chris@76 1177
Chris@76 1178 document.body.addEventListener('mousedown', this.onWindowMouseDown, false);
Chris@76 1179 }
Chris@76 1180
Chris@76 1181 // Setup the list of icons once it is received through xmlHTTP.
Chris@76 1182 IconList.prototype.onIconsReceived = function (oXMLDoc)
Chris@76 1183 {
Chris@76 1184 var icons = oXMLDoc.getElementsByTagName('smf')[0].getElementsByTagName('icon');
Chris@76 1185 var sItems = '';
Chris@76 1186
Chris@76 1187 for (var i = 0, n = icons.length; i < n; i++)
Chris@76 1188 sItems += '<div onmouseover="' + this.opt.sBackReference + '.onItemHover(this, true)" onmouseout="' + this.opt.sBackReference + '.onItemHover(this, false);" onmousedown="' + this.opt.sBackReference + '.onItemMouseDown(this, \'' + icons[i].getAttribute('value') + '\');" style="padding: 3px 0px 3px 0px; margin-left: auto; margin-right: auto; border: ' + this.opt.sItemBorder + '; background: ' + this.opt.sItemBackground + '"><img src="' + icons[i].getAttribute('url') + '" alt="' + icons[i].getAttribute('name') + '" title="' + icons[i].firstChild.nodeValue + '" /></div>';
Chris@76 1189
Chris@76 1190 setInnerHTML(this.oContainerDiv, sItems);
Chris@76 1191 this.oContainerDiv.style.display = 'block';
Chris@76 1192 this.bListLoaded = true;
Chris@76 1193
Chris@76 1194 if (is_ie)
Chris@76 1195 this.oContainerDiv.style.width = this.oContainerDiv.clientWidth + 'px';
Chris@76 1196
Chris@76 1197 ajax_indicator(false);
Chris@76 1198 }
Chris@76 1199
Chris@76 1200 // Event handler for hovering over the icons.
Chris@76 1201 IconList.prototype.onItemHover = function (oDiv, bMouseOver)
Chris@76 1202 {
Chris@76 1203 oDiv.style.background = bMouseOver ? this.opt.sItemBackgroundHover : this.opt.sItemBackground;
Chris@76 1204 oDiv.style.border = bMouseOver ? this.opt.sItemBorderHover : this.opt.sItemBorder;
Chris@76 1205 if (this.iCurTimeout != 0)
Chris@76 1206 window.clearTimeout(this.iCurTimeout);
Chris@76 1207 if (bMouseOver)
Chris@76 1208 this.onBoxHover(this.oClickedIcon, true);
Chris@76 1209 else
Chris@76 1210 this.iCurTimeout = window.setTimeout(this.opt.sBackReference + '.collapseList();', 500);
Chris@76 1211 }
Chris@76 1212
Chris@76 1213 // Event handler for clicking on one of the icons.
Chris@76 1214 IconList.prototype.onItemMouseDown = function (oDiv, sNewIcon)
Chris@76 1215 {
Chris@76 1216 if (this.iCurMessageId != 0)
Chris@76 1217 {
Chris@76 1218 ajax_indicator(true);
Chris@76 1219 this.tmpMethod = getXMLDocument;
Chris@76 1220 var oXMLDoc = this.tmpMethod(smf_prepareScriptUrl(this.opt.sScriptUrl) + 'action=jsmodify;topic=' + this.opt.iTopicId + ';msg=' + this.iCurMessageId + ';' + this.opt.sSessionVar + '=' + this.opt.sSessionId + ';icon=' + sNewIcon + ';xml');
Chris@76 1221 delete this.tmpMethod;
Chris@76 1222 ajax_indicator(false);
Chris@76 1223
Chris@76 1224 var oMessage = oXMLDoc.responseXML.getElementsByTagName('smf')[0].getElementsByTagName('message')[0];
Chris@76 1225 if (oMessage.getElementsByTagName('error').length == 0)
Chris@76 1226 {
Chris@76 1227 if (this.opt.bShowModify && oMessage.getElementsByTagName('modified').length != 0)
Chris@76 1228 setInnerHTML(document.getElementById('modified_' + this.iCurMessageId), oMessage.getElementsByTagName('modified')[0].childNodes[0].nodeValue);
Chris@76 1229 this.oClickedIcon.getElementsByTagName('img')[0].src = oDiv.getElementsByTagName('img')[0].src;
Chris@76 1230 }
Chris@76 1231 }
Chris@76 1232 }
Chris@76 1233
Chris@76 1234 // Event handler for clicking outside the list (will make the list disappear).
Chris@76 1235 IconList.prototype.onWindowMouseDown = function ()
Chris@76 1236 {
Chris@76 1237 for (var i = aIconLists.length - 1; i >= 0; i--)
Chris@76 1238 {
Chris@76 1239 aIconLists[i].funcParent.tmpMethod = aIconLists[i].collapseList;
Chris@76 1240 aIconLists[i].funcParent.tmpMethod();
Chris@76 1241 delete aIconLists[i].funcParent.tmpMethod;
Chris@76 1242 }
Chris@76 1243 }
Chris@76 1244
Chris@76 1245 // Collapse the list of icons.
Chris@76 1246 IconList.prototype.collapseList = function()
Chris@76 1247 {
Chris@76 1248 this.onBoxHover(this.oClickedIcon, false);
Chris@76 1249 this.oContainerDiv.style.display = 'none';
Chris@76 1250 this.iCurMessageId = 0;
Chris@76 1251 document.body.removeEventListener('mousedown', this.onWindowMouseDown, false);
Chris@76 1252 }
Chris@76 1253
Chris@76 1254 // Handy shortcuts for getting the mouse position on the screen - only used for IE at the moment.
Chris@76 1255 function smf_mousePose(oEvent)
Chris@76 1256 {
Chris@76 1257 var x = 0;
Chris@76 1258 var y = 0;
Chris@76 1259
Chris@76 1260 if (oEvent.pageX)
Chris@76 1261 {
Chris@76 1262 y = oEvent.pageY;
Chris@76 1263 x = oEvent.pageX;
Chris@76 1264 }
Chris@76 1265 else if (oEvent.clientX)
Chris@76 1266 {
Chris@76 1267 x = oEvent.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
Chris@76 1268 y = oEvent.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
Chris@76 1269 }
Chris@76 1270
Chris@76 1271 return [x, y];
Chris@76 1272 }
Chris@76 1273
Chris@76 1274 // Short function for finding the actual position of an item.
Chris@76 1275 function smf_itemPos(itemHandle)
Chris@76 1276 {
Chris@76 1277 var itemX = 0;
Chris@76 1278 var itemY = 0;
Chris@76 1279
Chris@76 1280 if ('offsetParent' in itemHandle)
Chris@76 1281 {
Chris@76 1282 itemX = itemHandle.offsetLeft;
Chris@76 1283 itemY = itemHandle.offsetTop;
Chris@76 1284 while (itemHandle.offsetParent && typeof(itemHandle.offsetParent) == 'object')
Chris@76 1285 {
Chris@76 1286 itemHandle = itemHandle.offsetParent;
Chris@76 1287 itemX += itemHandle.offsetLeft;
Chris@76 1288 itemY += itemHandle.offsetTop;
Chris@76 1289 }
Chris@76 1290 }
Chris@76 1291 else if ('x' in itemHandle)
Chris@76 1292 {
Chris@76 1293 itemX = itemHandle.x;
Chris@76 1294 itemY = itemHandle.y;
Chris@76 1295 }
Chris@76 1296
Chris@76 1297 return [itemX, itemY];
Chris@76 1298 }
Chris@76 1299
Chris@76 1300 // This function takes the script URL and prepares it to allow the query string to be appended to it.
Chris@76 1301 function smf_prepareScriptUrl(sUrl)
Chris@76 1302 {
Chris@76 1303 return sUrl.indexOf('?') == -1 ? sUrl + '?' : sUrl + (sUrl.charAt(sUrl.length - 1) == '?' || sUrl.charAt(sUrl.length - 1) == '&' || sUrl.charAt(sUrl.length - 1) == ';' ? '' : ';');
Chris@76 1304 }
Chris@76 1305
Chris@76 1306 var aOnloadEvents = new Array();
Chris@76 1307 function addLoadEvent(fNewOnload)
Chris@76 1308 {
Chris@76 1309 // If there's no event set, just set this one
Chris@76 1310 if (typeof(fNewOnload) == 'function' && (!('onload' in window) || typeof(window.onload) != 'function'))
Chris@76 1311 window.onload = fNewOnload;
Chris@76 1312
Chris@76 1313 // If there's just one event, setup the array.
Chris@76 1314 else if (aOnloadEvents.length == 0)
Chris@76 1315 {
Chris@76 1316 aOnloadEvents[0] = window.onload;
Chris@76 1317 aOnloadEvents[1] = fNewOnload;
Chris@76 1318 window.onload = function() {
Chris@76 1319 for (var i = 0, n = aOnloadEvents.length; i < n; i++)
Chris@76 1320 {
Chris@76 1321 if (typeof(aOnloadEvents[i]) == 'function')
Chris@76 1322 aOnloadEvents[i]();
Chris@76 1323 else if (typeof(aOnloadEvents[i]) == 'string')
Chris@76 1324 eval(aOnloadEvents[i]);
Chris@76 1325 }
Chris@76 1326 }
Chris@76 1327 }
Chris@76 1328
Chris@76 1329 // This isn't the first event function, add it to the list.
Chris@76 1330 else
Chris@76 1331 aOnloadEvents[aOnloadEvents.length] = fNewOnload;
Chris@76 1332 }
Chris@76 1333
Chris@76 1334 function smfFooterHighlight(element, value)
Chris@76 1335 {
Chris@76 1336 element.src = smf_images_url + '/' + (value ? 'h_' : '') + element.id + '.gif';
Chris@76 1337 }
Chris@76 1338
Chris@76 1339 // Get the text in a code tag.
Chris@76 1340 function smfSelectText(oCurElement, bActOnElement)
Chris@76 1341 {
Chris@76 1342 // The place we're looking for is one div up, and next door - if it's auto detect.
Chris@76 1343 if (typeof(bActOnElement) == 'boolean' && bActOnElement)
Chris@76 1344 var oCodeArea = document.getElementById(oCurElement);
Chris@76 1345 else
Chris@76 1346 var oCodeArea = oCurElement.parentNode.nextSibling;
Chris@76 1347
Chris@76 1348 if (typeof(oCodeArea) != 'object' || oCodeArea == null)
Chris@76 1349 return false;
Chris@76 1350
Chris@76 1351 // Start off with my favourite, internet explorer.
Chris@76 1352 if ('createTextRange' in document.body)
Chris@76 1353 {
Chris@76 1354 var oCurRange = document.body.createTextRange();
Chris@76 1355 oCurRange.moveToElementText(oCodeArea);
Chris@76 1356 oCurRange.select();
Chris@76 1357 }
Chris@76 1358 // Firefox at el.
Chris@76 1359 else if (window.getSelection)
Chris@76 1360 {
Chris@76 1361 var oCurSelection = window.getSelection();
Chris@76 1362 // Safari is special!
Chris@76 1363 if (oCurSelection.setBaseAndExtent)
Chris@76 1364 {
Chris@76 1365 var oLastChild = oCodeArea.lastChild;
Chris@76 1366 oCurSelection.setBaseAndExtent(oCodeArea, 0, oLastChild, 'innerText' in oLastChild ? oLastChild.innerText.length : oLastChild.textContent.length);
Chris@76 1367 }
Chris@76 1368 else
Chris@76 1369 {
Chris@76 1370 var curRange = document.createRange();
Chris@76 1371 curRange.selectNodeContents(oCodeArea);
Chris@76 1372
Chris@76 1373 oCurSelection.removeAllRanges();
Chris@76 1374 oCurSelection.addRange(curRange);
Chris@76 1375 }
Chris@76 1376 }
Chris@76 1377
Chris@76 1378 return false;
Chris@76 1379 }
Chris@76 1380
Chris@76 1381 // A function needed to discern HTML entities from non-western characters.
Chris@76 1382 function smc_saveEntities(sFormName, aElementNames, sMask)
Chris@76 1383 {
Chris@76 1384 if (typeof(sMask) == 'string')
Chris@76 1385 {
Chris@76 1386 for (var i = 0, n = document.forms[sFormName].elements.length; i < n; i++)
Chris@76 1387 if (document.forms[sFormName].elements[i].id.substr(0, sMask.length) == sMask)
Chris@76 1388 aElementNames[aElementNames.length] = document.forms[sFormName].elements[i].name;
Chris@76 1389 }
Chris@76 1390
Chris@76 1391 for (var i = 0, n = aElementNames.length; i < n; i++)
Chris@76 1392 {
Chris@76 1393 if (aElementNames[i] in document.forms[sFormName])
Chris@76 1394 document.forms[sFormName][aElementNames[i]].value = document.forms[sFormName][aElementNames[i]].value.replace(/&#/g, '&#38;#');
Chris@76 1395 }
Chris@76 1396 }
Chris@76 1397
Chris@76 1398 // A function used to clean the attachments on post page
Chris@76 1399 function cleanFileInput(idElement)
Chris@76 1400 {
Chris@76 1401 // Simpler solutions work in Opera, IE, Safari and Chrome.
Chris@76 1402 if (is_opera || is_ie || is_safari || is_chrome)
Chris@76 1403 {
Chris@76 1404 document.getElementById(idElement).outerHTML = document.getElementById(idElement).outerHTML;
Chris@76 1405 }
Chris@76 1406 // What else can we do? By the way, this doesn't work in Chrome and Mac's Safari.
Chris@76 1407 else
Chris@76 1408 {
Chris@76 1409 document.getElementById(idElement).type = 'input';
Chris@76 1410 document.getElementById(idElement).type = 'file';
Chris@76 1411 }
Chris@76 1412 }