Chromium Code Reviews| Index: chrome/browser/resources/options/browser_options_startup_page_list.js |
| diff --git a/chrome/browser/resources/options/browser_options_startup_page_list.js b/chrome/browser/resources/options/browser_options_startup_page_list.js |
| index 9ad476683ab254d9a588bb73c550d41fd675e78b..84f55168058609d3d484b9e8264bca779ecd3a51 100644 |
| --- a/chrome/browser/resources/options/browser_options_startup_page_list.js |
| +++ b/chrome/browser/resources/options/browser_options_startup_page_list.js |
| @@ -80,6 +80,7 @@ cr.define('options.browser_options', function() { |
| urlField.addEventListener('blur', function(event) { |
| self.parentNode.autocompleteList.detach(); |
| }); |
| + this.draggable = true; |
| }, |
| /** @inheritDoc */ |
| @@ -117,6 +118,23 @@ cr.define('options.browser_options', function() { |
| */ |
| autocompleteList: null, |
| + /** |
| + * The drop position information: "below" or "above". |
| + */ |
| + 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. :-
|
| + |
| + /** @inheritDoc */ |
| + decorate: function() { |
| + InlineEditableItemList.prototype.decorate.call(this); |
| + |
| + // Listen to drag and drop events. |
| + this.addEventListener('dragstart', this.handleDragStart_.bind(this)); |
| + this.addEventListener('dragenter', this.handleDragEnter_.bind(this)); |
| + this.addEventListener('dragover', this.handleDragOver_.bind(this)); |
| + this.addEventListener('drop', this.handleDrop_.bind(this)); |
| + this.addEventListener('dragleave', this.handleDragLeave_.bind(this)); |
| + }, |
| + |
| /** @inheritDoc */ |
| createItem: function(pageInfo) { |
| var item = new StartupPageListItem(pageInfo); |
| @@ -128,6 +146,140 @@ cr.define('options.browser_options', function() { |
| deleteItemAtIndex: function(index) { |
| chrome.send('removeStartupPages', [String(index)]); |
| }, |
| + |
| + /* |
| + * Computes the target item of drop event. |
| + * @param {Event} e The drop or dragover event. |
| + * @private |
| + */ |
| + getTargetFromDropEvent_ : function(e) { |
| + var target = e.target; |
| + // e.target may be an inner element of the list item |
| + while (target != null && !(target instanceof StartupPageListItem)) { |
| + target = target.parentNode; |
| + } |
| + return target; |
| + }, |
| + |
| + /* |
| + * Handles the dragstart event. |
| + * @param {Event} e The dragstart event. |
| + * @private |
| + */ |
| + handleDragStart_: function(e) { |
| + var target = e.target; |
| + // StartupPageListItem should be the only draggable element type in the |
| + // page but let's make sure. |
| + if (target instanceof StartupPageListItem) { |
| + this.draggedItem = target; |
| + this.draggedItem.editable = false; |
| + e.dataTransfer.effectAllowed = 'move'; |
| + // We need to put some kind of data in the drag or it will be |
| + // ignored. Use the URL in case the user drags to a text field or the |
| + // desktop. |
| + e.dataTransfer.setData('text/plain', target.urlField_.value); |
| + } |
| + }, |
| + |
| + /* |
| + * Handles the dragenter event. |
| + * @param {Event} e The dragenter event. |
| + * @private |
| + */ |
| + handleDragEnter_: function(e) { |
| + e.preventDefault(); |
| + }, |
| + |
| + /* |
| + * Handles the dragover event. |
| + * @param {Event} e The dragover event. |
| + * @private |
| + */ |
| + handleDragOver_: function(e) { |
| + var dropTarget = this.getTargetFromDropEvent_(e); |
| + // Determines whether the drop target is to accept the drop. |
| + // The drop is only successful on another StartupPageListItem. |
| + if (!(dropTarget instanceof StartupPageListItem) || |
| + dropTarget == this.draggedItem || dropTarget.isPlaceholder) { |
| + this.hideDropMarker_(); |
| + return; |
| + } |
| + // Compute the drop postion. Should we move the dragged item to |
| + // below or above the drop target? |
| + var rect = dropTarget.getBoundingClientRect(); |
| + var dy = e.clientY - rect.top; |
| + var yRatio = dy / rect.height; |
| + var dropPos = yRatio <= .5 ? 'above' : 'below'; |
| + this.dropPos = dropPos; |
| + this.showDropMarker_(dropTarget, dropPos); |
| + e.preventDefault(); |
| + }, |
| + |
| + /* |
| + * Handles the drop event. |
| + * @param {Event} e The drop event. |
| + * @private |
| + */ |
| + handleDrop_: function(e) { |
| + var dropTarget = this.getTargetFromDropEvent_(e); |
| + this.hideDropMarker_(); |
| + |
| + // Insert the selection at the new position. |
| + var newIndex = this.dataModel.indexOf(dropTarget.pageInfo_); |
| + if (this.dropPos == 'below') |
| + newIndex += 1; |
| + |
| + var selected = this.selectionModel.selectedIndexes; |
| + var stringized_selected = []; |
| + for (var j = 0; j < selected.length; j++) |
| + stringized_selected.push(String(selected[j])); |
| + |
| + chrome.send('dragDropStartupPage', |
| + [String(newIndex), stringized_selected] ); |
| + }, |
| + |
| + /* |
| + * Handles the dragleave event. |
| + * @param {Event} e The dragleave event |
| + * @private |
| + */ |
| + handleDragLeave_ : function(e) { |
| + this.hideDropMarker_(); |
| + }, |
| + |
| + /* |
| + * Shows and positions the marker to indicate the drop target. |
| + * @param {HTMLElement} target The current target list item of drop |
| + * @param {string} pos 'below' or 'above' |
| + * @private |
| + */ |
| + showDropMarker_ : function(target, pos) { |
| + window.clearTimeout(this.hideDropMarkerTimer_); |
| + var marker = $('startupPagesListDropmarker'); |
| + var rect = target.getBoundingClientRect(); |
| + var markerHeight = 6; |
| + if (pos == 'above') { |
| + marker.style.top = (rect.top - markerHeight/2) + 'px'; |
| + } else { |
| + marker.style.top = (rect.bottom - markerHeight/2) + 'px'; |
| + } |
| + marker.style.width = rect.width + 'px'; |
| + marker.style.left = rect.left + 'px'; |
| + marker.style.display = 'block'; |
| + }, |
| + |
| + /* |
| + * Hides the drop marker. |
| + * @private |
| + */ |
| + hideDropMarker_ : function() { |
| + // Hide the marker in a timeout to reduce flickering as we move between |
| + // valid drop targets. |
| + window.clearTimeout(this.hideDropMarkerTimer_); |
| + this.hideDropMarkerTimer_ = window.setTimeout(function() { |
| + $('startupPagesListDropmarker').style.display = ''; |
| + }, 100); |
| + }, |
| }; |
| return { |