marquex
2016-07-29 bf82818c798421a46aa02b916437920fb657244d
commit | author | age
0d9dc7 1 // Create the dom before requiring react
M 2 var DOM = require( './testdom');
3 DOM();
4
516b36 5
M 6 // Needs to be global to work in Travis CI
92a2c6 7 React = require('react');
2d8253 8 ReactDOM = require('react-dom');
15436d 9
92a2c6 10 var Datetime = require('../DateTime'),
0d9dc7 11     assert = require('assert'),
92a2c6 12     moment = require('moment'),
M 13     TestUtils = require('react-addons-test-utils')
0d9dc7 14 ;
M 15
516b36 16 var createDatetime = function( props ){
2d8253 17     document.body.innerHTML = '<div id="root"></div>';
0d9dc7 18
2d8253 19     ReactDOM.render(
516b36 20         React.createElement( Datetime, props ),
2d8253 21         document.getElementById('root')
0d9dc7 22     );
M 23
2d8253 24     return document.getElementById('root').children[0];
0d9dc7 25 };
M 26
59314a 27 var trigger = function( name, element ){
M 28     var ev = document.createEvent("MouseEvents");
29    ev.initEvent(name, true, true);
30    element.dispatchEvent( ev );
31 };
32
92a2c6 33 var ev = TestUtils.Simulate;
59314a 34 var dt = {
M 35     dt: function(){
2d8253 36         return document.getElementById('root').children[0];
59314a 37     },
M 38     view: function(){
39         return this.dt().children[1].children[0];
40     },
41     input: function(){
42         return this.dt().children[0];
43     },
44     switcher: function(){
2d8253 45         return document.querySelector('.rdtSwitch');
59314a 46     },
M 47     timeSwitcher: function(){
2d8253 48         return document.querySelector('.rdtTimeToggle');
59314a 49     },
M 50     year: function( n ){
2d8253 51         var years = document.querySelectorAll('.rdtYear');
59314a 52         return years[ n || 0 ];
M 53     },
54     month: function( n ){
2d8253 55         var months = document.querySelectorAll('.rdtMonth');
59314a 56         return months[ n || 0 ];
M 57     },
58     day: function( n ){
2d8253 59         return document.querySelector('.rdtDay[data-value="' + n + '"]');
59314a 60     },
M 61     next: function(){
a8a17a 62         return document.querySelector('.rdtNext span');
59314a 63     },
M 64     prev: function(){
a8a17a 65         return document.querySelector('.rdtPrev span');
59314a 66     },
M 67     timeUp: function( n ){
68         return document.querySelectorAll('.rdtCounter')[ n ].children[0];
69     },
70     timeDown: function( n ){
71         return document.querySelectorAll('.rdtCounter')[ n ].children[2];
72     },
73     hour: function(){
74         return document.querySelectorAll('.rdtCount')[0];
75     },
76     minute: function(){
77         return document.querySelectorAll('.rdtCount')[1];
78     },
79     second: function(){
80         return document.querySelectorAll('.rdtCount')[2];
81     },
82     milli: function(){
83         return document.querySelector('.rdtMilli input');
84     }
85 };
86
87 var date = new Date( 2000, 0, 15, 2, 2, 2, 2 ),
0d9dc7 88     mDate = moment( date ),
M 89     strDate = mDate.format('L') + ' ' + mDate.format('LT')
90 ;
91
92 describe( 'Datetime', function(){
93     it( 'Create Datetime', function(){
516b36 94         var component = createDatetime({});
0d9dc7 95         assert( component );
M 96         assert.equal( component.children.length, 2 );
97         assert.equal( component.children[0].tagName , 'INPUT' );
98         assert.equal( component.children[1].tagName , 'DIV' );
99     });
100
101     it( 'input=false', function(){
516b36 102         var component = createDatetime({ input: false });
0d9dc7 103         assert( component );
M 104         assert.equal( component.children.length, 1 );
105         assert.equal( component.children[0].tagName , 'DIV' );
106     });
107
92a2c6 108
0d9dc7 109     it( 'Date value', function(){
516b36 110         var component = createDatetime({ value: date }),
0d9dc7 111             input = component.children[0]
M 112         ;
113         assert.equal( input.value, strDate );
114     });
115
116     it( 'Moment value', function(){
516b36 117         var component = createDatetime({ value: mDate }),
0d9dc7 118             input = component.children[0]
M 119         ;
120         assert.equal( input.value, strDate );
121     });
122
123     it( 'String value', function(){
516b36 124         var component = createDatetime({ value: strDate }),
0d9dc7 125             input = component.children[0]
M 126         ;
127         assert.equal( input.value, strDate );
128     });
129
130     it( 'Date defaultValue', function(){
516b36 131         var component = createDatetime({ defaultValue: date }),
0d9dc7 132             input = component.children[0]
M 133         ;
134         assert.equal( input.value, strDate );
135     });
136
137     it( 'Moment defaultValue', function(){
516b36 138         var component = createDatetime({ defaultValue: mDate }),
0d9dc7 139             input = component.children[0]
M 140         ;
141         assert.equal( input.value, strDate );
142     });
143
144     it( 'String defaultValue', function(){
516b36 145         var component = createDatetime({ defaultValue: strDate }),
0d9dc7 146             input = component.children[0]
M 147         ;
148         assert.equal( input.value, strDate );
149     });
150
151     it( 'dateFormat', function(){
516b36 152         var component = createDatetime({ value: date, dateFormat: 'M&D' }),
0d9dc7 153             input = component.children[0]
M 154         ;
155         assert.equal( input.value, mDate.format('M&D LT') );
156     });
157
158     it( 'dateFormat=false', function(){
516b36 159         var component = createDatetime({ value: date, dateFormat: false }),
0d9dc7 160             input = component.children[0],
59314a 161             view = dt.view()
0d9dc7 162         ;
M 163         assert.equal( input.value, mDate.format('LT') );
164         // The view must be the timepicker
165         assert.equal( view.className, 'rdtTime' );
166         // There must not be a date toggle
167         assert.equal( view.querySelectorAll('thead').length, 0);
168     });
169     it( 'timeFormat', function(){
170         var format = 'HH:mm:ss:SSS',
516b36 171             component = createDatetime({ value: date, timeFormat: format }),
0d9dc7 172             input = component.children[0]
M 173         ;
174         assert.equal( input.value, mDate.format('L ' + format) );
175     });
176
177     it( 'timeFormat=false', function(){
516b36 178         var component = createDatetime({ value: date, timeFormat: false }),
0d9dc7 179             input = component.children[0],
59314a 180             view = dt.view()
0d9dc7 181         ;
M 182         assert.equal( input.value, mDate.format('L') );
183         // The view must be the daypicker
184         assert.equal( view.className, 'rdtDays' );
185         // There must not be a time toggle
186         assert.equal( view.querySelectorAll('.timeToggle').length, 0);
187     });
188
189     it( 'viewMode=years', function(){
516b36 190         var component = createDatetime({ viewMode: 'years' }),
59314a 191             view = dt.view()
0d9dc7 192         ;
M 193
194         assert.equal( view.className, 'rdtYears' );
195     });
196
197     it( 'viewMode=months', function(){
516b36 198         var component = createDatetime({ viewMode: 'months' }),
59314a 199             view = dt.view()
0d9dc7 200         ;
M 201
202         assert.equal( view.className, 'rdtMonths' );
203     });
204
205     it( 'viewMode=time', function(){
516b36 206         var component = createDatetime({ viewMode: 'time' }),
59314a 207             view = dt.view()
0d9dc7 208         ;
M 209
210         assert.equal( view.className, 'rdtTime' );
211     });
212
213     it( 'className', function(){
516b36 214         var component = createDatetime({ className: 'custom' });
0d9dc7 215         assert.notEqual( component.className.indexOf('custom'), -1 );
M 216     });
217
218     it( 'inputProps', function(){
516b36 219         var component = createDatetime({ inputProps: { className: 'myInput', type: 'email' } }),
0d9dc7 220             input = component.children[0]
M 221         ;
222
223         assert.equal( input.className, 'myInput' );
224         assert.equal( input.type, 'email' );
225     });
226
227     it( 'renderDay', function(){
228         var props, currentDate, selectedDate,
516b36 229             component = createDatetime({ value: mDate, renderDay: function( p, current, selected ){
0d9dc7 230                 props = p;
M 231                 currentDate = current;
232                 selectedDate = selected;
233
234                 return React.DOM.td( props, 'day' );
235             }}),
59314a 236             view = dt.view()
0d9dc7 237         ;
M 238
239         // Last day should be 6th of february
240         assert.equal( currentDate.day(), 6 );
241         assert.equal( currentDate.month(), 1 );
242
243         // The date must be the same
244         assert.equal( selectedDate.isSame( mDate ), true );
245
246         // There should be a onClick function in the props
247         assert.equal( typeof props.onClick, 'function' );
248
249         // The cell text should be 'day'
2d8253 250         assert.equal( view.querySelector('.rdtDay').innerHTML, 'day' );
0d9dc7 251     });
M 252
253
254     it( 'renderMonth', function(){
255         var props, month, year, selectedDate,
516b36 256             component = createDatetime({ value: mDate, viewMode: 'months', renderMonth: function( p, m, y, selected ){
0d9dc7 257                 props = p;
M 258                 month = m;
259                 year = y;
260                 selectedDate = selected;
261
262                 return React.DOM.td( props, 'month' );
263             }}),
59314a 264             view = dt.view()
0d9dc7 265         ;
M 266
267         // The date must be the same
268         assert.equal( selectedDate.isSame( mDate ), true );
269
270         assert.equal( month, 11 );
271         assert.equal( year, 2000 );
272
273         // There should be a onClick function in the props
274         assert.equal( typeof props.onClick, 'function' );
275
276         // The cell text should be 'day'
2d8253 277         assert.equal( view.querySelector('.rdtMonth').innerHTML, 'month' );
0d9dc7 278     });
M 279
280     it( 'renderYear', function(){
281         var props, year, selectedDate,
516b36 282             component = createDatetime({ value: mDate, viewMode: 'years', renderYear: function( p, y, selected ){
0d9dc7 283                 props = p;
M 284                 year = y;
285                 selectedDate = selected;
286
287                 return React.DOM.td( props, 'year' );
288             }}),
59314a 289             view = dt.view()
0d9dc7 290         ;
M 291
292         // The date must be the same
293         assert.equal( selectedDate.isSame( mDate ), true );
294
295         assert.equal( year, 2010 );
296
297         // There should be a onClick function in the props
298         assert.equal( typeof props.onClick, 'function' );
299
300         // The cell text should be 'day'
2d8253 301         assert.equal( view.querySelector('.rdtYear').innerHTML, 'year' );
0d9dc7 302     });
59314a 303
M 304     it( 'Time pickers depends on the time format', function() {
305         createDatetime({ viewMode: 'time', timeFormat: "HH:mm:ss:SSS"});
306         assert.equal( document.querySelectorAll('.rdtCounter').length, 4 );
307
308         createDatetime({ viewMode: 'time', timeFormat: "HH:mm:ss"});
309         assert.equal( document.querySelectorAll('.rdtCounter').length, 3 );
310
311         createDatetime({ viewMode: 'time', timeFormat: "HH:mm"});
312         assert.equal( document.querySelectorAll('.rdtCounter').length, 2 );
313
314         createDatetime({ viewMode: 'time', timeFormat: "HH"});
315         assert.equal( document.querySelectorAll('.rdtCounter').length, 1 );
316     });
317
318     it( 'viewChange', function() {
319         createDatetime({viewMode: 'time' });
320
321         assert.equal( dt.view().className, 'rdtTime' );
322         ev.click( dt.switcher() );
323         assert.equal( dt.view().className, 'rdtDays' );
324         ev.click( dt.switcher() );
325         assert.equal( dt.view().className, 'rdtMonths' );
326         ev.click( dt.switcher() );
327         assert.equal( dt.view().className, 'rdtYears' );
328     });
329
330     it( 'switch to time', function(){
331         createDatetime({});
332         assert.equal( dt.view().className, 'rdtDays' );
333         ev.click( dt.timeSwitcher() );
334         assert.equal( dt.view().className, 'rdtTime' );
335     })
336
337     it( 'selectYear', function(){
338         createDatetime({ viewMode: 'years', defaultValue: date });
339         assert.equal( dt.view().className, 'rdtYears' );
340         assert.equal( dt.switcher().innerHTML, '2000-2009' );
341
342         // First year is 1999
343         ev.click( dt.year() );
344         assert.equal( dt.view().className, 'rdtMonths' );
345         assert.equal( dt.switcher().innerHTML, '1999' );
346     });
347
348     it( 'increase decade', function(){
349         createDatetime({ viewMode: 'years', defaultValue: date });
350
351         assert.equal( dt.switcher().innerHTML, '2000-2009' );
352         ev.click( dt.next() );
353         assert.equal( dt.switcher().innerHTML, '2010-2019' );
354         ev.click( dt.next() );
355         assert.equal( dt.switcher().innerHTML, '2020-2029' );
356     });
357
358
359     it( 'decrease decade', function(){
360         createDatetime({ viewMode: 'years', defaultValue: date });
361
362         assert.equal( dt.switcher().innerHTML, '2000-2009' );
363         ev.click( dt.prev() );
364         assert.equal( dt.switcher().innerHTML, '1990-1999' );
365         ev.click( dt.prev() );
366         assert.equal( dt.switcher().innerHTML, '1980-1989' );
367     });
368
369     it( 'selectMonth', function(){
370         createDatetime({ viewMode: 'months', defaultValue: date });
371         assert.equal( dt.view().className, 'rdtMonths' );
372         assert.equal( dt.switcher().innerHTML, '2000' );
373
374         ev.click( dt.month(1) );
375         assert.equal( dt.view().className, 'rdtDays' );
376         assert.equal( dt.switcher().getAttribute('data-value'), "1" );
377     });
378
379     it( 'increase year', function(){
380         createDatetime({ viewMode: 'months', defaultValue: date });
381
382         assert.equal( dt.switcher().getAttribute('data-value'), '2000' );
383         ev.click( dt.next() );
384         assert.equal( dt.switcher().getAttribute('data-value'), '2001' );
385         ev.click( dt.next() );
386         assert.equal( dt.switcher().getAttribute('data-value'), '2002' );
387     });
388
389
390     it( 'decrease year', function(){
391         createDatetime({ viewMode: 'months', defaultValue: date });
392
393         assert.equal( dt.switcher().getAttribute('data-value'), '2000' );
394         ev.click( dt.prev() );
395         assert.equal( dt.switcher().getAttribute('data-value'), '1999' );
396         ev.click( dt.prev() );
397         assert.equal( dt.switcher().getAttribute('data-value'), '1998' );
398     });
399
400     it( 'increase month', function(){
401         createDatetime({ defaultValue: date });
402
403         assert.equal( dt.switcher().getAttribute('data-value'), '0' );
404         ev.click( dt.next() );
405         assert.equal( dt.switcher().getAttribute('data-value'), '1' );
406         ev.click( dt.next() );
407         assert.equal( dt.switcher().getAttribute('data-value'), '2' );
408     });
409
410     it( 'decrease month', function(){
411         createDatetime({ defaultValue: date });
412
413         assert.equal( dt.switcher().getAttribute('data-value'), '0' );
414         ev.click( dt.prev() );
415         assert.equal( dt.switcher().getAttribute('data-value'), '11' );
416         ev.click( dt.prev() );
417         assert.equal( dt.switcher().getAttribute('data-value'), '10' );
418     });
419
420     it( 'open picker', function(){
421         createDatetime({});
422         assert.equal(dt.dt().className.indexOf('rdtOpen'), -1);
423         ev.focus( dt.input() );
424         assert.notEqual(dt.dt().className.indexOf('rdtOpen'), -1);
425     });
426
427     it( 'onSelect', function( done ){
428         createDatetime({ defaultValue: date, onChange: function( selected ){
429             assert.equal( selected.date(), 2 );
430             assert.equal( selected.month(), mDate.month() );
431             assert.equal( selected.year(), mDate.year() );
432             done();
433         }});
434
435         ev.click( dt.day( 2 ) );
436     });
437
438     it( 'multiple onSelect', function( done ){
439         var i = 0;
440         createDatetime({ defaultValue: date, onChange: function( selected ){
441             i++;
442             if( i > 2 ){
443                 assert.equal( selected.date(), 4 );
444                 assert.equal( selected.month(), mDate.month() );
445                 assert.equal( selected.year(), mDate.year() );
446                 done();
447             }
448         }});
449
450         ev.click( dt.day( 2 ) );
451         ev.click( dt.day( 3 ) );
452         ev.click( dt.day( 4 ) );
453     });
454
aca9e6 455     it( 'onFocus', function(){
R 456         var focus = false;
457         createDatetime({ value: date, onFocus: function( selected ){
458             focus = true;
459         }});
460
461         ev.focus( dt.input() );
462         assert.equal( focus, true );
463     });
464
59314a 465     it( 'onBlur', function(){
M 466         createDatetime({ value: date, onBlur: function( selected ){
467             assert.equal( dt.dt().className.indexOf( 'rdtOpen' ), -1 );
468             assert.equal( selected.date(), mDate.date() );
469             assert.equal( selected.month(), mDate.month() );
470             assert.equal( selected.year(), mDate.year() );
471             done();
472         }});
473
474         assert.equal( dt.dt().className.indexOf( 'rdtOpen' ), -1 );
475         ev.focus( dt.input() );
476         assert.notEqual( dt.dt().className.indexOf( 'rdtOpen' ), -1 );
477         trigger( 'click', document.body );
478     });
479
9012e8 480     it( 'closeOnTab:true', function(){
M 481         createDatetime({ value: date });
482
483         assert.equal( dt.dt().className.indexOf( 'rdtOpen' ), -1 );
484         ev.focus( dt.input() );
485         assert.notEqual( dt.dt().className.indexOf( 'rdtOpen' ), -1 );
486         TestUtils.Simulate.keyDown(dt.input(), {key: "Tab", keyCode: 9, which: 9});
487         assert.equal( dt.dt().className.indexOf( 'rdtOpen' ), -1 );
488         trigger( 'click', document.body );
489     });
490
491     it( 'closeOnTab:false', function(){
492         createDatetime({ value: date, closeOnTab: false });
493
494         assert.equal( dt.dt().className.indexOf( 'rdtOpen' ), -1 );
495         ev.focus( dt.input() );
496         assert.notEqual( dt.dt().className.indexOf( 'rdtOpen' ), -1 );
497         TestUtils.Simulate.keyDown(dt.input(), {key: "Tab", keyCode: 9, which: 9});
498         assert.notEqual( dt.dt().className.indexOf( 'rdtOpen' ), -1 );
499         trigger( 'click', document.body );
500     });
501
59314a 502     it( 'increase time', function( done ){
M 503         var i = 0;
504         createDatetime({ timeFormat: "HH:mm:ss:SSS", viewMode: 'time', defaultValue: date, onChange: function( selected ){
505             i++;
506             if( i > 2 ){
507                 assert.equal( selected.hour(), 3 );
508                 assert.equal( selected.minute(), 3 );
509                 assert.equal( selected.second(), 3 );
510                 done();
511             }
512         }});
513
514         trigger( 'mousedown', dt.timeUp( 0 ) );
515         trigger('mouseup', document.body );
516         assert.equal( dt.hour().innerHTML, 3 );
517         trigger( 'mousedown', dt.timeUp( 1 ) );
518         trigger( 'mouseup', dt.timeUp( 1 ) );
519         assert.equal( dt.minute().innerHTML, 3 );
520         trigger( 'mousedown', dt.timeUp( 2 ) );
521         trigger( 'mouseup', dt.timeUp( 2 ) );
522         assert.equal( dt.second().innerHTML, 3 );
523     });
524
525     it( 'decrease time', function( done ){
526         var i = 0;
527         createDatetime({ timeFormat: "HH:mm:ss:SSS", viewMode: 'time', defaultValue: date, onChange: function( selected ){
528             i++;
529             if( i > 2 ){
530                 assert.equal( selected.hour(), 1 );
531                 assert.equal( selected.minute(), 1 );
532                 assert.equal( selected.second(), 1 );
533                 done();
534             }
535         }});
536
537         trigger('mousedown', dt.timeDown( 0 ) );
538         trigger('mouseup', dt.timeDown( 0 ) );
539         assert.equal( dt.hour().innerHTML, 1 );
540         trigger('mousedown', dt.timeDown( 1 ) );
541         trigger('mouseup', dt.timeDown( 1 ) );
542         assert.equal( dt.minute().innerHTML, 1 );
543         trigger('mousedown', dt.timeDown( 2 ) );
544         trigger('mouseup', dt.timeDown( 2 ) );
545         assert.equal( dt.second().innerHTML, 1 );
546     });
547
548     it( 'long increase time', function( done ){
549         var i = 0;
550         createDatetime({ timeFormat: "HH:mm:ss:SSS", viewMode: 'time', defaultValue: date});
551
552         trigger( 'mousedown', dt.timeUp( 0 ) );
553         setTimeout( function(){
554             trigger('mouseup', document.body );
555             assert.notEqual( dt.hour().innerHTML, 2 );
556             assert.notEqual( dt.hour().innerHTML, 3 );
557             done();
a79e6b 558         }, 920 );
59314a 559     });
M 560
561     it( 'long decrease time', function( done ){
562         var i = 0;
563         createDatetime({ timeFormat: "HH:mm:ss:SSS", viewMode: 'time', defaultValue: date});
564
565         trigger( 'mousedown', dt.timeDown( 0 ) );
566         setTimeout( function(){
567             trigger('mouseup', document.body );
568             assert.notEqual( dt.hour().innerHTML, 1 );
569             assert.notEqual( dt.hour().innerHTML, 0 );
570             done();
a79e6b 571         }, 920 );
59314a 572     });
62fd2f 573
9bb4f7 574     it( 'increase time with timeConstraints', function( done ){
LG 575         var i = 0;
576         createDatetime({ timeFormat: "HH:mm:ss:SSS", viewMode: 'time', defaultValue: date, onChange: function( selected ){
577             i++;
578             if( i > 2 ){
579                 assert.equal( selected.minute(), 17 );
580                 assert.equal( selected.second(), 3 );
581                 done();
582             }
4ed404 583         }, timeConstraints: { hours: { max: 6, step: 8 }, minutes: { step: 15 }}});
9bb4f7 584
LG 585         trigger( 'mousedown', dt.timeUp( 0 ) );
586         trigger('mouseup', document.body );
ef2929 587         assert.equal( dt.hour().innerHTML, 3 );
9bb4f7 588         trigger( 'mousedown', dt.timeUp( 1 ) );
LG 589         trigger( 'mouseup', dt.timeUp( 1 ) );
590         assert.equal( dt.minute().innerHTML, 17 );
591         trigger( 'mousedown', dt.timeUp( 2 ) );
592         trigger( 'mouseup', dt.timeUp( 2 ) );
593         assert.equal( dt.second().innerHTML, 3 );
594     });
595
4ed404 596     it( 'decrease time with timeConstraints', function( done ){
LG 597         createDatetime({ timeFormat: "HH:mm:ss:SSS", viewMode: 'time', defaultValue: date, onChange: function( selected ){
598             assert.equal( selected.minute(), 47 );
599             done();
600         }, timeConstraints: { minutes: { step: 15 }}});
601
602         trigger( 'mousedown', dt.timeDown( 1 ) );
603         trigger( 'mouseup', dt.timeDown( 1 ) );
604         assert.equal( dt.minute().innerHTML, 47 );
605     });
606
62fd2f 607     it( 'invalid input value', function( done ){
M 608         createDatetime({ defaultValue: 'luis', onChange: function( updated ){
609             assert.equal( mDate.format('L LT'), updated.format('L LT') );
610             done();
611         }});
612
613         assert.equal( dt.input().value, 'luis' );
614         dt.input().value = strDate;
92a2c6 615         ev.change( dt.input() );
62fd2f 616     });
M 617
618     it( 'delete input value', function( done ){
619         createDatetime({ defaultValue: date, onChange: function( date ){
620             assert.equal( date, '' );
621             done();
622         }});
623         dt.input().value = '';
92a2c6 624         ev.change( dt.input() );
62fd2f 625     });
0eb226 626
NB 627     it( 'strictParsing=true', function( done ){
628         var invalidStrDate = strDate + 'x';
629         createDatetime({ defaultValue: '', strictParsing: true, onChange: function( updated ){
630             assert.equal( updated, invalidStrDate);
631             done();
632         }});
633
634         dt.input().value = invalidStrDate;
92a2c6 635         ev.change( dt.input() );
0eb226 636     });
NB 637
638     it( 'strictParsing=false', function( done ){
639         var invalidStrDate = strDate + 'x';
640         createDatetime({ defaultValue: '', strictParsing: false, onChange: function( updated ){
641             assert.equal( mDate.format('L LT'), updated.format('L LT') );
642             done();
643         }});
644
645         dt.input().value = invalidStrDate;
92a2c6 646         ev.change( dt.input() );
0eb226 647     });
0d9dc7 648 });