Changeset 818


Ignore:
Timestamp:
04/19/07 23:17:41 (7 years ago)
Author:
ray
Message:

Ticket #1010 Documentation: JSdoc

Location:
trunk
Files:
1 added
2 deleted
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/XinhaCore.js

    • Property svn:keywords changed from LastChangedDate LastChangedRevision LastChangedBy HeadURL Id to LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Rev
    r817 r818  
    103103  _editor_skin = ""; 
    104104} 
    105  
     105/** 
     106* The list of Xinha editors on the page. May be multiple editors. 
     107* You can access each editor object through this global variable. 
     108* 
     109* Example:<br /> 
     110* <code> 
     111*       var html = __xinhas[0].getEditorContent(); // gives you the HTML of the first editor in the page 
     112* </code> 
     113*/ 
    106114var __xinhas = []; 
    107115 
    108116// browser identification 
     117/** Cache the user agent for the following checks 
     118 * @private 
     119 */ 
    109120Xinha.agt       = navigator.userAgent.toLowerCase(); 
     121/** Browser is Microsoft Internet Explorer 
     122@type string  
     123*/ 
    110124Xinha.is_ie    = ((Xinha.agt.indexOf("msie") != -1) && (Xinha.agt.indexOf("opera") == -1)); 
     125/** Version Number, if browser is Microsoft Internet Explorer 
     126@type string  
     127*/ 
    111128Xinha.ie_version= parseFloat(Xinha.agt.substring(Xinha.agt.indexOf("msie")+5)); 
     129/** Browser is Opera 
     130@type string  
     131*/ 
    112132Xinha.is_opera  = (Xinha.agt.indexOf("opera") != -1); 
     133/** Version Number, if browser is Opera  
     134@type string  
     135*/ 
     136Xinha.opera_version = navigator.appVersion.substring(0, navigator.appVersion.indexOf(" "))*1; 
     137/** Browserengine is KHTML (Konqueror, Safari) 
     138@type string  
     139*/ 
    113140Xinha.is_khtml  = (Xinha.agt.indexOf("khtml") != -1); 
     141/** Browser is Safari 
     142@type string  
     143*/ 
    114144Xinha.is_safari  = (Xinha.agt.indexOf("safari") != -1); 
    115 Xinha.opera_version = navigator.appVersion.substring(0, navigator.appVersion.indexOf(" "))*1; 
     145/** OS is MacOS 
     146@type string  
     147*/ 
    116148Xinha.is_mac       = (Xinha.agt.indexOf("mac") != -1); 
     149/** Browser is Microsoft Internet Explorer Mac 
     150@type string  
     151*/ 
    117152Xinha.is_mac_ie = (Xinha.is_ie && Xinha.is_mac); 
     153/** Browser is Microsoft Internet Explorer Windows 
     154@type string  
     155*/ 
    118156Xinha.is_win_ie = (Xinha.is_ie && !Xinha.is_mac); 
     157/** Browserengine is Gecko (Mozilla) 
     158@type string  
     159*/ 
    119160Xinha.is_gecko  = (navigator.product == "Gecko" && !Xinha.is_safari); // Safari lies! 
     161/** File is opened locally opened ("file://" protocol) 
     162 * @type string 
     163 * @private 
     164 */ 
    120165Xinha.isRunLocally = document.URL.toLowerCase().search(/^file:/) != -1; 
     166/** Editing is enabled by document.designMode (Gecko, Opera), as opposed to contenteditable (IE) 
     167 * @type string 
     168 * @private 
     169 */ 
    121170Xinha.is_designMode = (typeof document.designMode != 'undefined' && !Xinha.is_ie); // IE has designMode, but we're not using it 
     171 
     172/** Check if Xinha can run in the used browser, otherwise the textarea will be remain unchanged 
     173 * @type Boolean 
     174 * @private 
     175 */ 
    122176Xinha.checkSupportedBrowser = function() 
    123177{ 
     
    140194  return Xinha.is_gecko || (Xinha.is_opera && Xinha.opera_version >= 9.1) || Xinha.ie_version >= 5.5; 
    141195}; 
    142  
     196/** Cache result of checking for browser support 
     197 * @type Boolean 
     198 * @private 
     199 */ 
    143200Xinha.isSupportedBrowser = Xinha.checkSupportedBrowser(); 
    144201 
     
    148205} 
    149206 
    150 // Creates a new Xinha object.  Tries to replace the textarea with the given 
    151 // ID with it. 
     207/** Creates a new Xinha object 
     208 * @version $Rev 817$ $LastChangedDate$ 
     209 * @constructor 
     210 * @param {String|DomNode}   textarea the textarea to replace; can be either only the id or the DOM object as returned by document.getElementById() 
     211 * @param {Xinha.Config} config optional if no Xinha.Config object is passed, the default config is used 
     212 */ 
    152213function Xinha(textarea, config) 
    153214{ 
     
    161222  if ( typeof config == "undefined" ) 
    162223  { 
     224                /** The configuration used in the editor 
     225                 * @type Xinha.Config 
     226                 */ 
    163227    this.config = new Xinha.Config(); 
    164228  } 
     
    167231    this.config = config; 
    168232  } 
    169   this._htmlArea = null; 
    170233 
    171234  if ( typeof textarea != 'object' ) 
     
    173236    textarea = Xinha.getElementById('textarea', textarea); 
    174237  } 
     238  /** This property references the original textarea, which is at the same time the editor in text mode 
     239   * @type DomNode textarea 
     240   */ 
    175241  this._textArea = textarea; 
    176242  this._textArea.spellcheck = false; 
    177       
    178   // Before we modify anything, get the initial textarea size 
     243  Xinha.freeLater(this, '_textArea'); 
     244   
     245  //  
     246  /** Before we modify anything, get the initial textarea size 
     247   * @private 
     248   * @type Object w,h  
     249   */ 
    179250  this._initial_ta_size = 
    180251  { 
     
    192263  } 
    193264 
     265  /** the current editing mode 
     266  * @private  
     267  * @type string "wysiwyg"|"text" 
     268  */ 
    194269  this._editMode = "wysiwyg"; 
     270  /** this object holds the plugins used in the editor 
     271  * @private  
     272  * @type Object 
     273  */ 
    195274  this.plugins = {}; 
     275  /** periodically updates the toolbar 
     276  * @private  
     277  * @type timeout 
     278  */ 
    196279  this._timerToolbar = null; 
     280  /** periodically takes a snapshot of the current editor content 
     281  * @private  
     282  * @type timeout 
     283  */ 
    197284  this._timerUndo = null; 
     285  /** holds the undo snapshots 
     286  * @private  
     287  * @type Array 
     288  */ 
    198289  this._undoQueue = [this.config.undoSteps]; 
     290  /** the current position in the undo queue  
     291  * @private  
     292  * @type integer 
     293  */ 
    199294  this._undoPos = -1; 
     295  /** use our own undo implementation (true) or the browser's (false)  
     296  * @private  
     297  * @type Boolean 
     298  */ 
    200299  this._customUndo = true; 
     300  /** the document object of the page Xinha is embedded in 
     301  * @private  
     302  * @type document 
     303  */ 
    201304  this._mdoc = document; // cache the document, we need it in plugins 
     305  /** doctype of the edited document (fullpage mode) 
     306  * @private  
     307  * @type string 
     308  */ 
    202309  this.doctype = ''; 
     310  /** running number that identifies the current editor 
     311  * @public  
     312  * @type integer 
     313  */ 
    203314  this.__htmlarea_id_num = __xinhas.length; 
    204315  __xinhas[this.__htmlarea_id_num] = this; 
    205  
     316         
     317  /** holds the events for use with the notifyOn/notifyOf system 
     318  * @private  
     319  * @type Object 
     320  */ 
    206321  this._notifyListeners = {}; 
    207322 
     
    243358    Xinha.freeLater(panels[i], 'div'); 
    244359  } 
     360  /** holds the panels 
     361  * @private  
     362  * @type Array 
     363  */ 
    245364  // finally store the variable 
    246365  this._panels = panels; 
    247  
    248   Xinha.freeLater(this, '_textArea'); 
     366         
     367  // Init some properties that are defined later 
     368  /** The statusbar container 
     369   * @type DomNode statusbar div 
     370   */ 
     371  this._statusBar = null; 
     372  /** The DOM path that is shown in the statusbar in wysiwyg mode 
     373   * @private 
     374   * @type DomNode 
     375   */ 
     376  this._statusBarTree = null; 
     377  /** The message that is shown in the statusbar in text mode 
     378   * @private 
     379   * @type DomNode 
     380   */ 
     381  this._statusBarTextMode = null; 
     382  /** Holds the items of the DOM path that is shown in the statusbar in wysiwyg mode 
     383   * @private 
     384   * @type Array tag names 
     385   */ 
     386  this._statusBarItems = []; 
     387  /** Holds the parts (table cells) of the UI (toolbar, panels, statusbar) 
     388 
     389   * @type Object framework parts 
     390   */ 
     391  this._framework = {}; 
     392  /** Them whole thing (table) 
     393   * @private 
     394   * @type DomNode 
     395   */ 
     396  this._htmlArea = null; 
     397  /** This is the actual editable area.<br /> 
     398   *  Technically it's an iframe that's made editable using window.designMode = 'on', respectively document.body.contentEditable = true (IE).<br /> 
     399   *  Use this property to get a grip on the iframe's window features<br /> 
     400   * 
     401   * @type window 
     402   */ 
     403  this._iframe = null; 
     404  /** The document object of the iframe.<br /> 
     405  *   Use this property to perform DOM operations on the edited document 
     406  * @type document 
     407  */ 
     408  this._doc = null; 
     409  /** The toolbar 
     410   *  @private 
     411   *  @type DomNode  
     412   */ 
     413  this._toolBar = this._toolbar = null; //._toolbar is for legacy, ._toolBar is better thanks. 
     414  /** Holds the botton objects 
     415   *  @private 
     416   *  @type Object 
     417   */ 
     418  this._toolbarObjects = {}; 
     419   
    249420} 
    250421 
     
    253424 
    254425// cache some regexps 
     426/** Identifies HTML tag names 
     427* @type RegExp 
     428*/ 
    255429Xinha.RE_tagName  = /(<\/|<)\s*([^ \t\n>]+)/ig; 
     430/** Exracts DOCTYPE string from HTML 
     431* @type RegExp 
     432*/ 
    256433Xinha.RE_doctype  = /(<!doctype((.|\n)*?)>)\n?/i; 
     434/** Finds head section in HTML 
     435* @type RegExp 
     436*/ 
    257437Xinha.RE_head     = /<head>((.|\n)*?)<\/head>/i; 
     438/** Finds body section in HTML 
     439* @type RegExp 
     440*/ 
    258441Xinha.RE_body     = /<body[^>]*>((.|\n|\r|\t)*?)<\/body>/i; 
     442/** Special characters that need to be escaped when dynamically creating a RegExp from an arbtrary string 
     443* @private 
     444* @type RegExp 
     445*/ 
    259446Xinha.RE_Specials = /([\/\^$*+?.()|{}[\]])/g; 
     447/** When dynamically creating a RegExp from an arbtrary string, some charactes that have special meanings in regular expressions have to be escaped. 
     448*   Run any string through this function to escape reserved characters. 
     449* @param {string} string the string to be escaped 
     450* @returns string 
     451*/ 
     452Xinha.escapeStringForRegExp = function (string) 
     453{ 
     454  return string.replace(Xinha.RE_Specials, '\\$1'); 
     455} 
     456/** Identifies email addresses 
     457* @type RegExp 
     458*/ 
    260459Xinha.RE_email    = /[_a-z\d\-\.]{3,}@[_a-z\d\-]{2,}(\.[_a-z\d\-]{2,})+/i; 
     460/** Identifies URLs 
     461* @type RegExp 
     462*/ 
    261463Xinha.RE_url      = /(https?:\/\/)?(([a-z0-9_]+:[a-z0-9_]+@)?[a-z0-9_-]{2,}(\.[a-z0-9_-]{2,}){2,}(:[0-9]+)?(\/\S+)*)/i; 
    262464 
     465 
     466 
     467/** 
     468 * This class creates an object that can be passed to the Xinha constructor as a parameter. 
     469 * Set the object's properties as you need to configure the editor (toolbar etc.) 
     470 * @version $Rev 817$ $LastChangedDate$ 
     471 * @constructor 
     472 */ 
    263473Xinha.Config = function() 
    264474{ 
    265475  var cfg = this; 
    266476  this.version = Xinha.version.Revision; 
    267  
    268   // Width and Height 
    269   //  you may set these as follows 
    270   //  width = 'auto'      -- the width of the original textarea will be used 
    271   //  width = 'toolbar'   -- the width of the toolbar will be used 
    272   //  width = '<css measure>' -- use any css measurement, eg width = '75%' 
    273   // 
    274   //  height = 'auto'     -- the height of the original textarea 
    275   //  height = '<css measure>' -- any css measurement, eg height = '480px' 
     477   
     478 /** This property controls the width of the editor.<br /> 
     479  *  Allowed values are 'auto', 'toolbar' or a numeric value followed by "px".<br /> 
     480  *  <code>auto</code>: let Xinha choose the width to use.<br /> 
     481  *  <code>toolbar</code>: compute the width size from the toolbar width.<br /> 
     482  *  <code>numeric value</code>: forced width in pixels ('600px').<br /> 
     483  *  
     484  *  Default: <code>"auto"</code> 
     485  * @type String 
     486  */ 
    276487  this.width  = "auto"; 
     488 /** This property controls the height of the editor.<br /> 
     489  *  Allowed values are 'auto' or a numeric value followed by px.<br /> 
     490  *  <code>"auto"</code>: let Xinha choose the height to use.<br /> 
     491  *  <code>numeric value</code>: forced height in pixels ('200px').<br /> 
     492  *  Default: <code>"auto"</code>  
     493  * @type String 
     494  */ 
    277495  this.height = "auto"; 
    278496 
    279   // the next parameter specifies whether the toolbar should be included 
    280   // in the size above, or are extra to it.  If false then it's recommended 
    281   // to have explicit pixel sizes above (or on your textarea and have auto above) 
     497 /** Specifies whether the toolbar should be included 
     498  *  in the size, or are extra to it.  If false then it's recommended 
     499  *  to have the size set as explicit pixel sizes (either in Xinha.Config or on your textarea)<br /> 
     500  * 
     501  *  Default: <code>true</code> 
     502  * 
     503  *  @type Boolean 
     504  */ 
    282505  this.sizeIncludesBars = true; 
    283  
    284   // the next parameter specifies whether the panels should be included 
    285   // in the size above, or are extra to it.  If false then it's recommended 
    286   // to have explicit pixel sizes above (or on your textarea and have auto above) 
     506 /** 
     507  * Specifies whether the panels should be included 
     508  * in the size, or are extra to it.  If false then it's recommended 
     509  * to have the size set as explicit pixel sizes (either in Xinha.Config or on your textarea)<br /> 
     510  *   
     511  *  Default: <code>true</code> 
     512  * 
     513  *  @type Boolean 
     514  */ 
    287515  this.sizeIncludesPanels = true; 
    288516 
    289   // each of the panels has a dimension, for the left/right it's the width 
    290   // for the top/bottom it's the height. 
    291   // 
    292   // WARNING: PANEL DIMENSIONS MUST BE SPECIFIED AS PIXEL WIDTHS 
     517 /** 
     518  * each of the panels has a dimension, for the left/right it's the width 
     519  * for the top/bottom it's the height. 
     520  * 
     521  * WARNING: PANEL DIMENSIONS MUST BE SPECIFIED AS PIXEL WIDTHS<br /> 
     522  *Default values:   
     523  *<pre> 
     524  *       xinha_config.panel_dimensions = 
     525  *   { 
     526  *         left:   '200px', // Width 
     527  *         right:  '200px', 
     528  *         top:    '100px', // Height 
     529  *         bottom: '100px' 
     530  *       } 
     531  *</pre> 
     532  *  @type Object 
     533  */ 
    293534  this.panel_dimensions = 
    294535  { 
     
    299540  }; 
    300541 
    301   // to make the iframe width narrower than the toolbar width, e.g. to maintain 
    302   // the layout when editing a narrow column of text, set the next parameter (in pixels). 
     542 /**  To make the iframe width narrower than the toolbar width, e.g. to maintain 
     543  *   the layout when editing a narrow column of text, set the next parameter (in pixels).<br /> 
     544  * 
     545  *  Default: <code>true</code> 
     546  * 
     547  *  @type Integer|null 
     548  */ 
    303549  this.iframeWidth = null; 
    304  
    305   // enable creation of a status bar? 
     550  
     551 /** Enable creation of the status bar?<br /> 
     552  * 
     553  *  Default: <code>true</code> 
     554  * 
     555  *  @type Boolean  
     556  */ 
    306557  this.statusBar = true; 
    307558 
    308   // intercept ^V and use the Xinha paste command 
    309   // If false, then passes ^V through to browser editor widget 
     559 /** Intercept ^V and use the Xinha paste command 
     560  *  If false, then passes ^V through to browser editor widget, which is the only way it works without problems in Mozilla<br /> 
     561  * 
     562  *  Default: <code>false</code> 
     563  * 
     564  *  @type Boolean 
     565  */ 
    310566  this.htmlareaPaste = false; 
    311  
    312   this.mozParaHandler = 'best'; // set to 'built-in', 'dirty' or 'best' 
    313                                 // built-in: will (may) use 'br' instead of 'p' tags 
    314                                 // dirty   : will use p and work good enough for the majority of cases, 
    315                                 // best    : works the best, but it's about 12kb worth of javascript 
    316                                 //   and will probably be slower than 'dirty'.  This is the "EnterParagraphs" 
    317                                 //   plugin from "hipikat", rolled in to be part of the core code 
    318  
    319567   
    320   // possible values  
    321   //    'DOMwalk' (the "original") 
    322   //    'TransformInnerHTML' (this used to be the GetHtml plugin) 
     568 /** <strong>Gecko only:</strong> Let the built-in routine for handling the <em>return</em> key decide if to enter <em>br</em> or <em>p</em> tags, 
     569  *  or use a custom implementation.<br /> 
     570  *  For information about the rules applied by Gecko, <a href="http://www.mozilla.org/editor/rules.html">see Mozilla website</a> <br /> 
     571  *  Possible values are <em>built-in</em> or <em>best</em><br /> 
     572  * 
     573  *  Default: <code>"best"</code> 
     574  * 
     575  *  @type String 
     576  */ 
     577  this.mozParaHandler = 'best';  
     578   
     579 /** This determines the method how the HTML output is generated. 
     580  *  There are two choices: 
     581  *  
     582  *<table border="1"> 
     583  *   <tr> 
     584  *       <td><em>DOMwalk</em></td> 
     585  *       <td>This is the classic and proven method. It recusively traverses the DOM tree  
     586  *           and builds the HTML string "from scratch". Tends to be a bit slow, especially in IE.</td> 
     587  *   </tr> 
     588  *   <tr> 
     589  *       <td><em>TransformInnerHTML</em></td> 
     590  *       <td>This method uses the JavaScript innerHTML property and relies on Regular Expressions to produce 
     591  *            clean XHTML output. This method is much faster than the other one.</td> 
     592  *     </tr> 
     593  * </table> 
     594  * 
     595  *  Default: <code>"DOMwalk"</code> 
     596  * 
     597  * @type String 
     598  */ 
    323599  this.getHtmlMethod = 'DOMwalk'; 
    324600   
    325   // maximum size of the undo queue 
     601  /** Maximum size of the undo queue<br /> 
     602   *  Default: <code>20</code> 
     603   *  @type Integer 
     604   */ 
    326605  this.undoSteps = 20; 
    327606 
    328   // the time interval at which undo samples are taken 
    329   this.undoTimeout = 500;       // 1/2 sec. 
    330  
    331   // set this to true if you want to explicitly right-justify when  
    332   // setting the text direction to right-to-left 
     607  /** The time interval at which undo samples are taken<br /> 
     608   *  Default: <code>500</code> (1/2 sec) 
     609   *  @type Integer milliseconds 
     610   */ 
     611  this.undoTimeout = 500; 
     612 
     613  /** Set this to true if you want to explicitly right-justify when setting the text direction to right-to-left<br /> 
     614   *  Default: <code>false</code> 
     615   *  @type Boolean 
     616   */ 
    333617  this.changeJustifyWithDirection = false; 
    334618 
    335   // if true then Xinha will retrieve the full HTML, starting with the 
    336   // <HTML> tag. 
     619  /** If true then Xinha will retrieve the full HTML, starting with the &lt;HTML&gt; tag.<br /> 
     620   *  Default: <code>false</code> 
     621   *  @type Boolean 
     622   */ 
    337623  this.fullPage = false; 
    338624 
    339   // style included in the iframe document 
     625  /** Raw style definitions included in the edited document<br /> 
     626   *  When a lot of inline style is used, perhaps it is wiser to use one or more external stylesheets.<br /> 
     627   *  To set tags P in red, H1 in blue andn A not underlined, we may do the following 
     628   *<pre> 
     629   * xinha_config.pageStyle = 
     630   *  'p { color:red; }\n' + 
     631   *  'h1 { color:bleu; }\n' + 
     632   *  'a {text-decoration:none; }'; 
     633   *</pre> 
     634   *  Default: <code>""</code> (empty) 
     635   *  @type String 
     636   */ 
    340637  this.pageStyle = ""; 
    341638 
    342   // external stylesheets to load (REFERENCE THESE ABSOLUTELY) 
     639  /** Array of external stylesheets to load. (Reference these absolutely)<br /> 
     640   *  Example<br /> 
     641   *  <pre>xinha_config.pageStyleSheets = ["/css/myPagesStyleSheet.css","/css/anotherOne.css"];</pre> 
     642   *  Default: <code>[]</code> (empty) 
     643   *  @type Array 
     644   */ 
    343645  this.pageStyleSheets = []; 
    344646 
    345647  // specify a base href for relative links 
     648  /** Specify a base href for relative links<br /> 
     649   *  ATTENTION: this does not work as expected and needs t be changed, see Ticket #961 <br /> 
     650   *  Default: <code>null</code> 
     651   *  @type String|null 
     652   */ 
    346653  this.baseHref = null; 
    347654 
    348   // when the editor is in different directory depth as the edited page relative image sources 
    349   // will break the display of your images 
    350   // this fixes an issue where Mozilla converts the urls of images and links that are on the same server  
    351   // to relative ones (../) when dragging them around in the editor (Ticket #448) 
     655  /** If true, relative URLs (../) will be made absolute.  
     656   *  When the editor is in different directory depth  
     657   *  as the edited page relative image sources will break the display of your images. 
     658   *  this fixes an issue where Mozilla converts the urls of images and links that are on the same server  
     659   *  to relative ones (../) when dragging them around in the editor (Ticket #448)<br /> 
     660   *  Default: <code>true</code> 
     661   *  @type Boolean 
     662   */ 
    352663  this.expandRelativeUrl = true; 
    353664   
    354   //   we can strip the base href out of relative links to leave them relative, reason for this 
    355   //   especially if you don't specify a baseHref is that mozilla at least (& IE ?) will prefix 
    356   //   the baseHref to any relative links to make them absolute, which isn't what you want most the time. 
     665 /**  We can strip the server part out of URL to make/leave them semi-absolute, reason for this 
     666   *  is that the browsers will prefix  the server to any relative links to make them absolute,  
     667   *  which isn't what you want most the time.<br /> 
     668   *  Default: <code>true</code> 
     669   *  @type Boolean 
     670   */ 
    357671  this.stripBaseHref = true; 
    358672 
    359   // and we can strip the url of the editor page from named links (eg <a href="#top">...</a>) 
    360   //  reason for this is that mozilla at least (and IE ?) prefixes location.href to any 
    361   //  that don't have a url prefixing them 
     673   /**  We can strip the url of the editor page from named links (eg &lt;a href="#top"&gt;...&lt;/a&gt;) 
     674   *  reason for this is that mozilla at least (and IE ?) prefixes location.href to any anchor 
     675   *  that don't have a url prefixing them<br /> 
     676   *  Default: <code>true</code> 
     677   *  @type Boolean 
     678   */ 
    362679  this.stripSelfNamedAnchors = true; 
    363680 
    364   // sometimes high-ascii in links can cause problems for servers (basically they don't recognise them) 
    365   //  so you can use this flag to ensure that all characters other than the normal ascii set (actually 
    366   //  only ! through ~) are escaped in URLs to % codes 
     681  /** In URLs all characters above ASCII value 127 have to be encoded using % codes<br /> 
     682   *  Default: <code>true</code> 
     683   *  @type Boolean 
     684   */ 
    367685  this.only7BitPrintablesInURLs = true; 
    368686 
    369   // if you are putting the HTML written in Xinha into an email you might want it to be 7-bit 
    370   //  characters only.  This config option (off by default) will convert all characters consuming 
    371   //  more than 7bits into UNICODE decimal entity references (actually it will convert anything 
    372   //  below <space> (chr 20) except cr, lf and tab and above <tilde> (~, chr 7E)) 
     687  
     688  /** If you are putting the HTML written in Xinha into an email you might want it to be 7-bit 
     689   *  characters only.  This config option will convert all characters consuming 
     690   *  more than 7bits into UNICODE decimal entity references (actually it will convert anything 
     691   *  below <space> (chr 20) except cr, lf and tab and above <tilde> (~, chr 7E))<br /> 
     692   *  Default: <code>false</code> 
     693   *  @type Boolean 
     694   */ 
    373695  this.sevenBitClean = false; 
    374696 
    375   // sometimes we want to be able to replace some string in the html comng in and going out 
    376   //  so that in the editor we use the "internal" string, and outside and in the source view 
    377   //  we use the "external" string  this is useful for say making special codes for 
    378   //  your absolute links, your external string might be some special code, say "{server_url}" 
    379   //  an you say that the internal represenattion of that should be http://your.server/ 
     697 
     698  /** Sometimes we want to be able to replace some string in the html comng in and going out 
     699   *  so that in the editor we use the "internal" string, and outside and in the source view 
     700   *  we use the "external" string  this is useful for say making special codes for 
     701   *  your absolute links, your external string might be some special code, say "{server_url}" 
     702   *  an you say that the internal represenattion of that should be http://your.server/<br /> 
     703   *  Example:  <code>{'external_string' : 'internal_string'}</code><br /> 
     704   *  Default: <code>{}</code> (empty) 
     705   *  @type Object 
     706   */ 
    380707  this.specialReplacements = {}; // { 'external_string' : 'internal_string' } 
    381708 
    382   // set to true if you want Word code to be cleaned upon Paste 
     709 /** Set to true if you want Word code to be cleaned upon Paste. This only works if  
     710   * you use the toolbr button to paste, not ^V. This means that due to the restrictions 
     711   * regarding pasting, this actually has no real effect in Mozilla <br /> 
     712   *  Default: <code>true</code> 
     713   *  @type Boolean 
     714   */ 
    383715  this.killWordOnPaste = true; 
    384716 
    385   // enable the 'Target' field in the Make Link dialog 
     717  /** Enable the 'Target' field in the Make Link dialog. Note that the target attribute is invalid in (X)HTML strict<br /> 
     718   *  Default: <code>true</code> 
     719   *  @type Boolean 
     720   */ 
    386721  this.makeLinkShowsTarget = true; 
    387722 
    388   // CharSet of the iframe, default is the charset of the document 
     723  /** CharSet of the iframe, default is the charset of the document 
     724   *  @type String 
     725   */ 
    389726  this.charSet = (typeof document.characterSet != 'undefined') ? document.characterSet : document.charset; 
    390727 
    391   // Whether the edited document should be rendered in Quirksmode or Standard Compliant (Strict) Mode 
    392   // This is commonly known as the "doctype switch" 
    393   // for details read here http://www.quirksmode.org/css/quirksmode.html 
    394   // 
    395   // Possible values: 
    396   //    true     :  Quirksmode is used 
    397   //    false    :  Strict mode is used 
    398   // leave empty :  the mode of the document Xinha is in is used 
    399   this.browserQuirksMode = ''; 
     728 /** Whether the edited document should be rendered in Quirksmode or Standard Compliant (Strict) Mode.<br /> 
     729   * This is commonly known as the "doctype switch"<br /> 
     730   * for details read here http://www.quirksmode.org/css/quirksmode.html 
     731   * 
     732   * Possible values:<br /> 
     733   *    true     :  Quirksmode is used<br /> 
     734   *    false    :  Strict mode is used<br /> 
     735   *    null (default):  the mode of the document Xinha is in is used 
     736   * @type Boolean|null 
     737   */ 
     738  this.browserQuirksMode = null; 
    400739 
    401740  // URL-s 
     
    403742  this.popupURL = "popups/"; 
    404743 
    405   // remove tags (these have to be a regexp, or null if this functionality is not desired) 
     744  /** Remove given tags when rendering the HTML (these have to be a regexp, or null if this functionality is not desired)<br /> 
     745   *  Default: <code>null</code> 
     746   *  @type RegExp|null 
     747   */ 
    406748  this.htmlRemoveTags = null; 
    407749 
    408   // Turning this on will turn all "linebreak" and "separator" items in your toolbar into soft-breaks, 
    409   // this means that if the items between that item and the next linebreak/separator can 
    410   // fit on the same line as that which came before then they will, otherwise they will 
    411   // float down to the next line. 
    412  
    413   // If you put a linebreak and separator next to each other, only the separator will 
    414   // take effect, this allows you to have one toolbar that works for both flowToolbars = true and false 
    415   // infact the toolbar below has been designed in this way, if flowToolbars is false then it will 
    416   // create explictly two lines (plus any others made by plugins) breaking at justifyleft, however if 
    417   // flowToolbars is false and your window is narrow enough then it will create more than one line 
    418   // even neater, if you resize the window the toolbars will reflow.  Niiiice. 
    419  
     750 /** Turning this on will turn all "linebreak" and "separator" items in your toolbar into soft-breaks, 
     751   * this means that if the items between that item and the next linebreak/separator can 
     752   * fit on the same line as that which came before then they will, otherwise they will 
     753   * float down to the next line. 
     754 
     755   * If you put a linebreak and separator next to each other, only the separator will 
     756   * take effect, this allows you to have one toolbar that works for both flowToolbars = true and false 
     757   * infact the toolbar below has been designed in this way, if flowToolbars is false then it will 
     758   * create explictly two lines (plus any others made by plugins) breaking at justifyleft, however if 
     759   * flowToolbars is false and your window is narrow enough then it will create more than one line 
     760   * even neater, if you resize the window the toolbars will reflow.  <br /> 
     761   *  Default: <code>true</code> 
     762   *  @type Boolean 
     763   */ 
    420764  this.flowToolbars = true; 
    421765   
    422   // set to center or right to change button alignment in toolbar 
     766  /** Set to center or right to change button alignment in toolbar 
     767   *  @type String 
     768   */ 
    423769  this.toolbarAlign = "left"; 
    424770   
    425   // set to true if you want the loading panel to show at startup 
     771  /** Set to true if you want the loading panel to show at startup<br /> 
     772   *  Default: <code>false</code> 
     773   *  @type Boolean 
     774   */ 
    426775  this.showLoading = false; 
    427  
    428   // set to false if you want to allow JavaScript in the content, otherwise <script> tags are stripped out 
     776   
     777  /** Set to false if you want to allow JavaScript in the content, otherwise &lt;script&gt; tags are stripped out.<br /> 
     778   *  This currently only affects the "DOMwalk" getHtmlMethod.<br /> 
     779   *  Default: <code>true</code> 
     780   *  @type Boolean 
     781   */ 
    429782  this.stripScripts = true; 
    430783 
    431   // see if the text just typed looks like a URL, or email address 
    432   // and link it appropriatly 
    433   // Note: Setting this option to false only affects Mozilla based browsers. 
    434   // In InternetExplorer this is native behaviour and cannot be turned off. 
    435   this.convertUrlsToLinks = true; 
    436  
    437   // size of color picker cells 
     784 /** See if the text just typed looks like a URL, or email address 
     785   * and link it appropriatly 
     786   * Note: Setting this option to false only affects Mozilla based browsers. 
     787   * In InternetExplorer this is native behaviour and cannot be turned off.<br /> 
     788   *  Default: <code>true</code> 
     789   *  @type Boolean 
     790   */ 
     791   this.convertUrlsToLinks = true; 
     792 
     793 
     794 /** Size of color picker cells<br /> 
     795   * Use number + "px"<br /> 
     796   *  Default: <code>"6px"</code> 
     797   *  @type String 
     798   */ 
    438799  this.colorPickerCellSize = '6px'; 
    439   // granularity of color picker cells (number per column/row) 
     800 /** Granularity of color picker cells (number per column/row)<br /> 
     801   *  Default: <code>18</code> 
     802   *  @type Integer 
     803   */ 
    440804  this.colorPickerGranularity = 18; 
    441   // position of color picker from toolbar button 
     805 /** Position of color picker from toolbar button<br /> 
     806   *  Default: <code>"bottom,right"</code> 
     807   *  @type String 
     808   */ 
    442809  this.colorPickerPosition = 'bottom,right'; 
    443   // set to true to show websafe checkbox in picker 
     810  /** Set to true to show only websafe checkbox in picker<br /> 
     811   *  Default: <code>false</code> 
     812   *  @type Boolean 
     813   */ 
    444814  this.colorPickerWebSafe = false; 
    445   // number of recent colors to remember 
     815 /** Number of recent colors to remember<br /> 
     816   *  Default: <code>20</code> 
     817   *  @type Integer 
     818   */ 
    446819  this.colorPickerSaveColors = 20; 
    447820 
    448   // start up the editor in fullscreen mode 
     821  /** Start up the editor in fullscreen mode<br /> 
     822   *  Default: <code>false</code> 
     823   *  @type Boolean 
     824   */ 
    449825  this.fullScreen = false; 
    450826   
    451   // you can tell the fullscreen mode to leave certain margins on each side 
    452   // the value is an array with the values for [top,right,bottom,left] in that order 
     827 /** You can tell the fullscreen mode to leave certain margins on each side.<br /> 
     828   *  The value is an array with the values for <code>[top,right,bottom,left]</code> in that order<br /> 
     829   *  Default: <code>[0,0,0,0]</code> 
     830   *  @type Array 
     831   */ 
    453832  this.fullScreenMargins = [0,0,0,0]; 
    454833   
    455   /** CUSTOMIZING THE TOOLBAR 
    456    * ------------------------- 
    457    * 
    458    * It is recommended that you customize the toolbar contents in an 
    459    * external file (i.e. the one calling Xinha) and leave this one 
    460    * unchanged.  That's because when we (InteractiveTools.com) release a 
    461    * new official version, it's less likely that you will have problems 
    462    * upgrading Xinha. 
    463    */ 
     834  /** This array orders all buttons except plugin buttons in the toolbar. Plugin buttons typically look for one  
     835   *  a certain button in the toolbar and place themselves next to it. 
     836   * Default value: 
     837   *<pre> 
     838   *xinha_config.toolbar = 
     839   * [ 
     840   *   ["popupeditor"], 
     841   *   ["separator","formatblock","fontname","fontsize","bold","italic","underline","strikethrough"], 
     842   *   ["separator","forecolor","hilitecolor","textindicator"], 
     843   *   ["separator","subscript","superscript"], 
     844   *   ["linebreak","separator","justifyleft","justifycenter","justifyright","justifyfull"], 
     845   *   ["separator","insertorderedlist","insertunorderedlist","outdent","indent"], 
     846   *   ["separator","inserthorizontalrule","createlink","insertimage","inserttable"], 
     847   *   ["linebreak","separator","undo","redo","selectall","print"], (Xinha.is_gecko ? [] : ["cut","copy","paste","overwrite","saveas"]), 
     848   *   ["separator","killword","clearfonts","removeformat","toggleborders","splitblock","lefttoright", "righttoleft"], 
     849   *   ["separator","htmlmode","showhelp","about"] 
     850   * ]; 
     851   *</pre> 
     852   * @type Array 
     853   */   
    464854  this.toolbar = 
    465855  [ 
     
    476866  ]; 
    477867 
    478  
     868  /** The fontnames listed in the fontname dropdown 
     869   * Default value: 
     870   *<pre> 
     871   *xinha_config.fontname = 
     872   *{ 
     873   *  "&mdash; font &mdash;" : '', 
     874   *  "Arial"                : 'arial,helvetica,sans-serif', 
     875   *  "Courier New"          : 'courier new,courier,monospace', 
     876   *  "Georgia"              : 'georgia,times new roman,times,serif', 
     877   *  "Tahoma"               : 'tahoma,arial,helvetica,sans-serif', 
     878   *  "Times New Roman"      : 'times new roman,times,serif', 
     879   *  "Verdana"              : 'verdana,arial,helvetica,sans-serif', 
     880   *  "impact"               : 'impact', 
     881   *  "WingDings"            : 'wingdings' 
     882   *}; 
     883   *</pre> 
     884   * @type Object 
     885   */ 
    479886  this.fontname = 
    480887  { 
    481888    "&mdash; font &mdash;": '', 
    482     "Arial":             'arial,helvetica,sans-serif', 
    483     "Courier New":         'courier new,courier,monospace', 
    484     "Georgia":         'georgia,times new roman,times,serif', 
    485     "Tahoma":            'tahoma,arial,helvetica,sans-serif', 
    486     "Times New Roman": 'times new roman,times,serif', 
    487     "Verdana":         'verdana,arial,helvetica,sans-serif', 
    488     "impact":            'impact', 
    489     "WingDings":             'wingdings' 
     889    "Arial"           : 'arial,helvetica,sans-serif', 
     890    "Courier New"     : 'courier new,courier,monospace', 
     891    "Georgia"         : 'georgia,times new roman,times,serif', 
     892    "Tahoma"          : 'tahoma,arial,helvetica,sans-serif', 
     893    "Times New Roman" : 'times new roman,times,serif', 
     894    "Verdana"         : 'verdana,arial,helvetica,sans-serif', 
     895    "impact"          : 'impact', 
     896    "WingDings"       : 'wingdings'  
    490897  }; 
    491898 
     899  /** The fontsizes listed in the fontsize dropdown 
     900   * Default value: 
     901   *<pre> 
     902   *xinha_config.fontsize = 
     903   *{ 
     904   *  "&mdash; size &mdash;": "", 
     905   *  "1 (8 pt)" : "1", 
     906   *  "2 (10 pt)": "2", 
     907   *  "3 (12 pt)": "3", 
     908   *  "4 (14 pt)": "4", 
     909   *  "5 (18 pt)": "5", 
     910   *  "6 (24 pt)": "6", 
     911   *  "7 (36 pt)": "7" 
     912   *}; 
     913   *</pre> 
     914   * @type Object 
     915   */ 
    492916  this.fontsize = 
    493917  { 
     
    501925    "7 (36 pt)": "7" 
    502926  }; 
    503  
     927  /** The tags listed in the formatblock dropdown 
     928   * Default value: 
     929   *<pre> 
     930   *xinha_config.formatblock = 
     931   *{ 
     932   *  "&mdash; size &mdash;": "", 
     933   *  "1 (8 pt)" : "1", 
     934   *  "2 (10 pt)": "2", 
     935   *  "3 (12 pt)": "3", 
     936   *  "4 (14 pt)": "4", 
     937   *  "5 (18 pt)": "5", 
     938   *  "6 (24 pt)": "6", 
     939   *  "7 (36 pt)": "7" 
     940   *}; 
     941   *</pre> 
     942   * @type Object 
     943   */ 
    504944  this.formatblock = 
    505945  { 
     
    515955    "Formatted": "pre" 
    516956  }; 
    517  
     957  /** ?? 
     958   * Default: <code>{}</code> 
     959   * @type Object 
     960   */ 
    518961  this.customSelects = {}; 
    519962 
    520   function cut_copy_paste(e, cmd, obj) { e.execCommand(cmd); } 
    521  
     963  /** Switches on some debugging (only in execCommand() as far as I see at the moment)<br /> 
     964   * 
     965   * Default: <code>true</code> 
     966   * @type Boolean 
     967   */ 
    522968  this.debug = true; 
    523969 
     
    534980 
    535981 
    536   // ADDING CUSTOM BUTTONS: please read below! 
    537   // format of the btnList elements is "ID: [ ToolTip, Icon, Enabled in text mode?, ACTION ]" 
    538   //    - ID: unique ID for the button.  If the button calls document.execCommand 
    539   //        it's wise to give it the same name as the called command. 
    540   //    - ACTION: function that gets called when the button is clicked. 
    541   //              it has the following prototype: 
    542   //                 function(editor, buttonName) 
    543   //              - editor is the Xinha object that triggered the call 
    544   //              - buttonName is the ID of the clicked button 
    545   //              These 2 parameters makes it possible for you to use the same 
    546   //              handler for more Xinha objects or for more different buttons. 
    547   //    - ToolTip: tooltip, will be translated below 
    548   //    - Icon: path to an icon image file for the button 
    549   //            OR; you can use an 18x18 block of a larger image by supllying an array 
    550   //            that has three elemtents, the first is the larger image, the second is the column 
    551   //            the third is the row.  The ros and columns numbering starts at 0 but there is 
    552   //            a header row and header column which have numbering to make life easier. 
    553   //            See images/buttons_main.gif to see how it's done. 
    554   //    - Enabled in text mode: if false the button gets disabled for text-only mode; otherwise enabled all the time. 
     982   /** The button list conains the definitions of the toolbar button. Normally, there's nothing to change here :)  
     983   * <div style="white-space:pre">ADDING CUSTOM BUTTONS: please read below! 
     984   * format of the btnList elements is "ID: [ ToolTip, Icon, Enabled in text mode?, ACTION ]" 
     985   *    - ID: unique ID for the button.  If the button calls document.execCommand 
     986   *        it's wise to give it the same name as the called command. 
     987   *    - ACTION: function that gets called when the button is clicked. 
     988   *              it has the following prototype: 
     989   *                 function(editor, buttonName) 
     990   *              - editor is the Xinha object that triggered the call 
     991   *              - buttonName is the ID of the clicked button 
     992   *              These 2 parameters makes it possible for you to use the same 
     993   *              handler for more Xinha objects or for more different buttons. 
     994   *    - ToolTip: tooltip, will be translated below 
     995   *    - Icon: path to an icon image file for the button 
     996   *            OR; you can use an 18x18 block of a larger image by supllying an array 
     997   *            that has three elemtents, the first is the larger image, the second is the column 
     998   *            the third is the row.  The ros and columns numbering starts at 0 but there is 
     999   *            a header row and header column which have numbering to make life easier. 
     1000   *            See images/buttons_main.gif to see how it's done. 
     1001   *    - Enabled in text mode: if false the button gets disabled for text-only mode; otherwise enabled all the time.</div> 
     1002   * @type Object 
     1003   */ 
    5551004  this.btnList = 
    5561005  { 
     
    5791028    undo: [ "Undoes your last action", ["ed_buttons_main.gif",4,2], false, function(e) { e.execCommand("undo"); } ], 
    5801029    redo: [ "Redoes your last action", ["ed_buttons_main.gif",5,2], false, function(e) { e.execCommand("redo"); } ], 
    581     cut: [ "Cut selection", ["ed_buttons_main.gif",5,0], false, cut_copy_paste ], 
    582     copy: [ "Copy selection", ["ed_buttons_main.gif",4,0], false, cut_copy_paste ], 
    583     paste: [ "Paste from clipboard", ["ed_buttons_main.gif",4,1], false, cut_copy_paste ], 
     1030    cut: [ "Cut selection", ["ed_buttons_main.gif",5,0], false,  function (e, cmd) { e.execCommand(cmd); } ], 
     1031    copy: [ "Copy selection", ["ed_buttons_main.gif",4,0], false,  function (e, cmd) { e.execCommand(cmd); } ], 
     1032    paste: [ "Paste from clipboard", ["ed_buttons_main.gif",4,1], false,  function (e, cmd) { e.execCommand(cmd); } ], 
    5841033    selectall: [ "Select all", "ed_selectall.gif", false, function(e) {e.execCommand("selectall");} ], 
    5851034 
     
    6071056  }; 
    6081057 
    609   /* ADDING CUSTOM BUTTONS 
    610    * --------------------- 
    611    * 
    612    * It is recommended that you add the custom buttons in an external 
    613    * file and leave this one unchanged.  That's because when we 
    614    * (InteractiveTools.com) release a new official version, it's less 
    615    * likely that you will have problems upgrading Xinha. 
    616    * 
    617    * Example on how to add a custom button when you construct the Xinha: 
    618    * 
    619    *   var editor = new Xinha("your_text_area_id"); 
    620    *   var cfg = editor.config; // this is the default configuration 
    621    *   cfg.btnList["my-hilite"] = 
    622    *    [ function(editor) { editor.surroundHTML('<span style="background:yellow">', '</span>'); }, // action 
    623    *      "Highlight selection", // tooltip 
    624    *      "my_hilite.gif", // image 
    625    *      false // disabled in text mode 
    626    *    ]; 
    627    *   cfg.toolbar.push(["linebreak", "my-hilite"]); // add the new button to the toolbar 
    628    * 
    629    * An alternate (also more convenient and recommended) way to 
    630    * accomplish this is to use the registerButton function below. 
    631    */ 
     1058 
    6321059  // initialize tooltips from the I18N module and generate correct image path 
    6331060  for ( var i in this.btnList ) 
     
    6511078 
    6521079}; 
    653  
     1080/** ADDING CUSTOM BUTTONS 
     1081*   --------------------- 
     1082* 
     1083* 
     1084* Example on how to add a custom button when you construct the Xinha: 
     1085* 
     1086*   var editor = new Xinha("your_text_area_id"); 
     1087*   var cfg = editor.config; // this is the default configuration 
     1088*   cfg.btnList["my-hilite"] = 
     1089*       [ function(editor) { editor.surroundHTML('<span style="background:yellow">', '</span>'); }, // action 
     1090*         "Highlight selection", // tooltip 
     1091*         "my_hilite.gif", // image 
     1092*         false // disabled in text mode 
     1093*       ]; 
     1094*   cfg.toolbar.push(["linebreak", "my-hilite"]); // add the new button to the toolbar 
     1095* 
     1096* An alternate (also more convenient and recommended) way to 
     1097* accomplish this is to use the registerButton function below. 
     1098*/ 
    6541099/** Helper function: register a new button with the configuration.  It can be 
    6551100 * called with all 5 arguments, or with only one (first one).  When called with 
    6561101 * only one argument it must be an object with the following properties: id, 
    657  * tooltip, image, textMode, action.  Examples: 
    658  * 
    659  * 1. config.registerButton("my-hilite", "Hilite text", "my-hilite.gif", false, function(editor) {...}); 
    660  * 2. config.registerButton({ 
     1102 * tooltip, image, textMode, action.<br />   
     1103 *  
     1104 * Examples:<br /> 
     1105 *<pre> 
     1106 * config.registerButton("my-hilite", "Hilite text", "my-hilite.gif", false, function(editor) {...}); 
     1107 * config.registerButton({ 
    6611108 *      id       : "my-hilite",      // the ID of your button 
    6621109 *      tooltip  : "Hilite text",    // the tooltip 
     
    6671114 *                 }, 
    6681115 *      context  : "p"               // will be disabled if outside a <p> element 
    669  *    }); 
     1116 *    });</pre> 
    6701117 */ 
    6711118Xinha.Config.prototype.registerButton = function(id, tooltip, image, textMode, action, context) 
     
    9361383  } 
    9371384}; 
    938  
     1385/** Alias of Xinha.Config.prototype.hideSomeButtons() 
     1386* @type Function 
     1387*/ 
    9391388Xinha.Config.prototype.removeToolbarElement = Xinha.Config.prototype.hideSomeButtons; 
    9401389 
    941 /** Helper function: replace all TEXTAREA-s in the document with Xinha-s. */ 
     1390/** Helper function: replace all TEXTAREA-s in the document with Xinha-s.  
     1391* @param {Xinha.Config} optional config  
     1392*/ 
    9421393Xinha.replaceAll = function(config) 
    9431394{ 
     
    9501401}; 
    9511402 
    952 /** Helper function: replaces the TEXTAREA with the given ID with Xinha. */ 
     1403/** Helper function: replaces the TEXTAREA with the given ID with Xinha.  
     1404* @param {string} id id of the textarea to replace  
     1405* @param {Xinha.Config} optional config  
     1406*/ 
    9531407Xinha.replace = function(id, config) 
    9541408{ 
     
    9561410  return ta ? (new Xinha(ta, config)).generate() : null; 
    9571411}; 
    958  
    959 // Creates the toolbar and appends it to the _htmlarea 
     1412  
     1413/** Creates the toolbar and appends it to the _htmlarea 
     1414* @private 
     1415* @returns {DomNode} toolbar 
     1416*/ 
    9601417Xinha.prototype._createToolbar = function () 
    9611418{ 
     
    9681425  toolbar.className = "toolbar"; 
    9691426  toolbar.unselectable = "1"; 
    970   toolbar.align = this.config.toolbarAlign; 
    9711427 
    9721428  Xinha.freeLater(this, '_toolBar'); 
     
    9831439}; 
    9841440 
    985 // FIXME : function never used, can probably be removed from source 
     1441/** FIXME : function never used, can probably be removed from source 
     1442* @private 
     1443* @deprecated 
     1444*/ 
    9861445Xinha.prototype._setConfig = function(config) 
    9871446{ 
    9881447        this.config = config; 
    9891448}; 
    990  
     1449/** FIXME: How can this be used?? 
     1450* @private 
     1451*/ 
    9911452Xinha.prototype._addToolbar = function() 
    9921453{ 
     
    9971458 * Create a break element to add in the toolbar 
    9981459 * 
    999  * @return {Object} HTML element to add 
     1460 * @return {DomNode} HTML element to add 
    10001461 * @private 
    10011462 */ 
     
    10111472}; 
    10121473 
    1013 // separate from previous createToolBar to allow dynamic change of toolbar 
     1474 
     1475/** separate from previous createToolBar to allow dynamic change of toolbar 
     1476 * @private 
     1477 * @return {DomNode} toolbar 
     1478 */ 
    10141479Xinha.prototype._createToolbar1 = function (editor, toolbar, tb_objects) 
    10151480{ 
     
    14081873//         Why the hell this is not in the config object ? 
    14091874var use_clone_img = false; 
     1875/** creates a button (i.e. container element + image) 
     1876 * @private 
     1877 * @return {DomNode} conteainer element 
     1878 */ 
    14101879Xinha.makeBtnImg = function(imgDef, doc) 
    14111880{ 
     
    14811950  return i_contain; 
    14821951}; 
    1483  
     1952/** creates the status bar  
     1953 * @private 
     1954 * @return {DomNode} status bar 
     1955 */ 
    14841956Xinha.prototype._createStatusBar = function() 
    14851957{ 
     
    14951967  div.className = "statusBarTree"; 
    14961968  div.innerHTML = Xinha._lc("Path") + ": "; 
     1969 
    14971970  this._statusBarTree = div; 
    14981971  Xinha.freeLater(this, '_statusBarTree'); 
     
    15021975  div.innerHTML = Xinha._lc("You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG."); 
    15031976  div.style.display = "none"; 
     1977 
    15041978  this._statusBarTextMode = div; 
    15051979  Xinha.freeLater(this, '_statusBarTextMode'); 
     
    15111985    statusbar.style.display = "none"; 
    15121986  } 
    1513  
    1514   this._statusBarItems = []; 
    1515    
    15161987  return statusbar; 
    15171988}; 
    15181989 
    1519 // Creates the Xinha object and replaces the textarea with it. 
     1990/** Creates the Xinha object and replaces the textarea with it. Loads required files. 
     1991 *  @returns {Boolean} 
     1992 */ 
    15201993Xinha.prototype.generate = function () 
    15211994{ 
     
    19122385 *    false   = the tool & status bars will appear outside the width & height confines 
    19132386 * 
     2387 * @private 
    19142388 */ 
    19152389 
     
    19602434/** 
    19612435 *  Size the editor to a specific size, or just refresh the size (when window resizes for example) 
    1962  *  @param width optional width (CSS specification) 
    1963  *  @param height optional height (CSS specification) 
    1964  *  @param includingBars optional boolean to indicate if the size should include or exclude tool & status bars 
     2436 *  @param {string} width optional width (CSS specification) 
     2437 *  @param {string} height optional height (CSS specification) 
     2438 *  @param {Boolean} includingBars optional to indicate if the size should include or exclude tool & status bars 
     2439 *  @param {Boolean} includingPanels optional to indicate if the size should include or exclude panels 
    19652440 */ 
    19662441Xinha.prototype.sizeEditor = function(width, height, includingBars, includingPanels) 
     
    21512626    edcellwidth -= parseInt(this.config.panel_dimensions.right, 10);     
    21522627  } 
    2153   var iframeWidth = (this.config.iframeWidth)? parseInt(this.config.iframeWidth,10): null; 
    2154   this._iframe.style.width = (iframeWidth && iframeWidth < edcellwidth)? iframeWidth + "px": edcellwidth + "px"; 
     2628  this._iframe.style.width = edcellwidth + 'px'; 
    21552629 
    21562630  this._textArea.style.height = this._iframe.style.height; 
     
    21602634  this._risizing = false; 
    21612635}; 
    2162  
     2636/** FIXME: Never used, what is this for?  
     2637* @param {string} side  
     2638* @param {Object} 
     2639*/ 
     2640Xinha.prototype.registerPanel = function(side, object) 
     2641{ 
     2642  if ( !side ) 
     2643  { 
     2644    side = 'right'; 
     2645  } 
     2646  this.setLoadingMessage('Register ' + side + ' panel '); 
     2647  var panel = this.addPanel(side); 
     2648  if ( object ) 
     2649  { 
     2650    object.drawPanelIn(panel); 
     2651  } 
     2652}; 
     2653/** Creates a panel in the panel container on the specified side 
     2654* @param {String} side the panel container to which the new panel will be added<br /> 
     2655*                                                                       Possible values are: "right","left","top","bottom" 
     2656* @returns {DomNode} Panel div 
     2657*/ 
    21632658Xinha.prototype.addPanel = function(side) 
    21642659{ 
     
    21782673  return div; 
    21792674}; 
    2180  
    2181  
     2675/** Removes a panel 
     2676* @param {DomNode} panel object as returned by Xinha.prototype.addPanel() 
     2677*/ 
    21822678Xinha.prototype.removePanel = function(panel) 
    21832679{ 
     
    21942690  this.notifyOf('panel_change', {'action':'remove','panel':panel}); 
    21952691}; 
    2196  
     2692/** Hides a panel 
     2693* @param {DomNode} panel object as returned by Xinha.prototype.addPanel() 
     2694*/ 
    21972695Xinha.prototype.hidePanel = function(panel) 
    21982696{ 
     
    22052703  } 
    22062704}; 
    2207  
     2705/** Shows a panel 
     2706* @param {DomNode} panel object as returned by Xinha.prototype.addPanel() 
     2707*/ 
    22082708Xinha.prototype.showPanel = function(panel) 
    22092709{ 
     
    22162716  } 
    22172717}; 
    2218  
     2718/** Hides the panel(s) on one or more sides 
     2719* @param {Array} sides the sides on which the panels shall be hidden 
     2720*/ 
    22192721Xinha.prototype.hidePanels = function(sides) 
    22202722{ 
     
    22352737  this.notifyOf('panel_change', {'action':'multi_hide','sides':sides}); 
    22362738}; 
    2237  
     2739/** Shows the panel(s) on one or more sides 
     2740* @param {Array} sides the sides on which the panels shall be hidden 
     2741*/ 
    22382742Xinha.prototype.showPanels = function(sides) 
    22392743{ 
     
    22542758  this.notifyOf('panel_change', {'action':'multi_show','sides':sides}); 
    22552759}; 
    2256  
     2760/** Returns an array containig all properties that are set in an object 
     2761* @param {Object} obj 
     2762* @returns {Array} 
     2763*/ 
    22572764Xinha.objectProperties = function(obj) 
    22582765{ 
     
    22652772}; 
    22662773 
    2267 /* 
    2268  * EDITOR ACTIVATION NOTES: 
     2774/** Checks if editor is active 
     2775 *<br /> 
     2776 * EDITOR ACTIVATION NOTES:<br /> 
    22692777 *  when a page has multiple Xinha editors, ONLY ONE should be activated at any time (this is mostly to 
    22702778 *  work around a bug in Mozilla, but also makes some sense).  No editor should be activated or focused 
    22712779 *  automatically until at least one editor has been activated through user action (by mouse-clicking in 
    22722780 *  the editor). 
     2781 * @private 
     2782 * @returns {Boolean} 
    22732783 */ 
    22742784Xinha.prototype.editorIsActivated = function() 
     
    22832793  } 
    22842794}; 
    2285  
     2795/**  We need to know that at least one editor on the page has been activated 
     2796*    this is because we will not focus any editor until an editor has been activated 
     2797* @private 
     2798* @type {Boolean} 
     2799*/ 
    22862800Xinha._someEditorHasBeenActivated = false; 
    2287 Xinha._currentlyActiveEditor      = false; 
     2801/**  Stores a reference to the currently active editor 
     2802* @private 
     2803* @type {Xinha} 
     2804*/ 
     2805Xinha._currentlyActiveEditor      = null; 
     2806/** Enables one editor for editing, e.g. by a click in the editing area or after it has been  
     2807 *  deactivated programmatically before  
     2808 * @private 
     2809 * @returns {Boolean} 
     2810 */ 
    22882811Xinha.prototype.activateEditor = function() 
    22892812{ 
     
    23202843  } 
    23212844 
    2322   // We need to know that at least one editor on the page has been activated 
    2323   // this is because we will not focus any editor until an editor has been activated 
    23242845  Xinha._someEditorHasBeenActivated = true; 
    23252846  Xinha._currentlyActiveEditor      = this; 
     
    23282849  this.enableToolbar(); 
    23292850}; 
    2330  
     2851/** Disables the editor  
     2852 * @private 
     2853 */ 
    23312854Xinha.prototype.deactivateEditor = function() 
    23322855{ 
     
    23572880  Xinha._currentlyActiveEditor = false; 
    23582881}; 
    2359  
     2882/** Creates the iframe (editable area) 
     2883 * @private 
     2884 */ 
    23602885Xinha.prototype.initIframe = function() 
    23612886{ 
     
    24702995 * Delay a function until the document is ready for operations. 
    24712996 * See ticket:547 
    2472  * @param {object} F (Function) The function to call once the document is ready 
    24732997 * @public 
    2474  */ 
    2475 Xinha.prototype.whenDocReady = function(F) 
    2476 { 
    2477   var E = this; 
     2998 * @param {Function} f  The function to call once the document is ready 
     2999 */ 
     3000Xinha.prototype.whenDocReady = function(f) 
     3001{ 
     3002  var e = this; 
    24783003  if ( this._doc && this._doc.body ) 
    24793004  { 
    2480     F(); 
     3005    f(); 
    24813006  } 
    24823007  else 
    24833008  { 
    2484     setTimeout(function() { E.whenDocReady(F); }, 50); 
    2485   } 
    2486 }; 
    2487  
    2488 // Switches editor mode; parameter can be "textmode" or "wysiwyg".  If no 
    2489 // parameter was passed this function toggles between modes. 
     3009    setTimeout(function() { e.whenDocReady(f); }, 50); 
     3010  } 
     3011}; 
     3012 
     3013 
     3014/** Switches editor mode between wysiwyg and text (HTML) 
     3015 * @param {String} mode optional "textmode" or "wysiwyg", if omitted, toggles between modes. 
     3016 */ 
    24903017Xinha.prototype.setMode = function(mode) 
    24913018{ 
     
    25483075  } 
    25493076}; 
    2550  
     3077/** Sets the HTML in fullpage mode. Actually the whole iframe document is rewritten. 
     3078 * @private 
     3079 * @param {String} html 
     3080 */ 
    25513081Xinha.prototype.setFullHTML = function(html) 
    25523082{ 
     
    25933123  } 
    25943124}; 
    2595  
     3125/** Initialize some event handlers 
     3126 * @private 
     3127 */ 
    25963128Xinha.prototype.setEditorEvents = function() 
    25973129{ 
     
    26493181 ***************************************************/ 
    26503182 
    2651 // Create the specified plugin and register it with this Xinha 
    2652 // return the plugin created to allow refresh when necessary 
     3183 
     3184/** Create the specified plugin and register it with this Xinha 
     3185 *  return the plugin created to allow refresh when necessary.<br /> 
     3186 *  <strong>This is only useful if Xinha is generated without using Xinha.makeEditors()</strong> 
     3187 */ 
    26533188Xinha.prototype.registerPlugin = function() 
    26543189{ 
     
    26713206  return this.registerPlugin2(plugin, args); 
    26723207}; 
    2673  
    2674 // this is the variant of the function above where the plugin arguments are 
    2675 // already packed in an array.  Externally, it should be only used in the 
    2676 // full-screen editor code, in order to initialize plugins with the same 
    2677 // parameters as in the opener window. 
     3208/** This is the variant of the function above where the plugin arguments are 
     3209 * already packed in an array.  Externally, it should be only used in the 
     3210 * full-screen editor code, in order to initialize plugins with the same 
     3211 * parameters as in the opener window. 
     3212 * @private 
     3213 */ 
    26783214Xinha.prototype.registerPlugin2 = function(plugin, args) 
    26793215{ 
     
    27083244}; 
    27093245 
    2710 // static function that loads the required plugin and lang file, based on the 
    2711 // language loaded already for Xinha.  You better make sure that the plugin 
    2712 // _has_ that language, otherwise shit might happen ;-) 
     3246 
     3247/** Dynamically returns the directory from which the plugins are loaded<br /> 
     3248 *  This could be overridden to change the dir<br /> 
     3249 *  @TODO: Wouldn't this be better as a config option? 
     3250 * @private 
     3251 * @param {String} pluginName 
     3252 * @returns {String} path to plugin 
     3253 */ 
    27133254Xinha.getPluginDir = function(pluginName) 
    27143255{ 
    27153256  return _editor_url + "plugins/" + pluginName; 
    27163257}; 
    2717  
     3258/** Static function that loads the given plugin 
     3259 * @param {String} pluginName 
     3260 * @param {Function} callback function to be called when file is loaded 
     3261 * @param {String} plugin_file URL of the file to load 
     3262 * @returns {Boolean} true if plugin loaded, false otherwise 
     3263 */ 
    27183264Xinha.loadPlugin = function(pluginName, callback, plugin_file) 
    27193265{ 
     
    27443290  return false; 
    27453291}; 
    2746  
     3292/** Stores a status for each loading plugin that may be one of "loading","ready", or "failed" 
     3293 * @private 
     3294 * @type {Object}  
     3295 */ 
    27473296Xinha._pluginLoadStatus = {}; 
    27483297 
     3298/** Static function that loads the plugins (see xinha_plugins in NewbieGuide) 
     3299 * @param {Array} plugins 
     3300 * @param {Function} callbackIfNotReady function that is called repeatedly until all files are 
     3301 * @returns {Boolean} true if all plugins are loaded, false otherwise 
     3302 */ 
    27493303Xinha.loadPlugins = function(plugins, callbackIfNotReady) 
    27503304{ 
     
    28193373}; 
    28203374 
    2821 // refresh plugin by calling onGenerate or onGenerateOnce method. 
     3375//  
     3376/** Refresh plugin by calling onGenerate or onGenerateOnce method. 
     3377 * @private 
     3378 * @param {PluginInstance} plugin 
     3379 */ 
    28223380Xinha.refreshPlugin = function(plugin) 
    28233381{ 
     
    28333391}; 
    28343392 
    2835 /** Call a method of all plugins which define the method using the supplied arguments. 
     3393/** Call a method of all plugins which define the method using the supplied arguments.<br /><br /> 
    28363394 * 
    2837  *  Example: editor.firePluginEvent('onExecCommand', 'paste') 
     3395 *  Example: <code>editor.firePluginEvent('onExecCommand', 'paste')</code><br /> 
     3396 *           The plugin would then define a method<br /> 
     3397 *           <code>PluginName.prototype.onExecCommand = function (cmdID, UI, param) {do something...}</code><br /><br /> 
     3398 *           The following methodNames are currently available:<br /> 
     3399 *  <table border="1"> 
     3400 *    <tr> 
     3401 *       <th>methodName</th><th>Parameters</th> 
     3402 *     </tr> 
     3403 *     <tr> 
     3404 *       <td>onExecCommand</td><td> cmdID, UI, param</td> 
     3405 *     </tr> 
     3406 *     <tr> 
     3407 *       <td>onKeyPress</td><td>ev</td> 
     3408 *     </tr>  
     3409 *     <tr> 
     3410 *       <td>onMouseDown</td><td>ev</td> 
     3411 *     </tr> 
     3412 * </table><br /><br /> 
    28383413 *   
    28393414 *  The browser specific plugin (if any) is called last.  The result of each call is  
     
    28413416 *  will get the event, a false return means the event will continue to fire. 
    28423417 * 
    2843  *  @param methodName 
    2844  *  @param arguments to pass to the method, optional [2..n]  
     3418 *  @param {String} methodName 
     3419 *  @param {mixed} arguments to pass to the method, optional [2..n]  
     3420 *  @returns {Boolean} 
    28453421 */ 
    28463422 
     
    28823458  return false; 
    28833459} 
    2884  
     3460/** Adds a stylesheet to the document 
     3461 * @param {String} style name of the stylesheet file 
     3462 * @param {String} plugin optional name of a plugin; if passed this function looks for the stylesheet file in the plugin directory  
     3463 * @param {String} id optional a unique id for identifiing the created link element, e.g. for avoiding double loading  
     3464 *                 or later removing it again 
     3465 */ 
    28853466Xinha.loadStyle = function(style, plugin, id) 
    28863467{ 
     
    28883469  if ( plugin ) 
    28893470  { 
    2890     url += "plugins/" + plugin + "/"; 
     3471    url = Xinha.getPluginDir( plugin ) + "/"; 
    28913472  } 
    28923473  url += style; 
     
    29123493 *  Category: EDITOR UTILITIES 
    29133494 ***************************************************/ 
    2914  
     3495/** Utility function: Outputs the structure of the edited document */ 
    29153496Xinha.prototype.debugTree = function() 
    29163497{ 
     
    29433524  document.body.appendChild(ta); 
    29443525}; 
     3526/** Extracts the textual content of a given node 
     3527 * @param {DomNode} el 
     3528 */ 
    29453529 
    29463530Xinha.getInnerText = function(el) 
     
    29603544  return txt; 
    29613545}; 
    2962  
     3546/** Cleans dirty HTML from MS word; always cleans the whole editor content 
     3547 *  @TODO: move this in a separate file 
     3548 *  @TODO: turn this into a static function that cleans a given string 
     3549 */ 
    29633550Xinha.prototype._wordClean = function() 
    29643551{ 
     
    30903677}; 
    30913678 
     3679/** Removes &lt;font&gt; tags; always cleans the whole editor content 
     3680 *  @TODO: move this in a separate file 
     3681 *  @TODO: turn this into a static function that cleans a given string 
     3682 */ 
    30923683Xinha.prototype._clearFonts = function() 
    30933684{ 
     
    31233714}; 
    31243715 
     3716/** Sometimes the display has to be refreshed to make DOM changes visible (?) (Gecko bug?)  */ 
    31253717Xinha.prototype.forceRedraw = function() 
    31263718{ 
     
    31303722}; 
    31313723 
    3132 // focuses the iframe window.  returns a reference to the editor document. 
     3724/** Focuses the iframe window.  
     3725 * @returns {document} a reference to the editor document 
     3726 */ 
    31333727Xinha.prototype.focusEditor = function() 
    31343728{ 
     
    31613755}; 
    31623756 
    3163 // takes a snapshot of the current text (for undo) 
     3757/** Takes a snapshot of the current text (for undo) 
     3758 * @private 
     3759 */ 
    31643760Xinha.prototype._undoTakeSnapshot = function() 
    31653761{ 
     
    31873783  } 
    31883784}; 
    3189  
     3785/** Custom implementation of undo functionality 
     3786 * @private 
     3787 */ 
    31903788Xinha.prototype.undo = function() 
    31913789{ 
     
    32033801  } 
    32043802}; 
    3205  
     3803/** Custom implementation of redo functionality 
     3804 * @private 
     3805 */ 
    32063806Xinha.prototype.redo = function() 
    32073807{ 
     
    32193819  } 
    32203820}; 
    3221  
     3821/** Disables (greys out) the buttons of the toolbar 
     3822 * @param {Array} except this array contains ids of toolbar objects that will not be disabled 
     3823 */ 
    32223824Xinha.prototype.disableToolbar = function(except) 
    32233825{ 
     
    32503852  } 
    32513853}; 
    3252  
     3854/** Enables the toolbar again when disabled by disableToolbar() */ 
    32533855Xinha.prototype.enableToolbar = function() 
    32543856{ 
     
    32563858}; 
    32573859 
    3258 if ( !Array.prototype.contains ) 
    3259 { 
    3260   Array.prototype.contains = function(needle) 
    3261   { 
    3262     var haystack = this; 
    3263     for ( var i = 0; i < haystack.length; i++ ) 
    3264     { 
    3265       if ( needle == haystack[i] ) 
    3266       { 
    3267         return true; 
    3268       } 
    3269     } 
    3270     return false; 
    3271   }; 
    3272 } 
    3273  
    3274 if ( !Array.prototype.indexOf ) 
    3275 { 
    3276   Array.prototype.indexOf = function(needle) 
    3277   { 
    3278     var haystack = this; 
    3279     for ( var i = 0; i < haystack.length; i++ ) 
    3280     { 
    3281       if ( needle == haystack[i] ) 
    3282       { 
    3283         return i; 
    3284       } 
    3285     } 
    3286     return null; 
    3287   }; 
    3288 } 
    3289  
     3860/** Updates enabled/disable/active state of the toolbar elements, the statusbar and other things 
     3861 *  This function is called on every key stroke as well as by a timer on a regular basis.<br /> 
     3862 *  Plugins have the opportunity to implement a prototype.onUpdateToolbar() method, which will also 
     3863 *  be called by this function. 
     3864 * @param {Boolean} noStatus private use Exempt updating of statusbar 
     3865 */ 
    32903866// FIXME : this function needs to be splitted in more functions. 
    32913867// It is actually to heavy to be understable and very scary to manipulate 
    3292 // updates enabled/disable/active state of the toolbar elements 
    32933868Xinha.prototype.updateToolbar = function(noStatus) 
    32943869{ 
     
    36124187}; 
    36134188 
    3614  
    3615 // moved Xinha.prototype.insertNodeAtSelection() to browser specific file 
    3616 // moved Xinha.prototype.getParentElement() to browser specific file 
    3617  
    3618 // Returns an array with all the ancestor nodes of the selection. 
     4189/** Returns an array with all the ancestor nodes of the selection or current cursor position. 
     4190* @returns {Array} 
     4191*/ 
    36194192Xinha.prototype.getAllAncestors = function() 
    36204193{ 
     
    36304203}; 
    36314204 
    3632 // Returns the deepest ancestor of the selection that is of the current type 
     4205/** Traverses the DOM upwards and returns the first element that is of one of the specified types 
     4206 *  @param {Selection} sel  Selection object as returned by getSelection 
     4207 *  @param {Array} types Array of HTML tag names (lower case) 
     4208 *  @returns {DomNode|null}  
     4209 */ 
    36334210Xinha.prototype._getFirstAncestor = function(sel, types) 
    36344211{ 
     
    36794256}; 
    36804257 
    3681 // moved Xinha.prototype._activeElement() to browser specific file 
    3682 // moved Xinha.prototype._selectionEmpty() to browser specific file 
    3683  
     4258/** Traverses the DOM upwards and returns the first element that is a block level element 
     4259 *  @param {Selection} sel  Selection object as returned by getSelection 
     4260 *  @returns {DomNode|null}  
     4261 */ 
    36844262Xinha.prototype._getAncestorBlock = function(sel) 
    36854263{ 
     
    37284306}; 
    37294307 
     4308/** What's this? does nothing, has to be removed 
     4309 *  
     4310 * @deprecated 
     4311 */ 
    37304312Xinha.prototype._createImplicitBlock = function(type) 
    37314313{ 
     
    37504332 
    37514333 
    3752 // moved Xinha.prototype.selectNodeContents() to browser specific file 
    3753 // moved Xinha.prototype.insertHTML() to browser specific file 
    37544334 
    37554335/** 
    37564336 *  Call this function to surround the existing HTML code in the selection with 
    3757  *  your tags.  FIXME: buggy!  This function will be deprecated "soon". 
     4337 *  your tags.  FIXME: buggy! Don't use this  
    37584338 * @todo: when will it be deprecated ? Can it be removed already ? 
     4339 * @private (tagged private to not further promote use of this function) 
     4340 * @deprecated 
    37594341 */ 
    37604342Xinha.prototype.surroundHTML = function(startTag, endTag) 
     
    37654347}; 
    37664348 
    3767 // moved  Xinha.prototype.getSelectedHTML() to browser specific file 
    3768  
    3769 /// Return true if we have some selection 
     4349/** Return true if we have some selection 
     4350 *  @returns {Boolean}  
     4351 */ 
    37704352Xinha.prototype.hasSelectedText = function() 
    37714353{ 
     
    37734355  return this.getSelectedHTML() !== ''; 
    37744356}; 
    3775  
    3776 // moved Xinha.prototype._createLink() to popups/link.js 
    3777 // moved Xinha.prototype._insertImage() to popups/insert_image.js 
    3778  
    3779 // Called when the user clicks the Insert Table button 
    3780  
    37814357 
    37824358/*************************************************** 
     
    37844360 ***************************************************/ 
    37854361 
    3786 // el is reference to the SELECT object 
    3787 // txt is the name of the select field, as in config.toolbar 
     4362/** onChange handler for dropdowns in toolbar  
     4363 *  @private 
     4364 *  @param {DomNode} el Reference to the SELECT object 
     4365 *  @param {String} txt  The name of the select field, as in config.toolbar 
     4366 *  @returns {DomNode|null}  
     4367 */ 
    37884368Xinha.prototype._comboSelected = function(el, txt) 
    37894369{ 
     
    38244404}; 
    38254405 
    3826 /** 
    3827  * Open a popup to select the hilitecolor or forecolor 
    3828  * 
     4406/** Open a popup to select the hilitecolor or forecolor 
     4407 * @private 
    38294408 * @param {String} cmdID The commande ID (hilitecolor or forecolor) 
    3830  * @private 
    38314409 */ 
    38324410Xinha.prototype._colorSelector = function(cmdID) 
     
    38854463}; 
    38864464 
    3887 // the execCommand function (intercepts some commands and replaces them with 
    3888 // our own implementation) 
     4465/** This is a wrapper for the browser's execCommand function that handles things like  
     4466 *  formatting, inserting elements, etc.<br /> 
     4467 *  It intercepts some commands and replaces them with our own implementation.<br /> 
     4468 *  It provides a hook for the "firePluginEvent" system ("onExecCommand").<br /><br /> 
     4469 *  For reference see:<br /> 
     4470 *     <a href="http://www.mozilla.org/editor/midas-spec.html">Mozilla implementation</a><br /> 
     4471 *     <a href="http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/execcommand.asp">MS implementation</a> 
     4472 * 
     4473 *  @see Xinha#firePluginEvent 
     4474 *  @param {String} cmdID command to be executed as defined in the browsers implemantations or Xinha custom 
     4475 *  @param {Boolean} UI for compatibility with the execCommand syntax; false in most (all) cases 
     4476 *  @param {Mixed} param Some commands require parameters 
     4477 *  @returns {Boolean} always false  
     4478 */ 
    38894479Xinha.prototype.execCommand = function(cmdID, UI, param) 
    38904480{ 
     
    40164606}; 
    40174607 
    4018 /** A generic event handler for things that happen in the IFRAME's document. 
    4019  * @todo: this function is *TOO* generic, it needs to be splitted in more specific handlers 
    4020  * This function also handles key bindings. */ 
     4608/** A generic event handler for things that happen in the IFRAME's document.<br /> 
     4609 *  It provides two hooks for the "firePluginEvent" system:<br /> 
     4610 *   "onKeyPress"<br /> 
     4611 *   "onMouseDown" 
     4612 *  @see Xinha#firePluginEvent 
     4613 *  @param {Event} ev 
     4614 */ 
    40214615Xinha.prototype._editorEvent = function(ev) 
    40224616{ 
     
    40654659}; 
    40664660 
    4067 // handles ctrl + key shortcuts  
     4661/** Handles ctrl + key shortcuts  
     4662 *  @TODO: make this mor flexible 
     4663 *  @private 
     4664 *  @param {Event} ev 
     4665 */ 
    40684666Xinha.prototype._shortCuts = function (ev) 
    40694667{ 
     
    41114709  } 
    41124710}; 
    4113  
     4711/** Changes the type of a given node 
     4712 *  @param {DomNode} el The element to convert 
     4713 *  @param {String} newTagName The type the element will be converted to 
     4714 *  @returns {DomNode} A reference to the new element 
     4715 */ 
    41144716Xinha.prototype.convertNode = function(el, newTagName) 
    41154717{ 
     
    41224724}; 
    41234725 
    4124 // moved Xinha.prototype.checkBackspace() to browser specific file 
    4125 // moved Xinha.prototype.dom_checkInsertP() to browser specific file 
    4126  
     4726/** Scrolls the editor iframe to a given element or to the cursor 
     4727 *  @param {DomNode} e optional The element to scroll to; if ommitted, element the element the cursor is in 
     4728 */ 
    41274729Xinha.prototype.scrollToElement = function(e) 
    41284730{ 
     
    41414743 *   
    41424744 *  @public 
    4143  *  @returns {string} HTML content 
     4745 *  @returns {String} HTML content 
    41444746 */ 
    41454747Xinha.prototype.getEditorContent = function() 
     
    41484750} 
    41494751 
    4150 /** Completely change the HTML inside 
     4752/** Completely change the HTML inside the editor 
    41514753 * 
    41524754 *  @public 
    4153  *  @param {string} html new content 
     4755 *  @param {String} html new content 
    41544756 */ 
    41554757Xinha.prototype.setEditorContent = function(html) 
     
    41584760} 
    41594761 
    4160 // retrieve the HTML 
     4762/** Get the raw edited HTML, should not be used without Xinha.prototype.outwardHtml() 
     4763 *   
     4764 *  @private 
     4765 *  @returns {String} HTML content 
     4766 */ 
    41614767Xinha.prototype.getHTML = function() 
    41624768{ 
     
    41844790}; 
    41854791 
     4792/** Performs various transformations of the HTML used internally, complement to Xinha.prototype.inwardHtml()   
     4793 *  Plugins can provide their own, additional transformations by defining a plugin.prototype.outwardHtml() implematation, 
     4794 *  which is called by this function 
     4795 * 
     4796 *  @private 
     4797 *  @see Xinha#inwardHtml 
     4798 *  @param {String} html 
     4799 *  @returns {String} HTML content 
     4800 */ 
    41864801Xinha.prototype.outwardHtml = function(html) 
    41874802{ 
     
    42424857}; 
    42434858 
     4859/** Performs various transformations of the HTML to be edited  
     4860 *  Plugins can provide their own, additional transformations by defining a plugin.prototype.inwardHtml() implematation, 
     4861 *  which is called by this function 
     4862 *   
     4863 *  @private 
     4864 *  @see Xinha#outwardHtml 
     4865 *  @param {String} html   
     4866 *  @returns {String} transformed HTML 
     4867 */ 
    42444868Xinha.prototype.inwardHtml = function(html) 
    42454869 
     
    42824906  return html; 
    42834907}; 
    4284  
     4908/** Apply the replacements defined in Xinha.Config.specialReplacements 
     4909 *   
     4910 *  @private 
     4911 *  @see Xinha#inwardSpecialReplacements 
     4912 *  @param {String} html 
     4913 *  @returns {String}  transformed HTML 
     4914 */ 
    42854915Xinha.prototype.outwardSpecialReplacements = function(html) 
    42864916{ 
     
    42954925    }  
    42964926    // alert('out : ' + from + '=>' + to); 
    4297     var reg = new RegExp(from.replace(Xinha.RE_Specials, '\\$1'), 'g'); 
     4927    var reg = new RegExp(Xinha.escapeStringForRegExp(from), 'g'); 
    42984928    html = html.replace(reg, to.replace(/\$/g, '$$$$')); 
    42994929    //html = html.replace(from, to); 
     
    43014931  return html; 
    43024932}; 
    4303  
     4933/** Apply the replacements defined in Xinha.Config.specialReplacements 
     4934 *   
     4935 *  @private 
     4936 *  @see Xinha#outwardSpecialReplacements 
     4937 *  @param {String} html 
     4938 *  @returns {String}  transformed HTML 
     4939 */ 
    43044940Xinha.prototype.inwardSpecialReplacements = function(html) 
    43054941{ 
     
    43184954    // html = html.replace(reg, to); 
    43194955    // html = html.replace(from, to); 
    4320     var reg = new RegExp(from.replace(Xinha.RE_Specials, '\\$1'), 'g'); 
     4956    var reg = new RegExp(Xinha.escapeStringForRegExp(from), 'g'); 
    43214957    html = html.replace(reg, to.replace(/\$/g, '$$$$')); // IE uses doubled dollar signs to escape backrefs, also beware that IE also implements $& $_ and $' like perl. 
    43224958  } 
    43234959  return html; 
    43244960}; 
    4325  
     4961/** Transforms the paths in src & href attributes 
     4962 *   
     4963 *  @private 
     4964 *  @see Xinha.Config#expandRelativeUrl 
     4965 *  @see Xinha.Config#stripSelfNamedAnchors 
     4966 *  @see Xinha.Config#stripBaseHref 
     4967 *  @see Xinha.Config#baseHref 
     4968 *  @param {String} html  
     4969 *  @returns {String} transformed HTML 
     4970 */ 
    43264971Xinha.prototype.fixRelativeLinks = function(html) 
    43274972{ 
     
    43414986        base_m = b.match( relPath ); 
    43424987        absPath = url[2].replace(/(\.\.\/)*/,base_m[1]); 
    4343         html = html.replace( new RegExp(url[2].replace( Xinha.RE_Specials, '\\$1' ) ),absPath ); 
     4988        html = html.replace( new RegExp(Xinha.escapeStringForRegExp(url[2])),absPath ); 
    43444989      } 
    43454990    } 
     
    43484993  if ( typeof this.config.stripSelfNamedAnchors != 'undefined' && this.config.stripSelfNamedAnchors ) 
    43494994  { 
    4350     var stripRe = new RegExp(document.location.href.replace(/&/g,'&amp;').replace(Xinha.RE_Specials, '\\$1') + '(#[^\'" ]*)', 'g'); 
     4995    var stripRe = new RegExp(Xinha.escapeStringForRegExp(document.location.href.replace(/&/g,'&amp;')) + '(#[^\'" ]*)', 'g'); 
    43514996    html = html.replace(stripRe, '$1'); 
    43524997  } 
     
    43575002    if ( typeof this.config.baseHref != 'undefined' && this.config.baseHref !== null ) 
    43585003    { 
    4359       baseRe = new RegExp( "((href|src|background)=\")(" + this.config.baseHref.replace( Xinha.RE_Specials, '\\$1' ) + ")", 'g' ); 
     5004      baseRe = new RegExp( "((href|src|background)=\")(" + Xinha.escapeStringForRegExp(this.config.baseHref) + ")", 'g' ); 
    43605005    } 
    43615006    else 
    43625007    { 
    4363       baseRe = new RegExp( "((href|src|background)=\")(" + document.location.href.replace( /^(https?:\/\/[^\/]*)(.*)/, '$1' ).replace( Xinha.RE_Specials, '\\$1' ) + ")", 'g' ); 
     5008      baseRe = new RegExp( "((href|src|background)=\")(" +  Xinha.escapeStringForRegExp(document.location.href.replace( /^(https?:\/\/[^\/]*)(.*)/, '$1' )) + ")", 'g' ); 
    43645009    } 
    43655010 
     
    43705015}; 
    43715016 
    4372 // retrieve the HTML (fastest version, but uses innerHTML) 
     5017/** retrieve the HTML (fastest version, but uses innerHTML) 
     5018 *   
     5019 *  @private 
     5020 *  @returns {String} HTML content 
     5021 */ 
    43735022Xinha.prototype.getInnerHTML = function() 
    43745023{ 
     
    44025051}; 
    44035052 
    4404 // completely change the HTML inside 
     5053/** Completely change the HTML inside 
     5054 * 
     5055 *  @private 
     5056 *  @param {String} html new content, should have been run through inwardHtml() first 
     5057 */ 
    44055058Xinha.prototype.setHTML = function(html) 
    44065059{ 
     
    44165069}; 
    44175070 
    4418 // sets the given doctype (useful when config.fullPage is true) 
     5071/** sets the given doctype (useful only when config.fullPage is true) 
     5072 *   
     5073 *  @private 
     5074 *  @param {String} doctype 
     5075 */ 
    44195076Xinha.prototype.setDoctype = function(doctype) 
    44205077{ 
     
    44265083 ***************************************************/ 
    44275084 
    4428 // variable used to pass the object to the popup editor window. 
     5085/** Variable used to pass the object to the popup editor window. 
     5086 *  @FIXME: Is this in use? 
     5087 *  @deprecated  
     5088 *  @private 
     5089 *  @type {Object} 
     5090 */ 
    44295091Xinha._object = null; 
    44305092 
    4431 // function that returns a clone of the given object 
     5093/** function that returns a clone of the given object 
     5094 *   
     5095 *  @private 
     5096 *  @param {Object} obj 
     5097 *  @returns {Object} cloned object 
     5098 */ 
    44325099Xinha.cloneObject = function(obj) 
    44335100{ 
     
    44685135  return newObj; 
    44695136}; 
    4470  
    4471 // selection & ranges 
    4472  
    4473 // moved Xinha.prototype._getSelection() to browser specific file 
    4474 // moved Xinha.prototype._createRange()  to browser specific file 
    4475  
    4476 // event handling 
    44775137 
    44785138/** Event Flushing 
     
    44815141 *  onunload, it will remove any event listeners (that were added 
    44825142 *  through _addEvent(s)) and clear any DOM-0 events. 
    4483  */ 
    4484 Xinha._eventFlushers = []; 
     5143 *  @private 
     5144 * 
     5145 */ 
    44855146Xinha.flushEvents = function() 
    44865147{ 
     
    45325193  // alert('Flushed ' + x + ' events.'); 
    45335194}; 
     5195 /** Holds the events to be flushed 
     5196  * @type Array 
     5197  */ 
     5198Xinha._eventFlushers = []; 
    45345199 
    45355200if ( document.addEventListener ) 
    45365201{ 
     5202 /** adds an event listener for the specified element and event type 
     5203 *   
     5204 *  @public 
     5205 *  @see   Xinha#_addEvents 
     5206 *  @see   Xinha#addDom0Event 
     5207 *  @see   Xinha#prependDom0Event 
     5208 *  @param {DomNode}  el the DOM element the event should be attached to  
     5209 *  @param {String}   evname the name of the event to listen for (without leading "on") 
     5210 *  @param {function} func the function to be called when the event is fired 
     5211 */ 
    45375212  Xinha._addEvent = function(el, evname, func) 
    45385213  { 
     
    45405215    Xinha._eventFlushers.push([el, evname, func]); 
    45415216  }; 
     5217  
     5218 /** removes an event listener previously added 
     5219 *   
     5220 *  @public 
     5221 *  @see   Xinha#_removeEvents 
     5222 *  @param {DomNode}  el the DOM element the event should be removed from  
     5223 *  @param {String}   evname the name of the event the listener should be removed from (without leading "on") 
     5224 *  @param {function} func the function to be removed 
     5225 */ 
    45425226  Xinha._removeEvent = function(el, evname, func) 
    45435227  { 
    45445228    el.removeEventListener(evname, func, true); 
    45455229  }; 
     5230  
     5231 /** stops bubbling of the event, if no further listeners should be triggered 
     5232 *   
     5233 *  @public 
     5234 *  @param {event} ev the event to be stopped 
     5235 */ 
    45465236  Xinha._stopEvent = function(ev) 
    45475237  { 
     
    45505240  }; 
    45515241} 
     5242 /** same as above, for IE 
     5243 *   
     5244 */ 
    45525245else if ( document.attachEvent ) 
    45535246{ 
     
    45915284  }; 
    45925285} 
    4593  
     5286 /** add several events at once to one element 
     5287 *   
     5288 *  @public 
     5289 *  @see Xinha#_addEvent 
     5290 *  @param {DomNode}  el the DOM element the event should be attached to  
     5291 *  @param {Array}    evs the names of the event to listen for (without leading "on") 
     5292 *  @param {function} func the function to be called when the event is fired 
     5293 */ 
    45945294Xinha._addEvents = function(el, evs, func) 
    45955295{ 
     
    45995299  } 
    46005300}; 
    4601  
     5301 /** remove several events at once to from element 
     5302 *   
     5303 *  @public 
     5304 *  @see Xinha#_removeEvent 
     5305 *  @param {DomNode}  el the DOM element the events should be remove from 
     5306 *  @param {Array}    evs the names of the events the listener should be removed from (without leading "on") 
     5307 *  @param {function} func the function to be removed 
     5308 */ 
    46025309Xinha._removeEvents = function(el, evs, func) 
    46035310{ 
     
    46215328 * whether subsequent handlers will be triggered (ie that the event will 
    46225329 * continue or be canceled). 
    4623  * 
     5330 *   
     5331 *  @public 
     5332 *  @see Xinha#_addEvent 
     5333 *  @see Xinha#prependDom0Event 
     5334 *  @param {DomNode}  el the DOM element the event should be attached to  
     5335 *  @param {String}   ev the name of the event to listen for (without leading "on") 
     5336 *  @param {function} fn the function to be called when the event is fired 
    46245337 */ 
    46255338 
     
    46315344 
    46325345 
    4633 /** 
    4634  * See addDom0Event, the difference is that handlers registered using 
    4635  * prependDom0Event will be triggered before existing DOM-0 events of the 
    4636  * same name on the same element. 
     5346/** See addDom0Event, the difference is that handlers registered using 
     5347 *  prependDom0Event will be triggered before existing DOM-0 events of the 
     5348 *  same name on the same element. 
     5349 *   
     5350 *  @public 
     5351 *  @see Xinha#_addEvent 
     5352 *  @see Xinha#addDom0Event 
     5353 *  @param {DomNode}  the DOM element the event should be attached to  
     5354 *  @param {String}   the name of the event to listen for (without leading "on") 
     5355 *  @param {function} the function to be called when the event is fired 
    46375356 */ 
    46385357 
     
    46465365 * Prepares an element to receive more than one DOM-0 event handler 
    46475366 * when handlers are added via addDom0Event and prependDom0Event. 
     5367 * 
     5368 * @private 
    46485369 */ 
    46495370Xinha._prepareForDom0Events = function(el, ev) 
     
    47135434}; 
    47145435 
    4715 Xinha._removeClass = function(el, className) 
    4716 { 
    4717   if ( ! ( el && el.className ) ) 
    4718   { 
    4719     return; 
    4720   } 
    4721   var cls = el.className.split(" "); 
    4722   var ar = []; 
    4723   for ( var i = cls.length; i > 0; ) 
    4724   { 
    4725     if ( cls[--i] != className ) 
    4726     { 
    4727       ar[ar.length] = cls[i]; 
    4728     } 
    4729   } 
    4730   el.className = ar.join(" "); 
    4731 }; 
    4732  
    4733 Xinha._addClass = function(el, className) 
    4734 { 
    4735   // remove the class first, if already there 
    4736   Xinha._removeClass(el, className); 
    4737   el.className += " " + className; 
    4738 }; 
    4739  
    4740 Xinha._hasClass = function(el, className) 
    4741 { 
    4742   if ( ! ( el && el.className ) ) 
    4743   { 
    4744     return false; 
    4745   } 
    4746   var cls = el.className.split(" "); 
    4747   for ( var i = cls.length; i > 0; ) 
    4748   { 
    4749     if ( cls[--i] == className ) 
    4750     { 
    4751       return true; 
    4752     } 
    4753   } 
    4754   return false; 
    4755 }; 
    4756  
     5436/** List of tag names that are defined as block level elements in HTML 
     5437 *   
     5438 *  @private 
     5439 *  @see Xinha#isBlockElement 
     5440 *  @type {String} 
     5441 */ 
    47575442Xinha._blockTags = " body form textarea fieldset ul ol dl li div " + 
    47585443"p h1 h2 h3 h4 h5 h6 quote pre table thead " + 
    47595444"tbody tfoot tr td th iframe address blockquote "; 
     5445 
     5446/** Checks if one element is in the list of elements that are defined as block level elements in HTML 
     5447 *   
     5448 *  @param {DomNode}  el The DOM element to check 
     5449 *  @returns {Boolean} 
     5450 */ 
    47605451Xinha.isBlockElement = function(el) 
    47615452{ 
    47625453  return el && el.nodeType == 1 && (Xinha._blockTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1); 
    47635454}; 
    4764  
     5455/** List of tag names that are allowed to contain a paragraph 
     5456 *   
     5457 *  @private 
     5458 *  @see Xinha#isParaContainer 
     5459 *  @type {String} 
     5460 */ 
    47655461Xinha._paraContainerTags = " body td th caption fieldset div"; 
     5462/** Checks if one element is in the list of elements that are allowed to contain a paragraph in HTML 
     5463 *   
     5464 *  @param {DomNode}  el The DOM element to check 
     5465 *  @returns {Boolean} 
     5466 */ 
    47665467Xinha.isParaContainer = function(el) 
    47675468{ 
     
    47695470}; 
    47705471 
    4771 // These are all the tags for which the end tag is not optional or  
    4772 // forbidden, taken from the list at: 
    4773 //   http://www.w3.org/TR/REC-html40/index/elements.html 
     5472 
     5473/* * These are all the tags for which the end tag is not optional or  forbidden, taken from the list at: 
     5474 *   http: www.w3.org/TR/REC-html40/index/elements.html 
     5475 *   
     5476 *  @private 
     5477 *  @see Xinha#needsClosingTag 
     5478 *  @type {String} 
     5479 */ 
    47745480Xinha._closingTags = " a abbr acronym address applet b bdo big blockquote button caption center cite code del dfn dir div dl em fieldset font form frameset h1 h2 h3 h4 h5 h6 i iframe ins kbd label legend map menu noframes noscript object ol optgroup pre q s samp script select small span strike strong style sub sup table textarea title tt u ul var "; 
    47755481 
     5482/** Checks if one element is in the list of elements for which the end tag is not optional or  forbidden in HTML 
     5483 *   
     5484 *  @param {DomNode}  el The DOM element to check 
     5485 *  @returns {Boolean} 
     5486 */ 
    47765487Xinha.needsClosingTag = function(el) 
    47775488{ 
     
    47795490}; 
    47805491 
    4781 // performs HTML encoding of some given string 
     5492/** Performs HTML encoding of some given string (converts HTML special characters to entities) 
     5493 *   
     5494 *  @param {String}  str The unencoded input 
     5495 *  @returns {String} The encoded output 
     5496 */ 
    47825497Xinha.htmlEncode = function(str) 
    47835498{ 
     
    47975512}; 
    47985513 
    4799 // moved Xinha.getHTML() to getHTML.js  
     5514/** Strips host-part of URL which is added by browsers to links relative to server root 
     5515 *   
     5516 *  @param {String}  string  
     5517 *  @returns {String}  
     5518 */ 
    48005519Xinha.prototype.stripBaseURL = function(string) 
    48015520{ 
     
    48045523    return string; 
    48055524  } 
    4806   // strip host-part of URL which is added by MSIE to links relative to server root 
    48075525  var baseurl = this.config.baseHref.replace(/^(https?:\/\/[^\/]+)(.*)$/, '$1'); 
    48085526  var basere = new RegExp(baseurl); 
    48095527  return string.replace(basere, ""); 
    48105528}; 
    4811  
     5529/** Removes whitespace from beginning and end of a string 
     5530 *   
     5531 *  @returns {String}  
     5532 */ 
    48125533String.prototype.trim = function() 
    48135534{ 
     
    48155536}; 
    48165537 
    4817 // creates a rgb-style color from a number 
     5538/** Creates a rgb-style rgb(r,g,b) color from a (24bit) number 
     5539 *   
     5540 *  @param {Integer} 
     5541 *  @returns {String} rgb(r,g,b) color definition 
     5542 */ 
    48185543Xinha._makeColor = function(v) 
    48195544{ 
     
    48305555}; 
    48315556 
    4832 // returns hexadecimal color representation from a number or a rgb-style color. 
     5557/** Returns hexadecimal color representation from a number or a rgb-style color. 
     5558 *   
     5559 *  @param {String|Integer} v rgb(r,g,b) or 24bit color definition 
     5560 *  @returns {String} #RRGGBB color definition 
     5561 */ 
    48335562Xinha._colorToRgb = function(v) 
    48345563{ 
     
    48805609}; 
    48815610 
    4882 // modal dialogs for Mozilla (for IE we're using the showModalDialog() call). 
    4883  
    4884 // receives an URL to the popup dialog and a function that receives one value; 
    4885 // this function will get called after the dialog is closed, with the return 
    4886 // value of the dialog. 
     5611/** Modal popup dialogs 
     5612 *   
     5613 *  @param {String} url URL to the popup dialog 
     5614 *  @param {Function} action A function that receives one value; this function will get called  
     5615 *                    after the dialog is closed, with the return value of the dialog. 
     5616 *  @param {Mixed} init A variable that is passed to the popup window to pass arbitrary data 
     5617 */ 
    48875618Xinha.prototype._popupDialog = function(url, action, init) 
    48885619{ 
     
    48905621}; 
    48915622 
    4892 // paths 
    4893  
     5623/** Creates a path in the form _editor_url + "plugins/" + plugin + "/img/" + file 
     5624 *   
     5625 *  @deprecated 
     5626 *  @param {String} file Name of the image 
     5627 *  @param {String} plugin optional If omitted, simply _editor_url + file is returned  
     5628 *  @returns {String} 
     5629 */ 
    48945630Xinha.prototype.imgURL = function(file, plugin) 
    48955631{ 
     
    49035639  } 
    49045640}; 
    4905  
     5641/** Creates a path 
     5642 *   
     5643 *  @deprecated 
     5644 *  @param {String} file Name of the popup 
     5645 *  @returns {String} 
     5646 */ 
    49065647Xinha.prototype.popupURL = function(file) 
    49075648{ 
     
    49285669}; 
    49295670 
    4930 /** 
    4931  * FIX: Internet Explorer returns an item having the _name_ equal to the given 
     5671/** FIX: Internet Explorer returns an item having the _name_ equal to the given 
    49325672 * id, even if it's not having any id.  This way it can return a different form 
    4933  * field even if it's not a textarea.  This workarounds the problem by 
     5673 * field, even if it's not a textarea.  This workarounds the problem by 
    49345674 * specifically looking to search only elements having a certain tag name. 
     5675 * @param {String} tag The tag name to limit the return to 
     5676 * @param {String} id 
     5677 * @returns {DomNode} 
    49355678 */ 
    49365679Xinha.getElementById = function(tag, id) 
     
    49485691 
    49495692 
    4950 /** Use some CSS trickery to toggle borders on tables */ 
     5693/** Use some CSS trickery to toggle borders on tables  
     5694 *      @returns {Boolean} always true 
     5695 */ 
    49515696 
    49525697Xinha.prototype._toggleBorders = function() 
     
    49785723  return true; 
    49795724}; 
    4980  
     5725/** Adds styles for internal use to the edited document 
     5726 *   
     5727 *  @private 
     5728 *  @see Xinha#stripCoreCSS 
     5729 *  @param {String} html optional   
     5730 *  @returns {String} html HTML with added styles or only styles if html omitted 
     5731 */ 
    49815732Xinha.addCoreCSS = function(html) 
    49825733{ 
     
    50015752    } 
    50025753} 
    5003  
     5754/** Remove internal styles 
     5755 *   
     5756 *  @private 
     5757 *  @see Xinha#addCoreCSS 
     5758 *  @param {String} html  
     5759 *  @returns {String}  
     5760 */ 
    50045761Xinha.stripCoreCSS = function(html) 
    50055762{ 
    50065763  return html.replace(/<style[^>]+title="Xinha Internal CSS"(.|\n)*?<\/style>/i, '');  
    50075764} 
    5008  
     5765/** Removes one CSS class (that is one of possible more parts  
     5766 *   separated by spaces) from a given element 
     5767 *   
     5768 *  @see Xinha#_removeClasses 
     5769 *  @param {DomNode}  el The DOM element the class will be removed from 
     5770 *  @param {String}   className The class to be removed 
     5771 */ 
     5772Xinha._removeClass = function(el, className) 
     5773{ 
     5774  if ( ! ( el && el.className ) ) 
     5775  { 
     5776    return; 
     5777  } 
     5778  var cls = el.className.split(" "); 
     5779  var ar = []; 
     5780  for ( var i = cls.length; i > 0; ) 
     5781  { 
     5782    if ( cls[--i] != className ) 
     5783    { 
     5784      ar[ar.length] = cls[i]; 
     5785    } 
     5786  } 
     5787  el.className = ar.join(" "); 
     5788}; 
     5789/** Adds one CSS class  to a given element (that is, it expands its className property by the given string, 
     5790 *  separated by a space) 
     5791 *   
     5792 *  @see Xinha#addClasses 
     5793 *  @param {DomNode}  el The DOM element the class will be added to 
     5794 *  @param {String}   className The class to be added 
     5795 */ 
     5796Xinha._addClass = function(el, className) 
     5797{ 
     5798  // remove the class first, if already there 
     5799  Xinha._removeClass(el, className); 
     5800  el.className += " " + className; 
     5801}; 
     5802 
     5803/** Adds CSS classes  to a given element (that is, it expands its className property by the given string, 
     5804 *  separated by a space, thereby checking that no class is doubly added) 
     5805 *   
     5806 *  @see Xinha#addClass 
     5807 *  @param {DomNode}  el The DOM element the classes will be added to 
     5808 *  @param {String}   classes The classes to be added 
     5809 */ 
    50095810Xinha.addClasses = function(el, classes) 
    50105811{ 
     
    50325833}; 
    50335834 
     5835/** Removes CSS classes (that is one or more of possibly several parts  
     5836 *   separated by spaces) from a given element 
     5837 *   
     5838 *  @see Xinha#_removeClasses 
     5839 *  @param {DomNode}  el The DOM element the class will be removed from 
     5840 *  @param {String}   className The class to be removed 
     5841 */ 
    50345842Xinha.removeClasses = function(el, classes) 
    50355843{ 
     
    50565864}; 
    50575865 
    5058 /** Alias these for convenience */ 
     5866/** Alias of Xinha._addClass() 
     5867 *  @see Xinha#_addClass 
     5868 */ 
    50595869Xinha.addClass       = Xinha._addClass; 
     5870/** Alias of Xinha.Xinha._removeClass() 
     5871 *  @see Xinha#_removeClass 
     5872 */ 
    50605873Xinha.removeClass    = Xinha._removeClass; 
     5874/** Alias of Xinha.addClasses() 
     5875 *  @see Xinha#addClasses 
     5876 */ 
    50615877Xinha._addClasses    = Xinha.addClasses; 
     5878/** Alias of Xinha.removeClasses() 
     5879 *  @see Xinha#removeClasses 
     5880 */ 
    50625881Xinha._removeClasses = Xinha.removeClasses; 
    50635882 
    5064 /** Use XML HTTPRequest to post some data back to the server and do something 
    5065  * with the response (asyncronously!), this is used by such things as the tidy functions 
     5883/** Checks if one element has set the given className 
     5884 *   
     5885 *  @param {DomNode}  el The DOM element to check 
     5886 *  @param {String}   className The class to be looked for 
     5887 *  @returns {Boolean} 
     5888 */ 
     5889Xinha._hasClass = function(el, className) 
     5890{ 
     5891  if ( ! ( el && el.className ) ) 
     5892  { 
     5893    return false; 
     5894  } 
     5895  var cls = el.className.split(" "); 
     5896  for ( var i = cls.length; i > 0; ) 
     5897  { 
     5898    if ( cls[--i] == className ) 
     5899    { 
     5900      return true; 
     5901    } 
     5902  } 
     5903  return false; 
     5904}; 
     5905 
     5906/** Use XMLHTTPRequest to post some data back to the server and do something 
     5907 *  with the response (asyncronously!), this is used by such things as the tidy functions 
     5908 *  @param {String} url The address for the HTTPRequest 
     5909 *  @param {Object} data The data to be passed to the server like {name:"value"} 
     5910 *  @param {Function} handler A function that is called when an answer is received from the server with the responseText  
     5911 *                             as argument                              
    50665912 */ 
    50675913Xinha._postback = function(url, data, handler) 
     
    51095955}; 
    51105956 
     5957/** Use XMLHTTPRequest to receive some data from the server and do something 
     5958 *  with the it (asyncronously!) 
     5959 *  @param {String} url The address for the HTTPRequest 
     5960 *  @param {Function} handler A function that is called when an answer is received from the server with the responseText  
     5961 *                             as argument                              
     5962 */ 
    51115963Xinha._getback = function(url, handler) 
    51125964{ 
     
    51335985  req.send(null); 
    51345986}; 
    5135  
     5987/** Use XMLHTTPRequest to receive some data from the server syncronously 
     5988 *  @param {String} url The address for the HTTPRequest 
     5989 */ 
    51365990Xinha._geturlcontent = function(url) 
    51375991{ 
     
    51536007}; 
    51546008 
    5155 /** 
    5156  * Unless somebody already has, make a little function to debug things 
    5157  */ 
     6009// Unless somebody already has, make a little function to debug things 
     6010 
    51586011if ( typeof dump == 'undefined' ) 
    51596012{ 
     
    51696022  } 
    51706023} 
    5171  
     6024if ( !Array.prototype.contains ) 
     6025{ 
     6026  /** Walks through an array and checks if the specified item exists in it 
     6027  * @param {String} needle The string to search for 
     6028  * @returns {Boolean} True if item found, false otherwise  
     6029  */ 
     6030  Array.prototype.contains = function(needle) 
     6031  { 
     6032    var haystack = this; 
     6033    for ( var i = 0; i < haystack.length; i++ ) 
     6034    { 
     6035      if ( needle == haystack[i] ) 
     6036      { 
     6037        return true; 
     6038      } 
     6039    } 
     6040    return false; 
     6041  }; 
     6042} 
     6043 
     6044if ( !Array.prototype.indexOf ) 
     6045{ 
     6046  /** Walks through an array and, if the specified item exists in it, returns the position 
     6047  * @param {String} needle The string to search for 
     6048  * @returns {Integer|null} Index position if item found, null otherwise  
     6049  */ 
     6050  Array.prototype.indexOf = function(needle) 
     6051  { 
     6052    var haystack = this; 
     6053    for ( var i = 0; i < haystack.length; i++ ) 
     6054    { 
     6055      if ( needle == haystack[i] ) 
     6056      { 
     6057        return i; 
     6058      } 
     6059    } 
     6060    return null; 
     6061  }; 
     6062} 
     6063if ( !Array.prototype.append ) 
     6064{ 
     6065  /** Adds an item to an array 
     6066   * @param {Mixed} a Item to add 
     6067   * @returns {Array} The array including the newly added item 
     6068   */ 
     6069  Array.prototype.append  = function(a) 
     6070  { 
     6071    for ( var i = 0; i < a.length; i++ ) 
     6072    { 
     6073      this.push(a[i]); 
     6074    } 
     6075    return this; 
     6076  }; 
     6077} 
     6078/** Returns true if all elements of <em>a2</em> are also contained in <em>a1</em> (at least I think this is what it does) 
     6079* @param {Array} a1 
     6080* @param {Array} a2 
     6081* @returns {Boolean} 
     6082*/ 
    51726083Xinha.arrayContainsArray = function(a1, a2) 
    51736084{ 
     
    51926103  return all_found; 
    51936104}; 
    5194  
     6105/** Walks through an array and applies a filter function to each item 
     6106* @param {Array} a1 The array to filter 
     6107* @param {Function} filterfn If this function returns true, the item is added to the new array 
     6108* @returns {Array} Filtered array 
     6109*/ 
    51956110Xinha.arrayFilter = function(a1, filterfn) 
    51966111{ 
     
    52056120  return new_a; 
    52066121}; 
    5207  
     6122/** Converts a Collection object to an array  
     6123* @param {Collection} collection The array to filter 
     6124* @returns {Array} Array containing the item of collection 
     6125*/ 
     6126Xinha.collectionToArray = function(collection) 
     6127{ 
     6128  var array = [ ]; 
     6129  for ( var i = 0; i < collection.length; i++ ) 
     6130  { 
     6131    array.push(collection.item(i)); 
     6132  } 
     6133  return array; 
     6134}; 
     6135 
     6136/** Index for Xinha.uniq function  
     6137*       @private 
     6138*/ 
    52086139Xinha.uniq_count = 0; 
     6140/** Returns a string that is unique on the page 
     6141*       @param {String} prefix This string is prefixed to a running number 
     6142*   @returns {String} 
     6143*/ 
    52096144Xinha.uniq = function(prefix) 
    52106145{ 
     
    52126147}; 
    52136148 
    5214 /** New language handling functions **/ 
    5215  
     6149// New language handling functions 
    52166150 
    52176151/** Load a language file. 
    52186152 *  This function should not be used directly, Xinha._lc will use it when necessary. 
    5219  * @param context Case sensitive context name, eg 'Xinha', 'TableOperations', ... 
     6153 *  @private 
     6154 *  @param {String} context Case sensitive context name, eg 'Xinha', 'TableOperations', ... 
     6155 *  @returns {Object} 
    52206156 */ 
    52216157Xinha._loadlang = function(context,url) 
     
    52666202 
    52676203/** Return a localised string. 
    5268  * @param string    English language string. It can also contain variables in the form "Some text with $variable=replaced text$".  
     6204 * @param {String} string English language string. It can also contain variables in the form "Some text with $variable=replaced text$".  
    52696205 *                  This replaces $variable in "Some text with $variable" with "replaced text" 
    5270  * @param context   Case sensitive context name, eg 'Xinha' (default), 'TableOperations'... 
    5271  * @param replace   Replace $variables in String, eg {foo: 'replaceText'} ($foo in string will be replaced) 
     6206 * @param {String} context   Case sensitive context name, eg 'Xinha' (default), 'TableOperations'... 
     6207 * @param {Object} replace   Replace $variables in String, eg {foo: 'replaceText'} ($foo in string will be replaced by replaceText) 
    52726208 */ 
    52736209Xinha._lc = function(string, context, replace) 
     
    53746310  return ret; 
    53756311}; 
    5376  
     6312/** Walks through the children of a given element and checks if any of the are visible (= not display:none) 
     6313 * @param {DomNode} el  
     6314 * @returns {Boolean}  
     6315 */ 
    53776316Xinha.hasDisplayedChildren = function(el) 
    53786317{ 
     
    53916330}; 
    53926331 
    5393 /** 
    5394  * Load a javascript file by inserting it in the HEAD tag and eventually call a function when loaded 
     6332/** Load a javascript file by inserting it in the HEAD tag and eventually call a function when loaded 
    53956333 * 
    5396  * Note that this method cannot be abstracted into browser specific files 
     6334 *  Note that this method cannot be abstracted into browser specific files 
    53976335 *  because this method LOADS the browser specific files.  Hopefully it should work for most 
    53986336 *  browsers as it is. 
    53996337 * 
    5400  * @param {string} U (Url)      Source url of the file to load 
    5401  * @param {object} C {Callback} Callback function to launch once ready (optional) 
    5402  * @param {object} O (scOpe)    Application scope for the callback function (optional) 
    5403  * @param {object} B (Bonus}    Arbitrary object send as a param to the callback function (optional) 
    5404  * @public 
    5405  *  
    5406  */ 
    5407   
     6338 * @param {String} url               Source url of the file to load 
     6339 * @param {Object} callback optional Callback function to launch once ready  
     6340 * @param {Object} scope    optional Application scope for the callback function 
     6341 * @param {Object} bonus    optional Arbitrary object send as a param to the callback function 
     6342 */ 
    54086343Xinha._loadback = function(url, callback, scope, bonus) 
    54096344 
     
    54346369}; 
    54356370 
    5436 Xinha.collectionToArray = function(collection) 
    5437 { 
    5438   var array = [ ]; 
    5439   for ( var i = 0; i < collection.length; i++ ) 
    5440   { 
    5441     array.push(collection.item(i)); 
    5442   } 
    5443   return array; 
    5444 }; 
    5445  
    5446 if ( !Array.prototype.append ) 
    5447 { 
    5448   Array.prototype.append  = function(a) 
    5449   { 
    5450     for ( var i = 0; i < a.length; i++ ) 
    5451     { 
    5452       this.push(a[i]); 
    5453     } 
    5454     return this; 
    5455   }; 
    5456 } 
    5457  
     6371/** Xinha's main loading function (see NewbieGuide) 
     6372 * @param {Array} editor_names 
     6373 * @param {Xinha.Config} default_config 
     6374 * @param {Array} plugin_names 
     6375 * @returns {Object} An object that contains references to all created editors indexed by the IDs of the textareas  
     6376 */ 
    54586377Xinha.makeEditors = function(editor_names, default_config, plugin_names) 
    54596378{ 
     
    54796398  return editors; 
    54806399}; 
    5481  
     6400/** Another main loading function (see NewbieGuide) 
     6401 * @param {Object} editors As returned by Xinha.makeEditors() 
     6402 */ 
    54826403Xinha.startEditors = function(editors) 
    54836404{ 
     
    54926413  } 
    54936414}; 
    5494  
     6415/** Registers the loaded plugins with the editor 
     6416 * @private 
     6417 * @param {Array} plugin_names 
     6418 */ 
    54956419Xinha.prototype.registerPlugins = function(plugin_names) 
    54966420{ 
     
    55076431}; 
    55086432 
    5509 /** Utility function to base64_encode some arbitrary data, uses the builtin btoa() if it exists (Moz) */ 
    5510  
     6433/** Utility function to base64_encode some arbitrary data, uses the builtin btoa() if it exists (Moz)  
     6434*  @param {String} input 
     6435*  @returns {String} 
     6436*/ 
    55116437Xinha.base64_encode = function(input) 
    55126438{ 
     
    55436469}; 
    55446470 
    5545 /** Utility function to base64_decode some arbitrary data, uses the builtin atob() if it exists (Moz) */ 
    5546  
     6471/** Utility function to base64_decode some arbitrary data, uses the builtin atob() if it exists (Moz) 
     6472 *  @param {String} input 
     6473 *  @returns {String} 
     6474 */ 
    55476475Xinha.base64_decode = function(input) 
    55486476{ 
     
    55816509  return output; 
    55826510}; 
    5583  
     6511/** Removes a node from the DOM 
     6512 *  @param {DomNode} el The element to be removed 
     6513 *  @returns {DomNode} The removed element 
     6514 */ 
    55846515Xinha.removeFromParent = function(el) 
    55856516{ 
     
    55926523  return el; 
    55936524}; 
    5594  
     6525/** Checks if some element has a parent node 
     6526 *  @param {DomNode} el  
     6527 *  @returns {Boolean} 
     6528 */ 
    55956529Xinha.hasParentNode = function(el) 
    55966530{ 
     
    56096543}; 
    56106544 
    5611 // moved Xinha.getOuterHTML() to browser specific file 
    5612  
    5613 // detect the size of visible area 
    5614 // when calling from a popup window, call Xinha.viewportSize(window) to get the size of the popup 
     6545/** Detect the size of visible area 
     6546 *  @param {Window} scope optional When calling from a popup window, pass its window object to get the values of the popup 
     6547 *  @returns {Object} Object with Integer properties x and y 
     6548 */ 
    56156549Xinha.viewportSize = function(scope) 
    56166550{ 
     
    56356569  return {'x':x,'y':y}; 
    56366570}; 
    5637  
     6571/** Detect the size of the whole document 
     6572 *  @param {Window} scope optional When calling from a popup window, pass its window object to get the values of the popup 
     6573 *  @returns {Object} Object with Integer properties x and y 
     6574 */ 
    56386575Xinha.pageSize = function(scope) 
    56396576{ 
     
    56566593  return {'x':x,'y':y}; 
    56576594}; 
    5658  
     6595/** Detect the current scroll position 
     6596 *  @param {Window} scope optional When calling from a popup window, pass its window object to get the values of the popup 
     6597 *  @returns {Object} Object with Integer properties x and y 
     6598 */ 
    56596599Xinha.prototype.scrollPos = function(scope) 
    56606600{ 
     
    56806620}; 
    56816621 
    5682 /**  
    5683  *  Calculate the top and left pixel position of an element in the DOM. 
    5684  * 
    5685  *  @param   element HTML Element DOM Node 
    5686  *  @returns Object with integer properties top and left 
     6622/** Calculate the top and left pixel position of an element in the DOM. 
     6623 *  @param  {DomNode} element HTML Element 
     6624 *  @returns {Object} Object with Integer properties top and left 
    56876625 */ 
    56886626  
     
    57026640  return { top:curtop, left:curleft }; 
    57036641} 
    5704  
    5705 // find X position of an element 
     6642/** Find left pixel position of an element in the DOM. 
     6643 *  @param  {DomNode} element HTML Element 
     6644 *  @returns {Integer}  
     6645 */ 
    57066646Xinha.findPosX = function(obj) 
    57076647{ 
     
    57176657  return curleft; 
    57186658}; 
    5719  
    5720 // find Y position of an element 
     6659/** Find top pixel position of an element in the DOM. 
     6660 *  @param  {DomNode} element HTML Element 
     6661 *  @returns {Integer}  
     6662 */ 
    57216663Xinha.findPosY = function(obj) 
    57226664{ 
     
    58226764}; 
    58236765 
     6766/** List of objects that have to be trated on page unload in order to work around the broken  
     6767 * Garbage Collector in IE 
     6768 * @private 
     6769 * @see Xinha#freeLater 
     6770 * @see Xinha#free 
     6771 * @see Xinha#collectGarbageForIE 
     6772 */ 
    58246773Xinha.toFree = []; 
     6774/** Adds objects to Xinha.toFree  
     6775 * @param {Object} object The object to free memory 
     6776 * @param (String} prop optional  The property to release 
     6777 * @private 
     6778 * @see Xinha#toFree 
     6779 * @see Xinha#free 
     6780 * @see Xinha#collectGarbageForIE 
     6781 */ 
    58256782Xinha.freeLater = function(obj,prop) 
    58266783{ 
     
    58286785}; 
    58296786 
    5830 /** 
    5831  * Release memory properties from object 
    5832  * @param {object} object The object to free memory 
    5833  * @param (string} prop   The property to release (optional) 
     6787/** Release memory properties from object 
     6788 * @param {Object} object The object to free memory 
     6789 * @param (String} prop optional The property to release 
    58346790 * @private 
     6791 * @see Xinha#collectGarbageForIE 
     6792 * @see Xinha#free 
    58356793 */ 
    58366794Xinha.free = function(obj, prop) 
     
    58506808 
    58516809/** IE's Garbage Collector is broken very badly.  We will do our best to  
    5852  *   do it's job for it, but we can't be perfect. 
     6810 *   do it's job for it, but we can't be perfect. Takes all objects from Xinha.free and releases sets the null 
     6811 * @private 
     6812 * @see Xinha#toFree 
     6813 * @see Xinha#free 
    58536814 */ 
    58546815 
     
    58696830 
    58706831/** Insert a node at the current selection point.  
    5871  * @param toBeInserted DomNode 
     6832 * @param {DomNode} toBeInserted 
    58726833 */ 
    58736834 
     
    58756836 
    58766837/** Get the parent element of the supplied or current selection.  
    5877  *  @param   sel optional selection as returned by getSelection 
    5878  *  @returns DomNode 
     6838 *  @param {Selection} sel optional selection as returned by getSelection 
     6839 *  @returns {DomNode} 
    58796840 */ 
    58806841   
     
    58866847 * at the bottom of the editor, or a "control" (eg image) 
    58876848 * 
    5888  * @returns null | DomNode 
     6849 * @returns {DomNode|null} 
    58896850 */ 
    58906851  
     
    58936854/**  
    58946855 * Determines if the given selection is empty (collapsed). 
    5895  * @param selection Selection object as returned by getSelection 
    5896  * @returns true|false 
     6856 * @param {Selection} sel Selection object as returned by getSelection 
     6857 * @returns {Boolean} 
    58976858 */ 
    58986859  
    58996860Xinha.prototype.selectionEmpty        = function(sel) { Xinha.notImplemented("selectionEmpty"); } 
     6861/**  
     6862 * Returns a range object to be stored  
     6863 * and later restored with Xinha.prototype.restoreSelection() 
     6864 * @returns {Range} 
     6865 */ 
     6866 
     6867Xinha.prototype.saveSelection = function() { Xinha.notImplemented("saveSelection"); } 
     6868 
     6869/** Restores a selection previously stored 
     6870 * @param {Range} savedSelection Range object as returned by Xinha.prototype.restoreSelection() 
     6871 */ 
     6872Xinha.prototype.restoreSelection = function(savedSelection)  { Xinha.notImplemented("restoreSelection"); } 
    59006873 
    59016874/** 
     
    59036876 * the node itself is selected for manipulation. 
    59046877 * 
    5905  * @param node DomNode  
    5906  * @param pos  Set to a numeric position inside the node to collapse the cursor here if possible.  
    5907  */ 
    5908   
     6878 * @param {DomNode} node  
     6879 * @param {Integer} pos  Set to a numeric position inside the node to collapse the cursor here if possible.  
     6880 */ 
    59096881Xinha.prototype.selectNodeContents    = function(node,pos) { Xinha.notImplemented("selectNodeContents"); } 
    59106882 
    59116883/** Insert HTML at the current position, deleting the selection if any.  
    59126884 *   
    5913  *  @param html string 
     6885 *  @param {String} html 
    59146886 */ 
    59156887  
     
    59186890/** Get the HTML of the current selection.  HTML returned has not been passed through outwardHTML. 
    59196891 * 
    5920  * @returns string 
     6892 * @returns {String} 
    59216893 */ 
    59226894Xinha.prototype.getSelectedHTML       = function() { Xinha.notImplemented("getSelectedHTML"); } 
     
    59246896/** Get a Selection object of the current selection.  Note that selection objects are browser specific. 
    59256897 * 
    5926  * @returns Selection 
     6898 * @returns {Selection} 
    59276899 */ 
    59286900  
     
    59306902 
    59316903/** Create a Range object from the given selection.  Note that range objects are browser specific. 
    5932  * 
    5933  *  @param sel Selection object (see getSelection) 
    5934  *  @returns Range 
    5935  */ 
    5936   
     6904 *  @see Xinha#getSelection 
     6905 *  @param {Selection} sel Selection object  
     6906 *  @returns {Range} 
     6907 */ 
    59376908Xinha.prototype.createRange           = function(sel) { Xinha.notImplemented("createRange"); } 
    59386909 
    59396910/** Determine if the given event object is a keydown/press event. 
    59406911 * 
    5941  *  @param event Event  
    5942  *  @returns true|false 
     6912 *  @param {Event} event  
     6913 *  @returns {Boolean} 
    59436914 */ 
    59446915  
     
    59486919 *  which for Xinha is a shortcut.  Note that CTRL-ALT-<key> is not a shortcut. 
    59496920 * 
    5950  *  @param    keyEvent 
    5951  *  @returns  true|false 
     6921 *  @param    {Event} keyEvent 
     6922 *  @returns  {Boolean} 
    59526923 */ 
    59536924  
     
    59656936 *  this method will return 'a', press SHIFT-a and it will return 'A'. 
    59666937 *  
    5967  *  @param   keyEvent 
    5968  *  @returns string 
     6938 *  @param   {Event} keyEvent 
     6939 *  @returns {String} 
    59696940 */ 
    59706941                                    
     
    59736944/** Return the HTML string of the given Element, including the Element. 
    59746945 *  
    5975  * @param element HTML Element DomNode 
    5976  * @returns string 
     6946 * @param {DomNode} element HTML Element 
     6947 * @returns {String} 
    59776948 */ 
    59786949  
     
    59816952/** Get a new XMLHTTPRequest Object ready to be used.  
    59826953 * 
    5983  * @returns object XMLHTTPRequest  
     6954 * @returns {XMLHTTPRequest} 
    59846955 */ 
    59856956 
     
    60046975  
    60056976// Compatability - all these names are deprecated and will be removed in a future version 
     6977/** Alias of activeElement() 
     6978 * @see Xinha#activeElement 
     6979 * @deprecated 
     6980 * @returns {DomNode|null} 
     6981 */ 
    60066982Xinha.prototype._activeElement  = function(sel) { return this.activeElement(sel); } 
     6983/** Alias of selectionEmpty() 
     6984 * @see Xinha#selectionEmpty 
     6985 * @deprecated 
     6986 * @param {Selection} sel Selection object as returned by getSelection 
     6987 * @returns {Boolean} 
     6988 */ 
    60076989Xinha.prototype._selectionEmpty = function(sel) { return this.selectionEmpty(sel); } 
     6990/** Alias of getSelection() 
     6991 * @see Xinha#getSelection 
     6992 * @deprecated 
     6993 * @returns {Selection} 
     6994 */ 
    60086995Xinha.prototype._getSelection   = function() { return this.getSelection(); } 
     6996/** Alias of createRange() 
     6997 * @see Xinha#createRange 
     6998 * @deprecated 
     6999 * @param {Selection} sel Selection object 
     7000 * @returns {Range} 
     7001 */ 
    60097002Xinha.prototype._createRange    = function(sel) { return this.createRange(sel); } 
    60107003HTMLArea = Xinha; 
Note: See TracChangeset for help on using the changeset viewer.