Compare commits
73 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5173779f84 | |||
| 1616e9720d | |||
| b77f02cdce | |||
| 39d9b9886d | |||
| 2d831bcc2a | |||
| d846e2d788 | |||
| 409b7aa3b3 | |||
| ed3400bb68 | |||
| 1cbd73d227 | |||
| 433e536e6b | |||
| 1ec099767f | |||
| 4e0e34f47a | |||
| 7457fb0e63 | |||
| 23ef372a17 | |||
| 164811ab35 | |||
| 1de58a3e5d | |||
| 7e320e0e92 | |||
| d6fe9c7e7a | |||
| 75188211aa | |||
| 4e68778561 | |||
| a68cc20dd4 | |||
| ba113a050e | |||
| 0d8cec6e4f | |||
| a47bcedad4 | |||
| 387c6e7bbc | |||
| 9b24e1dfed | |||
| 5f4eedd0e7 | |||
| 96d52ce150 | |||
| 55cf26bf28 | |||
| 5fdcbd6b90 | |||
| e92fb7fa7c | |||
| 1a870a3bb1 | |||
| 6038403179 | |||
| fb38d0db2e | |||
| 5046bd4e56 | |||
| 2458c2863d | |||
| 3819bbe8fa | |||
| e2016fd2eb | |||
| 34a1443a85 | |||
| 35ced04445 | |||
| 90fa2f682a | |||
| 4fef0377bb | |||
| b0466d9e6e | |||
| 4b912228be | |||
| 9a606dca7c | |||
| 6d5b84a0ba | |||
| cce00970f1 | |||
| 23b91d951e | |||
| 053035234c | |||
| a075824087 | |||
| 13c14af9a2 | |||
| 280ddaf47e | |||
| dc85f67b2d | |||
| 2ffb86f201 | |||
| aec5304ef5 | |||
| eb02778297 | |||
| 26d399557e | |||
| 9436b9e7bd | |||
| b2984b0416 | |||
| 5188463f69 | |||
| a417ec2ab9 | |||
| d923df9100 | |||
| dd09148893 | |||
| 5741be9d5b | |||
| 1611248daa | |||
| e51373d84b | |||
| 4c40d9db7f | |||
| f88067a04f | |||
| 0137179ee6 | |||
| 2b48259a35 | |||
| 241fea8355 | |||
| f0e661c7c0 | |||
| 78db2cefe7 |
@@ -1,3 +1,29 @@
|
||||
<a name="1.3.3"></a>
|
||||
## [1.3.3](https://github.com/angular-ui/bootstrap/compare/1.3.2...v1.3.3) (2016-05-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datepicker:** add intermediary valid date check([a417ec2](https://github.com/angular-ui/bootstrap/commit/a417ec2)), closes [#5872](https://github.com/angular-ui/bootstrap/issues/5872) [#5865](https://github.com/angular-ui/bootstrap/issues/5865)
|
||||
* **datepickerPopup:** convert numbers to date before parsing([5188463](https://github.com/angular-ui/bootstrap/commit/5188463)), closes [#5873](https://github.com/angular-ui/bootstrap/issues/5873) [#5871](https://github.com/angular-ui/bootstrap/issues/5871)
|
||||
* **dropdown:** align position with vertical scrollbar([2b48259](https://github.com/angular-ui/bootstrap/commit/2b48259)), closes [#5830](https://github.com/angular-ui/bootstrap/issues/5830) [#4317](https://github.com/angular-ui/bootstrap/issues/4317)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **accordion:** add alternative attribute support([4c40d9d](https://github.com/angular-ui/bootstrap/commit/4c40d9d)), closes [#5834](https://github.com/angular-ui/bootstrap/issues/5834) [#5839](https://github.com/angular-ui/bootstrap/issues/5839)
|
||||
* **modal:** add resolve values to template([dd09148](https://github.com/angular-ui/bootstrap/commit/dd09148)), closes [#5808](https://github.com/angular-ui/bootstrap/issues/5808) [#5857](https://github.com/angular-ui/bootstrap/issues/5857)
|
||||
* **tab:** allow strings for index([26d3995](https://github.com/angular-ui/bootstrap/commit/26d3995)), closes [#5713](https://github.com/angular-ui/bootstrap/issues/5713) [#5827](https://github.com/angular-ui/bootstrap/issues/5827)
|
||||
* **tabs:** pass the selected index to onDeselect([241fea8](https://github.com/angular-ui/bootstrap/commit/241fea8)), closes [#5820](https://github.com/angular-ui/bootstrap/issues/5820) [#5821](https://github.com/angular-ui/bootstrap/issues/5821)
|
||||
* **typeahead:** Add support for `should-select`([2ffb86f](https://github.com/angular-ui/bootstrap/commit/2ffb86f)), closes [#5671](https://github.com/angular-ui/bootstrap/issues/5671) [#5794](https://github.com/angular-ui/bootstrap/issues/5794)
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* modal: Since this adds support for $resolve being exposed on $scope, it could potentially overwrite any pre-existing usage of it - this is an unlikely scenario, but marked as a breaking change in case this key is being used
|
||||
|
||||
|
||||
|
||||
<a name="1.3.2"></a>
|
||||
## [1.3.2](https://github.com/angular-ui/bootstrap/compare/1.3.1...v1.3.2) (2016-04-14)
|
||||
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ module.exports = function(grunt) {
|
||||
grunt.util.linefeed = '\n';
|
||||
|
||||
grunt.initConfig({
|
||||
ngversion: '1.5.3',
|
||||
ngversion: '1.5.5',
|
||||
bsversion: '3.3.6',
|
||||
modules: [],//to be filled in by build task
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
- [NuGet](#install-with-nuget)
|
||||
- [Custom](#custom-build)
|
||||
- [Manual](#manual-download)
|
||||
- [Webpack](#webpack)
|
||||
- [Webpack / JSPM](#webpack--jspm)
|
||||
- [Support](#support)
|
||||
- [FAQ](#faq)
|
||||
- [Code of Conduct](#code-of-conduct)
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
# Demo
|
||||
|
||||
Do you want to see directives in action? Visit http://angular-ui.github.io/bootstrap/!
|
||||
Do you want to see directives in action? Visit https://angular-ui.github.io/bootstrap/!
|
||||
|
||||
# Angular 2
|
||||
|
||||
@@ -73,7 +73,7 @@ PM> Install-Package Angular.UI.Bootstrap
|
||||
|
||||
#### Custom build
|
||||
|
||||
Head over to http://angular-ui.github.io/bootstrap/ and hit the *Custom build* button to create your own custom UI Bootstrap build, just the way you like it.
|
||||
Head over to https://angular-ui.github.io/bootstrap/ and hit the *Custom build* button to create your own custom UI Bootstrap build, just the way you like it.
|
||||
|
||||
#### Manual download
|
||||
|
||||
@@ -118,6 +118,7 @@ If you would prefer not to load your css through your JavaScript file loader/bun
|
||||
* datepicker
|
||||
* datepickerPopup
|
||||
* dropdown
|
||||
* modal
|
||||
* popover
|
||||
* position
|
||||
* timepicker
|
||||
@@ -133,6 +134,10 @@ import typeahead from 'angular-ui-bootstrap/src/typeahead/index-nocss.js';
|
||||
angular.module('myModule', [accordion, datepicker]);
|
||||
```
|
||||
|
||||
# Versioning
|
||||
|
||||
Pre-2.0.0 does not follow a particular versioning system. 2.0.0 and onwards follows [semantic versioning](http://semver.org/). All release changes can be viewed on our [changelog](CHANGELOG.md).
|
||||
|
||||
# Support
|
||||
|
||||
## FAQ
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"author": "https://github.com/angular-ui/bootstrap/graphs/contributors",
|
||||
"name": "angular-ui-bootstrap",
|
||||
"version": "1.3.2",
|
||||
"version": "2.0.0",
|
||||
"homepage": "http://angular-ui.github.io/bootstrap/",
|
||||
"dependencies": {},
|
||||
"directories": {
|
||||
@@ -22,9 +22,9 @@
|
||||
"url": "https://github.com/angular-ui/bootstrap.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"angular": "1.5.3",
|
||||
"angular-mocks": "1.5.3",
|
||||
"angular-sanitize": "1.5.3",
|
||||
"angular": "1.5.5",
|
||||
"angular-mocks": "1.5.5",
|
||||
"angular-sanitize": "1.5.5",
|
||||
"grunt": "^0.4.5",
|
||||
"grunt-contrib-concat": "^1.0.0",
|
||||
"grunt-contrib-copy": "^1.0.0",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])
|
||||
angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse', 'ui.bootstrap.tabindex'])
|
||||
|
||||
.constant('uibAccordionConfig', {
|
||||
closeOthers: true
|
||||
@@ -58,7 +58,7 @@ angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])
|
||||
return {
|
||||
require: '^uibAccordion', // We need this directive to be inside an accordion
|
||||
transclude: true, // It transcludes the contents of the directive into the template
|
||||
replace: true, // The element containing the directive will be replaced with the template
|
||||
restrict: 'A',
|
||||
templateUrl: function(element, attrs) {
|
||||
return attrs.templateUrl || 'uib/template/accordion/accordion-group.html';
|
||||
},
|
||||
@@ -74,6 +74,7 @@ angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])
|
||||
};
|
||||
},
|
||||
link: function(scope, element, attrs, accordionCtrl) {
|
||||
element.addClass('panel');
|
||||
accordionCtrl.addGroup(scope);
|
||||
|
||||
scope.openClass = attrs.openClass || 'panel-open';
|
||||
@@ -124,11 +125,21 @@ angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])
|
||||
link: function(scope, element, attrs, controller) {
|
||||
scope.$watch(function() { return controller[attrs.uibAccordionTransclude]; }, function(heading) {
|
||||
if (heading) {
|
||||
var elem = angular.element(element[0].querySelector('[uib-accordion-header]'));
|
||||
var elem = angular.element(element[0].querySelector(getHeaderSelectors()));
|
||||
elem.html('');
|
||||
elem.append(heading);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function getHeaderSelectors() {
|
||||
return 'uib-accordion-header,' +
|
||||
'data-uib-accordion-header,' +
|
||||
'x-uib-accordion-header,' +
|
||||
'uib\\:accordion-header,' +
|
||||
'[uib-accordion-header],' +
|
||||
'[data-uib-accordion-header],' +
|
||||
'[x-uib-accordion-header]';
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
<div ng-controller="AccordionDemoCtrl">
|
||||
<script type="text/ng-template" id="group-template.html">
|
||||
<div class="panel {{panelClass || 'panel-default'}}">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title" style="color:#fa39c3">
|
||||
<a href tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading"><span
|
||||
ng-class="{'text-muted': isDisabled}">{{heading}}</span></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="panel-collapse collapse" uib-collapse="!isOpen">
|
||||
<div class="panel-body" style="text-align: right" ng-transclude></div>
|
||||
</div>
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title" style="color:#fa39c3">
|
||||
<a href tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading">
|
||||
<span uib-accordion-header ng-class="{'text-muted': isDisabled}">
|
||||
{{heading}}
|
||||
</span>
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="panel-collapse collapse" uib-collapse="!isOpen">
|
||||
<div class="panel-body" style="text-align: right" ng-transclude></div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
@@ -25,29 +26,35 @@
|
||||
</label>
|
||||
</div>
|
||||
<uib-accordion close-others="oneAtATime">
|
||||
<uib-accordion-group heading="Static Header, initially expanded" is-open="status.isFirstOpen" is-disabled="status.isFirstDisabled">
|
||||
<div uib-accordion-group class="panel-default" heading="Static Header, initially expanded" is-open="status.isFirstOpen" is-disabled="status.isFirstDisabled">
|
||||
This content is straight in the template.
|
||||
</uib-accordion-group>
|
||||
<uib-accordion-group heading="{{group.title}}" ng-repeat="group in groups">
|
||||
</div>
|
||||
<div uib-accordion-group class="panel-default" heading="{{group.title}}" ng-repeat="group in groups">
|
||||
{{group.content}}
|
||||
</uib-accordion-group>
|
||||
<uib-accordion-group heading="Dynamic Body Content">
|
||||
</div>
|
||||
<div uib-accordion-group class="panel-default" heading="Dynamic Body Content">
|
||||
<p>The body of the uib-accordion group grows to fit the contents</p>
|
||||
<button type="button" class="btn btn-default btn-sm" ng-click="addItem()">Add Item</button>
|
||||
<div ng-repeat="item in items">{{item}}</div>
|
||||
</uib-accordion-group>
|
||||
<uib-accordion-group heading="Custom template" template-url="group-template.html">
|
||||
</div>
|
||||
<div uib-accordion-group class="panel-default" heading="Custom template" template-url="group-template.html">
|
||||
Hello
|
||||
</uib-accordion-group>
|
||||
<uib-accordion-group heading="Delete account" panel-class="panel-danger">
|
||||
</div>
|
||||
<div uib-accordion-group class="panel-default" is-open="status.isCustomHeaderOpen" template-url="group-template.html">
|
||||
<uib-accordion-heading>
|
||||
Custom template with custom header template <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': status.isCustomHeaderOpen, 'glyphicon-chevron-right': !status.isCustomHeaderOpen}"></i>
|
||||
</uib-accordion-heading>
|
||||
World
|
||||
</div>
|
||||
<div uib-accordion-group class="panel-danger" heading="Delete account">
|
||||
<p>Please, to delete your account, click the button below</p>
|
||||
<button class="btn btn-danger">Delete</button>
|
||||
</uib-accordion-group>
|
||||
<uib-accordion-group is-open="status.open">
|
||||
</div>
|
||||
<div uib-accordion-group class="panel-default" is-open="status.open">
|
||||
<uib-accordion-heading>
|
||||
I can have markup, too! <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': status.open, 'glyphicon-chevron-right': !status.open}"></i>
|
||||
</uib-accordion-heading>
|
||||
This is just some content to illustrate fancy headings.
|
||||
</uib-accordion-group>
|
||||
</div>
|
||||
</uib-accordion>
|
||||
</div>
|
||||
|
||||
@@ -20,6 +20,7 @@ angular.module('ui.bootstrap.demo').controller('AccordionDemoCtrl', function ($s
|
||||
};
|
||||
|
||||
$scope.status = {
|
||||
isCustomHeaderOpen: false,
|
||||
isFirstOpen: true,
|
||||
isFirstDisabled: false
|
||||
};
|
||||
|
||||
@@ -32,11 +32,6 @@ The body of each accordion group is transcluded into the body of the collapsible
|
||||
_(Default: `false`)_ -
|
||||
Whether accordion group is open or closed.
|
||||
|
||||
* `panel-class`
|
||||
<i class="glyphicon glyphicon-eye-open"></i>
|
||||
_(Default: `panel-default`)_ -
|
||||
Add ability to use Bootstrap's contextual panel classes (panel-primary, panel-success, panel-info, etc...) or your own. This must be a string.
|
||||
|
||||
* `template-url`
|
||||
_(Default: `uib/template/accordion/accordion-group.html`)_ -
|
||||
Add the ability to override the template used on the component.
|
||||
@@ -49,6 +44,6 @@ If you're using a custom template for the `uib-accordion-group`, you'll need to
|
||||
|
||||
### Known issues
|
||||
|
||||
To use clickable elements within the accordion, you have override the accordion-group template to use div elements instead of anchor elements, and add `cursor: pointer` in your CSS. This is due to browsers interpreting anchor elements as the target of any click event, which triggers routing when certain elements such as buttons are nested inside the anchor element.
|
||||
To use clickable elements within the accordion, you have to override the accordion-group template to use div elements instead of anchor elements, and add `cursor: pointer` in your CSS. This is due to browsers interpreting anchor elements as the target of any click event, which triggers routing when certain elements such as buttons are nested inside the anchor element.
|
||||
|
||||
If custom classes on the accordion-group element are desired, one needs to either modify the template to remove the `ng-class` usage in the accordion-group template and use ng-class on the accordion-group element (not recommended), or use an interpolated expression in the class attribute, i.e. `<uib-accordion-group class="{{customClass()}}"></uib-accordion-group>`.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
require('../collapse');
|
||||
require('../tabindex');
|
||||
require('../../template/accordion/accordion-group.html.js');
|
||||
require('../../template/accordion/accordion.html.js');
|
||||
require('./accordion');
|
||||
|
||||
@@ -176,12 +176,12 @@ describe('uib-accordion', function() {
|
||||
|
||||
var tpl =
|
||||
'<uib-accordion>' +
|
||||
'<uib-accordion-group heading="title 1" template-url="foo/bar.html"></uib-accordion-group>' +
|
||||
'<div uib-accordion-group heading="title 1" template-url="foo/bar.html"></div>' +
|
||||
'</uib-accordion>';
|
||||
|
||||
element = $compile(tpl)(scope);
|
||||
scope.$digest();
|
||||
expect(element.find('[template-url]').html()).toBe('baz');
|
||||
expect(element.find('[template-url]').html()).toBe('<div>baz</div>');
|
||||
}));
|
||||
|
||||
describe('with static panels', function() {
|
||||
@@ -189,8 +189,8 @@ describe('uib-accordion', function() {
|
||||
spyOn(Math, 'random').and.returnValue(0.1);
|
||||
var tpl =
|
||||
'<uib-accordion>' +
|
||||
'<uib-accordion-group heading="title 1">Content 1</uib-accordion-group>' +
|
||||
'<uib-accordion-group heading="title 2">Content 2</uib-accordion-group>' +
|
||||
'<div uib-accordion-group heading="title 1">Content 1</div>' +
|
||||
'<div uib-accordion-group heading="title 2">Content 2</div>' +
|
||||
'</uib-accordion>';
|
||||
element = angular.element(tpl);
|
||||
$compile(element)(scope);
|
||||
@@ -288,8 +288,8 @@ describe('uib-accordion', function() {
|
||||
beforeEach(function() {
|
||||
var tpl =
|
||||
'<uib-accordion>' +
|
||||
'<uib-accordion-group heading="title 1" open-class="custom-open-class">Content 1</uib-accordion-group>' +
|
||||
'<uib-accordion-group heading="title 2" open-class="custom-open-class">Content 2</uib-accordion-group>' +
|
||||
'<div uib-accordion-group heading="title 1" open-class="custom-open-class">Content 1</div>' +
|
||||
'<div uib-accordion-group heading="title 2" open-class="custom-open-class">Content 2</div>' +
|
||||
'</uib-accordion>';
|
||||
element = angular.element(tpl);
|
||||
$compile(element)(scope);
|
||||
@@ -318,7 +318,7 @@ describe('uib-accordion', function() {
|
||||
beforeEach(function() {
|
||||
var tpl =
|
||||
'<uib-accordion>' +
|
||||
'<uib-accordion-group ng-repeat="group in groups" heading="{{group.name}}">{{group.content}}</uib-accordion-group>' +
|
||||
'<div uib-accordion-group ng-repeat="group in groups" heading="{{group.name}}">{{group.content}}</div>' +
|
||||
'</uib-accordion>';
|
||||
element = angular.element(tpl);
|
||||
model = [
|
||||
@@ -363,8 +363,8 @@ describe('uib-accordion', function() {
|
||||
beforeEach(function() {
|
||||
var tpl =
|
||||
'<uib-accordion>' +
|
||||
'<uib-accordion-group heading="title 1" is-open="open.first">Content 1</uib-accordion-group>' +
|
||||
'<uib-accordion-group heading="title 2" is-open="open.second">Content 2</uib-accordion-group>' +
|
||||
'<div uib-accordion-group heading="title 1" is-open="open.first">Content 1</div>' +
|
||||
'<div uib-accordion-group heading="title 2" is-open="open.second">Content 2</div>' +
|
||||
'</uib-accordion>';
|
||||
element = angular.element(tpl);
|
||||
scope.open = { first: false, second: true };
|
||||
@@ -393,8 +393,8 @@ describe('uib-accordion', function() {
|
||||
beforeEach(function() {
|
||||
var tpl =
|
||||
'<uib-accordion>' +
|
||||
'<uib-accordion-group heading="title 1" is-open="open1"><div ng-repeat="item in items">{{item}}</div></uib-accordion-group>' +
|
||||
'<uib-accordion-group heading="title 2" is-open="open2">Static content</uib-accordion-group>' +
|
||||
'<div uib-accordion-group heading="title 1" is-open="open1"><div ng-repeat="item in items">{{item}}</div></div>' +
|
||||
'<div uib-accordion-group heading="title 2" is-open="open2">Static content</div>' +
|
||||
'</uib-accordion>';
|
||||
element = angular.element(tpl);
|
||||
scope.items = ['Item 1', 'Item 2', 'Item 3'];
|
||||
@@ -421,7 +421,7 @@ describe('uib-accordion', function() {
|
||||
beforeEach(function() {
|
||||
var tpl =
|
||||
'<uib-accordion>' +
|
||||
'<uib-accordion-group ng-repeat="group in groups" heading="{{group.name}}" is-open="group.open">{{group.content}}</uib-accordion-group>' +
|
||||
'<div uib-accordion-group ng-repeat="group in groups" heading="{{group.name}}" is-open="group.open">{{group.content}}</div>' +
|
||||
'</uib-accordion>';
|
||||
element = angular.element(tpl);
|
||||
scope.groups = [
|
||||
@@ -456,7 +456,7 @@ describe('uib-accordion', function() {
|
||||
beforeEach(function() {
|
||||
var tpl =
|
||||
'<uib-accordion>' +
|
||||
'<uib-accordion-group ng-repeat="group in groups" heading="{{group.name}}" is-open="group.open" class="testClass">{{group.content}}</uib-accordion-group>' +
|
||||
'<div uib-accordion-group ng-repeat="group in groups" heading="{{group.name}}" is-open="group.open" class="testClass">{{group.content}}</div>' +
|
||||
'</uib-accordion>';
|
||||
element = angular.element(tpl);
|
||||
scope.groups = [
|
||||
@@ -480,7 +480,7 @@ describe('uib-accordion', function() {
|
||||
beforeEach(function() {
|
||||
var tpl =
|
||||
'<uib-accordion>' +
|
||||
'<uib-accordion-group heading="title 1" is-disabled="disabled">Content 1</uib-accordion-group>' +
|
||||
'<div uib-accordion-group heading="title 1" is-disabled="disabled">Content 1</div>' +
|
||||
'</uib-accordion>';
|
||||
element = angular.element(tpl);
|
||||
scope.disabled = true;
|
||||
@@ -519,10 +519,10 @@ describe('uib-accordion', function() {
|
||||
function isDisabledStyleCheck() {
|
||||
var tpl =
|
||||
'<uib-accordion ng-init="a = [1,2,3]">' +
|
||||
'<uib-accordion-group heading="I get overridden" is-disabled="true">' +
|
||||
'<div uib-accordion-group heading="I get overridden" is-disabled="true">' +
|
||||
'<uib-accordion-heading>Heading Element <span ng-repeat="x in a">{{x}}</span> </uib-accordion-heading>' +
|
||||
'Body' +
|
||||
'</uib-accordion-group>' +
|
||||
'</div>' +
|
||||
'</uib-accordion>';
|
||||
scope.disabled = true;
|
||||
element = $compile(tpl)(scope);
|
||||
@@ -536,10 +536,10 @@ describe('uib-accordion', function() {
|
||||
beforeEach(function() {
|
||||
var tpl =
|
||||
'<uib-accordion ng-init="a = [1,2,3]">' +
|
||||
'<uib-accordion-group heading="I get overridden">' +
|
||||
'<div uib-accordion-group heading="I get overridden">' +
|
||||
'<uib-accordion-heading>Heading Element <span ng-repeat="x in a">{{x}}</span> </uib-accordion-heading>' +
|
||||
'Body' +
|
||||
'</uib-accordion-group>' +
|
||||
'</div>' +
|
||||
'</uib-accordion>';
|
||||
element = $compile(tpl)(scope);
|
||||
scope.$digest();
|
||||
@@ -565,10 +565,10 @@ describe('uib-accordion', function() {
|
||||
beforeEach(function() {
|
||||
var tpl =
|
||||
'<uib-accordion ng-init="a = [1,2,3]">' +
|
||||
'<uib-accordion-group heading="I get overridden">' +
|
||||
'<div uib-accordion-group heading="I get overridden">' +
|
||||
'<div uib-accordion-heading>Heading Element <span ng-repeat="x in a">{{x}}</span> </div>' +
|
||||
'Body' +
|
||||
'</uib-accordion-group>' +
|
||||
'</div>' +
|
||||
'</uib-accordion>';
|
||||
element = $compile(tpl)(scope);
|
||||
scope.$digest();
|
||||
@@ -588,7 +588,7 @@ describe('uib-accordion', function() {
|
||||
|
||||
describe('uib-accordion-heading, with repeating uib-accordion-groups', function() {
|
||||
it('should clone the uib-accordion-heading for each group', function() {
|
||||
element = $compile('<uib-accordion><uib-accordion-group ng-repeat="x in [1,2,3]"><uib-accordion-heading>{{x}}</uib-accordion-heading></uib-accordion-group></uib-accordion>')(scope);
|
||||
element = $compile('<uib-accordion><div uib-accordion-group ng-repeat="x in [1,2,3]"><uib-accordion-heading>{{x}}</uib-accordion-heading></div></uib-accordion>')(scope);
|
||||
scope.$digest();
|
||||
groups = element.find('.panel');
|
||||
expect(groups.length).toBe(3);
|
||||
@@ -600,7 +600,7 @@ describe('uib-accordion', function() {
|
||||
|
||||
describe('uib-accordion-heading attribute, with repeating uib-accordion-groups', function() {
|
||||
it('should clone the uib-accordion-heading for each group', function() {
|
||||
element = $compile('<uib-accordion><uib-accordion-group ng-repeat="x in [1,2,3]"><div uib-accordion-heading>{{x}}</div></uib-accordion-group></uib-accordion>')(scope);
|
||||
element = $compile('<uib-accordion><div uib-accordion-group ng-repeat="x in [1,2,3]"><div uib-accordion-heading>{{x}}</div></div></uib-accordion>')(scope);
|
||||
scope.$digest();
|
||||
groups = element.find('.panel');
|
||||
expect(groups.length).toBe(3);
|
||||
@@ -610,39 +610,15 @@ describe('uib-accordion', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('uib-accordion group panel class', function() {
|
||||
it('should use the default value when panel class is falsy - #3968', function() {
|
||||
element = $compile('<uib-accordion><uib-accordion-group heading="Heading">Content</uib-accordion-group></uib-accordion>')(scope);
|
||||
scope.$digest();
|
||||
groups = element.find('.panel');
|
||||
expect(groups.eq(0)).toHaveClass('panel-default');
|
||||
describe('uib-accordion-heading attribute, with custom template', function() {
|
||||
it('should transclude heading to a template using data-uib-accordion-header', inject(function($templateCache) {
|
||||
$templateCache.put('foo/bar.html', '<div class="panel"><a uib-accordion-transclude="heading" class="accordion-toggle"><span data-uib-accordion-header></span></a><div ng-transclude></div></div>');
|
||||
|
||||
element = $compile('<uib-accordion><uib-accordion-group heading="Heading" panel-class="">Content</uib-accordion-group></uib-accordion>')(scope);
|
||||
scope.$digest();
|
||||
groups = element.find('.panel');
|
||||
expect(groups.eq(0)).toHaveClass('panel-default');
|
||||
});
|
||||
|
||||
it('should use the specified value when not falsy - #3968', function() {
|
||||
element = $compile('<uib-accordion><uib-accordion-group heading="Heading" panel-class="custom-class">Content</uib-accordion-group></uib-accordion>')(scope);
|
||||
scope.$digest();
|
||||
groups = element.find('.panel');
|
||||
expect(groups.eq(0)).toHaveClass('custom-class');
|
||||
expect(groups.eq(0)).not.toHaveClass('panel-default');
|
||||
});
|
||||
|
||||
it('should change class if panel-class is changed', function() {
|
||||
element = $compile('<uib-accordion><uib-accordion-group heading="Heading" panel-class="{{panelClass}}">Content</uib-accordion-group></uib-accordion>')(scope);
|
||||
scope.panelClass = 'custom-class';
|
||||
scope.$digest();
|
||||
groups = element.find('.panel');
|
||||
expect(groups.eq(0)).toHaveClass('custom-class');
|
||||
|
||||
scope.panelClass = 'different-class';
|
||||
scope.$digest();
|
||||
expect(groups.eq(0)).toHaveClass('different-class');
|
||||
expect(groups.eq(0)).not.toHaveClass('custom-class');
|
||||
});
|
||||
element = $compile('<uib-accordion><div uib-accordion-group template-url="foo/bar.html"><uib-accordion-heading>baz</uib-accordion-heading></div></uib-accordion>')(scope);
|
||||
scope.$digest();
|
||||
groups = element.find('.panel');
|
||||
expect(findGroupLink(0).text()).toBe('baz');
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+7
-3
@@ -1,7 +1,12 @@
|
||||
angular.module('ui.bootstrap.alert', [])
|
||||
|
||||
.controller('UibAlertController', ['$scope', '$attrs', '$interpolate', '$timeout', function($scope, $attrs, $interpolate, $timeout) {
|
||||
.controller('UibAlertController', ['$scope', '$element', '$attrs', '$interpolate', '$timeout', function($scope, $element, $attrs, $interpolate, $timeout) {
|
||||
$scope.closeable = !!$attrs.close;
|
||||
$element.addClass('alert');
|
||||
$attrs.$set('role', 'alert');
|
||||
if ($scope.closeable) {
|
||||
$element.addClass('alert-dismissible');
|
||||
}
|
||||
|
||||
var dismissOnTimeout = angular.isDefined($attrs.dismissOnTimeout) ?
|
||||
$interpolate($attrs.dismissOnTimeout)($scope.$parent) : null;
|
||||
@@ -17,13 +22,12 @@ angular.module('ui.bootstrap.alert', [])
|
||||
return {
|
||||
controller: 'UibAlertController',
|
||||
controllerAs: 'alert',
|
||||
restrict: 'A',
|
||||
templateUrl: function(element, attrs) {
|
||||
return attrs.templateUrl || 'uib/template/alert/alert.html';
|
||||
},
|
||||
transclude: true,
|
||||
replace: true,
|
||||
scope: {
|
||||
type: '@',
|
||||
close: '&'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
<div ng-controller="AlertDemoCtrl">
|
||||
<script type="text/ng-template" id="alert.html">
|
||||
<div class="alert" style="background-color:#fa39c3;color:white" role="alert">
|
||||
<div ng-transclude></div>
|
||||
</div>
|
||||
<div ng-transclude></div>
|
||||
</script>
|
||||
|
||||
<uib-alert ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)">{{alert.msg}}</uib-alert>
|
||||
<uib-alert template-url="alert.html">A happy alert!</uib-alert>
|
||||
<div uib-alert ng-repeat="alert in alerts" ng-class="'alert-' + (alert.type || 'warning')" close="closeAlert($index)">{{alert.msg}}</div>
|
||||
<div uib-alert template-url="alert.html" style="background-color:#fa39c3;color:white">A happy alert!</div>
|
||||
<button type="button" class='btn btn-default' ng-click="addAlert()">Add Alert</button>
|
||||
</div>
|
||||
|
||||
@@ -5,15 +5,11 @@ This directive can be used both to generate alerts from static and dynamic model
|
||||
* `close()`
|
||||
<small class="badge">$</small> -
|
||||
A callback function that gets fired when an `alert` is closed. If the attribute exists, a close button is displayed as well.
|
||||
|
||||
|
||||
* `dismiss-on-timeout`
|
||||
_(Default: `none`)_ -
|
||||
Takes the number of milliseconds that specify the timeout duration, after which the alert will be closed. This attribute requires the presence of the `close` attribute.
|
||||
|
||||
|
||||
* `template-url`
|
||||
_(Default: `uib/template/alert/alert.html`)_ -
|
||||
Add the ability to override the template used in the component.
|
||||
|
||||
* `type`
|
||||
_(Default: `warning`)_ -
|
||||
Defines the type of the alert. Go to [bootstrap page](http://getbootstrap.com/components/#alerts) to see the type of alerts available.
|
||||
|
||||
@@ -12,9 +12,10 @@ describe('uib-alert', function() {
|
||||
|
||||
element = angular.element(
|
||||
'<div>' +
|
||||
'<uib-alert ng-repeat="alert in alerts" type="{{alert.type}}"' +
|
||||
'<div uib-alert ng-repeat="alert in alerts" ' +
|
||||
'ng-class="\'alert-\' + (alert.type || \'warning\')" ' +
|
||||
'close="removeAlert($index)">{{alert.msg}}' +
|
||||
'</uib-alert>' +
|
||||
'</div>' +
|
||||
'</div>');
|
||||
|
||||
scope.alerts = [
|
||||
@@ -41,7 +42,7 @@ describe('uib-alert', function() {
|
||||
it('should expose the controller to the view', function() {
|
||||
$templateCache.put('uib/template/alert/alert.html', '<div>{{alert.text}}</div>');
|
||||
|
||||
element = $compile('<uib-alert></uib-alert>')(scope);
|
||||
element = $compile('<div uib-alert></div>')(scope);
|
||||
scope.$digest();
|
||||
|
||||
var ctrl = element.controller('uib-alert');
|
||||
@@ -50,16 +51,16 @@ describe('uib-alert', function() {
|
||||
ctrl.text = 'foo';
|
||||
scope.$digest();
|
||||
|
||||
expect(element.html()).toBe('foo');
|
||||
expect(element.html()).toBe('<div class="ng-binding">foo</div>');
|
||||
});
|
||||
|
||||
it('should support custom templates', function() {
|
||||
$templateCache.put('foo/bar.html', '<div>baz</div>');
|
||||
|
||||
element = $compile('<uib-alert template-url="foo/bar.html"></uib-alert>')(scope);
|
||||
element = $compile('<div uib-alert template-url="foo/bar.html"></div>')(scope);
|
||||
scope.$digest();
|
||||
|
||||
expect(element.html()).toBe('baz');
|
||||
expect(element.html()).toBe('<div>baz</div>');
|
||||
});
|
||||
|
||||
it('should generate alerts using ng-repeat', function() {
|
||||
@@ -67,23 +68,6 @@ describe('uib-alert', function() {
|
||||
expect(alerts.length).toEqual(3);
|
||||
});
|
||||
|
||||
it('should use correct classes for different alert types', function() {
|
||||
var alerts = createAlerts();
|
||||
expect(alerts.eq(0)).toHaveClass('alert-success');
|
||||
expect(alerts.eq(1)).toHaveClass('alert-error');
|
||||
expect(alerts.eq(2)).toHaveClass('alert-warning');
|
||||
});
|
||||
|
||||
it('should respect alert type binding', function() {
|
||||
var alerts = createAlerts();
|
||||
expect(alerts.eq(0)).toHaveClass('alert-success');
|
||||
|
||||
scope.alerts[0].type = 'error';
|
||||
scope.$digest();
|
||||
|
||||
expect(alerts.eq(0)).toHaveClass('alert-error');
|
||||
});
|
||||
|
||||
it('should show the alert content', function() {
|
||||
var alerts = createAlerts();
|
||||
|
||||
@@ -115,22 +99,15 @@ describe('uib-alert', function() {
|
||||
});
|
||||
|
||||
it('should not show close button and have the dismissible class if no close callback specified', function() {
|
||||
element = $compile('<uib-alert>No close</uib-alert>')(scope);
|
||||
element = $compile('<div uib-alert>No close</div>')(scope);
|
||||
scope.$digest();
|
||||
expect(findCloseButton(0)).toBeHidden();
|
||||
expect(element).not.toHaveClass('alert-dismissible');
|
||||
});
|
||||
|
||||
it('should be possible to add additional classes for alert', function() {
|
||||
var element = $compile('<uib-alert class="alert-block" type="info">Default alert!</uib-alert>')(scope);
|
||||
scope.$digest();
|
||||
expect(element).toHaveClass('alert-block');
|
||||
expect(element).toHaveClass('alert-info');
|
||||
});
|
||||
|
||||
it('should close automatically if dismiss-on-timeout is defined on the element', function() {
|
||||
scope.removeAlert = jasmine.createSpy();
|
||||
$compile('<uib-alert close="removeAlert()" dismiss-on-timeout="500">Default alert!</uib-alert>')(scope);
|
||||
$compile('<div uib-alert close="removeAlert()" dismiss-on-timeout="500">Default alert!</div>')(scope);
|
||||
scope.$digest();
|
||||
|
||||
$timeout.flush();
|
||||
@@ -140,7 +117,7 @@ describe('uib-alert', function() {
|
||||
it('should not close immediately with a dynamic dismiss-on-timeout', function() {
|
||||
scope.removeAlert = jasmine.createSpy();
|
||||
scope.dismissTime = 500;
|
||||
$compile('<uib-alert close="removeAlert()" dismiss-on-timeout="{{dismissTime}}">Default alert!</uib-alert>')(scope);
|
||||
$compile('<div uib-alert close="removeAlert()" dismiss-on-timeout="{{dismissTime}}">Default alert!</div>')(scope);
|
||||
scope.$digest();
|
||||
|
||||
$timeout.flush(100);
|
||||
|
||||
@@ -44,3 +44,7 @@ With the buttons directive, we can make a group of buttons behave like a set of
|
||||
* `toggleEvent`
|
||||
_(Default: `click`)_ -
|
||||
Event used to toggle the buttons.
|
||||
|
||||
### Known issues
|
||||
|
||||
To use tooltips or popovers on elements within a `btn-group`, set the tooltip/popover `appendToBody` option to `true`. This is due to Bootstrap CSS styling. See [here](http://getbootstrap.com/components/#btn-groups) for more information.
|
||||
|
||||
@@ -8,6 +8,7 @@ angular.module('ui.bootstrap.carousel', [])
|
||||
currentInterval, isPlaying, bufferedTransitions = [];
|
||||
|
||||
var destroyed = false;
|
||||
$element.addClass('carousel');
|
||||
|
||||
self.addSlide = function(slide, element) {
|
||||
slides.push({
|
||||
@@ -145,6 +146,9 @@ angular.module('ui.bootstrap.carousel', [])
|
||||
}
|
||||
};
|
||||
|
||||
$element.on('mouseenter', $scope.pause);
|
||||
$element.on('mouseleave', $scope.play);
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
destroyed = true;
|
||||
resetTimer();
|
||||
@@ -280,9 +284,9 @@ angular.module('ui.bootstrap.carousel', [])
|
||||
.directive('uibCarousel', function() {
|
||||
return {
|
||||
transclude: true,
|
||||
replace: true,
|
||||
controller: 'UibCarouselController',
|
||||
controllerAs: 'carousel',
|
||||
restrict: 'A',
|
||||
templateUrl: function(element, attrs) {
|
||||
return attrs.templateUrl || 'uib/template/carousel/carousel.html';
|
||||
},
|
||||
@@ -296,11 +300,11 @@ angular.module('ui.bootstrap.carousel', [])
|
||||
};
|
||||
})
|
||||
|
||||
.directive('uibSlide', function() {
|
||||
.directive('uibSlide', ['$animate', function($animate) {
|
||||
return {
|
||||
require: '^uibCarousel',
|
||||
restrict: 'A',
|
||||
transclude: true,
|
||||
replace: true,
|
||||
templateUrl: function(element, attrs) {
|
||||
return attrs.templateUrl || 'uib/template/carousel/slide.html';
|
||||
},
|
||||
@@ -309,14 +313,19 @@ angular.module('ui.bootstrap.carousel', [])
|
||||
index: '=?'
|
||||
},
|
||||
link: function (scope, element, attrs, carouselCtrl) {
|
||||
element.addClass('item');
|
||||
carouselCtrl.addSlide(scope, element);
|
||||
//when the scope is destroyed then remove the slide from the current slides array
|
||||
scope.$on('$destroy', function() {
|
||||
carouselCtrl.removeSlide(scope);
|
||||
});
|
||||
|
||||
scope.$watch('active', function(active) {
|
||||
$animate[active ? 'addClass' : 'removeClass'](element, 'active');
|
||||
});
|
||||
}
|
||||
};
|
||||
})
|
||||
}])
|
||||
|
||||
.animation('.item', ['$animateCss',
|
||||
function($animateCss) {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<div ng-controller="CarouselDemoCtrl">
|
||||
<div style="height: 305px">
|
||||
<uib-carousel active="active" interval="myInterval" no-wrap="noWrapSlides">
|
||||
<uib-slide ng-repeat="slide in slides track by slide.id" index="slide.id">
|
||||
<div uib-carousel active="active" interval="myInterval" no-wrap="noWrapSlides">
|
||||
<div uib-slide ng-repeat="slide in slides track by slide.id" index="slide.id">
|
||||
<img ng-src="{{slide.image}}" style="margin:auto;">
|
||||
<div class="carousel-caption">
|
||||
<h4>Slide {{slide.id}}</h4>
|
||||
<p>{{slide.text}}</p>
|
||||
</div>
|
||||
</uib-slide>
|
||||
</uib-carousel>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
describe('carousel', function() {
|
||||
beforeEach(module('ui.bootstrap.carousel', function($compileProvider, $provide) {
|
||||
angular.forEach(['ngSwipeLeft', 'ngSwipeRight'], makeMock);
|
||||
function makeMock(name) {
|
||||
$provide.value(name + 'Directive', []); //remove existing directive if it exists
|
||||
$compileProvider.directive(name, function() {
|
||||
return function(scope, element, attr) {
|
||||
element.on(name, function() {
|
||||
scope.$apply(attr[name]);
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
}));
|
||||
beforeEach(module('ui.bootstrap.carousel'));
|
||||
beforeEach(module('ngAnimateMock'));
|
||||
beforeEach(module('uib/template/carousel/carousel.html', 'uib/template/carousel/slide.html'));
|
||||
|
||||
@@ -36,11 +24,11 @@ describe('carousel', function() {
|
||||
{content: 'three', index: 2}
|
||||
];
|
||||
elm = $compile(
|
||||
'<uib-carousel active="active" interval="interval" no-transition="true" no-pause="nopause">' +
|
||||
'<uib-slide ng-repeat="slide in slides track by slide.index" index="slide.index">' +
|
||||
'<div uib-carousel active="active" interval="interval" no-transition="true" no-pause="nopause">' +
|
||||
'<div uib-slide ng-repeat="slide in slides track by slide.index" index="slide.index">' +
|
||||
'{{slide.content}}' +
|
||||
'</uib-slide>' +
|
||||
'</uib-carousel>'
|
||||
'</div>' +
|
||||
'</div>'
|
||||
)(scope);
|
||||
scope.interval = 5000;
|
||||
scope.nopause = undefined;
|
||||
@@ -60,19 +48,19 @@ describe('carousel', function() {
|
||||
it('should allow overriding of the carousel template', function() {
|
||||
$templateCache.put('foo/bar.html', '<div>foo</div>');
|
||||
|
||||
elm = $compile('<uib-carousel template-url="foo/bar.html"></uib-carousel>')(scope);
|
||||
elm = $compile('<div uib-carousel template-url="foo/bar.html"></div>')(scope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(elm.html()).toBe('foo');
|
||||
expect(elm.html()).toBe('<div>foo</div>');
|
||||
});
|
||||
|
||||
it('should allow overriding of the slide template', function() {
|
||||
$templateCache.put('foo/bar.html', '<div class="slide">bar</div>');
|
||||
|
||||
elm = $compile(
|
||||
'<uib-carousel interval="interval" no-transition="true" no-pause="nopause">' +
|
||||
'<uib-slide template-url="foo/bar.html"></uib-slide>' +
|
||||
'</uib-carousel>'
|
||||
'<div uib-carousel interval="interval" no-transition="true" no-pause="nopause">' +
|
||||
'<div uib-slide template-url="foo/bar.html"></div>' +
|
||||
'</div>'
|
||||
)(scope);
|
||||
$rootScope.$digest();
|
||||
|
||||
@@ -101,11 +89,11 @@ describe('carousel', function() {
|
||||
|
||||
it('should stop cycling slides forward when noWrap is truthy', function () {
|
||||
elm = $compile(
|
||||
'<uib-carousel active="active" interval="interval" no-wrap="noWrap">' +
|
||||
'<uib-slide ng-repeat="slide in slides track by slide.index" index="slide.index">' +
|
||||
'<div uib-carousel active="active" interval="interval" no-wrap="noWrap">' +
|
||||
'<div uib-slide ng-repeat="slide in slides track by slide.index" index="slide.index">' +
|
||||
'{{slide.content}}' +
|
||||
'</uib-slide>' +
|
||||
'</uib-carousel>'
|
||||
'</div>' +
|
||||
'</div>'
|
||||
)(scope);
|
||||
|
||||
scope.noWrap = true;
|
||||
@@ -124,11 +112,11 @@ describe('carousel', function() {
|
||||
|
||||
it('should stop cycling slides backward when noWrap is truthy', function () {
|
||||
elm = $compile(
|
||||
'<uib-carousel active="active" interval="interval" no-wrap="noWrap">' +
|
||||
'<uib-slide ng-repeat="slide in slides track by slide.index" index="slide.index">' +
|
||||
'<div uib-carousel active="active" interval="interval" no-wrap="noWrap">' +
|
||||
'<div uib-slide ng-repeat="slide in slides track by slide.index" index="slide.index">' +
|
||||
'{{slide.content}}' +
|
||||
'</uib-slide>' +
|
||||
'</uib-carousel>'
|
||||
'</div>' +
|
||||
'</div>'
|
||||
)(scope);
|
||||
|
||||
scope.noWrap = true;
|
||||
@@ -147,11 +135,11 @@ describe('carousel', function() {
|
||||
scope.slides = [{active:false,content:'one'}];
|
||||
scope.$apply();
|
||||
elm = $compile(
|
||||
'<uib-carousel active="active" interval="interval" no-transition="true">' +
|
||||
'<uib-slide ng-repeat="slide in slides" index="$index">' +
|
||||
'<div uib-carousel active="active" interval="interval" no-transition="true">' +
|
||||
'<div uib-slide ng-repeat="slide in slides" index="$index">' +
|
||||
'{{slide.content}}' +
|
||||
'</uib-slide>' +
|
||||
'</uib-carousel>'
|
||||
'</div>' +
|
||||
'</div>'
|
||||
)(scope);
|
||||
var indicators = elm.find('ol.carousel-indicators > li');
|
||||
expect(indicators.length).toBe(0);
|
||||
@@ -228,20 +216,6 @@ describe('carousel', function() {
|
||||
testSlideActive(0);
|
||||
});
|
||||
|
||||
describe('swiping', function() {
|
||||
it('should go next on swipeLeft', function() {
|
||||
testSlideActive(0);
|
||||
elm.triggerHandler('ngSwipeLeft');
|
||||
testSlideActive(1);
|
||||
});
|
||||
|
||||
it('should go prev on swipeRight', function() {
|
||||
testSlideActive(0);
|
||||
elm.triggerHandler('ngSwipeRight');
|
||||
testSlideActive(2);
|
||||
});
|
||||
});
|
||||
|
||||
it('should select a slide when clicking on slide indicators', function () {
|
||||
var indicators = elm.find('ol.carousel-indicators > li');
|
||||
indicators.eq(1).click();
|
||||
@@ -269,7 +243,7 @@ describe('carousel', function() {
|
||||
});
|
||||
|
||||
it('should bind the content to slides', function() {
|
||||
var contents = elm.find('div.item');
|
||||
var contents = elm.find('div.item [ng-transclude]');
|
||||
|
||||
expect(contents.length).toBe(3);
|
||||
expect(contents.eq(0).text()).toBe('one');
|
||||
@@ -343,7 +317,7 @@ describe('carousel', function() {
|
||||
{content:'new3', index: 6}
|
||||
];
|
||||
scope.$apply();
|
||||
var contents = elm.find('div.item');
|
||||
var contents = elm.find('div.item [ng-transclude]');
|
||||
expect(contents.length).toBe(3);
|
||||
expect(contents.eq(0).text()).toBe('new1');
|
||||
expect(contents.eq(1).text()).toBe('new2');
|
||||
@@ -441,11 +415,11 @@ describe('carousel', function() {
|
||||
{content: 'three', id: 2}
|
||||
];
|
||||
elm = $compile(
|
||||
'<uib-carousel active="active" interval="interval" no-transition="true" no-pause="nopause">' +
|
||||
'<uib-slide ng-repeat="slide in slides | orderBy: \'id\' track by slide.id" index="slide.id">' +
|
||||
'<div uib-carousel active="active" interval="interval" no-transition="true" no-pause="nopause">' +
|
||||
'<div uib-slide ng-repeat="slide in slides | orderBy: \'id\' track by slide.id" index="slide.id">' +
|
||||
'{{slide.content}}' +
|
||||
'</uib-slide>' +
|
||||
'</uib-carousel>'
|
||||
'</div>' +
|
||||
'</div>'
|
||||
)(scope);
|
||||
scope.$apply();
|
||||
});
|
||||
@@ -465,7 +439,7 @@ describe('carousel', function() {
|
||||
scope.slides[1].id = 2;
|
||||
scope.slides[2].id = 1;
|
||||
scope.$apply();
|
||||
var contents = elm.find('div.item');
|
||||
var contents = elm.find('div.item [ng-transclude]');
|
||||
expect(contents.length).toBe(3);
|
||||
expect(contents.eq(0).text()).toBe('three');
|
||||
expect(contents.eq(1).text()).toBe('two');
|
||||
@@ -491,7 +465,7 @@ describe('carousel', function() {
|
||||
scope.slides[2].id = 4;
|
||||
scope.slides.push({content:'four', id: 5});
|
||||
scope.$apply();
|
||||
var contents = elm.find('div.item');
|
||||
var contents = elm.find('div.item [ng-transclude]');
|
||||
expect(contents.length).toBe(4);
|
||||
expect(contents.eq(0).text()).toBe('two');
|
||||
expect(contents.eq(1).text()).toBe('one');
|
||||
@@ -503,7 +477,7 @@ describe('carousel', function() {
|
||||
testSlideActive(1);
|
||||
scope.slides.splice(1, 1);
|
||||
scope.$apply();
|
||||
var contents = elm.find('div.item');
|
||||
var contents = elm.find('div.item [ng-transclude]');
|
||||
expect(contents.length).toBe(2);
|
||||
expect(contents.eq(0).text()).toBe('three');
|
||||
expect(contents.eq(1).text()).toBe('one');
|
||||
@@ -583,7 +557,7 @@ describe('carousel', function() {
|
||||
$templateCache.put('uib/template/carousel/carousel.html', '<div>{{carousel.text}}</div>');
|
||||
|
||||
var scope = $rootScope.$new();
|
||||
var elm = $compile('<uib-carousel interval="bar" no-transition="false" no-pause="true"></uib-carousel>')(scope);
|
||||
var elm = $compile('<div uib-carousel interval="bar" no-transition="false" no-pause="true"></div>')(scope);
|
||||
$rootScope.$digest();
|
||||
|
||||
var ctrl = elm.controller('uibCarousel');
|
||||
@@ -593,7 +567,7 @@ describe('carousel', function() {
|
||||
ctrl.text = 'foo';
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(elm.html()).toBe('foo');
|
||||
expect(elm.html()).toBe('<div class="ng-binding">foo</div>');
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -605,11 +579,11 @@ describe('carousel', function() {
|
||||
{active:false,content:'three'}
|
||||
];
|
||||
var elm = $compile(
|
||||
'<uib-carousel active="active" interval="interval" no-transition="true" no-pause="nopause">' +
|
||||
'<uib-slide ng-repeat="slide in slides" index="$index" actual="slide">' +
|
||||
'<div uib-carousel active="active" interval="interval" no-transition="true" no-pause="nopause">' +
|
||||
'<div uib-slide ng-repeat="slide in slides" index="$index" actual="slide">' +
|
||||
'{{slide.content}}' +
|
||||
'</uib-slide>' +
|
||||
'</uib-carousel>'
|
||||
'</div>' +
|
||||
'</div>'
|
||||
)(scope);
|
||||
$rootScope.$digest();
|
||||
|
||||
|
||||
+47
-19
@@ -5,16 +5,44 @@ angular.module('ui.bootstrap.collapse', [])
|
||||
return {
|
||||
link: function(scope, element, attrs) {
|
||||
var expandingExpr = $parse(attrs.expanding),
|
||||
expandedExpr = $parse(attrs.expanded),
|
||||
collapsingExpr = $parse(attrs.collapsing),
|
||||
collapsedExpr = $parse(attrs.collapsed);
|
||||
expandedExpr = $parse(attrs.expanded),
|
||||
collapsingExpr = $parse(attrs.collapsing),
|
||||
collapsedExpr = $parse(attrs.collapsed),
|
||||
horizontal = false,
|
||||
css = {},
|
||||
cssTo = {};
|
||||
|
||||
if (!scope.$eval(attrs.uibCollapse)) {
|
||||
element.addClass('in')
|
||||
.addClass('collapse')
|
||||
.attr('aria-expanded', true)
|
||||
.attr('aria-hidden', false)
|
||||
.css({height: 'auto'});
|
||||
init();
|
||||
|
||||
function init() {
|
||||
horizontal = !!('horizontal' in attrs);
|
||||
if (horizontal) {
|
||||
css = {
|
||||
width: 'auto',
|
||||
height: 'inherit'
|
||||
};
|
||||
cssTo = {width: '0'};
|
||||
} else {
|
||||
css = {
|
||||
width: 'inherit',
|
||||
height: 'auto'
|
||||
};
|
||||
cssTo = {height: '0'};
|
||||
}
|
||||
if (!scope.$eval(attrs.uibCollapse)) {
|
||||
element.addClass('in')
|
||||
.addClass('collapse')
|
||||
.attr('aria-expanded', true)
|
||||
.attr('aria-hidden', false)
|
||||
.css(css);
|
||||
}
|
||||
}
|
||||
|
||||
function getScrollFromElement(element) {
|
||||
if (horizontal) {
|
||||
return {width: element.scrollWidth + 'px'};
|
||||
}
|
||||
return {height: element.scrollHeight + 'px'};
|
||||
}
|
||||
|
||||
function expand() {
|
||||
@@ -33,11 +61,11 @@ angular.module('ui.bootstrap.collapse', [])
|
||||
$animateCss(element, {
|
||||
addClass: 'in',
|
||||
easing: 'ease',
|
||||
to: { height: element[0].scrollHeight + 'px' }
|
||||
to: getScrollFromElement(element[0])
|
||||
}).start()['finally'](expandDone);
|
||||
} else {
|
||||
$animate.addClass(element, 'in', {
|
||||
to: { height: element[0].scrollHeight + 'px' }
|
||||
to: getScrollFromElement(element[0])
|
||||
}).then(expandDone);
|
||||
}
|
||||
});
|
||||
@@ -46,7 +74,7 @@ angular.module('ui.bootstrap.collapse', [])
|
||||
function expandDone() {
|
||||
element.removeClass('collapsing')
|
||||
.addClass('collapse')
|
||||
.css({height: 'auto'});
|
||||
.css(css);
|
||||
expandedExpr(scope);
|
||||
}
|
||||
|
||||
@@ -58,10 +86,10 @@ angular.module('ui.bootstrap.collapse', [])
|
||||
$q.resolve(collapsingExpr(scope))
|
||||
.then(function() {
|
||||
element
|
||||
// IMPORTANT: The height must be set before adding "collapsing" class.
|
||||
// Otherwise, the browser attempts to animate from height 0 (in
|
||||
// collapsing class) to the given height here.
|
||||
.css({height: element[0].scrollHeight + 'px'})
|
||||
// IMPORTANT: The width must be set before adding "collapsing" class.
|
||||
// Otherwise, the browser attempts to animate from width 0 (in
|
||||
// collapsing class) to the given width here.
|
||||
.css(getScrollFromElement(element[0]))
|
||||
// initially all panel collapse have the collapse class, this removal
|
||||
// prevents the animation from jumping to collapsed state
|
||||
.removeClass('collapse')
|
||||
@@ -72,18 +100,18 @@ angular.module('ui.bootstrap.collapse', [])
|
||||
if ($animateCss) {
|
||||
$animateCss(element, {
|
||||
removeClass: 'in',
|
||||
to: {height: '0'}
|
||||
to: cssTo
|
||||
}).start()['finally'](collapseDone);
|
||||
} else {
|
||||
$animate.removeClass(element, 'in', {
|
||||
to: {height: '0'}
|
||||
to: cssTo
|
||||
}).then(collapseDone);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function collapseDone() {
|
||||
element.css({height: '0'}); // Required so that collapse works when animation is disabled
|
||||
element.css(cssTo); // Required so that collapse works when animation is disabled
|
||||
element.removeClass('collapsing')
|
||||
.addClass('collapse');
|
||||
collapsedExpr(scope);
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
<div ng-controller="CollapseDemoCtrl">
|
||||
<button type="button" class="btn btn-default" ng-click="isCollapsed = !isCollapsed">Toggle collapse</button>
|
||||
<button type="button" class="btn btn-default" ng-click="isCollapsed = !isCollapsed">Toggle collapse Vertically</button>
|
||||
<hr>
|
||||
<div uib-collapse="isCollapsed">
|
||||
<div class="well well-lg">Some content</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-default" ng-click="isCollapsedHorizontal = !isCollapsedHorizontal">Toggle collapse Horizontally</button>
|
||||
<hr>
|
||||
<div uib-collapse="isCollapsedHorizontal" horizontal>
|
||||
<div class="well well-lg">Some content</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
angular.module('ui.bootstrap.demo').controller('CollapseDemoCtrl', function ($scope) {
|
||||
$scope.isCollapsed = false;
|
||||
$scope.isCollapsedHorizontal = false;
|
||||
});
|
||||
|
||||
@@ -27,4 +27,8 @@
|
||||
<i class="glyphicon glyphicon-eye-open"></i>
|
||||
_(Default: `false`)_ -
|
||||
Whether the element should be collapsed or not.
|
||||
|
||||
* `horizontal`
|
||||
<small class="badge">$</small> -
|
||||
An optional attribute that permit to collapse horizontally.
|
||||
|
||||
|
||||
@@ -0,0 +1,255 @@
|
||||
describe('collapse directive', function() {
|
||||
var elementH, compileFnH, scope, $compile, $animate, $q;
|
||||
|
||||
beforeEach(module('ui.bootstrap.collapse'));
|
||||
beforeEach(module('ngAnimateMock'));
|
||||
beforeEach(inject(function(_$rootScope_, _$compile_, _$animate_, _$q_) {
|
||||
scope = _$rootScope_;
|
||||
$compile = _$compile_;
|
||||
$animate = _$animate_;
|
||||
$q = _$q_;
|
||||
}));
|
||||
|
||||
beforeEach(function() {
|
||||
elementH = angular.element(
|
||||
'<div uib-collapse="isCollapsed" '
|
||||
+ 'expanding="expanding()" '
|
||||
+ 'expanded="expanded()" '
|
||||
+ 'collapsing="collapsing()" '
|
||||
+ 'collapsed="collapsed()" '
|
||||
+ 'horizontal>'
|
||||
+ 'Some Content</div>');
|
||||
compileFnH = $compile(elementH);
|
||||
angular.element(document.body).append(elementH);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
elementH.remove();
|
||||
});
|
||||
|
||||
function initCallbacks() {
|
||||
scope.collapsing = jasmine.createSpy('scope.collapsing');
|
||||
scope.collapsed = jasmine.createSpy('scope.collapsed');
|
||||
scope.expanding = jasmine.createSpy('scope.expanding');
|
||||
scope.expanded = jasmine.createSpy('scope.expanded');
|
||||
}
|
||||
|
||||
function assertCallbacks(expected) {
|
||||
['collapsing', 'collapsed', 'expanding', 'expanded'].forEach(function(cbName) {
|
||||
if (expected[cbName]) {
|
||||
expect(scope[cbName]).toHaveBeenCalled();
|
||||
} else {
|
||||
expect(scope[cbName]).not.toHaveBeenCalled();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
it('should be hidden on initialization if isCollapsed = true', function() {
|
||||
initCallbacks();
|
||||
scope.isCollapsed = true;
|
||||
compileFnH(scope);
|
||||
scope.$digest();
|
||||
expect(elementH.width()).toBe(0);
|
||||
assertCallbacks({ collapsed: true });
|
||||
});
|
||||
|
||||
it('should not trigger any animation on initialization if isCollapsed = true', function() {
|
||||
var wrapperFn = function() {
|
||||
$animate.flush();
|
||||
};
|
||||
|
||||
scope.isCollapsed = true;
|
||||
compileFnH(scope);
|
||||
scope.$digest();
|
||||
|
||||
expect(wrapperFn).toThrowError(/No pending animations ready to be closed or flushed/);
|
||||
});
|
||||
|
||||
it('should collapse if isCollapsed = true on subsequent use', function() {
|
||||
scope.isCollapsed = false;
|
||||
compileFnH(scope);
|
||||
scope.$digest();
|
||||
initCallbacks();
|
||||
scope.isCollapsed = true;
|
||||
scope.$digest();
|
||||
$animate.flush();
|
||||
expect(elementH.width()).toBe(0);
|
||||
assertCallbacks({ collapsing: true, collapsed: true });
|
||||
});
|
||||
|
||||
it('should show after toggled from collapsed', function() {
|
||||
initCallbacks();
|
||||
scope.isCollapsed = true;
|
||||
compileFnH(scope);
|
||||
scope.$digest();
|
||||
expect(elementH.width()).toBe(0);
|
||||
assertCallbacks({ collapsed: true });
|
||||
scope.collapsed.calls.reset();
|
||||
|
||||
scope.isCollapsed = false;
|
||||
scope.$digest();
|
||||
$animate.flush();
|
||||
expect(elementH.width()).not.toBe(0);
|
||||
assertCallbacks({ expanding: true, expanded: true });
|
||||
});
|
||||
|
||||
it('should not trigger any animation on initialization if isCollapsed = false', function() {
|
||||
var wrapperFn = function() {
|
||||
$animate.flush();
|
||||
};
|
||||
|
||||
scope.isCollapsed = false;
|
||||
compileFnH(scope);
|
||||
scope.$digest();
|
||||
|
||||
expect(wrapperFn).toThrowError(/No pending animations ready to be closed or flushed/);
|
||||
});
|
||||
|
||||
it('should expand if isCollapsed = false on subsequent use', function() {
|
||||
scope.isCollapsed = false;
|
||||
compileFnH(scope);
|
||||
scope.$digest();
|
||||
scope.isCollapsed = true;
|
||||
scope.$digest();
|
||||
$animate.flush();
|
||||
initCallbacks();
|
||||
scope.isCollapsed = false;
|
||||
scope.$digest();
|
||||
$animate.flush();
|
||||
expect(elementH.width()).not.toBe(0);
|
||||
assertCallbacks({ expanding: true, expanded: true });
|
||||
});
|
||||
|
||||
it('should collapse if isCollapsed = true on subsequent uses', function() {
|
||||
scope.isCollapsed = false;
|
||||
compileFnH(scope);
|
||||
scope.$digest();
|
||||
scope.isCollapsed = true;
|
||||
scope.$digest();
|
||||
$animate.flush();
|
||||
scope.isCollapsed = false;
|
||||
scope.$digest();
|
||||
$animate.flush();
|
||||
initCallbacks();
|
||||
scope.isCollapsed = true;
|
||||
scope.$digest();
|
||||
$animate.flush();
|
||||
expect(elementH.width()).toBe(0);
|
||||
assertCallbacks({ collapsing: true, collapsed: true });
|
||||
});
|
||||
|
||||
it('should change aria-expanded attribute', function() {
|
||||
scope.isCollapsed = false;
|
||||
compileFnH(scope);
|
||||
scope.$digest();
|
||||
expect(elementH.attr('aria-expanded')).toBe('true');
|
||||
|
||||
scope.isCollapsed = true;
|
||||
scope.$digest();
|
||||
$animate.flush();
|
||||
expect(elementH.attr('aria-expanded')).toBe('false');
|
||||
});
|
||||
|
||||
it('should change aria-hidden attribute', function() {
|
||||
scope.isCollapsed = false;
|
||||
compileFnH(scope);
|
||||
scope.$digest();
|
||||
expect(elementH.attr('aria-hidden')).toBe('false');
|
||||
|
||||
scope.isCollapsed = true;
|
||||
scope.$digest();
|
||||
$animate.flush();
|
||||
expect(elementH.attr('aria-hidden')).toBe('true');
|
||||
});
|
||||
|
||||
describe('expanding callback returning a promise', function() {
|
||||
var defer, collapsedWidth;
|
||||
|
||||
beforeEach(function() {
|
||||
defer = $q.defer();
|
||||
|
||||
scope.isCollapsed = true;
|
||||
scope.expanding = function() {
|
||||
return defer.promise;
|
||||
};
|
||||
compileFnH(scope);
|
||||
scope.$digest();
|
||||
collapsedWidth = elementH.width();
|
||||
|
||||
// set flag to expand ...
|
||||
scope.isCollapsed = false;
|
||||
scope.$digest();
|
||||
|
||||
// ... shouldn't expand yet ...
|
||||
expect(elementH.attr('aria-expanded')).not.toBe('true');
|
||||
expect(elementH.width()).toBe(collapsedWidth);
|
||||
});
|
||||
|
||||
it('should wait for it to resolve before animating', function() {
|
||||
defer.resolve();
|
||||
|
||||
// should now expand
|
||||
scope.$digest();
|
||||
$animate.flush();
|
||||
|
||||
expect(elementH.attr('aria-expanded')).toBe('true');
|
||||
expect(elementH.width()).toBeGreaterThan(collapsedWidth);
|
||||
});
|
||||
|
||||
it('should not animate if it rejects', function() {
|
||||
defer.reject();
|
||||
|
||||
// should NOT expand
|
||||
scope.$digest();
|
||||
|
||||
expect(elementH.attr('aria-expanded')).not.toBe('true');
|
||||
expect(elementH.width()).toBe(collapsedWidth);
|
||||
});
|
||||
});
|
||||
|
||||
describe('collapsing callback returning a promise', function() {
|
||||
var defer, expandedWidth;
|
||||
|
||||
beforeEach(function() {
|
||||
defer = $q.defer();
|
||||
scope.isCollapsed = false;
|
||||
scope.collapsing = function() {
|
||||
return defer.promise;
|
||||
};
|
||||
compileFnH(scope);
|
||||
scope.$digest();
|
||||
|
||||
expandedWidth = elementH.width();
|
||||
|
||||
// set flag to collapse ...
|
||||
scope.isCollapsed = true;
|
||||
scope.$digest();
|
||||
|
||||
// ... but it shouldn't collapse yet ...
|
||||
expect(elementH.attr('aria-expanded')).not.toBe('false');
|
||||
expect(elementH.width()).toBe(expandedWidth);
|
||||
});
|
||||
|
||||
it('should wait for it to resolve before animating', function() {
|
||||
defer.resolve();
|
||||
|
||||
// should now collapse
|
||||
scope.$digest();
|
||||
$animate.flush();
|
||||
|
||||
expect(elementH.attr('aria-expanded')).toBe('false');
|
||||
expect(elementH.width()).toBeLessThan(expandedWidth);
|
||||
});
|
||||
|
||||
it('should not animate if it rejects', function() {
|
||||
defer.reject();
|
||||
|
||||
// should NOT collapse
|
||||
scope.$digest();
|
||||
|
||||
expect(elementH.attr('aria-expanded')).not.toBe('false');
|
||||
expect(elementH.width()).toBe(expandedWidth);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -234,7 +234,7 @@ angular.module('ui.bootstrap.dateparser', [])
|
||||
|
||||
this.init();
|
||||
|
||||
function createParser(format, func) {
|
||||
function createParser(format) {
|
||||
var map = [], regex = format.split('');
|
||||
|
||||
// check for literal values
|
||||
@@ -283,7 +283,7 @@ angular.module('ui.bootstrap.dateparser', [])
|
||||
map.push({
|
||||
index: index,
|
||||
key: data.key,
|
||||
apply: data[func],
|
||||
apply: data.apply,
|
||||
matcher: data.regex
|
||||
});
|
||||
}
|
||||
@@ -295,6 +295,70 @@ angular.module('ui.bootstrap.dateparser', [])
|
||||
};
|
||||
}
|
||||
|
||||
function createFormatter(format) {
|
||||
var formatters = [];
|
||||
var i = 0;
|
||||
var formatter, literalIdx;
|
||||
while (i < format.length) {
|
||||
if (angular.isNumber(literalIdx)) {
|
||||
if (format.charAt(i) === '\'') {
|
||||
if (i + 1 >= format.length || format.charAt(i + 1) !== '\'') {
|
||||
formatters.push(constructLiteralFormatter(format, literalIdx, i));
|
||||
literalIdx = null;
|
||||
}
|
||||
} else if (i === format.length) {
|
||||
while (literalIdx < format.length) {
|
||||
formatter = constructFormatterFromIdx(format, literalIdx);
|
||||
formatters.push(formatter);
|
||||
literalIdx = formatter.endIdx;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (format.charAt(i) === '\'') {
|
||||
literalIdx = i;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
formatter = constructFormatterFromIdx(format, i);
|
||||
|
||||
formatters.push(formatter.parser);
|
||||
i = formatter.endIdx;
|
||||
}
|
||||
|
||||
return formatters;
|
||||
}
|
||||
|
||||
function constructLiteralFormatter(format, literalIdx, endIdx) {
|
||||
return function() {
|
||||
return format.substr(literalIdx + 1, endIdx - literalIdx - 1);
|
||||
};
|
||||
}
|
||||
|
||||
function constructFormatterFromIdx(format, i) {
|
||||
var currentPosStr = format.substr(i);
|
||||
for (var j = 0; j < formatCodeToRegex.length; j++) {
|
||||
if (new RegExp('^' + formatCodeToRegex[j].key).test(currentPosStr)) {
|
||||
var data = formatCodeToRegex[j];
|
||||
return {
|
||||
endIdx: i + data.key.length,
|
||||
parser: data.formatter
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
endIdx: i + 1,
|
||||
parser: function() {
|
||||
return currentPosStr.charAt(0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
this.filter = function(date, format) {
|
||||
if (!angular.isDate(date) || isNaN(date) || !format) {
|
||||
return '';
|
||||
@@ -307,28 +371,13 @@ angular.module('ui.bootstrap.dateparser', [])
|
||||
}
|
||||
|
||||
if (!this.formatters[format]) {
|
||||
this.formatters[format] = createParser(format, 'formatter');
|
||||
this.formatters[format] = createFormatter(format);
|
||||
}
|
||||
|
||||
var parser = this.formatters[format],
|
||||
map = parser.map;
|
||||
var formatters = this.formatters[format];
|
||||
|
||||
var _format = format;
|
||||
|
||||
return map.reduce(function(str, mapper, i) {
|
||||
var match = _format.match(new RegExp('(.*)' + mapper.key));
|
||||
if (match && angular.isString(match[1])) {
|
||||
str += match[1];
|
||||
_format = _format.replace(match[1] + mapper.key, '');
|
||||
}
|
||||
|
||||
var endStr = i === map.length - 1 ? _format : '';
|
||||
|
||||
if (mapper.apply) {
|
||||
return str + mapper.apply.call(null, date) + endStr;
|
||||
}
|
||||
|
||||
return str + endStr;
|
||||
return formatters.reduce(function(str, formatter) {
|
||||
return str + formatter(date);
|
||||
}, '');
|
||||
};
|
||||
|
||||
@@ -442,8 +491,9 @@ angular.module('ui.bootstrap.dateparser', [])
|
||||
return date && timezone ? convertTimezoneToLocal(date, timezone, true) : date;
|
||||
}
|
||||
|
||||
//https://github.com/angular/angular.js/blob/4daafd3dbe6a80d578f5a31df1bb99c77559543e/src/Angular.js#L1207
|
||||
//https://github.com/angular/angular.js/blob/622c42169699ec07fc6daaa19fe6d224e5d2f70e/src/Angular.js#L1207
|
||||
function timezoneToOffset(timezone, fallback) {
|
||||
timezone = timezone.replace(/:/g, '');
|
||||
var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
|
||||
return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
|
||||
}
|
||||
@@ -456,7 +506,8 @@ angular.module('ui.bootstrap.dateparser', [])
|
||||
|
||||
function convertTimezoneToLocal(date, timezone, reverse) {
|
||||
reverse = reverse ? -1 : 1;
|
||||
var timezoneOffset = timezoneToOffset(timezone, date.getTimezoneOffset());
|
||||
return addDateMinutes(date, reverse * (timezoneOffset - date.getTimezoneOffset()));
|
||||
var dateTimezoneOffset = date.getTimezoneOffset();
|
||||
var timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
|
||||
return addDateMinutes(date, reverse * (timezoneOffset - dateTimezoneOffset));
|
||||
}
|
||||
}]);
|
||||
|
||||
@@ -565,27 +565,27 @@ describe('date parser', function() {
|
||||
});
|
||||
|
||||
describe('with value literals', function() {
|
||||
// describe('filter', function() {
|
||||
// it('should work with multiple literals', function() {
|
||||
// expect(dateParser.filter(new Date(2013, 0, 29), 'd \'de\' MMMM \'de\' y')).toEqual('29 de January de 2013');
|
||||
// });
|
||||
//
|
||||
// it('should work with escaped single quote', function() {
|
||||
// expect(dateParser.filter(new Date(2015, 2, 22, 12), 'd.MMMM.yy h \'o\'\'clock\'')).toEqual('22.March.15 12 o\'clock');
|
||||
// });
|
||||
//
|
||||
// it('should work with only a single quote', function() {
|
||||
// expect(dateParser.filter(new Date(2015, 2, 22), 'd.MMMM.yy \'\'\'')).toEqual('22.March.15 \'');
|
||||
// });
|
||||
//
|
||||
// it('should work with trailing literal', function() {
|
||||
// expect(dateParser.filter(new Date(2013, 0, 1), '\'year\' y')).toEqual('year 2013');
|
||||
// });
|
||||
//
|
||||
// it('should work without whitespace', function() {
|
||||
// expect(dateParser.filter(new Date(2013, 0, 1), '\'year:\'y')).toEqual('year:2013');
|
||||
// });
|
||||
// });
|
||||
describe('filter', function() {
|
||||
it('should work with multiple literals', function() {
|
||||
expect(dateParser.filter(new Date(2013, 0, 29), 'd \'de\' MMMM \'de\' y')).toEqual('29 de January de 2013');
|
||||
});
|
||||
|
||||
it('should work with escaped single quote', function() {
|
||||
expect(dateParser.filter(new Date(2015, 2, 22, 12), 'd.MMMM.yy h \'o\'\'clock\'')).toEqual('22.March.15 12 o\'clock');
|
||||
});
|
||||
|
||||
it('should work with only a single quote', function() {
|
||||
expect(dateParser.filter(new Date(2015, 2, 22), 'd.MMMM.yy \'\'\'')).toEqual('22.March.15 \'');
|
||||
});
|
||||
|
||||
it('should work with trailing literal', function() {
|
||||
expect(dateParser.filter(new Date(2013, 0, 1), '\'year\' y')).toEqual('year 2013');
|
||||
});
|
||||
|
||||
it('should work without whitespace', function() {
|
||||
expect(dateParser.filter(new Date(2013, 0, 1), '\'year:\'y')).toEqual('year:2013');
|
||||
});
|
||||
});
|
||||
|
||||
describe('parse', function() {
|
||||
it('should work with multiple literals', function() {
|
||||
|
||||
@@ -16,6 +16,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
|
||||
maxMode: 'year',
|
||||
minDate: null,
|
||||
minMode: 'day',
|
||||
monthColumns: 3,
|
||||
ngModelOptions: {},
|
||||
shortcutPropagation: false,
|
||||
showWeeks: true,
|
||||
@@ -23,13 +24,15 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
|
||||
yearRows: 4
|
||||
})
|
||||
|
||||
.controller('UibDatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$locale', '$log', 'dateFilter', 'uibDatepickerConfig', '$datepickerLiteralWarning', '$datepickerSuppressError', 'uibDateParser',
|
||||
function($scope, $attrs, $parse, $interpolate, $locale, $log, dateFilter, datepickerConfig, $datepickerLiteralWarning, $datepickerSuppressError, dateParser) {
|
||||
.controller('UibDatepickerController', ['$scope', '$element', '$attrs', '$parse', '$interpolate', '$locale', '$log', 'dateFilter', 'uibDatepickerConfig', '$datepickerLiteralWarning', '$datepickerSuppressError', 'uibDateParser',
|
||||
function($scope, $element, $attrs, $parse, $interpolate, $locale, $log, dateFilter, datepickerConfig, $datepickerLiteralWarning, $datepickerSuppressError, dateParser) {
|
||||
var self = this,
|
||||
ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl;
|
||||
ngModelOptions = {},
|
||||
watchListeners = [],
|
||||
optionsUsed = !!$attrs.datepickerOptions;
|
||||
watchListeners = [];
|
||||
|
||||
$element.addClass('uib-datepicker');
|
||||
$attrs.$set('role', 'application');
|
||||
|
||||
if (!$scope.datepickerOptions) {
|
||||
$scope.datepickerOptions = {};
|
||||
@@ -52,6 +55,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
|
||||
'maxMode',
|
||||
'minDate',
|
||||
'minMode',
|
||||
'monthColumns',
|
||||
'showWeeks',
|
||||
'shortcutPropagation',
|
||||
'startingDay',
|
||||
@@ -77,6 +81,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
|
||||
$interpolate($scope.datepickerOptions[key])($scope.$parent) :
|
||||
datepickerConfig[key];
|
||||
break;
|
||||
case 'monthColumns':
|
||||
case 'showWeeks':
|
||||
case 'shortcutPropagation':
|
||||
case 'yearColumns':
|
||||
@@ -156,7 +161,9 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
|
||||
|
||||
this.init = function(ngModelCtrl_) {
|
||||
ngModelCtrl = ngModelCtrl_;
|
||||
ngModelOptions = ngModelCtrl_.$options || datepickerConfig.ngModelOptions;
|
||||
ngModelOptions = ngModelCtrl_.$options ||
|
||||
$scope.datepickerOptions.ngModelOptions ||
|
||||
datepickerConfig.ngModelOptions;
|
||||
if ($scope.datepickerOptions.initDate) {
|
||||
self.activeDate = dateParser.fromTimezone($scope.datepickerOptions.initDate, ngModelOptions.timezone) || new Date();
|
||||
$scope.$watch('datepickerOptions.initDate', function(initDate) {
|
||||
@@ -169,8 +176,9 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
|
||||
self.activeDate = new Date();
|
||||
}
|
||||
|
||||
this.activeDate = ngModelCtrl.$modelValue ?
|
||||
dateParser.fromTimezone(new Date(ngModelCtrl.$modelValue), ngModelOptions.timezone) :
|
||||
var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : new Date();
|
||||
this.activeDate = !isNaN(date) ?
|
||||
dateParser.fromTimezone(date, ngModelOptions.timezone) :
|
||||
dateParser.fromTimezone(new Date(), ngModelOptions.timezone);
|
||||
|
||||
ngModelCtrl.$render = function() {
|
||||
@@ -327,6 +335,12 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
|
||||
}
|
||||
};
|
||||
|
||||
$element.on('keydown', function(evt) {
|
||||
$scope.$apply(function() {
|
||||
$scope.keydown(evt);
|
||||
});
|
||||
});
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
//Clear all watch listeners on destroy
|
||||
while (watchListeners.length) {
|
||||
@@ -477,7 +491,8 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
|
||||
}
|
||||
|
||||
scope.title = dateFilter(this.activeDate, this.formatMonthTitle);
|
||||
scope.rows = this.split(months, 3);
|
||||
scope.rows = this.split(months, this.monthColumns);
|
||||
scope.yearHeaderColspan = this.monthColumns > 3 ? this.monthColumns - 2 : 1;
|
||||
};
|
||||
|
||||
this.compare = function(date1, date2) {
|
||||
@@ -494,11 +509,11 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
|
||||
if (key === 'left') {
|
||||
date = date - 1;
|
||||
} else if (key === 'up') {
|
||||
date = date - 3;
|
||||
date = date - this.monthColumns;
|
||||
} else if (key === 'right') {
|
||||
date = date + 1;
|
||||
} else if (key === 'down') {
|
||||
date = date + 3;
|
||||
date = date + this.monthColumns;
|
||||
} else if (key === 'pageup' || key === 'pagedown') {
|
||||
var year = this.activeDate.getFullYear() + (key === 'pageup' ? - 1 : 1);
|
||||
this.activeDate.setFullYear(year);
|
||||
@@ -569,7 +584,6 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
|
||||
|
||||
.directive('uibDatepicker', function() {
|
||||
return {
|
||||
replace: true,
|
||||
templateUrl: function(element, attrs) {
|
||||
return attrs.templateUrl || 'uib/template/datepicker/datepicker.html';
|
||||
},
|
||||
@@ -577,6 +591,7 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
|
||||
datepickerOptions: '=?'
|
||||
},
|
||||
require: ['uibDatepicker', '^ngModel'],
|
||||
restrict: 'A',
|
||||
controller: 'UibDatepickerController',
|
||||
controllerAs: 'datepicker',
|
||||
link: function(scope, element, attrs, ctrls) {
|
||||
@@ -589,11 +604,11 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
|
||||
|
||||
.directive('uibDaypicker', function() {
|
||||
return {
|
||||
replace: true,
|
||||
templateUrl: function(element, attrs) {
|
||||
return attrs.templateUrl || 'uib/template/datepicker/day.html';
|
||||
},
|
||||
require: ['^uibDatepicker', 'uibDaypicker'],
|
||||
restrict: 'A',
|
||||
controller: 'UibDaypickerController',
|
||||
link: function(scope, element, attrs, ctrls) {
|
||||
var datepickerCtrl = ctrls[0],
|
||||
@@ -606,11 +621,11 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
|
||||
|
||||
.directive('uibMonthpicker', function() {
|
||||
return {
|
||||
replace: true,
|
||||
templateUrl: function(element, attrs) {
|
||||
return attrs.templateUrl || 'uib/template/datepicker/month.html';
|
||||
},
|
||||
require: ['^uibDatepicker', 'uibMonthpicker'],
|
||||
restrict: 'A',
|
||||
controller: 'UibMonthpickerController',
|
||||
link: function(scope, element, attrs, ctrls) {
|
||||
var datepickerCtrl = ctrls[0],
|
||||
@@ -623,11 +638,11 @@ angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootst
|
||||
|
||||
.directive('uibYearpicker', function() {
|
||||
return {
|
||||
replace: true,
|
||||
templateUrl: function(element, attrs) {
|
||||
return attrs.templateUrl || 'uib/template/datepicker/year.html';
|
||||
},
|
||||
require: ['^uibDatepicker', 'uibYearpicker'],
|
||||
restrict: 'A',
|
||||
controller: 'UibYearpickerController',
|
||||
link: function(scope, element, attrs, ctrls) {
|
||||
var ctrl = ctrls[0];
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
<h4>Inline</h4>
|
||||
<div style="display:inline-block; min-height:290px;">
|
||||
<uib-datepicker ng-model="dt" class="well well-sm" datepicker-options="options"></uib-datepicker>
|
||||
<div uib-datepicker ng-model="dt" class="well well-sm" datepicker-options="options"></div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
@@ -13,7 +13,7 @@ The datepicker has 3 modes:
|
||||
* `ng-model`
|
||||
<small class="badge">$</small>
|
||||
<i class="glyphicon glyphicon-eye-open"></i> -
|
||||
The date object. Needs to be a Javascript Date object.
|
||||
The date object. Must be a Javascript `Date` object. You may use the `uibDateParser` service to assist in string-to-object conversion.
|
||||
|
||||
* `ng-model-options`
|
||||
<small class="badge">$</small>
|
||||
@@ -104,6 +104,16 @@ Apart from the previous settings, to configure the uib-datepicker you need to cr
|
||||
_(Default: `day`)_ -
|
||||
Sets a lower limit for mode.
|
||||
|
||||
* `monthColumns`
|
||||
<small class="badge">C</small>
|
||||
_(Default: `3`)_ -
|
||||
Number of columns displayed in month selection.
|
||||
|
||||
* `ngModelOptions`
|
||||
<small class="badge">C</small>
|
||||
_(Default: `null`)_ -
|
||||
Sets `ngModelOptions` for datepicker. This can be overridden through attribute usage
|
||||
|
||||
* `shortcutPropagation`
|
||||
<small class="badge">C</small>
|
||||
_(Default: `false`)_ -
|
||||
@@ -118,7 +128,7 @@ Apart from the previous settings, to configure the uib-datepicker you need to cr
|
||||
<small class="badge">C</small>
|
||||
*(Default: `$locale.DATETIME_FORMATS.FIRSTDAYOFWEEK`)* -
|
||||
Starting day of the week from 0-6 (0=Sunday, ..., 6=Saturday).
|
||||
|
||||
|
||||
* `yearRows`
|
||||
<small class="badge">C</small>
|
||||
_(Default: `4`)_ -
|
||||
|
||||
@@ -26,8 +26,12 @@ describe('datepicker', function() {
|
||||
});
|
||||
}));
|
||||
|
||||
function getTitleCell() {
|
||||
return element.find('th').eq(1);
|
||||
}
|
||||
|
||||
function getTitleButton() {
|
||||
return element.find('th').eq(1).find('button').first();
|
||||
return getTitleCell().find('button').first();
|
||||
}
|
||||
|
||||
function getTitle() {
|
||||
@@ -155,7 +159,7 @@ describe('datepicker', function() {
|
||||
$scope.options = {
|
||||
minDate: '1984-01-01'
|
||||
};
|
||||
element = $compile('<uib-datepicker ng-model="locals.date" datepicker-options="options"></uib-datepicker>')($scope);
|
||||
element = $compile('<div uib-datepicker ng-model="locals.date" datepicker-options="options"></div>')($scope);
|
||||
$scope.$digest();
|
||||
|
||||
expect($log.warn).toHaveBeenCalledWith('Literal date support has been deprecated, please switch to date object usage');
|
||||
@@ -175,7 +179,7 @@ describe('datepicker', function() {
|
||||
$scope.options = {
|
||||
minDate: '1984-01-01'
|
||||
};
|
||||
element = $compile('<uib-datepicker ng-model="locals.date" datepicker-options="options"></uib-datepicker>')($scope);
|
||||
element = $compile('<div uib-datepicker ng-model="locals.date" datepicker-options="options"></div>')($scope);
|
||||
$scope.$digest();
|
||||
|
||||
expect($log.warn).not.toHaveBeenCalled();
|
||||
@@ -192,7 +196,7 @@ describe('datepicker', function() {
|
||||
$scope.options = {
|
||||
maxDate: '1984-01-01'
|
||||
};
|
||||
element = $compile('<uib-datepicker ng-model="locals.date" datepicker-options="options"></uib-datepicker>')($scope);
|
||||
element = $compile('<div uib-datepicker ng-model="locals.date" datepicker-options="options"></div>')($scope);
|
||||
$scope.$digest();
|
||||
|
||||
expect($log.warn).toHaveBeenCalledWith('Literal date support has been deprecated, please switch to date object usage');
|
||||
@@ -212,7 +216,7 @@ describe('datepicker', function() {
|
||||
$scope.options = {
|
||||
maxDate: '1984-01-01'
|
||||
};
|
||||
element = $compile('<uib-datepicker ng-model="locals.date" datepicker-options="options"></uib-datepicker>')($scope);
|
||||
element = $compile('<div uib-datepicker ng-model="locals.date" datepicker-options="options"></div>')($scope);
|
||||
$scope.$digest();
|
||||
|
||||
expect($log.warn).not.toHaveBeenCalled();
|
||||
@@ -232,7 +236,7 @@ describe('datepicker', function() {
|
||||
});
|
||||
|
||||
spyOn($log, 'error');
|
||||
element = $compile('<uib-datepicker ng-model="locals.date"></uib-datepicker>')($scope);
|
||||
element = $compile('<div uib-datepicker ng-model="locals.date"></div>')($scope);
|
||||
|
||||
$scope.locals = {
|
||||
date: 'lalala'
|
||||
@@ -253,7 +257,7 @@ describe('datepicker', function() {
|
||||
});
|
||||
|
||||
spyOn($log, 'error');
|
||||
element = $compile('<uib-datepicker ng-model="locals.date"></uib-datepicker>')($scope);
|
||||
element = $compile('<div uib-datepicker ng-model="locals.date"></div>')($scope);
|
||||
|
||||
$scope.locals = {
|
||||
date: 'lalala'
|
||||
@@ -274,7 +278,7 @@ describe('datepicker', function() {
|
||||
});
|
||||
spyOn($log, 'error');
|
||||
|
||||
element = $compile('<uib-datepicker ng-model="locals.date"></uib-datepicker>')($scope);
|
||||
element = $compile('<div uib-datepicker ng-model="locals.date"></div>')($scope);
|
||||
|
||||
$scope.locals = {
|
||||
date: 'lalala'
|
||||
@@ -305,7 +309,7 @@ describe('datepicker', function() {
|
||||
var baseTime = new Date(2015, 2, 23);
|
||||
jasmine.clock().mockDate(baseTime);
|
||||
|
||||
element = $compile('<uib-datepicker ng-model="fooDate"></uib-datepicker')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="fooDate"></div')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element.controller('uibDatepicker').activeDate.getTime()).toEqual(baseTime.getTime());
|
||||
@@ -315,10 +319,10 @@ describe('datepicker', function() {
|
||||
it('should support custom templates', function() {
|
||||
$templateCache.put('foo/bar.html', '<div>baz</div>');
|
||||
|
||||
element = $compile('<uib-datepicker ng-model="date" template-url="foo/bar.html"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" template-url="foo/bar.html"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element.html()).toBe('baz');
|
||||
expect(element.html()).toBe('<div>baz</div>');
|
||||
});
|
||||
|
||||
it('should support custom day, month and year templates', function() {
|
||||
@@ -327,15 +331,15 @@ describe('datepicker', function() {
|
||||
$templateCache.put('foo/year.html', '<div>year</div>');
|
||||
|
||||
$templateCache.put('foo/bar.html', '<div>' +
|
||||
'<uib-daypicker template-url="foo/day.html"></uib-daypicker>' +
|
||||
'<uib-monthpicker template-url="foo/month.html"></uib-monthpicker>' +
|
||||
'<uib-yearpicker template-url="foo/year.html"></uib-yearpicker>' +
|
||||
'<div uib-daypicker template-url="foo/day.html"></div>' +
|
||||
'<div uib-monthpicker template-url="foo/month.html"></div>' +
|
||||
'<div uib-yearpicker template-url="foo/year.html"></div>' +
|
||||
'</div>');
|
||||
|
||||
element = $compile('<uib-datepicker ng-model="date" template-url="foo/bar.html"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" template-url="foo/bar.html"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
var expectedHtml = '<div template-url="foo/day.html">day</div><div template-url="foo/month.html">month</div><div template-url="foo/year.html">year</div>';
|
||||
var expectedHtml = '<div><div uib-daypicker="" template-url="foo/day.html"><div>day</div></div><div uib-monthpicker="" template-url="foo/month.html"><div>month</div></div><div uib-yearpicker="" template-url="foo/year.html"><div>year</div></div></div>';
|
||||
|
||||
expect(element.html()).toBe(expectedHtml);
|
||||
});
|
||||
@@ -343,22 +347,22 @@ describe('datepicker', function() {
|
||||
it('should expose the controller in the template', function() {
|
||||
$templateCache.put('uib/template/datepicker/datepicker.html', '<div>{{datepicker.text}}</div>');
|
||||
|
||||
element = $compile('<uib-datepicker ng-model="date"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
var ctrl = element.controller('uib-datepicker');
|
||||
expect(ctrl).toBeDefined();
|
||||
expect(element.html()).toBe('');
|
||||
expect(element.html()).toBe('<div class="ng-binding"></div>');
|
||||
|
||||
ctrl.text = 'baz';
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element.html()).toBe('baz');
|
||||
expect(element.html()).toBe('<div class="ng-binding">baz</div>');
|
||||
});
|
||||
|
||||
describe('basic functionality', function() {
|
||||
beforeEach(function() {
|
||||
element = $compile('<uib-datepicker ng-model="date"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -953,12 +957,29 @@ describe('datepicker', function() {
|
||||
});
|
||||
|
||||
describe('attribute `datepicker-options`', function() {
|
||||
describe('ngModelOptions', function() {
|
||||
beforeEach(inject(function() {
|
||||
$rootScope.date = new Date('2005-11-07T10:00:00.000Z');
|
||||
$rootScope.options = {
|
||||
ngModelOptions: {
|
||||
timezone: '+600'
|
||||
}
|
||||
};
|
||||
element = $compile('<div uib-datepicker ng-model="date" datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
|
||||
it('supports ngModelOptions from options object and sets date to appropriate date', function() {
|
||||
expectSelectedElement(8);
|
||||
});
|
||||
});
|
||||
|
||||
describe('startingDay', function() {
|
||||
beforeEach(function() {
|
||||
$rootScope.options = {
|
||||
startingDay: 1
|
||||
};
|
||||
element = $compile('<uib-datepicker ng-model="date" datepicker-options="options"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -987,7 +1008,7 @@ describe('datepicker', function() {
|
||||
$rootScope.options = {
|
||||
showWeeks: false
|
||||
};
|
||||
element = $compile('<uib-datepicker ng-model="date" datepicker-options="options"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -1004,7 +1025,7 @@ describe('datepicker', function() {
|
||||
beforeEach(function() {
|
||||
$rootScope.options = {};
|
||||
$rootScope.date = new Date('September 10, 2010');
|
||||
element = $compile('<uib-datepicker ng-model="date" datepicker-options="options"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -1029,7 +1050,7 @@ describe('datepicker', function() {
|
||||
$rootScope.options = {
|
||||
minDate: new Date('September 12, 2010')
|
||||
};
|
||||
element = $compile('<uib-datepicker ng-model="date" datepicker-options="options"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -1114,7 +1135,7 @@ describe('datepicker', function() {
|
||||
|
||||
it('accepts literals, \'yyyy-MM-dd\' case', function() {
|
||||
$rootScope.options.minDate = '2010-09-05';
|
||||
element = $compile('<uib-datepicker ng-model="date" datepicker-options="options"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
var buttons = getAllOptionsEl();
|
||||
angular.forEach(buttons, function(button, index) {
|
||||
@@ -1127,7 +1148,7 @@ describe('datepicker', function() {
|
||||
beforeEach(function() {
|
||||
$rootScope.options = {};
|
||||
$rootScope.date = new Date('September 10, 2010');
|
||||
element = $compile('<uib-datepicker ng-model="date" datepicker-options="options"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -1152,7 +1173,7 @@ describe('datepicker', function() {
|
||||
$rootScope.options = {
|
||||
maxDate: new Date('September 25, 2010')
|
||||
};
|
||||
element = $compile('<uib-datepicker ng-model="date" datepicker-options="options"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -1244,8 +1265,8 @@ describe('datepicker', function() {
|
||||
yearColumns: 4,
|
||||
yearRows: 3
|
||||
};
|
||||
element = $compile('<uib-datepicker ng-model="date"' +
|
||||
'datepicker-options="options"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date"' +
|
||||
'datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -1308,8 +1329,9 @@ describe('datepicker', function() {
|
||||
uibDatepickerConfig.yearRows = 2;
|
||||
uibDatepickerConfig.yearColumns = 5;
|
||||
uibDatepickerConfig.startingDay = 6;
|
||||
uibDatepickerConfig.monthColumns = 4;
|
||||
|
||||
element = $compile('<uib-datepicker ng-model="date"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
afterEach(inject(function(uibDatepickerConfig) {
|
||||
@@ -1329,13 +1351,17 @@ describe('datepicker', function() {
|
||||
|
||||
expect(getTitle()).toBe('10');
|
||||
expect(getOptions()).toEqual([
|
||||
['Jan', 'Feb', 'Mar'],
|
||||
['Apr', 'May', 'Jun'],
|
||||
['Jul', 'Aug', 'Sep'],
|
||||
['Oct', 'Nov', 'Dec']
|
||||
['Jan', 'Feb', 'Mar', 'Apr'],
|
||||
['May', 'Jun', 'Jul', 'Aug'],
|
||||
['Sep', 'Oct', 'Nov', 'Dec']
|
||||
]);
|
||||
});
|
||||
|
||||
it('shows title year button to expand to fill width in `month` mode', function() {
|
||||
clickTitleButton();
|
||||
expect(getTitleCell().attr('colspan')).toBe('2');
|
||||
});
|
||||
|
||||
it('changes the title, year format & range in `year` mode', function() {
|
||||
clickTitleButton();
|
||||
clickTitleButton();
|
||||
@@ -1370,7 +1396,7 @@ describe('datepicker', function() {
|
||||
|
||||
describe('disabled', function() {
|
||||
beforeEach(function() {
|
||||
element = $compile('<uib-datepicker ng-model="date" disabled></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" disabled></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -1384,7 +1410,7 @@ describe('datepicker', function() {
|
||||
describe('ng-disabled', function() {
|
||||
beforeEach(function() {
|
||||
$rootScope.disabled = false;
|
||||
element = $compile('<uib-datepicker ng-model="date" ng-disabled="disabled"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" ng-disabled="disabled"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -1425,7 +1451,7 @@ describe('datepicker', function() {
|
||||
|
||||
describe('basics', function() {
|
||||
beforeEach(function() {
|
||||
element = $compile('<uib-datepicker ng-model="date"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -1444,7 +1470,7 @@ describe('datepicker', function() {
|
||||
initDate: new Date('2006-01-01T00:00:00.000Z')
|
||||
};
|
||||
$rootScope.date = null;
|
||||
element = $compile('<uib-datepicker ng-model="date" datepicker-options="options"><uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getTitle()).toEqual('January 2006');
|
||||
@@ -1454,7 +1480,7 @@ describe('datepicker', function() {
|
||||
$rootScope.options = {
|
||||
minDate: new Date('2010-10-01T00:00:00.000Z')
|
||||
};
|
||||
element = $compile('<uib-datepicker ng-model="date" datepicker-options="options"><uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getSelectedElement().prop('disabled')).toBe(true);
|
||||
@@ -1467,7 +1493,7 @@ describe('datepicker', function() {
|
||||
beforeEach(inject(function() {
|
||||
$rootScope.date = new Date('2005-11-07T10:00:00.000Z');
|
||||
$rootScope.ngModelOptions = { timezone: '+600'};
|
||||
element = $compile('<uib-datepicker ng-model="date" ng-model-options="ngModelOptions"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" ng-model-options="ngModelOptions"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
|
||||
@@ -1485,7 +1511,7 @@ describe('datepicker', function() {
|
||||
describe('with empty initial state', function() {
|
||||
beforeEach(inject(function() {
|
||||
$rootScope.date = null;
|
||||
element = $compile('<uib-datepicker ng-model="date"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
|
||||
@@ -1514,7 +1540,7 @@ describe('datepicker', function() {
|
||||
$rootScope.options = {
|
||||
initDate: new Date('November 9, 1980')
|
||||
};
|
||||
element = $compile('<uib-datepicker ng-model="date" datepicker-options="options"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
|
||||
@@ -1533,7 +1559,7 @@ describe('datepicker', function() {
|
||||
$rootScope.options = {
|
||||
datepickerMode: 'month'
|
||||
};
|
||||
element = $compile('<uib-datepicker ng-model="date" datepicker-options="options"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
|
||||
@@ -1554,7 +1580,7 @@ describe('datepicker', function() {
|
||||
minMode: 'month',
|
||||
datepickerMode: 'month'
|
||||
};
|
||||
element = $compile('<uib-datepicker ng-model="date" datepicker-options="options"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
|
||||
@@ -1584,7 +1610,7 @@ describe('datepicker', function() {
|
||||
$rootScope.options = {
|
||||
maxMode: 'month'
|
||||
};
|
||||
element = $compile('<uib-datepicker ng-model="date" datepicker-options="options"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
|
||||
@@ -1632,7 +1658,7 @@ describe('datepicker', function() {
|
||||
|
||||
// Use dateModel directive to add formatters and parsers to the
|
||||
// ngModelController that translate the custom date object.
|
||||
element = $compile('<uib-datepicker ng-model="date" date-model></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" date-model></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
|
||||
@@ -1657,7 +1683,7 @@ describe('datepicker', function() {
|
||||
}));
|
||||
|
||||
it('with the default starting day (sunday)', function() {
|
||||
element = $compile('<uib-datepicker ng-model="date"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getWeeks()).toEqual(['23', '24', '25', '26', '27', '28']);
|
||||
@@ -1668,7 +1694,7 @@ describe('datepicker', function() {
|
||||
$rootScope.options = {
|
||||
startingDay: 1
|
||||
};
|
||||
element = $compile('<uib-datepicker ng-model="date" datepicker-options="options"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getWeeks()).toEqual(['22', '23', '24', '25', '26', '27']);
|
||||
@@ -1678,7 +1704,7 @@ describe('datepicker', function() {
|
||||
$rootScope.options = {
|
||||
startingDay: 4
|
||||
};
|
||||
element = $compile('<uib-datepicker ng-model="date" datepicker-options="options"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getWeeks()).toEqual(['22', '23', '24', '25', '26', '27']);
|
||||
@@ -1688,7 +1714,7 @@ describe('datepicker', function() {
|
||||
$rootScope.options = {
|
||||
startingDay: 6
|
||||
};
|
||||
element = $compile('<uib-datepicker ng-model="date" datepicker-options="options"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date" datepicker-options="options"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getWeeks()).toEqual(['23', '24', '25', '26', '27', '28']);
|
||||
@@ -1698,7 +1724,7 @@ describe('datepicker', function() {
|
||||
describe('first week in january', function() {
|
||||
it('in current year', function() {
|
||||
$rootScope.date = new Date('January 07, 2014');
|
||||
element = $compile('<uib-datepicker ng-model="date"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getWeeks()).toEqual(['1', '2', '3', '4', '5', '6']);
|
||||
@@ -1706,7 +1732,7 @@ describe('datepicker', function() {
|
||||
|
||||
it('in last year', function() {
|
||||
$rootScope.date = new Date('January 07, 2010');
|
||||
element = $compile('<uib-datepicker ng-model="date"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getWeeks()).toEqual(['53', '1', '2', '3', '4', '5']);
|
||||
@@ -1719,7 +1745,7 @@ describe('datepicker', function() {
|
||||
}));
|
||||
|
||||
it('in next year', function() {
|
||||
element = $compile('<uib-datepicker ng-model="date"></uib-datepicker>')($rootScope);
|
||||
element = $compile('<div uib-datepicker ng-model="date"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getWeeks()).toEqual(['49', '50', '51', '52', '1', '2']);
|
||||
|
||||
@@ -57,6 +57,11 @@ Add the ability to override the template used on the component (inner uib-datepi
|
||||
_(Default: `false`)_ -
|
||||
Whether or not to show the datepicker.
|
||||
|
||||
* `ng-model`
|
||||
<small class="badge">$</small>
|
||||
<i class="glyphicon glyphicon-eye-open"></i> -
|
||||
The date object. Must be a Javascript `Date` object. You may use the `uibDateParser` service to assist in string-to-object conversion.
|
||||
|
||||
* `on-open-focus`
|
||||
<small class="badge">$</small>
|
||||
<small class="badge">C</small>
|
||||
|
||||
@@ -5,6 +5,6 @@ require('./popup.js');
|
||||
|
||||
var MODULE_NAME = 'ui.bootstrap.module.datepickerPopup';
|
||||
|
||||
angular.module(MODULE_NAME, ['ui.bootstrap.datepickerPopup', 'uib/template/datepickerPopup/popup.html']);
|
||||
angular.module(MODULE_NAME, ['ui.bootstrap.datepickerPopup', 'uib/template/datepickerPopup/popup.html', 'ui.bootstrap.module.datepicker']);
|
||||
|
||||
module.exports = MODULE_NAME;
|
||||
|
||||
@@ -28,8 +28,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $
|
||||
isHtml5DateInput = false;
|
||||
var dateFormat, closeOnDateSelection, appendToBody, onOpenFocus,
|
||||
datepickerPopupTemplateUrl, datepickerTemplateUrl, popupEl, datepickerEl, scrollParentEl,
|
||||
ngModel, ngModelOptions, $popup, altInputFormats, watchListeners = [],
|
||||
timezone;
|
||||
ngModel, ngModelOptions, $popup, altInputFormats, watchListeners = [];
|
||||
|
||||
this.init = function(_ngModel_) {
|
||||
ngModel = _ngModel_;
|
||||
@@ -85,19 +84,6 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $
|
||||
|
||||
// popup element used to display calendar
|
||||
popupEl = angular.element('<div uib-datepicker-popup-wrap><div uib-datepicker></div></div>');
|
||||
if (ngModelOptions) {
|
||||
timezone = ngModelOptions.timezone;
|
||||
$scope.ngModelOptions = angular.copy(ngModelOptions);
|
||||
$scope.ngModelOptions.timezone = null;
|
||||
if ($scope.ngModelOptions.updateOnDefault === true) {
|
||||
$scope.ngModelOptions.updateOn = $scope.ngModelOptions.updateOn ?
|
||||
$scope.ngModelOptions.updateOn + ' default' : 'default';
|
||||
}
|
||||
|
||||
popupEl.attr('ng-model-options', 'ngModelOptions');
|
||||
} else {
|
||||
timezone = null;
|
||||
}
|
||||
|
||||
popupEl.attr({
|
||||
'ng-model': 'date',
|
||||
@@ -133,17 +119,17 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $
|
||||
return value;
|
||||
}
|
||||
|
||||
$scope.date = dateParser.fromTimezone(value, timezone);
|
||||
|
||||
if (angular.isNumber($scope.date)) {
|
||||
$scope.date = new Date($scope.date);
|
||||
if (angular.isNumber(value)) {
|
||||
value = new Date(value);
|
||||
}
|
||||
|
||||
$scope.date = value;
|
||||
|
||||
return dateParser.filter($scope.date, dateFormat);
|
||||
});
|
||||
} else {
|
||||
ngModel.$formatters.push(function(value) {
|
||||
$scope.date = dateParser.fromTimezone(value, timezone);
|
||||
$scope.date = value;
|
||||
return value;
|
||||
});
|
||||
}
|
||||
@@ -195,7 +181,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $
|
||||
|
||||
$scope.isDisabled = function(date) {
|
||||
if (date === 'today') {
|
||||
date = dateParser.fromTimezone(new Date(), timezone);
|
||||
date = new Date();
|
||||
}
|
||||
|
||||
var dates = {};
|
||||
@@ -203,7 +189,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $
|
||||
if (!$scope.datepickerOptions[key]) {
|
||||
dates[key] = null;
|
||||
} else if (angular.isDate($scope.datepickerOptions[key])) {
|
||||
dates[key] = dateParser.fromTimezone(new Date($scope.datepickerOptions[key]), timezone);
|
||||
dates[key] = new Date($scope.datepickerOptions[key]);
|
||||
} else {
|
||||
if ($datepickerPopupLiteralWarning) {
|
||||
$log.warn('Literal date support has been deprecated, please switch to date object usage');
|
||||
@@ -224,9 +210,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $
|
||||
|
||||
// Inner change
|
||||
$scope.dateSelection = function(dt) {
|
||||
if (angular.isDefined(dt)) {
|
||||
$scope.date = dt;
|
||||
}
|
||||
$scope.date = dt;
|
||||
var date = $scope.date ? dateParser.filter($scope.date, dateFormat) : null; // Setting to NULL is necessary for form validators to function
|
||||
$element.val(date);
|
||||
ngModel.$setViewValue(date);
|
||||
@@ -344,7 +328,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $
|
||||
if (angular.isString(viewValue)) {
|
||||
var date = parseDateString(viewValue);
|
||||
if (!isNaN(date)) {
|
||||
return dateParser.toTimezone(date, timezone);
|
||||
return date;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,7 +355,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $
|
||||
}
|
||||
|
||||
if (angular.isString(value)) {
|
||||
return !isNaN(parseDateString(viewValue));
|
||||
return !isNaN(parseDateString(value));
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -450,7 +434,7 @@ function($scope, $element, $attrs, $compile, $log, $parse, $window, $document, $
|
||||
|
||||
.directive('uibDatepickerPopupWrap', function() {
|
||||
return {
|
||||
replace: true,
|
||||
restrict: 'A',
|
||||
transclude: true,
|
||||
templateUrl: function(element, attrs) {
|
||||
return attrs.templateUrl || 'uib/template/datepickerPopup/popup.html';
|
||||
|
||||
@@ -175,8 +175,10 @@ describe('datepicker popup', function() {
|
||||
$sniffer = _$sniffer_;
|
||||
|
||||
$rootScope.date = new Date('September 30, 2010 15:30:00');
|
||||
$rootScope.modelOptions = {allowInvalid: true};
|
||||
element = $compile('<div><input ng-model="date" ng-model-options="modelOptions" uib-datepicker-popup></div>')($rootScope);
|
||||
$rootScope.ngModelOptions = {
|
||||
allowInvalid: true
|
||||
};
|
||||
element = $compile('<div><input ng-model="date" ng-model-options="ngModelOptions" uib-datepicker-popup></div>')($rootScope);
|
||||
inputEl = element.find('input');
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
@@ -557,8 +559,13 @@ describe('datepicker popup', function() {
|
||||
$timeout = _$timeout_;
|
||||
$rootScope.isopen = true;
|
||||
$rootScope.date = new Date('2010-09-30T10:00:00.000Z');
|
||||
$rootScope.options = {
|
||||
ngModelOptions: {
|
||||
updateOn: 'default'
|
||||
}
|
||||
};
|
||||
wrapElement = $compile('<div><input ng-model="date" ' +
|
||||
'ng-model-options="{ updateOn: \'default\' }" ' +
|
||||
'datepicker-options="options" ' +
|
||||
'uib-datepicker-popup is-open="isopen"><div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
assignElements(wrapElement);
|
||||
@@ -1034,6 +1041,13 @@ describe('datepicker popup', function() {
|
||||
expect($rootScope.date).toBe(null);
|
||||
});
|
||||
|
||||
it('should clear the previously selected date', function() {
|
||||
$rootScope.date = new Date();
|
||||
$rootScope.$digest();
|
||||
buttons.eq(1).click();
|
||||
expect($rootScope.date).toBe(null);
|
||||
});
|
||||
|
||||
it('should have a button to close calendar', function() {
|
||||
buttons.eq(2).click();
|
||||
assignElements(wrapElement);
|
||||
@@ -1330,7 +1344,7 @@ describe('datepicker popup', function() {
|
||||
$compile(elm)($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(elm.children().eq(1).html()).toBe('baz');
|
||||
expect(elm.children().eq(1).html()).toBe('<div>baz</div>');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1353,7 +1367,7 @@ describe('datepicker popup', function() {
|
||||
|
||||
var datepicker = elm.find('[uib-datepicker]');
|
||||
|
||||
expect(datepicker.html()).toBe('baz');
|
||||
expect(datepicker.html()).toBe('<div>baz</div>');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1598,9 +1612,13 @@ describe('datepicker popup', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
$rootScope.date = new Date('2010-09-30T10:00:00.000Z');
|
||||
$rootScope.ngModelOptions = { timezone: '+600' };
|
||||
$rootScope.options = {
|
||||
ngModelOptions: {
|
||||
timezone: '+600'
|
||||
}
|
||||
};
|
||||
$rootScope.isopen = true;
|
||||
var wrapper = $compile('<div><input ng-model="date" uib-datepicker-popup="MM/dd/yyyy" ng-model-options="ngModelOptions" is-open="isopen"></div>')($rootScope);
|
||||
var wrapper = $compile('<div><input ng-model="date" uib-datepicker-popup="MM/dd/yyyy" datepicker-options="options" is-open="isopen"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
assignElements(wrapper);
|
||||
});
|
||||
@@ -1631,9 +1649,13 @@ describe('datepicker popup', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
$rootScope.date = new Date('2010-09-30T10:00:00.000Z');
|
||||
$rootScope.ngModelOptions = { timezone: '+600' };
|
||||
$rootScope.options = {
|
||||
ngModelOptions: {
|
||||
timezone: '+600'
|
||||
}
|
||||
};
|
||||
$rootScope.isopen = true;
|
||||
var wrapper = $compile('<div><input type="date" ng-model="date" uib-datepicker-popup ng-model-options="ngModelOptions" is-open="isopen"></div>')($rootScope);
|
||||
var wrapper = $compile('<div><input type="date" ng-model="date" uib-datepicker-popup datepicker-options="options" is-open="isopen"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
assignElements(wrapper);
|
||||
});
|
||||
|
||||
@@ -11,7 +11,6 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
this.open = function(dropdownScope, element) {
|
||||
if (!openScope) {
|
||||
$document.on('click', closeDropdown);
|
||||
element.on('keydown', keybindFilter);
|
||||
}
|
||||
|
||||
if (openScope && openScope !== dropdownScope) {
|
||||
@@ -25,7 +24,10 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
if (openScope === dropdownScope) {
|
||||
openScope = null;
|
||||
$document.off('click', closeDropdown);
|
||||
element.off('keydown', keybindFilter);
|
||||
var dropdownMenu = dropdownScope.getDropdownElement();
|
||||
if (dropdownMenu) {
|
||||
dropdownMenu.off('keydown', this.keybindFilter);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -50,13 +52,14 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
}
|
||||
|
||||
openScope.isOpen = false;
|
||||
openScope.focusToggleElement();
|
||||
|
||||
if (!$rootScope.$$phase) {
|
||||
openScope.$apply();
|
||||
}
|
||||
};
|
||||
|
||||
var keybindFilter = function(evt) {
|
||||
this.keybindFilter = function(evt) {
|
||||
if (evt.which === 27) {
|
||||
evt.stopPropagation();
|
||||
openScope.focusToggleElement();
|
||||
@@ -191,7 +194,9 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
if (appendTo && self.dropdownMenu) {
|
||||
var pos = $position.positionElements($element, self.dropdownMenu, 'bottom-left', true),
|
||||
css,
|
||||
rightalign;
|
||||
rightalign,
|
||||
scrollbarPadding,
|
||||
scrollbarWidth = 0;
|
||||
|
||||
css = {
|
||||
top: pos.top + 'px',
|
||||
@@ -204,7 +209,13 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
css.right = 'auto';
|
||||
} else {
|
||||
css.left = 'auto';
|
||||
css.right = window.innerWidth -
|
||||
scrollbarPadding = $position.scrollbarPadding(appendTo);
|
||||
|
||||
if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
|
||||
scrollbarWidth = scrollbarPadding.scrollbarWidth;
|
||||
}
|
||||
|
||||
css.right = window.innerWidth - scrollbarWidth -
|
||||
(pos.left + $element.prop('offsetWidth')) + 'px';
|
||||
}
|
||||
|
||||
@@ -245,13 +256,19 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
var newEl = dropdownElement;
|
||||
self.dropdownMenu.replaceWith(newEl);
|
||||
self.dropdownMenu = newEl;
|
||||
self.dropdownMenu.on('keydown', uibDropdownService.keybindFilter);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
if (self.dropdownMenu) {
|
||||
self.dropdownMenu.on('keydown', uibDropdownService.keybindFilter);
|
||||
}
|
||||
}
|
||||
|
||||
scope.focusToggleElement();
|
||||
uibDropdownService.open(scope, $element);
|
||||
} else {
|
||||
uibDropdownService.close(scope, $element);
|
||||
if (self.dropdownMenuTemplateUrl) {
|
||||
if (templateScope) {
|
||||
templateScope.$destroy();
|
||||
@@ -261,7 +278,6 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
self.dropdownMenu = newEl;
|
||||
}
|
||||
|
||||
uibDropdownService.close(scope, $element);
|
||||
self.selectedOption = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ describe('uib-dropdown', function() {
|
||||
|
||||
describe('basic', function() {
|
||||
function dropdown() {
|
||||
return $compile('<li uib-dropdown><a href uib-dropdown-toggle></a><ul><li><a href>Hello</a></li></ul></li>')($rootScope);
|
||||
return $compile('<li uib-dropdown><a href uib-dropdown-toggle></a><ul uib-dropdown-menu><li><a href>Hello</a></li></ul></li>')($rootScope);
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
@@ -69,9 +69,10 @@ describe('uib-dropdown', function() {
|
||||
});
|
||||
|
||||
it('should close on escape key & focus toggle element', function() {
|
||||
var dropdownMenu = element.find('[uib-dropdown-menu]');
|
||||
$document.find('body').append(element);
|
||||
clickDropdownToggle();
|
||||
var event = triggerKeyDown(element, 27);
|
||||
var event = triggerKeyDown(dropdownMenu, 27);
|
||||
expect(element).not.toHaveClass(dropdownConfig.openClass);
|
||||
expect(element.find('a')).toHaveFocus();
|
||||
expect(event.stopPropagation).toHaveBeenCalled();
|
||||
@@ -108,7 +109,7 @@ describe('uib-dropdown', function() {
|
||||
});
|
||||
|
||||
it('should not toggle if the element has `disabled` class', function() {
|
||||
var elm = $compile('<li uib-dropdown><a class="disabled" uib-dropdown-toggle></a><ul><li>Hello</li></ul></li>')($rootScope);
|
||||
var elm = $compile('<li uib-dropdown><a class="disabled" uib-dropdown-toggle></a><ul uib-dropdown-menu><li>Hello</li></ul></li>')($rootScope);
|
||||
clickDropdownToggle( elm );
|
||||
expect(elm).not.toHaveClass(dropdownConfig.openClass);
|
||||
});
|
||||
@@ -121,7 +122,7 @@ describe('uib-dropdown', function() {
|
||||
|
||||
it('should not toggle if the element has `ng-disabled` as true', function() {
|
||||
$rootScope.isdisabled = true;
|
||||
var elm = $compile('<li uib-dropdown><div ng-disabled="isdisabled" uib-dropdown-toggle></div><ul><li>Hello</li></ul></li>')($rootScope);
|
||||
var elm = $compile('<li uib-dropdown><div ng-disabled="isdisabled" uib-dropdown-toggle></div><ul uib-dropdown-menu><li>Hello</li></ul></li>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
elm.find('div').click();
|
||||
expect(elm).not.toHaveClass(dropdownConfig.openClass);
|
||||
@@ -134,7 +135,7 @@ describe('uib-dropdown', function() {
|
||||
|
||||
it('should unbind events on scope destroy', function() {
|
||||
var $scope = $rootScope.$new();
|
||||
var elm = $compile('<li uib-dropdown><button ng-disabled="isdisabled" uib-dropdown-toggle></button><ul><li>Hello</li></ul></li>')($scope);
|
||||
var elm = $compile('<li uib-dropdown><button ng-disabled="isdisabled" uib-dropdown-toggle></button><ul uib-dropdown-menu><li>Hello</li></ul></li>')($scope);
|
||||
$scope.$digest();
|
||||
|
||||
var buttonEl = elm.find('button');
|
||||
@@ -220,12 +221,28 @@ describe('uib-dropdown', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
element = dropdown();
|
||||
$document.find('body').append(element);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
element.remove();
|
||||
});
|
||||
|
||||
it('adds the menu to the body', function() {
|
||||
expect($document.find('#dropdown-menu').parent()[0]).toBe($document.find('body')[0]);
|
||||
});
|
||||
|
||||
it('focuses the dropdown element on close', function() {
|
||||
var toggle = element.find('[uib-dropdown-toggle]');
|
||||
var menu = $document.find('#dropdown-menu a');
|
||||
toggle.trigger('click');
|
||||
menu.focus();
|
||||
|
||||
menu.trigger('click');
|
||||
|
||||
expect(document.activeElement).toBe(toggle[0]);
|
||||
});
|
||||
|
||||
it('removes the menu when the dropdown is removed', function() {
|
||||
element.remove();
|
||||
$rootScope.$digest();
|
||||
@@ -268,6 +285,17 @@ describe('uib-dropdown', function() {
|
||||
expect(container).not.toHaveClass('uib-dropdown-open');
|
||||
});
|
||||
|
||||
it('focuses the dropdown element on close', function() {
|
||||
var toggle = element.find('[uib-dropdown-toggle]');
|
||||
var menu = $document.find('#dropdown-menu a');
|
||||
toggle.trigger('click');
|
||||
menu.focus();
|
||||
|
||||
menu.trigger('click');
|
||||
|
||||
expect(document.activeElement).toBe(toggle[0]);
|
||||
});
|
||||
|
||||
it('removes the menu when the dropdown is removed', function() {
|
||||
element.remove();
|
||||
$rootScope.$digest();
|
||||
@@ -279,7 +307,7 @@ describe('uib-dropdown', function() {
|
||||
describe('with uib-dropdown-toggle', function() {
|
||||
beforeEach(function() {
|
||||
$rootScope.isopen = true;
|
||||
element = $compile('<li uib-dropdown is-open="isopen"><a href uib-dropdown-toggle></a><ul><li>Hello</li></ul></li>')($rootScope);
|
||||
element = $compile('<li uib-dropdown is-open="isopen"><a href uib-dropdown-toggle></a><ul uib-dropdown-menu><li>Hello</li></ul></li>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -313,7 +341,7 @@ describe('uib-dropdown', function() {
|
||||
describe('without uib-dropdown-toggle', function() {
|
||||
beforeEach(function() {
|
||||
$rootScope.isopen = true;
|
||||
element = $compile('<li uib-dropdown is-open="isopen"><ul><li>Hello</li></ul></li>')($rootScope);
|
||||
element = $compile('<li uib-dropdown is-open="isopen"><ul uib-dropdown-menu><li>Hello</li></ul></li>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -334,7 +362,7 @@ describe('uib-dropdown', function() {
|
||||
beforeEach(function() {
|
||||
$rootScope.toggleHandler = jasmine.createSpy('toggleHandler');
|
||||
$rootScope.isopen = false;
|
||||
element = $compile('<li uib-dropdown on-toggle="toggleHandler(open)" is-open="isopen"><a uib-dropdown-toggle></a><ul><li>Hello</li></ul></li>')($rootScope);
|
||||
element = $compile('<li uib-dropdown on-toggle="toggleHandler(open)" is-open="isopen"><a uib-dropdown-toggle></a><ul uib-dropdown-menu><li>Hello</li></ul></li>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -361,7 +389,7 @@ describe('uib-dropdown', function() {
|
||||
beforeEach(function() {
|
||||
$rootScope.toggleHandler = jasmine.createSpy('toggleHandler');
|
||||
$rootScope.isopen = true;
|
||||
element = $compile('<li uib-dropdown on-toggle="toggleHandler(open)" is-open="isopen"><a uib-dropdown-toggle></a><ul><li>Hello</li></ul></li>')($rootScope);
|
||||
element = $compile('<li uib-dropdown on-toggle="toggleHandler(open)" is-open="isopen"><a uib-dropdown-toggle></a><ul uib-dropdown-menu><li>Hello</li></ul></li>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -389,7 +417,7 @@ describe('uib-dropdown', function() {
|
||||
describe('without is-open', function() {
|
||||
beforeEach(function() {
|
||||
$rootScope.toggleHandler = jasmine.createSpy('toggleHandler');
|
||||
element = $compile('<li uib-dropdown on-toggle="toggleHandler(open)"><a uib-dropdown-toggle></a><ul><li>Hello</li></ul></li>')($rootScope);
|
||||
element = $compile('<li uib-dropdown on-toggle="toggleHandler(open)"><a uib-dropdown-toggle></a><ul uib-dropdown-menu><li>Hello</li></ul></li>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -417,7 +445,7 @@ describe('uib-dropdown', function() {
|
||||
function dropdown(autoClose) {
|
||||
return $compile('<li uib-dropdown ' +
|
||||
(autoClose === undefined ? '' : 'auto-close="' + autoClose + '"') +
|
||||
'><a href uib-dropdown-toggle></a><ul><li><a href>Hello</a></li></ul></li>')($rootScope);
|
||||
'><a href uib-dropdown-toggle></a><ul uib-dropdown-menu><li><a href>Hello</a></li></ul></li>')($rootScope);
|
||||
}
|
||||
|
||||
describe('always', function() {
|
||||
@@ -449,7 +477,7 @@ describe('uib-dropdown', function() {
|
||||
|
||||
it('control with is-open', function() {
|
||||
$rootScope.isopen = true;
|
||||
element = $compile('<li uib-dropdown is-open="isopen" auto-close="disabled"><a href uib-dropdown-toggle></a><ul><li>Hello</li></ul></li>')($rootScope);
|
||||
element = $compile('<li uib-dropdown is-open="isopen" auto-close="disabled"><a href uib-dropdown-toggle></a><ul uib-dropdown-menu><li>Hello</li></ul></li>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element).toHaveClass(dropdownConfig.openClass);
|
||||
@@ -472,9 +500,10 @@ describe('uib-dropdown', function() {
|
||||
|
||||
it('should close anyway if esc is pressed', function() {
|
||||
element = dropdown('disabled');
|
||||
var dropdownMenu = element.find('[uib-dropdown-menu]');
|
||||
$document.find('body').append(element);
|
||||
clickDropdownToggle();
|
||||
triggerKeyDown(element, 27);
|
||||
triggerKeyDown(dropdownMenu, 27);
|
||||
expect(element).not.toHaveClass(dropdownConfig.openClass);
|
||||
expect(element.find('a')).toHaveFocus();
|
||||
});
|
||||
@@ -519,16 +548,17 @@ describe('uib-dropdown', function() {
|
||||
|
||||
describe('using keyboard-nav', function() {
|
||||
function dropdown() {
|
||||
return $compile('<li uib-dropdown keyboard-nav><a href uib-dropdown-toggle></a><ul><li><a href>Hello</a></li><li><a href>Hello Again</a></li></ul></li>')($rootScope);
|
||||
return $compile('<li uib-dropdown keyboard-nav><a href uib-dropdown-toggle></a><ul uib-dropdown-menu><li><a href>Hello</a></li><li><a href>Hello Again</a></li></ul></li>')($rootScope);
|
||||
}
|
||||
beforeEach(function() {
|
||||
element = dropdown();
|
||||
});
|
||||
|
||||
it('should focus first list element when down arrow pressed', function() {
|
||||
var dropdownMenu = element.find('[uib-dropdown-menu]');
|
||||
$document.find('body').append(element);
|
||||
clickDropdownToggle();
|
||||
triggerKeyDown(element, 40);
|
||||
triggerKeyDown(dropdownMenu, 40);
|
||||
|
||||
expect(element).toHaveClass(dropdownConfig.openClass);
|
||||
var optionEl = element.find('ul').eq(0).find('a').eq(0);
|
||||
@@ -536,8 +566,9 @@ describe('uib-dropdown', function() {
|
||||
});
|
||||
|
||||
it('should not focus first list element when down arrow pressed if closed', function() {
|
||||
var dropdownMenu = element.find('[uib-dropdown-menu]');
|
||||
$document.find('body').append(element);
|
||||
triggerKeyDown(element, 40);
|
||||
triggerKeyDown(dropdownMenu, 40);
|
||||
|
||||
expect(element).not.toHaveClass(dropdownConfig.openClass);
|
||||
var focusEl = element.find('ul').eq(0).find('a').eq(0);
|
||||
@@ -545,10 +576,11 @@ describe('uib-dropdown', function() {
|
||||
});
|
||||
|
||||
it('should focus second list element when down arrow pressed twice', function() {
|
||||
var dropdownMenu = element.find('[uib-dropdown-menu]');
|
||||
$document.find('body').append(element);
|
||||
clickDropdownToggle();
|
||||
triggerKeyDown(element, 40);
|
||||
triggerKeyDown(element, 40);
|
||||
triggerKeyDown(dropdownMenu, 40);
|
||||
triggerKeyDown(dropdownMenu, 40);
|
||||
|
||||
expect(element).toHaveClass(dropdownConfig.openClass);
|
||||
var focusEl = element.find('ul').eq(0).find('a').eq(1);
|
||||
@@ -556,19 +588,21 @@ describe('uib-dropdown', function() {
|
||||
});
|
||||
|
||||
it('should not focus first list element when up arrow pressed after dropdown toggled', function() {
|
||||
var dropdownMenu = element.find('[uib-dropdown-menu]');
|
||||
$document.find('body').append(element);
|
||||
clickDropdownToggle();
|
||||
expect(element).toHaveClass(dropdownConfig.openClass);
|
||||
|
||||
triggerKeyDown(element, 38);
|
||||
triggerKeyDown(dropdownMenu, 38);
|
||||
var focusEl = element.find('ul').eq(0).find('a').eq(0);
|
||||
expect(focusEl).not.toHaveFocus();
|
||||
});
|
||||
|
||||
it('should focus last list element when up arrow pressed after dropdown toggled', function() {
|
||||
var dropdownMenu = element.find('[uib-dropdown-menu]');
|
||||
$document.find('body').append(element);
|
||||
clickDropdownToggle();
|
||||
triggerKeyDown(element, 38);
|
||||
triggerKeyDown(dropdownMenu, 38);
|
||||
|
||||
expect(element).toHaveClass(dropdownConfig.openClass);
|
||||
var focusEl = element.find('ul').eq(0).find('a').eq(1);
|
||||
@@ -576,9 +610,10 @@ describe('uib-dropdown', function() {
|
||||
});
|
||||
|
||||
it('should not change focus when other keys are pressed', function() {
|
||||
var dropdownMenu = element.find('[uib-dropdown-menu]');
|
||||
$document.find('body').append(element);
|
||||
clickDropdownToggle();
|
||||
triggerKeyDown(element, 37);
|
||||
triggerKeyDown(dropdownMenu, 37);
|
||||
|
||||
expect(element).toHaveClass(dropdownConfig.openClass);
|
||||
var focusEl = element.find('ul').eq(0).find('a');
|
||||
@@ -587,12 +622,13 @@ describe('uib-dropdown', function() {
|
||||
});
|
||||
|
||||
it('should focus first list element when down arrow pressed 2x and up pressed 1x', function() {
|
||||
var dropdownMenu = element.find('[uib-dropdown-menu]');
|
||||
$document.find('body').append(element);
|
||||
clickDropdownToggle();
|
||||
triggerKeyDown(element, 40);
|
||||
triggerKeyDown(element, 40);
|
||||
triggerKeyDown(dropdownMenu, 40);
|
||||
triggerKeyDown(dropdownMenu, 40);
|
||||
|
||||
triggerKeyDown(element, 38);
|
||||
triggerKeyDown(dropdownMenu, 38);
|
||||
|
||||
expect(element).toHaveClass(dropdownConfig.openClass);
|
||||
var focusEl = element.find('ul').eq(0).find('a').eq(0);
|
||||
@@ -600,10 +636,11 @@ describe('uib-dropdown', function() {
|
||||
});
|
||||
|
||||
it('should stay focused on final list element if down pressed at list end', function() {
|
||||
var dropdownMenu = element.find('[uib-dropdown-menu]');
|
||||
$document.find('body').append(element);
|
||||
clickDropdownToggle();
|
||||
triggerKeyDown(element, 40);
|
||||
triggerKeyDown(element, 40);
|
||||
triggerKeyDown(dropdownMenu, 40);
|
||||
triggerKeyDown(dropdownMenu, 40);
|
||||
|
||||
expect(element).toHaveClass(dropdownConfig.openClass);
|
||||
var focusEl = element.find('ul').eq(0).find('a').eq(1);
|
||||
@@ -615,16 +652,17 @@ describe('uib-dropdown', function() {
|
||||
|
||||
it('should close if esc is pressed while focused', function() {
|
||||
element = dropdown('disabled');
|
||||
var dropdownMenu = element.find('[uib-dropdown-menu]');
|
||||
$document.find('body').append(element);
|
||||
clickDropdownToggle();
|
||||
|
||||
triggerKeyDown(element, 40);
|
||||
triggerKeyDown(dropdownMenu, 40);
|
||||
|
||||
expect(element).toHaveClass(dropdownConfig.openClass);
|
||||
var focusEl = element.find('ul').eq(0).find('a').eq(0);
|
||||
expect(focusEl).toHaveFocus();
|
||||
|
||||
triggerKeyDown(element, 27);
|
||||
triggerKeyDown(dropdownMenu, 27);
|
||||
expect(element).not.toHaveClass(dropdownConfig.openClass);
|
||||
});
|
||||
|
||||
@@ -640,10 +678,10 @@ describe('uib-dropdown', function() {
|
||||
it('should focus first list element when down arrow pressed', function() {
|
||||
clickDropdownToggle();
|
||||
|
||||
triggerKeyDown(element, 40);
|
||||
|
||||
var dropdownMenu = $document.find('#dropdown-menu');
|
||||
|
||||
triggerKeyDown(dropdownMenu, 40);
|
||||
|
||||
expect(dropdownMenu.parent()).toHaveClass(dropdownConfig.appendToOpenClass);
|
||||
var focusEl = $document.find('ul').eq(0).find('a');
|
||||
expect(focusEl).toHaveFocus();
|
||||
@@ -651,11 +689,10 @@ describe('uib-dropdown', function() {
|
||||
|
||||
it('should focus second list element when down arrow pressed twice', function() {
|
||||
clickDropdownToggle();
|
||||
triggerKeyDown(element, 40);
|
||||
triggerKeyDown(element, 40);
|
||||
triggerKeyDown(element, 40);
|
||||
|
||||
var dropdownMenu = $document.find('#dropdown-menu');
|
||||
triggerKeyDown(dropdownMenu, 40);
|
||||
triggerKeyDown(dropdownMenu, 40);
|
||||
triggerKeyDown(dropdownMenu, 40);
|
||||
|
||||
expect(dropdownMenu.parent()).toHaveClass(dropdownConfig.appendToOpenClass);
|
||||
var elem1 = $document.find('ul');
|
||||
@@ -665,4 +702,34 @@ describe('uib-dropdown', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// issue #5942
|
||||
describe('using dropdown-append-to-body with dropdown-menu-right class', function() {
|
||||
function dropdown() {
|
||||
return $compile('<li style="float: right;" uib-dropdown dropdown-append-to-body><a href uib-dropdown-toggle>Toggle menu</a><ul uib-dropdown-menu class="dropdown-menu-right" id="dropdown-menu"><li><a href>Hello On Body</a></li></ul></li>')($rootScope);
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
element = dropdown();
|
||||
$document.find('body').append(element);
|
||||
|
||||
var menu = $document.find('#dropdown-menu');
|
||||
menu.css('position', 'absolute');
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
element.remove();
|
||||
});
|
||||
|
||||
it('should align the menu correctly when the body has no vertical scrollbar', function() {
|
||||
var toggle = element.find('[uib-dropdown-toggle]');
|
||||
var menu = $document.find('#dropdown-menu');
|
||||
toggle.trigger('click');
|
||||
|
||||
// Get the offsets of the rightmost position of both the toggle and the menu (offset from the left of the window)
|
||||
var toggleRight = Math.round(toggle.offset().left + toggle.outerWidth());
|
||||
var menuRight = Math.round(menu.offset().left + menu.outerWidth());
|
||||
expect(menuRight).toBe(toggleRight);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -135,3 +135,5 @@ Events fired:
|
||||
##### UI Router resolves
|
||||
|
||||
If one wants to have the modal resolve using [UI Router's](https://github.com/angular-ui/ui-router) pre-1.0 resolve mechanism, one can call `$uibResolve.setResolver('$resolve')` in the configuration phase of the application. One can also provide a custom resolver as well, as long as the signature conforms to UI Router's [$resolve](http://angular-ui.github.io/ui-router/site/#/api/ui.router.util.$resolve).
|
||||
|
||||
When the modal is opened with a controller, a `$resolve` object is exposed on the template with the resolved values from the resolve object.
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
require('../position/index-nocss.js');
|
||||
require('../stackedMap');
|
||||
require('../../template/modal/backdrop.html.js');
|
||||
require('../../template/modal/window.html.js');
|
||||
require('./modal');
|
||||
|
||||
var MODULE_NAME = 'ui.bootstrap.module.modal';
|
||||
|
||||
angular.module(MODULE_NAME, ['ui.bootstrap.modal', 'uib/template/modal/backdrop.html', 'uib/template/modal/window.html']);
|
||||
angular.module(MODULE_NAME, ['ui.bootstrap.modal', 'uib/template/modal/window.html']);
|
||||
|
||||
module.exports = MODULE_NAME;
|
||||
|
||||
+53
-40
@@ -106,8 +106,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
.directive('uibModalBackdrop', ['$animate', '$injector', '$uibModalStack',
|
||||
function($animate, $injector, $modalStack) {
|
||||
return {
|
||||
replace: true,
|
||||
templateUrl: 'uib/template/modal/backdrop.html',
|
||||
restrict: 'A',
|
||||
compile: function(tElement, tAttrs) {
|
||||
tElement.addClass(tAttrs.backdropClass);
|
||||
return linkFn;
|
||||
@@ -136,13 +135,12 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
scope: {
|
||||
index: '@'
|
||||
},
|
||||
replace: true,
|
||||
restrict: 'A',
|
||||
transclude: true,
|
||||
templateUrl: function(tElement, tAttrs) {
|
||||
return tAttrs.templateUrl || 'uib/template/modal/window.html';
|
||||
},
|
||||
link: function(scope, element, attrs) {
|
||||
element.addClass(attrs.windowClass || '');
|
||||
element.addClass(attrs.windowTopClass || '');
|
||||
scope.size = attrs.size;
|
||||
|
||||
@@ -167,12 +165,9 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
|
||||
// Deferred object that will be resolved when this modal is render.
|
||||
var modalRenderDeferObj = $q.defer();
|
||||
// Observe function will be called on next digest cycle after compilation, ensuring that the DOM is ready.
|
||||
// In order to use this way of finding whether DOM is ready, we need to observe a scope property used in modal's template.
|
||||
attrs.$observe('modalRender', function(value) {
|
||||
if (value === 'true') {
|
||||
modalRenderDeferObj.resolve();
|
||||
}
|
||||
// Resolve render promise post-digest
|
||||
scope.$$postDigest(function() {
|
||||
modalRenderDeferObj.resolve();
|
||||
});
|
||||
|
||||
modalRenderDeferObj.promise.then(function() {
|
||||
@@ -235,16 +230,16 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
};
|
||||
})
|
||||
|
||||
.directive('uibModalTransclude', function() {
|
||||
.directive('uibModalTransclude', ['$animate', function($animate) {
|
||||
return {
|
||||
link: function(scope, element, attrs, controller, transclude) {
|
||||
transclude(scope.$parent, function(clone) {
|
||||
element.empty();
|
||||
element.append(clone);
|
||||
$animate.enter(clone, element);
|
||||
});
|
||||
}
|
||||
};
|
||||
})
|
||||
}])
|
||||
|
||||
.factory('$uibModalStack', ['$animate', '$animateCss', '$document',
|
||||
'$compile', '$rootScope', '$q', '$$multiMap', '$$stackedMap', '$uibPosition',
|
||||
@@ -261,9 +256,9 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
var previousTopOpenedModal = null;
|
||||
|
||||
//Modal focus behavior
|
||||
var tabableSelector = 'a[href], area[href], input:not([disabled]), ' +
|
||||
'button:not([disabled]),select:not([disabled]), textarea:not([disabled]), ' +
|
||||
'iframe, object, embed, *[tabindex], *[contenteditable=true]';
|
||||
var tabbableSelector = 'a[href], area[href], input:not([disabled]):not([tabindex=\'-1\']), ' +
|
||||
'button:not([disabled]):not([tabindex=\'-1\']),select:not([disabled]):not([tabindex=\'-1\']), textarea:not([disabled]):not([tabindex=\'-1\']), ' +
|
||||
'iframe, object, embed, *[tabindex]:not([tabindex=\'-1\']), *[contenteditable=true]';
|
||||
var scrollbarPadding;
|
||||
|
||||
function isVisible(element) {
|
||||
@@ -380,6 +375,10 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
afterAnimating.done = true;
|
||||
|
||||
$animate.leave(domEl).then(function() {
|
||||
if (done) {
|
||||
done();
|
||||
}
|
||||
|
||||
domEl.remove();
|
||||
if (closedDeferred) {
|
||||
closedDeferred.resolve();
|
||||
@@ -387,9 +386,6 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
});
|
||||
|
||||
scope.$destroy();
|
||||
if (done) {
|
||||
done();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,15 +473,26 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
backdropScope.modalOptions = modal;
|
||||
backdropScope.index = currBackdropIndex;
|
||||
backdropDomEl = angular.element('<div uib-modal-backdrop="modal-backdrop"></div>');
|
||||
backdropDomEl.attr('backdrop-class', modal.backdropClass);
|
||||
backdropDomEl.attr({
|
||||
'class': 'modal-backdrop',
|
||||
'ng-style': '{\'z-index\': 1040 + (index && 1 || 0) + index*10}',
|
||||
'uib-modal-animation-class': 'fade',
|
||||
'modal-in-class': 'in'
|
||||
});
|
||||
if (modal.backdropClass) {
|
||||
backdropDomEl.addClass(modal.backdropClass);
|
||||
}
|
||||
|
||||
if (modal.animation) {
|
||||
backdropDomEl.attr('modal-animation', 'true');
|
||||
}
|
||||
$compile(backdropDomEl)(backdropScope);
|
||||
$animate.enter(backdropDomEl, appendToElement);
|
||||
scrollbarPadding = $uibPosition.scrollbarPadding(appendToElement);
|
||||
if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
|
||||
appendToElement.css({paddingRight: scrollbarPadding.right + 'px'});
|
||||
if ($uibPosition.isScrollable(appendToElement)) {
|
||||
scrollbarPadding = $uibPosition.scrollbarPadding(appendToElement);
|
||||
if (scrollbarPadding.heightOverflow && scrollbarPadding.scrollbarWidth) {
|
||||
appendToElement.css({paddingRight: scrollbarPadding.right + 'px'});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,13 +500,22 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
topModalIndex = previousTopOpenedModal ? parseInt(previousTopOpenedModal.value.modalDomEl.attr('index'), 10) + 1 : 0;
|
||||
var angularDomEl = angular.element('<div uib-modal-window="modal-window"></div>');
|
||||
angularDomEl.attr({
|
||||
'class': 'modal',
|
||||
'template-url': modal.windowTemplateUrl,
|
||||
'window-class': modal.windowClass,
|
||||
'window-top-class': modal.windowTopClass,
|
||||
'role': 'dialog',
|
||||
'size': modal.size,
|
||||
'index': topModalIndex,
|
||||
'animate': 'animate'
|
||||
'animate': 'animate',
|
||||
'ng-style': '{\'z-index\': 1050 + index*10, display: \'block\'}',
|
||||
'tabindex': -1,
|
||||
'uib-modal-animation-class': 'fade',
|
||||
'modal-in-class': 'in'
|
||||
}).html(modal.content);
|
||||
if (modal.windowClass) {
|
||||
angularDomEl.addClass(modal.windowClass);
|
||||
}
|
||||
|
||||
if (modal.animation) {
|
||||
angularDomEl.attr('modal-animation', 'true');
|
||||
}
|
||||
@@ -599,7 +615,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
if (modalWindow) {
|
||||
var modalDomE1 = modalWindow.value.modalDomEl;
|
||||
if (modalDomE1 && modalDomE1.length) {
|
||||
var elements = modalDomE1[0].querySelectorAll(tabableSelector);
|
||||
var elements = modalDomE1[0].querySelectorAll(tabbableSelector);
|
||||
return elements ?
|
||||
Array.prototype.filter.call(elements, function(element) {
|
||||
return isVisible(element);
|
||||
@@ -695,30 +711,27 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
//controllers
|
||||
if (modalOptions.controller) {
|
||||
ctrlLocals.$scope = modalScope;
|
||||
ctrlLocals.$scope.$resolve = {};
|
||||
ctrlLocals.$uibModalInstance = modalInstance;
|
||||
angular.forEach(tplAndVars[1], function(value, key) {
|
||||
ctrlLocals[key] = value;
|
||||
ctrlLocals.$scope.$resolve[key] = value;
|
||||
});
|
||||
|
||||
// the third param will make the controller instantiate later,private api
|
||||
// @see https://github.com/angular/angular.js/blob/master/src/ng/controller.js#L126
|
||||
ctrlInstantiate = $controller(modalOptions.controller, ctrlLocals, true);
|
||||
if (modalOptions.controllerAs) {
|
||||
ctrlInstantiate = $controller(modalOptions.controller, ctrlLocals, true, modalOptions.controllerAs);
|
||||
if (modalOptions.controllerAs && modalOptions.bindToController) {
|
||||
ctrlInstance = ctrlInstantiate.instance;
|
||||
|
||||
if (modalOptions.bindToController) {
|
||||
ctrlInstance.$close = modalScope.$close;
|
||||
ctrlInstance.$dismiss = modalScope.$dismiss;
|
||||
angular.extend(ctrlInstance, providedScope);
|
||||
}
|
||||
|
||||
ctrlInstance = ctrlInstantiate();
|
||||
|
||||
modalScope[modalOptions.controllerAs] = ctrlInstance;
|
||||
} else {
|
||||
ctrlInstance = ctrlInstantiate();
|
||||
ctrlInstance.$close = modalScope.$close;
|
||||
ctrlInstance.$dismiss = modalScope.$dismiss;
|
||||
angular.extend(ctrlInstance, {
|
||||
$resolve: ctrlLocals.$scope.$resolve
|
||||
}, providedScope);
|
||||
}
|
||||
|
||||
ctrlInstance = ctrlInstantiate();
|
||||
|
||||
if (angular.isFunction(ctrlInstance.$onInit)) {
|
||||
ctrlInstance.$onInit();
|
||||
}
|
||||
|
||||
+127
-19
@@ -46,13 +46,68 @@ describe('$uibResolve', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('uibModalTransclude', function() {
|
||||
var uibModalTranscludeDDO,
|
||||
$animate;
|
||||
|
||||
beforeEach(module('ui.bootstrap.modal'));
|
||||
beforeEach(module(function($provide) {
|
||||
$animate = jasmine.createSpyObj('$animate', ['enter']);
|
||||
$provide.value('$animate', $animate);
|
||||
}));
|
||||
|
||||
beforeEach(inject(function(uibModalTranscludeDirective) {
|
||||
uibModalTranscludeDDO = uibModalTranscludeDirective[0];
|
||||
}));
|
||||
|
||||
describe('when initialised', function() {
|
||||
var scope,
|
||||
element,
|
||||
transcludeSpy,
|
||||
transcludeFn;
|
||||
|
||||
beforeEach(function() {
|
||||
scope = {
|
||||
$parent: 'parentScope'
|
||||
};
|
||||
|
||||
element = jasmine.createSpyObj('containerElement', ['empty']);
|
||||
transcludeSpy = jasmine.createSpy('transcludeSpy').and.callFake(function(scope, fn) {
|
||||
transcludeFn = fn;
|
||||
});
|
||||
|
||||
uibModalTranscludeDDO.link(scope, element, {}, {}, transcludeSpy);
|
||||
});
|
||||
|
||||
it('should call the transclusion function', function() {
|
||||
expect(transcludeSpy).toHaveBeenCalledWith(scope.$parent, jasmine.any(Function));
|
||||
});
|
||||
|
||||
describe('transclusion callback', function() {
|
||||
var transcludedContent;
|
||||
|
||||
beforeEach(function() {
|
||||
transcludedContent = 'my transcluded content';
|
||||
transcludeFn(transcludedContent);
|
||||
});
|
||||
|
||||
it('should empty the element', function() {
|
||||
expect(element.empty).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it('should append the transcluded content', function() {
|
||||
expect($animate.enter).toHaveBeenCalledWith(transcludedContent, element);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('$uibModal', function() {
|
||||
var $animate, $controllerProvider, $rootScope, $document, $compile, $templateCache, $timeout, $q;
|
||||
var $uibModal, $uibModalStack, $uibModalProvider;
|
||||
|
||||
beforeEach(module('ngAnimateMock'));
|
||||
beforeEach(module('ui.bootstrap.modal'));
|
||||
beforeEach(module('uib/template/modal/backdrop.html'));
|
||||
beforeEach(module('uib/template/modal/window.html'));
|
||||
beforeEach(module(function(_$controllerProvider_, _$uibModalProvider_, $compileProvider) {
|
||||
$controllerProvider = _$controllerProvider_;
|
||||
@@ -807,6 +862,52 @@ describe('$uibModal', function() {
|
||||
|
||||
initialPage.remove();
|
||||
});
|
||||
|
||||
it('should change focus to next tabbable element when tab is pressed', function() {
|
||||
var initialPage = angular.element('<a href="#" id="cannot-get-focus-from-modal">Outland link</a>');
|
||||
angular.element(document.body).append(initialPage);
|
||||
initialPage.focus();
|
||||
|
||||
open({
|
||||
template:'<button id="tab-focus-button1" tabindex="-1">Skip me!</button><a href="#" id="tab-focus-link1">a</a>' +
|
||||
'<a href="#" id="tab-focus-link2">b</a><a href="#" id="tab-focus-link3">c</a>' +
|
||||
'<button id="tab-focus-button2" tabindex="-1">Skip me!</button>',
|
||||
keyboard: false
|
||||
});
|
||||
$rootScope.$digest();
|
||||
expect($document).toHaveModalsOpen(1);
|
||||
|
||||
$('#tab-focus-link3').focus();
|
||||
expect(document.activeElement.getAttribute('id')).toBe('tab-focus-link3');
|
||||
|
||||
triggerKeyDown(angular.element(document.activeElement), 9, false);
|
||||
expect(document.activeElement.getAttribute('id')).toBe('tab-focus-link1');
|
||||
|
||||
initialPage.remove();
|
||||
});
|
||||
|
||||
it('should change focus to previous tabbable element when shift+tab is pressed', function() {
|
||||
var initialPage = angular.element('<a href="#" id="cannot-get-focus-from-modal">Outland link</a>');
|
||||
angular.element(document.body).append(initialPage);
|
||||
initialPage.focus();
|
||||
|
||||
open({
|
||||
template:'<button id="tab-focus-button1" tabindex="-1">Skip me!</button><a href="#" id="tab-focus-link1">a</a>' +
|
||||
'<a href="#" id="tab-focus-link2">b</a><a href="#" id="tab-focus-link3">c</a>' +
|
||||
'<button id="tab-focus-button2" tabindex="-1">Skip me!</button>',
|
||||
keyboard: false
|
||||
});
|
||||
$rootScope.$digest();
|
||||
expect($document).toHaveModalsOpen(1);
|
||||
|
||||
$('#tab-focus-link1').focus();
|
||||
expect(document.activeElement.getAttribute('id')).toBe('tab-focus-link1');
|
||||
|
||||
triggerKeyDown(angular.element(document.activeElement), 9, true);
|
||||
expect(document.activeElement.getAttribute('id')).toBe('tab-focus-link3');
|
||||
|
||||
initialPage.remove();
|
||||
});
|
||||
});
|
||||
|
||||
describe('default options can be changed in a provider', function() {
|
||||
@@ -1053,6 +1154,20 @@ describe('$uibModal', function() {
|
||||
});
|
||||
expect($document).toHaveModalOpenWithContent('Content from root scope', 'div');
|
||||
});
|
||||
|
||||
it('should expose $resolve in template', function() {
|
||||
open({
|
||||
controller: function($scope) {},
|
||||
resolve: {
|
||||
$foo: function() {
|
||||
return 'Content from resolve';
|
||||
}
|
||||
},
|
||||
template: '<div>{{$resolve.$foo}}</div>'
|
||||
});
|
||||
|
||||
expect($document).toHaveModalOpenWithContent('Content from resolve', 'div');
|
||||
});
|
||||
});
|
||||
|
||||
describe('keyboard', function () {
|
||||
@@ -1275,7 +1390,7 @@ describe('$uibModal', function() {
|
||||
expect(body).not.toHaveClass('modal-open');
|
||||
});
|
||||
|
||||
it('should remove the custom class on closing of modal', function() {
|
||||
it('should remove the custom class on closing of modal after animations have completed', function() {
|
||||
var modal = open({
|
||||
template: '<div>dummy modal</div>',
|
||||
openedClass: 'foo'
|
||||
@@ -1283,7 +1398,13 @@ describe('$uibModal', function() {
|
||||
|
||||
expect(body).toHaveClass('foo');
|
||||
|
||||
close(modal);
|
||||
close(modal, null, true);
|
||||
expect(body).toHaveClass('foo');
|
||||
|
||||
$animate.flush();
|
||||
$rootScope.$digest();
|
||||
$animate.flush();
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(body).not.toHaveClass('foo');
|
||||
});
|
||||
@@ -1355,15 +1476,6 @@ describe('$uibModal', function() {
|
||||
expect($rootScope.foo).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should support custom CSS classes as string', function() {
|
||||
$rootScope.animate = false;
|
||||
var windowEl = $compile('<div uib-modal-window animate="animate" window-class="test foo">content</div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(windowEl).toHaveClass('test');
|
||||
expect(windowEl).toHaveClass('foo');
|
||||
});
|
||||
|
||||
it('should support window top class', function () {
|
||||
$rootScope.animate = false;
|
||||
var windowEl = $compile('<div uib-modal-window animate="animate" window-top-class="test foo">content</div>')($rootScope);
|
||||
@@ -1374,13 +1486,12 @@ describe('$uibModal', function() {
|
||||
});
|
||||
|
||||
it('should support custom template url', inject(function($templateCache) {
|
||||
$templateCache.put('window.html', '<div class="mywindow" ng-transclude></div>');
|
||||
$templateCache.put('window.html', '<div ng-transclude></div>');
|
||||
|
||||
var windowEl = $compile('<div uib-modal-window template-url="window.html" window-class="test">content</div>')($rootScope);
|
||||
var windowEl = $compile('<div uib-modal-window template-url="window.html">content</div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(windowEl).toHaveClass('mywindow');
|
||||
expect(windowEl).toHaveClass('test');
|
||||
expect(windowEl.html()).toBe('<div ng-transclude=""><span class="ng-scope">content</span></div>');
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -1666,7 +1777,6 @@ describe('$uibModal', function() {
|
||||
content: '<div>Modal1</div>'
|
||||
});
|
||||
|
||||
expect($document).toHaveModalsOpen(0);
|
||||
$rootScope.$digest();
|
||||
$animate.flush();
|
||||
expect($document).toHaveModalsOpen(1);
|
||||
@@ -1686,7 +1796,6 @@ describe('$uibModal', function() {
|
||||
modal2Index = parseInt($uibModalStack.getTop().value.modalDomEl.attr('index'), 10);
|
||||
});
|
||||
|
||||
expect($document).toHaveModalsOpen(1);
|
||||
$rootScope.$digest();
|
||||
$animate.flush();
|
||||
expect($document).toHaveModalsOpen(2);
|
||||
@@ -1708,7 +1817,6 @@ describe('$uibModal', function() {
|
||||
modal3Index = parseInt($uibModalStack.getTop().value.modalDomEl.attr('index'), 10);
|
||||
});
|
||||
|
||||
expect($document).toHaveModalsOpen(1);
|
||||
$rootScope.$digest();
|
||||
$animate.flush();
|
||||
expect($document).toHaveModalsOpen(2);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div ng-controller="PagerDemoCtrl">
|
||||
<h4>Pager</h4>
|
||||
<pre>You are currently on page {{currentPage}}</pre>
|
||||
<uib-pager total-items="totalItems" ng-model="currentPage"></uib-pager>
|
||||
<ul uib-pager total-items="totalItems" ng-model="currentPage"></ul>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
require('../paging');
|
||||
require('../tabindex');
|
||||
require('../../template/pager/pager.html.js');
|
||||
require('./pager');
|
||||
|
||||
|
||||
+3
-2
@@ -1,4 +1,4 @@
|
||||
angular.module('ui.bootstrap.pager', ['ui.bootstrap.paging'])
|
||||
angular.module('ui.bootstrap.pager', ['ui.bootstrap.paging', 'ui.bootstrap.tabindex'])
|
||||
|
||||
.controller('UibPagerController', ['$scope', '$attrs', 'uibPaging', 'uibPagerConfig', function($scope, $attrs, uibPaging, uibPagerConfig) {
|
||||
$scope.align = angular.isDefined($attrs.align) ? $scope.$parent.$eval($attrs.align) : uibPagerConfig.align;
|
||||
@@ -22,13 +22,14 @@ angular.module('ui.bootstrap.pager', ['ui.bootstrap.paging'])
|
||||
ngDisabled: '='
|
||||
},
|
||||
require: ['uibPager', '?ngModel'],
|
||||
restrict: 'A',
|
||||
controller: 'UibPagerController',
|
||||
controllerAs: 'pager',
|
||||
templateUrl: function(element, attrs) {
|
||||
return attrs.templateUrl || 'uib/template/pager/pager.html';
|
||||
},
|
||||
replace: true,
|
||||
link: function(scope, element, attrs, ctrls) {
|
||||
element.addClass('pager');
|
||||
var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];
|
||||
|
||||
if (!ngModelCtrl) {
|
||||
|
||||
@@ -10,7 +10,7 @@ describe('pager directive', function() {
|
||||
$document = _$document_;
|
||||
$templateCache = _$templateCache_;
|
||||
body = $document.find('body');
|
||||
element = $compile('<uib-pager total-items="total" ng-model="currentPage"></uib-pager>')($rootScope);
|
||||
element = $compile('<ul uib-pager total-items="total" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
|
||||
@@ -56,7 +56,7 @@ describe('pager directive', function() {
|
||||
it('exposes the controller on the template', function() {
|
||||
$templateCache.put('uib/template/pager/pager.html', '<div>{{pager.text}}</div>');
|
||||
|
||||
element = $compile('<uib-pager></uib-pager>')($rootScope);
|
||||
element = $compile('<ul uib-pager></ul uib-pager>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
var ctrl = element.controller('uibPager');
|
||||
@@ -65,7 +65,7 @@ describe('pager directive', function() {
|
||||
ctrl.text = 'foo';
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element.html()).toBe('foo');
|
||||
expect(element.html()).toBe('<div class="ng-binding">foo</div>');
|
||||
});
|
||||
|
||||
it('disables the "previous" link if current page is 1', function() {
|
||||
@@ -102,7 +102,7 @@ describe('pager directive', function() {
|
||||
|
||||
it('executes the `ng-change` expression when an element is clicked', function() {
|
||||
$rootScope.selectPageHandler = jasmine.createSpy('selectPageHandler');
|
||||
element = $compile('<uib-pager total-items="total" ng-model="currentPage" ng-change="selectPageHandler()"></uib-pager>')($rootScope);
|
||||
element = $compile('<ul uib-pager total-items="total" ng-model="currentPage" ng-change="selectPageHandler()"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
clickPaginationEl(-1);
|
||||
@@ -147,16 +147,16 @@ describe('pager directive', function() {
|
||||
it('allows custom templates', function() {
|
||||
$templateCache.put('foo/bar.html', '<div>baz</div>');
|
||||
|
||||
element = $compile('<uib-pager template-url="foo/bar.html"></uib-pager>')($rootScope);
|
||||
element = $compile('<ul uib-pager template-url="foo/bar.html"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element.html()).toBe('baz');
|
||||
expect(element.html()).toBe('<div>baz</div>');
|
||||
});
|
||||
|
||||
describe('`items-per-page`', function() {
|
||||
beforeEach(function() {
|
||||
$rootScope.perpage = 5;
|
||||
element = $compile('<uib-pager total-items="total" items-per-page="perpage" ng-model="currentPage"></uib-pager>')($rootScope);
|
||||
element = $compile('<ul uib-pager total-items="total" items-per-page="perpage" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -190,7 +190,7 @@ describe('pager directive', function() {
|
||||
describe('`num-pages`', function() {
|
||||
beforeEach(function() {
|
||||
$rootScope.numpg = null;
|
||||
element = $compile('<uib-pager total-items="total" ng-model="currentPage" num-pages="numpg"></uib-pager>')($rootScope);
|
||||
element = $compile('<ul uib-pager total-items="total" ng-model="currentPage" num-pages="numpg"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -206,7 +206,7 @@ describe('pager directive', function() {
|
||||
uibPagerConfig.previousText = 'PR';
|
||||
uibPagerConfig.nextText = 'NE';
|
||||
uibPagerConfig.align = false;
|
||||
element = $compile('<uib-pager total-items="total" ng-model="currentPage"></uib-pager>')($rootScope);
|
||||
element = $compile('<ul uib-pager total-items="total" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
afterEach(inject(function(uibPagerConfig) {
|
||||
@@ -227,7 +227,7 @@ describe('pager directive', function() {
|
||||
|
||||
describe('override configuration from attributes', function() {
|
||||
beforeEach(function() {
|
||||
element = $compile('<uib-pager align="false" previous-text="<" next-text=">" total-items="total" ng-model="currentPage"></uib-pager>')($rootScope);
|
||||
element = $compile('<ul uib-pager align="false" previous-text="<" next-text=">" total-items="total" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -248,7 +248,7 @@ describe('pager directive', function() {
|
||||
it('changes "previous" & "next" text from interpolated attributes', function() {
|
||||
$rootScope.previousText = '<<';
|
||||
$rootScope.nextText = '>>';
|
||||
element = $compile('<uib-pager align="false" previous-text="{{previousText}}" next-text="{{nextText}}" total-items="total" ng-model="currentPage"></uib-pager>')($rootScope);
|
||||
element = $compile('<ul uib-pager align="false" previous-text="{{previousText}}" next-text="{{nextText}}" total-items="total" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getPaginationEl(0).text()).toBe('<<');
|
||||
@@ -259,7 +259,7 @@ describe('pager directive', function() {
|
||||
it('disables the component when ng-disabled is true', function() {
|
||||
$rootScope.disable = true;
|
||||
|
||||
element = $compile('<uib-pager total-items="total" ng-disabled="disable" ng-model="currentPage"></uib-pager>')($rootScope);
|
||||
element = $compile('<ul uib-pager total-items="total" ng-disabled="disable" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
updateCurrentPage(2);
|
||||
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
<div ng-controller="PaginationDemoCtrl">
|
||||
<h4>Default</h4>
|
||||
<uib-pagination total-items="totalItems" ng-model="currentPage" ng-change="pageChanged()"></uib-pagination>
|
||||
<uib-pagination boundary-links="true" total-items="totalItems" ng-model="currentPage" class="pagination-sm" previous-text="‹" next-text="›" first-text="«" last-text="»"></uib-pagination>
|
||||
<uib-pagination direction-links="false" boundary-links="true" total-items="totalItems" ng-model="currentPage"></uib-pagination>
|
||||
<uib-pagination direction-links="false" total-items="totalItems" ng-model="currentPage" num-pages="smallnumPages"></uib-pagination>
|
||||
<ul uib-pagination total-items="totalItems" ng-model="currentPage" ng-change="pageChanged()"></ul>
|
||||
<ul uib-pagination boundary-links="true" total-items="totalItems" ng-model="currentPage" class="pagination-sm" previous-text="‹" next-text="›" first-text="«" last-text="»"></ul>
|
||||
<ul uib-pagination direction-links="false" boundary-links="true" total-items="totalItems" ng-model="currentPage"></ul>
|
||||
<ul uib-pagination direction-links="false" total-items="totalItems" ng-model="currentPage" num-pages="smallnumPages"></ul>
|
||||
<pre>The selected page no: {{currentPage}}</pre>
|
||||
<button type="button" class="btn btn-info" ng-click="setPage(3)">Set current page to: 3</button>
|
||||
|
||||
<hr />
|
||||
<h4>Limit the maximum visible buttons</h4>
|
||||
<h6><code>rotate</code> defaulted to <code>true</code>:</h6>
|
||||
<uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-links="true" num-pages="numPages"></uib-pagination>
|
||||
<ul uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-links="true" num-pages="numPages"></ul>
|
||||
<h6><code>rotate</code> defaulted to <code>true</code> and <code>force-ellipses</code> set to <code>true</code>:</h6>
|
||||
<uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-links="true" force-ellipses="true"></uib-pagination>
|
||||
<ul uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-links="true" force-ellipses="true"></ul>
|
||||
<h6><code>rotate</code> set to <code>false</code>:</h6>
|
||||
<uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-links="true" rotate="false"></uib-pagination>
|
||||
<ul uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-links="true" rotate="false"></ul>
|
||||
<h6><code>boundary-link-numbers</code> set to <code>true</code> and <code>rotate</code> defaulted to <code>true</code>:</h6>
|
||||
<uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-link-numbers="true"></uib-pagination>
|
||||
<ul uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-link-numbers="true"></ul>
|
||||
<h6><code>boundary-link-numbers</code> set to <code>true</code> and <code>rotate</code> set to <code>false</code>:</h6>
|
||||
<uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-link-numbers="true" rotate="false"></uib-pagination>
|
||||
<ul uib-pagination total-items="bigTotalItems" ng-model="bigCurrentPage" max-size="maxSize" class="pagination-sm" boundary-link-numbers="true" rotate="false"></ul>
|
||||
<pre>Page: {{bigCurrentPage}} / {{numPages}}</pre>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
require('../paging');
|
||||
require('../tabindex');
|
||||
require('../../template/pagination/pagination.html.js');
|
||||
require('./pagination');
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module('ui.bootstrap.pagination', ['ui.bootstrap.paging'])
|
||||
angular.module('ui.bootstrap.pagination', ['ui.bootstrap.paging', 'ui.bootstrap.tabindex'])
|
||||
.controller('UibPaginationController', ['$scope', '$attrs', '$parse', 'uibPaging', 'uibPaginationConfig', function($scope, $attrs, $parse, uibPaging, uibPaginationConfig) {
|
||||
var ctrl = this;
|
||||
// Setup configuration parameters
|
||||
@@ -132,13 +132,14 @@ angular.module('ui.bootstrap.pagination', ['ui.bootstrap.paging'])
|
||||
ngDisabled:'='
|
||||
},
|
||||
require: ['uibPagination', '?ngModel'],
|
||||
restrict: 'A',
|
||||
controller: 'UibPaginationController',
|
||||
controllerAs: 'pagination',
|
||||
templateUrl: function(element, attrs) {
|
||||
return attrs.templateUrl || 'uib/template/pagination/pagination.html';
|
||||
},
|
||||
replace: true,
|
||||
link: function(scope, element, attrs, ctrls) {
|
||||
element.addClass('pagination');
|
||||
var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];
|
||||
|
||||
if (!ngModelCtrl) {
|
||||
|
||||
@@ -11,7 +11,7 @@ describe('pagination directive', function() {
|
||||
$document = _$document_;
|
||||
$templateCache = _$templateCache_;
|
||||
body = $document.find('body');
|
||||
element = $compile('<uib-pagination total-items="total" ng-model="currentPage"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination total-items="total" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
|
||||
@@ -58,7 +58,7 @@ describe('pagination directive', function() {
|
||||
$templateCache.put('uib/template/pagination/pagination.html', '<div>{{pagination.randomText}}</div>');
|
||||
var scope = $rootScope.$new();
|
||||
|
||||
element = $compile('<uib-pagination></uib-pagination>')(scope);
|
||||
element = $compile('<ul uib-pagination></ul>')(scope);
|
||||
$rootScope.$digest();
|
||||
|
||||
var ctrl = element.controller('uibPagination');
|
||||
@@ -68,17 +68,17 @@ describe('pagination directive', function() {
|
||||
ctrl.randomText = 'foo';
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element.html()).toBe('foo');
|
||||
expect(element.html()).toBe('<div class="ng-binding">foo</div>');
|
||||
});
|
||||
|
||||
it('allows custom templates', function() {
|
||||
$templateCache.put('foo/bar.html', '<div>baz</div>');
|
||||
var scope = $rootScope.$new();
|
||||
|
||||
element = $compile('<uib-pagination template-url="foo/bar.html"></uib-pagination>')(scope);
|
||||
element = $compile('<ul uib-pagination template-url="foo/bar.html"></ul>')(scope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element.html()).toBe('baz');
|
||||
expect(element.html()).toBe('<div>baz</div>');
|
||||
});
|
||||
|
||||
it('contains num-pages + 2 li elements', function() {
|
||||
@@ -213,7 +213,7 @@ describe('pagination directive', function() {
|
||||
describe('`items-per-page`', function() {
|
||||
beforeEach(function() {
|
||||
$rootScope.perpage = 5;
|
||||
element = $compile('<uib-pagination total-items="total" items-per-page="perpage" ng-model="currentPage"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination total-items="total" items-per-page="perpage" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -256,7 +256,7 @@ describe('pagination directive', function() {
|
||||
describe('executes `ng-change` expression', function() {
|
||||
beforeEach(function() {
|
||||
$rootScope.selectPageHandler = jasmine.createSpy('selectPageHandler');
|
||||
element = $compile('<uib-pagination total-items="total" ng-model="currentPage" ng-change="selectPageHandler()"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination total-items="total" ng-model="currentPage" ng-change="selectPageHandler()"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -286,7 +286,7 @@ describe('pagination directive', function() {
|
||||
$rootScope.total = 98; // 10 pages
|
||||
$rootScope.currentPage = 3;
|
||||
$rootScope.maxSize = 5;
|
||||
element = $compile('<uib-pagination total-items="total" ng-model="currentPage" max-size="maxSize"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination total-items="total" ng-model="currentPage" max-size="maxSize"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -367,7 +367,7 @@ describe('pagination directive', function() {
|
||||
$rootScope.total = 98; // 10 pages
|
||||
$rootScope.currentPage = 3;
|
||||
$rootScope.maxSize = 5;
|
||||
element = $compile('<uib-pagination total-items="total" ng-model="currentPage" max-size="maxSize" force-ellipses="true"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination total-items="total" ng-model="currentPage" max-size="maxSize" force-ellipses="true"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -429,7 +429,7 @@ describe('pagination directive', function() {
|
||||
$rootScope.total = 98; // 10 pages
|
||||
$rootScope.currentPage = 3;
|
||||
$rootScope.maxSize = 5;
|
||||
element = $compile('<uib-pagination total-items="total" ng-model="currentPage" max-size="maxSize" boundary-link-numbers="true"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination total-items="total" ng-model="currentPage" max-size="maxSize" boundary-link-numbers="true"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -522,7 +522,7 @@ describe('pagination directive', function() {
|
||||
$rootScope.currentPage = 7;
|
||||
$rootScope.maxSize = 5;
|
||||
$rootScope.rotate = false;
|
||||
element = $compile('<uib-pagination total-items="total" ng-model="currentPage" max-size="maxSize" rotate="rotate"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination total-items="total" ng-model="currentPage" max-size="maxSize" rotate="rotate"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -581,7 +581,7 @@ describe('pagination directive', function() {
|
||||
|
||||
describe('pagination directive with `boundary-links`', function() {
|
||||
beforeEach(function() {
|
||||
element = $compile('<uib-pagination boundary-links="true" total-items="total" ng-model="currentPage"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination boundary-links="true" total-items="total" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -636,7 +636,7 @@ describe('pagination directive', function() {
|
||||
});
|
||||
|
||||
it('changes "first" & "last" text from attributes', function() {
|
||||
element = $compile('<uib-pagination boundary-links="true" first-text="<<<" last-text=">>>" total-items="total" ng-model="currentPage"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination boundary-links="true" first-text="<<<" last-text=">>>" total-items="total" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getPaginationEl(0).text()).toBe('<<<');
|
||||
@@ -644,7 +644,7 @@ describe('pagination directive', function() {
|
||||
});
|
||||
|
||||
it('changes "previous" & "next" text from attributes', function() {
|
||||
element = $compile('<uib-pagination boundary-links="true" previous-text="<<" next-text=">>" total-items="total" ng-model="currentPage"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination boundary-links="true" previous-text="<<" next-text=">>" total-items="total" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getPaginationEl(1).text()).toBe('<<');
|
||||
@@ -654,7 +654,7 @@ describe('pagination directive', function() {
|
||||
it('changes "first" & "last" text from interpolated attributes', function() {
|
||||
$rootScope.myfirstText = '<<<';
|
||||
$rootScope.mylastText = '>>>';
|
||||
element = $compile('<uib-pagination boundary-links="true" first-text="{{myfirstText}}" last-text="{{mylastText}}" total-items="total" ng-model="currentPage"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination boundary-links="true" first-text="{{myfirstText}}" last-text="{{mylastText}}" total-items="total" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getPaginationEl(0).text()).toBe('<<<');
|
||||
@@ -664,7 +664,7 @@ describe('pagination directive', function() {
|
||||
it('changes "previous" & "next" text from interpolated attributes', function() {
|
||||
$rootScope.previousText = '<<';
|
||||
$rootScope.nextText = '>>';
|
||||
element = $compile('<uib-pagination boundary-links="true" previous-text="{{previousText}}" next-text="{{nextText}}" total-items="total" ng-model="currentPage"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination boundary-links="true" previous-text="{{previousText}}" next-text="{{nextText}}" total-items="total" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getPaginationEl(1).text()).toBe('<<');
|
||||
@@ -700,7 +700,7 @@ describe('pagination directive', function() {
|
||||
|
||||
describe('pagination directive with just number links', function() {
|
||||
beforeEach(function() {
|
||||
element = $compile('<uib-pagination direction-links="false" total-items="total" ng-model="currentPage"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination direction-links="false" total-items="total" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -752,7 +752,7 @@ describe('pagination directive', function() {
|
||||
describe('with just boundary & number links', function() {
|
||||
beforeEach(function() {
|
||||
$rootScope.directions = false;
|
||||
element = $compile('<uib-pagination boundary-links="true" direction-links="directions" total-items="total" ng-model="currentPage"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination boundary-links="true" direction-links="directions" total-items="total" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -784,7 +784,7 @@ describe('pagination directive', function() {
|
||||
describe('`num-pages`', function() {
|
||||
beforeEach(function() {
|
||||
$rootScope.numpg = null;
|
||||
element = $compile('<uib-pagination total-items="total" ng-model="currentPage" num-pages="numpg"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination total-items="total" ng-model="currentPage" num-pages="numpg"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -827,7 +827,7 @@ describe('pagination directive', function() {
|
||||
paginationConfig.previousText = 'PR';
|
||||
paginationConfig.nextText = 'NE';
|
||||
paginationConfig.lastText = 'LA';
|
||||
element = $compile('<uib-pagination total-items="total" ng-model="currentPage"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination total-items="total" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getPaginationEl(0).text()).toBe('FI');
|
||||
@@ -838,7 +838,7 @@ describe('pagination directive', function() {
|
||||
|
||||
it('contains number of pages + 2 li elements', function() {
|
||||
paginationConfig.itemsPerPage = 5;
|
||||
element = $compile('<uib-pagination total-items="total" ng-model="currentPage"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination total-items="total" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getPaginationBarSize()).toBe(12);
|
||||
@@ -846,7 +846,7 @@ describe('pagination directive', function() {
|
||||
|
||||
it('should take maxSize defaults into account', function() {
|
||||
paginationConfig.maxSize = 2;
|
||||
element = $compile('<uib-pagination total-items="total" ng-model="currentPage"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination total-items="total" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getPaginationBarSize()).toBe(4);
|
||||
@@ -854,7 +854,7 @@ describe('pagination directive', function() {
|
||||
|
||||
it('should take forceEllipses defaults into account', function () {
|
||||
paginationConfig.forceEllipses = true;
|
||||
element = $compile('<uib-pagination total-items="total" ng-model="currentPage" max-size="2"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination total-items="total" ng-model="currentPage" max-size="2"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
// Should contain 2 nav buttons, 2 pages, and 2 ellipsis since the currentPage defaults to 3, which is in the middle
|
||||
@@ -865,7 +865,7 @@ describe('pagination directive', function() {
|
||||
paginationConfig.boundaryLinkNumbers = true;
|
||||
$rootScope.total = 88; // 9 pages
|
||||
$rootScope.currentPage = 5;
|
||||
element = $compile('<uib-pagination total-items="total" ng-model="currentPage" max-size="3"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination total-items="total" ng-model="currentPage" max-size="3"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
// Should contain 2 nav buttons, 2 pages, 2 ellipsis, and 2 extra end numbers since the currentPage is in the middle
|
||||
@@ -879,7 +879,7 @@ describe('pagination directive', function() {
|
||||
$rootScope.pageLabel = function(id) {
|
||||
return 'test_'+ id;
|
||||
};
|
||||
element = $compile('<uib-pagination boundary-links="true" page-label="pageLabel($page)" first-text="<<" previous-text="<" next-text=">" last-text=">>" total-items="total" ng-model="currentPage"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination boundary-links="true" page-label="pageLabel($page)" first-text="<<" previous-text="<" next-text=">" last-text=">>" total-items="total" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -904,7 +904,7 @@ describe('pagination directive', function() {
|
||||
|
||||
describe('disabled with ngDisable', function() {
|
||||
beforeEach(function() {
|
||||
element = $compile('<uib-pagination total-items="total" ng-model="currentPage" ng-disabled="disabled"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination total-items="total" ng-model="currentPage" ng-disabled="disabled"></ul>')($rootScope);
|
||||
$rootScope.currentPage = 3;
|
||||
$rootScope.$digest();
|
||||
});
|
||||
@@ -941,7 +941,7 @@ describe('pagination directive', function() {
|
||||
it('should retain the model value when total-items starts as undefined', function() {
|
||||
$rootScope.currentPage = 5;
|
||||
$rootScope.total = undefined;
|
||||
element = $compile('<uib-pagination total-items="total" ng-model="currentPage"></uib-pagination>')($rootScope);
|
||||
element = $compile('<ul uib-pagination total-items="total" ng-model="currentPage"></ul>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect($rootScope.currentPage).toBe(5);
|
||||
|
||||
@@ -34,9 +34,9 @@
|
||||
<hr />
|
||||
<h4>Triggers</h4>
|
||||
<p>
|
||||
<button uib-popover="I appeared on mouse enter!" popover-trigger="mouseenter" type="button" class="btn btn-default">Mouseenter</button>
|
||||
<button uib-popover="I appeared on mouse enter!" popover-trigger="'mouseenter'" type="button" class="btn btn-default">Mouseenter</button>
|
||||
</p>
|
||||
<input type="text" value="Click me!" uib-popover="I appeared on focus! Click away and I'll vanish..." popover-trigger="focus" class="form-control">
|
||||
<input type="text" value="Click me!" uib-popover="I appeared on focus! Click away and I'll vanish..." popover-trigger="'focus'" class="form-control">
|
||||
|
||||
<hr />
|
||||
<h4>Other</h4>
|
||||
|
||||
@@ -76,8 +76,9 @@ All these settings are available for the three types of popovers.
|
||||
A string to display as a fancy title.
|
||||
|
||||
* `popover-trigger`
|
||||
_(Default: `click`)_ -
|
||||
What should trigger a show of the popover? Supports a space separated list of event names (see below).
|
||||
<small class="badge">$</small>
|
||||
_(Default: `'click'`)_ -
|
||||
What should trigger a show of the popover? Supports a space separated list of event names, or objects (see below).
|
||||
|
||||
**Note:** To configure the tooltips, you need to do it on `$uibTooltipProvider` (also see below).
|
||||
|
||||
|
||||
@@ -7,9 +7,8 @@ angular.module('ui.bootstrap.popover', ['ui.bootstrap.tooltip'])
|
||||
|
||||
.directive('uibPopoverTemplatePopup', function() {
|
||||
return {
|
||||
replace: true,
|
||||
scope: { uibTitle: '@', contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&',
|
||||
originScope: '&' },
|
||||
restrict: 'A',
|
||||
scope: { uibTitle: '@', contentExp: '&', originScope: '&' },
|
||||
templateUrl: 'uib/template/popover/popover-template.html'
|
||||
};
|
||||
})
|
||||
@@ -22,8 +21,8 @@ angular.module('ui.bootstrap.popover', ['ui.bootstrap.tooltip'])
|
||||
|
||||
.directive('uibPopoverHtmlPopup', function() {
|
||||
return {
|
||||
replace: true,
|
||||
scope: { contentExp: '&', uibTitle: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
|
||||
restrict: 'A',
|
||||
scope: { contentExp: '&', uibTitle: '@' },
|
||||
templateUrl: 'uib/template/popover/popover-html.html'
|
||||
};
|
||||
})
|
||||
@@ -36,8 +35,8 @@ angular.module('ui.bootstrap.popover', ['ui.bootstrap.tooltip'])
|
||||
|
||||
.directive('uibPopoverPopup', function() {
|
||||
return {
|
||||
replace: true,
|
||||
scope: { uibTitle: '@', content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
|
||||
restrict: 'A',
|
||||
scope: { uibTitle: '@', content: '@' },
|
||||
templateUrl: 'uib/template/popover/popover.html'
|
||||
};
|
||||
})
|
||||
|
||||
@@ -21,6 +21,7 @@ describe('popover', function() {
|
||||
scope.template = $sce.trustAsHtml('<span>My template</span>');
|
||||
$compile(elmBody)(scope);
|
||||
scope.$digest();
|
||||
$document.find('body').append(elmBody);
|
||||
elm = elmBody.find('span');
|
||||
elmScope = elm.scope();
|
||||
tooltipScope = elmScope.$$childTail;
|
||||
@@ -87,6 +88,7 @@ describe('popover', function() {
|
||||
it('should hide popover when template becomes empty', inject(function($timeout) {
|
||||
elm.trigger('click');
|
||||
tooltipScope.$digest();
|
||||
$timeout.flush(0);
|
||||
expect(tooltipScope.isOpen).toBe(true);
|
||||
|
||||
scope.template = '';
|
||||
|
||||
@@ -25,6 +25,7 @@ describe('popover template', function() {
|
||||
|
||||
scope = $rootScope;
|
||||
$compile(elmBody)(scope);
|
||||
$document.find('body').append(elmBody);
|
||||
scope.templateUrl = 'myUrl';
|
||||
|
||||
scope.$digest();
|
||||
@@ -35,6 +36,7 @@ describe('popover template', function() {
|
||||
|
||||
afterEach(function() {
|
||||
$document.off('keypress');
|
||||
elmBody.remove();
|
||||
});
|
||||
|
||||
it('should open on click', inject(function() {
|
||||
@@ -75,6 +77,7 @@ describe('popover template', function() {
|
||||
it('should hide popover when template becomes empty', inject(function($timeout) {
|
||||
elm.trigger('click');
|
||||
tooltipScope.$digest();
|
||||
$timeout.flush(0);
|
||||
expect(tooltipScope.isOpen).toBe(true);
|
||||
|
||||
scope.templateUrl = '';
|
||||
|
||||
@@ -529,13 +529,33 @@ angular.module('ui.bootstrap.position', [])
|
||||
},
|
||||
|
||||
/**
|
||||
* Provides a way for positioning tooltip & dropdown
|
||||
* arrows when using placement options beyond the standard
|
||||
* left, right, top, or bottom.
|
||||
*
|
||||
* @param {element} elem - The tooltip/dropdown element.
|
||||
* @param {string} placement - The placement for the elem.
|
||||
*/
|
||||
* Provides a way to adjust the top positioning after first
|
||||
* render to correctly align element to top after content
|
||||
* rendering causes resized element height
|
||||
*
|
||||
* @param {array} placementClasses - The array of strings of classes
|
||||
* element should have.
|
||||
* @param {object} containerPosition - The object with container
|
||||
* position information
|
||||
* @param {number} initialHeight - The initial height for the elem.
|
||||
* @param {number} currentHeight - The current height for the elem.
|
||||
*/
|
||||
adjustTop: function(placementClasses, containerPosition, initialHeight, currentHeight) {
|
||||
if (placementClasses.indexOf('top') !== -1 && initialHeight !== currentHeight) {
|
||||
return {
|
||||
top: containerPosition.top - currentHeight + 'px'
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Provides a way for positioning tooltip & dropdown
|
||||
* arrows when using placement options beyond the standard
|
||||
* left, right, top, or bottom.
|
||||
*
|
||||
* @param {element} elem - The tooltip/dropdown element.
|
||||
* @param {string} placement - The placement for the elem.
|
||||
*/
|
||||
positionArrow: function(elem, placement) {
|
||||
elem = this.getRawNode(elem);
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ It supports multiple (stacked) `<uib-bar>` into the same `<uib-progress>` elemen
|
||||
|
||||
* `type`
|
||||
_(Default: `null`)_ -
|
||||
Bootstrap style type. Possible values are 'success', 'info', 'warning', and, 'error' to use Bootstrap's pre-existing styling, or any desired custom suffix.
|
||||
Bootstrap style type. Possible values are 'success', 'info', 'warning', and, 'danger' to use Bootstrap's pre-existing styling, or any desired custom suffix.
|
||||
|
||||
* `title`
|
||||
_(Default: `progressbar`)_ -
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div ng-controller="RatingDemoCtrl">
|
||||
<h4>Default</h4>
|
||||
<uib-rating ng-model="rate" max="max" read-only="isReadonly" on-hover="hoveringOver(value)" on-leave="overStar = null" titles="['one','two','three']" aria-labelledby="default-rating"></uib-rating>
|
||||
<span uib-rating ng-model="rate" max="max" read-only="isReadonly" on-hover="hoveringOver(value)" on-leave="overStar = null" titles="['one','two','three']" aria-labelledby="default-rating"></span>
|
||||
<span class="label" ng-class="{'label-warning': percent<30, 'label-info': percent>=30 && percent<70, 'label-success': percent>=70}" ng-show="overStar && !isReadonly">{{percent}}%</span>
|
||||
|
||||
<pre style="margin:15px 0;">Rate: <b>{{rate}}</b> - Readonly is: <i>{{isReadonly}}</i> - Hovering over: <b>{{overStar || "none"}}</b></pre>
|
||||
@@ -10,6 +10,6 @@
|
||||
<hr />
|
||||
|
||||
<h4>Custom icons</h4>
|
||||
<div ng-init="x = 5"><uib-rating ng-model="x" max="15" state-on="'glyphicon-ok-sign'" state-off="'glyphicon-ok-circle'" aria-labelledby="custom-icons-1"></uib-rating> <b>(<i>Rate:</i> {{x}})</b></div>
|
||||
<div ng-init="y = 2"><uib-rating ng-model="y" rating-states="ratingStates" aria-labelledby="custom-icons-2"></uib-rating> <b>(<i>Rate:</i> {{y}})</b></div>
|
||||
<div ng-init="x = 5"><span uib-rating ng-model="x" max="15" state-on="'glyphicon-ok-sign'" state-off="'glyphicon-ok-circle'" aria-labelledby="custom-icons-1"></span> <b>(<i>Rate:</i> {{x}})</b></div>
|
||||
<div ng-init="y = 2"><span uib-rating ng-model="y" rating-states="ratingStates" aria-labelledby="custom-icons-2"></span> <b>(<i>Rate:</i> {{y}})</b></div>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@ angular.module('ui.bootstrap.rating', [])
|
||||
stateOn: null,
|
||||
stateOff: null,
|
||||
enableReset: true,
|
||||
titles : ['one', 'two', 'three', 'four', 'five']
|
||||
titles: ['one', 'two', 'three', 'four', 'five']
|
||||
})
|
||||
|
||||
.controller('UibRatingController', ['$scope', '$attrs', 'uibRatingConfig', function($scope, $attrs, ratingConfig) {
|
||||
@@ -90,6 +90,7 @@ angular.module('ui.bootstrap.rating', [])
|
||||
.directive('uibRating', function() {
|
||||
return {
|
||||
require: ['uibRating', 'ngModel'],
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
readonly: '=?readOnly',
|
||||
onHover: '&',
|
||||
@@ -97,7 +98,6 @@ angular.module('ui.bootstrap.rating', [])
|
||||
},
|
||||
controller: 'UibRatingController',
|
||||
templateUrl: 'uib/template/rating/rating.html',
|
||||
replace: true,
|
||||
link: function(scope, element, attrs, ctrls) {
|
||||
var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1];
|
||||
ratingCtrl.init(ngModelCtrl);
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
describe('rating directive', function() {
|
||||
var $rootScope, $compile, element;
|
||||
var $rootScope, $compile, element, innerElem;
|
||||
beforeEach(module('ui.bootstrap.rating'));
|
||||
beforeEach(module('uib/template/rating/rating.html'));
|
||||
beforeEach(inject(function(_$compile_, _$rootScope_) {
|
||||
$compile = _$compile_;
|
||||
$rootScope = _$rootScope_;
|
||||
$rootScope.rate = 3;
|
||||
element = $compile('<uib-rating ng-model="rate"></uib-rating>')($rootScope);
|
||||
element = $compile('<span uib-rating ng-model="rate"></span>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
innerElem = element.children().eq(0);
|
||||
}));
|
||||
|
||||
function getStars() {
|
||||
return element.find('i');
|
||||
return innerElem.find('i');
|
||||
}
|
||||
|
||||
function getStar(number) {
|
||||
@@ -38,17 +39,17 @@ describe('rating directive', function() {
|
||||
function triggerKeyDown(keyCode) {
|
||||
var e = $.Event('keydown');
|
||||
e.which = keyCode;
|
||||
element.trigger(e);
|
||||
innerElem.trigger(e);
|
||||
}
|
||||
|
||||
it('contains the default number of icons', function() {
|
||||
expect(getStars().length).toBe(5);
|
||||
expect(element.attr('aria-valuemax')).toBe('5');
|
||||
expect(innerElem.attr('aria-valuemax')).toBe('5');
|
||||
});
|
||||
|
||||
it('initializes the default star icons as selected', function() {
|
||||
expect(getState()).toEqual([true, true, true, false, false]);
|
||||
expect(element.attr('aria-valuenow')).toBe('3');
|
||||
expect(innerElem.attr('aria-valuenow')).toBe('3');
|
||||
});
|
||||
|
||||
it('handles correctly the click event', function() {
|
||||
@@ -56,19 +57,19 @@ describe('rating directive', function() {
|
||||
$rootScope.$digest();
|
||||
expect(getState()).toEqual([true, true, false, false, false]);
|
||||
expect($rootScope.rate).toBe(2);
|
||||
expect(element.attr('aria-valuenow')).toBe('2');
|
||||
expect(innerElem.attr('aria-valuenow')).toBe('2');
|
||||
|
||||
getStar(5).click();
|
||||
$rootScope.$digest();
|
||||
expect(getState()).toEqual([true, true, true, true, true]);
|
||||
expect($rootScope.rate).toBe(5);
|
||||
expect(element.attr('aria-valuenow')).toBe('5');
|
||||
expect(innerElem.attr('aria-valuenow')).toBe('5');
|
||||
|
||||
getStar(5).click();
|
||||
$rootScope.$digest();
|
||||
expect(getState()).toEqual([false, false, false, false, false]);
|
||||
expect($rootScope.rate).toBe(0);
|
||||
expect(element.attr('aria-valuenow')).toBe('0');
|
||||
expect(innerElem.attr('aria-valuenow')).toBe('0');
|
||||
});
|
||||
|
||||
it('handles correctly the hover event', function() {
|
||||
@@ -82,7 +83,7 @@ describe('rating directive', function() {
|
||||
expect(getState()).toEqual([true, true, true, true, true]);
|
||||
expect($rootScope.rate).toBe(3);
|
||||
|
||||
element.trigger('mouseout');
|
||||
innerElem.trigger('mouseout');
|
||||
expect(getState()).toEqual([true, true, true, false, false]);
|
||||
expect($rootScope.rate).toBe(3);
|
||||
});
|
||||
@@ -92,13 +93,13 @@ describe('rating directive', function() {
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getState()).toEqual([true, true, false, false, false]);
|
||||
expect(element.attr('aria-valuenow')).toBe('2');
|
||||
expect(innerElem.attr('aria-valuenow')).toBe('2');
|
||||
|
||||
$rootScope.rate = 2.5;
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getState()).toEqual([true, true, true, false, false]);
|
||||
expect(element.attr('aria-valuenow')).toBe('3');
|
||||
expect(innerElem.attr('aria-valuenow')).toBe('3');
|
||||
});
|
||||
|
||||
it('changes the number of selected icons when value changes', function() {
|
||||
@@ -106,30 +107,33 @@ describe('rating directive', function() {
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(getState()).toEqual([true, true, false, false, false]);
|
||||
expect(element.attr('aria-valuenow')).toBe('2');
|
||||
expect(element.attr('aria-valuetext')).toBe('two');
|
||||
expect(innerElem.attr('aria-valuenow')).toBe('2');
|
||||
expect(innerElem.attr('aria-valuetext')).toBe('two');
|
||||
});
|
||||
|
||||
it('shows different number of icons when `max` attribute is set', function() {
|
||||
element = $compile('<uib-rating ng-model="rate" max="7"></uib-rating>')($rootScope);
|
||||
element = $compile('<span uib-rating ng-model="rate" max="7"></span>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
innerElem = element.children().eq(0);
|
||||
|
||||
expect(getStars().length).toBe(7);
|
||||
expect(element.attr('aria-valuemax')).toBe('7');
|
||||
expect(innerElem.attr('aria-valuemax')).toBe('7');
|
||||
});
|
||||
|
||||
it('shows different number of icons when `max` attribute is from scope variable', function() {
|
||||
$rootScope.max = 15;
|
||||
element = $compile('<uib-rating ng-model="rate" max="max"></uib-rating>')($rootScope);
|
||||
element = $compile('<span uib-rating ng-model="rate" max="max"></span>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
innerElem = element.children().eq(0);
|
||||
expect(getStars().length).toBe(15);
|
||||
expect(element.attr('aria-valuemax')).toBe('15');
|
||||
expect(innerElem.attr('aria-valuemax')).toBe('15');
|
||||
});
|
||||
|
||||
it('handles read-only attribute', function() {
|
||||
$rootScope.isReadonly = true;
|
||||
element = $compile('<uib-rating ng-model="rate" read-only="isReadonly"></uib-rating>')($rootScope);
|
||||
element = $compile('<span uib-rating ng-model="rate" read-only="isReadonly"></span>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
innerElem = element.children().eq(0);
|
||||
|
||||
expect(getState()).toEqual([true, true, true, false, false]);
|
||||
|
||||
@@ -148,8 +152,9 @@ describe('rating directive', function() {
|
||||
|
||||
it('handles enable-reset attribute', function() {
|
||||
$rootScope.canReset = false;
|
||||
element = $compile('<uib-rating ng-model="rate" enable-reset="canReset"></uib-rating>')($rootScope);
|
||||
element = $compile('<span uib-rating ng-model="rate" enable-reset="canReset"></span>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
innerElem = element.children().eq(0);
|
||||
|
||||
var star = {
|
||||
states: [true, true, true, true, true],
|
||||
@@ -162,19 +167,20 @@ describe('rating directive', function() {
|
||||
$rootScope.$digest();
|
||||
expect(getState()).toEqual(star.states);
|
||||
expect($rootScope.rate).toBe(5);
|
||||
expect(element.attr('aria-valuenow')).toBe('5');
|
||||
expect(innerElem.attr('aria-valuenow')).toBe('5');
|
||||
|
||||
selectStar.click();
|
||||
$rootScope.$digest();
|
||||
expect(getState()).toEqual(star.states);
|
||||
expect($rootScope.rate).toBe(5);
|
||||
expect(element.attr('aria-valuenow')).toBe('5');
|
||||
expect(innerElem.attr('aria-valuenow')).toBe('5');
|
||||
});
|
||||
|
||||
it('should fire onHover', function() {
|
||||
$rootScope.hoveringOver = jasmine.createSpy('hoveringOver');
|
||||
element = $compile('<uib-rating ng-model="rate" on-hover="hoveringOver(value)"></uib-rating>')($rootScope);
|
||||
element = $compile('<span uib-rating ng-model="rate" on-hover="hoveringOver(value)"></span>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
innerElem = element.children().eq(0);
|
||||
|
||||
getStar(3).trigger('mouseover');
|
||||
$rootScope.$digest();
|
||||
@@ -183,10 +189,11 @@ describe('rating directive', function() {
|
||||
|
||||
it('should fire onLeave', function() {
|
||||
$rootScope.leaving = jasmine.createSpy('leaving');
|
||||
element = $compile('<uib-rating ng-model="rate" on-leave="leaving()"></uib-rating>')($rootScope);
|
||||
element = $compile('<span uib-rating ng-model="rate" on-leave="leaving()"></span>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
innerElem = element.children().eq(0);
|
||||
|
||||
element.trigger('mouseleave');
|
||||
innerElem.trigger('mouseleave');
|
||||
$rootScope.$digest();
|
||||
expect($rootScope.leaving).toHaveBeenCalled();
|
||||
});
|
||||
@@ -243,8 +250,9 @@ describe('rating directive', function() {
|
||||
beforeEach(inject(function() {
|
||||
$rootScope.classOn = 'icon-ok-sign';
|
||||
$rootScope.classOff = 'icon-ok-circle';
|
||||
element = $compile('<uib-rating ng-model="rate" state-on="classOn" state-off="classOff"></uib-rating>')($rootScope);
|
||||
element = $compile('<span uib-rating ng-model="rate" state-on="classOn" state-off="classOff"></span>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
innerElem = element.children().eq(0);
|
||||
}));
|
||||
|
||||
it('changes the default icons', function() {
|
||||
@@ -260,13 +268,14 @@ describe('rating directive', function() {
|
||||
{stateOn: 'heart'},
|
||||
{stateOff: 'off'}
|
||||
];
|
||||
element = $compile('<uib-rating ng-model="rate" rating-states="states"></uib-rating>')($rootScope);
|
||||
element = $compile('<span uib-rating ng-model="rate" rating-states="states"></span>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
innerElem = element.children().eq(0);
|
||||
}));
|
||||
|
||||
it('should define number of icon elements', function() {
|
||||
expect(getStars().length).toBe(4);
|
||||
expect(element.attr('aria-valuemax')).toBe('4');
|
||||
expect(innerElem.attr('aria-valuemax')).toBe('4');
|
||||
});
|
||||
|
||||
it('handles each icon', function() {
|
||||
@@ -291,8 +300,9 @@ describe('rating directive', function() {
|
||||
uibRatingConfig.max = 10;
|
||||
uibRatingConfig.stateOn = 'on';
|
||||
uibRatingConfig.stateOff = 'off';
|
||||
element = $compile('<uib-rating ng-model="rate"></uib-rating>')($rootScope);
|
||||
element = $compile('<span uib-rating ng-model="rate"></span>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
innerElem = element.children().eq(0);
|
||||
}));
|
||||
afterEach(inject(function(uibRatingConfig) {
|
||||
// return it to the original state
|
||||
@@ -320,8 +330,9 @@ describe('rating directive', function() {
|
||||
$rootScope.rate = 5;
|
||||
angular.extend(originalConfig, uibRatingConfig);
|
||||
uibRatingConfig.max = 10;
|
||||
element = $compile('<uib-rating ng-model="rate"></uib-rating>')($rootScope);
|
||||
element = $compile('<span uib-rating ng-model="rate"></span>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
innerElem = element.children().eq(0);
|
||||
}));
|
||||
afterEach(inject(function(uibRatingConfig) {
|
||||
// return it to the original state
|
||||
@@ -336,18 +347,20 @@ describe('rating directive', function() {
|
||||
describe('shows custom titles ', function() {
|
||||
it('should return the custom title for each star', function() {
|
||||
$rootScope.titles = [44,45,46];
|
||||
element = $compile('<uib-rating ng-model="rate" titles="titles"></uib-rating>')($rootScope);
|
||||
element = $compile('<span uib-rating ng-model="rate" titles="titles"></span>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
innerElem = element.children().eq(0);
|
||||
expect(getTitles()).toEqual(['44', '45', '46', '4', '5']);
|
||||
});
|
||||
it('should return the default title if the custom title is empty', function() {
|
||||
$rootScope.titles = [];
|
||||
element = $compile('<uib-rating ng-model="rate" titles="titles"></uib-rating>')($rootScope);
|
||||
element = $compile('<span uib-rating ng-model="rate" titles="titles"></span>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
innerElem = element.children().eq(0);
|
||||
expect(getTitles()).toEqual(['one', 'two', 'three', 'four', 'five']);
|
||||
});
|
||||
it('should return the default title if the custom title is not an array', function() {
|
||||
element = $compile('<uib-rating ng-model="rate" titles="test"></uib-rating>')($rootScope);
|
||||
element = $compile('<span uib-rating ng-model="rate" titles="test"></span>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
expect(getTitles()).toEqual(['one', 'two', 'three', 'four', 'five']);
|
||||
});
|
||||
|
||||
@@ -43,7 +43,7 @@ angular.module('ui.bootstrap.stackedMap', [])
|
||||
return stack.splice(idx, 1)[0];
|
||||
},
|
||||
removeTop: function() {
|
||||
return stack.splice(stack.length - 1, 1)[0];
|
||||
return stack.pop();
|
||||
},
|
||||
length: function() {
|
||||
return stack.length;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
require('./tabindex');
|
||||
|
||||
var MODULE_NAME = 'ui.bootstrap.module.tabindex';
|
||||
|
||||
angular.module(MODULE_NAME, ['ui.bootstrap.tabindex']);
|
||||
|
||||
module.exports = MODULE_NAME;
|
||||
@@ -0,0 +1,12 @@
|
||||
angular.module('ui.bootstrap.tabindex', [])
|
||||
|
||||
.directive('uibTabindexToggle', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
link: function(scope, elem, attrs) {
|
||||
attrs.$observe('disabled', function(disabled) {
|
||||
attrs.$set('tabindex', disabled ? -1 : null);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
describe('tabindex toggle directive', function() {
|
||||
var $rootScope, element;
|
||||
beforeEach(module('ui.bootstrap.tabindex'));
|
||||
beforeEach(inject(function($compile, _$rootScope_) {
|
||||
$rootScope = _$rootScope_;
|
||||
element = $compile('<a href uib-tabindex-toggle ng-disabled="disabled">foo</a>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
|
||||
it('should toggle the tabindex on disabled toggle', function() {
|
||||
expect(element.prop('tabindex')).toBe(0);
|
||||
|
||||
$rootScope.disabled = true;
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element.prop('tabindex')).toBe(-1);
|
||||
|
||||
$rootScope.disabled = false;
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element.prop('tabindex')).toBe(0);
|
||||
});
|
||||
});
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<uib-tabset active="active">
|
||||
<uib-tab index="0" heading="Static title">Static content</uib-tab>
|
||||
<uib-tab index="$index + 1" ng-repeat="tab in tabs" heading="{{tab.title}}" active="tab.active" disable="tab.disabled">
|
||||
<uib-tab index="$index + 1" ng-repeat="tab in tabs" heading="{{tab.title}}" disable="tab.disabled">
|
||||
{{tab.content}}
|
||||
</uib-tab>
|
||||
<uib-tab index="3" select="alertMe()">
|
||||
|
||||
@@ -33,7 +33,7 @@ AngularJS version of the tabs directive.
|
||||
|
||||
* `deselect()`
|
||||
<small class="badge">$</small> -
|
||||
An optional expression called when tab is deactivated. Supports $event in template for expression. You may call `$event.preventDefault()` in this event handler to prevent a tab change from occurring.
|
||||
An optional expression called when tab is deactivated. Supports `$event` and `$selectedIndex` in template for expression. You may call `$event.preventDefault()` in this event handler to prevent a tab change from occurring. The `$selectedIndex` can be used to determine which tab was attempted to be opened.
|
||||
|
||||
* `disable`
|
||||
<small class="badge">$</small>
|
||||
@@ -45,7 +45,7 @@ AngularJS version of the tabs directive.
|
||||
Heading text.
|
||||
|
||||
* `index` -
|
||||
Tab index. Must be unique.
|
||||
Tab index. Must be unique number or string.
|
||||
|
||||
* `select()`
|
||||
<small class="badge">$</small> -
|
||||
|
||||
+5
-7
@@ -11,7 +11,8 @@ angular.module('ui.bootstrap.tabs', [])
|
||||
var previousSelected = ctrl.tabs[previousIndex];
|
||||
if (previousSelected) {
|
||||
previousSelected.tab.onDeselect({
|
||||
$event: evt
|
||||
$event: evt,
|
||||
$selectedIndex: index
|
||||
});
|
||||
if (evt && evt.isDefaultPrevented()) {
|
||||
return;
|
||||
@@ -27,7 +28,7 @@ angular.module('ui.bootstrap.tabs', [])
|
||||
selected.tab.active = true;
|
||||
ctrl.active = selected.index;
|
||||
oldIndex = selected.index;
|
||||
} else if (!selected && angular.isNumber(oldIndex)) {
|
||||
} else if (!selected && angular.isDefined(oldIndex)) {
|
||||
ctrl.active = null;
|
||||
oldIndex = null;
|
||||
}
|
||||
@@ -51,7 +52,7 @@ angular.module('ui.bootstrap.tabs', [])
|
||||
return 0;
|
||||
});
|
||||
|
||||
if (tab.index === ctrl.active || !angular.isNumber(ctrl.active) && ctrl.tabs.length === 1) {
|
||||
if (tab.index === ctrl.active || !angular.isDefined(ctrl.active) && ctrl.tabs.length === 1) {
|
||||
var newActiveIndex = findTabIndex(tab.index);
|
||||
ctrl.select(newActiveIndex);
|
||||
}
|
||||
@@ -76,7 +77,7 @@ angular.module('ui.bootstrap.tabs', [])
|
||||
};
|
||||
|
||||
$scope.$watch('tabset.active', function(val) {
|
||||
if (angular.isNumber(val) && val !== oldIndex) {
|
||||
if (angular.isDefined(val) && val !== oldIndex) {
|
||||
ctrl.select(findTabIndex(val));
|
||||
}
|
||||
});
|
||||
@@ -114,9 +115,6 @@ angular.module('ui.bootstrap.tabs', [])
|
||||
scope.$parent.$eval(attrs.vertical) : false;
|
||||
scope.justified = angular.isDefined(attrs.justified) ?
|
||||
scope.$parent.$eval(attrs.justified) : false;
|
||||
if (angular.isUndefined(attrs.active)) {
|
||||
scope.active = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
|
||||
@@ -46,14 +46,14 @@ describe('tabs', function() {
|
||||
};
|
||||
elm = $compile([
|
||||
'<uib-tabset class="hello" data-pizza="pepperoni" active="active">',
|
||||
' <uib-tab index="1" heading="First Tab {{first}}" classes="{{firstClass}}" select="selectFirst($event)" deselect="deselectFirst($event)">',
|
||||
' <uib-tab index="1" heading="First Tab {{first}}" classes="{{firstClass}}" select="selectFirst($event)" deselect="deselectFirst($event, $selectedIndex)">',
|
||||
' first content is {{first}}',
|
||||
' </uib-tab>',
|
||||
' <uib-tab index="2" classes="{{secondClass}}" select="selectSecond($event)" deselect="deselectSecond($event)">',
|
||||
' <uib-tab index="2" classes="{{secondClass}}" select="selectSecond($event)" deselect="deselectSecond($event, $selectedIndex)">',
|
||||
' <uib-tab-heading><b>Second</b> Tab {{second}}</uib-tab-heading>',
|
||||
' second content is {{second}}',
|
||||
' </uib-tab>',
|
||||
' <uib-tab index="3" classes="{{thirdClass}}" deselect="deselectThird($event)">',
|
||||
' <uib-tab index="3" classes="{{thirdClass}}" deselect="deselectThird($event, $selectedIndex)">',
|
||||
' <uib-tab-heading><b>Second</b> Tab {{third}}</uib-tab-heading>',
|
||||
' third content is {{third}}',
|
||||
' </uib-tab>',
|
||||
@@ -118,12 +118,15 @@ describe('tabs', function() {
|
||||
titles().eq(1).find('> a').click();
|
||||
expect(scope.deselectFirst).toHaveBeenCalled();
|
||||
expect(scope.deselectFirst.calls.argsFor(0)[0].target).toBe(titles().eq(1).find('> a')[0]);
|
||||
expect(scope.deselectFirst.calls.argsFor(0)[1]).toBe(1);
|
||||
titles().eq(0).find('> a').click();
|
||||
expect(scope.deselectSecond).toHaveBeenCalled();
|
||||
expect(scope.deselectSecond.calls.argsFor(0)[0].target).toBe(titles().eq(0).find('> a')[0]);
|
||||
expect(scope.deselectSecond.calls.argsFor(0)[1]).toBe(0);
|
||||
titles().eq(1).find('> a').click();
|
||||
expect(scope.deselectFirst.calls.count()).toBe(2);
|
||||
expect(scope.deselectFirst.calls.argsFor(1)[0].target).toBe(titles().eq(1).find('> a')[0]);
|
||||
expect(scope.deselectFirst.calls.argsFor(1)[1]).toBe(1);
|
||||
});
|
||||
|
||||
it('should prevent tab deselection when $event.preventDefault() is called', function() {
|
||||
@@ -223,6 +226,41 @@ describe('tabs', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('index as strings', function() {
|
||||
beforeEach(inject(function($compile, $rootScope) {
|
||||
scope = $rootScope.$new();
|
||||
scope.first = 'one';
|
||||
scope.second = 'two';
|
||||
scope.active = 'two';
|
||||
elm = $compile([
|
||||
'<uib-tabset active="active">',
|
||||
' <uib-tab index="first" heading="First Tab">',
|
||||
' first content',
|
||||
' </uib-tab>',
|
||||
' <uib-tab index="second" heading="Second Tab">',
|
||||
' second content',
|
||||
' </uib-tab>',
|
||||
'</uib-tabset>'
|
||||
].join('\n'))(scope);
|
||||
scope.$apply();
|
||||
return elm;
|
||||
}));
|
||||
|
||||
it('should set second tab active', function() {
|
||||
expect(titles().eq(0)).not.toHaveClass('active');
|
||||
expect(titles().eq(1)).toHaveClass('active');
|
||||
expect(elm.controller('uibTabset').active).toBe('two');
|
||||
});
|
||||
|
||||
it('should change active on click', function() {
|
||||
expect(titles().eq(0)).not.toHaveClass('active');
|
||||
titles().eq(0).find('> a').click();
|
||||
expect(titles().eq(0)).toHaveClass('active');
|
||||
expect(titles().eq(1)).not.toHaveClass('active');
|
||||
expect(elm.controller('uibTabset').active).toBe('one');
|
||||
});
|
||||
});
|
||||
|
||||
describe('tab callback order', function() {
|
||||
var execOrder;
|
||||
beforeEach(inject(function($compile, $rootScope) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div ng-controller="TimepickerDemoCtrl">
|
||||
|
||||
<uib-timepicker ng-model="mytime" ng-change="changed()" hour-step="hstep" minute-step="mstep" show-meridian="ismeridian"></uib-timepicker>
|
||||
<div uib-timepicker ng-model="mytime" ng-change="changed()" hour-step="hstep" minute-step="mstep" show-meridian="ismeridian"></div>
|
||||
|
||||
<pre class="alert alert-info">Time is: {{mytime | date:'shortTime' }}</pre>
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ describe('timepicker directive', function() {
|
||||
$rootScope.time = newTime(14, 40, 25);
|
||||
$templateCache = _$templateCache_;
|
||||
|
||||
element = $compile('<uib-timepicker ng-model="time"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
modelCtrl = element.controller('ngModel');
|
||||
@@ -130,7 +130,7 @@ describe('timepicker directive', function() {
|
||||
|
||||
it('has `selected` current time when model is initially cleared', function() {
|
||||
$rootScope.time = null;
|
||||
element = $compile('<uib-timepicker ng-model="time"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect($rootScope.time).toBe(null);
|
||||
@@ -385,7 +385,7 @@ describe('timepicker directive', function() {
|
||||
});
|
||||
|
||||
it('changes only the time part when minutes change', function() {
|
||||
element = $compile('<uib-timepicker ng-model="time" minute-step="15"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time" minute-step="15"></div>')($rootScope);
|
||||
$rootScope.time = newTime(0, 0, 0);
|
||||
$rootScope.$digest();
|
||||
|
||||
@@ -648,7 +648,7 @@ describe('timepicker directive', function() {
|
||||
$rootScope.mstep = 30;
|
||||
$rootScope.sstep = 30;
|
||||
$rootScope.time = newTime(14, 0 , 0);
|
||||
element = $compile('<uib-timepicker ng-model="time" hour-step="hstep" minute-step="mstep" second-step="sstep"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time" hour-step="hstep" minute-step="mstep" second-step="sstep"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -840,7 +840,7 @@ describe('timepicker directive', function() {
|
||||
beforeEach(function(){
|
||||
$rootScope.displaysSeconds = false;
|
||||
$rootScope.time = newTime(14,40,35);
|
||||
element = $compile('<uib-timepicker ng-model="time" show-seconds="displaysSeconds"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time" show-seconds="displaysSeconds"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -914,7 +914,7 @@ describe('timepicker directive', function() {
|
||||
beforeEach(function() {
|
||||
$rootScope.meridian = false;
|
||||
$rootScope.time = newTime(14, 10, 20);
|
||||
element = $compile('<uib-timepicker ng-model="time" show-meridian="meridian"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time" show-meridian="meridian"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
});
|
||||
|
||||
@@ -946,7 +946,7 @@ describe('timepicker directive', function() {
|
||||
|
||||
it('handles correctly initially empty model on parent element', function() {
|
||||
$rootScope.time = null;
|
||||
element = $compile('<span ng-model="time"><uib-timepicker show-meridian="meridian"></uib-timepicker></span>')($rootScope);
|
||||
element = $compile('<span ng-model="time"><div uib-timepicker show-meridian="meridian"></div></span>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect($rootScope.time).toBe(null);
|
||||
@@ -956,7 +956,7 @@ describe('timepicker directive', function() {
|
||||
describe('`meridians` attribute', function() {
|
||||
beforeEach(inject(function() {
|
||||
$rootScope.meridiansArray = ['am', 'pm'];
|
||||
element = $compile('<uib-timepicker ng-model="time" meridians="meridiansArray"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time" meridians="meridiansArray"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
|
||||
@@ -974,7 +974,7 @@ describe('timepicker directive', function() {
|
||||
describe('`readonly-input` attribute', function() {
|
||||
beforeEach(inject(function() {
|
||||
$rootScope.meridiansArray = ['am', 'pm'];
|
||||
element = $compile('<uib-timepicker ng-model="time" readonly-input="true"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time" readonly-input="true"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
|
||||
@@ -993,7 +993,7 @@ describe('timepicker directive', function() {
|
||||
}
|
||||
|
||||
it('should pad the hours by default', function() {
|
||||
element = $compile('<uib-timepicker ng-model="time"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
var inputs = element.find('input');
|
||||
@@ -1005,7 +1005,7 @@ describe('timepicker directive', function() {
|
||||
});
|
||||
|
||||
it('should not pad the hours', function() {
|
||||
element = $compile('<uib-timepicker ng-model="time" pad-hours="false"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time" pad-hours="false"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
var inputs = element.find('input');
|
||||
@@ -1025,7 +1025,7 @@ describe('timepicker directive', function() {
|
||||
uibTimepickerConfig.minuteStep = 10;
|
||||
uibTimepickerConfig.secondStep = 10;
|
||||
uibTimepickerConfig.showMeridian = false;
|
||||
element = $compile('<uib-timepicker ng-model="time"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
|
||||
@@ -1086,7 +1086,7 @@ describe('timepicker directive', function() {
|
||||
angular.extend(originalConfig, uibTimepickerConfig);
|
||||
uibTimepickerConfig.meridians = ['π.μ.', 'μ.μ.'];
|
||||
uibTimepickerConfig.showMeridian = true;
|
||||
element = $compile('<uib-timepicker ng-model="time"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
afterEach(inject(function(uibTimepickerConfig) {
|
||||
@@ -1116,7 +1116,7 @@ describe('timepicker directive', function() {
|
||||
$templateCache.put(newTemplateUrl, '<div>baz</div>');
|
||||
uibTimepickerConfig.templateUrl = newTemplateUrl;
|
||||
|
||||
element = $compile('<uib-timepicker ng-model="time"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
afterEach(inject(function(uibTimepickerConfig) {
|
||||
@@ -1126,7 +1126,7 @@ describe('timepicker directive', function() {
|
||||
|
||||
it('should use a custom template', function() {
|
||||
expect(element[0].tagName.toLowerCase()).toBe('div');
|
||||
expect(element.html()).toBe('baz');
|
||||
expect(element.html()).toBe('<div>baz</div>');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1328,7 +1328,7 @@ describe('timepicker directive', function() {
|
||||
|
||||
it('handles 12/24H mode change', function() {
|
||||
$rootScope.meridian = true;
|
||||
element = $compile('<uib-timepicker ng-model="time" show-meridian="meridian"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time" show-meridian="meridian"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
var el = getHoursInputEl();
|
||||
@@ -1346,14 +1346,14 @@ describe('timepicker directive', function() {
|
||||
});
|
||||
|
||||
it('should have a default tabindex of 0', function() {
|
||||
element = $compile('<uib-timepicker ng-model="time"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element.isolateScope().tabindex).toBe(0);
|
||||
});
|
||||
|
||||
it('should have the correct tabindex', function() {
|
||||
element = $compile('<uib-timepicker ng-model="time" tabindex="5"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time" tabindex="5"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element.attr('tabindex')).toBe(undefined);
|
||||
@@ -1363,7 +1363,7 @@ describe('timepicker directive', function() {
|
||||
|
||||
describe('when model is not a Date', function() {
|
||||
beforeEach(inject(function() {
|
||||
element = $compile('<uib-timepicker ng-model="time"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time"></div>')($rootScope);
|
||||
}));
|
||||
|
||||
it('should not be invalid when the model is null', function() {
|
||||
@@ -1415,7 +1415,7 @@ describe('timepicker directive', function() {
|
||||
describe('use with `ng-required` directive', function() {
|
||||
beforeEach(inject(function() {
|
||||
$rootScope.time = null;
|
||||
element = $compile('<uib-timepicker ng-model="time" ng-required="true"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time" ng-required="true"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
|
||||
@@ -1434,7 +1434,7 @@ describe('timepicker directive', function() {
|
||||
beforeEach(inject(function() {
|
||||
$rootScope.changeHandler = jasmine.createSpy('changeHandler');
|
||||
$rootScope.time = new Date();
|
||||
element = $compile('<uib-timepicker ng-model="time" ng-change="changeHandler()"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time" ng-change="changeHandler()"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
|
||||
@@ -1465,7 +1465,7 @@ describe('timepicker directive', function() {
|
||||
describe('when used with min', function() {
|
||||
var changeInputValueTo;
|
||||
beforeEach(inject(function($sniffer) {
|
||||
element = $compile('<uib-timepicker ng-model="time" min="min"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time" min="min"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
changeInputValueTo = function(inputEl, value) {
|
||||
inputEl.val(value);
|
||||
@@ -1792,7 +1792,7 @@ describe('timepicker directive', function() {
|
||||
describe('when used with max', function() {
|
||||
var changeInputValueTo;
|
||||
beforeEach(inject(function($sniffer) {
|
||||
element = $compile('<uib-timepicker ng-model="time" max="max"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time" max="max"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
changeInputValueTo = function(inputEl, value) {
|
||||
inputEl.val(value);
|
||||
@@ -2121,16 +2121,16 @@ describe('timepicker directive', function() {
|
||||
it('should allow custom templates', function() {
|
||||
$templateCache.put('foo/bar.html', '<div>baz</div>');
|
||||
|
||||
element = $compile('<uib-timepicker ng-model="time" template-url="foo/bar.html"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time" template-url="foo/bar.html"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
expect(element[0].tagName.toLowerCase()).toBe('div');
|
||||
expect(element.html()).toBe('baz');
|
||||
expect(element.html()).toBe('<div>baz</div>');
|
||||
});
|
||||
|
||||
it('should expose the controller on the view', function() {
|
||||
$templateCache.put('uib/template/timepicker/timepicker.html', '<div><div>{{timepicker.text}}</div></div>');
|
||||
|
||||
element = $compile('<uib-timepicker ng-model="time"></uib-timepicker>')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
var ctrl = element.controller('uibTimepicker');
|
||||
@@ -2139,14 +2139,14 @@ describe('timepicker directive', function() {
|
||||
ctrl.text = 'foo';
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(element.html()).toBe('<div class="ng-binding">foo</div>');
|
||||
expect(element.html()).toBe('<div><div class="ng-binding">foo</div></div>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('ngDisabled', function() {
|
||||
it('prevents modifying date via controls when true', function() {
|
||||
$rootScope.disabled = false;
|
||||
element = $compile('<uib-timepicker ng-model="time" ng-disabled="disabled"></uib-timepicker')($rootScope);
|
||||
element = $compile('<div uib-timepicker ng-model="time" ng-disabled="disabled"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
||||
var inputs = element.find('input');
|
||||
@@ -2250,7 +2250,7 @@ describe('timepicker directive', function() {
|
||||
var $scope;
|
||||
beforeEach(inject(function() {
|
||||
$scope = $rootScope.$new();
|
||||
element = $compile('<uib-timepicker ng-model="time"></uib-timepicker>')($scope);
|
||||
element = $compile('<div uib-timepicker ng-model="time"></div>')($scope);
|
||||
$rootScope.$digest();
|
||||
}));
|
||||
|
||||
|
||||
@@ -547,9 +547,9 @@ angular.module('ui.bootstrap.timepicker', [])
|
||||
.directive('uibTimepicker', ['uibTimepickerConfig', function(uibTimepickerConfig) {
|
||||
return {
|
||||
require: ['uibTimepicker', '?^ngModel'],
|
||||
restrict: 'A',
|
||||
controller: 'UibTimepickerController',
|
||||
controllerAs: 'timepicker',
|
||||
replace: true,
|
||||
scope: {},
|
||||
templateUrl: function(element, attrs) {
|
||||
return attrs.templateUrl || uibTimepickerConfig.templateUrl;
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
|
||||
<div class="form-group">
|
||||
<label>Or use custom triggers, like focus: </label>
|
||||
<input type="text" value="Click me!" uib-tooltip="See? Now click away..." tooltip-trigger="focus" tooltip-placement="right" class="form-control" />
|
||||
<input type="text" value="Click me!" uib-tooltip="See? Now click away..." tooltip-trigger="'focus'" tooltip-placement="right" class="form-control" />
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{'has-error' : !inputModel}">
|
||||
@@ -60,7 +60,7 @@
|
||||
placeholder="Hover over this for a tooltip until this is filled"
|
||||
uib-tooltip="Enter something in this input field to disable this tooltip"
|
||||
tooltip-placement="top"
|
||||
tooltip-trigger="mouseenter"
|
||||
tooltip-trigger="'mouseenter'"
|
||||
tooltip-enable="!inputModel" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
||||
@@ -74,8 +74,9 @@ All these settings are available for the three types of tooltips.
|
||||
Popup delay in milliseconds until it opens.
|
||||
|
||||
* `tooltip-trigger`
|
||||
_(Default: `mouseenter`)_ -
|
||||
What should trigger a show of the tooltip? Supports a space separated list of event names (see below).
|
||||
<small class="badge">$</small>
|
||||
_(Default: `'mouseenter'`)_ -
|
||||
What should trigger a show of the tooltip? Supports a space separated list of event names, or objects (see below).
|
||||
|
||||
**Note:** To configure the tooltips, you need to do it on `$uibTooltipProvider` (also see below).
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ describe('tooltip template', function() {
|
||||
|
||||
it('should hide tooltip when template becomes empty', inject(function($timeout) {
|
||||
trigger(elm, 'mouseenter');
|
||||
$timeout.flush(0);
|
||||
expect(tooltipScope.isOpen).toBe(true);
|
||||
|
||||
scope.templateUrl = '';
|
||||
|
||||
@@ -179,7 +179,6 @@ describe('tooltip', function() {
|
||||
expect(elm.attr('alt')).toBe(scope.alt);
|
||||
|
||||
ttScope = angular.element(elmBody.children()[1]).isolateScope();
|
||||
expect(ttScope.placement).toBe('top');
|
||||
expect(ttScope.content).toBe(scope.tooltipMsg);
|
||||
|
||||
trigger(elm, 'mouseleave');
|
||||
@@ -188,7 +187,6 @@ describe('tooltip', function() {
|
||||
trigger(elm, 'mouseenter');
|
||||
|
||||
ttScope = angular.element(elmBody.children()[1]).isolateScope();
|
||||
expect(ttScope.placement).toBe('top');
|
||||
expect(ttScope.content).toBe(scope.tooltipMsg);
|
||||
}));
|
||||
|
||||
@@ -504,7 +502,7 @@ describe('tooltip', function() {
|
||||
|
||||
it('should use it to show but set the hide trigger based on the map for mapped triggers', inject(function($compile) {
|
||||
elmBody = angular.element(
|
||||
'<div><input uib-tooltip="Hello!" tooltip-trigger="focus" /></div>'
|
||||
'<div><input uib-tooltip="Hello!" tooltip-trigger="\'focus\'" /></div>'
|
||||
);
|
||||
$compile(elmBody)(scope);
|
||||
scope.$apply();
|
||||
@@ -521,7 +519,7 @@ describe('tooltip', function() {
|
||||
|
||||
it('should use it as both the show and hide triggers for unmapped triggers', inject(function($compile) {
|
||||
elmBody = angular.element(
|
||||
'<div><input uib-tooltip="Hello!" tooltip-trigger="fakeTriggerAttr" /></div>'
|
||||
'<div><input uib-tooltip="Hello!" tooltip-trigger="\'fakeTriggerAttr\'" /></div>'
|
||||
);
|
||||
$compile(elmBody)(scope);
|
||||
scope.$apply();
|
||||
@@ -540,8 +538,8 @@ describe('tooltip', function() {
|
||||
scope.test = true;
|
||||
elmBody = angular.element(
|
||||
'<div>' +
|
||||
'<input uib-tooltip="Hello!" tooltip-trigger="{{ (test && \'mouseenter\' || \'click\') }}" />' +
|
||||
'<input uib-tooltip="Hello!" tooltip-trigger="{{ (test && \'mouseenter\' || \'click\') }}" />' +
|
||||
'<input uib-tooltip="Hello!" tooltip-trigger="test && \'mouseenter\' || \'click\'" />' +
|
||||
'<input uib-tooltip="Hello!" tooltip-trigger="test && \'mouseenter\' || \'click\'" />' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
@@ -566,7 +564,7 @@ describe('tooltip', function() {
|
||||
|
||||
it('should accept multiple triggers based on the map for mapped triggers', inject(function($compile) {
|
||||
elmBody = angular.element(
|
||||
'<div><input uib-tooltip="Hello!" tooltip-trigger="focus fakeTriggerAttr" /></div>'
|
||||
'<div><input uib-tooltip="Hello!" tooltip-trigger="\'focus fakeTriggerAttr\'" /></div>'
|
||||
);
|
||||
$compile(elmBody)(scope);
|
||||
scope.$apply();
|
||||
@@ -587,7 +585,7 @@ describe('tooltip', function() {
|
||||
|
||||
it('should not show when trigger is set to "none"', inject(function($compile) {
|
||||
elmBody = angular.element(
|
||||
'<div><input uib-tooltip="Hello!" tooltip-trigger="none" /></div>'
|
||||
'<div><input uib-tooltip="Hello!" tooltip-trigger="\'none\'" /></div>'
|
||||
);
|
||||
$compile(elmBody)(scope);
|
||||
scope.$apply();
|
||||
@@ -601,7 +599,7 @@ describe('tooltip', function() {
|
||||
|
||||
it('should toggle on click and hide when anything else is clicked when trigger is set to "outsideClick"', inject(function($compile, $document) {
|
||||
elm = $compile(angular.element(
|
||||
'<span uib-tooltip="tooltip text" tooltip-trigger="outsideClick">Selector Text</span>'
|
||||
'<span uib-tooltip="tooltip text" tooltip-trigger="\'outsideClick\'">Selector Text</span>'
|
||||
))(scope);
|
||||
scope.$apply();
|
||||
elmScope = elm.scope();
|
||||
@@ -623,6 +621,23 @@ describe('tooltip', function() {
|
||||
tooltipScope.$digest();
|
||||
expect(tooltipScope.isOpen).toBeFalsy();
|
||||
}));
|
||||
|
||||
it('should support objects', inject(function($compile) {
|
||||
elmBody = angular.element(
|
||||
'<div><input uib-tooltip="Hello!" tooltip-trigger="{show: \'hide\'}" /></div>'
|
||||
);
|
||||
$compile(elmBody)(scope);
|
||||
scope.$apply();
|
||||
elm = elmBody.find('input');
|
||||
elmScope = elm.scope();
|
||||
tooltipScope = elmScope.$$childTail;
|
||||
|
||||
expect(tooltipScope.isOpen).toBeFalsy();
|
||||
trigger(elm, 'show');
|
||||
expect(tooltipScope.isOpen).toBeTruthy();
|
||||
trigger(elm, 'hide');
|
||||
expect(tooltipScope.isOpen).toBeFalsy();
|
||||
}));
|
||||
});
|
||||
|
||||
describe('with an append-to-body attribute', function() {
|
||||
@@ -673,7 +688,7 @@ describe('tooltip', function() {
|
||||
}
|
||||
|
||||
beforeEach(inject(function($compile, $rootScope) {
|
||||
elmBody = angular.element('<div><input uib-tooltip="Hello!" tooltip-trigger="fooTrigger" /></div>');
|
||||
elmBody = angular.element('<div><input uib-tooltip="Hello!" tooltip-trigger="\'fooTrigger\'" /></div>');
|
||||
|
||||
$compile(elmBody)($rootScope);
|
||||
$rootScope.$apply();
|
||||
@@ -754,7 +769,7 @@ describe('tooltipWithDifferentSymbols', function() {
|
||||
|
||||
it('should show the correct tooltip text', inject(function($compile, $rootScope) {
|
||||
elmBody = angular.element(
|
||||
'<div><input type="text" uib-tooltip="My tooltip" tooltip-trigger="focus" tooltip-placement="right" /></div>'
|
||||
'<div><input type="text" uib-tooltip="My tooltip" tooltip-trigger="\'focus\'" tooltip-placement="right" /></div>'
|
||||
);
|
||||
$compile(elmBody)($rootScope);
|
||||
$rootScope.$apply();
|
||||
@@ -1030,7 +1045,7 @@ describe('$uibTooltipProvider', function() {
|
||||
|
||||
it('should override the show and hide triggers if there is an attribute', inject(function($rootScope, $compile) {
|
||||
elmBody = angular.element(
|
||||
'<div><input uib-tooltip="tooltip text" tooltip-trigger="mouseenter"/></div>'
|
||||
'<div><input uib-tooltip="tooltip text" tooltip-trigger="\'mouseenter\'"/></div>'
|
||||
);
|
||||
|
||||
scope = $rootScope;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
describe('tooltip directive', function() {
|
||||
var $rootScope, $compile, $document, $timeout;
|
||||
var $rootScope, $compile, $document, $timeout, body, fragment;
|
||||
|
||||
beforeEach(module('ui.bootstrap.tooltip'));
|
||||
beforeEach(module('uib/template/tooltip/tooltip-popup.html'));
|
||||
@@ -10,6 +10,8 @@ describe('tooltip directive', function() {
|
||||
$compile = _$compile_;
|
||||
$document = _$document_;
|
||||
$timeout = _$timeout_;
|
||||
|
||||
body = $document.find('body');
|
||||
}));
|
||||
|
||||
beforeEach(function() {
|
||||
@@ -39,12 +41,13 @@ describe('tooltip directive', function() {
|
||||
|
||||
afterEach(function() {
|
||||
$document.off('keypress');
|
||||
fragment.remove();
|
||||
});
|
||||
|
||||
function compileTooltip(ttipMarkup) {
|
||||
var fragment = $compile('<div>' + ttipMarkup + '</div>')($rootScope);
|
||||
fragment = $compile('<div>' + ttipMarkup + '</div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
return fragment;
|
||||
body.append(fragment);
|
||||
}
|
||||
|
||||
function closeTooltip(hostEl, triggerEvt, shouldNotFlush) {
|
||||
@@ -62,7 +65,7 @@ describe('tooltip directive', function() {
|
||||
|
||||
describe('basic scenarios with default options', function() {
|
||||
it('shows default tooltip on mouse enter and closes on mouse leave', function() {
|
||||
var fragment = compileTooltip('<span uib-tooltip="tooltip text">Trigger here</span>');
|
||||
compileTooltip('<span uib-tooltip="tooltip text">Trigger here</span>');
|
||||
|
||||
trigger(fragment.find('span'), 'mouseenter');
|
||||
expect(fragment).toHaveOpenTooltips();
|
||||
@@ -72,16 +75,17 @@ describe('tooltip directive', function() {
|
||||
});
|
||||
|
||||
it('should not show a tooltip when its content is empty', function() {
|
||||
var fragment = compileTooltip('<span uib-tooltip=""></span>');
|
||||
compileTooltip('<span uib-tooltip=""></span>');
|
||||
trigger(fragment.find('span'), 'mouseenter');
|
||||
expect(fragment).not.toHaveOpenTooltips();
|
||||
});
|
||||
|
||||
it('should not show a tooltip when its content becomes empty', function() {
|
||||
$rootScope.content = 'some text';
|
||||
var fragment = compileTooltip('<span uib-tooltip="{{ content }}"></span>');
|
||||
compileTooltip('<span uib-tooltip="{{ content }}"></span>');
|
||||
|
||||
trigger(fragment.find('span'), 'mouseenter');
|
||||
$timeout.flush(0);
|
||||
expect(fragment).toHaveOpenTooltips();
|
||||
|
||||
$rootScope.content = '';
|
||||
@@ -92,7 +96,7 @@ describe('tooltip directive', function() {
|
||||
|
||||
it('should update tooltip when its content becomes empty', function() {
|
||||
$rootScope.content = 'some text';
|
||||
var fragment = compileTooltip('<span uib-tooltip="{{ content }}"></span>');
|
||||
compileTooltip('<span uib-tooltip="{{ content }}"></span>');
|
||||
|
||||
$rootScope.content = '';
|
||||
$rootScope.$digest();
|
||||
@@ -119,7 +123,7 @@ describe('tooltip directive', function() {
|
||||
describe(key, function() {
|
||||
describe('placement', function() {
|
||||
it('can specify an alternative, valid placement', function() {
|
||||
var fragment = compileTooltip('<span ' + html + ' tooltip-placement="left">Trigger here</span>');
|
||||
compileTooltip('<span ' + html + ' tooltip-placement="left">Trigger here</span>');
|
||||
trigger(fragment.find('span'), 'mouseenter');
|
||||
|
||||
var ttipElement = fragment.find('div.tooltip');
|
||||
@@ -133,7 +137,7 @@ describe('tooltip directive', function() {
|
||||
|
||||
describe('class', function() {
|
||||
it('can specify a custom class', function() {
|
||||
var fragment = compileTooltip('<span ' + html + ' tooltip-class="custom">Trigger here</span>');
|
||||
compileTooltip('<span ' + html + ' tooltip-class="custom">Trigger here</span>');
|
||||
trigger(fragment.find('span'), 'mouseenter');
|
||||
|
||||
var ttipElement = fragment.find('div.tooltip');
|
||||
@@ -149,7 +153,7 @@ describe('tooltip directive', function() {
|
||||
});
|
||||
|
||||
it('should show even after close trigger is called multiple times - issue #1847', function() {
|
||||
var fragment = compileTooltip('<span uib-tooltip="tooltip text">Trigger here</span>');
|
||||
compileTooltip('<span uib-tooltip="tooltip text">Trigger here</span>');
|
||||
|
||||
trigger(fragment.find('span'), 'mouseenter');
|
||||
expect(fragment).toHaveOpenTooltips();
|
||||
@@ -169,7 +173,7 @@ describe('tooltip directive', function() {
|
||||
});
|
||||
|
||||
it('should hide even after show trigger is called multiple times', function() {
|
||||
var fragment = compileTooltip('<span uib-tooltip="tooltip text" tooltip-popup-delay="1000">Trigger here</span>');
|
||||
compileTooltip('<span uib-tooltip="tooltip text" tooltip-popup-delay="1000">Trigger here</span>');
|
||||
|
||||
trigger(fragment.find('span'), 'mouseenter');
|
||||
trigger(fragment.find('span'), 'mouseenter');
|
||||
@@ -179,7 +183,7 @@ describe('tooltip directive', function() {
|
||||
});
|
||||
|
||||
it('should not show tooltips element is disabled (button) - issue #3167', function() {
|
||||
var fragment = compileTooltip('<button uib-tooltip="cancel!" ng-disabled="disabled" ng-click="disabled = true">Cancel</button>');
|
||||
compileTooltip('<button uib-tooltip="cancel!" ng-disabled="disabled" ng-click="disabled = true">Cancel</button>');
|
||||
|
||||
trigger(fragment.find('button'), 'mouseenter');
|
||||
expect(fragment).toHaveOpenTooltips();
|
||||
|
||||
+38
-17
@@ -126,12 +126,11 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
|
||||
(options.useContentExp ?
|
||||
'content-exp="contentExp()" ' :
|
||||
'content="' + startSym + 'content' + endSym + '" ') +
|
||||
'placement="' + startSym + 'placement' + endSym + '" ' +
|
||||
'popup-class="' + startSym + 'popupClass' + endSym + '" ' +
|
||||
'animation="animation" ' +
|
||||
'is-open="isOpen" ' +
|
||||
'origin-scope="origScope" ' +
|
||||
'class="uib-position-measure"' +
|
||||
'class="uib-position-measure ' + prefix + '" ' +
|
||||
'tooltip-animation-class="fade"' +
|
||||
'uib-tooltip-classes ' +
|
||||
'ng-class="{ in: isOpen }" ' +
|
||||
'>' +
|
||||
'</div>';
|
||||
|
||||
@@ -163,11 +162,14 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
|
||||
if (!positionTimeout) {
|
||||
positionTimeout = $timeout(function() {
|
||||
var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody);
|
||||
var initialHeight = angular.isDefined(tooltip.offsetHeight) ? tooltip.offsetHeight : tooltip.prop('offsetHeight');
|
||||
var elementPos = appendToBody ? $position.offset(element) : $position.position(element);
|
||||
tooltip.css({ top: ttPosition.top + 'px', left: ttPosition.left + 'px' });
|
||||
var placementClasses = ttPosition.placement.split('-');
|
||||
|
||||
if (!tooltip.hasClass(ttPosition.placement.split('-')[0])) {
|
||||
if (!tooltip.hasClass(placementClasses[0])) {
|
||||
tooltip.removeClass(lastPlacement.split('-')[0]);
|
||||
tooltip.addClass(ttPosition.placement.split('-')[0]);
|
||||
tooltip.addClass(placementClasses[0]);
|
||||
}
|
||||
|
||||
if (!tooltip.hasClass(options.placementClassPrefix + ttPosition.placement)) {
|
||||
@@ -175,6 +177,14 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
|
||||
tooltip.addClass(options.placementClassPrefix + ttPosition.placement);
|
||||
}
|
||||
|
||||
$timeout(function() {
|
||||
var currentHeight = angular.isDefined(tooltip.offsetHeight) ? tooltip.offsetHeight : tooltip.prop('offsetHeight');
|
||||
var adjustment = $position.adjustTop(placementClasses, elementPos, initialHeight, currentHeight);
|
||||
if (adjustment) {
|
||||
tooltip.css(adjustment);
|
||||
}
|
||||
}, 0, false);
|
||||
|
||||
// first time through tt element will have the
|
||||
// uib-position-measure class or if the placement
|
||||
// has changed we need to position the arrow.
|
||||
@@ -496,10 +506,22 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
|
||||
};
|
||||
|
||||
function prepTriggers() {
|
||||
var val = attrs[prefix + 'Trigger'];
|
||||
var showTriggers = [], hideTriggers = [];
|
||||
var val = scope.$eval(attrs[prefix + 'Trigger']);
|
||||
unregisterTriggers();
|
||||
|
||||
triggers = getTriggers(val);
|
||||
if (angular.isObject(val)) {
|
||||
Object.keys(val).forEach(function(key) {
|
||||
showTriggers.push(key);
|
||||
hideTriggers.push(val[key]);
|
||||
});
|
||||
triggers = {
|
||||
show: showTriggers,
|
||||
hide: hideTriggers
|
||||
};
|
||||
} else {
|
||||
triggers = getTriggers(val);
|
||||
}
|
||||
|
||||
if (triggers.show !== 'none') {
|
||||
triggers.show.forEach(function(trigger, idx) {
|
||||
@@ -644,7 +666,7 @@ function ($animate, $sce, $compile, $templateRequest) {
|
||||
element.addClass(scope.popupClass);
|
||||
}
|
||||
|
||||
if (scope.animation()) {
|
||||
if (scope.animation) {
|
||||
element.addClass(attrs.tooltipAnimationClass);
|
||||
}
|
||||
}
|
||||
@@ -653,8 +675,8 @@ function ($animate, $sce, $compile, $templateRequest) {
|
||||
|
||||
.directive('uibTooltipPopup', function() {
|
||||
return {
|
||||
replace: true,
|
||||
scope: { content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
|
||||
restrict: 'A',
|
||||
scope: { content: '@' },
|
||||
templateUrl: 'uib/template/tooltip/tooltip-popup.html'
|
||||
};
|
||||
})
|
||||
@@ -665,9 +687,8 @@ function ($animate, $sce, $compile, $templateRequest) {
|
||||
|
||||
.directive('uibTooltipTemplatePopup', function() {
|
||||
return {
|
||||
replace: true,
|
||||
scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&',
|
||||
originScope: '&' },
|
||||
restrict: 'A',
|
||||
scope: { contentExp: '&', originScope: '&' },
|
||||
templateUrl: 'uib/template/tooltip/tooltip-template-popup.html'
|
||||
};
|
||||
})
|
||||
@@ -680,8 +701,8 @@ function ($animate, $sce, $compile, $templateRequest) {
|
||||
|
||||
.directive('uibTooltipHtmlPopup', function() {
|
||||
return {
|
||||
replace: true,
|
||||
scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },
|
||||
restrict: 'A',
|
||||
scope: { contentExp: '&' },
|
||||
templateUrl: 'uib/template/tooltip/tooltip-html-popup.html'
|
||||
};
|
||||
})
|
||||
|
||||
@@ -42,10 +42,10 @@
|
||||
<p class="message">select location from drop down.</p>
|
||||
|
||||
<ul class="dropdown-menu" role="listbox">
|
||||
<li ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }"
|
||||
ng-mouseenter="selectActive($index)" ng-click="selectMatch($index)" role="option" id="{{::match.id}}">
|
||||
<div uib-typeahead-match index="$index" match="match" query="query" template-url="templateUrl"></div>
|
||||
</li>
|
||||
<li class="uib-typeahead-match" ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }"
|
||||
ng-mouseenter="selectActive($index)" ng-click="selectMatch($index)" role="option" id="{{::match.id}}">
|
||||
<div uib-typeahead-match index="$index" match="match" query="query" template-url="templateUrl"></div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
@@ -77,6 +77,11 @@ This directive works with promises, meaning you can retrieve matches using the `
|
||||
_(Default: `angular.noop`)_ -
|
||||
Binding to a variable that indicates if no matching results were found.
|
||||
|
||||
* `typeahead-should-select($event)`
|
||||
<small class="badge">$</small>
|
||||
_(Default: `null`)_ -
|
||||
A callback executed when a `keyup` event that might trigger a selection occurs. Selection will only occur if this function returns true.
|
||||
|
||||
* `typeahead-on-select($item, $model, $label, $event)`
|
||||
<small class="badge">$</small>
|
||||
_(Default: `null`)_ -
|
||||
@@ -115,3 +120,7 @@ This directive works with promises, meaning you can retrieve matches using the `
|
||||
<small class="badge">$</small>
|
||||
<i class="glyphicon glyphicon-eye-open"></i> -
|
||||
Comprehension Angular expression (see [select directive](http://docs.angularjs.org/api/ng.directive:select)).
|
||||
|
||||
**Notes**
|
||||
|
||||
If a custom template for the popup is used, the wrapper selector used for the match items is the `uib-typeahead-match` class.
|
||||
|
||||
@@ -222,8 +222,6 @@ describe('typeahead tests', function() {
|
||||
expect(element).toBeClosed();
|
||||
});
|
||||
|
||||
|
||||
|
||||
it('should support custom model selecting function', function() {
|
||||
$scope.updaterFn = function(selectedItem) {
|
||||
return 'prefix' + selectedItem;
|
||||
@@ -315,6 +313,39 @@ describe('typeahead tests', function() {
|
||||
expect($scope.form.input.$error.parse).toBeFalsy();
|
||||
});
|
||||
|
||||
// fix for #6032
|
||||
it('should clear errors and refresh scope after blur for typeahead-editable="false"', function () {
|
||||
var element = prepareInputEl(
|
||||
'<div><form name="form" ng-class="{invalid : form.input.$invalid}">' +
|
||||
'<input name="input" ng-model="result" uib-typeahead="item for item in source | filter:$viewValue" typeahead-editable="false">' +
|
||||
'</form></div>');
|
||||
var inputEl = findInput(element);
|
||||
|
||||
// first try
|
||||
changeInputValueTo(element, 'not in matches');
|
||||
expect($scope.result).toEqual(undefined);
|
||||
expect(inputEl.val()).toEqual('not in matches');
|
||||
expect(element.find('form')).toHaveClass('invalid');
|
||||
inputEl.blur();
|
||||
|
||||
expect(inputEl.val()).toEqual(''); // <-- input is reset
|
||||
expect($scope.form.input.$error.editable).toBeFalsy();
|
||||
expect($scope.form.input.$error.parse).toBeFalsy();
|
||||
expect(element.find('form')).not.toHaveClass('invalid'); // <-- form has no error (it always works for some reason)
|
||||
|
||||
// second try
|
||||
changeInputValueTo(element, 'not in matches');
|
||||
expect($scope.result).toEqual(undefined);
|
||||
expect(inputEl.val()).toEqual('not in matches');
|
||||
expect(element.find('form')).toHaveClass('invalid');
|
||||
inputEl.blur();
|
||||
|
||||
expect(inputEl.val()).toEqual(''); // <-- input is reset
|
||||
expect($scope.form.input.$error.editable).toBeFalsy();
|
||||
expect($scope.form.input.$error.parse).toBeFalsy();
|
||||
expect(element.find('form')).not.toHaveClass('invalid'); // <-- form has no error (it didn't work prior to #6032 fix)
|
||||
});
|
||||
|
||||
it('should go through other validators after blur for typeahead-editable="false"', function () {
|
||||
var element = prepareInputEl(
|
||||
'<div><form name="form">' +
|
||||
@@ -470,6 +501,57 @@ describe('typeahead tests', function() {
|
||||
};
|
||||
expect(prepareInvalidDir).toThrow();
|
||||
});
|
||||
|
||||
it('should remove the id attribute from the original DOM element', function() {
|
||||
var element = prepareInputEl('<div><input id="typeahead-element" ng-model="result" uib-typeahead="item for item in source | filter:$viewValue" typeahead-show-hint="true"></div>');
|
||||
var inputEl = findInput(element);
|
||||
|
||||
expect(inputEl.size()).toBe(2);
|
||||
expect(inputEl.eq(0).attr('id')).toBe(undefined);
|
||||
expect(inputEl.eq(1).attr('id')).toBe('typeahead-element');
|
||||
});
|
||||
});
|
||||
|
||||
describe('shouldSelect', function() {
|
||||
it('should select a match when function returns true', function() {
|
||||
$scope.shouldSelectFn = function() {
|
||||
return true;
|
||||
};
|
||||
var element = prepareInputEl('<div><input ng-model="result" typeahead-should-select="shouldSelectFn($event)" uib-typeahead="item for item in source | filter:$viewValue"></div>');
|
||||
var inputEl = findInput(element);
|
||||
|
||||
changeInputValueTo(element, 'b');
|
||||
triggerKeyDown(element, 13);
|
||||
|
||||
expect($scope.result).toEqual('bar');
|
||||
expect(inputEl.val()).toEqual('bar');
|
||||
expect(element).toBeClosed();
|
||||
});
|
||||
it('should not select a match when function returns false', function() {
|
||||
$scope.shouldSelectFn = function() {
|
||||
return false;
|
||||
};
|
||||
var element = prepareInputEl('<div><input ng-model="result" typeahead-should-select="shouldSelectFn($event)" uib-typeahead="item for item in source | filter:$viewValue"></div>');
|
||||
var inputEl = findInput(element);
|
||||
|
||||
changeInputValueTo(element, 'b');
|
||||
triggerKeyDown(element, 13);
|
||||
|
||||
// no change
|
||||
expect($scope.result).toEqual('b');
|
||||
expect(inputEl.val()).toEqual('b');
|
||||
});
|
||||
it('should pass key event into select trigger function', function() {
|
||||
$scope.shouldSelectFn = jasmine.createSpy('shouldSelectFn');//.and.returnValue(true);
|
||||
var element = prepareInputEl('<div><input ng-model="result" typeahead-should-select="shouldSelectFn($event)" uib-typeahead="item for item in source | filter:$viewValue"></div>');
|
||||
var inputEl = findInput(element);
|
||||
|
||||
changeInputValueTo(element, 'b');
|
||||
triggerKeyDown(element, 13);
|
||||
|
||||
expect($scope.shouldSelectFn.calls.count()).toEqual(1);
|
||||
expect($scope.shouldSelectFn.calls.argsFor(0)[0].which).toEqual(13);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selecting a match', function() {
|
||||
|
||||
+36
-22
@@ -42,7 +42,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap
|
||||
originalScope.$watch(attrs.typeaheadMinLength, function (newVal) {
|
||||
minLength = !newVal && newVal !== 0 ? 1 : newVal;
|
||||
});
|
||||
|
||||
|
||||
//minimal wait time after last character typed before typeahead kicks-in
|
||||
var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;
|
||||
|
||||
@@ -55,6 +55,12 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap
|
||||
//binding to a variable that indicates if matches are being retrieved asynchronously
|
||||
var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;
|
||||
|
||||
//a function to determine if an event should cause selection
|
||||
var isSelectEvent = attrs.typeaheadShouldSelect ? $parse(attrs.typeaheadShouldSelect) : function(scope, vals) {
|
||||
var evt = vals.$event;
|
||||
return evt.which === 13 || evt.which === 9;
|
||||
};
|
||||
|
||||
//a callback executed when a match is selected
|
||||
var onSelectCallback = $parse(attrs.typeaheadOnSelect);
|
||||
|
||||
@@ -146,6 +152,10 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap
|
||||
'vertical-align': 'top',
|
||||
'background-color': 'transparent'
|
||||
});
|
||||
|
||||
if (hintInputElem.attr('id')) {
|
||||
hintInputElem.removeAttr('id'); // remove duplicate id if present.
|
||||
}
|
||||
inputsContainer.append(hintInputElem);
|
||||
hintInputElem.after(element);
|
||||
}
|
||||
@@ -370,13 +380,15 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap
|
||||
return;
|
||||
}
|
||||
|
||||
var shouldSelect = isSelectEvent(originalScope, {$event: evt});
|
||||
|
||||
/**
|
||||
* if there's nothing selected (i.e. focusFirst) and enter or tab is hit
|
||||
* or
|
||||
* shift + tab is pressed to bring focus to the previous element
|
||||
* then clear the results
|
||||
*/
|
||||
if (scope.activeIdx === -1 && (evt.which === 9 || evt.which === 13) || evt.which === 9 && !!evt.shiftKey) {
|
||||
if (scope.activeIdx === -1 && shouldSelect || evt.which === 9 && !!evt.shiftKey) {
|
||||
resetMatches();
|
||||
scope.$digest();
|
||||
return;
|
||||
@@ -385,36 +397,36 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap
|
||||
evt.preventDefault();
|
||||
var target;
|
||||
switch (evt.which) {
|
||||
case 9:
|
||||
case 13:
|
||||
scope.$apply(function () {
|
||||
if (angular.isNumber(scope.debounceUpdate) || angular.isObject(scope.debounceUpdate)) {
|
||||
$$debounce(function() {
|
||||
scope.select(scope.activeIdx, evt);
|
||||
}, angular.isNumber(scope.debounceUpdate) ? scope.debounceUpdate : scope.debounceUpdate['default']);
|
||||
} else {
|
||||
scope.select(scope.activeIdx, evt);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 27:
|
||||
case 27: // escape
|
||||
evt.stopPropagation();
|
||||
|
||||
resetMatches();
|
||||
originalScope.$digest();
|
||||
break;
|
||||
case 38:
|
||||
case 38: // up arrow
|
||||
scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1;
|
||||
scope.$digest();
|
||||
target = popUpEl.find('li')[scope.activeIdx];
|
||||
target = popUpEl[0].querySelectorAll('.uib-typeahead-match')[scope.activeIdx];
|
||||
target.parentNode.scrollTop = target.offsetTop;
|
||||
break;
|
||||
case 40:
|
||||
case 40: // down arrow
|
||||
scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;
|
||||
scope.$digest();
|
||||
target = popUpEl.find('li')[scope.activeIdx];
|
||||
target = popUpEl[0].querySelectorAll('.uib-typeahead-match')[scope.activeIdx];
|
||||
target.parentNode.scrollTop = target.offsetTop;
|
||||
break;
|
||||
default:
|
||||
if (shouldSelect) {
|
||||
scope.$apply(function() {
|
||||
if (angular.isNumber(scope.debounceUpdate) || angular.isObject(scope.debounceUpdate)) {
|
||||
$$debounce(function() {
|
||||
scope.select(scope.activeIdx, evt);
|
||||
}, angular.isNumber(scope.debounceUpdate) ? scope.debounceUpdate : scope.debounceUpdate['default']);
|
||||
} else {
|
||||
scope.select(scope.activeIdx, evt);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -442,9 +454,11 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.debounce', 'ui.bootstrap
|
||||
}
|
||||
if (!isEditable && modelCtrl.$error.editable) {
|
||||
modelCtrl.$setViewValue();
|
||||
// Reset validity as we are clearing
|
||||
modelCtrl.$setValidity('editable', true);
|
||||
modelCtrl.$setValidity('parse', true);
|
||||
scope.$apply(function() {
|
||||
// Reset validity as we are clearing
|
||||
modelCtrl.$setValidity('editable', true);
|
||||
modelCtrl.$setValidity('parse', true);
|
||||
});
|
||||
element.val('');
|
||||
}
|
||||
hasFocus = false;
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
<div class="panel" ng-class="panelClass || 'panel-default'">
|
||||
<div role="tab" id="{{::headingId}}" aria-selected="{{isOpen}}" class="panel-heading" ng-keypress="toggleOpen($event)">
|
||||
<h4 class="panel-title">
|
||||
<a role="button" data-toggle="collapse" href aria-expanded="{{isOpen}}" aria-controls="{{::panelId}}" tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading"><span uib-accordion-header ng-class="{'text-muted': isDisabled}">{{heading}}</span></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="{{::panelId}}" aria-labelledby="{{::headingId}}" aria-hidden="{{!isOpen}}" role="tabpanel" class="panel-collapse collapse" uib-collapse="!isOpen">
|
||||
<div class="panel-body" ng-transclude></div>
|
||||
</div>
|
||||
<div role="tab" id="{{::headingId}}" aria-selected="{{isOpen}}" class="panel-heading" ng-keypress="toggleOpen($event)">
|
||||
<h4 class="panel-title">
|
||||
<a role="button" data-toggle="collapse" href aria-expanded="{{isOpen}}" aria-controls="{{::panelId}}" tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading" ng-disabled="isDisabled" uib-tabindex-toggle><span uib-accordion-header ng-class="{'text-muted': isDisabled}">{{heading}}</span></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="{{::panelId}}" aria-labelledby="{{::headingId}}" aria-hidden="{{!isOpen}}" role="tabpanel" class="panel-collapse collapse" uib-collapse="!isOpen">
|
||||
<div class="panel-body" ng-transclude></div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<div class="alert" ng-class="['alert-' + (type || 'warning'), closeable ? 'alert-dismissible' : null]" role="alert">
|
||||
<button ng-show="closeable" type="button" class="close" ng-click="close({$event: $event})">
|
||||
<span aria-hidden="true">×</span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<div ng-transclude></div>
|
||||
</div>
|
||||
<button ng-show="closeable" type="button" class="close" ng-click="close({$event: $event})">
|
||||
<span aria-hidden="true">×</span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<div ng-transclude></div>
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
<div ng-mouseenter="pause()" ng-mouseleave="play()" class="carousel" ng-swipe-right="prev()" ng-swipe-left="next()">
|
||||
<div class="carousel-inner" ng-transclude></div>
|
||||
<a role="button" href class="left carousel-control" ng-click="prev()" ng-class="{ disabled: isPrevDisabled() }" ng-show="slides.length > 1">
|
||||
<span aria-hidden="true" class="glyphicon glyphicon-chevron-left"></span>
|
||||
<span class="sr-only">previous</span>
|
||||
</a>
|
||||
<a role="button" href class="right carousel-control" ng-click="next()" ng-class="{ disabled: isNextDisabled() }" ng-show="slides.length > 1">
|
||||
<span aria-hidden="true" class="glyphicon glyphicon-chevron-right"></span>
|
||||
<span class="sr-only">next</span>
|
||||
</a>
|
||||
<ol class="carousel-indicators" ng-show="slides.length > 1">
|
||||
<li ng-repeat="slide in slides | orderBy:indexOfSlide track by $index" ng-class="{ active: isActive(slide) }" ng-click="select(slide)">
|
||||
<span class="sr-only">slide {{ $index + 1 }} of {{ slides.length }}<span ng-if="isActive(slide)">, currently active</span></span>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="carousel-inner" ng-transclude></div>
|
||||
<a role="button" href class="left carousel-control" ng-click="prev()" ng-class="{ disabled: isPrevDisabled() }" ng-show="slides.length > 1">
|
||||
<span aria-hidden="true" class="glyphicon glyphicon-chevron-left"></span>
|
||||
<span class="sr-only">previous</span>
|
||||
</a>
|
||||
<a role="button" href class="right carousel-control" ng-click="next()" ng-class="{ disabled: isNextDisabled() }" ng-show="slides.length > 1">
|
||||
<span aria-hidden="true" class="glyphicon glyphicon-chevron-right"></span>
|
||||
<span class="sr-only">next</span>
|
||||
</a>
|
||||
<ol class="carousel-indicators" ng-show="slides.length > 1">
|
||||
<li ng-repeat="slide in slides | orderBy:indexOfSlide track by $index" ng-class="{ active: isActive(slide) }" ng-click="select(slide)">
|
||||
<span class="sr-only">slide {{ $index + 1 }} of {{ slides.length }}<span ng-if="isActive(slide)">, currently active</span></span>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
<div ng-class="{
|
||||
'active': active
|
||||
}" class="item text-center" ng-transclude></div>
|
||||
<div class="text-center" ng-transclude></div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="uib-datepicker" ng-switch="datepickerMode" role="application" ng-keydown="keydown($event)">
|
||||
<uib-daypicker ng-switch-when="day" tabindex="0"></uib-daypicker>
|
||||
<uib-monthpicker ng-switch-when="month" tabindex="0"></uib-monthpicker>
|
||||
<uib-yearpicker ng-switch-when="year" tabindex="0"></uib-yearpicker>
|
||||
<div ng-switch="datepickerMode">
|
||||
<div uib-daypicker ng-switch-when="day" tabindex="0" class="uib-daypicker"></div>
|
||||
<div uib-monthpicker ng-switch-when="month" tabindex="0" class="uib-monthpicker"></div>
|
||||
<div uib-yearpicker ng-switch-when="year" tabindex="0" class="uib-yearpicker"></div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<table class="uib-daypicker" role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">
|
||||
<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<table class="uib-monthpicker" role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">
|
||||
<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>
|
||||
<th><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm uib-title" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1"><strong>{{title}}</strong></button></th>
|
||||
<th colspan="{{::yearHeaderColspan}}"><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm uib-title" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1"><strong>{{title}}</strong></button></th>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-right uib-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<table class="uib-yearpicker" role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">
|
||||
<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
<div>
|
||||
<ul class="uib-datepicker-popup dropdown-menu uib-position-measure" dropdown-nested ng-if="isOpen" ng-keydown="keydown($event)" ng-click="$event.stopPropagation()">
|
||||
<li ng-transclude></li>
|
||||
<li ng-if="showButtonBar" class="uib-button-bar">
|
||||
<span class="btn-group pull-left">
|
||||
<button type="button" class="btn btn-sm btn-info uib-datepicker-current" ng-click="select('today', $event)" ng-disabled="isDisabled('today')">{{ getText('current') }}</button>
|
||||
<button type="button" class="btn btn-sm btn-danger uib-clear" ng-click="select(null, $event)">{{ getText('clear') }}</button>
|
||||
</span>
|
||||
<button type="button" class="btn btn-sm btn-success pull-right uib-close" ng-click="close($event)">{{ getText('close') }}</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<ul class="uib-datepicker-popup dropdown-menu uib-position-measure" dropdown-nested ng-if="isOpen" ng-keydown="keydown($event)" ng-click="$event.stopPropagation()">
|
||||
<li ng-transclude></li>
|
||||
<li ng-if="showButtonBar" class="uib-button-bar">
|
||||
<span class="btn-group pull-left">
|
||||
<button type="button" class="btn btn-sm btn-info uib-datepicker-current" ng-click="select('today', $event)" ng-disabled="isDisabled('today')">{{ getText('current') }}</button>
|
||||
<button type="button" class="btn btn-sm btn-danger uib-clear" ng-click="select(null, $event)">{{ getText('clear') }}</button>
|
||||
</span>
|
||||
<button type="button" class="btn btn-sm btn-success pull-right uib-close" ng-click="close($event)">{{ getText('close') }}</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
<div class="modal-backdrop"
|
||||
uib-modal-animation-class="fade"
|
||||
modal-in-class="in"
|
||||
ng-style="{'z-index': 1040 + (index && 1 || 0) + index*10}"
|
||||
></div>
|
||||
@@ -1,6 +1 @@
|
||||
<div modal-render="{{$isRendered}}" tabindex="-1" role="dialog" class="modal"
|
||||
uib-modal-animation-class="fade"
|
||||
modal-in-class="in"
|
||||
ng-style="{'z-index': 1050 + index*10, display: 'block'}">
|
||||
<div class="modal-dialog {{size ? 'modal-' + size : ''}}"><div class="modal-content" uib-modal-transclude></div></div>
|
||||
</div>
|
||||
<div class="modal-dialog {{size ? 'modal-' + size : ''}}"><div class="modal-content" uib-modal-transclude></div></div>
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
<ul class="pager">
|
||||
<li ng-class="{disabled: noPrevious()||ngDisabled, previous: align}"><a href ng-click="selectPage(page - 1, $event)">{{::getText('previous')}}</a></li>
|
||||
<li ng-class="{disabled: noNext()||ngDisabled, next: align}"><a href ng-click="selectPage(page + 1, $event)">{{::getText('next')}}</a></li>
|
||||
</ul>
|
||||
<li ng-class="{disabled: noPrevious()||ngDisabled, previous: align}"><a href ng-click="selectPage(page - 1, $event)" ng-disabled="noPrevious()||ngDisabled" uib-tabindex-toggle>{{::getText('previous')}}</a></li>
|
||||
<li ng-class="{disabled: noNext()||ngDisabled, next: align}"><a href ng-click="selectPage(page + 1, $event)" ng-disabled="noNext()||ngDisabled" uib-tabindex-toggle>{{::getText('next')}}</a></li>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<ul class="pagination">
|
||||
<li ng-if="::boundaryLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-first"><a href ng-click="selectPage(1, $event)">{{::getText('first')}}</a></li>
|
||||
<li ng-if="::directionLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-prev"><a href ng-click="selectPage(page - 1, $event)">{{::getText('previous')}}</a></li>
|
||||
<li ng-repeat="page in pages track by $index" ng-class="{active: page.active,disabled: ngDisabled&&!page.active}" class="pagination-page"><a href ng-click="selectPage(page.number, $event)">{{page.text}}</a></li>
|
||||
<li ng-if="::directionLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-next"><a href ng-click="selectPage(page + 1, $event)">{{::getText('next')}}</a></li>
|
||||
<li ng-if="::boundaryLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-last"><a href ng-click="selectPage(totalPages, $event)">{{::getText('last')}}</a></li>
|
||||
</ul>
|
||||
<li ng-if="::boundaryLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-first"><a href ng-click="selectPage(1, $event)" ng-disabled="noPrevious()||ngDisabled" uib-tabindex-toggle>{{::getText('first')}}</a></li>
|
||||
<li ng-if="::directionLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-prev"><a href ng-click="selectPage(page - 1, $event)" ng-disabled="noPrevious()||ngDisabled" uib-tabindex-toggle>{{::getText('previous')}}</a></li>
|
||||
<li ng-repeat="page in pages track by $index" ng-class="{active: page.active,disabled: ngDisabled&&!page.active}" class="pagination-page"><a href ng-click="selectPage(page.number, $event)" ng-disabled="ngDisabled&&!page.active" uib-tabindex-toggle>{{page.text}}</a></li>
|
||||
<li ng-if="::directionLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-next"><a href ng-click="selectPage(page + 1, $event)" ng-disabled="noNext()||ngDisabled" uib-tabindex-toggle>{{::getText('next')}}</a></li>
|
||||
<li ng-if="::boundaryLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-last"><a href ng-click="selectPage(totalPages, $event)" ng-disabled="noNext()||ngDisabled" uib-tabindex-toggle>{{::getText('last')}}</a></li>
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
<div class="popover"
|
||||
tooltip-animation-class="fade"
|
||||
uib-tooltip-classes
|
||||
ng-class="{ in: isOpen() }">
|
||||
<div class="arrow"></div>
|
||||
<div class="arrow"></div>
|
||||
|
||||
<div class="popover-inner">
|
||||
<h3 class="popover-title" ng-bind="uibTitle" ng-if="uibTitle"></h3>
|
||||
<div class="popover-content" ng-bind-html="contentExp()"></div>
|
||||
</div>
|
||||
<div class="popover-inner">
|
||||
<h3 class="popover-title" ng-bind="uibTitle" ng-if="uibTitle"></h3>
|
||||
<div class="popover-content" ng-bind-html="contentExp()"></div>
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<div class="popover"
|
||||
tooltip-animation-class="fade"
|
||||
uib-tooltip-classes
|
||||
ng-class="{ in: isOpen() }">
|
||||
<div class="arrow"></div>
|
||||
<div class="arrow"></div>
|
||||
|
||||
<div class="popover-inner">
|
||||
<h3 class="popover-title" ng-bind="uibTitle" ng-if="uibTitle"></h3>
|
||||
<div class="popover-content"
|
||||
uib-tooltip-template-transclude="contentExp()"
|
||||
tooltip-template-transclude-scope="originScope()"></div>
|
||||
</div>
|
||||
<div class="popover-inner">
|
||||
<h3 class="popover-title" ng-bind="uibTitle" ng-if="uibTitle"></h3>
|
||||
<div class="popover-content"
|
||||
uib-tooltip-template-transclude="contentExp()"
|
||||
tooltip-template-transclude-scope="originScope()"></div>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
<div class="popover"
|
||||
tooltip-animation-class="fade"
|
||||
uib-tooltip-classes
|
||||
ng-class="{ in: isOpen() }">
|
||||
<div class="arrow"></div>
|
||||
<div class="arrow"></div>
|
||||
|
||||
<div class="popover-inner">
|
||||
<h3 class="popover-title" ng-bind="uibTitle" ng-if="uibTitle"></h3>
|
||||
<div class="popover-content" ng-bind="content"></div>
|
||||
</div>
|
||||
<div class="popover-inner">
|
||||
<h3 class="popover-title" ng-bind="uibTitle" ng-if="uibTitle"></h3>
|
||||
<div class="popover-content" ng-bind="content"></div>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<table class="uib-timepicker">
|
||||
<tbody>
|
||||
<tr class="text-center" ng-show="::showSpinners">
|
||||
<td class="uib-increment hours"><a ng-click="incrementHours()" ng-class="{disabled: noIncrementHours()}" class="btn btn-link" ng-disabled="noIncrementHours()" tabindex="{{::tabindex}}"><span class="glyphicon glyphicon-chevron-up"></span></a></td>
|
||||
<td class="uib-increment hours"><a ng-click="incrementHours()" ng-class="{disabled: noIncrementHours()}" class="btn btn-link" ng-disabled="noIncrementHours()" tabindex="-1"><span class="glyphicon glyphicon-chevron-up"></span></a></td>
|
||||
<td> </td>
|
||||
<td class="uib-increment minutes"><a ng-click="incrementMinutes()" ng-class="{disabled: noIncrementMinutes()}" class="btn btn-link" ng-disabled="noIncrementMinutes()" tabindex="{{::tabindex}}"><span class="glyphicon glyphicon-chevron-up"></span></a></td>
|
||||
<td class="uib-increment minutes"><a ng-click="incrementMinutes()" ng-class="{disabled: noIncrementMinutes()}" class="btn btn-link" ng-disabled="noIncrementMinutes()" tabindex="-1"><span class="glyphicon glyphicon-chevron-up"></span></a></td>
|
||||
<td ng-show="showSeconds"> </td>
|
||||
<td ng-show="showSeconds" class="uib-increment seconds"><a ng-click="incrementSeconds()" ng-class="{disabled: noIncrementSeconds()}" class="btn btn-link" ng-disabled="noIncrementSeconds()" tabindex="{{::tabindex}}"><span class="glyphicon glyphicon-chevron-up"></span></a></td>
|
||||
<td ng-show="showSeconds" class="uib-increment seconds"><a ng-click="incrementSeconds()" ng-class="{disabled: noIncrementSeconds()}" class="btn btn-link" ng-disabled="noIncrementSeconds()" tabindex="-1"><span class="glyphicon glyphicon-chevron-up"></span></a></td>
|
||||
<td ng-show="showMeridian"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -23,11 +23,11 @@
|
||||
<td ng-show="showMeridian" class="uib-time am-pm"><button type="button" ng-class="{disabled: noToggleMeridian()}" class="btn btn-default text-center" ng-click="toggleMeridian()" ng-disabled="noToggleMeridian()" tabindex="{{::tabindex}}">{{meridian}}</button></td>
|
||||
</tr>
|
||||
<tr class="text-center" ng-show="::showSpinners">
|
||||
<td class="uib-decrement hours"><a ng-click="decrementHours()" ng-class="{disabled: noDecrementHours()}" class="btn btn-link" ng-disabled="noDecrementHours()" tabindex="{{::tabindex}}"><span class="glyphicon glyphicon-chevron-down"></span></a></td>
|
||||
<td class="uib-decrement hours"><a ng-click="decrementHours()" ng-class="{disabled: noDecrementHours()}" class="btn btn-link" ng-disabled="noDecrementHours()" tabindex="-1"><span class="glyphicon glyphicon-chevron-down"></span></a></td>
|
||||
<td> </td>
|
||||
<td class="uib-decrement minutes"><a ng-click="decrementMinutes()" ng-class="{disabled: noDecrementMinutes()}" class="btn btn-link" ng-disabled="noDecrementMinutes()" tabindex="{{::tabindex}}"><span class="glyphicon glyphicon-chevron-down"></span></a></td>
|
||||
<td class="uib-decrement minutes"><a ng-click="decrementMinutes()" ng-class="{disabled: noDecrementMinutes()}" class="btn btn-link" ng-disabled="noDecrementMinutes()" tabindex="-1"><span class="glyphicon glyphicon-chevron-down"></span></a></td>
|
||||
<td ng-show="showSeconds"> </td>
|
||||
<td ng-show="showSeconds" class="uib-decrement seconds"><a ng-click="decrementSeconds()" ng-class="{disabled: noDecrementSeconds()}" class="btn btn-link" ng-disabled="noDecrementSeconds()" tabindex="{{::tabindex}}"><span class="glyphicon glyphicon-chevron-down"></span></a></td>
|
||||
<td ng-show="showSeconds" class="uib-decrement seconds"><a ng-click="decrementSeconds()" ng-class="{disabled: noDecrementSeconds()}" class="btn btn-link" ng-disabled="noDecrementSeconds()" tabindex="-1"><span class="glyphicon glyphicon-chevron-down"></span></a></td>
|
||||
<td ng-show="showMeridian"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -1,7 +1,2 @@
|
||||
<div class="tooltip"
|
||||
tooltip-animation-class="fade"
|
||||
uib-tooltip-classes
|
||||
ng-class="{ in: isOpen() }">
|
||||
<div class="tooltip-arrow"></div>
|
||||
<div class="tooltip-inner" ng-bind-html="contentExp()"></div>
|
||||
</div>
|
||||
<div class="tooltip-arrow"></div>
|
||||
<div class="tooltip-inner" ng-bind-html="contentExp()"></div>
|
||||
|
||||
@@ -1,7 +1,2 @@
|
||||
<div class="tooltip"
|
||||
tooltip-animation-class="fade"
|
||||
uib-tooltip-classes
|
||||
ng-class="{ in: isOpen() }">
|
||||
<div class="tooltip-arrow"></div>
|
||||
<div class="tooltip-inner" ng-bind="content"></div>
|
||||
</div>
|
||||
<div class="tooltip-arrow"></div>
|
||||
<div class="tooltip-inner" ng-bind="content"></div>
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
<div class="tooltip"
|
||||
tooltip-animation-class="fade"
|
||||
uib-tooltip-classes
|
||||
ng-class="{ in: isOpen() }">
|
||||
<div class="tooltip-arrow"></div>
|
||||
<div class="tooltip-inner"
|
||||
uib-tooltip-template-transclude="contentExp()"
|
||||
tooltip-template-transclude-scope="originScope()"></div>
|
||||
</div>
|
||||
<div class="tooltip-arrow"></div>
|
||||
<div class="tooltip-inner"
|
||||
uib-tooltip-template-transclude="contentExp()"
|
||||
tooltip-template-transclude-scope="originScope()"></div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<ul class="dropdown-menu" ng-show="isOpen() && !moveInProgress" ng-style="{top: position().top+'px', left: position().left+'px'}" role="listbox" aria-hidden="{{!isOpen()}}">
|
||||
<li ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index, $event)" role="option" id="{{::match.id}}">
|
||||
<li class="uib-typeahead-match" ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index, $event)" role="option" id="{{::match.id}}">
|
||||
<div uib-typeahead-match index="$index" match="match" query="query" template-url="templateUrl"></div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user