source: Dev/trunk/src/client/dojox/mobile/app/ImageThumbView.js @ 483

Last change on this file since 483 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 8.4 KB
Line 
1dojo.provide("dojox.mobile.app.ImageThumbView");
2dojo.experimental("dojox.mobile.app.ImageThumbView");
3
4dojo.require("dijit._WidgetBase");
5dojo.require("dojo.string");
6
7dojo.declare("dojox.mobile.app.ImageThumbView", dijit._WidgetBase, {
8        // summary:
9        //              An image thumbnail gallery
10
11        // items: Array
12        //              The data items from which the image urls are retrieved.
13        //              If an item is a string, it is expected to be a URL. Otherwise
14        //              by default it is expected to have a 'url' member.  This can
15        //              be configured using the 'urlParam' attribute on this widget.
16        items: [],
17
18        // urlParam: String
19        //              The paramter name used to retrieve an image url from a JSON object
20        urlParam: "url",
21
22        labelParam: null,
23
24        itemTemplate: '<div class="mblThumbInner">' +
25                                '<div class="mblThumbOverlay"></div>' +
26                                '<div class="mblThumbMask">' +
27                                        '<div class="mblThumbSrc" style="background-image:url(${url})"></div>' +
28                                '</div>' +
29                        '</div>',
30
31        minPadding: 4,
32
33        maxPerRow: 3,
34
35        maxRows: -1,
36
37        baseClass: "mblImageThumbView",
38
39        thumbSize: "medium",
40
41        animationEnabled: true,
42
43        selectedIndex: -1,
44
45        cache: null,
46
47        cacheMustMatch: false,
48
49        clickEvent: "onclick",
50
51        cacheBust: false,
52
53        disableHide: false,
54
55        constructor: function(params, node){
56        },
57
58        postCreate: function(){
59
60                this.inherited(arguments);
61                var _this = this;
62
63                var hoverCls = "mblThumbHover";
64
65                this.addThumb = dojo.hitch(this, this.addThumb);
66                this.handleImgLoad = dojo.hitch(this, this.handleImgLoad);
67                this.hideCached = dojo.hitch(this, this.hideCached);
68
69                this._onLoadImages = {};
70
71                this.cache = [];
72                this.visibleImages = [];
73
74                this._cacheCounter = 0;
75
76                this.connect(this.domNode, this.clickEvent, function(event){
77                        var itemNode = _this._getItemNodeFromEvent(event);
78
79                        if(itemNode && !itemNode._cached){
80                                _this.onSelect(itemNode._item, itemNode._index, _this.items);
81                                dojo.query(".selected", this.domNode).removeClass("selected");
82                                dojo.addClass(itemNode, "selected");
83                        }
84                });
85
86                dojo.addClass(this.domNode, this.thumbSize);
87
88                this.resize();
89                this.render();
90        },
91
92        onSelect: function(item, index, items){
93                // summary:
94                //              Dummy function that is triggered when an image is selected.
95        },
96
97        _setAnimationEnabledAttr: function(value){
98                this.animationEnabled = value;
99                dojo[value ? "addClass" : "removeClass"](this.domNode, "animated");
100        },
101
102        _setItemsAttr: function(items){
103                this.items = items || [];
104
105                var urls = {};
106                var i;
107                for(i = 0; i < this.items.length; i++){
108                        urls[this.items[i][this.urlParam]] = 1;
109                }
110
111                var clearedUrls = [];
112                for(var url in this._onLoadImages){
113                        if(!urls[url] && this._onLoadImages[url]._conn){
114                                dojo.disconnect(this._onLoadImages[url]._conn);
115                                this._onLoadImages[url].src = null;
116                                clearedUrls.push(url);
117                        }
118                }
119
120                for(i = 0; i < clearedUrls.length; i++){
121                        delete this._onLoadImages[url];
122                }
123
124                this.render();
125        },
126
127        _getItemNode: function(node){
128                while(node && !dojo.hasClass(node, "mblThumb") && node != this.domNode){
129                        node = node.parentNode;
130                }
131
132                return (node == this.domNode) ? null : node;
133        },
134
135        _getItemNodeFromEvent: function(event){
136                if(event.touches && event.touches.length > 0){
137                        event = event.touches[0];
138                }
139                return this._getItemNode(event.target);
140        },
141
142        resize: function(){
143                this._thumbSize = null;
144
145                this._size = dojo.contentBox(this.domNode);
146
147                this.disableHide = true;
148                this.render();
149                this.disableHide = false;
150        },
151
152        hideCached: function(){
153                // summary:
154                //              Hides all cached nodes, so that they're no invisible and overlaying
155                //              other screen elements.
156                for(var i = 0; i < this.cache.length; i++){
157                        if (this.cache[i]) {
158                                dojo.style(this.cache[i], "display", "none");
159                        }
160                }
161        },
162
163        render: function(){
164                var i;
165                var url;
166                var item;
167
168                var thumb;
169                while(this.visibleImages && this.visibleImages.length > 0){
170                        thumb = this.visibleImages.pop();
171                        this.cache.push(thumb);
172
173                        if (!this.disableHide) {
174                                dojo.addClass(thumb, "hidden");
175                        }
176                        thumb._cached = true;
177                }
178
179                if(this.cache && this.cache.length > 0){
180                        setTimeout(this.hideCached, 1000);
181                }
182
183                if(!this.items || this.items.length == 0){
184                        return;
185                }
186
187                for(i = 0; i < this.items.length; i++){
188                        item = this.items[i];
189                        url = (dojo.isString(item) ? item : item[this.urlParam]);
190
191                        this.addThumb(item, url, i);
192
193                        if(this.maxRows > 0 && (i + 1) / this.maxPerRow >= this.maxRows){
194                                break;
195                        }
196                }
197
198                if(!this._thumbSize){
199                        return;
200                }
201
202                var column = 0;
203                var row = -1;
204
205                var totalThumbWidth = this._thumbSize.w + (this.padding * 2);
206                var totalThumbHeight = this._thumbSize.h + (this.padding * 2);
207
208                var nodes = this.thumbNodes =
209                        dojo.query(".mblThumb", this.domNode);
210
211                var pos = 0;
212                nodes = this.visibleImages;
213                for(i = 0; i < nodes.length; i++){
214                        if(nodes[i]._cached){
215                                continue;
216                        }
217
218                        if(pos % this.maxPerRow == 0){
219                                row ++;
220                        }
221                        column = pos % this.maxPerRow;
222
223                        this.place(
224                                nodes[i],
225                                (column * totalThumbWidth) + this.padding,      // x position
226                                (row * totalThumbHeight) + this.padding         // y position
227                        );
228
229                        if(!nodes[i]._loading){
230                                dojo.removeClass(nodes[i], "hidden");
231                        }
232
233                        if(pos == this.selectedIndex){
234                                dojo[pos == this.selectedIndex ? "addClass" : "removeClass"]
235                                        (nodes[i], "selected");
236                        }
237                        pos++;
238                }
239
240                var numRows = Math.ceil(pos / this.maxPerRow);
241
242                this._numRows = numRows;
243
244                this.setContainerHeight((numRows * (this._thumbSize.h + this.padding * 2)));
245        },
246
247        setContainerHeight: function(amount){
248                dojo.style(this.domNode, "height", amount + "px");
249        },
250
251        addThumb: function(item, url, index){
252
253                var thumbDiv;
254                var cacheHit = false;
255                if(this.cache.length > 0){
256                        // Reuse a previously created node if possible
257                        var found = false;
258                        // Search for an image with the same url first
259                        for(var i = 0; i < this.cache.length; i++){
260                                if(this.cache[i]._url == url){
261                                        thumbDiv = this.cache.splice(i, 1)[0];
262                                        found = true;
263                                        break
264                                }
265                        }
266
267                        // if no image with the same url is found, just take the last one
268                        if(!thumbDiv && !this.cacheMustMatch){
269                thumbDiv = this.cache.pop();
270                                dojo.removeClass(thumbDiv, "selected");
271                        } else {
272                                cacheHit = true;
273                        }
274                }
275
276                if(!thumbDiv){
277
278                        // Create a new thumb
279                        thumbDiv = dojo.create("div", {
280                                "class": "mblThumb hidden",
281                                innerHTML: dojo.string.substitute(this.itemTemplate, {
282                                        url: url
283                                }, null, this)
284                        }, this.domNode);
285                }
286
287                if(this.labelParam) {
288                        var labelNode = dojo.query(".mblThumbLabel", thumbDiv)[0];
289                        if(!labelNode) {
290                                labelNode = dojo.create("div", {
291                                        "class": "mblThumbLabel"
292                                }, thumbDiv);
293                        }
294                        labelNode.innerHTML = item[this.labelParam] || "";
295                }
296
297            dojo.style(thumbDiv, "display", "");
298                if (!this.disableHide) {
299                        dojo.addClass(thumbDiv, "hidden");
300                }
301
302                if (!cacheHit) {
303                        var loader = dojo.create("img", {});
304                        loader._thumbDiv = thumbDiv;
305                        loader._conn = dojo.connect(loader, "onload", this.handleImgLoad);
306                        loader._url = url;
307                        thumbDiv._loading = true;
308
309                        this._onLoadImages[url] = loader;
310                        if (loader) {
311                                loader.src = url;
312                        }
313                }
314                this.visibleImages.push(thumbDiv);
315
316                thumbDiv._index = index;
317                thumbDiv._item = item;
318                thumbDiv._url = url;
319                thumbDiv._cached = false;
320
321                if(!this._thumbSize){
322                        this._thumbSize = dojo.marginBox(thumbDiv);
323
324                        if(this._thumbSize.h == 0){
325                                this._thumbSize.h = 100;
326                                this._thumbSize.w = 100;
327                        }
328
329                        if(this.labelParam){
330                                this._thumbSize.h += 8;
331                        }
332
333                        this.calcPadding();
334                }
335        },
336
337        handleImgLoad: function(event){
338                var img = event.target;
339                dojo.disconnect(img._conn);
340                dojo.removeClass(img._thumbDiv, "hidden");
341                img._thumbDiv._loading = false;
342                img._conn = null;
343
344                var url = img._url;
345                if(this.cacheBust){
346                        url += (url.indexOf("?") > -1 ? "&" : "?")
347                                + "cacheBust=" + (new Date()).getTime() + "_" + (this._cacheCounter++);
348                }
349
350                dojo.query(".mblThumbSrc", img._thumbDiv)
351                                .style("backgroundImage", "url(" + url + ")");
352
353                delete this._onLoadImages[img._url];
354        },
355
356        calcPadding: function(){
357                var width = this._size.w;
358
359                var thumbWidth = this._thumbSize.w;
360
361                var imgBounds = thumbWidth + this.minPadding;
362
363                this.maxPerRow = Math.floor(width / imgBounds);
364
365                this.padding = Math.floor((width - (thumbWidth * this.maxPerRow)) / (this.maxPerRow * 2));
366        },
367
368        place: function(node, x, y){
369                dojo.style(node, {
370                        "-webkit-transform" :"translate(" + x + "px," + y + "px)"
371                });
372        },
373
374        destroy: function(){
375                // Stop the loading of any more images
376
377                var img;
378                var counter = 0;
379                for (var url in this._onLoadImages){
380                        img = this._onLoadImages[url];
381                        if (img) {
382                                img.src = null;
383                                counter++;
384                        }
385                }
386
387                this.inherited(arguments);
388        }
389});
Note: See TracBrowser for help on using the repository browser.