/** * Pre-processes variables for the "bootstrap_panel" theme hook. * * See template for list of available variables. * * @see bootstrap-panel.tpl.php * * @ingroup theme_preprocess */ function bootstrap_preprocess_bootstrap_panel(&$variables) { $element =& $variables['element']; // Set the element's attributes. element_set_attributes($element, array('id')); // Retrieve the attributes for the element. $attributes =& _bootstrap_get_attributes($element); // Add panel and panel-default classes. $attributes['class'][] = 'panel'; $attributes['class'][] = 'panel-default'; // states.js requires form-wrapper on fieldset to work properly. $attributes['class'][] = 'form-wrapper'; // Handle collapsible panels. $variables['collapsible'] = FALSE; if (isset($element['#collapsible'])) { $variables['collapsible'] = $element['#collapsible']; } $variables['collapsed'] = FALSE; if (isset($element['#collapsed'])) { $variables['collapsed'] = $element['#collapsed']; // Remove collapsed class since we only want it to apply to the inner element if ($index = array_search('collapsed', $attributes['class'])) { unset($attributes['class'][$index]); $attributes['class'] = array_values($attributes['class']); } } // Force grouped fieldsets to not be collapsible (for vertical tabs). if (!empty($element['#group'])) { $variables['collapsible'] = FALSE; $variables['collapsed'] = FALSE; } // Collapsible elements need an ID, so generate one for the fieldset's inner element. if ($variables['collapsible']) { // Generate an ID for the outer element if necessary. if (!isset($element['#id'])) { $element['#id'] = drupal_html_id('bootstrap-panel'); } $variables['id_inner'] = drupal_html_id($element['#id'] . '-inner'); } $variables['target'] = NULL; if (isset($element['#id'])) { $attributes['id'] = $element['#id']; if (isset($variables['id_inner'])) { $variables['target'] = '#' . $variables['id_inner']; } } // Build the panel content. $variables['content'] = $element['#children']; if (isset($element['#value'])) { $variables['content'] .= $element['#value']; } // Iterate over optional variables. $keys = array('description', 'prefix', 'suffix', 'title'); foreach ($keys as $key) { $variables[$key] = !empty($element["#{$key}"]) ? $element["#{$key}"] : FALSE; } // Add the attributes. $variables['attributes'] = $attributes; }
/** * Returns HTML for a form element label and required marker. * * Form element labels include the #title and a #required marker. The label is * associated with the element itself by the element #id. Labels may appear * before or after elements, depending on theme_form_element() and * #title_display. * * This function will not be called for elements with no labels, depending on * #title_display. For elements that have an empty #title and are not required, * this function will output no label (''). For required elements that have an * empty #title, this will output the required marker alone within the label. * The label will use the #id to associate the marker with the field that is * required. That is especially important for screenreader users to know * which field is required. * * @param array $variables * An associative array containing: * - element: An associative array containing the properties of the element. * Properties used: #required, #title, #id, #value, #description. * * @return string * The constructed HTML. * * @see theme_form_element_label() * * @ingroup theme_functions */ function bootstrap_form_element_label(&$variables) { $element = $variables['element']; // Extract variables. $output = ''; $title = !empty($element['#title']) ? filter_xss_admin($element['#title']) : ''; // Only show the required marker if there is an actual title to display. if ($title && ($required = !empty($element['#required']) ? theme('form_required_marker', array('element' => $element)) : '')) { $title .= ' ' . $required; } $display = isset($element['#title_display']) ? $element['#title_display'] : 'before'; $type = !empty($element['#type']) ? $element['#type'] : FALSE; $checkbox = $type && $type === 'checkbox'; $radio = $type && $type === 'radio'; // Immediately return if the element is not a checkbox or radio and there is // no label to be rendered. if (!$checkbox && !$radio && ($display === 'none' || !$title)) { return ''; } // Retrieve the label attributes array. $attributes =& _bootstrap_get_attributes($element, 'label_attributes'); // Add Bootstrap label class. $attributes['class'][] = 'control-label'; // Add the necessary 'for' attribute if the element ID exists. if (!empty($element['#id'])) { $attributes['for'] = $element['#id']; } // Checkboxes and radios must construct the label differently. if ($checkbox || $radio) { if ($display === 'before') { $output .= $title; } elseif ($display === 'none' || $display === 'invisible') { $output .= '<span class="element-invisible">' . $title . '</span>'; } // Inject the rendered checkbox or radio element inside the label. if (!empty($element['#children'])) { $output .= $element['#children']; } if ($display === 'after') { $output .= $title; } } else { // Show label only to screen readers to avoid disruption in visual flows. if ($display === 'invisible') { $attributes['class'][] = 'element-invisible'; } $output .= $title; } // The leading whitespace helps visually separate fields from inline labels. return ' <label' . drupal_attributes($attributes) . '>' . $output . "</label>\n"; }
/** * Returns HTML for a form element. * * Each form element is wrapped in a DIV container having the following CSS * classes: * - form-item: Generic for all form elements. * - form-type-#type: The internal element #type. * - form-item-#name: The internal form element #name (usually derived from the * $form structure and set via form_builder()). * - form-disabled: Only set if the form element is #disabled. * * In addition to the element itself, the DIV contains a label for the element * based on the optional #title_display property, and an optional #description. * * The optional #title_display property can have these values: * - before: The label is output before the element. This is the default. * The label includes the #title and the required marker, if #required. * - after: The label is output after the element. For example, this is used * for radio and checkbox #type elements as set in system_element_info(). * If the #title is empty but the field is #required, the label will * contain only the required marker. * - invisible: Labels are critical for screen readers to enable them to * properly navigate through forms but can be visually distracting. This * property hides the label for everyone except screen readers. * - attribute: Set the title attribute on the element to create a tooltip * but output no label element. This is supported only for checkboxes * and radios in form_pre_render_conditional_form_element(). It is used * where a visual label is not needed, such as a table of checkboxes where * the row and column provide the context. The tooltip will include the * title and required marker. * * If the #title property is not set, then the label and any required marker * will not be output, regardless of the #title_display or #required values. * This can be useful in cases such as the password_confirm element, which * creates children elements that have their own labels and required markers, * but the parent element should have neither. Use this carefully because a * field without an associated label can cause accessibility challenges. * * @param array $variables * An associative array containing: * - element: An associative array containing the properties of the element. * Properties used: #title, #title_display, #description, #id, #required, * #children, #type, #name. * * @return string * The constructed HTML. * * @see theme_form_element() * * @ingroup theme_functions */ function bootstrap_form_element(&$variables) { $element =& $variables['element']; $name = !empty($element['#name']) ? $element['#name'] : FALSE; $type = !empty($element['#type']) ? $element['#type'] : FALSE; $checkbox = $type && $type === 'checkbox'; $radio = $type && $type === 'radio'; // Create an attributes array for the wrapping container. if (empty($element['#wrapper_attributes'])) { $element['#wrapper_attributes'] = array(); } $wrapper_attributes =& $element['#wrapper_attributes']; // This function is invoked as theme wrapper, but the rendered form element // may not necessarily have been processed by form_builder(). $element += array('#title_display' => 'before'); // Add wrapper ID for 'item' type. if ($type && $type === 'item' && !empty($element['#markup']) && !empty($element['#id'])) { $wrapper_attributes['id'] = $element['#id']; } // Check for errors and set correct error class. if (isset($element['#parents']) && form_get_error($element) || !empty($element['#required']) && bootstrap_setting('forms_required_has_error')) { $wrapper_attributes['class'][] = 'has-error'; } // Add necessary classes to wrapper container. $wrapper_attributes['class'][] = 'form-item'; if ($name) { $wrapper_attributes['class'][] = 'form-item-' . drupal_html_class($name); } if ($type) { $wrapper_attributes['class'][] = 'form-type-' . drupal_html_class($type); } if (!empty($element['#attributes']['disabled'])) { $wrapper_attributes['class'][] = 'form-disabled'; } if (!empty($element['#autocomplete_path']) && drupal_valid_path($element['#autocomplete_path'])) { $wrapper_attributes['class'][] = 'form-autocomplete'; } // Checkboxes and radios do no receive the 'form-group' class, instead they // simply have their own classes. if ($checkbox || $radio) { $wrapper_attributes['class'][] = drupal_html_class($type); } elseif ($type && $type !== 'hidden') { $wrapper_attributes['class'][] = 'form-group'; } // Create a render array for the form element. $build = array('#theme_wrappers' => array('container__form_element'), '#attributes' => $wrapper_attributes); // Render the label for the form element. $build['label'] = array('#markup' => theme('form_element_label', $variables)); // Increase the label weight if it should be displayed after the element. if ($element['#title_display'] === 'after') { $build['label']['#weight'] = 10; } // Checkboxes and radios render the input element inside the label. If the // element is neither of those, then the input element must be rendered here. if (!$checkbox && !$radio) { $prefix = isset($element['#field_prefix']) ? $element['#field_prefix'] : ''; $suffix = isset($element['#field_suffix']) ? $element['#field_suffix'] : ''; if ((!empty($prefix) || !empty($suffix)) && (!empty($element['#input_group']) || !empty($element['#input_group_button']))) { if (!empty($element['#field_prefix'])) { $prefix = '<span class="input-group-' . (!empty($element['#input_group_button']) ? 'btn' : 'addon') . '">' . $prefix . '</span>'; } if (!empty($element['#field_suffix'])) { $suffix = '<span class="input-group-' . (!empty($element['#input_group_button']) ? 'btn' : 'addon') . '">' . $suffix . '</span>'; } // Add a wrapping container around the elements. $input_group_attributes =& _bootstrap_get_attributes($element, 'input_group_attributes'); $input_group_attributes['class'][] = 'input-group'; $prefix = '<div' . drupal_attributes($input_group_attributes) . '>' . $prefix; $suffix .= '</div>'; } // Build the form element. $build['element'] = array('#markup' => $element['#children'], '#prefix' => !empty($prefix) ? $prefix : NULL, '#suffix' => !empty($suffix) ? $suffix : NULL); } // Construct the element's description markup. if (!empty($element['#description'])) { $build['description'] = array('#type' => 'container', '#attributes' => array('class' => array('help-block')), '#weight' => 20, 0 => array('#markup' => filter_xss_admin($element['#description']))); } // Render the form element build array. return drupal_render($build); }