1 | // Mark MacKay http://method.ac MIT License
|
---|
2 |
|
---|
3 |
|
---|
4 | $.fn.dragInput = function(cfg){
|
---|
5 | return this.each(function(){
|
---|
6 |
|
---|
7 | this.repeating = false;
|
---|
8 | // Apply specified options or defaults:
|
---|
9 | // (Ought to refactor this some day to use $.extend() instead)
|
---|
10 | this.dragCfg = {
|
---|
11 | min: cfg && !isNaN(parseFloat(cfg.min)) ? Number(cfg.min) : null, // Fixes bug with min:0
|
---|
12 | max: cfg && !isNaN(parseFloat(cfg.max)) ? Number(cfg.max) : null,
|
---|
13 | step: cfg && Number(cfg.step) ? cfg.step : 1,
|
---|
14 | stepfunc: cfg && cfg.stepfunc ? cfg.stepfunc : false,
|
---|
15 | dragAdjust: cfg && cfg.dragAdjust ? cfg.dragAdjust : 1,
|
---|
16 | height: 70,
|
---|
17 | cursor: cfg && cfg.cursor ? Boolean(cfg.cursor) : false,
|
---|
18 | start: cfg && cfg.start ? Number(cfg.start) : 0,
|
---|
19 | _btn_width: 20,
|
---|
20 | _direction: null,
|
---|
21 | _delay: null,
|
---|
22 | _repeat: null,
|
---|
23 | callback: cfg && cfg.callback ? cfg.callback : null
|
---|
24 | };
|
---|
25 | // if a smallStep isn't supplied, use half the regular step
|
---|
26 | this.dragCfg.smallStep = cfg && cfg.smallStep ? cfg.smallStep : this.dragCfg.step/2;
|
---|
27 | var dragAdjust = this.dragCfg.dragAdjust;
|
---|
28 | var $label = $(this).parent();
|
---|
29 | var $input = $(this);
|
---|
30 | var cursorHeight = this.dragCfg.height;
|
---|
31 | var min = this.dragCfg.min;
|
---|
32 | var max = this.dragCfg.max
|
---|
33 | var step = this.dragCfg.step
|
---|
34 | var area = (max - min > 0) ? (max - min) / step : 200;
|
---|
35 | var scale = area/cursorHeight * step;
|
---|
36 | var lastY = 0;
|
---|
37 | var attr = this.getAttribute("data-attr");
|
---|
38 | var canvas = methodDraw.canvas
|
---|
39 | var isTouch = svgedit.browser.isTouch();
|
---|
40 | var completed = true //for mousewheel
|
---|
41 | var $cursor = (area && this.dragCfg.cursor)
|
---|
42 | ? $("<div class='draginput_cursor' />").appendTo($label)
|
---|
43 | : false
|
---|
44 | $input.attr("readonly", "readonly")
|
---|
45 | if ($cursor && !isNaN(this.dragCfg.start)) $cursor.css("top", (this.dragCfg.start*-1)/scale+cursorHeight)
|
---|
46 |
|
---|
47 | //this is where all the magic happens
|
---|
48 | this.adjustValue = function(i, completed){
|
---|
49 | var v;
|
---|
50 | i = parseFloat(i);
|
---|
51 | if(isNaN(this.value)) {
|
---|
52 | v = this.dragCfg.reset;
|
---|
53 | } else if($.isFunction(this.dragCfg.stepfunc)) {
|
---|
54 | v = this.dragCfg.stepfunc(this, i);
|
---|
55 | } else {
|
---|
56 | v = Number((Number(this.value) + Number(i)).toFixed(5));
|
---|
57 | }
|
---|
58 | if (max !== null) v = Math.min(v, max);
|
---|
59 | if (min !== null) v = Math.max(v, min);
|
---|
60 | if ($cursor) this.updateCursor(v);
|
---|
61 | this.value = v;
|
---|
62 | $label.attr("data-value", v)
|
---|
63 | if ($.isFunction(this.dragCfg.callback)) this.dragCfg.callback(this, completed)
|
---|
64 | };
|
---|
65 |
|
---|
66 | $label.toggleClass("draginput", $label.is("label"))
|
---|
67 |
|
---|
68 | // when the mouse is down and moving
|
---|
69 | this.move = function(e, oy, val) {
|
---|
70 | if (isTouch) {
|
---|
71 | e = e.originalEvent.touches[0]
|
---|
72 | }
|
---|
73 | // just got started let's save for undo purposes
|
---|
74 | if (lastY === 0) {
|
---|
75 | lastY = oy;
|
---|
76 | }
|
---|
77 | var deltaY = (e.pageY - lastY) *-1
|
---|
78 | lastY = e.pageY;
|
---|
79 | val = (deltaY * scale) * dragAdjust
|
---|
80 | var fixed = (step < 1) ? 1 : 0
|
---|
81 | this.adjustValue(val.toFixed(fixed)) //no undo true
|
---|
82 | };
|
---|
83 |
|
---|
84 | //when the mouse is released
|
---|
85 | this.stop = function() {
|
---|
86 | var selectedElems = canvas.getSelectedElems();
|
---|
87 | $('body').removeClass('dragging');
|
---|
88 | $label.removeClass("active");
|
---|
89 | completed = true;
|
---|
90 | $(window).unbind("mousemove.draginput touchmove.draginput mouseup.draginput touchend.draginput");
|
---|
91 | lastY = 0;
|
---|
92 | if (selectedElems[0]) {
|
---|
93 | var batchCmd = canvas.undoMgr.finishUndoableChange();
|
---|
94 | if (!batchCmd.isEmpty()) canvas.undoMgr.addCommandToHistory(batchCmd);
|
---|
95 | }
|
---|
96 | this.adjustValue(0, completed)
|
---|
97 | }
|
---|
98 |
|
---|
99 | this.updateCursor = function(){
|
---|
100 | var value = parseFloat(this.value);
|
---|
101 | var pos = (value*-1)/scale+cursorHeight;
|
---|
102 | $cursor.css("top", pos);
|
---|
103 | }
|
---|
104 |
|
---|
105 | this.launch = function(e) {
|
---|
106 | var selectedElems = canvas.getSelectedElems();
|
---|
107 | if (isTouch) e = e.originalEvent.touches[0];
|
---|
108 | var oy = e.pageY;
|
---|
109 | var val = this.value;
|
---|
110 | var el = this;
|
---|
111 | canvas.undoMgr.beginUndoableChange(attr, selectedElems)
|
---|
112 | $('body').addClass('dragging');
|
---|
113 | $label.addClass('active');
|
---|
114 | $(window).bind("mousemove.draginput touchmove.draginput", function(e){el.move(e, oy, parseFloat(val))})
|
---|
115 | $(window).bind("mouseup.draginput touchend.draginput", function(e){el.stop()})
|
---|
116 | }
|
---|
117 |
|
---|
118 | $(this)
|
---|
119 | .attr("readonly", "readonly")
|
---|
120 | .attr("data-scale", scale)
|
---|
121 | .attr("data-domain", cursorHeight)
|
---|
122 | .attr("data-cursor", ($cursor != false))
|
---|
123 |
|
---|
124 | .bind("mousedown touchstart", function(e){
|
---|
125 | this.blur();
|
---|
126 | this.launch(e);
|
---|
127 | })
|
---|
128 |
|
---|
129 | .bind("dblclick taphold", function(e) {
|
---|
130 | this.removeAttribute("readonly", "readonly");
|
---|
131 | this.focus();
|
---|
132 | this.select();
|
---|
133 | })
|
---|
134 |
|
---|
135 | .keydown(function(e){
|
---|
136 | // Respond to up/down arrow keys.
|
---|
137 | switch(e.keyCode){
|
---|
138 | case 13: this.adjustValue(0); this.blur(); break; // Enter
|
---|
139 | }
|
---|
140 | })
|
---|
141 |
|
---|
142 | .focus(function(e){
|
---|
143 | if (this.getAttribute("readonly") === "readonly") this.blur()
|
---|
144 | })
|
---|
145 |
|
---|
146 | .blur(function(e){
|
---|
147 | this.setAttribute("readonly", "readonly")
|
---|
148 | })
|
---|
149 |
|
---|
150 | .bind("mousewheel", function(e, delta, deltaX, deltaY){
|
---|
151 | var selectedElems = canvas.getSelectedElems();
|
---|
152 | if (completed) canvas.undoMgr.beginUndoableChange(attr, selectedElems)
|
---|
153 | completed = false
|
---|
154 | clearTimeout(window.undoTimeout)
|
---|
155 | window.undoTimeout = setTimeout(function(){
|
---|
156 | wheel_input.stop()
|
---|
157 | },200)
|
---|
158 |
|
---|
159 | var wheel_input = this;
|
---|
160 | if (deltaY > 0)
|
---|
161 | this.adjustValue(this.dragCfg.step);
|
---|
162 | else if (deltaY < 0)
|
---|
163 | this.adjustValue(-this.dragCfg.step);
|
---|
164 | e.preventDefault();
|
---|
165 |
|
---|
166 | })
|
---|
167 |
|
---|
168 | });
|
---|
169 |
|
---|
170 | };
|
---|
171 |
|
---|
172 | // public function
|
---|
173 | $.fn.dragInput.updateCursor = function(el){
|
---|
174 | var value = parseFloat(el.value);
|
---|
175 | var scale = parseFloat(el.getAttribute("data-scale"));
|
---|
176 | var domain = parseFloat(el.getAttribute("data-domain"));
|
---|
177 | var pos = ((value*-1)/scale+domain) + "px";
|
---|
178 | var cursor = el.parentNode.lastChild
|
---|
179 | if (cursor.className == "draginput_cursor") cursor.style.top = pos;
|
---|
180 | }
|
---|
181 |
|
---|