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

Commit 4651191

Browse files
committed
feat(timepicker): add ngDisabled support
- Adds support for `ng-disabled` on timepicker element for disabling all controls programmatically Closes #2219 Closes #4811
1 parent beabb4a commit 4651191

File tree

3 files changed

+160
-38
lines changed

3 files changed

+160
-38
lines changed

Diff for: src/timepicker/test/timepicker.spec.js

+103
Original file line numberDiff line numberDiff line change
@@ -2015,4 +2015,107 @@ describe('timepicker directive', function() {
20152015
expect(element.html()).toBe('<div class="ng-binding">foo</div>');
20162016
});
20172017
});
2018+
2019+
describe('ngDisabled', function() {
2020+
it('prevents modifying date via controls when true', function() {
2021+
$rootScope.disabled = false;
2022+
element = $compile('<uib-timepicker ng-model="time" ng-disabled="disabled"></uib-timepicker')($rootScope);
2023+
$rootScope.$digest();
2024+
2025+
var inputs = element.find('input');
2026+
var hoursEl = inputs.eq(0), minutesEl = inputs.eq(1),
2027+
secondsEl = inputs.eq(2);
2028+
var upKeydownEvent = keydown('up');
2029+
var downKeydownEvent = keydown('down');
2030+
var leftKeydownEvent = keydown('left');
2031+
var upMouseWheelEvent = wheelThatMouse(1);
2032+
var downMouseWheelEvent = wheelThatMouse(-1);
2033+
2034+
expect(getTimeState()).toEqual(['02', '40', '25', 'PM']);
2035+
expect(getModelState()).toEqual([14, 40, 25]);
2036+
2037+
$rootScope.disabled = true;
2038+
$rootScope.$digest();
2039+
2040+
// UP
2041+
hoursEl.trigger(upKeydownEvent);
2042+
$rootScope.$digest();
2043+
expect(getTimeState()).toEqual(['02', '40', '25', 'PM']);
2044+
expect(getModelState()).toEqual([14, 40, 25]);
2045+
2046+
minutesEl.trigger(upKeydownEvent);
2047+
$rootScope.$digest();
2048+
expect(getTimeState()).toEqual(['02', '40', '25', 'PM']);
2049+
expect(getModelState()).toEqual([14, 40, 25]);
2050+
2051+
secondsEl.trigger(upKeydownEvent);
2052+
$rootScope.$digest();
2053+
expect(getTimeState()).toEqual(['02', '40', '25', 'PM']);
2054+
expect(getModelState()).toEqual([14, 40, 25]);
2055+
2056+
// DOWN
2057+
secondsEl.trigger(downKeydownEvent);
2058+
$rootScope.$digest();
2059+
expect(getTimeState()).toEqual(['02', '40', '25', 'PM']);
2060+
expect(getModelState()).toEqual([14, 40, 25]);
2061+
2062+
minutesEl.trigger(downKeydownEvent);
2063+
$rootScope.$digest();
2064+
expect(getTimeState()).toEqual(['02', '40', '25', 'PM']);
2065+
expect(getModelState()).toEqual([14, 40, 25]);
2066+
2067+
hoursEl.trigger(downKeydownEvent);
2068+
$rootScope.$digest();
2069+
expect(getTimeState()).toEqual(['02', '40', '25', 'PM']);
2070+
expect(getModelState()).toEqual([14, 40, 25]);
2071+
2072+
// Other keydown
2073+
hoursEl.trigger(leftKeydownEvent);
2074+
$rootScope.$digest();
2075+
expect(getTimeState()).toEqual(['02', '40', '25', 'PM']);
2076+
expect(getModelState()).toEqual([14, 40, 25]);
2077+
2078+
minutesEl.trigger(leftKeydownEvent);
2079+
$rootScope.$digest();
2080+
expect(getTimeState()).toEqual(['02', '40', '25', 'PM']);
2081+
expect(getModelState()).toEqual([14, 40, 25]);
2082+
2083+
secondsEl.trigger(leftKeydownEvent);
2084+
$rootScope.$digest();
2085+
expect(getTimeState()).toEqual(['02', '40', '25', 'PM']);
2086+
expect(getModelState()).toEqual([14, 40, 25]);
2087+
2088+
// WHEEL UP
2089+
secondsEl.trigger(upMouseWheelEvent);
2090+
$rootScope.$digest();
2091+
expect(getTimeState()).toEqual(['02', '40', '25', 'PM']);
2092+
expect(getModelState()).toEqual([14, 40, 25]);
2093+
2094+
minutesEl.trigger(upMouseWheelEvent);
2095+
$rootScope.$digest();
2096+
expect(getTimeState()).toEqual(['02', '40', '25', 'PM']);
2097+
expect(getModelState()).toEqual([14, 40, 25]);
2098+
2099+
hoursEl.trigger(upMouseWheelEvent);
2100+
$rootScope.$digest();
2101+
expect(getTimeState()).toEqual(['02', '40', '25', 'PM']);
2102+
expect(getModelState()).toEqual([14, 40, 25]);
2103+
2104+
// WHEEL DOWN
2105+
secondsEl.trigger(downMouseWheelEvent);
2106+
$rootScope.$digest();
2107+
expect(getTimeState()).toEqual(['02', '40', '25', 'PM']);
2108+
expect(getModelState()).toEqual([14, 40, 25]);
2109+
2110+
minutesEl.trigger(downMouseWheelEvent);
2111+
$rootScope.$digest();
2112+
expect(getTimeState()).toEqual(['02', '40', '25', 'PM']);
2113+
expect(getModelState()).toEqual([14, 40, 25]);
2114+
2115+
hoursEl.trigger(downMouseWheelEvent);
2116+
$rootScope.$digest();
2117+
expect(getTimeState()).toEqual(['02', '40', '25', 'PM']);
2118+
expect(getModelState()).toEqual([14, 40, 25]);
2119+
});
2120+
});
20182121
});

Diff for: src/timepicker/timepicker.js

+54-35
Original file line numberDiff line numberDiff line change
@@ -74,47 +74,54 @@ angular.module('ui.bootstrap.timepicker', [])
7474
max = isNaN(dt) ? undefined : dt;
7575
});
7676

77+
var disabled = false;
78+
if ($attrs.ngDisabled) {
79+
$scope.$parent.$watch($parse($attrs.ngDisabled), function(value) {
80+
disabled = value;
81+
});
82+
}
83+
7784
$scope.noIncrementHours = function() {
7885
var incrementedSelected = addMinutes(selected, hourStep * 60);
79-
return incrementedSelected > max ||
86+
return disabled || incrementedSelected > max ||
8087
(incrementedSelected < selected && incrementedSelected < min);
8188
};
8289

8390
$scope.noDecrementHours = function() {
8491
var decrementedSelected = addMinutes(selected, -hourStep * 60);
85-
return decrementedSelected < min ||
92+
return disabled || decrementedSelected < min ||
8693
(decrementedSelected > selected && decrementedSelected > max);
8794
};
8895

8996
$scope.noIncrementMinutes = function() {
9097
var incrementedSelected = addMinutes(selected, minuteStep);
91-
return incrementedSelected > max ||
98+
return disabled || incrementedSelected > max ||
9299
(incrementedSelected < selected && incrementedSelected < min);
93100
};
94101

95102
$scope.noDecrementMinutes = function() {
96103
var decrementedSelected = addMinutes(selected, -minuteStep);
97-
return decrementedSelected < min ||
104+
return disabled || decrementedSelected < min ||
98105
(decrementedSelected > selected && decrementedSelected > max);
99106
};
100107

101108
$scope.noIncrementSeconds = function() {
102109
var incrementedSelected = addSeconds(selected, secondStep);
103-
return incrementedSelected > max ||
110+
return disabled || incrementedSelected > max ||
104111
(incrementedSelected < selected && incrementedSelected < min);
105112
};
106113

107114
$scope.noDecrementSeconds = function() {
108115
var decrementedSelected = addSeconds(selected, -secondStep);
109-
return decrementedSelected < min ||
116+
return disabled || decrementedSelected < min ||
110117
(decrementedSelected > selected && decrementedSelected > max);
111118
};
112119

113120
$scope.noToggleMeridian = function() {
114121
if (selected.getHours() < 12) {
115-
return addMinutes(selected, 12 * 60) > max;
122+
return disabled || addMinutes(selected, 12 * 60) > max;
116123
} else {
117-
return addMinutes(selected, -12 * 60) < min;
124+
return disabled || addMinutes(selected, -12 * 60) < min;
118125
}
119126
};
120127

@@ -200,56 +207,68 @@ angular.module('ui.bootstrap.timepicker', [])
200207
};
201208

202209
hoursInputEl.bind('mousewheel wheel', function(e) {
203-
$scope.$apply(isScrollingUp(e) ? $scope.incrementHours() : $scope.decrementHours());
210+
if (!disabled) {
211+
$scope.$apply(isScrollingUp(e) ? $scope.incrementHours() : $scope.decrementHours());
212+
}
204213
e.preventDefault();
205214
});
206215

207216
minutesInputEl.bind('mousewheel wheel', function(e) {
208-
$scope.$apply(isScrollingUp(e) ? $scope.incrementMinutes() : $scope.decrementMinutes());
217+
if (!disabled) {
218+
$scope.$apply(isScrollingUp(e) ? $scope.incrementMinutes() : $scope.decrementMinutes());
219+
}
209220
e.preventDefault();
210221
});
211222

212223
secondsInputEl.bind('mousewheel wheel', function(e) {
213-
$scope.$apply((isScrollingUp(e)) ? $scope.incrementSeconds() : $scope.decrementSeconds());
224+
if (!disabled) {
225+
$scope.$apply((isScrollingUp(e)) ? $scope.incrementSeconds() : $scope.decrementSeconds());
226+
}
214227
e.preventDefault();
215228
});
216229
};
217230

218231
// Respond on up/down arrowkeys
219232
this.setupArrowkeyEvents = function(hoursInputEl, minutesInputEl, secondsInputEl) {
220233
hoursInputEl.bind('keydown', function(e) {
221-
if (e.which === 38) { // up
222-
e.preventDefault();
223-
$scope.incrementHours();
224-
$scope.$apply();
225-
} else if (e.which === 40) { // down
226-
e.preventDefault();
227-
$scope.decrementHours();
228-
$scope.$apply();
234+
if (!disabled) {
235+
if (e.which === 38) { // up
236+
e.preventDefault();
237+
$scope.incrementHours();
238+
$scope.$apply();
239+
} else if (e.which === 40) { // down
240+
e.preventDefault();
241+
$scope.decrementHours();
242+
$scope.$apply();
243+
}
229244
}
230245
});
231246

232247
minutesInputEl.bind('keydown', function(e) {
233-
if (e.which === 38) { // up
234-
e.preventDefault();
235-
$scope.incrementMinutes();
236-
$scope.$apply();
237-
} else if (e.which === 40) { // down
238-
e.preventDefault();
239-
$scope.decrementMinutes();
240-
$scope.$apply();
248+
if (!disabled) {
249+
if (e.which === 38) { // up
250+
e.preventDefault();
251+
$scope.incrementMinutes();
252+
$scope.$apply();
253+
} else if (e.which === 40) { // down
254+
e.preventDefault();
255+
$scope.decrementMinutes();
256+
$scope.$apply();
257+
}
241258
}
242259
});
243260

244261
secondsInputEl.bind('keydown', function(e) {
245-
if (e.which === 38) { // up
246-
e.preventDefault();
247-
$scope.incrementSeconds();
248-
$scope.$apply();
249-
} else if (e.which === 40) { // down
250-
e.preventDefault();
251-
$scope.decrementSeconds();
252-
$scope.$apply();
262+
if (!disabled) {
263+
if (e.which === 38) { // up
264+
e.preventDefault();
265+
$scope.incrementSeconds();
266+
$scope.$apply();
267+
} else if (e.which === 40) { // down
268+
e.preventDefault();
269+
$scope.decrementSeconds();
270+
$scope.$apply();
271+
}
253272
}
254273
});
255274
};

Diff for: template/timepicker/timepicker.html

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@
1010
</tr>
1111
<tr>
1212
<td class="form-group" ng-class="{'has-error': invalidHours}">
13-
<input style="width:50px;" type="text" placeholder="HH" ng-model="hours" ng-change="updateHours()" class="form-control text-center" ng-readonly="::readonlyInput" maxlength="2" tabindex="{{::tabindex}}">
13+
<input style="width:50px;" type="text" placeholder="HH" ng-model="hours" ng-change="updateHours()" class="form-control text-center" ng-readonly="::readonlyInput" maxlength="2" tabindex="{{::tabindex}}" ng-disabled="disabled">
1414
</td>
1515
<td>:</td>
1616
<td class="form-group" ng-class="{'has-error': invalidMinutes}">
17-
<input style="width:50px;" type="text" placeholder="MM" ng-model="minutes" ng-change="updateMinutes()" class="form-control text-center" ng-readonly="::readonlyInput" maxlength="2" tabindex="{{::tabindex}}">
17+
<input style="width:50px;" type="text" placeholder="MM" ng-model="minutes" ng-change="updateMinutes()" class="form-control text-center" ng-readonly="::readonlyInput" maxlength="2" tabindex="{{::tabindex}}" ng-disabled="disabled">
1818
</td>
1919
<td ng-show="showSeconds">:</td>
2020
<td class="form-group" ng-class="{'has-error': invalidSeconds}" ng-show="showSeconds">
21-
<input style="width:50px;" type="text" ng-model="seconds" ng-change="updateSeconds()" class="form-control text-center" ng-readonly="readonlyInput" maxlength="2" tabindex="{{::tabindex}}">
21+
<input style="width:50px;" type="text" ng-model="seconds" ng-change="updateSeconds()" class="form-control text-center" ng-readonly="readonlyInput" maxlength="2" tabindex="{{::tabindex}}" ng-disabled="disabled">
2222
</td>
2323
<td ng-show="showMeridian"><button type="button" ng-class="{disabled: noToggleMeridian()}" class="btn btn-default text-center" ng-click="toggleMeridian()" ng-disabled="noToggleMeridian()" tabindex="{{::tabindex}}">{{meridian}}</button></td>
2424
</tr>

0 commit comments

Comments
 (0)