UNPKG

67.7 kBHTMLView Raw
1<!DOCTYPE html>
2
3<html lang="en">
4<head>
5 <meta charset="utf-8">
6 <meta name="viewport" content="width=device-width">
7 <title>CrossBrowdy API documentation Source: CrossBrowdy.js</title>
8
9 <!--[if lt IE 9]>
10 <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
11 <![endif]-->
12 <link type="text/css" rel="stylesheet" href="styles/sunlight.default.css">
13
14 <link type="text/css" rel="stylesheet" href="styles/site.cosmo.css">
15
16</head>
17
18<body style="min-width:800px; overflow-wrap:break-word; word-wrap:break-word; word-break:break-word; line-break:strict; hyphens:none; -webkit-hyphens:none; -moz-hyphens:none;">
19
20<div class="navbar navbar-default navbar-fixed-top ">
21<div class="container">
22 <div class="navbar-header">
23 <a class="navbar-brand" href="index.html">CrossBrowdy API documentation</a>
24 <button class="navbar-toggle" type="button" data-toggle="collapse" data-target="#topNavigation">
25 <span class="icon-bar"></span>
26 <span class="icon-bar"></span>
27 <span class="icon-bar"></span>
28 </button>
29 </div>
30 <div class="navbar-collapse collapse" id="topNavigation">
31 <ul class="nav navbar-nav">
32
33 <li class="dropdown">
34 <a href="namespaces.list.html" class="dropdown-toggle" data-toggle="dropdown">Namespaces<b class="caret"></b></a>
35 <ul class="dropdown-menu inline">
36 <li><a href="CB_Arrays.html">CB_Arrays</a></li><li><a href="CB_AudioDetector.html">CB_AudioDetector</a></li><li><a href="CB_Client.html">CB_Client</a></li><li><a href="CB_Collisions.html">CB_Collisions</a></li><li><a href="CB_Configuration.html">CB_Configuration</a></li><li><a href="CB_Configuration.CrossBase.html">CB_Configuration.CrossBase</a></li><li><a href="CB_Configuration.CrossBrowdy.html">CB_Configuration.CrossBrowdy</a></li><li><a href="CB_Controllers.html">CB_Controllers</a></li><li><a href="CB_Controllers_Proprietary.html">CB_Controllers_Proprietary</a></li><li><a href="CB_Controllers_Proprietary.WII.html">CB_Controllers_Proprietary.WII</a></li><li><a href="CB_Controllers_Proprietary.WII_U.html">CB_Controllers_Proprietary.WII_U</a></li><li><a href="CB_Device.html">CB_Device</a></li><li><a href="CB_Device.AmbientLight.html">CB_Device.AmbientLight</a></li><li><a href="CB_Device.Battery.html">CB_Device.Battery</a></li><li><a href="CB_Device.Location.html">CB_Device.Location</a></li><li><a href="CB_Device.Motion.html">CB_Device.Motion</a></li><li><a href="CB_Device.Orientation.html">CB_Device.Orientation</a></li><li><a href="CB_Device.Proximity.html">CB_Device.Proximity</a></li><li><a href="CB_Device.Vibration.html">CB_Device.Vibration</a></li><li><a href="CB_Elements.html">CB_Elements</a></li><li><a href="CB_Events.html">CB_Events</a></li><li><a href="CB_Keyboard.html">CB_Keyboard</a></li><li><a href="CB_Keyboard.chars.html">CB_Keyboard.chars</a></li><li><a href="CB_Keyboard.extended.html">CB_Keyboard.extended</a></li><li><a href="CB_Keyboard.keys.html">CB_Keyboard.keys</a></li><li><a href="CB_Modules.html">CB_Modules</a></li><li><a href="CB_Mouse.html">CB_Mouse</a></li><li><a href="CB_Mouse.CursorImage.html">CB_Mouse.CursorImage</a></li><li><a href="CB_Net.html">CB_Net</a></li><li><a href="CB_Net.Fetch.html">CB_Net.Fetch</a></li><li><a href="CB_Net.REST.html">CB_Net.REST</a></li><li><a href="CB_Net.Sockets.html">CB_Net.Sockets</a></li><li><a href="CB_Net.Sockets.SockJS.html">CB_Net.Sockets.SockJS</a></li><li><a href="CB_Net.XHR.html">CB_Net.XHR</a></li><li><a href="CB_Pointer.html">CB_Pointer</a></li><li><a href="CB_Screen.html">CB_Screen</a></li><li><a href="CB_Speaker.html">CB_Speaker</a></li><li><a href="CB_Touch.html">CB_Touch</a></li><li><a href="CB_baseSymbols.html">CB_baseSymbols</a></li>
37 </ul>
38 </li>
39
40 <li class="dropdown">
41 <a href="classes.list.html" class="dropdown-toggle" data-toggle="dropdown">Classes<b class="caret"></b></a>
42 <ul class="dropdown-menu inline">
43 <li><a href="CB_AudioFile.html">CB_AudioFile</a></li><li><a href="CB_AudioFileCache.html">CB_AudioFileCache</a></li><li><a href="CB_AudioFileSprites.html">CB_AudioFileSprites</a></li><li><a href="CB_AudioFileSpritesPool.html">CB_AudioFileSpritesPool</a></li><li><a href="CB_AudioFile_API.AAPI.html">CB_AudioFile_API.AAPI</a></li><li><a href="CB_AudioFile_API.ACMP.html">CB_AudioFile_API.ACMP</a></li><li><a href="CB_AudioFile_API.SM2.html">CB_AudioFile_API.SM2</a></li><li><a href="CB_AudioFile_API.WAAPI.html">CB_AudioFile_API.WAAPI</a></li><li><a href="CB_Canvas.html">CB_Canvas</a></li><li><a href="CB_GraphicSprites.html">CB_GraphicSprites</a></li><li><a href="CB_GraphicSpritesScene.html">CB_GraphicSpritesScene</a></li>
44 </ul>
45 </li>
46
47 <li class="dropdown">
48 <a href="global.html" class="dropdown-toggle" data-toggle="dropdown">Global<b class="caret"></b></a>
49 <ul class="dropdown-menu inline">
50 <li><a href="global.html#CB_BASE_NAME">CB_BASE_NAME</a></li><li><a href="global.html#CB_CREDITS_DEFAULT">CB_CREDITS_DEFAULT</a></li><li><a href="global.html#CB_NAME">CB_NAME</a></li><li><a href="global.html#CB_OPTIONS">CB_OPTIONS</a></li><li><a href="global.html#CB_VERSION">CB_VERSION</a></li><li><a href="global.html#CB_addCredits">CB_addCredits</a></li><li><a href="global.html#CB_baseToBase">CB_baseToBase</a></li><li><a href="global.html#CB_baseToInt">CB_baseToInt</a></li><li><a href="global.html#CB_br2nl">CB_br2nl</a></li><li><a href="global.html#CB_brToNl">CB_brToNl</a></li><li><a href="global.html#CB_combineArraysOrObjects">CB_combineArraysOrObjects</a></li><li><a href="global.html#CB_combineAutomatically">CB_combineAutomatically</a></li><li><a href="global.html#CB_combineJSON">CB_combineJSON</a></li><li><a href="global.html#CB_combineURIParameters">CB_combineURIParameters</a></li><li><a href="global.html#CB_combineURLParameters">CB_combineURLParameters</a></li><li><a href="global.html#CB_console">CB_console</a></li><li><a href="global.html#CB_copyObject">CB_copyObject</a></li><li><a href="global.html#CB_countDecimalDigits">CB_countDecimalDigits</a></li><li><a href="global.html#CB_countDecimalPart">CB_countDecimalPart</a></li><li><a href="global.html#CB_countDecimals">CB_countDecimals</a></li><li><a href="global.html#CB_countIntegerDigits">CB_countIntegerDigits</a></li><li><a href="global.html#CB_countIntegerPart">CB_countIntegerPart</a></li><li><a href="global.html#CB_credits">CB_credits</a></li><li><a href="global.html#CB_forEach">CB_forEach</a></li><li><a href="global.html#CB_forceString">CB_forceString</a></li><li><a href="global.html#CB_getBase64StringObject">CB_getBase64StringObject</a></li><li><a href="global.html#CB_getCookie">CB_getCookie</a></li><li><a href="global.html#CB_getDatum">CB_getDatum</a></li><li><a href="global.html#CB_getJSONPropertyValue">CB_getJSONPropertyValue</a></li><li><a href="global.html#CB_getLZStringObject">CB_getLZStringObject</a></li><li><a href="global.html#CB_getValueIndex">CB_getValueIndex</a></li><li><a href="global.html#CB_getValuePath">CB_getValuePath</a></li><li><a href="global.html#CB_includeJSFile">CB_includeJSFile</a></li><li><a href="global.html#CB_indexOf">CB_indexOf</a></li><li><a href="global.html#CB_init">CB_init</a></li><li><a href="global.html#CB_intToBase">CB_intToBase</a></li><li><a href="global.html#CB_isArray">CB_isArray</a></li><li><a href="global.html#CB_isEmail">CB_isEmail</a></li><li><a href="global.html#CB_isFileLocal">CB_isFileLocal</a></li><li><a href="global.html#CB_isString">CB_isString</a></li><li><a href="global.html#CB_lastIndexOf">CB_lastIndexOf</a></li><li><a href="global.html#CB_ltrim">CB_ltrim</a></li><li><a href="global.html#CB_nl2br">CB_nl2br</a></li><li><a href="global.html#CB_nlToBr">CB_nlToBr</a></li><li><a href="global.html#CB_numberFormat">CB_numberFormat</a></li><li><a href="global.html#CB_numberOfDecimalDigits">CB_numberOfDecimalDigits</a></li><li><a href="global.html#CB_numberOfDecimals">CB_numberOfDecimals</a></li><li><a href="global.html#CB_numberOfIntegerDigits">CB_numberOfIntegerDigits</a></li><li><a href="global.html#CB_parseJSON">CB_parseJSON</a></li><li><a href="global.html#CB_parseString">CB_parseString</a></li><li><a href="global.html#CB_regularExpressionString">CB_regularExpressionString</a></li><li><a href="global.html#CB_renderString">CB_renderString</a></li><li><a href="global.html#CB_replaceAll">CB_replaceAll</a></li><li><a href="global.html#CB_rtrim">CB_rtrim</a></li><li><a href="global.html#CB_scriptPath">CB_scriptPath</a></li><li><a href="global.html#CB_scriptPathCalculate">CB_scriptPathCalculate</a></li><li><a href="global.html#CB_setCookie">CB_setCookie</a></li><li><a href="global.html#CB_setDatum">CB_setDatum</a></li><li><a href="global.html#CB_sizeOf">CB_sizeOf</a></li><li><a href="global.html#CB_sizeof">CB_sizeof</a></li><li><a href="global.html#CB_stringifyJSON">CB_stringifyJSON</a></li><li><a href="global.html#CB_symmetricCall">CB_symmetricCall</a></li><li><a href="global.html#CB_symmetricCallClear">CB_symmetricCallClear</a></li><li><a href="global.html#CB_this">CB_this</a></li><li><a href="global.html#CB_trim">CB_trim</a></li>
51 </ul>
52 </li>
53
54 </ul>
55
56 <div class="col-sm-3 col-md-3">
57 <form class="navbar-form" role="search">
58 <div class="input-group">
59 <input type="text" class="form-control" placeholder="Search" name="q" id="search-input">
60 <div class="input-group-btn">
61 <button class="btn btn-default" id="search-submit"><i class="glyphicon glyphicon-search"></i></button>
62 </div>
63 </div>
64 </form>
65 </div>
66
67 </div>
68
69</div>
70</div>
71
72
73<div class="container" id="toc-content" style="width:100%;">
74<div class="row" style="width:100%;">
75
76
77 <div class="col-md-12">
78
79 <div id="main">
80
81
82 <h1 class="page-title">Source: CrossBrowdy.js</h1>
83
84<section>
85 <article>
86 <pre
87 class="sunlight-highlight-javascript linenums">// CrossBrowdy by Joan Alba Maldonado (workindalian@gmail.com).
88
89/**
90 * @file Main CrossBrowdy file.
91 * @author Joan Alba Maldonado &lt;workindalian@gmail.com>
92 * @license Creative Commons Attribution 4.0 International. See more at {@link https://crossbrowdy.com/about#what_is_the_crossbrowdy_copyright_and_license}.
93 * @todo Clear all timeouts before creating them (just in case).
94 */
95
96
97//CrossBrowdy constants and variables:
98/**
99 * Keeps the name of the script (the main script will use this name with the ".js" extension). Case sensitive.
100 * @constant
101 * @type {string}
102 * @default
103 */
104var CB_NAME = "CrossBrowdy";
105
106/**
107 * CrossBrowdy version.
108 * @constant
109 * @type {string}
110 */
111var CB_VERSION = "0.99.96.33";
112
113/**
114 * Keeps the CrossBrowdy "this" context.
115 * @constant
116 * @type {Object}
117 */
118var CB_this = this;
119
120/**
121 * Two-dimensional object defined by the user with the desired options for CrossBrowdy and its modules. The options supported are the ones used by the {@link CB_Configuration} object.
122 &lt;br>
123 First-level indexes should belong to the module name (or to "CrossBrowdy", for general options) and second-level indexes should belong to the option name.
124 &lt;br>
125 Example:
126 &lt;br>
127 {
128 CrossBrowdy:
129 {
130 CB_console_ALLOW_ALERTS: false
131 },
132 CrossBase:
133 {
134 SLCANVAS_LOAD : true,
135 FLASHCANVAS_LOAD : true
136 }
137 }
138
139 * @constant CB_OPTIONS
140 * @type {Object}
141 * @default undefined
142 */
143
144/**
145 * Static class to manage the configuration. It will be overwritten with the values defined in {@link CB_OPTIONS} (if any).
146 &lt;br>
147 First-level indexes should belong to the module name and second-level indexes should belong to the option name.
148 &lt;br>
149 Follows the same format as {@link CB_OPTIONS}.
150 * @namespace
151*/
152var CB_Configuration = {};
153
154/**
155 Property that contains an object with the options for the main script.
156 * @namespace CB_Configuration.CrossBrowdy
157 */
158CB_Configuration[CB_NAME] =
159{
160 /**
161 * Default path of the script (path can be changed when {@link CB_init} is called)
162 * @memberof CB_Configuration.CrossBrowdy
163 * @constant
164 * @type {string}
165 * @default {@link CB_NAME} + "/"
166 */
167 SCRIPT_PATH_DEFAULT: "../" + CB_NAME + "/",
168
169
170 /**
171 * Defines whether to show the splash screen in the beginning by default or not.
172 * @memberof CB_Configuration.CrossBrowdy
173 * @constant
174 * @type {boolean}
175 * @default
176 */
177 SHOW_SPLASH_SCREEN_DEFAULT: true,
178
179
180 /**
181 * Defines whether to register statistics or not. If it is enabled, the URL defined in {@link CB_Configuration.CrossBrowdy.STATS_URL} will be called (by including it as a JavaScript file) as soon as CrossBrowdy gets called (might not be ready yet).
182 * This parameter do not do anything else, just includes your desired URL (defined in {@link CB_Configuration.CrossBrowdy.STATS_URL}) as a JavaScript file when CrossBrowdy is called.
183 * @memberof CB_Configuration.CrossBrowdy
184 * @constant
185 * @type {boolean}
186 * @default false
187 */
188 STATS: false,
189
190
191 /**
192 * URL to register the statistics if {@link CB_Configuration.CrossBrowdy.STATS} is enabled. When {@link CB_Configuration.CrossBrowdy.STATS} is enabled, this URL will be included as a JavaScript file as soon as CrossBrowdy gets called (might not be ready yet).
193 * The URL will be called (included in the document as a JavaScript file) adding three parameters: "cb" parameter with the CrossBrowdy version as the value, "time" with a timestamp which belongs to the current time of the client and "url" parameter with the current URL visited by the user as the value.
194 * @memberof CB_Configuration.CrossBrowdy
195 * @constant
196 * @type {string}
197 * @default
198 */
199 STATS_URL: "https://crossbrowdy.com/_stats/CB_stats.php",
200
201
202 /**
203 * Defines whether to allow the use of alert()'s as a fallback when using {@link CB_console} and neither the [console]{@link https://developer.mozilla.org/en-US/docs/Web/API/Console} object nor a DOM element with "CB_console" ID are found.
204 * @memberof CB_Configuration.CrossBrowdy
205 * @constant
206 * @type {boolean}
207 * @default
208 */
209 CB_console_ALLOW_ALERTS: true,
210
211
212 /**
213 * Default milliseconds before firing the timeout callback for the {@link CB_includeJSFile} function.
214 * @memberof CB_Configuration.CrossBrowdy
215 * @constant
216 * @type {int}
217 * @default
218 */
219 CB_includeJSFile_TIMEOUT_MS_DEFAULT: 90000
220};
221
222
223
224/**
225 * It will contain the CrossBrowdy path when it finally loads.
226 * @var
227 * @readonly
228 * @type {string}
229 * @default {@link CB_scriptPathCalculate}();
230 */
231var CB_scriptPath = CB_scriptPathCalculate(); //Can be modified later.
232
233
234//Applies the options set by the user (if any):
235CB_applyOptions(CB_NAME, CB_this);
236
237
238//Needed modules:
239/**
240 * Static class that contains all the modules and the tools to manage them.
241 * @namespace
242 */
243var CB_Modules = {};
244CB_Modules.modules = {};
245
246/**
247 * Enum which defines possible module statuses.
248 * @memberof CB_Modules
249 * @readonly
250 * @enum {integer} CB_Modules.STATUSES
251 */
252CB_Modules.STATUSES =
253{
254 /** The module has failed to load. */
255 FAILED: -1,
256 /** The module has an unkwnown status. */
257 UNKNOWN : 0,
258 /** The module is not loaded yet. Default status. */
259 UNLOADED : 1,
260 /** The module is being loading. */
261 LOADING : 2,
262 /** The module has loaded successfully (coudl be not ready yet). */
263 LOADED : 3,
264 /** The module has loaded successfully and it is ready to be used. */
265 READY : 4
266};
267
268/**
269 * Callback that is called before loading a file and should return true if we want to load the file or false otherwise.
270 * @memberof CB_Modules
271 * @callback CB_Modules.neededFile_LOAD_CHECKER
272 * @param {string} filepath - Filepath of the needed file (including the filename).
273 * @param {CB_Modules.NEEDED_FILE} neededFile - Object that contains the needed file.
274 * @returns {boolean} - Returns true if we want to load the file or false otherwise.
275 */
276
277/**
278 * Object that contains a needed file for a module.
279 * @memberof CB_Modules
280 * @typedef {Object} CB_Modules.NEEDED_FILE
281 * @property {boolean} [load=false] - Defines whether to load the file or not.
282 * @property {boolean} [mandatory=false] - Defines whether the file is mandatory. If the file is not mandatory, its module could be declared as loaded successfully before the file is loaded (and maybe never will).
283 * @property {boolean} [absolutePath=false] - Defines whether the path of the file is relative to the path of the main script or absolute.
284 * @property {CB_Modules.neededFile_LOAD_CHECKER} [loadChecker] - Callback that will be called when the file tries to be loaded and should return true if the file needs to be loaded.
285 * @property {string} [id] - Desired string to identify the file.
286 * @property {array} [requires] - Array of strings with the IDs of the files that must be loaded before loading this file. The file will not be loaded until the required files are loaded first.
287 */
288
289 /**
290 * Object that contains the needed files for a module. Each property will represent a needed file.
291 * @memberof CB_Modules
292 * @typedef {Object} CB_Modules.NEEDED_FILES
293 * @property {CB_Modules.NEEDED_FILE} path_to_the_file - Object that contains a needed file for a module. The property name must be either the path to the file or a variable containing it. Tto use a variable, the name of the property must start with "VALUEOF_" and continue with the name of the variable. In the case that the variable is an object, each property must be separated by a dot (".").
294 */
295
296
297 /**
298 * Object that contains a needed module for a parent module.
299 * @memberof CB_Modules
300 * @typedef {Object} CB_Modules.NEEDED_MODULE
301 * @property {string} name - Name of the module.
302 * @property {CB_Modules.NEEDED_FILES} neededFiles - Object containing the needed files.
303 */
304
305 /**
306 * Callback for the different events of a module.
307 * @memberof CB_Modules
308 * @callback CB_Modules.CALLBACK
309 * @param {string} scriptPath - The value for the "scriptPath" parameter used by {@link CB_init} when it was called.
310 */
311
312/**
313 * Object that contains a module.
314 * @memberof CB_Modules
315 * @typedef {Object} CB_Modules.MODULE
316 * @property {string} name - Name of the module.
317 * @property {CB_Modules.STATUSES} status - Module status.
318 * @property {CB_Modules.CALLBACK} onCall - Callback for when the module is called to be loaded. Being "this" the {@link CB_Modules.MODULE} object itself.
319 * @property {CB_Modules.CALLBACK} onLoad - Callback for when the module loads successfully. Being "this" the {@link CB_Modules.MODULE} object itself.
320 * @property {CB_Modules.CALLBACK} onReady - Callback for when the module is totally ready. Being "this" the {@link CB_Modules.MODULE} object itself.
321 * @property {CB_Modules.CALLBACK} onFail - Callback for when the module fails to load. Being "this" the {@link CB_Modules.MODULE} object itself. NOT IMPLEMENTED YET.
322 * @property {CB_Modules.NEEDED_FILES} neededFiles - Object containing the needed files.
323 * @property {array} neededModules - Array of {@link CB_Modules.NEEDED_MODULE} objects, containing the needed modules.
324 * @property {string} credits - Credits of the module.
325 */
326
327//Main module basic configuration:
328/**
329 * Contains all the modules, one per property.
330 * @var CB_Modules.modules
331 * @type {Object}
332 * @property {CB_Modules.MODULE} name_of_the_module - Object that contains the module data. The property name must be the name of the module.
333 */
334CB_Modules.modules[CB_NAME] =
335{
336 //Name of the module:
337 "name" : CB_NAME,
338 //Status (UNKNOWN, UNLOADED, LOADING, LOADED, READY or FAILED):
339 "status" : CB_Modules.STATUSES.UNLOADED,
340 //Function to call as soon as the module is called (before loading its scripts):
341 "onCall" :
342 function(scriptPathGiven)
343 {
344 if (CB_Configuration[CB_NAME].STATS) { CB_sendStats(); } //If we want, includes the file for statistics purposes.
345 CB_Modules.setStatus(CB_NAME, CB_Modules.STATUSES.LOADED);
346 },
347 //Callback function to call when the module has been loaded successfully:
348 "onLoad" :
349 function(scriptPathGiven)
350 {
351 CB_Modules.setStatus(CB_NAME, CB_Modules.STATUSES.READY);
352 },
353 //Callback function to call when the module is ready:
354 "onReady" :
355 function(scriptPathGiven)
356 {
357 CB_scriptPath = scriptPathGiven; //The path given was correct so we set it.
358 CB_ready = true; //Set as it's ready.
359 },
360 //Callback function to call when module has not been loaded successfully:
361 //"onFail" => null,
362 //Needed files:
363 "neededFiles" : null, //Format: "needed_file" : { load: needs_to_be_loaded, [mandatory: needed_to_begin_CrossBrowdy], [absolutePath: relative_to_CrossBrowdy_path_or_absolute], [loadChecker: function that will be called and return true if the file needs to be loaded], [id: file_identifier_string], [requires: array_with_required_ids_of_files_required] }
364 //Needed modules:
365 "neededModules" :
366 [
367 {
368 "name" : "CrossBase",
369 //Format: "needed_file" : { load: needs_to_be_loaded, [mandatory: needed_to_begin_CrossBrowdy], [absolutePath: relative_to_CrossBrowdy_path_or_absolute], [loadChecker: function that will be called and return true if the file needs to be loaded], [id: file_identifier_string], [requires: array_with_required_ids_of_files_required] }
370 "neededFiles" : { "CrossBase/CrossBase.js" : { load: true, mandatory: true } }
371 }
372 ],
373 //Credits:
374 "credits" : "[CB] " + CB_NAME + " " + CB_VERSION + " by Joan Alba Maldonado&lt;br />"
375};
376
377//Sets default credits:
378/**
379 * Default credits.
380 * @var
381 * @readonly
382 * @type {string}
383 * @default
384 */
385var CB_CREDITS_DEFAULT = "";
386CB_addCredits(CB_Modules.modules[CB_NAME]["credits"]);
387
388
389//If now() static function not available, uses getTime() method:
390if (!Date.now) { Date.now = function() { return new Date().getTime(); }; }
391
392
393/**
394 * Attaches the given credits to the default ones (to {@link CB_CREDITS_DEFAULT}).
395 * @function
396 * @param {string} credits - Path to the JS file.
397 * @returns {string} Returns the default credits after attaching the given ones.
398 */
399 function CB_addCredits(credits)
400 {
401 return CB_CREDITS_DEFAULT += credits;
402 }
403
404
405/**
406 * Alias for the "console" function which fallbacks to a DOM element with "CB_console" id (its CSS "style" attribute will be modified if needed, which means that its "display" property will be set to "block" if it is "none" and its "visibility" property to "visible" regardless its previous value) or even to an alert when it is not available ("alert" will only be used as a fallback in the case that the {@link CB_console_ALLOW_ALERTS} parameter is set to true).
407 * @function
408 * @param {string} message - Message to display
409 * @todo When "console" is not available and it gets polyfilled, allow more parameters (use "arguments").
410 */
411var CB_console;
412if (typeof(console) !== "undefined" &amp;&amp; typeof(console.log) !== "undefined")
413{
414 if (typeof(console.log.apply) !== "undefined")
415 {
416 CB_console = function() { console.log.apply(console, arguments); };
417 }
418 else
419 {
420 CB_console = console.log;
421 }
422}
423else
424{
425 CB_console =
426 function(message) //TODO: allow more parameters (use "arguments").
427 {
428 message += "";
429 var CB_consoleElement = document.getElementById("CB_console");
430 if (CB_consoleElement !== null)
431 {
432 CB_consoleElement.style.visibility = "visible";
433 if (CB_consoleElement.style.display === "none") { CB_consoleElement.style.display = "block"; }
434 CB_consoleElement.innerHTML += message.replace(/\n/gi, "&lt;br />") + "&lt;br />";
435 CB_consoleElement.scrollTop = CB_consoleElement.scrollHeight;
436 }
437 else if (CB_Configuration[CB_NAME].CB_console_ALLOW_ALERTS) { alert(message); }
438 };
439 console = { log : CB_console };
440}
441
442
443var CB_filesRequested = {};
444var CB_filesLoaded = [];
445var CB_filesLoadedIds = {};
446/**
447 * Callback for when the file is included successfully or fails to load.
448 * @callback CB_includeJSFile_CALLBACK
449 * @param {string} filepath - The 'filepath' parameter when {@link CB_includeJSFile} was called (if any).
450 * @param {CB_includeJSFile_CALLBACK} callbackOk - The 'callbackOk' parameter when {@link CB_includeJSFile} was called (if any).
451 * @param {CB_includeJSFile_CALLBACK} callbackError - The 'callbackError' parameter when {@link CB_includeJSFile} was called (if any).
452 * @param {integer} timeoutMs - The 'timeoutMs' parameter when {@link CB_includeJSFile} was called (if any).
453 * @param {boolean} asynchronously - The 'asynchronously' parameter when {@link CB_includeJSFile} was called (if any).
454 */
455
456/**
457 * Includes a JavaScript file to the current document.
458 * @function
459 * @param {string} filepath - Path to the JS file.
460 * @param {CB_includeJSFile_CALLBACK} [callbackOk] - Callback for when the file is included successfully.
461 * @param {CB_includeJSFile_CALLBACK} [callbackError] - Callback for when there is any error including the file or it cannot be included after the defined timeout.
462 * @param {integer} [timeoutMs={@link CB_Configuration.CrossBrowdy.CB_includeJSFile_TIMEOUT_MS_DEFAULT}] - Timeout in milliseconds to consider that the inclusion of the file has failed.
463 * @param {boolean} [asynchronously=true] - Defines whether to load the file asynchronously or not.
464 * @param {string} [fileId] - Internal usage recommended only.
465 * @param {array} [fileRequires] - Internal usage recommended only.
466 * @param {boolean} [notMandatory=false] - Internal usage recommended only.
467 * @returns {Object|null|false} Returns null when the script file cannot be loaded yet as some required file has still not been loaded. Returns false when neither the 'HEAD' tag nor the document body can be found. Otherwise, returns an object whose two properties are 'scriptElement' (with the [SCRIPT]{@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script} element just created) and 'timeoutFailure' (with the [setTimeout]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout} ID created to check whether the file cannot be loaded after the given time).
468 */
469function CB_includeJSFile(filepath, callbackOk, callbackError, timeoutMs, asynchronously, fileId, fileRequires, notMandatory)
470{
471 //If the file requires another one and it has still not loaded, calls the function again after a while:
472 if (fileRequires &amp;&amp; typeof(fileRequires.length) !== "undefined" &amp;&amp; fileRequires.length > 0)
473 {
474 for (var x = 0; x &lt; fileRequires.length; x++)
475 {
476 if (!CB_filesLoadedIds[fileRequires[x]])
477 {
478 setTimeout(function() { CB_includeJSFile(filepath, callbackOk, callbackError, timeoutMs, asynchronously, fileId, fileRequires, notMandatory); }, 10);
479 return null;
480 }
481 }
482 }
483
484 //If not given, uses the default timeout:
485 timeoutMs = timeoutMs || CB_Configuration[CB_NAME].CB_includeJSFile_TIMEOUT_MS_DEFAULT
486
487 //If not given, uses the default value for the 'asynchronously' parameter:
488 if (asynchronously !== false) { asynchronously = true; }
489
490 //Stores the file as not loaded in the array:
491 if (!notMandatory) { CB_filesRequested[filepath] = true; }
492
493 //var parentElement = document.getElementsByTagName("head") || document.head || document.getElementsByTagName("body") || document.body || document.documentElement;
494 var parentElement = CB_getElementsByTagName("head");
495 if (parentElement.length === 0) { parentElement = document.head || CB_getElementsByTagName("body"); }
496 if (parentElement.length === 0) { parentElement = document.body || document.documentElement || null; }
497 if (parentElement &amp;&amp; typeof(parentElement[0]) === "undefined") { parentElement = [parentElement]; }
498 if (typeof(parentElement) === "undefined" || parentElement === null || typeof(parentElement[0]) === "undefined" || parentElement[0] === null)
499 {
500 CB_console("[ERROR] Neither &lt;HEAD> tag nor document body could be found! (CB_includeJSFile)");
501 if (typeof(callbackError) === "function") { callbackError(filepath, callbackOk, callbackError, timeoutMs, asynchronously); }
502 return false;
503 }
504
505 parentElement = parentElement[0];
506
507 var scriptTag = document.createElement("script");
508 scriptTag.src = filepath;
509 scriptTag.language = "javascript";
510 scriptTag.type = "text/javascript";
511 scriptTag.async = asynchronously;
512
513 parentElement.appendChild(scriptTag);
514
515 var onLoadExecuted = false;
516 var onLoad =
517 function()
518 {
519 this.onreadystatechange = this.onload = null;
520 setTimeout
521 (
522 function()
523 {
524 if (onErrorExecuted || onLoadExecuted) { return; } //Exists if the timeout has already been executed.
525 onLoadExecuted = true;
526
527 //Stores the file as already loaded in the array:
528 CB_filesRequested[filepath] = false;
529 CB_filesLoaded[CB_filesLoaded.length] = filepath;
530 if (fileId) { CB_filesLoadedIds[fileId] = true; }
531
532 //If defined, calls the OK function:
533 if (typeof(callbackOk) === "function") { callbackOk(filepath, callbackOk, callbackError, timeoutMs, asynchronously); }
534 },
535 10
536 );
537 };
538
539 if (scriptTag.readyState)
540 {
541 scriptTag.onreadystatechange =
542 function()
543 {
544 if (this.readyState === "loaded" || this.readyState === "complete") { onLoad(); }
545 };
546 }
547 else { scriptTag.onload = onLoad; }
548
549 var onErrorExecuted = false;
550 var onError =
551 function()
552 {
553 if (onErrorExecuted || onLoadExecuted) { return; } //Exists if the onLoad has been already executed.
554 onErrorExecuted = true;
555
556 //Stores the file as failed to load in the array:
557 CB_filesRequested[filepath] = null;
558
559 if (typeof(callbackError) === "function") { callbackError(filepath, callbackOk, callbackError, timeoutMs, asynchronously); }
560 };
561 scriptTag.onerror = onError;
562
563 //Starts counting for the timeout:
564 var callbackErrorTimeout = setTimeout(onError, timeoutMs);
565
566 return { scriptElement: scriptTag, timeoutFailure: callbackErrorTimeout };
567}
568
569
570
571/**
572 * Callback for when the script is loaded successfully. Without parameters.
573 * @callback CB_includeRequiredFileErrorCallback
574 * @param {string} filepath - The 'filepath' parameter when {@link CB_includeJSFile} was called internally (if any).
575 * @param {CB_includeJSFile_CALLBACK} callbackOk - The 'callbackOk' parameter when {@link CB_includeJSFile} was called internally (if any).
576 * @param {CB_includeJSFile_CALLBACK} callbackError - The 'callbackError' parameter when {@link CB_includeJSFile} was called internally (if any).
577 * @param {integer} timeoutMs - The 'timeoutMs' parameter when {@link CB_includeJSFile} was called internally (if any).
578 * @param {boolean} asynchronously - The 'asynchronously' parameter when {@link CB_includeJSFile} was called (if any).
579 * @param {object} filesRequested - Object whose indexes are all the filepaths of the script files requested so far and the value is true when the file is still loading (or to be loaded in the future), false if it was loaded successfully (the most likely) or null if it failed to load.
580 * @param {array} filesLoaded - Numeric array whose values are the filepaths of the script files loaded successfully so far.
581 */
582
583//Function executed when a required file cannot be loaded (because of an error or timeout):
584CB_Modules._includeRequiredFileError = function(filepath, callbackOk, callbackError, timeoutMs, asynchronously)
585{
586 CB_console("[CB] [ERROR] Script file failed to load: " + filepath);
587 if (typeof(CB_initOnErrorLoadingFile) === "function") { CB_initOnErrorLoadingFile(filepath, callbackOk, callbackError, timeoutMs, asynchronously, CB_filesRequested, CB_filesLoaded); }
588}
589
590
591//Function that includes all required files:
592CB_Modules._includeAllRequiredFiles = function(CB_scriptPathGiven, neededFiles, callbackOk)
593{
594 //Parses the neededFiles object to turn variable keys into the real value of those variables:
595 var currentValue = null;
596 var allIndexes = null;
597 var allIndexesLength = 0;
598 var x = 0;
599 for (var currentFile in neededFiles)
600 {
601 if (currentFile.substring(0, 8) === "VALUEOF_")
602 {
603 allIndexes = currentFile.substring(8).split(".");
604 allIndexesLength = allIndexes.length;
605 currentValue = CB_this;//window;
606 for (var x = 0; x &lt; allIndexesLength; x++)
607 {
608 if (typeof(currentValue[allIndexes[x]]) !== "undefined" &amp;&amp; currentValue[allIndexes[x]] !== null) { currentValue = currentValue[allIndexes[x]]; }
609 else { break; }
610 }
611 if (typeof(currentValue) !== "string" &amp;&amp; !(currentValue instanceof String)) { currentValue = ""; }
612
613 if (currentValue !== "") { neededFiles[currentValue] = { load: neededFiles[currentFile].load, loadChecker: neededFiles[currentFile].loadChecker, mandatory: neededFiles[currentFile].mandatory, id: neededFiles[currentFile].id, requires: neededFiles[currentFile].requires }; }
614
615 neededFiles[currentFile].load = false; //It contains the key without parsing, so we set as we don't need it to load it to ignore it.
616 neededFiles[currentFile].disabled = true; //Disables it.
617 }
618 }
619
620 //Includes all files needed:
621 var neededFilesPending = 0;
622 for (currentFile in neededFiles)
623 {
624 if (neededFiles[currentFile].disabled) { continue; }
625
626 //Performs the load checker that can change the load property (if any):
627 if (typeof(neededFiles[currentFile].loadChecker) === "function" &amp;&amp; neededFiles[currentFile].load) { neededFiles[currentFile].load = neededFiles[currentFile].loadChecker(currentFile, neededFiles[currentFile]); }
628
629 //If the file needs to be loaded, we load it:
630 if (neededFiles[currentFile].load)
631 {
632 new function(currentFile) //Creates a new scope because we are in a loop.
633 {
634 var functionWhenLoad = null;
635 if (neededFiles[currentFile].mandatory) //Only increases and decreases counter for mandatory files.
636 {
637 neededFilesPending++;
638 functionWhenLoad =
639 function(filepath, callbackOk, callbackError, timeoutMs)
640 {
641 neededFilesPending--;
642 if (typeof(neededFiles) !== "undefined" &amp;&amp; neededFiles !== null &amp;&amp; typeof(neededFiles[currentFile]) !== "undefined" &amp;&amp; neededFiles[currentFile] !== null)
643 {
644 neededFiles[currentFile].load = false; //We have loaded it and don't need to load it more.
645 }
646 };
647 }
648 var scriptPath = CB_scriptPathGiven;
649 if (neededFiles[currentFile].absolutePath) { scriptPath = ""; }
650 CB_includeJSFile(scriptPath + currentFile, functionWhenLoad, CB_Modules._includeRequiredFileError, undefined, undefined, neededFiles[currentFile].id, neededFiles[currentFile].requires);
651 }(currentFile);
652 }
653 }
654
655 //Interval that will check when all the modules has been loaded:
656 var allRequiredFilesLoaded =
657 function()
658 {
659 if (neededFilesPending &lt;= 0 &amp;&amp; typeof(callbackOk) === "function")
660 {
661 callbackOk();
662 }
663 else if (typeof(callbackOk) === "function")
664 {
665 setTimeout(allRequiredFilesLoaded, 1);
666 }
667 };
668 allRequiredFilesLoaded();
669}
670
671
672
673//Function that includes all required modules:
674CB_Modules._includeAllRequiredModules = function(CB_scriptPathGiven, modules, callbackOk)
675{
676 if (typeof(modules) === "undefined" || modules === null) { return; }
677
678 var modulesLength = modules.length;
679 var neededModulesPending = 0;
680 for (var x = 0; x &lt; modulesLength; x++)
681 {
682 if (typeof(modules[x].name) !== "undefined" &amp;&amp; typeof(modules[x].neededFiles) !== "undefined" &amp;&amp; modules[x].neededFiles)
683 {
684 neededModulesPending++;
685 new function(moduleName) //Closure to keep moduleName value for every loop.
686 {
687 CB_Modules._includeAllRequiredFiles
688 (
689 CB_scriptPathGiven,
690 modules[x]["neededFiles"],
691 function()
692 {
693 setTimeout
694 (
695 function()
696 {
697 CB_Modules._initializeModule(CB_scriptPathGiven, moduleName);
698 neededModulesPending--;
699 },
700 10
701 );
702 }
703 );
704 }(modules[x].name);
705 }
706 }
707
708 //Interval that will check when all the modules has been loaded:
709 var allRequiredModulesLoaded =
710 function()
711 {
712 if (neededModulesPending &lt;= 0 &amp;&amp; typeof(callbackOk) === "function")
713 {
714 callbackOk();
715 }
716 else if (typeof(callbackOk) === "function")
717 {
718 setTimeout(allRequiredModulesLoaded, 1);
719 }
720 };
721 allRequiredModulesLoaded();
722}
723
724
725
726//Tells the number of required files loaded:
727CB_Modules._numberFilesLoaded = function(neededFiles, onlyMandatory)
728{
729 //Checks all files needed:
730 var numberNeededFilesLoaded = 0;
731 for (var currentFile in neededFiles)
732 {
733 //Checks whether the needed file has been loaded:
734 if (neededFiles[currentFile].load)
735 {
736 if (!onlyMandatory || neededFiles[currentFile].mandatory)
737 {
738 numberNeededFilesLoaded++;
739 }
740 }
741 }
742 return numberNeededFilesLoaded;
743}
744
745
746//Checks whether all required files have been loaded:
747CB_Modules._allFilesLoaded = function(neededFiles, onlyMandatory)
748{
749 //Checks all files needed:
750 var allFilesNeededIncluded = true;
751 for (var currentFile in neededFiles)
752 {
753 //If the file has not been included yet, exits the bucle:
754 if (neededFiles[currentFile].load)
755 {
756 if (!onlyMandatory || neededFiles[currentFile].mandatory)
757 {
758 allFilesNeededIncluded = false; break;
759 }
760 }
761 }
762 return allFilesNeededIncluded;
763}
764
765
766//Checks whether all required modules have been loaded:
767CB_Modules._allModulesLoaded = function(neededModules, onlyMandatory)
768{
769 if (typeof(neededModules) === "undefined" || neededModules === null) { return true; }
770 var allModulesNeededIncluded = true;
771 var neededModulesLength = neededModules.length;
772 for (var x = 0; x &lt; neededModulesLength; x++)
773 {
774 if (typeof(neededModules[x].name) !== "undefined" &amp;&amp; typeof(neededModules[x].neededFiles) !== "undefined" &amp;&amp; neededModules[x].neededFiles)
775 {
776 if (!CB_Modules._allFilesLoaded(neededModules[x].neededFiles, onlyMandatory)) { allModulesNeededIncluded = false; break; }
777 }
778 }
779 return allModulesNeededIncluded;
780}
781
782
783//Checks whether a given module is ready or not:
784CB_Modules._moduleReady = function(moduleName)
785{
786 return (CB_Modules._getModuleStatus(moduleName) === CB_Modules.STATUSES.READY);
787}
788
789
790//Checks whether all required modules are ready:
791CB_Modules._allModulesReady = function(neededModules)
792{
793 if (typeof(neededModules) === "undefined" || neededModules === null) { return true; }
794 var allModulesNeededReady = true;
795 var neededModulesLength = neededModules.length;
796 for (var x = 0; x &lt; neededModulesLength; x++)
797 {
798 if (typeof(neededModules[x].name) !== "undefined" &amp;&amp; typeof(neededModules[x].neededFiles) !== "undefined" &amp;&amp; neededModules[x].neededFiles)
799 {
800 if (!CB_Modules._moduleReady(neededModules[x].name)) { allModulesNeededReady = false; break; }
801 }
802 }
803 return allModulesNeededReady;
804}
805
806
807//Returns the status of a given module:
808CB_Modules._getModuleStatus = function(moduleName)
809{
810 if (typeof(CB_Modules.modules[moduleName]) !== "undefined" &amp;&amp; typeof(CB_Modules.modules[moduleName].status) !== "undefined")
811 {
812 return CB_Modules.modules[moduleName].status;
813 }
814 else { return CB_Modules.STATUSES.UNKNOWN; }
815}
816
817
818/**
819 * Sets a status for a given module.
820 * @memberof CB_Modules
821 * @function
822 * @param {string} moduleName - Name of the module.
823 * @param {integer} status - The desired status. Must be a value that exists in the {@link CB_Modules.STATUSES} enum.
824 * @returns {boolean} It will return true if succeeded or false otherwise.
825 */
826CB_Modules.setStatus = function(moduleName, status)
827{
828 if (typeof(CB_Modules.modules[moduleName]) !== "undefined")
829 {
830 CB_Modules.modules[moduleName].status = status;
831 }
832}
833
834
835//Function that initializes a module:
836//var CB_allFilesLoadedInterval; //Interval that checks if CrossBrowdy is ready or not.
837CB_Modules._initializeModule = function(CB_scriptPathGiven, moduleName)
838{
839 //It the module still does not exist (status is unknown), tries to load it again after some time:
840 if (CB_Modules._getModuleStatus(moduleName) === CB_Modules.STATUSES.UNKNOWN) { setTimeout(function() { CB_Modules._initializeModule(CB_scriptPathGiven, moduleName); }, 1); return; }
841
842 CB_Modules.setStatus(moduleName, CB_Modules.STATUSES.LOADING);
843
844 if (typeof(CB_Modules.modules[moduleName]["onCall"]) === "function")
845 {
846 CB_Modules.modules[moduleName]["onCall"].call(CB_Modules.modules[moduleName], CB_scriptPathGiven);
847 }
848
849 //Applies default path if it was not sent:
850 if (typeof(CB_scriptPathGiven) === "undefined" || CB_scriptPathGiven === null)
851 {
852 CB_scriptPathGiven = CB_scriptPathCalculate();
853 }
854
855 //Includes required files:
856 CB_Modules._includeAllRequiredFiles(CB_scriptPathGiven, CB_Modules.modules[moduleName]["neededFiles"]);
857
858 //Includes required modules:
859 CB_Modules._includeAllRequiredModules(CB_scriptPathGiven, CB_Modules.modules[moduleName]["neededModules"]);
860
861 //Show credits in console:
862 CB_console(CB_credits(CB_Modules.modules[moduleName]["credits"], false));
863
864 //Interval that checks if CrossBrowdy is ready (and initializes the static objects):
865 var onLoadProcessed = false;
866 var onReadyProcessed = false;
867 var CB_allFilesLoadedCheck =
868 function()
869 {
870 var loopAgain = true;
871 //If all files needed are loaded (mandatory files only):
872 if (CB_Modules._allFilesLoaded(CB_Modules.modules[moduleName]["neededFiles"], true))
873 {
874 //If all needed modules are loaded (mandatory module files only):
875 if (CB_Modules._allModulesLoaded(CB_Modules.modules[moduleName]["neededModules"], true))
876 {
877 //If defined, executes the onLoad function of the module:
878 if (!onLoadProcessed &amp;&amp; typeof(CB_Modules.modules[moduleName]["onLoad"]) === "function")
879 {
880 onLoadProcessed = true;
881 CB_Modules.modules[moduleName]["onLoad"].call(CB_Modules.modules[moduleName], CB_scriptPathGiven);
882 }
883
884 //If all needed modules are ready:
885 if (CB_Modules._allModulesReady(CB_Modules.modules[moduleName]["neededModules"]))
886 {
887 //If the module itself is ready:
888 if (CB_Modules._moduleReady(moduleName))
889 {
890 //If defined, executes the onReady function of the module:
891 if (!onReadyProcessed &amp;&amp; typeof(CB_Modules.modules[moduleName]["onReady"]) === "function")
892 {
893 onReadyProcessed = true;
894 CB_Modules.modules[moduleName]["onReady"].call(CB_Modules.modules[moduleName], CB_scriptPathGiven);
895 }
896 loopAgain = false;
897 }
898 }
899 }
900 }
901 if (loopAgain) { setTimeout(CB_allFilesLoadedCheck, 1); }
902 };
903 CB_allFilesLoadedCheck();
904}
905
906
907/**
908 * Returns a {@link CB_Modules.MODULE} object for module management.
909 * @memberof CB_Modules
910 * @function
911 * @param {string} moduleName - Name of the desired module.
912 * @returns {CB_Modules.MODULE|null} If found, it will return the {@link CB_Modules.MODULE} object desired. Otherwise, it will return null.
913 */
914CB_Modules.get = function(moduleName)
915{
916 if (typeof(CB_Modules.modules[moduleName]) !== "undefined")
917 {
918 return CB_Modules.modules[moduleName];
919 }
920 return null;
921}
922
923
924/**
925 * Gets the value of a desired module property (or returns null).
926 * @memberof CB_Modules
927 * @function
928 * @param {string} moduleName - Name of the desired module.
929 * @param {string} property - Name of the desired property.
930 * @returns {*|null} If found, it will return the value of the desired module property. Otherwise, it will return null.
931 */
932CB_Modules.getProperty = function(moduleName, property)
933{
934 var module = CB_Modules.get(moduleName);
935 if (module !== null &amp;&amp; typeof(module[property]) !== "undefined")
936 {
937 return module[property];
938 }
939 return null;
940}
941
942
943/**
944 * Modifies a desired property of a given module.
945 * @memberof CB_Modules
946 * @function
947 * @param {string} moduleName - Name of the module which contains the property to modify.
948 * @param {string} property - Name of the property to modify.
949 * @param {*} value - Value desired for the property.
950 * @param {('array'|'object'|'scalar')} [type='scalar']
951 Type that the property uses.
952 If it is "array", the given "value" will be attached at the end of the array (all in a new single index if the "iterateArray" parameter is set to false, or each value in a new index otherwise).
953 If it is "object", the given "value" and the given "property" to modify will be treated as objects and the members of the "value" will be copied one by one (overwriting previous members in the case they existed).
954 If it is "scalar" or any other, the given "property" value will be replaced with the given "value".
955 * @param {boolean} [iterateArray=false] - If is set to true and the given "type" is "array", the given "value" will be considered an array and will be iterated to copy each of its values to a new index in the destiny. Otherwise, if it is set to false and the given "type" is "array", the given "value" will be attached at the end of the array in a new single index.
956 * @returns {boolean} It will return true if succeeded or false otherwise.
957 */
958CB_Modules.editProperty = function(moduleName, property, value, type, iterateArray)
959{
960 if (typeof(moduleName) === "undefined" || moduleName === null || moduleName === "") { return false; }
961 if (typeof(property) === "undefined" || property === null || property === "") { return false; }
962 if (typeof(type) === "undefined" || type === null) { type = "scalar"; }
963 type += "";
964 type = type.toLowerCase();
965
966 var modified = false;
967
968 var module = CB_Modules.get(moduleName);
969 if (module !== null)
970 {
971 var propertyValue = CB_Modules.getProperty(moduleName, property);
972 if (type === "array")
973 {
974 if (propertyValue === null) { module[property] = []; }
975 if (!iterateArray)
976 {
977 module[property][module[property].length] = value;
978 modified = true;
979 }
980 else
981 {
982 var valueLength = value.length;
983 for (var x = 0; x &lt; valueLength; x++)
984 {
985 module[property][module[property].length] = value[x];
986 }
987 if (x > 0) { modified = true; }
988 }
989 }
990 else if (type === "object")
991 {
992 if (propertyValue === null) { module[property] = {}; }
993 for (var propertyName in value)
994 {
995 module[property][propertyName] = value[propertyName];
996 modified = true;
997 }
998 }
999 else
1000 {
1001 if (propertyValue === null) { module[property] = null; }
1002 module[property] = value;
1003 modified = true;
1004 }
1005 }
1006 return modified;
1007}
1008
1009
1010/**
1011 * Attaches one module to another one.
1012 * @memberof CB_Modules
1013 * @function
1014 * @param {string} moduleNameParent - Name of the parent module where the new child module will be attached to.
1015 * @param {string} moduleName - Name of the new child module which will be attached to the given parent.
1016 * @param {CB_Modules.NEEDED_FILES} neededFiles - The "neededFiles" parameter for the new child module.
1017 * @returns {boolean} It will return true if succeeded or false otherwise.
1018 */
1019CB_Modules.addNeededModule = function(moduleNameParent, moduleName, neededFiles)
1020{
1021 return CB_Modules.editProperty(moduleNameParent, "neededModules", { "name" : moduleName, "neededFiles" : neededFiles }, "array");
1022}
1023
1024
1025/**
1026 * Attaches files to a module.
1027 * @memberof CB_Modules
1028 * @function
1029 * @param {string} moduleName - Name of the module which will contain the new files.
1030 * @param {CB_Modules.NEEDED_FILES} neededFiles - The "neededFiles" parameter for the module.
1031 * @returns {boolean} It will return true if succeeded or false otherwise.
1032 */
1033CB_Modules.addNeededFiles = function(moduleName, neededFiles)
1034{
1035 return CB_Modules.editProperty(moduleName, "neededFiles", neededFiles, "object");
1036}
1037
1038
1039function CB_getElementsByTagName(tagName)
1040{
1041 if (!tagName) { return []; }
1042 var elementsFound = [];
1043 if (typeof(document.getElementsByTagName) !== "undefined" &amp;&amp; document.getElementsByTagName !== null)
1044 {
1045 elementsFound = document.getElementsByTagName(tagName);
1046 }
1047 else if (document.querySelectorAll)
1048 {
1049 elementsFound = document.querySelectorAll(tagName);
1050 }
1051 else if (document.querySelectorAll)
1052 {
1053 elementsFound = document.querySelectorAll(tagName);
1054 }
1055 else if (typeof(document.all) !== "undefined" &amp;&amp; document.all !== null)
1056 {
1057 elementsFound = document.all.tags(tagName);
1058 }
1059 else if (document.layers)
1060 {
1061 var allElements = document.layers;
1062
1063 //Obtains all elements with the given tag name:
1064 var allElementsLength = allElements.length;
1065
1066 var elementCurrent;
1067 for (var x = 0; x &lt; allElementsLength; x++)
1068 {
1069 elementCurrent = allElements[x];
1070 if (elementCurrent !== null &amp;&amp; typeof(elementCurrent.tagName) !== "undefined")
1071 {
1072 if (CB_trim(elementCurrent.tagName).toLowerCase() === tagName)
1073 {
1074 elementsFound.push(elementCurrent);
1075 }
1076 }
1077 }
1078 //elementsFound = document.layers[tagName];
1079 }
1080 return elementsFound;
1081}
1082
1083
1084var CB_scriptPathCalculateLastReturn = CB_this.CB_scriptPathCalculateLastReturn || null;
1085/**
1086 * Tries to calculate and returns the path where the script is located.
1087 * @function
1088 * @returns {string} If it cannot be calculated, it will returns the value of {@link CB_Configuration[CB_NAME].SCRIPT_PATH_DEFAULT}.
1089 */
1090function CB_scriptPathCalculate()
1091{
1092 if (typeof(CB_scriptPathCalculateLastReturn) !== "undefined" &amp;&amp; CB_scriptPathCalculateLastReturn !== null) { return CB_scriptPathCalculateLastReturn; }
1093
1094 //Gets the "SCRIPT" DOM elements:
1095 var scriptElements = CB_getElementsByTagName("script");
1096
1097 var scriptFileName = CB_NAME + ".js";
1098 for (var x = 0, scriptElementsLength = scriptElements.length; x &lt; scriptElementsLength; x++)
1099 {
1100 if (scriptElements[x].src &amp;&amp; scriptElements[x].src.length)
1101 {
1102 var src = scriptElements[x].src;
1103 if (src === scriptFileName || src.substring(src.length - scriptFileName.length - 1, src.length + 1) === "/" + scriptFileName)
1104 {
1105 CB_scriptPathCalculateLastReturn = src.substring(0, src.length - scriptFileName.length);
1106 return CB_scriptPathCalculateLastReturn;
1107 }
1108 }
1109 }
1110
1111 return CB_Configuration[CB_NAME].SCRIPT_PATH_DEFAULT;
1112}
1113
1114
1115var CB_ready = false; //Defines weather CrossBrowdy is ready or not.
1116var CB_initWait = true;
1117var CB_initWaitMs = 50;
1118var CB_readyInterval; //Interval that will execute the main function when CrossBrowdy is ready.
1119var CB_deviceReady = false;
1120var CB_initOnErrorLoadingFile; //Function to call if any required file fails to load.
1121/**
1122 * Callback for when the script is loaded successfully. Without parameters.
1123 * @callback CB_init_CALLBACK
1124 */
1125
1126/**
1127 * Starts CrossBrowdy.
1128 * @function
1129 * @param {CB_init_CALLBACK} [mainFunction] - Callback for when CrossBrowdy is loaded successfully. Recommended.
1130 * @param {string} [scriptPath={@link CB_scriptPathCalculate}()] - Path where the main script is located. If not provided (it is undefined or null), it will try to calculate it calling the {@link CB_scriptPathCalculate} function internally.
1131 * @param {CB_includeRequiredFileErrorCallback} [onErrorLoadingFile] - Function to call when any of the required files fails to load (because of an error or because its timeout was fired). It could be called more than once, for each file which failed loading. If a function is provided, it will be stored in the global 'CB_initOnErrorLoadingFile' variable.
1132 * @param {boolean} [showSplashScreen={@link CB_Configuration.CrossBrowdy.SHOW_SPLASH_SCREEN_DEFAULT}] - Defines whether to show the splash screen or not.
1133 */
1134function CB_init(mainFunction, scriptPath, onErrorLoadingFile, showSplashScreen)
1135{
1136 //If Cordova is detected, exits this function and it will be called again when the device is ready:
1137 if ((typeof(window.cordova) !== "undefined") &amp;&amp; !CB_deviceReady &amp;&amp; document.addEventListener) { document.addEventListener("deviceready", function() { CB_deviceReady = true; CB_init(mainFunction, scriptPath, onErrorLoadingFile, showSplashScreen) }, false); return; }
1138
1139 //Applies the options set by the user (if any):
1140 CB_applyOptions(CB_NAME, CB_this);
1141
1142 if (typeof(showSplashScreen) === "undefined" || showSplashScreen === null) { showSplashScreen = CB_Configuration[CB_NAME].SHOW_SPLASH_SCREEN_DEFAULT; }
1143
1144 //If defined, shows splash screen:
1145 if (showSplashScreen) { CB_showSplashScreen(); }
1146
1147 //Executes this same function only after some milliseconds (avoids problems with Internet Explorer and excanvas):
1148 if (CB_initWait)
1149 {
1150 setTimeout(function() { CB_initWait = false; CB_init(mainFunction, scriptPath, onErrorLoadingFile, showSplashScreen); }, CB_initWaitMs);
1151 return;
1152 }
1153
1154 //Applies default path if it was not sent:
1155 if (typeof(scriptPath) === "undefined" || scriptPath === null)
1156 {
1157 scriptPath = CB_scriptPathCalculate();
1158 //scriptPath = CB_Configuration[CB_NAME].SCRIPT_PATH_DEFAULT;
1159 }
1160
1161 //If given, sets the callback when a required file fails to load:
1162 if (typeof(onErrorLoadingFile) === "function") { CB_initOnErrorLoadingFile = onErrorLoadingFile; }
1163
1164 //Initializes the main module:
1165 CB_Modules._initializeModule(scriptPath, CB_NAME);
1166
1167 //If defined, the main function will be executed when CrossBrowdy is ready:
1168 if (typeof(mainFunction) === "function")
1169 {
1170 var CB_readyExecute =
1171 function()
1172 {
1173 var loopAgain = true;
1174 if (CB_ready)
1175 {
1176 setTimeout(mainFunction, 1); //Calls the function given.
1177 if (showSplashScreen) { CB_hideSplashScreen = true; } //If showing, hides splash screen.
1178 loopAgain = false;
1179 }
1180 if (loopAgain) { setTimeout(CB_readyExecute, 1); }
1181 };
1182 CB_readyExecute();
1183 }
1184}
1185
1186
1187//Function that applies the given options:
1188function CB_applyOptions(moduleName)//, containerObject)
1189{
1190 if (typeof(CB_OPTIONS) !== "undefined" &amp;&amp; typeof(CB_OPTIONS[moduleName]) !== "undefined")
1191 {
1192 for (var option in CB_OPTIONS[moduleName])
1193 {
1194 CB_Configuration[moduleName][option] = CB_OPTIONS[moduleName][option];
1195 }
1196 }
1197}
1198
1199
1200/**
1201 * Returns the credits with the desired format.
1202 * @function
1203 * @param {string} [credits={@link CB_CREDITS_DEFAULT}] - Desired credits to be shown.
1204 * @param {boolean} [html=true] - Strips all HTML tags (if any) when it is false.
1205 * @param {boolean} [showPrefix=true] - Defines whether to show the "[CB]" prefix for every line or not (it will remove all "[CB]" occurrences if it is false).
1206 * @returns {string}
1207 */
1208function CB_credits(credits, html, showPrefix)
1209{
1210 if (typeof(html) === "undefined" || html === null) { html = true; }
1211 if (typeof(showPrefix) === "undefined" || showPrefix === null) { showPrefix = true; }
1212 if (typeof(credits) === "undefined" || credits === null || credits === "") { credits = CB_CREDITS_DEFAULT; }
1213 if (!html)
1214 {
1215 if (typeof(CB_br2nl) !== "undefined") { credits = CB_br2nl(credits); }
1216 else { credits = credits.replace(/&lt;br \/>/gi, "\n"); }
1217 credits = credits.replace(/&lt;[^>]*>?/gm, '');
1218 }
1219 if (!showPrefix) { credits = credits.replace(/\[CB\]/gi, ""); }
1220 return credits;
1221}
1222
1223
1224//Show a splash screen:
1225var CB_showSplashScreenInterval; //Checks when the body is ready to show the splash screen.
1226var CB_hideSplashScreen = false;
1227var CB_showSplashScreenExecuted = false;
1228function CB_showSplashScreen()
1229{
1230 if (CB_showSplashScreenExecuted) { return; }
1231 CB_showSplashScreenExecuted = true;
1232 var CB_showSplashScreenShow =
1233 function()
1234 {
1235 var loopAgain = true;
1236 //var bodyTag = document.getElementsByTagName("body");
1237 var bodyTag = CB_getElementsByTagName("body");
1238 if (typeof(bodyTag) !== "undefined" &amp;&amp; bodyTag !== null &amp;&amp; typeof(bodyTag[0]) !== "undefined" &amp;&amp; bodyTag[0] !== null)
1239 {
1240 bodyTag = bodyTag[0];
1241 if (!CB_hideSplashScreen &amp;&amp; document.getElementById("CB_splashScreenDiv") === null)
1242 {
1243 var splashScreenDivPosition = "fixed";
1244 var additionalCSS = "";
1245 //if (window.navigator.appName === "Microsoft Internet Explorer")
1246 if (navigator.userAgent.indexOf("MSIE") !== -1 &amp;&amp; (navigator.appVersion.indexOf("MSIE 5") !== -1 || navigator.appVersion.indexOf("MSIE 6") !== -1 || navigator.appVersion.indexOf("MSIE 7") !== -1 || navigator.appVersion.indexOf("MSIE 8") !== -1))
1247 {
1248 /*
1249 if (typeof(document.compatMode) !== "undefined" &amp;&amp; document.compatMode === "BackCompat" || typeof(document.documentMode) !== "undefined" &amp;&amp; document.documentMode == 5)
1250 {
1251 additionalCSS = " _position:absolute; _top:expression(eval(document.body.scrollTop));";
1252 }
1253 else if (navigator.appVersion.indexOf("MSIE 8") === -1)
1254 {
1255 splashScreenDivPosition = "absolute";
1256 }
1257 */
1258
1259 //If it is not IE8 (but IE5, IE6 or IE7) or it is in quirks mode ("fixed" property is not supported in IE8 when it is in quirks mode):
1260 if (navigator.appVersion.indexOf("MSIE 8") === -1 || typeof(document.compatMode) !== "undefined" &amp;&amp; document.compatMode === "BackCompat" || typeof(document.documentMode) !== "undefined" &amp;&amp; document.documentMode == 5)
1261 {
1262 splashScreenDivPosition = "absolute";
1263 //additionalCSS = " _position:absolute; _top: expression(eval(document.compatMode &amp;&amp; document.compatMode=='CSS1Compat') ? documentElement.scrollTop +(documentElement.clientHeight-this.clientHeight) : document.body.scrollTop +(document.body.clientHeight-this.clientHeight));";
1264 additionalCSS = " _position:absolute; _top: expression(eval(document.compatMode &amp;&amp; document.compatMode=='CSS1Compat') ? documentElement.scrollTop : document.body.scrollTop);";
1265 additionalCSS += " _left: expression(eval(document.compatMode &amp;&amp; document.compatMode=='CSS1Compat') ? documentElement.scrollLeft : document.body.scrollLeft);";
1266 }
1267
1268 bodyTag.style.width = bodyTag.style.height = "100%";
1269 }
1270 var splashScreenDiv = '\
1271 &lt;div id="CB_splashScreenDiv" onmousedown="return false;" style="position:' + splashScreenDivPosition + '; top:0px; left:0px; width:100%; height:100%; background-color:#cccccc; z-index:999; opacity:0.95; transition:opacity 1000ms; -moz-transition:opacity 1000ms; -webkit-transition:opacity 1000ms; -o-transition:opacity 1000ms; -khtml-transition:opacity 1000ms; -ms-transition:opacity 1000ms;' + additionalCSS + '">\
1272 &lt;table style="padding:0px; border:#ffffff solid 10px; width:100%; height:100%;">\
1273 &lt;tr>\
1274 &lt;td align="center" style="text-align:center; font-size:13px; font-family:terminal; color:#ffffff;">\
1275 &lt;table style="width:100%; height:30px; background:#aa0000; margin:0px; padding:0px; width:100%; height:30px; line-height:30px; border:0px;">\
1276 &lt;tr>\
1277 &lt;td align="center" valign="middle" style="text-align:center; font-size:25px; font-family:terminal; color:#ffffff;">\
1278 CrossBrowdy&lt;span style="font-size:10px;">' + CB_VERSION + '&lt;/span>\
1279 &lt;/td>\
1280 &lt;/tr>\
1281 &lt;/table>\
1282 &lt;div style="font-family:arial; font-size:9px; line-height:10px; color:#696969; text-align:center;">\
1283 &lt;div style="display:block; width:55%; text-align:left; margin:0px auto 0px auto;">\
1284 &lt;div style="font-family:verdana; text-align:center;" id="CB_splashScreenDivCredits">' + CB_credits(CB_Modules.modules[CB_NAME]["credits"], true, false).replace(/&lt;br \/>/i, "").replace(/&lt;br \/>/gi, ". ").replace(/- /i, "&lt;/div>").replace(/- /gi, "") + '&lt;/div>\
1285 &lt;/div>\
1286 * &lt;span id="CB_splashScreenDivLoadingBlink" style="color:#000000;">Loading...&lt;/span> *\
1287 &lt;br />\
1288 &lt;div id="CB_splashScreenDivLoader" style="color:#ffffff; text-align:center;">&lt;/div>\
1289 &lt;/td>\
1290 &lt;/tr>\
1291 &lt;/table>\
1292 &lt;/div>\
1293 ';
1294 bodyTag.innerHTML += splashScreenDiv;
1295 }
1296 else if (CB_hideSplashScreen &amp;&amp; document.getElementById("CB_splashScreenDiv") !== null)
1297 {
1298 var CB_splashScreenDiv = document.getElementById("CB_splashScreenDiv");
1299 CB_splashScreenDiv.style.opacity = 0;
1300 setTimeout(function() { CB_splashScreenDiv.style.visibility = "hidden"; }, 1000);
1301 loopAgain = false;
1302 }
1303 if (document.getElementById("CB_splashScreenDivLoadingBlink") !== null)
1304 {
1305 document.getElementById("CB_splashScreenDivLoadingBlink").style.visibility = (document.getElementById("CB_splashScreenDivLoadingBlink").style.visibility === "visible") ? "hidden" : "visible";
1306 }
1307 if (document.getElementById("CB_splashScreenDivLoader") !== null)
1308 {
1309 var loader = "";
1310 for (var file in CB_filesRequested)
1311 {
1312 if (CB_filesRequested[file]) { loader += '&lt;span style="color:#aa00aa;">Loading&lt;/span> ' + file; }
1313 else if (CB_filesRequested[file] === null) { loader += '&lt;span style="color:#aa0000; font-weight:bold;">ERROR LOADING&lt;/span> ' + file; }
1314 //else { loader += file + ' &lt;span style="color:#0000aa;">Loaded!&lt;/span>'; }
1315 loader += "&lt;br />";
1316 }
1317 //if (typeof(CB_filesLoaded[CB_filesLoaded.length - 1]) !== "undefined") { loader += CB_filesLoaded[CB_filesLoaded.length - 1] + ' &lt;span style="color:#aa0000;">Loaded&lt;/span>'; }
1318 document.getElementById("CB_splashScreenDivLoader").innerHTML = loader;
1319 }
1320 }
1321 if (loopAgain) { setTimeout(CB_showSplashScreenShow, 1); }
1322 };
1323 CB_showSplashScreenShow();
1324}
1325
1326
1327//Sends the statistics:
1328var CB_statsStored = false;
1329function CB_sendStats()
1330{
1331 //Gets the information:
1332 //var OS = "";
1333 var version = CB_VERSION;
1334 var url = typeof(window.location) !== "undefined" ? window.location : "";
1335 var time = Date.now();
1336
1337 if (typeof(encodeURIComponent) !== "undefined")
1338 {
1339 version = encodeURIComponent(version);
1340 url = encodeURIComponent(url);
1341 time = encodeURIComponent(time);
1342 }
1343 else if (typeof(escape) !== "undefined")
1344 {
1345 version = escape(version);
1346 url = escape(url);
1347 time = escape(time);
1348 }
1349
1350 /*
1351 txt = "&lt;p>Browser CodeName: " + navigator.appCodeName + "&lt;/p>";
1352 txt+= "&lt;p>Browser Name: " + navigator.appName + "&lt;/p>";
1353 txt+= "&lt;p>Browser Version: " + navigator.appVersion + "&lt;/p>";
1354 txt+= "&lt;p>Cookies Enabled: " + navigator.cookieEnabled + "&lt;/p>";
1355 txt+= "&lt;p>Browser Language: " + navigator.language + "&lt;/p>";
1356 txt+= "&lt;p>Browser Online: " + navigator.onLine + "&lt;/p>";
1357 txt+= "&lt;p>Platform: " + navigator.platform + "&lt;/p>";
1358 txt+= "&lt;p>User-agent header: " + navigator.userAgent + "&lt;/p>";
1359 txt+= "&lt;p>User-agent language: " + navigator.systemLanguage + "&lt;/p>";
1360 */
1361
1362 //Sends the information by including the statistics file:
1363 CB_includeJSFile(CB_Configuration[CB_NAME].STATS_URL + "?cb=" + version + "&amp;time=" + time + "&amp;url=" + url, undefined, undefined, undefined, true, undefined, undefined, true);
1364}</pre>
1365 </article>
1366</section>
1367
1368
1369
1370
1371
1372 </div>
1373 </div>
1374
1375 <div class="clearfix"></div>
1376
1377
1378
1379</div>
1380</div>
1381
1382
1383 <div class="modal fade" id="searchResults">
1384 <div class="modal-dialog">
1385 <div class="modal-content">
1386 <div class="modal-header">
1387 <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
1388 <h4 class="modal-title">Search results</h4>
1389 </div>
1390 <div class="modal-body"></div>
1391 <div class="modal-footer">
1392 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
1393 </div>
1394 </div><!-- /.modal-content -->
1395 </div><!-- /.modal-dialog -->
1396 </div>
1397
1398
1399<footer>
1400
1401
1402 <span class="copyright">
1403 <a href="printable/" target="_blank">See a more printer-friendly version</a><hr /><span style="color:#000000">© <address style="display:inline; font-style:normal;"><a href="https://crossbrowdy.com/" target="_blank">CrossBrowdy</a> API documentation</address> by <a href="https://joanalbamaldonado.com/" target="_blank">Joan Alba Maldonado</a> - <a href="https://creativecommons.org/licenses/by/4.0/" target="_blank">Creative Commons Attribution 4.0 International</a><br />DocStrap Copyright © 2012-2015 The contributors to the JSDoc3 and DocStrap projects.</span>
1404 </span>
1405
1406<span class="jsdoc-message">
1407 Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.2</a>
1408
1409 on Wed Mar 22nd 2023
1410
1411 using the <a href="https://github.com/docstrap/docstrap">DocStrap template</a>.
1412</span>
1413</footer>
1414
1415<script src="scripts/docstrap.lib.js"></script>
1416<script src="scripts/toc.js"></script>
1417
1418 <script type="text/javascript" src="scripts/fulltext-search-ui.js"></script>
1419
1420
1421<script>
1422$( function () {
1423 $( "[id*='$']" ).each( function () {
1424 var $this = $( this );
1425
1426 $this.attr( "id", $this.attr( "id" ).replace( "$", "__" ) );
1427 } );
1428
1429 $( ".tutorial-section pre, .readme-section pre, pre.prettyprint.source" ).each( function () {
1430 var $this = $( this );
1431
1432 var example = $this.find( "code" );
1433 exampleText = example.html();
1434 var lang = /{@lang (.*?)}/.exec( exampleText );
1435 if ( lang && lang[1] ) {
1436 exampleText = exampleText.replace( lang[0], "" );
1437 example.html( exampleText );
1438 lang = lang[1];
1439 } else {
1440 var langClassMatch = example.parent()[0].className.match(/lang\-(\S+)/);
1441 lang = langClassMatch ? langClassMatch[1] : "javascript";
1442 }
1443
1444 if ( lang ) {
1445
1446 $this
1447 .addClass( "sunlight-highlight-" + lang )
1448 .addClass( "linenums" )
1449 .html( example.html() );
1450
1451 }
1452 } );
1453
1454 Sunlight.highlightAll( {
1455 lineNumbers : true,
1456 showMenu : true,
1457 enableDoclinks : true
1458 } );
1459
1460 $.catchAnchorLinks( {
1461 navbarOffset: 10
1462 } );
1463 $( "#toc" ).toc( {
1464 anchorName : function ( i, heading, prefix ) {
1465 return $( heading ).attr( "id" ) || ( prefix + i );
1466 },
1467 selectors : "#toc-content h1,#toc-content h2,#toc-content h3,#toc-content h4",
1468 showAndHide : false,
1469 smoothScrolling: true
1470 } );
1471
1472 $( "#main span[id^='toc']" ).addClass( "toc-shim" );
1473 $( '.dropdown-toggle' ).dropdown();
1474
1475 $( "table" ).each( function () {
1476 var $this = $( this );
1477 $this.addClass('table');
1478 } );
1479
1480} );
1481</script>
1482
1483
1484
1485<!--Navigation and Symbol Display-->
1486
1487<script>
1488 $( function () {
1489 $( '#main' ).localScroll( {
1490 offset : { top : 60 } //offset by the height of your header (give or take a few px, see what works for you)
1491 } );
1492 $( "dt.name" ).each( function () {
1493 var $this = $( this ).find("h4");
1494 var icon = $( "<i/>" ).addClass( "icon-plus-sign" ).addClass( "pull-right" ).addClass( "icon-white" );
1495 var dt = $(this);
1496 var children = dt.next( "dd" );
1497
1498 dt.prepend( icon ).css( {cursor : "pointer"} );
1499 dt.addClass( "member-collapsed" ).addClass( "member" );
1500
1501
1502 children.hide();
1503
1504 dt.children().on( "click", function () {
1505 children = dt.next( "dd" );
1506 children.slideToggle( "fast", function () {
1507
1508 if ( children.is( ":visible" ) ) {
1509 icon.addClass( "icon-minus-sign" ).removeClass( "icon-plus-sign" ).removeClass( "icon-white" );
1510 dt.addClass( "member-open" ).animate( "member-collapsed" );
1511 } else {
1512 icon.addClass( "icon-plus-sign" ).removeClass( "icon-minus-sign" ).addClass( "icon-white" );
1513 dt.addClass( "member-collapsed" ).removeClass( "member-open" );
1514 }
1515 } );
1516 } );
1517
1518 } );
1519 } );
1520</script>
1521
1522
1523<!--Google Analytics-->
1524
1525
1526
1527 <script type="text/javascript">
1528 $(document).ready(function() {
1529 SearcherDisplay.init();
1530 });
1531 </script>
1532
1533
1534</body>
1535</html>