If I have a parent category called, say "music", and two sub-categories (say, R&B and Pop), I would naturally always want "music" to be selected if either sub-category is selected. I don't want a user to be able to unselect music since that defeats the whole advantage to the hierarchical input (to be honest, this would be better managed at the server level anyway but the UI should conform to expectations).

One can add a setting in the widget's form that can let the developer decide the default action - that is whether custom-unchecked boxes can prevent an unselect all.

For example, a class name such as "term-reference-tree-unselect-parents-unselect-partial-children" (too long :)) can be added in addition to "term-reference-tree-cascading-selection" so that in our current javascript we can change remaining checkboxes in the cases where this extra class exists e.g.

        $(this).find('.form-checkbox').change(function(event) {
          var event_target = $(event.target);
          var control_id = event_target.attr('id');
          var children = event_target.parent().next().children().children('div.form-type-checkbox').children('input[id^="' + control_id + '-children"]');
          if(event_target.attr('checked')) {
            //Checkbox checked - check children if none were checked.
            if(!$(children).filter(':checked').length) {
              $(children).click().trigger('change');
            }
            
            if(tree.hasClass('term-reference-tree-unselect-parents-unselect-partial-children')) {
							$(children).not(':checked').click().trigger('change');
						}            
          }
          else {
            //Checkbox unchecked. Uncheck children if all were checked.
            if(!$(children).not(':checked').length) {
              $(children).click().trigger('change');
            }
            
            if(tree.hasClass('term-reference-tree-unselect-parents-unselect-partial-children')) {
							$(children).filter(':checked').click().trigger('change');
						}
          }

        });

In term_reference_tree.widget.inc we'd have to add the new setting into several places.

i.e.

'unselect_parents_unselect_partial_children' => 0

into the settings array in term_reference_tree_field_widget_info().

    $form['unselect_parents_unselect_partial_children'] = array(
      '#type' => 'checkbox',
      '#title' => t('Unselecting parent unselect children unconditionally'),
      '#description' => t('On parent unselection, deselect ALL children even if some children have already been manually unselected'),
      '#default_value' => $settings['unselect_parents_unselect_partial_children'],
      '#return_value' => 1,
    );

in term_reference_tree_field_widget_settings_form().

  if (array_key_exists('#unselect_parents_unselect_partial_children', $element) && $element['#unselect_parents_unselect_partial_children']) {
    $attributes['class'][] = "term-reference-tree-unselect-parents-unselect-partial-children";
  }

in theme_checkbox_tree().

$element['#unselect_parents_unselect_partial_children'] = $settings['unselect_parents_unselect_partial_children'];

in the switch in term_reference_tree_field_widget_form().

Comments

alex_optim’s picture

Status: Active » Fixed

This behaviour is only observed when all the child elements are selected. And that's right. When one of the children is not selected, this rule does not apply. Therefore, I see no reason to change the logic of work. Because everything is working right now.

alex_optim’s picture

Status: Fixed » Closed (works as designed)
alex_optim’s picture