@@ 1329-1643 (lines=315) @@ | ||
1326 | }) |
|
1327 | ||
1328 | .controller('UibDatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$locale', '$log', 'dateFilter', 'uibDatepickerConfig', '$datepickerLiteralWarning', '$datepickerSuppressError', 'uibDateParser', |
|
1329 | function($scope, $attrs, $parse, $interpolate, $locale, $log, dateFilter, datepickerConfig, $datepickerLiteralWarning, $datepickerSuppressError, dateParser) { |
|
1330 | var self = this, |
|
1331 | ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl; |
|
1332 | ngModelOptions = {}, |
|
1333 | watchListeners = [], |
|
1334 | optionsUsed = !!$attrs.datepickerOptions; |
|
1335 | ||
1336 | if (!$scope.datepickerOptions) { |
|
1337 | $scope.datepickerOptions = {}; |
|
1338 | } |
|
1339 | ||
1340 | // Modes chain |
|
1341 | this.modes = ['day', 'month', 'year']; |
|
1342 | ||
1343 | [ |
|
1344 | 'customClass', |
|
1345 | 'dateDisabled', |
|
1346 | 'datepickerMode', |
|
1347 | 'formatDay', |
|
1348 | 'formatDayHeader', |
|
1349 | 'formatDayTitle', |
|
1350 | 'formatMonth', |
|
1351 | 'formatMonthTitle', |
|
1352 | 'formatYear', |
|
1353 | 'maxDate', |
|
1354 | 'maxMode', |
|
1355 | 'minDate', |
|
1356 | 'minMode', |
|
1357 | 'showWeeks', |
|
1358 | 'shortcutPropagation', |
|
1359 | 'startingDay', |
|
1360 | 'yearColumns', |
|
1361 | 'yearRows' |
|
1362 | ].forEach(function(key) { |
|
1363 | switch (key) { |
|
1364 | case 'customClass': |
|
1365 | case 'dateDisabled': |
|
1366 | $scope[key] = $scope.datepickerOptions[key] || angular.noop; |
|
1367 | break; |
|
1368 | case 'datepickerMode': |
|
1369 | $scope.datepickerMode = angular.isDefined($scope.datepickerOptions.datepickerMode) ? |
|
1370 | $scope.datepickerOptions.datepickerMode : datepickerConfig.datepickerMode; |
|
1371 | break; |
|
1372 | case 'formatDay': |
|
1373 | case 'formatDayHeader': |
|
1374 | case 'formatDayTitle': |
|
1375 | case 'formatMonth': |
|
1376 | case 'formatMonthTitle': |
|
1377 | case 'formatYear': |
|
1378 | self[key] = angular.isDefined($scope.datepickerOptions[key]) ? |
|
1379 | $interpolate($scope.datepickerOptions[key])($scope.$parent) : |
|
1380 | datepickerConfig[key]; |
|
1381 | break; |
|
1382 | case 'showWeeks': |
|
1383 | case 'shortcutPropagation': |
|
1384 | case 'yearColumns': |
|
1385 | case 'yearRows': |
|
1386 | self[key] = angular.isDefined($scope.datepickerOptions[key]) ? |
|
1387 | $scope.datepickerOptions[key] : datepickerConfig[key]; |
|
1388 | break; |
|
1389 | case 'startingDay': |
|
1390 | if (angular.isDefined($scope.datepickerOptions.startingDay)) { |
|
1391 | self.startingDay = $scope.datepickerOptions.startingDay; |
|
1392 | } else if (angular.isNumber(datepickerConfig.startingDay)) { |
|
1393 | self.startingDay = datepickerConfig.startingDay; |
|
1394 | } else { |
|
1395 | self.startingDay = ($locale.DATETIME_FORMATS.FIRSTDAYOFWEEK + 8) % 7; |
|
1396 | } |
|
1397 | ||
1398 | break; |
|
1399 | case 'maxDate': |
|
1400 | case 'minDate': |
|
1401 | $scope.$watch('datepickerOptions.' + key, function(value) { |
|
1402 | if (value) { |
|
1403 | if (angular.isDate(value)) { |
|
1404 | self[key] = dateParser.fromTimezone(new Date(value), ngModelOptions.timezone); |
|
1405 | } else { |
|
1406 | if ($datepickerLiteralWarning) { |
|
1407 | $log.warn('Literal date support has been deprecated, please switch to date object usage'); |
|
1408 | } |
|
1409 | ||
1410 | self[key] = new Date(dateFilter(value, 'medium')); |
|
1411 | } |
|
1412 | } else { |
|
1413 | self[key] = datepickerConfig[key] ? |
|
1414 | dateParser.fromTimezone(new Date(datepickerConfig[key]), ngModelOptions.timezone) : |
|
1415 | null; |
|
1416 | } |
|
1417 | ||
1418 | self.refreshView(); |
|
1419 | }); |
|
1420 | ||
1421 | break; |
|
1422 | case 'maxMode': |
|
1423 | case 'minMode': |
|
1424 | if ($scope.datepickerOptions[key]) { |
|
1425 | $scope.$watch(function() { return $scope.datepickerOptions[key]; }, function(value) { |
|
1426 | self[key] = $scope[key] = angular.isDefined(value) ? value : datepickerOptions[key]; |
|
1427 | if (key === 'minMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) < self.modes.indexOf(self[key]) || |
|
1428 | key === 'maxMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) > self.modes.indexOf(self[key])) { |
|
1429 | $scope.datepickerMode = self[key]; |
|
1430 | $scope.datepickerOptions.datepickerMode = self[key]; |
|
1431 | } |
|
1432 | }); |
|
1433 | } else { |
|
1434 | self[key] = $scope[key] = datepickerConfig[key] || null; |
|
1435 | } |
|
1436 | ||
1437 | break; |
|
1438 | } |
|
1439 | }); |
|
1440 | ||
1441 | $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000); |
|
1442 | ||
1443 | $scope.disabled = angular.isDefined($attrs.disabled) || false; |
|
1444 | if (angular.isDefined($attrs.ngDisabled)) { |
|
1445 | watchListeners.push($scope.$parent.$watch($attrs.ngDisabled, function(disabled) { |
|
1446 | $scope.disabled = disabled; |
|
1447 | self.refreshView(); |
|
1448 | })); |
|
1449 | } |
|
1450 | ||
1451 | $scope.isActive = function(dateObject) { |
|
1452 | if (self.compare(dateObject.date, self.activeDate) === 0) { |
|
1453 | $scope.activeDateId = dateObject.uid; |
|
1454 | return true; |
|
1455 | } |
|
1456 | return false; |
|
1457 | }; |
|
1458 | ||
1459 | this.init = function(ngModelCtrl_) { |
|
1460 | ngModelCtrl = ngModelCtrl_; |
|
1461 | ngModelOptions = ngModelCtrl_.$options || datepickerConfig.ngModelOptions; |
|
1462 | if ($scope.datepickerOptions.initDate) { |
|
1463 | self.activeDate = dateParser.fromTimezone($scope.datepickerOptions.initDate, ngModelOptions.timezone) || new Date(); |
|
1464 | $scope.$watch('datepickerOptions.initDate', function(initDate) { |
|
1465 | if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) { |
|
1466 | self.activeDate = dateParser.fromTimezone(initDate, ngModelOptions.timezone); |
|
1467 | self.refreshView(); |
|
1468 | } |
|
1469 | }); |
|
1470 | } else { |
|
1471 | self.activeDate = new Date(); |
|
1472 | } |
|
1473 | ||
1474 | this.activeDate = ngModelCtrl.$modelValue ? |
|
1475 | dateParser.fromTimezone(new Date(ngModelCtrl.$modelValue), ngModelOptions.timezone) : |
|
1476 | dateParser.fromTimezone(new Date(), ngModelOptions.timezone); |
|
1477 | ||
1478 | ngModelCtrl.$render = function() { |
|
1479 | self.render(); |
|
1480 | }; |
|
1481 | }; |
|
1482 | ||
1483 | this.render = function() { |
|
1484 | if (ngModelCtrl.$viewValue) { |
|
1485 | var date = new Date(ngModelCtrl.$viewValue), |
|
1486 | isValid = !isNaN(date); |
|
1487 | ||
1488 | if (isValid) { |
|
1489 | this.activeDate = dateParser.fromTimezone(date, ngModelOptions.timezone); |
|
1490 | } else if (!$datepickerSuppressError) { |
|
1491 | $log.error('Datepicker directive: "ng-model" value must be a Date object'); |
|
1492 | } |
|
1493 | } |
|
1494 | this.refreshView(); |
|
1495 | }; |
|
1496 | ||
1497 | this.refreshView = function() { |
|
1498 | if (this.element) { |
|
1499 | $scope.selectedDt = null; |
|
1500 | this._refreshView(); |
|
1501 | if ($scope.activeDt) { |
|
1502 | $scope.activeDateId = $scope.activeDt.uid; |
|
1503 | } |
|
1504 | ||
1505 | var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; |
|
1506 | date = dateParser.fromTimezone(date, ngModelOptions.timezone); |
|
1507 | ngModelCtrl.$setValidity('dateDisabled', !date || |
|
1508 | this.element && !this.isDisabled(date)); |
|
1509 | } |
|
1510 | }; |
|
1511 | ||
1512 | this.createDateObject = function(date, format) { |
|
1513 | var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; |
|
1514 | model = dateParser.fromTimezone(model, ngModelOptions.timezone); |
|
1515 | var today = new Date(); |
|
1516 | today = dateParser.fromTimezone(today, ngModelOptions.timezone); |
|
1517 | var time = this.compare(date, today); |
|
1518 | var dt = { |
|
1519 | date: date, |
|
1520 | label: dateParser.filter(date, format), |
|
1521 | selected: model && this.compare(date, model) === 0, |
|
1522 | disabled: this.isDisabled(date), |
|
1523 | past: time < 0, |
|
1524 | current: time === 0, |
|
1525 | future: time > 0, |
|
1526 | customClass: this.customClass(date) || null |
|
1527 | }; |
|
1528 | ||
1529 | if (model && this.compare(date, model) === 0) { |
|
1530 | $scope.selectedDt = dt; |
|
1531 | } |
|
1532 | ||
1533 | if (self.activeDate && this.compare(dt.date, self.activeDate) === 0) { |
|
1534 | $scope.activeDt = dt; |
|
1535 | } |
|
1536 | ||
1537 | return dt; |
|
1538 | }; |
|
1539 | ||
1540 | this.isDisabled = function(date) { |
|
1541 | return $scope.disabled || |
|
1542 | this.minDate && this.compare(date, this.minDate) < 0 || |
|
1543 | this.maxDate && this.compare(date, this.maxDate) > 0 || |
|
1544 | $scope.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode}); |
|
1545 | }; |
|
1546 | ||
1547 | this.customClass = function(date) { |
|
1548 | return $scope.customClass({date: date, mode: $scope.datepickerMode}); |
|
1549 | }; |
|
1550 | ||
1551 | // Split array into smaller arrays |
|
1552 | this.split = function(arr, size) { |
|
1553 | var arrays = []; |
|
1554 | while (arr.length > 0) { |
|
1555 | arrays.push(arr.splice(0, size)); |
|
1556 | } |
|
1557 | return arrays; |
|
1558 | }; |
|
1559 | ||
1560 | $scope.select = function(date) { |
|
1561 | if ($scope.datepickerMode === self.minMode) { |
|
1562 | var dt = ngModelCtrl.$viewValue ? dateParser.fromTimezone(new Date(ngModelCtrl.$viewValue), ngModelOptions.timezone) : new Date(0, 0, 0, 0, 0, 0, 0); |
|
1563 | dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); |
|
1564 | dt = dateParser.toTimezone(dt, ngModelOptions.timezone); |
|
1565 | ngModelCtrl.$setViewValue(dt); |
|
1566 | ngModelCtrl.$render(); |
|
1567 | } else { |
|
1568 | self.activeDate = date; |
|
1569 | setMode(self.modes[self.modes.indexOf($scope.datepickerMode) - 1]); |
|
1570 | ||
1571 | $scope.$emit('uib:datepicker.mode'); |
|
1572 | } |
|
1573 | ||
1574 | $scope.$broadcast('uib:datepicker.focus'); |
|
1575 | }; |
|
1576 | ||
1577 | $scope.move = function(direction) { |
|
1578 | var year = self.activeDate.getFullYear() + direction * (self.step.years || 0), |
|
1579 | month = self.activeDate.getMonth() + direction * (self.step.months || 0); |
|
1580 | self.activeDate.setFullYear(year, month, 1); |
|
1581 | self.refreshView(); |
|
1582 | }; |
|
1583 | ||
1584 | $scope.toggleMode = function(direction) { |
|
1585 | direction = direction || 1; |
|
1586 | ||
1587 | if ($scope.datepickerMode === self.maxMode && direction === 1 || |
|
1588 | $scope.datepickerMode === self.minMode && direction === -1) { |
|
1589 | return; |
|
1590 | } |
|
1591 | ||
1592 | setMode(self.modes[self.modes.indexOf($scope.datepickerMode) + direction]); |
|
1593 | ||
1594 | $scope.$emit('uib:datepicker.mode'); |
|
1595 | }; |
|
1596 | ||
1597 | // Key event mapper |
|
1598 | $scope.keys = { 13: 'enter', 32: 'space', 33: 'pageup', 34: 'pagedown', 35: 'end', 36: 'home', 37: 'left', 38: 'up', 39: 'right', 40: 'down' }; |
|
1599 | ||
1600 | var focusElement = function() { |
|
1601 | self.element[0].focus(); |
|
1602 | }; |
|
1603 | ||
1604 | // Listen for focus requests from popup directive |
|
1605 | $scope.$on('uib:datepicker.focus', focusElement); |
|
1606 | ||
1607 | $scope.keydown = function(evt) { |
|
1608 | var key = $scope.keys[evt.which]; |
|
1609 | ||
1610 | if (!key || evt.shiftKey || evt.altKey || $scope.disabled) { |
|
1611 | return; |
|
1612 | } |
|
1613 | ||
1614 | evt.preventDefault(); |
|
1615 | if (!self.shortcutPropagation) { |
|
1616 | evt.stopPropagation(); |
|
1617 | } |
|
1618 | ||
1619 | if (key === 'enter' || key === 'space') { |
|
1620 | if (self.isDisabled(self.activeDate)) { |
|
1621 | return; // do nothing |
|
1622 | } |
|
1623 | $scope.select(self.activeDate); |
|
1624 | } else if (evt.ctrlKey && (key === 'up' || key === 'down')) { |
|
1625 | $scope.toggleMode(key === 'up' ? 1 : -1); |
|
1626 | } else { |
|
1627 | self.handleKeyDown(key, evt); |
|
1628 | self.refreshView(); |
|
1629 | } |
|
1630 | }; |
|
1631 | ||
1632 | $scope.$on('$destroy', function() { |
|
1633 | //Clear all watch listeners on destroy |
|
1634 | while (watchListeners.length) { |
|
1635 | watchListeners.shift()(); |
|
1636 | } |
|
1637 | }); |
|
1638 | ||
1639 | function setMode(mode) { |
|
1640 | $scope.datepickerMode = mode; |
|
1641 | $scope.datepickerOptions.datepickerMode = mode; |
|
1642 | } |
|
1643 | }]) |
|
1644 | ||
1645 | .controller('UibDaypickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) { |
|
1646 | var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; |
@@ 1328-1642 (lines=315) @@ | ||
1325 | }) |
|
1326 | ||
1327 | .controller('UibDatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$locale', '$log', 'dateFilter', 'uibDatepickerConfig', '$datepickerLiteralWarning', '$datepickerSuppressError', 'uibDateParser', |
|
1328 | function($scope, $attrs, $parse, $interpolate, $locale, $log, dateFilter, datepickerConfig, $datepickerLiteralWarning, $datepickerSuppressError, dateParser) { |
|
1329 | var self = this, |
|
1330 | ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl; |
|
1331 | ngModelOptions = {}, |
|
1332 | watchListeners = [], |
|
1333 | optionsUsed = !!$attrs.datepickerOptions; |
|
1334 | ||
1335 | if (!$scope.datepickerOptions) { |
|
1336 | $scope.datepickerOptions = {}; |
|
1337 | } |
|
1338 | ||
1339 | // Modes chain |
|
1340 | this.modes = ['day', 'month', 'year']; |
|
1341 | ||
1342 | [ |
|
1343 | 'customClass', |
|
1344 | 'dateDisabled', |
|
1345 | 'datepickerMode', |
|
1346 | 'formatDay', |
|
1347 | 'formatDayHeader', |
|
1348 | 'formatDayTitle', |
|
1349 | 'formatMonth', |
|
1350 | 'formatMonthTitle', |
|
1351 | 'formatYear', |
|
1352 | 'maxDate', |
|
1353 | 'maxMode', |
|
1354 | 'minDate', |
|
1355 | 'minMode', |
|
1356 | 'showWeeks', |
|
1357 | 'shortcutPropagation', |
|
1358 | 'startingDay', |
|
1359 | 'yearColumns', |
|
1360 | 'yearRows' |
|
1361 | ].forEach(function(key) { |
|
1362 | switch (key) { |
|
1363 | case 'customClass': |
|
1364 | case 'dateDisabled': |
|
1365 | $scope[key] = $scope.datepickerOptions[key] || angular.noop; |
|
1366 | break; |
|
1367 | case 'datepickerMode': |
|
1368 | $scope.datepickerMode = angular.isDefined($scope.datepickerOptions.datepickerMode) ? |
|
1369 | $scope.datepickerOptions.datepickerMode : datepickerConfig.datepickerMode; |
|
1370 | break; |
|
1371 | case 'formatDay': |
|
1372 | case 'formatDayHeader': |
|
1373 | case 'formatDayTitle': |
|
1374 | case 'formatMonth': |
|
1375 | case 'formatMonthTitle': |
|
1376 | case 'formatYear': |
|
1377 | self[key] = angular.isDefined($scope.datepickerOptions[key]) ? |
|
1378 | $interpolate($scope.datepickerOptions[key])($scope.$parent) : |
|
1379 | datepickerConfig[key]; |
|
1380 | break; |
|
1381 | case 'showWeeks': |
|
1382 | case 'shortcutPropagation': |
|
1383 | case 'yearColumns': |
|
1384 | case 'yearRows': |
|
1385 | self[key] = angular.isDefined($scope.datepickerOptions[key]) ? |
|
1386 | $scope.datepickerOptions[key] : datepickerConfig[key]; |
|
1387 | break; |
|
1388 | case 'startingDay': |
|
1389 | if (angular.isDefined($scope.datepickerOptions.startingDay)) { |
|
1390 | self.startingDay = $scope.datepickerOptions.startingDay; |
|
1391 | } else if (angular.isNumber(datepickerConfig.startingDay)) { |
|
1392 | self.startingDay = datepickerConfig.startingDay; |
|
1393 | } else { |
|
1394 | self.startingDay = ($locale.DATETIME_FORMATS.FIRSTDAYOFWEEK + 8) % 7; |
|
1395 | } |
|
1396 | ||
1397 | break; |
|
1398 | case 'maxDate': |
|
1399 | case 'minDate': |
|
1400 | $scope.$watch('datepickerOptions.' + key, function(value) { |
|
1401 | if (value) { |
|
1402 | if (angular.isDate(value)) { |
|
1403 | self[key] = dateParser.fromTimezone(new Date(value), ngModelOptions.timezone); |
|
1404 | } else { |
|
1405 | if ($datepickerLiteralWarning) { |
|
1406 | $log.warn('Literal date support has been deprecated, please switch to date object usage'); |
|
1407 | } |
|
1408 | ||
1409 | self[key] = new Date(dateFilter(value, 'medium')); |
|
1410 | } |
|
1411 | } else { |
|
1412 | self[key] = datepickerConfig[key] ? |
|
1413 | dateParser.fromTimezone(new Date(datepickerConfig[key]), ngModelOptions.timezone) : |
|
1414 | null; |
|
1415 | } |
|
1416 | ||
1417 | self.refreshView(); |
|
1418 | }); |
|
1419 | ||
1420 | break; |
|
1421 | case 'maxMode': |
|
1422 | case 'minMode': |
|
1423 | if ($scope.datepickerOptions[key]) { |
|
1424 | $scope.$watch(function() { return $scope.datepickerOptions[key]; }, function(value) { |
|
1425 | self[key] = $scope[key] = angular.isDefined(value) ? value : datepickerOptions[key]; |
|
1426 | if (key === 'minMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) < self.modes.indexOf(self[key]) || |
|
1427 | key === 'maxMode' && self.modes.indexOf($scope.datepickerOptions.datepickerMode) > self.modes.indexOf(self[key])) { |
|
1428 | $scope.datepickerMode = self[key]; |
|
1429 | $scope.datepickerOptions.datepickerMode = self[key]; |
|
1430 | } |
|
1431 | }); |
|
1432 | } else { |
|
1433 | self[key] = $scope[key] = datepickerConfig[key] || null; |
|
1434 | } |
|
1435 | ||
1436 | break; |
|
1437 | } |
|
1438 | }); |
|
1439 | ||
1440 | $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000); |
|
1441 | ||
1442 | $scope.disabled = angular.isDefined($attrs.disabled) || false; |
|
1443 | if (angular.isDefined($attrs.ngDisabled)) { |
|
1444 | watchListeners.push($scope.$parent.$watch($attrs.ngDisabled, function(disabled) { |
|
1445 | $scope.disabled = disabled; |
|
1446 | self.refreshView(); |
|
1447 | })); |
|
1448 | } |
|
1449 | ||
1450 | $scope.isActive = function(dateObject) { |
|
1451 | if (self.compare(dateObject.date, self.activeDate) === 0) { |
|
1452 | $scope.activeDateId = dateObject.uid; |
|
1453 | return true; |
|
1454 | } |
|
1455 | return false; |
|
1456 | }; |
|
1457 | ||
1458 | this.init = function(ngModelCtrl_) { |
|
1459 | ngModelCtrl = ngModelCtrl_; |
|
1460 | ngModelOptions = ngModelCtrl_.$options || datepickerConfig.ngModelOptions; |
|
1461 | if ($scope.datepickerOptions.initDate) { |
|
1462 | self.activeDate = dateParser.fromTimezone($scope.datepickerOptions.initDate, ngModelOptions.timezone) || new Date(); |
|
1463 | $scope.$watch('datepickerOptions.initDate', function(initDate) { |
|
1464 | if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) { |
|
1465 | self.activeDate = dateParser.fromTimezone(initDate, ngModelOptions.timezone); |
|
1466 | self.refreshView(); |
|
1467 | } |
|
1468 | }); |
|
1469 | } else { |
|
1470 | self.activeDate = new Date(); |
|
1471 | } |
|
1472 | ||
1473 | this.activeDate = ngModelCtrl.$modelValue ? |
|
1474 | dateParser.fromTimezone(new Date(ngModelCtrl.$modelValue), ngModelOptions.timezone) : |
|
1475 | dateParser.fromTimezone(new Date(), ngModelOptions.timezone); |
|
1476 | ||
1477 | ngModelCtrl.$render = function() { |
|
1478 | self.render(); |
|
1479 | }; |
|
1480 | }; |
|
1481 | ||
1482 | this.render = function() { |
|
1483 | if (ngModelCtrl.$viewValue) { |
|
1484 | var date = new Date(ngModelCtrl.$viewValue), |
|
1485 | isValid = !isNaN(date); |
|
1486 | ||
1487 | if (isValid) { |
|
1488 | this.activeDate = dateParser.fromTimezone(date, ngModelOptions.timezone); |
|
1489 | } else if (!$datepickerSuppressError) { |
|
1490 | $log.error('Datepicker directive: "ng-model" value must be a Date object'); |
|
1491 | } |
|
1492 | } |
|
1493 | this.refreshView(); |
|
1494 | }; |
|
1495 | ||
1496 | this.refreshView = function() { |
|
1497 | if (this.element) { |
|
1498 | $scope.selectedDt = null; |
|
1499 | this._refreshView(); |
|
1500 | if ($scope.activeDt) { |
|
1501 | $scope.activeDateId = $scope.activeDt.uid; |
|
1502 | } |
|
1503 | ||
1504 | var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; |
|
1505 | date = dateParser.fromTimezone(date, ngModelOptions.timezone); |
|
1506 | ngModelCtrl.$setValidity('dateDisabled', !date || |
|
1507 | this.element && !this.isDisabled(date)); |
|
1508 | } |
|
1509 | }; |
|
1510 | ||
1511 | this.createDateObject = function(date, format) { |
|
1512 | var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null; |
|
1513 | model = dateParser.fromTimezone(model, ngModelOptions.timezone); |
|
1514 | var today = new Date(); |
|
1515 | today = dateParser.fromTimezone(today, ngModelOptions.timezone); |
|
1516 | var time = this.compare(date, today); |
|
1517 | var dt = { |
|
1518 | date: date, |
|
1519 | label: dateParser.filter(date, format), |
|
1520 | selected: model && this.compare(date, model) === 0, |
|
1521 | disabled: this.isDisabled(date), |
|
1522 | past: time < 0, |
|
1523 | current: time === 0, |
|
1524 | future: time > 0, |
|
1525 | customClass: this.customClass(date) || null |
|
1526 | }; |
|
1527 | ||
1528 | if (model && this.compare(date, model) === 0) { |
|
1529 | $scope.selectedDt = dt; |
|
1530 | } |
|
1531 | ||
1532 | if (self.activeDate && this.compare(dt.date, self.activeDate) === 0) { |
|
1533 | $scope.activeDt = dt; |
|
1534 | } |
|
1535 | ||
1536 | return dt; |
|
1537 | }; |
|
1538 | ||
1539 | this.isDisabled = function(date) { |
|
1540 | return $scope.disabled || |
|
1541 | this.minDate && this.compare(date, this.minDate) < 0 || |
|
1542 | this.maxDate && this.compare(date, this.maxDate) > 0 || |
|
1543 | $scope.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode}); |
|
1544 | }; |
|
1545 | ||
1546 | this.customClass = function(date) { |
|
1547 | return $scope.customClass({date: date, mode: $scope.datepickerMode}); |
|
1548 | }; |
|
1549 | ||
1550 | // Split array into smaller arrays |
|
1551 | this.split = function(arr, size) { |
|
1552 | var arrays = []; |
|
1553 | while (arr.length > 0) { |
|
1554 | arrays.push(arr.splice(0, size)); |
|
1555 | } |
|
1556 | return arrays; |
|
1557 | }; |
|
1558 | ||
1559 | $scope.select = function(date) { |
|
1560 | if ($scope.datepickerMode === self.minMode) { |
|
1561 | var dt = ngModelCtrl.$viewValue ? dateParser.fromTimezone(new Date(ngModelCtrl.$viewValue), ngModelOptions.timezone) : new Date(0, 0, 0, 0, 0, 0, 0); |
|
1562 | dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); |
|
1563 | dt = dateParser.toTimezone(dt, ngModelOptions.timezone); |
|
1564 | ngModelCtrl.$setViewValue(dt); |
|
1565 | ngModelCtrl.$render(); |
|
1566 | } else { |
|
1567 | self.activeDate = date; |
|
1568 | setMode(self.modes[self.modes.indexOf($scope.datepickerMode) - 1]); |
|
1569 | ||
1570 | $scope.$emit('uib:datepicker.mode'); |
|
1571 | } |
|
1572 | ||
1573 | $scope.$broadcast('uib:datepicker.focus'); |
|
1574 | }; |
|
1575 | ||
1576 | $scope.move = function(direction) { |
|
1577 | var year = self.activeDate.getFullYear() + direction * (self.step.years || 0), |
|
1578 | month = self.activeDate.getMonth() + direction * (self.step.months || 0); |
|
1579 | self.activeDate.setFullYear(year, month, 1); |
|
1580 | self.refreshView(); |
|
1581 | }; |
|
1582 | ||
1583 | $scope.toggleMode = function(direction) { |
|
1584 | direction = direction || 1; |
|
1585 | ||
1586 | if ($scope.datepickerMode === self.maxMode && direction === 1 || |
|
1587 | $scope.datepickerMode === self.minMode && direction === -1) { |
|
1588 | return; |
|
1589 | } |
|
1590 | ||
1591 | setMode(self.modes[self.modes.indexOf($scope.datepickerMode) + direction]); |
|
1592 | ||
1593 | $scope.$emit('uib:datepicker.mode'); |
|
1594 | }; |
|
1595 | ||
1596 | // Key event mapper |
|
1597 | $scope.keys = { 13: 'enter', 32: 'space', 33: 'pageup', 34: 'pagedown', 35: 'end', 36: 'home', 37: 'left', 38: 'up', 39: 'right', 40: 'down' }; |
|
1598 | ||
1599 | var focusElement = function() { |
|
1600 | self.element[0].focus(); |
|
1601 | }; |
|
1602 | ||
1603 | // Listen for focus requests from popup directive |
|
1604 | $scope.$on('uib:datepicker.focus', focusElement); |
|
1605 | ||
1606 | $scope.keydown = function(evt) { |
|
1607 | var key = $scope.keys[evt.which]; |
|
1608 | ||
1609 | if (!key || evt.shiftKey || evt.altKey || $scope.disabled) { |
|
1610 | return; |
|
1611 | } |
|
1612 | ||
1613 | evt.preventDefault(); |
|
1614 | if (!self.shortcutPropagation) { |
|
1615 | evt.stopPropagation(); |
|
1616 | } |
|
1617 | ||
1618 | if (key === 'enter' || key === 'space') { |
|
1619 | if (self.isDisabled(self.activeDate)) { |
|
1620 | return; // do nothing |
|
1621 | } |
|
1622 | $scope.select(self.activeDate); |
|
1623 | } else if (evt.ctrlKey && (key === 'up' || key === 'down')) { |
|
1624 | $scope.toggleMode(key === 'up' ? 1 : -1); |
|
1625 | } else { |
|
1626 | self.handleKeyDown(key, evt); |
|
1627 | self.refreshView(); |
|
1628 | } |
|
1629 | }; |
|
1630 | ||
1631 | $scope.$on('$destroy', function() { |
|
1632 | //Clear all watch listeners on destroy |
|
1633 | while (watchListeners.length) { |
|
1634 | watchListeners.shift()(); |
|
1635 | } |
|
1636 | }); |
|
1637 | ||
1638 | function setMode(mode) { |
|
1639 | $scope.datepickerMode = mode; |
|
1640 | $scope.datepickerOptions.datepickerMode = mode; |
|
1641 | } |
|
1642 | }]) |
|
1643 | ||
1644 | .controller('UibDaypickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) { |
|
1645 | var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; |