xref: /dokuwiki/lib/scripts/toolbar.js (revision 8ddf96a80b5d86bed96751fa293ecea428fa6975)
1// used to identify pickers
2var pickercounter=0;
3
4/**
5 * Create a toolbar
6 *
7 * @param  string tbid       ID of the element where to insert the toolbar
8 * @param  string edid       ID of the editor textarea
9 * @param  array  tb         Associative array defining the buttons
10 * @param  bool   allowblock Allow buttons creating multiline content
11 * @author Andreas Gohr <andi@splitbrain.org>
12 */
13function initToolbar(tbid,edid,tb, allowblock){
14    var $toolbar, $edit;
15    if (typeof tbid == 'string') {
16        $toolbar = jQuery('#' + tbid);
17    } else {
18        $toolbar = jQuery(tbid);
19    }
20
21    $edit = jQuery('#' + edid);
22
23    if ($toolbar.length == 0 || $edit.length == 0 || $edit.attr('readOnly')) {
24        return;
25    }
26
27    if (typeof allowblock === 'undefined') {
28        allowblock = true;
29    }
30
31    //empty the toolbar area:
32    $toolbar.html('');
33
34    jQuery.each(tb, function (k, val) {
35        if (!tb.hasOwnProperty(k) || (!allowblock && val.block === true)) {
36            return;
37        }
38        var actionFunc, $btn;
39
40        // create new button (jQuery object)
41        $btn = jQuery(createToolButton(val.icon, val.title, val.key, val.id,
42                                       val['class']));
43
44        // type is a tb function -> assign it as onclick
45        actionFunc = 'tb_'+val.type;
46        if( jQuery.isFunction(window[actionFunc]) ){
47            $btn.on('click', bind(window[actionFunc],$btn,val,edid) );
48            $toolbar.append($btn);
49            return;
50        }
51
52        // type is a init function -> execute it
53        actionFunc = 'addBtnAction'+val.type.charAt(0).toUpperCase()+val.type.substring(1);
54        if( jQuery.isFunction(window[actionFunc]) ){
55            var pickerid = window[actionFunc]($btn, val, edid);
56            if(pickerid !== ''){
57                $toolbar.append($btn);
58                $toolbar.append(jQuery('#'+pickerid));
59                $btn.attr('aria-expanded', 'false');
60            }
61            return;
62        }
63
64        alert('unknown toolbar type: '+val.type+'  '+actionFunc);
65    });
66}
67
68/**
69 * Button action for format buttons
70 *
71 * @param  DOMElement btn   Button element to add the action to
72 * @param  array      props Associative array of button properties
73 * @param  string     edid  ID of the editor textarea
74 * @author Gabriel Birke <birke@d-scribe.de>
75 * @author Andreas Gohr <andi@splitbrain.org>
76 */
77function tb_format(btn, props, edid) {
78    var sample = props.sample || props.title;
79    insertTags(edid,
80               fixtxt(props.open),
81               fixtxt(props.close),
82               fixtxt(sample));
83    pickerClose();
84    return false;
85}
86
87/**
88 * Button action for format buttons
89 *
90 * This works exactly as tb_format() except that, if multiple lines
91 * are selected, each line will be formatted seperately
92 *
93 * @param  DOMElement btn   Button element to add the action to
94 * @param  array      props Associative array of button properties
95 * @param  string     edid  ID of the editor textarea
96 * @author Gabriel Birke <birke@d-scribe.de>
97 * @author Andreas Gohr <andi@splitbrain.org>
98 */
99function tb_formatln(btn, props, edid) {
100    var sample = props.sample || props.title,
101        opts,
102        selection = DWgetSelection(jQuery('#'+edid)[0]);
103
104    sample = fixtxt(sample);
105    props.open  = fixtxt(props.open);
106    props.close = fixtxt(props.close);
107
108    // is something selected?
109    if(selection.getLength()){
110        sample = selection.getText();
111        opts = {nosel: true};
112    }else{
113        opts = {
114            startofs: props.open.length,
115            endofs: props.close.length
116        };
117    }
118
119    sample = sample.split("\n").join(props.close+"\n"+props.open);
120    sample = props.open+sample+props.close;
121
122    pasteText(selection,sample,opts);
123
124    pickerClose();
125    return false;
126}
127
128/**
129 * Button action for insert buttons
130 *
131 * @param  DOMElement btn   Button element to add the action to
132 * @param  array      props Associative array of button properties
133 * @param  string     edid  ID of the editor textarea
134 * @author Gabriel Birke <birke@d-scribe.de>
135 * @author Andreas Gohr <andi@splitbrain.org>
136 */
137function tb_insert(btn, props, edid) {
138    insertAtCarret(edid,fixtxt(props.insert));
139    pickerClose();
140    return false;
141}
142
143/**
144 * Button action for the media popup
145 *
146 * @param  DOMElement btn   Button element to add the action to
147 * @param  array      props Associative array of button properties
148 * @param  string     edid  ID of the editor textarea
149 * @author Andreas Gohr <andi@splitbrain.org>
150 */
151function tb_mediapopup(btn, props, edid) {
152    window.open(
153        DOKU_BASE+props.url+encodeURIComponent(NS)+'&edid='+encodeURIComponent(edid),
154        props.name,
155        props.options);
156    return false;
157}
158
159/**
160 * Button action for automatic headlines
161 *
162 * Insert a new headline based on the current section level
163 *
164 * @param  DOMElement btn   Button element to add the action to
165 * @param  array      props Associative array of button properties
166 * @param  string     edid  ID of the editor textarea
167 * @author Andreas Gohr <andi@splitbrain.org>
168 */
169function tb_autohead(btn, props, edid){
170    var lvl = currentHeadlineLevel(edid),
171        tags;
172
173    // determine new level
174    lvl += props.mod;
175    if(lvl < 1) lvl = 1;
176    if(lvl > 5) lvl = 5;
177
178    tags = (new Array(8 - lvl)).join('=');
179    insertTags(edid, tags+' ', ' '+tags+"\n", props.text);
180    pickerClose();
181    return false;
182}
183
184
185/**
186 * Add button action for picker buttons and create picker element
187 *
188 * @param  jQuery      btn   Button element to add the action to
189 * @param  array      props Associative array of button properties
190 * @param  string     edid  ID of the editor textarea
191 * @return boolean    If button should be appended
192 * @author Gabriel Birke <birke@d-scribe.de>
193 */
194function addBtnActionPicker($btn, props, edid) {
195    var pickerid = 'picker'+(pickercounter++);
196    var picker = createPicker(pickerid, props, edid);
197    jQuery(picker).attr('aria-hidden', 'true');
198
199    $btn.click(
200        function(e) {
201            pickerToggle(pickerid,$btn);
202            e.preventDefault();
203            return '';
204        }
205    );
206
207    return pickerid;
208}
209
210/**
211 * Add button action for the link wizard button
212 *
213 * @param  DOMElement btn   Button element to add the action to
214 * @param  array      props Associative array of button properties
215 * @param  string     edid  ID of the editor textarea
216 * @return boolean    If button should be appended
217 * @author Andreas Gohr <gohr@cosmocode.de>
218 */
219function addBtnActionLinkwiz($btn, props, edid) {
220    dw_linkwiz.init(jQuery('#'+edid));
221    jQuery($btn).click(function(e){
222        dw_linkwiz.val = props;
223        dw_linkwiz.toggle();
224        e.preventDefault();
225        return '';
226    });
227    return 'link__wiz';
228}
229
230
231/**
232 * Show/Hide a previously created picker window
233 *
234 * @author Andreas Gohr <andi@splitbrain.org>
235 */
236function pickerToggle(pickerid,$btn){
237    var $picker = jQuery('#' + pickerid),
238        pos = $btn.offset();
239    if ($picker.hasClass('a11y')) {
240        $picker.removeClass('a11y').attr('aria-hidden', 'false');
241        $btn.attr('aria-expanded', 'true');
242    } else {
243        $picker.addClass('a11y').attr('aria-hidden', 'true');
244        $btn.attr('aria-expanded', 'false');
245    }
246    var picker_left = pos.left + 3,
247        picker_width = $picker.width(),
248        window_width = jQuery(window).width();
249    if (picker_width > 300) {
250        $picker.css("max-width", "300");
251        picker_width = 300;
252    }
253    if ((picker_left + picker_width + 40) > window_width) {
254        picker_left = window_width - picker_width - 40;
255    }
256    if (picker_left < 0) {
257        picker_left = 0;
258    }
259    $picker.offset({left: picker_left, top: pos.top+$btn[0].offsetHeight+3});
260}
261
262/**
263 * Close all open pickers
264 *
265 * @author Andreas Gohr <andi@splitbrain.org>
266 */
267function pickerClose(){
268    jQuery('.picker').addClass('a11y').attr('aria-hidden', 'true');
269    jQuery('.picker').prev().attr('aria-expanded', 'false');
270}
271
272
273/**
274 * Replaces \n with linebreaks
275 */
276function fixtxt(str){
277    return str.replace(/\\n/g,"\n");
278}
279
280jQuery(function () {
281    initToolbar('tool__bar','wiki__text',toolbar);
282    jQuery('#tool__bar').attr('role', 'toolbar');
283});
284