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

Commit

Permalink
feat(position): implement auto positioning
Browse files Browse the repository at this point in the history
Implementing the ability to auto position elements
in the position service - positionElements function.

Closes 4899
  • Loading branch information
RobJacobs committed Nov 23, 2015
1 parent 526e6de commit d265113
Show file tree
Hide file tree
Showing 12 changed files with 1,161 additions and 203 deletions.
11 changes: 6 additions & 5 deletions src/popover/docs/demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ <h4>Dynamic</h4>
</script>
<hr />
<h4>Positional</h4>
<button popover-placement="top" uib-popover="On the Top!" type="button" class="btn btn-default">Top</button>
<button popover-placement="left" uib-popover="On the Left!" type="button" class="btn btn-default">Left</button>
<button popover-placement="right" uib-popover="On the Right!" type="button" class="btn btn-default">Right</button>
<button popover-placement="bottom" uib-popover="On the Bottom!" type="button" class="btn btn-default">Bottom</button>

<div class="form-group">
<label>Popover placement</label>
<select class="form-control" ng-model="placement.selected" ng-options="o as o for o in placement.options"></select>
</div>
<button popover-placement="{{placement.selected}}" uib-popover="On the {{placement.selected}}" type="button" class="btn btn-default">Popover {{placement.selected}}</button>

<hr />
<h4>Triggers</h4>
<p>
Expand Down
18 changes: 18 additions & 0 deletions src/popover/docs/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,22 @@ angular.module('ui.bootstrap.demo').controller('PopoverDemoCtrl', function ($sco
templateUrl: 'myPopoverTemplate.html',
title: 'Title'
};

$scope.placement = {
options: [
'top',
'top-left',
'top-right',
'bottom',
'bottom-left',
'bottom-right',
'left',
'left-top',
'left-bottom',
'right',
'right-top',
'right-bottom'
],
selected: 'top'
};
});
18 changes: 16 additions & 2 deletions src/popover/docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,22 @@ The popover directives provides several optional attributes to control how it
will display:

- `popover-title`: A string to display as a fancy title.
- `popover-placement`: Where to place it? Defaults to "top", but also accepts
"bottom", "left", "right".
- `popover-placement`: Where to place it? Defaults to "top". Passing in 'auto' seperated by a space before the placement will
enable auto positioning, e.g: "auto bottom-left". The popover will attempt to position where it fits in
the closest scrollable ancestor. Accepts:

- "top" - popover on top, horizontally centered on host element.
- "top-left" - popover on top, left edge aligned with host element left edge.
- "top-right" - popover on top, right edge aligned with host element right edge.
- "bottom" - popover on bottom, horizontally centered on host element.
- "bottom-left" - popover on bottom, left edge aligned with host element left edge.
- "bottom-right" - popover on bottom, right edge aligned with host element right edge.
- "left" - popover on left, vertically centered on host element.
- "left-top" - popover on left, top edge aligned with host element top edge.
- "left-bottom" - popover on left, bottom edge aligned with host element bottom edge.
- "right" - popover on right, vertically centered on host element.
- "right-top" - popover on right, top edge aligned with host element top edge.
- "right-bottom" - popover on right, bottom edge aligned with host element bottom edge.
- `popover-animation`: Should it fade in and out? Defaults to "true".
- `popover-popup-delay`: For how long should the user have to have the mouse
over the element before the popover shows (in milliseconds)? Defaults to 0.
Expand Down
34 changes: 34 additions & 0 deletions src/position/docs/demo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<div ng-controller="PositionDemoCtrl">
<h4>$uibPosition service</h4>
<div id="posdemoparent" ng-style="{'overflow': (parentScrollable && 'scroll'), 'position': (parentRelative && 'relative')}" style="border: 1px solid #ccc; padding: 15px;">
<div class="checkbox">
<label>
<input type="checkbox" ng-model="parentScrollable"> Parent scrollable
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="parentRelative"> Parent relative
</label>
</div>
<button id="posdemobtn" class="btn btn-default" ng-click="getValues()">Get values</button>

<div id="posdemodiv" style="width: 100px; height: 100px; margin: 15px 0; padding: 10px; background-color: #f8f8f8; border: 1px solid #ccc;">
Demo element
</div>
</div>
<br />
offsetParent: {{elemVals.offsetParent}}
<br />
scrollParent: {{elemVals.scrollParent}}
<br />
scrollbarWidth: {{scrollbarWidth}}
<br />
position: {{elemVals.position}}
<br />
offset: {{elemVals.offset}}
<br />
viewportOffset: {{elemVals.viewportOffset}}
<br />
positionElements: {{elemVals.positionElements}}
</div>
27 changes: 27 additions & 0 deletions src/position/docs/demo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
angular.module('ui.bootstrap.demo').controller('PositionDemoCtrl', function ($scope, $window, $uibPosition) {

$scope.elemVals = {};
$scope.parentScrollable = true;
$scope.parentRelative = true;

$scope.getValues = function() {
var divEl = $window.document.querySelector('#posdemodiv');
var btnEl = $window.document.querySelector('#posdemobtn');

var offsetParent = $uibPosition.offsetParent(divEl);
$scope.elemVals.offsetParent = 'type: ' + offsetParent.tagName + ', id: ' + offsetParent.id;

var scrollParent = $uibPosition.scrollParent(divEl);
$scope.elemVals.scrollParent = 'type: ' + scrollParent.tagName + ', id: ' + scrollParent.id;

$scope.scrollbarWidth = $uibPosition.scrollbarWidth();

$scope.elemVals.position = $uibPosition.position(divEl);

$scope.elemVals.offset = $uibPosition.offset(divEl);

$scope.elemVals.viewportOffset = $uibPosition.viewportOffset(divEl);

$scope.elemVals.positionElements = $uibPosition.positionElements(btnEl, divEl, 'auto bottom-left');
};
});
167 changes: 167 additions & 0 deletions src/position/docs/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
The `$uibPosition` service provides a set of DOM utilities used internally to absolute-position an element in relation to another element (tooltips, popovers, typeaheads etc...).

### getRawNode(element)
Takes a jQuery/jqLite element and converts it to a raw DOM element.

##### parameters

* `element` _(Type 'object')_ - The element to convert.

##### returns

_(Type 'element')_ - A raw DOM element.

### parseSyle(element)
Parses a numeric style value to a number. Strips units and will return 0 for invalid (NaN) numbers.

##### parameters

* `value` _(Type 'string')_ - The style value to parse.

##### returns

_(Type 'number')_ - The numeric value of the style property.

### offsetParent(element)
Gets the closest positioned ancestor.

##### parameters

* `element` _(Type 'element')_ - The element to get the offset parent for.

##### returns

_(Type 'element')_ - The closest positioned ancestor.

### scrollbarWidth()
Calculates the browser scrollbar width and caches the result for future calls. Concept from the TWBS measureScrollbar() function in [modal.js](https://github.com/twbs/bootstrap/blob/master/js/modal.js).

##### returns

_(Type 'number')_ - The width of the browser scrollbar.

### scrollParent(element, includeHidden)
Gets the closest scrollable ancestor. Concept from the jQueryUI [scrollParent.js](https://github.com/jquery/jquery-ui/blob/master/ui/scroll-parent.js).

##### parameters

* `element` _(Type 'element')_ - The element to get the closest scrollable ancestor for.

* `includeHidden` _(Type 'boolean', optional - default is false)_ - Should scroll style of 'hidden' be considered.

##### returns

_(Type 'element')_ - The closest scrollable ancestor.

### position(element, includeMargins)
A read-only equivalent of jQuery's [position](http://api.jquery.com/position/) function, distance to closest positioned ancestor. Does not account for margins by default like jQuery's position.

##### parameters

* `element` _(Type 'element')_ - The element to get the position for.

* `includeMagins` _(Type 'boolean', optional - default is false)_ - Should margins be accounted for.

##### returns

_(Type 'object')_ - An object with the following properties:

* width: _(Type 'number')_ The width of the element.
* height: _(Type 'number')_ The height of the element.
* top: _(Type 'number')_ Distance to top edge of offset parent.
* left: _(Type 'number')_ Distance to left edge of offset parent.

### offset(element)
A read-only equivalent of jQuery's [offset](http://api.jquery.com/offset/) function, distance to viewport.

##### parameters

* `element` _(Type 'element')_ - The element to get the offset for.

##### returns

_(Type 'object')_ - An object with the following properties:

* width: _(Type 'number')_ The width of the element.
* height: _(Type 'number')_ The height of the element.
* top: _(Type 'number')_ Distance to top edge of the viewport.
* left: _(Type 'number')_ Distance to left edge of the viewport.

### viewportOffset(element, useDocument, includePadding)
Gets the elements available space relative to the closest scrollable ancestor. Accounts for padding, border, and scrollbar width.
Right and bottom dimensions represent the distance to the respective edge of the viewport element, not the top and left edge.
If the element edge extends beyond the viewport, a negative value will be reported.

##### parameters

* `element` _(Type 'element')_ - The element to get the viewport offset for.
* `useDocument` _(Type 'boolean', optional - default is false)_ - Should the viewport be the document element instead of the first scrollable element.
* `includePadding` _(Type 'boolean', optional - default is true)_ - Should the padding on the viewport element be accounted for, default is true.

##### returns

_(Type 'object')_ - An object with the following properties:

* top: _(Type 'number')_ Distance to top content edge of the viewport.
* bottom: _(Type 'number')_ Distance to bottom content edge of the viewport.
* left: _(Type 'number')_ Distance to left content edge of the viewport.
* right: _(Type 'number')_ Distance to right content edge of the viewport.

### parsePlacement(placement)
Gets an array of placement values parsed from a placement string. Along with the 'auto' indicator, supported placement strings are:

* top: element on top, horizontally centered on host element.
* top-left: element on top, left edge aligned with host element left edge.
* top-right: element on top, right edge aligned with host element right edge.
* bottom: element on bottom, horizontally centered on host element.
* bottom-left: element on bottom, left edge aligned with host element left edge.
* bottom-right: element on bottom, right edge aligned with host element right edge.
* left: element on left, vertically centered on host element.
* left-top: element on left, top edge aligned with host element top edge.
* left-bottom: element on left, bottom edge aligned with host element bottom edge.
* right: element on right, vertically centered on host element.
* right-top: element on right, top edge aligned with host element top edge.
* right-bottom: element on right, bottom edge aligned with host element bottom edge.

A placement string with an 'auto' indicator is expected to be space separated from the placement, i.e: 'auto bottom-left'.
If the primary and secondary placement values do not match 'top, bottom, left, right' then 'top' will be the primary placement and
'center' will be the secondary placement. If 'auto' is passed, true will be returned as the 3rd value of the array.

##### parameters

* `placement` _(Type 'string', e.g. 'auto top-left')_ - The placement string to parse.

##### returns

_(Type 'array')_ - An array with the following values:

* [0]: _(Type 'string')_ - The primary placement.
* [1]: _(Type 'string')_ - The secondary placement.
* [2]: _(Type 'boolean')_ - Is auto place enabled.

### positionElements(hostElement, targetElement, placement, appendToBody)
Gets gets coordinates for an element to be positioned relative to another element.

##### parameters

* `hostElement` _(Type 'element')_ - The element to position against.
* `targetElement` _(Type 'element')_ - The element to position.
* `placement` _(Type 'string', optional - default is top)_ - The placement for the target element. See the parsePlacement() function for
available options. If 'auto' placement is used, the viewportOffset() function is used to decide where the targetElement will fit.
* `appendToBody` _(Type 'boolean', optional - default is false)_ - Should the coordinates be cacluated from the body element.

##### returns

_(Type 'object')_ - An object with the following properties:

* top: _(Type 'number')_ The targetElement top value.
* left: _(Type 'number')_ The targetElement left value.
* right: _(Type 'number')_ The resolved placement with 'auto' removed.

### positionArrow(element, placement)
Positions the tooltip and popover arrow elements when using placement options beyond the standard top, left, bottom, or right.

##### parameters

* `element` _(Type 'element')_ - The element to position the arrow element for.
* `placement` _(Type 'string')_ - The placement for the element.
Loading

0 comments on commit d265113

Please sign in to comment.