You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

350 lines
12 KiB

  1. /**
  2. * The Indexmenu Wizard
  3. *
  4. * @author Gerrit Uitslag
  5. * based on Linkwiz by
  6. * @author Andreas Gohr <gohr@cosmocode.de>
  7. * @author Pierre Spring <pierre.spring@caillou.ch>
  8. * and the concepts of the old indexmenu wizard
  9. */
  10. const indexmenu_wiz = {
  11. $wiz: null,
  12. timer: null,
  13. textArea: null,
  14. defaulttheme: 'default',
  15. fields: {
  16. div1: {
  17. elems: {
  18. jstoggle: {label: 'js'}
  19. }
  20. },
  21. div2: {
  22. tlbclass: 'jsitem theme',
  23. elems: {
  24. el1: {headerid: 'theme'}
  25. }
  26. },
  27. div3: {
  28. elems: {
  29. el2: {headerid: 'navigation'},
  30. navbar: {},
  31. context: {},
  32. nocookie: {tlbclass: 'jsitem'},
  33. noscroll: {tlbclass: 'jsitem'},
  34. notoc: {tlbclass: 'jsitem'}
  35. }
  36. },
  37. div4: {
  38. elems: {
  39. el3: {headerid: 'sort'},
  40. tsort: {},
  41. dsort: {},
  42. msort: {},
  43. hsort: {},
  44. rsort: {},
  45. nsort: {}
  46. }
  47. },
  48. div5: {
  49. elems: {
  50. el4: {headerid: 'filter'},
  51. nons: {},
  52. nopg: {}
  53. }
  54. },
  55. div6: {
  56. tlbclass: 'jsitem',
  57. elems: {
  58. el5: {headerid: 'performance'},
  59. max: {tlbclass: 'jsitem', numberinput: ['maxn', 'maxm']},
  60. maxjs: {tlbclass: 'jsitem', numberinput: ['maxjsn']},
  61. id: {tlbclass: 'jsitem', numberinput: ['idn']}
  62. }
  63. }
  64. },
  65. /**
  66. * Initialize the indexmenu_wiz by creating the needed HTML
  67. * and attaching the eventhandlers
  68. */
  69. init: function ($editor) {
  70. // position relative to the text area
  71. const pos = $editor.position();
  72. // create HTML Structure
  73. indexmenu_wiz.$wiz = jQuery(document.createElement('div'))
  74. .dialog({
  75. autoOpen: false,
  76. draggable: true,
  77. title: LANG.plugins.indexmenu.indexmenuwizard,
  78. resizable: false
  79. })
  80. .html(
  81. '<fieldset class="indexmenu_index"><legend>' + LANG.plugins.indexmenu.index + '</legend>' +
  82. '<div><label>' + LANG.plugins.indexmenu.namespace + '<input id="namespace" type="text"></label></div>' +
  83. '<div><label class="number">' + LANG.plugins.indexmenu.nsdepth + ' #<input id="nsdepth" type="text" value=1></label></div>' +
  84. '</fieldset>' +
  85. '<fieldset class="indexmenu_options"><legend>' + LANG.plugins.indexmenu.options + '</legend>' +
  86. '</fieldset>' +
  87. '<input type="submit" value="' + LANG.plugins.indexmenu.insert + '" class="button" id="indexmenu__insert">' +
  88. '<fieldset class="indexmenu_metanumber">' +
  89. '<label class="number">' + LANG.plugins.indexmenu.metanum + '<input type="text" id="metanumber"></label>' +
  90. '<input type="submit" value="' + LANG.plugins.indexmenu.insertmetanum + '" class="button" id="indexmenu__insertmetanum">' +
  91. '</fieldset>'
  92. )
  93. .parent()
  94. .attr('id', 'indexmenu__wiz')
  95. .css({
  96. 'position': 'absolute',
  97. 'top': (pos.top + 20) + 'px',
  98. 'left': (pos.left + 80) + 'px'
  99. })
  100. .hide()
  101. .appendTo('.dokuwiki:first');
  102. indexmenu_wiz.textArea = $editor[0];
  103. let $opt_fieldset = jQuery('#indexmenu__wiz fieldset.indexmenu_options');
  104. jQuery.each(indexmenu_wiz.fields, function (i, section) {
  105. let div = jQuery('<div>').addClass(section.tlbclass);
  106. jQuery.each(section.elems, function (elid, props) {
  107. if (props.headerid) {
  108. div.append('<strong>' + LANG.plugins.indexmenu[props.headerid] + '</strong><br />');
  109. } else {
  110. let label = props.label || elid;
  111. //checkbox
  112. jQuery("<label>")
  113. .addClass(props.tlbclass).addClass(props.numberinput ? ' hasnumber' : '')
  114. .html('<input id="' + elid + '" type="checkbox">' + label)
  115. .attr({title: LANG.plugins.indexmenu[elid]})
  116. .appendTo(div);
  117. //number inputs
  118. if (props.numberinput) {
  119. jQuery.each(props.numberinput, function (j, numid) {
  120. jQuery("<label>")
  121. .attr({title: LANG.plugins.indexmenu[elid]})
  122. .addClass("number " + props.tlbclass)
  123. .html('#<input type="text" id="' + numid + '">')
  124. .appendTo(div);
  125. });
  126. }
  127. }
  128. });
  129. $opt_fieldset.append(div);
  130. });
  131. indexmenu_wiz.includeThemes();
  132. if (JSINFO && JSINFO.namespace) {
  133. jQuery('#namespace').val(':' + JSINFO.namespace);
  134. }
  135. // attach event handlers
  136. //toggle js fields
  137. jQuery('#jstoggle')
  138. .on('change', function () {
  139. jQuery('#indexmenu__wiz .jsitem').toggle(this.checked);
  140. }).trigger('change')
  141. .parent().css({display: 'inline-block', width: '40px'}); //enlarge clickable area of label
  142. //interactive number fields
  143. jQuery('label.number input').on('keydown keyup', function () {
  144. //allow only numbers
  145. indexmenu_wiz.filterNumberinput(this);
  146. //checked the option if a number in input
  147. indexmenu_wiz.autoCheckboxForNumbers(this);
  148. });
  149. jQuery('#indexmenu__insert').on('click', indexmenu_wiz.insertIndexmenu);
  150. jQuery('#indexmenu__insertmetanum').on('click', indexmenu_wiz.insertMetaNumber);
  151. jQuery('#indexmenu__wiz').find('.ui-dialog-titlebar-close').on('click', indexmenu_wiz.hide);
  152. },
  153. /**
  154. * Request and include themes in wizard
  155. */
  156. includeThemes: function () {
  157. let addButtons = function (data) {
  158. jQuery('<div>')
  159. .attr('id', 'themebar')
  160. .addClass('toolbar')
  161. .appendTo('div.theme');
  162. jQuery.each(data.themes, function (i, theme) {
  163. let themeName = theme.split('.');
  164. let icoUrl = DOKU_BASE + data.themebase + '/' + theme + '/base.' + IndexmenuUtils.determineExtension(theme);
  165. let $ico = jQuery('<div>')
  166. .css({background: 'url(' + icoUrl + ') no-repeat center'});
  167. jQuery('<button>')
  168. .addClass('themebutton toolbutton')
  169. .attr('id', theme)
  170. .attr('title', themeName[0])
  171. .append($ico)
  172. .on('click', indexmenu_wiz.selectTheme)
  173. .appendTo('div#themebar');
  174. });
  175. //select default theme
  176. jQuery('#themebar button#' + indexmenu_wiz.defaulttheme).trigger('click');
  177. };
  178. jQuery.post(
  179. DOKU_BASE + 'lib/exe/ajax.php',
  180. {call: 'indexmenu', req: 'local'},
  181. addButtons,
  182. 'json'
  183. );
  184. },
  185. /**
  186. * set class 'selected' to clicked theme, remove from other
  187. */
  188. selectTheme: function () {
  189. jQuery('.themebutton').toggleClass('selected', false);
  190. jQuery(this).toggleClass('selected', true);
  191. },
  192. /**
  193. * Allow only number, by direct removing other characters from input
  194. */
  195. filterNumberinput: function (elem) {
  196. if (elem.value.match(/\D/)) {
  197. elem.value = this.value.replace(/\D/g, '');
  198. }
  199. },
  200. /**
  201. * When a number larger than zero is inputted, check the checkbox
  202. */
  203. autoCheckboxForNumbers: function (elem) {
  204. let checkboxid = elem.id.substring(0, elem.id.length - 1);
  205. let value = elem.value;
  206. //exception for second number field of max: only uncheck when first field is also empty
  207. if (elem.id === 'maxm' && !(elem.value > 0)) {
  208. value = parseInt(jQuery('input#maxn').val());
  209. }
  210. jQuery('input#' + checkboxid).prop('checked', value > 0);
  211. },
  212. /**
  213. * Insert the indexmenu with options to the textarea,
  214. * replacing the current selection or at the cursor position.
  215. */
  216. insertIndexmenu: function () {
  217. let options = '';
  218. jQuery('fieldset.indexmenu_options input').each(function (i, input) {
  219. let $label = jQuery(this).parent();
  220. if (input.checked && (!$label.hasClass('jsitem') || jQuery('input#jstoggle').is(':checked'))) {
  221. if (input.id === 'jstoggle') {
  222. //add js options
  223. options += ' js';
  224. //add theme
  225. let themename = jQuery('#themebar button.selected').attr('id');
  226. if (indexmenu_wiz.defaulttheme !== themename) { //skip default theme
  227. options += '#' + themename;
  228. }
  229. } else {
  230. //add option
  231. options += ' ' + input.id;
  232. //add numbers
  233. if ($label.hasClass('hasnumber')) {
  234. jQuery.each(indexmenu_wiz.fields.div6.elems[input.id].numberinput, function (j, numid) {
  235. let num = parseInt(jQuery('input#' + numid).val());
  236. options += num ? '#' + num : '';
  237. });
  238. }
  239. }
  240. }
  241. });
  242. options = options ? '|' + options.trim() : '';
  243. let sel, ns, depth, syntax, eo;
  244. // XXX: Compatibility Fix for 2014-05-05 "Ponder Stibbons", splitbrain/dokuwiki#505
  245. if (DWgetSelection) {
  246. sel = DWgetSelection(indexmenu_wiz.textArea);
  247. } else {
  248. sel = getSelection(indexmenu_wiz.textArea);
  249. }
  250. ns = jQuery('#namespace').val();
  251. depth = parseInt(jQuery('#nsdepth').val());
  252. depth = depth ? '#' + depth : '';
  253. syntax = '{{indexmenu>' + ns + depth + options + '}}';
  254. eo = depth.length + options.length + 2;
  255. pasteText(sel, syntax, {startofs: 12, endofs: eo});
  256. indexmenu_wiz.hide();
  257. },
  258. /**
  259. * Insert meta number for sorting in textarea
  260. * Takes number from input, otherwise tries the selection in textarea
  261. */
  262. insertMetaNumber: function () {
  263. let sel, selnum, syntax, number;
  264. // XXX: Compatibility Fix for 2014-05-05 "Ponder Stibbons", splitbrain/dokuwiki#505
  265. if (DWgetSelection) {
  266. sel = DWgetSelection(indexmenu_wiz.textArea);
  267. } else {
  268. sel = getSelection(indexmenu_wiz.textArea);
  269. }
  270. selnum = parseInt(sel.getText());
  271. number = parseInt(jQuery('input#metanumber').val());
  272. number = number || selnum || 1;
  273. syntax = '{{indexmenu_n>' + number + '}}';
  274. pasteText(sel, syntax, {startofs: 14, endofs: 2});
  275. indexmenu_wiz.hide();
  276. },
  277. /**
  278. * Show the indexmenu wizard
  279. */
  280. show: function () {
  281. // XXX: Compatibility Fix for 2014-05-05 "Ponder Stibbons", splitbrain/dokuwiki#505
  282. if (DWgetSelection) {
  283. indexmenu_wiz.selection = DWgetSelection(indexmenu_wiz.textArea);
  284. } else {
  285. indexmenu_wiz.selection = getSelection(indexmenu_wiz.textArea);
  286. }
  287. indexmenu_wiz.$wiz.show();
  288. jQuery('#namespace').trigger('focus');
  289. },
  290. /**
  291. * Hide the indexmenu wizard
  292. */
  293. hide: function () {
  294. indexmenu_wiz.$wiz.hide();
  295. indexmenu_wiz.textArea.focus(); //pure js
  296. },
  297. /**
  298. * Toggle the indexmenu wizard
  299. */
  300. toggle: function () {
  301. if (indexmenu_wiz.$wiz.css('display') === 'none') {
  302. indexmenu_wiz.show();
  303. } else {
  304. indexmenu_wiz.hide();
  305. }
  306. }
  307. };