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 @ 441:cbce1fd3b1b7

History | View | Annotate | Download (11.2 KB)

1
/* ***** 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
        // Dragable resizing (only for gecko)
48
        if (this.editor.addEventListener)
49
        {
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
                var h = document.createElement('div');
211
                h.className = 'help'
212
                h.innerHTML = this.help_link;
213
                '<a href="/help/wiki_syntax.html" onclick="window.open(\'/help/wiki_syntax.html\', \'\', \'resizable=yes, location=no, width=300, height=640, menubar=no, status=no, scrollbars=yes\'); return false;">Aide</a>';
214
                this.toolbar.appendChild(h);
215

    
216
                // Draw toolbar elements
217
                var b, tool, newTool;
218
                
219
                for (var i in this.elements) {
220
                        b = this.elements[i];
221

    
222
                        var disabled =
223
                        b.type == undefined || b.type == ''
224
                        || (b.disabled != undefined && b.disabled)
225
                        || (b.context != undefined && b.context != null && b.context != this.context);
226
                        
227
                        if (!disabled && typeof this[b.type] == 'function') {
228
                                tool = this[b.type](i);
229
                                if (tool) newTool = tool.draw();
230
                                if (newTool) {
231
                                        this.toolNodes[i] = newTool; //mémorise l'accès DOM pour usage éventuel ultérieur
232
                                        this.toolbar.appendChild(newTool);
233
                                }
234
                        }
235
                }
236
        },
237
        
238
        singleTag: function(stag,etag) {
239
                stag = stag || null;
240
                etag = etag || stag;
241
                
242
                if (!stag || !etag) { return; }
243
                
244
                this.encloseSelection(stag,etag);
245
        },
246
        
247
        encloseLineSelection: function(prefix, suffix, fn) {
248
                this.textarea.focus();
249
                
250
                prefix = prefix || '';
251
                suffix = suffix || '';
252
                
253
                var start, end, sel, scrollPos, subst, res;
254
                
255
                if (typeof(document["selection"]) != "undefined") {
256
                        sel = document.selection.createRange().text;
257
                } else if (typeof(this.textarea["setSelectionRange"]) != "undefined") {
258
                        start = this.textarea.selectionStart;
259
                        end = this.textarea.selectionEnd;
260
                        scrollPos = this.textarea.scrollTop;
261
                        // go to the start of the line
262
                        start = this.textarea.value.substring(0, start).replace(/[^\r\n]*$/g,'').length;
263
                        // go to the end of the line
264
            end = this.textarea.value.length - this.textarea.value.substring(end, this.textarea.value.length).replace(/^[^\r\n]*/, '').length;
265
                        sel = this.textarea.value.substring(start, end);
266
                }
267
                
268
                if (sel.match(/ $/)) { // exclude ending space char, if any
269
                        sel = sel.substring(0, sel.length - 1);
270
                        suffix = suffix + " ";
271
                }
272
                
273
                if (typeof(fn) == 'function') {
274
                        res = (sel) ? fn.call(this,sel) : fn('');
275
                } else {
276
                        res = (sel) ? sel : '';
277
                }
278
                
279
                subst = prefix + res + suffix;
280
                
281
                if (typeof(document["selection"]) != "undefined") {
282
                        document.selection.createRange().text = subst;
283
                        var range = this.textarea.createTextRange();
284
                        range.collapse(false);
285
                        range.move('character', -suffix.length);
286
                        range.select();
287
                } else if (typeof(this.textarea["setSelectionRange"]) != "undefined") {
288
                        this.textarea.value = this.textarea.value.substring(0, start) + subst +
289
                        this.textarea.value.substring(end);
290
                        if (sel) {
291
                                this.textarea.setSelectionRange(start + subst.length, start + subst.length);
292
                        } else {
293
                                this.textarea.setSelectionRange(start + prefix.length, start + prefix.length);
294
                        }
295
                        this.textarea.scrollTop = scrollPos;
296
                }
297
        },
298
        
299
        encloseSelection: function(prefix, suffix, fn) {
300
                this.textarea.focus();
301
                
302
                prefix = prefix || '';
303
                suffix = suffix || '';
304
                
305
                var start, end, sel, scrollPos, subst, res;
306
                
307
                if (typeof(document["selection"]) != "undefined") {
308
                        sel = document.selection.createRange().text;
309
                } else if (typeof(this.textarea["setSelectionRange"]) != "undefined") {
310
                        start = this.textarea.selectionStart;
311
                        end = this.textarea.selectionEnd;
312
                        scrollPos = this.textarea.scrollTop;
313
                        sel = this.textarea.value.substring(start, end);
314
                }
315
                
316
                if (sel.match(/ $/)) { // exclude ending space char, if any
317
                        sel = sel.substring(0, sel.length - 1);
318
                        suffix = suffix + " ";
319
                }
320
                
321
                if (typeof(fn) == 'function') {
322
                        res = (sel) ? fn.call(this,sel) : fn('');
323
                } else {
324
                        res = (sel) ? sel : '';
325
                }
326
                
327
                subst = prefix + res + suffix;
328
                
329
                if (typeof(document["selection"]) != "undefined") {
330
                        document.selection.createRange().text = subst;
331
                        var range = this.textarea.createTextRange();
332
                        range.collapse(false);
333
                        range.move('character', -suffix.length);
334
                        range.select();
335
//                        this.textarea.caretPos -= suffix.length;
336
                } else if (typeof(this.textarea["setSelectionRange"]) != "undefined") {
337
                        this.textarea.value = this.textarea.value.substring(0, start) + subst +
338
                        this.textarea.value.substring(end);
339
                        if (sel) {
340
                                this.textarea.setSelectionRange(start + subst.length, start + subst.length);
341
                        } else {
342
                                this.textarea.setSelectionRange(start + prefix.length, start + prefix.length);
343
                        }
344
                        this.textarea.scrollTop = scrollPos;
345
                }
346
        },
347
        
348
        stripBaseURL: function(url) {
349
                if (this.base_url != '') {
350
                        var pos = url.indexOf(this.base_url);
351
                        if (pos == 0) {
352
                                url = url.substr(this.base_url.length);
353
                        }
354
                }
355
                
356
                return url;
357
        }
358
};
359

    
360
/** Resizer
361
-------------------------------------------------------- */
362
jsToolBar.prototype.resizeSetStartH = function() {
363
        this.dragStartH = this.textarea.offsetHeight + 0;
364
};
365
jsToolBar.prototype.resizeDragStart = function(event) {
366
        var This = this;
367
        this.dragStartY = event.clientY;
368
        this.resizeSetStartH();
369
        document.addEventListener('mousemove', this.dragMoveHdlr=function(event){This.resizeDragMove(event);}, false);
370
        document.addEventListener('mouseup', this.dragStopHdlr=function(event){This.resizeDragStop(event);}, false);
371
};
372

    
373
jsToolBar.prototype.resizeDragMove = function(event) {
374
        this.textarea.style.height = (this.dragStartH+event.clientY-this.dragStartY)+'px';
375
};
376

    
377
jsToolBar.prototype.resizeDragStop = function(event) {
378
        document.removeEventListener('mousemove', this.dragMoveHdlr, false);
379
        document.removeEventListener('mouseup', this.dragStopHdlr, false);
380
};