source: Dev/branches/rest-dojo-ui/client/dojox/mobile/app/ImageThumbView.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

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.