1/** 2 * Text selection related functions. 3 */ 4 5/** 6 * selection prototype 7 * 8 * Object that capsulates the selection in a textarea. Returned by getSelection. 9 * 10 * @author Andreas Gohr <andi@splitbrain.org> 11 */ 12function selection_class(){ 13 this.start = 0; 14 this.end = 0; 15 this.obj = null; 16 this.rangeCopy = null; 17 18 this.getLength = function(){ 19 return this.end - this.start; 20 }; 21 22 this.getText = function(){ 23 if(!this.obj) return ''; 24 return this.obj.value.substring(this.start,this.end); 25 } 26} 27 28/** 29 * Get current selection/cursor position in a given textArea 30 * 31 * @link http://groups.drupal.org/node/1210 32 * @author Andreas Gohr <andi@splitbrain.org> 33 * @returns object - a selection object 34 */ 35function getSelection(textArea) { 36 var sel = new selection_class(); 37 38 sel.obj = textArea; 39 sel.start = textArea.value.length; 40 sel.end = textArea.value.length; 41 42 textArea.focus(); 43 if(document.getSelection) { // Mozilla et al. 44 sel.start = textArea.selectionStart; 45 sel.end = textArea.selectionEnd; 46 } else if(document.selection) { // MSIE 47 // The current selection 48 var range = document.selection.createRange(); 49 sel.rangeCopy = range.duplicate(); 50 // Select all text 51 sel.rangeCopy.moveToElementText(textArea); 52 // Now move 'dummy' end point to end point of original range 53 sel.rangeCopy.setEndPoint( 'EndToEnd', range ); 54 // Now we can calculate start and end points 55 sel.start = sel.rangeCopy.text.length - range.text.length; 56 sel.end = sel.start + range.text.length; 57 } 58 return sel; 59} 60 61/** 62 * Set the selection 63 * 64 * You need to get a selection object via getSelection() first, then modify the 65 * start and end properties and pass it back to this function. 66 * 67 * @link http://groups.drupal.org/node/1210 68 * @author Andreas Gohr <andi@splitbrain.org> 69 * @param object selection - a selection object as returned by getSelection() 70 */ 71function setSelection(selection){ 72 if(document.getSelection){ // FF 73 // what a pleasure in FF ;) 74 selection.obj.setSelectionRange(selection.start,selection.end); 75 } else if(document.selection) { // IE 76 // count number of newlines in str to work around stupid IE selection bug 77 var countNL = function(str) { 78 var m = str.split("\n"); 79 if (!m || !m.length) return 0; 80 return m.length-1; 81 }; 82 var fix = countNL(selection.obj.value.substring(0,selection.start)); 83 84 selection.rangeCopy.collapse(true); 85 selection.rangeCopy.moveStart('character',selection.start - fix); 86 selection.rangeCopy.moveEnd('character',selection.end - selection.start); 87 selection.rangeCopy.select(); 88 } 89} 90 91/** 92 * Inserts the given text at the current cursor position or replaces the current 93 * selection 94 * 95 * @author Andreas Gohr <andi@splitbrain.org> 96 * @param string text - the new text to be pasted 97 * @param objct selecttion - selection object returned by getSelection 98 * @param int opts.startofs - number of charcters at the start to skip from new selection 99 * @param int opts.endofs - number of charcters at the end to skip from new selection 100 * @param bool opts.ofs - set tru if new text should not be selected 101 */ 102function pasteText(selection,text,opts){ 103 if(!opts) opts = {}; 104 // replace the content 105 selection.obj.value = 106 selection.obj.value.substring(0, selection.start) + text + 107 selection.obj.value.substring(selection.end, selection.obj.value.length); 108 109 // set new selection 110 selection.end = selection.start + text.length; 111 112 // modify the new selection if wanted 113 if(opts.startofs) selection.start += opts.startofs; 114 if(opts.endofs) selection.end -= opts.endofs; 115 116 // no selection wanted? set cursor to end position 117 if(opts.nosel) selection.start = selection.end; 118 119 setSelection(selection); 120} 121 122 123/** 124 * Format selection 125 * 126 * Apply tagOpen/tagClose to selection in textarea, use sampleText instead 127 * of selection if there is none. 128 * 129 * @author Andreas Gohr <andi@splitbrain.org> 130 */ 131function insertTags(textAreaID, tagOpen, tagClose, sampleText){ 132 var txtarea = $(textAreaID); 133 134 var selection = getSelection(txtarea); 135 var text = selection.getText(); 136 var opts; 137 138 // don't include trailing space in selection 139 if(text.charAt(text.length - 1) == ' '){ 140 selection.end--; 141 text = selection.getText(); 142 } 143 144 if(!text){ 145 // nothing selected, use the sample text and select it 146 text = sampleText; 147 opts = { 148 startofs: tagOpen.length, 149 endofs: tagClose.length 150 }; 151 }else{ 152 // place cursor at the end 153 opts = { 154 nosel: true 155 }; 156 } 157 158 // surround with tags 159 text = tagOpen + text + tagClose; 160 161 // do it 162 pasteText(selection,text,opts); 163} 164 165/** 166 * Wraps around pasteText() for backward compatibility 167 * 168 * @author Andreas Gohr <andi@splitbrain.org> 169 */ 170function insertAtCarret(textAreaID, text){ 171 var txtarea = $(textAreaID); 172 var selection = getSelection(txtarea); 173 pasteText(selection,text,{nosel: true}); 174} 175 176