JHtmlRbootstrap   F
last analyzed

Complexity

Total Complexity 154

Size/Duplication

Total Lines 958
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 154
eloc 260
c 1
b 0
f 0
dl 0
loc 958
rs 2

30 Methods

Rating   Name   Duplication   Size   Complexity  
F tooltip() 0 57 28
B framework() 0 20 9
A loadCss() 0 14 3
A scrollspy() 0 24 4
A endAccordion() 0 3 1
A dropdown() 0 21 2
A addTab() 0 25 4
A endPane() 0 3 1
A button() 0 21 2
A affix() 0 24 4
A endTabSet() 0 5 1
A tooltipExtended() 0 6 2
A responsive() 0 12 5
F typeahead() 0 29 16
A fontawesome() 0 6 1
F startAccordion() 0 73 22
A endPanel() 0 3 1
A endSlide() 0 3 1
C modal() 0 27 10
A startPane() 0 28 3
A carousel() 0 25 6
A renderModal() 0 18 2
A addSlide() 0 17 4
A startTabSet() 0 24 4
A alert() 0 21 2
F popover() 0 32 11
A checkbox() 0 6 1
A endTab() 0 5 1
A addPanel() 0 5 2
A timepicker() 0 6 1

How to fix   Complexity   

Complex Class

Complex classes like JHtmlRbootstrap often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use JHtmlRbootstrap, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @package     Redcore
4
 * @subpackage  Html
5
 *
6
 * @copyright   Copyright (C) 2008 - 2021 redWEB.dk. All rights reserved.
7
 * @license     GNU General Public License version 2 or later, see LICENSE.
8
 */
9
10
defined('JPATH_REDCORE') or die;
11
12
/**
13
 * Bootstrap HTML class.
14
 *
15
 * @package     Redcore
16
 * @subpackage  Html
17
 * @since       1.0
18
 */
19
abstract class JHtmlRbootstrap
20
{
21
	/**
22
	 * Extension name to use in the asset calls
23
	 * Basically the media/com_xxxxx folder to use
24
	 */
25
	const EXTENSION = 'redcore';
26
27
	/**
28
	 * Array containing information for loaded files
29
	 *
30
	 * @var  array
31
	 */
32
	protected static $loaded = array();
33
34
	/**
35
	 * Load the entire bootstrap framework
36
	 *
37
	 * @param   mixed    $debug    Is debugging mode on? [optional]
38
	 * @param   boolean  $loadCss  Load bootstrap CSS ?
39
	 *
40
	 * @return  void
41
	 */
42
	public static function framework($debug = null, $loadCss = false)
43
	{
44
		JHtml::_('rjquery.framework');
45
46
		$isAdmin = (version_compare(JVERSION, '3.7', '<') ?
47
			JFactory::getApplication()->isAdmin() : JFactory::getApplication()->isClient('administrator'));
0 ignored issues
show
Bug introduced by
The type JFactory was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
48
49
		// Load Bootstrap in administration, or if it's frontend site and it has been asked via plugin parameters
50
		if ($isAdmin || (!$isAdmin && RBootstrap::$loadFrontendCSS))
51
		{
52
			if ($loadCss)
53
			{
54
				RHtmlMedia::loadFrameworkCss();
55
			}
56
57
			RHtmlMedia::loadFrameworkJs();
58
		}
59
		elseif (!$isAdmin && !RBootstrap::$loadFrontendCSS && !version_compare(JVERSION, '3.0', '<'))
60
		{
61
			JHtml::_('bootstrap.framework');
62
		}
63
	}
64
65
	/**
66
	 * Load the responsive css.
67
	 *
68
	 * @return  void
69
	 */
70
	public static function responsive()
71
	{
72
		self::framework();
73
74
		$isAdmin = (version_compare(JVERSION, '3.7', '<') ?
75
			JFactory::getApplication()->isAdmin() : JFactory::getApplication()->isClient('administrator'));
76
77
		// Load Bootstrap in administration, or if it's frontend site and it has been asked via plugin parameters
78
		if ($isAdmin || (!$isAdmin && RBootstrap::$loadFrontendCSS))
79
		{
80
			RHelperAsset::load('lib/bootstrap/css/bootstrap.min.css', static::EXTENSION);
81
			RHelperAsset::load('lib/bootstrap/css/bootstrap-responsive.min.css', static::EXTENSION);
82
		}
83
	}
84
85
	/**
86
	 * Load the timepicker.
87
	 *
88
	 * @return  void
89
	 *
90
	 * @since   1.0
91
	 */
92
	public static function timepicker()
93
	{
94
		static::framework();
95
96
		RHelperAsset::load('lib/bootstrap-timepicker/css/bootstrap-timepicker.min.css', static::EXTENSION);
97
		RHelperAsset::load('lib/bootstrap-timepicker/js/bootstrap-timepicker.min.js', static::EXTENSION);
98
	}
99
100
	/**
101
	 * Add javascript support for the Bootstrap affix plugin
102
	 *
103
	 * @param   string  $selector  Unique selector for the element to be affixed.
104
	 * @param   array   $params    An array of options.
105
	 *                             Options for the affix plugin can be:
106
	 *                             - offset  number|function|object  Pixels to offset from screen when calculating position of scroll.
107
	 *                                                               If a single number is provided, the offset will be applied in both top
108
	 *                                                               and left directions. To listen for a single direction, or multiple
109
	 *                                                               unique offsets, just provide an object offset: { x: 10 }.
110
	 *                                                               Use a function when you need to dynamically provide an offset
111
	 *                                                               (useful for some responsive designs).
112
	 *
113
	 * @return  void
114
	 */
115
	public static function affix($selector = 'affix', $params = array())
116
	{
117
		$sig = md5(serialize(array($selector, $params)));
118
119
		if (!isset(static::$loaded[__METHOD__][$sig]))
120
		{
121
			// Include Bootstrap framework
122
			static::framework();
123
124
			// Setup options object
125
			$opt['offset'] = (isset($params['offset']) && ($params['offset'])) ? $params['offset'] : 10;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$opt was never initialized. Although not strictly required by PHP, it is generally a good practice to add $opt = array(); before regardless.
Loading history...
126
127
			// Attach affix to document
128
			JFactory::getDocument()->addScriptDeclaration(
129
				"(function($){
130
					$(" . json_encode('#' . $selector) . ").affix(" . json_encode($opt) . ");
131
					})(jQuery);"
132
			);
133
134
			// Set static array
135
			static::$loaded[__METHOD__][$sig] = true;
136
		}
137
138
		return;
139
	}
140
141
	/**
142
	 * Add javascript support for Bootstrap alerts
143
	 *
144
	 * @param   string  $selector  Common class for the alerts
145
	 *
146
	 * @return  void
147
	 */
148
	public static function alert($selector = 'alert')
149
	{
150
		// Only load once
151
		if (isset(static::$loaded[__METHOD__][$selector]))
152
		{
153
			return;
154
		}
155
156
		// Include Bootstrap framework
157
		static::framework();
158
159
		// Attach the alerts to the document
160
		JFactory::getDocument()->addScriptDeclaration(
161
			"(function($){
162
				$(" . json_encode('.' . $selector) . ").alert();
163
				})(jQuery);"
164
		);
165
166
		static::$loaded[__METHOD__][$selector] = true;
167
168
		return;
169
	}
170
171
	/**
172
	 * Add javascript support for Bootstrap buttons
173
	 *
174
	 * @param   string  $selector  Common class for the buttons
175
	 *
176
	 * @return  void
177
	 */
178
	public static function button($selector = 'button')
179
	{
180
		// Only load once
181
		if (isset(static::$loaded[__METHOD__][$selector]))
182
		{
183
			return;
184
		}
185
186
		// Include Bootstrap framework
187
		static::framework();
188
189
		// Attach the button to the document
190
		JFactory::getDocument()->addScriptDeclaration(
191
			"(function($){
192
				$(" . json_encode('.' . $selector) . ").button();
193
				})(jQuery);"
194
		);
195
196
		static::$loaded[__METHOD__][$selector] = true;
197
198
		return;
199
	}
200
201
	/**
202
	 * Add javascript support for Bootstrap carousels
203
	 *
204
	 * @param   string  $selector  Common class for the carousels.
205
	 * @param   array   $params    An array of options for the carousel.
206
	 *                             Options for the carousel can be:
207
	 *                             - interval  number  The amount of time to delay between automatically cycling an item.
208
	 *                                                 If false, carousel will not automatically cycle.
209
	 *                             - pause     string  Pauses the cycling of the carousel on mouseenter and resumes the cycling
210
	 *                                                 of the carousel on mouseleave.
211
	 *
212
	 * @return  void
213
	 */
214
	public static function carousel($selector = 'carousel', $params = array())
215
	{
216
		$sig = md5(serialize(array($selector, $params)));
217
218
		if (!isset(static::$loaded[__METHOD__][$sig]))
219
		{
220
			// Include Bootstrap framework
221
			static::framework();
222
223
			// Setup options object
224
			$opt['interval'] = (isset($params['interval']) && ($params['interval'])) ? (int) $params['interval'] : 5000;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$opt was never initialized. Although not strictly required by PHP, it is generally a good practice to add $opt = array(); before regardless.
Loading history...
225
			$opt['pause']    = (isset($params['pause']) && ($params['pause'])) ? $params['pause'] : 'hover';
226
227
			// Attach the carousel to document
228
			JFactory::getDocument()->addScriptDeclaration(
229
				"(function($){
230
					$(" . json_encode('.' . $selector) . ").carousel(" . json_encode($opt) . ");
231
					})(jQuery);"
232
			);
233
234
			// Set static array
235
			static::$loaded[__METHOD__][$sig] = true;
236
		}
237
238
		return;
239
	}
240
241
	/**
242
	 * Add javascript support for Bootstrap dropdowns
243
	 *
244
	 * @param   string  $selector  Common class for the dropdowns
245
	 *
246
	 * @return  void
247
	 */
248
	public static function dropdown($selector = 'dropdown-toggle')
249
	{
250
		// Only load once
251
		if (isset(static::$loaded[__METHOD__][$selector]))
252
		{
253
			return;
254
		}
255
256
		// Include Bootstrap framework
257
		static::framework();
258
259
		// Attach the dropdown to the document
260
		JFactory::getDocument()->addScriptDeclaration(
261
			"(function($){
262
				$(" . json_encode('.' . $selector) . ").dropdown();
263
				})(jQuery);"
264
		);
265
266
		static::$loaded[__METHOD__][$selector] = true;
267
268
		return;
269
	}
270
271
	/**
272
	 * Add javascript support for Bootstrap modals
273
	 *
274
	 * @param   string  $selector  The ID selector for the modal.
275
	 * @param   array   $params    An array of options for the modal.
276
	 *                             Options for the modal can be:
277
	 *                             - backdrop  boolean  Includes a modal-backdrop element.
278
	 *                             - keyboard  boolean  Closes the modal when escape key is pressed.
279
	 *                             - show      boolean  Shows the modal when initialized.
280
	 *                             - remote    string   An optional remote URL to load
281
	 *
282
	 * @return  void
283
	 */
284
	public static function modal($selector = 'modal', $params = array())
285
	{
286
		$sig = md5(serialize(array($selector, $params)));
287
288
		if (!isset(static::$loaded[__METHOD__][$sig]))
289
		{
290
			// Include Bootstrap framework
291
			static::framework();
292
293
			// Setup options object
294
			$opt['backdrop'] = (isset($params['backdrop']) && ($params['backdrop'])) ? (boolean) $params['backdrop'] : true;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$opt was never initialized. Although not strictly required by PHP, it is generally a good practice to add $opt = array(); before regardless.
Loading history...
295
			$opt['keyboard'] = (isset($params['keyboard']) && ($params['keyboard'])) ? (boolean) $params['keyboard'] : true;
296
			$opt['show']     = (isset($params['show']) && ($params['show'])) ? (boolean) $params['show'] : true;
297
			$opt['remote']   = (isset($params['remote']) && ($params['remote'])) ? $params['remote'] : '';
298
299
			// Attach the modal to document
300
			JFactory::getDocument()->addScriptDeclaration(
301
				"(function($){
302
					$(" . json_encode('#' . $selector) . ").modal(" . json_encode($opt) . ");
303
					})(jQuery);"
304
			);
305
306
			// Set static array
307
			static::$loaded[__METHOD__][$sig] = true;
308
		}
309
310
		return;
311
	}
312
313
	/**
314
	 * Method to render a Bootstrap modal
315
	 *
316
	 * @param   string  $selector  The ID selector for the modal.
317
	 * @param   array   $params    An array of options for the modal.
318
	 *                             Options for the modal can be:
319
	 *                             - title     string   The modal title
320
	 *                             - backdrop  mixed    A boolean select if a modal-backdrop element should be included (default = true)
321
	 *                                                  The string 'static' includes a backdrop which doesn't close the modal on click.
322
	 *                             - keyboard  boolean  Closes the modal when escape key is pressed (default = true)
323
	 *                             - closeButton  boolean  Display modal close button (default = true)
324
	 *                             - animation boolean  Fade in from the top of the page (default = true)
325
	 *                             - footer    string   Optional markup for the modal footer
326
	 *                             - url       string   URL of a resource to be inserted as an <iframe> inside the modal body
327
	 *                             - height    string   height of the <iframe> containing the remote resource
328
	 *                             - width     string   width of the <iframe> containing the remote resource
329
	 * @param   string  $body      Markup for the modal body. Appended after the <iframe> if the url option is set
330
	 *
331
	 * @return  string  HTML markup for a modal
332
	 *
333
	 * @since   1.4
334
	 */
335
	public static function renderModal($selector = 'modal', $params = array(), $body = '')
336
	{
337
		// Include Bootstrap framework
338
		static::framework();
339
340
		$layoutData = array(
341
			'selector' => $selector,
342
			'params'   => $params,
343
			'body'     => $body,
344
		);
345
346
		if (RHtmlMedia::getFramework() == 'bootstrap3')
347
		{
348
			return RLayoutHelper::render('modal.dialog', $layoutData);
0 ignored issues
show
Bug introduced by
$layoutData of type array<string,array|string> is incompatible with the type object expected by parameter $displayData of RLayoutHelper::render(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

348
			return RLayoutHelper::render('modal.dialog', /** @scrutinizer ignore-type */ $layoutData);
Loading history...
349
		}
350
		else
351
		{
352
			return JLayoutHelper::render('joomla.modal.main', $layoutData);
0 ignored issues
show
Bug introduced by
$layoutData of type array<string,array|string> is incompatible with the type object expected by parameter $displayData of JLayoutHelper::render(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

352
			return JLayoutHelper::render('joomla.modal.main', /** @scrutinizer ignore-type */ $layoutData);
Loading history...
353
		}
354
	}
355
356
	/**
357
	 * Add javascript support for Bootstrap popovers
358
	 *
359
	 * Use element's Title as popover content
360
	 *
361
	 * @param   string  $selector  Selector for the popover
362
	 * @param   array   $params    An array of options for the popover.
363
	 *                  Options for the popover can be:
364
	 *                      animation  boolean          apply a css fade transition to the popover
365
	 *                      html       boolean          Insert HTML into the popover. If false, jQuery's text method will be used to insert
366
	 *                                                  content into the dom.
367
	 *                      placement  string|function  how to position the popover - top | bottom | left | right
368
	 *                      selector   string           If a selector is provided, popover objects will be delegated to the specified targets.
369
	 *                      trigger    string           how popover is triggered - hover | focus | manual
370
	 *                      title      string|function  default title value if `title` tag isn't present
371
	 *                      content    string|function  default content value if `data-content` attribute isn't present
372
	 *                      delay      number|object    delay showing and hiding the popover (ms) - does not apply to manual trigger type
373
	 *                                                  If a number is supplied, delay is applied to both hide/show
374
	 *                                                  Object structure is: delay: { show: 500, hide: 100 }
375
	 *                      container  string|boolean   Appends the popover to a specific element: { container: 'body' }
376
	 *
377
	 * @return  void
378
	 */
379
	public static function popover($selector = '.hasPopover', $params = array())
380
	{
381
		// Only load once
382
		if (isset(static::$loaded[__METHOD__][$selector]))
383
		{
384
			return;
385
		}
386
387
		// Include Bootstrap framework
388
		static::framework();
389
390
		$opt['animation'] = isset($params['animation']) ? $params['animation'] : null;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$opt was never initialized. Although not strictly required by PHP, it is generally a good practice to add $opt = array(); before regardless.
Loading history...
391
		$opt['html']      = isset($params['html']) ? $params['html'] : true;
392
		$opt['placement'] = isset($params['placement']) ? $params['placement'] : null;
393
		$opt['selector']  = isset($params['selector']) ? $params['selector'] : null;
394
		$opt['title']     = isset($params['title']) ? $params['title'] : null;
395
		$opt['trigger']   = isset($params['trigger']) ? $params['trigger'] : 'hover focus';
396
		$opt['content']   = isset($params['content']) ? $params['content'] : null;
397
		$opt['delay']     = isset($params['delay']) ? $params['delay'] : null;
398
		$opt['container'] = isset($params['container']) ? $params['container'] : 'body';
399
400
		// Attach the popover to the document
401
		JFactory::getDocument()->addScriptDeclaration(
402
			"jQuery(document).ready(function()
403
			{
404
				jQuery(" . json_encode($selector) . ").popover(" . json_encode($opt) . ");
405
			});"
406
		);
407
408
		static::$loaded[__METHOD__][$selector] = true;
409
410
		return;
411
	}
412
413
	/**
414
	 * Add javascript support for Bootstrap ScrollSpy
415
	 *
416
	 * @param   string  $selector  The ID selector for the ScrollSpy element.
417
	 * @param   array   $params    An array of options for the ScrollSpy.
418
	 *                             Options for the ScrollSpy can be:
419
	 *                             - offset  number  Pixels to offset from top when calculating position of scroll.
420
	 *
421
	 * @return  void
422
	 */
423
	public static function scrollspy($selector = 'navbar', $params = array())
424
	{
425
		$sig = md5(serialize(array($selector, $params)));
426
427
		if (!isset(static::$loaded[__METHOD__][$sig]))
428
		{
429
			// Include Bootstrap framework
430
			static::framework();
431
432
			// Setup options object
433
			$opt['offset'] = (isset($params['offset']) && ($params['offset'])) ? (int) $params['offset'] : 10;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$opt was never initialized. Although not strictly required by PHP, it is generally a good practice to add $opt = array(); before regardless.
Loading history...
434
435
			// Attach ScrollSpy to document
436
			JFactory::getDocument()->addScriptDeclaration(
437
				"(function($){
438
					$(" . json_encode('#' . $selector) . ").scrollspy(" . json_encode($opt) . ");
439
					})(jQuery);"
440
			);
441
442
			// Set static array
443
			static::$loaded[__METHOD__][$sig] = true;
444
		}
445
446
		return;
447
	}
448
449
	/**
450
	 * Add javascript support for Bootstrap tooltips
451
	 *
452
	 * Add a title attribute to any element in the form
453
	 * title="title::text"
454
	 *
455
	 * @param   string  $selector  The ID selector for the tooltip.
456
	 * @param   array   $params    An array of options for the tooltip.
457
	 *                             Options for the tooltip can be:
458
	 *                             - animation  boolean          Apply a CSS fade transition to the tooltip
459
	 *                             - html       boolean          Insert HTML into the tooltip. If false, jQuery's text method will be used to insert
460
	 *                                                           content into the dom.
461
	 *                             - placement  string|function  How to position the tooltip - top | bottom | left | right
462
	 *                             - selector   string           If a selector is provided, tooltip objects will be delegated to the specified targets.
463
	 *                             - title      string|function  Default title value if `title` tag isn't present
464
	 *                             - trigger    string           How tooltip is triggered - hover | focus | manual
465
	 *                             - delay      integer          Delay showing and hiding the tooltip (ms) - does not apply to manual trigger type
466
	 *                                                           If a number is supplied, delay is applied to both hide/show
467
	 *                                                           Object structure is: delay: { show: 500, hide: 100 }
468
	 *                             - container  string|boolean   Appends the popover to a specific element: { container: 'body' }
469
	 *
470
	 * @return  void
471
	 */
472
	public static function tooltip($selector = '.hasTooltip', $params = array())
473
	{
474
		if (!isset(static::$loaded[__METHOD__][$selector]))
475
		{
476
			// Include Bootstrap framework
477
			static::framework();
478
479
			// Setup options object
480
			$opt['animation'] = (isset($params['animation']) && ($params['animation'])) ? (boolean) $params['animation'] : null;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$opt was never initialized. Although not strictly required by PHP, it is generally a good practice to add $opt = array(); before regardless.
Loading history...
481
			$opt['html']      = (isset($params['html']) && ($params['html'])) ? (boolean) $params['html'] : true;
482
			$opt['placement'] = (isset($params['placement']) && ($params['placement'])) ? (string) $params['placement'] : null;
483
			$opt['selector']  = (isset($params['selector']) && ($params['selector'])) ? (string) $params['selector'] : null;
484
			$opt['title']     = (isset($params['title']) && ($params['title'])) ? (string) $params['title'] : null;
485
			$opt['trigger']   = (isset($params['trigger']) && ($params['trigger'])) ? (string) $params['trigger'] : 'hover focus';
486
			$opt['delay']     = (isset($params['delay']) && ($params['delay'])) ? (is_array($params['delay']) ? $params['delay'] : (int) $params['delay']) : null;
487
			$opt['container'] = (isset($params['container']) && ($params['container'])) ? (int) $params['container'] : 'body';
488
			$opt['template']  = isset($params['template']) ? (string) $params['template'] : null;
489
			$onShow           = isset($params['onShow']) ? (string) $params['onShow'] : null;
490
			$onShown          = isset($params['onShown']) ? (string) $params['onShown'] : null;
491
			$onHide           = isset($params['onHide']) ? (string) $params['onHide'] : null;
492
			$onHidden         = isset($params['onHidden']) ? (string) $params['onHidden'] : null;
493
494
			// Build the script.
495
			$script   = array();
496
			$script[] = "jQuery(document).ready(function(){";
497
			$script[] = "\tjQuery(" . json_encode($selector) . ").tooltip(" . json_encode($opt) . ");";
498
499
			if (!is_null($onShow))
500
			{
501
				$script[] = "\tjQuery(" . json_encode($selector) . ").on('show.bs.tooltip', " . $onShow . ");";
502
			}
503
504
			if (!is_null($onShown))
505
			{
506
				$script[] = "\tjQuery(" . json_encode($selector) . ").on('shown.bs.tooltip', " . $onShown . ");";
507
			}
508
509
			if (!is_null($onHide))
510
			{
511
				$script[] = "\tjQuery(" . json_encode($selector) . ").on('hideme.bs.tooltip', " . $onHide . ");";
512
			}
513
514
			if (!is_null($onHidden))
515
			{
516
				$script[] = "\tjQuery(" . json_encode($selector) . ").on('hidden.bs.tooltip', " . $onHidden . ");";
517
			}
518
519
			$script[] = "});";
520
521
			// Attach tooltips to document
522
			JFactory::getDocument()->addScriptDeclaration(implode("\n", $script));
523
524
			// Set static array
525
			static::$loaded[__METHOD__][$selector] = true;
526
		}
527
528
		return;
529
	}
530
531
	/**
532
	 * Loads js and css files needed by Bootstrap Tooltip Extended plugin
533
	 *
534
	 * @param   boolean  $extended  If true, bootstrap-tooltip-extended.js and .css files are loaded
535
	 *
536
	 * @return  void
537
	 *
538
	 * @since   3.6
539
	 */
540
	public static function tooltipExtended($extended = true)
541
	{
542
		if ($extended)
543
		{
544
			JHtml::_('script', 'jui/bootstrap-tooltip-extended.min.js', false, true);
545
			JHtml::_('stylesheet', 'jui/bootstrap-tooltip-extended.css', false, true);
546
		}
547
	}
548
549
	/**
550
	 * Add javascript support for Bootstrap typeahead
551
	 *
552
	 * @param   string  $selector  The selector for the typeahead element.
553
	 * @param   array   $params    An array of options for the typeahead element.
554
	 *                             Options for the tooltip can be:
555
	 *                             - source       array, function  The data source to query against. May be an array of strings or a function.
556
	 *                                                             The function is passed two arguments, the query value in the input field and the
557
	 *                                                             process callback. The function may be used synchronously by returning the data
558
	 *                                                             source directly or asynchronously via the process callback's single argument.
559
	 *                             - items        number           The max number of items to display in the dropdown.
560
	 *                             - minLength    number           The minimum character length needed before triggering autocomplete suggestions
561
	 *                             - matcher      function         The method used to determine if a query matches an item. Accepts a single argument,
562
	 *                                                             the item against which to test the query. Access the current query with this.query.
563
	 *                                                             Return a boolean true if query is a match.
564
	 *                             - sorter       function         Method used to sort autocomplete results. Accepts a single argument items and has
565
	 *                                                             the scope of the typeahead instance. Reference the current query with this.query.
566
	 *                             - updater      function         The method used to return selected item. Accepts a single argument, the item and
567
	 *                                                             has the scope of the typeahead instance.
568
	 *                             - highlighter  function         Method used to highlight autocomplete results. Accepts a single argument item and
569
	 *                                                             has the scope of the typeahead instance. Should return html.
570
	 *
571
	 * @return  void
572
	 */
573
	public static function typeahead($selector = '.typeahead', $params = array())
574
	{
575
		if (!isset(static::$loaded[__METHOD__][$selector]))
576
		{
577
			// Include Bootstrap framework
578
			static::framework();
579
580
			// Setup options object
581
			$opt['source']      = (isset($params['source']) && ($params['source'])) ? $params['source'] : '[]';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$opt was never initialized. Although not strictly required by PHP, it is generally a good practice to add $opt = array(); before regardless.
Loading history...
582
			$opt['items']       = (isset($params['items']) && ($params['items'])) ? (int) $params['items'] : 8;
583
			$opt['minLength']   = (isset($params['minLength']) && ($params['minLength'])) ? (int) $params['minLength'] : 1;
584
			$opt['matcher']     = (isset($params['matcher']) && ($params['matcher'])) ? (string) $params['matcher'] : null;
585
			$opt['sorter']      = (isset($params['sorter']) && ($params['sorter'])) ? (string) $params['sorter'] : null;
586
			$opt['updater']     = (isset($params['updater']) && ($params['updater'])) ? (string) $params['updater'] : null;
587
			$opt['highlighter'] = (isset($params['highlighter']) && ($params['highlighter'])) ? (int) $params['highlighter'] : null;
588
589
			// Attach typehead to document
590
			JFactory::getDocument()->addScriptDeclaration(
591
				"jQuery(document).ready(function()
592
				{
593
					jQuery(" . json_encode($selector) . ").typeahead(" . json_encode($opt) . ");
594
				});"
595
			);
596
597
			// Set static array
598
			static::$loaded[__METHOD__][$selector] = true;
599
		}
600
601
		return;
602
	}
603
604
	/**
605
	 * Add javascript support for Bootstrap accordians and insert the accordian
606
	 *
607
	 * @param   string  $selector  The ID selector for the tooltip.
608
	 * @param   array   $params    An array of options for the tooltip.
609
	 *                             Options for the tooltip can be:
610
	 *                             - parent  selector  If selector then all collapsible elements under the specified parent will be closed when this
611
	 *                                                 collapsible item is shown. (similar to traditional accordion behavior)
612
	 *                             - toggle  boolean   Toggles the collapsible element on invocation
613
	 *                             - active  string    Sets the active slide during load
614
	 *
615
	 *                             - onShow    function  This event fires immediately when the show instance method is called.
616
	 *                             - onShown   function  This event is fired when a collapse element has been made visible to the user
617
	 *                                                   (will wait for css transitions to complete).
618
	 *                             - onHide    function  This event is fired immediately when the hide method has been called.
619
	 *                             - onHidden  function  This event is fired when a collapse element has been hidden from the user
620
	 *                                                   (will wait for css transitions to complete).
621
	 *
622
	 * @return  string  HTML for the accordian
623
	 */
624
	public static function startAccordion($selector = 'myAccordian', $params = array())
625
	{
626
		$sig = md5(serialize(array($selector, $params)));
627
628
		if (!isset(static::$loaded[__METHOD__][$sig]))
629
		{
630
			// Include Bootstrap framework
631
			static::framework();
632
633
			// Setup options object
634
			$opt['parent'] = isset($params['parent']) && $params['parent'] ? ($params['parent'] == true ? '#' . $selector : $params['parent']) : false;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$opt was never initialized. Although not strictly required by PHP, it is generally a good practice to add $opt = array(); before regardless.
Loading history...
635
			$opt['toggle'] = isset($params['toggle']) && $params['toggle']
636
				? (boolean) $params['toggle'] : ($opt['parent'] === false
637
				|| isset($params['active']) ? false : true);
638
			$onShow        = isset($params['onShow']) ? (string) $params['onShow'] : null;
639
			$onShown       = isset($params['onShown']) ? (string) $params['onShown'] : null;
640
			$onHide        = isset($params['onHide']) ? (string) $params['onHide'] : null;
641
			$onHidden      = isset($params['onHidden']) ? (string) $params['onHidden'] : null;
642
643
			$options = json_encode($opt);
644
645
			$opt['active'] = (isset($params['active']) && ($params['active'])) ? (string) $params['active'] : '';
646
647
			// Build the script.
648
			$script   = array();
649
			$script[] = "jQuery(document).ready(function($){";
650
			$script[] = "\t$('#" . $selector . "').collapse(" . $options . ")";
651
652
			if ($onShow !== null)
653
			{
654
				$script[] = "\t.on('show', " . $onShow . ")";
655
			}
656
657
			if ($onShown !== null)
658
			{
659
				$script[] = "\t.on('shown', " . $onShown . ")";
660
			}
661
662
			if ($onHide !== null)
663
			{
664
				$script[] = "\t.on('hideme', " . $onHide . ")";
665
			}
666
667
			if ($onHidden !== null)
668
			{
669
				$script[] = "\t.on('hidden', " . $onHidden . ")";
670
			}
671
672
			$parents = array_key_exists(__METHOD__, static::$loaded) ? array_filter(array_column(static::$loaded[__METHOD__], 'parent')) : array();
673
674
			if ($opt['parent'] && empty($parents))
675
			{
676
				$script[] = "
677
					$(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) {
678
						var \$this   = $(this), href
679
						var parent  = \$this.attr('data-parent')
680
						var \$parent = parent && $(parent)
681
682
						if (\$parent) \$parent.find('[data-toggle=collapse][data-parent=' + parent + ']').not(\$this).addClass('collapsed')
683
					})";
684
			}
685
686
			$script[] = "});";
687
688
			// Attach accordion to document
689
			JFactory::getDocument()->addScriptDeclaration(implode("\n", $script));
690
691
			// Set static array
692
			static::$loaded[__METHOD__][$sig]     = true;
693
			static::$loaded[__METHOD__]['active'] = $opt['active'];
694
		}
695
696
		return '<div id="' . $selector . '" class="accordion">';
697
	}
698
699
	/**
700
	 * Close the current accordion
701
	 *
702
	 * @return  string  HTML to close the accordian
703
	 */
704
	public static function endAccordion()
705
	{
706
		return '</div>';
707
	}
708
709
	/**
710
	 * Begins the display of a new accordion slide.
711
	 *
712
	 * @param   string  $selector  Identifier of the accordion group.
713
	 * @param   string  $text      Text to display.
714
	 * @param   string  $id        Identifier of the slide.
715
	 * @param   string  $class     Class of the accordion group.
716
	 *
717
	 * @return  string  HTML to add the slide
718
	 */
719
	public static function addSlide($selector, $text, $id, $class = '')
720
	{
721
		$in     = (static::$loaded['JHtmlRbootstrap::startAccordion']['active'] == $id) ? ' in' : '';
722
		$parent = static::$loaded['JHtmlRbootstrap::startAccordion'][$selector]['parent'] ?
723
			' data-parent="' . static::$loaded['JHtmlRbootstrap::startAccordion'][$selector]['parent'] . '"' : '';
724
		$class  = (!empty($class)) ? ' ' . $class : '';
725
726
		$html = '<div class="panel panel-default accordion-group' . $class . '">'
727
			. '<div class="panel-heading accordion-heading">'
728
			. '<strong><a href="#' . $id . '" data-parent="#' . $selector . '" data-toggle="collapse" ' . $parent . ' class="accordion-toggle">'
729
			. $text
730
			. '</a></strong>'
731
			. '</div>'
732
			. '<div class="panel-collapse accordion-body collapse' . $in . '" id="' . $id . '">'
733
			. '<div class="panel-body accordion-inner">';
734
735
		return $html;
736
	}
737
738
	/**
739
	 * Close the current slide
740
	 *
741
	 * @return  string  HTML to close the slide
742
	 */
743
	public static function endSlide()
744
	{
745
		return '</div></div></div>';
746
	}
747
748
	/**
749
	 * Creates a tab pane
750
	 *
751
	 * @param   string  $selector  The pane identifier.
752
	 * @param   array   $params    The parameters for the pane
753
	 *
754
	 * @return  string
755
	 */
756
	public static function startTabSet($selector = 'myTab', $params = array())
757
	{
758
		$sig = md5(serialize(array($selector, $params)));
759
760
		if (!isset(static::$loaded[__METHOD__][$sig]))
761
		{
762
			// Include Bootstrap framework
763
			static::framework();
764
765
			// Setup options object
766
			$opt['active'] = (isset($params['active']) && ($params['active'])) ? (string) $params['active'] : '';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$opt was never initialized. Although not strictly required by PHP, it is generally a good practice to add $opt = array(); before regardless.
Loading history...
767
768
			// Attach tabs to document
769
			JFactory::getDocument()
770
				->addScriptDeclaration(RLayoutHelper::render('libraries.cms.html.bootstrap.starttabsetscript', array('selector' => $selector)));
0 ignored issues
show
Bug introduced by
array('selector' => $selector) of type array<string,string> is incompatible with the type object expected by parameter $displayData of RLayoutHelper::render(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

770
				->addScriptDeclaration(RLayoutHelper::render('libraries.cms.html.bootstrap.starttabsetscript', /** @scrutinizer ignore-type */ array('selector' => $selector)));
Loading history...
771
772
			// Set static array
773
			static::$loaded[__METHOD__][$sig]                = true;
774
			static::$loaded[__METHOD__][$selector]['active'] = $opt['active'];
775
		}
776
777
		$html = RLayoutHelper::render('libraries.cms.html.bootstrap.starttabset', array('selector' => $selector));
778
779
		return $html;
780
	}
781
782
	/**
783
	 * Close the current tab pane
784
	 *
785
	 * @return  string  HTML to close the pane
786
	 */
787
	public static function endTabSet()
788
	{
789
		$html = RLayoutHelper::render('libraries.cms.html.bootstrap.endtabset');
790
791
		return $html;
792
	}
793
794
	/**
795
	 * Begins the display of a new tab content panel.
796
	 *
797
	 * @param   string  $selector  Identifier of the panel.
798
	 * @param   string  $id        The ID of the div element
799
	 * @param   string  $title     The title text for the new UL tab
800
	 *
801
	 * @return  string  HTML to start a new panel
802
	 */
803
	public static function addTab($selector, $id, $title)
804
	{
805
		static $tabScriptLayout = null;
806
		static $tabLayout       = null;
807
808
		$tabScriptLayout = is_null($tabScriptLayout) ? new RLayoutFile('libraries.cms.html.bootstrap.addtabscript') : $tabScriptLayout;
809
		$tabLayout       = is_null($tabLayout) ? new RLayoutFile('libraries.cms.html.bootstrap.addtab') : $tabLayout;
810
811
		$active = (static::$loaded['JHtmlRbootstrap::startTabSet'][$selector]['active'] == $id) ? ' active' : '';
812
813
		// Inject tab into UL
814
		JFactory::getDocument()->addScriptDeclaration(
815
			$tabScriptLayout->render(
816
				array(
817
					'selector' => $selector,
818
					'id' => $id,
819
					'active' => $active,
820
					'title' => $title
821
				)
822
			)
823
		);
824
825
		$html = $tabLayout->render(array('id' => $id, 'active' => $active));
826
827
		return $html;
828
	}
829
830
	/**
831
	 * Close the current tab content panel
832
	 *
833
	 * @return  string  HTML to close the pane
834
	 */
835
	public static function endTab()
836
	{
837
		$html = RLayoutHelper::render('libraries.cms.html.bootstrap.endtab');
838
839
		return $html;
840
	}
841
842
	/**
843
	 * Creates a tab pane
844
	 *
845
	 * @param   string  $selector  The pane identifier.
846
	 * @param   array   $params    The parameters for the pane
847
	 *
848
	 * @return  string
849
	 *
850
	 * @since   3.0
851
	 * @deprecated  4.0	Use JHtml::_('bootstrap.startTabSet') instead.
852
	 */
853
	public static function startPane($selector = 'myTab', $params = array())
854
	{
855
		$sig = md5(serialize(array($selector, $params)));
856
857
		if (!isset(static::$loaded['JHtmlRBootstrap::startTabSet'][$sig]))
858
		{
859
			// Include Bootstrap framework
860
			static::framework();
861
862
			// Setup options object
863
			$opt['active'] = isset($params['active']) ? (string) $params['active'] : '';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$opt was never initialized. Although not strictly required by PHP, it is generally a good practice to add $opt = array(); before regardless.
Loading history...
864
865
			// Attach tab to document
866
			JFactory::getDocument()->addScriptDeclaration(
867
				"(function($){
868
					$(" . json_encode('#' . $selector . ' a') . ").click(function (e) {
869
						e.preventDefault();
870
						$(this).tab('show');
871
					});
872
				})(jQuery);"
873
			);
874
875
			// Set static array
876
			static::$loaded['JHtmlRBootstrap::startTabSet'][$sig]                = true;
877
			static::$loaded['JHtmlRBootstrap::startTabSet'][$selector]['active'] = $opt['active'];
878
		}
879
880
		return '<div class="tab-content" id="' . $selector . 'Content">';
881
	}
882
883
	/**
884
	 * Close the current tab pane
885
	 *
886
	 * @return  string  HTML to close the pane
887
	 *
888
	 * @since   3.0
889
	 * @deprecated  4.0	Use JHtml::_('bootstrap.endTabSet') instead.
890
	 */
891
	public static function endPane()
892
	{
893
		return '</div>';
894
	}
895
896
	/**
897
	 * Begins the display of a new tab content panel.
898
	 *
899
	 * @param   string  $selector  Identifier of the panel.
900
	 * @param   string  $id        The ID of the div element
901
	 *
902
	 * @return  string  HTML to start a new panel
903
	 *
904
	 * @since   3.0
905
	 * @deprecated  4.0 Use JHtml::_('bootstrap.addTab') instead.
906
	 */
907
	public static function addPanel($selector, $id)
908
	{
909
		$active = (static::$loaded['JHtmlRBootstrap::startTabSet'][$selector]['active'] == $id) ? ' active' : '';
910
911
		return '<div id="' . $id . '" class="tab-pane' . $active . '">';
912
	}
913
914
	/**
915
	 * Close the current tab content panel
916
	 *
917
	 * @return  string  HTML to close the pane
918
	 *
919
	 * @since   3.0
920
	 * @deprecated  4.0 Use JHtml::_('bootstrap.endTab') instead.
921
	 */
922
	public static function endPanel()
923
	{
924
		return '</div>';
925
	}
926
927
	/**
928
	 * Loads CSS files needed by Bootstrap
929
	 *
930
	 * @param   boolean  $includeMainCss  If true, main bootstrap.css files are loaded
931
	 * @param   string   $direction       rtl or ltr direction. If empty, ltr is assumed
932
	 * @param   array    $attribs         Optional array of attributes to be passed to JHtml::_('stylesheet')
933
	 *
934
	 * @return  void
935
	 */
936
	public static function loadCss($includeMainCss = true, $direction = 'ltr', $attribs = array())
937
	{
938
		// Load Bootstrap main CSS
939
		if ($includeMainCss)
940
		{
941
			JHtml::_('stylesheet', 'jui/bootstrap.min.css', $attribs, true);
942
			JHtml::_('stylesheet', 'jui/bootstrap-responsive.min.css', $attribs, true);
943
			JHtml::_('stylesheet', 'jui/bootstrap-extended.css', $attribs, true);
944
		}
945
946
		// Load Bootstrap RTL CSS
947
		if ($direction === 'rtl')
948
		{
949
			JHtml::_('stylesheet', 'jui/bootstrap-rtl.css', $attribs, true);
950
		}
951
	}
952
953
	/**
954
	 * Load font-awesome
955
	 *
956
	 * @return  void
957
	 */
958
	public static function fontawesome()
959
	{
960
		// Include Bootstrap framework
961
		static::framework();
962
963
		RHelperAsset::load('lib/font-awesome/css/font-awesome.min.css', static::EXTENSION);
964
	}
965
966
	/**
967
	 * Load the bootstrap-checkbox.
968
	 *
969
	 * @return  void
970
	 */
971
	public static function checkbox()
972
	{
973
		static::framework();
974
975
		RHelperAsset::load('lib/bootstrap-checkbox/css/bootstrap-checkbox.min.css', static::EXTENSION);
976
		RHelperAsset::load('lib/bootstrap-checkbox/js/bootstrap-checkbox.min.js', static::EXTENSION);
977
	}
978
}
979