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 * Global (placed in the window object) variable name to hold internal | 6 * Global (placed in the window object) variable name to hold internal |
7 * file dragging information. Needed to show visual feedback while dragging | 7 * file dragging information. Needed to show visual feedback while dragging |
8 * since DataTransfer object is in protected state. Reachable from other | 8 * since DataTransfer object is in protected state. Reachable from other |
9 * file manager instances. | 9 * file manager instances. |
10 */ | 10 */ |
(...skipping 18 matching lines...) Expand all Loading... |
29 /** | 29 /** |
30 * DOM element to represent selected file in drag operation. Used if only | 30 * DOM element to represent selected file in drag operation. Used if only |
31 * one element is selected. | 31 * one element is selected. |
32 * @type {HTMLElement} | 32 * @type {HTMLElement} |
33 * @private | 33 * @private |
34 */ | 34 */ |
35 this.preloadedThumbnailImageNode_ = null; | 35 this.preloadedThumbnailImageNode_ = null; |
36 | 36 |
37 /** | 37 /** |
38 * File objects for seletced files. | 38 * File objects for seletced files. |
| 39 * |
39 * @type {Array.<File>} | 40 * @type {Array.<File>} |
40 * @private | 41 * @private |
41 */ | 42 */ |
42 this.selectedFileObjects_ = []; | 43 this.selectedFileObjects_ = []; |
43 } | 44 } |
44 | 45 |
45 FileTransferController.prototype = { | 46 FileTransferController.prototype = { |
46 __proto__: cr.EventTarget.prototype, | 47 __proto__: cr.EventTarget.prototype, |
47 | 48 |
48 /** | 49 /** |
| 50 * @this {FileTransferController} |
49 * @param {cr.ui.List} list Items in the list will be draggable. | 51 * @param {cr.ui.List} list Items in the list will be draggable. |
50 */ | 52 */ |
51 attachDragSource: function(list) { | 53 attachDragSource: function(list) { |
52 list.style.webkitUserDrag = 'element'; | 54 list.style.webkitUserDrag = 'element'; |
53 list.addEventListener('dragstart', this.onDragStart_.bind(this, list)); | 55 list.addEventListener('dragstart', this.onDragStart_.bind(this, list)); |
54 list.addEventListener('dragend', this.onDragEnd_.bind(this, list)); | 56 list.addEventListener('dragend', this.onDragEnd_.bind(this, list)); |
55 }, | 57 }, |
56 | 58 |
57 /** | 59 /** |
| 60 * @this {FileTransferController} |
58 * @param {cr.ui.List} list List itself and its directory items will could | 61 * @param {cr.ui.List} list List itself and its directory items will could |
59 * be drop target. | 62 * be drop target. |
60 * @param {boolean=} opt_onlyIntoDirectories If true only directory list | 63 * @param {boolean=} opt_onlyIntoDirectories If true only directory list |
61 * items could be drop targets. Otherwise any other place of the list | 64 * items could be drop targets. Otherwise any other place of the list |
62 * accetps files (putting it into the current directory). | 65 * accetps files (putting it into the current directory). |
63 */ | 66 */ |
64 attachDropTarget: function(list, opt_onlyIntoDirectories) { | 67 attachDropTarget: function(list, opt_onlyIntoDirectories) { |
65 list.addEventListener('dragover', this.onDragOver_.bind(this, | 68 list.addEventListener('dragover', this.onDragOver_.bind(this, |
66 !!opt_onlyIntoDirectories, list)); | 69 !!opt_onlyIntoDirectories, list)); |
67 list.addEventListener('dragenter', this.onDragEnterList_.bind(this, list)); | 70 list.addEventListener('dragenter', this.onDragEnterList_.bind(this, list)); |
68 list.addEventListener('dragleave', this.onDragLeave_.bind(this, list)); | 71 list.addEventListener('dragleave', this.onDragLeave_.bind(this, list)); |
69 list.addEventListener('drop', this.onDrop_.bind(this, | 72 list.addEventListener('drop', this.onDrop_.bind(this, |
70 !!opt_onlyIntoDirectories)); | 73 !!opt_onlyIntoDirectories)); |
71 }, | 74 }, |
72 | 75 |
| 76 /** |
| 77 * @this {FileTransferController} |
| 78 */ |
73 attachBreadcrumbsDropTarget: function(breadcrumbsController) { | 79 attachBreadcrumbsDropTarget: function(breadcrumbsController) { |
74 var container = breadcrumbsController.getContainer(); | 80 var container = breadcrumbsController.getContainer(); |
75 container.addEventListener('dragover', | 81 container.addEventListener('dragover', |
76 this.onDragOver_.bind(this, true, null)); | 82 this.onDragOver_.bind(this, true, null)); |
77 container.addEventListener('dragenter', | 83 container.addEventListener('dragenter', |
78 this.onDragEnterBreadcrumbs_.bind(this, breadcrumbsController)); | 84 this.onDragEnterBreadcrumbs_.bind(this, breadcrumbsController)); |
79 container.addEventListener('dragleave', | 85 container.addEventListener('dragleave', |
80 this.onDragLeave_.bind(this, null)); | 86 this.onDragLeave_.bind(this, null)); |
81 container.addEventListener('drop', this.onDrop_.bind(this, true)); | 87 container.addEventListener('drop', this.onDrop_.bind(this, true)); |
82 }, | 88 }, |
83 | 89 |
84 /** | 90 /** |
85 * Attach handlers of copy, cut and paste operations to the document. | 91 * Attach handlers of copy, cut and paste operations to the document. |
| 92 * |
| 93 * @this {FileTransferController} |
86 */ | 94 */ |
87 attachCopyPasteHandlers: function() { | 95 attachCopyPasteHandlers: function() { |
88 this.document_.addEventListener('beforecopy', | 96 this.document_.addEventListener('beforecopy', |
89 this.onBeforeCopy_.bind(this)); | 97 this.onBeforeCopy_.bind(this)); |
90 this.document_.addEventListener('copy', | 98 this.document_.addEventListener('copy', |
91 this.onCopy_.bind(this)); | 99 this.onCopy_.bind(this)); |
92 this.document_.addEventListener('beforecut', | 100 this.document_.addEventListener('beforecut', |
93 this.onBeforeCut_.bind(this)); | 101 this.onBeforeCut_.bind(this)); |
94 this.document_.addEventListener('cut', | 102 this.document_.addEventListener('cut', |
95 this.onCut_.bind(this)); | 103 this.onCut_.bind(this)); |
96 this.document_.addEventListener('beforepaste', | 104 this.document_.addEventListener('beforepaste', |
97 this.onBeforePaste_.bind(this)); | 105 this.onBeforePaste_.bind(this)); |
98 this.document_.addEventListener('paste', | 106 this.document_.addEventListener('paste', |
99 this.onPaste_.bind(this)); | 107 this.onPaste_.bind(this)); |
100 this.copyCommand_ = this.document_.querySelector('command#copy'); | 108 this.copyCommand_ = this.document_.querySelector('command#copy'); |
101 }, | 109 }, |
102 | 110 |
103 /** | 111 /** |
104 * Write the current selection to system clipboard. | 112 * Write the current selection to system clipboard. |
105 * | 113 * |
| 114 * @this {FileTransferController} |
106 * @param {DataTransfer} dataTransfer DataTransfer from the event. | 115 * @param {DataTransfer} dataTransfer DataTransfer from the event. |
107 * @param {string} effectAllowed Value must be valid for the | 116 * @param {string} effectAllowed Value must be valid for the |
108 * |dataTransfer.effectAllowed| property ('move', 'copy', 'copyMove'). | 117 * |dataTransfer.effectAllowed| property ('move', 'copy', 'copyMove'). |
109 */ | 118 */ |
110 cutOrCopy_: function(dataTransfer, effectAllowed) { | 119 cutOrCopy_: function(dataTransfer, effectAllowed) { |
111 var directories = []; | 120 var directories = []; |
112 var files = []; | 121 var files = []; |
113 var entries = this.selectedEntries_; | 122 var entries = this.selectedEntries_; |
114 for (var i = 0; i < entries.length; i++) { | 123 for (var i = 0; i < entries.length; i++) { |
115 (entries[i].isDirectory ? directories : files).push(entries[i].fullPath); | 124 (entries[i].isDirectory ? directories : files).push(entries[i].fullPath); |
(...skipping 10 matching lines...) Expand all Loading... |
126 dataTransfer.effectAllowed = effectAllowed; | 135 dataTransfer.effectAllowed = effectAllowed; |
127 dataTransfer.setData('fs/effectallowed', effectAllowed); | 136 dataTransfer.setData('fs/effectallowed', effectAllowed); |
128 | 137 |
129 for (var i = 0; i < this.selectedFileObjects_.length; i++) { | 138 for (var i = 0; i < this.selectedFileObjects_.length; i++) { |
130 dataTransfer.items.add(this.selectedFileObjects_[i]); | 139 dataTransfer.items.add(this.selectedFileObjects_[i]); |
131 } | 140 } |
132 }, | 141 }, |
133 | 142 |
134 /** | 143 /** |
135 * Extracts source root from the |dataTransfer| object. | 144 * Extracts source root from the |dataTransfer| object. |
| 145 * |
| 146 * @this {FileTransferController} |
136 * @param {DataTransfer} dataTransfer DataTransfer object from the event. | 147 * @param {DataTransfer} dataTransfer DataTransfer object from the event. |
137 * @return {string} Path or empty string (if unknown). | 148 * @return {string} Path or empty string (if unknown). |
138 */ | 149 */ |
139 getSourceRoot_: function(dataTransfer) { | 150 getSourceRoot_: function(dataTransfer) { |
140 var sourceDir = dataTransfer.getData('fs/sourceDir'); | 151 var sourceDir = dataTransfer.getData('fs/sourceDir'); |
141 if (sourceDir) | 152 if (sourceDir) |
142 return PathUtil.getRootPath(sourceDir); | 153 return PathUtil.getRootPath(sourceDir); |
143 | 154 |
144 // For drive search, sourceDir will be set to null, so we should double | 155 // For drive search, sourceDir will be set to null, so we should double |
145 // check that we are not on drive. | 156 // check that we are not on drive. |
(...skipping 10 matching lines...) Expand all Loading... |
156 if (views[i][DRAG_AND_DROP_GLOBAL_DATA]) | 167 if (views[i][DRAG_AND_DROP_GLOBAL_DATA]) |
157 return views[i][DRAG_AND_DROP_GLOBAL_DATA].sourceRoot; | 168 return views[i][DRAG_AND_DROP_GLOBAL_DATA].sourceRoot; |
158 } | 169 } |
159 | 170 |
160 // Unknown source. | 171 // Unknown source. |
161 return ''; | 172 return ''; |
162 }, | 173 }, |
163 | 174 |
164 /** | 175 /** |
165 * Queue up a file copy operation based on the current system clipboard. | 176 * Queue up a file copy operation based on the current system clipboard. |
| 177 * |
| 178 * @this {FileTransferController} |
166 * @param {DataTransfer} dataTransfer System data transfer object. | 179 * @param {DataTransfer} dataTransfer System data transfer object. |
167 * @param {string=} opt_destinationPath Paste destination. | 180 * @param {string=} opt_destinationPath Paste destination. |
168 * @param {string=} opt_effect Desired drop/paste effect. Could be | 181 * @param {string=} opt_effect Desired drop/paste effect. Could be |
169 * 'move'|'copy' (default is copy). Ignored if conflicts with | 182 * 'move'|'copy' (default is copy). Ignored if conflicts with |
170 * |dataTransfer.effectAllowed|. | 183 * |dataTransfer.effectAllowed|. |
171 * @return {string} Either "copy" or "move". | 184 * @return {string} Either "copy" or "move". |
172 */ | 185 */ |
173 paste: function(dataTransfer, opt_destinationPath, opt_effect) { | 186 paste: function(dataTransfer, opt_destinationPath, opt_effect) { |
174 var destinationPath = opt_destinationPath || | 187 var destinationPath = opt_destinationPath || |
175 this.directoryModel_.getCurrentDirPath(); | 188 this.directoryModel_.getCurrentDirPath(); |
(...skipping 21 matching lines...) Expand all Loading... |
197 targetOnDrive); | 210 targetOnDrive); |
198 } else { | 211 } else { |
199 console.log('Ignore move into the same folder'); | 212 console.log('Ignore move into the same folder'); |
200 } | 213 } |
201 | 214 |
202 return toMove ? 'move' : 'copy'; | 215 return toMove ? 'move' : 'copy'; |
203 }, | 216 }, |
204 | 217 |
205 /** | 218 /** |
206 * Preloads an image thumbnail for the specified file entry. | 219 * Preloads an image thumbnail for the specified file entry. |
| 220 * |
| 221 * @this {FileTransferController} |
207 * @param {Entry} entry Entry to preload a thumbnail for. | 222 * @param {Entry} entry Entry to preload a thumbnail for. |
208 */ | 223 */ |
209 preloadThumbnailImage_: function(entry) { | 224 preloadThumbnailImage_: function(entry) { |
210 var imageUrl = entry.toURL(); | 225 var imageUrl = entry.toURL(); |
211 var metadataTypes = 'thumbnail|filesystem'; | 226 var metadataTypes = 'thumbnail|filesystem'; |
212 this.preloadedThumbnailImageNode_ = this.document_.createElement('div'); | 227 this.preloadedThumbnailImageNode_ = this.document_.createElement('div'); |
213 this.preloadedThumbnailImageNode_.className = 'img-container'; | 228 this.preloadedThumbnailImageNode_.className = 'img-container'; |
214 this.directoryModel_.getMetadataCache().get( | 229 this.directoryModel_.getMetadataCache().get( |
215 imageUrl, | 230 imageUrl, |
216 metadataTypes, | 231 metadataTypes, |
217 function(metadata) { | 232 function(metadata) { |
218 new ThumbnailLoader(imageUrl, | 233 new ThumbnailLoader(imageUrl, |
219 ThumbnailLoader.LoaderType.IMAGE, | 234 ThumbnailLoader.LoaderType.IMAGE, |
220 metadata). | 235 metadata). |
221 load(this.preloadedThumbnailImageNode_, | 236 load(this.preloadedThumbnailImageNode_, |
222 ThumbnailLoader.FillMode.FILL); | 237 ThumbnailLoader.FillMode.FILL); |
223 }.bind(this)); | 238 }.bind(this)); |
224 }, | 239 }, |
225 | 240 |
226 /** | 241 /** |
227 * Renders a drag-and-drop thumbnail. | 242 * Renders a drag-and-drop thumbnail. |
| 243 * |
| 244 * @this {FileTransferController} |
228 * @return {HTMLElement} Element containing the thumbnail. | 245 * @return {HTMLElement} Element containing the thumbnail. |
229 */ | 246 */ |
230 renderThumbnail_: function() { | 247 renderThumbnail_: function() { |
231 var length = this.selectedEntries_.length; | 248 var length = this.selectedEntries_.length; |
232 | 249 |
233 var container = this.document_.querySelector('#drag-container'); | 250 var container = this.document_.querySelector('#drag-container'); |
234 var contents = this.document_.createElement('div'); | 251 var contents = this.document_.createElement('div'); |
235 contents.className = 'drag-contents'; | 252 contents.className = 'drag-contents'; |
236 container.appendChild(contents); | 253 container.appendChild(contents); |
237 | 254 |
(...skipping 24 matching lines...) Expand all Loading... |
262 icon.className = 'detail-icon'; | 279 icon.className = 'detail-icon'; |
263 icon.setAttribute('file-type-icon', FileType.getIcon(entry)); | 280 icon.setAttribute('file-type-icon', FileType.getIcon(entry)); |
264 contents.appendChild(icon); | 281 contents.appendChild(icon); |
265 var label = this.document_.createElement('div'); | 282 var label = this.document_.createElement('div'); |
266 label.className = 'label'; | 283 label.className = 'label'; |
267 label.textContent = entry.name; | 284 label.textContent = entry.name; |
268 contents.appendChild(label); | 285 contents.appendChild(label); |
269 return container; | 286 return container; |
270 }, | 287 }, |
271 | 288 |
| 289 /** |
| 290 * @this {FileTransferController} |
| 291 */ |
272 onDragStart_: function(list, event) { | 292 onDragStart_: function(list, event) { |
273 // Nothing selected. | 293 // Nothing selected. |
274 if (!this.selectedEntries_.length) { | 294 if (!this.selectedEntries_.length) { |
275 event.preventDefault(); | 295 event.preventDefault(); |
276 return; | 296 return; |
277 } | 297 } |
278 | 298 |
279 var dt = event.dataTransfer; | 299 var dt = event.dataTransfer; |
280 var dragThumbnail = this.renderThumbnail_(); | 300 var dragThumbnail = this.renderThumbnail_(); |
281 dt.setDragImage(dragThumbnail, 1000, 1000); | 301 dt.setDragImage(dragThumbnail, 1000, 1000); |
282 | 302 |
283 if (this.canCopyOrDrag_(dt)) { | 303 if (this.canCopyOrDrag_(dt)) { |
284 if (this.canCutOrDrag_(dt)) | 304 if (this.canCutOrDrag_(dt)) |
285 this.cutOrCopy_(dt, 'copyMove'); | 305 this.cutOrCopy_(dt, 'copyMove'); |
286 else | 306 else |
287 this.cutOrCopy_(dt, 'copy'); | 307 this.cutOrCopy_(dt, 'copy'); |
288 } else { | 308 } else { |
289 event.preventDefault(); | 309 event.preventDefault(); |
290 } | 310 } |
291 | 311 |
292 window[DRAG_AND_DROP_GLOBAL_DATA] = { | 312 window[DRAG_AND_DROP_GLOBAL_DATA] = { |
293 sourceRoot: this.directoryModel_.getCurrentRootPath() | 313 sourceRoot: this.directoryModel_.getCurrentRootPath() |
294 }; | 314 }; |
295 }, | 315 }, |
296 | 316 |
| 317 /** |
| 318 * @this {FileTransferController} |
| 319 */ |
297 onDragEnd_: function(list, event) { | 320 onDragEnd_: function(list, event) { |
298 var container = this.document_.querySelector('#drag-container'); | 321 var container = this.document_.querySelector('#drag-container'); |
299 container.textContent = ''; | 322 container.textContent = ''; |
300 this.setDropTarget_(null); | 323 this.setDropTarget_(null); |
301 this.setScrollSpeed_(null, 0); | 324 this.setScrollSpeed_(null, 0); |
302 delete window[DRAG_AND_DROP_GLOBAL_DATA]; | 325 delete window[DRAG_AND_DROP_GLOBAL_DATA]; |
303 }, | 326 }, |
304 | 327 |
| 328 /** |
| 329 * @this {FileTransferController} |
| 330 */ |
305 onDragOver_: function(onlyIntoDirectories, list, event) { | 331 onDragOver_: function(onlyIntoDirectories, list, event) { |
306 if (list) { | 332 if (list) { |
307 // Scroll the list if mouse close to the top or the bottom. | 333 // Scroll the list if mouse close to the top or the bottom. |
308 var rect = list.getBoundingClientRect(); | 334 var rect = list.getBoundingClientRect(); |
309 if (event.clientY - rect.top < rect.bottom - event.clientY) { | 335 if (event.clientY - rect.top < rect.bottom - event.clientY) { |
310 this.setScrollSpeed_(list, | 336 this.setScrollSpeed_(list, |
311 -this.calculateScrollSpeed_(event.clientY - rect.top)); | 337 -this.calculateScrollSpeed_(event.clientY - rect.top)); |
312 } else { | 338 } else { |
313 this.setScrollSpeed_(list, | 339 this.setScrollSpeed_(list, |
314 this.calculateScrollSpeed_(rect.bottom - event.clientY)); | 340 this.calculateScrollSpeed_(rect.bottom - event.clientY)); |
315 } | 341 } |
316 } | 342 } |
317 event.preventDefault(); | 343 event.preventDefault(); |
318 var path = this.destinationPath_ || | 344 var path = this.destinationPath_ || |
319 (!onlyIntoDirectories && this.directoryModel_.getCurrentDirPath()); | 345 (!onlyIntoDirectories && this.directoryModel_.getCurrentDirPath()); |
320 event.dataTransfer.dropEffect = this.selectDropEffect_(event, path); | 346 event.dataTransfer.dropEffect = this.selectDropEffect_(event, path); |
321 event.preventDefault(); | 347 event.preventDefault(); |
322 }, | 348 }, |
323 | 349 |
| 350 /** |
| 351 * @this {FileTransferController} |
| 352 */ |
324 onDragEnterList_: function(list, event) { | 353 onDragEnterList_: function(list, event) { |
325 event.preventDefault(); // Required to prevent the cursor flicker. | 354 event.preventDefault(); // Required to prevent the cursor flicker. |
326 this.lastEnteredTarget_ = event.target; | 355 this.lastEnteredTarget_ = event.target; |
327 var item = list.getListItemAncestor(event.target); | 356 var item = list.getListItemAncestor(event.target); |
328 item = item && list.isItem(item) ? item : null; | 357 item = item && list.isItem(item) ? item : null; |
329 if (item == this.dropTarget_) | 358 if (item == this.dropTarget_) |
330 return; | 359 return; |
331 | 360 |
332 var entry = item && list.dataModel.item(item.listIndex); | 361 var entry = item && list.dataModel.item(item.listIndex); |
333 if (entry) { | 362 if (entry) { |
334 this.setDropTarget_(item, entry.isDirectory, event.dataTransfer, | 363 this.setDropTarget_(item, entry.isDirectory, event.dataTransfer, |
335 entry.fullPath); | 364 entry.fullPath); |
336 } else { | 365 } else { |
337 this.setDropTarget_(null); | 366 this.setDropTarget_(null); |
338 } | 367 } |
339 }, | 368 }, |
340 | 369 |
| 370 /** |
| 371 * @this {FileTransferController} |
| 372 */ |
341 onDragEnterBreadcrumbs_: function(breadcrumbsContainer, event) { | 373 onDragEnterBreadcrumbs_: function(breadcrumbsContainer, event) { |
342 event.preventDefault(); // Required to prevent the cursor flicker. | 374 event.preventDefault(); // Required to prevent the cursor flicker. |
343 this.lastEnteredTarget_ = event.target; | 375 this.lastEnteredTarget_ = event.target; |
344 var path = breadcrumbsContainer.getTargetPath(event); | 376 var path = breadcrumbsContainer.getTargetPath(event); |
345 if (!path) | 377 if (!path) |
346 return; | 378 return; |
347 | 379 |
348 this.setDropTarget_(event.target, true, event.dataTransfer, path); | 380 this.setDropTarget_(event.target, true, event.dataTransfer, path); |
349 }, | 381 }, |
350 | 382 |
| 383 /** |
| 384 * @this {FileTransferController} |
| 385 */ |
351 onDragLeave_: function(list, event) { | 386 onDragLeave_: function(list, event) { |
352 // If mouse moves from one element to another the 'dragenter' | 387 // If mouse moves from one element to another the 'dragenter' |
353 // event for the new element comes before the 'dragleave' event for | 388 // event for the new element comes before the 'dragleave' event for |
354 // the old one. In this case event.target != this.lastEnteredTarget_ | 389 // the old one. In this case event.target != this.lastEnteredTarget_ |
355 // and handler of the 'dragenter' event has already caried of | 390 // and handler of the 'dragenter' event has already caried of |
356 // drop target. So event.target == this.lastEnteredTarget_ | 391 // drop target. So event.target == this.lastEnteredTarget_ |
357 // could only be if mouse goes out of listened element. | 392 // could only be if mouse goes out of listened element. |
358 if (event.target == this.lastEnteredTarget_) { | 393 if (event.target == this.lastEnteredTarget_) { |
359 this.setDropTarget_(null); | 394 this.setDropTarget_(null); |
360 this.lastEnteredTarget_ = null; | 395 this.lastEnteredTarget_ = null; |
361 } | 396 } |
362 if (event.target == list) | 397 if (event.target == list) |
363 this.setScrollSpeed_(list, 0); | 398 this.setScrollSpeed_(list, 0); |
364 }, | 399 }, |
365 | 400 |
| 401 /** |
| 402 * @this {FileTransferController} |
| 403 */ |
366 onDrop_: function(onlyIntoDirectories, event) { | 404 onDrop_: function(onlyIntoDirectories, event) { |
367 if (onlyIntoDirectories && !this.dropTarget_) | 405 if (onlyIntoDirectories && !this.dropTarget_) |
368 return; | 406 return; |
369 var destinationPath = this.destinationPath_ || | 407 var destinationPath = this.destinationPath_ || |
370 this.directoryModel_.getCurrentDirPath(); | 408 this.directoryModel_.getCurrentDirPath(); |
371 if (!this.canPasteOrDrop_(event.dataTransfer, destinationPath)) | 409 if (!this.canPasteOrDrop_(event.dataTransfer, destinationPath)) |
372 return; | 410 return; |
373 event.preventDefault(); | 411 event.preventDefault(); |
374 this.paste(event.dataTransfer, destinationPath, | 412 this.paste(event.dataTransfer, destinationPath, |
375 this.selectDropEffect_(event, destinationPath)); | 413 this.selectDropEffect_(event, destinationPath)); |
376 this.setDropTarget_(null); | 414 this.setDropTarget_(null); |
377 this.setScrollSpeed_(null, 0); | 415 this.setScrollSpeed_(null, 0); |
378 }, | 416 }, |
379 | 417 |
| 418 /** |
| 419 * @this {FileTransferController} |
| 420 */ |
380 setDropTarget_: function(domElement, isDirectory, opt_dataTransfer, | 421 setDropTarget_: function(domElement, isDirectory, opt_dataTransfer, |
381 opt_destinationPath) { | 422 opt_destinationPath) { |
382 if (this.dropTarget_ == domElement) | 423 if (this.dropTarget_ == domElement) |
383 return; | 424 return; |
384 | 425 |
385 /** @type {string?} */ | 426 /** @type {string?} */ |
386 this.destinationPath_ = null; | 427 this.destinationPath_ = null; |
387 if (domElement) { | 428 if (domElement) { |
388 if (isDirectory && | 429 if (isDirectory && |
389 this.canPasteOrDrop_(opt_dataTransfer, opt_destinationPath)) { | 430 this.canPasteOrDrop_(opt_dataTransfer, opt_destinationPath)) { |
(...skipping 14 matching lines...) Expand all Loading... |
404 clearTimeout(this.navigateTimer_); | 445 clearTimeout(this.navigateTimer_); |
405 this.navigateTimer_ = undefined; | 446 this.navigateTimer_ = undefined; |
406 } | 447 } |
407 if (domElement && isDirectory && opt_destinationPath) { | 448 if (domElement && isDirectory && opt_destinationPath) { |
408 this.navigateTimer_ = setTimeout(function() { | 449 this.navigateTimer_ = setTimeout(function() { |
409 this.directoryModel_.changeDirectory(opt_destinationPath); | 450 this.directoryModel_.changeDirectory(opt_destinationPath); |
410 }.bind(this), 2000); | 451 }.bind(this), 2000); |
411 } | 452 } |
412 }, | 453 }, |
413 | 454 |
414 isDocumentWideEvent_: function(event) { | 455 /** |
| 456 * @this {FileTransferController} |
| 457 * @return {boolean} Returns false if {@code <input type="text">} element is |
| 458 * currently active. Otherwise, returns true. |
| 459 */ |
| 460 isDocumentWideEvent_: function() { |
415 return this.document_.activeElement.nodeName.toLowerCase() != 'input' || | 461 return this.document_.activeElement.nodeName.toLowerCase() != 'input' || |
416 this.document_.activeElement.type.toLowerCase() != 'text'; | 462 this.document_.activeElement.type.toLowerCase() != 'text'; |
417 }, | 463 }, |
418 | 464 |
| 465 /** |
| 466 * @this {FileTransferController} |
| 467 */ |
419 onCopy_: function(event) { | 468 onCopy_: function(event) { |
420 if (!this.isDocumentWideEvent_(event) || | 469 if (!this.isDocumentWideEvent_() || |
421 !this.canCopyOrDrag_()) { | 470 !this.canCopyOrDrag_()) { |
422 return; | 471 return; |
423 } | 472 } |
424 event.preventDefault(); | 473 event.preventDefault(); |
425 this.cutOrCopy_(event.clipboardData, 'copy'); | 474 this.cutOrCopy_(event.clipboardData, 'copy'); |
426 this.notify_('selection-copied'); | 475 this.notify_('selection-copied'); |
427 }, | 476 }, |
428 | 477 |
| 478 /** |
| 479 * @this {FileTransferController} |
| 480 */ |
429 onBeforeCopy_: function(event) { | 481 onBeforeCopy_: function(event) { |
430 if (!this.isDocumentWideEvent_(event)) | 482 if (!this.isDocumentWideEvent_()) |
431 return; | 483 return; |
432 | 484 |
433 // queryCommandEnabled returns true if event.returnValue is false. | 485 // queryCommandEnabled returns true if event.returnValue is false. |
434 event.returnValue = !this.canCopyOrDrag_(); | 486 event.returnValue = !this.canCopyOrDrag_(); |
435 }, | 487 }, |
436 | 488 |
| 489 /** |
| 490 * @this {FileTransferController} |
| 491 * @return {boolean} Returns true if some files are selected and all the file |
| 492 * on drive is available to be copied. Otherwise, returns false. |
| 493 */ |
437 canCopyOrDrag_: function() { | 494 canCopyOrDrag_: function() { |
438 if (this.isOnDrive && | 495 if (this.isOnDrive && |
439 this.directoryModel_.isDriveOffline() && | 496 this.directoryModel_.isDriveOffline() && |
440 !this.allDriveFilesAvailable) | 497 !this.allDriveFilesAvailable) |
441 return false; | 498 return false; |
442 return this.selectedEntries_.length > 0; | 499 return this.selectedEntries_.length > 0; |
443 }, | 500 }, |
444 | 501 |
| 502 /** |
| 503 * @this {FileTransferController} |
| 504 */ |
445 onCut_: function(event) { | 505 onCut_: function(event) { |
446 if (!this.isDocumentWideEvent_(event) || | 506 if (!this.isDocumentWideEvent_() || |
447 !this.canCutOrDrag_()) { | 507 !this.canCutOrDrag_()) { |
448 return; | 508 return; |
449 } | 509 } |
450 event.preventDefault(); | 510 event.preventDefault(); |
451 this.cutOrCopy_(event.clipboardData, 'move'); | 511 this.cutOrCopy_(event.clipboardData, 'move'); |
452 this.notify_('selection-cut'); | 512 this.notify_('selection-cut'); |
453 }, | 513 }, |
454 | 514 |
| 515 /** |
| 516 * @this {FileTransferController} |
| 517 */ |
455 onBeforeCut_: function(event) { | 518 onBeforeCut_: function(event) { |
456 if (!this.isDocumentWideEvent_(event)) | 519 if (!this.isDocumentWideEvent_()) |
457 return; | 520 return; |
458 // queryCommandEnabled returns true if event.returnValue is false. | 521 // queryCommandEnabled returns true if event.returnValue is false. |
459 event.returnValue = !this.canCutOrDrag_(); | 522 event.returnValue = !this.canCutOrDrag_(); |
460 }, | 523 }, |
461 | 524 |
| 525 /** |
| 526 * @this {FileTransferController} |
| 527 * @return {boolean} Returns true if some files are selected and all the file |
| 528 * on drive is available to be cut. Otherwise, returns false. |
| 529 */ |
462 canCutOrDrag_: function() { | 530 canCutOrDrag_: function() { |
463 return !this.readonly && this.canCopyOrDrag_(); | 531 return !this.readonly && this.canCopyOrDrag_(); |
464 }, | 532 }, |
465 | 533 |
| 534 /** |
| 535 * @this {FileTransferController} |
| 536 */ |
466 onPaste_: function(event) { | 537 onPaste_: function(event) { |
467 // Need to update here since 'beforepaste' doesn't fire. | 538 // Need to update here since 'beforepaste' doesn't fire. |
468 if (!this.isDocumentWideEvent_(event) || | 539 if (!this.isDocumentWideEvent_() || |
469 !this.canPasteOrDrop_(event.clipboardData)) { | 540 !this.canPasteOrDrop_(event.clipboardData)) { |
470 return; | 541 return; |
471 } | 542 } |
472 event.preventDefault(); | 543 event.preventDefault(); |
473 var effect = this.paste(event.clipboardData); | 544 var effect = this.paste(event.clipboardData); |
474 | 545 |
475 // On cut, we clear the clipboard after the file is pasted/moved so we don't | 546 // On cut, we clear the clipboard after the file is pasted/moved so we don't |
476 // try to move/delete the original file again. | 547 // try to move/delete the original file again. |
477 if (effect == 'move') { | 548 if (effect == 'move') { |
478 this.simulateCommand_('cut', function(event) { | 549 this.simulateCommand_('cut', function(event) { |
479 event.preventDefault(); | 550 event.preventDefault(); |
480 event.clipboardData.setData('fs/clear', ''); | 551 event.clipboardData.setData('fs/clear', ''); |
481 }); | 552 }); |
482 } | 553 } |
483 }, | 554 }, |
484 | 555 |
| 556 /** |
| 557 * @this {FileTransferController} |
| 558 */ |
485 onBeforePaste_: function(event) { | 559 onBeforePaste_: function(event) { |
486 if (!this.isDocumentWideEvent_(event)) | 560 if (!this.isDocumentWideEvent_()) |
487 return; | 561 return; |
488 // queryCommandEnabled returns true if event.returnValue is false. | 562 // queryCommandEnabled returns true if event.returnValue is false. |
489 event.returnValue = !this.canPasteOrDrop_(event.clipboardData); | 563 event.returnValue = !this.canPasteOrDrop_(event.clipboardData); |
490 }, | 564 }, |
491 | 565 |
| 566 /** |
| 567 * @this {FileTransferController} |
| 568 * @return {boolean} Returns true if {@code opt_destinationPath} is |
| 569 * available to be pasted to. Otherwise, returns false. |
| 570 */ |
492 canPasteOrDrop_: function(dataTransfer, opt_destinationPath) { | 571 canPasteOrDrop_: function(dataTransfer, opt_destinationPath) { |
493 var destinationPath = opt_destinationPath || | 572 var destinationPath = opt_destinationPath || |
494 this.directoryModel_.getCurrentDirPath(); | 573 this.directoryModel_.getCurrentDirPath(); |
495 if (this.directoryModel_.isPathReadOnly(destinationPath)) { | 574 if (this.directoryModel_.isPathReadOnly(destinationPath)) { |
496 return false; | 575 return false; |
497 } | 576 } |
498 if (this.directoryModel_.isSearching()) | 577 if (this.directoryModel_.isSearching()) |
499 return false; | 578 return false; |
500 | 579 |
501 if (!dataTransfer.types || dataTransfer.types.indexOf('fs/tag') == -1) | 580 if (!dataTransfer.types || dataTransfer.types.indexOf('fs/tag') == -1) |
502 return false; // Unsupported type of content. | 581 return false; // Unsupported type of content. |
503 if (dataTransfer.getData('fs/tag') == '') { | 582 if (dataTransfer.getData('fs/tag') == '') { |
504 // Data protected. Other checks are not possible but it makes sense to | 583 // Data protected. Other checks are not possible but it makes sense to |
505 // let the user try. | 584 // let the user try. |
506 return true; | 585 return true; |
507 } | 586 } |
508 | 587 |
509 var directories = dataTransfer.getData('fs/directories').split('\n'). | 588 var directories = dataTransfer.getData('fs/directories').split('\n'). |
510 filter(function(d) { return d != ''; }); | 589 filter(function(d) { return d != ''; }); |
511 | 590 |
512 for (var i = 0; i < directories.length; i++) { | 591 for (var i = 0; i < directories.length; i++) { |
513 if (destinationPath.substr(0, directories[i].length) == directories[i]) | 592 if (destinationPath.substr(0, directories[i].length) == directories[i]) |
514 return false; // recursive paste. | 593 return false; // recursive paste. |
515 } | 594 } |
516 | 595 |
517 return true; | 596 return true; |
518 }, | 597 }, |
519 | 598 |
| 599 /** |
| 600 * Execute paste command. |
| 601 * |
| 602 * @this {FileTransferController} |
| 603 * @return {boolean} Returns true, the paste is success. Otherwise, returns |
| 604 * false. |
| 605 */ |
520 queryPasteCommandEnabled: function() { | 606 queryPasteCommandEnabled: function() { |
521 if (!this.isDocumentWideEvent_()) { | 607 if (!this.isDocumentWideEvent_()) { |
522 return false; | 608 return false; |
523 } | 609 } |
524 | 610 |
525 // HACK(serya): return this.document_.queryCommandEnabled('paste') | 611 // HACK(serya): return this.document_.queryCommandEnabled('paste') |
526 // should be used. | 612 // should be used. |
527 var result; | 613 var result; |
528 this.simulateCommand_('paste', function(event) { | 614 this.simulateCommand_('paste', function(event) { |
529 result = this.canPasteOrDrop_(event.clipboardData); | 615 result = this.canPasteOrDrop_(event.clipboardData); |
530 }.bind(this)); | 616 }.bind(this)); |
531 return result; | 617 return result; |
532 }, | 618 }, |
533 | 619 |
534 /** | 620 /** |
535 * Allows to simulate commands to get access to clipboard. | 621 * Allows to simulate commands to get access to clipboard. |
| 622 * |
| 623 * @this {FileTransferController} |
536 * @param {string} command 'copy', 'cut' or 'paste'. | 624 * @param {string} command 'copy', 'cut' or 'paste'. |
537 * @param {Function} handler Event handler. | 625 * @param {Function} handler Event handler. |
538 */ | 626 */ |
539 simulateCommand_: function(command, handler) { | 627 simulateCommand_: function(command, handler) { |
540 var iframe = this.document_.querySelector('#command-dispatcher'); | 628 var iframe = this.document_.querySelector('#command-dispatcher'); |
541 var doc = iframe.contentDocument; | 629 var doc = iframe.contentDocument; |
542 doc.addEventListener(command, handler); | 630 doc.addEventListener(command, handler); |
543 doc.execCommand(command); | 631 doc.execCommand(command); |
544 doc.removeEventListener(command, handler); | 632 doc.removeEventListener(command, handler); |
545 }, | 633 }, |
546 | 634 |
| 635 /** |
| 636 * @this {FileTransferController} |
| 637 */ |
547 onSelectionChanged_: function(event) { | 638 onSelectionChanged_: function(event) { |
548 var entries = this.selectedEntries_; | 639 var entries = this.selectedEntries_; |
549 var files = this.selectedFileObjects_ = []; | 640 var files = this.selectedFileObjects_ = []; |
550 this.preloadedThumbnailImageNode_ = null; | 641 this.preloadedThumbnailImageNode_ = null; |
551 | 642 |
552 var fileEntries = []; | 643 var fileEntries = []; |
553 for (var i = 0; i < entries.length; i++) { | 644 for (var i = 0; i < entries.length; i++) { |
554 if (entries[i].isFile) | 645 if (entries[i].isFile) |
555 fileEntries.push(entries[i]); | 646 fileEntries.push(entries[i]); |
556 } | 647 } |
(...skipping 30 matching lines...) Expand all Loading... |
587 this.copyCommand_.disabled = !this.canCopyOrDrag_(); | 678 this.copyCommand_.disabled = !this.canCopyOrDrag_(); |
588 | 679 |
589 if (this.allDriveFilesAvailable) | 680 if (this.allDriveFilesAvailable) |
590 prepareFileObjects(); | 681 prepareFileObjects(); |
591 }.bind(this)); | 682 }.bind(this)); |
592 } else { | 683 } else { |
593 prepareFileObjects(); | 684 prepareFileObjects(); |
594 } | 685 } |
595 }, | 686 }, |
596 | 687 |
| 688 /** |
| 689 * @this {FileTransferController} |
| 690 */ |
597 get currentDirectory() { | 691 get currentDirectory() { |
598 if (this.directoryModel_.isSearching() && this.isOnDrive) | 692 if (this.directoryModel_.isSearching() && this.isOnDrive) |
599 return null; | 693 return null; |
600 return this.directoryModel_.getCurrentDirEntry(); | 694 return this.directoryModel_.getCurrentDirEntry(); |
601 }, | 695 }, |
602 | 696 |
| 697 /** |
| 698 * @this {FileTransferController} |
| 699 */ |
603 get readonly() { | 700 get readonly() { |
604 return this.directoryModel_.isReadOnly(); | 701 return this.directoryModel_.isReadOnly(); |
605 }, | 702 }, |
606 | 703 |
| 704 /** |
| 705 * @this {FileTransferController} |
| 706 */ |
607 get isOnDrive() { | 707 get isOnDrive() { |
608 return this.directoryModel_.getCurrentRootType() === RootType.DRIVE; | 708 return this.directoryModel_.getCurrentRootType() === RootType.DRIVE; |
609 }, | 709 }, |
610 | 710 |
| 711 /** |
| 712 * @this {FileTransferController} |
| 713 */ |
611 notify_: function(eventName) { | 714 notify_: function(eventName) { |
612 var self = this; | 715 var self = this; |
613 // Set timeout to avoid recursive events. | 716 // Set timeout to avoid recursive events. |
614 setTimeout(function() { | 717 setTimeout(function() { |
615 cr.dispatchSimpleEvent(self, eventName); | 718 cr.dispatchSimpleEvent(self, eventName); |
616 }, 0); | 719 }, 0); |
617 }, | 720 }, |
618 | 721 |
619 /** | 722 /** |
| 723 * @this {FileTransferController} |
620 * @type {Array.<Entry>} | 724 * @type {Array.<Entry>} |
621 */ | 725 */ |
622 get selectedEntries_() { | 726 get selectedEntries_() { |
623 var list = this.directoryModel_.getFileList(); | 727 var list = this.directoryModel_.getFileList(); |
624 var selectedIndexes = this.directoryModel_.getFileListSelection(). | 728 var selectedIndexes = this.directoryModel_.getFileListSelection(). |
625 selectedIndexes; | 729 selectedIndexes; |
626 var entries = selectedIndexes.map(function(index) { | 730 var entries = selectedIndexes.map(function(index) { |
627 return list.item(index); | 731 return list.item(index); |
628 }); | 732 }); |
629 | 733 |
630 // TODO(serya): Diagnostics for http://crbug/129642 | 734 // TODO(serya): Diagnostics for http://crbug/129642 |
631 if (entries.indexOf(undefined) != -1) { | 735 if (entries.indexOf(undefined) != -1) { |
632 var index = entries.indexOf(undefined); | 736 var index = entries.indexOf(undefined); |
633 entries = entries.filter(function(e) { return !!e; }); | 737 entries = entries.filter(function(e) { return !!e; }); |
634 console.error('Invalid selection found: list items: ', list.length, | 738 console.error('Invalid selection found: list items: ', list.length, |
635 'wrong indexe value: ', selectedIndexes[index], | 739 'wrong indexe value: ', selectedIndexes[index], |
636 'Stack trace: ', new Error().stack); | 740 'Stack trace: ', new Error().stack); |
637 } | 741 } |
638 return entries; | 742 return entries; |
639 }, | 743 }, |
640 | 744 |
| 745 /** |
| 746 * @this {FileTransferController} |
| 747 * @return {string} Returns the appropriate drop query type ('none', 'move' |
| 748 * or copy') to the current modifiers status and the destination. |
| 749 */ |
641 selectDropEffect_: function(event, destinationPath) { | 750 selectDropEffect_: function(event, destinationPath) { |
642 if (!destinationPath || | 751 if (!destinationPath || |
643 this.directoryModel_.isPathReadOnly(destinationPath)) | 752 this.directoryModel_.isPathReadOnly(destinationPath)) |
644 return 'none'; | 753 return 'none'; |
645 if (event.dataTransfer.effectAllowed == 'copyMove' && | 754 if (event.dataTransfer.effectAllowed == 'copyMove' && |
646 this.getSourceRoot_(event.dataTransfer) == | 755 this.getSourceRoot_(event.dataTransfer) == |
647 PathUtil.getRootPath(destinationPath) && | 756 PathUtil.getRootPath(destinationPath) && |
648 !event.ctrlKey) { | 757 !event.ctrlKey) { |
649 return 'move'; | 758 return 'move'; |
650 } | 759 } |
651 if (event.dataTransfer.effectAllowed == 'copyMove' && | 760 if (event.dataTransfer.effectAllowed == 'copyMove' && |
652 event.shiftKey) { | 761 event.shiftKey) { |
653 return 'move'; | 762 return 'move'; |
654 } | 763 } |
655 return 'copy'; | 764 return 'copy'; |
656 }, | 765 }, |
657 | 766 |
| 767 /** |
| 768 * @this {FileTransferController} |
| 769 * @return {number} Returns an appropriate scroll speed to the distance. |
| 770 */ |
658 calculateScrollSpeed_: function(distance) { | 771 calculateScrollSpeed_: function(distance) { |
659 var SCROLL_AREA = 25; // Pixels. | 772 var SCROLL_AREA = 25; // Pixels. |
660 var MIN_SCROLL_SPEED = 50; // Pixels/sec. | 773 var MIN_SCROLL_SPEED = 50; // Pixels/sec. |
661 var MAX_SCROLL_SPEED = 300; // Pixels/sec. | 774 var MAX_SCROLL_SPEED = 300; // Pixels/sec. |
662 if (distance < 0 || distance > SCROLL_AREA) | 775 if (distance < 0 || distance > SCROLL_AREA) |
663 return 0; | 776 return 0; |
664 return MAX_SCROLL_SPEED - (MAX_SCROLL_SPEED - MIN_SCROLL_SPEED) * | 777 return MAX_SCROLL_SPEED - (MAX_SCROLL_SPEED - MIN_SCROLL_SPEED) * |
665 (distance / SCROLL_AREA); | 778 (distance / SCROLL_AREA); |
666 }, | 779 }, |
667 | 780 |
| 781 /** |
| 782 * @this {FileTransferController} |
| 783 */ |
668 setScrollSpeed_: function(list, speed) { | 784 setScrollSpeed_: function(list, speed) { |
669 var SCROLL_INTERVAL = 200; // Milliseconds. | 785 var SCROLL_INTERVAL = 200; // Milliseconds. |
670 if (speed == 0 && this.scrollInterval_) { | 786 if (speed == 0 && this.scrollInterval_) { |
671 clearInterval(this.scrollInterval_); | 787 clearInterval(this.scrollInterval_); |
672 this.scrollInterval_ = null; | 788 this.scrollInterval_ = null; |
673 } else if (speed != 0 && !this.scrollInterval_) { | 789 } else if (speed != 0 && !this.scrollInterval_) { |
674 this.scrollInterval_ = setInterval(this.scroll_.bind(this), | 790 this.scrollInterval_ = setInterval(this.scroll_.bind(this), |
675 SCROLL_INTERVAL); | 791 SCROLL_INTERVAL); |
676 } | 792 } |
677 this.scrollStep_ = speed * SCROLL_INTERVAL / 1000; | 793 this.scrollStep_ = speed * SCROLL_INTERVAL / 1000; |
678 this.scrollList_ = list; | 794 this.scrollList_ = list; |
679 }, | 795 }, |
680 | 796 |
| 797 /** |
| 798 * @this {FileTransferController} |
| 799 */ |
681 scroll_: function() { | 800 scroll_: function() { |
682 if (this.scrollList_) | 801 if (this.scrollList_) |
683 this.scrollList_.scrollTop += this.scrollStep_; | 802 this.scrollList_.scrollTop += this.scrollStep_; |
684 } | 803 } |
685 }; | 804 }; |
OLD | NEW |