updated core to 7.58 (right after the site was hacked)
This commit is contained in:
@@ -0,0 +1,441 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Functions used by more than one Hierarchical Select implementation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Retrieve a config. If certain settings are not yet configured by the user,
|
||||
* defaults will be set. These defaults can also be overriden. This allows
|
||||
* modules to provide their own meaningful defaults.
|
||||
*
|
||||
* @param $config_id
|
||||
* A config id, typically of the form "module-someid", e.g.
|
||||
* "taxonomy-field_name".
|
||||
* @param $defaults_override
|
||||
* Optionally override the defaults.
|
||||
*
|
||||
* @return array
|
||||
* An array of default config.
|
||||
*/
|
||||
function hierarchical_select_common_config_get($config_id, $defaults_override = array()) {
|
||||
$config = variable_get('hs_config_' . $config_id, array());
|
||||
return _hierarchical_select_inherit_default_config($config, $defaults_override);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a config.
|
||||
*
|
||||
* @param $config_id
|
||||
* A config id.
|
||||
* @param $config
|
||||
* The config to store.
|
||||
*/
|
||||
function hierarchical_select_common_config_set($config_id, $config) {
|
||||
variable_set('hs_config_' . $config_id, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a config.
|
||||
*
|
||||
* @param $config_id
|
||||
* The config id to delete.
|
||||
*/
|
||||
function hierarchical_select_common_config_del($config_id) {
|
||||
variable_del('hs_config_' . $config_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a config to a form item.
|
||||
*
|
||||
* @param $form_item
|
||||
* The form item that will be updated.
|
||||
* @param $config_id
|
||||
* A config id.
|
||||
* @param $defaults_override
|
||||
* Optionally override the defaults.
|
||||
* @see hierarchical_select_common_config_get()
|
||||
*/
|
||||
function hierarchical_select_common_config_apply(&$form_item, $config_id, $defaults_override = array()) {
|
||||
$config = hierarchical_select_common_config_get($config_id, $defaults_override);
|
||||
$form_item['#config'] = array_merge((isset($form_item['#config']) && is_array($form_item['#config'])) ? $form_item['#config'] : array(), $config);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Forms API callbacks.
|
||||
|
||||
/**
|
||||
* Form definition of the hierarchical_select_common_config_form form.
|
||||
*/
|
||||
function hierarchical_select_common_config_form($module, $params, $config_id, $defaults_override, $strings, $max_hierarchy_depth, $preview_is_required) {
|
||||
$config = hierarchical_select_common_config_get($config_id, $defaults_override);
|
||||
$args = array(
|
||||
'!item' => $strings['item'],
|
||||
'!items' => $strings['items'],
|
||||
'!entity' => $strings['entity'],
|
||||
'!entities' => $strings['entities'],
|
||||
'!hierarchy' => $strings['hierarchy'],
|
||||
'!hierarchies' => $strings['hierarchies']
|
||||
);
|
||||
|
||||
$form = array(
|
||||
'#tree' => TRUE,
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Hierarchical Select configuration'),
|
||||
'#attributes' => array(
|
||||
'class' => array('hierarchical-select-config-form'),
|
||||
'id' => 'hierarchical-select-config-form-' . $config_id,
|
||||
),
|
||||
'#attached' => array(
|
||||
'css' => array(
|
||||
drupal_get_path('module', 'hierarchical_select') . '/includes/common_config_form.css'
|
||||
),
|
||||
'js' => array(
|
||||
array(
|
||||
'type' => 'file',
|
||||
'data' => drupal_get_path('module', 'hierarchical_select') . '/includes/common_config_form.js',
|
||||
),
|
||||
array(
|
||||
'type' => 'setting',
|
||||
'data' => array('HierarchicalSelect' => array('configForm' => array($config_id))),
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$form['config_id'] = array('#type' => 'value', '#value' => $config_id);
|
||||
|
||||
// TODO: really make this a *live* preview, i.e. refresh the preview on each
|
||||
// change in the form. This cannot be done easily in Drupal 5 or 6, so let's
|
||||
// do so in Drupal 7. See cfg.livePreview in common_config_form.js.
|
||||
$form['live_preview'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Preview'),
|
||||
'#description' => t('This is what the Hierarchical Select will look like with your current configuration.'),
|
||||
'#collapsible' => FALSE,
|
||||
'#attributes' => array('class' => array('live-preview')),
|
||||
);
|
||||
$form['live_preview']['example'] = array(
|
||||
'#type' => 'hierarchical_select',
|
||||
'#required' => $preview_is_required,
|
||||
'#title' => t('Preview'),
|
||||
'#description' => t('The description.'),
|
||||
// Skip al validation for this form element: the data collected through it
|
||||
// is always discarded, it's merely here for illustrative purposes.
|
||||
'#validated' => TRUE,
|
||||
);
|
||||
hierarchical_select_common_config_apply($form['live_preview']['example'], $config_id, array_merge($defaults_override, array('module' => $module, 'params' => $params)));
|
||||
|
||||
$form['save_lineage'] = array(
|
||||
'#type' => 'radios',
|
||||
'#title' => t('Save lineage'),
|
||||
'#options' => array(
|
||||
1 => t('Save !item lineage', $args),
|
||||
0 => t('Save only the deepest !item', $args),
|
||||
),
|
||||
'#default_value' => (isset($config['save_lineage'])) ? $config['save_lineage'] : NULL,
|
||||
'#description' => t(
|
||||
'Saving the !item lineage means saving the <em>the !item itself and all
|
||||
its ancestors</em>.',
|
||||
$args
|
||||
),
|
||||
);
|
||||
|
||||
$form['enforce_deepest'] = array(
|
||||
'#type' => 'radios',
|
||||
'#title' => t('Level choice'),
|
||||
'#options' => array(
|
||||
1 => t('Force the user to choose a !item from a <em>deepest level</em>', $args),
|
||||
0 => t('Allow the user to choose a !item from <em>any level</em>', $args),
|
||||
),
|
||||
'#default_value' => (isset($config['enforce_deepest'])) ? $config['enforce_deepest'] : NULL,
|
||||
'#description' => t(
|
||||
'This setting determines from which level in the !hierarchy tree a
|
||||
user can select a !item.',
|
||||
$args
|
||||
),
|
||||
'#attributes' => array('class' => array('enforce-deepest')),
|
||||
);
|
||||
|
||||
$form['resizable'] = array(
|
||||
'#type' => 'radios',
|
||||
'#title' => t('Resizable'),
|
||||
'#description' => t(
|
||||
"When enabled, a handle appears below the Hierarchical Select to allow
|
||||
the user to dynamically resize it. Double clicking will toggle between
|
||||
the smallest and a sane 'big size'."
|
||||
),
|
||||
'#options' => array(
|
||||
0 => t('Disabled'),
|
||||
1 => t('Enabled'),
|
||||
),
|
||||
'#default_value' => (isset($config['resizable'])) ? $config['resizable'] : NULL,
|
||||
'#attributes' => array('class' => array('resizable')),
|
||||
);
|
||||
|
||||
$form['level_labels'] = array(
|
||||
'#tree' => TRUE,
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Level labels'),
|
||||
'#description' => t(
|
||||
'When the user is allowed to choose a !item from any level in the
|
||||
<em>Level choice</em> setting, you can enter a label for <em>each</em>
|
||||
level.<br />
|
||||
However, when the user is only allowed to choose a !item from the
|
||||
deepest level, then you can only enter a label for the <em>root</em>
|
||||
level.',
|
||||
$args
|
||||
),
|
||||
'#collapsible' => TRUE,
|
||||
);
|
||||
$form['level_labels']['status'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Enable level labels'),
|
||||
'#default_value' => (isset($config['level_labels']['status'])) ? $config['level_labels']['status'] : NULL,
|
||||
'#attributes' => array('class' => array('level-labels-status')),
|
||||
);
|
||||
for ($depth = 0; $depth <= $max_hierarchy_depth; $depth++) {
|
||||
$form['level_labels']['labels'][$depth] = array(
|
||||
'#type' => 'textfield',
|
||||
'#size' => 20,
|
||||
'#maxlength' => 255,
|
||||
'#default_value' => (isset($config['level_labels']['labels'][$depth])) ? $config['level_labels']['labels'][$depth] : NULL,
|
||||
'#attributes' => array('class' => array('level-label')),
|
||||
);
|
||||
}
|
||||
$form['level_labels']['#theme'] = 'hierarchical_select_common_config_form_level_labels';
|
||||
$form['level_labels']['#strings'] = $strings;
|
||||
|
||||
$form['dropbox'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Dropbox settings'),
|
||||
'#description' => t('The dropbox allows the user to <strong>make multiple selections</strong>.'),
|
||||
'#collapsible' => TRUE,
|
||||
);
|
||||
$form['dropbox']['status'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Enable the dropbox'),
|
||||
'#default_value' => (isset($config['dropbox']['status'])) ? $config['dropbox']['status'] : NULL,
|
||||
'#attributes' => array('class' => array('dropbox-status')),
|
||||
);
|
||||
$form['dropbox']['title'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Title'),
|
||||
'#description' => t('The title you enter here appears above the dropbox.'),
|
||||
'#size' => 20,
|
||||
'#maxlength' => 255,
|
||||
'#default_value' => (isset($config['dropbox']['title'])) ? $config['dropbox']['title'] : NULL,
|
||||
'#attributes' => array('class' => array('dropbox-title')),
|
||||
);
|
||||
$form['dropbox']['limit'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Limit the number of selections'),
|
||||
'#description' => t(
|
||||
'Limits the number of selections that can be added to the dropbox.
|
||||
0 means no limit.
|
||||
<br />
|
||||
Note: the "Save !item lineage" option has no effect on this, even if
|
||||
a lineage consists of 3 !items, this will count as only one selection
|
||||
in the dropbox.',
|
||||
$args
|
||||
),
|
||||
'#size' => 5,
|
||||
'#maxlength' => 5,
|
||||
'#default_value' => (isset($config['dropbox']['limit'])) ? $config['dropbox']['limit'] : NULL,
|
||||
'#attributes' => array('class' => array('dropbox-limit')),
|
||||
);
|
||||
$form['dropbox']['reset_hs'] = array(
|
||||
'#type' => 'radios',
|
||||
'#title' => t('Reset selection of hierarchical select'),
|
||||
'#description' => t(
|
||||
'This setting determines what will happen to the hierarchical select
|
||||
when the user has added a selection to the dropbox.'
|
||||
),
|
||||
'#options' => array(
|
||||
0 => t('Disabled'),
|
||||
1 => t('Enabled'),
|
||||
),
|
||||
'#default_value' => (isset($config['dropbox']['reset_hs'])) ? $config['dropbox']['reset_hs'] : NULL,
|
||||
'#attributes' => array('class' => array('dropbox-reset-hs')),
|
||||
);
|
||||
$form['dropbox']['sort'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Sort dropbox items'),
|
||||
'#description' => t('Automatically sort items added to the dropbox. If unchecked new items will be added to the end of the dropbox list.'),
|
||||
'#default_value' => (isset($config['dropbox']['sort'])) ? $config['dropbox']['sort'] : 1,
|
||||
'#attributes' => array('class' => array('dropbox-sort')),
|
||||
);
|
||||
if (module_hook($module, 'hierarchical_select_create_item')) {
|
||||
$form['editability'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Editability settings'),
|
||||
'#description' => t(
|
||||
'You can allow the user to <strong>add new !items to this
|
||||
!hierarchy</strong> <em>through</em> Hierarchical Select.',
|
||||
$args
|
||||
),
|
||||
'#collapsible' => TRUE,
|
||||
);
|
||||
$form['editability']['status'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Allow creation of new !items', $args),
|
||||
'#options' => array(
|
||||
0 => t('Disabled'),
|
||||
1 => t('Enabled'),
|
||||
),
|
||||
'#default_value' => (isset($config['editability']['status'])) ? $config['editability']['status'] : NULL,
|
||||
'#attributes' => array('class' => array('editability-status')),
|
||||
);
|
||||
for ($depth = 0; $depth <= $max_hierarchy_depth; $depth++) {
|
||||
$form['editability']['item_types'][$depth] = array(
|
||||
'#type' => 'textfield',
|
||||
'#size' => 20,
|
||||
'#maxlength' => 255,
|
||||
'#default_value' => (isset($config['editability']['item_types'][$depth])) ? $config['editability']['item_types'][$depth] : NULL,
|
||||
'#attributes' => array('class' => array('editability-item-type')),
|
||||
);
|
||||
}
|
||||
for ($depth = 0; $depth <= $max_hierarchy_depth; $depth++) {
|
||||
$form['editability']['allowed_levels'][$depth] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#default_value' => (isset($config['editability']['allowed_levels'][$depth])) ? $config['editability']['allowed_levels'][$depth] : 1,
|
||||
);
|
||||
}
|
||||
$form['editability']['allow_new_levels'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Allow creation of new levels'),
|
||||
'#default_value' => $config['editability']['allow_new_levels'],
|
||||
'#description' => t(
|
||||
'Allow the user to create child !items for !items that do not yet have
|
||||
children.',
|
||||
$args
|
||||
),
|
||||
'#attributes' => array('class' => array('editability-allow-new-levels')),
|
||||
);
|
||||
$form['editability']['max_levels'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Maximum number of levels allowed'),
|
||||
'#options' => array(
|
||||
0 => t('0 (no limit)'), 1, 2, 3, 4, 5, 6, 7, 8, 9
|
||||
),
|
||||
'#default_value' => (isset($config['editability']['max_levels'])) ? $config['editability']['max_levels'] : NULL,
|
||||
'#description' => t(
|
||||
'When the user is allowed to create new levels, this option prevents
|
||||
the user from creating extremely deep !hierarchies.',
|
||||
$args
|
||||
),
|
||||
'#attributes' => array('class' => array('editability-max-levels')),
|
||||
);
|
||||
|
||||
$form['editability']['#theme'] = 'hierarchical_select_common_config_form_editability';
|
||||
$form['editability']['#strings'] = $strings;
|
||||
}
|
||||
|
||||
if (module_hook($module, 'hierarchical_select_entity_count')) {
|
||||
$form['entity_count'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Entity Count'),
|
||||
'#collapsible' => TRUE,
|
||||
);
|
||||
|
||||
$form['entity_count']['enabled'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Display number of entities'),
|
||||
'#description' => t('Display the number of entities associated with the !item. Do not forget to check which entities should be counted.', $args),
|
||||
'#default_value' => isset($config['entity_count']['enabled']) ? $config['entity_count']['enabled'] : FALSE,
|
||||
'#weight' => -1,
|
||||
'#attributes' => array('class' => array('entity-count-enabled')),
|
||||
);
|
||||
|
||||
$form['entity_count']['require_entity'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Require associated entity'),
|
||||
'#description' => t('If checked only !items that have at least one entity associated with them will be displayed.', $args),
|
||||
'#default_value' => (isset($config['entity_count']['require_entity'])) ? $config['entity_count']['require_entity'] : FALSE,
|
||||
);
|
||||
|
||||
$form['entity_count']['settings'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Entity count settings'),
|
||||
'#collapsible' => TRUE,
|
||||
'#collapsed' => FALSE,
|
||||
'#weight' => -1,
|
||||
'#attributes' => array('class' => array('entity-count-settings')),
|
||||
);
|
||||
|
||||
$form['entity_count']['settings']['count_children'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Also count children of !item.', $args),
|
||||
'#description' => t('If checked this will result in a larger number because the children will be counted also.'),
|
||||
'#default_value' => isset($config['entity_count']['settings']['count_children']) ? $config['entity_count']['settings']['count_children'] : FALSE,
|
||||
);
|
||||
|
||||
$form['entity_count']['settings']['entity_types'] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => t('Select entities that should be counted.'),
|
||||
'#description' => t('Select entity type or one of it\'s bundles that should be counted'),
|
||||
);
|
||||
|
||||
$entity_info = entity_get_info();
|
||||
foreach ($entity_info as $entity => $entity_info) {
|
||||
if (!empty($entity_info['bundles']) && $entity_info['fieldable'] === TRUE) {
|
||||
$options = array();
|
||||
$default_values = array();
|
||||
|
||||
$form['entity_count']['settings']['entity_types'][$entity] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => check_plain($entity_info['label']),
|
||||
'#collapsible' => TRUE,
|
||||
'#collapsed' => TRUE,
|
||||
);
|
||||
|
||||
foreach ($entity_info['bundles'] as $bundle => $bundle_info) {
|
||||
$options[$bundle] = check_plain($bundle_info['label']);
|
||||
$default_values[$entity][$bundle] = isset($config['entity_count']['settings']['entity_types'][$entity]['count_' . $entity][$bundle]) ? $config['entity_count']['settings']['entity_types'][$entity]['count_' . $entity][$bundle] : 0;
|
||||
}
|
||||
|
||||
$form['entity_count']['settings']['entity_types'][$entity]['count_' . $entity] = array(
|
||||
'#type' => 'checkboxes',
|
||||
'#options' => $options,
|
||||
'#default_value' => $default_values[$entity],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit callback for the hierarchical_select_common_config_form form.
|
||||
*/
|
||||
function hierarchical_select_common_config_form_submit($form, &$form_state) {
|
||||
$config = _hierarchical_select_get_form_item_by_parents($form_state['values'], $form['#hs_common_config_form_parents']);
|
||||
|
||||
// Don't include the value of the live preview in the config.
|
||||
unset($config['live_preview']);
|
||||
|
||||
hierarchical_select_common_config_set($config['config_id'], $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the form element of a form that has a certain lineage of parents.
|
||||
*
|
||||
* @param $form
|
||||
* A structured array for use in the Forms API.
|
||||
* @param $parents
|
||||
* An array of parent form element names.
|
||||
* @return
|
||||
* The form element that has the specified lineage of parents.
|
||||
*/
|
||||
function _hierarchical_select_get_form_item_by_parents($form, $parents) {
|
||||
if (count($parents)) {
|
||||
$parent = array_shift($parents);
|
||||
return _hierarchical_select_get_form_item_by_parents($form[$parent], $parents);
|
||||
}
|
||||
else {
|
||||
return $form;
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
|
||||
.hierarchical-select-config-form .live-preview {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 25em;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.hierarchical-select-config-form fieldset {
|
||||
clear: right;
|
||||
}
|
@@ -0,0 +1,148 @@
|
||||
|
||||
Drupal.HierarchicalSelectConfigForm = {};
|
||||
|
||||
(function ($, cfg) {
|
||||
|
||||
cfg.context = function(configId) {
|
||||
if (configId === undefined) {
|
||||
return $('.hierarchical-select-config-form > *').not('.live-preview');
|
||||
}
|
||||
else {
|
||||
return $('#hierarchical-select-config-form-'+ configId + ' > *').not('.live-preview');
|
||||
}
|
||||
};
|
||||
|
||||
cfg.levelLabels = function(configId) {
|
||||
var $status = $('.level-labels-status', cfg.context(configId));
|
||||
var $enforceDeepest = $('.enforce-deepest input', cfg.context(configId));
|
||||
|
||||
var showHide = function(speed) {
|
||||
$affected = $('.level-labels-settings', cfg.context(configId));
|
||||
if (!$status.is(':checked')) {
|
||||
$affected.hide(speed);
|
||||
}
|
||||
else {
|
||||
// For showing/hiding rows, I'm relying on setting the style
|
||||
// "display: none" and removing it again. jQuery's show()/hide() leave
|
||||
// "display: block" behind and are thereby messing up the table layout.
|
||||
if ($enforceDeepest.slice(1, 2).is(':checked')) {
|
||||
$affected.find('tr').removeAttr('style');
|
||||
}
|
||||
else {
|
||||
// We need to take special measures if sticky headers are enabled, so
|
||||
// handle the show/hide separately when it's enabled.
|
||||
if ($affected.find('table.sticky-header').length == 0) {
|
||||
$affected.find('tr').slice(0, 2).removeAttr('style'); // Show header tr and root level tr.
|
||||
$affected.find('tr').slice(2).attr('style', 'display: none'); // Hide all other tr's.
|
||||
}
|
||||
else {
|
||||
$affected.find('table').show(speed); // Show both tables (the one with the sticky headers and the one with the actual content).
|
||||
$affected.find('table').slice(1).find('tr').slice(2).attr('style', 'display: none'); // Show all tr's after the header tr and root level tr of the 2nd table (the one with the actual content).
|
||||
}
|
||||
}
|
||||
|
||||
// If $status was unchecked previously, the entire div would have been
|
||||
// hidden!
|
||||
if ($affected.css('display') == 'none') {
|
||||
$affected.show(speed);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$status.click(function() { showHide(200); });
|
||||
$enforceDeepest.click(function() { showHide(200); });
|
||||
showHide(0);
|
||||
};
|
||||
|
||||
cfg.dropbox = function(configId) {
|
||||
var $status = $('.dropbox-status', cfg.context(configId));
|
||||
|
||||
var showHide = function(speed) {
|
||||
var $affected = $('.dropbox-title, .dropbox-limit, .dropbox-reset-hs', cfg.context(configId)).parent();
|
||||
if ($status.is(':checked')) {
|
||||
$affected.show(speed);
|
||||
}
|
||||
else {
|
||||
$affected.hide(speed);
|
||||
}
|
||||
};
|
||||
|
||||
$status.click(function() { showHide(200); });
|
||||
showHide(0);
|
||||
};
|
||||
|
||||
cfg.editability = function(configId) {
|
||||
var $status = $('.editability-status', cfg.context(configId));
|
||||
var $allowNewLevels = $('.editability-allow-new-levels', cfg.context(configId));
|
||||
|
||||
var showHide = function(speed) {
|
||||
var $affected = $('.editability-per-level-settings, .form-item:has(.editability-allow-new-levels)', cfg.context(configId));
|
||||
var $maxLevels = $('.form-item:has(.editability-max-levels)', cfg.context(configId));
|
||||
if ($status.is(':checked')) {
|
||||
if ($allowNewLevels.is(':checked')) {
|
||||
$affected.add($maxLevels).show(speed);
|
||||
}
|
||||
else {
|
||||
$affected.show(speed);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$affected.add($maxLevels).hide(speed);
|
||||
}
|
||||
};
|
||||
|
||||
var showHideMaxLevels = function(speed) {
|
||||
$affected = $('.editability-max-levels', cfg.context(configId)).parent();
|
||||
if ($allowNewLevels.is(':checked')) {
|
||||
$affected.show(speed);
|
||||
}
|
||||
else {
|
||||
$affected.hide(speed);
|
||||
}
|
||||
};
|
||||
|
||||
$status.click(function() { showHide(200); });
|
||||
$allowNewLevels.click(function() { showHideMaxLevels(200); });
|
||||
showHideMaxLevels(0);
|
||||
showHide(0);
|
||||
};
|
||||
|
||||
cfg.entityCount = function(configId) {
|
||||
var $status = $('.entity-count-enabled', cfg.context(configId));
|
||||
|
||||
var showHide = function(speed) {
|
||||
var $affected = $('.entity-count-settings', cfg.context(configId));
|
||||
if ($status.is(':checked')) {
|
||||
$affected.show(speed);
|
||||
}
|
||||
else {
|
||||
$affected.hide(speed);
|
||||
}
|
||||
};
|
||||
|
||||
$status.click(function() { showHide(200); });
|
||||
showHide(0);
|
||||
};
|
||||
|
||||
cfg.livePreview = function(configId) {
|
||||
// React on changes to any input, except the ones in the live preview.
|
||||
$updateLivePreview = $('input', cfg.context(configId))
|
||||
.filter(':not(.create-new-item-input):not(.create-new-item-create):not(.create-new-item-cancel)')
|
||||
.change(function() {
|
||||
// TODO: Do an AJAX submit of the entire form.
|
||||
});
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
for (var id in Drupal.settings.HierarchicalSelect.configForm) {
|
||||
var configId = Drupal.settings.HierarchicalSelect.configForm.id;
|
||||
|
||||
cfg.levelLabels(configId);
|
||||
cfg.dropbox(configId);
|
||||
cfg.editability(configId);
|
||||
cfg.entityCount(configId);
|
||||
//cfg.livePreview(configId);
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery, Drupal.HierarchicalSelectConfigForm);
|
@@ -0,0 +1,413 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* All theme functions for the Hierarchical Select module.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup themeable
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return a themed Hierarchical Select form element.
|
||||
*
|
||||
* @param array $variables
|
||||
* An associative array containing the properties of the element.
|
||||
* Properties used: title, description, id, required
|
||||
*
|
||||
* @return string
|
||||
* A string representing the form element.
|
||||
*
|
||||
* @ingroup themeable
|
||||
*/
|
||||
function theme_hierarchical_select_form_element($variables) {
|
||||
$element = $variables['element'];
|
||||
$value = $variables['value'];
|
||||
|
||||
$output = '<div class="form-item hierarchical-select-wrapper-wrapper"';
|
||||
if (!empty($element['#id'])) {
|
||||
$output .= ' id="' . $element['#id'] . '-wrapper"';
|
||||
}
|
||||
$output .= ">\n";
|
||||
$required = !empty($element['#required']) ? '<span class="form-required" title="' . t('This field is required.') . '">*</span>' : '';
|
||||
|
||||
if (!empty($element['#title'])) {
|
||||
$title = $element['#title'];
|
||||
if (!empty($element['#id'])) {
|
||||
$output .= ' <label for="' . $element['#id'] . '">' . t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) . "</label>\n";
|
||||
}
|
||||
else {
|
||||
$output .= ' <label>' . t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) . "</label>\n";
|
||||
}
|
||||
}
|
||||
|
||||
$output .= " $value\n";
|
||||
|
||||
if (!empty($element['#description'])) {
|
||||
$output .= ' <div class="description">' . $element['#description'] . "</div>\n";
|
||||
}
|
||||
|
||||
$output .= "</div>\n";
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a hierarchical select.
|
||||
*
|
||||
* @param array $variables
|
||||
* An associative array containing the properties of the element.
|
||||
* @return string
|
||||
* A themed HTML string representing the form element.
|
||||
*/
|
||||
function theme_hierarchical_select($variables) {
|
||||
$element = $variables['element'];
|
||||
$output = '';
|
||||
|
||||
// Update $element['#attributes']['class'].
|
||||
if (!isset($element['#attributes']['class'])) {
|
||||
$element['#attributes']['class'] = array();
|
||||
}
|
||||
$hsid = $element['hsid']['#value'];
|
||||
$level_labels_style = variable_get('hierarchical_select_level_labels_style', 'none');
|
||||
$classes = array(
|
||||
'hierarchical-select-wrapper',
|
||||
"hierarchical-select-level-labels-style-$level_labels_style",
|
||||
// Classes that make it possible to override the styling of specific
|
||||
// instances of Hierarchical Select, based on either the ID of the form
|
||||
// element or the config that it uses.
|
||||
'hierarchical-select-wrapper-for-name-' . $element['#id'],
|
||||
(isset($element['#config']['config_id'])) ? 'hierarchical-select-wrapper-for-config-' . $element['#config']['config_id'] : NULL,
|
||||
);
|
||||
$element['#attributes']['class'] = array_merge($element['#attributes']['class'], $classes);
|
||||
$element['#attributes']['id'] = "hierarchical-select-$hsid-wrapper";
|
||||
$element['#id'] = "hierarchical-select-$hsid-wrapper"; // This ensures the label's for attribute is correct.
|
||||
|
||||
return '<div ' . drupal_attributes($element['#attributes']) . '>' . drupal_render_children($element) . '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the container for all selects in the hierarchical select.
|
||||
*
|
||||
* @param array $variables
|
||||
* An associative array containing the properties of the element.
|
||||
* @return string
|
||||
* A themed HTML string representing the form element.
|
||||
*/
|
||||
function theme_hierarchical_select_selects_container($variables) {
|
||||
$element = $variables['element'];
|
||||
$output = '';
|
||||
$output .= '<div class="hierarchical-select clearfix">';
|
||||
$output .= drupal_render_children($element);
|
||||
$output .= '</div>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a select in the .hierarchial-select div: prevent it from being
|
||||
* wrapped in a div. This simplifies the CSS and JS code.
|
||||
*
|
||||
* @param array $variables
|
||||
* An associative array containing the properties of the element.
|
||||
* @return string
|
||||
* A themed HTML string representing the form element.
|
||||
*/
|
||||
function theme_hierarchical_select_select($variables) {
|
||||
$element = $variables['element'];
|
||||
element_set_attributes($element, array('id', 'name', 'size'));
|
||||
_form_set_class($element, array('form-select'));
|
||||
|
||||
return '<select' . drupal_attributes($element['#attributes']) . '>' . _hierarchical_select_options($element) . '</select>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Format an item separator (for use in a lineage).
|
||||
*/
|
||||
function theme_hierarchical_select_item_separator($variables) {
|
||||
$output = '';
|
||||
$output .= '<span class="hierarchical-select-item-separator">';
|
||||
$output .= '›';
|
||||
$output .= '</span>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a special option in a Hierarchical Select select. For example the
|
||||
* "none" option or the "create new item" option. This theme function allows
|
||||
* you to change how a special option is indicated textually.
|
||||
*
|
||||
* @param array $variables
|
||||
* A special option.
|
||||
* @return string
|
||||
* A textually indicated special option.
|
||||
*/
|
||||
function theme_hierarchical_select_special_option($variables) {
|
||||
$option = $variables['option'];
|
||||
return '<' . $option . '>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Forms API theming callback for the dropbox. Renders the dropbox as a table.
|
||||
*
|
||||
* @param array $variables
|
||||
* An element for which the #theme property was set to this function.
|
||||
* @return string
|
||||
* A themed HTML string.
|
||||
*/
|
||||
function theme_hierarchical_select_dropbox_table($variables) {
|
||||
$element = $variables['element'];
|
||||
$output = '';
|
||||
|
||||
$class = 'dropbox';
|
||||
if (form_get_error($element) === '') {
|
||||
$class .= ' error';
|
||||
}
|
||||
|
||||
$title = $element['title']['#value'];
|
||||
$separator = $element['separator']['#value'];
|
||||
$is_empty = $element['is_empty']['#value'];
|
||||
|
||||
$separator_html = '<span class="hierarchical-select-item-separator">' . $separator . '</span>';
|
||||
|
||||
$output .= '<div class="' . $class . '">';
|
||||
$output .= '<table>';
|
||||
$output .= '<caption class="dropbox-title">' . $title . '</caption>';
|
||||
$output .= '<tbody>';
|
||||
|
||||
if (!$is_empty) {
|
||||
// Each lineage in the dropbox corresponds to an entry in the dropbox table.
|
||||
$lineage_count = count(element_children($element['lineages']));
|
||||
for ($x = 0; $x < $lineage_count; $x++) {
|
||||
$db_entry = $element['lineages']["lineage-$x"];
|
||||
$zebra = $db_entry['#zebra'];
|
||||
$first = $db_entry['#first'];
|
||||
$last = $db_entry['#last'];
|
||||
// The deepest level is the number of child levels minus one. This "one"
|
||||
// is the element for the "Remove" checkbox.
|
||||
$deepest_level = count(element_children($db_entry)) - 1;
|
||||
|
||||
$output .= '<tr class="dropbox-entry ' . $first . ' ' . $last . ' ' . $zebra . '">';
|
||||
$output .= '<td>';
|
||||
// Each item in a lineage is separated by the separator string.
|
||||
for ($depth = 0; $depth < $deepest_level; $depth++) {
|
||||
$output .= drupal_render($db_entry[$depth]);
|
||||
|
||||
if ($depth < $deepest_level - 1) {
|
||||
$output .= $separator_html;
|
||||
}
|
||||
}
|
||||
$output .= '</td>';
|
||||
$output .= '<td class="dropbox-remove">' . drupal_render($db_entry['remove']) . '</td>';
|
||||
$output .= '</tr>';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$output .= '<tr class="dropbox-entry first last dropbox-is-empty"><td>';
|
||||
$output .= t('Nothing has been selected.');
|
||||
$output .= '</td></tr>';
|
||||
}
|
||||
|
||||
$output .= '</tbody>';
|
||||
$output .= '</table>';
|
||||
$output .= '</div>';
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Themeing function to render the level_labels settings as a table.
|
||||
*/
|
||||
// TODO: rename $form to $element for consistency (and update hook_theme() after that), make the comment consistent.
|
||||
/**
|
||||
* @todo Please document this function.
|
||||
* @see http://drupal.org/node/1354
|
||||
*/
|
||||
function theme_hierarchical_select_common_config_form_level_labels($variables) {
|
||||
$form = $variables['form'];
|
||||
// Recover the stored strings.
|
||||
$strings = $form['#strings'];
|
||||
|
||||
$output = '';
|
||||
$header = array(t('Level'), t('Label'));
|
||||
$rows = array();
|
||||
|
||||
$output .= drupal_render($form['status']);
|
||||
|
||||
$output .= '<div class="level-labels-settings">';
|
||||
if (isset($form['labels']) && count(element_children($form['labels']))) {
|
||||
foreach (element_children($form['labels']) as $depth) {
|
||||
$row = array();
|
||||
$row[]['data'] = ($depth == 0) ? t('Root level') : t('Sublevel !depth', array('!depth' => $depth));
|
||||
$row[]['data'] = drupal_render($form['labels'][$depth]);
|
||||
$rows[] = $row;
|
||||
}
|
||||
|
||||
// Render the table.
|
||||
$output .= theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('style' => 'width: auto;')));
|
||||
}
|
||||
else {
|
||||
// No levels exist yet in the hierarchy!
|
||||
$output .= '<p><strong>';
|
||||
$output .= t('There are no levels yet in this !hierarchy!', array('!hierarchy' => $strings['hierarchy']));
|
||||
$output .= '</strong></p>';
|
||||
}
|
||||
$output .= '</div>';
|
||||
|
||||
// Render the remaining form items.
|
||||
$output .= drupal_render_children($form);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Themeing function to render the per-level editability settings as a table,
|
||||
* (these are the item_types and allowed_levels settings).
|
||||
*/
|
||||
// TODO: rename $form to $element for consistency (and update hook_theme() after that), make the comment consistent.
|
||||
/**
|
||||
* @todo Please document this function.
|
||||
* @see http://drupal.org/node/1354
|
||||
*/
|
||||
function theme_hierarchical_select_common_config_form_editability($variables) {
|
||||
$form = $variables['form'];
|
||||
// Recover the stored strings.
|
||||
$strings = $form['#strings'];
|
||||
|
||||
$output = '';
|
||||
$header = array(t('Level'), t('Allow'), t('!item_type', array('!item_type' => drupal_ucfirst($strings['item_type']))));
|
||||
$rows = array();
|
||||
|
||||
$output .= drupal_render($form['status']);
|
||||
|
||||
$output .= '<div class="editability-per-level-settings">';
|
||||
if (isset($form['item_types']) && count(element_children($form['item_types']))) {
|
||||
foreach (element_children($form['item_types']) as $depth) {
|
||||
$row = array();
|
||||
$row[]['data'] = ($depth == 0) ? t('Root level') : t('Sublevel !depth', array('!depth' => $depth));
|
||||
$row[]['data'] = drupal_render($form['allowed_levels'][$depth]);
|
||||
$row[]['data'] = drupal_render($form['item_types'][$depth]);
|
||||
$rows[] = $row;
|
||||
}
|
||||
|
||||
// Render the table and description.
|
||||
$output .= theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('style' => 'width: auto;'), 'caption' => '<em>' . t('Per-level settings for creating new !items.', array('!items' => $strings['items']))));
|
||||
$output .= '<div class="description">';
|
||||
$output .= t(
|
||||
'The %item_type you enter for each level is what will be used in
|
||||
each level to replace a "<create new item>" option with a
|
||||
"<create new %item_type>" option, which is often more
|
||||
intuitive.',
|
||||
array(
|
||||
'%item_type' => $strings['item_type'],
|
||||
)
|
||||
);
|
||||
$output .= '</div>';
|
||||
}
|
||||
else {
|
||||
// No levels exist yet in the hierarchy!
|
||||
$output .= '<p><strong>';
|
||||
$output .= t('There are no levels yet in this !hierarchy!', array('!hierarchy' => $strings['hierarchy']));
|
||||
$output .= '</strong></p>';
|
||||
}
|
||||
$output .= '</div>';
|
||||
|
||||
// Render the remaining form items.
|
||||
$output .= drupal_render_children($form);
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Themeing function to render a selection (of items) according to a given
|
||||
* Hierarchical Select configuration as one or more lineages.
|
||||
*
|
||||
* @param $selection
|
||||
* A selection of items of a hierarchy.
|
||||
* @param $config
|
||||
* A config array with at least the following settings:
|
||||
* - module
|
||||
* - save_lineage
|
||||
* - params
|
||||
*/
|
||||
function theme_hierarchical_select_selection_as_lineages($variables) {
|
||||
$selection = $variables['selection'];
|
||||
$config = $variables['config'];
|
||||
$output = '';
|
||||
|
||||
$selection = (!is_array($selection)) ? array($selection) : $selection;
|
||||
|
||||
// Generate a dropbox out of the selection. This will automatically
|
||||
// calculate all lineages for us.
|
||||
$selection = array_keys($selection);
|
||||
$dropbox = _hierarchical_select_dropbox_generate($config, $selection);
|
||||
|
||||
// Actual formatting.
|
||||
foreach ($dropbox->lineages as $id => $lineage) {
|
||||
if ($id > 0) {
|
||||
$output .= '<br />';
|
||||
}
|
||||
|
||||
$items = array();
|
||||
foreach ($lineage as $level => $item) {
|
||||
$items[] = $item['label'];
|
||||
}
|
||||
$output .= implode('<span class="hierarchical-select-item-separator">›</span>', $items);
|
||||
}
|
||||
|
||||
// Add the CSS.
|
||||
drupal_add_css(drupal_get_path('module', 'hierarchical_select') . '/hierarchical_select.css');
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "ingroup themeable".
|
||||
*/
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Private functions.
|
||||
|
||||
/**
|
||||
* This is an altered clone of form_select_options(). The reason: I need to be
|
||||
* able to set a class on an option element if it contains a level label, to
|
||||
* allow for level label styles.
|
||||
* TODO: rename to _hierarchical_select_select_options().
|
||||
*/
|
||||
function _hierarchical_select_options($element) {
|
||||
if (!isset($choices)) {
|
||||
$choices = $element['#options'];
|
||||
}
|
||||
// array_key_exists() accommodates the rare event where $element['#value'] is NULL.
|
||||
// isset() fails in this situation.
|
||||
$value_valid = isset($element['#value']) || array_key_exists('#value', $element);
|
||||
$value_is_array = isset($element['#value']) && is_array($element['#value']);
|
||||
$options = '';
|
||||
foreach ($choices as $key => $choice) {
|
||||
$key = (string) $key;
|
||||
if ($value_valid && (!$value_is_array && (string) $element['#value'] === $key || ($value_is_array && in_array($key, $element['#value'])))) {
|
||||
$selected = ' selected="selected"';
|
||||
}
|
||||
else {
|
||||
$selected = '';
|
||||
}
|
||||
|
||||
// If an option DOES NOT have child info, then it's a special option:
|
||||
// - label_\d+ (level label)
|
||||
// - none ("<none>")
|
||||
// - create_new_item ("<create new item>")
|
||||
// Only when it's a level label, we have to add a class to this option.
|
||||
if (!isset($element['#childinfo'][$key])) {
|
||||
$class = (preg_match('/label_\d+/', $key)) ? ' level-label' : '';
|
||||
}
|
||||
else {
|
||||
$class = ($element['#childinfo'][$key] == 0) ? 'has-no-children' : 'has-children';
|
||||
}
|
||||
|
||||
$options .= '<option value="' . check_plain($key) . '" class="' . $class . '"' . $selected . '>' . check_plain($choice) . '</option>';
|
||||
}
|
||||
return $options;
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Make Hierarchical Select work in Views' exposed filters form.
|
||||
*
|
||||
* Views' exposed filters form is a GET form, but since Hierarchical Select
|
||||
* really is a combination of various form items, this will result in a very
|
||||
* ugly and unnecessarily long GET URL, which also breaks the exposed filters.
|
||||
* This piece of JavaScript is a necessity to make it work again, but it will
|
||||
* of course only work when JavaScript is enabled!
|
||||
*/
|
||||
|
||||
|
||||
if (Drupal.jsEnabled) {
|
||||
$(document).ready(function(){
|
||||
$('.view-filters form').submit(function() {
|
||||
// Remove the Hierarchical Select form build id and the form id, to
|
||||
// prevent them from ending up in the GET URL.
|
||||
$('#edit-hs-form-build-id').remove();
|
||||
|
||||
// Prepare the hierarchical select form elements that are used as
|
||||
// exposed filters for a GET submit.
|
||||
$('.view-filters form')
|
||||
.find('.hierarchical-select-wrapper')
|
||||
.trigger('prepare-GET-submit');
|
||||
});
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user