From: Coleman Watts Date: Wed, 4 Mar 2015 03:04:29 +0000 (-0500) Subject: CRM-16019 - Datepicker unit tests and fixes X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=ac5009c1801aa5a695677854be670b3e053189be;p=civicrm-core.git CRM-16019 - Datepicker unit tests and fixes --- diff --git a/js/Common.js b/js/Common.js index b9f26de384..5a8e0cb9ba 100644 --- a/js/Common.js +++ b/js/Common.js @@ -611,19 +611,22 @@ CRM.strings = CRM.strings || {}; $dateField.datepicker(settings).change(updateDataField); } function updateInputFields(e, context) { + var val = $dataField.val(), + time = null; if (context !== 'userInput' && context !== 'crmClear') { - if ($(this).val()) { - if ($dateField.length) { - $dateField.datepicker('setDate', $.datepicker.parseDate('yy-mm-dd', $(this).val())); - } - if ($timeField.length) { - $timeField.timeEntry('setTime', ($dateField.length ? $(this).val().split(' ')[1] : $(this).val()) || null); + if ($dateField.length) { + $dateField.datepicker('setDate', _.includes(val, '-') ? $.datepicker.parseDate('yy-mm-dd', val) : null); + } + if ($timeField.length) { + if (val.length === 8) { + time = val; + } else if (val.length === 19) { + time = val.split(' ')[1]; } - } else { - $dateField.add($timeField).val(''); + $timeField.timeEntry('setTime', time); } } - $clearLink.css('visibility', $(this).val() ? 'visible' : 'hidden'); + $clearLink.css('visibility', val ? 'visible' : 'hidden'); } function updateDataField(e, context) { if (context !== 'crmClear') { @@ -632,7 +635,7 @@ CRM.strings = CRM.strings || {}; val = $.datepicker.formatDate('yy-mm-dd', $dateField.datepicker('getDate')); } if ($timeField.val()) { - val += (val ? ' ' : '') + $timeField.timeEntry('getTime').toTimeString().substr(0, 5); + val += (val ? ' ' : '') + $timeField.timeEntry('getTime').toTimeString().substr(0, 8); } $dataField.val(val).trigger('change', ['userInput']); } diff --git a/js/angular-crm-ui.js b/js/angular-crm-ui.js index 48c688955d..b810b39fce 100644 --- a/js/angular-crm-ui.js +++ b/js/angular-crm-ui.js @@ -65,15 +65,19 @@ crmUiDatepicker: '=' }, link: function (scope, element, attrs, ngModel) { + ngModel.$render = function () { + element.val(ngModel.$viewValue).change(); + }; + element .crmDatepicker(scope.crmUiDatepicker) .on('change', function() { - var requiredLength = 16; + var requiredLength = 19; if (scope.crmUiDatepicker && scope.crmUiDatepicker.time === false) { requiredLength = 10; } if (scope.crmUiDatepicker && scope.crmUiDatepicker.date === false) { - requiredLength = 5; + requiredLength = 8; } ngModel.$setValidity('incompleteDateTime', !($(this).val().length && $(this).val().length !== requiredLength)); }); diff --git a/js/angular-crmMailing/directives.js b/js/angular-crmMailing/directives.js index a175bf6c86..a9977a6a9f 100644 --- a/js/angular-crmMailing/directives.js +++ b/js/angular-crmMailing/directives.js @@ -122,9 +122,17 @@ }; ngModel.$render = function $render() { - validate(); + var sched = ngModel.$viewValue; + if (!_.isEmpty(sched)) { + schedule.mode = 'at'; + schedule.datetime = sched; + } + else { + schedule.mode = 'now'; + schedule.datetime = ''; + } }; - // Update time value based on radio selection + var updateParent = (function () { switch (schedule.mode) { case 'now': @@ -132,39 +140,32 @@ schedule.datetime = ''; break; case 'at': + schedule.datetime = schedule.datetime || '?'; ngModel.$setViewValue(schedule.datetime); break; default: throw 'Unrecognized schedule mode: ' + schedule.mode; } - validate(); - // Angular model changes don't seem to trigger the "change" event. - // Redundantly setting the value here to ensure it happens before the event and not after - $('.crm-hidden-date', element).val(schedule.datetime).trigger('change'); }); - function validate() { - switch (schedule.mode) { - case 'now': - ngModel.$setValidity('empty', true); - break; - case 'at': - ngModel.$setValidity('empty', !_.isEmpty(schedule.datetime)); - break; - default: - throw 'Unrecognized schedule mode: ' + schedule.mode; - } - } + element.on('click', ':radio[value=at]', function() { + $('.crm-form-date', element).focus(); + }); $scope.$watch(attrs.crmMailingRadioDate + '.mode', updateParent); - - // Watch changes in the date element, but only those initiated by the user - // (model-based changes to this field should not force-update other parts of the model) - $(element).on('change', '.crm-hidden-date', function(e, context) { - if (context === 'userInput' || context === 'crmClear') { - schedule.mode = $(this).val() ? 'at' : 'now'; - updateParent(); + $scope.$watch(attrs.crmMailingRadioDate + '.datetime', function (newValue, oldValue) { + // automatically switch mode based on datetime entry + if (typeof oldValue === 'undefined') oldValue = ''; + if (typeof newValue === 'undefined') newValue = ''; + if (oldValue !== newValue) { + if (_.isEmpty(newValue)) { + schedule.mode = 'now'; + } + else { + schedule.mode = 'at'; + } } + updateParent(); }); } }; diff --git a/tests/karma/unit/crmMailingRadioDateSpec.js b/tests/karma/unit/crmMailingRadioDateSpec.js index 196b1152ca..a90a820f6b 100644 --- a/tests/karma/unit/crmMailingRadioDateSpec.js +++ b/tests/karma/unit/crmMailingRadioDateSpec.js @@ -1,5 +1,5 @@ 'use strict'; -/* global CRM:true */ +/* global $, CRM:true */ describe('crmMailingRadioDate', function() { @@ -61,15 +61,16 @@ describe('crmMailingRadioDate', function() { expect(element.find('.crm-form-date').datepicker('getDate')).toBe(null); expect(element.find('.crm-form-time').timeEntry('getTime')).toBe(null); - model.the_date = '2014-01-01 '; + model.the_date = '2014-01-01'; $rootScope.$digest(); expect($rootScope.myForm.$valid).toBe(false); expect(element.find('.radio-now').prop('checked')).toBe(false); expect(element.find('.radio-at').prop('checked')).toBe(true); - expect(element.find('.crm-form-date').datepicker('getDate').toDateString()).toEqual('Wed Jan 01 2014'); + expect(element.find('.crm-hidden-date').val()).toEqual('2014-01-01'); + expect(element.find('.crm-form-date').val()).toEqual('01/01/2014'); expect(element.find('.crm-form-time').timeEntry('getTime')).toBe(null); - model.the_date = '02:03:04'; + model.the_date = '02:03:00'; $rootScope.$digest(); expect($rootScope.myForm.$valid).toBe(false); expect(element.find('.radio-now').prop('checked')).toBe(false); @@ -77,7 +78,7 @@ describe('crmMailingRadioDate', function() { expect(element.find('.crm-form-date').datepicker('getDate')).toBe(null); expect(element.find('.crm-form-time').timeEntry('getTime').getMinutes()).toBe(3); - model.the_date = '2014-01-02 02:03:04'; + model.the_date = '2014-01-02 02:03:00'; $rootScope.$digest(); expect($rootScope.myForm.$valid).toBe(true); expect(element.find('.radio-now').prop('checked')).toBe(false); @@ -88,13 +89,15 @@ describe('crmMailingRadioDate', function() { it('should update the model after changing the date and time', function() { element = $compile(standardMarkup)($rootScope); + model.the_date = ''; $rootScope.$digest(); expect($rootScope.myForm.$valid).toBe(true); expect(element.find('.radio-now').prop('checked')).toBe(true); expect(element.find('.radio-at').prop('checked')).toBe(false); - element.find('.crm-form-date').datepicker('setDate', '2014-01-03').trigger('change'); + element.find('.radio-now').click().trigger('click').trigger('change'); + element.find('.crm-form-date').datepicker('setDate', $.datepicker.parseDate('yy-mm-dd', '2014-01-03')).trigger('change'); $rootScope.$digest(); expect(model.the_date).toBe('2014-01-03'); expect($rootScope.myForm.$valid).toBe(false); @@ -103,14 +106,14 @@ describe('crmMailingRadioDate', function() { element.find('.crm-form-time').timeEntry('setTime', '04:05').trigger('change'); $rootScope.$digest(); - expect(model.the_date).toBe('2014-01-03 04:05'); + expect(model.the_date).toBe('2014-01-03 04:05:00'); expect($rootScope.myForm.$valid).toBe(true); expect(element.find('.radio-now').prop('checked')).toBe(false); expect(element.find('.radio-at').prop('checked')).toBe(true); element.find('.crm-form-date').datepicker('setDate', '').trigger('change'); $rootScope.$digest(); - expect(model.the_date).toBe('04:05'); + expect(model.the_date).toBe('04:05:00'); expect($rootScope.myForm.$valid).toBe(false); expect(element.find('.radio-now').prop('checked')).toBe(false); expect(element.find('.radio-at').prop('checked')).toBe(true);