| @@ 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]; |
|