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

Commit

Permalink
fix(typeahead): Rebased from master.
Browse files Browse the repository at this point in the history
  • Loading branch information
fernando-sendMail committed Aug 9, 2015
2 parents 89c3e4c + 209312e commit be28195
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 601 deletions.
15 changes: 6 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
### UI Bootstrap - [AngularJS](http://angularjs.org/) directives specific to [Bootstrap](http://getbootstrap.com)
# UI Bootstrap - [AngularJS](http://angularjs.org/) directives specific to [Bootstrap](http://getbootstrap.com)

[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/angular-ui/bootstrap?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://secure.travis-ci.org/angular-ui/bootstrap.svg)](http://travis-ci.org/angular-ui/bootstrap)
Expand All @@ -7,10 +7,10 @@
### Quick links
- [Demo](#demo)
- [Installation](#installation)
- [Bower](#install-with-bower)
- [NuGet](#install-with-nuget)
- [Custom](#custom-build)
- [Manual](#manual-download)
- [Bower](#Install with Bower)
- [NuGet](#Install with NuGet)
- [Custom](#Custom build)
- [Manual](#Manual download)
- [Support](#support)
- [FAQ](#faq)
- [Supported browsers](#supported-browsers)
Expand All @@ -27,15 +27,12 @@ Do you want to see directives in action? Visit http://angular-ui.github.io/boots
# Installation

Installation is easy as UI Bootstrap has minimal dependencies - only the AngularJS and Twitter Bootstrap's CSS are required.
Note: Since version 0.13.0, UI Bootstrap depends on [ngAnimate](https://docs.angularjs.org/api/ngAnimate) for transitions and animations, such as the accordion, carousel, etc. Include `ngAnimate` in the module dependencies for your app in order to enable animation.

#### Install with Bower
```sh
$ bower install angular-bootstrap
$ bower install angular-ui-bootstrap
```

Note: do not install 'angular-ui-bootstrap'. A separate repository - [bootstrap-bower](https://github.com/angular-ui/bootstrap-bower) - hosts the compiled javascript file and bower.json.

#### Install with NuGet
To install AngularJS UI Bootstrap, run the following command in the Package Manager Console

Expand Down
97 changes: 67 additions & 30 deletions src/dropdown/docs/demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,74 @@
<li><a href="#">Separated link</a></li>
</ul>
</div>

<!-- Single button using template-url -->
<div class="btn-group" dropdown>
<button type="button" class="btn btn-primary dropdown-toggle" dropdown-toggle ng-disabled="disabled">
Dropdown using template <span class="caret"></span>

<!-- Single button using append-to-body -->
<div class="btn-group" dropdown dropdown-append-to-body>
<button type="button" class="btn btn-primary dropdown-toggle" dropdown-toggle>
Dropdown on Body <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</div>

<!-- Single button using append-to-body -->
<div class="btn-group" dropdown dropdown-append-to-body>
<button type="button" class="btn btn-primary dropdown-toggle" dropdown-toggle>
Dropdown on Body <span class="caret"></span>
</button>
<ul class="dropdown-menu" template-url="dropdown.html">
<ul class="dropdown-menu" role="menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</div>

<!-- Single button using append-to-body -->
<div class="btn-group" dropdown dropdown-append-to-body>
<button type="button" class="btn btn-primary dropdown-toggle" dropdown-toggle>
Dropdown on Body <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</div>

<!-- Single button using append-to-body -->
<div class="btn-group" dropdown dropdown-append-to-body>
<button type="button" class="btn btn-primary dropdown-toggle" dropdown-toggle>
Dropdown on Body <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</div>

<!-- Single button using append-to-body -->
<div class="btn-group" dropdown dropdown-append-to-body>
<button type="button" class="btn btn-primary dropdown-toggle" dropdown-toggle>
Dropdown on Body <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</div>

Expand All @@ -71,28 +132,4 @@
<button type="button" class="btn btn-warning btn-sm" ng-click="disabled = !disabled">Enable/Disable</button>
</p>

<hr>
<!-- Single button with keyboard nav -->
<div class="btn-group" dropdown keyboard-nav>
<button type="button" class="btn btn-primary dropdown-toggle" dropdown-toggle>
Dropdown with keyboard navigation <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</div>

<script type="text/ng-template" id="dropdown.html">
<ul class="dropdown-menu" role="menu">
<li><a href="#">Action in Template</a></li>
<li><a href="#">Another action in Template</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link in Template</a></li>
</ul>
</script>
</div>
7 changes: 1 addition & 6 deletions src/dropdown/docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,9 @@ There is also the `on-toggle(open)` optional expression fired when dropdown chan
Add `dropdown-append-to-body` to the `dropdown` element to append to the inner `dropdown-menu` to the body.
This is useful when the dropdown button is inside a div with `overflow: hidden`, and the menu would otherwise be hidden.

Add `keyboard-nav` to the `dropdown` element to enable navigation of dropdown list elements with the arrow keys.

By default the dropdown will automatically close if any of its elements is clicked, you can change this behavior by setting the `auto-close` option as follows:

* `always` - (Default) automatically closes the dropdown when any of its elements is clicked.
* `outsideClick` - closes the dropdown automatically only when the user clicks any element outside the dropdown.
* `disabled` - disables the auto close. You can then control the open/close status of the dropdown manually, by using `is-open`. Please notice that the dropdown will still close if the toggle is clicked, the `esc` key is pressed or another dropdown is open. The dropdown will no longer close on `$locationChangeSuccess` events.

Optionally, you may specify a template for the dropdown menu using the `template-url` attribute. This is especially useful when you have multiple similar dropdowns in a repeater and you want to keep your HTML output lean and your number of scopes to a minimum. The template has full access to the scope in which the dropdown lies.
* `disabled` - disables the auto close. You can then control the open/close status of the dropdown manually, by using `is-open`. Please notice that the dropdown will still close if the toggle is clicked, the `esc` key is pressed or another dropdown is open.

Example: `<ul class="dropdown-menu" template-url="custom-dropdown.html"></ul>`.
140 changes: 15 additions & 125 deletions src/dropdown/dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
this.open = function( dropdownScope ) {
if ( !openScope ) {
$document.bind('click', closeDropdown);
$document.bind('keydown', keybindFilter);
$document.bind('keydown', escapeKeyBind);
}

if ( openScope && openScope !== dropdownScope ) {
openScope.isOpen = false;
openScope.isOpen = false;
}

openScope = dropdownScope;
Expand All @@ -24,7 +24,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
if ( openScope === dropdownScope ) {
openScope = null;
$document.unbind('click', closeDropdown);
$document.unbind('keydown', keybindFilter);
$document.unbind('keydown', escapeKeyBind);
}
};

Expand All @@ -37,7 +37,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])

var toggleElement = openScope.getToggleElement();
if ( evt && toggleElement && toggleElement[0].contains(evt.target) ) {
return;
return;
}

var $element = openScope.getElement();
Expand All @@ -52,30 +52,22 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
}
};

var keybindFilter = function( evt ) {
var escapeKeyBind = function( evt ) {
if ( evt.which === 27 ) {
openScope.focusToggleElement();
closeDropdown();
}
else if ( openScope.isKeynavEnabled() && /(38|40)/.test(evt.which) && openScope.isOpen ) {
evt.preventDefault();
evt.stopPropagation();
openScope.focusDropdownEntry(evt.which);
}
};
}])

.controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', '$position', '$document', '$compile', '$templateRequest', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate, $position, $document, $compile, $templateRequest) {
.controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', '$position', '$document', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate, $position, $document) {
var self = this,
scope = $scope.$new(), // create a child scope so we are not polluting original one
templateScope,
openClass = dropdownConfig.openClass,
getIsOpen,
setIsOpen = angular.noop,
toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop,
appendToBody = false,
keynavEnabled =false,
selectedOption = null;
scope = $scope.$new(), // create a child scope so we are not polluting original one
openClass = dropdownConfig.openClass,
getIsOpen,
setIsOpen = angular.noop,
toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop,
appendToBody = false;

this.init = function( element ) {
self.$element = element;
Expand All @@ -90,7 +82,6 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
}

appendToBody = angular.isDefined($attrs.dropdownAppendToBody);
keynavEnabled = angular.isDefined($attrs.keyboardNav);

if ( appendToBody && self.dropdownMenu ) {
$document.find('body').append( self.dropdownMenu );
Expand Down Expand Up @@ -121,40 +112,6 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
return self.$element;
};

scope.isKeynavEnabled = function() {
return keynavEnabled;
};

scope.focusDropdownEntry = function(keyCode) {
var elems = self.dropdownMenu ? //If append to body is used.
(angular.element(self.dropdownMenu).find('a')) :
(angular.element(self.$element).find('ul').eq(0).find('a'));

switch (keyCode) {
case (40): {
if ( !angular.isNumber(self.selectedOption)) {
self.selectedOption = 0;
} else {
self.selectedOption = (self.selectedOption === elems.length -1 ?
self.selectedOption :
self.selectedOption + 1);
}
break;
}
case (38): {
if ( !angular.isNumber(self.selectedOption)) {
return;
} else {
self.selectedOption = (self.selectedOption === 0 ?
0 :
self.selectedOption - 1);
}
break;
}
}
elems[self.selectedOption].focus();
};

scope.focusToggleElement = function() {
if ( self.toggleElement ) {
self.toggleElement[0].focus();
Expand All @@ -174,31 +131,10 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
$animate[isOpen ? 'addClass' : 'removeClass'](self.$element, openClass);

if ( isOpen ) {
if (self.dropdownMenuTemplateUrl) {
$templateRequest(self.dropdownMenuTemplateUrl).then(function(tplContent) {
templateScope = scope.$new();
$compile(tplContent.trim())(templateScope, function(dropdownElement) {
var newEl = dropdownElement;
self.dropdownMenu.replaceWith(newEl);
self.dropdownMenu = newEl;
});
});
}

scope.focusToggleElement();
dropdownService.open( scope );
} else {
if (self.dropdownMenuTemplateUrl) {
if (templateScope) {
templateScope.$destroy();
}
var newEl = angular.element('<ul class="dropdown-menu"></ul>');
self.dropdownMenu.replaceWith(newEl);
self.dropdownMenu = newEl;
}

dropdownService.close( scope );
self.selectedOption = null;
}

setIsOpen($scope, isOpen);
Expand All @@ -208,9 +144,7 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
});

$scope.$on('$locationChangeSuccess', function() {
if (scope.getAutoClose() !== 'disabled') {
scope.isOpen = false;
}
scope.isOpen = false;
});

$scope.$on('$destroy', function() {
Expand All @@ -232,55 +166,11 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
restrict: 'AC',
require: '?^dropdown',
link: function(scope, element, attrs, dropdownCtrl) {
if (!dropdownCtrl) {
if ( !dropdownCtrl ) {
return;
}
var tplUrl = attrs.templateUrl;
if (tplUrl) {
dropdownCtrl.dropdownMenuTemplateUrl = tplUrl;
}
if (!dropdownCtrl.dropdownMenu) {
dropdownCtrl.dropdownMenu = element;
}
}
};
})

.directive('keyboardNav', function() {
return {
restrict: 'A',
require: '?^dropdown',
link: function (scope, element, attrs, dropdownCtrl) {

element.bind('keydown', function(e) {

if ( /(38|40)/.test(e.which)) {

e.preventDefault();
e.stopPropagation();

var elems = angular.element(element).find('a');

switch (e.keyCode) {
case (40): { // Down
if ( !angular.isNumber(dropdownCtrl.selectedOption)) {
dropdownCtrl.selectedOption = 0;
} else {
dropdownCtrl.selectedOption = (dropdownCtrl.selectedOption === elems.length -1 ? dropdownCtrl.selectedOption : dropdownCtrl.selectedOption+1);
}

}
break;
case (38): { // Up
dropdownCtrl.selectedOption = (dropdownCtrl.selectedOption === 0 ? 0 : dropdownCtrl.selectedOption-1);
}
break;
}
elems[dropdownCtrl.selectedOption].focus();
}
});
dropdownCtrl.dropdownMenu = element;
}

};
})

Expand Down
Loading

0 comments on commit be28195

Please sign in to comment.