OLD | NEW |
(Empty) | |
| 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 function Gallery(container, closeCallback) { |
| 6 this.container_ = container; |
| 7 this.document_ = container.ownerDocument; |
| 8 this.editing_ = false; |
| 9 this.closeCallback_ = closeCallback; |
| 10 this.onFadeTimeoutBound_ = this.onFadeTimeout_.bind(this); |
| 11 this.fadeTimeoutId_ = null; |
| 12 this.initDom_(); |
| 13 } |
| 14 |
| 15 Gallery.open = function(parentDirEntry, entries, closeCallback) { |
| 16 var container = document.querySelector('.gallery'); |
| 17 var gallery = new Gallery(container, closeCallback); |
| 18 gallery.load(parentDirEntry, entries); |
| 19 }; |
| 20 |
| 21 // TODO(dgozman): localization. |
| 22 Gallery.CLOSE_LABEL = 'Close'; |
| 23 Gallery.EDIT_LABEL = 'Edit'; |
| 24 Gallery.SHARE_LABEL = 'Share'; |
| 25 |
| 26 Gallery.FADE_TIMEOUT = 5000; |
| 27 |
| 28 Gallery.prototype.initDom_ = function() { |
| 29 var doc = this.document_; |
| 30 this.container_.addEventListener('keydown', this.onKeyDown_.bind(this)); |
| 31 this.container_.addEventListener('mousemove', this.onMouseMove_.bind(this)); |
| 32 |
| 33 this.closeButton_ = doc.createElement('div'); |
| 34 this.closeButton_.className = 'close'; |
| 35 this.closeButton_.textContent = Gallery.CLOSE_LABEL; |
| 36 this.closeButton_.addEventListener('click', this.closeCallback_); |
| 37 this.container_.appendChild(this.closeButton_); |
| 38 |
| 39 this.imageContainer_ = doc.createElement('div'); |
| 40 this.imageContainer_.className = 'image-container'; |
| 41 this.container_.appendChild(this.imageContainer_); |
| 42 |
| 43 this.toolbar_ = doc.createElement('div'); |
| 44 this.toolbar_.className = 'toolbar'; |
| 45 this.container_.appendChild(this.toolbar_); |
| 46 |
| 47 this.ribbon_ = new Ribbon(this.toolbar_, |
| 48 this.onImageSelected_.bind(this)); |
| 49 |
| 50 this.editBar_ = doc.createElement('div'); |
| 51 this.editBar_.className = 'edit-bar'; |
| 52 this.toolbar_.appendChild(this.editBar_); |
| 53 |
| 54 this.editButton_ = doc.createElement('div'); |
| 55 this.editButton_.className = 'button'; |
| 56 this.editButton_.textContent = Gallery.EDIT_LABEL; |
| 57 this.editButton_.addEventListener('click', this.onEdit_.bind(this)); |
| 58 this.toolbar_.appendChild(this.editButton_); |
| 59 |
| 60 this.shareButton_ = doc.createElement('div'); |
| 61 this.shareButton_.className = 'button'; |
| 62 this.shareButton_.textContent = Gallery.SHARE_LABEL; |
| 63 this.shareButton_.addEventListener('click', this.onShare_.bind(this)); |
| 64 this.toolbar_.appendChild(this.shareButton_); |
| 65 |
| 66 this.editor_ = new ImageEditor(this.imageContainer_, this.editBar_, |
| 67 this.onSave_.bind(this), null /*closeCallback*/); |
| 68 }; |
| 69 |
| 70 Gallery.prototype.load = function(parentDirEntry, entries) { |
| 71 this.editBar_.setAttribute('hidden', 'hidden'); |
| 72 this.editButton_.removeAttribute('pressed'); |
| 73 this.shareButton_.removeAttribute('pressed'); |
| 74 |
| 75 this.ribbon_.setEntries(entries); |
| 76 this.parentDirEntry_ = parentDirEntry; |
| 77 |
| 78 if (entries.length == 0) |
| 79 return; |
| 80 |
| 81 this.ribbon_.select(0); |
| 82 this.editor_.resizeFrame(); |
| 83 |
| 84 this.initiateFading_(); |
| 85 }; |
| 86 |
| 87 Gallery.prototype.onSave_ = function(blob) { |
| 88 var name = this.entry_.name; |
| 89 var ext = ''; |
| 90 var index = name.lastIndexOf('.'); |
| 91 if (index != -1) { |
| 92 ext = name.substr(index); |
| 93 name = name.substr(0, index); |
| 94 } |
| 95 var now = new Date(); |
| 96 // TODO(dgozman): better name format. |
| 97 name = name + '_Edited_' + now.getFullYear() + '_' + |
| 98 (now.getMonth() + 1) + '_' + now.getDate() + '_' + |
| 99 now.getHours() + '_' + now.getMinutes() + ext; |
| 100 |
| 101 function onError(error) { |
| 102 console.log('Error saving from gallery: "' + name + '"'); |
| 103 console.log(error); |
| 104 } |
| 105 |
| 106 // TODO(dgozman): Check for existence. |
| 107 this.parentDirEntry_.getFile( |
| 108 name, {create: true, exclusive: true}, function(fileEntry) { |
| 109 fileEntry.createWriter(function(fileWriter) { |
| 110 fileWriter.onerror = onError; |
| 111 fileWriter.onwritened = function() { |
| 112 console.log('Saving from gallery succeeded: "' + name + '"'); |
| 113 }; |
| 114 fileWriter.write(blob); |
| 115 }, onError); |
| 116 }, onError); |
| 117 }; |
| 118 |
| 119 Gallery.prototype.onImageSelected_ = function(entry) { |
| 120 this.entry_ = entry; |
| 121 this.editor_.load(entry.toURL()); |
| 122 }; |
| 123 |
| 124 Gallery.prototype.onEdit_ = function(event) { |
| 125 // TODO(dgozman): nice animation. |
| 126 if (this.editing_) { |
| 127 this.editBar_.setAttribute('hidden', 'hidden'); |
| 128 this.editButton_.removeAttribute('pressed'); |
| 129 this.editing_ = false; |
| 130 this.initiateFading_(); |
| 131 } else { |
| 132 this.editBar_.removeAttribute('hidden'); |
| 133 this.editButton_.setAttribute('pressed', 'pressed'); |
| 134 this.editing_ = true; |
| 135 } |
| 136 this.ribbon_.redraw(); |
| 137 }; |
| 138 |
| 139 Gallery.prototype.onShare_ = function(event) { |
| 140 // TODO(dgozman): implement. |
| 141 }; |
| 142 |
| 143 Gallery.prototype.onKeyDown_ = function(event) { |
| 144 if (this.editing_) |
| 145 return; |
| 146 switch (event.keyIdentifier) { |
| 147 case 'Home': |
| 148 this.ribbon_.scrollToFirst(); |
| 149 break; |
| 150 case 'Left': |
| 151 this.ribbon_.scrollLeft(); |
| 152 break; |
| 153 case 'Right': |
| 154 this.ribbon_.scrollRight(); |
| 155 break; |
| 156 case 'End': |
| 157 this.ribbon_.scrollToLast(); |
| 158 break; |
| 159 } |
| 160 }; |
| 161 |
| 162 Gallery.prototype.onMouseMove_ = function(e) { |
| 163 if (this.fadeTimeoutId_) { |
| 164 window.clearTimeout(this.fadeTimeoutId_); |
| 165 } |
| 166 this.toolbar_.removeAttribute('hidden'); |
| 167 this.initiateFading_(); |
| 168 }; |
| 169 |
| 170 Gallery.prototype.onFadeTimeout_ = function() { |
| 171 this.fadeTimeoutId_ = null; |
| 172 this.toolbar_.setAttribute('hidden', 'hidden'); |
| 173 }; |
| 174 |
| 175 Gallery.prototype.initiateFading_ = function() { |
| 176 if (this.editing_) { |
| 177 return; |
| 178 } |
| 179 this.fadeTimeoutId_ = window.setTimeout( |
| 180 this.onFadeTimeoutBound_, Gallery.FADE_TIMEOUT); |
| 181 }; |
| 182 |
| 183 function Ribbon(parentNode, onSelect) { |
| 184 this.container_ = parentNode; |
| 185 this.document_ = parentNode.ownerDocument; |
| 186 |
| 187 this.bar_ = this.document_.createElement('div'); |
| 188 this.bar_.className = 'ribbon'; |
| 189 this.container_.appendChild(this.bar_); |
| 190 |
| 191 this.left_ = this.document_.createElement('div'); |
| 192 this.left_.className = 'ribbon-left'; |
| 193 this.left_.addEventListener('click', this.scrollLeft.bind(this)); |
| 194 |
| 195 this.right_ = this.document_.createElement('div'); |
| 196 this.right_.className = 'ribbon-right'; |
| 197 this.right_.addEventListener('click', this.scrollRight.bind(this)); |
| 198 |
| 199 this.spacer_ = this.document_.createElement('div'); |
| 200 this.spacer_.className = 'ribbon-spacer'; |
| 201 |
| 202 this.onSelect_ = onSelect; |
| 203 this.entries_ = []; |
| 204 this.images_ = []; |
| 205 this.selectedIndex_ = -1; |
| 206 this.firstIndex_ = 0; |
| 207 } |
| 208 |
| 209 Ribbon.prototype.clear = function() { |
| 210 this.bar_.textContent = ''; |
| 211 this.entries_ = []; |
| 212 this.images_ = []; |
| 213 this.selectedIndex_ = -1; |
| 214 this.firstIndex_ = 0; |
| 215 }; |
| 216 |
| 217 Ribbon.prototype.add = function(entry) { |
| 218 this.entries_.push(entry); |
| 219 var index = this.entries_.length - 1; |
| 220 |
| 221 var box = this.document_.createElement('div'); |
| 222 box.className = 'ribbon-image'; |
| 223 box.addEventListener('click', this.select.bind(this, index)); |
| 224 this.images_.push(box); |
| 225 |
| 226 var img = this.document_.createElement('img'); |
| 227 img.setAttribute('src', entry.toURL()); |
| 228 box.appendChild(img); |
| 229 }; |
| 230 |
| 231 Ribbon.prototype.setEntries = function(entries) { |
| 232 this.clear(); |
| 233 for (var index = 0; index < entries.length; ++index) { |
| 234 this.add(entries[index]); |
| 235 } |
| 236 |
| 237 window.setTimeout(this.redraw.bind(this), 0); |
| 238 }; |
| 239 |
| 240 Ribbon.prototype.select = function(index) { |
| 241 if (index < 0 || index >= this.entries_.length) |
| 242 return; |
| 243 if (this.selectedIndex_ != -1) |
| 244 this.images_[this.selectedIndex_].removeAttribute('selected'); |
| 245 this.selectedIndex_ = index; |
| 246 this.images_[this.selectedIndex_].setAttribute('selected', 'selected'); |
| 247 if (this.onSelect_) |
| 248 this.onSelect_(this.entries_[index]); |
| 249 }; |
| 250 |
| 251 Ribbon.prototype.redraw = function() { |
| 252 this.bar_.textContent = ''; |
| 253 |
| 254 // TODO(dgozman): get rid of these constants. |
| 255 var itemWidth = 80; |
| 256 var width = this.bar_.clientWidth - 40; |
| 257 |
| 258 var fit = Math.round(Math.floor(width / itemWidth)); |
| 259 var lastIndex = Math.min(this.entries_.length, this.firstIndex_ + fit); |
| 260 this.firstIndex_ = Math.max(0, lastIndex - fit); |
| 261 this.bar_.appendChild(this.left_); |
| 262 for (var index = this.firstIndex_; index < lastIndex; ++index) { |
| 263 this.bar_.appendChild(this.images_[index]); |
| 264 } |
| 265 this.bar_.appendChild(this.spacer_); |
| 266 this.bar_.appendChild(this.right_); |
| 267 }; |
| 268 |
| 269 Ribbon.prototype.scrollLeft = function() { |
| 270 if (this.firstIndex_ > 0) { |
| 271 this.firstIndex_--; |
| 272 this.redraw(); |
| 273 } |
| 274 }; |
| 275 |
| 276 Ribbon.prototype.scrollRight = function() { |
| 277 if (this.firstIndex_ < this.entries_.length - 1) { |
| 278 this.firstIndex_++; |
| 279 this.redraw(); |
| 280 } |
| 281 }; |
| 282 |
| 283 Ribbon.prototype.scrollToFirst = function() { |
| 284 if (this.firstIndex_ > 0) { |
| 285 this.firstIndex_ = 0; |
| 286 this.redraw(); |
| 287 } |
| 288 }; |
| 289 |
| 290 Ribbon.prototype.scrollToLast = function() { |
| 291 if (this.firstIndex_ < this.entries_.length - 1) { |
| 292 this.firstIndex_ = this.entries_.length - 1; |
| 293 this.redraw(); |
| 294 } |
| 295 }; |
OLD | NEW |