comparison service/pilight/static/input-number/input-number.js @ 945:752e620f1293

add input-rgb polymer element Ignore-this: 2ba2ef39af2ef4f6c14036c5ac188e97 darcs-hash:20140712183250-312f9-dbe5a232f2d861b3088e314e2cd53ff70ce839d3
author drewp <drewp@bigasterisk.com>
date Sat, 12 Jul 2014 11:32:50 -0700
parents
children
comparison
equal deleted inserted replaced
944:5a3121704234 945:752e620f1293
1 (function() {
2
3 var style = document.createElement('style');
4 style.type = 'text/css';
5 var css = 'body.ew-resize, body.ew-resize * {cursor: ew-resize; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none;}\n';
6 style.appendChild(document.createTextNode(css));
7 document.getElementsByTagName('head')[0].appendChild(style);
8
9 var validKeys = [46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 189, 190, 37, 38, 39, 40, 8, 9];
10
11 var oldValue, selection, range, rect;
12
13 var delta = 0;
14 var deltaStep = 5;
15 var x = 0;
16 var y = 0;
17 var xOld = 0;
18
19 Polymer({
20
21 __doc__: {
22 element: 'input-number',
23 description: 'Input element for numeric data type.',
24 status: 'alpha',
25 url: 'https://github.com/arodic/input-number/',
26 demo: 'http://arodic.github.com/input-number/',
27 attributes: [
28 { name: 'value', type: 'number', description: 'Input value.' },
29 { name: 'min', type: 'number', description: 'Minimum value.' },
30 { name: 'max', type: 'number', description: 'Maximum value.' },
31 { name: 'step', type: 'number', description: 'Value increment when dragging in powers of 10.' },
32 { name: 'toDeg', type: 'boolean', description: 'Converts displayed value to degrees.' },
33 { name: 'editable', type: 'boolean', description: 'Determines if the input can be edited.' }
34 ],
35 properties: [],
36 methods: [],
37 events: [
38 {
39 name: 'input-changed',
40 description: 'Fires when value attribute is changed.'
41 }
42 ]
43 },
44
45 value: 0,
46 min: -Infinity,
47 max: Infinity,
48 step: -3,
49 toDeg: false,
50 editable: true,
51 displayValue: 0,
52 ready: function() {
53 this.setAttribute('tabindex', 0);
54 this.setAttribute('contenteditable', true);
55 this.setAttribute('spellcheck', false);
56 this.addEventListener('keydown', this.onKeydown.bind(this));
57 this.addEventListener('focus', this.onFocus.bind(this));
58 this.addEventListener('blur', this.onBlur.bind(this));
59
60 // TODO: make better on mobile
61 this.$.blocker.addEventListener('dblclick', this.onFocus.bind(this));
62 this.$.blocker.addEventListener('contextmenu', this.onFocus.bind(this));
63 this.$.blocker.addEventListener('mousedown', this.onStartDrag.bind(this));
64 this.$.blocker.addEventListener('touchstart', this.onStartDrag.bind(this));
65
66 this.addEventListener('keydown', this.onKeydown.bind(this));
67 this.addEventListener('mouseover', this.updateBlocker.bind(this));
68
69 },
70 domReady: function() {
71 this.stepChanged();
72 this.displayValueChanged();
73 this.updateBlocker();
74 },
75 onStartDrag: function(event) {
76 // event.stopPropagation();
77 event.preventDefault();
78 event = event.changedTouches ? event.changedTouches[0] : event;
79
80 document.body.classList.add('ew-resize');
81 xOld = event.clientX;
82 delta = 0;
83 document.activeElement.blur();
84 this._onDrag = this.onDrag.bind(this);
85 this._onEndDrag = this.onEndDrag.bind(this);
86 document.addEventListener('mousemove', this._onDrag, false);
87 document.addEventListener('mouseup', this._onEndDrag, false);
88 this.addEventListener('touchmove', this._onDrag, false);
89 this.addEventListener('touchend', this._onEndDrag, false);
90 this.addEventListener('touchcancel', this._onEndDrag, false);
91 this.addEventListener('touchleave', this._onEndDrag, false);
92 },
93 onEndDrag: function(event) {
94 // event.stopPropagation();
95 event = event.changedTouches ? event.changedTouches[0] : event;
96
97 document.body.classList.remove('ew-resize');
98 document.removeEventListener('mousemove', this._onDrag, false);
99 document.removeEventListener('mouseup', this._onEndDrag, false);
100 this.removeEventListener('touchmove', this._onDrag, false);
101 this.removeEventListener('touchend', this._onEndDrag, false);
102 this.removeEventListener('touchcancel', this._onEndDrag, false);
103 this.removeEventListener('touchleave', this._onEndDrag, false);
104 },
105 onDrag: function(event) {
106 // event.stopPropagation();
107 // TODO: add acceleration
108 if (!this.editable) return;
109 if (event.type == 'mousemove' && event.which === 0) {
110 this._onEndDrag(event);
111 return;
112 }
113
114 oldValue = this.value;
115
116 event = event.changedTouches ? event.changedTouches[0] : event;
117
118 x = event.clientX;
119 y = event.clientY;
120 delta += x - xOld;
121 xOld = event.clientX;
122
123 while (Math.abs(delta) > deltaStep) {
124 if (delta > deltaStep) {
125 if (this.toDeg) this.value += Math.pow(10, this.step) / 180 * Math.PI;
126 else this.value += Math.pow(10, this.step);
127 delta -= deltaStep;
128 }
129 if (delta < -deltaStep) {
130 if (this.toDeg) this.value -= Math.pow(10, this.step) / 180 * Math.PI;
131 else this.value -= Math.pow(10, this.step);
132 delta += deltaStep;
133 }
134 }
135 this.value = Math.max(this.value, this.min);
136 this.value = Math.min(this.value, this.max);
137 if (this.value != oldValue) this.fire('input-changed', { input: this, oldValue: oldValue, newValue: this.value, delta: this.value - oldValue });
138 },
139
140 onKeydown: function(event) {
141 // TODO: number keyboard on mobile
142 event.stopPropagation();
143 if(event.which == 13) {
144 selection = window.getSelection();
145 selection.removeAllRanges();
146 this.blur();
147 return;
148 }
149
150 oldValue = this.value;
151
152 if (!this.editable || validKeys.indexOf(event.which) == -1) {
153 event.preventDefault();
154 return;
155 }
156 setTimeout(function(){
157 this.updateValue();
158 this.fire('input-changed', { input: this, oldValue: oldValue, newValue: this.value, delta: this.value - oldValue });
159 }.bind(this), 1);
160
161 },
162 onFocus: function(event) {
163 event.preventDefault();
164 selection = window.getSelection();
165 selection.removeAllRanges();
166 range = document.createRange();
167 this.textContent = this.displayValue;
168 range.selectNodeContents(this);
169 selection.addRange(range);
170 this.focused = true;
171 },
172 onBlur: function() {
173 this.updateValue();
174 selection = window.getSelection();
175 selection.removeAllRanges();
176 this.focused = false;
177 this.updateValue();
178 this.valueChanged();
179 this._match = this.displayValue.toString().match(this.regEx);
180 this.textContent = this._match ? parseFloat(this._match[1]) : this.displayValue;
181 },
182 updateValue: function() {
183 if (!isNaN(this.textContent) && (this.textContent.slice(-1) != '.')) {
184 if (this.toDeg)
185 this.value = parseFloat(this.textContent) / 180 * Math.PI;
186 else
187 this.value = parseFloat(this.textContent);
188 }
189 },
190 updateBlocker: function() {
191 rect = this.getBoundingClientRect();
192 this.$.blocker.style.width = rect.width + 'px';
193 this.$.blocker.style.height = rect.height + 'px';
194 },
195 valueChanged: function() {
196 if (this.value < this.min) this.min = this.value;
197 if (this.value > this.max) this.max = this.value;
198
199 if (!this.focused) {
200 if (this.toDeg)
201 this.displayValue = this.value / Math.PI * 180;
202 else
203 this.displayValue = this.value;
204 }
205 },
206 displayValueChanged: function() {
207 this._match = this.displayValue.toString().match(this.regEx);
208 this.textContent = this._match ? parseFloat(this._match[1]) : this.displayValue;
209 this.updateBlocker();
210 },
211 toDegChanged: function() {
212 this.valueChanged();
213 },
214 minChanged: function() {
215 this.value = Math.max(this.value, this.min);
216 },
217 maxChanged: function() {
218 this.value = Math.min(this.value, this.max);
219 },
220 stepChanged: function() {
221 if (this.step < 0) {
222 this.regEx = new RegExp("(^-?\\d+\\.\\d{" + Math.abs(this.step) + "})(\\d)");
223 } else {
224 this.regEx = new RegExp("(^-?\\d+\\.\\d{" + 1 + "})(\\d)");
225 }
226 }
227 });
228
229 })();