Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 cr.define('options.browser_options', function() { | 5 cr.define('options.browser_options', function() { |
| 6 const AutocompleteList = options.AutocompleteList; | 6 const AutocompleteList = options.AutocompleteList; |
| 7 const InlineEditableItem = options.InlineEditableItem; | 7 const InlineEditableItem = options.InlineEditableItem; |
| 8 const InlineEditableItemList = options.InlineEditableItemList; | 8 const InlineEditableItemList = options.InlineEditableItemList; |
| 9 | 9 |
| 10 /** | 10 /** |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 | 73 |
| 74 this.addEventListener('commitedit', this.onEditCommitted_); | 74 this.addEventListener('commitedit', this.onEditCommitted_); |
| 75 | 75 |
| 76 var self = this; | 76 var self = this; |
| 77 urlField.addEventListener('focus', function(event) { | 77 urlField.addEventListener('focus', function(event) { |
| 78 self.parentNode.autocompleteList.attachToInput(urlField); | 78 self.parentNode.autocompleteList.attachToInput(urlField); |
| 79 }); | 79 }); |
| 80 urlField.addEventListener('blur', function(event) { | 80 urlField.addEventListener('blur', function(event) { |
| 81 self.parentNode.autocompleteList.detach(); | 81 self.parentNode.autocompleteList.detach(); |
| 82 }); | 82 }); |
| 83 this.draggable = true; | |
| 83 }, | 84 }, |
| 84 | 85 |
| 85 /** @inheritDoc */ | 86 /** @inheritDoc */ |
| 86 get currentInputIsValid() { | 87 get currentInputIsValid() { |
| 87 return this.urlField_.validity.valid; | 88 return this.urlField_.validity.valid; |
| 88 }, | 89 }, |
| 89 | 90 |
| 90 /** @inheritDoc */ | 91 /** @inheritDoc */ |
| 91 get hasBeenEdited() { | 92 get hasBeenEdited() { |
| 92 return this.urlField_.value != this.pageInfo_['url']; | 93 return this.urlField_.value != this.pageInfo_['url']; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 110 | 111 |
| 111 StartupPageList.prototype = { | 112 StartupPageList.prototype = { |
| 112 __proto__: InlineEditableItemList.prototype, | 113 __proto__: InlineEditableItemList.prototype, |
| 113 | 114 |
| 114 /** | 115 /** |
| 115 * An autocomplete suggestion list for URL editing. | 116 * An autocomplete suggestion list for URL editing. |
| 116 * @type {AutocompleteList} | 117 * @type {AutocompleteList} |
| 117 */ | 118 */ |
| 118 autocompleteList: null, | 119 autocompleteList: null, |
| 119 | 120 |
| 121 /** | |
| 122 * The drop position information: "below" or "above". | |
| 123 */ | |
| 124 dropPos: null, | |
|
csilv
2011/06/13 22:57:02
Seems like it might be cleaner to use a boolean va
groby-ooo-7-16
2011/06/13 23:45:27
Following other d&d implementations in language li
csilv
2011/06/14 00:06:12
You won me over w/ your style guide reference. :-
| |
| 125 | |
| 126 /** @inheritDoc */ | |
| 127 decorate: function() { | |
| 128 InlineEditableItemList.prototype.decorate.call(this); | |
| 129 | |
| 130 // Listen to drag and drop events. | |
| 131 this.addEventListener('dragstart', this.handleDragStart_.bind(this)); | |
| 132 this.addEventListener('dragenter', this.handleDragEnter_.bind(this)); | |
| 133 this.addEventListener('dragover', this.handleDragOver_.bind(this)); | |
| 134 this.addEventListener('drop', this.handleDrop_.bind(this)); | |
| 135 this.addEventListener('dragleave', this.handleDragLeave_.bind(this)); | |
| 136 }, | |
| 137 | |
| 120 /** @inheritDoc */ | 138 /** @inheritDoc */ |
| 121 createItem: function(pageInfo) { | 139 createItem: function(pageInfo) { |
| 122 var item = new StartupPageListItem(pageInfo); | 140 var item = new StartupPageListItem(pageInfo); |
| 123 item.urlField_.disabled = this.disabled; | 141 item.urlField_.disabled = this.disabled; |
| 124 return item; | 142 return item; |
| 125 }, | 143 }, |
| 126 | 144 |
| 127 /** @inheritDoc */ | 145 /** @inheritDoc */ |
| 128 deleteItemAtIndex: function(index) { | 146 deleteItemAtIndex: function(index) { |
| 129 chrome.send('removeStartupPages', [String(index)]); | 147 chrome.send('removeStartupPages', [String(index)]); |
| 130 }, | 148 }, |
| 149 | |
| 150 /* | |
| 151 * Computes the target item of drop event. | |
| 152 * @param {Event} e The drop or dragover event. | |
| 153 * @private | |
| 154 */ | |
| 155 getTargetFromDropEvent_ : function(e) { | |
| 156 var target = e.target; | |
| 157 // e.target may be an inner element of the list item | |
| 158 while (target != null && !(target instanceof StartupPageListItem)) { | |
| 159 target = target.parentNode; | |
| 160 } | |
| 161 return target; | |
| 162 }, | |
| 163 | |
| 164 /* | |
| 165 * Handles the dragstart event. | |
| 166 * @param {Event} e The dragstart event. | |
| 167 * @private | |
| 168 */ | |
| 169 handleDragStart_: function(e) { | |
| 170 var target = e.target; | |
| 171 // StartupPageListItem should be the only draggable element type in the | |
| 172 // page but let's make sure. | |
| 173 if (target instanceof StartupPageListItem) { | |
| 174 this.draggedItem = target; | |
| 175 this.draggedItem.editable = false; | |
| 176 e.dataTransfer.effectAllowed = 'move'; | |
| 177 // We need to put some kind of data in the drag or it will be | |
| 178 // ignored. Use the URL in case the user drags to a text field or the | |
| 179 // desktop. | |
| 180 e.dataTransfer.setData('text/plain', target.urlField_.value); | |
| 181 } | |
| 182 }, | |
| 183 | |
| 184 /* | |
| 185 * Handles the dragenter event. | |
| 186 * @param {Event} e The dragenter event. | |
| 187 * @private | |
| 188 */ | |
| 189 handleDragEnter_: function(e) { | |
| 190 e.preventDefault(); | |
| 191 }, | |
| 192 | |
| 193 /* | |
| 194 * Handles the dragover event. | |
| 195 * @param {Event} e The dragover event. | |
| 196 * @private | |
| 197 */ | |
| 198 handleDragOver_: function(e) { | |
| 199 var dropTarget = this.getTargetFromDropEvent_(e); | |
| 200 // Determines whether the drop target is to accept the drop. | |
| 201 // The drop is only successful on another StartupPageListItem. | |
| 202 if (!(dropTarget instanceof StartupPageListItem) || | |
| 203 dropTarget == this.draggedItem || dropTarget.isPlaceholder) { | |
| 204 this.hideDropMarker_(); | |
| 205 return; | |
| 206 } | |
| 207 // Compute the drop postion. Should we move the dragged item to | |
| 208 // below or above the drop target? | |
| 209 var rect = dropTarget.getBoundingClientRect(); | |
| 210 var dy = e.clientY - rect.top; | |
| 211 var yRatio = dy / rect.height; | |
| 212 var dropPos = yRatio <= .5 ? 'above' : 'below'; | |
| 213 this.dropPos = dropPos; | |
| 214 this.showDropMarker_(dropTarget, dropPos); | |
| 215 e.preventDefault(); | |
| 216 }, | |
| 217 | |
| 218 /* | |
| 219 * Handles the drop event. | |
| 220 * @param {Event} e The drop event. | |
| 221 * @private | |
| 222 */ | |
| 223 handleDrop_: function(e) { | |
| 224 var dropTarget = this.getTargetFromDropEvent_(e); | |
| 225 this.hideDropMarker_(); | |
| 226 | |
| 227 // Insert the selection at the new position. | |
| 228 var newIndex = this.dataModel.indexOf(dropTarget.pageInfo_); | |
| 229 if (this.dropPos == 'below') | |
| 230 newIndex += 1; | |
| 231 | |
| 232 var selected = this.selectionModel.selectedIndexes; | |
| 233 var stringized_selected = []; | |
| 234 for (var j = 0; j < selected.length; j++) | |
| 235 stringized_selected.push(String(selected[j])); | |
| 236 | |
| 237 chrome.send('dragDropStartupPage', | |
| 238 [String(newIndex), stringized_selected] ); | |
| 239 }, | |
| 240 | |
| 241 /* | |
| 242 * Handles the dragleave event. | |
| 243 * @param {Event} e The dragleave event | |
| 244 * @private | |
| 245 */ | |
| 246 handleDragLeave_ : function(e) { | |
| 247 this.hideDropMarker_(); | |
| 248 }, | |
| 249 | |
| 250 /* | |
| 251 * Shows and positions the marker to indicate the drop target. | |
| 252 * @param {HTMLElement} target The current target list item of drop | |
| 253 * @param {string} pos 'below' or 'above' | |
| 254 * @private | |
| 255 */ | |
| 256 showDropMarker_ : function(target, pos) { | |
| 257 window.clearTimeout(this.hideDropMarkerTimer_); | |
| 258 var marker = $('startupPagesListDropmarker'); | |
| 259 var rect = target.getBoundingClientRect(); | |
| 260 var markerHeight = 6; | |
| 261 if (pos == 'above') { | |
| 262 marker.style.top = (rect.top - markerHeight/2) + 'px'; | |
| 263 } else { | |
| 264 marker.style.top = (rect.bottom - markerHeight/2) + 'px'; | |
| 265 } | |
| 266 marker.style.width = rect.width + 'px'; | |
| 267 marker.style.left = rect.left + 'px'; | |
| 268 marker.style.display = 'block'; | |
| 269 }, | |
| 270 | |
| 271 /* | |
| 272 * Hides the drop marker. | |
| 273 * @private | |
| 274 */ | |
| 275 hideDropMarker_ : function() { | |
| 276 // Hide the marker in a timeout to reduce flickering as we move between | |
| 277 // valid drop targets. | |
| 278 window.clearTimeout(this.hideDropMarkerTimer_); | |
| 279 this.hideDropMarkerTimer_ = window.setTimeout(function() { | |
| 280 $('startupPagesListDropmarker').style.display = ''; | |
| 281 }, 100); | |
| 282 }, | |
| 131 }; | 283 }; |
| 132 | 284 |
| 133 return { | 285 return { |
| 134 StartupPageList: StartupPageList | 286 StartupPageList: StartupPageList |
| 135 }; | 287 }; |
| 136 }); | 288 }); |
| OLD | NEW |