diff options
-rw-r--r-- | lib/scripts/edit.js | 2 | ||||
-rw-r--r-- | lib/scripts/textselection.js | 91 |
2 files changed, 73 insertions, 20 deletions
diff --git a/lib/scripts/edit.js b/lib/scripts/edit.js index 51a8e3f8e..fe9057898 100644 --- a/lib/scripts/edit.js +++ b/lib/scripts/edit.js @@ -210,7 +210,7 @@ function keyHandler(e){ if(e.keyCode == 13){ // Enter //FIXME IE // keep current indention for lists and code - var match = search.match(/(\n +([*-] ?)?)/); + var match = search.match(/(\n +([\*-] ?)?)/); if(match){ insertAtCarret(field.id,match[1]); e.preventDefault(); // prevent enter key diff --git a/lib/scripts/textselection.js b/lib/scripts/textselection.js index 3ebab35e4..8b7632831 100644 --- a/lib/scripts/textselection.js +++ b/lib/scripts/textselection.js @@ -15,6 +15,7 @@ function selection_class(){ this.obj = null; this.rangeCopy = null; this.scroll = 0; + this.fix = 0; this.getLength = function(){ return this.end - this.start; @@ -29,8 +30,9 @@ function selection_class(){ /** * Get current selection/cursor position in a given textArea * - * @link http://groups.drupal.org/node/1210 + * @link http://groups.drupal.org/node/1210 * @author Andreas Gohr <andi@splitbrain.org> + * @link http://linebyline.blogspot.com/2006/11/textarea-cursor-position-in-internet.html * @returns object - a selection object */ function getSelection(textArea) { @@ -46,16 +48,74 @@ function getSelection(textArea) { sel.end = textArea.selectionEnd; sel.scroll = textArea.scrollTop; } else if(document.selection) { // MSIE + /* + * This huge lump of code is neccessary to work around two MSIE bugs: + * + * 1. Selections trim newlines at the end of the code + * 2. Selections count newlines as two characters + * + * FIXME see what code is not needed here and can be removed + */ + // The current selection - var range = document.selection.createRange(); - sel.rangeCopy = range.duplicate(); - // Select all text - sel.rangeCopy.moveToElementText(textArea); - // Now move 'dummy' end point to end point of original range - sel.rangeCopy.setEndPoint( 'EndToEnd', range ); - // Now we can calculate start and end points - sel.start = sel.rangeCopy.text.length - range.text.length; - sel.end = sel.start + range.text.length; + sel.rangeCopy = document.selection.createRange().duplicate(); + + var before_range = document.body.createTextRange(); + before_range.moveToElementText(textArea); // Selects all the text + before_range.setEndPoint("EndToStart", sel.rangeCopy); // Moves the end where we need it + + var before_finished = false, selection_finished = false; + var before_text, untrimmed_before_text, selection_text, untrimmed_selection_text; + + // Load the text values we need to compare + before_text = untrimmed_before_text = before_range.text; + selection_text = untrimmed_selection_text = sel.rangeCopy.text; + + // Check each range for trimmed newlines by shrinking the range by 1 character and seeing + // if the text property has changed. If it has not changed then we know that IE has trimmed + // a \r\n from the end. + do { + if (!before_finished) { + if (before_range.compareEndPoints("StartToEnd", before_range) == 0) { + before_finished = true; + } else { + before_range.moveEnd("character", -1) + if (before_range.text == before_text) { + untrimmed_before_text += "\n"; + } else { + before_finished = true; + } + } + } + if (!selection_finished) { + if (sel.rangeCopy.compareEndPoints("StartToEnd", sel.rangeCopy) == 0) { + selection_finished = true; + } else { + sel.rangeCopy.moveEnd("character", -1) + if (sel.rangeCopy.text == selection_text) { + untrimmed_selection_text += "\n"; + } else { + selection_finished = true; + } + } + } + } while ((!before_finished || !selection_finished)); + + var startPoint = untrimmed_before_text.length; + var endPoint = startPoint + untrimmed_selection_text.length; + + sel.start = startPoint; + sel.end = endPoint; + + + // count number of newlines in str to work around stupid IE selection bug + var countNL = function(str) { + var m = str.split("\r\n"); + if (!m || !m.length) return 0; + return m.length-1; + }; + sel.fix = countNL(sel.obj.value.substring(0,sel.start)); + } return sel; } @@ -76,16 +136,8 @@ function setSelection(selection){ selection.obj.setSelectionRange(selection.start,selection.end); if(selection.scroll) selection.obj.scrollTop = selection.scroll; } else if(document.selection) { // IE - // count number of newlines in str to work around stupid IE selection bug - var countNL = function(str) { - var m = str.split("\n"); - if (!m || !m.length) return 0; - return m.length-1; - }; - var fix = countNL(selection.obj.value.substring(0,selection.start)); - selection.rangeCopy.collapse(true); - selection.rangeCopy.moveStart('character',selection.start - fix); + selection.rangeCopy.moveStart('character',selection.start - selection.fix); selection.rangeCopy.moveEnd('character',selection.end - selection.start); selection.rangeCopy.select(); } @@ -105,6 +157,7 @@ function setSelection(selection){ function pasteText(selection,text,opts){ if(!opts) opts = {}; // replace the content + selection.obj.value = selection.obj.value.substring(0, selection.start) + text + selection.obj.value.substring(selection.end, selection.obj.value.length); |