comparison plugins/contextmenu/MANUAL.md @ 0:1e000243b222

vanilla 1.3.3 distro, I hope
author Charlie Root
date Thu, 04 Jan 2018 15:50:29 -0500
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e000243b222
1 # Contextmenu manual
2
3 This file provides information for plugin and skin developers. The Contextmenu plugin can be extended by other plugins; new menus can be created and existing menus manipulated. For basic installation information please see the [README](./README.md).
4
5 - [Creating a new Contextmenu](#creating-a-new-contextmenu)
6 - [Working with an existing Contextmenu](#working-with-an-existing-contextmenu)
7 - [Events](#events)
8 - [Contextmenu and skins](#contextmenu-and-skins)
9
10 ## Creating a new Contextmenu
11
12 By default Contextmenu is added to the `mail` and `addressbook` tasks in Roundcube. It can be added to other tasks by calling the PHP function `include_plugin()` like this `$this->include_plugin('contextmenu');` from inside your plugin. This function checks if the Contextmenu plugin is available and loads it if possible.
13
14 The JavaScript function `rcm_callbackmenu_init()` creates the Contextmenu object. If the Contextmenu functions are enabled in the UI then the `rcmail.env.contextmenu` variable JavaScript will be set to true. Setting this variable to false will disable all context menus.
15
16 ```js
17 var menu = rcm_callbackmenu_init(props, events);
18 ```
19
20 The functions takes 2 parameters:
21
22 `props` (required) JSON object:
23 * menu_name - (string) required - A friendly name for the Contextmenu, it is also used as the ID for the Contextmenu element.
24 * menu_source - (string or array) required - See [Menu sources](#menu-sources) for details.
25 * list_object - (object) optional - If Contextmenu is used on a Roundcube list object then that list object should be set here (e.g. `rcmail.message_list`), set to `null` if using Contextmenu on another element. It is set to `rcmail.message_list` by default.
26 * source_class - (string) optional - The CSS class applied to the triggering element, `contextRow` by default.
27 * mouseover_timeout - (int) optional - The delay for displaying submenus on mouseover, set to -1 to disable mouseover. `400` by default.
28
29 `events` (optional) JSON object. Contextmenu triggers a number of events during execution, for example `command` is tiggered when the user clicks on an item in the menu. Full details of all the events can be found in the [Events](#events) section of this file. This parameters allows a plugin author to attach their own functions to the Contextmenu events, overriding the defaults.
30
31 Creating a simple Contextmenu looks like this:
32 ```js
33 var menu = rcm_callbackmenu_init(
34 {'menu_name': 'messagelist', 'menu_source': '#messagetoolbar'},
35 {'beforeactivate': function(p) {
36 rcmail.env.contextmenu_selection = p.ref.list_selection(true);
37 },
38 'afteractivate': function(p) {
39 p.ref.list_selection(false, rcmail.env.contextmenu_selection);
40 }});
41 ```
42
43 The Contextmenu must then be attached to the element(s) in the UI. For example:
44 ```js
45 $(el).on("contextmenu", function(e) {
46 rcm_show_menu(e, obj, source_id, menu);
47 });
48 ```
49
50 The `rcm_show_menu` displays a Contextmenu on the screen. It has the following parameters:
51 * e - (event) The JS event object
52 * obj - (object) The object the Contextmenu is active on (typically `this`)
53 * source_id - (string) The object ID used by core function. When using the Contextmenu on a Roundcube list object then the ID can be retrieved from the object, like this:
54 ```js
55 if (uid = list_object.get_row_uid(this)) {
56 rcm_show_menu(e, this, uid, menu);
57 }
58 ```
59 The ID can also be extracted from the originial function call, like this:
60 ```js
61 if (source.attr('onclick') && source.attr('onclick').match(rcmail.context_menu_command_pattern)) {
62 rcm_show_menu(e, this, RegExp.$2, menu);
63 }
64 ```
65 * menu - (object) The menu object as created by `rcm_callbackmenu_init`
66
67 ## Menu sources
68
69 The menu_source parameter can be a string (for building the Contextmenu from a single source) or an array of jQuery selectors. To add custom elements to the Contextmenu a menu element must first be added to the IU, for example:
70 ```php
71 $li = '';
72 $li .= html::tag('li', null, $this->api->output->button(array('command' => 'plugin.myplugin.command1', 'type' => 'link', 'class' => 'myclass1', 'label' => 'myplugin.command1')));
73 $li .= html::tag('li', null, $this->api->output->button(array('command' => 'plugin.myplugin.command2', 'type' => 'link', 'class' => 'myclass2', 'label' => 'myplugin.command2')));
74 $li .= html::tag('li', null, $this->api->output->button(array('command' => 'plugin.myplugin.command3', 'type' => 'link', 'class' => 'myclass3', 'label' => 'myplugin.command3')));
75 $out = html::tag('ul', array('id' => 'mymenu'), $li);
76 $this->api->output->add_footer(html::div(array('style' => 'display: none;'), $out));
77 ```
78 The Contextmenu can then be invoked like this:
79 ```js
80 var menu = rcm_callbackmenu_init({menu_name: 'mymenu', menu_source: '#mymenu'});
81 ```
82 A JSON object can also be used instead of an element selector to add simple elements to the Contextmenu. For example:
83 ```js
84 var menu = rcm_callbackmenu_init({menu_name: 'mymenu', menu_source: ['#mymenu', {lable: 'extra item', command: 'plugin.myplugin.command', props: '', class: 'myclass'}]});
85 ```
86 The JSON object can have:
87 * `label` (string) required - text for the menu element
88 * `command` (string) required - the Roundcube command to execute on click
89 * `props` (string) optional - arguments to pass to the Roundcube command
90 * `classes` (string) optional - classes to apply to the menu element
91
92 ## Working with an existing Contextmenu
93
94 A global event `contextmenu_init` is triggered when a new Contextmenu is initialised so other plugins can interact with it.
95 ```js
96 rcmail.addEventListener('contextmenu_init', function(menu) {
97 // identify the folder list context menu
98 if (menu.menu_name == 'folderlist') {
99 // add a shortcut to the folder management screen to the end of the menu
100 menu.menu_source.push({label: 'Manage folders', command: 'folders', props: '', classes: 'managefolders'});
101
102 // make sure this new shortcut is always active
103 menu.addEventListener('activate', function(p) {
104 if (p.command == 'folders') {
105 return true;
106 }
107 });
108 }
109 });
110 ```
111
112 The Contextmnu object is passed to the function allowing properities to be manipulated and/or new events to be attached. By default the following menus are created:
113
114 On the mail screen:
115 * messagelist - attached to rows in the message list
116 * folderlist - attached to entries in the folder list
117
118 On the message composing screen:
119 * composeto - attached to contacts in the contacts search widget
120
121 On the address book screen:
122 * contactlist - attached to rows in the contacts list
123 * abooklist - attached to addressbooks and groups
124
125 To prevent an element from appearing in a Contextmenu give it the class `rcm_ignore`.
126
127 To make sure an element in the Contextmenu is always active give it the class `rcm_active`.
128
129 The environmental variable `rcmail.env.context_menu_source_id` contains the ID of the specific element that the Contextmenu was triggered on, this is the `source_id` passed to `rcm_show_menu`
130
131 ## Events
132
133 The following events are triggered by Contextmenu:
134
135 `init` - Triggered once the Contextmenu object has been initalized
136 * ref - The Contextmenu object
137
138 `beforecommand` - Triggered when an element in the menu is clicked
139 * ref - The Contextmenu object
140 * el - The HTML object being clicked
141 * command - The Roundcube command to run
142 * args - The arguments being passed to the Roundcube command
143 This function can return the following in a JSON object:
144 * abort - Boolean, abort the default command execution, other events like `command` and `aftercommand` will not be executed
145 * result - Result of the command, if abort if true this is returned to the client
146
147 `command` - Triggered when an element in the menu is clicked
148 * ref - The Contextmenu object
149 * el - The HTML object being clicked
150 * command - The Roundcube command to run
151 * args - The arguments being passed to the Roundcube command
152 * evt - The JS event object
153 This function can return the result of the command to pass back to the client
154
155 By default the following function is used:
156
157 ```js
158 function(p) {
159 if (!$(p.el).hasClass('active'))
160 return false;
161
162 if (p.ref.list_object) {
163 var prev_display_next = rcmail.env.display_next;
164
165 if (!(p.ref.list_object.selection.length == 1 && p.ref.list_object.in_selection(rcmail.env.context_menu_source_id)))
166 rcmail.env.display_next = false;
167
168 var prev_sel = p.ref.list_selection(true);
169 }
170
171 // enable the required command
172 var prev_command = rcmail.commands[p.command];
173 rcmail.enable_command(p.command, true);
174 var result = rcmail.command(p.command, p.args, p.el, p.evt);
175 rcmail.enable_command(p.command, prev_command);
176
177 if (p.ref.list_object) {
178 p.ref.list_selection(false, prev_sel);
179 rcmail.env.display_next = prev_display_next;
180 }
181
182 if ($.inArray(p.command, rcmail.context_menu_overload_commands) >= 0) {
183 rcmail.context_menu_commands[p.command] = rcmail.commands[p.command];
184 rcmail.enable_command(p.command, true);
185 }
186
187 return result;
188 }
189 ```
190
191 The Contextmenu works by faking a message selection and calling the normal Roundcube command before putting everything back to normal.
192
193 `aftercommand` - Triggered when an element in the menu is clicked
194 * ref - The Contextmenu object
195 * el - The HTML object being clicked
196 * command - The Roundcube command to run
197 * args - The arguments being passed to the Roundcube command
198
199 `beforeactivate` - Triggered when a Contextmenu is displayed
200 * ref - The Contextmenu object
201 * source - The element the Contextmenu has been triggered on
202 This function can return the following in a JSON object:
203 * abort - Boolean, abort the default activation process, other events like `activate` and `afteractivat` will not be executed
204 * show - Boolean, show the menu or not
205
206 `activate` - Triggered when a Contextmenu is displayed, a separate event is triggered for each menu item
207 * el - The menu element being activated
208 * btn - The ID of the button in the UI on which the menu element is based
209 * source - The element the Contextmenu has been triggered on
210 * command - The command the menu element executes
211 * enabled - Boolean, if the menu element is active or not
212 This function can return a boolean value: true to activate the element, false to disable it
213
214 `afteractivate` - Triggered when a Contextmenu is displayed
215 * ref - The Contextmenu object
216 * source - The element the Contextmenu has been triggered on
217
218 `insertitem` - Triggered each time an item is added to a Contextmenu
219 * item - The HTML object to be added to the menu
220
221 For example permanently deactivating the delete option on the message list Contextmenu could be done like this:
222 ```js
223 rcmail.addEventListener('contextmenu_init', function(menu) {
224 if (menu.menu_name == 'messagelist') {
225 menu.addEventListener('activate', function(p) {
226 var is_delete = false;
227
228 $.each(rcmail.buttons['delete'], function() {
229 if (this.id == p.btn) {
230 is_delete = true;
231 return false;
232 }
233 });
234
235 return is_delete ? false : null;
236 });
237 }
238 });
239 ```
240
241 ## Contextmenu and skins
242
243 In the plugin folder there is a skins folder, and inside that there is a folder for each skin. Two files are needed for each skin: contextmenu.css - CSS for the menu, and functions.js containing the JavaScript to create Contextmenus in the skin. This plugin provides some helper functions for adding the default menus to the UI, they are: `rcm_listmenu_init()` for attaching a Contextmenu to a Roundcube list object, `rcm_foldermenu_init()` for attaching a Contextmenu to the folder list on the mail screen, and `rcm_abookmenu_init()` for attaching a Contextmenu to the address book and groups list on the address book screen. Each function expects the same 3 parameters:
244 * The HTML object or jQuery selector of the element to attach to.
245 * A props object, see [Creating a new Contextmenu](#creating-a-new-contextmenu)
246 * An events object, see [Events](#events)
247
248 Contextmenus must be defined separately for each skin because they are built from the toolbar elements in the UI which may have different IDs as well as different construction on each skin.