PageSourceSearch

https://remesla-khv.ru/templates/remesla/js/menu.js

js remesla-khv.ru collected 2026-09-30 10:02:20 UTC 16,876 bytes, 643 lines download raw bytes

1/**
2 * ------------------------------------------------------------------------------
3 * 
4 * @package T3 Framework for Joomla!
5 *          ------------------------------------------------------------------------------
6 * @copyright Copyright (C) 2004-2013 JoomlArt.com. All Rights Reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE.txt
8 * @authors JoomlArt, JoomlaBamboo, (contribute to this project at github &
9 *          Google group to become co-author)
10 * @Google group: https://groups.google.com/forum/#!forum/t3fw
11 * @Link: http://t3-framework.org
12 *        ------------------------------------------------------------------------------
13 */
14
15;
16(function($) {
17
18	var T3Menu = function(elm, options) {
19		this.$menu = $(elm);
20		if (!this.$menu.length) {
21			return;
22		}
23
24		this.options = $.extend({}, $.fn.t3menu.defaults, options);
25		this.child_open = [];
26		this.loaded = false;
27
28		this.start();
29	};
30
31	T3Menu.prototype = {
32		constructor : T3Menu,
33
34		start : function() {
35			// init once
36			if (this.loaded) {
37				return;
38			}
39			this.loaded = true;
40
41			// start
42			var self = this, options = this.options, $menu = this.$menu;
43
44			this.$items = $menu.find('li');
45			this.$items
46					.each(function(idx, li) {
47
48						var $item = $(this), $child = $item
49								.children('.dropdown-menu'), $link = $item
50								.children('a'), item = {
51							$item : $item,
52							child : $child.length,
53							link : $link.length,
54							clickable : !($link.length && $child.length),
55							mega : $item.hasClass('mega'),
56							status : 'close',
57							timer : null,
58							atimer : null
59						};
60
61						// store
62						$item.data('t3menu.item', item);
63
64						// click action
65						if ($child.length && !options.hover) {
66							$item.on('click', function(e) {
67								e.stopPropagation();
68
69								if ($item.hasClass('group')) {
70									return;
71								}
72
73								if (item.status == 'close') {
74									e.preventDefault();
75									self.show(item);
76								}
77							});
78						} else {
79
80							// stop if click on menu item - prevent bubble event
81							$item.on('click', function(e) {
82								// ignore if this is toggle button
83								if ($(e.target).data('toggle')) return;
84								e.stopPropagation()
85							});
86						}
87
88						// click on caret, no action on link
89						$item.find('a > .caret').on('click tap', function(e) {
90							item.clickable = false;
91						});
92
93						if (options.hover) {
94							$item.on('mouseover', function(e) {
95								if ($item.hasClass('group'))
96									return;
97
98								// check and handle only once - replace for
99								// stopPropagation
100								var $target = $(e.target);
101								if ($target.data('show-processed'))
102									return;
103								$target.data('show-processed', true);
104								setTimeout(function() {
105									$target.data('show-processed', false);
106								}, 10);
107
108								self.show(item);
109
110							}).on('mouseleave', function(e) {
111								if ($item.hasClass('group'))
112									return;
113
114								// check and handle only once - replace for
115								// stopPropagation
116								var $target = $(e.target);
117								if ($target.data('hide-processed'))
118									return;
119								$target.data('hide-processed', true);
120								setTimeout(function() {
121									$target.data('hide-processed', false);
122								}, 10);
123
124								self.hide(item, $target);
125							});
126
127							// if has child, don't goto link before open child -
128							// fix for touch screen
129							if ($link.length && $child.length) {
130								$link.on('click', function(e) {
131									if (item.clickable) {
132										e.stopPropagation();
133									}
134									return item.clickable;
135								});
136							}
137						}
138
139					});
140
141			$(document.body)
142					.on(
143							'tap hideall.t3menu',
144							function(e) {
145								clearTimeout(self.timer);
146								self.timer = setTimeout($.proxy(self.hide_alls,
147										self), e.type == 'tap' ? 500
148										: self.options.hidedelay);
149							});
150
151			// ignore click on direct child
152			$menu.find('.mega-dropdown-menu').on('hideall.t3menu', function(e) {
153				e.stopPropagation();
154				e.preventDefault();
155				return false;
156			});
157
158			// prevent close menu if click on form element
159			$menu.find('input, select, textarea, label').on('click tap',
160					function(e) {
161						e.stopPropagation();
162					});
163
164			// update mega-tab height
165			var $megatab = $menu.find('.mega-tab');
166			if ($megatab.length) {
167				$megatab.each(function() {
168					var $tabul = $(this).find('>div>ul'), 
169						$tabItems = $tabul.children('.dropdown-submenu'),
170						$tabs = $tabul.find('>li>.dropdown-menu'), 
171						tabheight = 0,
172						$parentItem = $(this).closest('li');
173					// mark item as tab-item
174					$tabItems.data('mega-tab-item', 1);
175					// add this tabs to parent item
176					var megatabs = $parentItem.data('mega-tabs') ? $parentItem.data('mega-tabs') : [];
177					megatabs.push($tabul);
178					$parentItem.data('mega-tabs', megatabs);
179
180					// default active the first
181					// $tabul.data('mega-tab', 0);
182					$tabItems.first().data('mega-tab-active', true).addClass('open');
183					// make all parent visible to get height
184					var $p = $tabul.parents('.dropdown-menu');
185					$p.each(function() {
186						var $this = $(this);
187						$this.data('prev-style', $this.attr('style')).css({
188							visibility : "visible",
189							display : "block"
190						});
191					})
192					$tabs.each(function() {
193						var $this = $(this), thisstyle = $this.attr('style');
194						$this.css({
195							visibility : "hidden",
196							display : "block"
197						});
198						tabheight = Math.max(tabheight, $this.children()
199								.innerHeight());
200						// restore style
201						if (thisstyle) {
202							$this.attr('style', thisstyle);
203						} else {
204							$this.removeAttr('style');
205						}
206					});
207					$tabul.css('min-height', tabheight);
208					// restore
209					$p.each(function() {
210						var $this = $(this);
211						if ($this.data('prev-style'))
212							$this.attr('style', $this.data('prev-style'));
213						else
214							$this.removeAttr('style');
215						$this.removeData('prev-style');
216					})
217				})
218			}
219			// fix for modal in menu
220			$menu.find('.modal').appendTo('body');
221		},
222
223		show : function(item) {
224			// check if current item is mega-tab
225			if (item.$item.data('mega-tab-item')) {
226				item.$item.parent().children().removeClass('open').data('mega-tab-active', false);
227				item.$item.addClass('open').data('mega-tab-active', true);
228			}			
229			// hide all others menu of this instance
230			if ($.inArray(item, this.child_open) < this.child_open.length - 1) {
231				this.hide_others(item);
232			}
233
234			// hide all for other instances as well
235			$(document.body).trigger('hideall.t3menu', [ this ]);
236
237			clearTimeout(this.timer); // hide alls
238			clearTimeout(item.timer); // hide this item
239			clearTimeout(item.ftimer); // on hidden
240			clearTimeout(item.ctimer); // on hidden
241
242			if (item.status != 'open' || !item.$item.hasClass('open')
243					|| !this.child_open.length) {
244				if (item.mega) {
245					// remove timer
246					clearTimeout(item.astimer); // animate
247					clearTimeout(item.atimer); // animate
248
249					// place menu
250					this.position(item.$item);
251
252					// add class animate
253					item.astimer = setTimeout(function() {
254						item.$item.addClass('animating')
255					}, 10);
256					item.atimer = setTimeout(function() {
257						item.$item.removeClass('animating')
258					}, this.options.duration + 50);
259					item.timer = setTimeout(function() {
260						item.$item.addClass('open');
261					}, 100);
262				} else {
263					item.$item.addClass('open');
264				}
265
266				item.status = 'open';
267				if (item.child && $.inArray(item, this.child_open) == -1) {
268					this.child_open.push(item);
269				}
270			}
271
272			item.ctimer = setTimeout($.proxy(this.clickable, this, item), 300);
273
274		},
275
276		hide : function(item, $target) {
277			clearTimeout(this.timer); // hide alls
278			clearTimeout(item.timer); // hide this item
279			clearTimeout(item.astimer); // animate timer
280			clearTimeout(item.atimer); // animate timer
281			clearTimeout(item.ftimer); // on hidden
282
283			// cancel hide if still in menu
284			if ($target && $target.is('input', item.$item)) {
285				return;
286			}
287
288			if (item.mega) {
289				// animate out
290				item.$item.addClass('animating');
291				item.atimer = setTimeout(function() {
292					item.$item.removeClass('animating')
293				}, this.options.duration);
294				item.timer = setTimeout(function() {
295					if (!item.$item.data('mega-tab-active'))
296						item.$item.removeClass('open')
297				}, 100);
298			} else {
299				item.timer = setTimeout(function() {
300					if (!item.$item.data('mega-tab-active'))
301						item.$item.removeClass('open');
302				}, 100);
303			}
304
305			item.status = 'close';
306			for (var i = this.child_open.length; i--;) {
307				if (this.child_open[i] === item) {
308					this.child_open.splice(i, 1);
309				}
310			}
311
312			item.ftimer = setTimeout($.proxy(this.hidden, this, item),
313					this.options.duration);
314			this.timer = setTimeout($.proxy(this.hide_alls, this),
315					this.options.hidedelay);
316		},
317
318		hidden : function(item) {
319			// hide done
320			if (item.status == 'close') {
321				item.clickable = false;
322			}
323		},
324
325		hide_others : function(item) {
326			var self = this;
327			$
328					.each(this.child_open.slice(),
329							function(idx, open) {
330								if (!item
331										|| (open != item && !open.$item
332												.has(item.$item).length)) {
333									self.hide(open);
334								}
335							});
336		},
337
338		hide_alls : function(e, inst) {
339			if (!e || e.type == 'tap' || (e.type == 'hideall' && this != inst)) {
340				var self = this;
341				$.each(this.child_open.slice(), function(idx, item) {
342					item && self.hide(item);
343				});
344			}
345		},
346
347		clickable : function(item) {
348			item.clickable = true;
349		},
350
351		position : function($item) {
352			var sub = $item.children('.mega-dropdown-menu'), is_show = sub
353					.is(':visible');
354
355			if (!is_show) {
356				sub.show();
357			}
358
359			var offset = $item.offset(), width = $item.outerWidth(), screen_width = $(
360					window).width()
361					- this.options.sb_width, sub_width = sub.outerWidth(), level = $item
362					.data('level');
363
364			if (!is_show) {
365				sub.css('display', '');
366			}
367
368			// reset custom align
369			sub.css({
370				left : '',
371				right : ''
372			});
373
374			if (level == 1) {
375
376				var align = $item.data('alignsub'), align_offset = 0, align_delta = 0, align_trans = 0;
377
378				if (align == 'justify') {
379					return; // do nothing
380				}
381
382				if (!align) {
383					align = 'left';
384				}
385
386				if (align == 'center') {
387					align_offset = offset.left + (width / 2);
388
389					if (!$.support.t3transform) {
390						align_trans = -sub_width / 2;
391						sub.css(this.options.rtl ? 'right' : 'left',
392								align_trans + width / 2);
393					}
394
395				} else {
396					align_offset = offset.left
397							+ ((align == 'left' && this.options.rtl || align == 'right'
398									&& !this.options.rtl) ? width : 0);
399				}
400
401				if (this.options.rtl) {
402
403					if (align == 'right') {
404						if (align_offset + sub_width > screen_width) {
405							align_delta = screen_width - align_offset
406									- sub_width;
407							sub.css('left', align_delta);
408
409							if (screen_width < sub_width) {
410								sub.css('left', align_delta + sub_width
411										- screen_width);
412							}
413						}
414					} else {
415						if (align_offset < (align == 'center' ? sub_width / 2
416								: sub_width)) {
417							align_delta = align_offset
418									- (align == 'center' ? sub_width / 2
419											: sub_width);
420							sub.css('right', align_delta + align_trans);
421						}
422
423						if (align_offset
424								+ (align == 'center' ? sub_width / 2 : 0)
425								- align_delta > screen_width) {
426							sub
427									.css(
428											'right',
429											align_offset
430													+ (align == 'center' ? (sub_width + width) / 2
431															: 0) + align_trans
432													- screen_width);
433						}
434					}
435
436				} else {
437
438					if (align == 'right') {
439						if (align_offset < sub_width) {
440							align_delta = align_offset - sub_width;
441							sub.css('right', align_delta);
442
443							if (sub_width > screen_width) {
444								sub.css('right', sub_width - screen_width
445										+ align_delta);
446							}
447						}
448					} else {
449
450						if (align_offset
451								+ (align == 'center' ? sub_width / 2
452										: sub_width) > screen_width) {
453							align_delta = screen_width
454									- align_offset
455									- (align == 'center' ? sub_width / 2
456											: sub_width);
457							sub.css('left', align_delta + align_trans);
458						}
459
460						if (align_offset
461								- (align == 'center' ? sub_width / 2 : 0)
462								+ align_delta < 0) {
463							sub
464									.css(
465											'left',
466											(align == 'center' ? (sub_width + width) / 2
467													: 0)
468													+ align_trans
469													- align_offset);
470						}
471					}
472				}
473			} else {
474
475				if (this.options.rtl) {
476					if ($item.closest('.mega-dropdown-menu').parent().hasClass(
477							'mega-align-right')) {
478
479						// should be align to the right as parent
480						// $item.removeClass('mega-align-left').addClass('mega-align-right');
481
482						// check if not able => revert the direction
483						if (offset.left + width + sub_width > screen_width) {
484							$item.removeClass('mega-align-right'); // should we
485							// add align
486							// left ? it
487							// is th
488							// default
489							// now
490
491							if (offset.left - sub_width < 0) {
492								sub.css('right', offset.left + width
493										- sub_width);
494							}
495						}
496					} else {
497						if (offset.left - sub_width < 0) {
498							$item.removeClass('mega-align-left').addClass(
499									'mega-align-right');
500
501							if (offset.left + width + sub_width > screen_width) {
502								sub.css('left', screen_width - offset.left
503										- sub_width);
504							}
505						}
506					}
507				} else {
508
509					if ($item.closest('.mega-dropdown-menu').parent().hasClass(
510							'mega-align-right')) {
511						// should be align to the right as parent
512						// $item.removeClass('mega-align-left').addClass('mega-align-right');
513
514						// check if not able => revert the direction
515						if (offset.left - sub_width < 0) {
516							$item.removeClass('mega-align-right'); // should we
517							// add align
518							// left ? it
519							// is th
520							// default
521							// now
522
523							if (offset.left + width + sub_width > screen_width) {
524								sub.css('left', screen_width - offset.left
525										- sub_width);
526							}
527						}
528					} else {
529
530						if (offset.left + width + sub_width > screen_width) {
531							$item.removeClass('mega-align-left').addClass(
532									'mega-align-right');
533
534							if (offset.left - sub_width < 0) {
535								sub.css('right', offset.left + width
536										- sub_width);
537							}
538						}
539					}
540				}
541			}
542		}
543	};
544
545	$.fn.t3menu = function(option) {
546		return this
547				.each(function() {
548					var $this = $(this), data = $this.data('megamenu'), options = typeof option == 'object'
549							&& option;
550
551					// Ignore off-canvas navigation
552					if ($this.parents('#off-canvas-nav').length)
553						return;
554					if ($this.parents('#t3-off-canvas').length)
555						return;
556
557					if (!data) {
558						$this.data('megamenu',
559								(data = new T3Menu(this, options)));
560
561					} else {
562						if (typeof option == 'string' && data[option]) {
563							data[option]()
564						}
565					}
566				})
567	};
568
569	$.fn.t3menu.defaults = {
570		duration : 400,
571		timeout : 100,
572		hidedelay : 200,
573		hover : true,
574		sb_width : 20
575	};
576
577	// apply script
578	$(document)
579			.ready(
580					function() {
581
582						// detect settings
583						var mm_duration = $('.t3-megamenu').data('duration') || 0;
584						if (mm_duration) {
585
586							$(
587									'<style type="text/css">'
588											+ '.t3-megamenu.animate .animating > .mega-dropdown-menu,'
589											+ '.t3-megamenu.animate.slide .animating > .mega-dropdown-menu > div {'
590											+ 'transition-duration: '
591											+ mm_duration + 'ms !important;'
592											+ '-webkit-transition-duration: '
593											+ mm_duration + 'ms !important;'
594											+ '}' + '</style>')
595									.appendTo('head');
596						}
597
598						var mm_timeout = mm_duration ? 100 + mm_duration : 500, mm_rtl = $(
599								document.documentElement).attr('dir') == 'rtl', mm_trigger = $(
600								document.documentElement).hasClass('mm-hover'), sb_width = (function() {
601							var parent = $(
602									'<div style="width:50px;height:50px;overflow:auto"><div/></div>')
603									.appendTo('body'), child = parent
604									.children(), width = child.innerWidth()
605									- child.height(100).innerWidth();
606
607							parent.remove();
608
609							return width;
610						})();
611
612						// lt IE 10
613						if (!$.support.transition) {
614							// it is not support animate
615							$('.t3-megamenu').removeClass('animate');
616
617							mm_timeout = 100;
618						}
619
620						// get ready
621						$('ul.nav').has('.dropdown-menu').t3menu({
622							duration : mm_duration,
623							timeout : mm_timeout,
624							rtl : mm_rtl,
625							sb_width : sb_width,
626							hover : mm_trigger
627						});
628
629						$(window).load(function() {
630
631							// check we miss any nav
632							$('ul.nav').has('.dropdown-menu').t3menu({
633								duration : mm_duration,
634								timeout : mm_timeout,
635								rtl : mm_rtl,
636								sb_width : sb_width,
637								hover : mm_trigger
638							});
639
640						});
641					});
642
643})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.