Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(294)

Unified Diff: elements/designer-selection/designer-selection.html

Issue 877243005: Add designer-selection element (Closed) Base URL: https://github.com/PolymerLabs/designer2.git@master
Patch Set: Move style outside template Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« bower.json ('K') | « elements/designer-selection/demo.html ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: elements/designer-selection/designer-selection.html
diff --git a/elements/designer-selection/designer-selection.html b/elements/designer-selection/designer-selection.html
new file mode 100644
index 0000000000000000000000000000000000000000..06e788e2ae3e8ed6b4c4c6b024d4b419c746896c
--- /dev/null
+++ b/elements/designer-selection/designer-selection.html
@@ -0,0 +1,257 @@
+<!doctype html>
+<html>
+ <head>
+ <link rel="import" href="../../../polymer/polymer.html">
+ <link rel="import" href="../../../neoprene/components/x-elements/x-template/x-template.html">
+ </head>
+ <body>
+
+ <dom-module id="designer-selection">
+ <style>
+ designer-selection {
+ display: block;
+ position: absolute;
+ box-sizing: border-box;
+ }
+ designer-selection > #bounds {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(128, 128, 255, .5);
+ 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.
+ }
+ designer-selection > .handle {
+ position: absolute;
+ box-sizing: border-box;
+ width: 8px;
+ height: 8px;
+ border: solid 1px #88f;
+ background: #fff;
+ }
+ designer-selection > .handle:hover {
+ background: #88f;
+ }
+ designer-selection > #top {
+ top: -4px;
+ left: calc(50% - 4px);
+ cursor: ns-resize;
+ }
+ designer-selection > #left {
+ top: calc(50% - 4px);
+ left: -4px;
+ cursor: ew-resize;
+ }
+ designer-selection > #bottom {
+ bottom: -4px;
+ left: calc(50% - 4px);
+ cursor: ns-resize;
+ }
+ designer-selection > #right {
+ top: calc(50% - 4px);
+ right: -4px;
+ cursor: ew-resize;
+ }
+ designer-selection > #top_left {
+ top: -4px;
+ left: -4px;
+ cursor: nwse-resize;
+ }
+ designer-selection > #top_right {
+ top: -4px;
+ right: -4px;
+ cursor: nesw-resize;
+ }
+ designer-selection > #bottom_left {
+ bottom: -4px;
+ left: -4px;
+ cursor: nesw-resize;
+ }
+ designer-selection > #bottom_right {
+ bottom: -4px;
+ right: -4px;
+ cursor: nwse-resize;
+ }
+ </style>
+ <template>
+ <div id="bounds"></div>
+ <template is="x-repeat" items="{{directions}}">
+ <div class="handle" id$="{{item.name}}"></div>
+ </template>
+ </template>
+ </dom-module>
+
+ <script type="text/javascript">
+ function ResizeDirection(name, x, y) {
+ this.name = name;
+ this.x = x;
+ this.y = y;
+ }
+
+ ResizeDirection.prototype.toString = function() {
+ return 'ResizeDirection(' + this.name + ', ' + this.x + ', ' + this.y + ')';
+ };
imac 2015/02/05 03:18:33 Yay!
justinfagnani 2015/02/05 20:15:54 Done.
+
+ ResizeDirection.prototype.locate = function(rect) {
+ return {
+ x: rect.left + rect.width * this.x,
+ y: rect.top + rect.height * this.y
+ };
+ };
+
+ ResizeDirection.prototype.resizesLeft = function() {
+ return this.x == 0.0;
+ },
+
+ ResizeDirection.prototype.resizesRight = function() {
+ return this.x == 1.0;
+ },
+
+ ResizeDirection.prototype.resizesTop = function() {
+ return this.y == 0.0;
+ },
+
+ ResizeDirection.prototype.resizesBottom = function() {
+ return this.y == 1.0;
+ },
+
+ (function () {
+ var top = ResizeDirection.top = new ResizeDirection('top', 0.5, 0.0);
+ var left = ResizeDirection.left = new ResizeDirection('left', 0.0, 0.5);
+ var bottom = ResizeDirection.bottom = new ResizeDirection('bottom', 0.5, 1.0);
+ var right = ResizeDirection.right = new ResizeDirection('right', 1.0, 0.5);
+ var top_left = ResizeDirection.top_left = new ResizeDirection('top_left', 0.0, 0.0);
+ var top_right = ResizeDirection.top_right = new ResizeDirection('top_right', 1.0, 0.0);
+ var bottom_left = ResizeDirection.bottom_left = new ResizeDirection('bottom_left', 0.0, 1.0);
+ var bottom_right = ResizeDirection.bottom_right = new ResizeDirection('bottom_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
+
+ ResizeDirection.all_directions = [top, left, bottom, right, top_left, top_right, bottom_left, bottom_right];
+ ResizeDirection.width_height = [bottom, right, bottom_right];
+ })();
imac 2015/02/05 03:18:33 consider moving ResizeDirection out to a separate
justinfagnani 2015/02/05 20:15:54 Done.
+
+ Polymer({
+ is: 'designer-selection',
+
+ created: function() {
+ this._onMove = null;
+ this._dragging = false;
+ this._offsetX = null;
+ this._offsetY = null;
+ this._onMouseMove_bound = this._onMouseMove.bind(this);
+ this._onMouseUp_bound = this._onMouseUp.bind(this);
+ this._resizeDirection = null;
+ },
+
+ ready: function() {
+ this.directions = ResizeDirection.all_directions;
+ },
+
+ listeners: {
+ 'mousedown': '_onMouseDown'
+ },
+
+ _onMouseDown: function(e) {
+ if (e.target.id == 'bounds') {
+ this._boundsDown(e);
+ } else {
+ this._handleDown(e);
+ }
+ },
+
+ _onMouseUp: function(e) {
+ this._stopDrag();
+ },
+
+ _onMouseMove: function(e) {
+ 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.
+ var deltaX = e.clientX - this._offsetX;
+ var deltaY = e.clientY - this._offsetY;
+ this._onMove(deltaX, deltaY);
+ }
+ },
+
+ // called for mousedown on the main bounding box div
+ _boundsDown: function(e) {
+ 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
+ this._startDrag(this._boundsMove, e.clientX - this.offsetLeft, e.clientY - this.offsetTop);
+ },
+
+ // [x], and [y] are relative to the offset passed to _startDrag
+ _boundsMove: function(x, y) {
+ var event = new CustomEvent('designer-selection-resize',
+ {detail: {
+ left: x,
+ top: y,
+ width: this.offsetWidth,
+ height: this.offsetHeight}});
+ this.dispatchEvent(event);
+ },
+
+ // called for mousedown on one of the resize handle divs
+ _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.
+ var handle = e.target;
+ var direction = this._resizeDirection = ResizeDirection[handle.id];
+
+ var boundsBounds = this.$.bounds.getBoundingClientRect();
imac 2015/02/05 03:18:33 http://vimeo.com/87712359
justinfagnani 2015/02/05 20:15:54 Acknowledged.
+ var handleBounds = handle.getBoundingClientRect();
+
+ var offsetLeft = direction.resizesLeft()
+ ? 0
+ : 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
+
+ var offsetTop = direction.resizesTop()
+ ? 0
+ : boundsBounds.top + (e.clientY - handleBounds.top);
+
+ this._startDrag(this._handleMove, offsetLeft, offsetTop);
+ },
+
+ _handleMove: function(x, y) {
+ var direction = this._resizeDirection;
+
+ var newWidth =
+ 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
+ direction.resizesRight() ? x :
+ this.offsetWidth;
+
+ var newHeight =
+ direction.resizesTop() ? this.offsetHeight + this.offsetTop - y :
+ direction.resizesBottom() ? y :
+ this.offsetHeight;
+
+ var newLeft = direction.resizesLeft() ? x : this.offsetLeft;
+ var newTop = direction.resizesTop() ? y : this.offsetTop;
+
+ var event = new CustomEvent('designer-selection-resize',
+ {detail: {
+ left: newLeft,
+ top: newTop,
+ width: newWidth,
+ height: newHeight}});
+ this.dispatchEvent(event);
+
+ },
+
+ _startDrag: function(onMove, offsetX, offsetY) {
+ this._dragging = true;
+ this._onMove = onMove;
+ this._offsetX = offsetX;
+ this._offsetY = offsetY;
+ window.addEventListener('mouseup', this._onMouseUp_bound);
+ window.addEventListener('mousemove', this._onMouseMove_bound);
+ },
+
+ _stopDrag: function() {
+ this._dragging = false;
+ this._onMove = null;
+ this._offsetX = null;
+ this._offsetY = null;
+ window.removeEventListener('mouseup', this._onMouseUp_bound);
+ window.removeEventListener('mousemove', this._onMouseMove_bound);
+ this.$.bounds.style.cursor = 'auto';
+ }
+ });
+ </script>
+ </body>
+</html>
« bower.json ('K') | « elements/designer-selection/demo.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698