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

Commit

Permalink
feat(datepicker): implement auto position
Browse files Browse the repository at this point in the history
Added popup-placement attribute that implements the auto position
feature that exists in the tooltip directive.  Accepts the same
placement options as the tooltip.

Closes #5444
  • Loading branch information
RobJacobs authored and wesleycho committed Feb 13, 2016
1 parent b835332 commit f9903ba
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 9 deletions.
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

0 comments on commit f9903ba

Please sign in to comment.