Changeset 177


Ignore:
Timestamp:
05/19/05 15:28:30 (9 years ago)
Author:
gogo
Message:
  • Minor comment changes.
  • Refactor events for form submit, reset and window unload
  • Fix reset handler to properly use the original textarea content
  • Minor changes to setHTML etc
  • Use onload for iframe to determine when to initIframe, instead of a timeout
  • Remove overlooked debugging statement in loadPlugins
  • Change some event registrations to use addDom0Event rather than element.onxxx = something
  • Add HTMLArea.flushEvents() as an implementation of #30 - sadly, doesn't work. This is not enabled in the full_example, use examples/testbed.html to test it out.
  • Added methods HTMLArea.addDom0Event and HTMLArea.prependDom0Event which are to be used instead of element.onxxxxx = something;
Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/examples/full_example-body.html

    r166 r177  
    6060       'TableOperations' 
    6161      ]; 
     62 
    6263             // THIS BIT OF JAVASCRIPT LOADS THE PLUGINS, NO TOUCHING  :) 
    6364             if(!HTMLArea.loadPlugins(xinha_plugins, xinha_init)) return; 
     
    132133</head> 
    133134 
    134 <body onload="xinha_init()"> 
     135<body> 
    135136 
    136   <form id="editors_here"> 
     137  <form id="editors_here" onsubmit="alert(this.myTextArea0.value);"> 
    137138    <textarea id="myTextArea" name="myTextArea" rows="10" cols="80" style="width:100%"></textarea> 
    138139    <textarea id="anotherOne" name="anotherOne" rows="10" cols="80" style="width:100%"></textarea> 
  • trunk/examples/full_example-menu.html

    r156 r177  
    8686 
    8787      <label> 
     88                  <input type="checkbox" name="plugins" value="FormOperations" /> FormOperations 
     89      </label> 
     90 
     91      <label> 
     92                  <input type="checkbox" name="plugins" value="HorizontalRule" /> HorizontalRule 
     93      </label> 
     94 
     95      <label> 
    8896        <input type="checkbox" name="plugins" value="LangMarks" /> LangMarks 
    8997      </label> 
  • trunk/examples/testbed.html

    r166 r177  
     1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
    12<html> 
    23<head> 
     
    5152      xinha_plugins = xinha_plugins ? xinha_plugins : 
    5253      [ 
    53       'FullScreen', 
    54       'TableOperations' 
     54        'FullScreen' 
    5555      ]; 
    5656             // THIS BIT OF JAVASCRIPT LOADS THE PLUGINS, NO TOUCHING  :) 
     
    118118 
    119119      HTMLArea.startEditors(xinha_editors); 
     120      window.onload = null; 
    120121    } 
    121122 
    122     window.onload = xinha_init; 
     123    window.onload   = xinha_init; 
     124    window.onunload = HTMLArea.flushEvents; 
    123125  </script> 
    124126</head> 
     
    127129 
    128130  <form action="javascript:var x = document.getElementById('editors_here');alert(x.myTextArea.value);" id="editors_here" onsubmit="alert(this.myTextArea.value);"> 
    129     <textarea id="myTextArea" name="myTextArea" style="width:100%;height:320"> 
     131    <textarea id="myTextArea" name="myTextArea" style="width:100%;height:320px;"> 
    130132      &lt;p&gt; 
    131133        Lorem ipsum dolor sit amet, consectetuer adipiscing elit. 
     
    148150    </textarea> 
    149151 
    150     <input type="submit" /> 
     152    <input type="submit" /> <input type="reset" /> 
    151153  </form> 
    152  
    153154</body> 
    154155</html> 
  • trunk/htmlarea.js

    r173 r177  
    186186  this.sizeIncludesPanels = true; 
    187187 
    188   // Width of the "Right Side" panel, when present 
    189   // these, and the width and height of the editor 
    190   // _must_ be pixel widths if you wish to have config.sizeIncludesPanels = false 
    191   // if you have sizeIncludesPanels true, they can be any valid CSS measurement. 
    192   // 
    193188  // If you are using Xinha in a "Standards Mode" page (using doctype switching) 
    194189  // then you must use pixel heights for the top and bottom panels, otherwise 
     
    12961291    // create the IFRAME & add to container 
    12971292  var iframe = document.createElement("iframe"); 
    1298   iframe.src = _editor_url + editor.config.URIs["blank"]; 
    12991293  this._framework.ed_cell.appendChild(iframe); 
    13001294  this._iframe = iframe; 
     
    13121306  this._framework.ed_cell.appendChild(textarea); 
    13131307 
     1308 
    13141309  // Set up event listeners for saving the iframe content to the textarea 
    1315   if (textarea.form) { 
    1316     // we have a form, on submit get the HTMLArea content and 
    1317     // update original textarea. 
    1318     var f = textarea.form; 
    1319     if (typeof f.__msh_prevOnSubmit == "undefined") 
    1320     { 
    1321       f.__msh_prevOnSubmit = []; 
    1322       if (typeof f.onsubmit == "function") 
    1323       { 
    1324         var funcref = f.onsubmit; 
    1325         f.__msh_prevOnSubmit.push(funcref); 
    1326         f.onsubmit = null; 
    1327       } 
    1328  
    1329       f.onsubmit = function() 
    1330       { 
    1331         var a = this.__msh_prevOnSubmit; 
    1332         // call previous submit methods if they were there. 
    1333         var allOK = true; 
    1334         for (var i = a.length; --i >= 0;) 
    1335         { 
    1336           // We want the handler to be a member of the form, not the array, so that "this" will work correctly 
    1337           this.__msh_tempEventHandler = a[i]; 
    1338           if(this.__msh_tempEventHandler() == false) 
    1339           { 
    1340             allOK = false; 
    1341             break; 
    1342           } 
    1343         } 
    1344         return allOK; 
    1345       } 
    1346     } 
    1347     f.__msh_prevOnSubmit.push(function() {editor._textArea.value = editor.outwardHtml(editor.getHTML());}); 
    1348  
    1349     if (typeof f.__msh_prevOnReset == "undefined") 
    1350     { 
    1351       f.__msh_prevOnReset = []; 
    1352       if (typeof f.onreset == "function") 
    1353       { 
    1354         var funcref = f.onreset; 
    1355         f.__msh_prevOnReset.push(funcref); 
    1356         f.onreset = null; 
    1357       } 
    1358  
    1359       f.onreset = function() 
    1360       { 
    1361         var a = this.__msh_prevOnReset; 
    1362         // call previous submit methods if they were there. 
    1363         var allOK = true; 
    1364         for (var i = a.length; --i >= 0;) 
    1365         { 
    1366           if(a[i]() == false) 
    1367           { 
    1368             allOK = false; 
    1369             break; 
    1370           } 
    1371         } 
    1372         return allOK; 
    1373       } 
    1374     } 
    1375     f.__msh_prevOnReset.push(function() {editor.setHTML(editor._textArea.value); editor.updateToolbar();}); 
     1310  if (textarea.form) 
     1311  { 
     1312    // onsubmit get the HTMLArea content and update original textarea. 
     1313    HTMLArea.prependDom0Event 
     1314    ( 
     1315      this._textArea.form, 
     1316      'submit', 
     1317      function() {editor._textArea.value = editor.outwardHtml(editor.getHTML()); return true;} 
     1318    ); 
     1319 
     1320    var initialTAContent = textarea.value; 
     1321 
     1322    // onreset revert the HTMLArea content to the textarea content 
     1323    HTMLArea.prependDom0Event 
     1324    ( 
     1325      this._textArea.form, 
     1326      'reset', 
     1327      function() { editor.setHTML(editor.inwardHtml(initialTAContent)); editor.updateToolbar(); return true; } 
     1328    ); 
    13761329  } 
    13771330 
    13781331  // add a handler for the "back/forward" case -- on body.unload we save 
    13791332  // the HTML content into the original textarea. 
    1380   try { 
    1381     HTMLArea._addEvent(window, 'unload', function() {textarea.value = editor.outwardHtml(editor.getHTML());} ); 
    1382   } catch(e) {}; 
     1333  HTMLArea.prependDom0Event(window, 'unload', function() {textarea.value = editor.outwardHtml(editor.getHTML()); return true; }); 
    13831334 
    13841335  // Hide textarea 
     
    13881339  editor.initSize(); 
    13891340 
    1390   // IMPORTANT: we have to allow Mozilla a short time to recognize the 
    1391   // new frame.  Otherwise we get a stupid exception. 
    1392  
    1393   setTimeout(function() { editor.initIframe()}, 50); 
     1341  // Add an event to initialize the iframe once loaded. 
     1342  editor._iframeLoadDone = false; 
     1343  HTMLArea._addEvent 
     1344  ( 
     1345    this._iframe, 
     1346    'load', 
     1347    function(e) 
     1348    { 
     1349      if(! editor._iframeLoadDone) 
     1350      { 
     1351        editor._iframeLoadDone = true; 
     1352        editor.initIframe(); 
     1353      } 
     1354      return true; 
     1355    } 
     1356  ); 
     1357 
     1358  // Set src of iframe 
     1359  this._iframe.src = _editor_url + editor.config.URIs["blank"]; 
    13941360}; 
    13951361 
     
    20642030      this._doc.getElementsByTagName("body")[0].innerHTML = RegExp.$1; 
    20652031  } else { 
     2032    var reac = this.editorIsActivated(); 
     2033    if(reac) this.deactivateEditor(); 
    20662034    var html_re = /<html>((.|\n)*?)<\/html>/i; 
    20672035    html = html.replace(html_re, "$1"); 
     
    20692037    this._doc.write(html); 
    20702038    this._doc.close(); 
    2071     this.activateEditor(); 
     2039    if(reac) this.activateEditor(); 
    20722040    return true; 
    20732041  } 
     
    20812049// return the plugin created to allow refresh when necessary 
    20822050HTMLArea.prototype.registerPlugin = function() { 
     2051  var plugin = arguments[0]; 
     2052 
    20832053  // We can only register plugins that have been succesfully loaded 
    2084   var plugin = arguments[0]; 
    20852054  if 
    20862055  ( 
     
    20892058    || (typeof plugin == 'string' && eval('typeof ' + plugin) == 'undefined') 
    20902059  ) return false; 
    2091    
     2060 
    20922061  var args = []; 
    20932062  for (var i = 1; i < arguments.length; ++i) 
     
    25452514        a.el = el; 
    25462515        a.editor = this; 
    2547         a.onclick = function() { 
     2516        HTMLArea.addDom0Event(a, 'click', function() { 
    25482517          this.blur(); 
    25492518          this.editor.selectNodeContents(this.el); 
    25502519          this.editor.updateToolbar(true); 
    25512520          return false; 
    2552         }; 
    2553         a.oncontextmenu = function() { 
     2521        }); 
     2522        HTMLArea.addDom0Event(a, 'contextmenu', function() { 
    25542523          // TODO: add context menu here 
    25552524          this.blur(); 
     
    25582527          alert(info); 
    25592528          return false; 
    2560         }; 
     2529        }); 
    25612530        var txt = el.tagName.toLowerCase(); 
    25622531        a.title = el.style.cssText; 
     
    42744243// completely change the HTML inside 
    42754244HTMLArea.prototype.setHTML = function(html) { 
    4276   switch (this._editMode) { 
    4277       case "wysiwyg"  : 
    4278     if (!this.config.fullPage) 
    4279       this._doc.body.innerHTML = html; 
    4280     else 
    4281       // this._doc.documentElement.innerHTML = html; 
    4282       this._doc.body.innerHTML = html; 
     4245  switch (this._editMode) 
     4246  { 
     4247    case "wysiwyg"  : 
     4248    { 
     4249      if (!this.config.fullPage) 
     4250      { 
     4251        this._doc.body.innerHTML = html; 
     4252      } 
     4253      else 
     4254      { 
     4255        this._doc.setFullHTML(html); 
     4256      } 
     4257    } 
    42834258    break; 
    4284       case "textmode" : this._textArea.value = html; break; 
    4285       default       : alert("Mode <" + mode + "> not defined!"); 
     4259 
     4260    case "textmode" : 
     4261    { 
     4262      this._textArea.value = html; 
     4263    } 
     4264    break; 
     4265 
     4266    default             : 
     4267    { 
     4268      alert("Mode <" + mode + "> not defined!"); 
     4269    } 
     4270    break; 
    42864271  } 
    42874272  return false; 
     
    43694354// event handling 
    43704355 
     4356/** Event Flushing 
     4357 *  To try and work around memory leaks in the rather broken 
     4358 *  garbage collector in IE, HTMLArea.flushEvents can be called 
     4359 *  onunload, it will remove any event listeners (that were added 
     4360 *  through _addEvent(s)) and clear any DOM-0 events. 
     4361 */ 
     4362HTMLArea._eventFlushers = [ ]; 
     4363HTMLArea.flushEvents = function() 
     4364{ 
     4365  var x = 0; 
     4366  var e = null; 
     4367  while(e = HTMLArea._eventFlushers.pop()) 
     4368  { 
     4369    if(e.length == 3) 
     4370    { 
     4371      HTMLArea._removeEvent(e[0], e[1], e[2]); 
     4372      x++; 
     4373    } 
     4374    else if (e.length == 2) 
     4375    { 
     4376      e[0]['on' + e[1]] = null; 
     4377      e[0]._xinha_dom0Events[e[1]] = null; 
     4378      x++; 
     4379    } 
     4380  } 
     4381 
     4382  if(document.all) 
     4383  { 
     4384    for(var i = 0; i < document.all.length; i++) 
     4385    { 
     4386      for(var j in document.all[i]) 
     4387      { 
     4388        if(/^on/.test(j) && typeof document.all[i][j] == 'function') 
     4389        { 
     4390          document.all[i][j] = null; 
     4391          x++; 
     4392        } 
     4393      } 
     4394    } 
     4395  } 
     4396  alert('Flushed ' + x + ' events.'); 
     4397} 
     4398 
    43714399HTMLArea._addEvent = function(el, evname, func) { 
    43724400  if (HTMLArea.is_ie) { 
     
    43754403    el.addEventListener(evname, func, true); 
    43764404  } 
     4405  HTMLArea._eventFlushers.push([el, evname, func]); 
    43774406}; 
    43784407 
     
    44074436}; 
    44084437 
     4438/** 
     4439 * Adds a standard "DOM-0" event listener to an element. 
     4440 * The DOM-0 events are those applied directly as attributes to 
     4441 * an element - eg element.onclick = stuff; 
     4442 * 
     4443 * By using this function instead of simply overwriting any existing 
     4444 * DOM-0 event by the same name on the element it will trigger as well 
     4445 * as the existing ones.  Handlers are triggered one after the other 
     4446 * in the order they are added. 
     4447 * 
     4448 * Remember to return true/false from your handler, this will determine 
     4449 * whether subsequent handlers will be triggered (ie that the event will 
     4450 * continue or be canceled). 
     4451 * 
     4452 */ 
     4453 
     4454HTMLArea.addDom0Event = function(el, ev, fn) 
     4455{ 
     4456  HTMLArea._prepareForDom0Events(el, ev); 
     4457  el._xinha_dom0Events[ev].unshift(fn); 
     4458} 
     4459 
     4460 
     4461/** 
     4462 * See addDom0Event, the difference is that handlers registered using 
     4463 * prependDom0Event will be triggered before existing DOM-0 events of the 
     4464 * same name on the same element. 
     4465 */ 
     4466 
     4467HTMLArea.prependDom0Event = function(el, ev, fn) 
     4468{ 
     4469  HTMLArea._prepareForDom0Events(el, ev); 
     4470  el._xinha_dom0Events[ev].push(fn); 
     4471} 
     4472 
     4473/** 
     4474 * Prepares an element to receive more than one DOM-0 event handler 
     4475 * when handlers are added via addDom0Event and prependDom0Event. 
     4476 */ 
     4477HTMLArea._prepareForDom0Events = function(el, ev) 
     4478{ 
     4479  // Create a structure to hold our lists of event handlers 
     4480  if(typeof el._xinha_dom0Events == 'undefined')     el._xinha_dom0Events = { }; 
     4481 
     4482  // Create a list of handlers for this event type 
     4483  if(typeof el._xinha_dom0Events[ev] == 'undefined') 
     4484  { 
     4485    el._xinha_dom0Events[ev] = [ ]; 
     4486    if(typeof el['on'+ev] == 'function') 
     4487    { 
     4488      el._xinha_dom0Events[ev].push(el['on'+ev]); 
     4489    } 
     4490 
     4491    // Make the actual event handler, which runs through 
     4492    // each of the handlers in the list and executes them 
     4493    // in the correct context. 
     4494    el['on'+ev] = function(event) 
     4495    { 
     4496      var a = el._xinha_dom0Events[ev]; 
     4497      // call previous submit methods if they were there. 
     4498      var allOK = true; 
     4499      for (var i = a.length; --i >= 0;) 
     4500      { 
     4501        // We want the handler to be a member of the form, not the array, so that "this" will work correctly 
     4502        el._xinha_tempEventHandler = a[i]; 
     4503        if(el._xinha_tempEventHandler(event) == false) 
     4504        { 
     4505          el._xinha_tempEventHandler = null; 
     4506          allOK = false; 
     4507          break; 
     4508        } 
     4509        el._xinha_tempEventHandler = null; 
     4510      } 
     4511      return allOK; 
     4512    } 
     4513 
     4514    HTMLArea._eventFlushers.push([el, ev]); 
     4515  } 
     4516} 
    44094517 
    44104518HTMLArea.prototype.notifyOn = function(ev, fn) 
     
    48975005        alert('An error has occurred: ' + req.statusText); 
    48985006      } 
     5007      req.onreadystatechange = null; 
    48995008    } 
    49005009  } 
     
    49365045        alert('An error has occurred: ' + req.statusText); 
    49375046      } 
     5047      req.onreadystatechange = null; 
    49385048    } 
    49395049  } 
  • trunk/inline-dialog.js

    r167 r177  
    130130  { 
    131131    var elems = this.getElementsByName(i); 
     132    if(!elems) continue; 
    132133    for(var x = 0; x < elems.length; x++) 
    133134    { 
     
    254255        else 
    255256        { 
    256           if(i.selectedIndex) 
     257          if(i.selectedIndex >= 0) 
    257258          { 
    258259            v = i.options[i.selectedIndex]; 
     
    289290            if(i.checked) 
    290291            { 
    291               if(v && v.push) 
     292              if(typeof v == 'object' && v.push) 
    292293              { 
    293294                v.push(i.value); 
  • trunk/popups/popup.js

    r76 r177  
    1111// 
    1212// $Id$ 
     13HTMLArea = window.opener.HTMLArea; 
    1314 
    1415function getAbsolutePos(el) { 
     
    7374                window.moveTo(x, y); 
    7475        } 
    75         document.body.onkeypress = __dlg_close_on_esc; 
     76        HTMLArea.addDom0Event(document.body, 'keypress', __dlg_close_on_esc); 
    7677}; 
    7778 
    7879function __dlg_translate(context) { 
    79     HTMLArea = window.opener.HTMLArea; 
    8080        var types = ["input", "select", "legend", "span", "option", "td", "button", "div", "label"]; 
    8181        for (var type = 0; type < types.length; ++type) { 
  • trunk/popupwin.js

    r87 r177  
    9696                switch (btn.toLowerCase()) { 
    9797                    case "ok": 
    98                         button.onclick = function() { 
     98      HTMLArea.addDom0Event(button, 'click', 
     99                        function() { 
    99100                                self.callHandler(); 
    100101                                self.close(); 
    101102                                return false; 
    102                         }; 
     103                        }); 
    103104                        break; 
    104105                    case "cancel": 
    105                         button.onclick = function() { 
     106                        HTMLArea.addDom0Event(button, 'click', function() { 
    106107                                self.close(); 
    107108                                return false; 
    108                         }; 
     109                        }); 
    109110                        break; 
    110111                } 
Note: See TracChangeset for help on using the changeset viewer.