我们在其中一个管理页面上遇到了脚本行为不同的问题。仅在Google Chrome浏览器中发现了该问题。
我们在用户界面中输入了日期时间字段:
z(...functions)(x)
以下是脚本正确与错误之间的区别: http://prntscr.com/o96jjb http://prntscr.com/o96ju0
我们在Google Chrome 75.0.3770.100上使用Angular JS 1.7.8
这是datetimepicker的剪切代码:
<datetime-picker ng-model="io.start"
name="start"
min="getMinStartDate()"
max="getMaxStartDate()"
date-title="startDateTitle"
time-title="startTimeTitle"
default-time=""
timezone="timezone"
disabled="startDisabled"
required></datetime-picker>
然后编辑控制器剪切代码:
// DATETIME PICKER
/*
globals moment
*/
(function(angular) {
'use strict';
var app = angular.module('asDMgr');
app.directive('datetimePicker', function() {
...
return {
restrict: 'E',
replace: true,
templateUrl: '/app/modules/static/tpl/datetime-picker.html',
scope: {
ngModel: '=',
min: '=',
max: '=',
timezone: '=',
disabled: '=',
dateTitle: '=',
timeTitle: '=',
required: '@',
name: '@',
infoMsg: '@',
defaultTime: '@', // leave empty if default time is NOW
},
link: function($scope, $element, $attrs) {
...
/**
* MIN TIME
*/
$scope.$watch('min', function(newVal) {
console.log("DATETIME PICKER MIN");
if (newVal) {
min = newVal;
var minToPrint = min - $scope.timezoneOffset;
$scope.minDisplay = printDateTimeFormatted(
minToPrint,
dateTimeFormat
);
$date
.data('DateTimePicker')
.minDate(moment.utc(minToPrint).format(pickerFormat));
if (
$scope.minInvalid || // if already invalidated, we still need to update the datetime in error message
($scope.ngModel && min > $scope.ngModel)
) {
$scope.ngModel = undefined;
$scope.displayDate = '';
$scope.invalid =
'Min. Date: ' +
printDateTimeFormatted(minToPrint, dateTimeFormat);
$scope.minInvalid = true;
}
} else {
min = null;
}
});
/**
* MAX TIME
*/
$scope.$watch('max', function(newVal) {
console.log("DATETIME PICKER MAX");
if (newVal) {
max = newVal;
var maxToPrint = max - $scope.timezoneOffset;
if ($scope.min && newVal < $scope.min) {
// max can not be less than min
max = null;
return;
}
$scope.maxDisplay = printDateTimeFormatted(
maxToPrint,
dateTimeFormat
);
$date
.data('DateTimePicker')
.maxDate(moment.utc(maxToPrint).format(pickerFormat));
if ($scope.maxInvalid || ($scope.ngModel && max < $scope.ngModel)) {
$scope.ngModel = undefined;
$scope.displayDate = '';
$scope.maxInvalid = true;
$scope.invalid =
'Max. Date: ' +
printDateTimeFormatted(maxToPrint, dateTimeFormat);
}
} else {
max = null;
}
});
/**
* Angular init
*/
$scope.$watch('ngModel', function(newVal) {
console.log("Datetime picker init");
console.log(newVal);
if (!isValid(newVal) && !$scope.wasInitialised) {
// first init
$scope.timeDisplay = defaultTime;
$scope.wasInitialised = true;
return;
} else if (!isValid(newVal) && $scope.wasInitialised) {
return;
}
var datetimeToPrint = newVal - $scope.timezoneOffset;
$scope.pickerDate = printDateTimeFormatted(
extractDate(datetimeToPrint),
pickerFormat
);
$scope.displayDate = printDateTimeFormatted(
extractDate(datetimeToPrint),
dateFormat
);
$scope.timeDisplay = printDateTimeFormatted(
extractTime(datetimeToPrint),
timeFormat
);
});
function userActionHandler() {
console.log("userActionHandler started");
var utcMilliseconds = getUserInputInUtcMilliseconds();
if (validate(utcMilliseconds)) {
$scope.ngModel = utcMilliseconds;
} else {
$scope.ngModel = undefined;
}
$scope.$apply();
}
$date
.datetimepicker({
format: pickerFormat,
useCurrent: false,
ignoreReadonly: true,
debug: false,
})
.on('dp.change', function(event) {
var momentDate = moment.utc($date.val(), pickerFormat).format();
$scope.displayDate = printDateTimeFormatted(
extractDate(momentDate.valueOf()),
dateFormat
);
userActionHandler();
});
$time.on('change', userActionHandler);
},
};
});
})(window.angular);
InsertionOrderApi.read方法详细信息:
/**
* Edit Controller
*/
/*
globals moment
*/
(function(angular) {
'use strict';
var app = angular.module('asDMgr');
app.controller('IOEditController', [
'$scope',
'$window',
'$timeout',
'IOApi',
function($scope, $window, $timeout, IOApi) {
$scope.now = moment
.utc()
.seconds(0)
.milliseconds(0)
.valueOf();
$scope.startDateTitle = $scope.endDateTitle = '';
$scope.startTimeTitle = $scope.endTimeTitle = '';
$scope.startDisabled = $scope.endDisabled = false;
// init values
$scope.io = {
minEndDate: null,
minStartDate: null,
};
$scope.getMinStartDate = function() {
console.log("getMinStartDate starts");
console.log($scope.io);
if (
!$scope.io._id || // for new IOs
!$scope.io.minStartDate || //
($scope.io.minStartDate && $scope.now <= $scope.io.minStartDate) // NOW <= start date
) {
if (
$scope.io.start &&
$scope.io.minStartDate &&
$scope.io.start > $scope.io.minStartDate
) {
$scope.startDisabled = true;
console.log("getMinStartDate: return null");
return null;
} else {
console.log("getMinStartDate: return now");
return $scope.now;
}
}
console.log("getMinStartDate: return now");
return $scope.now;
};
$scope.getMaxStartDate = function() {
console.log("getMaxStartDate starts");
if (
$scope.io._id && // for existing IOs
$scope.io.minStartDate && // if assigned
!$scope.startDisabled
) {
var max = $scope.io.minStartDate;
if (max < $scope.getMinStartDate()) {
console.log("getMaxStartDate: startDisabled = true");
$scope.startDisabled = true;
} else {
console.log("getMaxStartDate: return $scope.io.minStartDate");
console.log($scope.io.minStartDate);
return $scope.io.minStartDate;
}
}
console.log("getMaxStartDate: return null");
return null;
};
//$scope.fetch = function() {
// load io from server
if (window.ioId) {
insertionOrderApi.read(window.ioId).then(
function (data) {
$scope.io = data.io;
console.log("IO Received from server!");
console.log(data);
console.log($scope.io);
},
function () {
console.error('could not load io');
}
);
} else if (!window.ioId && window.advertiserId) {
//
}
//}
//$timeout( function(){$scope.fetch();}, 20); // if add this timeout - errors appear very rarely
},
]);
})(window.angular);
我在从服务器接收数据的呼叫中添加了延迟之后,错误几乎消失了(很少出现)
this.read = function(campaignId) {
var url = '/campaign/read?id=' + campaignId;
return $q(function(resolve, reject) {
$http.get(url).then(
// success
function(res) {
resolve(res.data);
},
// error
function(res) {
reject();
}
);
});
};
如何彻底解决此问题?