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