Completed
Push — release-2.1 ( e5becb...01aa55 )
by John
18:36 queued 08:55
created

$.fn.SMFtooltip   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 4
rs 10
1
/**
2
 * SMFtooltip, Basic JQuery function to provide styled tooltips
3
 *
4
 * - will use the hoverintent plugin if available
5
 * - shows the tooltip in a div with the class defined in tooltipClass
6
 * - moves all selector titles to a hidden div and removes the title attribute to
7
 *   prevent any default browser actions
8
 * - attempts to keep the tooltip on screen
9
 *
10
 * Simple Machines Forum (SMF)
11
 *
12
 * @package SMF
13
 * @author Simple Machines http://www.simplemachines.org
14
 * @copyright 2017 Simple Machines and individual contributors
15
 * @license http://www.simplemachines.org/about/smf/license.php BSD
16
 *
17
 * @version 2.1 Beta 3
18
 *
19
 */
20
21
(function($) {
22
	$.fn.SMFtooltip = function(oInstanceSettings) {
23
		$.fn.SMFtooltip.oDefaultsSettings = {
24
			followMouse: 1,
25
			hoverIntent: {sensitivity: 10, interval: 300, timeout: 50},
26
			positionTop: 12,
27
			positionLeft: 12,
28
			tooltipID: 'smf_tooltip', // ID used on the outer div
29
			tooltipTextID: 'smf_tooltipText', // as above but on the inner div holding the text
30
			tooltipClass: 'tooltip', // The class applied to the outer div (that displays on hover), use this in your css
31
			tooltipSwapClass: 'smf_swaptip', // a class only used internally, change only if you have a conflict
32
			tooltipContent: 'html' // display captured title text as html or text
33
		};
34
35
		// account for any user options
36
		var oSettings = $.extend({}, $.fn.SMFtooltip.oDefaultsSettings , oInstanceSettings || {});
37
38
		// move passed selector titles to a hidden span, then remove the selector title to prevent any default browser actions
39
		$(this).each(function()
40
		{
41
			var sTitle = $('<span class="' + oSettings.tooltipSwapClass + '">' + htmlspecialchars(this.title) + '</span>').hide();
42
			$(this).append(sTitle).attr('title', '');
43
		});
44
45
		// determine where we are going to place the tooltip, while trying to keep it on screen
46
		var positionTooltip = function(event)
47
		{
48
			var iPosx = 0;
49
			var iPosy = 0;
50
51
			if (!event)
52
				var event = window.event;
53
54
			if (event.pageX || event.pageY)
55
			{
56
				iPosx = event.pageX;
57
				iPosy = event.pageY;
58
			}
59
			else if (event.clientX || event.clientY)
60
			{
61
				iPosx = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
62
				iPosy = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
63
			}
64
65
			// Position of the tooltip top left corner and its size
66
			var oPosition = {
67
				x: iPosx + oSettings.positionLeft,
68
				y: iPosy + oSettings.positionTop,
69
				w: $('#' + oSettings.tooltipID).width(),
70
				h: $('#' + oSettings.tooltipID).height()
71
			}
72
73
			// Display limits and window scroll postion
74
			var oLimits = {
75
				x: $(window).scrollLeft(),
76
				y: $(window).scrollTop(),
77
				w: $(window).width() - 24,
78
				h: $(window).height() - 24
79
			};
80
81
			// don't go off screen with our tooltop
82
			if ((oPosition.y + oPosition.h > oLimits.y + oLimits.h) && (oPosition.x + oPosition.w > oLimits.x + oLimits.w))
83
			{
84
				oPosition.x = (oPosition.x - oPosition.w) - 45;
85
				oPosition.y = (oPosition.y - oPosition.h) - 45;
86
			}
87
			else if ((oPosition.x + oPosition.w) > (oLimits.x + oLimits.w))
88
			{
89
				oPosition.x = oPosition.x - (((oPosition.x + oPosition.w) - (oLimits.x + oLimits.w)) + 24);
90
			}
91
			else if (oPosition.y + oPosition.h > oLimits.y + oLimits.h)
92
			{
93
				oPosition.y = oPosition.y - (((oPosition.y + oPosition.h) - (oLimits.y + oLimits.h)) + 24);
94
			}
95
96
			// finally set the position we determined
97
			$('#' + oSettings.tooltipID).css({'left': oPosition.x + 'px', 'top': oPosition.y + 'px'});
98
		}
99
100
		// used to show a tooltip
101
		var showTooltip = function(){
102
			$('#' + oSettings.tooltipID + ' #' + oSettings.tooltipTextID).show();
103
		}
104
105
		// used to hide a tooltip
106
		var hideTooltip = function(valueOfThis){
0 ignored issues
show
Unused Code introduced by
The parameter valueOfThis is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
107
			$('#' + oSettings.tooltipID).fadeOut('slow').trigger("unload").remove();
108
		}
109
110
		// used to keep html encoded
111
		function htmlspecialchars(string)
112
		{
113
			return $('<span>').text(string).html();
114
		}
115
116
		// for all of the elements that match the selector on the page, lets set up some actions
117
		return this.each(function(index)
0 ignored issues
show
Unused Code introduced by
The parameter index is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
118
		{
119
			// if we find hoverIntent use it
120
			if ($.fn.hoverIntent)
121
			{
122
				$(this).hoverIntent({
123
					sensitivity: oSettings.hoverIntent.sensitivity,
124
					interval: oSettings.hoverIntent.interval,
125
					over: smf_tooltip_on,
126
					timeout: oSettings.hoverIntent.timeout,
127
					out: smf_tooltip_off
128
				});
129
			}
130
			else
131
			{
132
				// plain old hover it is
133
				$(this).hover(smf_tooltip_on, smf_tooltip_off);
134
			}
135
136
			// create the on tip action
137
			function smf_tooltip_on(event)
138
			{
139
				// If we have text in the hidden span element we created on page load
140
				if ($(this).children('.' + oSettings.tooltipSwapClass).text())
141
				{
142
					// create a ID'ed div with our style class that holds the tooltip info, hidden for now
143
					$('body').append('<div id="' + oSettings.tooltipID + '" class="' + oSettings.tooltipClass + '"><div id="' + oSettings.tooltipTextID + '" style="display:none;"></div></div>');
144
145
					// load information in to our newly created div
146
					var tt = $('#' + oSettings.tooltipID);
147
					var ttContent = $('#' + oSettings.tooltipID + ' #' + oSettings.tooltipTextID);
148
149
					if (oSettings.tooltipContent == 'html')
150
						ttContent.html($(this).children('.' + oSettings.tooltipSwapClass).html());
151
					else
152
						ttContent.text($(this).children('.' + oSettings.tooltipSwapClass).text());
153
154
					oSettings.tooltipContent
0 ignored issues
show
introduced by
The result of the property access to oSettings.tooltipContent is not used.
Loading history...
155
156
					// show then position or it may postion off screen
157
					tt.show();
158
					showTooltip();
159
					positionTooltip(event);
160
				}
161
162
				return false;
163
			};
164
165
			// create the Bye bye tip
166
			function smf_tooltip_off(event)
0 ignored issues
show
Unused Code introduced by
The parameter event is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
167
			{
168
				hideTooltip(this);
169
				return false;
170
			};
171
172
			// create the tip move with the cursor
173
			if (oSettings.followMouse)
174
			{
175
				$(this).on("mousemove", function(event){
176
					positionTooltip(event);
177
					return false;
178
				});
179
			}
180
181
			// clear the tip on a click
182
			$(this).on("click", function(event){
0 ignored issues
show
Unused Code introduced by
The parameter event is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
183
				hideTooltip(this);
184
				return true;
185
			});
186
187
		});
188
	};
189
190
	// A simple plugin for deleting an element from the DOM.
191
	$.fn.fadeOutAndRemove = function(speed){
192
		$(this).fadeOut(speed,function(){
193
			$(this).remove();
194
		});
195
	};
196
197
	// Range to percent.
198
	$.fn.rangeToPercent = function(number, min, max){
199
		return ((number - min) / (max - min));
200
	};
201
202
	// Percent to range.
203
	$.fn.percentToRange = function(percent, min, max){
204
		return((max - min) * percent + min);
205
	};
206
207
})(jQuery);
208
209
/**
210
 * AnimaDrag
211
 * Animated jQuery Drag and Drop Plugin
212
 * Version 0.5.1 beta
213
 * Author Abel Mohler
214
 * Released with the MIT License: http://www.opensource.org/licenses/mit-license.php
215
 */
216
(function($){
217
	$.fn.animaDrag = function(o, callback) {
218
		var defaults = {
219
			speed: 400,
220
			interval: 300,
221
			easing: null,
222
			cursor: 'move',
223
			boundary: document.body,
224
			grip: null,
225
			overlay: true,
226
			after: function(e) {},
0 ignored issues
show
Unused Code introduced by
The parameter e is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
227
			during: function(e) {},
0 ignored issues
show
Unused Code introduced by
The parameter e is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
228
			before: function(e) {},
0 ignored issues
show
Unused Code introduced by
The parameter e is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
229
			afterEachAnimation: function(e) {}
0 ignored issues
show
Unused Code introduced by
The parameter e is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
230
		}
231
		if(typeof callback == 'function') {
232
				defaults.after = callback;
233
		}
234
		o = $.extend(defaults, o || {});
235
		return this.each(function() {
236
			var id, startX, startY, draggableStartX, draggableStartY, dragging = false, Ev, draggable = this,
237
			grip = ($(this).find(o.grip).length > 0) ? $(this).find(o.grip) : $(this);
238
			if(o.boundary) {
239
				var limitTop = $(o.boundary).offset().top, limitLeft = $(o.boundary).offset().left,
240
				limitBottom = limitTop + $(o.boundary).innerHeight(), limitRight = limitLeft + $(o.boundary).innerWidth();
241
			}
242
			grip.mousedown(function(e) {
243
				o.before.call(draggable, e);
244
245
				var lastX, lastY;
246
				dragging = true;
247
248
				Ev = e;
249
250
				startX = lastX = e.pageX;
251
				startY = lastY = e.pageY;
252
				draggableStartX = $(draggable).offset().left;
253
				draggableStartY = $(draggable).offset().top;
254
255
				$(draggable).css({
256
					position: 'absolute',
257
					left: draggableStartX + 'px',
258
					top: draggableStartY + 'px',
259
					cursor: o.cursor,
260
					zIndex: '1010'
261
				}).addClass('anima-drag').appendTo(document.body);
262
				if(o.overlay && $('#anima-drag-overlay').length == 0) {
263
					$('<div id="anima-drag-overlay"></div>').css({
264
						position: 'absolute',
265
						top: '0',
266
						left: '0',
267
						zIndex: '1000',
268
						width: $(document.body).outerWidth() + 'px',
269
						height: $(document.body).outerHeight() + 'px'
270
					}).appendTo(document.body);
271
				}
272
				else if(o.overlay) {
273
					$('#anima-drag-overlay').show();
274
				}
275
				id = setInterval(function() {
276
					if(lastX != Ev.pageX || lastY != Ev.pageY) {
277
						var positionX = draggableStartX - (startX - Ev.pageX), positionY = draggableStartY - (startY - Ev.pageY);
278
						if(positionX < limitLeft && o.boundary) {
0 ignored issues
show
Bug introduced by
The variable limitLeft does not seem to be initialized in case o.boundary on line 238 is false. Are you sure this can never be the case?
Loading history...
279
							positionX = limitLeft;
280
						}
281
						else if(positionX + $(draggable).innerWidth() > limitRight && o.boundary) {
0 ignored issues
show
Bug introduced by
The variable limitRight does not seem to be initialized in case o.boundary on line 238 is false. Are you sure this can never be the case?
Loading history...
282
							positionX = limitRight - $(draggable).outerWidth();
283
						}
284
						if(positionY < limitTop && o.boundary) {
0 ignored issues
show
Bug introduced by
The variable limitTop does not seem to be initialized in case o.boundary on line 238 is false. Are you sure this can never be the case?
Loading history...
285
							positionY = limitTop;
286
						}
287
						else if(positionY + $(draggable).innerHeight() > limitBottom && o.boundary) {
0 ignored issues
show
Bug introduced by
The variable limitBottom does not seem to be initialized in case o.boundary on line 238 is false. Are you sure this can never be the case?
Loading history...
288
							positionY = limitBottom - $(draggable).outerHeight();
289
						}
290
						$(draggable).stop().animate({
291
							left: positionX + 'px',
292
							top: positionY + 'px'
293
						}, o.speed, o.easing, function(){o.afterEachAnimation.call(draggable, Ev)});
294
					}
295
					lastX = Ev.pageX;
296
					lastY = Ev.pageY;
297
				}, o.interval);
298
				($.browser.safari || e.preventDefault());
299
			});
300
			$(document).mousemove(function(e) {
301
				if(dragging) {
302
					Ev = e;
303
					o.during.call(draggable, e);
304
				}
305
			});
306
			$(document).mouseup(function(e) {
307
				if(dragging) {
308
					$(draggable).css({
309
						cursor: '',
310
						zIndex: '990'
311
					}).removeClass('anima-drag');
312
					$('#anima-drag-overlay').hide().appendTo(document.body);
313
					clearInterval(id);
314
					o.after.call(draggable, e);
315
					dragging = false;
316
				}
317
			});
318
		});
319
	}
320
})(jQuery);
321
322
/*
323
 * jQuery Superfish Menu Plugin - v1.7.7
324
 * Copyright (c) 2015
325
 *
326
 * Dual licensed under the MIT and GPL licenses:
327
 *	http://www.opensource.org/licenses/mit-license.php
328
 *	http://www.gnu.org/licenses/gpl.html
329
 */
330
331
;(function ($, w) {
332
	"use strict";
333
334
	var methods = (function () {
335
		// private properties and methods go here
336
		var c = {
337
				bcClass: 'sf-breadcrumb',
338
				menuClass: 'sf-js-enabled',
339
				anchorClass: 'sf-with-ul',
340
				menuArrowClass: 'sf-arrows'
341
			},
342
			ios = (function () {
343
				var ios = /^(?![\w\W]*Windows Phone)[\w\W]*(iPhone|iPad|iPod)/i.test(navigator.userAgent);
344
				if (ios) {
345
					// tap anywhere on iOS to unfocus a submenu
346
					$('html').css('cursor', 'pointer').on('click', $.noop);
347
				}
348
				return ios;
349
			})(),
350
			wp7 = (function () {
351
				var style = document.documentElement.style;
352
				return ('behavior' in style && 'fill' in style && /iemobile/i.test(navigator.userAgent));
353
			})(),
354
			unprefixedPointerEvents = (function () {
355
				return (!!w.PointerEvent);
356
			})(),
357
			toggleMenuClasses = function ($menu, o) {
358
				var classes = c.menuClass;
359
				if (o.cssArrows) {
360
					classes += ' ' + c.menuArrowClass;
361
				}
362
				$menu.toggleClass(classes);
363
			},
364
			setPathToCurrent = function ($menu, o) {
365
				return $menu.find('li.' + o.pathClass).slice(0, o.pathLevels)
366
					.addClass(o.hoverClass + ' ' + c.bcClass)
367
						.filter(function () {
368
							return ($(this).children(o.popUpSelector).hide().show().length);
369
						}).removeClass(o.pathClass);
370
			},
371
			toggleAnchorClass = function ($li) {
372
				$li.children('a').toggleClass(c.anchorClass);
373
			},
374
			toggleTouchAction = function ($menu) {
375
				var msTouchAction = $menu.css('ms-touch-action');
376
				var touchAction = $menu.css('touch-action');
377
				touchAction = touchAction || msTouchAction;
378
				touchAction = (touchAction === 'pan-y') ? 'auto' : 'pan-y';
379
				$menu.css({
380
					'ms-touch-action': touchAction,
381
					'touch-action': touchAction
382
				});
383
			},
384
			applyHandlers = function ($menu, o) {
385
				var targets = 'li:has(' + o.popUpSelector + ')';
386
				if ($.fn.hoverIntent && !o.disableHI) {
387
					$menu.hoverIntent(over, out, targets);
388
				}
389
				else {
390
					$menu
391
						.on('mouseenter.superfish', targets, over)
392
						.on('mouseleave.superfish', targets, out);
393
				}
394
				var touchevent = 'MSPointerDown.superfish';
395
				if (unprefixedPointerEvents) {
396
					touchevent = 'pointerdown.superfish';
397
				}
398
				if (!ios) {
399
					touchevent += ' touchend.superfish';
400
				}
401
				if (wp7) {
402
					touchevent += ' mousedown.superfish';
403
				}
404
				$menu
405
					.on('focusin.superfish', 'li', over)
406
					.on('focusout.superfish', 'li', out)
407
					.on(touchevent, 'a', o, touchHandler);
408
			},
409
			touchHandler = function (e) {
410
				var $this = $(this),
411
					o = getOptions($this),
412
					$ul = $this.siblings(e.data.popUpSelector);
413
414
				if (o.onHandleTouch.call($ul) === false) {
415
					return this;
416
				}
417
418
				if ($ul.length > 0 && $ul.is(':hidden')) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if $ul.length > 0 && $ul.is(":hidden") is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
419
					$this.one('click.superfish', false);
420
					if (e.type === 'MSPointerDown' || e.type === 'pointerdown') {
421
						$this.trigger('focus');
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
422
					} else {
423
						$.proxy(over, $this.parent('li'))();
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
424
					}
425
				}
426
			},
427
			over = function () {
428
				var $this = $(this),
429
					o = getOptions($this);
430
				clearTimeout(o.sfTimer);
431
				$this.siblings().superfish('hide').end().superfish('show');
432
			},
433
			out = function () {
434
				var $this = $(this),
435
					o = getOptions($this);
436
				if (ios) {
437
					$.proxy(close, $this, o)();
438
				}
439
				else {
440
					clearTimeout(o.sfTimer);
441
					o.sfTimer = setTimeout($.proxy(close, $this, o), o.delay);
442
				}
443
			},
444
			close = function (o) {
445
				o.retainPath = ($.inArray(this[0], o.$path) > -1);
446
				this.superfish('hide');
447
448
				if (!this.parents('.' + o.hoverClass).length) {
449
					o.onIdle.call(getMenu(this));
450
					if (o.$path.length) {
451
						$.proxy(over, o.$path)();
452
					}
453
				}
454
			},
455
			getMenu = function ($el) {
456
				return $el.closest('.' + c.menuClass);
457
			},
458
			getOptions = function ($el) {
459
				return getMenu($el).data('sf-options');
460
			};
461
462
		return {
463
			// public methods
464
			hide: function (instant) {
465
				if (this.length) {
466
					var $this = this,
467
						o = getOptions($this);
468
					if (!o) {
469
						return this;
470
					}
471
					var not = (o.retainPath === true) ? o.$path : '',
472
						$ul = $this.find('li.' + o.hoverClass).add(this).not(not).removeClass(o.hoverClass).children(o.popUpSelector),
473
						speed = o.speedOut;
474
475
					if (instant) {
476
						$ul.show();
477
						speed = 0;
478
					}
479
					o.retainPath = false;
480
481
					if (o.onBeforeHide.call($ul) === false) {
482
						return this;
483
					}
484
485
					$ul.stop(true, true).animate(o.animationOut, speed, function () {
486
						var $this = $(this);
487
						o.onHide.call($this);
488
					});
489
				}
490
				return this;
491
			},
492
			show: function () {
493
				var o = getOptions(this);
494
				if (!o) {
495
					return this;
496
				}
497
				var $this = this.addClass(o.hoverClass),
498
					$ul = $this.children(o.popUpSelector);
499
500
				if (o.onBeforeShow.call($ul) === false) {
501
					return this;
502
				}
503
504
				$ul.stop(true, true).animate(o.animation, o.speed, function () {
505
					o.onShow.call($ul);
506
				});
507
				return this;
508
			},
509
			destroy: function () {
510
				return this.each(function () {
511
					var $this = $(this),
512
						o = $this.data('sf-options'),
513
						$hasPopUp;
514
					if (!o) {
515
						return false;
516
					}
517
					$hasPopUp = $this.find(o.popUpSelector).parent('li');
518
					clearTimeout(o.sfTimer);
519
					toggleMenuClasses($this, o);
520
					toggleAnchorClass($hasPopUp);
521
					toggleTouchAction($this);
522
					// remove event handlers
523
					$this.off('.superfish').off('.hoverIntent');
524
					// clear animation's inline display style
525
					$hasPopUp.children(o.popUpSelector).attr('style', function (i, style) {
526
						return style.replace(/display[^;]+;?/g, '');
527
					});
528
					// reset 'current' path classes
529
					o.$path.removeClass(o.hoverClass + ' ' + c.bcClass).addClass(o.pathClass);
530
					$this.find('.' + o.hoverClass).removeClass(o.hoverClass);
531
					o.onDestroy.call($this);
532
					$this.removeData('sf-options');
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
533
				});
534
			},
535
			init: function (op) {
536
				return this.each(function () {
537
					var $this = $(this);
538
					if ($this.data('sf-options')) {
539
						return false;
540
					}
541
					var o = $.extend({}, $.fn.superfish.defaults, op),
542
						$hasPopUp = $this.find(o.popUpSelector).parent('li');
543
					o.$path = setPathToCurrent($this, o);
544
545
					$this.data('sf-options', o);
546
547
					toggleMenuClasses($this, o);
548
					toggleAnchorClass($hasPopUp);
549
					toggleTouchAction($this);
550
					applyHandlers($this, o);
551
552
					$hasPopUp.not('.' + c.bcClass).superfish('hide', true);
553
554
					o.onInit.call(this);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
555
				});
556
			}
557
		};
558
	})();
559
560
	$.fn.superfish = function (method, args) {
0 ignored issues
show
Unused Code introduced by
The parameter args is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
561
		if (methods[method]) {
562
			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
563
		}
564
		else if (typeof method === 'object' || ! method) {
565
			return methods.init.apply(this, arguments);
566
		}
567
		else {
568
			return $.error('Method ' +  method + ' does not exist on jQuery.fn.superfish');
569
		}
570
	};
571
572
	$.fn.superfish.defaults = {
573
		popUpSelector: 'ul,.sf-mega', // within menu context
574
		hoverClass: 'sfHover',
575
		pathClass: 'overrideThisToUse',
576
		pathLevels: 1,
577
		delay: 800,
578
		animation: {opacity: 'show'},
579
		animationOut: {opacity: 'hide'},
580
		speed: 'normal',
581
		speedOut: 'fast',
582
		cssArrows: true,
583
		disableHI: false,
584
		onInit: $.noop,
585
		onBeforeShow: $.noop,
586
		onShow: $.noop,
587
		onBeforeHide: $.noop,
588
		onHide: $.noop,
589
		onIdle: $.noop,
590
		onDestroy: $.noop,
591
		onHandleTouch: $.noop
592
	};
593
594
})(jQuery, window);
595
596
/**
597
 * hoverIntent is similar to jQuery's built-in "hover" method except that
598
 * instead of firing the handlerIn function immediately, hoverIntent checks
599
 * to see if the user's mouse has slowed down (beneath the sensitivity
600
 * threshold) before firing the event. The handlerOut function is only
601
 * called after a matching handlerIn.
602
 *
603
 * hoverIntent r7 // 2013.03.11 // jQuery 1.9.1+
604
 * http://cherne.net/brian/resources/jquery.hoverIntent.html
605
 *
606
 * You may use hoverIntent under the terms of the MIT license. Basically that
607
 * means you are free to use hoverIntent as long as this header is left intact.
608
 * Copyright 2007, 2013 Brian Cherne
609
 *
610
 * // basic usage ... just like .hover()
611
 * .hoverIntent( handlerIn, handlerOut )
612
 * .hoverIntent( handlerInOut )
613
 *
614
 * // basic usage ... with event delegation!
615
 * .hoverIntent( handlerIn, handlerOut, selector )
616
 * .hoverIntent( handlerInOut, selector )
617
 *
618
 * // using a basic configuration object
619
 * .hoverIntent( config )
620
 *
621
 * @param  handlerIn   function OR configuration object
0 ignored issues
show
Documentation introduced by
The parameter handlerIn does not exist. Did you maybe forget to remove this comment?
Loading history...
622
 * @param  handlerOut  function OR selector for delegation OR undefined
0 ignored issues
show
Documentation introduced by
The parameter handlerOut does not exist. Did you maybe forget to remove this comment?
Loading history...
623
 * @param  selector    selector OR undefined
0 ignored issues
show
Documentation introduced by
The parameter selector does not exist. Did you maybe forget to remove this comment?
Loading history...
624
 * @author Brian Cherne <brian(at)cherne(dot)net>
625
 **/
626
(function($) {
627
    $.fn.hoverIntent = function(handlerIn,handlerOut,selector) {
628
629
        // default configuration values
630
        var cfg = {
631
            interval: 100,
632
            sensitivity: 7,
633
            timeout: 0
634
        };
635
636
        if ( typeof handlerIn === "object" ) {
637
            cfg = $.extend(cfg, handlerIn );
638
        } else if ($.isFunction(handlerOut)) {
639
            cfg = $.extend(cfg, { over: handlerIn, out: handlerOut, selector: selector } );
640
        } else {
641
            cfg = $.extend(cfg, { over: handlerIn, out: handlerIn, selector: handlerOut } );
642
        }
643
644
        // instantiate variables
645
        // cX, cY = current X and Y position of mouse, updated by mousemove event
646
        // pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
647
        var cX, cY, pX, pY;
648
649
        // A private function for getting mouse position
650
        var track = function(ev) {
651
            cX = ev.pageX;
652
            cY = ev.pageY;
653
        };
654
655
        // A private function for comparing current and previous mouse position
656
        var compare = function(ev,ob) {
657
            ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
658
            // compare mouse positions to see if they've crossed the threshold
659
            if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
660
                $(ob).off("mousemove.hoverIntent",track);
661
                // set hoverIntent state to true (so mouseOut can be called)
662
                ob.hoverIntent_s = 1;
663
                return cfg.over.apply(ob,[ev]);
664
            } else {
665
                // set previous coordinates for next time
666
                pX = cX; pY = cY;
667
                // use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
668
                ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
669
            }
670
        };
671
672
        // A private function for delaying the mouseOut function
673
        var delay = function(ev,ob) {
674
            ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
675
            ob.hoverIntent_s = 0;
676
            return cfg.out.apply(ob,[ev]);
677
        };
678
679
        // A private function for handling mouse 'hovering'
680
        var handleHover = function(e) {
681
            // copy objects to be passed into t (required for event object to be passed in IE)
682
            var ev = jQuery.extend({},e);
683
            var ob = this;
684
685
            // cancel hoverIntent timer if it exists
686
            if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }
687
688
            // if e.type == "mouseenter"
689
            if (e.type == "mouseenter") {
690
                // set "previous" X and Y position based on initial entry point
691
                pX = ev.pageX; pY = ev.pageY;
692
                // update "current" X and Y position based on mousemove
693
                $(ob).on("mousemove.hoverIntent",track);
694
                // start polling interval (self-calling timeout) to compare mouse coordinates over time
695
                if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}
696
697
                // else e.type == "mouseleave"
698
            } else {
699
                // unbind expensive mousemove event
700
                $(ob).off("mousemove.hoverIntent",track);
701
                // if hoverIntent state is true, then call the mouseOut function after the specified delay
702
                if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
703
            }
704
        };
705
706
        // listen for mouseenter and mouseleave
707
        return this.on({'mouseenter.hoverIntent':handleHover,'mouseleave.hoverIntent':handleHover}, cfg.selector);
708
    };
709
})(jQuery);
710
711
/* Takes every category header available and adds a collapse option */
712
$(function() {
713
	if (smf_member_id > 0)
714
		$('div.boardindex_table div.cat_bar').each(function(index, el)
715
		{
716
			var catid = el.id.replace('category_', '');
717
			new smc_Toggle({
0 ignored issues
show
Unused Code Best Practice introduced by
The object created with new smc_Toggle({Identifi...false),false,false)))}) is not used but discarded. Consider invoking another function instead of a constructor if you are doing this purely for side effects.
Loading history...
Coding Style Best Practice introduced by
By convention, constructors like smc_Toggle should be capitalized.
Loading history...
718
				bToggleEnabled: true,
719
				bCurrentlyCollapsed: $('#category_' + catid + '_upshrink').data('collapsed'),
720
				aSwappableContainers: [
721
					'category_' + catid + '_boards'
722
				],
723
				aSwapImages: [
724
					{
725
						sId: 'category_' + catid + '_upshrink',
726
						msgExpanded: '',
727
						msgCollapsed: ''
728
					}
729
				],
730
				oThemeOptions: {
731
					bUseThemeSettings: true,
732
					sOptionName: 'collapse_category_' + catid,
733
					sSessionVar: smf_session_var,
734
					sSessionId: smf_session_id
735
				}
736
			});
737
		});
738
});
739
740
/* Mobile Pop */
741
$(function() {
742
	$( '.mobile_act' ).click(function() {
743
		$( '#mobile_action' ).show();
744
		});
745
	$( '.hide_popup' ).click(function() {
746
		$( '#mobile_action' ).hide();
747
	});
748
	$( '.mobile_mod' ).click(function() {
749
		$( '#mobile_moderation' ).show();
750
	});
751
	$( '.hide_popup' ).click(function() {
752
		$( '#mobile_moderation' ).hide();
753
	});
754
	$( '.mobile_user_menu' ).click(function() {
755
		$( '#mobile_user_menu' ).show();
756
		});
757
	$( '.hide_popup' ).click(function() {
758
		$( '#mobile_user_menu' ).hide();
759
	});
760
});
761