Skip to content
This repository
Browse code

Fix: x-scrolling to the end of a table would cause the header and the…

… columns to go out of alignment due to the header not being able to scroll as far as was needed (this was caused by the changes in 876a75f) - 8332.

Fix: Table could conitnually expand when x-scrolling was enabled. This was partly addressed in 6776, but the fix was incomplete as it would still occur on Safari Mac (possibly other browsers as well). This fix is very closely related to 8332 (hence commiting together as they are interdependent). Now use padding right on the header/footer wrapper to provide the overflow scroll ability, but only add it when a scrollbar is present - otherwise the width gets added on and we get the forever expanding table.
Dev: Unit tests - New tests for scrolling to ensure 6776 and 8332 don't occur again
  • Loading branch information...
commit ab9dfd50529de0daa8bea9d4e8f1035f2b5e6e52 1 parent 0151d43
Allan Jardine authored
13 media/js/jquery.dataTables.js
@@ -3128,7 +3128,7 @@
3128 3128 if ( ie67 && ($('tbody', nScrollBody).height() > nScrollBody.offsetHeight ||
3129 3129 $(nScrollBody).css('overflow-y') == "scroll") )
3130 3130 {
3131   - o.nTable.style.width = _fnStringToCss( $(o.nTable).outerWidth()-o.oScroll.iBarWidth );
  3131 + o.nTable.style.width = _fnStringToCss( $(o.nTable).outerWidth() - o.oScroll.iBarWidth);
3132 3132 }
3133 3133 }
3134 3134 else
@@ -3305,12 +3305,19 @@
3305 3305 var iOuterWidth = $(o.nTable).outerWidth();
3306 3306 nScrollHeadTable.style.width = _fnStringToCss( iOuterWidth );
3307 3307 nScrollHeadInner.style.width = _fnStringToCss( iOuterWidth );
  3308 +
  3309 + var bScrolling = $(o.nTable).height() > nScrollBody.clientHeight || $(nScrollBody).css('overflow-y') == "scroll";
  3310 + nScrollHeadInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px";
3308 3311
3309 3312 if ( o.nTFoot !== null )
3310 3313 {
3311   - nScrollFootInner.style.width = _fnStringToCss( o.nTable.offsetWidth );
3312   - nScrollFootTable.style.width = _fnStringToCss( o.nTable.offsetWidth );
  3314 + nScrollFootTable.style.width = _fnStringToCss( iOuterWidth );
  3315 + nScrollFootInner.style.width = _fnStringToCss( iOuterWidth );
  3316 + nScrollFootInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px";
3313 3317 }
  3318 +
  3319 + /* Adjust the position of the header incase we loose the y-scrollbar */
  3320 + $(nScrollBody).scroll();
3314 3321
3315 3322 /* If sorting or filtering has occurred, jump the scrolling back to the top */
3316 3323 if ( o.bSorted || o.bFiltered )
15 media/src/core/core.scrolling.js
@@ -259,7 +259,7 @@ function _fnScrollDraw ( o )
259 259 if ( ie67 && ($('tbody', nScrollBody).height() > nScrollBody.offsetHeight ||
260 260 $(nScrollBody).css('overflow-y') == "scroll") )
261 261 {
262   - o.nTable.style.width = _fnStringToCss( $(o.nTable).outerWidth()-o.oScroll.iBarWidth );
  262 + o.nTable.style.width = _fnStringToCss( $(o.nTable).outerWidth() - o.oScroll.iBarWidth);
263 263 }
264 264 }
265 265 else
@@ -436,12 +436,21 @@ function _fnScrollDraw ( o )
436 436 var iOuterWidth = $(o.nTable).outerWidth();
437 437 nScrollHeadTable.style.width = _fnStringToCss( iOuterWidth );
438 438 nScrollHeadInner.style.width = _fnStringToCss( iOuterWidth );
  439 +
  440 + // Figure out if there are scrollbar present - if so then we need a the header and footer to
  441 + // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
  442 + var bScrolling = $(o.nTable).height() > nScrollBody.clientHeight || $(nScrollBody).css('overflow-y') == "scroll";
  443 + nScrollHeadInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px";
439 444
440 445 if ( o.nTFoot !== null )
441 446 {
442   - nScrollFootInner.style.width = _fnStringToCss( o.nTable.offsetWidth );
443   - nScrollFootTable.style.width = _fnStringToCss( o.nTable.offsetWidth );
  447 + nScrollFootTable.style.width = _fnStringToCss( iOuterWidth );
  448 + nScrollFootInner.style.width = _fnStringToCss( iOuterWidth );
  449 + nScrollFootInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px";
444 450 }
  451 +
  452 + /* Adjust the position of the header incase we loose the y-scrollbar */
  453 + $(nScrollBody).scroll();
445 454
446 455 /* If sorting or filtering has occurred, jump the scrolling back to the top */
447 456 if ( o.bSorted || o.bFiltered )
116 media/unit_testing/templates/6776.php
... ... @@ -0,0 +1,116 @@
  1 +<?php
  2 + header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
  3 + header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
  4 + header( 'Cache-Control: no-store, no-cache, must-revalidate' );
  5 + header( 'Cache-Control: post-check=0, pre-check=0', false );
  6 + header( 'Pragma: no-cache' );
  7 +?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
  8 +<html>
  9 + <head>
  10 + <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  11 + <link rel="shortcut icon" type="image/ico" href="http://www.sprymedia.co.uk/media/images/favicon.ico" />
  12 +
  13 + <title>DataTables unit testing</title>
  14 + <style type="text/css" title="currentStyle">
  15 + @import "../../css/demo_page.css";
  16 + @import "../../css/demo_table.css";
  17 + </style>
  18 + <script type="text/javascript" language="javascript" src="../../js/jquery.js"></script>
  19 + <script type="text/javascript" language="javascript" src="../../js/jquery.dataTables.js"></script>
  20 + <script type="text/javascript" language="javascript" src="../unit_test.js"></script>
  21 + <?php
  22 + $aScripts = explode( ":", $_GET['scripts'] );
  23 + for ( $i=0 ; $i<count($aScripts) ; $i++ )
  24 + {
  25 + echo '<script type="text/javascript" language="javascript" src="../'.$aScripts[$i].'?rand='.rand().'"></script>'."\n";
  26 + }
  27 + ?>
  28 + </head>
  29 + <body id="dt_example">
  30 + <div id="container">
  31 + <div id="demo">
  32 + <h1>Live example</h1>
  33 + <table>
  34 + <thead/>
  35 + <tbody>
  36 + <tr>
  37 + <td>
  38 + <div>
  39 + <table cellpadding="0" cellspacing="0" border="0" class="display" id="example">
  40 + <thead>
  41 + <tr>
  42 + <th>Rendering engine</th>
  43 + <th width="25%">Browser</th>
  44 + <th>Platform(s)</th>
  45 + <th>Engine version</th>
  46 + <th>CSS grade</th>
  47 + </tr>
  48 + </thead>
  49 + <tbody>
  50 + <tr class="odd gradeX">
  51 + <td>Trident</td>
  52 + <td>Internet Explorer 4.0</td>
  53 + <td>Win 95+</td>
  54 + <td class="center"> 4</td>
  55 + <td class="center">X</td>
  56 + </tr>
  57 + <tr class="odd gradeX">
  58 + <td>Trident</td>
  59 + <td>Internet Explorer 4.0</td>
  60 + <td>Win 95+</td>
  61 + <td class="center"> 4</td>
  62 + <td class="center">X</td>
  63 + </tr>
  64 + <tr class="odd gradeX">
  65 + <td>Trident</td>
  66 + <td>Internet Explorer 4.0</td>
  67 + <td>Win 95+</td>
  68 + <td class="center"> 4</td>
  69 + <td class="center">X</td>
  70 + </tr>
  71 + <tr class="odd gradeX">
  72 + <td>Trident</td>
  73 + <td>Internet Explorer 4.0</td>
  74 + <td>Win 95+</td>
  75 + <td class="center"> 4</td>
  76 + <td class="center">X</td>
  77 + </tr>
  78 + <tr class="odd gradeX">
  79 + <td>Trident</td>
  80 + <td>Internet Explorer 4.0</td>
  81 + <td>Win 95+</td>
  82 + <td class="center"> 4</td>
  83 + <td class="center">X</td>
  84 + </tr>
  85 + <tr class="odd gradeX">
  86 + <td>Trident</td>
  87 + <td>Internet Explorer 4.0</td>
  88 + <td>Win 95+</td>
  89 + <td class="center"> 4</td>
  90 + <td class="center">X</td>
  91 + </tr>
  92 + <tr class="odd gradeX">
  93 + <td>Trident</td>
  94 + <td>Internet Explorer 4.0</td>
  95 + <td>Win 95+</td>
  96 + <td class="center"> 4</td>
  97 + <td class="center">X</td>
  98 + </tr>
  99 + <tr class="odd gradeX">
  100 + <td>Trident</td>
  101 + <td>Internet Explorer 4.0</td>
  102 + <td>Win 95+</td>
  103 + <td class="center"> 4</td>
  104 + <td class="center">X</td>
  105 + </tr>
  106 + </tbody>
  107 + </table>
  108 + </div>
  109 + </td>
  110 + </tr>
  111 + </tbody>
  112 + </table>
  113 + </div>
  114 + </div>
  115 + </body>
  116 +</html>
64 media/unit_testing/tests_onhold/1_dom/6776-scrolling-table-grows.js
... ... @@ -0,0 +1,64 @@
  1 +// DATA_TEMPLATE: 6776
  2 +oTest.fnStart( "Actions on a scrolling table keep width" );
  3 +
  4 +
  5 +$(document).ready( function () {
  6 + var oTable = $('#example').dataTable( {
  7 + "bFilter": true,
  8 + "bSort": true,
  9 + "sScrollY": "100px",
  10 + "bPaginate": false
  11 + } );
  12 +
  13 + var iWidth = $('div.dataTables_wrapper').width();
  14 +
  15 + oTest.fnTest(
  16 + "First sort has no effect on width",
  17 + function () { $('th:eq(1)').click(); },
  18 + function () { return $('div.dataTables_wrapper').width() == iWidth; }
  19 + );
  20 +
  21 + oTest.fnTest(
  22 + "Second sort has no effect on width",
  23 + function () { $('th:eq(1)').click(); },
  24 + function () { return $('div.dataTables_wrapper').width() == iWidth; }
  25 + );
  26 +
  27 + oTest.fnTest(
  28 + "Third sort has no effect on width",
  29 + function () { $('th:eq(2)').click(); },
  30 + function () { return $('div.dataTables_wrapper').width() == iWidth; }
  31 + );
  32 +
  33 + oTest.fnTest(
  34 + "Filter has no effect on width",
  35 + function () { oTable.fnFilter('i'); },
  36 + function () { return $('div.dataTables_wrapper').width() == iWidth; }
  37 + );
  38 +
  39 + oTest.fnTest(
  40 + "Filter 2 has no effect on width",
  41 + function () { oTable.fnFilter('in'); },
  42 + function () { return $('div.dataTables_wrapper').width() == iWidth; }
  43 + );
  44 +
  45 + oTest.fnTest(
  46 + "No result filter has header and body at same width",
  47 + function () { oTable.fnFilter('xxx'); },
  48 + function () { return $('#example').width() == $('div.dataTables_scrollHeadInner').width(); }
  49 + );
  50 +
  51 + oTest.fnTest(
  52 + "Filter with no results has no effect on width",
  53 + function () { oTable.fnFilter('xxx'); },
  54 + function () { return $('div.dataTables_wrapper').width() == iWidth; }
  55 + );
  56 +
  57 + oTest.fnTest(
  58 + "Filter with no results has table equal to wrapper width",
  59 + function () { oTable.fnFilter('xxx'); },
  60 + function () { return $('div.dataTables_wrapper').width() == $('#example').width(); }
  61 + );
  62 +
  63 + oTest.fnComplete();
  64 +} );
63 media/unit_testing/tests_onhold/1_dom/sScrollXY.js
... ... @@ -0,0 +1,63 @@
  1 +// DATA_TEMPLATE: dom_data
  2 +oTest.fnStart( "sScrollX / Y" );
  3 +
  4 +
  5 +$(document).ready( function () {
  6 + // Force some x scrolling
  7 + $('body').css('white-space', 'nowrap');
  8 + $('#container').css('width', '400px');
  9 +
  10 + var oTable = $('#example').dataTable( {
  11 + "sScrollX": "100%",
  12 + "sScrollY": "200px",
  13 + "bPaginate": false
  14 + } );
  15 +
  16 + oTest.fnWaitTest(
  17 + "Header follows x-scrolling",
  18 + function () { $('div.dataTables_scrollBody').scrollLeft(20); },
  19 + function () { return $('div.dataTables_scrollHead').scrollLeft() == 20; }
  20 + );
  21 +
  22 + oTest.fnWaitTest(
  23 + "Footer follows x-scrolling",
  24 + null,
  25 + function () { return $('div.dataTables_scrollFoot').scrollLeft() == 20; }
  26 + );
  27 +
  28 + oTest.fnWaitTest(
  29 + "y-scrolling has no effect on header",
  30 + function () { $('div.dataTables_scrollBody').scrollTop(20); },
  31 + function () { return $('div.dataTables_scrollHead').scrollLeft() == 20; }
  32 + );
  33 +
  34 + oTest.fnWaitTest(
  35 + "Filtering results in sets y-scroll back to 0",
  36 + function () { oTable.fnFilter('1') },
  37 + function () { return $('div.dataTables_scrollBody').scrollTop() == 0; }
  38 + );
  39 +
  40 + oTest.fnWaitTest(
  41 + "Filtering has no effect on x-scroll",
  42 + null,
  43 + function () { return $('div.dataTables_scrollBody').scrollLeft() == 20; }
  44 + );
  45 +
  46 + oTest.fnWaitTest(
  47 + "Full x-scroll has header track all the way with it",
  48 + function () {
  49 + $('div.dataTables_scrollBody').scrollLeft(
  50 + $('#example').width() - $('div.dataTables_scrollBody')[0].clientWidth
  51 + );
  52 + },
  53 + function () { return $('div.dataTables_scrollBody').scrollLeft() == $('div.dataTables_scrollHead').scrollLeft(); }
  54 + );
  55 +
  56 + oTest.fnTest(
  57 + "Footer also tracked all the way",
  58 + null,
  59 + function () { return $('div.dataTables_scrollBody').scrollLeft() == $('div.dataTables_scrollFoot').scrollLeft(); }
  60 + );
  61 +
  62 + oTest.fnComplete();
  63 +} );

0 comments on commit ab9dfd5

Please sign in to comment.
Something went wrong with that request. Please try again.