| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
1 /* 2 Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. 3 For licensing, see LICENSE.html or http://ckeditor.com/license 4 */ 5 6 /** 7 * @fileOverview Defines the {@link CKEDITOR.editor} class, which represents an 8 * editor instance. 9 */ 10 11 (function() 12 { 13 // The counter for automatic instance names. 14 var nameCounter = 0; 15 16 var getNewName = function() 17 { 18 var name = 'editor' + ( ++nameCounter ); 19 return ( CKEDITOR.instances && CKEDITOR.instances[ name ] ) ? getNewName() : name; 20 }; 21 22 // ##### START: Config Privates 23 24 // These function loads custom configuration files and cache the 25 // CKEDITOR.editorConfig functions defined on them, so there is no need to 26 // download them more than once for several instances. 27 var loadConfigLoaded = {}; 28 var loadConfig = function( editor ) 29 { 30 var customConfig = editor.config.customConfig; 31 32 // Check if there is a custom config to load. 33 if ( !customConfig ) 34 return false; 35 36 customConfig = CKEDITOR.getUrl( customConfig ); 37 38 var loadedConfig = loadConfigLoaded[ customConfig ] || ( loadConfigLoaded[ customConfig ] = {} ); 39 40 // If the custom config has already been downloaded, reuse it. 41 if ( loadedConfig.fn ) 42 { 43 // Call the cached CKEDITOR.editorConfig defined in the custom 44 // config file for the editor instance depending on it. 45 loadedConfig.fn.call( editor, editor.config ); 46 47 // If there is no other customConfig in the chain, fire the 48 // "configLoaded" event. 49 if ( CKEDITOR.getUrl( editor.config.customConfig ) == customConfig || !loadConfig( editor ) ) 50 editor.fireOnce( 'customConfigLoaded' ); 51 } 52 else 53 { 54 // Load the custom configuration file. 55 CKEDITOR.scriptLoader.load( customConfig, function() 56 { 57 // If the CKEDITOR.editorConfig function has been properly 58 // defined in the custom configuration file, cache it. 59 if ( CKEDITOR.editorConfig ) 60 loadedConfig.fn = CKEDITOR.editorConfig; 61 else 62 loadedConfig.fn = function(){}; 63 64 // Call the load config again. This time the custom 65 // config is already cached and so it will get loaded. 66 loadConfig( editor ); 67 }); 68 } 69 70 return true; 71 }; 72 73 var initConfig = function( editor, instanceConfig ) 74 { 75 // Setup the lister for the "customConfigLoaded" event. 76 editor.on( 'customConfigLoaded', function() 77 { 78 if ( instanceConfig ) 79 { 80 // Register the events that may have been set at the instance 81 // configuration object. 82 if ( instanceConfig.on ) 83 { 84 for ( var eventName in instanceConfig.on ) 85 { 86 editor.on( eventName, instanceConfig.on[ eventName ] ); 87 } 88 } 89 90 // Overwrite the settings from the in-page config. 91 CKEDITOR.tools.extend( editor.config, instanceConfig, true ); 92 93 delete editor.config.on; 94 } 95 96 onConfigLoaded( editor ); 97 }); 98 99 // The instance config may override the customConfig setting to avoid 100 // loading the default ~/config.js file. 101 if ( instanceConfig && instanceConfig.customConfig != undefined ) 102 editor.config.customConfig = instanceConfig.customConfig; 103 104 // Load configs from the custom configuration files. 105 if ( !loadConfig( editor ) ) 106 editor.fireOnce( 'customConfigLoaded' ); 107 }; 108 109 // ##### END: Config Privates 110 111 var onConfigLoaded = function( editor ) 112 { 113 // Set config related properties. 114 115 var skin = editor.config.skin.split( ',' ), 116 skinName = skin[ 0 ], 117 skinPath = CKEDITOR.getUrl( skin[ 1 ] || ( 118 '_source/' + // @Packager.RemoveLine 119 'skins/' + skinName + '/' ) ); 120 121 editor.skinName = skinName; 122 editor.skinPath = skinPath; 123 editor.skinClass = 'cke_skin_' + skinName; 124 125 editor.tabIndex = editor.config.tabIndex || editor.element.getAttribute( 'tabindex' ) || 0; 126 127 // Fire the "configLoaded" event. 128 editor.fireOnce( 'configLoaded' ); 129 130 // Load language file. 131 loadSkin( editor ); 132 }; 133 134 var loadLang = function( editor ) 135 { 136 CKEDITOR.lang.load( editor.config.language, editor.config.defaultLanguage, function( languageCode, lang ) 137 { 138 editor.langCode = languageCode; 139 140 // As we'll be adding plugin specific entries that could come 141 // from different language code files, we need a copy of lang, 142 // not a direct reference to it. 143 editor.lang = CKEDITOR.tools.prototypedCopy( lang ); 144 145 // We're not able to support RTL in Firefox 2 at this time. 146 if ( CKEDITOR.env.gecko && CKEDITOR.env.version < 10900 && editor.lang.dir == 'rtl' ) 147 editor.lang.dir = 'ltr'; 148 149 var config = editor.config; 150 config.contentsLangDirection == 'ui' && ( config.contentsLangDirection = editor.lang.dir ); 151 152 loadPlugins( editor ); 153 }); 154 }; 155 156 var loadPlugins = function( editor ) 157 { 158 var config = editor.config, 159 plugins = config.plugins, 160 extraPlugins = config.extraPlugins, 161 removePlugins = config.removePlugins; 162 163 if ( extraPlugins ) 164 { 165 // Remove them first to avoid duplications. 166 var removeRegex = new RegExp( '(?:^|,)(?:' + extraPlugins.replace( /\s*,\s*/g, '|' ) + ')(?=,|$)' , 'g' ); 167 plugins = plugins.replace( removeRegex, '' ); 168 169 plugins += ',' + extraPlugins; 170 } 171 172 if ( removePlugins ) 173 { 174 removeRegex = new RegExp( '(?:^|,)(?:' + removePlugins.replace( /\s*,\s*/g, '|' ) + ')(?=,|$)' , 'g' ); 175 plugins = plugins.replace( removeRegex, '' ); 176 } 177 178 // Load all plugins defined in the "plugins" setting. 179 CKEDITOR.plugins.load( plugins.split( ',' ), function( plugins ) 180 { 181 // The list of plugins. 182 var pluginsArray = []; 183 184 // The language code to get loaded for each plugin. Null 185 // entries will be appended for plugins with no language files. 186 var languageCodes = []; 187 188 // The list of URLs to language files. 189 var languageFiles = []; 190 191 // Cache the loaded plugin names. 192 editor.plugins = plugins; 193 194 // Loop through all plugins, to build the list of language 195 // files to get loaded. 196 for ( var pluginName in plugins ) 197 { 198 var plugin = plugins[ pluginName ], 199 pluginLangs = plugin.lang, 200 pluginPath = CKEDITOR.plugins.getPath( pluginName ), 201 lang = null; 202 203 // Set the plugin path in the plugin. 204 plugin.path = pluginPath; 205 206 // If the plugin has "lang". 207 if ( pluginLangs ) 208 { 209 // Resolve the plugin language. If the current language 210 // is not available, get the first one (default one). 211 lang = ( CKEDITOR.tools.indexOf( pluginLangs, editor.langCode ) >= 0 ? editor.langCode : pluginLangs[ 0 ] ); 212 213 if ( !plugin.lang[ lang ] ) 214 { 215 // Put the language file URL into the list of files to 216 // get downloaded. 217 languageFiles.push( CKEDITOR.getUrl( pluginPath + 'lang/' + lang + '.js' ) ); 218 } 219 else 220 { 221 CKEDITOR.tools.extend( editor.lang, plugin.lang[ lang ] ); 222 lang = null; 223 } 224 } 225 226 // Save the language code, so we know later which 227 // language has been resolved to this plugin. 228 languageCodes.push( lang ); 229 230 pluginsArray.push( plugin ); 231 } 232 233 // Load all plugin specific language files in a row. 234 CKEDITOR.scriptLoader.load( languageFiles, function() 235 { 236 // Initialize all plugins that have the "beforeInit" and "init" methods defined. 237 var methods = [ 'beforeInit', 'init', 'afterInit' ]; 238 for ( var m = 0 ; m < methods.length ; m++ ) 239 { 240 for ( var i = 0 ; i < pluginsArray.length ; i++ ) 241 { 242 var plugin = pluginsArray[ i ]; 243 244 // Uses the first loop to update the language entries also. 245 if ( m === 0 && languageCodes[ i ] && plugin.lang ) 246 CKEDITOR.tools.extend( editor.lang, plugin.lang[ languageCodes[ i ] ] ); 247 248 // Call the plugin method (beforeInit and init). 249 if ( plugin[ methods[ m ] ] ) 250 plugin[ methods[ m ] ]( editor ); 251 } 252 } 253 254 // Load the editor skin. 255 editor.fire( 'pluginsLoaded' ); 256 loadTheme( editor ); 257 }); 258 }); 259 }; 260 261 var loadSkin = function( editor ) 262 { 263 CKEDITOR.skins.load( editor, 'editor', function() 264 { 265 loadLang( editor ); 266 }); 267 }; 268 269 var loadTheme = function( editor ) 270 { 271 var theme = editor.config.theme; 272 CKEDITOR.themes.load( theme, function() 273 { 274 var editorTheme = editor.theme = CKEDITOR.themes.get( theme ); 275 editorTheme.path = CKEDITOR.themes.getPath( theme ); 276 editorTheme.build( editor ); 277 278 if ( editor.config.autoUpdateElement ) 279 attachToForm( editor ); 280 }); 281 }; 282 283 var attachToForm = function( editor ) 284 { 285 var element = editor.element; 286 287 // If are replacing a textarea, we must 288 if ( editor.elementMode == CKEDITOR.ELEMENT_MODE_REPLACE && element.is( 'textarea' ) ) 289 { 290 var form = element.$.form && new CKEDITOR.dom.element( element.$.form ); 291 if ( form ) 292 { 293 function onSubmit() 294 { 295 editor.updateElement(); 296 } 297 form.on( 'submit',onSubmit ); 298 299 // Setup the submit function because it doesn't fire the 300 // "submit" event. 301 if ( !form.$.submit.nodeName ) 302 { 303 form.$.submit = CKEDITOR.tools.override( form.$.submit, function( originalSubmit ) 304 { 305 return function() 306 { 307 editor.updateElement(); 308 309 // For IE, the DOM submit function is not a 310 // function, so we need thid check. 311 if ( originalSubmit.apply ) 312 originalSubmit.apply( this, arguments ); 313 else 314 originalSubmit(); 315 }; 316 }); 317 } 318 319 // Remove 'submit' events registered on form element before destroying.(#3988) 320 editor.on( 'destroy', function() 321 { 322 form.removeListener( 'submit', onSubmit ); 323 } ); 324 } 325 } 326 }; 327 328 function updateCommandsMode() 329 { 330 var command, 331 commands = this._.commands, 332 mode = this.mode; 333 334 for ( var name in commands ) 335 { 336 command = commands[ name ]; 337 command[ command.startDisabled ? 'disable' : command.modes[ mode ] ? 'enable' : 'disable' ](); 338 } 339 } 340 341 /** 342 * Initializes the editor instance. This function is called by the editor 343 * contructor (editor_basic.js). 344 * @private 345 */ 346 CKEDITOR.editor.prototype._init = function() 347 { 348 // Get the properties that have been saved in the editor_base 349 // implementation. 350 var element = CKEDITOR.dom.element.get( this._.element ), 351 instanceConfig = this._.instanceConfig; 352 delete this._.element; 353 delete this._.instanceConfig; 354 355 this._.commands = {}; 356 this._.styles = []; 357 358 /** 359 * The DOM element that has been replaced by this editor instance. This 360 * element holds the editor data on load and post. 361 * @name CKEDITOR.editor.prototype.element 362 * @type CKEDITOR.dom.element 363 * @example 364 * var editor = CKEDITOR.instances.editor1; 365 * alert( <b>editor.element</b>.getName() ); "textarea" 366 */ 367 this.element = element; 368 369 /** 370 * The editor instance name. It hay be the replaced element id, name or 371 * a default name using a progressive counter (editor1, editor2, ...). 372 * @name CKEDITOR.editor.prototype.name 373 * @type String 374 * @example 375 * var editor = CKEDITOR.instances.editor1; 376 * alert( <b>editor.name</b> ); "editor1" 377 */ 378 this.name = ( element && ( this.elementMode == CKEDITOR.ELEMENT_MODE_REPLACE ) 379 && ( element.getId() || element.getNameAtt() ) ) 380 || getNewName(); 381 382 if ( this.name in CKEDITOR.instances ) 383 throw '[CKEDITOR.editor] The instance "' + this.name + '" already exists.'; 384 385 /** 386 * The configurations for this editor instance. It inherits all 387 * settings defined in (@link CKEDITOR.config}, combined with settings 388 * loaded from custom configuration files and those defined inline in 389 * the page when creating the editor. 390 * @name CKEDITOR.editor.prototype.config 391 * @type Object 392 * @example 393 * var editor = CKEDITOR.instances.editor1; 394 * alert( <b>editor.config.theme</b> ); "default" e.g. 395 */ 396 this.config = CKEDITOR.tools.prototypedCopy( CKEDITOR.config ); 397 398 /** 399 * Namespace containing UI features related to this editor instance. 400 * @name CKEDITOR.editor.prototype.ui 401 * @type CKEDITOR.ui 402 * @example 403 */ 404 this.ui = new CKEDITOR.ui( this ); 405 406 /** 407 * Controls the focus state of this editor instance. This property 408 * is rarely used for normal API operations. It is mainly 409 * destinated to developer adding UI elements to the editor interface. 410 * @name CKEDITOR.editor.prototype.focusManager 411 * @type CKEDITOR.focusManager 412 * @example 413 */ 414 this.focusManager = new CKEDITOR.focusManager( this ); 415 416 CKEDITOR.fire( 'instanceCreated', null, this ); 417 418 this.on( 'mode', updateCommandsMode, null, null, 1 ); 419 420 initConfig( this, instanceConfig ); 421 }; 422 })(); 423 424 CKEDITOR.tools.extend( CKEDITOR.editor.prototype, 425 /** @lends CKEDITOR.editor.prototype */ 426 { 427 /** 428 * Adds a command definition to the editor instance. Commands added with 429 * this function can be later executed with {@link #execCommand}. 430 * @param {String} commandName The indentifier name of the command. 431 * @param {CKEDITOR.commandDefinition} commandDefinition The command definition. 432 * @example 433 * editorInstance.addCommand( 'sample', 434 * { 435 * exec : function( editor ) 436 * { 437 * alert( 'Executing a command for the editor name "' + editor.name + '"!' ); 438 * } 439 * }); 440 */ 441 addCommand : function( commandName, commandDefinition ) 442 { 443 return this._.commands[ commandName ] = new CKEDITOR.command( this, commandDefinition ); 444 }, 445 446 /** 447 * Add a trunk of css text to the editor which will be applied to the wysiwyg editing document. 448 * Note: This function should be called before editor is loaded to take effect. 449 * @param css {String} CSS text. 450 * @example 451 * editorInstance.addCss( 'body { background-color: grey; }' ); 452 */ 453 addCss : function( css ) 454 { 455 this._.styles.push( css ); 456 }, 457 458 /** 459 * Destroys the editor instance, releasing all resources used by it. 460 * If the editor replaced an element, the element will be recovered. 461 * @param {Boolean} [noUpdate] If the instance is replacing a DOM 462 * element, this parameter indicates whether or not to update the 463 * element with the instance contents. 464 * @example 465 * alert( CKEDITOR.instances.editor1 ); e.g "object" 466 * <b>CKEDITOR.instances.editor1.destroy()</b>; 467 * alert( CKEDITOR.instances.editor1 ); "undefined" 468 */ 469 destroy : function( noUpdate ) 470 { 471 if ( !noUpdate ) 472 this.updateElement(); 473 474 if ( this.mode ) 475 { 476 // -> currentMode.unload( holderElement ); 477 this._.modes[ this.mode ].unload( this.getThemeSpace( 'contents' ) ); 478 } 479 480 this.theme.destroy( this ); 481 482 var toolbars, 483 index = 0, 484 j, 485 items, 486 instance; 487 488 if ( this.toolbox ) 489 { 490 toolbars = this.toolbox.toolbars; 491 for ( ; index < toolbars.length ; index++ ) 492 { 493 items = toolbars[ index ].items; 494 for ( j = 0 ; j < items.length ; j++ ) 495 { 496 instance = items[ j ]; 497 if ( instance.clickFn ) CKEDITOR.tools.removeFunction( instance.clickFn ); 498 if ( instance.keyDownFn ) CKEDITOR.tools.removeFunction( instance.keyDownFn ); 499 500 if ( instance.index ) CKEDITOR.ui.button._.instances[ instance.index ] = null; 501 } 502 } 503 } 504 505 if ( this.contextMenu ) 506 CKEDITOR.tools.removeFunction( this.contextMenu._.functionId ); 507 508 if ( this._.filebrowserFn ) 509 CKEDITOR.tools.removeFunction( this._.filebrowserFn ); 510 511 this.fire( 'destroy' ); 512 CKEDITOR.remove( this ); 513 CKEDITOR.fire( 'instanceDestroyed', null, this ); 514 }, 515 516 /** 517 * Executes a command. 518 * @param {String} commandName The indentifier name of the command. 519 * @param {Object} [data] Data to be passed to the command 520 * @returns {Boolean} "true" if the command has been successfuly 521 * executed, otherwise "false". 522 * @example 523 * editorInstance.execCommand( 'Bold' ); 524 */ 525 execCommand : function( commandName, data ) 526 { 527 var command = this.getCommand( commandName ); 528 529 var eventData = 530 { 531 name: commandName, 532 commandData: data, 533 command: command 534 }; 535 536 if ( command && command.state != CKEDITOR.TRISTATE_DISABLED ) 537 { 538 if ( this.fire( 'beforeCommandExec', eventData ) !== true ) 539 { 540 eventData.returnValue = command.exec( eventData.commandData ); 541 542 // Fire the 'afterCommandExec' immediately if command is synchronous. 543 if ( !command.async && this.fire( 'afterCommandExec', eventData ) !== true ) 544 return eventData.returnValue; 545 } 546 } 547 548 // throw 'Unknown command name "' + commandName + '"'; 549 return false; 550 }, 551 552 /** 553 * Gets one of the registered commands. Note that, after registering a 554 * command definition with addCommand, it is transformed internally 555 * into an instance of {@link CKEDITOR.command}, which will be then 556 * returned by this function. 557 * @param {String} commandName The name of the command to be returned. 558 * This is the same used to register the command with addCommand. 559 * @returns {CKEDITOR.command} The command object identified by the 560 * provided name. 561 */ 562 getCommand : function( commandName ) 563 { 564 return this._.commands[ commandName ]; 565 }, 566 567 /** 568 * Gets the editor data. The data will be in raw format. It is the same 569 * data that is posted by the editor. 570 * @type String 571 * @returns (String) The editor data. 572 * @example 573 * if ( CKEDITOR.instances.editor1.<b>getData()</b> == '' ) 574 * alert( 'There is no data available' ); 575 */ 576 getData : function() 577 { 578 this.fire( 'beforeGetData' ); 579 580 var eventData = this._.data; 581 582 if ( typeof eventData != 'string' ) 583 { 584 var element = this.element; 585 if ( element && this.elementMode == CKEDITOR.ELEMENT_MODE_REPLACE ) 586 eventData = element.is( 'textarea' ) ? element.getValue() : element.getHtml(); 587 else 588 eventData = ''; 589 } 590 591 eventData = { dataValue : eventData }; 592 593 // Fire "getData" so data manipulation may happen. 594 this.fire( 'getData', eventData ); 595 596 return eventData.dataValue; 597 }, 598 599 getSnapshot : function() 600 { 601 var data = this.fire( 'getSnapshot' ); 602 603 if ( typeof data != 'string' ) 604 { 605 var element = this.element; 606 if ( element && this.elementMode == CKEDITOR.ELEMENT_MODE_REPLACE ) 607 data = element.is( 'textarea' ) ? element.getValue() : element.getHtml(); 608 } 609 610 return data; 611 }, 612 613 loadSnapshot : function( snapshot ) 614 { 615 this.fire( 'loadSnapshot', snapshot ); 616 }, 617 618 /** 619 * Sets the editor data. The data must be provided in raw format (HTML).<br /> 620 * <br /> 621 * Note that this menthod is asynchronous. The "callback" parameter must 622 * be used if interaction with the editor is needed after setting the data. 623 * @param {String} data HTML code to replace the curent content in the 624 * editor. 625 * @param {Function} callback Function to be called after the setData 626 * is completed. 627 * @example 628 * CKEDITOR.instances.editor1.<b>setData</b>( '<p>This is the editor data.</p>' ); 629 * @example 630 * CKEDITOR.instances.editor1.<b>setData</b>( '<p>Some other editor data.</p>', function() 631 * { 632 * this.checkDirty(); // true 633 * }); 634 */ 635 setData : function( data , callback ) 636 { 637 if( callback ) 638 { 639 this.on( 'dataReady', function( evt ) 640 { 641 evt.removeListener(); 642 callback.call( evt.editor ); 643 } ); 644 } 645 646 // Fire "setData" so data manipulation may happen. 647 var eventData = { dataValue : data }; 648 this.fire( 'setData', eventData ); 649 650 this._.data = eventData.dataValue; 651 652 this.fire( 'afterSetData', eventData ); 653 }, 654 655 /** 656 * Inserts HTML into the currently selected position in the editor. 657 * @param {String} data HTML code to be inserted into the editor. 658 * @example 659 * CKEDITOR.instances.editor1.<b>insertHtml( '<p>This is a new paragraph.</p>' )</b>; 660 */ 661 insertHtml : function( data ) 662 { 663 this.fire( 'insertHtml', data ); 664 }, 665 666 /** 667 * Inserts an element into the currently selected position in the 668 * editor. 669 * @param {CKEDITOR.dom.element} element The element to be inserted 670 * into the editor. 671 * @example 672 * var element = CKEDITOR.dom.element.createFromHtml( '<img src="hello.png" border="0" title="Hello" />' ); 673 * CKEDITOR.instances.editor1.<b>insertElement( element )</b>; 674 */ 675 insertElement : function( element ) 676 { 677 this.fire( 'insertElement', element ); 678 }, 679 680 checkDirty : function() 681 { 682 return ( this.mayBeDirty && this._.previousValue !== this.getSnapshot() ); 683 }, 684 685 resetDirty : function() 686 { 687 if ( this.mayBeDirty ) 688 this._.previousValue = this.getSnapshot(); 689 }, 690 691 /** 692 * Updates the <textarea> element that has been replaced by the editor with 693 * the current data available in the editor. 694 * @example 695 * CKEDITOR.instances.editor1.updateElement(); 696 * alert( document.getElementById( 'editor1' ).value ); // The current editor data. 697 */ 698 updateElement : function() 699 { 700 var element = this.element; 701 if ( element && this.elementMode == CKEDITOR.ELEMENT_MODE_REPLACE ) 702 { 703 var data = this.getData(); 704 705 if ( this.config.htmlEncodeOutput ) 706 data = CKEDITOR.tools.htmlEncode( data ); 707 708 if ( element.is( 'textarea' ) ) 709 element.setValue( data ); 710 else 711 element.setHtml( data ); 712 } 713 } 714 }); 715 716 CKEDITOR.on( 'loaded', function() 717 { 718 // Run the full initialization for pending editors. 719 var pending = CKEDITOR.editor._pending; 720 if ( pending ) 721 { 722 delete CKEDITOR.editor._pending; 723 724 for ( var i = 0 ; i < pending.length ; i++ ) 725 pending[ i ]._init(); 726 } 727 }); 728 729 /** 730 * Whether escape HTML when editor update original input element. 731 * @name CKEDITOR.config.htmlEncodeOutput 732 * @since 3.1 733 * @type Boolean 734 * @default false 735 * @example 736 * config.htmlEncodeOutput = true; 737 */ 738 739 /** 740 * Fired when a CKEDITOR instance is created, but still before initializing it. 741 * To interact with a fully initialized instance, use the 742 * {@link CKEDITOR#instanceReady} event instead. 743 * @name CKEDITOR#instanceCreated 744 * @event 745 * @param {CKEDITOR.editor} editor The editor instance that has been created. 746 */ 747 748 /** 749 * Fired when a CKEDITOR instance is destroyed. 750 * @name CKEDITOR#instanceDestroyed 751 * @event 752 * @param {CKEDITOR.editor} editor The editor instance that has been destroyed. 753 */ 754 755 /** 756 * Fired when all plugins are loaded and initialized into the editor instance. 757 * @name CKEDITOR#pluginsLoaded 758 * @event 759 */
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |