tom@1199: /* Copyright (C) 2013 by Bundesamt fuer Strahlenschutz
tom@1199:  * Software engineering by Intevation GmbH
tom@1199:  *
tom@1199:  * This file is Free Software under the GNU GPL (v>=3)
tom@1199:  * and comes with ABSOLUTELY NO WARRANTY! Check out
tom@1199:  * the documentation coming with IMIS-Labordaten-Application for details.
tom@1199:  */
tom@1199: 
tom@1199: /**
tom@1199:  * Panel to select month and day of month,
tom@1199:  * that can be serialized to day of year
tom@1199:  */
tom@1199: Ext.define('Lada.view.widget.DayOfYear', {
tom@1199:     extend: 'Ext.panel.Panel',
tom@1199:     alias: 'widget.dayofyear',
tom@1199: 
tom@1199:     layout: {
tom@1199:         type: 'hbox',
tom@1199:         pack: 'end',
tom@1199:         defaultMargins: '3'
tom@1199:     },
tom@1199: 
tom@1199:     initComponent: function() {
tom@1199:         var me = this;
tom@1199: 
tom@1211:         var monthsStore = Ext.create('Ext.data.Store', {
tom@1211:             fields: ['id', 'name'],
tom@1211:             data: [{
tom@1211:                 'id': 0,
tom@1211:                 'name': 'Januar'
tom@1211:             }, {
tom@1211:                 'id': 1,
tom@1211:                 'name': 'Februar'
tom@1211:             }, {
tom@1211:                 'id': 2,
tom@1211:                 'name': 'März'
tom@1211:             }, {
tom@1211:                 'id': 3,
tom@1211:                 'name': 'April'
tom@1211:             }, {
tom@1211:                 'id': 4,
tom@1211:                 'name': 'Mai'
tom@1211:             }, {
tom@1211:                 'id': 5,
tom@1211:                 'name': 'Juni'
tom@1211:             }, {
tom@1211:                 'id': 6,
tom@1211:                 'name': 'Juli'
tom@1211:             }, {
tom@1211:                 'id': 7,
tom@1211:                 'name': 'August'
tom@1211:             }, {
tom@1211:                 'id': 8,
tom@1211:                 'name': 'September'
tom@1211:             }, {
tom@1211:                 'id': 9,
tom@1211:                 'name': 'Oktober'
tom@1211:             }, {
tom@1211:                 'id': 10,
tom@1211:                 'name': 'November'
tom@1211:             }, {
tom@1211:                 'id': 11,
tom@1211:                 'name': 'Dezember'
tom@1211:             }]
tom@1211:         });
tom@1211: 
tom@1199:         /*
tom@1199:          * Create hidden field to hold the day of year value
tom@1199:          * for/of the record of the form.
tom@1199:          */
tom@1199:         var DOYField = Ext.create('Ext.form.field.Number', {
tom@1199:             name: this.name,
tom@1199:             hidden: true,
tom@1212:             allowBlank: this.allowBlank,
tom@1199:             listeners: this.listeners
tom@1199:         });
tom@1199:         /* Use dirtychange to avoid endless loop with change listeners on
tom@1199:          * visible items. This one is for initialisation by the form. */
tom@1199:         DOYField.addListener('dirtychange', me.setFields);
tom@1212:         DOYField.addListener('validitychange', me.validityChange);
tom@1199: 
tom@1199:         /*
tom@1199:          * Add hidden field and visible fields to let the user choose
tom@1199:          * day and month to the panel.
tom@1199:          */
tom@1199:         this.items = [{
tom@1199:             xtype: 'numberfield',
tom@1199:             isFormField: false,
tom@1199:             fieldLabel: this.fieldLabel,
tom@1199:             labelWidth: this.labelWidth,
tom@1199:             width: 50 + this.labelWidth,
tom@1199:             msgTarget: 'none',
tom@1199:             allowDecimals: false,
tom@1199:             maxLength: 2,
tom@1199:             enforceMaxLength: true,
tom@1199:             allowBlank: this.allowBlank,
tom@1199:             minValue: 1,
tom@1199:             maxValue: 31,
tom@1199:             emptyText: 'Tag',
tom@1199:             listeners: {
tom@1199:                 /* we have to listen on change because checkMaxDay() might
tom@1199:                  * change the value. UI events like blur do not track this. */
tom@1199:                 change: { fn: me.setDOY }
tom@1199:             }
tom@1199:         }, {
tom@1199:             xtype: 'combobox',
tom@1199:             isFormField: false,
tom@1199:             width: 100,
tom@1199:             msgTarget: 'none',
tom@1199:             store: monthsStore,
tom@1199:             allowBlank: this.allowBlank,
tom@1199:             forceSelection: true,
tom@1199:             valueField: 'id',
tom@1199:             displayField: 'name',
tom@1199:             emptyText: 'Monat',
tom@1199:             queryMode: 'local',
tom@1199:             listeners: {
tom@1199:                 collapse: { fn: me.setDOY },
tom@1199:                 change: { fn: me.checkMaxDay }
tom@1199:             }
tom@1199:         }, {
tom@1199:             xtype: 'image',
tom@1199:             name: 'warnImg',
tom@1199:             src: 'resources/img/dialog-warning.png',
tom@1199:             width: 14,
tom@1199:             height: 14,
tom@1199:             hidden: true
tom@1199:         }, {
tom@1199:             xtype: 'image',
tom@1199:             name: 'errorImg',
tom@1199:             src: 'resources/img/emblem-important.png',
tom@1199:             width: 14,
tom@1199:             height: 14,
tom@1199:             hidden: true
tom@1199:         }, DOYField];
tom@1199: 
tom@1199:         this.callParent(arguments);
tom@1199:     },
tom@1199: 
tom@1199:     /*
tom@1199:      * Set values in panel items for day and month
tom@1199:      * from hidden day of year field
tom@1199:      */
tom@1199:     setFields: function() {
tom@1199:         var panel = this.up('panel');
tom@1199: 
tom@1199:         // create a date object with arbitrary non-leap year
tom@1199:         var doy = panel.down('numberfield[hidden]').getValue();
tom@1199: 
tom@1199:         if (doy != null) {
tom@1207:             // day of year is 0-based in ExtJS, but 1-based in the model
tom@1207:             doy -= 1;
tom@1199:             var date = Ext.Date.subtract(
tom@1199:                 new Date(1970, 0, 1), Ext.Date.DAY, -doy);
tom@1199:             var month = date.getMonth();
tom@1199:             var day = date.getDate();
tom@1199:             panel.down('combobox').setValue(month);
tom@1199:             panel.down('numberfield[hidden=false]').setValue(day);
tom@1199:         }
tom@1199:     },
tom@1199: 
tom@1199:     /*
tom@1199:      * Function to be called from listeners of visible items
tom@1199:      * to set the value of the hidden day of year field.
tom@1199:      */
tom@1199:     setDOY: function() {
tom@1199:         var panel = this.up('panel');
tom@1199:         var month = panel.down('combobox').getValue();
tom@1199:         var day = panel.down('numberfield[hidden=false]').getValue();
tom@1199:         var maxDay = panel.down('numberfield[hidden=false]').maxValue;
tom@1212:         var doy = null;
tom@1199: 
tom@1199:         if (month != null && day != null && day <= maxDay) {
tom@1199:             // create a date object with arbitrary non-leap year
tom@1199:             var date = new Date(1970, month, day);
tom@1207: 
tom@1207:             // day of year is 0-based in ExtJS, but 1-based in the model
tom@1212:             doy = Ext.Date.getDayOfYear(date) + 1;
tom@1199:         }
tom@1212:         panel.down('numberfield[hidden]').setValue(doy);
tom@1199:     },
tom@1199: 
tom@1199:     /*
tom@1199:      * Call from listener of month selection widget to set maximum and
tom@1199:      * validate associated day value.
tom@1199:      */
tom@1199:     checkMaxDay: function() {
tom@1199:         // create a date object with arbitrary non-leap year
tom@1199:         var maxDay = Ext.Date.getDaysInMonth(
tom@1199:             new Date(1970, this.getValue()));
tom@1199:         this.up('panel').down('numberfield[hidden=false]')
tom@1199:             .setMaxValue(maxDay);
tom@1199: 
tom@1199:         var curDay = this.up('panel')
tom@1199:             .down('numberfield[hidden=false]').getValue();
tom@1212:         if (curDay) {
tom@1212:             if (curDay > maxDay) {
tom@1212:                 this.up('panel').down('numberfield[hidden=false]')
tom@1212:                     .setValue(maxDay);
tom@1212:             }
tom@1199:             this.up('panel').down('numberfield[hidden=false]')
tom@1212:                 .clearInvalid();
tom@1199:         }
tom@1199:     },
tom@1199: 
tom@1199: 
tom@1199:     showWarnings: function(warnings) {
tom@1199:         var img = this.down('image[name=warnImg]');
tom@1199:         Ext.create('Ext.tip.ToolTip', {
tom@1199:             target: img.getEl(),
tom@1199:             html: warnings
tom@1199:         });
tom@1199:         img.show();
tom@1199:         this.down('numberfield[hidden=false]').invalidCls = 'x-lada-warning';
tom@1199:         this.down('numberfield[hidden=false]').markInvalid('');
tom@1199:         this.down('combobox').markInvalid('');
tom@1199:         var fieldset = this.up('fieldset[collapsible=true]');
tom@1199:         if (fieldset) {
tom@1199:             var i18n = Lada.getApplication().bundle;
tom@1199:             var warningText = i18n.getMsg(this.name) + ': ' + warnings;
tom@1199:             fieldset.showWarningOrError(true, warningText);
tom@1199:         }
tom@1199:     },
tom@1199: 
tom@1199:     showErrors: function(errors) {
tom@1199:         var img = this.down('image[name=errorImg]');
tom@1199:         var warnImg = this.down('image[name=warnImg]');
tom@1199:         warnImg.hide();
tom@1199:         Ext.create('Ext.tip.ToolTip', {
tom@1199:             target: img.getEl(),
tom@1199:             html: errors
tom@1199:         });
tom@1199:         this.down('numberfield[hidden=false]').invalidCls = 'x-lada-error';
tom@1199:         this.down('numberfield[hidden=false]').markInvalid('');
tom@1199:         this.down('combobox').markInvalid('');
tom@1199:         img.show();
tom@1199:         var fieldset = this.up('fieldset[collapsible=true]');
tom@1199:         if (fieldset) {
tom@1199:             var i18n = Lada.getApplication().bundle;
tom@1199:             var errorText = i18n.getMsg(this.name) + ': ' + errors;
tom@1199:             fieldset.showWarningOrError(false, '', true, errorText);
tom@1199:         }
tom@1199:     },
tom@1199: 
tom@1212:     /*
tom@1212:      * When the hidden field is validated as part of a form, make the result
tom@1212:      * user visible.
tom@1212:      */
tom@1212:     validityChange: function(field, isValid) {
tom@1212:         if (!isValid) {
tom@1212:             var errors = field.getActiveErrors()
tom@1212:             field.up('panel').down('combobox').markInvalid(errors);
tom@1212:             field.up('panel').down('numberfield[hidden=false]')
tom@1212:                 .markInvalid(errors);
tom@1212:         } else {
tom@1212:             field.up('panel').down('combobox').clearInvalid();
tom@1212:             field.up('panel').down('numberfield[hidden=false]').clearInvalid();
tom@1212:         }
tom@1212:     },
tom@1212: 
tom@1199:     clearWarningOrError: function() {
tom@1199:         this.down('image[name=errorImg]').hide();
tom@1199:         this.down('image[name=warnImg]').hide();
tom@1199:     },
tom@1199: 
tom@1199:     getValue: function() {
tom@1199:         this.down('numberfield[hidden]').getValue();
tom@1199:     },
tom@1199: 
tom@1199:     setValue: function(value) {
tom@1199:         this.down('numberfield[hidden]').setValue(value);
tom@1199:     }
tom@1199: });