Ignore:
Timestamp:
10/02/08 17:07:26 (11 years ago)
Author:
douglas
Message:

FIXED Ticket #1176 Merging new dialogs branch back to trunk.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/modules/InternetExplorer/InternetExplorer.js

    r1001 r1044  
    147147   html = html.replace(/(<script|<!--)/i,"&nbsp;$1"); 
    148148    
     149   // We've got a workaround for certain issues with saving and restoring 
     150   // selections that may cause us to fill in junk span tags.  We'll clean 
     151   // those here 
     152   html = html.replace(/<span[^>]+id="__InsertSpan_Workaround_[a-z]+".*?>([\s\S]*?)<\/span>/i,"$1"); 
     153    
    149154   return html; 
    150155} 
     
    154159   // remove space added before first script on the page 
    155160   html = html.replace(/&nbsp;(\s*)(<script|<!--)/i,"$1$2"); 
     161 
     162   // We've got a workaround for certain issues with saving and restoring 
     163   // selections that may cause us to fill in junk span tags.  We'll clean 
     164   // those here 
     165   html = html.replace(/<span[^>]+id="__InsertSpan_Workaround_[a-z]+".*?>([\s\S]*?)<\/span>/i,"$1"); 
    156166    
    157167   return html; 
     
    441451Xinha.prototype.restoreSelection = function(savedSelection) 
    442452{ 
     453  // In order to prevent triggering the IE bug mentioned below, we will try to 
     454  // optimize by not restoring the selection if it happens to match the current 
     455  // selection. 
     456  var range = this.createRange(this.getSelection()); 
     457 
     458  // We can't compare two selections that come from different documents, so we 
     459  // must make sure they're from the same document. 
     460  var findDoc = function(el) 
     461  { 
     462    for (var root=el; root; root=root.parentNode) 
     463    { 
     464      if (root.tagName.toLowerCase() == 'html') 
     465      { 
     466        return root.parentNode; 
     467      } 
     468    } 
     469    return null; 
     470  } 
     471 
     472  if (findDoc(savedSelection.parentElement()) == findDoc(range.parentElement())) 
     473  { 
     474    if ((0 == range.compareEndPoints('StartToStart',savedSelection)) && 
     475        (0 == range.compareEndPoints('EndToEnd',savedSelection))) 
     476    { 
     477      // The selection hasn't moved, no need to restore. 
     478      return; 
     479    } 
     480  } 
     481 
    443482  try { savedSelection.select() } catch (e) {}; 
     483  range = this.createRange(this.getSelection()); 
     484  if (range.parentElement() != savedSelection.parentElement()) 
     485  { 
     486    // IE has a problem with selections at the end of text nodes that 
     487    // immediately precede block nodes. Example markup: 
     488    // <div>Text Node<p>Text in Block</p></div> 
     489    //               ^ 
     490    // The problem occurs when the cursor is after the 'e' in Node. 
     491 
     492    var solution = editor.config.selectWorkaround || 'InsertSpan'; 
     493    switch (solution) 
     494    { 
     495      case 'SimulateClick': 
     496        // Try to get the bounding box of the selection and then simulate a 
     497        // mouse click in the upper right corner to return the cursor to the 
     498        // correct location. 
     499 
     500        // No code yet, fall through to InsertSpan 
     501      case 'InsertSpan': 
     502        // This workaround inserts an empty span element so that we are no 
     503        // longer trying to select a text node, 
     504        var parentDoc = findDoc(savedSelection.parentElement()); 
     505 
     506        // A function used to generate a unique ID for our temporary span. 
     507        var randLetters = function(count) 
     508        { 
     509          // Build a list of 26 letters. 
     510          var Letters = ''; 
     511          for (var index = 0; index<26; ++index) 
     512          { 
     513            Letters += String.fromCharCode('a'.charCodeAt(0) + index); 
     514          } 
     515 
     516          var result = ''; 
     517          for (var index=0; index<count; ++index) 
     518          { 
     519            result += Letters.substr(Math.floor(Math.random()*Letters.length + 1), 1); 
     520          } 
     521          return result; 
     522        } 
     523 
     524        // We'll try to find a unique ID to use for finding our element. 
     525        var keyLength = 1; 
     526        var tempId = '__InsertSpan_Workaround_' + randLetters(keyLength); 
     527        while (parentDoc.getElementById(tempId)) 
     528        { 
     529          // Each time there's a collision, we'll increase our key length by 
     530          // one, making the chances of a collision exponentially more rare. 
     531          keyLength += 1; 
     532          tempId = '__InsertSpan_Workaround_' + randLetters(keyLength); 
     533        } 
     534 
     535        // Now that we have a uniquely identifiable element, we'll stick it and 
     536        // and use it to orient our selection. 
     537        savedSelection.pasteHTML('<span id="' + tempId + '"></span>'); 
     538        var tempSpan = parentDoc.getElementById(tempId); 
     539        savedSelection.moveToElementText(tempSpan); 
     540        savedSelection.select(); 
     541        break; 
     542      case 'JustificationHack': 
     543        // Setting the justification on an element causes IE to alter the 
     544        // markup so that the selection we want to make is possible. 
     545        // Unfortunately, this can force block elements to be kicked out of 
     546        // their containing element, so it is not recommended. 
     547 
     548        // Set a non-valid character and use it to anchor our selection. 
     549        var magicString = String.fromCharCode(1); 
     550        savedSelection.pasteHTML(magicString); 
     551        savedSelection.findText(magicString,-1); 
     552        savedSelection.select(); 
     553 
     554        // I don't know how to find out if there's an existing justification on 
     555        // this element.  Hopefully, you're doing all of your styling outside, 
     556        // so I'll just clear.  I already told you this was a hack. 
     557        savedSelection.execCommand('JustifyNone'); 
     558        savedSelection.pasteHTML(''); 
     559        break; 
     560      case 'VisiblePrompt': 
     561      default: 
     562        // This method will insert a little box character to hold our selection 
     563        // in the desired spot.  We're depending on the user to see this ugly 
     564        // box and delete it themselves. 
     565        var magicString = String.fromCharCode(1); 
     566        savedSelection.pasteHTML(magicString); 
     567        savedSelection.findText(magicString,-1); 
     568        savedSelection.select(); 
     569    } 
     570  } 
    444571} 
    445572 
     
    449576 * 
    450577 * @param node DomNode  
    451  * @param pos  Set to a numeric position inside the node to collapse the cursor here if possible.  
    452  */ 
    453   
    454 Xinha.prototype.selectNodeContents = function(node, pos) 
     578 * @param collapseToStart A boolean that, when supplied, says to collapse the selection. True collapses to the start, and false to the end. 
     579 */ 
     580  
     581Xinha.prototype.selectNodeContents = function(node, collapseToStart) 
    455582{ 
    456583  this.focusEditor(); 
    457584  this.forceRedraw(); 
    458585  var range; 
    459   var collapsed = typeof pos == "undefined" ? true : false; 
     586  var collapsed = typeof collapseToStart == "undefined" ? true : false; 
    460587  // Tables and Images get selected as "objects" rather than the text contents 
    461588  if ( collapsed && node.tagName && node.tagName.toLowerCase().match(/table|img|input|select|textarea/) ) 
     
    467594  { 
    468595    range = this._doc.body.createTextRange(); 
     596    if (3 == node.nodeType) 
     597    { 
     598      // Special handling for text nodes, since moveToElementText fails when 
     599      // attempting to select a text node 
     600 
     601      // Since the TextRange has a quite limited API, our strategy here is to 
     602      // select (where possible) neighboring nodes, and then move our ranges 
     603      // endpoints to be just inside of neighboring selections. 
     604      if (node.parentNode) 
     605      { 
     606        range.moveToElementText(node.parentNode); 
     607      } else 
     608      { 
     609        range.moveToElementText(this._doc.body); 
     610      } 
     611      var trimmingRange = this._doc.body.createTextRange(); 
     612 
     613      // In rare situations (mostly html that's been monkeyed about with by 
     614      // javascript, but that's what we're doing) there can be two adjacent 
     615      // text nodes.  Since we won't be able to handle these, we'll have to 
     616      // hack an offset by 'move'ing the number of characters they contain. 
     617      var texthackOffset = 0; 
     618      var borderElement=node.previousSibling; 
     619      for (; borderElement && (1 != borderElement.nodeType); borderElement = borderElement.previousSibling) 
     620      { 
     621        if (3 == borderElement.nodeType) 
     622        { 
     623          // IE doesn't count '\r' as a character, so we have to adjust the offset. 
     624          texthackOffset += borderElement.nodeValue.length-borderElement.nodeValue.split('\r').length-1; 
     625        } 
     626      } 
     627      if (borderElement && (1 == borderElement.nodeType)) 
     628      { 
     629        trimmingRange.moveToElementText(borderElement); 
     630        range.setEndPoint('StartToEnd', trimmingRange); 
     631      } 
     632      if (texthackOffset) 
     633      { 
     634        // We now need to move the selection forward the number of characters 
     635        // in all text nodes in between our text node and our ranges starting 
     636        // border. 
     637        range.moveStart('character',texthackOffset); 
     638      } 
     639 
     640      // Youpi!  Now we get to repeat this trimming on the right side. 
     641      texthackOffset = 0; 
     642      borderElement=node.nextSibling; 
     643      for (; borderElement && (1 != borderElement.nodeType); borderElement = borderElement.nextSibling) 
     644      { 
     645        if (3 == borderElement.nodeType) 
     646        { 
     647          // IE doesn't count '\r' as a character, so we have to adjust the offset. 
     648          texthackOffset += borderElement.nodeValue.length-borderElement.nodeValue.split('\r').length-1; 
     649          if (!borderElement.nextSibling) 
     650          { 
     651            // When a text node is the last child, IE adds an extra selection 
     652            // "placeholder" for the newline character.  We need to adjust for 
     653            // this character as well. 
     654            texthackOffset += 1; 
     655          } 
     656        } 
     657      } 
     658      if (borderElement && (1 == borderElement.nodeType)) 
     659      { 
     660        trimmingRange.moveToElementText(borderElement); 
     661        range.setEndPoint('EndToStart', trimmingRange); 
     662      } 
     663      if (texthackOffset) 
     664      { 
     665        // We now need to move the selection backward the number of characters 
     666        // in all text nodes in between our text node and our ranges ending 
     667        // border. 
     668        range.moveEnd('character',-texthackOffset); 
     669      } 
     670      if (!node.nextSibling) 
     671      { 
     672        // Above we performed a slight adjustment to the offset if the text 
     673        // node contains a selectable "newline".  We need to do the same if the 
     674        // node we are trying to select contains a newline. 
     675        range.moveEnd('character',-1); 
     676      } 
     677    } 
     678    else 
     679    { 
    469680    range.moveToElementText(node); 
    470     //(collapsed) && range.collapse(pos); 
     681    } 
     682  } 
     683  if (typeof collapseToStart != "undefined") 
     684  { 
     685    range.collapse(collapseToStart); 
     686    if (!collapseToStart) 
     687    { 
     688      range.moveStart('character',-1); 
     689      range.moveEnd('character',-1); 
     690    } 
    471691  } 
    472692  range.select(); 
Note: See TracChangeset for help on using the changeset viewer.