fix #7760 - translation allowed on date and time fields
authorAlan <alan@roojs.com>
Thu, 10 Aug 2023 08:27:55 +0000 (16:27 +0800)
committerAlan <alan@roojs.com>
Thu, 10 Aug 2023 08:27:55 +0000 (16:27 +0800)
Roo/bootstrap/form/DateField.js
Roo/bootstrap/form/TimeField.js
roojs-bootstrap-debug.js
roojs-bootstrap.js

index 6f07f05..f392310 100644 (file)
@@ -27,7 +27,7 @@
  * Create a new DateField
  * @param {Object} config The config object
  */
-
 Roo.bootstrap.form.DateField = function(config){
     Roo.bootstrap.form.DateField.superclass.constructor.call(this, config);
      this.addEvents({
@@ -70,12 +70,6 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
      * valid according to {@link Date#parseDate} (defaults to 'm/d/y').
      */
     format : "m/d/y",
-    /**
-     * @cfg {String} altFormats
-     * Multiple date formats separated by "|" to try when parsing a user input value and it doesn't match the defined
-     * format (defaults to 'm/d/Y|m-d-y|m-d-Y|m/d|m-d|d').
-     */
-    altFormats : "m/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d",
     
     weekStart : 0,
     
@@ -102,6 +96,8 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
     _events: [],
     
     singleMode : false,
+
+    hiddenField : false,
     
     UTCDate: function()
     {
@@ -129,17 +125,77 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
     
     setUTCDate: function(d) {
             this.date = d;
-            this.setValue(this.formatDate(this.date));
+            this.setValue(this.date);
+    },
+
+    translateDates: function(lang) 
+    {
+        var translation = Roo.bootstrap.form.DateField.dates[lang] = {
+            days: [],
+            daysShort: [],
+            daysMin: [],
+            months: [],
+            monthsShort: []
+        };
+
+        var locale = lang.replace('_', '-');
+
+        var is_latin = [ 'zh-hk', 'zh-cn', 'jp', 'ko' ].indexOf(locale.toLowerCase()) < 0; 
+                
+
+        // fill days
+        for(var i = 0; i < 7; i++) {
+            var date = new Date(2020, 0, 5 + i);
+
+            var day = new Intl.DateTimeFormat(locale, {
+                weekday : 'long'
+            }).format(date);
+
+            var dayShort = new Intl.DateTimeFormat(locale, {
+                weekday : 'short'
+            }).format(date);
+
+            var dayMin = new Intl.DateTimeFormat(locale, {
+                weekday : 'narrow'
+            }).format(date);
+
+            if(is_latin) {
+                dayShort = day.substring(0, 3);
+                dayMin = day.substring(0, 2);
+            }
+            
+            translation.days.push(day);
+            translation.daysShort.push(dayShort);
+            translation.daysMin.push(dayMin);
+        }
+
+        // fill months
+        for(var i = 0; i < 12; i++) {
+            var date = new Date(2020, i);
+
+            var month = new Intl.DateTimeFormat(locale, {
+                month : 'long'
+            }).format(date);
+
+            var monthShort = new Intl.DateTimeFormat(locale, {
+                month : 'short'
+            }).format(date);
+
+            if(is_latin) {
+                monthShort = month.substring(0, 3);
+            }
+
+            translation.months.push(month);
+            translation/monthsShort.push(monthShort);
+        }
     },
         
     onRender: function(ct, position)
     {
         
         Roo.bootstrap.form.DateField.superclass.onRender.call(this, ct, position);
-        
-        this.language = this.language || 'en';
-        this.language = this.language in Roo.bootstrap.form.DateField.dates ? this.language : this.language.split('-')[0];
-        this.language = this.language in Roo.bootstrap.form.DateField.dates ? this.language : "en";
+
+        this.translateDates(this.language);
         
         this.isRTL = Roo.bootstrap.form.DateField.dates[this.language].rtl || false;
         this.format = this.format || 'm/d/y';
@@ -202,15 +258,7 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
         }
         
         Roo.each(this.picker().select('tfoot th.today', true).elements, function(v){
-            if(!this.calendarWeeks){
-                v.remove();
-                return;
-            }
-            
-            v.dom.innerHTML = Roo.bootstrap.form.DateField.dates[this.language].today;
-            v.attr('colspan', function(i, val){
-                return parseInt(val) + 1;
-            });
+            v.dom.innerHTML = Roo.bootstrap.form.DateField.todayText;
         });
                        
         
@@ -229,6 +277,14 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
         if(this.isInline) {
             this.showPopup();
         }
+
+        this.hiddenField = this.inputEl().insertSibling(
+            {tag : 'input', type : 'hidden', name : this.name},
+            'before',
+            true
+        );
+        this.inputEl().dom.setAttribute('name', this.name + '____hidden___');
+
     },
     
     picker : function()
@@ -248,14 +304,6 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
             ]
         };
         
-        if(this.calendarWeeks){
-            dow.cn.push({
-                tag: 'th',
-                cls: 'cw',
-                html: '&nbsp;'
-            })
-        }
-        
         while (dowCnt < this.weekStart + 7) {
             dow.cn.push({
                 tag: 'th',
@@ -314,12 +362,6 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
                 today = this.UTCToday();
         
         this.picker().select('>.datepicker-days thead th.switch', true).first().dom.innerHTML = Roo.bootstrap.form.DateField.dates[this.language].months[month]+' '+year;
-        
-//        this.picker().select('>tfoot th.today', true).first().dom.innerHTML = Roo.bootstrap.form.DateField.dates[this.language].today;
-        
-//        this.picker.select('>tfoot th.today').
-//                                             .text(dates[this.language].today)
-//                                             .toggle(this.todayBtn !== false);
     
         this.updateNavArrows();
         this.fillMonths();
@@ -354,26 +396,6 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
                     tag: 'tr',
                     cn: []
                 };
-                
-                if(this.calendarWeeks){
-                    // ISO 8601: First week contains first thursday.
-                    // ISO also states week starts on Monday, but we can be more abstract here.
-                    var
-                    // Start of current week: based on weekstart/current date
-                    ws = new Date(+prevMonth + (this.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5),
-                    // Thursday of this week
-                    th = new Date(+ws + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
-                    // First Thursday of year, year from thursday
-                    yth = new Date(+(yth = this.UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5),
-                    // Calendar week: ms between thursdays, div ms per day, div 7 days
-                    calWeek =  (th - yth) / 864e5 / 7 + 1;
-                    
-                    fillMonths.cn.push({
-                        tag: 'td',
-                        cls: 'cw',
-                        html: calWeek
-                    });
-                }
             }
             
             if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) {
@@ -481,24 +503,18 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
         this.picker().setTop(this.inputEl().getBottom()).setLeft(this.inputEl().getLeft());
     },
     
+    // return false when it fails
     parseDate : function(value)
     {
-        if(!value || value instanceof Date){
-            return value;
-        }
-        var v = Date.parseDate(value, this.format);
-        if (!v && (this.useIso || value.match(/^(\d{4})-0?(\d+)-0?(\d+)/))) {
-            v = Date.parseDate(value, 'Y-m-d');
+        if(!value) {
+            return false;
         }
-        if(!v && this.altFormats){
-            if(!this.altFormatsArray){
-                this.altFormatsArray = this.altFormats.split("|");
-            }
-            for(var i = 0, len = this.altFormatsArray.length; i < len && !v; i++){
-                v = Date.parseDate(value, this.altFormatsArray[i]);
-            }
+        if(value instanceof Date){
+            return value;
         }
-        return v;
+        var v = Date.parseDate(value, 'Y-m-d');
+
+        return (typeof(v) == 'undefined') ? false : v;
     },
     
     formatDate : function(date, fmt)
@@ -506,6 +522,20 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
         return (!date || !(date instanceof Date)) ?
         date : date.dateFormat(fmt || this.format);
     },
+
+    translateDate : function(date)
+    {
+        switch(this.language) {
+            case 'zh_CN':
+                return new Intl.DateTimeFormat('zh-CN', {
+                    year : 'numeric',
+                    month : 'long',
+                    day : 'numeric'
+                }).format(date);
+            default :
+                return this.formatDate(date);
+        }
+    },
     
     onFocus : function()
     {
@@ -516,10 +546,17 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
     onBlur : function()
     {
         Roo.bootstrap.form.DateField.superclass.onBlur.call(this);
-        
-        var d = this.inputEl().getValue();
-        
-        this.setValue(d);
+
+        if(!this.readOnly) {
+            var d = this.inputEl().getValue();
+            var date = this.parseDate(d);
+            if(date) {
+                this.setValue(date);
+            }
+            else {
+                this.setValue(this.getValue());
+            }
+        }
                 
         this.hidePopup();
     },
@@ -561,17 +598,56 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
     setValue: function(v)
     {
         if(this.fireEvent('beforeselect', this, v) !== false){
-            var d = new Date(this.parseDate(v) ).clearTime();
-        
-            if(isNaN(d.getTime())){
-                this.date = this.viewDate = '';
-                Roo.bootstrap.form.DateField.superclass.setValue.call(this, '');
+            var d = this.parseDate(v);
+
+            if(!d) {
+                this.date = this.viewDate = this.value = this.hiddenField.value =  '';
+                if(this.rendered){
+                    this.inputEl().dom.value = '';
+                    this.validate();
+                }
+                return;
+            }
+
+            d = new Date(d).clearTime();
+
+            this.value = this.hiddenField.value = d.dateFormat('Y-m-d');
+
+            v = this.translateDate(d);
+            if(this.rendered){
+                this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
+                this.validate();
+            }
+
+            this.date = new Date(d.getTime() - d.getTimezoneOffset()*60000);
+
+            this.update();
+
+            this.fireEvent('select', this, this.date);
+        }
+    },
+
+    // bypass validation
+    setRawValue : function(v){
+        if(this.fireEvent('beforeselect', this, v) !== false){
+            var d = this.parseDate(v);
+
+            if(!d) {
+                this.date = this.viewDate = this.value = this.hiddenField.value =  '';
+                if(this.rendered){
+                    this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
+                }
                 return;
             }
 
-            v = this.formatDate(d);
+            d = new Date(d).clearTime();
+
+            this.value = this.hiddenField.value = d.dateFormat('Y-m-d');
 
-            Roo.bootstrap.form.DateField.superclass.setValue.call(this, v);
+            v = this.translateDate(d);
+            if(this.rendered){
+                this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
+            }
 
             this.date = new Date(d.getTime() - d.getTimezoneOffset()*60000);
 
@@ -583,7 +659,11 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
     
     getValue: function()
     {
-        return this.formatDate(this.date);
+        return this.value;
+    },
+
+    getRawValue : function(){
+        return this.getValue();
     },
     
     fireKey: function(e)
@@ -626,7 +706,7 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
                 if (this.dateWithinRange(newDate)){
                     this.date = newDate;
                     this.viewDate = newViewDate;
-                    this.setValue(this.formatDate(this.date));
+                    this.setValue(this.date);
 //                    this.update();
                     e.preventDefault();
                     dateChanged = true;
@@ -653,19 +733,19 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
                 if (this.dateWithinRange(newDate)){
                     this.date = newDate;
                     this.viewDate = newViewDate;
-                    this.setValue(this.formatDate(this.date));
+                    this.setValue(this.date);
 //                    this.update();
                     e.preventDefault();
                     dateChanged = true;
                 }
                 break;
             case 13: // enter
-                this.setValue(this.formatDate(this.date));
+                this.setValue(this.date);
                 this.hidePopup();
                 e.preventDefault();
                 break;
             case 9: // tab
-                this.setValue(this.formatDate(this.date));
+                this.setValue(this.date);
                 this.hidePopup();
                 break;
             case 16: // shift
@@ -719,7 +799,7 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
                         var date = new Date();
                         this.date = this.UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
 //                        this.fill()
-                        this.setValue(this.formatDate(this.date));
+                        this.setValue(this.date);
                         
                         this.hidePopup();
                         break;
@@ -740,7 +820,7 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
                     }
                     
                     if(this.singleMode){
-                        this.setValue(this.formatDate(this.viewDate));
+                        this.setValue(this.viewDate);
                         this.hidePopup();
                         return;
                     }
@@ -776,8 +856,7 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
                     this.date = this.UTCDate(year, month, day,0,0,0,0);
                     this.viewDate = this.UTCDate(year, month, Math.min(28, day),0,0,0,0);
 //                    this.fill();
-                    //Roo.log(this.formatDate(this.date));
-                    this.setValue(this.formatDate(this.date));
+                    this.setValue(this.date);
                     this.hidePopup();
                 }
                 break;
@@ -788,7 +867,8 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
     {
         this.startDate = startDate || -Infinity;
         if (this.startDate !== -Infinity) {
-            this.startDate = this.parseDate(this.startDate);
+            var date = this.parseDate(this.startDate);
+            this.startDate = date ? date : -Infinity;
         }
         this.update();
         this.updateNavArrows();
@@ -798,7 +878,8 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
     {
         this.endDate = endDate || Infinity;
         if (this.endDate !== Infinity) {
-            this.endDate = this.parseDate(this.endDate);
+            var date = this.parseDate(this.endDate);
+            this.endDate = date ? date : Infinity;
         }
         this.update();
         this.updateNavArrows();
@@ -967,7 +1048,7 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
             return false;
         }
         
-        if(typeof(this.parseDate(value)) == 'undefined'){
+        if(!this.parseDate(value)){
             return false;
         }
         
@@ -1053,16 +1134,9 @@ Roo.apply(Roo.bootstrap.form.DateField,  {
         ]
     },
     
-    dates:{
-        en: {
-            days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
-            daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
-            daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
-            months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
-            monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
-            today: "Today"
-        }
-    },
+    dates : {},
+
+    todayText : "Today",
     
     modes: [
     {
index 3c7dce6..121f875 100644 (file)
@@ -53,7 +53,8 @@ Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input,  {
      */
     format : "H:i",
     minuteStep : 1,
-
+    language : 'en',
+    hiddenField : false,
     getAutoCreate : function()
     {
         this.after = '<i class="fa far fa-clock"></i>';
@@ -65,6 +66,8 @@ Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input,  {
     {
         
         Roo.bootstrap.form.TimeField.superclass.onRender.call(this, ct, position);
+
+        this.language = this.language in Roo.bootstrap.form.TimeField.periodText ? this.language : "en";
                 
         this.pickerEl = Roo.get(document.body).createChild(Roo.bootstrap.form.TimeField.template);
         
@@ -87,6 +90,14 @@ Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input,  {
         this.pop.select('.minutes-down', true).first().on('click', this.onDecrementMinutes, this);
         this.pop.select('button.period', true).first().on('click', this.onTogglePeriod, this);
         this.pop.select('button.ok', true).first().on('click', this.setTime, this);
+        this.pop.select('button.ok', true).first().dom.innerHTML = Roo.bootstrap.form.TimeField.okText;
+
+        this.hiddenField = this.inputEl().insertSibling(
+            {tag : 'input', type : 'hidden', name : this.name},
+            'before',
+            true
+        );
+        this.inputEl().dom.setAttribute('name', this.name + '____hidden___');
 
     },
     
@@ -294,10 +305,10 @@ Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input,  {
     {
         var hours = this.time.getHours();
         var minutes = this.time.getMinutes();
-        var period = 'AM';
+        var period = Roo.bootstrap.form.TimeField.periodText[this.language]['am'];
         
         if(hours > 11){
-            period = 'PM';
+            period = Roo.bootstrap.form.TimeField.periodText[this.language]['pm'];
         }
         
         if(hours == 0){
@@ -393,7 +404,7 @@ Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input,  {
         this.update();
         this.place();
         
-        this.fireEvent('show', this, this.date);
+        this.fireEvent('show', this, this.time);
     },
     
     hide : function()
@@ -401,18 +412,107 @@ Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input,  {
         this.picker().hide();
         this.pop.hide();
         
-        this.fireEvent('hide', this, this.date);
+        this.fireEvent('hide', this, this.time);
     },
     
     setTime : function()
     {
         this.hide();
-        this.setValue(this.time.format(this.format));
+        this.setValue(this.time);
         
-        this.fireEvent('select', this, this.date);
+        this.fireEvent('select', this, this.time);
         
         
     },
+
+    // return false when it fails
+    parseTime : function(value)
+    {
+        if(!value) {
+            return false;
+        }
+        if(value instanceof Date){
+            return value;
+        }
+        var v = Date.parseDate(value, 'H:i:s');
+
+        return (typeof(v) == 'undefined') ? false : v;
+    },
+
+    translateTime : function(time)
+    {
+        switch(this.language) {
+            case 'zh_CN':
+                return new Intl.DateTimeFormat('zh-CN', {
+                    hour : 'numeric',
+                    minute : 'numeric',
+                    hour12 : true
+                }).format(time);
+            default :
+                return time.format(this.format);
+        }
+    },
+
+    setValue: function(v)
+    {
+        var t = this.parseTime(v);
+
+        if(!t) {
+            this.time = this.value = this.hiddenField.value =  '';
+            if(this.rendered){
+                this.inputEl().dom.value = '';
+                this.validate();
+            }
+            return;
+        }
+
+        this.value = this.hiddenField.value = t.dateFormat('H:i:s');
+
+        v = this.translateTime(t);
+
+        if(this.rendered){
+            this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
+            this.validate();
+        }
+
+        this.time = t;
+
+        this.update();
+    },
+
+    setRawValue: function(v)
+    {
+        var t = this.parseTime(v);
+
+        if(!t) {
+            this.time = this.value = this.hiddenField.value =  '';
+            if(this.rendered){
+                this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
+            }
+            return;
+        }
+
+        this.value = this.hiddenField.value = t.dateFormat('H:i:s');
+
+        v = this.translateTime(t);
+
+        if(this.rendered){
+            this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
+        }
+
+        this.time = t;
+
+        this.update();
+    },
+
+    getValue: function()
+    {
+        return this.value;
+    },
+
+    getRawValue : function(){
+        return this.getValue();
+    },
     
     onMousedown: function(e){
         e.stopPropagation();
@@ -459,10 +559,21 @@ Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input,  {
     
    
 });
+Roo.apply(Roo.bootstrap.form.TimeField,  {
+    okText : 'OK',
+    periodText : {
+        en : {
+            am : 'AM',
+            pm : 'PM'
+        },
+        zh_CN : {
+            am : '上午',
+            pm : '下午'
+        }
+    }
+});
 
 Roo.apply(Roo.bootstrap.form.TimeField,  {
-  
     template : {
         tag: 'div',
         cls: 'datepicker dropdown-menu',
@@ -503,7 +614,7 @@ Roo.apply(Roo.bootstrap.form.TimeField,  {
                                             {
                                                 tag: 'button',
                                                 cls: 'btn btn-info ok',
-                                                html: 'OK'
+                                                html: "OK" // this is overridden on construciton
                                             }
                                         ]
                                     }
index 3880c68..61f231c 100644 (file)
@@ -22873,7 +22873,7 @@ Roo.extend(Roo.bootstrap.TabPanel, Roo.bootstrap.Component,  {
  * Create a new DateField
  * @param {Object} config The config object
  */
-
 Roo.bootstrap.form.DateField = function(config){
     Roo.bootstrap.form.DateField.superclass.constructor.call(this, config);
      this.addEvents({
@@ -22916,12 +22916,6 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
      * valid according to {@link Date#parseDate} (defaults to 'm/d/y').
      */
     format : "m/d/y",
-    /**
-     * @cfg {String} altFormats
-     * Multiple date formats separated by "|" to try when parsing a user input value and it doesn't match the defined
-     * format (defaults to 'm/d/Y|m-d-y|m-d-Y|m/d|m-d|d').
-     */
-    altFormats : "m/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d",
     
     weekStart : 0,
     
@@ -22948,6 +22942,8 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
     _events: [],
     
     singleMode : false,
+
+    hiddenField : false,
     
     UTCDate: function()
     {
@@ -22975,17 +22971,77 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
     
     setUTCDate: function(d) {
             this.date = d;
-            this.setValue(this.formatDate(this.date));
+            this.setValue(this.date);
+    },
+
+    translateDates: function(lang) 
+    {
+        var translation = Roo.bootstrap.form.DateField.dates[lang] = {
+            days: [],
+            daysShort: [],
+            daysMin: [],
+            months: [],
+            monthsShort: []
+        };
+
+        var locale = lang.replace('_', '-');
+
+        var is_latin = [ 'zh-hk', 'zh-cn', 'jp', 'ko' ].indexOf(locale.toLowerCase()) < 0; 
+                
+
+        // fill days
+        for(var i = 0; i < 7; i++) {
+            var date = new Date(2020, 0, 5 + i);
+
+            var day = new Intl.DateTimeFormat(locale, {
+                weekday : 'long'
+            }).format(date);
+
+            var dayShort = new Intl.DateTimeFormat(locale, {
+                weekday : 'short'
+            }).format(date);
+
+            var dayMin = new Intl.DateTimeFormat(locale, {
+                weekday : 'narrow'
+            }).format(date);
+
+            if(is_latin) {
+                dayShort = day.substring(0, 3);
+                dayMin = day.substring(0, 2);
+            }
+            
+            translation.days.push(day);
+            translation.daysShort.push(dayShort);
+            translation.daysMin.push(dayMin);
+        }
+
+        // fill months
+        for(var i = 0; i < 12; i++) {
+            var date = new Date(2020, i);
+
+            var month = new Intl.DateTimeFormat(locale, {
+                month : 'long'
+            }).format(date);
+
+            var monthShort = new Intl.DateTimeFormat(locale, {
+                month : 'short'
+            }).format(date);
+
+            if(is_latin) {
+                monthShort = month.substring(0, 3);
+            }
+
+            translation.months.push(month);
+            translation/monthsShort.push(monthShort);
+        }
     },
         
     onRender: function(ct, position)
     {
         
         Roo.bootstrap.form.DateField.superclass.onRender.call(this, ct, position);
-        
-        this.language = this.language || 'en';
-        this.language = this.language in Roo.bootstrap.form.DateField.dates ? this.language : this.language.split('-')[0];
-        this.language = this.language in Roo.bootstrap.form.DateField.dates ? this.language : "en";
+
+        this.translateDates(this.language);
         
         this.isRTL = Roo.bootstrap.form.DateField.dates[this.language].rtl || false;
         this.format = this.format || 'm/d/y';
@@ -23048,15 +23104,7 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
         }
         
         Roo.each(this.picker().select('tfoot th.today', true).elements, function(v){
-            if(!this.calendarWeeks){
-                v.remove();
-                return;
-            }
-            
-            v.dom.innerHTML = Roo.bootstrap.form.DateField.dates[this.language].today;
-            v.attr('colspan', function(i, val){
-                return parseInt(val) + 1;
-            });
+            v.dom.innerHTML = Roo.bootstrap.form.DateField.todayText;
         });
                        
         
@@ -23075,6 +23123,14 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
         if(this.isInline) {
             this.showPopup();
         }
+
+        this.hiddenField = this.inputEl().insertSibling(
+            {tag : 'input', type : 'hidden', name : this.name},
+            'before',
+            true
+        );
+        this.inputEl().dom.setAttribute('name', this.name + '____hidden___');
+
     },
     
     picker : function()
@@ -23094,14 +23150,6 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
             ]
         };
         
-        if(this.calendarWeeks){
-            dow.cn.push({
-                tag: 'th',
-                cls: 'cw',
-                html: '&nbsp;'
-            })
-        }
-        
         while (dowCnt < this.weekStart + 7) {
             dow.cn.push({
                 tag: 'th',
@@ -23160,12 +23208,6 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
                 today = this.UTCToday();
         
         this.picker().select('>.datepicker-days thead th.switch', true).first().dom.innerHTML = Roo.bootstrap.form.DateField.dates[this.language].months[month]+' '+year;
-        
-//        this.picker().select('>tfoot th.today', true).first().dom.innerHTML = Roo.bootstrap.form.DateField.dates[this.language].today;
-        
-//        this.picker.select('>tfoot th.today').
-//                                             .text(dates[this.language].today)
-//                                             .toggle(this.todayBtn !== false);
     
         this.updateNavArrows();
         this.fillMonths();
@@ -23200,26 +23242,6 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
                     tag: 'tr',
                     cn: []
                 };
-                
-                if(this.calendarWeeks){
-                    // ISO 8601: First week contains first thursday.
-                    // ISO also states week starts on Monday, but we can be more abstract here.
-                    var
-                    // Start of current week: based on weekstart/current date
-                    ws = new Date(+prevMonth + (this.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5),
-                    // Thursday of this week
-                    th = new Date(+ws + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
-                    // First Thursday of year, year from thursday
-                    yth = new Date(+(yth = this.UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5),
-                    // Calendar week: ms between thursdays, div ms per day, div 7 days
-                    calWeek =  (th - yth) / 864e5 / 7 + 1;
-                    
-                    fillMonths.cn.push({
-                        tag: 'td',
-                        cls: 'cw',
-                        html: calWeek
-                    });
-                }
             }
             
             if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) {
@@ -23327,24 +23349,18 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
         this.picker().setTop(this.inputEl().getBottom()).setLeft(this.inputEl().getLeft());
     },
     
+    // return false when it fails
     parseDate : function(value)
     {
-        if(!value || value instanceof Date){
-            return value;
-        }
-        var v = Date.parseDate(value, this.format);
-        if (!v && (this.useIso || value.match(/^(\d{4})-0?(\d+)-0?(\d+)/))) {
-            v = Date.parseDate(value, 'Y-m-d');
+        if(!value) {
+            return false;
         }
-        if(!v && this.altFormats){
-            if(!this.altFormatsArray){
-                this.altFormatsArray = this.altFormats.split("|");
-            }
-            for(var i = 0, len = this.altFormatsArray.length; i < len && !v; i++){
-                v = Date.parseDate(value, this.altFormatsArray[i]);
-            }
+        if(value instanceof Date){
+            return value;
         }
-        return v;
+        var v = Date.parseDate(value, 'Y-m-d');
+
+        return (typeof(v) == 'undefined') ? false : v;
     },
     
     formatDate : function(date, fmt)
@@ -23352,6 +23368,20 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
         return (!date || !(date instanceof Date)) ?
         date : date.dateFormat(fmt || this.format);
     },
+
+    translateDate : function(date)
+    {
+        switch(this.language) {
+            case 'zh_CN':
+                return new Intl.DateTimeFormat('zh-CN', {
+                    year : 'numeric',
+                    month : 'long',
+                    day : 'numeric'
+                }).format(date);
+            default :
+                return this.formatDate(date);
+        }
+    },
     
     onFocus : function()
     {
@@ -23362,10 +23392,17 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
     onBlur : function()
     {
         Roo.bootstrap.form.DateField.superclass.onBlur.call(this);
-        
-        var d = this.inputEl().getValue();
-        
-        this.setValue(d);
+
+        if(!this.readOnly) {
+            var d = this.inputEl().getValue();
+            var date = this.parseDate(d);
+            if(date) {
+                this.setValue(date);
+            }
+            else {
+                this.setValue(this.getValue());
+            }
+        }
                 
         this.hidePopup();
     },
@@ -23407,17 +23444,56 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
     setValue: function(v)
     {
         if(this.fireEvent('beforeselect', this, v) !== false){
-            var d = new Date(this.parseDate(v) ).clearTime();
-        
-            if(isNaN(d.getTime())){
-                this.date = this.viewDate = '';
-                Roo.bootstrap.form.DateField.superclass.setValue.call(this, '');
+            var d = this.parseDate(v);
+
+            if(!d) {
+                this.date = this.viewDate = this.value = this.hiddenField.value =  '';
+                if(this.rendered){
+                    this.inputEl().dom.value = '';
+                    this.validate();
+                }
+                return;
+            }
+
+            d = new Date(d).clearTime();
+
+            this.value = this.hiddenField.value = d.dateFormat('Y-m-d');
+
+            v = this.translateDate(d);
+            if(this.rendered){
+                this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
+                this.validate();
+            }
+
+            this.date = new Date(d.getTime() - d.getTimezoneOffset()*60000);
+
+            this.update();
+
+            this.fireEvent('select', this, this.date);
+        }
+    },
+
+    // bypass validation
+    setRawValue : function(v){
+        if(this.fireEvent('beforeselect', this, v) !== false){
+            var d = this.parseDate(v);
+
+            if(!d) {
+                this.date = this.viewDate = this.value = this.hiddenField.value =  '';
+                if(this.rendered){
+                    this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
+                }
                 return;
             }
 
-            v = this.formatDate(d);
+            d = new Date(d).clearTime();
 
-            Roo.bootstrap.form.DateField.superclass.setValue.call(this, v);
+            this.value = this.hiddenField.value = d.dateFormat('Y-m-d');
+
+            v = this.translateDate(d);
+            if(this.rendered){
+                this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
+            }
 
             this.date = new Date(d.getTime() - d.getTimezoneOffset()*60000);
 
@@ -23429,7 +23505,11 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
     
     getValue: function()
     {
-        return this.formatDate(this.date);
+        return this.value;
+    },
+
+    getRawValue : function(){
+        return this.getValue();
     },
     
     fireKey: function(e)
@@ -23472,7 +23552,7 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
                 if (this.dateWithinRange(newDate)){
                     this.date = newDate;
                     this.viewDate = newViewDate;
-                    this.setValue(this.formatDate(this.date));
+                    this.setValue(this.date);
 //                    this.update();
                     e.preventDefault();
                     dateChanged = true;
@@ -23499,19 +23579,19 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
                 if (this.dateWithinRange(newDate)){
                     this.date = newDate;
                     this.viewDate = newViewDate;
-                    this.setValue(this.formatDate(this.date));
+                    this.setValue(this.date);
 //                    this.update();
                     e.preventDefault();
                     dateChanged = true;
                 }
                 break;
             case 13: // enter
-                this.setValue(this.formatDate(this.date));
+                this.setValue(this.date);
                 this.hidePopup();
                 e.preventDefault();
                 break;
             case 9: // tab
-                this.setValue(this.formatDate(this.date));
+                this.setValue(this.date);
                 this.hidePopup();
                 break;
             case 16: // shift
@@ -23565,7 +23645,7 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
                         var date = new Date();
                         this.date = this.UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
 //                        this.fill()
-                        this.setValue(this.formatDate(this.date));
+                        this.setValue(this.date);
                         
                         this.hidePopup();
                         break;
@@ -23586,7 +23666,7 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
                     }
                     
                     if(this.singleMode){
-                        this.setValue(this.formatDate(this.viewDate));
+                        this.setValue(this.viewDate);
                         this.hidePopup();
                         return;
                     }
@@ -23622,8 +23702,7 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
                     this.date = this.UTCDate(year, month, day,0,0,0,0);
                     this.viewDate = this.UTCDate(year, month, Math.min(28, day),0,0,0,0);
 //                    this.fill();
-                    //Roo.log(this.formatDate(this.date));
-                    this.setValue(this.formatDate(this.date));
+                    this.setValue(this.date);
                     this.hidePopup();
                 }
                 break;
@@ -23634,7 +23713,8 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
     {
         this.startDate = startDate || -Infinity;
         if (this.startDate !== -Infinity) {
-            this.startDate = this.parseDate(this.startDate);
+            var date = this.parseDate(this.startDate);
+            this.startDate = date ? date : -Infinity;
         }
         this.update();
         this.updateNavArrows();
@@ -23644,7 +23724,8 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
     {
         this.endDate = endDate || Infinity;
         if (this.endDate !== Infinity) {
-            this.endDate = this.parseDate(this.endDate);
+            var date = this.parseDate(this.endDate);
+            this.endDate = date ? date : Infinity;
         }
         this.update();
         this.updateNavArrows();
@@ -23813,7 +23894,7 @@ Roo.extend(Roo.bootstrap.form.DateField, Roo.bootstrap.form.Input,  {
             return false;
         }
         
-        if(typeof(this.parseDate(value)) == 'undefined'){
+        if(!this.parseDate(value)){
             return false;
         }
         
@@ -23899,16 +23980,9 @@ Roo.apply(Roo.bootstrap.form.DateField,  {
         ]
     },
     
-    dates:{
-        en: {
-            days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
-            daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
-            daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
-            months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
-            monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
-            today: "Today"
-        }
-    },
+    dates : {},
+
+    todayText : "Today",
     
     modes: [
     {
@@ -24042,7 +24116,8 @@ Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input,  {
      */
     format : "H:i",
     minuteStep : 1,
-
+    language : 'en',
+    hiddenField : false,
     getAutoCreate : function()
     {
         this.after = '<i class="fa far fa-clock"></i>';
@@ -24054,6 +24129,8 @@ Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input,  {
     {
         
         Roo.bootstrap.form.TimeField.superclass.onRender.call(this, ct, position);
+
+        this.language = this.language in Roo.bootstrap.form.TimeField.periodText ? this.language : "en";
                 
         this.pickerEl = Roo.get(document.body).createChild(Roo.bootstrap.form.TimeField.template);
         
@@ -24076,6 +24153,14 @@ Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input,  {
         this.pop.select('.minutes-down', true).first().on('click', this.onDecrementMinutes, this);
         this.pop.select('button.period', true).first().on('click', this.onTogglePeriod, this);
         this.pop.select('button.ok', true).first().on('click', this.setTime, this);
+        this.pop.select('button.ok', true).first().dom.innerHTML = Roo.bootstrap.form.TimeField.okText;
+
+        this.hiddenField = this.inputEl().insertSibling(
+            {tag : 'input', type : 'hidden', name : this.name},
+            'before',
+            true
+        );
+        this.inputEl().dom.setAttribute('name', this.name + '____hidden___');
 
     },
     
@@ -24283,10 +24368,10 @@ Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input,  {
     {
         var hours = this.time.getHours();
         var minutes = this.time.getMinutes();
-        var period = 'AM';
+        var period = Roo.bootstrap.form.TimeField.periodText[this.language]['am'];
         
         if(hours > 11){
-            period = 'PM';
+            period = Roo.bootstrap.form.TimeField.periodText[this.language]['pm'];
         }
         
         if(hours == 0){
@@ -24382,7 +24467,7 @@ Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input,  {
         this.update();
         this.place();
         
-        this.fireEvent('show', this, this.date);
+        this.fireEvent('show', this, this.time);
     },
     
     hide : function()
@@ -24390,18 +24475,107 @@ Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input,  {
         this.picker().hide();
         this.pop.hide();
         
-        this.fireEvent('hide', this, this.date);
+        this.fireEvent('hide', this, this.time);
     },
     
     setTime : function()
     {
         this.hide();
-        this.setValue(this.time.format(this.format));
+        this.setValue(this.time);
         
-        this.fireEvent('select', this, this.date);
+        this.fireEvent('select', this, this.time);
         
         
     },
+
+    // return false when it fails
+    parseTime : function(value)
+    {
+        if(!value) {
+            return false;
+        }
+        if(value instanceof Date){
+            return value;
+        }
+        var v = Date.parseDate(value, 'H:i:s');
+
+        return (typeof(v) == 'undefined') ? false : v;
+    },
+
+    translateTime : function(time)
+    {
+        switch(this.language) {
+            case 'zh_CN':
+                return new Intl.DateTimeFormat('zh-CN', {
+                    hour : 'numeric',
+                    minute : 'numeric',
+                    hour12 : true
+                }).format(time);
+            default :
+                return time.format(this.format);
+        }
+    },
+
+    setValue: function(v)
+    {
+        var t = this.parseTime(v);
+
+        if(!t) {
+            this.time = this.value = this.hiddenField.value =  '';
+            if(this.rendered){
+                this.inputEl().dom.value = '';
+                this.validate();
+            }
+            return;
+        }
+
+        this.value = this.hiddenField.value = t.dateFormat('H:i:s');
+
+        v = this.translateTime(t);
+
+        if(this.rendered){
+            this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
+            this.validate();
+        }
+
+        this.time = t;
+
+        this.update();
+    },
+
+    setRawValue: function(v)
+    {
+        var t = this.parseTime(v);
+
+        if(!t) {
+            this.time = this.value = this.hiddenField.value =  '';
+            if(this.rendered){
+                this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
+            }
+            return;
+        }
+
+        this.value = this.hiddenField.value = t.dateFormat('H:i:s');
+
+        v = this.translateTime(t);
+
+        if(this.rendered){
+            this.inputEl().dom.value = (v === null || v === undefined ? '' : v);
+        }
+
+        this.time = t;
+
+        this.update();
+    },
+
+    getValue: function()
+    {
+        return this.value;
+    },
+
+    getRawValue : function(){
+        return this.getValue();
+    },
     
     onMousedown: function(e){
         e.stopPropagation();
@@ -24448,10 +24622,21 @@ Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input,  {
     
    
 });
+Roo.apply(Roo.bootstrap.form.TimeField,  {
+    okText : 'OK',
+    periodText : {
+        en : {
+            am : 'AM',
+            pm : 'PM'
+        },
+        zh_CN : {
+            am : '上午',
+            pm : '下午'
+        }
+    }
+});
 
 Roo.apply(Roo.bootstrap.form.TimeField,  {
-  
     template : {
         tag: 'div',
         cls: 'datepicker dropdown-menu',
@@ -24492,7 +24677,7 @@ Roo.apply(Roo.bootstrap.form.TimeField,  {
                                             {
                                                 tag: 'button',
                                                 cls: 'btn btn-info ok',
-                                                html: 'OK'
+                                                html: "OK" // this is overridden on construciton
                                             }
                                         ]
                                     }
index a710323..7403366 100644 (file)
@@ -963,48 +963,51 @@ if(this.active&&tg.bullets>0&&i<tg.bullets){tg.setActiveBullet(i);}}this.el.on('
 this.startY=e.browserEvent.touches[0].clientY;},onTouchMove:function(e){this.swiping=true;this.endX=e.browserEvent.touches[0].clientX;this.endY=e.browserEvent.touches[0].clientY;},onTouchEnd:function(e){if(!this.swiping){this.onClick(e);return;}var A=this.parent();
 if(this.endX>this.startX){A.showPanelPrev();return;}if(this.startX>this.endX){A.showPanelNext();return;}}});
 // Roo/bootstrap/form/DateField.js
-Roo.bootstrap.form.DateField=function(A){Roo.bootstrap.form.DateField.superclass.constructor.call(this,A);this.addEvents({show:true,hide:true,select:true,beforeselect:true});};Roo.extend(Roo.bootstrap.form.DateField,Roo.bootstrap.form.Input,{format:"m/d/y",altFormats:"m/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d",weekStart:0,viewMode:'',minViewMode:'',todayHighlight:false,todayBtn:false,language:'en',keyboardNavigation:true,calendarWeeks:false,startDate:-Infinity,endDate:Infinity,daysOfWeekDisabled:[],_events:[],singleMode:false,UTCDate:function(){return new Date(Date.UTC.apply(Date,arguments));
+Roo.bootstrap.form.DateField=function(A){Roo.bootstrap.form.DateField.superclass.constructor.call(this,A);this.addEvents({show:true,hide:true,select:true,beforeselect:true});};Roo.extend(Roo.bootstrap.form.DateField,Roo.bootstrap.form.Input,{format:"m/d/y",weekStart:0,viewMode:'',minViewMode:'',todayHighlight:false,todayBtn:false,language:'en',keyboardNavigation:true,calendarWeeks:false,startDate:-Infinity,endDate:Infinity,daysOfWeekDisabled:[],_events:[],singleMode:false,hiddenField:false,UTCDate:function(){return new Date(Date.UTC.apply(Date,arguments));
 },UTCToday:function(){var A=new Date();return this.UTCDate(A.getUTCFullYear(),A.getUTCMonth(),A.getUTCDate());},getDate:function(){var d=this.getUTCDate();return new Date(d.getTime()+(d.getTimezoneOffset()*60000));},getUTCDate:function(){return this.date;
-},setDate:function(d){this.setUTCDate(new Date(d.getTime()-(d.getTimezoneOffset()*60000)));},setUTCDate:function(d){this.date=d;this.setValue(this.formatDate(this.date));},onRender:function(ct,A){Roo.bootstrap.form.DateField.superclass.onRender.call(this,ct,A);
-this.language=this.language||'en';this.language=this.language in Roo.bootstrap.form.DateField.dates?this.language:this.language.split('-')[0];this.language=this.language in Roo.bootstrap.form.DateField.dates?this.language:"en";this.isRTL=Roo.bootstrap.form.DateField.dates[this.language].rtl||false;
+},setDate:function(d){this.setUTCDate(new Date(d.getTime()-(d.getTimezoneOffset()*60000)));},setUTCDate:function(d){this.date=d;this.setValue(this.date);},translateDates:function(A){var B=Roo.bootstrap.form.DateField.dates[A]={days:[],daysShort:[],daysMin:[],months:[],monthsShort:[]}
+;var C=A.replace('_','-');var D=['zh-hk','zh-cn','jp','ko'].indexOf(C.toLowerCase())<0;for(var i=0;i<7;i++){var E=new Date(2020,0,5+i);var F=new Intl.DateTimeFormat(C,{weekday:'long'}).format(E);var G=new Intl.DateTimeFormat(C,{weekday:'short'}).format(E);
+var H=new Intl.DateTimeFormat(C,{weekday:'narrow'}).format(E);if(D){G=F.substring(0,3);H=F.substring(0,2);}B.days.push(F);B.daysShort.push(G);B.daysMin.push(H);}for(var i=0;i<12;i++){var E=new Date(2020,i);var I=new Intl.DateTimeFormat(C,{month:'long'}).format(E);
+var J=new Intl.DateTimeFormat(C,{month:'short'}).format(E);if(D){J=I.substring(0,3);}B.months.push(I);B/monthsShort.push(J);}},onRender:function(ct,A){Roo.bootstrap.form.DateField.superclass.onRender.call(this,ct,A);this.translateDates(this.language);this.isRTL=Roo.bootstrap.form.DateField.dates[this.language].rtl||false;
 this.format=this.format||'m/d/y';this.isInline=false;this.isInput=true;this.component=this.el.select('.add-on',true).first()||false;this.component=(this.component&&this.component.length===0)?false:this.component;this.hasInput=this.component&&this.inputEl().length;
 if(typeof(this.minViewMode==='string')){switch(this.minViewMode){case 'months':this.minViewMode=1;break;case 'years':this.minViewMode=2;break;default:this.minViewMode=0;break;}}if(typeof(this.viewMode==='string')){switch(this.viewMode){case 'months':this.viewMode=1;
 break;case 'years':this.viewMode=2;break;default:this.viewMode=0;break;}}this.pickerEl=Roo.get(document.body).createChild(Roo.bootstrap.form.DateField.template);this.picker().setVisibilityMode(Roo.Element.DISPLAY).originalDisplay='block';this.picker().on('mousedown',this.onMousedown,this);
 this.picker().on('click',this.onClick,this);this.picker().addClass('datepicker-dropdown');this.startViewMode=this.viewMode;if(this.singleMode){Roo.each(this.picker().select('thead > tr > th',true).elements,function(v){v.setVisibilityMode(Roo.Element.DISPLAY);
-v.hide();});Roo.each(this.picker().select('tbody > tr > td',true).elements,function(v){v.setStyle('width','189px');});}Roo.each(this.picker().select('tfoot th.today',true).elements,function(v){if(!this.calendarWeeks){v.remove();return;}v.dom.innerHTML=Roo.bootstrap.form.DateField.dates[this.language].today;
-v.attr('colspan',function(i,B){return parseInt(B)+1;});});this.weekEnd=this.weekStart===0?6:this.weekStart-1;this.setStartDate(this.startDate);this.setEndDate(this.endDate);this.setDaysOfWeekDisabled(this.daysOfWeekDisabled);this.fillDow();this.fillMonths();
-this.update();this.showMode();if(this.isInline){this.showPopup();}},picker:function(){return this.pickerEl;},fillDow:function(){var A=this.weekStart;var B={tag:'tr',cn:[]};if(this.calendarWeeks){B.cn.push({tag:'th',cls:'cw',html:'&nbsp;'})}while(A<this.weekStart+7){B.cn.push({tag:'th',cls:'dow',html:Roo.bootstrap.form.DateField.dates[this.language].daysMin[(A++)%7]}
+v.hide();});Roo.each(this.picker().select('tbody > tr > td',true).elements,function(v){v.setStyle('width','189px');});}Roo.each(this.picker().select('tfoot th.today',true).elements,function(v){v.dom.innerHTML=Roo.bootstrap.form.DateField.todayText;});this.weekEnd=this.weekStart===0?6:this.weekStart-1;
+this.setStartDate(this.startDate);this.setEndDate(this.endDate);this.setDaysOfWeekDisabled(this.daysOfWeekDisabled);this.fillDow();this.fillMonths();this.update();this.showMode();if(this.isInline){this.showPopup();}this.hiddenField=this.inputEl().insertSibling({tag:'input',type:'hidden',name:this.name}
+,'before',true);this.inputEl().dom.setAttribute('name',this.name+'____hidden___');},picker:function(){return this.pickerEl;},fillDow:function(){var A=this.weekStart;var B={tag:'tr',cn:[]};while(A<this.weekStart+7){B.cn.push({tag:'th',cls:'dow',html:Roo.bootstrap.form.DateField.dates[this.language].daysMin[(A++)%7]}
 );}this.picker().select('>.datepicker-days thead',true).first().createChild(B);},fillMonths:function(){var i=0;var A=this.picker().select('>.datepicker-months td',true).first();A.dom.innerHTML='';while(i<12){var B={tag:'span',cls:'month',html:Roo.bootstrap.form.DateField.dates[this.language].monthsShort[i++]}
 ;A.createChild(B);}},update:function(){this.date=(typeof(this.date)==='undefined'||((typeof(this.date)==='string')&&!this.date.length))?this.UTCToday():(typeof(this.date)==='string')?this.parseDate(this.date):this.date;if(this.date<this.startDate){this.viewDate=new Date(this.startDate);
 }else if(this.date>this.endDate){this.viewDate=new Date(this.endDate);}else{this.viewDate=new Date(this.date);}this.fill();},fill:function(){var d=new Date(this.viewDate),A=d.getUTCFullYear(),B=d.getUTCMonth(),C=this.startDate!==-Infinity?this.startDate.getUTCFullYear():-Infinity,D=this.startDate!==-Infinity?this.startDate.getUTCMonth():-Infinity,E=this.endDate!==Infinity?this.endDate.getUTCFullYear():Infinity,F=this.endDate!==Infinity?this.endDate.getUTCMonth():Infinity,G=this.date&&this.date.valueOf(),H=this.UTCToday();
 this.picker().select('>.datepicker-days thead th.switch',true).first().dom.innerHTML=Roo.bootstrap.form.DateField.dates[this.language].months[B]+' '+A;this.updateNavArrows();this.fillMonths();var I=this.UTCDate(A,B-1,28,0,0,0,0),J=I.getDaysInMonth(I.getUTCFullYear(),I.getUTCMonth());
 I.setUTCDate(J);I.setUTCDate(J-(I.getUTCDay()-this.weekStart+7)%7);var K=new Date(I);K.setUTCDate(K.getUTCDate()+42);K=K.valueOf();var L=false;this.picker().select('>.datepicker-days tbody',true).first().dom.innerHTML='';while(I.valueOf()<=K){var M='';if(I.getUTCDay()===this.weekStart){if(L){this.picker().select('>.datepicker-days tbody',true).first().createChild(L);
-}L={tag:'tr',cn:[]};if(this.calendarWeeks){var ws=new Date(+I+(this.weekStart-I.getUTCDay()-7)%7*864e5),th=new Date(+ws+(7+4-ws.getUTCDay())%7*864e5),N=new Date(+(N=this.UTCDate(th.getUTCFullYear(),0,1))+(7+4-N.getUTCDay())%7*864e5),O=(th-N)/864e5/7+1;L.cn.push({tag:'td',cls:'cw',html:O}
-);}}if(I.getUTCFullYear()<A||(I.getUTCFullYear()==A&&I.getUTCMonth()<B)){M+=' old';}else if(I.getUTCFullYear()>A||(I.getUTCFullYear()==A&&I.getUTCMonth()>B)){M+=' new';}if(this.todayHighlight&&I.getUTCFullYear()==H.getFullYear()&&I.getUTCMonth()==H.getMonth()&&I.getUTCDate()==H.getDate()){M+=' today';
-}if(G&&I.valueOf()===G){M+=' active';}if(I.valueOf()<this.startDate||I.valueOf()>this.endDate||this.daysOfWeekDisabled.indexOf(I.getUTCDay())!==-1){M+=' disabled';}L.cn.push({tag:'td',cls:'day '+M,html:I.getDate()});I.setDate(I.getDate()+1);}var P=this.date&&this.date.getUTCFullYear();
-var Q=this.date&&this.date.getUTCMonth();this.picker().select('>.datepicker-months th.switch',true).first().dom.innerHTML=A;Roo.each(this.picker().select('>.datepicker-months tbody span',true).elements,function(v,k){v.removeClass('active');if(P===A&&k===Q){v.addClass('active');
+}L={tag:'tr',cn:[]};}if(I.getUTCFullYear()<A||(I.getUTCFullYear()==A&&I.getUTCMonth()<B)){M+=' old';}else if(I.getUTCFullYear()>A||(I.getUTCFullYear()==A&&I.getUTCMonth()>B)){M+=' new';}if(this.todayHighlight&&I.getUTCFullYear()==H.getFullYear()&&I.getUTCMonth()==H.getMonth()&&I.getUTCDate()==H.getDate()){M+=' today';
+}if(G&&I.valueOf()===G){M+=' active';}if(I.valueOf()<this.startDate||I.valueOf()>this.endDate||this.daysOfWeekDisabled.indexOf(I.getUTCDay())!==-1){M+=' disabled';}L.cn.push({tag:'td',cls:'day '+M,html:I.getDate()});I.setDate(I.getDate()+1);}var N=this.date&&this.date.getUTCFullYear();
+var O=this.date&&this.date.getUTCMonth();this.picker().select('>.datepicker-months th.switch',true).first().dom.innerHTML=A;Roo.each(this.picker().select('>.datepicker-months tbody span',true).elements,function(v,k){v.removeClass('active');if(N===A&&k===O){v.addClass('active');
 }if(A<C||A>E||(A==C&&k<D)||(A==E&&k>F)){v.addClass('disabled');}});A=parseInt(A/10,10)*10;this.picker().select('>.datepicker-years th.switch',true).first().dom.innerHTML=A+'-'+(A+9);this.picker().select('>.datepicker-years tbody td',true).first().dom.innerHTML='';
-A-=1;for(var i=-1;i<11;i++){this.picker().select('>.datepicker-years tbody td',true).first().createChild({tag:'span',cls:'year'+(i===-1||i===10?' old':'')+(P===A?' active':'')+(A<C||A>E?' disabled':''),html:A});A+=1;}},showMode:function(A){if(A){this.viewMode=Math.max(this.minViewMode,Math.min(2,this.viewMode+A));
+A-=1;for(var i=-1;i<11;i++){this.picker().select('>.datepicker-years tbody td',true).first().createChild({tag:'span',cls:'year'+(i===-1||i===10?' old':'')+(N===A?' active':'')+(A<C||A>E?' disabled':''),html:A});A+=1;}},showMode:function(A){if(A){this.viewMode=Math.max(this.minViewMode,Math.min(2,this.viewMode+A));
 }Roo.each(this.picker().select('>div',true).elements,function(v){v.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay='block';v.hide();});this.picker().select('>.datepicker-'+Roo.bootstrap.form.DateField.modes[this.viewMode].clsName,true).first().show();
 },place:function(){if(this.isInline){return;}this.picker().removeClass(['bottom','top']);if((Roo.lib.Dom.getViewHeight()+Roo.get(document.body).getScroll().top)-(this.inputEl().getBottom()+this.picker().getHeight())<0){this.picker().addClass('top');this.picker().setTop(this.inputEl().getTop()-this.picker().getHeight()).setLeft(this.inputEl().getLeft());
-return;}this.picker().addClass('bottom');this.picker().setTop(this.inputEl().getBottom()).setLeft(this.inputEl().getLeft());},parseDate:function(A){if(!A||A instanceof Date){return A;}var v=Date.parseDate(A,this.format);if(!v&&(this.useIso||A.match(/^(\d{4})-0?(\d+)-0?(\d+)/))){v=Date.parseDate(A,'Y-m-d');
-}if(!v&&this.altFormats){if(!this.altFormatsArray){this.altFormatsArray=this.altFormats.split("|");}for(var i=0,B=this.altFormatsArray.length;i<B&&!v;i++){v=Date.parseDate(A,this.altFormatsArray[i]);}}return v;},formatDate:function(A,B){return (!A||!(A instanceof Date))?A:A.dateFormat(B||this.format);
-},onFocus:function(){Roo.bootstrap.form.DateField.superclass.onFocus.call(this);this.showPopup();},onBlur:function(){Roo.bootstrap.form.DateField.superclass.onBlur.call(this);var d=this.inputEl().getValue();this.setValue(d);this.hidePopup();},showPopup:function(){this.picker().show();
-this.update();this.place();this.fireEvent('showpopup',this,this.date);},hidePopup:function(){if(this.isInline){return;}this.picker().hide();this.viewMode=this.startViewMode;this.showMode();this.fireEvent('hidepopup',this,this.date);},onMousedown:function(e){e.stopPropagation();
-e.preventDefault();},keyup:function(e){Roo.bootstrap.form.DateField.superclass.keyup.call(this);this.update();},setValue:function(v){if(this.fireEvent('beforeselect',this,v)!==false){var d=new Date(this.parseDate(v)).clearTime();if(isNaN(d.getTime())){this.date=this.viewDate='';
-Roo.bootstrap.form.DateField.superclass.setValue.call(this,'');return;}v=this.formatDate(d);Roo.bootstrap.form.DateField.superclass.setValue.call(this,v);this.date=new Date(d.getTime()-d.getTimezoneOffset()*60000);this.update();this.fireEvent('select',this,this.date);
-}},getValue:function(){return this.formatDate(this.date);},fireKey:function(e){if(!this.picker().isVisible()){if(e.keyCode==27){this.showPopup();}return;}var A=false,B,C,D,E,F;switch(e.keyCode){case 27:this.hidePopup();e.preventDefault();break;case 37:case 39:if(!this.keyboardNavigation){break;
-}B=e.keyCode==37?-1:1;if(e.ctrlKey){E=this.moveYear(this.date,B);F=this.moveYear(this.viewDate,B);}else if(e.shiftKey){E=this.moveMonth(this.date,B);F=this.moveMonth(this.viewDate,B);}else{E=new Date(this.date);E.setUTCDate(this.date.getUTCDate()+B);F=new Date(this.viewDate);
-F.setUTCDate(this.viewDate.getUTCDate()+B);}if(this.dateWithinRange(E)){this.date=E;this.viewDate=F;this.setValue(this.formatDate(this.date));e.preventDefault();A=true;}break;case 38:case 40:if(!this.keyboardNavigation){break;}B=e.keyCode==38?-1:1;if(e.ctrlKey){E=this.moveYear(this.date,B);
-F=this.moveYear(this.viewDate,B);}else if(e.shiftKey){E=this.moveMonth(this.date,B);F=this.moveMonth(this.viewDate,B);}else{E=new Date(this.date);E.setUTCDate(this.date.getUTCDate()+B*7);F=new Date(this.viewDate);F.setUTCDate(this.viewDate.getUTCDate()+B*7);
-}if(this.dateWithinRange(E)){this.date=E;this.viewDate=F;this.setValue(this.formatDate(this.date));e.preventDefault();A=true;}break;case 13:this.setValue(this.formatDate(this.date));this.hidePopup();e.preventDefault();break;case 9:this.setValue(this.formatDate(this.date));
-this.hidePopup();break;case 16:case 17:case 18:break;default:this.hidePopup();}},onClick:function(e){e.stopPropagation();e.preventDefault();var A=e.getTarget();if(A.nodeName.toLowerCase()==='i'){A=Roo.get(A).dom.parentNode;}var B=A.nodeName;var C=A.className;
-var D=A.innerHTML;switch(B.toLowerCase()){case 'th':switch(C){case 'switch':this.showMode(1);break;case 'prev':case 'next':var E=Roo.bootstrap.form.DateField.modes[this.viewMode].navStep*(C=='prev'?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveMonth(this.viewDate,E);
-break;case 1:case 2:this.viewDate=this.moveYear(this.viewDate,E);break;}this.fill();break;case 'today':var F=new Date();this.date=this.UTCDate(F.getFullYear(),F.getMonth(),F.getDate(),0,0,0);this.setValue(this.formatDate(this.date));this.hidePopup();break;
-}break;case 'span':if(C.indexOf('disabled')<0){if(!this.viewDate){this.viewDate=new Date();}this.viewDate.setUTCDate(1);if(C.indexOf('month')>-1){this.viewDate.setUTCMonth(Roo.bootstrap.form.DateField.dates[this.language].monthsShort.indexOf(D));}else{var G=parseInt(D,10)||0;
-this.viewDate.setUTCFullYear(G);}if(this.singleMode){this.setValue(this.formatDate(this.viewDate));this.hidePopup();return;}this.showMode(-1);this.fill();}break;case 'td':if(C.indexOf('day')>-1&&C.indexOf('disabled')<0){var H=parseInt(D,10)||1;var G=(this.viewDate||new Date()).getUTCFullYear(),I=(this.viewDate||new Date()).getUTCMonth();
-if(C.indexOf('old')>-1){if(I===0){I=11;G-=1;}else{I-=1;}}else if(C.indexOf('new')>-1){if(I==11){I=0;G+=1;}else{I+=1;}}this.date=this.UTCDate(G,I,H,0,0,0,0);this.viewDate=this.UTCDate(G,I,Math.min(28,H),0,0,0,0);this.setValue(this.formatDate(this.date));this.hidePopup();
-}break;}},setStartDate:function(A){this.startDate=A||-Infinity;if(this.startDate!==-Infinity){this.startDate=this.parseDate(this.startDate);}this.update();this.updateNavArrows();},setEndDate:function(A){this.endDate=A||Infinity;if(this.endDate!==Infinity){this.endDate=this.parseDate(this.endDate);
+return;}this.picker().addClass('bottom');this.picker().setTop(this.inputEl().getBottom()).setLeft(this.inputEl().getLeft());},parseDate:function(A){if(!A){return false;}if(A instanceof Date){return A;}var v=Date.parseDate(A,'Y-m-d');return (typeof(v)=='undefined')?false:v;
+},formatDate:function(A,B){return (!A||!(A instanceof Date))?A:A.dateFormat(B||this.format);},translateDate:function(A){switch(this.language){case 'zh_CN':return new Intl.DateTimeFormat('zh-CN',{year:'numeric',month:'long',day:'numeric'}).format(A);default:return this.formatDate(A);
+}},onFocus:function(){Roo.bootstrap.form.DateField.superclass.onFocus.call(this);this.showPopup();},onBlur:function(){Roo.bootstrap.form.DateField.superclass.onBlur.call(this);if(!this.readOnly){var d=this.inputEl().getValue();var A=this.parseDate(d);if(A){this.setValue(A);
+}else{this.setValue(this.getValue());}}this.hidePopup();},showPopup:function(){this.picker().show();this.update();this.place();this.fireEvent('showpopup',this,this.date);},hidePopup:function(){if(this.isInline){return;}this.picker().hide();this.viewMode=this.startViewMode;
+this.showMode();this.fireEvent('hidepopup',this,this.date);},onMousedown:function(e){e.stopPropagation();e.preventDefault();},keyup:function(e){Roo.bootstrap.form.DateField.superclass.keyup.call(this);this.update();},setValue:function(v){if(this.fireEvent('beforeselect',this,v)!==false){var d=this.parseDate(v);
+if(!d){this.date=this.viewDate=this.value=this.hiddenField.value='';if(this.rendered){this.inputEl().dom.value='';this.validate();}return;}d=new Date(d).clearTime();this.value=this.hiddenField.value=d.dateFormat('Y-m-d');v=this.translateDate(d);if(this.rendered){this.inputEl().dom.value=(v===null||v===undefined?'':v);
+this.validate();}this.date=new Date(d.getTime()-d.getTimezoneOffset()*60000);this.update();this.fireEvent('select',this,this.date);}},setRawValue:function(v){if(this.fireEvent('beforeselect',this,v)!==false){var d=this.parseDate(v);if(!d){this.date=this.viewDate=this.value=this.hiddenField.value='';
+if(this.rendered){this.inputEl().dom.value=(v===null||v===undefined?'':v);}return;}d=new Date(d).clearTime();this.value=this.hiddenField.value=d.dateFormat('Y-m-d');v=this.translateDate(d);if(this.rendered){this.inputEl().dom.value=(v===null||v===undefined?'':v);
+}this.date=new Date(d.getTime()-d.getTimezoneOffset()*60000);this.update();this.fireEvent('select',this,this.date);}},getValue:function(){return this.value;},getRawValue:function(){return this.getValue();},fireKey:function(e){if(!this.picker().isVisible()){if(e.keyCode==27){this.showPopup();
+}return;}var A=false,B,C,D,E,F;switch(e.keyCode){case 27:this.hidePopup();e.preventDefault();break;case 37:case 39:if(!this.keyboardNavigation){break;}B=e.keyCode==37?-1:1;if(e.ctrlKey){E=this.moveYear(this.date,B);F=this.moveYear(this.viewDate,B);}else if(e.shiftKey){E=this.moveMonth(this.date,B);
+F=this.moveMonth(this.viewDate,B);}else{E=new Date(this.date);E.setUTCDate(this.date.getUTCDate()+B);F=new Date(this.viewDate);F.setUTCDate(this.viewDate.getUTCDate()+B);}if(this.dateWithinRange(E)){this.date=E;this.viewDate=F;this.setValue(this.date);e.preventDefault();
+A=true;}break;case 38:case 40:if(!this.keyboardNavigation){break;}B=e.keyCode==38?-1:1;if(e.ctrlKey){E=this.moveYear(this.date,B);F=this.moveYear(this.viewDate,B);}else if(e.shiftKey){E=this.moveMonth(this.date,B);F=this.moveMonth(this.viewDate,B);}else{E=new Date(this.date);
+E.setUTCDate(this.date.getUTCDate()+B*7);F=new Date(this.viewDate);F.setUTCDate(this.viewDate.getUTCDate()+B*7);}if(this.dateWithinRange(E)){this.date=E;this.viewDate=F;this.setValue(this.date);e.preventDefault();A=true;}break;case 13:this.setValue(this.date);
+this.hidePopup();e.preventDefault();break;case 9:this.setValue(this.date);this.hidePopup();break;case 16:case 17:case 18:break;default:this.hidePopup();}},onClick:function(e){e.stopPropagation();e.preventDefault();var A=e.getTarget();if(A.nodeName.toLowerCase()==='i'){A=Roo.get(A).dom.parentNode;
+}var B=A.nodeName;var C=A.className;var D=A.innerHTML;switch(B.toLowerCase()){case 'th':switch(C){case 'switch':this.showMode(1);break;case 'prev':case 'next':var E=Roo.bootstrap.form.DateField.modes[this.viewMode].navStep*(C=='prev'?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveMonth(this.viewDate,E);
+break;case 1:case 2:this.viewDate=this.moveYear(this.viewDate,E);break;}this.fill();break;case 'today':var F=new Date();this.date=this.UTCDate(F.getFullYear(),F.getMonth(),F.getDate(),0,0,0);this.setValue(this.date);this.hidePopup();break;}break;case 'span':if(C.indexOf('disabled')<0){if(!this.viewDate){this.viewDate=new Date();
+}this.viewDate.setUTCDate(1);if(C.indexOf('month')>-1){this.viewDate.setUTCMonth(Roo.bootstrap.form.DateField.dates[this.language].monthsShort.indexOf(D));}else{var G=parseInt(D,10)||0;this.viewDate.setUTCFullYear(G);}if(this.singleMode){this.setValue(this.viewDate);
+this.hidePopup();return;}this.showMode(-1);this.fill();}break;case 'td':if(C.indexOf('day')>-1&&C.indexOf('disabled')<0){var H=parseInt(D,10)||1;var G=(this.viewDate||new Date()).getUTCFullYear(),I=(this.viewDate||new Date()).getUTCMonth();if(C.indexOf('old')>-1){if(I===0){I=11;
+G-=1;}else{I-=1;}}else if(C.indexOf('new')>-1){if(I==11){I=0;G+=1;}else{I+=1;}}this.date=this.UTCDate(G,I,H,0,0,0,0);this.viewDate=this.UTCDate(G,I,Math.min(28,H),0,0,0,0);this.setValue(this.date);this.hidePopup();}break;}},setStartDate:function(A){this.startDate=A||-Infinity;
+if(this.startDate!==-Infinity){var B=this.parseDate(this.startDate);this.startDate=B?B:-Infinity;}this.update();this.updateNavArrows();},setEndDate:function(A){this.endDate=A||Infinity;if(this.endDate!==Infinity){var B=this.parseDate(this.endDate);this.endDate=B?B:Infinity;
 }this.update();this.updateNavArrows();},setDaysOfWeekDisabled:function(A){this.daysOfWeekDisabled=A||[];if(typeof(this.daysOfWeekDisabled)!=='object'){this.daysOfWeekDisabled=this.daysOfWeekDisabled.split(/,\s*/);}this.daysOfWeekDisabled=this.daysOfWeekDisabled.map(function(d){return parseInt(d,10);
 });this.update();this.updateNavArrows();},updateNavArrows:function(){if(this.singleMode){return;}var d=new Date(this.viewDate),A=d.getUTCFullYear(),B=d.getUTCMonth();Roo.each(this.picker().select('.prev',true).elements,function(v){v.show();switch(this.viewMode){case 0:if(this.startDate!==-Infinity&&A<=this.startDate.getUTCFullYear()&&B<=this.startDate.getUTCMonth()){v.hide();
 }break;case 1:case 2:if(this.startDate!==-Infinity&&A<=this.startDate.getUTCFullYear()){v.hide();}break;}});Roo.each(this.picker().select('.next',true).elements,function(v){v.show();switch(this.viewMode){case 0:if(this.endDate!==Infinity&&A>=this.endDate.getUTCFullYear()&&B>=this.endDate.getUTCMonth()){v.hide();
@@ -1012,33 +1015,40 @@ if(C.indexOf('old')>-1){if(I===0){I=11;G-=1;}else{I-=1;}}else if(C.indexOf('new'
 }:function(){return C.getUTCMonth()!=G;};G=E+B;C.setUTCMonth(G);if(G<0||G>11){G=(G+12)%12;}}else{for(var i=0;i<F;i++){C=this.moveMonth(C,B);}G=C.getUTCMonth();C.setUTCDate(D);H=function(){return G!=C.getUTCMonth();};}while(H()){C.setUTCDate(--D);C.setUTCMonth(G);
 }return C;},moveYear:function(A,B){return this.moveMonth(A,B*12);},dateWithinRange:function(A){return A>=this.startDate&&A<=this.endDate;},remove:function(){this.picker().remove();},validateValue:function(A){if(this.getVisibilityEl().hasClass('hidden')){return true;
 }if(A.length<1){if(this.allowBlank){return true;}return false;}if(A.length<this.minLength){return false;}if(A.length>this.maxLength){return false;}if(this.vtype){var vt=Roo.form.VTypes;if(!vt[this.vtype](A,this)){return false;}}if(typeof this.validator=="function"){var B=this.validator(A);
-if(B!==true){return false;}}if(this.regex&&!this.regex.test(A)){return false;}if(typeof(this.parseDate(A))=='undefined'){return false;}if(this.endDate!==Infinity&&this.parseDate(A).getTime()>this.endDate.getTime()){return false;}if(this.startDate!==-Infinity&&this.parseDate(A).getTime()<this.startDate.getTime()){return false;
+if(B!==true){return false;}}if(this.regex&&!this.regex.test(A)){return false;}if(!this.parseDate(A)){return false;}if(this.endDate!==Infinity&&this.parseDate(A).getTime()>this.endDate.getTime()){return false;}if(this.startDate!==-Infinity&&this.parseDate(A).getTime()<this.startDate.getTime()){return false;
 }return true;},reset:function(){this.date=this.viewDate='';Roo.bootstrap.form.DateField.superclass.setValue.call(this,'');}});Roo.apply(Roo.bootstrap.form.DateField,{head:{tag:'thead',cn:[{tag:'tr',cn:[{tag:'th',cls:'prev',html:'<i class="fa fa-arrow-left"/>'}
-,{tag:'th',cls:'switch',colspan:'5'},{tag:'th',cls:'next',html:'<i class="fa fa-arrow-right"/>'}]}]},content:{tag:'tbody',cn:[{tag:'tr',cn:[{tag:'td',colspan:'7'}]}]},footer:{tag:'tfoot',cn:[{tag:'tr',cn:[{tag:'th',colspan:'7',cls:'today'}]}]},dates:{en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today"}
-},modes:[{clsName:'days',navFnc:'Month',navStep:1},{clsName:'months',navFnc:'FullYear',navStep:1},{clsName:'years',navFnc:'FullYear',navStep:10}]});Roo.apply(Roo.bootstrap.form.DateField,{template:{tag:'div',cls:'datepicker dropdown-menu roo-dynamic shadow',cn:[{tag:'div',cls:'datepicker-days',cn:[{tag:'table',cls:'table-condensed',cn:[Roo.bootstrap.form.DateField.head,{tag:'tbody'}
+,{tag:'th',cls:'switch',colspan:'5'},{tag:'th',cls:'next',html:'<i class="fa fa-arrow-right"/>'}]}]},content:{tag:'tbody',cn:[{tag:'tr',cn:[{tag:'td',colspan:'7'}]}]},footer:{tag:'tfoot',cn:[{tag:'tr',cn:[{tag:'th',colspan:'7',cls:'today'}]}]},dates:{},todayText:"Today",modes:[{clsName:'days',navFnc:'Month',navStep:1}
+,{clsName:'months',navFnc:'FullYear',navStep:1},{clsName:'years',navFnc:'FullYear',navStep:10}]});Roo.apply(Roo.bootstrap.form.DateField,{template:{tag:'div',cls:'datepicker dropdown-menu roo-dynamic shadow',cn:[{tag:'div',cls:'datepicker-days',cn:[{tag:'table',cls:'table-condensed',cn:[Roo.bootstrap.form.DateField.head,{tag:'tbody'}
 ,Roo.bootstrap.form.DateField.footer]}]},{tag:'div',cls:'datepicker-months',cn:[{tag:'table',cls:'table-condensed',cn:[Roo.bootstrap.form.DateField.head,Roo.bootstrap.form.DateField.content,Roo.bootstrap.form.DateField.footer]}]},{tag:'div',cls:'datepicker-years',cn:[{tag:'table',cls:'table-condensed',cn:[Roo.bootstrap.form.DateField.head,Roo.bootstrap.form.DateField.content,Roo.bootstrap.form.DateField.footer]}
 ]}]}});
 // Roo/bootstrap/form/TimeField.js
-Roo.bootstrap.form.TimeField=function(A){Roo.bootstrap.form.TimeField.superclass.constructor.call(this,A);this.addEvents({show:true,hide:true,select:true});};Roo.extend(Roo.bootstrap.form.TimeField,Roo.bootstrap.form.Input,{format:"H:i",minuteStep:1,getAutoCreate:function(){this.after='<i class="fa far fa-clock"></i>';
-return Roo.bootstrap.form.TimeField.superclass.getAutoCreate.call(this);},onRender:function(ct,A){Roo.bootstrap.form.TimeField.superclass.onRender.call(this,ct,A);this.pickerEl=Roo.get(document.body).createChild(Roo.bootstrap.form.TimeField.template);this.picker().setVisibilityMode(Roo.Element.DISPLAY).originalDisplay='block';
-this.pop=this.picker().select('>.datepicker-time',true).first();this.pop.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay='block';this.picker().on('mousedown',this.onMousedown,this);this.picker().on('click',this.onClick,this);this.picker().addClass('datepicker-dropdown');
-this.fillTime();this.update();this.pop.select('.hours-up',true).first().on('click',this.onIncrementHours,this);this.pop.select('.hours-down',true).first().on('click',this.onDecrementHours,this);this.pop.select('.minutes-up',true).first().on('click',this.onIncrementMinutes,this);
-this.pop.select('.minutes-down',true).first().on('click',this.onDecrementMinutes,this);this.pop.select('button.period',true).first().on('click',this.onTogglePeriod,this);this.pop.select('button.ok',true).first().on('click',this.setTime,this);},fireKey:function(e){if(!this.picker().isVisible()){if(e.keyCode==27){this.show();
-}return;}e.preventDefault();switch(e.keyCode){case 27:this.hide();break;case 37:case 39:this.onTogglePeriod();break;case 38:this.onIncrementMinutes();break;case 40:this.onDecrementMinutes();break;case 13:case 9:this.setTime();break;}},onClick:function(e){e.stopPropagation();
-e.preventDefault();},picker:function(){return this.pickerEl;},fillTime:function(){var A=this.pop.select('tbody',true).first();A.dom.innerHTML='';A.createChild({tag:'tr',cn:[{tag:'td',cn:[{tag:'a',href:'#',cls:'btn',cn:[{tag:'i',cls:'hours-up fa fas fa-chevron-up'}
-]}]},{tag:'td',cls:'separator'},{tag:'td',cn:[{tag:'a',href:'#',cls:'btn',cn:[{tag:'i',cls:'minutes-up fa fas fa-chevron-up'}]}]},{tag:'td',cls:'separator'}]});A.createChild({tag:'tr',cn:[{tag:'td',cn:[{tag:'span',cls:'timepicker-hour',html:'00'}]},{tag:'td',cls:'separator',html:':'}
-,{tag:'td',cn:[{tag:'span',cls:'timepicker-minute',html:'00'}]},{tag:'td',cls:'separator'},{tag:'td',cn:[{tag:'button',type:'button',cls:'btn btn-primary period',html:'AM'}]}]});A.createChild({tag:'tr',cn:[{tag:'td',cn:[{tag:'a',href:'#',cls:'btn',cn:[{tag:'span',cls:'hours-down fa fas fa-chevron-down'}
-]}]},{tag:'td',cls:'separator'},{tag:'td',cn:[{tag:'a',href:'#',cls:'btn',cn:[{tag:'span',cls:'minutes-down fa fas fa-chevron-down'}]}]},{tag:'td',cls:'separator'}]});},update:function(){if(typeof(this.time)==='undefined'){this.time=new Date();this.time=this.time.add(Date.MINUTE,Math.round(parseInt(this.time.format('i'))/this.minuteStep)*this.minuteStep-parseInt(this.time.format('i')));
-}this.time=(typeof(this.time)==='undefined')?new Date():this.time;this.fill();},fill:function(){var A=this.time.getHours();var B=this.time.getMinutes();var C='AM';if(A>11){C='PM';}if(A==0){A=12;}if(A>12){A=A-12;}if(A<10){A='0'+A;}if(B<10){B='0'+B;}this.pop.select('.timepicker-hour',true).first().dom.innerHTML=A;
-this.pop.select('.timepicker-minute',true).first().dom.innerHTML=B;this.pop.select('button',true).first().dom.innerHTML=C;},place:function(){this.picker().removeClass(['bottom-left','bottom-right','top-left','top-right']);var A=['bottom'];if((Roo.lib.Dom.getViewHeight()+Roo.get(document.body).getScroll().top)-(this.inputEl().getBottom()+this.picker().getHeight())<0){A.pop();
+Roo.bootstrap.form.TimeField=function(A){Roo.bootstrap.form.TimeField.superclass.constructor.call(this,A);this.addEvents({show:true,hide:true,select:true});};Roo.extend(Roo.bootstrap.form.TimeField,Roo.bootstrap.form.Input,{format:"H:i",minuteStep:1,language:'en',hiddenField:false,getAutoCreate:function(){this.after='<i class="fa far fa-clock"></i>';
+return Roo.bootstrap.form.TimeField.superclass.getAutoCreate.call(this);},onRender:function(ct,A){Roo.bootstrap.form.TimeField.superclass.onRender.call(this,ct,A);this.language=this.language in Roo.bootstrap.form.TimeField.periodText?this.language:"en";this.pickerEl=Roo.get(document.body).createChild(Roo.bootstrap.form.TimeField.template);
+this.picker().setVisibilityMode(Roo.Element.DISPLAY).originalDisplay='block';this.pop=this.picker().select('>.datepicker-time',true).first();this.pop.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay='block';this.picker().on('mousedown',this.onMousedown,this);
+this.picker().on('click',this.onClick,this);this.picker().addClass('datepicker-dropdown');this.fillTime();this.update();this.pop.select('.hours-up',true).first().on('click',this.onIncrementHours,this);this.pop.select('.hours-down',true).first().on('click',this.onDecrementHours,this);
+this.pop.select('.minutes-up',true).first().on('click',this.onIncrementMinutes,this);this.pop.select('.minutes-down',true).first().on('click',this.onDecrementMinutes,this);this.pop.select('button.period',true).first().on('click',this.onTogglePeriod,this);
+this.pop.select('button.ok',true).first().on('click',this.setTime,this);this.pop.select('button.ok',true).first().dom.innerHTML=Roo.bootstrap.form.TimeField.okText;this.hiddenField=this.inputEl().insertSibling({tag:'input',type:'hidden',name:this.name},'before',true);
+this.inputEl().dom.setAttribute('name',this.name+'____hidden___');},fireKey:function(e){if(!this.picker().isVisible()){if(e.keyCode==27){this.show();}return;}e.preventDefault();switch(e.keyCode){case 27:this.hide();break;case 37:case 39:this.onTogglePeriod();
+break;case 38:this.onIncrementMinutes();break;case 40:this.onDecrementMinutes();break;case 13:case 9:this.setTime();break;}},onClick:function(e){e.stopPropagation();e.preventDefault();},picker:function(){return this.pickerEl;},fillTime:function(){var A=this.pop.select('tbody',true).first();
+A.dom.innerHTML='';A.createChild({tag:'tr',cn:[{tag:'td',cn:[{tag:'a',href:'#',cls:'btn',cn:[{tag:'i',cls:'hours-up fa fas fa-chevron-up'}]}]},{tag:'td',cls:'separator'},{tag:'td',cn:[{tag:'a',href:'#',cls:'btn',cn:[{tag:'i',cls:'minutes-up fa fas fa-chevron-up'}
+]}]},{tag:'td',cls:'separator'}]});A.createChild({tag:'tr',cn:[{tag:'td',cn:[{tag:'span',cls:'timepicker-hour',html:'00'}]},{tag:'td',cls:'separator',html:':'},{tag:'td',cn:[{tag:'span',cls:'timepicker-minute',html:'00'}]},{tag:'td',cls:'separator'},{tag:'td',cn:[{tag:'button',type:'button',cls:'btn btn-primary period',html:'AM'}
+]}]});A.createChild({tag:'tr',cn:[{tag:'td',cn:[{tag:'a',href:'#',cls:'btn',cn:[{tag:'span',cls:'hours-down fa fas fa-chevron-down'}]}]},{tag:'td',cls:'separator'},{tag:'td',cn:[{tag:'a',href:'#',cls:'btn',cn:[{tag:'span',cls:'minutes-down fa fas fa-chevron-down'}
+]}]},{tag:'td',cls:'separator'}]});},update:function(){if(typeof(this.time)==='undefined'){this.time=new Date();this.time=this.time.add(Date.MINUTE,Math.round(parseInt(this.time.format('i'))/this.minuteStep)*this.minuteStep-parseInt(this.time.format('i')));
+}this.time=(typeof(this.time)==='undefined')?new Date():this.time;this.fill();},fill:function(){var A=this.time.getHours();var B=this.time.getMinutes();var C=Roo.bootstrap.form.TimeField.periodText[this.language]['am'];if(A>11){C=Roo.bootstrap.form.TimeField.periodText[this.language]['pm'];
+}if(A==0){A=12;}if(A>12){A=A-12;}if(A<10){A='0'+A;}if(B<10){B='0'+B;}this.pop.select('.timepicker-hour',true).first().dom.innerHTML=A;this.pop.select('.timepicker-minute',true).first().dom.innerHTML=B;this.pop.select('button',true).first().dom.innerHTML=C;
+},place:function(){this.picker().removeClass(['bottom-left','bottom-right','top-left','top-right']);var A=['bottom'];if((Roo.lib.Dom.getViewHeight()+Roo.get(document.body).getScroll().top)-(this.inputEl().getBottom()+this.picker().getHeight())<0){A.pop();
 A.push('top');}A.push('right');if((Roo.lib.Dom.getViewWidth()+Roo.get(document.body).getScroll().left)-(this.inputEl().getLeft()+this.picker().getWidth())<0){A.pop();A.push('left');}this.picker().addClass(A.join('-'));var B=this;Roo.each(A,function(c){if(c=='bottom'){(function(){}
 ).defer(200);B.picker().alignTo(B.inputEl(),"tr-br",[0,10],false);return;}if(c=='top'){B.picker().alignTo(B.inputEl(),"br-tr",[0,10],false);return;}});},onFocus:function(){Roo.bootstrap.form.TimeField.superclass.onFocus.call(this);this.show();},onBlur:function(){Roo.bootstrap.form.TimeField.superclass.onBlur.call(this);
-this.hide();},show:function(){this.picker().show();this.pop.show();this.update();this.place();this.fireEvent('show',this,this.date);},hide:function(){this.picker().hide();this.pop.hide();this.fireEvent('hide',this,this.date);},setTime:function(){this.hide();
-this.setValue(this.time.format(this.format));this.fireEvent('select',this,this.date);},onMousedown:function(e){e.stopPropagation();e.preventDefault();},onIncrementHours:function(){Roo.log('onIncrementHours');this.time=this.time.add(Date.HOUR,1);this.update();
-},onDecrementHours:function(){Roo.log('onDecrementHours');this.time=this.time.add(Date.HOUR,-1);this.update();},onIncrementMinutes:function(){Roo.log('onIncrementMinutes');var A=Math.round((parseInt(this.time.format('i'))+this.minuteStep)/this.minuteStep)*this.minuteStep-parseInt(this.time.format('i'));
-this.time=this.time.add(Date.MINUTE,A);this.update();},onDecrementMinutes:function(){Roo.log('onDecrementMinutes');var A=parseInt(this.time.format('i'))-Math.round((parseInt(this.time.format('i'))-this.minuteStep)/this.minuteStep)*this.minuteStep;this.time=this.time.add(Date.MINUTE,-1*A);
-this.update();},onTogglePeriod:function(){Roo.log('onTogglePeriod');this.time=this.time.add(Date.HOUR,12);this.update();}});Roo.apply(Roo.bootstrap.form.TimeField,{template:{tag:'div',cls:'datepicker dropdown-menu',cn:[{tag:'div',cls:'datepicker-time',cn:[{tag:'table',cls:'table-condensed',cn:[{tag:'tbody',cn:[{tag:'tr',cn:[{tag:'td',colspan:'7'}
-]}]},{tag:'tfoot',cn:[{tag:'tr',cn:[{tag:'th',colspan:'7',cls:'',cn:[{tag:'button',cls:'btn btn-info ok',html:'OK'}]}]}]}]}]}]}});
+this.hide();},show:function(){this.picker().show();this.pop.show();this.update();this.place();this.fireEvent('show',this,this.time);},hide:function(){this.picker().hide();this.pop.hide();this.fireEvent('hide',this,this.time);},setTime:function(){this.hide();
+this.setValue(this.time);this.fireEvent('select',this,this.time);},parseTime:function(A){if(!A){return false;}if(A instanceof Date){return A;}var v=Date.parseDate(A,'H:i:s');return (typeof(v)=='undefined')?false:v;},translateTime:function(A){switch(this.language){case 'zh_CN':return new Intl.DateTimeFormat('zh-CN',{hour:'numeric',minute:'numeric',hour12:true}
+).format(A);default:return A.format(this.format);}},setValue:function(v){var t=this.parseTime(v);if(!t){this.time=this.value=this.hiddenField.value='';if(this.rendered){this.inputEl().dom.value='';this.validate();}return;}this.value=this.hiddenField.value=t.dateFormat('H:i:s');
+v=this.translateTime(t);if(this.rendered){this.inputEl().dom.value=(v===null||v===undefined?'':v);this.validate();}this.time=t;this.update();},setRawValue:function(v){var t=this.parseTime(v);if(!t){this.time=this.value=this.hiddenField.value='';if(this.rendered){this.inputEl().dom.value=(v===null||v===undefined?'':v);
+}return;}this.value=this.hiddenField.value=t.dateFormat('H:i:s');v=this.translateTime(t);if(this.rendered){this.inputEl().dom.value=(v===null||v===undefined?'':v);}this.time=t;this.update();},getValue:function(){return this.value;},getRawValue:function(){return this.getValue();
+},onMousedown:function(e){e.stopPropagation();e.preventDefault();},onIncrementHours:function(){Roo.log('onIncrementHours');this.time=this.time.add(Date.HOUR,1);this.update();},onDecrementHours:function(){Roo.log('onDecrementHours');this.time=this.time.add(Date.HOUR,-1);
+this.update();},onIncrementMinutes:function(){Roo.log('onIncrementMinutes');var A=Math.round((parseInt(this.time.format('i'))+this.minuteStep)/this.minuteStep)*this.minuteStep-parseInt(this.time.format('i'));this.time=this.time.add(Date.MINUTE,A);this.update();
+},onDecrementMinutes:function(){Roo.log('onDecrementMinutes');var A=parseInt(this.time.format('i'))-Math.round((parseInt(this.time.format('i'))-this.minuteStep)/this.minuteStep)*this.minuteStep;this.time=this.time.add(Date.MINUTE,-1*A);this.update();},onTogglePeriod:function(){Roo.log('onTogglePeriod');
+this.time=this.time.add(Date.HOUR,12);this.update();}});Roo.apply(Roo.bootstrap.form.TimeField,{okText:'OK',periodText:{en:{am:'AM',pm:'PM'},zh_CN:{am:'上午',pm:'下午'}}});Roo.apply(Roo.bootstrap.form.TimeField,{template:{tag:'div',cls:'datepicker dropdown-menu',cn:[{tag:'div',cls:'datepicker-time',cn:[{tag:'table',cls:'table-condensed',cn:[{tag:'tbody',cn:[{tag:'tr',cn:[{tag:'td',colspan:'7'}
+]}]},{tag:'tfoot',cn:[{tag:'tr',cn:[{tag:'th',colspan:'7',cls:'',cn:[{tag:'button',cls:'btn btn-info ok',html:"OK"}]}]}]}]}]}]}});
 // Roo/bootstrap/form/MonthField.js
 Roo.bootstrap.form.MonthField=function(A){Roo.bootstrap.form.MonthField.superclass.constructor.call(this,A);this.addEvents({show:true,hide:true,select:true});};Roo.extend(Roo.bootstrap.form.MonthField,Roo.bootstrap.form.Input,{onRender:function(ct,A){Roo.bootstrap.form.MonthField.superclass.onRender.call(this,ct,A);
 this.language=this.language||'en';this.language=this.language in Roo.bootstrap.form.MonthField.dates?this.language:this.language.split('-')[0];this.language=this.language in Roo.bootstrap.form.MonthField.dates?this.language:"en";this.isRTL=Roo.bootstrap.form.MonthField.dates[this.language].rtl||false;