diff options
Diffstat (limited to 'plugins/55/indexmenu/script.js')
-rw-r--r-- | plugins/55/indexmenu/script.js | 504 |
1 files changed, 504 insertions, 0 deletions
diff --git a/plugins/55/indexmenu/script.js b/plugins/55/indexmenu/script.js new file mode 100644 index 0000000..93d48d3 --- /dev/null +++ b/plugins/55/indexmenu/script.js @@ -0,0 +1,504 @@ + +// Context menu +var indexmenu_contextmenu = {'all': []}; + +/* DOKUWIKI:include scripts/nojsindex.js */ +/* DOKUWIKI:include scripts/toolbarindexwizard.js */ +/* DOKUWIKI:include scripts/contextmenu.js */ +/* DOKUWIKI:include scripts/indexmenu.js */ +/* DOKUWIKI:include scripts/contextmenu.local.js */ + + +/* DOKUWIKI:include scripts/fancytree/jquery.fancytree-all.min.js */ + +// - page id without URL rewriting http://example.doku/doku.php?id=test:start +// - page id without URL rewriting http://example.doku/doku.php?id=test:plugins#interwikipaste +// - page id with .htaccess URL rewriting http://example.doku/test:plugins +// - page id with .htaccess URL rewriting and 'useslash' config http://example.doku/test/plugins +// - page id with internal URL rewriting http://example.doku/doku.php/test:plugins +// - http://example.doku/lib/exe/detail.php?id=test%3Aplugins&media=ns:image.jpg +// - http://example.doku/lib/exe/fetch.php?w=400&tok=097122&media=ns:image.jpg +// - http://example.doku/lib/exe/fetch.php?media=test:file.pdf +// - http://example.doku/_detail/ns:image.jpg?id=test%3Aplugins +// - http://example.doku/_media/test:file.pdf +// - http://example.doku/_detail/ns/image.jpg?id=test%3Aplugins +// - http://example.doku/_media/test/file.pdf + + +jQuery(function(){ // on page load + // Create the tree inside the <div id="tree"> element. + const predefinedPresets = { + 'bootstrap': { //works with template bootstrap3 or by manually adding resources to icon plugin assets + 'preset': 'bootstrap3', + 'map': {} + }, + 'bootstrap-n': { //works with template bootstrap3 or ..etc + 'preset': 'bootstrap3', + 'map': {} + }, + 'awesome': { //works with icons-plugin, settings: enable plugin»icons»loadFontAwesome + 'preset': 'awesome4', //plugin icons does include only awesome4, not awesome5. + 'map': {} + }, + 'material': { // add Material Icons font stylesheet to header with TPL_METAHEADER_OUTPUT in action component + 'preset': 'material', + 'map': {} + }, + 'mdi': { //works with icons-plugin, settings: enable plugin»icons»loadMaterialDesignIcons + 'preset': '', + 'map': { + _addClass: "mdi", + checkbox: "mdi-checkbox-blank-outline", + checkboxSelected: "mdi-check-box-outline", + checkboxUnknown: "mdi-checkbox-intermediate fancytree-helper-indeterminate-cb", + dragHelper: "mdi-play", + dropMarker: "mdi-skip-forward", + error: "mdi-warning", + expanderClosed: "mdi-chevron-right", + expanderLazy: "mdi-chevron-right", + expanderOpen: "mdi-chevron-down", + // We may prevent wobbling rotations on FF by creating a separate sub element: + loading: "mdi-refresh", + nodata: "mdi-information-outline", + noExpander: "", + radio: "mdi-radiobox-blank", // "fa-circle-o" + radioSelected: "mdi-radiobox-marked", + // Default node icons. + // (Use tree.options.icon callback to define custom icons based on node data) + doc: "mdi-file-outline", + docOpen: "mdi-file-outline", + folder: "mdi-folder", + folderOpen: "mdi-folder-open", + } + }, + 'typicons': { //works with icons-plugin, settings: enable plugin»icons»loadTypicons + 'preset': '', + 'map': { + _addClass: "typcn", + checkbox: "typcn-media-stop-outline", + checkboxSelected: "typcn-input-checked", + checkboxUnknown: "typcn-media-stop-outline fancytree-helper-indeterminate-cb", + dragHelper: "typcn-media-play-outline", + dropMarker: "typcn-media-fast-forward-outline", + error: "typcn-warning", + expanderClosed: "typcn-media-play", + expanderLazy: "typcn-media-play", + expanderOpen: "typcn-arrow-sorted-down", + // We may prevent wobbling rotations on FF by creating a separate sub element: + loading: "typcn-arrow-sync", + nodata: "typcn-info-large", + noExpander: "", + radio: "typcn-media-record-outline", // "fa-circle-o" + radioSelected: "typcn-media-record", + // Default node icons. + // (Use tree.options.icon callback to define custom icons based on node data) + doc: "typcn-document", + docOpen: "typcn-document", + folder: "typcn-folder", + folderOpen: "typcn-folder-open", + } + } + + }; + // userDefinedPresets can be defined in conf/userscript.js + const presets = {...predefinedPresets, ...(typeof userDefinedPresets === 'undefined' ? [] : userDefinedPresets)}; + //let targettype; + // function logEvent(event, data, msg){ + // // var args = Array.isArray(args) ? args.join(", ") : + // msg = msg ? ": " + msg : ""; + // jQuery.ui.fancytree.info("Event('" + event.type + "', node=" + data.node + ")" + msg); + // } + jQuery(".indexmenu_js2").each(function(){ + let $tree = jQuery(this), + id = $tree.attr('id'); + const options = $tree.data('options'); + // console.log("options"); + // console.log(options); + let themePreset = presets[options.opts.theme]; + let targettype; //to share type between handlers + let extensions = []; + if(themePreset) { + extensions.push("glyph"); + } + if(options.opts.persist) { + extensions.push("persist"); + } + + $tree.fancytree({ + //enabled extensions + extensions: extensions, + //settings for glyph extension + glyph: { + preset: themePreset ? themePreset.preset : '', + map: themePreset ? themePreset.map : {} + }, + // 0=quite, 1=only errors, upto 4=also debug + //debugLevel: 4, + //settings for persist extension + persist: { + expandLazy: true, + // fireActivate: false, // false: suppress `activate` event after active node was restored + // overrideSource: false, // true: cookie takes precedence over `source` data attributes. + store: "auto" // 'cookie', 'local': use localStore, 'session': sessionStore + // Sample for a custom store: + // store: { + // get: function(key){ this.info("get(" + key + ")"); return window.sessionStorage.getItem(key); }, + // set: function(key, value){ this.info("set(" + key + ", " + value + ")"); window.sessionStorage.setItem(key, value); }, + // remove: function(key){ this.info("remove(" + key + ")"); window.sessionStorage.removeItem(key); } + }, + // number of levels already expanded, and not unexpandable. + //minExpandLevel: 2, + // expand with single click instead of dblclick + clickFolderMode: 3, + // closes other opened nodes, so only one node is opened + //autoCollapse: true, + // for keyboard.. --opening folders becomes jumpy + //autoScroll: true, + // Looping in combination with clicking + autoActivate: false, + // disabled because it causes also autoscrolling, such that select node is out-of-view + activeVisible: false, + + escapeTitles: false, + tooltip: true, + //use same setting as wiki page + rtl: jQuery('html[dir=rtl]').length, + + //for keyboard control + keydown: function (event, data) { + switch (event.which) { + case 32: // [space] + // logEvent(event,data); + break; + case 13: // [enter] + // logEvent(event,data); + if(data.node.data.url){ + // console.log('redirect'); + window.location.href = data.node.data.url; + } + break; + } + }, + + //store in click some event data for the activate handler + click: function(event, data) { + // return false to prevent default behavior (i.e. activation, ...) + targettype = data.targetType; //store target type, only available in click handler + }, + + //go to wiki page if node is activated + activate: function(event, data){ + const node = data.node; + + //prevent looping (hns is false or a page id) + if(node.key === JSINFO.id || node.data.hns === JSINFO.id) { + //node is equal to current page, prevent to follow the url + return; + } + if(options.opts.nopg && node.key === JSINFO.namespace + ':') { + //nopg marks parent ns node active, prevent to follow the url + return; + } + + // expander should not follow link + if(targettype === 'expander') { + targettype = false; //reset + return false; + } + + if(node.data.url === false) { + return false; + } + + if(node.data.url){ + window.location.href = node.data.url; + } + }, + + // active marked node (=current page) + init: function(event, data) { + //activate current node + data.tree.reactivate(); + }, + //add url + enhanceTitle: function(event, data) { + let node = data.node; + + if(node.data.url === false) { + return; + } + if(node.data.url) { // pagename 0 has url /0 + //nopg has potentially not existing pages + let cls = ''; + if(node.data.hnsNotExisting) { + cls = ' class="wikilink2"'; + } + data.$title.html("<a href='" + node.data.url + "'"+cls+">" + node.title + "</a>"); + } + }, + //retrieve initial data + source: { + url: DOKU_BASE + 'lib/exe/ajax.php', + data: { + ns: options.ns, + call: 'indexmenu', + req: 'fancytree', + + level: options.opts.level, //only init + nons: options.opts.nons ? 1 : 0, //only init; without ns, no lower levels possible + nopg: options.opts.nopg ? 1 : 0, + subnss: options.opts.subnss, //subns to open. Only on init array, later just current ns string + navbar: options.opts.navbar ? 1 : 0, //only init: open tree at current page + currentpage: JSINFO.id, + max: options.opts.max, //#n of max#n#m + skipns: options.opts.skipns, + skipfile: options.opts.skipfile, + sort: options.sort.sort ? options.sort.sort : 0, //'t', 'd', false TODO is false handled correctly? + msort: options.sort.msort ? options.sort.msort : 0, //'indexmenu_n', or metadata 'key subkey' TODO is empty handled correctly? + rsort: options.sort.rsort ? 1 : 0, + nsort: options.sort.nsort ? 1 : 0, + hsort: options.sort.hsort ? 1 : 0, + + init: 1 + } + }, + //retrieve data of expanded nodes + lazyLoad: function(event, data) { + const node = data.node; + // Issue an Ajax request to load child nodes + data.result = { + url: DOKU_BASE + 'lib/exe/ajax.php', + data: { + ns: node.key, // ns with trailing : + call: 'indexmenu', + req: 'fancytree', + + level: 1, //level opened nodes, for follow up ajax requests only next level, so:1 + nons: options.opts.nons ? 1 : 0, + nopg: options.opts.nopg ? 1 : 0, + subnss: '', //options.opts.subnss is used on init + currentpage: JSINFO.id, + max: options.opts.maxajax, //#m of max#n#m + skipns: options.opts.skipns, + skipfile: options.opts.skipfile, + sort: options.sort.sort ? options.sort.sort : 0, + msort: options.sort.msort ? options.sort.msort : 0, + rsort: options.sort.rsort ? 1 : 0, + nsort: options.sort.nsort ? 1 : 0, + hsort: options.sort.hsort ? 1 : 0, + + init: 0 + } + } + } + }); + + //hide the fallback nojs indexmenu + jQuery('#nojs_' + id.substring(6)).css("display", "none"); + + + // Note: Loading and initialization may be asynchronous, so the nodes may not be accessible yet. + + // On page load, activate node if node.data.href matches the url#href +// let tree = jQuery.ui.fancytree.getTree("#" + id), +// path = window.parent && window.parent.location.pathname; +// // console.log(path); +// // console.log('test'); +// if(path) { +// let arr = path.split('/'); // not reliable with config:useslash? +// let last = arr[arr.length-1] || arr[arr.length-2]; +// // console.log(arr); +// // console.log(last); +// +// // tree.activateKey(last); +// // var node1=tree.getNodeByKey(last); +// // console.log(node1); +// // node1.setActive(); +// // also possible: +// // $.ui.fancytree.getTree("#tree").getNodeByKey("id4.3.2").setActive(); +// +// // tree.visit(function(n) { +// // console.log(n.key); +// // console.log(n); +// // if( n.key && n.key === last ) { +// // n.setActive(); //if not using iframes, this creates a loops in combination with activate above +// // return false; // done: break traversal +// // } +// // }); +// } +// console.log(tree); +// console.log("test"); +// jQuery.contextMenu({ +// selector: "span.fancytree-title", +// items: { +// // "cut": {name: "Cut", icon: "cut", +// // callback: function(key, opt){ +// // var node = jQuery.ui.fancytree.getNode(opt.$trigger); +// // alert("Clicked on " + key + " on " + node); +// // } +// // }, +// "page": {name: "Page", icon: "", disabled: true }, +// "sep1": "----", +// "revs": {name: "Revisions", icon: "ui-icon-arrowreturn-1-w", disabled: false }, +// "toc": {name: "ToC preview", icon: "ui-icon-bookmark", disabled: false }, +// "edit": {name: "Edit", icon: "edit", disabled: false }, +// "hpage": {name: "Headpage", icon: "add", disabled: false}, +// "spage": {name: "Start page", icon: "add", disabled: false}, +// "cpage": {name: "Custom page...", icon: "add", disabled: false}, +// "acls": {name: "Acls", icon: "ui-icon-locked", disabled: false}, +// "purge": {name: "Purge cache", icon: "loading", disabled: false}, +// "html": {name: "Export as HTML", icon: "ui-icon-document", disabled: false}, +// "text": {name: "Export as text", icon: "ui-icon-note", disabled: false}, +// "sep2": "----", +// "ns": {name: "Namespace", icon: "", disabled: true}, +// "sep3": "----", +// "search": {name: "Search...", icon: "ui-icon-search", disabled: false}, +// "npage": {name: "New page...", icon: "add", disabled: false}, +// "nshpage": {name: "Headpage here", icon: "add", disabled: false}, +// "nsacls": {name: "Acls", icon: "ui-icon-locked", disabled: false} +// }, +// callback: function(itemKey, opt) { +// var node = jQuery.ui.fancytree.getNode(opt.$trigger); +// alert("select " + itemKey + " on " + node); +// } +// }); + + // $tree.contextmenu({ + // delegate: "span.fancytree-title", + // autoFocus: true, + // // menu: "#options", + // menu: [ + // {title: "Page", cmd: 'pg'}, + // {title: "----", cmd: 'pg'}, + // {title: "Revisions", cmd: "revs", uiIcon: "ui-icon-arrowreturn-1-w"}, + // {title: "ToC preview", cmd: "toc", uiIcon: "ui-icon-bookmark"}, + // {title: "Edit", cmd: "edit", uiIcon: "ui-icon-pencil", disabled: false }, + // {title: "Headpage", cmd: "hpage", uiIcon: "ui-icon-plus"}, + // {title: "Start page", cmd: "spage", uiIcon: "ui-icon-plus"}, + // {title: "Custom page...", cmd: "cpage", uiIcon: "ui-icon-plus"}, + // {title: "Acls", cmd: "acls", uiIcon: "ui-icon-locked", disabled: true }, + // {title: "Purge cache", cmd: "purge", uiIcon: "ui-icon-arrowrefresh-1-e"}, + // {title: "Export as HTML", cmd: "html", uiIcon: "ui-icon-document"}, + // {title: "Export as text", cmd: "text", uiIcon: "ui-icon-note"}, + // {title: "Namespace", cmd:'ns'}, + // {title: "----", cmd:'ns'}, + // {title: "Search...", cmd: "search", uiIcon: "ui-icon-search"}, + // {title: "New page...", cmd: "npage", uiIcon: "ui-icon-plus"},// children:[] + // {title: "Headpage here", cmd: "nshpage", uiIcon: "ui-icon-plus"}, + // {title: "Acls", cmd: "nsacls", uiIcon: "ui-icon-locked"} + // ], + // beforeOpen: function(event, ui) { + // var node = jQuery.ui.fancytree.getNode(ui.target); + // // Modify menu entries depending on node status + // $tree.contextmenu("enableEntry", "toc", node.isFolder()); + // // Show/hide single entries + // $tree.contextmenu("showEntry", "pg", !node.isFolder()); + // $tree.contextmenu("showEntry", "revs", !node.isFolder()); + // $tree.contextmenu("showEntry", "toc", !node.isFolder()); + // $tree.contextmenu("showEntry", "edit", !node.isFolder()); + // $tree.contextmenu("showEntry", "hpage", !node.isFolder()); + // $tree.contextmenu("showEntry", "spage", !node.isFolder()); + // $tree.contextmenu("showEntry", "cpage", !node.isFolder()); + // $tree.contextmenu("showEntry", "acls", !node.isFolder()); + // $tree.contextmenu("showEntry", "purge", !node.isFolder()); + // $tree.contextmenu("showEntry", "html", !node.isFolder()); + // $tree.contextmenu("showEntry", "text", !node.isFolder()); + // + // $tree.contextmenu("showEntry", "ns", node.isFolder()); + // $tree.contextmenu("showEntry", "search", node.isFolder()); + // $tree.contextmenu("showEntry", "npage", node.isFolder()); + // $tree.contextmenu("showEntry", "nshpage", node.isFolder()); + // $tree.contextmenu("showEntry", "nsacls", node.isFolder()); + // + // // Activate node on right-click + // node.setActive(); + // // Disable tree keyboard handling + // ui.menu.prevKeyboard = node.tree.options.keyboard; + // node.tree.options.keyboard = false; + // }, + // close: function(event, ui) { + // // Restore tree keyboard handling + // // console.log("close", event, ui, this) + // // Note: ui is passed since v1.15.0 + // var node = jQuery.ui.fancytree.getNode(ui.target); + // node.tree.options.keyboard = ui.menu.prevKeyboard; + // node.setFocus(); + // }, + // select: function(event, ui) { + // var node = jQuery.ui.fancytree.getNode(ui.target); + // alert("select " + ui.cmd + " on " + node); + // } + // }); + }); +}); + + +/** + * Add button action for the indexmenu wizard button + * + * @param {jQuery} $btn Button element to add the action to + * @param {Array} props Associative array of button properties + * @param {string} edid ID of the editor textarea + * @return {boolean} If button should be appended + */ +function addBtnActionIndexmenu($btn, props, edid) { + indexmenu_wiz.init(jQuery('#' + edid)); + $btn.on('click', function () { + indexmenu_wiz.toggle(); + return false; + }); + return true; +} + + +// try to add button to toolbar +if (window.toolbar !== undefined) { + window.toolbar[window.toolbar.length] = { + "type": "Indexmenu", + "title": "Insert the Indexmenu tree", + "icon": "../../plugins/indexmenu/images/indexmenu_toolbar.png" + } +} + + +/** + * functions for js index renderer and contextmenu + */ +var IndexmenuUtils = { + + /** + * Determine extension from given theme dir name + * + * @param {string} themedir name of theme dir + * @returns {string} extension gif, png or jpg + */ + determineExtension: function (themedir) { + let extension = "gif"; + let posext = themedir.lastIndexOf("."); + if (posext > -1) { + posext++; + let ext = themedir.substring(posext, themedir.length).toLowerCase(); + if ((ext === "png") || (ext === "jpg")) { + extension = ext; + } + } + return extension; + }, + + /** + * Create div with given id and class on body and return it + * + * @param {string} id picker id + * @param {string} cl class(es) + * @return {jQuery} jQuery div + */ + createPicker: function (id, cl) { + return jQuery('<div>') + .addClass(cl || 'picker') + .attr('id', id) + .css({position: 'absolute'}) + .hide() + .appendTo('body'); + } + +}; |