Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 <!doctype html> | |
| 2 <html> | |
| 3 <head> | |
| 4 <link rel="import" href="../../../polymer/polymer.html"> | |
| 5 <link rel="import" href="../../../neoprene/components/x-elements/x-template/ x-template.html"> | |
| 6 </head> | |
| 7 <body> | |
| 8 | |
| 9 <dom-module id="designer-selection"> | |
| 10 <style> | |
| 11 designer-selection { | |
| 12 display: block; | |
| 13 position: absolute; | |
| 14 box-sizing: border-box; | |
| 15 } | |
| 16 designer-selection > #bounds { | |
| 17 position: absolute; | |
| 18 top: 0; | |
| 19 left: 0; | |
| 20 right: 0; | |
| 21 bottom: 0; | |
| 22 background: rgba(128, 128, 255, .5); | |
| 23 border: solid 1px #88f; | |
|
imac
2015/02/05 03:18:33
do you want border-box here?
justinfagnani
2015/02/05 20:15:54
Done.
| |
| 24 } | |
| 25 designer-selection > .handle { | |
| 26 position: absolute; | |
| 27 box-sizing: border-box; | |
| 28 width: 8px; | |
| 29 height: 8px; | |
| 30 border: solid 1px #88f; | |
| 31 background: #fff; | |
| 32 } | |
| 33 designer-selection > .handle:hover { | |
| 34 background: #88f; | |
| 35 } | |
| 36 designer-selection > #top { | |
| 37 top: -4px; | |
| 38 left: calc(50% - 4px); | |
| 39 cursor: ns-resize; | |
| 40 } | |
| 41 designer-selection > #left { | |
| 42 top: calc(50% - 4px); | |
| 43 left: -4px; | |
| 44 cursor: ew-resize; | |
| 45 } | |
| 46 designer-selection > #bottom { | |
| 47 bottom: -4px; | |
| 48 left: calc(50% - 4px); | |
| 49 cursor: ns-resize; | |
| 50 } | |
| 51 designer-selection > #right { | |
| 52 top: calc(50% - 4px); | |
| 53 right: -4px; | |
| 54 cursor: ew-resize; | |
| 55 } | |
| 56 designer-selection > #top_left { | |
| 57 top: -4px; | |
| 58 left: -4px; | |
| 59 cursor: nwse-resize; | |
| 60 } | |
| 61 designer-selection > #top_right { | |
| 62 top: -4px; | |
| 63 right: -4px; | |
| 64 cursor: nesw-resize; | |
| 65 } | |
| 66 designer-selection > #bottom_left { | |
| 67 bottom: -4px; | |
| 68 left: -4px; | |
| 69 cursor: nesw-resize; | |
| 70 } | |
| 71 designer-selection > #bottom_right { | |
| 72 bottom: -4px; | |
| 73 right: -4px; | |
| 74 cursor: nwse-resize; | |
| 75 } | |
| 76 </style> | |
| 77 <template> | |
| 78 <div id="bounds"></div> | |
| 79 <template is="x-repeat" items="{{directions}}"> | |
| 80 <div class="handle" id$="{{item.name}}"></div> | |
| 81 </template> | |
| 82 </template> | |
| 83 </dom-module> | |
| 84 | |
| 85 <script type="text/javascript"> | |
| 86 function ResizeDirection(name, x, y) { | |
| 87 this.name = name; | |
| 88 this.x = x; | |
| 89 this.y = y; | |
| 90 } | |
| 91 | |
| 92 ResizeDirection.prototype.toString = function() { | |
| 93 return 'ResizeDirection(' + this.name + ', ' + this.x + ', ' + this.y + ')'; | |
| 94 }; | |
|
imac
2015/02/05 03:18:33
Yay!
justinfagnani
2015/02/05 20:15:54
Done.
| |
| 95 | |
| 96 ResizeDirection.prototype.locate = function(rect) { | |
| 97 return { | |
| 98 x: rect.left + rect.width * this.x, | |
| 99 y: rect.top + rect.height * this.y | |
| 100 }; | |
| 101 }; | |
| 102 | |
| 103 ResizeDirection.prototype.resizesLeft = function() { | |
| 104 return this.x == 0.0; | |
| 105 }, | |
| 106 | |
| 107 ResizeDirection.prototype.resizesRight = function() { | |
| 108 return this.x == 1.0; | |
| 109 }, | |
| 110 | |
| 111 ResizeDirection.prototype.resizesTop = function() { | |
| 112 return this.y == 0.0; | |
| 113 }, | |
| 114 | |
| 115 ResizeDirection.prototype.resizesBottom = function() { | |
| 116 return this.y == 1.0; | |
| 117 }, | |
| 118 | |
| 119 (function () { | |
| 120 var top = ResizeDirection.top = new ResizeDirection('top', 0.5, 0.0); | |
| 121 var left = ResizeDirection.left = new ResizeDirection('left', 0.0, 0.5); | |
| 122 var bottom = ResizeDirection.bottom = new ResizeDirection('bottom', 0.5, 1.0); | |
| 123 var right = ResizeDirection.right = new ResizeDirection('right', 1.0, 0. 5); | |
| 124 var top_left = ResizeDirection.top_left = new ResizeDirection('top_left' , 0.0, 0.0); | |
| 125 var top_right = ResizeDirection.top_right = new ResizeDirection('top_rig ht', 1.0, 0.0); | |
| 126 var bottom_left = ResizeDirection.bottom_left = new ResizeDirection('bot tom_left', 0.0, 1.0); | |
| 127 var bottom_right = ResizeDirection.bottom_right = new ResizeDirection('b ottom_right', 1.0, 1.0); | |
|
imac
2015/02/05 03:18:33
these should probably be ALL_CAPS (constants), or
justinfagnani
2015/02/05 20:15:54
I'll do camel case, I don't find ALL_CAPS to conve
| |
| 128 | |
| 129 ResizeDirection.all_directions = [top, left, bottom, right, top_left, to p_right, bottom_left, bottom_right]; | |
| 130 ResizeDirection.width_height = [bottom, right, bottom_right]; | |
| 131 })(); | |
|
imac
2015/02/05 03:18:33
consider moving ResizeDirection out to a separate
justinfagnani
2015/02/05 20:15:54
Done.
| |
| 132 | |
| 133 Polymer({ | |
| 134 is: 'designer-selection', | |
| 135 | |
| 136 created: function() { | |
| 137 this._onMove = null; | |
| 138 this._dragging = false; | |
| 139 this._offsetX = null; | |
| 140 this._offsetY = null; | |
| 141 this._onMouseMove_bound = this._onMouseMove.bind(this); | |
| 142 this._onMouseUp_bound = this._onMouseUp.bind(this); | |
| 143 this._resizeDirection = null; | |
| 144 }, | |
| 145 | |
| 146 ready: function() { | |
| 147 this.directions = ResizeDirection.all_directions; | |
| 148 }, | |
| 149 | |
| 150 listeners: { | |
| 151 'mousedown': '_onMouseDown' | |
| 152 }, | |
| 153 | |
| 154 _onMouseDown: function(e) { | |
| 155 if (e.target.id == 'bounds') { | |
| 156 this._boundsDown(e); | |
| 157 } else { | |
| 158 this._handleDown(e); | |
| 159 } | |
| 160 }, | |
| 161 | |
| 162 _onMouseUp: function(e) { | |
| 163 this._stopDrag(); | |
| 164 }, | |
| 165 | |
| 166 _onMouseMove: function(e) { | |
| 167 if (this._onMove != null) { | |
|
imac
2015/02/05 03:18:33
this feels like it should be an assert
justinfagnani
2015/02/05 20:15:54
Done.
| |
| 168 var deltaX = e.clientX - this._offsetX; | |
| 169 var deltaY = e.clientY - this._offsetY; | |
| 170 this._onMove(deltaX, deltaY); | |
| 171 } | |
| 172 }, | |
| 173 | |
| 174 // called for mousedown on the main bounding box div | |
| 175 _boundsDown: function(e) { | |
| 176 this.$.bounds.style.cursor = 'move'; | |
|
imac
2015/02/05 03:18:33
wouldn't you want the cursor to always be this to
justinfagnani
2015/02/05 20:15:54
I'm not totally sure, you should also be able to c
| |
| 177 this._startDrag(this._boundsMove, e.clientX - this.offsetLeft, e.clien tY - this.offsetTop); | |
| 178 }, | |
| 179 | |
| 180 // [x], and [y] are relative to the offset passed to _startDrag | |
| 181 _boundsMove: function(x, y) { | |
| 182 var event = new CustomEvent('designer-selection-resize', | |
| 183 {detail: { | |
| 184 left: x, | |
| 185 top: y, | |
| 186 width: this.offsetWidth, | |
| 187 height: this.offsetHeight}}); | |
| 188 this.dispatchEvent(event); | |
| 189 }, | |
| 190 | |
| 191 // called for mousedown on one of the resize handle divs | |
| 192 _handleDown: function(e) { | |
|
imac
2015/02/05 03:18:33
_resizeDown/_resizeMove would be clearer, I think
justinfagnani
2015/02/05 20:15:54
_resizeHandleDown is the most clear!
imac
2015/02/06 20:26:31
Most clearerer!
justinfagnani
2015/02/06 23:46:39
Acknowledged.
| |
| 193 var handle = e.target; | |
| 194 var direction = this._resizeDirection = ResizeDirection[handle.id]; | |
| 195 | |
| 196 var boundsBounds = this.$.bounds.getBoundingClientRect(); | |
|
imac
2015/02/05 03:18:33
http://vimeo.com/87712359
justinfagnani
2015/02/05 20:15:54
Acknowledged.
| |
| 197 var handleBounds = handle.getBoundingClientRect(); | |
| 198 | |
| 199 var offsetLeft = direction.resizesLeft() | |
| 200 ? 0 | |
| 201 : boundsBounds.left + (e.clientX - handleBounds.left); | |
|
imac
2015/02/05 03:18:33
I'm confused, why does the position of the handle
justinfagnani
2015/02/05 20:15:54
This prevents a jump on first move by the amount t
| |
| 202 | |
| 203 var offsetTop = direction.resizesTop() | |
| 204 ? 0 | |
| 205 : boundsBounds.top + (e.clientY - handleBounds.top); | |
| 206 | |
| 207 this._startDrag(this._handleMove, offsetLeft, offsetTop); | |
| 208 }, | |
| 209 | |
| 210 _handleMove: function(x, y) { | |
| 211 var direction = this._resizeDirection; | |
| 212 | |
| 213 var newWidth = | |
| 214 direction.resizesLeft() ? this.offsetWidth + this.offsetLeft - x : | |
|
imac
2015/02/05 03:18:33
Rather than having to calculate offsetLeft/Top eac
justinfagnani
2015/02/05 20:15:54
Yeah, this.offsetWidth + this.offsetLeft is what I
imac
2015/02/06 20:26:31
Hmm, I mean that you shouldn't need to refer to th
justinfagnani
2015/02/06 23:46:39
Yes, but I want to restructure this so I don't hav
| |
| 215 direction.resizesRight() ? x : | |
| 216 this.offsetWidth; | |
| 217 | |
| 218 var newHeight = | |
| 219 direction.resizesTop() ? this.offsetHeight + this.offsetTop - y : | |
| 220 direction.resizesBottom() ? y : | |
| 221 this.offsetHeight; | |
| 222 | |
| 223 var newLeft = direction.resizesLeft() ? x : this.offsetLeft; | |
| 224 var newTop = direction.resizesTop() ? y : this.offsetTop; | |
| 225 | |
| 226 var event = new CustomEvent('designer-selection-resize', | |
| 227 {detail: { | |
| 228 left: newLeft, | |
| 229 top: newTop, | |
| 230 width: newWidth, | |
| 231 height: newHeight}}); | |
| 232 this.dispatchEvent(event); | |
| 233 | |
| 234 }, | |
| 235 | |
| 236 _startDrag: function(onMove, offsetX, offsetY) { | |
| 237 this._dragging = true; | |
| 238 this._onMove = onMove; | |
| 239 this._offsetX = offsetX; | |
| 240 this._offsetY = offsetY; | |
| 241 window.addEventListener('mouseup', this._onMouseUp_bound); | |
| 242 window.addEventListener('mousemove', this._onMouseMove_bound); | |
| 243 }, | |
| 244 | |
| 245 _stopDrag: function() { | |
| 246 this._dragging = false; | |
| 247 this._onMove = null; | |
| 248 this._offsetX = null; | |
| 249 this._offsetY = null; | |
| 250 window.removeEventListener('mouseup', this._onMouseUp_bound); | |
| 251 window.removeEventListener('mousemove', this._onMouseMove_bound); | |
| 252 this.$.bounds.style.cursor = 'auto'; | |
| 253 } | |
| 254 }); | |
| 255 </script> | |
| 256 </body> | |
| 257 </html> | |
| OLD | NEW |