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 // Setting the src of an img to an empty string can crash the browser, so we | 5 // Setting the src of an img to an empty string can crash the browser, so we |
6 // use an empty 1x1 gif instead. | 6 // use an empty 1x1 gif instead. |
7 const EMPTY_IMAGE_URI = 'data:image/gif;base64,' | 7 const EMPTY_IMAGE_URI = 'data:image/gif;base64,' |
8 + 'R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw%3D%3D'; | 8 + 'R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw%3D%3D'; |
9 | 9 |
10 // If directory files changes too often, don't rescan directory more than once | 10 // If directory files changes too often, don't rescan directory more than once |
(...skipping 1119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1130 }; | 1130 }; |
1131 | 1131 |
1132 /** | 1132 /** |
1133 * Initialize the file thumbnail grid. | 1133 * Initialize the file thumbnail grid. |
1134 */ | 1134 */ |
1135 FileManager.prototype.initGrid_ = function() { | 1135 FileManager.prototype.initGrid_ = function() { |
1136 this.grid_ = this.dialogDom_.querySelector('.thumbnail-grid'); | 1136 this.grid_ = this.dialogDom_.querySelector('.thumbnail-grid'); |
1137 cr.ui.Grid.decorate(this.grid_); | 1137 cr.ui.Grid.decorate(this.grid_); |
1138 | 1138 |
1139 var self = this; | 1139 var self = this; |
1140 this.grid_.itemConstructor = function(entry) { | 1140 this.grid_.itemConstructor = GridItem.bind(null, this); |
1141 return self.renderThumbnail_(entry); | |
1142 }; | |
1143 | 1141 |
1144 this.grid_.selectionModel = new this.selectionModelClass_(); | 1142 this.grid_.selectionModel = new this.selectionModelClass_(); |
1145 | 1143 |
1146 this.grid_.addEventListener( | 1144 this.grid_.addEventListener( |
1147 'dblclick', this.onDetailDoubleClick_.bind(this)); | 1145 'dblclick', this.onDetailDoubleClick_.bind(this)); |
1148 this.grid_.selectionModel.addEventListener( | 1146 this.grid_.selectionModel.addEventListener( |
1149 'change', this.onSelectionChanged_.bind(this)); | 1147 'change', this.onSelectionChanged_.bind(this)); |
1150 cr.ui.contextMenuHandler.addContextMenuProperty(this.grid_); | 1148 cr.ui.contextMenuHandler.addContextMenuProperty(this.grid_); |
1151 this.grid_.contextMenu = this.fileContextMenu_; | 1149 this.grid_.contextMenu = this.fileContextMenu_; |
1152 this.grid_.addEventListener('mousedown', | 1150 this.grid_.addEventListener('mousedown', |
(...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1656 if (opt_imageLoadCallback) | 1654 if (opt_imageLoadCallback) |
1657 opt_imageLoadCallback(img, transform); | 1655 opt_imageLoadCallback(img, transform); |
1658 box.appendChild(img); | 1656 box.appendChild(img); |
1659 }; | 1657 }; |
1660 img.src = url; | 1658 img.src = url; |
1661 self.applyImageTransformation_(box, transform); | 1659 self.applyImageTransformation_(box, transform); |
1662 }); | 1660 }); |
1663 return box; | 1661 return box; |
1664 }; | 1662 }; |
1665 | 1663 |
1666 FileManager.prototype.renderThumbnail_ = function(entry) { | 1664 function GridItem(fileManager, entry) { |
1667 var li = this.document_.createElement('li'); | 1665 var li = fileManager.document_.createElement('li'); |
1666 GridItem.decorate(li, fileManager, entry); | |
1667 return li; | |
1668 } | |
1669 | |
1670 GridItem.prototype = { | |
1671 __proto__: cr.ui.ListItem.prototype, | |
1672 | |
1673 get label() { | |
1674 return this.querySelector('filename-label').textContent; | |
1675 }, | |
1676 set label(value) { | |
1677 // Grid sets it to entry. Ignore. | |
1678 } | |
1679 }; | |
1680 | |
1681 GridItem.decorate = function(li, fileManager, entry) { | |
1682 li.__proto__ = GridItem.prototype; | |
1683 fileManager.decorateThumbnail_(li, entry); | |
1684 }; | |
1685 | |
1686 FileManager.prototype.decorateThumbnail_ = function(li, entry) { | |
1668 li.className = 'thumbnail-item'; | 1687 li.className = 'thumbnail-item'; |
1669 | 1688 |
1670 if (this.showCheckboxes_) | 1689 if (this.showCheckboxes_) |
1671 li.appendChild(this.renderCheckbox_(entry)); | 1690 li.appendChild(this.renderCheckbox_(entry)); |
1672 | 1691 |
1673 li.appendChild(this.renderThumbnailBox_(entry, false)); | 1692 li.appendChild(this.renderThumbnailBox_(entry, false)); |
1674 | 1693 |
1675 var div = this.document_.createElement('div'); | 1694 var div = this.document_.createElement('div'); |
1676 div.className = 'filename-label'; | 1695 div.className = 'filename-label'; |
1677 var labelText = entry.name; | 1696 var labelText = entry.name; |
1678 if (this.currentDirEntry_.name == '') | 1697 if (this.currentDirEntry_.name == '') |
1679 labelText = this.getLabelForRootPath_(labelText); | 1698 labelText = this.getLabelForRootPath_(labelText); |
1680 | 1699 |
1681 div.textContent = labelText; | 1700 div.textContent = labelText; |
1682 div.entry = entry; | 1701 div.entry = entry; |
1683 | 1702 |
1684 li.appendChild(div); | 1703 li.appendChild(div); |
1704 }; | |
1685 | 1705 |
1686 cr.defineProperty(li, 'lead', cr.PropertyKind.BOOL_ATTR); | 1706 GridItem.prototype.__proto__ = cr.ui.ListItem.prototype; |
dgozman
2011/12/09 11:14:43
This is already set above.
SeRya
2011/12/09 14:31:13
Removed.
| |
1687 cr.defineProperty(li, 'selected', cr.PropertyKind.BOOL_ATTR); | |
1688 return li; | |
1689 }; | |
1690 | 1707 |
1691 /** | 1708 /** |
1692 * Render the type column of the detail table. | 1709 * Render the type column of the detail table. |
1693 * | 1710 * |
1694 * Invoked by cr.ui.Table when a file needs to be rendered. | 1711 * Invoked by cr.ui.Table when a file needs to be rendered. |
1695 * | 1712 * |
1696 * @param {Entry} entry The Entry object to render. | 1713 * @param {Entry} entry The Entry object to render. |
1697 * @param {string} columnId The id of the column to be rendered. | 1714 * @param {string} columnId The id of the column to be rendered. |
1698 * @param {cr.ui.Table} table The table doing the rendering. | 1715 * @param {cr.ui.Table} table The table doing the rendering. |
1699 */ | 1716 */ |
(...skipping 28 matching lines...) Expand all Loading... | |
1728 * @param {string} columnId The id of the column to be rendered. | 1745 * @param {string} columnId The id of the column to be rendered. |
1729 * @param {cr.ui.Table} table The table doing the rendering. | 1746 * @param {cr.ui.Table} table The table doing the rendering. |
1730 */ | 1747 */ |
1731 FileManager.prototype.renderName_ = function(entry, columnId, table) { | 1748 FileManager.prototype.renderName_ = function(entry, columnId, table) { |
1732 var label = this.document_.createElement('div'); | 1749 var label = this.document_.createElement('div'); |
1733 if (this.showCheckboxes_) | 1750 if (this.showCheckboxes_) |
1734 label.appendChild(this.renderCheckbox_(entry)); | 1751 label.appendChild(this.renderCheckbox_(entry)); |
1735 label.appendChild(this.renderIconType_(entry, columnId, table)); | 1752 label.appendChild(this.renderIconType_(entry, columnId, table)); |
1736 label.entry = entry; | 1753 label.entry = entry; |
1737 label.className = 'detail-name'; | 1754 label.className = 'detail-name'; |
1755 // Filename need to be in a '.filename-label' container for correct | |
1756 // work of inplace renaming. | |
1757 var fileName = this.document_.createElement('div'); | |
1758 fileName.className = 'filename-label'; | |
1738 if (this.currentDirEntry_.name == '') { | 1759 if (this.currentDirEntry_.name == '') { |
1739 label.appendChild(this.document_.createTextNode( | 1760 fileName.appendChild(this.document_.createTextNode( |
dgozman
2011/12/09 11:14:43
You can use instead:
fileName.textContent = this.g
SeRya
2011/12/09 14:31:13
Fixed and extracted to a method to avoid code dupl
| |
1740 this.getLabelForRootPath_(entry.name))); | 1761 this.getLabelForRootPath_(entry.name))); |
1741 } else { | 1762 } else { |
1742 label.appendChild(this.document_.createTextNode(entry.name)); | 1763 fileName.appendChild(this.document_.createTextNode(entry.name)); |
1743 } | 1764 } |
1765 label.appendChild(fileName); | |
1744 | 1766 |
1745 return label; | 1767 return label; |
1746 }; | 1768 }; |
1747 | 1769 |
1748 /** | 1770 /** |
1749 * Render the Size column of the detail table. | 1771 * Render the Size column of the detail table. |
1750 * | 1772 * |
1751 * @param {Entry} entry The Entry object to render. | 1773 * @param {Entry} entry The Entry object to render. |
1752 * @param {string} columnId The id of the column to be rendered. | 1774 * @param {string} columnId The id of the column to be rendered. |
1753 * @param {cr.ui.Table} table The table doing the rendering. | 1775 * @param {cr.ui.Table} table The table doing the rendering. |
(...skipping 1489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3243 FileManager.prototype.prefetchCacheForSorting_ = function(entries, callback) { | 3265 FileManager.prototype.prefetchCacheForSorting_ = function(entries, callback) { |
3244 var field = this.dataModel_.sortStatus.field; | 3266 var field = this.dataModel_.sortStatus.field; |
3245 if (field) { | 3267 if (field) { |
3246 this.prepareSortEntries_(entries, field, callback); | 3268 this.prepareSortEntries_(entries, field, callback); |
3247 } else { | 3269 } else { |
3248 callback(); | 3270 callback(); |
3249 return; | 3271 return; |
3250 } | 3272 } |
3251 }; | 3273 }; |
3252 | 3274 |
3253 FileManager.prototype.findListItem_ = function(event) { | 3275 FileManager.prototype.findListItemForEvent_ = function(event, list) { |
3254 var node = event.srcElement; | 3276 var node = event.srcElement; |
3277 // Assume list items are direct children of the list. | |
3278 if (node == list) | |
3279 return null; | |
3255 while (node) { | 3280 while (node) { |
3256 if (node.tagName == 'LI') | 3281 var parent = node.parentNode; |
3257 break; | 3282 if (parent == list) |
3258 node = node.parentNode; | 3283 return node; |
3284 node = parent; | |
3259 } | 3285 } |
3260 | 3286 return null; |
3261 return node; | |
3262 }; | 3287 }; |
3263 | 3288 |
3264 FileManager.prototype.onGridMouseDown_ = function(event) { | 3289 FileManager.prototype.onGridMouseDown_ = function(event) { |
3265 this.updateCommands_(); | 3290 this.updateCommands_(); |
3266 | 3291 |
3267 if (this.allowRenameClick_(event, event.srcElement.parentNode)) { | 3292 var list = this.grid_; |
3293 var item = this.findListItemForEvent_(event, list); | |
3294 if (!item) | |
3295 return; | |
3296 if (this.allowRenameClick_(event, list, item)) { | |
3268 event.preventDefault(); | 3297 event.preventDefault(); |
3269 this.initiateRename_(event.srcElement); | 3298 this.initiateRename_(list, item); |
3270 } | 3299 } |
3271 | |
3272 if (event.button != 1) | |
3273 return; | |
3274 | |
3275 var li = this.findListItem_(event); | |
3276 if (!li) | |
3277 return; | |
3278 }; | 3300 }; |
3279 | 3301 |
3280 FileManager.prototype.onTableMouseDown_ = function(event) { | 3302 FileManager.prototype.onTableMouseDown_ = function(event) { |
3281 this.updateCommands_(); | 3303 this.updateCommands_(); |
3282 | 3304 |
3283 if (this.allowRenameClick_(event, | 3305 var list = this.table_.list; |
3284 event.srcElement.parentNode.parentNode)) { | 3306 var item = this.findListItemForEvent_(event, list); |
3307 if (!item) | |
3308 return; | |
3309 if (this.allowRenameClick_(event, list, item)) { | |
3285 event.preventDefault(); | 3310 event.preventDefault(); |
3286 this.initiateRename_(event.srcElement); | 3311 this.initiateRename_(list, item); |
3287 } | |
3288 | |
3289 if (event.button != 1) | |
3290 return; | |
3291 | |
3292 var li = this.findListItem_(event); | |
3293 if (!li) { | |
3294 console.log('li not found', event); | |
3295 return; | |
3296 } | 3312 } |
3297 }; | 3313 }; |
3298 | 3314 |
3299 /** | 3315 /** |
3300 * Unload handler for the page. May be called manually for the file picker | 3316 * Unload handler for the page. May be called manually for the file picker |
3301 * dialog, because it closes by calling extension API functions that do not | 3317 * dialog, because it closes by calling extension API functions that do not |
3302 * return. | 3318 * return. |
3303 */ | 3319 */ |
3304 FileManager.prototype.onUnload_ = function() { | 3320 FileManager.prototype.onUnload_ = function() { |
3305 if (this.subscribedOnDirectoryChanges_) { | 3321 if (this.subscribedOnDirectoryChanges_) { |
(...skipping 12 matching lines...) Expand all Loading... | |
3318 if (event.fileUrl == this.currentDirEntry_.toURL()) | 3334 if (event.fileUrl == this.currentDirEntry_.toURL()) |
3319 this.rescanDirectoryLater_(); | 3335 this.rescanDirectoryLater_(); |
3320 }; | 3336 }; |
3321 | 3337 |
3322 /** | 3338 /** |
3323 * Determine whether or not a click should initiate a rename. | 3339 * Determine whether or not a click should initiate a rename. |
3324 * | 3340 * |
3325 * Renames can happen on mouse click if the user clicks on a label twice, | 3341 * Renames can happen on mouse click if the user clicks on a label twice, |
3326 * at least a half second apart. | 3342 * at least a half second apart. |
3327 */ | 3343 */ |
3328 FileManager.prototype.allowRenameClick_ = function(event, row) { | 3344 FileManager.prototype.allowRenameClick_ = function(event, list, item) { |
3329 if (this.dialogType_ != FileManager.DialogType.FULL_PAGE || | 3345 if (this.dialogType_ != FileManager.DialogType.FULL_PAGE || |
3330 this.currentDirEntry_ == null || this.currentDirEntry_.name == '' || | 3346 this.currentDirEntry_ == null || this.currentDirEntry_.name == '' || |
3331 isSystemDirEntry(this.currentDirEntry_)) { | 3347 isSystemDirEntry(this.currentDirEntry_)) { |
3332 // Renaming only enabled for full-page mode, outside of the root | 3348 // Renaming only enabled for full-page mode, outside of the root |
3333 // directory. | 3349 // directory. |
3334 return false; | 3350 return false; |
3335 } | 3351 } |
3336 | 3352 |
3337 // Didn't click on the label. | 3353 // Didn't click on the label. |
3338 if (!event.srcElement.classList.contains('filename-label')) | 3354 if (!event.srcElement.classList.contains('filename-label')) |
3339 return false; | 3355 return false; |
3340 | 3356 |
3341 // Wrong button or using a keyboard modifier. | 3357 // Wrong button or using a keyboard modifier. |
3342 if (event.button != 0 || event.shiftKey || event.metaKey || event.altKey) { | 3358 if (event.button != 0 || event.shiftKey || event.metaKey || event.altKey) { |
3343 this.lastLabelClick_ = null; | 3359 this.lastLabelClick_ = null; |
3344 return false; | 3360 return false; |
3345 } | 3361 } |
3346 | 3362 |
3347 var now = new Date(); | 3363 var now = new Date(); |
3348 var path = event.srcElement.entry.fullPath; | 3364 var index = list.getIndexOfListItem(item); |
3349 var lastLabelClick = this.lastLabelClick_; | 3365 var lastLabelClick = this.lastLabelClick_; |
3350 this.lastLabelClick_ = {path: path, date: now}; | 3366 this.lastLabelClick_ = {index: index, date: now}; |
3351 | 3367 |
3352 // Rename already in progress. | 3368 // Rename already in progress. |
3353 if (this.renameInput_.currentEntry) | 3369 if (this.renameInput_.currentEntry) |
3354 return false; | 3370 return false; |
3355 | 3371 |
3356 if (lastLabelClick && lastLabelClick.path == path) { | 3372 if (lastLabelClick && lastLabelClick.index == index) { |
3357 var delay = now - lastLabelClick.date; | 3373 var delay = now - lastLabelClick.date; |
3358 if (delay > 500 && delay < 2000) { | 3374 if (delay > 500 && delay < 2000) { |
3359 this.lastLabelClick_ = null; | 3375 this.lastLabelClick_ = null; |
3360 return true; | 3376 return true; |
3361 } | 3377 } |
3362 } | 3378 } |
3363 | 3379 |
3364 return false; | 3380 return false; |
3365 }; | 3381 }; |
3366 | 3382 |
3367 FileManager.prototype.initiateRename_= function(label) { | 3383 FileManager.prototype.initiateRename_= function(list, item) { |
3384 var label = item.querySelector('.filename-label'); | |
3368 var input = this.renameInput_; | 3385 var input = this.renameInput_; |
3369 | 3386 |
3370 input.value = label.textContent; | 3387 input.value = label.textContent; |
3371 input.style.top = label.offsetTop + 'px'; | 3388 input.style.top = label.offsetTop + 'px'; |
3372 input.style.left = label.offsetLeft + 'px'; | 3389 input.style.left = label.offsetLeft + 'px'; |
3373 input.style.width = label.clientWidth + 'px'; | 3390 input.style.width = label.clientWidth + 'px'; |
3374 label.parentNode.appendChild(input); | 3391 label.parentNode.appendChild(input); |
3375 input.focus(); | 3392 input.focus(); |
3376 var selectionEnd = input.value.lastIndexOf('.'); | 3393 var selectionEnd = input.value.lastIndexOf('.'); |
3377 if (selectionEnd == -1) { | 3394 if (selectionEnd == -1) { |
3378 input.select(); | 3395 input.select(); |
3379 } else { | 3396 } else { |
3380 input.selectionStart = 0; | 3397 input.selectionStart = 0; |
3381 input.selectionEnd = selectionEnd; | 3398 input.selectionEnd = selectionEnd; |
3382 } | 3399 } |
3383 | 3400 |
3384 // This has to be set late in the process so we don't handle spurious | 3401 // This has to be set late in the process so we don't handle spurious |
3385 // blur events. | 3402 // blur events. |
3386 input.currentEntry = label.entry; | 3403 var index = list.getIndexOfListItem(item); |
3404 input.currentEntry = list.dataModel.item(index); | |
3387 }; | 3405 }; |
3388 | 3406 |
3389 FileManager.prototype.onRenameInputKeyDown_ = function(event) { | 3407 FileManager.prototype.onRenameInputKeyDown_ = function(event) { |
3390 if (!this.renameInput_.currentEntry) | 3408 if (!this.renameInput_.currentEntry) |
3391 return; | 3409 return; |
3392 | 3410 |
3393 switch (event.keyCode) { | 3411 switch (event.keyCode) { |
3394 case 27: // Escape | 3412 case 27: // Escape |
3395 this.cancelRename_(); | 3413 this.cancelRename_(); |
3396 event.preventDefault(); | 3414 event.preventDefault(); |
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3968 }); | 3986 }); |
3969 }, onError); | 3987 }, onError); |
3970 | 3988 |
3971 function onError(err) { | 3989 function onError(err) { |
3972 console.log('Error while checking free space: ' + err); | 3990 console.log('Error while checking free space: ' + err); |
3973 setTimeout(doCheck, 1000 * 60); | 3991 setTimeout(doCheck, 1000 * 60); |
3974 } | 3992 } |
3975 } | 3993 } |
3976 } | 3994 } |
3977 })(); | 3995 })(); |
OLD | NEW |