Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 11e5eff

Browse files
committed
feat(input[range]): support step
1 parent 9130166 commit 11e5eff

File tree

3 files changed

+346
-49
lines changed

3 files changed

+346
-49
lines changed

src/jqLite.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,8 @@ var ALIASED_ATTR = {
577577
'ngMaxlength': 'maxlength',
578578
'ngMin': 'min',
579579
'ngMax': 'max',
580-
'ngPattern': 'pattern'
580+
'ngPattern': 'pattern',
581+
'ngStep': 'step'
581582
};
582583

583584
function getBooleanAttrName(element, name) {

src/ng/directive/input.js

+85-48
Original file line numberDiff line numberDiff line change
@@ -1556,6 +1556,10 @@ function rangeInputType(scope, element, attr, ctrl, $sniffer, $browser) {
15561556

15571557
var minVal = 0,
15581558
maxVal = 100,
1559+
stepVal = 1,
1560+
minAttrType = isDefined(attr.ngMin) ? 'ngMin' : isDefined(attr.min) ? 'min' : false,
1561+
maxAttrType = isDefined(attr.ngMax) ? 'ngMax' : isDefined(attr.max) ? 'max' : false,
1562+
stepAttributeType = isDefined(attr.ngStep) ? 'ngStep' : isDefined(attr.step) ? 'step' : false,
15591563
supportsRange = ctrl.$$hasNativeValidators && element[0].type === 'range',
15601564
validity = element[0].validity;
15611565

@@ -1570,33 +1574,8 @@ function rangeInputType(scope, element, attr, ctrl, $sniffer, $browser) {
15701574
} :
15711575
originalRender;
15721576

1573-
function minChange(val) {
1574-
if (isDefined(val) && !isNumber(val)) {
1575-
val = parseFloat(val);
1576-
}
1577-
minVal = isNumber(val) && !isNaN(val) ? val : undefined;
1578-
// ignore changes before model is initialized
1579-
if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
1580-
return;
1581-
}
1582-
1583-
if (supportsRange && minAttrType === 'min') {
1584-
var elVal = element.val();
1585-
// IE11 doesn't set the el val correctly if the minVal is greater than the element value
1586-
if (minVal > elVal) {
1587-
element.val(minVal);
1588-
elVal = minVal;
1589-
}
1590-
ctrl.$setViewValue(elVal);
1591-
} else {
1592-
// TODO(matsko): implement validateLater to reduce number of validations
1593-
ctrl.$validate();
1594-
}
1595-
}
1596-
1597-
var minAttrType = isDefined(attr.ngMin) ? 'ngMin' : isDefined(attr.min) ? 'min' : false;
15981577
if (minAttrType) {
1599-
ctrl.$validators.min = isDefined(attr.min) && supportsRange ?
1578+
ctrl.$validators.min = minAttrType === 'min' && supportsRange ?
16001579
function noopMinValidator(value) {
16011580
// Since all browsers set the input to a valid value, we don't need to check validity
16021581
return true;
@@ -1609,34 +1588,34 @@ function rangeInputType(scope, element, attr, ctrl, $sniffer, $browser) {
16091588
// Assign minVal when the directive is linked. This won't run the validators as the model isn't ready yet
16101589
minChange(attr.min);
16111590
attr.$observe('min', minChange);
1612-
}
16131591

1614-
function maxChange(val) {
1615-
if (isDefined(val) && !isNumber(val)) {
1616-
val = parseFloat(val);
1617-
}
1618-
maxVal = isNumber(val) && !isNaN(val) ? val : undefined;
1619-
// ignore changes before model is initialized
1620-
if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
1621-
return;
1622-
}
1592+
function minChange(val) {
1593+
if (isDefined(val) && !isNumber(val)) {
1594+
val = parseFloat(val);
1595+
}
1596+
minVal = isNumber(val) && !isNaN(val) ? val : undefined;
1597+
// ignore changes before model is initialized
1598+
if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
1599+
return;
1600+
}
16231601

1624-
if (supportsRange && maxAttrType === 'max') {
1625-
var elVal = element.val();
1626-
// IE11 doesn't set the el val correctly if the maxVal is less than the element value
1627-
if (maxVal < elVal) {
1628-
element.val(maxVal);
1629-
elVal = minVal;
1602+
if (supportsRange && minAttrType === 'min') {
1603+
var elVal = element.val();
1604+
// IE11 doesn't set the el val correctly if the minVal is greater than the element value
1605+
if (minVal > elVal) {
1606+
element.val(minVal);
1607+
elVal = minVal;
1608+
}
1609+
ctrl.$setViewValue(elVal);
1610+
} else {
1611+
// TODO(matsko): implement validateLater to reduce number of validations
1612+
ctrl.$validate();
16301613
}
1631-
ctrl.$setViewValue(elVal);
1632-
} else {
1633-
// TODO(matsko): implement validateLater to reduce number of validations
1634-
ctrl.$validate();
16351614
}
16361615
}
1637-
var maxAttrType = isDefined(attr.max) ? 'max' : attr.ngMax ? 'ngMax' : false;
1616+
16381617
if (maxAttrType) {
1639-
ctrl.$validators.max = isDefined(attr.max) && supportsRange ?
1618+
ctrl.$validators.max = maxAttrType === 'max' && supportsRange ?
16401619
function noopMaxValidator() {
16411620
// Since all browsers set the input to a valid value, we don't need to check validity
16421621
return true;
@@ -1649,8 +1628,66 @@ function rangeInputType(scope, element, attr, ctrl, $sniffer, $browser) {
16491628
// Assign maxVal when the directive is linked. This won't run the validators as the model isn't ready yet
16501629
maxChange(attr.max);
16511630
attr.$observe('max', maxChange);
1631+
1632+
function maxChange(val) {
1633+
if (isDefined(val) && !isNumber(val)) {
1634+
val = parseFloat(val);
1635+
}
1636+
maxVal = isNumber(val) && !isNaN(val) ? val : undefined;
1637+
// ignore changes before model is initialized
1638+
if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
1639+
return;
1640+
}
1641+
1642+
if (supportsRange && maxAttrType === 'max') {
1643+
var elVal = element.val();
1644+
// IE11 doesn't set the el val correctly if the maxVal is less than the element value
1645+
if (maxVal < elVal) {
1646+
element.val(maxVal);
1647+
elVal = minVal;
1648+
}
1649+
ctrl.$setViewValue(elVal);
1650+
} else {
1651+
// TODO(matsko): implement validateLater to reduce number of validations
1652+
ctrl.$validate();
1653+
}
1654+
}
16521655
}
16531656

1657+
if (stepAttributeType) {
1658+
ctrl.$validators.step = stepAttributeType === 'step' && supportsRange ?
1659+
function noopStepValidator() {
1660+
// Since all browsers set the input to a valid value, we don't need to check validity
1661+
return true;
1662+
} :
1663+
// ngStep doesn't set the setp attr, so the browser doesn't adjust the input value as setting step would
1664+
function stepValidator(modelValue, viewValue) {
1665+
console.log('StepValidator', viewValue, stepVal, viewValue % stepVal)
1666+
return ctrl.$isEmpty(viewValue) || isUndefined(stepVal) || viewValue % stepVal === 0;
1667+
};
1668+
1669+
// Assign stepVal when the directive is linked. This won't run the validators as the model isn't ready yet
1670+
stepChange(attr.step);
1671+
attr.$observe('step', stepChange);
1672+
1673+
function stepChange(val) {
1674+
if (isDefined(val) && !isNumber(val)) {
1675+
val = parseFloat(val);
1676+
}
1677+
stepVal = isNumber(val) && !isNaN(val) ? val : undefined;
1678+
// ignore changes before model is initialized
1679+
if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
1680+
return;
1681+
}
1682+
1683+
if (supportsRange && stepAttributeType === 'step') {
1684+
ctrl.$setViewValue(element.val());
1685+
} else {
1686+
// TODO(matsko): implement validateLater to reduce number of validations
1687+
ctrl.$validate();
1688+
}
1689+
}
1690+
}
16541691
}
16551692

16561693
function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {

0 commit comments

Comments
 (0)