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 3// found in the LICENSE file. 4 5/** 6 * Item used in preview grid view. 7 * @param {picasa.LocalFile} dataItem Data item. 8 * @extends {cr.ui.GridItem} 9 */ 10function PreviewItem(dataItem) { 11 var item = new cr.ui.GridItem(dataItem); 12 item.__proto__ = PreviewItem.prototype; 13 return item; 14} 15 16PreviewItem.prototype = { 17 __proto__: cr.ui.GridItem.prototype, 18 19 /** 20 * Called to initialize element. 21 */ 22 decorate: function() { 23 cr.ui.GridItem.prototype.decorate.call(this, arguments); 24 this.textContent = ''; 25 this.className = 'preview-item'; 26 27 var div = this.ownerDocument.createElement('div'); 28 this.appendChild(div); 29 30 var img = this.ownerDocument.createElement('img'); 31 this.dataItem.showInImage(img); 32 div.appendChild(img); 33 } 34}; 35 36 37/** 38 * UploadPage constructor. 39 * 40 * UploadPage object is responsible for manipulating upload page. 41 */ 42function UploadPage() { 43 this.files_ = new cr.ui.ArrayDataModel([]); 44 this.files_.addEventListener('splice', this.handleOnFilesChanged_.bind(this)); 45 46 this.title_ = document.querySelector('.header-title'); 47 48 this.loginDiv_ = document.querySelector('.login-div'); 49 this.loginInput_ = document.getElementById('login-input'); 50 this.passwordInput_ = document.getElementById('password-input'); 51 this.captchaRow_ = document.querySelector('.captcha-row'); 52 this.captchaImage_ = document.querySelector('.captcha-row img'); 53 this.captchaInput_ = document.getElementById('captcha-input'); 54 this.loginFailure_ = document.querySelector('.login-failure'); 55 this.loginButton_ = document.querySelector('.login-button'); 56 this.loginButton_.addEventListener('click', 57 this.handleOnLoginClicked_.bind(this)); 58 59 var buttons = document.querySelectorAll('.cancel-button'); 60 for (var i = 0; i < buttons.length; i++) { 61 buttons[i].addEventListener('click', this.close_.bind(this)); 62 } 63 64 this.albumDiv_ = document.querySelector('.album-div'); 65 this.filesCountSpan_ = document.getElementById('files-count-span'); 66 67 this.albumSelect_ = document.getElementById('album-select'); 68 this.albumSelect_.addEventListener('change', 69 this.handleOnAlbumSelected_.bind(this)); 70 this.albumTitleInput_ = document.getElementById('album-title-input'); 71 this.albumTitleInput_.addEventListener('change', 72 this.handleOnAlbumTitleChanged_.bind(this)); 73 this.albumLocationInput_ = document.getElementById('album-location-input'); 74 this.albumLocationInput_.addEventListener('change', 75 this.handleOnAlbumLocationChanged_.bind(this)); 76 this.albumDescriptionTextarea_ = 77 document.getElementById('album-description-textarea'); 78 this.albumDescriptionTextarea_.addEventListener('change', 79 this.handleOnAlbumDescriptionChanged_.bind(this)); 80 81 this.previewGrid_ = document.querySelector('.preview-grid'); 82 cr.ui.Grid.decorate(this.previewGrid_); 83 this.previewGrid_.itemConstructor = PreviewItem; 84 this.previewGrid_.dataModel = this.files_; 85 this.previewGrid_.selectionModel = new cr.ui.ListSingleSelectionModel(); 86 87 this.uploadButton_ = document.querySelector('.upload-button'); 88 this.uploadButton_.addEventListener('click', 89 this.handleOnUploadClicked_.bind(this)); 90 document.querySelector('.logout-button').addEventListener('click', 91 this.handleOnLogoutClicked_.bind(this)); 92 93 // Login page is shown first. 94 this.showLogin_(); 95 this.client_ = chrome.extension.getBackgroundPage().bg.client; 96 // If user logged in before, skip the login page. 97 if (this.client_.authorized) { 98 this.loginCallback_('success'); 99 } 100} 101 102UploadPage.prototype = { 103 /** 104 * Adds more files to upload. 105 * @param {Array.<picasa.LocalFile>} files The files to add. 106 */ 107 addFiles: function(files) { 108 for (var i = 0; i < files.length; i++) { 109 this.files_.push(files[i]); 110 } 111 }, 112 113 /** 114 * Loads files to upload from background page. 115 */ 116 loadFilesFromBackgroundPage_: function() { 117 var newFiles = chrome.extension.getBackgroundPage().bg.getNewFiles(); 118 this.addFiles(newFiles); 119 }, 120 121 /** 122 * @return {boolean} Whether upload should be enabled. 123 */ 124 canUpload_: function() { 125 return (this.albumTitleInput_.value != '') && 126 (this.files_.length > 0) && this.client_.authorized; 127 }, 128 129 /** 130 * Sets enabled attribute to element. 131 * @param {HTMLElement} elt Element to set enabled on. 132 * @param {boolean} enabled Whether element should be enabled or disabled. 133 */ 134 setEnabled_: function(elt, enabled) { 135 if (enabled) { 136 elt.removeAttribute('disabled'); 137 } else { 138 elt.setAttribute('disabled', 'disabled'); 139 } 140 }, 141 142 /** 143 * Enables/disables upload button as needed. 144 */ 145 checkUploadButtonEnabled_: function() { 146 this.setEnabled_(this.uploadButton_, this.canUpload_()); 147 }, 148 149 /** 150 * Shows login page. 151 */ 152 showLogin_: function() { 153 this.title_.textContent = 'Sign in to Picasa'; 154 this.loginDiv_.classList.remove('invisible'); 155 this.albumDiv_.classList.add('invisible'); 156 this.captchaRow_.classList.add('invisible'); 157 }, 158 159 /** 160 * Shows the number of upload files. 161 */ 162 showFilesCount_: function() { 163 this.filesCountSpan_.textContent = '' + this.files_.length; 164 }, 165 166 /** 167 * Shows the "choose album" page. 168 */ 169 showChooseAlbum_: function() { 170 this.title_.textContent = 'Choose an Album'; 171 this.checkUploadButtonEnabled_(); 172 this.loginDiv_.classList.add('invisible'); 173 this.albumDiv_.classList.remove('invisible'); 174 this.showFilesCount_(); 175 }, 176 177 /** 178 * Event handler for files list changed. 179 * @param {Event} e Event. 180 */ 181 handleOnFilesChanged_: function(e) { 182 this.showFilesCount_(); 183 this.checkUploadButtonEnabled_(); 184 }, 185 186 /** 187 * Callback from picasa client after login. 188 * @param {string} status Login status: success, failure or captcha. 189 */ 190 loginCallback_: function(status) { 191 this.setEnabled_(this.loginButton_, true); 192 if (status == 'success') { 193 this.loginFailure_.classList.add('invisible'); 194 this.showChooseAlbum_(); 195 this.loadFilesFromBackgroundPage_(); 196 this.client_.getAlbums(this.getAlbumsCallback_.bind(this)); 197 } else if (status == 'captcha') { 198 this.captchaRow_.classList.remove('invisible'); 199 this.captchaImage_.setAttribute('src', this.client_.captchaUrl); 200 } else if (status == 'failure') { 201 this.loginFailure_.classList.remove('invisible'); 202 } 203 }, 204 205 /** 206 * Event handler for login button clicked. 207 * @param {Event} e Event. 208 */ 209 handleOnLoginClicked_: function(e) { 210 this.setEnabled_(this.loginButton_, false); 211 var password = this.passwordInput_.value; 212 this.passwordInput_.value = ''; 213 var captcha = this.client_.captchaUrl ? this.captchaInput_.value : null; 214 this.client_.login(this.loginInput_.value, password, 215 this.loginCallback_.bind(this), captcha); 216 }, 217 218 /** 219 * Callback from picasa client after getting albums list. 220 * @param {Array.<picasa.Album>} albums Albums list. 221 */ 222 getAlbumsCallback_: function(albums) { 223 // Adding fake album with id=null. 224 this.client_.albums.push( 225 new picasa.Album(null, 'Create New Album', '', '', '')); 226 albums = this.client_.albums; 227 this.albumSelect_.options.length = 0; 228 for (var album, i = 0; album = albums[i]; i++) { 229 this.albumSelect_.options[i] = new Option(album.title, i); 230 } 231 this.albumSelect_.selectedIndex = albums.length - 1; 232 albums[albums.length - 1].title = ''; 233 this.handleOnAlbumSelected_(null); 234 }, 235 236 /** 237 * Event handler for logout button clicked. 238 * @param {Event} e Event. 239 */ 240 handleOnLogoutClicked_: function(e) { 241 this.client_.logout(); 242 this.showLogin_(); 243 }, 244 245 /** 246 * Event handler for album selection changed. 247 * @param {Event} e Event. 248 */ 249 handleOnAlbumSelected_: function(e) { 250 var album = this.client_.albums[this.albumSelect_.selectedIndex]; 251 var enabled = album.id == null; 252 this.setEnabled_(this.albumTitleInput_, enabled); 253 this.setEnabled_(this.albumLocationInput_, enabled); 254 this.setEnabled_(this.albumDescriptionTextarea_, enabled); 255 this.albumTitleInput_.value = album.title; 256 this.albumLocationInput_.value = album.location; 257 this.albumDescriptionTextarea_.value = album.description; 258 this.checkUploadButtonEnabled_(); 259 }, 260 261 /** 262 * Event handler for upload button clicked. 263 * @param {Event} e Event. 264 */ 265 handleOnUploadClicked_: function(e) { 266 this.setEnabled_(this.uploadButton_, false); 267 var album = this.client_.albums[this.albumSelect_.selectedIndex]; 268 if (album.id == null) { 269 this.client_.createAlbum(album, this.createAlbumCallback_.bind(this)); 270 } else { 271 this.createAlbumCallback_(album); 272 } 273 }, 274 275 /** 276 * Callback from picasa client after album created. 277 * @param {Event} e Event. 278 */ 279 createAlbumCallback_: function(album) { 280 if (!album) { 281 this.setEnabled_(this.uploadButton_, true); 282 alert('Failed to create album.\nTry again.'); 283 return; 284 } 285 286 var files = []; 287 for (var i = 0; i < this.files_.length; i++) { 288 files.push(this.files_.item(i)); 289 } 290 291 chrome.extension.getBackgroundPage().bg.uploadFiles(files, album); 292 this.close_(); 293 }, 294 295 /** 296 * Event handler for album title changed. 297 * @param {Event} e Event. 298 */ 299 handleOnAlbumTitleChanged_: function(e) { 300 var album = this.client_.albums[this.albumSelect_.selectedIndex]; 301 album.title = this.albumTitleInput_.value; 302 this.checkUploadButtonEnabled_(); 303 }, 304 305 /** 306 * Event handler for album location changed. 307 * @param {Event} e Event. 308 */ 309 handleOnAlbumLocationChanged_: function(e) { 310 var album = this.client_.albums[this.albumSelect_.selectedIndex]; 311 album.location = this.albumLocationInput_.value; 312 }, 313 314 /** 315 * Event handler for album description changed. 316 * @param {Event} e Event. 317 */ 318 handleOnAlbumDescriptionChanged_: function(e) { 319 var album = this.client_.albums[this.albumSelect_.selectedIndex]; 320 album.description = this.albumDescriptionTextarea_.value; 321 }, 322 323 /** 324 * Closes the upload page. 325 */ 326 close_: function() { 327 window.close(); 328 } 329}; 330 331var uploadPage = new UploadPage(); 332