PageSourceSearch

https://www.editionsmichelquintin.ca/js/jquery.vMenuMobile.js

js editionsmichelquintin.ca collected 2026-09-24 20:37:06 UTC 16,408 bytes, 455 lines download raw bytes

1/*
2                                                                __           ___             
3            /'\_/`\                             /'\_/`\        /\ \      __ /\_ \            
4 __  __    /\      \     __    ___   __  __    /\      \    ___\ \ \____/\_\\//\ \      __   
5/\ \/\ \   \ \ \__\ \  /'__`\/' _ `\/\ \/\ \   \ \ \__\ \  / __`\ \ '__`\/\ \ \ \ \   /'__`\ 
6\ \ \_/ |   \ \ \_/\ \/\  __//\ \/\ \ \ \_\ \   \ \ \_/\ \/\ \L\ \ \ \L\ \ \ \ \_\ \_/\  __/ 
7 \ \___/     \ \_\\ \_\ \____\ \_\ \_\ \____/    \ \_\\ \_\ \____/\ \_,__/\ \_\/\____\ \____\
8  \/__/       \/_/ \/_/\/____/\/_/\/_/\/___/      \/_/ \/_/\/___/  \/___/  \/_/\/____/\/____/
9                                                                                             
10
11	Version : 0.8
12	Date 		: 10/12/14
13	Auteurs : Vortex Solution / Mikhaël Bois
14	Langues supportées : Français et anglais
15
16*/
17
18;(function ( $, window, document, undefined ) {
19
20	// Options par défaut
21	var pluginName = "vMenuMobile",
22	defaults = {
23		auto: true,
24		mode: "vertical",
25		type: 1,
26		langue: "fr",
27		position: "gauche",
28		idIcone: "iconeMenu",
29		texteIconeMenu: {
30			"ouvrir": {
31				"fr": "Ouvrir le menu",
32				"en": "Open menu"
33			},
34			"fermer": {
35				"fr": "Fermer le menu",
36				"en": "Close menu"
37			}
38		},
39		idMobile: "menuMobile",
40		classeMobile: "mobile",
41		classeBureau: "bureau",
42		classeOuverture: "vMenu-open",
43		classeAnimation: "vAnimationMargin",
44		largeurBureau: 960,
45		classeSousMenu: "avecSousMenu",
46		classeNePasCopierType1: "vNoCopy",
47		classeBtnType2: "vAfficherSousMenu",
48		classeWrapType2: "vWrapType2",
49		texteLienRetour: {
50			"fr": "Retour",
51			"en": "Back"
52		},
53		classeLienRetour: "vRetour"
54	};
55
56	// The actual plugin constructor
57	function Plugin ( element, options ) {
58		this.element = element;
59		this.settings = $.extend( {}, defaults, options );
60		this._defaults = defaults;
61		this._name = pluginName;
62		this.init();
63	}
64
65
66	// Avoid Plugin.prototype conflicts
67	$.extend(Plugin.prototype, {
68		init: function () {
69			// Initialisation du plugin
70
71			var _ = this;
72
73			// État du menu
74			_.isOpen = false;
75
76			/*! A fix for the iOS orientationchange zoom bug. Script by @scottjehl, rebound by @wilto.MIT / GPLv2 License.*/
77			(function(a){function m(){d.setAttribute("content",g),h=!0}function n(){d.setAttribute("content",f),h=!1}function o(b){l=b.accelerationIncludingGravity,i=Math.abs(l.x),j=Math.abs(l.y),k=Math.abs(l.z),(!a.orientation||a.orientation===180)&&(i>7||(k>6&&j<8||k<8&&j>6)&&i>5)?h&&n():h||m()}var b=navigator.userAgent;if(!(/iPhone|iPad|iPod/.test(navigator.platform)&&/OS [1-5]_[0-9_]* like Mac OS X/i.test(b)&&b.indexOf("AppleWebKit")>-1))return;var c=a.document;if(!c.querySelector)return;var d=c.querySelector("meta[name=viewport]"),e=d&&d.getAttribute("content"),f=e+",maximum-scale=1",g=e+",maximum-scale=10",h=!0,i,j,k,l;if(!d)return;a.addEventListener("orientationchange",m,!1),a.addEventListener("devicemotion",o,!1)})(this);
78
79			// Détection de la version d'Android transféré dans le <head>
80
81			// Ajoute une classe si le menu s'ouvre à droite ou si le bouton du menu est à droite
82			if(_.settings.position === "droite"){
83				$("html").addClass("vMenu-droit");
84			}
85
86			// Change le titre du bouton menu
87			_.setIconTitle();
88
89			// Menu vertical
90			if(_.settings.mode === "vertical"){
91				
92				// Replace le menu lorsque l'on change l'orientation de l'appareil. Évite certains bugs sur iPhone
93				if(window.addEventListener){
94					window.addEventListener("orientationchange", function() {window.scrollTo(0, 0);}, false);
95				}				
96
97				// Ajoute une classe au pour différencier le mode et le type du menu en CSS
98				$("html").addClass("vMenu-v-"+_.settings.type);
99
100				// Création du menu mobile automatiquement
101				if(_.settings.auto){
102					$(_.element).clone().attr({ "id": _.settings.idMobile}).prependTo("body");
103				}
104
105				// Vérifie si le plugin Swipe est inclu
106				if(!jQuery().swipe){
107					console.log("Veuillez fournir le plugin Swipe");	
108				}else{
109					// Création des sous-menus
110					_.initSousMenu();
111
112					// Toggle du menu
113					$(document).on('click', "#"+_.settings.idIcone, function(e) {
114						e.preventDefault();
115						_.isOpen ? _.toggleState("fermer") : _.toggleState("ouvrir");
116					});
117
118					/* Ferme le menu si on clique à l'extérieur ou si on clique sur le bouton du menu */
119					$(document).on('click', function(e) {
120						!$(e.target).closest("#"+_.settings.idMobile+",#"+_.settings.idIcone).length && _.isOpen ? _.toggleState("fermer") : "";
121					});
122				}
123			// Menu horizontal
124			}else if(_.settings.mode === "horizontal"){
125
126				// Ajoute une classe au pour différencier le mode et le type du menu en CSS
127				$("html").addClass("vMenu-h-"+_.settings.type);
128
129				// Création des sous-menus
130				_.initSousMenu();
131
132				// Déplace le menu vers le haut pour le cacher à sa pleine hauteur
133				_.moveMenuH();
134
135				// Détecte lorsqu'on passe en mode bureau pour afficher le bon menu
136				_.checkMenuH();
137
138				// Toggle du menu
139				$(document).on('click', "#"+_.settings.idIcone, function(e) {
140					e.preventDefault();
141					_.isOpen ? _.toggleState("fermer") : _.toggleState("ouvrir");
142				});
143			// Erreur
144			}else{
145				console.log("Veuillez spécifier le mode du menu");
146			}
147
148		},
149		initSousMenu: function () {
150			var _ = this;
151
152			// Menu mobile vertical
153			if(_.settings.mode === "vertical"){
154				var $menuMobile = $("#"+_.settings.idMobile);
155			// Menu mobile horizontal
156			}else if (_.settings.mode === "horizontal"){
157				var $menuMobile =  $(_.element);
158			}
159
160
161			// Type 1
162			if(_.settings.type === 1){
163				// Duplication du lien contenant le sous-menu
164				$menuMobile.find("."+_.settings.classeSousMenu+" > a").each(function(){
165					// Ne copie pas si le lien a cette classe
166					if(!$(this).hasClass(_.settings.classeNePasCopierType1)){
167						$(this).clone().prependTo($(this).next("ul")).wrap("<li class='vMenu-clone'></li>");
168					}
169				});
170
171				// Ouvre les sous-menus actifs
172				$menuMobile.find("."+_.settings.classeSousMenu+".actif > ul").slideDown();
173
174				// Toggle des sous-menus
175				if(_.settings.mode === "vertical"){
176					$menuMobile.find("."+_.settings.classeSousMenu+" > a").on('click',function(e){
177						$this = $(this).closest("."+_.settings.classeSousMenu);
178						_.toggleSousMenu($this,e);
179					});
180				}else if (_.settings.mode === "horizontal"){
181					// Évite de garder la détection du click sur la version bureau
182					$menuMobile.find("."+_.settings.classeSousMenu+" > a").on('click',function(e){
183						if($(_.element).hasClass(_.settings.classeMobile)){
184							$this = $(this).closest("."+_.settings.classeSousMenu);
185							_.toggleSousMenu($this,e);							
186						}
187					});
188				}
189			}
190
191
192			// Type 2
193			if(_.settings.type === 2){
194				// Ajoute un bouton pour séparer la détection du clique entre le texte et le +
195				$menuMobile.find("."+_.settings.classeSousMenu).each(function(){
196					if(!$(this).find('> .'+_.settings.classeWrapType2).length){
197						$(this).append("<a href='##' class='"+_.settings.classeBtnType2+"'><span></span></a>");
198						$(this).children(":not(ul)").wrapAll("<div class='"+_.settings.classeWrapType2+"'></div>");
199					}
200				});
201
202				// Ouvre les sous-menus actifs
203				$menuMobile.find("."+_.settings.classeSousMenu+".actif > ul").slideDown();
204
205				// Toggle des sous-menus
206				$menuMobile.find("."+_.settings.classeBtnType2).on('click',function(e){
207					$this = $(this).closest("."+_.settings.classeSousMenu);
208					_.toggleSousMenu($this,e);
209				});
210			}
211
212
213			// Type 3
214			if(_.settings.type === 3){
215				// Duplication du lien contenant le sous-menu
216				$menuMobile.find("."+_.settings.classeSousMenu+" > a").each(function(){
217					$(this).clone().prependTo($(this).next("ul")).wrap("<li class='vMenu-clone'></li>");
218				});
219
220				
221				// Déplace les sous-menus et les organise un à la suite de l'autre
222				var decompteNiv1 = 0;
223				$menuMobile.find(" > ul:first-child").addClass("actif");
224				$menuMobile.find(" > ul > li > ul").each(function(){
225					var decompteNiv2 = 0;
226					decompteNiv1++;
227
228					$(this).parent("."+_.settings.classeSousMenu).attr("data-niv","1-"+decompteNiv1);
229					$(this).attr("id","niv1-"+decompteNiv1).appendTo($menuMobile).addClass("niv1");
230
231					// Ajoute le lien de retour
232					$(this).prepend("<li><a href='#' class='"+_.settings.classeLienRetour+"'>"+_.settings.texteLienRetour[_.settings.langue]+"</a></li>");
233
234					$(this).find("ul").each(function(){
235						decompteNiv2++;
236						$(this).parent("."+_.settings.classeSousMenu).attr("data-niv","2-"+decompteNiv2);
237						$(this).attr("id","niv2-"+decompteNiv2).appendTo($menuMobile).addClass("niv2");
238
239						// Ajoute le lien de retour
240						$(this).prepend("<li><a href='#' class='"+_.settings.classeLienRetour+"'>"+_.settings.texteLienRetour[_.settings.langue]+"</a></li>");
241					});
242				});
243
244				// Toggle des sous-menus
245				$menuMobile.find("."+_.settings.classeSousMenu+" > a").on('click',function(e){						
246					_.toggleSousMenu($(this),e);						
247				});
248
249				// Retour à l'arrière
250				$menuMobile.find("a."+_.settings.classeLienRetour).on('click',function(e){
251					e.preventDefault();
252
253					// Niveau 1
254					if($(this).closest("ul").hasClass("niv1")){
255						$menuMobile.find("ul:first-child").removeClass("menuPrec");					
256					// Niveau 2
257					} else if($(this).closest("ul").hasClass("niv2")){
258						$menuMobile.find("ul.niv1").removeClass("menuPrec");
259					}
260					$(this).closest("ul").removeClass("actif");
261				});
262			}
263		},
264		setIconTitle: function ($this,e) {
265			var _ = this;
266
267			// Attribut le "title" du bouton menu selon la langue et l'état du menu
268			if(_.isOpen){
269				$("#"+_.settings.idIcone).attr("title",_.settings.texteIconeMenu["fermer"][_.settings.langue]);
270			}else{
271				$("#"+_.settings.idIcone).attr("title",_.settings.texteIconeMenu["ouvrir"][_.settings.langue]);
272			}
273		},
274		toggleSousMenu: function ($this,e) {
275			var _ = this;
276
277			// Type 3 Vertical seulement
278			if(_.settings.type === 3){
279				if($this.parent("."+_.settings.classeSousMenu)){
280					e.preventDefault();
281
282					var idNiv = "niv"+$this.parent("."+_.settings.classeSousMenu).data("niv");
283					$this.closest("ul").addClass("menuPrec");
284					$("#"+idNiv).addClass("actif");
285				}
286
287			// Types 1 et 2
288			}else{
289				e.preventDefault();
290				
291				$this.siblings().removeClass("actif").find("ul").stop(1,1).slideUp().closest("."+_.settings.classeSousMenu).removeClass("actif");
292				
293				if(!$this.hasClass("actif")){
294					$this.addClass("actif").find("> ul").stop(1,1).slideDown();
295				}else{
296					$this.removeClass("actif").find("ul").stop(1,1).slideUp().closest("."+_.settings.classeSousMenu).removeClass("actif");
297				}
298				e.stopPropagation();
299			}
300		},
301		moveMenuH: function () {
302			// Mode horizontal seulement
303
304			var _ = this;
305
306			// Déplace le menu vers le haut pour le cacher à sa pleine hauteur
307			if($(_.element).hasClass(_.settings.classeMobile) && !_.isOpen){
308				$(_.element).css("marginTop","-"+$(_.element).innerHeight()+"px");
309			}else if($(_.element).hasClass(_.settings.classeMobile) && _.isOpen){
310				$(_.element).css("marginTop","");
311			}else{
312				$(_.element).css({"marginTop":"","height":""});
313			}
314		},
315		checkMenuH: function () {
316			// Mode horizontal seulement
317			
318			var _ = this;
319
320			// Détecte lorsqu'on passe en mode bureau pour afficher le bon menu
321
322			// window.innerWidth n'est pas supporté dans IE8
323			var largeurDocument = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
324
325			if($(_.element).hasClass(_.settings.classeMobile) && largeurDocument >= _.settings.largeurBureau){
326				$(_.element).removeClass(_.settings.classeMobile);
327				$(_.element).addClass(_.settings.classeBureau);
328				_.toggleState("fermer");
329			}else if($(_.element).hasClass(_.settings.classeBureau)  && largeurDocument < _.settings.largeurBureau){
330				$(_.element).removeClass(_.settings.classeBureau);
331				$(_.element).addClass(_.settings.classeMobile);					
332			}
333			if(largeurDocument < _.settings.largeurBureau){
334				// Place le menu au cas on change d'orientation
335				_.moveMenuH();
336			}
337		},
338		toggleState: function (action) {
339			var _ = this;
340
341			// La classe "_.settings.classeAnimation" est utilisé pour l'animation du menu.
342			// Elle doit être retirée aussitôt terminée pour éviter des bugs visuelles
343
344			// Ouverture du menu
345			if(action === "ouvrir"){
346				// Vertical
347				if(_.settings.mode === "vertical"){
348					_.isOpen = true;
349					$("html").addClass(_.settings.classeOuverture+" "+_.settings.classeAnimation);
350					setTimeout(function(){
351						$("html").removeClass(_.settings.classeAnimation);
352					},500);
353
354					/* Si le menu est ouvert, option de glisser/taper pour fermer */
355					$(document).swipe({
356						swipeLeft:function() {
357							// Menu gauche
358							_.isOpen && _.settings.position === "gauche" ? _.toggleState("fermer") : "";
359						},
360						swipeRight:function() {	
361							// Menu droite
362							_.isOpen && _.settings.position === "droite" ? _.toggleState("fermer") : "";
363						},
364						tap:function(event, target) {
365							// Extérieur du menu
366							!$(target).closest("#"+_.settings.idMobile+",#"+_.settings.idIcone).length && _.isOpen ? _.toggleState("fermer") : "";
367						},
368						threshold:5
369					});
370				// Horizontal
371				}else if(_.settings.mode === "horizontal"){
372					_.isOpen = true;
373					$("html").addClass(_.settings.classeOuverture+" "+_.settings.classeAnimation);
374					_.moveMenuH();					
375					setTimeout(function(){
376						$("html").removeClass(_.settings.classeAnimation);
377					},500);
378				}
379			}
380
381			// Fermeture du menu
382			if(action === "fermer"){
383				// Vertical
384				if(_.settings.mode === "vertical"){					
385					_.isOpen = false;
386					$("html").addClass(_.settings.classeAnimation).removeClass(_.settings.classeOuverture);
387					setTimeout(function(){
388						$("html").removeClass(_.settings.classeAnimation);
389					},500);
390					
391					// Retire la détection du swipe pour éviter des problèmes
392					$(document).swipe("destroy");
393				// Horizontal
394				}else if(_.settings.mode === "horizontal"){
395					_.isOpen = false;
396					$("html").addClass(_.settings.classeAnimation).removeClass(_.settings.classeOuverture);
397
398					// Retire le "display:block" pour les sous-menus
399					$(_.element).find("."+_.settings.classeSousMenu).removeClass("actif").find("ul").css("display","").closest("."+_.settings.classeSousMenu).removeClass("actif");
400
401					_.moveMenuH();
402
403					setTimeout(function(){
404						$("html").removeClass(_.settings.classeAnimation);
405					},500);
406				}
407			}
408
409			// Change le titre du bouton menu
410			_.setIconTitle();
411		},
412		update: function () {
413			// Réinitialise le plugin
414			var _ = this;
415			// Retire le click sur le bouton du menu
416			$(document).off('click', "#"+_.settings.idIcone);
417			// Menu mobile vertical
418			if(_.settings.mode === "vertical"){
419				var $menuMobile = $("#"+_.settings.idMobile);
420			// Menu mobile horizontal
421			}else if (_.settings.mode === "horizontal"){
422				var $menuMobile =  $(_.element);
423			}
424			// Retire le click sur les liens
425			$menuMobile.find("."+_.settings.classeSousMenu+" > a").off('click');
426			// Retire toutes les classes ajoutées au html
427			$("html").removeClass('vMenu-droit vMenu-v-1 vMenu-v-2 vMenu-v-3 vMenu-h-1 vMenu-h-2');
428			// Supprime les <li> étant dupliqué dans les types 1 et 3
429			$(".vMenu-clone").remove();
430			// Supprime le bouton et le wrap ajoutés par le type 2			
431			$(_.element).find("."+_.settings.classeWrapType2).children().unwrap();
432			$(_.element).find("."+_.settings.classeBtnType2).remove();
433			// Supprime le menu mobile dupliqué dans le menu horizontal
434			$("#"+_.settings.idMobile).remove();
435			// Réinitialise
436			_.init();
437		}
438	});
439
440
441	// A really lightweight plugin wrapper around the constructor,
442	// preventing against multiple instantiations
443	$.fn[ pluginName ] = function ( options ) {
444		this.each(function() {
445			if ( !$.data( this, "plugin_" + pluginName ) ) {
446				$.data( this, "plugin_" + pluginName, new Plugin( this, options ) );
447			}
448		});
449
450		// chain jQuery functions
451		return this;
452	};
453
454
455})( jQuery, window, document );

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.