Overview
Comment:Firefox est encore plus bugué dans les dernières versions: il annonce supporter input[type=date] et désactive donc le widget de fallback de Garradin, mais aucune manière de détecter ces ***** de Firefox, donc on abandonne la détection de input type date et on utilise toujours le widget custom.

Implémentation de sucres ergonomiques pour améliorer l'utilisabilité du widget au passage.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 0504e69180f60da32789a679bdd7deb5f1e49224
User & Date: bohwaz on 2016-05-31 03:57:56
Other Links: manifest | tags
Context
2016-05-31
04:10
Augmenter le timeout en cas de concurrency, car des fois on a des erreurs sur certaines assos check-in: 0a88984edf user: bohwaz tags: trunk
03:57
Firefox est encore plus bugué dans les dernières versions: il annonce supporter input[type=date] et désactive donc le widget de fallback de Garradin, mais aucune manière de détecter ces ***** de Firefox, donc on abandonne la détection de input type date et on utilise toujours le widget custom.

Implémentation de sucres ergonomiques pour améliorer l'utilisabilité du widget au passage. check-in: 0504e69180 user: bohwaz tags: trunk

03:54
Suite de [6596fd8999] : cela autorisait au final des dates invalides, on fait donc la conversion en UTC dans le modèle plutôt que le contrôleur check-in: 3dc757a543 user: bohwaz tags: trunk
Changes

Modified src/templates/admin/wiki/editer.tpl from [dbb3dc8b75] to [e660a7c338].

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

<form method="post" action="{$self_url|escape}" id="f_form">

    <fieldset class="wikiMain">
        <legend>Informations générales</legend>
        <dl>
            <dt><label for="f_titre">Titre</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
            <dd><input type="text" name="titre" id="f_titre" value="{form_field data=$page name=titre}" /></dd>
            <dt><label for="f_uri">Adresse unique</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
            <dd class="help">
                Ne peut comporter que des lettres, des chiffres, des tirets et des tirets bas.
            </dd>
            <dd><input type="text" name="uri" id="f_uri" value="{form_field data=$page name=uri}" /></dd>
            <dt><label for="f_browse_parent">Cette page est une sous-rubrique de...</label></dt>
            <dd>
                <input type="hidden" name="parent" id="f_parent" value="{form_field data=$page name=parent}" />
                {if $page.parent == 0}
                    <samp id="current_parent_name">la racine du site</samp>
                {else}
                    <samp id="current_parent_name">{$parent|escape}</samp>
                {/if}
                <input type="button" id="f_browse_parent" onclick="browseWikiForParent();" value="Changer" />
            </dd>
            <dt><label for="f_date">Date</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
            <dd>
                <input type="date" size="10" name="date" id="f_date" value="{$date|date_fr:'Y-m-d'|escape}" />
                <input type="text" class="time" size="2" name="date_h" value="{$date|date_fr:'H'|escape}" /> h
                <input type="text" class="time" size="2" name="date_min" value="{$date|date_fr:'i'|escape}" />
            </dd>
        </dl>
    </fieldset>

    <fieldset class="wikiRights">
        <legend>Droits d'accès</legend>
        <dl>







|




|












|
|
|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

<form method="post" action="{$self_url|escape}" id="f_form">

    <fieldset class="wikiMain">
        <legend>Informations générales</legend>
        <dl>
            <dt><label for="f_titre">Titre</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
            <dd><input type="text" name="titre" id="f_titre" value="{form_field data=$page name=titre}" required="required" /></dd>
            <dt><label for="f_uri">Adresse unique</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
            <dd class="help">
                Ne peut comporter que des lettres, des chiffres, des tirets et des tirets bas.
            </dd>
            <dd><input type="text" name="uri" id="f_uri" value="{form_field data=$page name=uri}" required="required" /></dd>
            <dt><label for="f_browse_parent">Cette page est une sous-rubrique de...</label></dt>
            <dd>
                <input type="hidden" name="parent" id="f_parent" value="{form_field data=$page name=parent}" />
                {if $page.parent == 0}
                    <samp id="current_parent_name">la racine du site</samp>
                {else}
                    <samp id="current_parent_name">{$parent|escape}</samp>
                {/if}
                <input type="button" id="f_browse_parent" onclick="browseWikiForParent();" value="Changer" />
            </dd>
            <dt><label for="f_date">Date</label> <b title="(Champ obligatoire)">obligatoire</b></dt>
            <dd>
                <input type="date" size="10" name="date" id="f_date" value="{$date|date_fr:'Y-m-d'|escape}" pattern="{literal}^\d{4}-\d{2}-\d{2}${/literal}" required="required" />
                <input type="text" class="time" size="2" name="date_h" value="{$date|date_fr:'H'|escape}" pattern="^{literal}\d{1,2}${/literal}" required="required" /> h
                <input type="text" class="time" size="2" name="date_min" value="{$date|date_fr:'i'|escape}" pattern="{literal}^\d{1,2}${/literal}" required="required" />
            </dd>
        </dl>
    </fieldset>

    <fieldset class="wikiRights">
        <legend>Droits d'accès</legend>
        <dl>

Modified src/www/admin/static/scripts/datepickr.css from [d54547c03f] to [766cefa9b1].

6
7
8
9
10
11
12










13
14
15
16
17
18
19
    border: 1px solid #DDD;
    -moz-border-radius: 4px;
    -webkit-border-radius: 4px;
    border-radius: 4px;
    padding: 0.2em;
    width: 14em;
    box-shadow: 2px 2px 5px #666;










}

.calendar a {
    outline: none;
}

.calendar .months {







>
>
>
>
>
>
>
>
>
>







6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    border: 1px solid #DDD;
    -moz-border-radius: 4px;
    -webkit-border-radius: 4px;
    border-radius: 4px;
    padding: 0.2em;
    width: 14em;
    box-shadow: 2px 2px 5px #666;
    transition: all .5s;
    opacity: 1;
    display: block;
    position: absolute;
}

.calendar.hidden {
    overflow: hidden;
    visibility: hidden;
    opacity: 0;
}

.calendar a {
    outline: none;
}

.calendar .months {

Modified src/www/admin/static/scripts/datepickr.js from [34b4a67e07] to [491ae371e7].

252
253
254
255
256
257
258


259
260
261
262
263
264
265
...
269
270
271
272
273
274
275
276
277
278
279

280
281
282
283
284

285
286
287
288

289







290
291
292
293
294
295
296
...
332
333
334
335
336
337
338


339
340
341
342
343
344
345
346
347
348
349
350



351
352
353
354
355
356
357

































358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384

		currentMaxRows = weekCount+1;

		return html;
	}

	function open() {


		document.onmousedown = function(e) {
			e = e || window.event;
			var target = e.target || e.srcElement;

			var parentNode = target.parentNode;
			if(target != element && parentNode != container) {
				while(parentNode != container) {
................................................................................
						break;
					}
				}
			}

			if (target == element)
			{
				close();
			}

			e.preventDefault();

		}

		document.onkeyup = function(e) {
			var k = e.keyCode || e.which;


			if (k == 27)
			{
				close();
				e.preventDefault();

				return false;







			}
		};

		document.onkeypress = function(e) {
			var k = e.keyCode || e.which;

			if (k == 33) // PgUp
................................................................................
				if (row.innerHTML == "") return;

				table.getElementsByTagName('td')[currentPosition[0]*7+currentPosition[1]-7].className = '';
				row.className = 'today';

				currentPosition = pos;
				currentDate = new Date(currentYearView, currentMonthView, row.firstChild.innerHTML);


			}
			else if (k == 13 || k == 32)
			{
				element.value = formatDate(currentDate.getTime());
				element.onchange(element);
				close();
				e.preventDefault();
				return false;
			}
		}

		handleMonthClick();



		container.style.display = 'block';
	}

	function close() {
		document.onmousedown = null;
		document.onkeypress = null;
		container.style.display = 'none';

































	}

	function initialise(userConfig) {
		if(userConfig) {
			for(var key in userConfig) {
				if(config.hasOwnProperty(key)) {
					config[key] = userConfig[key];
				}
			}
		}

		if (element.value)
		{
			var d = element.value.split('/').reverse();
			currentDate = new Date(parseInt(d[0], 10), parseInt(d[1], 10) - 1, parseInt(d[2], 10), 0, 0, 0, 0);
			currentYearView = get.current.year();
			currentMonthView = get.current.month.integer();
		}
		container = build('div', { className: 'calendar' });
		container.style.cssText = 'display: none; position: absolute; z-index: 9999;';

		var months = build('div', { className: 'months' });
		prevMonth = build('span', { className: 'prev-month' }, build('a', { href: '#' }, '&lt;'));
		nextMonth = build('span', { className: 'next-month' }, build('a', { href: '#' }, '&gt;'));
		month = build('span', { className: 'current-month' }, get.month.string(config.fullCurrentMonth) + ' ' + currentYearView);

		months.appendChild(prevMonth);







>
>







 







|



>





>



<
>
|
>
>
>
>
>
>
>







 







>
>












>
>
>
|


|


<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











|
<
<
<
<
<
<
|
|







252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
...
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291

292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
...
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372

373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417






418
419
420
421
422
423
424
425
426

		currentMaxRows = weekCount+1;

		return html;
	}

	function open() {
		element.onkeyup = element.onclick = null;

		document.onmousedown = function(e) {
			e = e || window.event;
			var target = e.target || e.srcElement;

			var parentNode = target.parentNode;
			if(target != element && parentNode != container) {
				while(parentNode != container) {
................................................................................
						break;
					}
				}
			}

			if (target == element)
			{
				close(true);
			}

			e.preventDefault();
			return false;
		}

		document.onkeyup = function(e) {
			var k = e.keyCode || e.which;

			// Esc key pressed
			if (k == 27)
			{
				close();

			}
			else if ((k >= 37 && k <= 40) || k == 33 || k == 34 || k == 32 || k == 40)
			{
				// Handled in onkeypress
			}
			else if (e.target == element && element.value.match(/^\d+\/\d+\/\d{4}$/))
			{
				parseInputValue();
				handleMonthClick();
			}
		};

		document.onkeypress = function(e) {
			var k = e.keyCode || e.which;

			if (k == 33) // PgUp
................................................................................
				if (row.innerHTML == "") return;

				table.getElementsByTagName('td')[currentPosition[0]*7+currentPosition[1]-7].className = '';
				row.className = 'today';

				currentPosition = pos;
				currentDate = new Date(currentYearView, currentMonthView, row.firstChild.innerHTML);

				return false;
			}
			else if (k == 13 || k == 32)
			{
				element.value = formatDate(currentDate.getTime());
				element.onchange(element);
				close();
				e.preventDefault();
				return false;
			}
		}

		handleMonthClick();
		container.className = 'calendar';
		parseInputValue();
		handleMonthClick();
		container.focus();
	}

	function close(no_reopen = false) {
		document.onmousedown = null;
		document.onkeypress = null;

		container.className = 'calendar hidden';
		element.onclick = function (e) {
			if (no_reopen) {
				no_reopen = false;
				return;
			}

			open();
		};

		element.onkeyup = function (e) {
			var k = e.keyCode || e.which;
			var c = String.fromCharCode(e.charCode || e.keyCode);

			if (k == 40)
			{
				open();
			}
			else if (c.match(/[0-9\/]/) && element.value.match(/^\d{2}\/\d{2}\/\d{4}$/))
			{
				open();
			}
		};
	}

	function parseInputValue() {
		if (element.value)
		{
			var d = element.value.split('/').reverse();
			currentDate = new Date(parseInt(d[0], 10), parseInt(d[1], 10) - 1, parseInt(d[2], 10), 0, 0, 0, 0);
			currentYearView = get.current.year();
			currentMonthView = get.current.month.integer();
		}
	}

	function initialise(userConfig) {
		if(userConfig) {
			for(var key in userConfig) {
				if(config.hasOwnProperty(key)) {
					config[key] = userConfig[key];
				}
			}
		}

		parseInputValue();






		container = build('div', { className: 'calendar hidden' });
//		container.style.cssText = 'display: none; position: absolute; z-index: 9999;';

		var months = build('div', { className: 'months' });
		prevMonth = build('span', { className: 'prev-month' }, build('a', { href: '#' }, '&lt;'));
		nextMonth = build('span', { className: 'next-month' }, build('a', { href: '#' }, '&gt;'));
		month = build('span', { className: 'current-month' }, get.month.string(config.fullCurrentMonth) + ' ' + currentYearView);

		months.appendChild(prevMonth);

Modified src/www/admin/static/scripts/global.js from [bb189de32a] to [bab9903c66].

106
107
108
109
110
111
112



113
114
115
116
117
118
119
120
121
122
123
124
125

126
127
128
129
130

131
132
133
134
135
136
137
138
139
140
141
142
		}

		return true;
	};

	var dateInputFallback = function ()
	{



		var input = document.createElement('input');
		input.setAttribute('type', 'date');
		input.value = ':-)';
		input.style.position = 'absolute';
		input.style.visibility = 'hidden';
		document.body.appendChild(input);

		// If input type changed or value hasn't been sanitized then
		// the input type date element is not supported
		if (input.type === 'text' || input.value === ':-)')
		{
			document.body.removeChild(input);


			if (document.querySelector && !document.querySelector('input[type=date]'))
				return false;

			g.script('scripts/datepickr.js');
			g.style('scripts/datepickr.css');

		}
		else
		{
			document.body.removeChild(input);
		}
	};

	g.onload(dateInputFallback);

	if (document.querySelectorAll)
	{
		g.onload(function () {







>
>
>






|


|


<
>





>




|







106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
		}

		return true;
	};

	var dateInputFallback = function ()
	{
		/*
		// Firefox dit implémenter date, mais ne l'implémente pas, aucun moyen de détecter ce cas
		// donc on force l'utilisation du custom datepicker de Garradin…
		var input = document.createElement('input');
		input.setAttribute('type', 'date');
		input.value = ':-)';
		input.style.position = 'absolute';
		input.style.visibility = 'hidden';
		document.body.appendChild(input);
		
		// If input type changed or value hasn't been sanitized then
		// the input type date element is not supported
		if (input.type !== 'text' && input.value !== ':-)')
		{
			document.body.removeChild(input);

		*/
			if (document.querySelector && !document.querySelector('input[type=date]'))
				return false;

			g.script('scripts/datepickr.js');
			g.style('scripts/datepickr.css');
		/*
		}
		else
		{
			document.body.removeChild(input);
		}*/
	};

	g.onload(dateInputFallback);

	if (document.querySelectorAll)
	{
		g.onload(function () {