Last active
December 29, 2015 04:08
-
-
Save lionelB/7612233 to your computer and use it in GitHub Desktop.
An attempt to do a Numeric Stepper the Angular Way http://plnkr.co/edit/R4FYQKCGyB1GYl2hL4LO
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html ng-app="ui"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Angular numeric Stepper</title> | |
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1, height=device-height, maximum-scale=1" /> | |
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.2/css/bootstrap-theme.css" /> | |
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.2/css/bootstrap.css" /> | |
<style> | |
.ui-stepper{ | |
position:relative; | |
} | |
.stepper-bt{ | |
position:absolute; | |
right:0; | |
height:15px; | |
border:#ccc 1px solid; | |
font-size:.8em; | |
background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fff), to(#e6e6e6)); // Safari 4+, Chrome 2+ | |
background-image: -webkit-linear-gradient(top, #fff, 0%, #e6e6e6, 100%); // Safari 5.1+, Chrome 10+ | |
background-image: -moz-linear-gradient(top, #fff 0%, #e6e6e6 100%); // FF 3.6+ | |
background-image: linear-gradient(to bottom, #fff 0%, #e6e6e6 100%); // Standard, IE10 | |
background-repeat: repeat-x; | |
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff', endColorstr='#e6e6e6', GradientType=0)",argb(#fff),argb(#e6e6e6))); // IE9 and down | |
display: inline-block; | |
padding: 0 .5em; | |
margin-right:-3px; | |
} | |
.stepper-bt:hover{ | |
background: #dedede; | |
background-image: none; | |
} | |
.stepper-bt:active{ | |
background: #efefef; | |
background-image: none; | |
} | |
.stepper-bt__up{ | |
top:0; | |
border-top-right-radius: 3px; | |
} | |
.stepper-bt__up .caret{ | |
position:relative; | |
top:-2px; | |
} | |
.stepper-bt__down{ | |
border-bottom-right-radius: 3px; | |
bottom:0; | |
} | |
</style> | |
</head> | |
<body> | |
<div ng-controller="AppController"> | |
<ui-stepper min="0" max="12" value="hours" step-size="1"></ui-stepper> | |
<span class="help-block text-left">{{hours}} hours</span> | |
</div> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.js"></script> | |
<script src="/js/ui.stepper.js"></script> | |
<script src="/js/app.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var app = angular.module('ui', ['ui.stepper']); | |
app.controller('AppController', ['$scope', | |
function($scope){ | |
$scope.hours="0"; | |
} | |
]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="ui-stepper input-group"> | |
<input type="text" class="form-control input-sm" ng-model="value" /> | |
<a class="stepper-bt stepper-bt__up dropup" ng-click="increment()"> | |
<i class="caret"></i> | |
<span class="sr-only">Increment</span> | |
</a> | |
<a class="stepper-bt stepper-bt__down" ng-click="decrement()"> | |
<span class="caret"></span> | |
<span class="sr-only">Decrement</span> | |
</a> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* global angular, console */ | |
angular.module('ui.stepper', []) | |
.constant('stepperConfig',{ | |
stepSize: 10, | |
min: 0, | |
max: 100 | |
}) | |
.directive('uiStepper', ['stepperConfig', | |
function(stepperConfig){ | |
'use strict'; | |
return { | |
restrict: 'A', | |
require: 'ngModel', | |
scope: { | |
'value': "=ngModel" | |
}, | |
replace: true, | |
templateUrl: 'view/stepper.html', | |
link: function(scope, element, attrs, ngModel ){ | |
// Set default values | |
attrs.min = parseInt(attrs.min || stepperConfig.min, 10); | |
attrs.max = parseInt(attrs.max || stepperConfig.max, 10); | |
attrs.value = parseInt(attrs.value || stepperConfig.value, 10); | |
attrs.stepSize = parseInt(attrs.stepSize || stepperConfig.stepSize, 10); | |
attrs.allowCycle = attrs.allowCycle; | |
console.log(attrs.allowCycle); | |
var input = element.find('input'); | |
// Allow user to increment / decrement using arrow key | |
input.bind('keydown', function(evt){ | |
var key = evt.charCode || evt.keyCode || 0; | |
if (key === 38) { | |
scope.increment(); | |
scope.$apply(); | |
} | |
if (key === 40){ | |
scope.decrement(); | |
scope.$apply(); | |
} | |
}); | |
// Prevent user to enter non numeric char | |
input.bind('keypress', function(evt){ | |
var key = evt.charCode || evt.keyCode || 0; | |
if ( !/[0-9]/.test( String.fromCharCode(key) )) { | |
evt.preventDefault(); | |
return false; | |
} | |
}); | |
scope.increment = function(){ | |
var val = parseInt(ngModel.$modelValue, 10) | |
, updateFn = attrs.allowCycle ? loop : clamp; | |
input[0].focus(); | |
ngModel.$setViewValue(updateFn( val + attrs.stepSize, attrs.min, attrs.max) ); | |
}; | |
scope.decrement = function(){ | |
var val = parseInt(ngModel.$modelValue, 10) | |
, updateFn = attrs.allowCycle ? loop : clamp; | |
ngModel.$setViewValue(updateFn( val - attrs.stepSize, attrs.min, attrs.max) ); | |
}; | |
function loop(val, min, max){ | |
return val < min? max : (val > max? min : val); | |
} | |
function clamp(val, min, max){ | |
return val < min? min : (val > max? max : val); | |
} | |
} | |
}; | |
} | |
]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thx a lot... It seems that I made some mistake when isolating my code... Also on plunker, I saw some error when I dropped jquery which I need on my project)... Now I understand!
Not sure about scoping max, min, and stepSize... My goal was I to mabe them updatable/bindable from code or other binding (ex:switching AM/PM, max going from 12 to 24)
About requiring a ng-model, I'm not sure to see the benefit cause it's a bit new to me, but I see some example using that scheme.
Nice to have insightfull comment !