Skip to content

Instantly share code, notes, and snippets.

@rondale-sc
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rondale-sc/3e0e86d6cf103a9e77e9 to your computer and use it in GitHub Desktop.
Save rondale-sc/3e0e86d6cf103a9e77e9 to your computer and use it in GitHub Desktop.
{{input type="text" value=value}}
{{#directional-link action="handleIncrement"}}
<a class="increment" href="#">+</a>
{{/directional-link}}
{{#directional-link action="handleDecrement"}}
<a class="decrement" href="#">-</a>
{{/directional-link}}
<p>Standard</p>
{{super-number id="standard"}}
<p>Min</p>
{{super-number id="min" min=1}}
<p>Max</p>
{{super-number id="max" max=1}}
<p>Step</p>
{{super-number id="step" step=5}}
<p>Precision</p>
{{super-number id="precision" precision=3}}
<p>Scale</p>
{{super-number id="scale" scale=2}}
<p>Loop</p>
{{super-number id="loop" loop=true min=1 max=9}}
<p>Max hold</p>
{{super-number id="max-hold" max=3}}
var NumberFormatter = function(value, options) {
this._options = options || {};
if (value != null && typeof value === "object") {
this._options = value;
value = null;
}
if (value != null & (parseFloat(value)).toString() === "NaN") {
value = (this._options.min || "0");
}
this.setValue(value);
};
var snapToNearestStep = function(value, num) {
var resto = value % num;
if (resto <= (num / 2)) {
return value - resto;
} else {
return value + num - resto;
}
};
var proto = NumberFormatter.prototype;
proto.setValue = function(value) {
value = value === null ? "0" : value;
if(this._options.min && value < this._options.min) { value = this._options.min; }
if(this._options.max && value > this._options.max) { value = this._options.max; }
if(this._options.step) {
value = snapToNearestStep((parseFloat(value) || 0), parseFloat(this._options.step));
}
this._value = ((parseFloat(value)).toString() === "NaN") ? "0" : value;
return this;
};
proto.add = function(x) {
var value = parseFloat(this._value) + parseFloat(x);
var o = this._options;
if(o.loop && o.min && o.max && o.max < value) { value = o.min; }
this.setValue(value);
return this.toString();
};
proto.subtract = function(x) {
var value = parseFloat(this._value) - parseFloat(x);
var o = this._options;
if(o.loop && o.min && o.max && value < o.min) { value = o.max; }
this.setValue(value);
return this.toString();
};
proto.toString = function() {
var value, absolute_value, sign, whole_number, decimal, precision;
value = this._value + "";
if(this._options.scale) {
var scale = parseFloat(this._options.scale);
value = parseFloat(this._value).toFixed(scale);
}
if(this._options.precision) {
precision = this._options.precision - (this._options.scale || 0);
absolute_value = value.replace(/\-/, "");
sign = (value.length === absolute_value.length) ? "" : "-";
whole_number = absolute_value.replace(/\..*/, "");
decimal = absolute_value.replace(/-?\d*\.?/, "");
if(absolute_value.length < this._options.precision) {
whole_number = new Array(precision - whole_number.length + 1).join("0") + whole_number;
value = sign + whole_number + (decimal ? "." + decimal : "");
}
}
return value;
};
.super_number {
margin: 30px 0 30px 0;
display: inline-block;
position: relative;
}
.super_number a.increment,
.super_number a.decrement {
font-family: Helvetica, Arial, sans-serif;
position: absolute;
z-index: 1;
left: 0;
right: 0;
height: 30px;
font-weight: 200;
text-align: center;
color: white;
text-decoration: none;
font-size: 30px;
line-height: 26px;
background: #d7472b;
transition: background linear 0.2s;
-webkit-transition: background linear 0.2s;
-moz-transition: background linear 0.2;
}
.super_number a.increment:hover,
.super_number a.decrement:hover {
background: #f4401d;
}
.super_number a.increment {
user-select: none;
bottom: 100%;
-moz-border-radius-topleft: 3px;
border-top-left-radius: 3px;
-moz-border-radius-topright: 3px;
border-top-right-radius: 3px;
}
.super_number a.decrement {
user-select: none;
top: 100%;
-moz-border-radius-bottomleft: 3px;
border-bottom-left-radius: 3px;
-moz-border-radius-bottomright: 3px;
border-bottom-right-radius: 3px;
}
var DOWN_ARROW = 40,
UP_ARROW = 38;
Ember.Component.extend({
classNames: ["super_number"],
value: null,
min: null,
max: null,
precision: null,
scale: null,
loop: false,
step: 1,
numberFormatter: null,
init: function() {
this._super();
var options = {
step: this.get('step'),
precision: this.get('precision'),
scale: this.get('scale'),
min: this.get('min'),
max: this.get('max'),
loop: this.get('loop')
};
this.set('numberFormatter', new NumberFormatter(this.get('value'), options));
},
syncFormatter: function(){
this.set('numberFormatter', this.numberFormatter.setValue(this.get('value')));
}.observes('value'),
focusOut: function(){
this.set('value', this.get('numberFormatter').toString());
},
keyDown: function(e) {
if(e.which === DOWN_ARROW) {
this.send('handleDecrement');
} else if(e.which === UP_ARROW) {
this.send('handleIncrement');
}
},
actions: {
handleIncrement: function(){
this.set('value', this.get('numberFormatter').add(this.get('step')));
},
handleDecrement: function(){
this.set('value', this.get('numberFormatter').subtract(this.get('step')));
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment