1 <!DOCTYPE html> 2 <!-- 3 Copyright (c) 2014 The Chromium Authors. All rights reserved. 4 Use of this source code is governed by a BSD-style license that can be 5 found in the LICENSE file. 6 --> 7 8 <link rel="stylesheet" href="/ui/base/drag_handle.css"> 9 10 <link rel="import" href="/ui/base/ui.html"> 11 12 <script> 13 'use strict'; 14 15 tr.exportTo('tr.ui.b', function() { 16 17 /** 18 * Detects when user clicks handle determines new height of container based 19 * on user's vertical mouse move and resizes the target. 20 * @constructor 21 * @extends {HTMLDivElement} 22 * You will need to set target to be the draggable element 23 */ 24 var DragHandle = tr.ui.b.define('x-drag-handle'); 25 26 DragHandle.prototype = { 27 __proto__: HTMLDivElement.prototype, 28 29 decorate: function() { 30 this.lastMousePos_ = 0; 31 this.onMouseMove_ = this.onMouseMove_.bind(this); 32 this.onMouseUp_ = this.onMouseUp_.bind(this); 33 this.addEventListener('mousedown', this.onMouseDown_); 34 this.target_ = undefined; 35 this.horizontal = true; 36 this.observer_ = new WebKitMutationObserver( 37 this.didTargetMutate_.bind(this)); 38 this.targetSizesByModeKey_ = {}; 39 }, 40 41 get modeKey_() { 42 return this.target_.className == '' ? '.' : this.target_.className; 43 }, 44 45 get target() { 46 return this.target_; 47 }, 48 49 set target(target) { 50 this.observer_.disconnect(); 51 this.target_ = target; 52 if (!this.target_) 53 return; 54 this.observer_.observe(this.target_, { 55 attributes: true, 56 attributeFilter: ['class'] 57 }); 58 }, 59 60 get horizontal() { 61 return this.horizontal_; 62 }, 63 64 set horizontal(h) { 65 this.horizontal_ = h; 66 if (this.horizontal_) 67 this.className = 'horizontal-drag-handle'; 68 else 69 this.className = 'vertical-drag-handle'; 70 }, 71 72 get vertical() { 73 return !this.horizontal_; 74 }, 75 76 set vertical(v) { 77 this.horizontal = !v; 78 }, 79 80 forceMutationObserverFlush_: function() { 81 var records = this.observer_.takeRecords(); 82 if (records.length) 83 this.didTargetMutate_(records); 84 }, 85 86 didTargetMutate_: function(e) { 87 var modeSize = this.targetSizesByModeKey_[this.modeKey_]; 88 if (modeSize !== undefined) { 89 this.setTargetSize_(modeSize); 90 return; 91 } 92 93 // If we hadn't previously sized the target, then just remove any manual 94 // sizing that we applied. 95 this.target_.style[this.targetStyleKey_] = ''; 96 }, 97 98 get targetStyleKey_() { 99 return this.horizontal_ ? 'height' : 'width'; 100 }, 101 102 getTargetSize_: function() { 103 // If style is not set, start off with computed height. 104 var targetStyleKey = this.targetStyleKey_; 105 if (!this.target_.style[targetStyleKey]) { 106 this.target_.style[targetStyleKey] = 107 window.getComputedStyle(this.target_)[targetStyleKey]; 108 } 109 var size = parseInt(this.target_.style[targetStyleKey]); 110 this.targetSizesByModeKey_[this.modeKey_] = size; 111 return size; 112 }, 113 114 setTargetSize_: function(s) { 115 this.target_.style[this.targetStyleKey_] = s + 'px'; 116 this.targetSizesByModeKey_[this.modeKey_] = s; 117 }, 118 119 applyDelta_: function(delta) { 120 // Apply new size to the container. 121 var curSize = this.getTargetSize_(); 122 var newSize; 123 if (this.target_ === this.nextElementSibling) { 124 newSize = curSize + delta; 125 } else { 126 newSize = curSize - delta; 127 } 128 this.setTargetSize_(newSize); 129 }, 130 131 onMouseMove_: function(e) { 132 // Compute the difference in height position. 133 var curMousePos = this.horizontal_ ? e.clientY : e.clientX; 134 var delta = this.lastMousePos_ - curMousePos; 135 136 this.applyDelta_(delta); 137 138 this.lastMousePos_ = curMousePos; 139 e.preventDefault(); 140 return true; 141 }, 142 143 onMouseDown_: function(e) { 144 if (!this.target_) 145 return; 146 this.forceMutationObserverFlush_(); 147 this.lastMousePos_ = this.horizontal_ ? e.clientY : e.clientX; 148 document.addEventListener('mousemove', this.onMouseMove_); 149 document.addEventListener('mouseup', this.onMouseUp_); 150 e.preventDefault(); 151 return true; 152 }, 153 154 onMouseUp_: function(e) { 155 document.removeEventListener('mousemove', this.onMouseMove_); 156 document.removeEventListener('mouseup', this.onMouseUp_); 157 e.preventDefault(); 158 } 159 }; 160 161 return { 162 DragHandle: DragHandle 163 }; 164 }); 165 </script> 166