summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Gohr <gohr@cosmocode.de>2009-08-04 17:05:01 +0200
committerAndreas Gohr <gohr@cosmocode.de>2009-08-04 17:05:01 +0200
commit8f99c3ec15712c974b5a5caf5f40ef9170103f67 (patch)
tree0cd92ce48d719617bca1021bad2659959b0bbe68
parent201ea5f3891ddc2bd1841288c6c03916fe3c68dc (diff)
downloadrpg-8f99c3ec15712c974b5a5caf5f40ef9170103f67.tar.gz
rpg-8f99c3ec15712c974b5a5caf5f40ef9170103f67.tar.bz2
Some text selection workarounds for MSIE
Ignore-this: b4a14bbf96712ec9ce9011e172f2af81 This patch solves some problems with reading the cursor positions and text selection on MSIE. note: development was part of the ICKE 2.0 project see http://www.icke-projekt.de for info darcs-hash:20090804150501-6e07b-5e3cf60261f5f51906df2d4cf15509e9075757e0.gz
-rw-r--r--lib/scripts/edit.js2
-rw-r--r--lib/scripts/textselection.js91
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);