Newer
Older
* List of common helper functions for use in Bootstrap based themes.
define('BOOTSTRAP_VERSION_MAJOR', 3);
define('BOOTSTRAP_VERSION_MINOR', 3);
define('BOOTSTRAP_VERSION_PATCH', 5);
define('BOOTSTRAP_VERSION', BOOTSTRAP_VERSION_MAJOR . '.' . BOOTSTRAP_VERSION_MINOR . '.' . BOOTSTRAP_VERSION_PATCH);
Mark Halliwell
committed
/**
* @defgroup subtheme_helper_functions Helper Functions
* @ingroup subtheme
*
* List of common helper functions for use in Drupal Bootstrap based themes.
*
* @{
*/
/**
* Converts an element description into a tooltip based on certain criteria.
Mark Halliwell
committed
*
* @param array $element
* An element render array, passed by reference.
* @param array $target
* The target element render array the tooltip is to be attached to, passed
* by reference. If not set, it will default to the $element passed.
* @param bool $input_only
* Toggle determining whether or not to only convert input elements.
* @param int $length
* The length of characters to determine if description is "simple".
*/
function bootstrap_element_smart_description(&$element, &$target = NULL, $input_only = TRUE, $length = NULL) {
// Determine if tooltips are enabled.
static $enabled;
if (!isset($enabled)) {
$enabled = bootstrap_setting('tooltip_enabled') && bootstrap_setting('forms_smart_descriptions');
}
// Immediately return if "simple" tooltip descriptions are not enabled.
if (!$enabled) {
Mark Halliwell
committed
}
// Allow a different element to attach the tooltip.
if (!isset($target)) {
$target = &$element;
}
// Retrieve the length limit for smart descriptions.
if (!isset($length)) {
$length = (int) bootstrap_setting('forms_smart_descriptions_limit');
// Disable length checking by setting it to FALSE if empty.
if (empty($length)) {
$length = FALSE;
}
}
// Retrieve the allowed tags for smart descriptions. This is primarily used
// for display purposes only (i.e. non-UI/UX related elements that wouldn't
// require a user to "click", like a link).
$allowed_tags = array_filter(array_unique(array_map('trim', explode(',', bootstrap_setting('forms_smart_descriptions_allowed_tags') . ''))));
// Disable length checking by setting it to FALSE if empty.
if (empty($allowed_tags)) {
$allowed_tags = FALSE;
}
$html = FALSE;
$type = !empty($element['#type']) ? $element['#type'] : FALSE;
Mark Halliwell
committed
// Return if element or target shouldn't have "simple" tooltip descriptions.
if (($input_only && !isset($target['#input']))
Mark Halliwell
committed
// Ignore text_format elements.
// @see https://www.drupal.org/node/2478339
|| $type === 'text_format'
Mark Halliwell
committed
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Ignore if the actual element has no #description set.
|| empty($element['#description'])
// Ignore if the target element already has a "data-toggle" attribute set.
|| !empty($target['#attributes']['data-toggle'])
// Ignore if the target element is #disabled.
|| isset($target['#disabled'])
// Ignore if either the actual element or target element has an explicit
// #smart_description property set to FALSE.
|| (isset($element['#smart_description']) && !$element['#smart_description'])
|| (isset($target['#smart_description']) && !$target['#smart_description'])
// Ignore if the description is not "simple".
|| !_bootstrap_is_simple_string($element['#description'], $length, $allowed_tags, $html)
) {
// Set the both the actual element and the target element
// #smart_description property to FALSE.
$element['#smart_description'] = FALSE;
$target['#smart_description'] = FALSE;
return;
}
// Default property (on the element itself).
$property = 'attributes';
// Add the tooltip to the #label_attributes property for 'checkbox'
// and 'radio' elements.
if ($type === 'checkbox' || $type === 'radio') {
$property = 'label_attributes';
}
// Add the tooltip to the #wrapper_attributes property for 'checkboxes'
// and 'radios' elements.
elseif ($type === 'checkboxes' || $type === 'radios') {
$property = 'wrapper_attributes';
}
// Add the tooltip to the #input_group_attributes property for elements
// that have valid input groups set.
elseif ((!empty($element['#field_prefix']) || !empty($element['#field_suffix'])) && (!empty($element['#input_group']) || !empty($element['#input_group_button']))) {
$property = 'input_group_attributes';
Mark Halliwell
committed
}
Mark Halliwell
committed
// Retrieve the proper attributes array.
$attributes = &_bootstrap_get_attributes($target, $property);
// Set the tooltip attributes.
$attributes['title'] = $allowed_tags !== FALSE ? filter_xss($element['#description'], $allowed_tags) : $element['#description'];
$attributes['data-toggle'] = 'tooltip';
if ($html || $allowed_tags === FALSE) {
$attributes['data-html'] = 'true';
}
// Remove the element description so it isn't (re-)rendered later.
unset($element['#description']);
Mark Halliwell
committed
}
/**
* Retrieves CDN assets for the active provider, if any.
*
* @param string|array $type
* The type of asset to retrieve: "css" or "js", defaults to an array
* array containing both if not set.
* @param string $provider
* The name of a specific CDN provider to use, defaults to the active provider
* set in the theme settings.
* @param string $theme
* The name of a specific theme the settings should be retrieved from,
* defaults to the active theme.
*
* @return array
* If $type is a string or an array with only one (1) item in it, the assets
* are returned as an indexed array of files. Otherwise, an associative array
* is returned keyed by the type.
*/
function bootstrap_get_cdn_assets($type = NULL, $provider = NULL, $theme = NULL) {
$original_type = $type;
$assets = array();
$types = array();
// If no type is set, return all CSS and JS.
if (!isset($type)) {
$types = array('css', 'js');
}
elseif (isset($type)) {
if (!is_array($type)) {
$type = array($type);
}
$types = $type;
}
// Ensure default arrays exist for the requested types.
foreach ($types as $type) {
$assets[$type] = array();
// Retrieve the CDN provider from the theme.
if (!isset($provider)) {
$provider = bootstrap_setting('cdn_provider', $theme);
// Load the CDN provider data.
bootstrap_include('bootstrap', 'includes/cdn.inc');
if (!empty($provider) && ($data = bootstrap_cdn_provider($provider))) {
// Alter the assets based on provider.
$function = 'bootstrap_bootstrap_cdn_provider_' . $provider . '_assets_alter';
if (function_exists($function)) {
$function($data, $theme);
// @todo Use drupal_alter() once CDN is in bootstrap_core companion module.
// drupal_alter('bootstrap_cdn_provider_' . $provider . '_assets', $data, $theme);
// Iterate over each type.
foreach ($types as $type) {
if (variable_get("preprocess_$type", FALSE) && !empty($data['min'][$type])) {
$assets[$type] = $data['min'][$type];
}
elseif (!empty($data[$type])) {
$assets[$type] = $data[$type];
}
}
}
return is_string($original_type) ? $assets[$original_type] : $assets;
Mark Halliwell
committed
* Return information from the .info file of a theme (and possible base themes).
*
* @param string $theme_key
* The machine name of the theme.
* @param string $key
* The key name of the item to return from the .info file. This value can
* include "][" to automatically attempt to traverse any arrays.
* @param bool $base_themes
* Recursively search base themes, defaults to TRUE.
*
* @return string|array|false
* A string or array depending on the type of value and if a base theme also
* contains the same $key, FALSE if no $key is found.
Mark Halliwell
committed
function bootstrap_get_theme_info($theme_key = NULL, $key = NULL, $base_themes = TRUE) {
// If no $theme_key is given, use the current theme if we can determine it.
if (!isset($theme_key)) {
$theme_key = !empty($GLOBALS['theme_key']) ? $GLOBALS['theme_key'] : FALSE;
Mark Halliwell
committed
if ($theme_key) {
Mark Halliwell
committed
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
if (!empty($themes[$theme_key])) {
$theme = $themes[$theme_key];
// If a key name was specified, return just that array.
if ($key) {
$value = FALSE;
// Recursively add base theme values.
if ($base_themes && isset($theme->base_themes)) {
foreach (array_keys($theme->base_themes) as $base_theme) {
$value = bootstrap_get_theme_info($base_theme, $key);
}
}
if (!empty($themes[$theme_key])) {
$info = $themes[$theme_key]->info;
// Allow array traversal.
$keys = explode('][', $key);
foreach ($keys as $parent) {
if (isset($info[$parent])) {
$info = $info[$parent];
}
else {
$info = FALSE;
}
}
if (is_array($value)) {
if (!empty($info)) {
if (!is_array($info)) {
$info = array($info);
}
$value = drupal_array_merge_deep($value, $info);
}
}
else {
if (!empty($info)) {
if (empty($value)) {
$value = $info;
}
else {
if (!is_array($value)) {
$value = array($value);
}
if (!is_array($info)) {
$info = array($info);
}
$value = drupal_array_merge_deep($value, $info);
}
}
}
}
return $value;
Mark Halliwell
committed
// If no info $key was specified, just return the entire info array.
return $theme->info;
Mark Halliwell
committed
return FALSE;
Mark Halliwell
committed
/**
Mark Halliwell
committed
*
* @param string $theme
* Name of the theme to use for base path.
* @param string $path
* Path relative to $theme.
*/
function bootstrap_include($theme, $path) {
static $themes = array();
if (!isset($themes[$theme])) {
$themes[$theme] = drupal_get_path('theme', $theme);
}
if ($themes[$theme] && ($file = DRUPAL_ROOT . '/' . $themes[$theme] . '/' . $path) && file_exists($file)) {
include_once $file;
}
}
/**
* Retrieves a setting for the current theme or for a given theme.
*
* This is a wrapper for theme_get_setting(), ensuring to use deprecated
* setting values instead.
*
* @param string $name
* The name of the setting to be retrieved.
* @param string $theme
* The name of a given theme; defaults to the currently active theme.
* @param string $prefix
* The prefix used on the $name of the setting, this will be appended with
* "_" automatically if set.
*
* @return mixed
* The value of the requested setting, NULL if the setting does not exist.
*
* @see theme_get_setting()
*
* @todo Refactor in 7.x-4.x and get rid of the deprecated settings.
*/
function bootstrap_setting($name, $theme = NULL, $prefix = 'bootstrap') {
$prefix = !empty($prefix) ? $prefix . '_' : '';
$setting = theme_get_setting($prefix . $name, $theme);
switch ($prefix . $name) {
case 'bootstrap_cdn_provider':
$deprecated = theme_get_setting('bootstrap_cdn', $theme);
if (isset($deprecated)) {
$setting = empty($deprecated) ? '' : 'jsdelivr';
}
break;
case 'bootstrap_cdn_jsdelivr_version':
$deprecated = theme_get_setting('bootstrap_cdn', $theme);
if (isset($deprecated)) {
$setting = empty($deprecated) ? BOOTSTRAP_VERSION : $deprecated;
}
break;
case 'bootstrap_cdn_jsdelivr_theme':
$deprecated = theme_get_setting('bootstrap_bootswatch', $theme);
if (isset($deprecated)) {
$setting = empty($deprecated) ? 'bootstrap' : $deprecated;
}
break;
Mark Halliwell
committed
case 'bootstrap_forms_smart_descriptions':
$deprecated = theme_get_setting('bootstrap_tooltip_descriptions', $theme);
if (isset($deprecated)) {
$setting = (int) !empty($deprecated);
}
break;
case 'bootstrap_forms_smart_descriptions_limit':
$deprecated = theme_get_setting('bootstrap_tooltip_descriptions_length', $theme);
if (isset($deprecated)) {
$setting = (int) !empty($deprecated);
}
break;
return $setting;
/**
* Retrieves an element's "attributes" array.
*
* @param array $element
* The individual renderable array element. It is possible to also pass the
* $variables parameter in [pre]process functions and it will logically
* determine the correct path to that particular theme hook's attribute array.
* Passed by reference.
Mark Halliwell
committed
* @param string $property
* Determines which attributes array to retrieve. By default, this is the
* normal attributes, but can be "wrapper_attributes" or
* "input_group_attributes".
*
* @return array
* The attributes array. Passed by reference.
*/
Mark Halliwell
committed
function &_bootstrap_get_attributes(&$element, $property = 'attributes') {
// Attempt to retrieve a renderable element attributes first.
if (
isset($element['#type']) ||
isset($element['#theme']) ||
isset($element['#pre_render']) ||
isset($element['#markup']) ||
isset($element['#theme_wrappers']) ||
Mark Halliwell
committed
isset($element["#$property"])
) {
Mark Halliwell
committed
if (!isset($element["#$property"])) {
$element["#$property"] = array();
}
Mark Halliwell
committed
return $element["#$property"];
}
// Treat $element as if it were a [pre]process function $variables parameter
// and look for a renderable "element".
elseif (isset($element['element'])) {
Mark Halliwell
committed
if (!isset($element['element']["#$property"])) {
$element['element']["#$property"] = array();
}
Mark Halliwell
committed
return $element['element']["#$property"];
}
// If all else fails, create (if needed) a default "attributes" array. This
// will, at the very least, either work or cause an error that can be tracked.
Mark Halliwell
committed
if (!isset($element[$property])) {
$element[$property] = array();
}
Mark Halliwell
committed
return $element[$property];
}
/**
* Retrieves an element's "class" array.
*
* @param array $element
* The individual renderable array element. It is possible to also pass the
* $variables parameter in [pre]process functions and it will logically
* determine the correct path to that particular theme hook's classes array.
* Passed by reference.
Mark Halliwell
committed
* @param string $property
* Determines which attributes array to retrieve. By default, this is the
* normal attributes, but can be "wrapper_attributes" or
* "input_group_attributes".
*
* @return array
* The classes array. Passed by reference.
*/
Mark Halliwell
committed
function &_bootstrap_get_classes(&$element, $property = 'attributes') {
$attributes = &_bootstrap_get_attributes($element, $property);
if (!isset($attributes['class'])) {
$attributes['class'] = array();
}
// Contrib modules have a very bad habit of frequently adding classes as
// strings, convert them to a proper array.
// @see https://www.drupal.org/node/2269653
elseif (!is_array($attributes['class'])) {
$attributes['class'] = explode(' ', $attributes['class']);
}
// Ensure classes are not duplicated.
$attributes['class'] = array_unique($attributes['class']);
return $attributes['class'];
}
/**
* Adds a class to an element's render array.
*
* @param string|array $class
* An individual class or an array of classes to add.
* @param array $element
* The individual renderable array element. It is possible to also pass the
* $variables parameter in [pre]process functions and it will logically
* determine the correct path to that particular theme hook's classes array.
* Passed by reference.
Mark Halliwell
committed
* @param string $property
* Determines which attributes array to retrieve. By default, this is the
* normal attributes, but can be "wrapper_attributes" or
* "input_group_attributes".
*/
Mark Halliwell
committed
function _bootstrap_add_class($class, &$element, $property = 'attributes') {
// Retrieve the element's classes.
Mark Halliwell
committed
$classes = &_bootstrap_get_classes($element, $property);
// Convert the class to an array.
if (!is_array($class)) {
$class = array($class);
}
// Iterate over all classes to add.
foreach ($class as $_class) {
// Ensure the class to add does not yet already exist.
if (!in_array($_class, $classes)) {
$classes[] = $_class;
}
}
}
/**
* Removes a class from an element's render array.
*
* @param string|array $class
* An individual class or an array of classes to remove.
* @param array $element
* The individual renderable array element. It is possible to also pass the
* $variables parameter in [pre]process functions and it will logically
* determine the correct path to that particular theme hook's classes array.
* Passed by reference.
Mark Halliwell
committed
* @param string $property
* Determines which attributes array to retrieve. By default, this is the
* normal attributes, but can be "wrapper_attributes" or
* "input_group_attributes".
*/
Mark Halliwell
committed
function _bootstrap_remove_class($class, &$element, $property = 'attributes') {
// Retrieve the element's classes.
Mark Halliwell
committed
$classes = &_bootstrap_get_classes($element, $property);
// Convert the class to an array.
if (!is_array($class)) {
$class = array($class);
}
// Iterate over all classes to add.
foreach ($class as $_class) {
$key = array_search($_class, $classes);
if ($key !== FALSE) {
unset($classes[$key]);
}
}
}
* Returns a list of base themes for active or provided theme.
*
* @param string $theme_key
* The machine name of the theme to check, if not set the active theme name
* will be used.
* @param bool $include_theme_key
* Whether to append the returned list with $theme_key.
*
* @return array
* An indexed array of base themes.
*/
function _bootstrap_get_base_themes($theme_key = NULL, $include_theme_key = FALSE) {
static $themes;
if (!isset($theme_key)) {
$theme_key = $GLOBALS['theme_key'];
}
if (!isset($themes[$theme_key])) {
$themes[$theme_key] = array_unique(array_filter((array) bootstrap_get_theme_info($theme_key, 'base theme')));
}
if ($include_theme_key) {
$themes[$theme_key][] = $theme_key;
}
return $themes[$theme_key];
}
Mark Halliwell
committed
/**
* Wrapper for the core file_scan_directory() function.
Mark Halliwell
committed
*
* Finds all files that match a given mask in a given directory and then caches
* the results. A general site cache clear will force new scans to be initiated
* for already cached directories.
*
* @param string $dir
* The base directory or URI to scan, without trailing slash.
* @param string $mask
* The preg_match() regular expression of the files to find.
* @param array $options
* Additional options to pass to file_scan_directory().
*
* @return array
* An associative array (keyed on the chosen key) of objects with 'uri',
* 'filename', and 'name' members corresponding to the matching files.
*
* @see file_scan_directory()
*/
function _bootstrap_file_scan_directory($dir, $mask, array $options = array()) {
Mark Halliwell
committed
$files = &drupal_static(__FUNCTION__, array());
// Generate a unique cache identifier for all parameters passed as a change
// in any of them would return different results.
$cid = 'theme_registry:bootstrap:files:' . drupal_hash_base64(serialize(func_get_args()));
// Load from DB cache or scan filesystem if files are not statically cached.
if (!isset($files[$cid])) {
if (($cache = cache_get($cid)) && isset($cache->data)) {
$files[$cid] = $cache->data;
}
else {
$files[$cid] = file_scan_directory($dir, $mask, $options);
cache_set($cid, $files[$cid]);
}
}
return $files[$cid];
Mark Halliwell
committed
}
/**
* Filters HTML to prevent cross-site-scripting (XSS) vulnerabilities.
*
* Very similar to core's filter_xss(). It does, however, include the addition
* of the "span", "div" and "i" elements which are commonly used in Bootstrap.
*
* @param string $string
* The string with raw HTML in it. It will be stripped of everything that can
* cause an XSS attack.
* @param array $allowed_tags
* An array of allowed tags.
*
* @return string
* An XSS safe version of $string, or an empty string if $string is not
* valid UTF-8.
*
* @see filter_xss()
Mark Halliwell
committed
* @see filter_xss_admin()
*
* @deprecated Use filter_xss() or filter_xss_admin() instead.
* Will be removed in a future release.
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
*/
function _bootstrap_filter_xss($string, array $allowed_tags = NULL) {
if (is_null($allowed_tags)) {
$allowed_tags = array(
// Inline elements.
'a',
'cite',
'em',
'i',
'span',
'strong',
// Block elements.
'blockquote',
'code',
'div',
'ul',
'ol',
'li',
'dl',
'dt',
'dd',
);
}
return filter_xss($string, $allowed_tags);
}
/**
* Returns a list of available Bootstrap Glyphicons.
*
* @param string $version
* The specific version of glyphicons to return. If not set, the latest
* BOOTSTRAP_VERSION will be used.
*
* @return array
* An associative array of icons keyed by their classes.
Mark Halliwell
committed
*/
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
function _bootstrap_glyphicons($version = NULL) {
static $versions;
if (!isset($versions)) {
$versions = array();
$versions['3.0.0'] = array(
// Class => Name.
'glyphicon-adjust' => 'adjust',
'glyphicon-align-center' => 'align-center',
'glyphicon-align-justify' => 'align-justify',
'glyphicon-align-left' => 'align-left',
'glyphicon-align-right' => 'align-right',
'glyphicon-arrow-down' => 'arrow-down',
'glyphicon-arrow-left' => 'arrow-left',
'glyphicon-arrow-right' => 'arrow-right',
'glyphicon-arrow-up' => 'arrow-up',
'glyphicon-asterisk' => 'asterisk',
'glyphicon-backward' => 'backward',
'glyphicon-ban-circle' => 'ban-circle',
'glyphicon-barcode' => 'barcode',
'glyphicon-bell' => 'bell',
'glyphicon-bold' => 'bold',
'glyphicon-book' => 'book',
'glyphicon-bookmark' => 'bookmark',
'glyphicon-briefcase' => 'briefcase',
'glyphicon-bullhorn' => 'bullhorn',
'glyphicon-calendar' => 'calendar',
'glyphicon-camera' => 'camera',
'glyphicon-certificate' => 'certificate',
'glyphicon-check' => 'check',
'glyphicon-chevron-down' => 'chevron-down',
'glyphicon-chevron-left' => 'chevron-left',
'glyphicon-chevron-right' => 'chevron-right',
'glyphicon-chevron-up' => 'chevron-up',
'glyphicon-circle-arrow-down' => 'circle-arrow-down',
'glyphicon-circle-arrow-left' => 'circle-arrow-left',
'glyphicon-circle-arrow-right' => 'circle-arrow-right',
'glyphicon-circle-arrow-up' => 'circle-arrow-up',
'glyphicon-cloud' => 'cloud',
'glyphicon-cloud-download' => 'cloud-download',
'glyphicon-cloud-upload' => 'cloud-upload',
'glyphicon-cog' => 'cog',
'glyphicon-collapse-down' => 'collapse-down',
'glyphicon-collapse-up' => 'collapse-up',
'glyphicon-comment' => 'comment',
'glyphicon-compressed' => 'compressed',
'glyphicon-copyright-mark' => 'copyright-mark',
'glyphicon-credit-card' => 'credit-card',
'glyphicon-cutlery' => 'cutlery',
'glyphicon-dashboard' => 'dashboard',
'glyphicon-download' => 'download',
'glyphicon-download-alt' => 'download-alt',
'glyphicon-earphone' => 'earphone',
'glyphicon-edit' => 'edit',
'glyphicon-eject' => 'eject',
'glyphicon-envelope' => 'envelope',
'glyphicon-euro' => 'euro',
'glyphicon-exclamation-sign' => 'exclamation-sign',
'glyphicon-expand' => 'expand',
'glyphicon-export' => 'export',
'glyphicon-eye-close' => 'eye-close',
'glyphicon-eye-open' => 'eye-open',
'glyphicon-facetime-video' => 'facetime-video',
'glyphicon-fast-backward' => 'fast-backward',
'glyphicon-fast-forward' => 'fast-forward',
'glyphicon-file' => 'file',
'glyphicon-film' => 'film',
'glyphicon-filter' => 'filter',
'glyphicon-fire' => 'fire',
'glyphicon-flag' => 'flag',
'glyphicon-flash' => 'flash',
'glyphicon-floppy-disk' => 'floppy-disk',
'glyphicon-floppy-open' => 'floppy-open',
'glyphicon-floppy-remove' => 'floppy-remove',
'glyphicon-floppy-save' => 'floppy-save',
'glyphicon-floppy-saved' => 'floppy-saved',
'glyphicon-folder-close' => 'folder-close',
'glyphicon-folder-open' => 'folder-open',
'glyphicon-font' => 'font',
'glyphicon-forward' => 'forward',
'glyphicon-fullscreen' => 'fullscreen',
'glyphicon-gbp' => 'gbp',
'glyphicon-gift' => 'gift',
'glyphicon-glass' => 'glass',
'glyphicon-globe' => 'globe',
'glyphicon-hand-down' => 'hand-down',
'glyphicon-hand-left' => 'hand-left',
'glyphicon-hand-right' => 'hand-right',
'glyphicon-hand-up' => 'hand-up',
'glyphicon-hd-video' => 'hd-video',
'glyphicon-hdd' => 'hdd',
'glyphicon-header' => 'header',
'glyphicon-headphones' => 'headphones',
'glyphicon-heart' => 'heart',
'glyphicon-heart-empty' => 'heart-empty',
'glyphicon-home' => 'home',
'glyphicon-import' => 'import',
'glyphicon-inbox' => 'inbox',
'glyphicon-indent-left' => 'indent-left',
'glyphicon-indent-right' => 'indent-right',
'glyphicon-info-sign' => 'info-sign',
'glyphicon-italic' => 'italic',
'glyphicon-leaf' => 'leaf',
'glyphicon-link' => 'link',
'glyphicon-list' => 'list',
'glyphicon-list-alt' => 'list-alt',
'glyphicon-lock' => 'lock',
'glyphicon-log-in' => 'log-in',
'glyphicon-log-out' => 'log-out',
'glyphicon-magnet' => 'magnet',
'glyphicon-map-marker' => 'map-marker',
'glyphicon-minus' => 'minus',
'glyphicon-minus-sign' => 'minus-sign',
'glyphicon-move' => 'move',
'glyphicon-music' => 'music',
'glyphicon-new-window' => 'new-window',
'glyphicon-off' => 'off',
'glyphicon-ok' => 'ok',
'glyphicon-ok-circle' => 'ok-circle',
'glyphicon-ok-sign' => 'ok-sign',
'glyphicon-open' => 'open',
'glyphicon-paperclip' => 'paperclip',
'glyphicon-pause' => 'pause',
'glyphicon-pencil' => 'pencil',
'glyphicon-phone' => 'phone',
'glyphicon-phone-alt' => 'phone-alt',
'glyphicon-picture' => 'picture',
'glyphicon-plane' => 'plane',
'glyphicon-play' => 'play',
'glyphicon-play-circle' => 'play-circle',
'glyphicon-plus' => 'plus',
'glyphicon-plus-sign' => 'plus-sign',
'glyphicon-print' => 'print',
'glyphicon-pushpin' => 'pushpin',
'glyphicon-qrcode' => 'qrcode',
'glyphicon-question-sign' => 'question-sign',
'glyphicon-random' => 'random',
'glyphicon-record' => 'record',
'glyphicon-refresh' => 'refresh',
'glyphicon-registration-mark' => 'registration-mark',
'glyphicon-remove' => 'remove',
'glyphicon-remove-circle' => 'remove-circle',
'glyphicon-remove-sign' => 'remove-sign',
'glyphicon-repeat' => 'repeat',
'glyphicon-resize-full' => 'resize-full',
'glyphicon-resize-horizontal' => 'resize-horizontal',
'glyphicon-resize-small' => 'resize-small',
'glyphicon-resize-vertical' => 'resize-vertical',
'glyphicon-retweet' => 'retweet',
'glyphicon-road' => 'road',
'glyphicon-save' => 'save',
'glyphicon-saved' => 'saved',
'glyphicon-screenshot' => 'screenshot',
'glyphicon-sd-video' => 'sd-video',
'glyphicon-search' => 'search',
'glyphicon-send' => 'send',
'glyphicon-share' => 'share',
'glyphicon-share-alt' => 'share-alt',
'glyphicon-shopping-cart' => 'shopping-cart',
'glyphicon-signal' => 'signal',
'glyphicon-sort' => 'sort',
'glyphicon-sort-by-alphabet' => 'sort-by-alphabet',
'glyphicon-sort-by-alphabet-alt' => 'sort-by-alphabet-alt',
'glyphicon-sort-by-attributes' => 'sort-by-attributes',
'glyphicon-sort-by-attributes-alt' => 'sort-by-attributes-alt',
'glyphicon-sort-by-order' => 'sort-by-order',
'glyphicon-sort-by-order-alt' => 'sort-by-order-alt',
'glyphicon-sound-5-1' => 'sound-5-1',
'glyphicon-sound-6-1' => 'sound-6-1',
'glyphicon-sound-7-1' => 'sound-7-1',
'glyphicon-sound-dolby' => 'sound-dolby',
'glyphicon-sound-stereo' => 'sound-stereo',
'glyphicon-star' => 'star',
'glyphicon-star-empty' => 'star-empty',
'glyphicon-stats' => 'stats',
'glyphicon-step-backward' => 'step-backward',
'glyphicon-step-forward' => 'step-forward',
'glyphicon-stop' => 'stop',
'glyphicon-subtitles' => 'subtitles',
'glyphicon-tag' => 'tag',
'glyphicon-tags' => 'tags',
'glyphicon-tasks' => 'tasks',
'glyphicon-text-height' => 'text-height',
'glyphicon-text-width' => 'text-width',
'glyphicon-th' => 'th',
'glyphicon-th-large' => 'th-large',
'glyphicon-th-list' => 'th-list',
'glyphicon-thumbs-down' => 'thumbs-down',
'glyphicon-thumbs-up' => 'thumbs-up',
'glyphicon-time' => 'time',
'glyphicon-tint' => 'tint',
'glyphicon-tower' => 'tower',
'glyphicon-transfer' => 'transfer',
'glyphicon-trash' => 'trash',
'glyphicon-tree-conifer' => 'tree-conifer',
'glyphicon-tree-deciduous' => 'tree-deciduous',
'glyphicon-unchecked' => 'unchecked',
'glyphicon-upload' => 'upload',
'glyphicon-usd' => 'usd',
'glyphicon-user' => 'user',
'glyphicon-volume-down' => 'volume-down',
'glyphicon-volume-off' => 'volume-off',
'glyphicon-volume-up' => 'volume-up',
'glyphicon-warning-sign' => 'warning-sign',
'glyphicon-wrench' => 'wrench',
'glyphicon-zoom-in' => 'zoom-in',
'glyphicon-zoom-out' => 'zoom-out',
);
$versions['3.0.1'] = $versions['3.0.0'];
$versions['3.0.2'] = $versions['3.0.1'];
$versions['3.0.3'] = $versions['3.0.2'];
$versions['3.1.0'] = $versions['3.0.3'];
$versions['3.1.1'] = $versions['3.1.0'];
$versions['3.2.0'] = $versions['3.1.1'];
$versions['3.3.0'] = array_merge($versions['3.2.0'], array(
'glyphicon-eur' => 'eur',
));
$versions['3.3.1'] = $versions['3.3.0'];
$versions['3.3.2'] = array_merge($versions['3.3.1'], array(
'glyphicon-alert' => 'alert',
'glyphicon-apple' => 'apple',
'glyphicon-baby-formula' => 'baby-formula',
'glyphicon-bed' => 'bed',
'glyphicon-bishop' => 'bishop',
'glyphicon-bitcoin' => 'bitcoin',
'glyphicon-blackboard' => 'blackboard',
'glyphicon-cd' => 'cd',
'glyphicon-console' => 'console',
'glyphicon-copy' => 'copy',
'glyphicon-duplicate' => 'duplicate',
'glyphicon-education' => 'education',
'glyphicon-equalizer' => 'equalizer',
'glyphicon-erase' => 'erase',
'glyphicon-grain' => 'grain',
'glyphicon-hourglass' => 'hourglass',
'glyphicon-ice-lolly' => 'ice-lolly',
'glyphicon-ice-lolly-tasted' => 'ice-lolly-tasted',
'glyphicon-king' => 'king',
'glyphicon-knight' => 'knight',
'glyphicon-lamp' => 'lamp',
'glyphicon-level-up' => 'level-up',
'glyphicon-menu-down' => 'menu-down',
'glyphicon-menu-hamburger' => 'menu-hamburger',
'glyphicon-menu-left' => 'menu-left',
'glyphicon-menu-right' => 'menu-right',
'glyphicon-menu-up' => 'menu-up',
'glyphicon-modal-window' => 'modal-window',
'glyphicon-object-align-bottom' => 'object-align-bottom',
'glyphicon-object-align-horizontal' => 'object-align-horizontal',
'glyphicon-object-align-left' => 'object-align-left',
'glyphicon-object-align-right' => 'object-align-right',
'glyphicon-object-align-top' => 'object-align-top',
'glyphicon-object-align-vertical' => 'object-align-vertical',
'glyphicon-oil' => 'oil',
'glyphicon-open-file' => 'open-file',
'glyphicon-option-horizontal' => 'option-horizontal',
'glyphicon-option-vertical' => 'option-vertical',
'glyphicon-paste' => 'paste',
'glyphicon-pawn' => 'pawn',
'glyphicon-piggy-bank' => 'piggy-bank',
'glyphicon-queen' => 'queen',
'glyphicon-ruble' => 'ruble',
'glyphicon-save-file' => 'save-file',
'glyphicon-scale' => 'scale',
'glyphicon-scissors' => 'scissors',
'glyphicon-subscript' => 'subscript',
'glyphicon-sunglasses' => 'sunglasses',
'glyphicon-superscript' => 'superscript',
'glyphicon-tent' => 'tent',
'glyphicon-text-background' => 'text-background',
'glyphicon-text-color' => 'text-color',
'glyphicon-text-size' => 'text-size',
'glyphicon-triangle-bottom' => 'triangle-bottom',
'glyphicon-triangle-left' => 'triangle-left',
'glyphicon-triangle-right' => 'triangle-right',
'glyphicon-triangle-top' => 'triangle-top',
'glyphicon-yen' => 'yen',
));
$versions['3.3.4'] = array_merge($versions['3.3.2'], array(
'glyphicon-btc' => 'btc',
'glyphicon-jpy' => 'jpy',
'glyphicon-rub' => 'rub',
'glyphicon-xbt' => 'xbt',
));
$versions['3.3.5'] = $versions['3.3.4'];
$versions['3.3.6'] = $versions['3.3.5'];
$versions['3.3.7'] = $versions['3.3.6'];
}
// Return a specific versions icon set.
if (isset($version) && isset($versions[$version])) {
return $versions[$version];
}
// Return the latest version.
return $versions[BOOTSTRAP_VERSION];
Mark Halliwell
committed
}
/**
* Returns a specific Bootstrap Glyphicon.
*
* @param string $name
* The icon name, minus the "glyphicon-" prefix.
Mark Halliwell
committed
* @param string $default
* (Optional) The default value to return.
*
* @return string
Mark Halliwell
committed
* The HTML markup containing the icon defined by $name, $default value if
* icon does not exist or returns empty output for whatever reason.
*/
Mark Halliwell
committed
function _bootstrap_icon($name, $default = NULL) {
$output = NULL;
// Ensure the icon specified is a valid Bootstrap Glyphicon.
// @todo Supply a specific version to _bootstrap_glyphicons() when Icon API
// supports versioning.
Mark Halliwell
committed
if (_bootstrap_glyphicons_supported() && in_array($name, _bootstrap_glyphicons())) {
Mark Halliwell
committed
// Attempt to use the Icon API module, if enabled and it generates output.
if (module_exists('icon')) {
$output = theme('icon', array('bundle' => 'bootstrap', 'icon' => 'glyphicon-' . $name));
}
if (empty($output)) {
// Mimic the Icon API markup.
$attributes = array(
'class' => array('icon', 'glyphicon', 'glyphicon-' . $name),
'aria-hidden' => 'true',
);
$output = '<span' . drupal_attributes($attributes) . '></span>';
}
Mark Halliwell
committed
}
Mark Halliwell
committed
return empty($output) && isset($default) ? $default : $output;
Mark Halliwell
committed
Mark Halliwell
committed
/**
* Determine whether or not Bootstrap Glyphicons can be used.
Mark Halliwell
committed
*/
function _bootstrap_glyphicons_supported() {
Mark Halliwell
committed
// Use the advanced drupal_static() pattern, since this has the potential to
// be called very often by _bootstrap_icon().
static $drupal_static_fast;
if (!isset($drupal_static_fast)) {
$drupal_static_fast['supported'] = &drupal_static(__FUNCTION__);
// Get the active theme.
$drupal_static_fast['theme'] = variable_get('theme_default', $GLOBALS['theme']);
}
// Get static data.
$supported = &$drupal_static_fast['supported'];
$theme = &$drupal_static_fast['theme'];
// Retrieve supported themes.
Mark Halliwell
committed
if (!isset($supported)) {
Mark Halliwell
committed
$supported = array();
// Retrieve cached data.
$cid = 'theme_registry:bootstrap:icon_support';
if (($cache = cache_get($cid)) && !empty($cache->data)) {
$supported = $cache->data;
}
if (!isset($supported[$theme])) {
// Bootstrap based themes are enabled by default to use CDN. Check if
// that is the case here so no file discovery is necessary. If the active