Index: chrome/browser/resources/file_manager/js/photo/photo_import.js |
diff --git a/chrome/browser/resources/file_manager/js/photo/photo_import.js b/chrome/browser/resources/file_manager/js/photo/photo_import.js |
deleted file mode 100644 |
index 346e13c01788b8dedd4c980d703ad0c35339ffcc..0000000000000000000000000000000000000000 |
--- a/chrome/browser/resources/file_manager/js/photo/photo_import.js |
+++ /dev/null |
@@ -1,582 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-'use strict'; |
- |
-document.addEventListener('DOMContentLoaded', function() { |
- PhotoImport.load(); |
-}); |
- |
-/** |
- * The main Photo App object. |
- * @param {HTMLElement} dom Container. |
- * @param {VolumeManagerWrapper} volumeManager The initialized |
- * VolumeManagerWrapper instance. |
- * @param {Object} params Parameters. |
- * @constructor |
- */ |
-function PhotoImport(dom, volumeManager, params) { |
- this.dom_ = dom; |
- this.document_ = this.dom_.ownerDocument; |
- this.metadataCache_ = params.metadataCache; |
- this.volumeManager_ = volumeManager; |
- this.fileOperationManager_ = FileOperationManagerWrapper.getInstance(); |
- this.mediaFilesList_ = null; |
- this.destination_ = null; |
- this.myPhotosDirectory_ = null; |
- this.parentWindowId_ = params.parentWindowId; |
- |
- this.initDom_(); |
- this.initMyPhotos_(); |
- this.loadSource_(params.source); |
-} |
- |
-PhotoImport.prototype = { __proto__: cr.EventTarget.prototype }; |
- |
-/** |
- * Single item width. |
- * Keep in sync with .grid-item rule in photo_import.css. |
- */ |
-PhotoImport.ITEM_WIDTH = 164 + 8; |
- |
-/** |
- * Number of tries in creating a destination directory. |
- */ |
-PhotoImport.CREATE_DESTINATION_TRIES = 100; |
- |
-/** |
- * Loads app in the document body. |
- * @param {Object=} opt_params Parameters. |
- */ |
-PhotoImport.load = function(opt_params) { |
- ImageUtil.metrics = metrics; |
- |
- var hash = location.hash ? location.hash.substr(1) : ''; |
- var query = location.search ? location.search.substr(1) : ''; |
- var params = opt_params || {}; |
- if (!params.source) params.source = hash; |
- if (!params.parentWindowId && query) params.parentWindowId = query; |
- if (!params.metadataCache) params.metadataCache = MetadataCache.createFull(); |
- |
- var api = chrome.fileBrowserPrivate || window.top.chrome.fileBrowserPrivate; |
- api.getStrings(function(strings) { |
- loadTimeData.data = strings; |
- var dom = document.querySelector('.photo-import'); |
- |
- var volumeManager = new VolumeManagerWrapper( |
- VolumeManagerWrapper.DriveEnabledStatus.DRIVE_ENABLED); |
- volumeManager.ensureInitialized(function() { |
- new PhotoImport(dom, volumeManager, params); |
- }); |
- }); |
-}; |
- |
-/** |
- * One-time initialization of dom elements. |
- * @private |
- */ |
-PhotoImport.prototype.initDom_ = function() { |
- this.dom_.setAttribute('loading', ''); |
- this.dom_.ownerDocument.defaultView.addEventListener( |
- 'resize', this.onResize_.bind(this)); |
- |
- this.spinner_ = this.dom_.querySelector('.spinner'); |
- |
- this.document_.querySelector('title').textContent = |
- loadTimeData.getString('PHOTO_IMPORT_TITLE'); |
- this.dom_.querySelector('.caption').textContent = |
- loadTimeData.getString('PHOTO_IMPORT_CAPTION'); |
- this.selectAllNone_ = this.dom_.querySelector('.select'); |
- this.selectAllNone_.addEventListener('click', |
- this.onSelectAllNone_.bind(this)); |
- |
- this.dom_.querySelector('label[for=delete-after-checkbox]').textContent = |
- loadTimeData.getString('PHOTO_IMPORT_DELETE_AFTER'); |
- this.selectedCount_ = this.dom_.querySelector('.selected-count'); |
- |
- this.importButton_ = this.dom_.querySelector('button.import'); |
- this.importButton_.textContent = |
- loadTimeData.getString('PHOTO_IMPORT_IMPORT_BUTTON'); |
- this.importButton_.addEventListener('click', this.onImportClick_.bind(this)); |
- |
- this.cancelButton_ = this.dom_.querySelector('button.cancel'); |
- this.cancelButton_.textContent = str('CANCEL_LABEL'); |
- this.cancelButton_.addEventListener('click', this.onCancelClick_.bind(this)); |
- |
- this.grid_ = this.dom_.querySelector('grid'); |
- cr.ui.Grid.decorate(this.grid_); |
- this.grid_.itemConstructor = GridItem.bind(null, this); |
- this.fileList_ = new cr.ui.ArrayDataModel([]); |
- this.grid_.selectionModel = new cr.ui.ListSelectionModel(); |
- this.grid_.dataModel = this.fileList_; |
- this.grid_.selectionModel.addEventListener('change', |
- this.onSelectionChanged_.bind(this)); |
- this.onSelectionChanged_(); |
- |
- this.importingDialog_ = new ImportingDialog( |
- this.dom_, this.fileOperationManager_, |
- this.metadataCache_, this.parentWindowId_); |
- |
- var dialogs = cr.ui.dialogs; |
- dialogs.BaseDialog.OK_LABEL = str('OK_LABEL'); |
- dialogs.BaseDialog.CANCEL_LABEL = str('CANCEL_LABEL'); |
- this.alert_ = new dialogs.AlertDialog(this.dom_); |
-}; |
- |
-/** |
- * One-time initialization of the My Photos directory. |
- * @private |
- */ |
-PhotoImport.prototype.initMyPhotos_ = function() { |
- var driveVolume = this.volumeManager_.getVolumeInfo(RootDirectory.DRIVE); |
- if (!driveVolume || driveVolume.error || !driveVolume.root) { |
- this.onError_(loadTimeData.getString('PHOTO_IMPORT_DRIVE_ERROR')); |
- return; |
- } |
- |
- util.getOrCreateDirectory( |
- driveVolume.root, |
- loadTimeData.getString('PHOTO_IMPORT_MY_PHOTOS_DIRECTORY_NAME'), |
- function(entry) { |
- // This may enable the import button, so check that. |
- this.myPhotosDirectory_ = entry; |
- this.onSelectionChanged_(); |
- }, |
- function(error) { |
- this.onError_(loadTimeData.getString('PHOTO_IMPORT_DRIVE_ERROR')); |
- }.bind(this)); |
-}; |
- |
-/** |
- * Creates the destination directory. |
- * @param {function} onSuccess Callback on success. |
- * @private |
- */ |
-PhotoImport.prototype.createDestination_ = function(onSuccess) { |
- var onError = this.onError_.bind( |
- this, loadTimeData.getString('PHOTO_IMPORT_DESTINATION_ERROR')); |
- |
- var dateFormatter = Intl.DateTimeFormat( |
- [] /* default locale */, |
- {year: 'numeric', month: 'short', day: 'numeric'}); |
- |
- var baseName = PathUtil.join( |
- RootDirectory.DRIVE, |
- loadTimeData.getString('PHOTO_IMPORT_MY_PHOTOS_DIRECTORY_NAME'), |
- dateFormatter.format(new Date())); |
- |
- var driveVolume = this.volumeManager_.getVolumeInfo(RootDirectory.DRIVE); |
- if (!driveVolume || driveVolume.error || !driveVolume.root) { |
- onError(); |
- return; |
- } |
- |
- var tryNext = function(number) { |
- if (number > PhotoImport.CREATE_DESTINATION_TRIES) { |
- console.error('Too many directories with the same base name exist.'); |
- onError(); |
- return; |
- } |
- |
- var directoryName = baseName; |
- if (number > 1) |
- directoryName += ' (' + (tryNumber) + ')'; |
- driveVolume.root.getDirectory( |
- directoryName, |
- {create: true, exclusive: true}, |
- function(entry) { |
- this.destination_ = entry; |
- onSuccess(); |
- }.bind(this), |
- function(error) { |
- if (error.code === FileError.PATH_EXISTS_ERR) { |
- // If there already exists an entry, retry with incrementing the |
- // number. |
- tryNext(number + 1); |
- return; |
- } |
- onError(); |
- }.bind(this)); |
- }.bind(this); |
- |
- tryNext(1); |
-}; |
- |
- |
-/** |
- * Load the source contents. |
- * @param {string} source Path to source. |
- * @private |
- */ |
-PhotoImport.prototype.loadSource_ = function(source) { |
- var onError = this.onError_.bind( |
- this, loadTimeData.getString('PHOTO_IMPORT_SOURCE_ERROR')); |
- |
- var result = []; |
- this.volumeManager_.resolvePath( |
- source, |
- function(sourceEntry) { |
- util.traverseTree( |
- entry, |
- function(entry) { |
- if (!FileType.isVisible(entry)) |
- return false; |
- if (FileType.isImageOrVideo(entry)) |
- result.push(entry); |
- return true; |
- }, |
- function() { |
- this.dom_.removeAttribute('loading'); |
- this.mediaFilesList_ = result; |
- this.fillGrid_(); |
- }.bind(this), |
- onError); |
- }.bind(this), |
- onError); |
-}; |
- |
-/** |
- * Renders files into grid. |
- * @private |
- */ |
-PhotoImport.prototype.fillGrid_ = function() { |
- if (!this.mediaFilesList_) return; |
- this.fileList_.splice(0, this.fileList_.length); |
- this.fileList_.push.apply(this.fileList_, this.mediaFilesList_); |
-}; |
- |
-/** |
- * Creates groups for files based on modification date. |
- * @param {Array.<Entry>} files File list. |
- * @param {Object} filesystem Filesystem metadata. |
- * @return {Array.<Object>} List of grouped items. |
- * @private |
- */ |
-PhotoImport.prototype.createGroups_ = function(files, filesystem) { |
- var dateFormatter = Intl.DateTimeFormat( |
- [] /* default locale */, |
- {year: 'numeric', month: 'short', day: 'numeric'}); |
- |
- var columns = this.grid_.columns; |
- |
- var unknownGroup = { |
- type: 'group', |
- date: 0, |
- title: loadTimeData.getString('PHOTO_IMPORT_UNKNOWN_DATE'), |
- items: [] |
- }; |
- |
- var groupsMap = {}; |
- |
- for (var index = 0; index < files.length; index++) { |
- var props = filesystem[index]; |
- var item = { type: 'entry', entry: files[index] }; |
- |
- if (!props || !props.modificationTime) { |
- item.group = unknownGroup; |
- unknownGroup.items.push(item); |
- continue; |
- } |
- |
- var date = new Date(props.modificationTime); |
- date.setHours(0); |
- date.setMinutes(0); |
- date.setSeconds(0); |
- date.setMilliseconds(0); |
- |
- var time = date.getTime(); |
- if (!(time in groupsMap)) { |
- groupsMap[time] = { |
- type: 'group', |
- date: date, |
- title: dateFormatter.format(date), |
- items: [] |
- }; |
- } |
- |
- var group = groupsMap[time]; |
- group.items.push(item); |
- item.group = group; |
- } |
- |
- var groups = []; |
- for (var time in groupsMap) { |
- if (groupsMap.hasOwnProperty(time)) { |
- groups.push(groupsMap[time]); |
- } |
- } |
- if (unknownGroup.items.length > 0) |
- groups.push(unknownGroup); |
- |
- groups.sort(function(a, b) { |
- return b.date.getTime() - a.date.getTime(); |
- }); |
- |
- var list = []; |
- for (var index = 0; index < groups.length; index++) { |
- var group = groups[index]; |
- |
- list.push(group); |
- for (var t = 1; t < columns; t++) { |
- list.push({ type: 'empty' }); |
- } |
- |
- for (var j = 0; j < group.items.length; j++) { |
- list.push(group.items[j]); |
- } |
- |
- var count = group.items.length; |
- while (count % columns != 0) { |
- list.push({ type: 'empty' }); |
- count++; |
- } |
- } |
- |
- return list; |
-}; |
- |
-/** |
- * Decorates grid item. |
- * @param {HTMLLIElement} li The list item. |
- * @param {FileEntry} entry The file entry. |
- * @private |
- */ |
-PhotoImport.prototype.decorateGridItem_ = function(li, entry) { |
- li.className = 'grid-item'; |
- li.entry = entry; |
- |
- var frame = this.document_.createElement('div'); |
- frame.className = 'grid-frame'; |
- li.appendChild(frame); |
- |
- var box = this.document_.createElement('div'); |
- box.className = 'img-container'; |
- this.metadataCache_.get(entry, 'thumbnail|filesystem', |
- function(metadata) { |
- new ThumbnailLoader(entry.toURL(), |
- ThumbnailLoader.LoaderType.IMAGE, |
- metadata). |
- load(box, ThumbnailLoader.FillMode.FIT, |
- ThumbnailLoader.OptimizationMode.DISCARD_DETACHED); |
- }); |
- frame.appendChild(box); |
- |
- var check = this.document_.createElement('div'); |
- check.className = 'check'; |
- li.appendChild(check); |
-}; |
- |
-/** |
- * Handles the 'pick all/none' action. |
- * @private |
- */ |
-PhotoImport.prototype.onSelectAllNone_ = function() { |
- var sm = this.grid_.selectionModel; |
- if (sm.selectedIndexes.length == this.fileList_.length) { |
- sm.unselectAll(); |
- } else { |
- sm.selectAll(); |
- } |
-}; |
- |
-/** |
- * Show error message. |
- * @param {string} message Error message. |
- * @private |
- */ |
-PhotoImport.prototype.onError_ = function(message) { |
- this.importingDialog_.hide(function() { |
- this.alert_.show(message, |
- function() { |
- window.close(); |
- }); |
- }.bind(this)); |
-}; |
- |
-/** |
- * Resize event handler. |
- * @private |
- */ |
-PhotoImport.prototype.onResize_ = function() { |
- var g = this.grid_; |
- g.startBatchUpdates(); |
- setTimeout(function() { |
- g.columns = 0; |
- g.redraw(); |
- g.endBatchUpdates(); |
- }, 0); |
-}; |
- |
-/** |
- * @return {Array.<Object>} The list of selected entries. |
- * @private |
- */ |
-PhotoImport.prototype.getSelectedItems_ = function() { |
- var indexes = this.grid_.selectionModel.selectedIndexes; |
- var list = []; |
- for (var i = 0; i < indexes.length; i++) { |
- list.push(this.fileList_.item(indexes[i])); |
- } |
- return list; |
-}; |
- |
-/** |
- * Event handler for picked items change. |
- * @private |
- */ |
-PhotoImport.prototype.onSelectionChanged_ = function() { |
- var count = this.grid_.selectionModel.selectedIndexes.length; |
- this.selectedCount_.textContent = count == 0 ? '' : |
- count == 1 ? loadTimeData.getString('PHOTO_IMPORT_ONE_SELECTED') : |
- loadTimeData.getStringF('PHOTO_IMPORT_MANY_SELECTED', count); |
- this.importButton_.disabled = count == 0 || this.myPhotosDirectory_ == null; |
- this.selectAllNone_.textContent = loadTimeData.getString( |
- count == this.fileList_.length && count > 0 ? |
- 'PHOTO_IMPORT_SELECT_NONE' : 'PHOTO_IMPORT_SELECT_ALL'); |
-}; |
- |
-/** |
- * Event handler for import button click. |
- * @param {Event} event The event. |
- * @private |
- */ |
-PhotoImport.prototype.onImportClick_ = function(event) { |
- var entries = this.getSelectedItems_(); |
- var move = this.dom_.querySelector('#delete-after-checkbox').checked; |
- this.importingDialog_.show(entries, move); |
- |
- this.createDestination_(function() { |
- var percentage = Math.round(entries.length / this.fileList_.length * 100); |
- metrics.recordMediumCount('PhotoImport.ImportCount', entries.length); |
- metrics.recordSmallCount('PhotoImport.ImportPercentage', percentage); |
- |
- this.importingDialog_.start(this.destination_); |
- }.bind(this)); |
-}; |
- |
-/** |
- * Click event handler for the cancel button. |
- * @param {Event} event The event. |
- * @private |
- */ |
-PhotoImport.prototype.onCancelClick_ = function(event) { |
- window.close(); |
-}; |
- |
-/** |
- * Item in the grid. |
- * @param {PhotoImport} app Application instance. |
- * @param {Entry} entry File entry. |
- * @constructor |
- */ |
-function GridItem(app, entry) { |
- var li = app.document_.createElement('li'); |
- li.__proto__ = GridItem.prototype; |
- app.decorateGridItem_(li, entry); |
- return li; |
-} |
- |
-GridItem.prototype = { |
- __proto__: cr.ui.ListItem.prototype, |
- get label() {}, |
- set label(value) {} |
-}; |
- |
-/** |
- * Creates a selection controller that is to be used with grid. |
- * @param {cr.ui.ListSelectionModel} selectionModel The selection model to |
- * interact with. |
- * @param {cr.ui.Grid} grid The grid to interact with. |
- * @constructor |
- * @extends {!cr.ui.ListSelectionController} |
- */ |
-function GridSelectionController(selectionModel, grid) { |
- this.selectionModel_ = selectionModel; |
- this.grid_ = grid; |
-} |
- |
-/** |
- * Extends cr.ui.ListSelectionController. |
- */ |
-GridSelectionController.prototype.__proto__ = |
- cr.ui.ListSelectionController.prototype; |
- |
-/** @override */ |
-GridSelectionController.prototype.getIndexBelow = function(index) { |
- if (index == this.getLastIndex()) { |
- return -1; |
- } |
- |
- var dm = this.grid_.dataModel; |
- var columns = this.grid_.columns; |
- var min = (Math.floor(index / columns) + 1) * columns; |
- |
- for (var row = 1; true; row++) { |
- var end = index + columns * row; |
- var start = Math.max(min, index + columns * (row - 1)); |
- if (start > dm.length) break; |
- |
- for (var i = end; i > start; i--) { |
- if (i < dm.length && dm.item(i).type == 'entry') |
- return i; |
- } |
- } |
- |
- return this.getLastIndex(); |
-}; |
- |
-/** @override */ |
-GridSelectionController.prototype.getIndexAbove = function(index) { |
- if (index == this.getFirstIndex()) { |
- return -1; |
- } |
- |
- var dm = this.grid_.dataModel; |
- index -= this.grid_.columns; |
- while (index >= 0 && dm.item(index).type != 'entry') { |
- index--; |
- } |
- |
- return index < 0 ? this.getFirstIndex() : index; |
-}; |
- |
-/** @override */ |
-GridSelectionController.prototype.getIndexBefore = function(index) { |
- var dm = this.grid_.dataModel; |
- index--; |
- while (index >= 0 && dm.item(index).type != 'entry') { |
- index--; |
- } |
- return index; |
-}; |
- |
-/** @override */ |
-GridSelectionController.prototype.getIndexAfter = function(index) { |
- var dm = this.grid_.dataModel; |
- index++; |
- while (index < dm.length && dm.item(index).type != 'entry') { |
- index++; |
- } |
- return index == dm.length ? -1 : index; |
-}; |
- |
-/** @override */ |
-GridSelectionController.prototype.getFirstIndex = function() { |
- var dm = this.grid_.dataModel; |
- for (var index = 0; index < dm.length; index++) { |
- if (dm.item(index).type == 'entry') |
- return index; |
- } |
- return -1; |
-}; |
- |
-/** @override */ |
-GridSelectionController.prototype.getLastIndex = function() { |
- var dm = this.grid_.dataModel; |
- for (var index = dm.length - 1; index >= 0; index--) { |
- if (dm.item(index).type == 'entry') |
- return index; |
- } |
- return -1; |
-}; |