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 |