DokuWiki

It's better when it's simple

User Tools

Site Tools


plugin:explorertree

explorertree Plugin

Compatible with DokuWiki

  • 2017-02-19 "Frusterick Manners" unknown
  • 2016-06-26 "Elenor Of Tsort" unknown
  • 2015-08-10 "Detritus" unknown
  • 2014-09-29 "Hrun" yes

plugin DokuWiki helper for embedding NS/page explorer to a plugin

Last updated on
2015-07-29
Provides
Helper
Repository
Source
Requires
(memcache)

Similar to acl

Tagged with ajax, embed, explorer, tree

Installation

Install the plugin using the Plugin Manager and the download URL above, which points to latest version of the plugin. Refer to Plugins on how to install plugins manually.

If memcache plugin is installed, automatically caches the tree structure for quicker responses (useful on large trees or slow disk IO)

Overview

This plugin is for plugin authors, to simply embed almost the same explorertree as the ACL plugin uses. The only addition is that this is ajax based.

Use the the page_selected_cb and ns_selected_cb callbacks inside your plugin to send data back to client by ajax.

Usage

There are multiple ways to use the tree:

  • use the php callbacks, which are called inside an ajax request
  • use the javascript callbacks, which called on client side
  • listen on events emmitted by the tree

Ajax queries are made in new requests, hence the plugin's object that embeds the explorertree not exists in the ajax request context. To solve this, you need to create a function that sets all callbacks, and register this route:

class admin_plugin_yourplugin extends DokuWiki_Admin_Plugin {
 
	private $explorer_helper = null;
	private $explorer_registered = false;
 
	function get_explorer(){
		if (!$this->explorer_helper){
			$this->explorer_helper = plugin_load('helper','explorertree');
		}
		return $this->explorer_helper;
	}
	function init_explorertree(){
		if (!($e = $this->get_explorer())) return;
		if (!$this->explorer_registered){
			$e->registerRoute('yourroutingname',array(
				'init_plugin' => array(	// this is the method to register routing, hence this method itself is the 'init_plugin' option.
					'plugin' => 'yourplugin',
					'type' => 'admin',
					'method' => 'init_explorertree',
				),
				'vars' => array(
					'class' => 'explorertree', // override css class
					'id' => 'mytreeid', // override id for the tree
				),
				'callbacks' => array(	// callbacks in your plugin, or any callback
					// php callbacks, which are called via ajax
					'page_selected_cb' => array($this,'pageselected'),
					'ns_selected_cb' => function($id){ /* any closure or callable*/ return array(); },
					// javascript callbacks, which are called on client side (name must be a string, your client side defined function name):
					'page_selected_js' => 'my_ns_callback',
					'ns_selected_js' => 'my_page_callback',
				),
			));
			$this->explorer_registered = true;
		}
		return $e;
	}
/* rest of your plugin... */
}

After this, you can display the explorertree simply:

 /* in admin_plugin_yourplugin:  */
function html(){
        echo '<h1>'.$this->getLang('admin_title').'</h1>'.NL; // your code to create html
 
        // init and display the explorertree
        if (!($e = $this->init_explorertree())){
                echo "Something wrong...";
        }
        echo $e->htmlExplorer('yourroutingname',':'); //display the explorer from root (':')
 
        // some more html your admin uses...
        echo "<div id='edit_nsorpage_container'></div>";
}

Use of php callbacks

You can define javascript function, that are called if the page_selected_cb or ns_selected_cb is set in options.

In case a namespace or page is selected you can reply by your callbacks, because your plugin will automatically loaded.

Your reply will be embedded in json, needs to be an array. You can call your javascript functions as well:

 /* in admin_plugin_yourplugin:  */
function nsselected($id){
	/* do something here, $id is absolute path */
	return array(
		'msg'=>"Yaay! Namespace '{$id}' is selected!"
	);
}
function pageselected($id){
	$server_side_prepared_part = $this->my_plugins_purpose(); // or whatever
	return array(
		'args'=> array(  '' these will be the arguments of your javascript function
			$id,
			$server_side_prepared_part,
		),
		'func'=> "javascript_function_name" // defined in script.js in your plugin or wherever
	);
}

Use of javascript callbacks

You can define javascript function, that are called if the page_selected_js or ns_selected_js is set in options.

The called function will have the arguments:

  1. id: (string) the absolute id of the selected item
  2. elem: (jquery dom object) the html dom what is selected
  3. tree: (jquery dom object) the root html dom of the tree
function my_ns_callback(id,jq_elem,jq_tree){
  /* ... do something ... */
  console.log('a namespace with id:"'+id+'" is selected in tree:'+jq_tree.attr('id'));
}

Use of dom events

You don't need to set up anything in the options to use the events.

All events have extra parameters:

  1. id: (string) the absolute id of the selected item
  2. elem: (jquery dom object) the html dom what is selected
  3. tree: (jquery dom object) the root html dom of the tree

Events:

  • tree_folder_open: emitted when a tree folder is clicked and going to open.
  • tree_folder_open_ready: emitted when a tree folder is opened (after the folders contents are loaded with ajax if necessary)
  • tree_folder_closed: emitted when a tree folder is closed.
  • tree_selected: emitted when an item (namespace or page) in the tree is selected.
  • tree_selected_ns: emitted when a namespace in the tree is selected.
  • tree_selected_page: emitted when a page in the tree is selected.
// you you want to listen to one tree, you can use the options to set your desired id.
jQuery('#mytreeid').on('tree_folder_open',function(event,id,jq_elem,jq_tree){
	console.log('folder with branch is going to be opened:',id);
});
 
// if you want to listen on all trees in the page.
jQuery(document).on('tree_folder_open_ready',function(event,id,jq_elem,jq_tree){
	console.log('folder with branch is going to be opened:',id);
});

Customization, usage tipps

Ajax

You don't have to do anything with Ajax. With javascript function wrapping (see callback examples) you can call you client side javascript function with server side prepared arguments… how could it be simpler?

Admin, syntax, helper plugins

You can include the tree in admin to enhance your plugin's usability. You can also include it to interactive sidebars-TOCs or TOC-syntax plugins. You can include it in your plugin's helper, to extend the usage transparently.

NOTE: if you use syntax plugins, you should prepare to different renderers… Ajax won't work in pdf…

Style

Just copy this plugin's styles.css in your plugin, and change the css classnames in your css and the $options['var']['class'].

Voila, you can use your own custom style, even multiple styles per page.

Multiple tree / page or plugin

To use multiple trees in a page: simply use different routingname per tree (see registerRoute). One init function can register multiple routing name/object.

To use multiple trees in you plugin - if your plugin have more plugin classes of the same type: your plugin should look like this (assuming it's admin plugin).

.                    <-- your plugin's directory
/admin               <-- directory in your plugin
/admin/onepage.php   <-- the 'admin_plugin_yourplugin_onepage' class.
/admin/otherpage.php   <-- the 'admin_plugin_yourplugin_otherpage' class.

use registerrute with init_plugin:

// in your 'admin_plugin_yourplugin_onepage' class, assuming 
// the init_explorertree function is the same, as first example:
 
	/* ... function init_explorertree() ... */
// routing name needs to be unique per tree!
	$e->registerRoute('yourroutingnamepageone',array(
		'init_plugin' => array(	
// your 'plugin' needs to include the tpye and sub-class of the plugin: 'admin_plugin_[yourplugin_onepage]' classname...
			'plugin' => 'yourplugin_onepage',
			'type' => 'admin',
			'method' => 'init_explorertree',
		),
		/* other settings ...*/
	));
	/* ... rest of the function ...*/	

Methods

$explorertree->registerRoute($name,array $options);

Registers a route: the tree will be created by the options and ajax will be routed to the caller class.
$name: string, unique name, usually the registerer plugin's name (with suffix, if the plugin uses more trees)
$options: array of options, that replace the original options (see Configuration and Settings)
returns: void

$explorertree->getOptions($name = null);

Returns a registered route options or the default options.
$name: string, unique name for the registered options. If null, the default options are returned.
return: array of options or null if $name is set, but does not exists.

$explorertree->getTree($folder = ':');

Gets the level of NS and pages tree, which is usable in html_buildlist.
$folder: string, the starting directory.
return: array

$explorertree->htmlExplorer($name = null,$base = ':');

Gets html explorer of the wiki from base.
$name: string, unique name for the registered options.
$base: string, ID of the root node.
return: string, the html code, including the script tag that initializes the javascript tree handler.

Configuration and Settings

The options array:

$options = array(
	'callbacks' =>array(	// your callable for these events
		'page_selected_cb' => null, // php callback
		'ns_selected_cb' => null,   // php callback
//WARNING!: javascript callback names should never be invalid javascript function names or callbacks!
		'page_selected_js' => null, // javascript callback
		'ns_selected_js' => null,   // javascript callback
	),
	'vars'=>array(		// options for the explorertree's html
		'id'=> null,			// ID (html id) of the tree, if null it is generated.
//NOTE: if you don't set id, the generated id will be: "explorertree_" + yourroutingname
		'class' => 'explorertree',	// css class of the tree (to create your own css styles)
//NOTE: class currently not fully implemented, will be in an update in a few days.
	),
	'init_plugin' => array(
		'plugin'=> 'yourplaginname',	// the plugin name 
		'type' => 'yourplugintype',	// the plugin type
		'method' => 'yourloadermethod',	// the method that sets the options, or null if the plugin __construct does that.
	),
);

Development

In development, some simple features and config are planned. Current release is just to fulfill dependencies for 'published' plugin, but the code will be cleaned out, credits and licence to be placed etc as soon as I have time.

The goal is to create small helper plugins, so code-reuse is possible even in different plugins or authors, and to minimize code in pull requests for other author's plugins.

Current plans:

  • add 'default open' setting to set a page that is opened on initial page load.
  • wrap this inside settingstree helper plugin (soon…) to simply create an admin page that's purpose is to configure a (default) setting array – structure defined by your plugin – by namespace/page, similar how current ACL works.
  • ?: add 'ns only' option (don't show pages)

Change Log

  • 2015-07-06
    • Initial release
  • 2015-07-08
    • fixed: typo in function name and function description.
    • fixes: css class name for tree.
    • feature: events for tree
    • feature: js callback for tree
  • 2015-07-13
    • update: distinguish between select and fold
      • on singleclick: select
      • on dblclick: fold or unfold (and don't select)
  • 2015-07-20
    • formalities
  • 2015-07-27
    • fix: jQuery's .trigger() can not trigger two different events at once, exploded to two distinct triggers.
  • 2015-07-27
    • added $current parameter to htmlExplorerto set defaultly selected item.

Known Bugs and Issues

see Development.

List your issues here, or mail me.

Discussion

plugin/explorertree.txt · Last modified: 2016-01-13 14:47 by Aleksandr