To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / public / javascripts / jstoolbar / jstoolbar.js @ 1298:4f746d8966dd

History | View | Annotate | Download (10.9 KB)

1 0:513646585e45 Chris
/* ***** BEGIN LICENSE BLOCK *****
2
 * This file is part of DotClear.
3
 * Copyright (c) 2005 Nicolas Martin & Olivier Meunier and contributors. All
4
 * rights reserved.
5
 *
6
 * DotClear is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * DotClear is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with DotClear; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 *
20
 * ***** END LICENSE BLOCK *****
21
*/
22
23
/* Modified by JP LANG for textile formatting */
24
25
function jsToolBar(textarea) {
26
        if (!document.createElement) { return; }
27
28
        if (!textarea) { return; }
29
30
        if ((typeof(document["selection"]) == "undefined")
31
        && (typeof(textarea["setSelectionRange"]) == "undefined")) {
32
                return;
33
        }
34
35
        this.textarea = textarea;
36
37
        this.editor = document.createElement('div');
38
        this.editor.className = 'jstEditor';
39
40
        this.textarea.parentNode.insertBefore(this.editor,this.textarea);
41
        this.editor.appendChild(this.textarea);
42
43
        this.toolbar = document.createElement("div");
44
        this.toolbar.className = 'jstElements';
45
        this.editor.parentNode.insertBefore(this.toolbar,this.editor);
46
47 1115:433d4f72a19b Chris
        // Dragable resizing
48
        if (this.editor.addEventListener && navigator.appVersion.match(/\bMSIE\b/))
49 0:513646585e45 Chris
        {
50
                this.handle = document.createElement('div');
51
                this.handle.className = 'jstHandle';
52
                var dragStart = this.resizeDragStart;
53
                var This = this;
54
                this.handle.addEventListener('mousedown',function(event) { dragStart.call(This,event); },false);
55
                // fix memory leak in Firefox (bug #241518)
56
                window.addEventListener('unload',function() {
57
                                var del = This.handle.parentNode.removeChild(This.handle);
58
                                delete(This.handle);
59
                },false);
60
61
                this.editor.parentNode.insertBefore(this.handle,this.editor.nextSibling);
62
        }
63
64
        this.context = null;
65
        this.toolNodes = {}; // lorsque la toolbar est dessinée , cet objet est garni
66
                                        // de raccourcis vers les éléments DOM correspondants aux outils.
67
}
68
69
function jsButton(title, fn, scope, className) {
70
    if(typeof jsToolBar.strings == 'undefined') {
71
      this.title = title || null;
72
    } else {
73
      this.title = jsToolBar.strings[title] || title || null;
74
    }
75
        this.fn = fn || function(){};
76
        this.scope = scope || null;
77
        this.className = className || null;
78
}
79
jsButton.prototype.draw = function() {
80
        if (!this.scope) return null;
81
82
        var button = document.createElement('button');
83
        button.setAttribute('type','button');
84
        button.tabIndex = 200;
85
        if (this.className) button.className = this.className;
86
        button.title = this.title;
87
        var span = document.createElement('span');
88
        span.appendChild(document.createTextNode(this.title));
89
        button.appendChild(span);
90
91
        if (this.icon != undefined) {
92
                button.style.backgroundImage = 'url('+this.icon+')';
93
        }
94
        if (typeof(this.fn) == 'function') {
95
                var This = this;
96
                button.onclick = function() { try { This.fn.apply(This.scope, arguments) } catch (e) {} return false; };
97
        }
98
        return button;
99
}
100
101
function jsSpace(id) {
102
        this.id = id || null;
103
        this.width = null;
104
}
105
jsSpace.prototype.draw = function() {
106
        var span = document.createElement('span');
107
        if (this.id) span.id = this.id;
108
        span.appendChild(document.createTextNode(String.fromCharCode(160)));
109
        span.className = 'jstSpacer';
110
        if (this.width) span.style.marginRight = this.width+'px';
111
112
        return span;
113
}
114
115
function jsCombo(title, options, scope, fn, className) {
116
        this.title = title || null;
117
        this.options = options || null;
118
        this.scope = scope || null;
119
        this.fn = fn || function(){};
120
        this.className = className || null;
121
}
122
jsCombo.prototype.draw = function() {
123
        if (!this.scope || !this.options) return null;
124
125
        var select = document.createElement('select');
126
        if (this.className) select.className = className;
127
        select.title = this.title;
128
129
        for (var o in this.options) {
130
                //var opt = this.options[o];
131
                var option = document.createElement('option');
132
                option.value = o;
133
                option.appendChild(document.createTextNode(this.options[o]));
134
                select.appendChild(option);
135
        }
136
137
        var This = this;
138
        select.onchange = function() {
139
                try {
140
                        This.fn.call(This.scope, this.value);
141
                } catch (e) { alert(e); }
142
143
                return false;
144
        }
145
146
        return select;
147
}
148
149
150
jsToolBar.prototype = {
151
        base_url: '',
152
        mode: 'wiki',
153
        elements: {},
154
        help_link: '',
155
156
        getMode: function() {
157
                return this.mode;
158
        },
159
160
        setMode: function(mode) {
161
                this.mode = mode || 'wiki';
162
        },
163
164
        switchMode: function(mode) {
165
                mode = mode || 'wiki';
166
                this.draw(mode);
167
        },
168
169
        setHelpLink: function(link) {
170
                this.help_link = link;
171
        },
172
173
        button: function(toolName) {
174
                var tool = this.elements[toolName];
175
                if (typeof tool.fn[this.mode] != 'function') return null;
176
                var b = new jsButton(tool.title, tool.fn[this.mode], this, 'jstb_'+toolName);
177
                if (tool.icon != undefined) b.icon = tool.icon;
178
                return b;
179
        },
180
        space: function(toolName) {
181
                var tool = new jsSpace(toolName)
182
                if (this.elements[toolName].width !== undefined)
183
                        tool.width = this.elements[toolName].width;
184
                return tool;
185
        },
186
        combo: function(toolName) {
187
                var tool = this.elements[toolName];
188
                var length = tool[this.mode].list.length;
189
190
                if (typeof tool[this.mode].fn != 'function' || length == 0) {
191
                        return null;
192
                } else {
193
                        var options = {};
194
                        for (var i=0; i < length; i++) {
195
                                var opt = tool[this.mode].list[i];
196
                                options[opt] = tool.options[opt];
197
                        }
198
                        return new jsCombo(tool.title, options, this, tool[this.mode].fn);
199
                }
200
        },
201
        draw: function(mode) {
202
                this.setMode(mode);
203
204
                // Empty toolbar
205
                while (this.toolbar.hasChildNodes()) {
206
                        this.toolbar.removeChild(this.toolbar.firstChild)
207
                }
208
                this.toolNodes = {}; // vide les raccourcis DOM/**/
209
210
                // Draw toolbar elements
211
                var b, tool, newTool;
212
213
                for (var i in this.elements) {
214
                        b = this.elements[i];
215
216
                        var disabled =
217
                        b.type == undefined || b.type == ''
218
                        || (b.disabled != undefined && b.disabled)
219
                        || (b.context != undefined && b.context != null && b.context != this.context);
220
221
                        if (!disabled && typeof this[b.type] == 'function') {
222
                                tool = this[b.type](i);
223
                                if (tool) newTool = tool.draw();
224
                                if (newTool) {
225
                                        this.toolNodes[i] = newTool; //mémorise l'accès DOM pour usage éventuel ultérieur
226
                                        this.toolbar.appendChild(newTool);
227
                                }
228
                        }
229
                }
230
        },
231
232
        singleTag: function(stag,etag) {
233
                stag = stag || null;
234
                etag = etag || stag;
235
236
                if (!stag || !etag) { return; }
237
238
                this.encloseSelection(stag,etag);
239
        },
240
241
        encloseLineSelection: function(prefix, suffix, fn) {
242
                this.textarea.focus();
243
244
                prefix = prefix || '';
245
                suffix = suffix || '';
246
247
                var start, end, sel, scrollPos, subst, res;
248
249
                if (typeof(document["selection"]) != "undefined") {
250
                        sel = document.selection.createRange().text;
251
                } else if (typeof(this.textarea["setSelectionRange"]) != "undefined") {
252
                        start = this.textarea.selectionStart;
253
                        end = this.textarea.selectionEnd;
254
                        scrollPos = this.textarea.scrollTop;
255
                        // go to the start of the line
256
                        start = this.textarea.value.substring(0, start).replace(/[^\r\n]*$/g,'').length;
257
                        // go to the end of the line
258
            end = this.textarea.value.length - this.textarea.value.substring(end, this.textarea.value.length).replace(/^[^\r\n]*/, '').length;
259
                        sel = this.textarea.value.substring(start, end);
260
                }
261
262
                if (sel.match(/ $/)) { // exclude ending space char, if any
263
                        sel = sel.substring(0, sel.length - 1);
264
                        suffix = suffix + " ";
265
                }
266
267
                if (typeof(fn) == 'function') {
268
                        res = (sel) ? fn.call(this,sel) : fn('');
269
                } else {
270
                        res = (sel) ? sel : '';
271
                }
272
273
                subst = prefix + res + suffix;
274
275
                if (typeof(document["selection"]) != "undefined") {
276
                        document.selection.createRange().text = subst;
277
                        var range = this.textarea.createTextRange();
278
                        range.collapse(false);
279
                        range.move('character', -suffix.length);
280
                        range.select();
281
                } else if (typeof(this.textarea["setSelectionRange"]) != "undefined") {
282
                        this.textarea.value = this.textarea.value.substring(0, start) + subst +
283
                        this.textarea.value.substring(end);
284
                        if (sel) {
285
                                this.textarea.setSelectionRange(start + subst.length, start + subst.length);
286
                        } else {
287
                                this.textarea.setSelectionRange(start + prefix.length, start + prefix.length);
288
                        }
289
                        this.textarea.scrollTop = scrollPos;
290
                }
291
        },
292
293
        encloseSelection: function(prefix, suffix, fn) {
294
                this.textarea.focus();
295
296
                prefix = prefix || '';
297
                suffix = suffix || '';
298
299
                var start, end, sel, scrollPos, subst, res;
300
301
                if (typeof(document["selection"]) != "undefined") {
302
                        sel = document.selection.createRange().text;
303
                } else if (typeof(this.textarea["setSelectionRange"]) != "undefined") {
304
                        start = this.textarea.selectionStart;
305
                        end = this.textarea.selectionEnd;
306
                        scrollPos = this.textarea.scrollTop;
307
                        sel = this.textarea.value.substring(start, end);
308
                }
309
310
                if (sel.match(/ $/)) { // exclude ending space char, if any
311
                        sel = sel.substring(0, sel.length - 1);
312
                        suffix = suffix + " ";
313
                }
314
315
                if (typeof(fn) == 'function') {
316
                        res = (sel) ? fn.call(this,sel) : fn('');
317
                } else {
318
                        res = (sel) ? sel : '';
319
                }
320
321
                subst = prefix + res + suffix;
322
323
                if (typeof(document["selection"]) != "undefined") {
324
                        document.selection.createRange().text = subst;
325
                        var range = this.textarea.createTextRange();
326
                        range.collapse(false);
327
                        range.move('character', -suffix.length);
328
                        range.select();
329
//                        this.textarea.caretPos -= suffix.length;
330
                } else if (typeof(this.textarea["setSelectionRange"]) != "undefined") {
331
                        this.textarea.value = this.textarea.value.substring(0, start) + subst +
332
                        this.textarea.value.substring(end);
333
                        if (sel) {
334
                                this.textarea.setSelectionRange(start + subst.length, start + subst.length);
335
                        } else {
336
                                this.textarea.setSelectionRange(start + prefix.length, start + prefix.length);
337
                        }
338
                        this.textarea.scrollTop = scrollPos;
339
                }
340
        },
341
342
        stripBaseURL: function(url) {
343
                if (this.base_url != '') {
344
                        var pos = url.indexOf(this.base_url);
345
                        if (pos == 0) {
346
                                url = url.substr(this.base_url.length);
347
                        }
348
                }
349
350
                return url;
351
        }
352
};
353
354
/** Resizer
355
-------------------------------------------------------- */
356
jsToolBar.prototype.resizeSetStartH = function() {
357
        this.dragStartH = this.textarea.offsetHeight + 0;
358
};
359
jsToolBar.prototype.resizeDragStart = function(event) {
360
        var This = this;
361
        this.dragStartY = event.clientY;
362
        this.resizeSetStartH();
363
        document.addEventListener('mousemove', this.dragMoveHdlr=function(event){This.resizeDragMove(event);}, false);
364
        document.addEventListener('mouseup', this.dragStopHdlr=function(event){This.resizeDragStop(event);}, false);
365
};
366
367
jsToolBar.prototype.resizeDragMove = function(event) {
368
        this.textarea.style.height = (this.dragStartH+event.clientY-this.dragStartY)+'px';
369
};
370
371
jsToolBar.prototype.resizeDragStop = function(event) {
372
        document.removeEventListener('mousemove', this.dragMoveHdlr, false);
373
        document.removeEventListener('mouseup', this.dragStopHdlr, false);
374
};