How can I get an input event to stop typing e.preventDefault() ? Or are there any other ways to implement this?

 var maxTotal = 150, inputs = [].slice.call(document.getElementsByTagName('input')), getTotal = function() { var sum = 0; inputs.forEach(function(input) { sum += parseInt(input.value, 10); }); return sum; }, maxReached = function(e) { var sum = getTotal(), target; if (sum > maxTotal) { target = e.target; target.value = target.value - (sum - maxTotal); // next line is just for demonstrational purposes document.getElementById('total').innerHTML = getTotal(); e.preventDefault(); return false; } // next line is just for demonstrational purposes document.getElementById('total').innerHTML = getTotal(); return true; }; inputs.forEach(function(input) { input.addEventListener('input', maxReached); }); 
 <input type="range" min="0" max="100" value="0" /> <input type="range" min="0" max="100" value="0" /> <input type="range" min="0" max="100" value="0" /> <div>total: <strong id="total">0</strong>/150</div> 

http://jsfiddle.net/EL4tf/

  • What prevents to transfer the existing code to the angular? - Grundy
  • @Grundy, this is quite beautifully done by angular methods :) - Qwertiy

1 answer 1

You can make a directive that will make nested items and control the amount. And it is possible in another way: just set a limit for the ng-model :

 angular.module('app', []) .controller('Ctrl', function ($scope) { $scope.a = $scope.b = $scope.c = 0; $scope.lim = 150; ($scope.update = function () { $scope.sum = $scope.a + $scope.b + $scope.c; })(); }) .directive('mySumLimit', function () { return { restrict: 'A', require: 'ngModel', link: function (scope, el, attrs, ngModel) { var old = scope.$eval(attrs.ngModel); var lim = scope.$eval(attrs.mySumLimit); ngModel.$parsers.unshift(function (val) { val = +val; if (val > lim + old) { ngModel.$setViewValue(val = lim + old); ngModel.$render(); } return val; }); scope.$on('destroy', scope.$watch(attrs.mySumLimit, function (val) { lim = val; })); scope.$on('destroy', scope.$watch(function () { return ngModel.$modelValue }, function (val) { old = val; })); } }; }) 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="app" ng-controller="Ctrl"> <input type="range" min="0" max="100" ng-model="a" my-sum-limit="lim-sum" ng-change="update()" /> <input type="range" min="0" max="100" ng-model="b" my-sum-limit="lim-sum" ng-change="update()" /> <input type="range" min="0" max="100" ng-model="c" my-sum-limit="lim-sum" ng-change="update()" /> <div>total: <strong id="total">{{sum}}</strong>/{{lim}}</div> 

  • Wonderful, thank you! Only $scope.a, $scope.b, $scope.c replaced with one object so that there is no dependence on the number of input 's. - Sasay
  • @Sasay, just use an array and ng-repeat. This does not affect the given directive. If there is a problem with binding inputov, ask a separate question and write me a link in the comments - I will answer. - Qwertiy