From 3b1de8a368dda48be3d8d33bb2106978309c7d19 Mon Sep 17 00:00:00 2001 From: Thomas Roch Date: Tue, 11 Mar 2014 23:53:09 +0000 Subject: [PATCH 1/4] feat(position): add aligning functions --- src/position/position.js | 48 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/position/position.js b/src/position/position.js index 3444c33449..c74948ce46 100644 --- a/src/position/position.js +++ b/src/position/position.js @@ -146,6 +146,54 @@ angular.module('ui.bootstrap.position', []) break; } + return targetElPos; + }, + + /** + * Provides coordinates for aligning horizontally the targetEl + * to the hostEl. Allowed values for positionStr are "left", "right", + * "left-auto", "right-auto" and "center" + */ + alignElements: function (hostEl, targetEl, positionStr, appendToBody) { + + positionStr = positionStr || 'left'; + + var hostElPos, + hostElOffset, + targetElWidth, + targetElPos; + + hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl); + hostElOffset = this.offset(hostEl); + + targetElWidth = targetEl.prop('offsetWidth'); + + var shiftHorizontally = { + left: function () { + return hostElPos.left; + }, + // Like left but prevents target element to overflow on the right + 'left-auto': function () { + var clientWidth = $document[0].documentElement.clientWidth; + return Math.min(hostElPos.left, clientWidth - targetElWidth); + }, + right: function () { + return hostElPos.left + hostElPos.width - targetElWidth; + }, + // Like left but prevents target element to overflow on the left + 'right-auto': function () { + return Math.max(-hostElOffset.left, hostElPos.left + hostElPos.width - targetElWidth); + }, + center: function () { + return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2; + } + }; + + targetElPos = { + top: hostElPos.top + hostElPos.height, + left: shiftHorizontally[positionStr]() + }; + return targetElPos; } }; From 692832e9214ae3f6d0d56215a0f321f9ca6b86c9 Mon Sep 17 00:00:00 2001 From: Thomas Roch Date: Tue, 11 Mar 2014 23:54:28 +0000 Subject: [PATCH 2/4] feat(dropdown): add dropdown menu alignment option --- src/dropdown/dropdown.js | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/dropdown/dropdown.js b/src/dropdown/dropdown.js index c674f44ee0..73ffb11b93 100644 --- a/src/dropdown/dropdown.js +++ b/src/dropdown/dropdown.js @@ -1,4 +1,4 @@ -angular.module('ui.bootstrap.dropdown', []) +angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) .constant('dropdownConfig', { openClass: 'open' @@ -42,7 +42,7 @@ angular.module('ui.bootstrap.dropdown', []) }; }]) -.controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate) { +.controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', '$position', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate, $position) { var self = this, scope = $scope.$new(), // create a child scope so we are not polluting original one openClass = dropdownConfig.openClass, @@ -78,11 +78,21 @@ angular.module('ui.bootstrap.dropdown', []) } }; + scope.positionMenuElement = function() { + if ( self.menuElement ) { + var pos = $position.alignElements(self.toggleElement, self.menuElement, self.menuAlign); + if (angular.isDefined( pos.left )) { + self.menuElement.css('left', pos.left + 'px'); + } + } + }; + scope.$watch('isOpen', function( isOpen ) { $animate[isOpen ? 'addClass' : 'removeClass'](self.$element, openClass); if ( isOpen ) { scope.focusToggleElement(); + scope.positionMenuElement(); dropdownService.open( scope ); } else { dropdownService.close( scope ); @@ -106,11 +116,24 @@ angular.module('ui.bootstrap.dropdown', []) restrict: 'CA', controller: 'DropdownController', link: function(scope, element, attrs, dropdownCtrl) { + dropdownCtrl.init( element ); } }; }) +.directive('dropdownMenu', function() { + return { + restrict: 'CA', + require: '?^dropdown', + link: function(scope, element, attrs, dropdownCtrl) { + + dropdownCtrl.menuElement = element; + dropdownCtrl.menuAlign = attrs.dropdownAlign || 'left'; + } + }; +}) + .directive('dropdownToggle', function() { return { restrict: 'CA', From fd79e05e13e9348b319fd87a56f838e34e406f2c Mon Sep 17 00:00:00 2001 From: Thomas Roch Date: Wed, 12 Mar 2014 22:43:51 +0000 Subject: [PATCH 3/4] feat(dropdown): add alignment option --- src/dropdown/dropdown.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dropdown/dropdown.js b/src/dropdown/dropdown.js index 73ffb11b93..a6920f97e6 100644 --- a/src/dropdown/dropdown.js +++ b/src/dropdown/dropdown.js @@ -79,7 +79,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) }; scope.positionMenuElement = function() { - if ( self.menuElement ) { + if ( self.menuElement && self.menuAlign ) { var pos = $position.alignElements(self.toggleElement, self.menuElement, self.menuAlign); if (angular.isDefined( pos.left )) { self.menuElement.css('left', pos.left + 'px'); @@ -129,7 +129,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) link: function(scope, element, attrs, dropdownCtrl) { dropdownCtrl.menuElement = element; - dropdownCtrl.menuAlign = attrs.dropdownAlign || 'left'; + dropdownCtrl.menuAlign = attrs.dropdownAlign; } }; }) From 6741f1108a073926061509138ec33b1e30eac785 Mon Sep 17 00:00:00 2001 From: Thomas Roch Date: Thu, 13 Mar 2014 23:40:03 +0000 Subject: [PATCH 4/4] feat(dropdown): add alignment option --- src/dropdown/dropdown.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dropdown/dropdown.js b/src/dropdown/dropdown.js index a6920f97e6..9759d6057f 100644 --- a/src/dropdown/dropdown.js +++ b/src/dropdown/dropdown.js @@ -127,6 +127,9 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position']) restrict: 'CA', require: '?^dropdown', link: function(scope, element, attrs, dropdownCtrl) { + if ( !dropdownCtrl ) { + return; + } dropdownCtrl.menuElement = element; dropdownCtrl.menuAlign = attrs.dropdownAlign;