toolbar.js 7.9 KB

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