| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview This implements a splitter element which can be used to resize | 6 * @fileoverview This implements a splitter element which can be used to resize |
| 7 * elements in split panes. | 7 * elements in split panes. |
| 8 * | 8 * |
| 9 * The parent of the splitter should be an hbox (display: -webkit-box) with at | 9 * The parent of the splitter should be an hbox (display: -webkit-box) with at |
| 10 * least one previous element sibling. The splitter controls the width of the | 10 * least one previous element sibling. The splitter controls the width of the |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 | 35 |
| 36 /** | 36 /** |
| 37 * This uses a WebKit bug to work around the same bug. getComputedStyle does | 37 * This uses a WebKit bug to work around the same bug. getComputedStyle does |
| 38 * not take the page zoom into account so it returns the physical pixels | 38 * not take the page zoom into account so it returns the physical pixels |
| 39 * instead of the logical pixel size. | 39 * instead of the logical pixel size. |
| 40 * @param {!Document} doc The document to get the page zoom factor for. | 40 * @param {!Document} doc The document to get the page zoom factor for. |
| 41 * @return {number} The zoom factor of the document. | 41 * @return {number} The zoom factor of the document. |
| 42 */ | 42 */ |
| 43 function getZoomFactor(doc) { | 43 function getZoomFactor(doc) { |
| 44 var dummyElement = doc.createElement('div'); | 44 var dummyElement = doc.createElement('div'); |
| 45 dummyElement.style.cssText = | 45 dummyElement.style.cssText = 'position:absolute;width:100px;height:100px;' + |
| 46 'position:absolute;width:100px;height:100px;top:-1000px;overflow:hidden'; | 46 'top:-1000px;overflow:hidden'; |
| 47 doc.body.appendChild(dummyElement); | 47 doc.body.appendChild(dummyElement); |
| 48 var cs = doc.defaultView.getComputedStyle(dummyElement); | 48 var cs = doc.defaultView.getComputedStyle(dummyElement); |
| 49 var rect = dummyElement.getBoundingClientRect(); | 49 var rect = dummyElement.getBoundingClientRect(); |
| 50 var zoomFactor = parseFloat(cs.width) / 100; | 50 var zoomFactor = parseFloat(cs.width) / 100; |
| 51 doc.body.removeChild(dummyElement); | 51 doc.body.removeChild(dummyElement); |
| 52 return zoomFactor; | 52 return zoomFactor; |
| 53 } | 53 } |
| 54 | 54 |
| 55 /** | 55 /** |
| 56 * Creates a new splitter element. | 56 * Creates a new splitter element. |
| 57 * @param {Object=} opt_propertyBag Optional properties. | 57 * @param {Object=} opt_propertyBag Optional properties. |
| 58 * @constructor | 58 * @constructor |
| 59 * @extends {HTMLDivElement} | 59 * @extends {HTMLDivElement} |
| 60 */ | 60 */ |
| 61 var Splitter = cr.ui.define('div'); | 61 var Splitter = cr.ui.define('div'); |
| 62 | 62 |
| 63 Splitter.prototype = { | 63 Splitter.prototype = { |
| 64 __proto__: HTMLDivElement.prototype, | 64 __proto__: HTMLDivElement.prototype, |
| 65 | 65 |
| 66 /** | 66 /** |
| 67 * Initializes the element. | 67 * Initializes the element. |
| 68 */ | 68 */ |
| 69 decorate: function() { | 69 decorate: function() { |
| 70 this.addEventListener('mousedown', this.handleMouseDown_.bind(this), | 70 this.addEventListener( |
| 71 true); | 71 'mousedown', this.handleMouseDown_.bind(this), true); |
| 72 this.addEventListener('touchstart', this.handleTouchStart_.bind(this), | 72 this.addEventListener( |
| 73 true); | 73 'touchstart', this.handleTouchStart_.bind(this), true); |
| 74 this.resizeNextElement_ = false; | 74 this.resizeNextElement_ = false; |
| 75 }, | 75 }, |
| 76 | 76 |
| 77 /** | 77 /** |
| 78 * @param {boolean} resizeNext True if resize the next element. | 78 * @param {boolean} resizeNext True if resize the next element. |
| 79 * By default, splitter resizes previous (left) element. | 79 * By default, splitter resizes previous (left) element. |
| 80 */ | 80 */ |
| 81 set resizeNextElement(resizeNext) { | 81 set resizeNextElement(resizeNext) { this.resizeNextElement_ = resizeNext; }, |
| 82 this.resizeNextElement_ = resizeNext; | |
| 83 }, | |
| 84 | 82 |
| 85 /** | 83 /** |
| 86 * Starts the dragging of the splitter. Adds listeners for mouse or touch | 84 * Starts the dragging of the splitter. Adds listeners for mouse or touch |
| 87 * events and calls splitter drag start handler. | 85 * events and calls splitter drag start handler. |
| 88 * @param {number} clientX X position of the mouse or touch event that | 86 * @param {number} clientX X position of the mouse or touch event that |
| 89 * started the drag. | 87 * started the drag. |
| 90 * @param {boolean} isTouchEvent True if the drag started by touch event. | 88 * @param {boolean} isTouchEvent True if the drag started by touch event. |
| 91 */ | 89 */ |
| 92 startDrag: function(clientX, isTouchEvent) { | 90 startDrag: function(clientX, isTouchEvent) { |
| 93 if (this.handlers_) { | 91 if (this.handlers_) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 calcDeltaX_: function(deltaX) { | 153 calcDeltaX_: function(deltaX) { |
| 156 return this.resizeNextElement_ ? -deltaX : deltaX; | 154 return this.resizeNextElement_ ? -deltaX : deltaX; |
| 157 }, | 155 }, |
| 158 | 156 |
| 159 /** | 157 /** |
| 160 * Handles the mousedown event which starts the dragging of the splitter. | 158 * Handles the mousedown event which starts the dragging of the splitter. |
| 161 * @param {!Event} e The mouse event. | 159 * @param {!Event} e The mouse event. |
| 162 * @private | 160 * @private |
| 163 */ | 161 */ |
| 164 handleMouseDown_: function(e) { | 162 handleMouseDown_: function(e) { |
| 165 e = /** @type {!MouseEvent} */(e); | 163 e = /** @type {!MouseEvent} */ (e); |
| 166 if (e.button) | 164 if (e.button) |
| 167 return; | 165 return; |
| 168 this.startDrag(e.clientX, false); | 166 this.startDrag(e.clientX, false); |
| 169 // Default action is to start selection and to move focus. | 167 // Default action is to start selection and to move focus. |
| 170 e.preventDefault(); | 168 e.preventDefault(); |
| 171 }, | 169 }, |
| 172 | 170 |
| 173 /** | 171 /** |
| 174 * Handles the touchstart event which starts the dragging of the splitter. | 172 * Handles the touchstart event which starts the dragging of the splitter. |
| 175 * @param {!Event} e The touch event. | 173 * @param {!Event} e The touch event. |
| 176 * @private | 174 * @private |
| 177 */ | 175 */ |
| 178 handleTouchStart_: function(e) { | 176 handleTouchStart_: function(e) { |
| 179 e = /** @type {!TouchEvent} */(e); | 177 e = /** @type {!TouchEvent} */ (e); |
| 180 if (e.touches.length == 1) { | 178 if (e.touches.length == 1) { |
| 181 this.startDrag(e.touches[0].clientX, true); | 179 this.startDrag(e.touches[0].clientX, true); |
| 182 e.preventDefault(); | 180 e.preventDefault(); |
| 183 } | 181 } |
| 184 }, | 182 }, |
| 185 | 183 |
| 186 /** | 184 /** |
| 187 * Handles the mousemove event which moves the splitter as the user moves | 185 * Handles the mousemove event which moves the splitter as the user moves |
| 188 * the mouse. | 186 * the mouse. |
| 189 * @param {!MouseEvent} e The mouse event. | 187 * @param {!MouseEvent} e The mouse event. |
| 190 * @private | 188 * @private |
| 191 */ | 189 */ |
| 192 handleMouseMove_: function(e) { | 190 handleMouseMove_: function(e) { this.handleMove_(e.clientX); }, |
| 193 this.handleMove_(e.clientX); | |
| 194 }, | |
| 195 | 191 |
| 196 /** | 192 /** |
| 197 * Handles the touch move event. | 193 * Handles the touch move event. |
| 198 * @param {!TouchEvent} e The touch event. | 194 * @param {!TouchEvent} e The touch event. |
| 199 */ | 195 */ |
| 200 handleTouchMove_: function(e) { | 196 handleTouchMove_: function(e) { |
| 201 if (e.touches.length == 1) | 197 if (e.touches.length == 1) |
| 202 this.handleMove_(e.touches[0].clientX); | 198 this.handleMove_(e.touches[0].clientX); |
| 203 }, | 199 }, |
| 204 | 200 |
| 205 /** | 201 /** |
| 206 * Common part of handling mousemove and touchmove. Calls splitter drag | 202 * Common part of handling mousemove and touchmove. Calls splitter drag |
| 207 * move handler. | 203 * move handler. |
| 208 * @param {number} clientX X position of the mouse or touch event. | 204 * @param {number} clientX X position of the mouse or touch event. |
| 209 * @private | 205 * @private |
| 210 */ | 206 */ |
| 211 handleMove_: function(clientX) { | 207 handleMove_: function(clientX) { |
| 212 var rtl = this.ownerDocument.defaultView.getComputedStyle(this). | 208 var rtl = |
| 213 direction == 'rtl'; | 209 this.ownerDocument.defaultView.getComputedStyle(this).direction == |
| 210 'rtl'; |
| 214 var dirMultiplier = rtl ? -1 : 1; | 211 var dirMultiplier = rtl ? -1 : 1; |
| 215 var deltaX = dirMultiplier * (clientX - this.startX_); | 212 var deltaX = dirMultiplier * (clientX - this.startX_); |
| 216 this.handleSplitterDragMove(deltaX); | 213 this.handleSplitterDragMove(deltaX); |
| 217 }, | 214 }, |
| 218 | 215 |
| 219 /** | 216 /** |
| 220 * Handles the mouse up event which ends the dragging of the splitter. | 217 * Handles the mouse up event which ends the dragging of the splitter. |
| 221 * @param {!MouseEvent} e The mouse event. | 218 * @param {!MouseEvent} e The mouse event. |
| 222 * @private | 219 * @private |
| 223 */ | 220 */ |
| 224 handleMouseUp_: function(e) { | 221 handleMouseUp_: function(e) { this.endDrag_(); }, |
| 225 this.endDrag_(); | |
| 226 }, | |
| 227 | 222 |
| 228 /** | 223 /** |
| 229 * Handles start of the splitter dragging. Saves current width of the | 224 * Handles start of the splitter dragging. Saves current width of the |
| 230 * element being resized. | 225 * element being resized. |
| 231 * @protected | 226 * @protected |
| 232 */ | 227 */ |
| 233 handleSplitterDragStart: function() { | 228 handleSplitterDragStart: function() { |
| 234 // Use the computed width style as the base so that we can ignore what | 229 // Use the computed width style as the base so that we can ignore what |
| 235 // box sizing the element has. | 230 // box sizing the element has. |
| 236 var targetElement = this.getResizeTarget_(); | 231 var targetElement = this.getResizeTarget_(); |
| 237 var doc = targetElement.ownerDocument; | 232 var doc = targetElement.ownerDocument; |
| 238 this.startWidth_ = parseFloat( | 233 this.startWidth_ = |
| 239 doc.defaultView.getComputedStyle(targetElement).width); | 234 parseFloat(doc.defaultView.getComputedStyle(targetElement).width); |
| 240 }, | 235 }, |
| 241 | 236 |
| 242 /** | 237 /** |
| 243 * Handles splitter moves. Updates width of the element being resized. | 238 * Handles splitter moves. Updates width of the element being resized. |
| 244 * @param {number} deltaX The change of splitter horizontal position. | 239 * @param {number} deltaX The change of splitter horizontal position. |
| 245 * @protected | 240 * @protected |
| 246 */ | 241 */ |
| 247 handleSplitterDragMove: function(deltaX) { | 242 handleSplitterDragMove: function(deltaX) { |
| 248 var targetElement = this.getResizeTarget_(); | 243 var targetElement = this.getResizeTarget_(); |
| 249 var newWidth = this.startWidth_ + this.calcDeltaX_(deltaX); | 244 var newWidth = this.startWidth_ + this.calcDeltaX_(deltaX); |
| 250 targetElement.style.width = newWidth + 'px'; | 245 targetElement.style.width = newWidth + 'px'; |
| 251 }, | 246 }, |
| 252 | 247 |
| 253 /** | 248 /** |
| 254 * Handles end of the splitter dragging. This fires a 'resize' event if the | 249 * Handles end of the splitter dragging. This fires a 'resize' event if the |
| 255 * size changed. | 250 * size changed. |
| 256 * @protected | 251 * @protected |
| 257 */ | 252 */ |
| 258 handleSplitterDragEnd: function() { | 253 handleSplitterDragEnd: function() { |
| 259 // Check if the size changed. | 254 // Check if the size changed. |
| 260 var targetElement = this.getResizeTarget_(); | 255 var targetElement = this.getResizeTarget_(); |
| 261 var doc = targetElement.ownerDocument; | 256 var doc = targetElement.ownerDocument; |
| 262 var computedWidth = parseFloat( | 257 var computedWidth = |
| 263 doc.defaultView.getComputedStyle(targetElement).width); | 258 parseFloat(doc.defaultView.getComputedStyle(targetElement).width); |
| 264 if (this.startWidth_ != computedWidth) | 259 if (this.startWidth_ != computedWidth) |
| 265 cr.dispatchSimpleEvent(this, 'resize'); | 260 cr.dispatchSimpleEvent(this, 'resize'); |
| 266 }, | 261 }, |
| 267 }; | 262 }; |
| 268 | 263 |
| 269 return { | 264 return {Splitter: Splitter}; |
| 270 Splitter: Splitter | |
| 271 }; | |
| 272 }); | 265 }); |
| OLD | NEW |