| 1 |
$Id: API.txt,v 1.57 2009/07/25 10:27:59 wimleers Exp $
|
| 2 |
|
| 3 |
Terminology
|
| 4 |
-----------
|
| 5 |
- item: an item in the hierarchy. A hierarchy can also be seen as a tree. In
|
| 6 |
that case, an item can be either a parent or a child. However, if
|
| 7 |
"multiple parents" are supported (i.e. a child can have multiple
|
| 8 |
parents), then it's actually not a tree but a directed acyclic graph
|
| 9 |
(see http://en.wikipedia.org/wiki/Directed_acyclic_graph), in which
|
| 10 |
each case technically is a "node".
|
| 11 |
An example: in the case of taxonomy, this is the term id (tid).
|
| 12 |
- label: the label associated with an item in the hierarchy. You may now it
|
| 13 |
as "title" or something else similar.
|
| 14 |
An example: in the case of taxonomy, this is the actual term.
|
| 15 |
- item type: a per-level, human-readable name that describes what kind of
|
| 16 |
items that level contains.
|
| 17 |
- entity: an item is often associated with an entity. E.g. a term is usually
|
| 18 |
associated with a node.
|
| 19 |
- form element: a form element allows the developer to assign a new value to
|
| 20 |
a #type property in a form item. Examples of form elements
|
| 21 |
supported by Drupal core are: select, checkboxes, textfield.
|
| 22 |
- form item: an instance of a form element, with various other properties
|
| 23 |
defined, such as #title, #default_value and #description. These
|
| 24 |
are used to define a form in Drupal.
|
| 25 |
- Hierarchical Select: this is the name of the module.
|
| 26 |
- hierarchical_select: this is the internal name of the Hierarchical Select
|
| 27 |
form element.
|
| 28 |
- hierarchical select: (note the difference in case) this is the part of the
|
| 29 |
widget with the multiple selects.
|
| 30 |
- dropbox: this is the part of the widget where the selections are stored when
|
| 31 |
multiple selections are allowed.
|
| 32 |
|
| 33 |
|
| 34 |
Form API usage
|
| 35 |
--------------
|
| 36 |
You have to make sure your form item is using the "hierarchical_select" form
|
| 37 |
element type:
|
| 38 |
|
| 39 |
$form['select_some_term'] = array(
|
| 40 |
'#type' => 'hierarchical_select',
|
| 41 |
'#title' => t('Select the tag you wish to use.'),
|
| 42 |
'#size' => 1,
|
| 43 |
'#config' => array(
|
| 44 |
'module' => 'hs_taxonomy',
|
| 45 |
'params' => array(
|
| 46 |
'vid' => $vid,
|
| 47 |
),
|
| 48 |
'save_lineage' => 0,
|
| 49 |
'enforce_deepest' => 0,
|
| 50 |
'entity_count' => 0,
|
| 51 |
'require_entity' => 0,
|
| 52 |
'resizable' => 1,
|
| 53 |
'level_labels' => array(
|
| 54 |
'status' => 0,
|
| 55 |
'labels' => array(
|
| 56 |
0 => t('Main category'),
|
| 57 |
1 => t('Subcategory'),
|
| 58 |
2 => t('Third level category'),
|
| 59 |
),
|
| 60 |
),
|
| 61 |
'dropbox' => array(
|
| 62 |
'status' => 0,
|
| 63 |
'title' => t('All selections'),
|
| 64 |
'limit' => 0,
|
| 65 |
'reset_hs' => 1,
|
| 66 |
),
|
| 67 |
'editability' => array(
|
| 68 |
'status' => 0,
|
| 69 |
'item_types' => array(),
|
| 70 |
'allowed_levels' => array(
|
| 71 |
0 => 0,
|
| 72 |
1 => 0,
|
| 73 |
2 => 1,
|
| 74 |
),
|
| 75 |
'allow_new_levels' => 0,
|
| 76 |
'max_levels' => 3,
|
| 77 |
),
|
| 78 |
// These settings cannot be configured through the UI: they can only be
|
| 79 |
// overridden through code.
|
| 80 |
'animation_delay' => 400,
|
| 81 |
'special_items' => array(),
|
| 82 |
'render_flat_select' => 0,
|
| 83 |
'path' => 'hierarchical_select_json',
|
| 84 |
),
|
| 85 |
'#default_value' => '83',
|
| 86 |
);
|
| 87 |
|
| 88 |
Now, let's explain what we see here:
|
| 89 |
1) We've set the #type property to "hierarchical_select" instead of "select".
|
| 90 |
2) The #size property is inherited by the selects of the hierarchical select.
|
| 91 |
3) There's a new property: #config. This must be an
|
| 92 |
array. These are the items it can contain:
|
| 93 |
- module (required)
|
| 94 |
This will be passed through in the AJAX requests, to let Hierarchical
|
| 95 |
Select know which module's hooks should be used.
|
| 96 |
|
| 97 |
- params (optional, may be necessary for some implementations)
|
| 98 |
An array of parameters that will also be passed through in every AJAX
|
| 99 |
request.
|
| 100 |
e.g. In the case of taxonomy, this is the vocabulary id (vid). In case of
|
| 101 |
content_taxonomy, there's three parameters: vid, tid and depth (tid allows
|
| 102 |
one to define a new root, depth allows one to limit the depth of the
|
| 103 |
displayed hierarchy).
|
| 104 |
|
| 105 |
- save_lineage (optional, defaults to 0)
|
| 106 |
Triggers the lineage saving functionality. If enabled, the selection can
|
| 107 |
consist of multiple values.
|
| 108 |
|
| 109 |
- enforce_deepest (optional, defaults to 0)
|
| 110 |
Triggers the enforcing of a selection in the deepest level. If enabled, the
|
| 111 |
selection will always be a single value.
|
| 112 |
|
| 113 |
- entity_count (optional, defaults to 0)
|
| 114 |
Enables the display of entity counts, between parentheses, for each item in
|
| 115 |
the hierarchy.
|
| 116 |
|
| 117 |
- require_entity (optional, defaults to 0)
|
| 118 |
Whether an item should only be displayed if it has at least one associated
|
| 119 |
entity.
|
| 120 |
|
| 121 |
- resizable (optional, defaults to 1)
|
| 122 |
Makes the hierarchical select resizable.
|
| 123 |
|
| 124 |
- level_labels['status'] (optional, defaults to 0)
|
| 125 |
Whether level labels should be enabled or not. When save_lineage is
|
| 126 |
enabled, this will result in *empty* level labels.
|
| 127 |
|
| 128 |
- level_labels['labels] (optional)
|
| 129 |
An array of labels, one per level. The label for the first level should be
|
| 130 |
the value of key 0.
|
| 131 |
When enforce_deepest is set to:
|
| 132 |
- 0, then you can provide n level labels, with n the number of levels
|
| 133 |
- 1, then you can provide only one level label.
|
| 134 |
|
| 135 |
- dropbox['status'] (optional, defaults to 0)
|
| 136 |
Whether the dropbox is enabled or not (the dropbox allows the user to make
|
| 137 |
multiple selections).
|
| 138 |
|
| 139 |
- dropbox['title'] (optional, defaults to "All selections:")
|
| 140 |
The title of the dropbox. The dropbox is the area where all selections are
|
| 141 |
displayed when the dropbox is enabled.
|
| 142 |
|
| 143 |
- dropbox['limit'] (optional, defaults to 0, which means "no limit")
|
| 144 |
Limit the number of selection that can be added to the dropbox. So this
|
| 145 |
allows you the restrict the number of items that can be selected when
|
| 146 |
the dropbox has been enabled.
|
| 147 |
|
| 148 |
- dropbox['reset_hs'] (optional, defaults to 1, which means "do reset")
|
| 149 |
Determines what will happen to the hierarchical select when the user has
|
| 150 |
added a selection to the dropbox.
|
| 151 |
|
| 152 |
- editability['status] (optional, defaults to 0)
|
| 153 |
Allow the user to create new items in the hierarchy.
|
| 154 |
|
| 155 |
- editability['item_types'] (optional, defaults to the empty array)
|
| 156 |
Only meaningful when editable is set to TRUE.
|
| 157 |
Set the item type for each level. E.g.: "country" for the first level,
|
| 158 |
"region" for the second and "city" for the third. When the user then wants
|
| 159 |
to create a new item, the default label for the new item will be of the
|
| 160 |
form "new <item type>", e.g. "new region".
|
| 161 |
|
| 162 |
- editability['allowed_levels'] (optional, defaults to 1 for each level)
|
| 163 |
Only meaningful when editable is set to TRUE.
|
| 164 |
Specify in which levels the user is allowed to create new items. In the
|
| 165 |
example, the user is only allowed to create new items in the third level.
|
| 166 |
When a setting for a level is ommitted, it defaults to 1 (i.e. allowed for
|
| 167 |
that level). This means you only have to specify in which levels the user
|
| 168 |
is not allowed to create new items.
|
| 169 |
This only applies to *existing* levels: it does not affect the
|
| 170 |
allow_new_levels setting (the next setting).
|
| 171 |
|
| 172 |
- editability['allow_new_levels'] (optional, defaults to 0)
|
| 173 |
Only meaningful when editable is set to TRUE.
|
| 174 |
Allow the user to create new levels, i.e. when a certain item does not yet
|
| 175 |
have children, the user can create a first child for it (thus thereby
|
| 176 |
creating a new level).
|
| 177 |
|
| 178 |
- editability['max_levels'] (optional, defaults to 3)
|
| 179 |
Only meaningful when editable_settings['allow_new_levels'] is set to TRUE.
|
| 180 |
Limits the maximum number of levels. Don't set this too high or you'll end
|
| 181 |
up with very deep hierarchies. This only affects how deep new levels can be
|
| 182 |
created, it will not affect the existing hierarchy.
|
| 183 |
|
| 184 |
- animation_delay (optional, defaults to 400)
|
| 185 |
The delay of each animation (the drop in left and right animations), in ms.
|
| 186 |
|
| 187 |
- special_items (optional, defaults to the empty array)
|
| 188 |
Through this setting, you can mark each item with special properties it
|
| 189 |
possesses. There currently are two special properties: 'exclusive' and
|
| 190 |
'none'.
|
| 191 |
Note: you should include these items in the hierarchy as if it were a
|
| 192 |
normal item and then you can mark them as special through this property.
|
| 193 |
* 'exclusive': Sometimes it's desirable to have exclusive lineages. When
|
| 194 |
such an option is selected, the user should not be able to
|
| 195 |
select anything else. This also means that nothing else in
|
| 196 |
the dropbox can be selected: if the dropbox contains
|
| 197 |
anything, it will be reset.
|
| 198 |
Can be applied to multiple items.
|
| 199 |
e.g. an 'entire_tree' item:
|
| 200 |
'special_items' => array(
|
| 201 |
'entire_tree' => array('exclusive'),
|
| 202 |
)
|
| 203 |
* 'none': Sometimes you want to replace the default '<none>' option by
|
| 204 |
something else. This replacement should of course also exist in
|
| 205 |
the root level.
|
| 206 |
Can be applied to only one item.
|
| 207 |
e.g. an 'any' item (used in hs_taxonomy_views):
|
| 208 |
'special_items' => array(
|
| 209 |
'any' => array('none', 'exclusive'),
|
| 210 |
)
|
| 211 |
And a final example for a better overview:
|
| 212 |
'special_items' => array(
|
| 213 |
'entire_tree' => array('exclusive'),
|
| 214 |
'any' => array('none', 'exclusive'),
|
| 215 |
)
|
| 216 |
|
| 217 |
- render_flat_select (optional, defaults to 0)
|
| 218 |
Because the hierarchical_select form element consists of multiple form
|
| 219 |
items, it doesn't work well in GET forms. By enabling this setting, a flat
|
| 220 |
select will also be rendered, that contains only the selected lineages.
|
| 221 |
Combine that with Drupal.HierarchicalSelect.prepareGETSubmit in the JS code
|
| 222 |
(or, alternatively, the 'prepare-GET-submit' event that can be triggered,
|
| 223 |
see the JavaScript events section for details) and you have a work-around
|
| 224 |
(which, admittedly, only works when JS is enabled).
|
| 225 |
|
| 226 |
- path (optional, defaults to 'hierarchical_select_json')
|
| 227 |
The Drupal path at which a JSON object with Hierarchical Select update
|
| 228 |
information is available. In 99% of the cases, this will remain unchanged,
|
| 229 |
but for advanced use cases, e.g. Views, where an object is referenced by
|
| 230 |
the form in which Hierarchical Select is present and must this exist before
|
| 231 |
the form is rendered, this can be a work-around.
|
| 232 |
3) We *don't* specify a list of options: Hierarchical Select automatically
|
| 233 |
generates the options for us, thanks to the 'module' and 'params' settings.
|
| 234 |
|
| 235 |
|
| 236 |
Concepts
|
| 237 |
--------
|
| 238 |
- Item Unicity: each item in the hierarchy must be *unique*. It doesn't have
|
| 239 |
to be numerical, it can also be a string.
|
| 240 |
If your hierarchy does not have unique items by nature or by
|
| 241 |
design (your items may be unique per level instead), that's
|
| 242 |
not a problem. You can simply prepend the item's ancestors to
|
| 243 |
get a unique item.
|
| 244 |
e.g. you have an item "foobar" at the first, second and third
|
| 245 |
levels. By prepending the ancestors using the dash as the
|
| 246 |
separator, you'd get an item "foobar-foobar-foobar" at the
|
| 247 |
third level.
|
| 248 |
Also see the "Reserved item values" section.
|
| 249 |
- #options: it's gone, because it was the inherent cause for scalability
|
| 250 |
problems: if a hierarchy consists of 10,000 or even 100,000 items,
|
| 251 |
this results in huge HTML being generated. Huge HTML means more
|
| 252 |
processing power necessary, and more bandwidth necessary. So where
|
| 253 |
does Hierarchical Select get its "options"? It uses the hooks that
|
| 254 |
every implementation has to implement to only get what it needs.
|
| 255 |
- The General Concept: you should think of Hierarchical Select as an abstract
|
| 256 |
widget that can represent *any* hierarchy. To be able
|
| 257 |
to display any hierarchy, you obviously need some
|
| 258 |
universal way to "browse" a hierarchy.
|
| 259 |
If you are familiar with C++ or Java iterators, this
|
| 260 |
should come natural: the hooks you have to implement
|
| 261 |
is what allows Hierarchical Select to iterate over your
|
| 262 |
hierarchy. Then the heart of the iterator would be the
|
| 263 |
root_level() and children() hooks. params() allows you
|
| 264 |
to define which information is necessary before you can
|
| 265 |
determine *which* hierarchy or which *part* of the
|
| 266 |
hierarchy is being browsed. lineage() must return the
|
| 267 |
lineage, i.e. the item itself and all its ancestors,
|
| 268 |
this allows a hierarchy to be generated from just one
|
| 269 |
(selected) item.
|
| 270 |
|
| 271 |
|
| 272 |
Reserved item values
|
| 273 |
--------------------
|
| 274 |
- Ensure that your items don't have a "none", "all", "create_new_item" nor
|
| 275 |
"label_\d+" values (the latter means "label_" followed by one or more
|
| 276 |
digits). Your values should also not contain a pipe ("|"), since pipes are
|
| 277 |
used to separate the selection of values that are sent back to the server
|
| 278 |
in the callbacks.
|
| 279 |
- Valid 'empty' selections (i.e. if you want to set the #default_value
|
| 280 |
property of your form item), are -1 and the empty array. The empty string is
|
| 281 |
also considered valid, because Drupal core's Taxonomy module uses this as
|
| 282 |
the empty selection.
|
| 283 |
|
| 284 |
|
| 285 |
Developer mode
|
| 286 |
--------------
|
| 287 |
When you are writing your implementation of the Hierarchical Select API, you
|
| 288 |
will often wonder what Hierarchical Select is doing internally with the data
|
| 289 |
you're feeding it. That's why there's a developer mode: it will show you this
|
| 290 |
data, even the data generated in AJAX callbacks. It'll also show you the time
|
| 291 |
it took to generate the lineage, to fill up the levels and to calculate the
|
| 292 |
child info, to track down badly performing code.
|
| 293 |
Also, when you're just creating a new HS config and it doesn't quite work
|
| 294 |
right, it can be helpful to enable the developer mode. It will perform some
|
| 295 |
basic diagnostics that might help you track down the cause.
|
| 296 |
To use this, you must have a browser with console.log() support. Install
|
| 297 |
Firebug Lite (http://getfirebug.com/lite.html) if your browser does not
|
| 298 |
suport this. Next, go to Hierarchical Select's .module file and set the define
|
| 299 |
for the HS_DEVELOPER_MODE constant to TRUE.
|
| 300 |
When you now open Firebug (Firefox) or the Web Inspector (Safari), you'll see
|
| 301 |
the debug output. New output is added after each callback to the server.
|
| 302 |
|
| 303 |
|
| 304 |
Hierarchical Select implementations: gotcha's
|
| 305 |
---------------------------------------------
|
| 306 |
- "warning: Missing argument 1 for drupal_retrieve_form() …"
|
| 307 |
This implies that your implementation's module weight is heavier than
|
| 308 |
hierarchical_select.module. In that case, Hierarchical Select will not be
|
| 309 |
able to detect hierarchical_select form items, preventing it from applying
|
| 310 |
some magic, and AJAX updates won't work.
|
| 311 |
|
| 312 |
|
| 313 |
Why Hierarchical Select can't take advantage of Drupal 6 Form API
|
| 314 |
-----------------------------------------------------------------
|
| 315 |
There are two main things that make Hierarchical Select's FAPI code very
|
| 316 |
complex. But for neither one I can take advantage of Drupal 6's FAPI
|
| 317 |
improvements.
|
| 318 |
1) Hierarchical Select has its own "light" form cache (only a unique id, the
|
| 319 |
form_id and the parameters that are passed to the form definition function)
|
| 320 |
to make AJAX updates possible (in an AJAX callback only the Hierarchical
|
| 321 |
Select should be re-rendered and returned).
|
| 322 |
One would think he can use Drupal 6's shiny $form_state. But one would be
|
| 323 |
wrong, because Views (the exposed filters form) support is a necessity. And
|
| 324 |
that particular form doesn't work when $form['#cache'] is set.
|
| 325 |
2) add child form items based on the user's input
|
| 326 |
|
| 327 |
|
| 328 |
Hooks
|
| 329 |
-----
|
| 330 |
1) hook_hierarchical_select_params();
|
| 331 |
Returns an array with the names of all parameters that are necessary for
|
| 332 |
this implementation to work.
|
| 333 |
|
| 334 |
2) hook_hierarchical_select_root_level($params, $dropbox = FALSE);
|
| 335 |
Returns the root level of the hierarchy: an array of (item, label) pairs.
|
| 336 |
The $dropbox parameter can is optional and can even ommitted, as it's only
|
| 337 |
necessary if you need the dropbox to influence your hierarchy.
|
| 338 |
|
| 339 |
3) hook_hierarchical_select_children($parent, $params, $dropbox = FALSE);
|
| 340 |
Gets the children of $parent ($parent is an item in the hierarchy) and
|
| 341 |
returns them: an array of (item, label) pairs, or the empty array if the
|
| 342 |
given $parent has no children.
|
| 343 |
The $dropbox parameter can is optional and can even ommitted, as it's only
|
| 344 |
necessary if you need the dropbox to influence your hierarchy.
|
| 345 |
|
| 346 |
4) hook_hierarchical_select_lineage($item, $params);
|
| 347 |
Calculates the lineage of $item (array of items, with $item the last) and
|
| 348 |
returns it. Necessary when the "enforce_deepest" option is enabled.
|
| 349 |
|
| 350 |
5) hook_hierarchical_select_valid_item($item, $params);
|
| 351 |
Validates an item, returns TRUE if valid, FALSE if invalid.
|
| 352 |
|
| 353 |
6) hook_hierarchical_select_item_get_label($item, $params);
|
| 354 |
Given a valid item, returns the label. Is only used for rendering the
|
| 355 |
selections in the dropbox.
|
| 356 |
|
| 357 |
7) hook_hierarchical_select_create_item($label, $parent, $params);
|
| 358 |
Given a parent item and the label of a new item, create a new item as a
|
| 359 |
child of the parent item. When $parent == 0, this means a new item is being
|
| 360 |
created at the root level.
|
| 361 |
Optional hook. When this hook is not implemented, this functionality will
|
| 362 |
never be used, even when you configure it that way in code.
|
| 363 |
|
| 364 |
8) hook_hierarchical_select_entity_count($item, $params);
|
| 365 |
Given a item, get the number of entities (most of the time the entity type
|
| 366 |
is 'node') that are related to the given item. Used for the entity_count
|
| 367 |
and require_entity settings.
|
| 368 |
Optional hook. When this hook is not implemented, this functionality will
|
| 369 |
never be used, even when you configure it that way (i.e. when you enable
|
| 370 |
the entity_count and require_entity settings).
|
| 371 |
|
| 372 |
9) hook_hierarchical_select_implementation_info();
|
| 373 |
Return metadata about this implementation.
|
| 374 |
This information is used to generate the implementations overview at
|
| 375 |
admin/settings/hierarchical_select/implementations. The expected format is:
|
| 376 |
|
| 377 |
array(
|
| 378 |
'hierarchy type' => t('Taxonomy'),
|
| 379 |
'entity type' => t('Node'),
|
| 380 |
'entity' => t('Story'),
|
| 381 |
'context type' => t('Node form'),
|
| 382 |
'context' => '',
|
| 383 |
);
|
| 384 |
|
| 385 |
another example:
|
| 386 |
|
| 387 |
array(
|
| 388 |
'hierarchy type' => t('Taxonomy'),
|
| 389 |
'entity type' => t('Node'),
|
| 390 |
'entity' => '',
|
| 391 |
'context type' => t('Views exposed filter'),
|
| 392 |
'context' => t('some view'),
|
| 393 |
);
|
| 394 |
|
| 395 |
10) hook_hierarchical_select_config_info();
|
| 396 |
Return metadata about each available user-editable configuration for this
|
| 397 |
implementation.
|
| 398 |
Optional hook. This information is used to generate the configurations
|
| 399 |
overview at admin/settings/hierarchical_select/configs. The expected
|
| 400 |
format is:
|
| 401 |
|
| 402 |
$config_info[$config_id] = array(
|
| 403 |
'config_id' => $config_id,
|
| 404 |
'hierarchy type' => t('Taxonomy'),
|
| 405 |
'hierarchy' => t($vocabulary->name),
|
| 406 |
'entity type' => t('Node'),
|
| 407 |
'entity' => implode(', ', array_map('t', $entities)),
|
| 408 |
'edit link' => "admin/content/taxonomy/edit/vocabulary/$vid",
|
| 409 |
);
|
| 410 |
|
| 411 |
|
| 412 |
Standardized configuration form
|
| 413 |
-------------------------------
|
| 414 |
Hierarchical Select 3 comes with a standardized configuration form:
|
| 415 |
hierarchical_select_common_config_form(). This function accepts a lot of
|
| 416 |
parameters, which allows you to use names typical to your module's hierarchy
|
| 417 |
(e.g. 'leaf' instead of 'term' and 'tree' instead of 'vocabulary'). A submit
|
| 418 |
handler is also provided, of course.
|
| 419 |
An example:
|
| 420 |
|
| 421 |
// I'm not configuring all parameters here. For an example of that, see one
|
| 422 |
// of the included modules.
|
| 423 |
$form['foobar_hierarchical_select_config'] = hierarchical_select_common_config_form($module, $params, $config_id, $defaults, $strings, $max_hierarchy_depth, $preview_is_required);
|
| 424 |
|
| 425 |
// Add the the submit handler for the Hierarchical Select config form.
|
| 426 |
$parents = array('foobar_hierarchical_select_config');
|
| 427 |
$form['#submit'][] = 'hierarchical_select_common_config_form_submit';
|
| 428 |
$form['#hs_common_config_form_parents'] = $parents;
|
| 429 |
|
| 430 |
|
| 431 |
Configuration management
|
| 432 |
------------------------
|
| 433 |
It's now possible to export Hierarchical Select configurations, and there is a
|
| 434 |
function to set the configuration of a certain Hierarchical Select. Combine
|
| 435 |
the two and you can manage your Hierarchical Select configurations in code!
|
| 436 |
An example:
|
| 437 |
|
| 438 |
// The exported configuration.
|
| 439 |
$config = array( … );
|
| 440 |
$config_id = $config['config_id];
|
| 441 |
|
| 442 |
// Apply the configuration.
|
| 443 |
require_once(drupal_get_path('module', 'hierarchical_select') .'/includes/common.inc');
|
| 444 |
hierarchical_select_common_config_set($config_id, $config);
|
| 445 |
|
| 446 |
|
| 447 |
JavaScript events
|
| 448 |
-----------------
|
| 449 |
The Hierarchical Select module's JavaScript code triggers several events, to
|
| 450 |
allow for advanced interactions.
|
| 451 |
|
| 452 |
You can find all hierarchical_select form items using this selector:
|
| 453 |
|
| 454 |
$('.hierarchical-select-wrapper');
|
| 455 |
|
| 456 |
You can find a *specific* hierarchical_select form item using this selector:
|
| 457 |
|
| 458 |
$('#hierarchical-select-x-wrapper');
|
| 459 |
|
| 460 |
where x is a number, or more accurately: a hsid (hierarchical select id).
|
| 461 |
Retrieving all hsids in the current document can be done like this:
|
| 462 |
|
| 463 |
for (var hsid in Drupal.settings.HierarchicalSelect.settings) {
|
| 464 |
// …
|
| 465 |
}
|
| 466 |
|
| 467 |
The following events are triggered:
|
| 468 |
- change-hierarchical-select
|
| 469 |
- update-hierarchical-select
|
| 470 |
- create-new-item
|
| 471 |
- cancel-new-item
|
| 472 |
- add-to-dropbox
|
| 473 |
- remove-from-dropbox
|
| 474 |
- enforced-update
|
| 475 |
- prepared-GET-submit
|
| 476 |
All events are triggered *after* the animations have completed.
|
| 477 |
|
| 478 |
However, it's often useful to do something *before* an event (especially
|
| 479 |
because all of the above events perform an AJAX request to the server). So,
|
| 480 |
the equivalent "before" events exist as well:
|
| 481 |
- before-update-hierarchical-select
|
| 482 |
- before-create-new-item
|
| 483 |
- before-cancel-new-item
|
| 484 |
- before-add-to-dropbox
|
| 485 |
- before-remove-from-dropbox
|
| 486 |
- before-enforced-update
|
| 487 |
There is one exception: when the cache is enabled, the "before update
|
| 488 |
hierarchical select" event will not be triggered. This makes sense, because
|
| 489 |
updates from the cache are instantaneous.
|
| 490 |
|
| 491 |
An example of binding a function to the 'create-new-item' event of the second
|
| 492 |
(hsid == 1) hierarchical_select form item on the page:
|
| 493 |
|
| 494 |
$('#hierarchical-select-1-wrapper')
|
| 495 |
.bind('create-new-item', function() {
|
| 496 |
// …
|
| 497 |
});
|
| 498 |
|
| 499 |
And finally, you can trigger a special event to enforce an update (this can be
|
| 500 |
useful when you have changed a hierarchy through another form item, or for
|
| 501 |
live previews, or …). You can then also pass additional information that will
|
| 502 |
be POSTed. You can even disable normal updates, to manage that completely
|
| 503 |
yourself via enforced updates. This allows you to write a Hierarchical Select
|
| 504 |
implementation that gets some of its information ($params) from another form
|
| 505 |
item!
|
| 506 |
Suppose you'd like to enforce an update of the first (hsid == 0)
|
| 507 |
hierarchical_select form item on the page:
|
| 508 |
|
| 509 |
$('#hierarchical-select-0-wrapper')
|
| 510 |
.trigger('enforce-update');
|
| 511 |
|
| 512 |
Now let's move on to a more advanced example, in which we will disable normal
|
| 513 |
updates and let another form item (here a select) provide a part of the
|
| 514 |
information that will be used to render the Hierarchical Select. Effectively,
|
| 515 |
this other form item will *influence* the hierarchy that will be presented by
|
| 516 |
Hierarchical Select!
|
| 517 |
|
| 518 |
$(document).ready(function() {
|
| 519 |
Drupal.settings.specialfilter = {};
|
| 520 |
|
| 521 |
// .specialfilter-first: a select form item
|
| 522 |
// .specialfilter-second: a hierarchical_select form item
|
| 523 |
|
| 524 |
update = function() {
|
| 525 |
var selection = Drupal.settings.specialfilter.currentSelection;
|
| 526 |
|
| 527 |
// Send an extra parameter via POST: dynamicParameter. This is the stored
|
| 528 |
// selection.
|
| 529 |
$('.specialfilter-second')
|
| 530 |
.trigger('enforce-update',
|
| 531 |
[
|
| 532 |
{ name : 'dynamicParameter', value : selection }
|
| 533 |
]
|
| 534 |
);
|
| 535 |
};
|
| 536 |
|
| 537 |
attachHSBindings = function() {
|
| 538 |
// When a user navigates the hierarchical_select form item, we still want to
|
| 539 |
// POST the the extra dynamicParameter, or otherwise we will no longer have
|
| 540 |
// a hierarchy in the hierarchical_select form item that really depends on
|
| 541 |
// the select.
|
| 542 |
$('.specialfilter-second .hierarchical-select > select')
|
| 543 |
.change(function() { update(); });
|
| 544 |
|
| 545 |
$('.specialfilter-second')
|
| 546 |
.unbind('enforced-update').bind('enforced-update', function() { return attachHSBindings(); });
|
| 547 |
};
|
| 548 |
|
| 549 |
// Initialize after 25 ms, because otherwise the event binding of HS will
|
| 550 |
// not yet be ready, and hence this won't have any effect
|
| 551 |
setTimeout(function() {
|
| 552 |
// Get the initial selection (before the user has changed anything).
|
| 553 |
Drupal.settings.specialfilter.currentSelection = $('.specialfilter-first').attr('value');
|
| 554 |
|
| 555 |
// When the select form item changes, we want to *store* that selection, and
|
| 556 |
// update the hierarchical_select form item.
|
| 557 |
$('.specialfilter-first')
|
| 558 |
.change(function() {
|
| 559 |
// Store the current selection.
|
| 560 |
Drupal.settings.specialfilter.currentSelection = $(this).attr('value');
|
| 561 |
|
| 562 |
update();
|
| 563 |
});
|
| 564 |
|
| 565 |
$('.specialfilter-second')
|
| 566 |
.trigger('disable-updates');
|
| 567 |
|
| 568 |
attachHSBindings();
|
| 569 |
}, 25);
|
| 570 |
});
|
| 571 |
|
| 572 |
The 'enforced-update' (notice the past tense!) event is triggered upon
|
| 573 |
completion.
|
| 574 |
An even more rarely used special event can be triggered to prepare the
|
| 575 |
hierarchical_select form element for a get submit: the 'prepare GET submit'
|
| 576 |
event. To use this event, the 'render_flat_select' setting should be enabled
|
| 577 |
in the config.
|