ribbon.js revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Scrollable thumbnail ribbon at the bottom of the Gallery in the Slide mode. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Document} document Document. 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {MetadataCache} metadataCache MetadataCache instance. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {cr.ui.ArrayDataModel} dataModel Data model. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {cr.ui.ListSelectionModel} selectionModel Selection model. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function(string)} onThumbnailError Thumbnail load error handler. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {Element} Ribbon element. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function Ribbon(document, metadataCache, dataModel, selectionModel, 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onThumbnailError) { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var self = document.createElement('div'); 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Ribbon.decorate(self, 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) metadataCache, dataModel, selectionModel, onThumbnailError); 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Inherit from HTMLDivElement. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Ribbon.prototype.__proto__ = HTMLDivElement.prototype; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Decorate a Ribbon instance. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Ribbon} self Self pointer. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {MetadataCache} metadataCache MetadataCache instance. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {cr.ui.ArrayDataModel} dataModel Data model. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {cr.ui.ListSelectionModel} selectionModel Selection model. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function(string)} onThumbnailError Thumbnail load error handler. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Ribbon.decorate = function(self, metadataCache, dataModel, selectionModel, 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onThumbnailError) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.__proto__ = Ribbon.prototype; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.metadataCache_ = metadataCache; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.dataModel_ = dataModel; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.selectionModel_ = selectionModel; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.onThumbnailError_ = onThumbnailError; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.className = 'ribbon'; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Max number of thumbnails in the ribbon. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {Number} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Ribbon.ITEMS_COUNT = 5; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Force redraw the ribbon. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Ribbon.prototype.redraw = function() { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onSelection_(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Clear all cached data to force full redraw on the next selection change. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Ribbon.prototype.reset = function() { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.renderCache_ = {}; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.firstVisibleIndex_ = 0; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lastVisibleIndex_ = -1; // Zero thumbnails 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Enable the ribbon. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Ribbon.prototype.enable = function() { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onContentBound_ = this.onContentChange_.bind(this); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dataModel_.addEventListener('content', this.onContentBound_); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onSpliceBound_ = this.onSplice_.bind(this); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dataModel_.addEventListener('splice', this.onSpliceBound_); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onSelectionBound_ = this.onSelection_.bind(this); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectionModel_.addEventListener('change', this.onSelectionBound_); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.reset(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.redraw(); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Disable ribbon. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Ribbon.prototype.disable = function() { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dataModel_.removeEventListener('content', this.onContentBound_); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.dataModel_.removeEventListener('splice', this.onSpliceBound_); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectionModel_.removeEventListener('change', this.onSelectionBound_); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeVanishing_(); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.textContent = ''; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Data model splice handler. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} event Event. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Ribbon.prototype.onSplice_ = function(event) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event.removed.length == 0) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event.removed.length > 1) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) console.error('Cannot remove multiple items'); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var removed = this.renderCache_[event.removed[0].getUrl()]; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!removed || !removed.parentNode || !removed.hasAttribute('selected')) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) console.error('Can only remove the selected item'); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var persistentNodes = this.querySelectorAll('.ribbon-image:not([vanishing])'); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.lastVisibleIndex_ < this.dataModel_.length) { // Not at the end. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var lastNode = persistentNodes[persistentNodes.length - 1]; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lastNode.nextSibling) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pull back a vanishing node from the right. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lastNode.nextSibling.removeAttribute('vanishing'); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Push a new item at the right end. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild(this.renderThumbnail_(this.lastVisibleIndex_)); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No items to the right, move the window to the left. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lastVisibleIndex_--; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.firstVisibleIndex_) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.firstVisibleIndex_--; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var firstNode = persistentNodes[0]; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (firstNode.previousSibling) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pull back a vanishing node from the left. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) firstNode.previousSibling.removeAttribute('vanishing'); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Push a new item at the left end. 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newThumbnail = this.renderThumbnail_(this.firstVisibleIndex_); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newThumbnail.style.marginLeft = -(this.clientHeight - 2) + 'px'; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.insertBefore(newThumbnail, this.firstChild); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setTimeout(function() { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newThumbnail.style.marginLeft = '0'; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 0); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) removed.removeAttribute('selected'); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) removed.setAttribute('vanishing', 'smooth'); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.scheduleRemove_(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Selection change handler. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Ribbon.prototype.onSelection_ = function() { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var indexes = this.selectionModel_.selectedIndexes; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (indexes.length == 0) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // Ignore temporary empty selection. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var selectedIndex = indexes[0]; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var length = this.dataModel_.length; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(dgozman): use margin instead of 2 here. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var itemWidth = this.clientHeight - 2; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var fullItems = Ribbon.ITEMS_COUNT; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fullItems = Math.min(fullItems, length); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var right = Math.floor((fullItems - 1) / 2); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var fullWidth = fullItems * itemWidth; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.style.width = fullWidth + 'px'; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var lastIndex = selectedIndex + right; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lastIndex = Math.max(lastIndex, fullItems - 1); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lastIndex = Math.min(lastIndex, length - 1); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var firstIndex = lastIndex - fullItems + 1; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.firstVisibleIndex_ != firstIndex || 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lastVisibleIndex_ != lastIndex) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.lastVisibleIndex_ == -1) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.firstVisibleIndex_ = firstIndex; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lastVisibleIndex_ = lastIndex; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeVanishing_(); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.textContent = ''; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var startIndex = Math.min(firstIndex, this.firstVisibleIndex_); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All the items except the first one treated equally. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var index = startIndex + 1; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index <= Math.max(lastIndex, this.lastVisibleIndex_); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++index) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only add items that are in either old or the new viewport. 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.lastVisibleIndex_ < index && index < firstIndex || 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lastIndex < index && index < this.firstVisibleIndex_) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var box = this.renderThumbnail_(index); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) box.style.marginLeft = '0'; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild(box); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index < firstIndex || index > lastIndex) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the node is not in the new viewport we only need it while 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the animation is playing out. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) box.setAttribute('vanishing', 'slide'); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var slideCount = this.childNodes.length + 1 - Ribbon.ITEMS_COUNT; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var margin = itemWidth * slideCount; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var startBox = this.renderThumbnail_(startIndex); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (startIndex == firstIndex) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sliding to the right. 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) startBox.style.marginLeft = -margin + 'px'; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.firstChild) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.insertBefore(startBox, this.firstChild); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild(startBox); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setTimeout(function() { 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) startBox.style.marginLeft = '0'; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 0); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sliding to the left. Start item will become invisible and should be 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // removed afterwards. 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) startBox.setAttribute('vanishing', 'slide'); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) startBox.style.marginLeft = '0'; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.firstChild) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.insertBefore(startBox, this.firstChild); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.appendChild(startBox); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setTimeout(function() { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) startBox.style.marginLeft = -margin + 'px'; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, 0); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.setClass(this, 'fade-left', 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) firstIndex > 0 && selectedIndex != firstIndex); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.setClass(this, 'fade-right', 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lastIndex < length - 1 && selectedIndex != lastIndex); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.firstVisibleIndex_ = firstIndex; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.lastVisibleIndex_ = lastIndex; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.scheduleRemove_(); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var oldSelected = this.querySelector('[selected]'); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (oldSelected) oldSelected.removeAttribute('selected'); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var newSelected = 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.renderCache_[this.dataModel_.item(selectedIndex).getUrl()]; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (newSelected) newSelected.setAttribute('selected', true); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Schedule the removal of thumbnails marked as vanishing. 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Ribbon.prototype.scheduleRemove_ = function() { 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.removeTimeout_) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clearTimeout(this.removeTimeout_); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeTimeout_ = setTimeout(function() { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeTimeout_ = null; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeVanishing_(); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }.bind(this), 200); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Remove all thumbnails marked as vanishing. 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Ribbon.prototype.removeVanishing_ = function() { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.removeTimeout_) { 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clearTimeout(this.removeTimeout_); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeTimeout_ = 0; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var vanishingNodes = this.querySelectorAll('[vanishing]'); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (var i = 0; i != vanishingNodes.length; i++) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vanishingNodes[i].removeAttribute('vanishing'); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.removeChild(vanishingNodes[i]); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Create a DOM element for a thumbnail. 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} index Item index. 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {Element} Newly created element. 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Ribbon.prototype.renderThumbnail_ = function(index) { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var item = this.dataModel_.item(index); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var url = item.getUrl(); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var cached = this.renderCache_[url]; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cached) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cached; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var thumbnail = this.ownerDocument.createElement('div'); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail.className = 'ribbon-image'; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail.addEventListener('click', function() { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = this.dataModel_.indexOf(item); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectionModel_.unselectAll(); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.selectionModel_.setIndexSelected(index, true); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }.bind(this)); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) util.createChild(thumbnail, 'image-wrapper'); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.metadataCache_.get(url, Gallery.METADATA_TYPE, 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.setThumbnailImage_.bind(this, thumbnail, url)); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO: Implement LRU eviction. 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Never evict the thumbnails that are currently in the DOM because we rely 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on this cache to find them by URL. 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.renderCache_[url] = thumbnail; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return thumbnail; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Set the thumbnail image. 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Element} thumbnail Thumbnail element 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} url Image url. 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Object} metadata Metadata. 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Ribbon.prototype.setThumbnailImage_ = function(thumbnail, url, metadata) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ThumbnailLoader(url, metadata).load( 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thumbnail.querySelector('.image-wrapper'), 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true /* fill */, 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) null /* success callback */, 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onThumbnailError_.bind(null, url)); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Content change handler. 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} event Event. 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Ribbon.prototype.onContentChange_ = function(event) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var url = event.item.getUrl(); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.remapCache_(event.oldUrl, url); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var thumbnail = this.renderCache_[url]; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (thumbnail && event.metadata) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.setThumbnailImage_(thumbnail, url, event.metadata); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Update the thumbnail element cache. 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} oldUrl Old url. 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} newUrl New url. 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Ribbon.prototype.remapCache_ = function(oldUrl, newUrl) { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (oldUrl != newUrl && (oldUrl in this.renderCache_)) { 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.renderCache_[newUrl] = this.renderCache_[oldUrl]; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this.renderCache_[oldUrl]; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 368