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                $btn.attr('aria-controls', pickerid);
59                if (actionFunc === 'addBtnActionPicker') {
60                    $btn.attr('aria-haspopup', 'true');
61                }
62            }
63            return;
64        }
65
66        alert('unknown toolbar type: '+val.type+'  '+actionFunc);
67    });
68}
69
70/**
71 * Button action for format buttons
72 *
73 * @param  DOMElement btn   Button element to add the action to
74 * @param  array      props Associative array of button properties
75 * @param  string     edid  ID of the editor textarea
76 * @author Gabriel Birke <birke@d-scribe.de>
77 * @author Andreas Gohr <andi@splitbrain.org>
78 */
79function tb_format(btn, props, edid) {
80    var sample = props.sample || props.title;
81    insertTags(edid,
82               fixtxt(props.open),
83               fixtxt(props.close),
84               fixtxt(sample));
85    pickerClose();
86    return false;
87}
88
89/**
90 * Button action for format buttons
91 *
92 * This works exactly as tb_format() except that, if multiple lines
93 * are selected, each line will be formatted seperately
94 *
95 * @param  DOMElement btn   Button element to add the action to
96 * @param  array      props Associative array of button properties
97 * @param  string     edid  ID of the editor textarea
98 * @author Gabriel Birke <birke@d-scribe.de>
99 * @author Andreas Gohr <andi@splitbrain.org>
100 */
101function tb_formatln(btn, props, edid) {
102    var sample = props.sample || props.title,
103        opts,
104        selection = DWgetSelection(jQuery('#'+edid)[0]);
105
106    sample = fixtxt(sample);
107    props.open  = fixtxt(props.open);
108    props.close = fixtxt(props.close);
109
110    // is something selected?
111    if(selection.getLength()){
112        sample = selection.getText();
113        opts = {nosel: true};
114    }else{
115        opts = {
116            startofs: props.open.length,
117            endofs: props.close.length
118        };
119    }
120
121    sample = sample.split("\n").join(props.close+"\n"+props.open);
122    sample = props.open+sample+props.close;
123
124    pasteText(selection,sample,opts);
125
126    pickerClose();
127    return false;
128}
129
130/**
131 * Button action for insert buttons
132 *
133 * @param  DOMElement btn   Button element to add the action to
134 * @param  array      props Associative array of button properties
135 * @param  string     edid  ID of the editor textarea
136 * @author Gabriel Birke <birke@d-scribe.de>
137 * @author Andreas Gohr <andi@splitbrain.org>
138 */
139function tb_insert(btn, props, edid) {
140    insertAtCarret(edid,fixtxt(props.insert));
141    pickerClose();
142    return false;
143}
144
145/**
146 * Button action for the media popup
147 *
148 * @param  DOMElement btn   Button element to add the action to
149 * @param  array      props Associative array of button properties
150 * @param  string     edid  ID of the editor textarea
151 * @author Andreas Gohr <andi@splitbrain.org>
152 */
153function tb_mediapopup(btn, props, edid) {
154    window.open(
155        DOKU_BASE+props.url+encodeURIComponent(NS)+'&edid='+encodeURIComponent(edid),
156        props.name,
157        props.options);
158    return false;
159}
160
161/**
162 * Button action for automatic headlines
163 *
164 * Insert a new headline based on the current section level
165 *
166 * @param  DOMElement btn   Button element to add the action to
167 * @param  array      props Associative array of button properties
168 * @param  string     edid  ID of the editor textarea
169 * @author Andreas Gohr <andi@splitbrain.org>
170 */
171function tb_autohead(btn, props, edid){
172    var lvl = currentHeadlineLevel(edid),
173        tags;
174
175    // determine new level
176    lvl += props.mod;
177    if(lvl < 1) lvl = 1;
178    if(lvl > 5) lvl = 5;
179
180    tags = (new Array(8 - lvl)).join('=');
181    insertTags(edid, tags+' ', ' '+tags+"\n", props.text);
182    pickerClose();
183    return false;
184}
185
186
187/**
188 * Add button action for picker buttons and create picker element
189 *
190 * @param  jQuery      btn   Button element to add the action to
191 * @param  array      props Associative array of button properties
192 * @param  string     edid  ID of the editor textarea
193 * @return boolean    If button should be appended
194 * @author Gabriel Birke <birke@d-scribe.de>
195 */
196function addBtnActionPicker($btn, props, edid) {
197    var pickerid = 'picker'+(pickercounter++);
198    var picker = createPicker(pickerid, props, edid);
199    jQuery(picker).attr('aria-hidden', 'true');
200
201    $btn.click(
202        function(e) {
203            pickerToggle(pickerid,$btn);
204            e.preventDefault();
205            return '';
206        }
207    );
208
209    return pickerid;
210}
211
212/**
213 * Add button action for the link wizard button
214 *
215 * @param  DOMElement btn   Button element to add the action to
216 * @param  array      props Associative array of button properties
217 * @param  string     edid  ID of the editor textarea
218 * @return boolean    If button should be appended
219 * @author Andreas Gohr <gohr@cosmocode.de>
220 */
221function addBtnActionLinkwiz($btn, props, edid) {
222    dw_linkwiz.init(jQuery('#'+edid));
223    jQuery($btn).click(function(e){
224        dw_linkwiz.val = props;
225        dw_linkwiz.toggle();
226        e.preventDefault();
227        return '';
228    });
229    return 'link__wiz';
230}
231
232
233/**
234 * Show/Hide a previously created picker window
235 *
236 * @author Andreas Gohr <andi@splitbrain.org>
237 */
238function pickerToggle(pickerid,$btn){
239    var $picker = jQuery('#' + pickerid),
240        pos = $btn.offset();
241    if ($picker.hasClass('a11y')) {
242        $picker.removeClass('a11y').attr('aria-hidden', 'false');
243    } else {
244        $picker.addClass('a11y').attr('aria-hidden', 'true');
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');
269}
270
271
272/**
273 * Replaces \n with linebreaks
274 */
275function fixtxt(str){
276    return str.replace(/\\n/g,"\n");
277}
278
279jQuery(function () {
280    initToolbar('tool__bar','wiki__text',toolbar);
281    jQuery('#tool__bar').attr('role', 'toolbar');
282});
283