/**
* Hierarchical select form element type #process callback.
*/
function hierarchical_select_process($element) {
$hsid = 0;
}
else {
$hsid++;
}
$element['hsid'] =
array('#type' =>
'value',
'#value' =>
$hsid);
// A hierarchical_select form element expands to multiple items. For example
// $element['hsid'] got set just above. If #value is not an array, then
// form_set_value(), which is called by form_builder() will fail, because it
// assumes that #value is an array, because we are trying to set a child of
// it.
$element['#value'] =
array($element['#value']);
}
// Store the #name property of each hierarchical_select form item, this is
// necessary to find this form item back in an AJAX callback.
_hierarchical_select_store_name($element, $hsid);
// Set up Javascript and add settings specifically for the current
// hierarchical select.
_hierarchical_select_setup_js();
$config = $element['#config'];
'HierarchicalSelect' =>
array(
'animationDelay' =>
($config['animation_delay'] ==
0) ?
(int
) variable_get('hierarchical_select_animation_delay',
400) :
$config['animation_delay'],
'cacheId' =>
$config['module'] .
'_'.
implode('_',
(is_array($config['params'])) ?
$config['params'] :
array()),
'renderFlatSelect' =>
(isset($config['render_flat_select'])) ?
(int
) $config['render_flat_select'] :
0,
'createNewItems' =>
(isset($config['editability']['status'])) ?
(int
) $config['editability']['status'] :
0,
'createNewLevels' =>
(isset($config['editability']['allow_new_levels'])) ?
(int
) $config['editability']['allow_new_levels'] :
0,
'resizable' =>
(isset($config['resizable'])) ?
(int
) $config['resizable'] :
0,
),
),
)
),
'setting'
);
// Basic config validation and diagnostics.
if (HS_DEVELOPER_MODE) {
if (!
isset($config['module']) ||
empty($config['module'])) {
$diagnostics[] = "'module is not set!";
}
else {
$required_params =
module_invoke($config['module'],
'hierarchical_select_params');
if (!
empty($missing_params)) {
$diagnostics[] =
"'params' is missing values for: ".
implode(', ',
$missing_params) .
'.';
}
}
$config_id =
(isset($config['config_id']) &&
is_string($config['config_id'])) ?
$config['config_id'] :
'none';
if (empty($diagnostics)) {
_hierarchical_select_log("Config diagnostics (config id: $config_id): no problems found!");
}
else {
$diagnostics_string =
print_r($diagnostics,
TRUE);
$message = "Config diagnostics (config id: $config_id): $diagnostics_string";
_hierarchical_select_log($message);
$element['#type']= 'item';
$element['#value'] =
'<p><span style="color:red;">Fix the indicated errors in the #config property first!</span><br />'.
nl2br($message) .
'</p>';
return $element;
}
}
// Calculate the selections in both the hierarchical select and the dropbox,
// we need these before we can render anything.
list($hs_selection,
$db_selection) = _hierarchical_select_process_calculate_selections
($element);
if (HS_DEVELOPER_MODE) {
_hierarchical_select_log("Calculated hierarchical select selection:");
_hierarchical_select_log($hs_selection);
if ($config['dropbox']['status']) {
_hierarchical_select_log("Calculated dropbox selection:");
_hierarchical_select_log($db_selection);
}
}
// If the exclusive_lineages setting has been configured, and the dropbox
// is enabled, then do the necessary processing to make exclusive lineages
// possible.
if (count($config['exclusive_lineages']) &&
$config['dropbox']['status']) {
// When the form is first loaded, $db_selection will contain the selection
// that we should check, but in updates, $hs_selection will.
$selection =
(!
empty($hs_selection)) ?
$hs_selection :
$db_selection;
// If the current selection of the hierarchical select matches one of the
// configured exclusive items, then disable the dropbox (to ensure an
// exclusive selection).
if (in_array($selection,
$config['exclusive_lineages']) // A lineage.
||
(count($selection) ==
1 &&
in_array($selection[0],
$config['exclusive_lineages']))) { // An item at the root level.
// By also updating the configuration stored in $element, we ensure that
// the validation step, which extracts the configuration again, also gets
// the updated config.
$element['#config']['dropbox']['status'] = 0;
$config = $element['#config'];
// When the form is first loaded, $db_selection contained the selection
// selection that we checked for. Since we've now disabled the dropbox,
// we should overwrite $hs_selection with the value of $db_selection and
// reset $db_selection.
if (empty($hs_selection)) {
$hs_selection = $db_selection;
}
}
}
// Generate the $hierarchy and $dropbox objects using the selections that
// were just calculated.
$dropbox = (!$config['dropbox']['status']) ? FALSE : _hierarchical_select_dropbox_generate($config, $db_selection);
$hierarchy = _hierarchical_select_hierarchy_generate($config, $hs_selection, $element['#required'], $dropbox);
if (HS_DEVELOPER_MODE) {
_hierarchical_select_log('Generated hierarchy in '. $hierarchy->build_time['total'] .' ms:');
_hierarchical_select_log($hierarchy);
if ($config['dropbox']['status']) {
_hierarchical_select_log('Generated dropbox in '. $dropbox->build_time .' ms: ');
_hierarchical_select_log($dropbox);
}
}
// Store the hierarchy object in the element, we'll need this if the user's
// browser supports the active cache system.
$element['hierarchy'] =
array('#type' =>
'value',
'#value' =>
$hierarchy);
// Ensure that #tree is enabled!
$element['#tree'] = TRUE;
// If render_flat_select is enabled, render a flat select.
if ($config['render_flat_select']) {
$element['flat_select'] = _hierarchical_select_process_render_flat_select($hierarchy, $dropbox, $config);
}
// Render the hierarchical select.
$element['hierarchical_select'] =
array(
'#prefix' => '<div class="hierarchical-select clear-block">',
'#suffix' => '</div>',
);
$element['hierarchical_select']['selects'] = _hierarchical_select_process_render_hs_selects($hsid, $hierarchy);
// The selects in the hierarchical select should inherit the #size property.
foreach (element_children($element['hierarchical_select']['selects']) as $depth) {
$element['hierarchical_select']['selects'][$depth]['#size'] = $element['#size'];
}
// Check if a new item is being created.
$creating_new_item = FALSE;
if (isset($element['#value']['hierarchical_select']['selects'])) {
foreach ($element['#value']['hierarchical_select']['selects'] as $depth => $value) {
if ($value == 'create_new_item' && _hierarchical_select_create_new_item_is_allowed($config, $depth)) {
$creating_new_item = TRUE;
// We want to override the select in which the "create_new_item"
// option was selected and hide all selects after that, if they exist.
for ($i =
$depth;
$i <
count($hierarchy->
lineage);
$i++
) {
unset($element['hierarchical_select']['selects'][$i]);
}
$element['hierarchical_select']['create_new_item'] =
array(
'#prefix' =>
'<div class="'.
str_replace('_',
'-',
$value) .
'">',
'#suffix' => '</div>',
);
$item_type_depth = ($value == 'create_new_item') ? $depth : $depth + 1;
$item_type =
(!
empty($config['editability']['item_types'][$item_type_depth])) ?
t($config['editability']['item_types'][$item_type_depth]) :
t('item');
$element['hierarchical_select']['create_new_item']['input'] =
array(
'#type' => 'textfield',
'#size' => 20,
'#maxlength' => 255,
'#default_value' =>
t('new @item',
array('@item' =>
$item_type)),
'title' =>
t('new @item',
array('@item' =>
$item_type)),
'class' => 'create-new-item-input'
),
// Use a #theme callback to prevent the textfield from being wrapped
// in a div. This simplifies the CSS and JS code.
'#theme' => 'hierarchical_select_textfield',
);
$element['hierarchical_select']['create_new_item']['create'] =
array(
'#type' => 'button',
'#attributes' =>
array('class' =>
'create-new-item-create'),
);
$element['hierarchical_select']['create_new_item']['cancel'] =
array(
'#type' => 'button',
'#attributes' =>
array('class' =>
'create-new-item-cancel'),
);
}
}
}
if ($config['dropbox']['status']) {
if (!$creating_new_item) {
// Append an "Add" button to the selects.
$element['hierarchical_select']['dropbox_add'] =
array(
'#type' => 'button',
'#attributes' =>
array('class' =>
'add-to-dropbox'),
);
}
if ($config['dropbox']['limit'] > 0) { // Zero as dropbox limit means no limit.
if (count($dropbox->
lineages) ==
$config['dropbox']['limit']) {
$element['dropbox_limit_warning'] =
array(
'#value' =>
t("You've reached the maximal number of items you can select."),
'#prefix' => '<p class="hierarchical-select-dropbox-limit-warning">',
'#suffix' => '</p>',
);
// Disable all child form elements of $element['hierarchical_select].
_hierarchical_select_mark_as_disabled($element['hierarchical_select']);
}
}
// Add the hidden part of the dropbox. This will be used to store the
// currently selected lineages.
$element['dropbox']['hidden'] =
array(
'#prefix' => '<div class="dropbox-hidden">',
'#suffix' => '</div>',
);
$element['dropbox']['hidden'] = _hierarchical_select_process_render_db_hidden($hsid, $dropbox);
// Add the dropbox-as-a-table that will be visible to the user.
$element['dropbox']['visible'] = _hierarchical_select_process_render_db_visible($hsid, $dropbox);
}
// This button and accompanying help text will be hidden when Javascript is
// enabled.
$element['nojs'] =
array(
'#prefix' => '<div class="nojs">',
'#suffix' => '</div>',
);
$element['nojs']['update_button'] =
array(
'#type' => 'button',
'#attributes' =>
array('class' =>
'update-button'),
);
$element['nojs']['update_button_help_text'] =
array(
'#value' => _hierarchical_select_nojs_helptext($config['dropbox']['status']),
'#prefix' => '<div class="help-text">',
'#suffix' => '</div>',
);
// Ensure the render order is correct.
$element['hierarchical_select']['#weight'] = 0;
$element['dropbox_limit_warning']['#weight'] = 1;
$element['dropbox']['#weight'] = 2;
$element['nojs']['#weight'] = 3;
// This prevents values from in $element['#post'] to be used instead of the
// generated default values (#default_value).
// For example: $element['hierarchical_select']['selects']['0']['#default_value']
// is set to 'label_0' after an "Add" operation. When $element['#post'] is
// NOT unset, the corresponding value in $element['#post'] will be used
// instead of the default value that was set. This is undesired behavior.
unset($element['#post']);
// Finally, calculate the return value of this hierarchical_select form
// element. This will be set in _hierarchical_select_validate(). (If we'd
// set it now, it would be overridden again.)
$element['#return_value'] = _hierarchical_select_process_calculate_return_value($hierarchy, ($config['dropbox']['status']) ? $dropbox : FALSE, $config['module'], $config['params'], $config['save_lineage']);
// Add a validate callback, which will:
// - validate that the dropbox limit was not exceeded.
// - set the return value of this form element.
$element['#validate'] =
array('_hierarchical_select_validate' =>
array());
if (HS_DEVELOPER_MODE) {
$element['log'] =
array('#type' =>
'value',
'#value' => _hierarchical_select_log
(NULL,
TRUE));
'HierarchicalSelect' =>
array(
$hsid => $element['log']['#value'],
),
),
),
'setting'
);
}
// If the form item is marked as disabled, disable all child form items as
// well.
if ($element['#disabled']) {
_hierarchical_select_mark_as_disabled($element);
}
return $element;
}
Comments
Post new comment