OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 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 * Scrollable thumbnail ribbon at the bottom of the Gallery in the Slide mode. | |
7 * | |
8 * @param {Document} document Document. | |
9 * @param {MetadataCache} metadataCache MetadataCache instance. | |
10 * @param {function(number)} selectFunc Selection function. | |
11 * @return {Element} Ribbon element. | |
12 * @constructor | |
13 */ | |
14 function Ribbon(document, metadataCache, selectFunc) { | |
15 var self = document.createElement('div'); | |
16 Ribbon.decorate(self, metadataCache, selectFunc); | |
17 return self; | |
18 } | |
19 | |
20 /** | |
21 * Inherit from HTMLDivElement. | |
22 */ | |
23 Ribbon.prototype.__proto__ = HTMLDivElement.prototype; | |
24 | |
25 /** | |
26 * Decorate a Ribbon instance. | |
27 * | |
28 * @param {Ribbon} self Self pointer. | |
29 * @param {MetadataCache} metadataCache MetadataCache instance. | |
30 * @param {function(number)} selectFunc Selection function. | |
31 */ | |
32 Ribbon.decorate = function(self, metadataCache, selectFunc) { | |
33 self.__proto__ = Ribbon.prototype; | |
34 self.metadataCache_ = metadataCache; | |
35 self.selectFunc_ = selectFunc; | |
36 | |
37 self.className = 'ribbon'; | |
38 | |
39 self.firstVisibleIndex_ = 0; | |
40 self.lastVisibleIndex_ = -1; // Zero thumbnails | |
41 | |
42 self.renderCache_ = {}; | |
43 }; | |
44 | |
45 /** | |
46 * Max number of thumbnails in the ribbon. | |
47 * @type {Number} | |
48 */ | |
49 Ribbon.ITEMS_COUNT = 5; | |
50 | |
51 /** | |
52 * Update the ribbon. | |
53 * | |
54 * @param {Array.<Gallery.Item>} items Array of items. | |
55 * @param {number} selectedIndex Selected index. | |
56 */ | |
57 Ribbon.prototype.update = function(items, selectedIndex) { | |
58 // Never show a single thumbnail. | |
59 if (items.length == 1) | |
60 return; | |
61 | |
62 // TODO(dgozman): use margin instead of 2 here. | |
63 var itemWidth = this.clientHeight - 2; | |
64 var fullItems = Ribbon.ITEMS_COUNT; | |
65 fullItems = Math.min(fullItems, items.length); | |
66 var right = Math.floor((fullItems - 1) / 2); | |
67 | |
68 var fullWidth = fullItems * itemWidth; | |
69 this.style.width = fullWidth + 'px'; | |
70 | |
71 var lastIndex = selectedIndex + right; | |
72 lastIndex = Math.max(lastIndex, fullItems - 1); | |
73 lastIndex = Math.min(lastIndex, items.length - 1); | |
74 var firstIndex = lastIndex - fullItems + 1; | |
75 | |
76 if (this.firstVisibleIndex_ != firstIndex || | |
77 this.lastVisibleIndex_ != lastIndex) { | |
78 | |
79 if (this.lastVisibleIndex_ == -1) { | |
80 this.firstVisibleIndex_ = firstIndex; | |
81 this.lastVisibleIndex_ = lastIndex; | |
82 } | |
83 | |
84 this.textContent = ''; | |
85 var startIndex = Math.min(firstIndex, this.firstVisibleIndex_); | |
86 var toRemove = []; | |
87 // All the items except the first one treated equally. | |
88 for (var index = startIndex + 1; | |
89 index <= Math.max(lastIndex, this.lastVisibleIndex_); | |
90 ++index) { | |
91 var box = this.renderThumbnail_(index, items); | |
92 box.style.marginLeft = '0'; | |
93 this.appendChild(box); | |
94 if (index < firstIndex || index > lastIndex) { | |
95 toRemove.push(box); | |
96 } | |
97 } | |
98 | |
99 var margin = itemWidth * Math.abs(firstIndex - this.firstVisibleIndex_); | |
100 var startBox = this.renderThumbnail_(startIndex, items); | |
101 if (startIndex == firstIndex) { | |
102 // Sliding to the right. | |
103 startBox.style.marginLeft = -margin + 'px'; | |
104 if (this.firstChild) | |
105 this.insertBefore(startBox, this.firstChild); | |
106 else | |
107 this.appendChild(startBox); | |
108 setTimeout(function() { | |
109 startBox.style.marginLeft = '0'; | |
110 }, 0); | |
111 } else { | |
112 // Sliding to the left. Start item will become invisible and should be | |
113 // removed afterwards. | |
114 toRemove.push(startBox); | |
115 startBox.style.marginLeft = '0'; | |
116 if (this.firstChild) | |
117 this.insertBefore(startBox, this.firstChild); | |
118 else | |
119 this.appendChild(startBox); | |
120 setTimeout(function() { | |
121 startBox.style.marginLeft = -margin + 'px'; | |
122 }, 0); | |
123 } | |
124 | |
125 ImageUtil.setClass(this, 'fade-left', | |
126 firstIndex > 0 && selectedIndex != firstIndex); | |
127 | |
128 ImageUtil.setClass(this, 'fade-right', | |
129 lastIndex < items.length - 1 && selectedIndex != lastIndex); | |
130 | |
131 this.firstVisibleIndex_ = firstIndex; | |
132 this.lastVisibleIndex_ = lastIndex; | |
133 | |
134 if (this.removeTimeout_) | |
135 clearTimeout(this.removeTimeout_); | |
136 | |
137 this.removeTimeout_ = setTimeout(function() { | |
138 this.removeTimeout_ = null; | |
139 for (var i = 0; i < toRemove.length; i++) { | |
140 var box = toRemove[i]; | |
141 if (box.parentNode == this) | |
142 this.removeChild(box); | |
dgozman
2012/08/17 07:11:03
2 extra spaces
Vladislav Kaznacheev
2012/08/17 09:20:40
Done.
| |
143 } | |
144 }.bind(this), 200); | |
145 } | |
146 | |
147 var oldSelected = this.querySelector('[selected]'); | |
148 if (oldSelected) oldSelected.removeAttribute('selected'); | |
149 | |
150 var newSelected = this.getThumbnail_(selectedIndex); | |
151 if (newSelected) newSelected.setAttribute('selected', true); | |
152 }; | |
153 | |
154 /** | |
155 * Create a DOM element for a thumbnail. | |
156 * | |
157 * @param {number} index Item index. | |
158 * @param {Array.<Gallery.Item>} items Items array. | |
159 * @return {Element} Newly created element. | |
160 * @private | |
161 */ | |
162 Ribbon.prototype.renderThumbnail_ = function(index, items) { | |
163 var url = items[index].getUrl(); | |
164 | |
165 var cached = this.renderCache_[url]; | |
166 if (cached) | |
167 return cached; | |
168 | |
169 var thumbnail = this.ownerDocument.createElement('div'); | |
170 thumbnail.className = 'ribbon-image'; | |
171 thumbnail.addEventListener('click', this.selectFunc_.bind(null, index)); | |
172 thumbnail.setAttribute('index', index); | |
173 | |
174 createChild(thumbnail, 'image-wrapper'); | |
dgozman
2012/08/17 07:11:03
util.createChild ?
Vladislav Kaznacheev
2012/08/17 09:20:40
Done.
| |
175 | |
176 this.metadataCache_.get(url, Gallery.METADATA_TYPE, | |
177 this.setThumbnailImage_.bind(this, thumbnail, url)); | |
178 | |
179 this.renderCache_[url] = thumbnail; | |
180 return thumbnail; | |
181 }; | |
182 | |
183 /** | |
184 * Set the thumbnail image. | |
185 * | |
186 * @param {Element} thumbnail Thumbnail element | |
187 * @param {string} url Image url. | |
188 * @param {Object} metadata Metadata. | |
189 * @private | |
190 */ | |
191 Ribbon.prototype.setThumbnailImage_ = function(thumbnail, url, metadata) { | |
192 new ThumbnailLoader(url, metadata).load( | |
193 thumbnail.querySelector('.image-wrapper'), true /* fill */); | |
194 }; | |
195 | |
196 /** | |
197 * Update the thumbnail image. | |
198 * | |
199 * @param {number} index Item index. | |
200 * @param {string} url Image url. | |
201 * @param {Object} metadata Metadata. | |
202 */ | |
203 Ribbon.prototype.updateThumbnail = function(index, url, metadata) { | |
dgozman
2012/08/17 07:11:03
I think, this method should update/invalidate thum
Vladislav Kaznacheev
2012/08/17 09:20:40
Actually we only ever update the current image's t
| |
204 var thumbnail = this.getThumbnail_(index); | |
205 if (thumbnail) | |
206 this.setThumbnailImage_(thumbnail, url, metadata); | |
207 }; | |
208 | |
209 /** | |
210 * @param {number} index Thumbnail index. | |
211 * @return {Element} Thumbnail element or null if not rendered. | |
212 * @private | |
213 */ | |
214 Ribbon.prototype.getThumbnail_ = function(index) { | |
215 return this.querySelector('[index="' + index + '"]'); | |
216 }; | |
217 | |
218 /** | |
219 * Update the thumbnail element cache. | |
220 * | |
221 * @param {string} oldUrl Old url. | |
222 * @param {string} newUrl New url. | |
223 */ | |
224 Ribbon.prototype.remapCache = function(oldUrl, newUrl) { | |
225 if (oldUrl != newUrl && (oldUrl in this.renderCache_)) { | |
226 this.renderCache_[newUrl] = this.renderCache_[oldUrl]; | |
227 delete this.renderCache_[oldUrl]; | |
228 } | |
229 }; | |
OLD | NEW |