Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 25db68e903 | |||
| 78559761dc | |||
| 14384fc40f | |||
| 58f1813aca | |||
| 9666c64f4a | |||
| f9f7e02d15 | |||
| a4bea6f229 | |||
| c00851a18b | |||
| c687acd489 | |||
| 3f70d76327 | |||
| 08ee30a91e | |||
| 7671bd6ed4 | |||
| 1a132dd757 | |||
| 9881a27397 |
+1
-1
@@ -13,7 +13,7 @@ addons:
|
||||
before_install:
|
||||
- export DISPLAY=:99.0
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
- npm install --quiet -g grunt-cli karma
|
||||
- npm install --quiet -g karma
|
||||
|
||||
script: grunt
|
||||
sudo: false
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
<a name="2.2.0"></a>
|
||||
# [2.2.0](https://github.com/angular-ui/bootstrap/compare/2.1.4...v2.2.0) (2016-10-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **dropdown:** exit keybind is not open ([14384fc](https://github.com/angular-ui/bootstrap/commit/14384fc)), closes [#6278](https://github.com/angular-ui/bootstrap/issues/6278) [#6208](https://github.com/angular-ui/bootstrap/issues/6208)
|
||||
* **modal:** improve ARIA support. ([f9f7e02](https://github.com/angular-ui/bootstrap/commit/f9f7e02)), closes [#6203](https://github.com/angular-ui/bootstrap/issues/6203)
|
||||
* **position:** correct scrollbar width calculation ([58f1813](https://github.com/angular-ui/bootstrap/commit/58f1813)), closes [#6273](https://github.com/angular-ui/bootstrap/issues/6273)
|
||||
* **tooltip:** cancel timeout when hidden ([7855976](https://github.com/angular-ui/bootstrap/commit/7855976)), closes [#6226](https://github.com/angular-ui/bootstrap/issues/6226) [#6221](https://github.com/angular-ui/bootstrap/issues/6221)
|
||||
|
||||
### Features
|
||||
|
||||
* **timepicker:** add validation information ([9666c64](https://github.com/angular-ui/bootstrap/commit/9666c64)), closes [#6230](https://github.com/angular-ui/bootstrap/issues/6230) [#6259](https://github.com/angular-ui/bootstrap/issues/6259)
|
||||
|
||||
|
||||
|
||||
<a name="2.1.4"></a>
|
||||
## [2.1.4](https://github.com/angular-ui/bootstrap/compare/2.1.3...v2.1.4) (2016-09-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datepicker:** improve accessibility ([3f70d76](https://github.com/angular-ui/bootstrap/commit/3f70d76)), closes [#6247](https://github.com/angular-ui/bootstrap/issues/6247)
|
||||
* **dropdown:** prevent premature scope removal ([08ee30a](https://github.com/angular-ui/bootstrap/commit/08ee30a)), closes [#6238](https://github.com/angular-ui/bootstrap/issues/6238) [#6225](https://github.com/angular-ui/bootstrap/issues/6225)
|
||||
|
||||
|
||||
|
||||
<a name="2.1.3"></a>
|
||||
## [2.1.3](https://github.com/angular-ui/bootstrap/compare/2.1.2...v2.1.3) (2016-08-25)
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ section {
|
||||
|
||||
}
|
||||
|
||||
.navbar .collapse {
|
||||
.navbar-fixed-top .collapse {
|
||||
border-top: 1px solid #e7e7e7;
|
||||
margin-left: -15px;
|
||||
margin-right: -15px;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 8.2 KiB |
+4
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"author": "https://github.com/angular-ui/bootstrap/graphs/contributors",
|
||||
"name": "angular-ui-bootstrap",
|
||||
"version": "2.1.3",
|
||||
"version": "2.2.0",
|
||||
"homepage": "http://angular-ui.github.io/bootstrap/",
|
||||
"dependencies": {},
|
||||
"directories": {
|
||||
@@ -15,6 +15,7 @@
|
||||
],
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"demo": "grunt after-test && static dist -a 0.0.0.0 -H '{\"Cache-Control\": \"no-cache, must-revalidate\"}'",
|
||||
"test": "grunt"
|
||||
},
|
||||
"repository": {
|
||||
@@ -26,6 +27,7 @@
|
||||
"angular-mocks": "1.5.8",
|
||||
"angular-sanitize": "1.5.8",
|
||||
"grunt": "^0.4.5",
|
||||
"grunt-cli": "^1.2.0",
|
||||
"grunt-contrib-concat": "^1.0.0",
|
||||
"grunt-contrib-copy": "^1.0.0",
|
||||
"grunt-contrib-uglify": "^1.0.1",
|
||||
@@ -44,6 +46,7 @@
|
||||
"load-grunt-tasks": "^3.3.0",
|
||||
"lodash": "^4.1.0",
|
||||
"marked": "^0.3.5",
|
||||
"node-static": "^0.7.8",
|
||||
"semver": "^5.0.1",
|
||||
"shelljs": "^0.6.0"
|
||||
},
|
||||
|
||||
@@ -2,8 +2,30 @@
|
||||
.horizontal-collapse {
|
||||
height: 70px;
|
||||
}
|
||||
.navbar-collapse.in {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
</style>
|
||||
<div ng-controller="CollapseDemoCtrl">
|
||||
<p>Resize window to less than 768 pixels to display mobile menu toggle button.</p>
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" ng-click="isNavCollapsed = !isNavCollapsed">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">A menu</a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse" uib-collapse="isNavCollapsed">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="#">Link 1</a></li>
|
||||
<li><a href="#">Link 2</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<hr>
|
||||
<button type="button" class="btn btn-default" ng-click="isCollapsed = !isCollapsed">Toggle collapse Vertically</button>
|
||||
<hr>
|
||||
<div uib-collapse="isCollapsed">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
angular.module('ui.bootstrap.demo').controller('CollapseDemoCtrl', function ($scope) {
|
||||
$scope.isNavCollapsed = true;
|
||||
$scope.isCollapsed = false;
|
||||
$scope.isCollapsedHorizontal = false;
|
||||
});
|
||||
|
||||
@@ -22,9 +22,9 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
|
||||
this.close = function(dropdownScope, element) {
|
||||
if (openScope === dropdownScope) {
|
||||
openScope = null;
|
||||
$document.off('click', closeDropdown);
|
||||
$document.off('keydown', this.keybindFilter);
|
||||
openScope = null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -48,8 +48,8 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
return;
|
||||
}
|
||||
|
||||
openScope.isOpen = false;
|
||||
openScope.focusToggleElement();
|
||||
openScope.isOpen = false;
|
||||
|
||||
if (!$rootScope.$$phase) {
|
||||
openScope.$apply();
|
||||
@@ -57,6 +57,11 @@ angular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])
|
||||
};
|
||||
|
||||
this.keybindFilter = function(evt) {
|
||||
if (!openScope) {
|
||||
// see this.close as ESC could have been pressed which kills the scope so we can not proceed
|
||||
return;
|
||||
}
|
||||
|
||||
var dropdownElement = openScope.getDropdownElement();
|
||||
var toggleElement = openScope.getToggleElement();
|
||||
var dropdownElementTargeted = dropdownElement && dropdownElement[0].contains(evt.target);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div ng-controller="ModalDemoCtrl as $ctrl">
|
||||
<div ng-controller="ModalDemoCtrl as $ctrl" class="modal-demo">
|
||||
<script type="text/ng-template" id="myModalContent.html">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title" id="modal-title">I'm a modal!</h3>
|
||||
@@ -16,11 +16,29 @@
|
||||
<button class="btn btn-warning" type="button" ng-click="$ctrl.cancel()">Cancel</button>
|
||||
</div>
|
||||
</script>
|
||||
<script type="text/ng-template" id="stackedModal.html">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title" id="modal-title-{{name}}">The {{name}} modal!</h3>
|
||||
</div>
|
||||
<div class="modal-body" id="modal-body-{{name}}">
|
||||
Having multiple modals open at once is probably bad UX but it's technically possible.
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<button type="button" class="btn btn-default" ng-click="$ctrl.open()">Open me!</button>
|
||||
<button type="button" class="btn btn-default" ng-click="$ctrl.open('lg')">Large modal</button>
|
||||
<button type="button" class="btn btn-default" ng-click="$ctrl.open('sm')">Small modal</button>
|
||||
<button type="button"
|
||||
class="btn btn-default"
|
||||
ng-click="$ctrl.open('sm', '.modal-parent')">
|
||||
Modal appended to a custom parent
|
||||
</button>
|
||||
<button type="button" class="btn btn-default" ng-click="$ctrl.toggleAnimation()">Toggle Animation ({{ $ctrl.animationsEnabled }})</button>
|
||||
<button type="button" class="btn btn-default" ng-click="$ctrl.openComponentModal()">Open a component modal!</button>
|
||||
<button type="button" class="btn btn-default" ng-click="$ctrl.openMultipleModals()">
|
||||
Open multiple modals at once
|
||||
</button>
|
||||
<div ng-show="$ctrl.selected">Selection from a modal: {{ $ctrl.selected }}</div>
|
||||
<div class="modal-parent">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+29
-2
@@ -1,10 +1,12 @@
|
||||
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($uibModal, $log) {
|
||||
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($uibModal, $log, $document) {
|
||||
var $ctrl = this;
|
||||
$ctrl.items = ['item1', 'item2', 'item3'];
|
||||
|
||||
$ctrl.animationsEnabled = true;
|
||||
|
||||
$ctrl.open = function (size) {
|
||||
$ctrl.open = function (size, parentSelector) {
|
||||
var parentElem = parentSelector ?
|
||||
angular.element($document[0].querySelector('.modal-demo ' + parentSelector)) : undefined;
|
||||
var modalInstance = $uibModal.open({
|
||||
animation: $ctrl.animationsEnabled,
|
||||
ariaLabelledBy: 'modal-title',
|
||||
@@ -13,6 +15,7 @@ angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($uibMo
|
||||
controller: 'ModalInstanceCtrl',
|
||||
controllerAs: '$ctrl',
|
||||
size: size,
|
||||
appendTo: parentElem,
|
||||
resolve: {
|
||||
items: function () {
|
||||
return $ctrl.items;
|
||||
@@ -45,6 +48,30 @@ angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($uibMo
|
||||
});
|
||||
};
|
||||
|
||||
$ctrl.openMultipleModals = function () {
|
||||
$uibModal.open({
|
||||
animation: $ctrl.animationsEnabled,
|
||||
ariaLabelledBy: 'modal-title-bottom',
|
||||
ariaDescribedBy: 'modal-body-bottom',
|
||||
templateUrl: 'stackedModal.html',
|
||||
size: 'sm',
|
||||
controller: function($scope) {
|
||||
$scope.name = 'bottom';
|
||||
}
|
||||
});
|
||||
|
||||
$uibModal.open({
|
||||
animation: $ctrl.animationsEnabled,
|
||||
ariaLabelledBy: 'modal-title-top',
|
||||
ariaDescribedBy: 'modal-body-top',
|
||||
templateUrl: 'stackedModal.html',
|
||||
size: 'sm',
|
||||
controller: function($scope) {
|
||||
$scope.name = 'top';
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$ctrl.toggleAnimation = function () {
|
||||
$ctrl.animationsEnabled = !$ctrl.animationsEnabled;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
`$uibModal` is a service to create modal windows.
|
||||
Creating modals is straightforward: create a template, a controller and reference them when using `$uibModal`.
|
||||
Creating modals is straightforward: create a template and controller, and reference them when using `$uibModal`.
|
||||
|
||||
The `$uibModal` service has only one method: `open(options)`.
|
||||
|
||||
|
||||
+53
-2
@@ -163,7 +163,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
// {@link Attribute#$observe} on it. For more details please see {@link TableColumnResize}.
|
||||
scope.$isRendered = true;
|
||||
|
||||
// Deferred object that will be resolved when this modal is render.
|
||||
// Deferred object that will be resolved when this modal is rendered.
|
||||
var modalRenderDeferObj = $q.defer();
|
||||
// Resolve render promise post-digest
|
||||
scope.$$postDigest(function() {
|
||||
@@ -196,7 +196,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
|
||||
/**
|
||||
* If something within the freshly-opened modal already has focus (perhaps via a
|
||||
* directive that causes focus). then no need to try and focus anything.
|
||||
* directive that causes focus) then there's no need to try to focus anything.
|
||||
*/
|
||||
if (!($document[0].activeElement && element[0].contains($document[0].activeElement))) {
|
||||
var inputWithAutofocus = element[0].querySelector('[autofocus]');
|
||||
@@ -254,6 +254,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
};
|
||||
var topModalIndex = 0;
|
||||
var previousTopOpenedModal = null;
|
||||
var ARIA_HIDDEN_ATTRIBUTE_NAME = 'data-bootstrap-modal-aria-hidden-count';
|
||||
|
||||
//Modal focus behavior
|
||||
var tabbableSelector = 'a[href], area[href], input:not([disabled]):not([tabindex=\'-1\']), ' +
|
||||
@@ -555,25 +556,74 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
|
||||
openedWindows.top().value.modalDomEl = angularDomEl;
|
||||
openedWindows.top().value.modalOpener = modalOpener;
|
||||
|
||||
applyAriaHidden(angularDomEl);
|
||||
|
||||
function applyAriaHidden(el) {
|
||||
if (!el || el[0].tagName === 'BODY') {
|
||||
return;
|
||||
}
|
||||
|
||||
getSiblings(el).forEach(function(sibling) {
|
||||
var elemIsAlreadyHidden = sibling.getAttribute('aria-hidden') === 'true',
|
||||
ariaHiddenCount = parseInt(sibling.getAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME), 10);
|
||||
|
||||
if (!ariaHiddenCount) {
|
||||
ariaHiddenCount = elemIsAlreadyHidden ? 1 : 0;
|
||||
}
|
||||
|
||||
sibling.setAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME, ariaHiddenCount + 1);
|
||||
sibling.setAttribute('aria-hidden', 'true');
|
||||
});
|
||||
|
||||
return applyAriaHidden(el.parent());
|
||||
|
||||
function getSiblings(el) {
|
||||
var children = el.parent() ? el.parent().children() : [];
|
||||
|
||||
return Array.prototype.filter.call(children, function(child) {
|
||||
return child !== el[0];
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function broadcastClosing(modalWindow, resultOrReason, closing) {
|
||||
return !modalWindow.value.modalScope.$broadcast('modal.closing', resultOrReason, closing).defaultPrevented;
|
||||
}
|
||||
|
||||
function unhideBackgroundElements() {
|
||||
Array.prototype.forEach.call(
|
||||
document.querySelectorAll('[' + ARIA_HIDDEN_ATTRIBUTE_NAME + ']'),
|
||||
function(hiddenEl) {
|
||||
var ariaHiddenCount = parseInt(hiddenEl.getAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME), 10),
|
||||
newHiddenCount = ariaHiddenCount - 1;
|
||||
hiddenEl.setAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME, newHiddenCount);
|
||||
|
||||
if (!newHiddenCount) {
|
||||
hiddenEl.removeAttribute(ARIA_HIDDEN_ATTRIBUTE_NAME);
|
||||
hiddenEl.removeAttribute('aria-hidden');
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$modalStack.close = function(modalInstance, result) {
|
||||
var modalWindow = openedWindows.get(modalInstance);
|
||||
unhideBackgroundElements();
|
||||
if (modalWindow && broadcastClosing(modalWindow, result, true)) {
|
||||
modalWindow.value.modalScope.$$uibDestructionScheduled = true;
|
||||
modalWindow.value.deferred.resolve(result);
|
||||
removeModalWindow(modalInstance, modalWindow.value.modalOpener);
|
||||
return true;
|
||||
}
|
||||
|
||||
return !modalWindow;
|
||||
};
|
||||
|
||||
$modalStack.dismiss = function(modalInstance, reason) {
|
||||
var modalWindow = openedWindows.get(modalInstance);
|
||||
unhideBackgroundElements();
|
||||
if (modalWindow && broadcastClosing(modalWindow, reason, false)) {
|
||||
modalWindow.value.modalScope.$$uibDestructionScheduled = true;
|
||||
modalWindow.value.deferred.reject(reason);
|
||||
@@ -596,6 +646,7 @@ angular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap', 'ui.bootstrap.p
|
||||
|
||||
$modalStack.modalRendered = function(modalInstance) {
|
||||
var modalWindow = openedWindows.get(modalInstance);
|
||||
$modalStack.focusFirstFocusableElement($modalStack.loadFocusElementList(modalWindow));
|
||||
if (modalWindow) {
|
||||
modalWindow.value.renderDeferred.resolve();
|
||||
}
|
||||
|
||||
@@ -526,7 +526,7 @@ describe('$uibModal', function() {
|
||||
|
||||
var modal = open({template: '<div>Content<button>inside modal</button></div>'});
|
||||
$rootScope.$digest();
|
||||
expect(document.activeElement.tagName).toBe('DIV');
|
||||
expect(document.activeElement.tagName).toBe('BUTTON');
|
||||
expect($document).toHaveModalsOpen(1);
|
||||
|
||||
triggerKeyDown($document, 27);
|
||||
@@ -656,7 +656,7 @@ describe('$uibModal', function() {
|
||||
it('should not focus on the element that has autofocus attribute when the modal is opened and something in the modal already has focus and the animations have finished', function() {
|
||||
function openAndCloseModalWithAutofocusElement() {
|
||||
|
||||
var modal = open({template: '<div><input type="text" id="auto-focus-element" autofocus><input type="text" id="pre-focus-element" focus-me></div>'});
|
||||
var modal = open({template: '<div><input type="text" id="pre-focus-element" focus-me><input type="text" id="auto-focus-element" autofocus></div>'});
|
||||
$rootScope.$digest();
|
||||
expect(angular.element('#auto-focus-element')).not.toHaveFocus();
|
||||
expect(angular.element('#pre-focus-element')).toHaveFocus();
|
||||
@@ -698,7 +698,7 @@ describe('$uibModal', function() {
|
||||
$rootScope.$digest();
|
||||
$animate.flush();
|
||||
|
||||
expect(document.activeElement.tagName).toBe('DIV');
|
||||
expect(document.activeElement.tagName).toBe('INPUT');
|
||||
|
||||
close(modal, 'closed ok');
|
||||
|
||||
|
||||
@@ -34,6 +34,9 @@ All these settings are available for the three types of popovers.
|
||||
_(Default: `false`, Config: `appendToBody`)_ -
|
||||
Should the popover be appended to '$body' instead of the parent element?
|
||||
|
||||
* `popover-class` -
|
||||
Custom class to be applied to the popover.
|
||||
|
||||
* `popover-enable`
|
||||
<small class="badge">$</small>
|
||||
_(Default: `true`)_ -
|
||||
|
||||
@@ -130,7 +130,7 @@ angular.module('ui.bootstrap.position', [])
|
||||
var paddingRight = this.parseStyle(elemStyle.paddingRight);
|
||||
var paddingBottom = this.parseStyle(elemStyle.paddingBottom);
|
||||
var scrollParent = this.scrollParent(elem, false, true);
|
||||
var scrollbarWidth = this.scrollbarWidth(scrollParent, BODY_REGEX.test(scrollParent.tagName));
|
||||
var scrollbarWidth = this.scrollbarWidth(BODY_REGEX.test(scrollParent.tagName));
|
||||
|
||||
return {
|
||||
scrollbarWidth: scrollbarWidth,
|
||||
|
||||
@@ -1230,6 +1230,7 @@ describe('timepicker directive', function() {
|
||||
changeInputValueTo(el, 'pizza');
|
||||
expect($rootScope.time).toBe(null);
|
||||
expect(el.parent().hasClass('has-error')).toBe(true);
|
||||
expect(el.hasClass('ng-invalid-hours'));
|
||||
expect(element.hasClass('ng-invalid-time')).toBe(true);
|
||||
|
||||
changeInputValueTo(el, 8);
|
||||
@@ -1247,6 +1248,7 @@ describe('timepicker directive', function() {
|
||||
changeInputValueTo(el, '8a');
|
||||
expect($rootScope.time).toBe(null);
|
||||
expect(el.parent().hasClass('has-error')).toBe(true);
|
||||
expect(el.hasClass('ng-invalid-minutes'));
|
||||
expect(element.hasClass('ng-invalid-time')).toBe(true);
|
||||
|
||||
changeInputValueTo(el, 22);
|
||||
@@ -1262,6 +1264,7 @@ describe('timepicker directive', function() {
|
||||
changeInputValueTo(el, 'pizza');
|
||||
expect($rootScope.time).toBe(null);
|
||||
expect(el.parent().hasClass('has-error')).toBe(true);
|
||||
expect(el.hasClass('ng-invalid-seconds'));
|
||||
expect(element.hasClass('ng-invalid-time')).toBe(true);
|
||||
|
||||
changeInputValueTo(el, 13);
|
||||
@@ -1291,6 +1294,9 @@ describe('timepicker directive', function() {
|
||||
elS.blur();
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(elH.hasClass('ng-valid'));
|
||||
expect(elM.hasClass('ng-valid'));
|
||||
expect(elS.hasClass('ng-valid'));
|
||||
expect(element.hasClass('ng-invalid-time')).toBe(false);
|
||||
});
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ angular.module('ui.bootstrap.timepicker', [])
|
||||
})
|
||||
|
||||
.controller('UibTimepickerController', ['$scope', '$element', '$attrs', '$parse', '$log', '$locale', 'uibTimepickerConfig', function($scope, $element, $attrs, $parse, $log, $locale, timepickerConfig) {
|
||||
var hoursModelCtrl, minutesModelCtrl, secondsModelCtrl;
|
||||
var selected = new Date(),
|
||||
watchers = [],
|
||||
ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl
|
||||
@@ -36,6 +37,10 @@ angular.module('ui.bootstrap.timepicker', [])
|
||||
minutesInputEl = inputs.eq(1),
|
||||
secondsInputEl = inputs.eq(2);
|
||||
|
||||
hoursModelCtrl = hoursInputEl.controller('ngModel');
|
||||
minutesModelCtrl = minutesInputEl.controller('ngModel');
|
||||
secondsModelCtrl = secondsInputEl.controller('ngModel');
|
||||
|
||||
var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel;
|
||||
|
||||
if (mousewheel) {
|
||||
@@ -295,14 +300,23 @@ angular.module('ui.bootstrap.timepicker', [])
|
||||
ngModelCtrl.$setValidity('time', false);
|
||||
if (angular.isDefined(invalidHours)) {
|
||||
$scope.invalidHours = invalidHours;
|
||||
if (hoursModelCtrl) {
|
||||
hoursModelCtrl.$setValidity('hours', false);
|
||||
}
|
||||
}
|
||||
|
||||
if (angular.isDefined(invalidMinutes)) {
|
||||
$scope.invalidMinutes = invalidMinutes;
|
||||
if (minutesModelCtrl) {
|
||||
minutesModelCtrl.$setValidity('minutes', false);
|
||||
}
|
||||
}
|
||||
|
||||
if (angular.isDefined(invalidSeconds)) {
|
||||
$scope.invalidSeconds = invalidSeconds;
|
||||
if (secondsModelCtrl) {
|
||||
secondsModelCtrl.$setValidity('seconds', false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -425,6 +439,18 @@ angular.module('ui.bootstrap.timepicker', [])
|
||||
}
|
||||
|
||||
function makeValid() {
|
||||
if (hoursModelCtrl) {
|
||||
hoursModelCtrl.$setValidity('hours', true);
|
||||
}
|
||||
|
||||
if (minutesModelCtrl) {
|
||||
minutesModelCtrl.$setValidity('minutes', true);
|
||||
}
|
||||
|
||||
if (secondsModelCtrl) {
|
||||
secondsModelCtrl.$setValidity('seconds', true);
|
||||
}
|
||||
|
||||
ngModelCtrl.$setValidity('time', true);
|
||||
$scope.invalidHours = false;
|
||||
$scope.invalidMinutes = false;
|
||||
|
||||
@@ -144,6 +144,7 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
|
||||
var showTimeout;
|
||||
var hideTimeout;
|
||||
var positionTimeout;
|
||||
var adjustmentTimeout;
|
||||
var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false;
|
||||
var triggers = getTriggers(undefined);
|
||||
var hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']);
|
||||
@@ -176,12 +177,13 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
|
||||
tooltip.addClass(options.placementClassPrefix + ttPosition.placement);
|
||||
}
|
||||
|
||||
$timeout(function() {
|
||||
adjustmentTimeout = $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);
|
||||
}
|
||||
adjustmentTimeout = null;
|
||||
}, 0, false);
|
||||
|
||||
// first time through tt element will have the
|
||||
@@ -346,7 +348,11 @@ angular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.s
|
||||
|
||||
if (tooltip) {
|
||||
tooltip.remove();
|
||||
|
||||
tooltip = null;
|
||||
if (adjustmentTimeout) {
|
||||
$timeout.cancel(adjustmentTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
openedTooltips.remove(ttScope);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<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 type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-left"></i><span class="sr-only">previous</span></button></th>
|
||||
<th colspan="{{::5 + showWeeks}}"><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>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-right uib-right" ng-click="move(1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-right"></i><span class="sr-only">next</span></button></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th ng-if="showWeeks" class="text-center"></th>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<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 type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-left"></i><span class="sr-only">previous</span></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>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-right uib-right" ng-click="move(1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-right"></i><span class="sr-only">next</span></i></button></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<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 type="button" class="btn btn-default btn-sm pull-left uib-left" ng-click="move(-1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-left"></i><span class="sr-only">previous</span></button></th>
|
||||
<th colspan="{{::columns - 2}}"><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>
|
||||
<th><button type="button" class="btn btn-default btn-sm pull-right uib-right" ng-click="move(1)" tabindex="-1"><i aria-hidden="true" class="glyphicon glyphicon-chevron-right"></i><span class="sr-only">next</span></button></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<ul class="uib-datepicker-popup dropdown-menu uib-position-measure" dropdown-nested ng-if="isOpen" ng-keydown="keydown($event)" ng-click="$event.stopPropagation()">
|
||||
<ul role="presentation" 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">
|
||||
|
||||
Reference in New Issue
Block a user