Mercurial > repos > saskia-hiltemann > ireport
comparison DataTables-1.9.4/media/src/core/core.sizing.js @ 0:ac5f9272033b draft
first upload
author | saskia-hiltemann |
---|---|
date | Tue, 01 Jul 2014 11:42:23 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:ac5f9272033b |
---|---|
1 /** | |
2 * Convert a CSS unit width to pixels (e.g. 2em) | |
3 * @param {string} sWidth width to be converted | |
4 * @param {node} nParent parent to get the with for (required for relative widths) - optional | |
5 * @returns {int} iWidth width in pixels | |
6 * @memberof DataTable#oApi | |
7 */ | |
8 function _fnConvertToWidth ( sWidth, nParent ) | |
9 { | |
10 if ( !sWidth || sWidth === null || sWidth === '' ) | |
11 { | |
12 return 0; | |
13 } | |
14 | |
15 if ( !nParent ) | |
16 { | |
17 nParent = document.body; | |
18 } | |
19 | |
20 var iWidth; | |
21 var nTmp = document.createElement( "div" ); | |
22 nTmp.style.width = _fnStringToCss( sWidth ); | |
23 | |
24 nParent.appendChild( nTmp ); | |
25 iWidth = nTmp.offsetWidth; | |
26 nParent.removeChild( nTmp ); | |
27 | |
28 return ( iWidth ); | |
29 } | |
30 | |
31 | |
32 /** | |
33 * Calculate the width of columns for the table | |
34 * @param {object} oSettings dataTables settings object | |
35 * @memberof DataTable#oApi | |
36 */ | |
37 function _fnCalculateColumnWidths ( oSettings ) | |
38 { | |
39 var iTableWidth = oSettings.nTable.offsetWidth; | |
40 var iUserInputs = 0; | |
41 var iTmpWidth; | |
42 var iVisibleColumns = 0; | |
43 var iColums = oSettings.aoColumns.length; | |
44 var i, iIndex, iCorrector, iWidth; | |
45 var oHeaders = $('th', oSettings.nTHead); | |
46 var widthAttr = oSettings.nTable.getAttribute('width'); | |
47 var nWrapper = oSettings.nTable.parentNode; | |
48 | |
49 /* Convert any user input sizes into pixel sizes */ | |
50 for ( i=0 ; i<iColums ; i++ ) | |
51 { | |
52 if ( oSettings.aoColumns[i].bVisible ) | |
53 { | |
54 iVisibleColumns++; | |
55 | |
56 if ( oSettings.aoColumns[i].sWidth !== null ) | |
57 { | |
58 iTmpWidth = _fnConvertToWidth( oSettings.aoColumns[i].sWidthOrig, | |
59 nWrapper ); | |
60 if ( iTmpWidth !== null ) | |
61 { | |
62 oSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth ); | |
63 } | |
64 | |
65 iUserInputs++; | |
66 } | |
67 } | |
68 } | |
69 | |
70 /* If the number of columns in the DOM equals the number that we have to process in | |
71 * DataTables, then we can use the offsets that are created by the web-browser. No custom | |
72 * sizes can be set in order for this to happen, nor scrolling used | |
73 */ | |
74 if ( iColums == oHeaders.length && iUserInputs === 0 && iVisibleColumns == iColums && | |
75 oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "" ) | |
76 { | |
77 for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) | |
78 { | |
79 iTmpWidth = $(oHeaders[i]).width(); | |
80 if ( iTmpWidth !== null ) | |
81 { | |
82 oSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth ); | |
83 } | |
84 } | |
85 } | |
86 else | |
87 { | |
88 /* Otherwise we are going to have to do some calculations to get the width of each column. | |
89 * Construct a 1 row table with the widest node in the data, and any user defined widths, | |
90 * then insert it into the DOM and allow the browser to do all the hard work of | |
91 * calculating table widths. | |
92 */ | |
93 var | |
94 nCalcTmp = oSettings.nTable.cloneNode( false ), | |
95 nTheadClone = oSettings.nTHead.cloneNode(true), | |
96 nBody = document.createElement( 'tbody' ), | |
97 nTr = document.createElement( 'tr' ), | |
98 nDivSizing; | |
99 | |
100 nCalcTmp.removeAttribute( "id" ); | |
101 nCalcTmp.appendChild( nTheadClone ); | |
102 if ( oSettings.nTFoot !== null ) | |
103 { | |
104 nCalcTmp.appendChild( oSettings.nTFoot.cloneNode(true) ); | |
105 _fnApplyToChildren( function(n) { | |
106 n.style.width = ""; | |
107 }, nCalcTmp.getElementsByTagName('tr') ); | |
108 } | |
109 | |
110 nCalcTmp.appendChild( nBody ); | |
111 nBody.appendChild( nTr ); | |
112 | |
113 /* Remove any sizing that was previously applied by the styles */ | |
114 var jqColSizing = $('thead th', nCalcTmp); | |
115 if ( jqColSizing.length === 0 ) | |
116 { | |
117 jqColSizing = $('tbody tr:eq(0)>td', nCalcTmp); | |
118 } | |
119 | |
120 /* Apply custom sizing to the cloned header */ | |
121 var nThs = _fnGetUniqueThs( oSettings, nTheadClone ); | |
122 iCorrector = 0; | |
123 for ( i=0 ; i<iColums ; i++ ) | |
124 { | |
125 var oColumn = oSettings.aoColumns[i]; | |
126 if ( oColumn.bVisible && oColumn.sWidthOrig !== null && oColumn.sWidthOrig !== "" ) | |
127 { | |
128 nThs[i-iCorrector].style.width = _fnStringToCss( oColumn.sWidthOrig ); | |
129 } | |
130 else if ( oColumn.bVisible ) | |
131 { | |
132 nThs[i-iCorrector].style.width = ""; | |
133 } | |
134 else | |
135 { | |
136 iCorrector++; | |
137 } | |
138 } | |
139 | |
140 /* Find the biggest td for each column and put it into the table */ | |
141 for ( i=0 ; i<iColums ; i++ ) | |
142 { | |
143 if ( oSettings.aoColumns[i].bVisible ) | |
144 { | |
145 var nTd = _fnGetWidestNode( oSettings, i ); | |
146 if ( nTd !== null ) | |
147 { | |
148 nTd = nTd.cloneNode(true); | |
149 if ( oSettings.aoColumns[i].sContentPadding !== "" ) | |
150 { | |
151 nTd.innerHTML += oSettings.aoColumns[i].sContentPadding; | |
152 } | |
153 nTr.appendChild( nTd ); | |
154 } | |
155 } | |
156 } | |
157 | |
158 /* Build the table and 'display' it */ | |
159 nWrapper.appendChild( nCalcTmp ); | |
160 | |
161 /* When scrolling (X or Y) we want to set the width of the table as appropriate. However, | |
162 * when not scrolling leave the table width as it is. This results in slightly different, | |
163 * but I think correct behaviour | |
164 */ | |
165 if ( oSettings.oScroll.sX !== "" && oSettings.oScroll.sXInner !== "" ) | |
166 { | |
167 nCalcTmp.style.width = _fnStringToCss(oSettings.oScroll.sXInner); | |
168 } | |
169 else if ( oSettings.oScroll.sX !== "" ) | |
170 { | |
171 nCalcTmp.style.width = ""; | |
172 if ( $(nCalcTmp).width() < nWrapper.offsetWidth ) | |
173 { | |
174 nCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth ); | |
175 } | |
176 } | |
177 else if ( oSettings.oScroll.sY !== "" ) | |
178 { | |
179 nCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth ); | |
180 } | |
181 else if ( widthAttr ) | |
182 { | |
183 nCalcTmp.style.width = _fnStringToCss( widthAttr ); | |
184 } | |
185 nCalcTmp.style.visibility = "hidden"; | |
186 | |
187 /* Scrolling considerations */ | |
188 _fnScrollingWidthAdjust( oSettings, nCalcTmp ); | |
189 | |
190 /* Read the width's calculated by the browser and store them for use by the caller. We | |
191 * first of all try to use the elements in the body, but it is possible that there are | |
192 * no elements there, under which circumstances we use the header elements | |
193 */ | |
194 var oNodes = $("tbody tr:eq(0)", nCalcTmp).children(); | |
195 if ( oNodes.length === 0 ) | |
196 { | |
197 oNodes = _fnGetUniqueThs( oSettings, $('thead', nCalcTmp)[0] ); | |
198 } | |
199 | |
200 /* Browsers need a bit of a hand when a width is assigned to any columns when | |
201 * x-scrolling as they tend to collapse the table to the min-width, even if | |
202 * we sent the column widths. So we need to keep track of what the table width | |
203 * should be by summing the user given values, and the automatic values | |
204 */ | |
205 if ( oSettings.oScroll.sX !== "" ) | |
206 { | |
207 var iTotal = 0; | |
208 iCorrector = 0; | |
209 for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) | |
210 { | |
211 if ( oSettings.aoColumns[i].bVisible ) | |
212 { | |
213 if ( oSettings.aoColumns[i].sWidthOrig === null ) | |
214 { | |
215 iTotal += $(oNodes[iCorrector]).outerWidth(); | |
216 } | |
217 else | |
218 { | |
219 iTotal += parseInt(oSettings.aoColumns[i].sWidth.replace('px',''), 10) + | |
220 ($(oNodes[iCorrector]).outerWidth() - $(oNodes[iCorrector]).width()); | |
221 } | |
222 iCorrector++; | |
223 } | |
224 } | |
225 | |
226 nCalcTmp.style.width = _fnStringToCss( iTotal ); | |
227 oSettings.nTable.style.width = _fnStringToCss( iTotal ); | |
228 } | |
229 | |
230 iCorrector = 0; | |
231 for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) | |
232 { | |
233 if ( oSettings.aoColumns[i].bVisible ) | |
234 { | |
235 iWidth = $(oNodes[iCorrector]).width(); | |
236 if ( iWidth !== null && iWidth > 0 ) | |
237 { | |
238 oSettings.aoColumns[i].sWidth = _fnStringToCss( iWidth ); | |
239 } | |
240 iCorrector++; | |
241 } | |
242 } | |
243 | |
244 var cssWidth = $(nCalcTmp).css('width'); | |
245 oSettings.nTable.style.width = (cssWidth.indexOf('%') !== -1) ? | |
246 cssWidth : _fnStringToCss( $(nCalcTmp).outerWidth() ); | |
247 nCalcTmp.parentNode.removeChild( nCalcTmp ); | |
248 } | |
249 | |
250 if ( widthAttr ) | |
251 { | |
252 oSettings.nTable.style.width = _fnStringToCss( widthAttr ); | |
253 } | |
254 } | |
255 | |
256 | |
257 /** | |
258 * Adjust a table's width to take account of scrolling | |
259 * @param {object} oSettings dataTables settings object | |
260 * @param {node} n table node | |
261 * @memberof DataTable#oApi | |
262 */ | |
263 function _fnScrollingWidthAdjust ( oSettings, n ) | |
264 { | |
265 if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY !== "" ) | |
266 { | |
267 /* When y-scrolling only, we want to remove the width of the scroll bar so the table | |
268 * + scroll bar will fit into the area avaialble. | |
269 */ | |
270 var iOrigWidth = $(n).width(); | |
271 n.style.width = _fnStringToCss( $(n).outerWidth()-oSettings.oScroll.iBarWidth ); | |
272 } | |
273 else if ( oSettings.oScroll.sX !== "" ) | |
274 { | |
275 /* When x-scrolling both ways, fix the table at it's current size, without adjusting */ | |
276 n.style.width = _fnStringToCss( $(n).outerWidth() ); | |
277 } | |
278 } | |
279 | |
280 | |
281 /** | |
282 * Get the widest node | |
283 * @param {object} oSettings dataTables settings object | |
284 * @param {int} iCol column of interest | |
285 * @returns {node} widest table node | |
286 * @memberof DataTable#oApi | |
287 */ | |
288 function _fnGetWidestNode( oSettings, iCol ) | |
289 { | |
290 var iMaxIndex = _fnGetMaxLenString( oSettings, iCol ); | |
291 if ( iMaxIndex < 0 ) | |
292 { | |
293 return null; | |
294 } | |
295 | |
296 if ( oSettings.aoData[iMaxIndex].nTr === null ) | |
297 { | |
298 var n = document.createElement('td'); | |
299 n.innerHTML = _fnGetCellData( oSettings, iMaxIndex, iCol, '' ); | |
300 return n; | |
301 } | |
302 return _fnGetTdNodes(oSettings, iMaxIndex)[iCol]; | |
303 } | |
304 | |
305 | |
306 /** | |
307 * Get the maximum strlen for each data column | |
308 * @param {object} oSettings dataTables settings object | |
309 * @param {int} iCol column of interest | |
310 * @returns {string} max string length for each column | |
311 * @memberof DataTable#oApi | |
312 */ | |
313 function _fnGetMaxLenString( oSettings, iCol ) | |
314 { | |
315 var iMax = -1; | |
316 var iMaxIndex = -1; | |
317 | |
318 for ( var i=0 ; i<oSettings.aoData.length ; i++ ) | |
319 { | |
320 var s = _fnGetCellData( oSettings, i, iCol, 'display' )+""; | |
321 s = s.replace( /<.*?>/g, "" ); | |
322 if ( s.length > iMax ) | |
323 { | |
324 iMax = s.length; | |
325 iMaxIndex = i; | |
326 } | |
327 } | |
328 | |
329 return iMaxIndex; | |
330 } | |
331 | |
332 | |
333 /** | |
334 * Append a CSS unit (only if required) to a string | |
335 * @param {array} aArray1 first array | |
336 * @param {array} aArray2 second array | |
337 * @returns {int} 0 if match, 1 if length is different, 2 if no match | |
338 * @memberof DataTable#oApi | |
339 */ | |
340 function _fnStringToCss( s ) | |
341 { | |
342 if ( s === null ) | |
343 { | |
344 return "0px"; | |
345 } | |
346 | |
347 if ( typeof s == 'number' ) | |
348 { | |
349 if ( s < 0 ) | |
350 { | |
351 return "0px"; | |
352 } | |
353 return s+"px"; | |
354 } | |
355 | |
356 /* Check if the last character is not 0-9 */ | |
357 var c = s.charCodeAt( s.length-1 ); | |
358 if (c < 0x30 || c > 0x39) | |
359 { | |
360 return s; | |
361 } | |
362 return s+"px"; | |
363 } | |
364 | |
365 | |
366 /** | |
367 * Get the width of a scroll bar in this browser being used | |
368 * @returns {int} width in pixels | |
369 * @memberof DataTable#oApi | |
370 */ | |
371 function _fnScrollBarWidth () | |
372 { | |
373 var inner = document.createElement('p'); | |
374 var style = inner.style; | |
375 style.width = "100%"; | |
376 style.height = "200px"; | |
377 style.padding = "0px"; | |
378 | |
379 var outer = document.createElement('div'); | |
380 style = outer.style; | |
381 style.position = "absolute"; | |
382 style.top = "0px"; | |
383 style.left = "0px"; | |
384 style.visibility = "hidden"; | |
385 style.width = "200px"; | |
386 style.height = "150px"; | |
387 style.padding = "0px"; | |
388 style.overflow = "hidden"; | |
389 outer.appendChild(inner); | |
390 | |
391 document.body.appendChild(outer); | |
392 var w1 = inner.offsetWidth; | |
393 outer.style.overflow = 'scroll'; | |
394 var w2 = inner.offsetWidth; | |
395 if ( w1 == w2 ) | |
396 { | |
397 w2 = outer.clientWidth; | |
398 } | |
399 | |
400 document.body.removeChild(outer); | |
401 return (w1 - w2); | |
402 } | |
403 |