1 2var Drupal = Drupal || { 'settings': {}, 'behaviors': {}, 'locale': {} }; 3 4// Allow other JavaScript libraries to use $. 5jQuery.noConflict(); 6 7(function ($) { 8 9/** 10 * Override jQuery.fn.init to guard against XSS attacks. 11 * 12 * See http://bugs.jquery.com/ticket/9521 13 */ 14var jquery_init = $.fn.init; 15$.fn.init = function (selector, context, rootjQuery) { 16 // If the string contains a "#" before a "<", treat it as invalid HTML. 17 if (selector && typeof selector === 'string') { 18 var hash_position = selector.indexOf('#'); 19 if (hash_position >= 0) { 20 var bracket_position = selector.indexOf('<'); 21 if (bracket_position > hash_position) { 22 throw 'Syntax error, unrecognized expression: ' + selector; 23 } 24 } 25 } 26 return jquery_init.call(this, selector, context, rootjQuery); 27}; 28$.fn.init.prototype = jquery_init.prototype; 29 30/** 31 * Attach all registered behaviors to a page element. 32 * 33 * Behaviors are event-triggered actions that attach to page elements, enhancing 34 * default non-JavaScript UIs. Behaviors are registered in the Drupal.behaviors 35 * object using the method 'attach' and optionally also 'detach' as follows: 36 * @code 37 * Drupal.behaviors.behaviorName = { 38 * attach: function (context, settings) { 39 * ... 40 * }, 41 * detach: function (context, settings, trigger) { 42 * ... 43 * } 44 * }; 45 * @endcode 46 * 47 * Drupal.attachBehaviors is added below to the jQuery ready event and so 48 * runs on initial page load. Developers implementing AHAH/Ajax in their 49 * solutions should also call this function after new page content has been 50 * loaded, feeding in an element to be processed, in order to attach all 51 * behaviors to the new content. 52 * 53 * Behaviors should use 54 * @code 55 * $(selector).once('behavior-name', function () { 56 * ... 57 * }); 58 * @endcode 59 * to ensure the behavior is attached only once to a given element. (Doing so 60 * enables the reprocessing of given elements, which may be needed on occasion 61 * despite the ability to limit behavior attachment to a particular element.) 62 * 63 * @param context 64 * An element to attach behaviors to. If none is given, the document element 65 * is used. 66 * @param settings 67 * An object containing settings for the current context. If none given, the 68 * global Drupal.settings object is used. 69 */ 70Drupal.attachBehaviors = function (context, settings) { 71 context = context || document; 72 settings = settings || Drupal.settings; 73 // Execute all of them. 74 $.each(Drupal.behaviors, function () { 75 if ($.isFunction(this.attach)) { 76 this.attach(context, settings); 77 } 78 }); 79}; 80 81/** 82 * Detach registered behaviors from a page element. 83 * 84 * Developers implementing AHAH/Ajax in their solutions should call this 85 * function before page content is about to be removed, feeding in an element 86 * to be processed, in order to allow special behaviors to detach from the 87 * content. 88 * 89 * Such implementations should look for the class name that was added in their 90 * corresponding Drupal.behaviors.behaviorName.attach implementation, i.e. 91 * behaviorName-processed, to ensure the behavior is detached only from 92 * previously processed elements. 93 * 94 * @param context 95 * An element to detach behaviors from. If none is given, the document element 96 * is used. 97 * @param settings 98 * An object containing settings for the current context. If none given, the 99 * global Drupal.settings object is used. 100 * @param trigger 101 * A string containing what's causing the behaviors to be detached. The 102 * possible triggers are: 103 * - unload: (default) The context element is being removed from the DOM. 104 * - move: The element is about to be moved within the DOM (for example, 105 * during a tabledrag row swap). After the move is completed, 106 * Drupal.attachBehaviors() is called, so that the behavior can undo 107 * whatever it did in response to the move. Many behaviors won't need to 108 * do anything simply in response to the element being moved, but because 109 * IFRAME elements reload their "src" when being moved within the DOM, 110 * behaviors bound to IFRAME elements (like WYSIWYG editors) may need to 111 * take some action. 112 * - serialize: When an Ajax form is submitted, this is called with the 113 * form as the context. This provides every behavior within the form an 114 * opportunity to ensure that the field elements have correct content 115 * in them before the form is serialized. The canonical use-case is so 116 * that WYSIWYG editors can update the hidden textarea to which they are 117 * bound. 118 * 119 * @see Drupal.attachBehaviors 120 */ 121Drupal.detachBehaviors = function (context, settings, trigger) { 122 context = context || document; 123 settings = settings || Drupal.settings; 124 trigger = trigger || 'unload'; 125 // Execute all of them. 126 $.each(Drupal.behaviors, function () { 127 if ($.isFunction(this.detach)) { 128 this.detach(context, settings, trigger); 129 } 130 }); 131}; 132 133/** 134 * Encode special characters in a plain-text string for display as HTML. 135 * 136 * @ingroup sanitization 137 */ 138Drupal.checkPlain = function (str) { 139 var character, regex, 140 replace = { '&': '&', '"': '"', '<': '<', '>': '>' }; 141 str = String(str); 142 for (character in replace) { 143 if (replace.hasOwnProperty(character)) { 144 regex = new RegExp(character, 'g'); 145 str = str.replace(regex, replace[character]); 146 } 147 } 148 return str; 149}; 150 151/** 152 * Replace placeholders with sanitized values in a string. 153 * 154 * @param str 155 * A string with placeholders. 156 * @param args 157 * An object of replacements pairs to make. Incidences of any key in this 158 * array are replaced with the corresponding value. Based on the first 159 * character of the key, the value is escaped and/or themed: 160 * - !variable: inserted as is 161 * - @variable: escape plain text to HTML (Drupal.checkPlain) 162 * - %variable: escape text and theme as a placeholder for user-submitted 163 * content (checkPlain + Drupal.theme('placeholder')) 164 * 165 * @see Drupal.t() 166 * @ingroup sanitization 167 */ 168Drupal.formatString = function(str, args) { 169 // Transform arguments before inserting them. 170 for (var key in args) { 171 switch (key.charAt(0)) { 172 // Escaped only. 173 case '@': 174 args[key] = Drupal.checkPlain(args[key]); 175 break; 176 // Pass-through. 177 case '!': 178 break; 179 // Escaped and placeholder. 180 case '%': 181 default: 182 args[key] = Drupal.theme('placeholder', args[key]); 183 break; 184 } 185 str = str.replace(key, args[key]); 186 } 187 return str; 188}; 189 190/** 191 * Translate strings to the page language or a given language. 192 * 193 * See the documentation of the server-side t() function for further details. 194 * 195 * @param str 196 * A string containing the English string to translate. 197 * @param args 198 * An object of replacements pairs to make after translation. Incidences 199 * of any key in this array are replaced with the corresponding value. 200 * See Drupal.formatString(). 201 * 202 * @param options 203 * - 'context' (defaults to the empty context): The context the source string 204 * belongs to. 205 * 206 * @return 207 * The translated string. 208 */ 209Drupal.t = function (str, args, options) { 210 options = options || {}; 211 options.context = options.context || ''; 212 213 // Fetch the localized version of the string. 214 if (Drupal.locale.strings && Drupal.locale.strings[options.context] && Drupal.locale.strings[options.context][str]) { 215 str = Drupal.locale.strings[options.context][str]; 216 } 217 218 if (args) { 219 str = Drupal.formatString(str, args); 220 } 221 return str; 222}; 223 224/** 225 * Format a string containing a count of items. 226 * 227 * This function ensures that the string is pluralized correctly. Since Drupal.t() is 228 * called by this function, make sure not to pass already-localized strings to it. 229 * 230 * See the documentation of the server-side format_plural() function for further details. 231 * 232 * @param count 233 * The item count to display. 234 * @param singular 235 * The string for the singular case. Please make sure it is clear this is 236 * singular, to ease translation (e.g. use "1 new comment" instead of "1 new"). 237 * Do not use @count in the singular string. 238 * @param plural 239 * The string for the plural case. Please make sure it is clear this is plural, 240 * to ease translation. Use @count in place of the item count, as in "@count 241 * new comments". 242 * @param args 243 * An object of replacements pairs to make after translation. Incidences 244 * of any key in this array are replaced with the corresponding value. 245 * See Drupal.formatString(). 246 * Note that you do not need to include @count in this array. 247 * This replacement is done automatically for the plural case. 248 * @param options 249 * The options to pass to the Drupal.t() function. 250 * @return 251 * A translated string. 252 */ 253Drupal.formatPlural = function (count, singular, plural, args, options) { 254 var args = args || {}; 255 args['@count'] = count; 256 // Determine the index of the plural form. 257 var index = Drupal.locale.pluralFormula ? Drupal.locale.pluralFormula(args['@count']) : ((args['@count'] == 1) ? 0 : 1); 258 259 if (index == 0) { 260 return Drupal.t(singular, args, options); 261 } 262 else if (index == 1) { 263 return Drupal.t(plural, args, options); 264 } 265 else { 266 args['@count[' + index + ']'] = args['@count']; 267 delete args['@count']; 268 return Drupal.t(plural.replace('@count', '@count[' + index + ']'), args, options); 269 } 270}; 271 272/** 273 * Generate the themed representation of a Drupal object. 274 * 275 * All requests for themed output must go through this function. It examines 276 * the request and routes it to the appropriate theme function. If the current 277 * theme does not provide an override function, the generic theme function is 278 * called. 279 * 280 * For example, to retrieve the HTML for text that should be emphasized and 281 * displayed as a placeholder inside a sentence, call 282 * Drupal.theme('placeholder', text). 283 * 284 * @param func 285 * The name of the theme function to call. 286 * @param ... 287 * Additional arguments to pass along to the theme function. 288 * @return 289 * Any data the theme function returns. This could be a plain HTML string, 290 * but also a complex object. 291 */ 292Drupal.theme = function (func) { 293 var args = Array.prototype.slice.apply(arguments, [1]); 294 295 return (Drupal.theme[func] || Drupal.theme.prototype[func]).apply(this, args); 296}; 297 298/** 299 * Freeze the current body height (as minimum height). Used to prevent 300 * unnecessary upwards scrolling when doing DOM manipulations. 301 */ 302Drupal.freezeHeight = function () { 303 Drupal.unfreezeHeight(); 304 $('<div id="freeze-height"></div>').css({ 305 position: 'absolute', 306 top: '0px', 307 left: '0px', 308 width: '1px', 309 height: $('body').css('height') 310 }).appendTo('body'); 311}; 312 313/** 314 * Unfreeze the body height. 315 */ 316Drupal.unfreezeHeight = function () { 317 $('#freeze-height').remove(); 318}; 319 320/** 321 * Encodes a Drupal path for use in a URL. 322 * 323 * For aesthetic reasons slashes are not escaped. 324 */ 325Drupal.encodePath = function (item, uri) { 326 uri = uri || location.href; 327 return encodeURIComponent(item).replace(/%2F/g, '/'); 328}; 329 330/** 331 * Get the text selection in a textarea. 332 */ 333Drupal.getSelection = function (element) { 334 if (typeof element.selectionStart != 'number' && document.selection) { 335 // The current selection. 336 var range1 = document.selection.createRange(); 337 var range2 = range1.duplicate(); 338 // Select all text. 339 range2.moveToElementText(element); 340 // Now move 'dummy' end point to end point of original range.
341 range2.setEndPoint('EndToEnd', range1); 342 // Now we can calculate start and end points. 343 var start = range2.text.length - range1.text.length; 344 var end = start + range1.text.length; 345 return { 'start': start, 'end': end }; 346 } 347 return { 'start': element.selectionStart, 'end': element.selectionEnd }; 348}; 349 350/** 351 * Build an error message from an Ajax response. 352 */ 353Drupal.ajaxError = function (xmlhttp, uri) { 354 var statusCode, statusText, pathText, responseText, readyStateText, message; 355 if (xmlhttp.status) { 356 statusCode = "\n" + Drupal.t("An AJAX HTTP error occurred.") + "\n" + Drupal.t("HTTP Result Code: !status", {'!status': xmlhttp.status}); 357 } 358 else { 359 statusCode = "\n" + Drupal.t("An AJAX HTTP request terminated abnormally."); 360 } 361 statusCode += "\n" + Drupal.t("Debugging information follows."); 362 pathText = "\n" + Drupal.t("Path: !uri", {'!uri': uri} ); 363 statusText = ''; 364 // In some cases, when statusCode == 0, xmlhttp.statusText may not be defined. 365 // Unfortunately, testing for it with typeof, etc, doesn't seem to catch that 366 // and the test causes an exception. So we need to catch the exception here. 367 try { 368 statusText = "\n" + Drupal.t("StatusText: !statusText", {'!statusText': $.trim(xmlhttp.statusText)}); 369 } 370 catch (e) {} 371 372 responseText = ''; 373 // Again, we don't have a way to know for sure whether accessing 374 // xmlhttp.responseText is going to throw an exception. So we'll catch it. 375 try { 376 responseText = "\n" + Drupal.t("ResponseText: !responseText", {'!responseText': $.trim(xmlhttp.responseText) } ); 377 } catch (e) {} 378 379 // Make the responseText more readable by stripping HTML tags and newlines. 380 responseText = responseText.replace(/<("[^"]*"|'[^']*'|[^'">])*>/gi,""); 381 responseText = responseText.replace(/[\n]+\s+/g,"\n"); 382 383 // We don't need readyState except for status == 0. 384 readyStateText = xmlhttp.status == 0 ? ("\n" + Drupal.t("ReadyState: !readyState", {'!readyState': xmlhttp.readyState})) : ""; 385 386 message = statusCode + pathText + statusText + responseText + readyStateText; 387 return message; 388}; 389 390// Class indicating that JS is enabled; used for styling purpose. 391$('html').addClass('js'); 392 393// 'js enabled' cookie. 394document.cookie = 'has_js=1; path=/'; 395 396/** 397 * Additions to jQuery.support. 398 */ 399$(function () { 400 /** 401 * Boolean indicating whether or not position:fixed is supported. 402 */ 403 if (jQuery.support.positionFixed === undefined) { 404 var el = $('<div style="position:fixed; top:10px" />').appendTo(document.body); 405 jQuery.support.positionFixed = el[0].offsetTop === 10; 406 el.remove(); 407 } 408}); 409 410//Attach all behaviors. 411$(function () { 412 Drupal.attachBehaviors(document, Drupal.settings); 413}); 414 415/** 416 * The default themes. 417 */ 418Drupal.theme.prototype = { 419 420 /** 421 * Formats text for emphasized display in a placeholder inside a sentence. 422 * 423 * @param str 424 * The text to format (plain-text). 425 * @return 426 * The formatted text (html). 427 */ 428 placeholder: function (str) { 429 return '<em class="placeholder">' + Drupal.checkPlain(str) + '</em>'; 430 } 431}; 432 433})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.