2020-08-14 13:36:36 +02:00
/ * *
* @ file
* Provides dependent visibility for form items in CTools ' ajax forms .
*
* To your $form item definition add :
* - '#process' => array ( 'ctools_process_dependency' ) ,
* - '#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 .
* /
( function ( $ ) {
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 ;
while ( i -- ) {
if ( array [ i ] == search _term ) {
return true ;
}
}
return false ;
}
Drupal . CTools . dependent . autoAttach = function ( ) {
// Clear active bindings and triggers.
2020-10-23 13:02:00 +02:00
for ( var i in Drupal . CTools . dependent . activeTriggers ) {
2020-08-14 13:36:36 +02:00
$ ( Drupal . CTools . dependent . activeTriggers [ i ] ) . unbind ( 'change.ctools-dependent' ) ;
}
Drupal . CTools . dependent . activeTriggers = [ ] ;
Drupal . CTools . dependent . activeBindings = { } ;
Drupal . CTools . dependent . bindings = { } ;
if ( ! Drupal . settings . CTools ) {
return ;
}
// Iterate through all relationships
2020-10-23 13:02:00 +02:00
for ( var id in Drupal . settings . CTools . dependent ) {
2020-08-14 13:36:36 +02:00
// Test to make sure the id even exists; this helps clean up multiple
// AJAX calls with multiple forms.
// 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
2020-10-23 13:02:00 +02:00
for ( var bind _id in Drupal . settings . CTools . dependent [ id ] . values ) {
2020-08-14 13:36:36 +02:00
// 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 ) ;
if ( $ ( trigger _id ) . attr ( 'type' ) == 'checkbox' ) {
$ ( trigger _id ) . siblings ( 'label' ) . addClass ( 'hidden-options' ) ;
}
var getValue = function ( item , trigger ) {
2020-10-23 13:02:00 +02:00
if ( $ ( trigger ) . length == 0 ) {
2020-08-14 13:36:36 +02:00
return null ;
}
if ( item . substring ( 0 , 6 ) == 'radio:' ) {
var val = $ ( trigger + ':checked' ) . val ( ) ;
}
else {
switch ( $ ( trigger ) . attr ( 'type' ) ) {
case 'checkbox' :
// **This check determines if using a jQuery version 1.7 or newer which requires the use of the prop function instead of the attr function when not called on an attribute
if ( $ ( ) . prop ) {
var val = $ ( trigger ) . prop ( 'checked' ) ? true : false ;
}
else {
var val = $ ( trigger ) . attr ( 'checked' ) ? true : false ;
}
if ( val ) {
$ ( trigger ) . siblings ( 'label' ) . removeClass ( 'hidden-options' ) . addClass ( 'expanded-options' ) ;
}
else {
$ ( trigger ) . siblings ( 'label' ) . removeClass ( 'expanded-options' ) . addClass ( 'hidden-options' ) ;
}
break ;
default :
var val = $ ( 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 ) ;
if ( val == null ) {
return ;
}
2020-10-23 13:02:00 +02:00
for ( var i in Drupal . CTools . dependent . bindings [ bind _id ] ) {
2020-08-14 13:36:36 +02:00
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 ( val != null && 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 ;
2020-10-23 13:02:00 +02:00
for ( var i in Drupal . CTools . dependent . activeBindings [ id ] ) {
2020-08-14 13:36:36 +02:00
len ++ ;
}
var $original = $ ( '#' + id ) ;
if ( $original . is ( 'fieldset' ) || $original . is ( 'textarea' ) ) {
continue ;
}
var object = $original . parent ( ) ;
if ( Drupal . settings . CTools . dependent [ id ] . type == 'disable' ) {
if ( Drupal . settings . CTools . dependent [ id ] . num <= len ) {
// Show if the element if criteria is matched
// **This check determines if using a jQuery version 1.7 or newer which requires the use of the prop function instead of the attr function when not called on an attribute
if ( typeof $ ( ) . prop == 'function' ) {
object . prop ( 'disabled' , false ) ;
object . addClass ( 'dependent-options' ) ;
object . children ( ) . prop ( 'disabled' , false ) ;
}
else {
object . attr ( 'disabled' , false ) ;
object . addClass ( 'dependent-options' ) ;
object . children ( ) . attr ( 'disabled' , false ) ;
}
}
else {
// Otherwise hide. Use css rather than hide() because hide()
// does not work if the item is already hidden, for example,
// in a collapsed fieldset.
// **This check determines if using a jQuery version 1.7 or newer which requires the use of the prop function instead of the attr function when not called on an attribute
if ( typeof $ ( ) . prop == 'function' ) {
object . prop ( 'disabled' , true ) ;
object . children ( ) . prop ( 'disabled' , true ) ;
}
else {
object . attr ( 'disabled' , true ) ;
object . children ( ) . attr ( 'disabled' , true ) ;
}
}
}
else {
if ( Drupal . settings . CTools . dependent [ id ] . num <= len ) {
// Show if the element if criteria is matched
object . show ( 0 ) ;
object . addClass ( 'dependent-options' ) ;
}
else {
// Otherwise hide. Use css rather than hide() because hide()
// does not work if the item is already hidden, for example,
// in a collapsed fieldset.
object . css ( 'display' , 'none' ) ;
}
}
}
}
$ ( trigger _id ) . bind ( 'change.ctools-dependent' , 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 = {
attach : 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" )
. once ( 'ctools-dependent' )
. bind ( 'change.ctools-dependent' , 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.ctools-dependent' ) ;
}
}
} ) ( jQuery ) ;