PageSourceSearch

https://www.mesves-sur-loire.fr/js/datepicker-accessible.js?1789111234

js mesves-sur-loire.fr collected 2026-10-02 22:27:15 UTC 3,305 bytes, 101 lines download raw bytes

1/*
2 * Accessibilité des flèches « mois précédent / mois suivant » du datepicker
3 * jQuery UI 1.12.1 utilisé par les agendas (RGAA 7.1, 7.3, 10.7).
4 *
5 * jQuery UI génère des <a> sans href : non atteignables au clavier, sans rôle,
6 * intitulés « Précédent » / « Suivant » peu explicites, et le focus est perdu
7 * à chaque redessin du calendrier (changement de mois, rafraîchissement ajax).
8 */
9(function ($) {
10	if (!$ || !$.datepicker || $.datepicker._webseeAccessible)
11		return;
12
13	$.datepicker._webseeAccessible = true;
14
15	var textes = {
16		fr: { prev: 'Mois précédent', next: 'Mois suivant' },
17		en: { prev: 'Previous month', next: 'Next month' }
18	};
19
20	var langue = (document.documentElement.lang || 'fr').substring(0, 2).toLowerCase();
21	var t = textes[langue] || textes.fr;
22
23	var $annonce = null;
24
25	// Zone de statut persistante : annonce le mois affiché aux lecteurs d'écran
26	function annoncer(texte) {
27		if ($annonce === null)
28			$annonce = $('<div class="ui-helper-hidden-accessible" role="status" aria-live="polite"></div>').appendTo('body');
29
30		$annonce.text(texte);
31	}
32
33	function libelleMois(inst, decalage) {
34		var noms = $.datepicker._get(inst, 'monthNames');
35		var date = new Date(inst.drawYear, inst.drawMonth + decalage, 1);
36
37		return noms[date.getMonth()] + ' ' + date.getFullYear();
38	}
39
40	function rendreAccessible(inst) {
41		var pas = $.datepicker._get(inst, 'stepMonths');
42
43		inst.dpDiv.find('.ui-datepicker-prev, .ui-datepicker-next').each(function () {
44			var $fleche = $(this);
45			var sens = $fleche.hasClass('ui-datepicker-prev') ? 'prev' : 'next';
46			var libelle = t[sens] + ' : ' + libelleMois(inst, sens === 'prev' ? -pas : pas);
47
48			$fleche.attr({ 'role': 'button', 'title': libelle, 'aria-label': libelle });
49
50			if ($fleche.hasClass('ui-state-disabled'))
51				$fleche.attr('aria-disabled', 'true');
52			else
53				$fleche.attr('tabindex', '0');
54		});
55	}
56
57	var updateOriginal = $.datepicker._updateDatepicker;
58
59	$.datepicker._updateDatepicker = function (inst) {
60		var actif = document.activeElement;
61		var sensFocus = null;
62
63		if (actif && inst.dpDiv.length && $.contains(inst.dpDiv[0], actif)) {
64			if ($(actif).hasClass('ui-datepicker-prev'))
65				sensFocus = 'prev';
66			else if ($(actif).hasClass('ui-datepicker-next'))
67				sensFocus = 'next';
68		}
69
70		var moisAvant = inst.webseeMois;
71
72		updateOriginal.apply(this, arguments);
73		rendreAccessible(inst);
74
75		inst.webseeMois = inst.drawYear * 12 + inst.drawMonth;
76
77		// Le HTML est entièrement régénéré : on redonne le focus à la flèche équivalente
78		if (sensFocus !== null) {
79			var $cible = inst.dpDiv.find('.ui-datepicker-' + sensFocus + '[tabindex]');
80
81			if (!$cible.length)
82				$cible = inst.dpDiv.find('.ui-datepicker-prev[tabindex], .ui-datepicker-next[tabindex]');
83
84			$cible.first().trigger('focus');
85		}
86
87		if (moisAvant !== undefined && moisAvant !== inst.webseeMois)
88			annoncer(inst.dpDiv.find('.ui-datepicker-title').first().text());
89	};
90
91	// Activation au clavier (Entrée / Espace) comme un bouton natif
92	$(document).on('keydown', '.ui-datepicker-prev[role=button], .ui-datepicker-next[role=button]', function (e) {
93		if (e.which !== 13 && e.which !== 32)
94			return;
95
96		e.preventDefault();
97
98		if (!$(this).hasClass('ui-state-disabled'))
99			$(this).trigger('click');
100	});
101})(window.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.