Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

feat(datepicker): implement auto position #5444

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/datepicker/datepicker.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@

.uib-datepicker-popup.dropdown-menu {
display: block;
float: none;
visibility: hidden;
margin: 0;
top: -9999px;
left: -9999px;
}

.uib-button-bar {
Expand Down
49 changes: 42 additions & 7 deletions src/datepicker/datepicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
} else {
self.activeDate = date;
$scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) - 1];
$scope.$emit('uib:datepicker.mode');
}
};

Expand All @@ -351,6 +352,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
}

$scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) + direction];
$scope.$emit('uib:datepicker.mode');
};

// Key event mapper
Expand Down Expand Up @@ -717,15 +719,16 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
'month': 'yyyy-MM'
},
onOpenFocus: true,
showButtonBar: true
showButtonBar: true,
placement: 'auto bottom-left'
})

.controller('UibDatepickerPopupController', ['$scope', '$element', '$attrs', '$compile', '$log', '$parse', '$document', '$rootScope', '$uibPosition', 'dateFilter', 'uibDateParser', 'uibDatepickerPopupConfig', '$timeout', 'uibDatepickerConfig', 'uibDatepickerPopupAttributeWarning',
function($scope, $element, $attrs, $compile, $log, $parse, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout, datepickerConfig, datepickerPopupAttributeWarning) {
.controller('UibDatepickerPopupController', ['$scope', '$element', '$attrs', '$compile', '$log', '$parse', '$window', '$document', '$rootScope', '$uibPosition', 'dateFilter', 'uibDateParser', 'uibDatepickerPopupConfig', '$timeout', 'uibDatepickerConfig', 'uibDatepickerPopupAttributeWarning',
function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout, datepickerConfig, datepickerPopupAttributeWarning) {
var cache = {},
isHtml5DateInput = false;
var dateFormat, closeOnDateSelection, appendToBody, onOpenFocus,
datepickerPopupTemplateUrl, datepickerTemplateUrl, popupEl, datepickerEl,
datepickerPopupTemplateUrl, datepickerTemplateUrl, popupEl, datepickerEl, scrollParentEl,
ngModel, ngModelOptions, $popup, altInputFormats, watchListeners = [];

$scope.watchData = {};
Expand Down Expand Up @@ -965,6 +968,10 @@ function($scope, $element, $attrs, $compile, $log, $parse, $document, $rootScope
$popup.remove();
$element.off('keydown', inputKeydownBind);
$document.off('click', documentClickBind);
if (scrollParentEl) {
scrollParentEl.off('scroll', positionPopup);
}
angular.element($window).off('resize', positionPopup);

//Clear all watch listeners on destroy
while (watchListeners.length) {
Expand Down Expand Up @@ -1045,20 +1052,35 @@ function($scope, $element, $attrs, $compile, $log, $parse, $document, $rootScope
$scope.$watch('isOpen', function(value) {
if (value) {
if (!$scope.disabled) {
$scope.position = appendToBody ? $position.offset($element) : $position.position($element);
$scope.position.top = $scope.position.top + $element.prop('offsetHeight');

$timeout(function() {
positionPopup();

if (onOpenFocus) {
$scope.$broadcast('uib:datepicker.focus');
}
$document.on('click', documentClickBind);

var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
if (appendToBody || $position.parsePlacement(placement)[2]) {
scrollParentEl = scrollParentEl || angular.element($position.scrollParent($element));
if (scrollParentEl) {
scrollParentEl.on('scroll', positionPopup);
}
} else {
scrollParentEl = null;
}

angular.element($window).on('resize', positionPopup);
}, 0, false);
} else {
$scope.isOpen = false;
}
} else {
$document.off('click', documentClickBind);
if (scrollParentEl) {
scrollParentEl.off('scroll', positionPopup);
}
angular.element($window).off('resize', positionPopup);
}
});

Expand Down Expand Up @@ -1162,6 +1184,19 @@ function($scope, $element, $attrs, $compile, $log, $parse, $document, $rootScope
});
}
}

function positionPopup() {
if ($scope.isOpen) {
var dpElement = $popup[0].querySelector('.uib-datepicker-popup');
var placement = $attrs.popupPlacement ? $attrs.popupPlacement : datepickerPopupConfig.placement;
var position = $position.positionElements($element, dpElement, placement, appendToBody);
angular.element(dpElement).css({top: position.top + 'px', left: position.left + 'px', visibility: 'visible'});
}
}

$scope.$on('uib:datepicker.mode', function() {
$timeout(positionPopup, 0, false);
});
}])

.directive('uibDatepickerPopup', function() {
Expand Down
22 changes: 20 additions & 2 deletions src/datepicker/docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ The datepicker has 3 modes:
* `format-month-title`
<small class="badge">C</small>
_(Default: `yyyy`)_ -
Format of title when selecting month.
Format of title when selecting month.

* `init-date`
<small class="badge">$</small>
Expand Down Expand Up @@ -210,7 +210,7 @@ The popup is a wrapper that you can use in an input to toggle a datepicker. To c
* `datepicker-template-url`
<small class="badge">C</small>
_(Default: `uib/template/datepicker/datepicker.html`)_ -
Add the ability to override the template used on the component (inner uib-datepicker).
Add the ability to override the template used on the component (inner uib-datepicker).

* `is-open`
<small class="badge">$</small>
Expand All @@ -235,6 +235,24 @@ The popup is a wrapper that you can use in an input to toggle a datepicker. To c
_(Default: `text`, Config: `html5Types`)_ -
You can override the input type to be _(date|datetime-local|month)_. That will change the date format of the popup.

* `popup-placement`
<small class="badge">C</small>
_(Default: `auto bottom-left`, Config: 'placement')_ -
Passing in 'auto' separated by a space before the placement will enable auto positioning, e.g: "auto bottom-left". The popup will attempt to position where it fits in the closest scrollable ancestor. Accepts:

* `top` - popup on top, horizontally centered on input element.
* `top-left` - popup on top, left edge aligned with input element left edge.
* `top-right` - popup on top, right edge aligned with input element right edge.
* `bottom` - popup on bottom, horizontally centered on input element.
* `bottom-left` - popup on bottom, left edge aligned with input element left edge.
* `bottom-right` - popup on bottom, right edge aligned with input element right edge.
* `left` - popup on left, vertically centered on input element.
* `left-top` - popup on left, top edge aligned with input element top edge.
* `left-bottom` - popup on left, bottom edge aligned with input element bottom edge.
* `right` - popup on right, vertically centered on input element.
* `right-top` - popup on right, top edge aligned with input element top edge.
* `right-bottom` - popup on right, bottom edge aligned with input element bottom edge.

* `uib-datepicker-popup`
<small class="badge">C</small>
_(Default: `yyyy-MM-dd`, Config: `datepickerConfig`)_ -
Expand Down