1 | |
---|
2 | function RVGTLine(margin, rowHeight) { |
---|
3 | this.elements = new Array; |
---|
4 | this.margin = margin; |
---|
5 | this.rowHeight = rowHeight; |
---|
6 | this.maxHeight = 0; |
---|
7 | } |
---|
8 | |
---|
9 | RVGTLine.prototype = { |
---|
10 | width: 0, |
---|
11 | elementsWidth: 0, |
---|
12 | firstThumbIndex: 0, |
---|
13 | |
---|
14 | add: function($elt, absIndex) { |
---|
15 | if (this.elements.length === 0) |
---|
16 | this.firstThumbIndex = absIndex; |
---|
17 | var w,h; |
---|
18 | |
---|
19 | if (! (w=$elt.data("w")) ) { |
---|
20 | if ( (w=$elt[0].getAttribute("width")) && (w=parseInt(w)) ) { |
---|
21 | h=parseInt($elt[0].getAttribute("height")); |
---|
22 | } |
---|
23 | else { |
---|
24 | w=$elt.width(); |
---|
25 | h=$elt.height(); |
---|
26 | } |
---|
27 | if (h > this.rowHeight) { |
---|
28 | w = Math.round(w * this.rowHeight/h); |
---|
29 | h = this.rowHeight; |
---|
30 | } |
---|
31 | $elt.data("w", w) |
---|
32 | .data("h", h); |
---|
33 | } |
---|
34 | else |
---|
35 | h=$elt.data("h"); |
---|
36 | |
---|
37 | |
---|
38 | var eltObj = { |
---|
39 | $elt: $elt, |
---|
40 | w: w, |
---|
41 | h: h |
---|
42 | }; |
---|
43 | this.elements.push(eltObj); |
---|
44 | |
---|
45 | if (eltObj.h > this.maxHeight) |
---|
46 | this.maxHeight = eltObj.h; |
---|
47 | |
---|
48 | this.width += this.margin + eltObj.w; |
---|
49 | this.elementsWidth += eltObj.w; |
---|
50 | }, |
---|
51 | |
---|
52 | clear: function() { |
---|
53 | if (!this.elements.length) return; |
---|
54 | this.width = this.elementsWidth = 0; |
---|
55 | this.maxHeight = 0; |
---|
56 | this.elements.length = 0; |
---|
57 | } |
---|
58 | } |
---|
59 | |
---|
60 | |
---|
61 | function RVGThumbs(options) { |
---|
62 | this.opts = options; |
---|
63 | |
---|
64 | this.$thumbs = $('#thumbnails'); |
---|
65 | if (this.$thumbs.length==0) return; |
---|
66 | this.$thumbs.css('text-align', 'left'); |
---|
67 | |
---|
68 | this.opts.extraRowHeight = 0; |
---|
69 | if (window.devicePixelRatio > 1) { |
---|
70 | var dpr = window.devicePixelRatio; |
---|
71 | this.opts.resizeThreshold = 1.01; |
---|
72 | this.opts.resizeFactor = 0.95; |
---|
73 | this.opts.extraRowHeight = 6; /*loose sharpness but only for small screens when we could "almost" fit with full sharpness*/ |
---|
74 | this.opts.rowHeight = Math.round(this.opts.rowHeight / dpr ) + this.opts.extraRowHeight; |
---|
75 | } |
---|
76 | else { |
---|
77 | this.opts.resizeThreshold = 1.12; /*if row is less than 12% larger than available width, distribute extra width through cropping*/ |
---|
78 | this.opts.resizeFactor = 0.8;/* when row is more than 12% larger than available width, distribute extra width 80% through resizing and 20% through cropping*/ |
---|
79 | } |
---|
80 | this.process(); |
---|
81 | |
---|
82 | var that = this; |
---|
83 | $(window).on('resize', function() { |
---|
84 | if (Math.abs(that.$thumbs.width() - that.prevContainerWidth)>1) |
---|
85 | that.process(); |
---|
86 | }) |
---|
87 | .on('RVTS_loaded', function(evt, down) { |
---|
88 | that.process( down && that.$thumbs.width() == that.prevContainerWidth ? that.prevLastLineFirstThumbIndex : 0); |
---|
89 | } ); |
---|
90 | |
---|
91 | if (!$.isReady) { |
---|
92 | $(document).ready( function() { |
---|
93 | if ( that.$thumbs.width() < that.prevContainerWidth ) |
---|
94 | that.process(); |
---|
95 | } ); |
---|
96 | } |
---|
97 | } |
---|
98 | |
---|
99 | RVGThumbs.prototype = { |
---|
100 | prevContainerWidth:0, |
---|
101 | prevLastLineFirstThumbIndex: 0, |
---|
102 | |
---|
103 | process: function(startIndex) { |
---|
104 | startIndex = startIndex ? startIndex : 0; |
---|
105 | var containerWidth = this.$thumbs.width() |
---|
106 | , maxExtraMarginPerThumb = 1; |
---|
107 | this.prevContainerWidth = containerWidth; |
---|
108 | |
---|
109 | var $elts = $('li>a>img', this.$thumbs) |
---|
110 | , line = new RVGTLine(this.opts.hMargin, this.opts.rowHeight); |
---|
111 | |
---|
112 | for (var i=startIndex; i<$elts.length; i++) { |
---|
113 | var $elt = $( $elts[i] ); |
---|
114 | |
---|
115 | line.add($elt, i); |
---|
116 | if (line.width >= containerWidth - maxExtraMarginPerThumb * line.elements.length) { |
---|
117 | this.processLine(line, containerWidth); |
---|
118 | line.clear(); |
---|
119 | } |
---|
120 | }; |
---|
121 | |
---|
122 | if(line.elements.length) |
---|
123 | this.processLine(line, containerWidth, true); |
---|
124 | this.prevLastLineFirstThumbIndex = line.firstThumbIndex; |
---|
125 | }, |
---|
126 | |
---|
127 | processLine: function(line, containerWidth, lastLine) { |
---|
128 | var toRecover, eltW, eltH |
---|
129 | , rowHeight = line.maxHeight ? line.maxHeight : line.elements[0].h; |
---|
130 | |
---|
131 | if (line.width / containerWidth > this.opts.resizeThreshold) { |
---|
132 | var ratio = line.elementsWidth / (line.elementsWidth + containerWidth - line.width); |
---|
133 | var adjustedRowHeight = rowHeight / (1 + (ratio-1) * this.opts.resizeFactor ); |
---|
134 | adjustedRowHeight = 6 * Math.round( adjustedRowHeight/6 ); |
---|
135 | if (adjustedRowHeight < rowHeight / ratio ) { |
---|
136 | adjustedRowHeight = Math.ceil( rowHeight / ratio ); |
---|
137 | var missing = this.opts.rowHeight - this.opts.extraRowHeight - adjustedRowHeight; |
---|
138 | if (missing>0 && missing<6) |
---|
139 | adjustedRowHeight += missing; |
---|
140 | } |
---|
141 | if (adjustedRowHeight < rowHeight) |
---|
142 | rowHeight = adjustedRowHeight; |
---|
143 | } |
---|
144 | else if (lastLine) |
---|
145 | rowHeight = Math.min( rowHeight, this.opts.rowHeight - this.opts.extraRowHeight); |
---|
146 | |
---|
147 | toRecover = line.width - containerWidth; |
---|
148 | if (lastLine) |
---|
149 | toRecover = 0; |
---|
150 | |
---|
151 | for(var i=0; i<line.elements.length; i++) { |
---|
152 | var eltObj = line.elements[i] |
---|
153 | , eltW=eltObj.w |
---|
154 | , eltH=eltObj.h |
---|
155 | , eltToRecover; |
---|
156 | |
---|
157 | if (i==line.elements.length-1) |
---|
158 | eltToRecover = toRecover; |
---|
159 | else |
---|
160 | eltToRecover = Math.round(toRecover * eltW / line.elementsWidth); |
---|
161 | |
---|
162 | toRecover -= eltToRecover; |
---|
163 | line.elementsWidth -= eltW; |
---|
164 | |
---|
165 | if (eltH > rowHeight ) { |
---|
166 | eltW = Math.round( eltW * rowHeight/eltObj.h ); |
---|
167 | eltH = rowHeight; |
---|
168 | eltToRecover -= eltObj.w - eltW; |
---|
169 | if (lastLine) |
---|
170 | eltToRecover = 0; |
---|
171 | } |
---|
172 | |
---|
173 | this.reposition(eltObj.$elt, eltW, eltH, eltW-eltToRecover, rowHeight); |
---|
174 | } |
---|
175 | }, |
---|
176 | |
---|
177 | reposition: function($img, imgW, imgH, liW, liH) { |
---|
178 | /* JQuery .attr and .css functions add too much overhead ...*/ |
---|
179 | var elt = $img[0]; |
---|
180 | elt.setAttribute("width", imgW+""); |
---|
181 | elt.setAttribute("height", imgH+""); |
---|
182 | |
---|
183 | elt = elt.parentNode;//a |
---|
184 | elt.style.left = Math.round((liW-imgW)/2)+"px"; |
---|
185 | elt.style.top = Math.round((liH-imgH)/2)+"px"; |
---|
186 | |
---|
187 | elt = elt.parentNode;//li |
---|
188 | elt.style.width = liW+"px"; |
---|
189 | elt.style.height = liH+"px"; |
---|
190 | |
---|
191 | } |
---|
192 | |
---|
193 | } |
---|
194 | |
---|