/** * Preprocess input. */ function bootstrap_preprocess_input(&$variables) { $element =& $variables['element']; $attributes = new Attribute($variables['attributes']); // Set the element's attributes. \Drupal\Core\Render\Element::setAttributes($element, array('id', 'name', 'value', 'type')); // Handle button inputs. if (_bootstrap_is_button($element)) { $variables['attributes']['class'][] = 'btn'; _bootstrap_colorize_button($variables); _bootstrap_iconize_button($element); // Add button size, if necessary. if ($size = bootstrap_setting('button_size')) { $variables['attributes']['class'][] = $size; } // Add in the button type class. $variables['attributes']['class'][] = 'form-' . $element['#type']; $variables['label'] = $element['#value']; } _bootstrap_prerender_input($variables); // Autocomplete fields. if (!empty($element['#autocomplete_route_name']) && Drupal::PathValidator($element['#autocomplete_route_name'])) { $variables['autocomplete'] = TRUE; // Attributes for hidden input field. $autocomplete_attributes = new Attribute(); $autocomplete_attributes['type'] = 'hidden'; $autocomplete_attributes['id'] = $element['#attributes']['id'] . '-autocomplete'; $autocomplete_attributes['value'] = Drupal::Url($element['#autocomplete_route_name'], $element['#autocomplete_route_parameters']); $autocomplete_attributes['disabled'] = 'disabled'; $autocomplete_attributes['class'] = 'autocomplete'; // Uses icon for autocomplete "throbber". $icon = _bootstrap_icon('refresh'); // Fallback to using core's throbber. if (empty($icon)) { $icon = array('#type' => 'container', '#attributes' => array('class' => array('ajax-progress', 'ajax-progress-throbber', 'invisible')), 'throbber' => array('#type' => 'html_tag', '#tag' => 'div', '#attributes' => array('class' => array('throbber')))); } $variables['autocomplete_icon'] = $icon; $variables['autocomplete_attributes'] = $autocomplete_attributes; } // Search fields. if ($element['#type'] == 'search') { $attributes['placeholder'] = t('Search'); $attributes['data-original-title'] = t('Enter the terms you wish to search for.'); } // Additional Twig variables. $variables['icon'] = $element['#icon']; $variables['element'] = $element; }
/** * Overrides theme_textfield(). */ function bootstrap_sst_textfield($variables) { $element = $variables['element']; $element['#attributes']['type'] = 'text'; element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength')); _form_set_class($element, array('form-text')); $output = '<input' . drupal_attributes($element['#attributes']) . ' />'; $extra = ''; if ($element['#autocomplete_path'] && drupal_valid_path($element['#autocomplete_path'])) { drupal_add_library('system', 'drupal.autocomplete'); $element['#attributes']['class'][] = 'form-autocomplete'; $attributes = array(); $attributes['type'] = 'hidden'; $attributes['id'] = $element['#attributes']['id'] . '-autocomplete'; $attributes['value'] = url($element['#autocomplete_path'], array('absolute' => TRUE)); $attributes['disabled'] = 'disabled'; $attributes['class'][] = 'autocomplete'; // Uses icon for autocomplete "throbber". if ($icon = _bootstrap_icon('refresh')) { $output = '<div class="input-group">' . $output . '<span class="input-group-addon">' . $icon . '</span></div>'; } else { $output = '<div class="input-group">' . $output . '<span class="input-group-addon">'; // The throbber's background image must be set here because sites may not // be at the root of the domain (ie: /) and this value cannot be set via // CSS. $output .= '<span class="autocomplete-throbber" style="background-image:url(' . url('misc/throbber.gif') . ')"></span>'; $output .= '</span></div>'; } $extra = '<input' . drupal_attributes($attributes) . ' />'; } return $output . $extra; }
/** * Implements hook_preprocess_region(). */ function teca3_preprocess_region(&$variables) { global $theme; static $wells; if (!isset($wells)) { foreach (system_region_list($theme) as $name => $title) { $wells[$name] = theme_get_setting('bootstrap_region_well-' . $name); } } switch ($variables['region']) { // @todo is this actually used properly? case 'content': $variables['theme_hook_suggestions'][] = 'region__no_wrapper'; break; case 'help': $variables['content'] = _bootstrap_icon('question-sign') . $variables['content']; $variables['classes_array'][] = 'alert'; $variables['classes_array'][] = 'alert-info'; break; case 'footer': $variables['classes_array'][] = 'container'; break; } if (!empty($wells[$variables['region']])) { $variables['classes_array'][] = $wells[$variables['region']]; } }
/** * Implements hook_preprocess_region(). */ function bootstrap_preprocess_region(&$variables) { global $theme; $region = $variables['region']; $classes =& $variables['classes_array']; // Content region. if ($region === 'content') { // @todo is this actually used properly? $variables['theme_hook_suggestions'][] = 'region__no_wrapper'; } elseif ($region === 'help' && !empty($variables['content'])) { $variables['content'] = _bootstrap_icon('question-sign') . $variables['content']; $classes[] = 'alert'; $classes[] = 'alert-info'; $classes[] = 'messages'; $classes[] = 'info'; } // Support for "well" classes in regions. static $wells; if (!isset($wells)) { foreach (system_region_list($theme) as $name => $title) { $wells[$name] = bootstrap_setting('region_well-' . $name); } } if (!empty($wells[$region])) { $classes[] = $wells[$region]; } }
/** * Pre-processes variables for the "region" theme hook. * * See template for list of available variables. * * @see region.tpl.php * * @ingroup theme_preprocess */ function bootstrap_preprocess_region(&$variables) { $region = $variables['elements']['#region']; $variables['region'] = $region; $variables['content'] = $variables['elements']['#children']; $theme = \Drupal::theme()->getActiveTheme()->getName(); // Content region. if ($region === 'content') { // @todo is this actually used properly? $variables['theme_hook_suggestions'][] = 'region__no_wrapper'; } elseif ($region === 'help' && !empty($variables['content'])) { $content = $variables['content']; $variables['content'] = array('icon' => array('#markup' => _bootstrap_icon('question-sign')), 'content' => array('#markup' => $content)); $variables['attributes']['class'][] = 'alert'; $variables['attributes']['class'][] = 'alert-info'; $variables['attributes']['class'][] = 'messages'; $variables['attributes']['class'][] = 'info'; } // Support for "well" classes in regions. static $wells; if (!isset($wells)) { foreach (system_region_list($theme) as $name => $title) { $wells[$name] = bootstrap_setting('region_well-' . $name); } } if (!empty($wells[$region])) { $variables['attributes']['class'][] = $wells[$region]; } }
/** * Theme function implementation for bootstrap_search_form_wrapper. */ function subtheme_subtheme_search_form_wrapper($variables) { $output = ' <ul class="nav navbar-nav navbar-right"> <li class="expanded dropdown"> <a href="#" title data-target="#" class="dropdown-toggle nolink" data-toggle="dropdown"> <i title="glyphicon-search" class="icon glyphicon glyphicon-search" aria-hidden="true"></i> <span class="caret"></span> </a> <ul class="dropdown-menu" style="padding: 15px; min-width: 250px;"> <li class="first leaf"> <div class="row"> <div class="col-md-12">'; $output = '<div class="input-group">'; $output .= $variables['element']['#children']; $output .= '<span class="input-group-btn">'; $output .= '<button type="submit" class="btn btn-default">'; // We can be sure that the font icons exist in CDN. if (theme_get_setting('bootstrap_cdn')) { $output .= _bootstrap_icon('search'); } else { $output .= t('Search'); } $output .= '</button>'; $output .= '</span>'; $output .= '</div>'; $output .= ' </div> </div> </li> </ul> </li> </ul>'; return $output; }
/** * Returns HTML for a link to the more extensive filter tips. * * @return string * The constructed HTML. * * @see theme_filter_tips_more_info() * * @ingroup theme_functions */ function bootstrap_filter_tips_more_info() { $attributes = array('target' => '_blank', 'title' => t('Opens in new window')); if (bootstrap_setting('tooltip_enabled')) { $attributes['data-toggle'] = 'tooltip'; } return l(_bootstrap_icon('question-sign') . t('More information about text formats'), 'filter/tips', array('html' => TRUE, 'attributes' => $attributes)); }
/** * Theme function implementation for bootstrap_search_form_wrapper. */ function bootstrap_psdpt_bootstrap_search_form_wrapper($variables) { $output = '<div class="input-group">'; $output .= $variables['element']['#children']; $output .= '<span class="input-group-btn">'; $output .= '<button type="submit" class="btn btn-primary">' . _bootstrap_icon('search', t('Search')) . '</button>'; $output .= '</span>'; $output .= '</div>'; return $output; }
/** * Overrides theme_menu_tree() for book module. */ function bootstrap_menu_tree__book_toc(&$variables) { $output = '<div class="book-toc btn-group pull-right">'; $output .= ' <button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown">'; $output .= t('!icon Outline !caret', array('!icon' => _bootstrap_icon('list'), '!caret' => '<span class="caret"></span>')); $output .= '</button>'; $output .= '<ul class="dropdown-menu" role="menu">' . $variables['tree'] . '</ul>'; $output .= '</div>'; return $output; }
/** * Overrides bootstrap_bootstrap_search_form_wrapper(). * * Outputs an icon for the search form instead of text even though we're not * loading bootstrap from a CDN. (The deault function assumes we don't have the * bootstrap icons if we don't load the library from the CDN.) */ function bootstrap_ignitor_bootstrap_search_form_wrapper($variables) { $output = '<div class="input-group">'; $output .= $variables['element']['#children']; $output .= '<span class="input-group-btn">'; $output .= '<button type="submit" class="btn btn-default">'; $output .= _bootstrap_icon('search'); $output .= '</button>'; $output .= '</span>'; $output .= '</div>'; return $output; }
/** * Theme function implementation for bootstrap_search_form_wrapper. */ function bootstrap_bootstrap_search_form_wrapper($variables) { $output = '<div class="input-group">'; $output .= $variables['element']['#children']; $output .= '<span class="input-group-btn">'; $output .= '<button type="submit" class="btn btn-default">'; // We can be sure that the font icons exist in CDN. if (theme_get_setting('bootstrap_cdn')) { $output .= _bootstrap_icon('search'); } else { $output .= t('Search'); } $output .= '</button>'; $output .= '</span>'; $output .= '</div>'; return $output; }
/** * Prepares variables for file upload help text templates. * * Default template: file-upload-help.html.twig. * * @param array $variables * An associative array containing: * - description: The normal description for this field, specified by the * user. * - upload_validators: An array of upload validators as used in * $element['#upload_validators']. */ function bootstrap_preprocess_file_upload_help(&$variables) { $config = \Drupal::config('bootstrap.settings'); $upload_validators = $variables['upload_validators']; $cardinality = $variables['cardinality']; $descriptions = array(); if (isset($cardinality)) { if ($cardinality == -1) { $descriptions[] = t('Unlimited number of files can be uploaded to this field.'); } else { $descriptions[] = \Drupal::translation()->formatPlural($cardinality, 'One file only.', 'Maximum @count files.'); } } if (isset($upload_validators['file_validate_size'])) { $descriptions[] = t('@size limit.', array('@size' => format_size($upload_validators['file_validate_size'][0]))); } if (isset($upload_validators['file_validate_extensions'])) { $descriptions[] = t('Allowed types: @extensions.', array('@extensions' => $upload_validators['file_validate_extensions'][0])); } if (isset($upload_validators['file_validate_image_resolution'])) { $max = $upload_validators['file_validate_image_resolution'][0]; $min = $upload_validators['file_validate_image_resolution'][1]; if ($min && $max && $min == $max) { $descriptions[] = t('Images must be exactly <strong>@size</strong> pixels.', array('@size' => $max)); } elseif ($min && $max) { $descriptions[] = t('Images must be larger than <strong>@min</strong> pixels. Images larger than <strong>@max</strong> pixels will be resized.', array('@min' => $min, '@max' => $max)); } elseif ($min) { $descriptions[] = t('Images must be larger than <strong>@min</strong> pixels.', array('@min' => $min)); } elseif ($max) { $descriptions[] = t('Images larger than <strong>@max</strong> pixels will be resized.', array('@max' => $max)); } } // If popovers are enabled. if ($config->get('bootstrap_popover_enabled')) { $id = html::getUniqueId('upload-instructions'); $icon = _bootstrap_icon('question-sign'); $link_title = SafeMarkup::format($icon . ' ' . '@text', array('@text' => 'More information')); $variables['popover_link'] = _bootstrap_popover_link($link_title, $id, t('File requirements'), 'bottom'); $description_content = array('#theme' => 'item_list', '#items' => $descriptions); $variables['popover_content'] = _bootstrap_popover_content($id, array($description_content)); } $variables['descriptions'] = $descriptions; }
/** * Overrides theme_textfield(). */ function evolve_textfield($variables) { $element = $variables['element']; $element['#attributes']['type'] = 'text'; element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength')); _form_set_class($element, array('form-text')); $output = '<input' . drupal_attributes($element['#attributes']) . ' />'; $extra = ''; if ($element['#autocomplete_path'] && drupal_valid_path($element['#autocomplete_path'])) { drupal_add_library('system', 'drupal.autocomplete'); $element['#attributes']['class'][] = 'form-autocomplete'; $attributes = array(); $attributes['type'] = 'hidden'; $attributes['id'] = $element['#attributes']['id'] . '-autocomplete'; $attributes['value'] = url($element['#autocomplete_path'], array('absolute' => TRUE)); $attributes['disabled'] = 'disabled'; $attributes['class'][] = 'autocomplete'; $output = '<div class="input-group">' . $output . '<span class="input-group-addon">' . _bootstrap_icon('refresh') . '</span></div>'; $extra = '<input' . drupal_attributes($attributes) . ' />'; } return $output . $extra; }
/** * Returns HTML for help text based on file upload validators. * * @param array $variables * An associative array containing: * - description: The normal description for this field, specified by the * user. * - upload_validators: An array of upload validators as used in * $element['#upload_validators']. * * @return string * The constructed HTML. * * @see theme_file_upload_help() * * @ingroup theme_functions */ function bootstrap_file_upload_help($variables) { // If popover's are disabled, just theme this normally. if (!bootstrap_setting('popover_enabled')) { return theme_file_upload_help($variables); } $build = array(); if (!empty($variables['description'])) { $build['description'] = array('#markup' => $variables['description'] . '<br>'); } $descriptions = array(); $upload_validators = $variables['upload_validators']; if (isset($upload_validators['file_validate_size'])) { $descriptions[] = t('Files must be less than !size.', array('!size' => '<strong>' . format_size($upload_validators['file_validate_size'][0]) . '</strong>')); } if (isset($upload_validators['file_validate_extensions'])) { $descriptions[] = t('Allowed file types: !extensions.', array('!extensions' => '<strong>' . check_plain($upload_validators['file_validate_extensions'][0]) . '</strong>')); } if (isset($upload_validators['file_validate_image_resolution'])) { $max = $upload_validators['file_validate_image_resolution'][0]; $min = $upload_validators['file_validate_image_resolution'][1]; if ($min && $max && $min == $max) { $descriptions[] = t('Images must be exactly !size pixels.', array('!size' => '<strong>' . $max . '</strong>')); } elseif ($min && $max) { $descriptions[] = t('Images must be between !min and !max pixels.', array('!min' => '<strong>' . $min . '</strong>', '!max' => '<strong>' . $max . '</strong>')); } elseif ($min) { $descriptions[] = t('Images must be larger than !min pixels.', array('!min' => '<strong>' . $min . '</strong>')); } elseif ($max) { $descriptions[] = t('Images must be smaller than !max pixels.', array('!max' => '<strong>' . $max . '</strong>')); } } if ($descriptions) { $id = drupal_html_id('upload-instructions'); $build['instructions'] = array('#theme' => 'link__file_upload_requirements', '#text' => _bootstrap_icon('question-sign') . ' ' . t('More information'), '#path' => '#', '#options' => array('attributes' => array('data-toggle' => 'popover', 'data-target' => "#{$id}", 'data-html' => TRUE, 'data-placement' => 'bottom', 'data-title' => t('File requirements')), 'html' => TRUE, 'external' => TRUE)); $build['requirements'] = array('#theme_wrappers' => array('container__file_upload_requirements'), '#attributes' => array('id' => $id, 'class' => array('element-invisible', 'help-block'))); $build['requirements']['validators'] = array('#theme' => 'item_list__file_upload_requirements', '#items' => $descriptions); } return drupal_render($build); }
/** * Returns HTML for a group of file upload widgets. * * @param array $variables * An associative array containing: * - element: A render element representing the widgets. * * @return string * The constructed HTML. * * @see theme_file_widget_multiple() * * @ingroup theme_functions */ function bootstrap_file_widget_multiple($variables) { $element = $variables['element']; // Special ID and classes for draggable tables. $weight_class = $element['#id'] . '-weight'; $table_id = $element['#id'] . '-table'; // Build up a table of applicable fields. $headers = array(); $headers[] = t('File information'); if ($element['#display_field']) { $headers[] = array('data' => t('Display'), 'class' => array('checkbox')); } $headers[] = t('Weight'); $headers[] = t('Operations'); // Get our list of widgets in order (needed when the form comes back after // preview or failed validation). $widgets = array(); foreach (element_children($element) as $key) { $widgets[] =& $element[$key]; } usort($widgets, '_field_sort_items_value_helper'); $rows = array(); foreach ($widgets as $key => &$widget) { // Save the uploading row for last. if ($widget['#file'] == FALSE) { $widget['#title'] = $element['#file_upload_title']; $widget['#description'] = $element['#file_upload_description']; continue; } // Delay rendering of the buttons, so that they can be rendered later in the // "operations" column. $operations_elements = array(); foreach (element_children($widget) as $sub_key) { if (isset($widget[$sub_key]['#type']) && $widget[$sub_key]['#type'] == 'submit') { hide($widget[$sub_key]); $operations_elements[] =& $widget[$sub_key]; } } // Delay rendering of the "Display" option and the weight selector, so that // each can be rendered later in its own column. if ($element['#display_field']) { hide($widget['display']); } hide($widget['_weight']); // Render everything else together in a column, without the normal wrappers. $widget['#theme_wrappers'] = array(); $information = drupal_render($widget); // Render the previously hidden elements, using render() instead of // drupal_render(), to undo the earlier hide(). $operations = ''; foreach ($operations_elements as $operation_element) { $operation_element['#attributes']['class'][] = 'btn-xs'; switch ($operation_element['#value']) { case t('Remove'): $operation_element['#icon'] = _bootstrap_icon('remove'); break; } $operations .= render($operation_element); } $display = ''; if ($element['#display_field']) { unset($widget['display']['#title']); $display = array('data' => render($widget['display']), 'class' => array('checkbox')); } $widget['_weight']['#attributes']['class'] = array($weight_class); $weight = render($widget['_weight']); // Arrange the row with all of the rendered columns. $row = array(); $row[] = $information; if ($element['#display_field']) { $row[] = $display; } $row[] = $weight; $row[] = $operations; $rows[] = array('data' => $row, 'class' => isset($widget['#attributes']['class']) ? array_merge($widget['#attributes']['class'], array('draggable')) : array('draggable')); } drupal_add_tabledrag($table_id, 'order', 'sibling', $weight_class); $output = ''; if (!empty($rows)) { $table = array('#theme' => 'table', '#header' => $headers, '#rows' => $rows, '#attributes' => array('id' => $table_id, 'class' => array('managed-files'))); $output = drupal_render($table); } $output .= drupal_render_children($element); return $output; }
/** * Returns HTML for a link to the more extensive filter tips. * * @ingroup themeable */ function bootstrap_subtheme_filter_tips_more_info() { return l(_bootstrap_icon('question-sign') . t('Formatting Tips'), 'filter/tips', array('html' => TRUE, 'attributes' => ['target' => '_blank'])); }