Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2101)

Unified Diff: chrome/browser/resources/file_manager/js/image_editor/gallery.js

Issue 10834354: Refactor the Photo Editor to enable new feature work (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/file_manager/js/image_editor/gallery.js
diff --git a/chrome/browser/resources/file_manager/js/image_editor/gallery.js b/chrome/browser/resources/file_manager/js/image_editor/gallery.js
deleted file mode 100644
index 48bc0b1d418429d2f76206f22ecb1217b2082ae3..0000000000000000000000000000000000000000
--- a/chrome/browser/resources/file_manager/js/image_editor/gallery.js
+++ /dev/null
@@ -1,1549 +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.
-
-/**
- * Base interface Ribbon uses to display photos.
- * @interface
- */
-function RibbonClient() {}
-
-/**
- * Request prefetch for an image.
- * @param {number} id The content id for caching.
- * @param {string} url Image url.
- */
-RibbonClient.prototype.prefetchImage = function(id, url) {};
-
-//TODO(JSDOC)
-RibbonClient.prototype.openImage = function(id, url, metadata, direction) {};
-
-//TODO(JSDOC)
-RibbonClient.prototype.closeImage = function(item) {};
-
-/**
- * Image gallery for viewing and editing image files.
- *
- * @param {HTMLDivElement} container Container to create gallery in.
- * @param {Object} context Object containing the following:
- * @class
- * @constructor
- * @implements {RibbonClient}
- */
-function Gallery(container, context) {
- this.container_ = container;
- this.document_ = container.ownerDocument;
- this.context_ = context;
- this.metadataCache_ = context.metadataCache;
-
- var strf = context.displayStringFunction;
- this.displayStringFunction_ = function(id, formatArgs) {
- var args = Array.prototype.slice.call(arguments);
- args[0] = 'GALLERY_' + id.toUpperCase();
- return strf.apply(null, args);
- };
-
- this.onFadeTimeoutBound_ = this.onFadeTimeout_.bind(this);
- this.fadeTimeoutId_ = null;
- this.mouseOverTool_ = false;
-
- this.initDom_();
-}
-
-Gallery.prototype = { __proto__: RibbonClient.prototype };
-
-//TODO(JSDOC)
-Gallery.open = function(context, items, selectedItem) {
- var container = document.querySelector('.gallery');
- ImageUtil.removeChildren(container);
- var gallery = new Gallery(container, context);
- gallery.load(items, selectedItem);
-};
-
-/**
- * List of available editor modes.
- * @type {Array.<ImageEditor.Mode>}
- */
-Gallery.editorModes = [
- new ImageEditor.Mode.InstantAutofix(),
- new ImageEditor.Mode.Crop(),
- new ImageEditor.Mode.Exposure(),
- new ImageEditor.Mode.OneClick('rotate_left', new Command.Rotate(-1)),
- new ImageEditor.Mode.OneClick('rotate_right', new Command.Rotate(1))
-];
-
-/**
- * Fade timeout im milliseconds on image transition.
- * @type {Number}
- */
-Gallery.FADE_TIMEOUT = 3000;
-
-/**
- * Fade timeout im milliseconds on first gallery load.
- * @type {Number}
- */
-Gallery.FIRST_FADE_TIMEOUT = 1000;
-
-//TODO(JSDOC)
-Gallery.OVERWRITE_BUBBLE_MAX_TIMES = 5;
-
-/**
- * Types of metadata Gallery uses (to query the metadata cache).
- */
-Gallery.METADATA_TYPE = 'thumbnail|filesystem|media|streaming';
-
-/**
- * Initializes gallery UI
- * @private
- */
-Gallery.prototype.initDom_ = function() {
- var doc = this.document_;
-
- doc.oncontextmenu = function(e) { e.preventDefault(); };
-
- doc.body.addEventListener('keydown', this.onKeyDown_.bind(this));
-
- doc.body.addEventListener('mousemove', this.onMouseMove_.bind(this));
-
- // Show tools when the user touches the screen.
- doc.body.addEventListener('touchstart', this.cancelFading_.bind(this));
- var initiateFading = this.initiateFading_.bind(this, Gallery.FADE_TIMEOUT);
- doc.body.addEventListener('touchend', initiateFading);
- doc.body.addEventListener('touchcancel', initiateFading);
-
- window.addEventListener('unload', this.onUnload_.bind(this));
-
- // We need to listen to the top window 'unload' and 'beforeunload' because
- // the Gallery iframe does not get notified if the tab is closed.
- this.onTopUnloadBound_ = this.onTopUnload_.bind(this);
- window.top.addEventListener('unload', this.onTopUnloadBound_);
-
- this.onBeforeUnloadBound_ = this.onBeforeUnload_.bind(this);
- window.top.addEventListener('beforeunload', this.onBeforeUnloadBound_);
-
- this.closeButton_ = doc.createElement('div');
- this.closeButton_.className = 'close tool dimmable';
- this.closeButton_.appendChild(doc.createElement('div'));
- this.closeButton_.addEventListener('click', this.onClose_.bind(this));
- this.container_.appendChild(this.closeButton_);
-
- this.imageContainer_ = doc.createElement('div');
- this.imageContainer_.className = 'image-container';
- this.imageContainer_.addEventListener('click', (function() {
- this.filenameEdit_.blur();
- if (this.isShowingVideo_())
- this.mediaControls_.togglePlayStateWithFeedback();
- }).bind(this));
- this.container_.appendChild(this.imageContainer_);
-
- this.toolbar_ = doc.createElement('div');
- this.toolbar_.className = 'toolbar tool dimmable';
- this.container_.appendChild(this.toolbar_);
-
- this.filenameSpacer_ = doc.createElement('div');
- this.filenameSpacer_.className = 'filename-spacer';
- this.toolbar_.appendChild(this.filenameSpacer_);
-
- this.bubble_ = doc.createElement('div');
- this.bubble_.className = 'bubble';
- var bubbleContent = doc.createElement('div');
- bubbleContent.innerHTML = this.displayStringFunction_('overwrite_bubble');
- this.bubble_.appendChild(bubbleContent);
- var bubblePointer = doc.createElement('span');
- bubblePointer.className = 'pointer bottom';
- this.bubble_.appendChild(bubblePointer);
- var bubbleClose = doc.createElement('div');
- bubbleClose.className = 'close-x';
- bubbleClose.addEventListener('click', this.onCloseBubble_.bind(this));
- this.bubble_.appendChild(bubbleClose);
- this.bubble_.hidden = true;
- this.toolbar_.appendChild(this.bubble_);
-
- var nameBox = doc.createElement('div');
- nameBox.className = 'namebox';
- this.filenameSpacer_.appendChild(nameBox);
-
- this.filenameText_ = doc.createElement('div');
- this.filenameText_.addEventListener('click',
- this.onFilenameClick_.bind(this));
- nameBox.appendChild(this.filenameText_);
-
- this.filenameEdit_ = doc.createElement('input');
- this.filenameEdit_.setAttribute('type', 'text');
- this.filenameEdit_.addEventListener('blur',
- this.onFilenameEditBlur_.bind(this));
- this.filenameEdit_.addEventListener('keydown',
- this.onFilenameEditKeydown_.bind(this));
- nameBox.appendChild(this.filenameEdit_);
-
- var options = doc.createElement('div');
- options.className = 'options';
- this.filenameSpacer_.appendChild(options);
-
- this.savedLabel_ = doc.createElement('div');
- this.savedLabel_.className = 'saved';
- this.savedLabel_.textContent = this.displayStringFunction_('saved');
- options.appendChild(this.savedLabel_);
-
- var overwriteOriginalBox = doc.createElement('div');
- overwriteOriginalBox.className = 'overwrite-original';
- options.appendChild(overwriteOriginalBox);
-
- this.overwriteOriginal_ = doc.createElement('input');
- this.overwriteOriginal_.type = 'checkbox';
- this.overwriteOriginal_.id = 'overwrite-checkbox';
- this.overwriteOriginal_.className = 'common white';
- overwriteOriginalBox.appendChild(this.overwriteOriginal_);
- this.overwriteOriginal_.addEventListener('click',
- this.onOverwriteOriginalClick_.bind(this));
-
- var overwriteLabel = doc.createElement('label');
- overwriteLabel.textContent =
- this.displayStringFunction_('overwrite_original');
- overwriteLabel.setAttribute('for', 'overwrite-checkbox');
- overwriteOriginalBox.appendChild(overwriteLabel);
-
- this.buttonSpacer_ = doc.createElement('div');
- this.buttonSpacer_.className = 'button-spacer';
- this.toolbar_.appendChild(this.buttonSpacer_);
-
- this.ribbonSpacer_ = doc.createElement('div');
- this.ribbonSpacer_.className = 'ribbon-spacer';
- this.toolbar_.appendChild(this.ribbonSpacer_);
-
- this.mediaSpacer_ = doc.createElement('div');
- this.mediaSpacer_.className = 'video-controls-spacer';
- this.container_.appendChild(this.mediaSpacer_);
-
- this.mediaToolbar_ = doc.createElement('div');
- this.mediaToolbar_.className = 'tool';
- this.mediaSpacer_.appendChild(this.mediaToolbar_);
-
- this.mediaControls_ = new VideoControls(
- this.mediaToolbar_,
- this.showErrorBanner_.bind(this, 'VIDEO_ERROR'),
- this.toggleFullscreen_.bind(this),
- this.container_);
-
- this.arrowBox_ = this.document_.createElement('div');
- this.arrowBox_.className = 'arrow-box';
- this.container_.appendChild(this.arrowBox_);
-
- this.arrowLeft_ = this.document_.createElement('div');
- this.arrowLeft_.className = 'arrow left tool dimmable';
- this.arrowLeft_.appendChild(doc.createElement('div'));
- this.arrowBox_.appendChild(this.arrowLeft_);
-
- this.arrowSpacer_ = this.document_.createElement('div');
- this.arrowSpacer_.className = 'arrow-spacer';
- this.arrowBox_.appendChild(this.arrowSpacer_);
-
- this.arrowRight_ = this.document_.createElement('div');
- this.arrowRight_.className = 'arrow right tool dimmable';
- this.arrowRight_.appendChild(doc.createElement('div'));
- this.arrowBox_.appendChild(this.arrowRight_);
-
- this.spinner_ = this.document_.createElement('div');
- this.spinner_.className = 'spinner';
- this.container_.appendChild(this.spinner_);
-
- this.errorWrapper_ = this.document_.createElement('div');
- this.errorWrapper_.className = 'prompt-wrapper';
- this.errorWrapper_.setAttribute('pos', 'center');
- this.container_.appendChild(this.errorWrapper_);
-
- this.errorBanner_ = this.document_.createElement('div');
- this.errorBanner_.className = 'error-banner';
- this.errorWrapper_.appendChild(this.errorBanner_);
-
- this.ribbon_ = new Ribbon(this.document_,
- this, this.metadataCache_, this.arrowLeft_, this.arrowRight_);
- this.ribbonSpacer_.appendChild(this.ribbon_);
-
- this.editBar_ = doc.createElement('div');
- this.editBar_.className = 'edit-bar';
- this.toolbar_.appendChild(this.editBar_);
-
- this.editButton_ = doc.createElement('div');
- this.editButton_.className = 'button edit';
- this.editButton_.textContent = this.displayStringFunction_('edit');
- this.editButton_.addEventListener('click', this.onEdit_.bind(this));
- this.toolbar_.appendChild(this.editButton_);
-
- this.editBarMain_ = doc.createElement('div');
- this.editBarMain_.className = 'edit-main';
- this.editBar_.appendChild(this.editBarMain_);
-
- this.editBarMode_ = doc.createElement('div');
- this.editBarMode_.className = 'edit-modal';
- this.container_.appendChild(this.editBarMode_);
-
- this.editBarModeWrapper_ = doc.createElement('div');
- this.editBarModeWrapper_.hidden = true;
- this.editBarModeWrapper_.className = 'edit-modal-wrapper';
- this.editBarMode_.appendChild(this.editBarModeWrapper_);
-
- this.viewport_ = new Viewport();
-
- this.imageView_ = new ImageView(
- this.imageContainer_,
- this.viewport_,
- this.metadataCache_);
-
- this.editor_ = new ImageEditor(
- this.viewport_,
- this.imageView_,
- {
- root: this.container_,
- image: this.imageContainer_,
- toolbar: this.editBarMain_,
- mode: this.editBarModeWrapper_
- },
- Gallery.editorModes,
- this.displayStringFunction_);
-
- this.editor_.getBuffer().addOverlay(new SwipeOverlay(this.ribbon_));
-
- this.imageView_.addContentCallback(this.onImageContentChanged_.bind(this));
-
- this.editor_.trackWindow(doc.defaultView);
-
- Gallery.getFileBrowserPrivate().isFullscreen(function(fullscreen) {
- this.originalFullscreen_ = fullscreen;
- }.bind(this));
-};
-
-/**
- * BeforeUnload event listener.
- * @param {Event} event Not used
- * @return {string} Message to show if there's unsaved changes.
- * @private
- */
-Gallery.prototype.onBeforeUnload_ = function(event) {
- if (this.editor_.isBusy())
- return this.displayStringFunction_('unsaved_changes');
- return null;
-};
-
-//TODO(JSDOC)
-Gallery.prototype.load = function(items, selectedItem) {
- var urls = [];
- var selectedIndex = -1;
-
- // Convert canvas and blob items to blob urls.
- for (var i = 0; i != items.length; i++) {
- var item = items[i];
- var selected = (item == selectedItem);
-
- if (typeof item == 'string') {
- if (selected) selectedIndex = urls.length;
- urls.push(item);
- } else {
- console.error('Unsupported item type', item);
- }
- }
-
- if (urls.length == 0)
- throw new Error('Cannot open the gallery for 0 items');
-
- if (selectedIndex == -1)
- throw new Error('Cannot find selected item');
-
- var self = this;
-
- var selectedURL = urls[selectedIndex];
-
- function initRibbon() {
- self.ribbon_.load(urls, selectedIndex);
- if (urls.length == 1 && self.isShowingVideo_()) {
- // We only have one item and it is a video. Move the playback controls
- // in place of thumbnails and start the playback immediately.
- self.mediaSpacer_.removeChild(self.mediaToolbar_);
- self.ribbonSpacer_.appendChild(self.mediaToolbar_);
- self.mediaControls_.play();
- }
- // Flash the toolbar briefly to let the user know it is there.
- self.cancelFading_();
- self.initiateFading_(Gallery.FIRST_FADE_TIMEOUT);
- }
-
- // Show the selected item ASAP, then complete the initialization (populating
- // the ribbon can take especially long time).
- this.metadataCache_.get(selectedURL, Gallery.METADATA_TYPE,
- function(metadata) {
- self.openImage(selectedIndex, selectedURL, metadata, 0, initRibbon);
- });
-
- this.context_.getShareActions(urls, function(tasks) {
- if (tasks.length > 0) {
- this.shareMode_ = new ShareMode(this.editor_, this.container_,
- this.toolbar_, tasks,
- this.onShare_.bind(this), this.onActionExecute_.bind(this),
- this.displayStringFunction_);
- } else {
- this.shareMode_ = null;
- }
- }.bind(this));
-};
-
-//TODO(JSDOC)
-Gallery.prototype.onImageContentChanged_ = function() {
- var revision = this.imageView_.getContentRevision();
- if (revision == 0) {
- // Just loaded.
- var key = 'gallery-overwrite-bubble';
- var times = key in localStorage ? parseInt(localStorage[key], 10) : 0;
- if (times < Gallery.OVERWRITE_BUBBLE_MAX_TIMES) {
- this.bubble_.hidden = false;
- if (this.isEditing_()) {
- localStorage[key] = times + 1;
- }
- }
- }
-
- if (revision == 1) {
- // First edit.
- ImageUtil.setAttribute(this.filenameSpacer_, 'saved', true);
- ImageUtil.metrics.recordUserAction(ImageUtil.getMetricName('Edit'));
- }
-};
-
-//TODO(JSDOC)
-Gallery.prototype.flashSavedLabel_ = function() {
- var selLabelHighlighted =
- ImageUtil.setAttribute.bind(null, this.savedLabel_, 'highlighted');
- setTimeout(selLabelHighlighted.bind(null, true), 0);
- setTimeout(selLabelHighlighted.bind(null, false), 300);
-};
-
-//TODO(JSDOC)
-Gallery.prototype.applyDefaultOverwrite_ = function() {
- var key = 'gallery-overwrite-original';
- var overwrite = key in localStorage ? (localStorage[key] == 'true') : true;
- this.overwriteOriginal_.checked = overwrite;
- this.applyOverwrite_(overwrite);
-};
-
-//TODO(JSDOC)
-Gallery.prototype.applyOverwrite_ = function(overwrite) {
- if (overwrite) {
- this.ribbon_.getSelectedItem().setOriginalName(this.context_.saveDirEntry,
- this.updateFilename_.bind(this));
- } else {
- this.ribbon_.getSelectedItem().setCopyName(this.context_.saveDirEntry,
- this.selectedImageMetadata_,
- this.updateFilename_.bind(this));
- }
-};
-
-//TODO(JSDOC)
-Gallery.prototype.onOverwriteOriginalClick_ = function(event) {
- var overwrite = event.target.checked;
- localStorage['gallery-overwrite-original'] = overwrite;
- this.applyOverwrite_(overwrite);
-};
-
-//TODO(JSDOC)
-Gallery.prototype.onCloseBubble_ = function(event) {
- this.bubble_.hidden = true;
- localStorage['gallery-overwrite-bubble'] = Gallery.OVERWRITE_BUBBLE_MAX_TIMES;
-};
-
-//TODO(JSDOC)
-Gallery.prototype.saveCurrentImage_ = function(callback) {
- var item = this.ribbon_.getSelectedItem();
- var canvas = this.imageView_.getCanvas();
-
- this.showSpinner_(true);
- var metadataEncoder = ImageEncoder.encodeMetadata(
- this.selectedImageMetadata_.media, canvas, 1 /* quality */);
-
- this.selectedImageMetadata_ = ContentProvider.ConvertContentMetadata(
- metadataEncoder.getMetadata(), this.selectedImageMetadata_);
- item.setThumbnail(this.selectedImageMetadata_);
-
- item.saveToFile(
- this.context_.saveDirEntry,
- canvas,
- metadataEncoder,
- function(success) {
- // TODO(kaznacheev): Implement write error handling.
- // Until then pretend that the save succeeded.
- this.showSpinner_(false);
- this.flashSavedLabel_();
- this.metadataCache_.clear(item.getUrl(), Gallery.METADATA_TYPE);
- callback();
- }.bind(this));
-};
-
-//TODO(JSDOC)
-Gallery.prototype.onActionExecute_ = function(action) {
- // |executeWhenReady| closes the sharing menu.
- this.editor_.executeWhenReady(function() {
- action.execute([this.ribbon_.getSelectedItem().getUrl()]);
- }.bind(this));
-};
-
-//TODO(JSDOC)
-Gallery.prototype.updateFilename_ = function(opt_url) {
- var fullName;
-
- var item = this.ribbon_.getSelectedItem();
- if (item) {
- fullName = item.getNameAfterSaving();
- } else if (opt_url) {
- fullName = ImageUtil.getFullNameFromUrl(opt_url);
- } else {
- return;
- }
-
- this.context_.onNameChange(fullName);
-
- var displayName = ImageUtil.getFileNameFromFullName(fullName);
- this.filenameEdit_.value = displayName;
- this.filenameText_.textContent = displayName;
-};
-
-/**
- * Click event handler on filename edit box
- * @private
- */
-Gallery.prototype.onFilenameClick_ = function() {
- // We can't rename files in readonly directory.
- if (this.context_.readonlyDirName)
- return;
-
- ImageUtil.setAttribute(this.filenameSpacer_, 'renaming', true);
- setTimeout(this.filenameEdit_.select.bind(this.filenameEdit_), 0);
- this.cancelFading_();
-};
-
-/**
- * Blur event handler on filename edit box
- * @private
- */
-Gallery.prototype.onFilenameEditBlur_ = function() {
- if (this.filenameEdit_.value && this.filenameEdit_.value[0] == '.') {
- this.editor_.getPrompt().show('file_hidden_name', 5000);
- this.filenameEdit_.focus();
- return;
- }
-
- if (this.filenameEdit_.value) {
- this.renameItem_(this.ribbon_.getSelectedItem(),
- this.filenameEdit_.value);
- }
-
- ImageUtil.setAttribute(this.filenameSpacer_, 'renaming', false);
- this.initiateFading_();
-};
-
-/**
- * Keydown event handler on filename edit box
- * @private
- */
-Gallery.prototype.onFilenameEditKeydown_ = function() {
- switch (event.keyCode) {
- case 27: // Escape
- this.updateFilename_();
- this.filenameEdit_.blur();
- break;
-
- case 13: // Enter
- this.filenameEdit_.blur();
- break;
- }
- event.stopPropagation();
-};
-
-//TODO(JSDOC)
-Gallery.prototype.renameItem_ = function(item, name) {
- var dir = this.context_.saveDirEntry;
- var self = this;
- var originalName = item.getNameAfterSaving();
- if (ImageUtil.getExtensionFromFullName(name) ==
- ImageUtil.getExtensionFromFullName(originalName)) {
- name = ImageUtil.getFileNameFromFullName(name);
- }
- var newName = ImageUtil.replaceFileNameInFullName(originalName, name);
- if (originalName == newName) return;
-
- function onError() {
- console.log('Rename error: "' + originalName + '" to "' + newName + '"');
- }
-
- function onSuccess(entry) {
- item.setUrl(entry.toURL());
- self.updateFilename_();
- }
-
- function doRename() {
- if (item.hasNameForSaving()) {
- // Use this name in the next save operation.
- item.setNameForSaving(newName);
- ImageUtil.setAttribute(self.filenameSpacer_, 'overwrite', false);
- self.updateFilename_();
- } else {
- // Rename file in place.
- dir.getFile(
- ImageUtil.getFullNameFromUrl(item.getUrl()),
- {create: false},
- function(entry) { entry.moveTo(dir, newName, onSuccess, onError); },
- onError);
- }
- }
-
- function onVictimFound(victim) {
- self.editor_.getPrompt().show('file_exists', 3000);
- self.filenameEdit_.value = name;
- self.onFilenameClick_();
- }
-
- dir.getFile(newName, {create: false, exclusive: false},
- onVictimFound, doRename);
-};
-
-/**
- * @return {Boolean} True if file renaming is currently in progress
- * @private
- */
-Gallery.prototype.isRenaming_ = function() {
- return this.filenameSpacer_.hasAttribute('renaming');
-};
-
-/**
- * @return {Object} File browser private API.
- */
-Gallery.getFileBrowserPrivate = function() {
- return chrome.fileBrowserPrivate || window.top.chrome.fileBrowserPrivate;
-};
-
-/**
- * Switches gallery to fullscreen mode and back
- * @private
- */
-Gallery.prototype.toggleFullscreen_ = function() {
- Gallery.getFileBrowserPrivate().toggleFullscreen();
-};
-
-/**
- * Close the Gallery.
- * @private
- */
-Gallery.prototype.close_ = function() {
- Gallery.getFileBrowserPrivate().isFullscreen(function(fullscreen) {
- if (this.originalFullscreen_ != fullscreen) {
- Gallery.getFileBrowserPrivate().toggleFullscreen();
- }
- this.context_.onClose();
- }.bind(this));
-};
-
-/**
- * Handle user's 'Close' action (Escape or a click on the X icon).
- * @private
- */
-Gallery.prototype.onClose_ = function() {
- // TODO: handle write errors gracefully (suggest retry or saving elsewhere).
- this.editor_.executeWhenReady(this.close_.bind(this));
-};
-
-Gallery.prototype.prefetchImage = function(id, url) {
- this.editor_.prefetchImage(id, url);
-};
-
-Gallery.prototype.openImage = function(id, url, metadata, slide, callback) {
- this.selectedImageMetadata_ = ImageUtil.deepCopy(metadata);
- this.updateFilename_(url);
- if (this.ribbon_.getSelectedItem()) {
- // In edit mode, read overwrite setting.
- // In view mode, don't change the name, so passing |true|.
- if (this.isEditing_()) {
- this.applyDefaultOverwrite_();
- } else {
- this.applyOverwrite_(true);
- }
-
- if (!this.ribbon_.getSelectedItem().isOriginal()) {
- // For once edited image, do not allow the 'overwrite' setting.
- ImageUtil.setAttribute(this.filenameSpacer_, 'saved', true);
- } else {
- ImageUtil.setAttribute(this.filenameSpacer_, 'saved', false);
- }
- }
-
- this.showSpinner_(true);
-
- var self = this;
- function loadDone(loadType) {
- var video = self.isShowingVideo_();
- ImageUtil.setAttribute(self.container_, 'video', video);
-
- self.showSpinner_(false);
- if (loadType == ImageView.LOAD_TYPE_ERROR) {
- self.showErrorBanner_(video ? 'VIDEO_ERROR' : 'IMAGE_ERROR');
- } else if (loadType == ImageView.LOAD_TYPE_OFFLINE) {
- self.showErrorBanner_(video ? 'VIDEO_OFFLINE' : 'IMAGE_OFFLINE');
- }
-
- if (video) {
- if (self.isEditing_()) {
- // The editor toolbar does not make sense for video, hide it.
- self.onEdit_();
- }
- self.mediaControls_.attachMedia(self.imageView_.getVideo());
- //TODO(kaznacheev): Add metrics for video playback.
- } else {
- ImageUtil.metrics.recordUserAction(ImageUtil.getMetricName('View'));
-
- function toMillions(number) { return Math.round(number / (1000 * 1000)) }
-
- ImageUtil.metrics.recordSmallCount(ImageUtil.getMetricName('Size.MB'),
- toMillions(metadata.filesystem.size));
-
- var canvas = self.imageView_.getCanvas();
- ImageUtil.metrics.recordSmallCount(ImageUtil.getMetricName('Size.MPix'),
- toMillions(canvas.width * canvas.height));
-
- var extIndex = url.lastIndexOf('.');
- var ext = extIndex < 0 ? '' : url.substr(extIndex + 1).toLowerCase();
- if (ext == 'jpeg') ext = 'jpg';
- ImageUtil.metrics.recordEnum(
- ImageUtil.getMetricName('FileType'), ext, ImageUtil.FILE_TYPES);
- }
-
- callback(loadType);
- }
-
- this.editor_.openSession(
- id, url, metadata, slide, this.saveCurrentImage_.bind(this), loadDone);
-};
-
-//TODO(JSDOC)
-Gallery.prototype.closeImage = function(callback) {
- this.showSpinner_(false);
- this.showErrorBanner_(false);
- this.editor_.getPrompt().hide();
- if (this.isShowingVideo_()) {
- this.mediaControls_.pause();
- this.mediaControls_.detachMedia();
- }
- this.editor_.closeSession(callback);
-};
-
-Gallery.prototype.showSpinner_ = function(on) {
- if (this.spinnerTimer_) {
- clearTimeout(this.spinnerTimer_);
- this.spinnerTimer_ = null;
- }
-
- if (on) {
- this.spinnerTimer_ = setTimeout(function() {
- this.spinnerTimer_ = null;
- ImageUtil.setAttribute(this.container_, 'spinner', true);
- }.bind(this), 1000);
- } else {
- ImageUtil.setAttribute(this.container_, 'spinner', false);
- }
-};
-
-Gallery.prototype.showErrorBanner_ = function(message) {
- if (message) {
- this.errorBanner_.textContent = this.displayStringFunction_(message);
- }
- ImageUtil.setAttribute(this.container_, 'error', !!message);
-};
-
-Gallery.prototype.isShowingVideo_ = function() {
- return !!this.imageView_.getVideo();
-};
-
-Gallery.prototype.saveVideoPosition_ = function() {
- if (this.isShowingVideo_() && this.mediaControls_.isPlaying()) {
- this.mediaControls_.savePosition();
- }
-};
-
-Gallery.prototype.onUnload_ = function() {
- this.saveVideoPosition_();
- window.top.removeEventListener('beforeunload', this.onBeforeUnloadBound_);
- window.top.removeEventListener('unload', this.onTopUnloadBound_);
-};
-
-Gallery.prototype.onTopUnload_ = function() {
- this.saveVideoPosition_();
-};
-
-Gallery.prototype.isEditing_ = function() {
- return this.container_.hasAttribute('editing');
-};
-
-Gallery.prototype.onEdit_ = function() {
- ImageUtil.setAttribute(this.container_, 'editing', !this.isEditing_());
-
- // The user has just clicked on the Edit button. Dismiss the Share menu.
- if (this.isSharing_()) {
- this.onShare_();
- }
-
- // isEditing_ has just been flipped to a new value.
- if (this.isEditing_()) {
- this.applyDefaultOverwrite_();
- if (this.context_.readonlyDirName) {
- this.editor_.getPrompt().showAt(
- 'top', 'readonly_warning', 0, this.context_.readonlyDirName);
- }
- this.cancelFading_();
- } else {
- this.applyOverwrite_(true);
- this.editor_.getPrompt().hide();
- this.initiateFading_();
- }
-
- ImageUtil.setAttribute(this.editButton_, 'pressed', this.isEditing_());
-};
-
-Gallery.prototype.isSharing_ = function(event) {
- return this.shareMode_ && this.shareMode_ == this.editor_.getMode();
-};
-
-Gallery.prototype.onShare_ = function(event) {
- this.editor_.enterMode(this.shareMode_, event);
- if (this.isSharing_()) {
- this.cancelFading_();
- } else {
- this.initiateFading_();
- }
-};
-
-Gallery.prototype.onKeyDown_ = function(event) {
- if (this.isEditing_() && this.editor_.onKeyDown(event))
- return;
-
- switch (util.getKeyModifiers(event) + event.keyIdentifier) {
- case 'U+0008': // Backspace.
- // The default handler would call history.back and close the Gallery.
- event.preventDefault();
- break;
-
- case 'U+001B': // Escape
- if (this.isEditing_()) {
- this.onEdit_();
- } else if (this.isSharing_()) {
- this.onShare_();
- } else {
- this.onClose_();
- }
- break;
-
- case 'U+0045': // 'e' toggles the editor
- if (!this.isShowingVideo_()) {
- this.onEdit_();
- }
- break;
-
- case 'U+0020': // Space toggles the video playback.
- if (this.isShowingVideo_()) {
- this.mediaControls_.togglePlayStateWithFeedback();
- }
- break;
-
- case 'Home':
- this.ribbon_.selectFirst();
- break;
- case 'Left':
- this.ribbon_.selectNext(-1);
- break;
- case 'Right':
- this.ribbon_.selectNext(1);
- break;
- case 'End':
- this.ribbon_.selectLast();
- break;
-
- case 'Ctrl-U+00DD': // Ctrl+] (cryptic on purpose).
- this.ribbon_.toggleDebugSlideshow();
- break;
- }
-};
-
-Gallery.prototype.onMouseMove_ = function(e) {
- if (this.clientX_ == e.clientX && this.clientY_ == e.clientY) {
- // The mouse has not moved, must be the cursor change triggered by
- // some of the attributes on the root container. Ignore the event.
- return;
- }
- this.clientX_ = e.clientX;
- this.clientY_ = e.clientY;
-
- this.cancelFading_();
-
- this.mouseOverTool_ = false;
- for (var elem = e.target; elem != this.container_; elem = elem.parentNode) {
- if (elem.classList.contains('tool')) {
- this.mouseOverTool_ = true;
- break;
- }
- }
-
- this.initiateFading_();
-};
-
-Gallery.prototype.onFadeTimeout_ = function() {
- this.fadeTimeoutId_ = null;
- if (this.isEditing_() || this.isSharing_() || this.isRenaming_()) return;
- ImageUtil.setAttribute(this.container_, 'tools', false);
-};
-
-Gallery.prototype.initiateFading_ = function(opt_timeout) {
- if (this.mouseOverTool_ || this.isEditing_() || this.isSharing_() ||
- this.isRenaming_())
- return;
-
- if (!this.fadeTimeoutId_)
- this.fadeTimeoutId_ = window.setTimeout(
- this.onFadeTimeoutBound_, opt_timeout || Gallery.FADE_TIMEOUT);
-};
-
-Gallery.prototype.cancelFading_ = function() {
- ImageUtil.setAttribute(this.container_, 'tools', true);
-
- if (this.fadeTimeoutId_) {
- window.clearTimeout(this.fadeTimeoutId_);
- this.fadeTimeoutId_ = null;
- }
-};
-
-//TODO(JSDOC)
-function Ribbon(document, client, metadataCache, arrowLeft, arrowRight) {
- var self = document.createElement('div');
- Ribbon.decorate(self, client, metadataCache, arrowLeft, arrowRight);
- return self;
-}
-
-Ribbon.prototype.__proto__ = HTMLDivElement.prototype;
-
-//TODO(JSDOC)
-Ribbon.decorate = function(
- self, client, metadataCache, arrowLeft, arrowRight) {
- self.__proto__ = Ribbon.prototype;
- self.client_ = client;
- self.metadataCache_ = metadataCache;
-
- self.items_ = [];
- self.selectedIndex_ = -1;
-
- self.arrowLeft_ = arrowLeft;
- self.arrowLeft_.
- addEventListener('click', self.selectNext.bind(self, -1, null));
-
- self.arrowRight_ = arrowRight;
- self.arrowRight_.
- addEventListener('click', self.selectNext.bind(self, 1, null));
-
- self.className = 'ribbon';
-};
-
-//TODO(JSDOC)
-Ribbon.PAGING_SINGLE_ITEM_DELAY = 20;
-
-//TODO(JSDOC)
-Ribbon.PAGING_ANIMATION_DURATION = 200;
-
-/**
- * @return {Ribbon.Item?} The selected item.
- */
-Ribbon.prototype.getSelectedItem = function() {
- return this.items_[this.selectedIndex_];
-};
-
-//TODO(JSDOC)
-Ribbon.prototype.clear = function() {
- this.textContent = '';
- this.items_ = [];
- this.selectedIndex_ = -1;
- this.firstVisibleIndex_ = 0;
- this.lastVisibleIndex_ = -1; // Zero thumbnails
- this.sequenceDirection_ = 0;
- this.sequenceLength_ = 0;
-};
-
-//TODO(JSDOC)
-Ribbon.prototype.add = function(url) {
- var index = this.items_.length;
- var item = new Ribbon.Item(this.ownerDocument, index, url);
- item.addEventListener('click', this.select.bind(this, index, 0, null));
- this.items_.push(item);
-};
-
-//TODO(JSDOC)
-Ribbon.prototype.load = function(urls, selectedIndex) {
- this.clear();
- for (var index = 0; index < urls.length; ++index) {
- this.add(urls[index]);
- }
- this.selectedIndex_ = selectedIndex;
-
- // We do not want to call this.select because the selected image is already
- // displayed. Instead we just update the UI.
- this.getSelectedItem().select(true);
- this.redraw();
-
- // Let the thumbnails load before prefetching the next image.
- setTimeout(this.requestPrefetch.bind(this, 1), 1000);
-
- // Make the arrows visible if there are more than 1 image.
- ImageUtil.setAttribute(this.arrowLeft_, 'active', this.items_.length > 1);
- ImageUtil.setAttribute(this.arrowRight_, 'active', this.items_.length > 1);
-};
-
-//TODO(JSDOC)
-Ribbon.prototype.select = function(index, opt_forceStep, opt_callback) {
- if (index == this.selectedIndex_)
- return; // Do not reselect.
-
- this.client_.closeImage(
- this.doSelect_.bind(this, index, opt_forceStep, opt_callback));
-};
-
-//TODO(JSDOC)
-Ribbon.prototype.doSelect_ = function(index, opt_forceStep, opt_callback) {
- if (index == this.selectedIndex_)
- return; // Do not reselect
-
- var selectedItem = this.getSelectedItem();
- selectedItem.select(false);
-
- var step = opt_forceStep || (index - this.selectedIndex_);
-
- if (Math.abs(step) != 1) {
- // Long leap, the sequence is broken, we have no good prefetch candidate.
- this.sequenceDirection_ = 0;
- this.sequenceLength_ = 0;
- } else if (this.sequenceDirection_ == step) {
- // Keeping going in sequence.
- this.sequenceLength_++;
- } else {
- // Reversed the direction. Reset the counter.
- this.sequenceDirection_ = step;
- this.sequenceLength_ = 1;
- }
-
- if (this.sequenceLength_ <= 1) {
- // We have just broke the sequence. Touch the current image so that it stays
- // in the cache longer.
- this.client_.prefetchImage(selectedItem.getIndex(), selectedItem.getUrl());
- }
-
- this.selectedIndex_ = index;
-
- selectedItem = this.getSelectedItem();
- selectedItem.select(true);
- this.redraw();
-
- function shouldPrefetch(loadType, step, sequenceLength) {
- // Never prefetch when selecting out of sequence.
- if (Math.abs(step) != 1)
- return false;
-
- // Never prefetch after a video load (decoding the next image can freeze
- // the UI for a second or two).
- if (loadType == ImageView.LOAD_TYPE_VIDEO_FILE)
- return false;
-
- // Always prefetch if the previous load was from cache.
- if (loadType == ImageView.LOAD_TYPE_CACHED_FULL)
- return true;
-
- // Prefetch if we have been going in the same direction for long enough.
- return sequenceLength >= 3;
- }
-
- var self = this;
- function onMetadata(metadata) {
- if (!selectedItem.isSelected()) return;
- self.client_.openImage(
- selectedItem.getIndex(), selectedItem.getUrl(), metadata, step,
- function(loadType) {
- if (!selectedItem.isSelected()) return;
- if (shouldPrefetch(loadType, step, self.sequenceLength_)) {
- self.requestPrefetch(step);
- }
- if (opt_callback) opt_callback();
- });
- }
- this.metadataCache_.get(selectedItem.getUrl(),
- Gallery.METADATA_TYPE, onMetadata);
-};
-
-//TODO(JSDOC)
-Ribbon.prototype.requestPrefetch = function(direction) {
- if (this.items_.length < 2) return;
-
- var index = this.getNextSelectedIndex_(direction);
- var nextItemUrl = this.items_[index].getUrl();
-
- var selectedItem = this.getSelectedItem();
- this.metadataCache_.get(nextItemUrl, Gallery.METADATA_TYPE,
- function(metadata) {
- if (!selectedItem.isSelected()) return;
- this.client_.prefetchImage(index, nextItemUrl, metadata);
- }.bind(this));
-};
-
-//TODO(JSDOC)
-Ribbon.ITEMS_COUNT = 5;
-
-//TODO(JSDOC)
-Ribbon.prototype.redraw = function() {
- // Never show a single thumbnail.
- if (this.items_.length == 1)
- return;
-
- var initThumbnail = function(index) {
- var item = this.items_[index];
- if (!item.hasThumbnail())
- this.metadataCache_.get(item.getUrl(), Gallery.METADATA_TYPE,
- item.setThumbnail.bind(item));
- }.bind(this);
-
- // TODO(dgozman): use margin instead of 2 here.
- var itemWidth = this.clientHeight - 2;
- var fullItems = Ribbon.ITEMS_COUNT;
- fullItems = Math.min(fullItems, this.items_.length);
- var right = Math.floor((fullItems - 1) / 2);
-
- var fullWidth = fullItems * itemWidth;
- this.style.width = fullWidth + 'px';
-
- var lastIndex = this.selectedIndex_ + right;
- lastIndex = Math.max(lastIndex, fullItems - 1);
- lastIndex = Math.min(lastIndex, this.items_.length - 1);
- var firstIndex = lastIndex - fullItems + 1;
-
- if (this.firstVisibleIndex_ == firstIndex &&
- this.lastVisibleIndex_ == lastIndex) {
- return;
- }
-
- if (this.lastVisibleIndex_ == -1) {
- this.firstVisibleIndex_ = firstIndex;
- this.lastVisibleIndex_ = lastIndex;
- }
-
- this.textContent = '';
- var startIndex = Math.min(firstIndex, this.firstVisibleIndex_);
- var toRemove = [];
- // All the items except the first one treated equally.
- for (var index = startIndex + 1;
- index <= Math.max(lastIndex, this.lastVisibleIndex_);
- ++index) {
- initThumbnail(index);
- var box = this.items_[index];
- box.style.marginLeft = '0';
- this.appendChild(box);
- if (index < firstIndex || index > lastIndex) {
- toRemove.push(index);
- }
- }
-
- var margin = itemWidth * Math.abs(firstIndex - this.firstVisibleIndex_);
- initThumbnail(startIndex);
- var startBox = this.items_[startIndex];
- if (startIndex == firstIndex) {
- // Sliding to the right.
- startBox.style.marginLeft = -margin + 'px';
- if (this.firstChild)
- this.insertBefore(startBox, this.firstChild);
- else
- this.appendChild(startBox);
- setTimeout(function() {
- startBox.style.marginLeft = '0';
- }, 0);
- } else {
- // Sliding to the left. Start item will become invisible and should be
- // removed afterwards.
- toRemove.push(startIndex);
- startBox.style.marginLeft = '0';
- if (this.firstChild)
- this.insertBefore(startBox, this.firstChild);
- else
- this.appendChild(startBox);
- setTimeout(function() {
- startBox.style.marginLeft = -margin + 'px';
- }, 0);
- }
-
- ImageUtil.setClass(this, 'fade-left',
- firstIndex > 0 && this.selectedIndex_ != firstIndex);
-
- ImageUtil.setClass(this, 'fade-right',
- lastIndex < this.items_.length - 1 && this.selectedIndex_ != lastIndex);
-
- this.firstVisibleIndex_ = firstIndex;
- this.lastVisibleIndex_ = lastIndex;
-
- setTimeout(function() {
- for (var i = 0; i < toRemove.length; i++) {
- var index = toRemove[i];
- if (index < this.firstVisibleIndex_ || index > this.lastVisibleIndex_) {
- var box = this.items_[index];
- if (box.parentNode == this)
- this.removeChild(box);
- }
- }
- }.bind(this), 200);
-};
-
-//TODO(JSDOC)
-Ribbon.prototype.getNextSelectedIndex_ = function(direction) {
- var index = this.selectedIndex_ + (direction > 0 ? 1 : -1);
- if (index == -1) return this.items_.length - 1;
- if (index == this.items_.length) return 0;
- return index;
-};
-
-//TODO(JSDOC)
-Ribbon.prototype.selectNext = function(direction, opt_callback) {
- this.select(this.getNextSelectedIndex_(direction), direction, opt_callback);
-};
-
-//TODO(JSDOC)
-Ribbon.prototype.selectFirst = function() {
- this.select(0);
-};
-
-//TODO(JSDOC)
-Ribbon.prototype.selectLast = function() {
- this.select(this.items_.length - 1);
-};
-
-/**
- * Start/stop the slide show. This is useful for performance debugging and
- * available only through a cryptic keyboard shortcut.
- */
-Ribbon.prototype.toggleDebugSlideshow = function() {
- if (this.slideShowTimeout_) {
- clearInterval(this.slideShowTimeout_);
- this.slideShowTimeout_ = null;
- } else {
- var self = this;
- function nextSlide() {
- self.selectNext(1,
- function() { self.slideShowTimeout_ = setTimeout(nextSlide, 5000) });
- }
- nextSlide();
- }
-};
-
-//TODO(JSDOC)
-Ribbon.Item = function(document, index, url) {
- var self = document.createElement('div');
- Ribbon.Item.decorate(self, index, url);
- return self;
-};
-
-Ribbon.Item.prototype.__proto__ = HTMLDivElement.prototype;
-
-//TODO(JSDOC)
-Ribbon.Item.decorate = function(self, index, url, selectClosure) {
- self.__proto__ = Ribbon.Item.prototype;
- self.index_ = index;
- self.url_ = url;
-
- self.className = 'ribbon-image';
-
- var wrapper = self.ownerDocument.createElement('div');
- wrapper.className = 'image-wrapper';
- self.appendChild(wrapper);
-
- self.original_ = true;
- self.nameForSaving_ = null;
-};
-
-//TODO(JSDOC)
-Ribbon.Item.prototype.getIndex = function() { return this.index_ };
-
-//TODO(JSDOC)
-Ribbon.Item.prototype.isOriginal = function() { return this.original_ };
-
-//TODO(JSDOC)
-Ribbon.Item.prototype.getUrl = function() { return this.url_ };
-
-//TODO(JSDOC)
-Ribbon.Item.prototype.setUrl = function(url) { this.url_ = url };
-
-//TODO(JSDOC)
-Ribbon.Item.prototype.getNameAfterSaving = function() {
- return this.nameForSaving_ || ImageUtil.getFullNameFromUrl(this.url_);
-};
-
-//TODO(JSDOC)
-Ribbon.Item.prototype.hasNameForSaving = function() {
- return !!this.nameForSaving_;
-};
-
-//TODO(JSDOC)
-Ribbon.Item.prototype.isSelected = function() {
- return this.hasAttribute('selected');
-};
-
-//TODO(JSDOC)
-Ribbon.Item.prototype.select = function(on) {
- ImageUtil.setAttribute(this, 'selected', on);
-};
-
-//TODO(JSDOC)
-Ribbon.Item.prototype.saveToFile = function(
- dirEntry, canvas, metadataEncoder, opt_callback) {
- ImageUtil.metrics.startInterval(ImageUtil.getMetricName('SaveTime'));
-
- var self = this;
-
- var name = this.getNameAfterSaving();
- // If we do overwrite original, keep this one as 'original'.
- this.original_ = this.nameForSaving_ == null;
- this.nameForSaving_ = null;
-
- function onSuccess(url) {
- console.log('Saved from gallery', name);
- ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('SaveResult'), 1, 2);
- ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('SaveTime'));
- self.setUrl(url);
- if (opt_callback) opt_callback(true);
- }
-
- function onError(error) {
- console.log('Error saving from gallery', name, error);
- ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('SaveResult'), 0, 2);
- if (opt_callback) opt_callback(false);
- }
-
- function doSave(newFile, fileEntry) {
- fileEntry.createWriter(function(fileWriter) {
- function writeContent() {
- fileWriter.onwriteend = onSuccess.bind(null, fileEntry.toURL());
- fileWriter.write(ImageEncoder.getBlob(canvas, metadataEncoder));
- }
- fileWriter.onerror = function(error) {
- onError(error);
- // Disable all callbacks on the first error.
- fileWriter.onerror = null;
- fileWriter.onwriteend = null;
- };
- if (newFile) {
- writeContent();
- } else {
- fileWriter.onwriteend = writeContent;
- fileWriter.truncate(0);
- }
- }, onError);
- }
-
- function getFile(newFile) {
- dirEntry.getFile(name, {create: newFile, exclusive: newFile},
- doSave.bind(null, newFile), onError);
- }
-
- dirEntry.getFile(name, {create: false, exclusive: false},
- getFile.bind(null, false /* existing file */),
- getFile.bind(null, true /* create new file */));
-};
-
-// TODO: Localize?
-//TODO(JSDOC)
-Ribbon.Item.COPY_SIGNATURE = 'Edited';
-
-//TODO(JSDOC)
-Ribbon.Item.REGEXP_COPY_N =
- new RegExp('^' + Ribbon.Item.COPY_SIGNATURE + ' \\((\\d+)\\)( - .+)$');
-
-//TODO(JSDOC)
-Ribbon.Item.REGEXP_COPY_0 =
- new RegExp('^' + Ribbon.Item.COPY_SIGNATURE + '( - .+)$');
-
-//TODO(JSDOC)
-Ribbon.Item.prototype.createCopyName_ = function(dirEntry, metadata, callback) {
- var name = ImageUtil.getFullNameFromUrl(this.url_);
-
- // If the item represents a file created during the current Gallery session
- // we reuse it for subsequent saves instead of creating multiple copies.
- if (!this.original_)
- return name;
-
- var ext = '';
- var index = name.lastIndexOf('.');
- if (index != -1) {
- ext = name.substr(index);
- name = name.substr(0, index);
- }
-
- var mimeType = metadata.media && metadata.media.mimeType;
- mimeType = (mimeType || '').toLowerCase();
- if (mimeType != 'image/jpeg') {
- // Chrome can natively encode only two formats: JPEG and PNG.
- // All non-JPEG images are saved in PNG, hence forcing the file extension.
- ext = '.png';
- }
-
- function tryNext(tries) {
- // All the names are used. Let's overwrite the last one.
- if (tries == 0) {
- setTimeout(callback, 0, name + ext);
- return;
- }
-
- // If the file name contains the copy signature add/advance the sequential
- // number.
- var matchN = Ribbon.Item.REGEXP_COPY_N.exec(name);
- var match0 = Ribbon.Item.REGEXP_COPY_0.exec(name);
- if (matchN && matchN[1] && matchN[2]) {
- var copyNumber = parseInt(matchN[1], 10) + 1;
- name = Ribbon.Item.COPY_SIGNATURE + ' (' + copyNumber + ')' + matchN[2];
- } else if (match0 && match0[1]) {
- name = Ribbon.Item.COPY_SIGNATURE + ' (1)' + match0[1];
- } else {
- name = Ribbon.Item.COPY_SIGNATURE + ' - ' + name;
- }
-
- dirEntry.getFile(name + ext, {create: false, exclusive: false},
- tryNext.bind(null, tries - 1),
- callback.bind(null, name + ext));
- }
-
- tryNext(10);
-};
-
-//TODO(JSDOC)
-Ribbon.Item.prototype.setCopyName = function(dirEntry, metadata, opt_callback) {
- this.createCopyName_(dirEntry, metadata, function(name) {
- this.nameForSaving_ = name;
- if (opt_callback) opt_callback();
- }.bind(this));
-};
-
-//TODO(JSDOC)
-Ribbon.Item.prototype.setOriginalName = function(dirEntry, opt_callback) {
- this.nameForSaving_ = null;
- if (opt_callback) opt_callback();
-};
-
-//TODO(JSDOC)
-Ribbon.Item.prototype.setNameForSaving = function(newName) {
- this.nameForSaving_ = newName;
-};
-
-//TODO(JSDOC)
-Ribbon.Item.prototype.hasThumbnail = function() {
- return !!this.querySelector('img[src]');
-};
-
-//TODO(JSDOC)
-Ribbon.Item.prototype.setThumbnail = function(metadata) {
- new ThumbnailLoader(this.url_, metadata).
- load(this.querySelector('.image-wrapper'), true /* fill */);
-};
-
-//TODO(JSDOC)
-function ShareMode(editor, container, toolbar, shareActions,
- onClick, actionCallback, displayStringFunction) {
- ImageEditor.Mode.call(this, 'share');
-
- this.message_ = null;
-
- var doc = container.ownerDocument;
- var button = doc.createElement('div');
- button.className = 'button share';
- button.textContent = displayStringFunction('share');
- button.addEventListener('click', onClick);
- toolbar.appendChild(button);
-
- this.bind(editor, button);
-
- this.menu_ = doc.createElement('div');
- this.menu_.className = 'share-menu';
- this.menu_.hidden = true;
- for (var index = 0; index < shareActions.length; index++) {
- var action = shareActions[index];
- var row = doc.createElement('div');
- var img = doc.createElement('img');
- img.src = action.iconUrl;
- row.appendChild(img);
- row.appendChild(doc.createTextNode(action.title));
- row.addEventListener('click', actionCallback.bind(null, action));
- this.menu_.appendChild(row);
- }
- var arrow = doc.createElement('div');
- arrow.className = 'bubble-point';
- this.menu_.appendChild(arrow);
- container.appendChild(this.menu_);
-}
-
-ShareMode.prototype = { __proto__: ImageEditor.Mode.prototype };
-
-/**
- * Shows share mode UI.
- */
-ShareMode.prototype.setUp = function() {
- ImageEditor.Mode.prototype.setUp.apply(this, arguments);
- this.menu_.hidden = false;
- ImageUtil.setAttribute(this.button_, 'pressed', false);
-};
-
-/**
- * Hides share mode UI.
- */
-ShareMode.prototype.cleanUpUI = function() {
- ImageEditor.Mode.prototype.cleanUpUI.apply(this, arguments);
- this.menu_.hidden = true;
-};
-
-/**
- * Overlay that handles swipe gestures. Changes to the next or previous file.
- * @param {Ribbon} ribbon Ribbon to handle swipes.
- * @constructor
- * @implements {ImageBuffer.Overlay}
- */
-function SwipeOverlay(ribbon) {
- this.ribbon_ = ribbon;
-}
-
-SwipeOverlay.prototype.__proto__ = ImageBuffer.Overlay.prototype;
-
-/**
- * @param {number} x X pointer position.
- * @param {number} y Y pointer position.
- * @param {boolean} touch True if dragging caused by touch.
- * @return {function} The closure to call on drag.
- */
-SwipeOverlay.prototype.getDragHandler = function(x, y, touch) {
- if (!touch)
- return null;
- var origin = x;
- var done = false;
- var self = this;
- return function(x, y) {
- if (!done && origin - x > SwipeOverlay.SWIPE_THRESHOLD) {
- self.handleSwipe_(1);
- done = true;
- } else if (!done && x - origin > SwipeOverlay.SWIPE_THRESHOLD) {
- self.handleSwipe_(-1);
- done = true;
- }
- };
-};
-
-/**
- * Called when the swipe gesture is recognized.
- * @param {number} direction 1 means swipe to left, -1 swipe to right.
- * @private
- */
-SwipeOverlay.prototype.handleSwipe_ = function(direction) {
- this.ribbon_.selectNext(direction);
-};
-
-/**
- * If the user touched the image and moved the finger more than SWIPE_THRESHOLD
- * horizontally it's considered as a swipe gesture (change the current image).
- */
-SwipeOverlay.SWIPE_THRESHOLD = 100;

Powered by Google App Engine
This is Rietveld 408576698