Skip to content
Snippets Groups Projects
Commit 81c195f2 authored by Earl Miles's avatar Earl Miles
Browse files

Add dependent form fields tool from Views.

parent a4ed6c2c
No related branches found
No related tags found
No related merge requests found
<?php
// $Id$
/**
* @file
* Provide dependent checkboxes that can be easily used in forms.
*
* This system will ensure that form items are invisible if the dependency is
* not met. What this means is that you set the #dependency of an item to a
* list of form ids that must be set, and the list of values that qualify.
*
* For a simple use, setting an item to be dependent upon a select box, if
* any of the listed values are selected, the item will be visible. Otherwise,
* the item will be visible.
*
* If dependent upon multiple items, all of the items must contain one of the
* acceptable values.
*
* Checkboxes don't have their own id, so you need to add one in a div
* around the checkboxes via #prefix and #suffix. You actually need to add TWO
* divs because it's the parent that gets hidden. Also be sure to retain the
* 'expand_checkboxes' in the #process array, because the views process will
* override it.
*
* For radios, because they are selected a little bit differently, instead of
* using the CSS id, use: radio:NAME where NAME is the #name of the property.
* This can be quickly found by looking at the HTML of the generated form, but
* it is usually derived from the array which contains the item. For example,
* $form['menu']['type'] would have a name of menu[type]. This name is the same
* field that is used to determine where in $form_state['values'] you will find
* the value of the form.
*
* Usage:
*
* First, ensure this tool is loaded:
* @code { ctools_include('dependent'); }
*
* On any form item, add
* - @code '#process' => 'ctools_dependent_process' @endcode
* - @code '#dependency' => array('id-of-form-without-the-#' => array(list, of, values, that, make, this, gadget, visible)); @endcode
*/
/**
* Process callback to add dependency to form items.
*/
function ctools_dependent_process($element, $edit, &$form_state, &$form) {
if (isset($element['#dependency'])) {
if (!isset($element['#dependency_count'])) {
$element['#dependency_count'] = 1;
}
if (!empty($form_state['ajax'])) {
$form_state['js settings']['CTools']['dependent'][$element['#id']] = array('num' => $element['#dependency_count'], 'values' => $element['#dependency']);
}
else {
ctools_add_js('dependent');
$options['CTools']['dependent'][$element['#id']] = array('num' => $element['#dependency_count'], 'values' => $element['#dependency']);
drupal_add_js($options, 'setting');
}
}
return $element;
}
// $Id$
/**
* @file dependent.js
*
* Written by dmitrig01 (Dmitri Gaskin) for CTools; this provides dependent
* visibility for form items in CTools' ajax forms.
*
* To your $form item definition add:
* - '#process' => array('CTools_process_dependency'),
* - Add '#dependency' => array('id-of-form-item' => array(list, of, values, that,
make, this, item, show),
*
* Special considerations:
* - radios are harder. Because Drupal doesn't give radio groups individual ids,
* use 'radio:name-of-radio'
*
* - Checkboxes don't have their own id, so you need to add one in a div
* around the checkboxes via #prefix and #suffix. You actually need to add TWO
* divs because it's the parent that gets hidden. Also be sure to retain the
* 'expand_checkboxes' in the #process array, because the CTools process will
* override it.
*/
Drupal.CTools = Drupal.CTools || {};
Drupal.CTools.dependent = {};
Drupal.CTools.dependent.bindings = {};
Drupal.CTools.dependent.activeBindings = {};
Drupal.CTools.dependent.activeTriggers = [];
Drupal.CTools.dependent.inArray = function(array, search_term) {
var i = array.length;
if (i > 0) {
do {
if (array[i] == search_term) {
return true;
}
} while (i--);
}
return false;
}
Drupal.CTools.dependent.autoAttach = function() {
// Clear active bindings and triggers.
for (i in Drupal.CTools.dependent.activeTriggers) {
jQuery(Drupal.CTools.dependent.activeTriggers[i]).unbind('change');
}
Drupal.CTools.dependent.activeTriggers = [];
Drupal.CTools.dependent.activeBindings = {};
Drupal.CTools.dependent.bindings = {};
if (!Drupal.settings.CTools) {
return;
}
// Iterate through all relationships
for (id in Drupal.settings.CTools.dependent) {
// Drupal.CTools.dependent.activeBindings[id] is a boolean,
// whether the binding is active or not. Defaults to no.
Drupal.CTools.dependent.activeBindings[id] = 0;
// Iterate through all possible values
for(bind_id in Drupal.settings.CTools.dependent[id].values) {
// This creates a backward relationship. The bind_id is the ID
// of the element which needs to change in order for the id to hide or become shown.
// The id is the ID of the item which will be conditionally hidden or shown.
// Here we're setting the bindings for the bind
// id to be an empty array if it doesn't already have bindings to it
if (!Drupal.CTools.dependent.bindings[bind_id]) {
Drupal.CTools.dependent.bindings[bind_id] = [];
}
// Add this ID
Drupal.CTools.dependent.bindings[bind_id].push(id);
// Big long if statement.
// Drupal.settings.CTools.dependent[id].values[bind_id] holds the possible values
if (bind_id.substring(0, 6) == 'radio:') {
var trigger_id = "input[@name='" + bind_id.substring(6) + "']";
}
else {
var trigger_id = '#' + bind_id;
}
Drupal.CTools.dependent.activeTriggers.push(trigger_id);
var getValue = function(item, trigger) {
if (item.substring(0, 6) == 'radio:') {
var val = jQuery(trigger + ':checked').val();
}
else {
switch (jQuery(trigger).attr('type')) {
case 'checkbox':
var val = jQuery(trigger).attr('checked') || 0;
break;
default:
var val = jQuery(trigger).val();
}
}
return val;
}
var setChangeTrigger = function(trigger_id, bind_id) {
// Triggered when change() is clicked.
var changeTrigger = function() {
var val = getValue(bind_id, trigger_id);
for (i in Drupal.CTools.dependent.bindings[bind_id]) {
var id = Drupal.CTools.dependent.bindings[bind_id][i];
// Fix numerous errors
if (typeof id != 'string') {
continue;
}
// This bit had to be rewritten a bit because two properties on the
// same set caused the counter to go up and up and up.
if (!Drupal.CTools.dependent.activeBindings[id]) {
Drupal.CTools.dependent.activeBindings[id] = {};
}
if (Drupal.CTools.dependent.inArray(Drupal.settings.CTools.dependent[id].values[bind_id], val)) {
Drupal.CTools.dependent.activeBindings[id][bind_id] = 'bind';
}
else {
delete Drupal.CTools.dependent.activeBindings[id][bind_id];
}
var len = 0;
for (i in Drupal.CTools.dependent.activeBindings[id]) {
len++;
}
var object = jQuery('#' + id + '-wrapper');
if (!object.size()) {
object = jQuery('#' + id).parent();
}
if (Drupal.settings.CTools.dependent[id].num <= len) {
// Show if the element if criteria is matched
object.show(0);
}
else {
// Otherwise hide
object.hide(0);
}
}
}
jQuery(trigger_id).change(function() {
// Trigger the internal change function
// the attr('id') is used because closures are more confusing
changeTrigger(trigger_id, bind_id);
});
// Trigger initial reaction
changeTrigger(trigger_id, bind_id);
}
setChangeTrigger(trigger_id, bind_id);
}
}
}
Drupal.behaviors.CToolsDependent = function (context) {
Drupal.CTools.dependent.autoAttach();
// Really large sets of fields are too slow with the above method, so this
// is a sort of hacked one that's faster but much less flexible.
$("select.ctools-master-dependent:not(.ctools-processed)")
.addClass('ctools-processed')
.change(function() {
var val = $(this).val();
if (val == 'all') {
$('.ctools-dependent-all').show(0);
}
else {
$('.ctools-dependent-all').hide(0);
$('.ctools-dependent-' + val).show(0);
}
})
.trigger('change');
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment