Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added sticky-header functionality #25

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 149 additions & 0 deletions app/js/sticky.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
$(function(){
$('table').each(function() {
if($(this).find('thead').length > 0 && $(this).find('th').length > 0) {
// Clone <thead>
var $w = $(window);
var $t = $(this);
var $thead = $t.find('thead').clone();
var $col = $t.find('thead, tbody').clone();

// Add class, remove margins, reset width and wrap table
$t
.addClass('sticky-enabled')
.css({
margin: 0,
width: '100%'
}).wrap('<div class="sticky-wrap" />');

if($t.hasClass('overflow-y')) $t.removeClass('overflow-y').parent().addClass('overflow-y');

// Create new sticky table head (basic)
$t.after('<table class="sticky-thead" />');

// If <tbody> contains <th>, then we create sticky column and intersect (advanced)
if($t.find('tbody th').length > 0) {
$t.after('<table class="sticky-col" /><table class="sticky-intersect" />');
}

// Create shorthand for things
var $stickyHead = $(this).siblings('.sticky-thead'),
$stickyCol = $(this).siblings('.sticky-col'),
$stickyInsct = $(this).siblings('.sticky-intersect'),
$stickyWrap = $(this).parent('.sticky-wrap');

$stickyHead.append($thead);

$stickyCol
.append($col)
.find('thead th:gt(0)').remove()
.end()
.find('tbody td').remove();

$stickyInsct.html('<thead><tr><th>'+$t.find('thead th:first-child').html()+'</th></tr></thead>');

// Set widths
var setWidths = function () {
$t
.find('thead th').each(function (i) {
$stickyHead.find('th').eq(i).width($(this).width());
})
.end()
.find('tr').each(function (i) {
$stickyCol.find('tr').eq(i).height($(this).height());
});

// Set width of sticky table head
$stickyHead.width($t.width());

// Set width of sticky table col
$stickyCol.find('th').add($stickyInsct.find('th')).width($t.find('thead th').width())
},
repositionStickyHead = function () {
// Return value of calculated allowance
var allowance = calcAllowance();

// Check if wrapper parent is overflowing along the y-axis
if($t.height() > $stickyWrap.height()) {
// If it is overflowing (advanced layout)
// Position sticky header based on wrapper scrollTop()
if($stickyWrap.scrollTop() > 0) {
// When top of wrapping parent is out of view
$stickyHead.add($stickyInsct).css({
opacity: 1,
top: $stickyWrap.scrollTop()
});
} else {
// When top of wrapping parent is in view
$stickyHead.add($stickyInsct).css({
opacity: 0,
top: 0
});
}
} else {
// If it is not overflowing (basic layout)
// Position sticky header based on viewport scrollTop
if($w.scrollTop() > $t.offset().top && $w.scrollTop() < $t.offset().top + $t.outerHeight() - allowance) {
// When top of viewport is in the table itself
$stickyHead.add($stickyInsct).css({
opacity: 1,
top: $w.scrollTop() - $t.offset().top
});
} else {
// When top of viewport is above or below table
$stickyHead.add($stickyInsct).css({
opacity: 0,
top: 0
});
}
}
},
repositionStickyCol = function () {
if($stickyWrap.scrollLeft() > 0) {
// When left of wrapping parent is out of view
$stickyCol.add($stickyInsct).css({
opacity: 1,
left: $stickyWrap.scrollLeft()
});
} else {
// When left of wrapping parent is in view
$stickyCol
.css({ opacity: 0 })
.add($stickyInsct).css({ left: 0 });
}
},
calcAllowance = function () {
var a = 0;
// Calculate allowance
$t.find('tbody tr:lt(3)').each(function () {
a += $(this).height();
});

// Set fail safe limit (last three row might be too tall)
// Set arbitrary limit at 0.25 of viewport height, or you can use an arbitrary pixel value
if(a > $w.height()*0.25) {
a = $w.height()*0.25;
}

// Add the height of sticky header
a += $stickyHead.height();
return a;
};

setWidths();

$t.parent('.sticky-wrap').scroll($.throttle(15, function() {
repositionStickyHead();
repositionStickyCol();
}));

$w
.load(setWidths)
.resize($.debounce(250, function () {
setWidths();
repositionStickyHead();
repositionStickyCol();
}))
.scroll($.throttle(15, repositionStickyHead));
}
});
});
39 changes: 38 additions & 1 deletion app/scss/stylesheet.scss
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ table {
border: 1px solid #373737;
margin-bottom: 20px;
text-align: left;
position: relative;
}

th {
Expand Down Expand Up @@ -443,4 +444,40 @@ td img {
img.toggle {
float: right;
width: 24px;
}
}

/*************
Sticky header
*************/
.sticky-wrap {
overflow-x: auto;
overflow-y: hidden;
position: relative;
margin: 3em 0;
width: 100%;
.sticky-thead, .sticky-col, .sticky-intersect {
opacity: 0;
position: absolute;
top: 0;
left: 0;
transition: all .125s ease-in-out;
z-index: 50;
width: auto; /* Prevent table from stretching to full size */
}
.sticky-thead {
box-shadow: 0 0.25em 0.1em -0.1em rgba(0,0,0,.125);
z-index: 100;
width: 100%; /* Force stretch */
}
.sticky-intersect {
opacity: 1;
z-index: 150;
}
.sticky-intersect th {
background-color: #666;
color: #eee;
}
td,th {
box-sizing: border-box;
}
}
20 changes: 12 additions & 8 deletions app/templates/companies.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@
<col width="15%">
<col width="15%">
<col width="15%">
<tr>
<th>#</th>
<th>Company</th>
<th>Contributors</th>
<th>Mentions</th>
<th>Percent</th>
</tr>
<thead>
<tr>
<th>#</th>
<th>Company</th>
<th>Contributors</th>
<th>Mentions</th>
<th>Percent</th>
</tr>
</thead>
<tbody>
<% companies.each do |name, values| %>
<tr>
<td id="<%= name %>"><%= (lastMentions == values['mentions']) ? lastOrder : i %></td>
Expand All @@ -48,7 +51,8 @@
</tr>
<% end %>

</tbody>
</table>
</section>
</div>
<%= footer %>
<%= footer %>
16 changes: 10 additions & 6 deletions app/templates/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@
<col width="65%">
<col width="15%">
<col width="15%">
<tr>
<th>#</th>
<th>Drupal.org Username</th>
<th>Mentions</th>
<th>Percent</th>
</tr>
<thead>
<tr>
<th>#</th>
<th>Drupal.org Username</th>
<th>Mentions</th>
<th>Percent</th>
</tr>
</thead>
<tbody>
<% contributors.each do |name, mentions| %>
<tr>
<td id="<%= name %>"><%= (lastMentions == mentions) ? lastOrder : i %></td>
Expand All @@ -35,6 +38,7 @@
<% lastMentions = mentions %></tr>
<% end %>

</tbody>
</table>
</section>
</div>
Expand Down
4 changes: 3 additions & 1 deletion app/templates/partials/footer.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
<!-- build:js js/all.min.js -->
<script src="js/libs/jquery/dist/jquery.min.js"></script>
<script src="js/libs/jquery-timeago/jquery.timeago.js"></script>
<script src="js/libs/jquery-throttle-debounce/jquery.ba-throttle-debounce.min.js"></script>
<script src="js/timeago.js"></script>
<script src="js/reveal-employees.js"></script>
<script src="js/sticky.js"></script>
<!-- endbuild -->
</body>
</html>
</html>
1 change: 1 addition & 0 deletions bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
],
"dependencies": {
"jquery-timeago": "~1.4.1",
"jquery-throttle-debounce": "v1.1",
"jquery": "~2.1.1"
}
}