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