Skip to content
This repository has been archived by the owner on Sep 2, 2022. It is now read-only.

Commit

Permalink
Add a JS tiler to fix layout of tiles
Browse files Browse the repository at this point in the history
The HTML now includes data attributes telling the JS tiler the grid
location of each tile, it's size, and the gap between tiles (this data
lives on the container, not each tile).  The tiler then iterates over
each tile and absolutely positions each tile accordingly.
  • Loading branch information
h-lame committed Apr 21, 2017
1 parent a79213b commit 6a31d24
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 10 deletions.
8 changes: 4 additions & 4 deletions source/_blog_grid.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="container--grid">
<div class="container--grid" data-tile-layout data-tile-gap="6">
<%
tiler = Tiler.new(columns: 3, rows: articles.size * 2)
articles.each do |article|
Expand All @@ -11,12 +11,12 @@
end
end
tiles = tiler.lay_tiles
tiles.each do |row|
row.each do |article_tile|
tiles.each.with_index do |row, row_idx|
row.each.with_index do |article_tile, column_idx|
next if article_tile == Tiler::NoTile
next if article_tile.is_a? Tiler::LargeTileReference
%>
<%= partial article_tile.contents.last, locals: { article: article_tile.contents.first } %>
<%= partial article_tile.contents.last, locals: { article: article_tile.contents.first, row: row_idx, column: column_idx } %>
<%
end
end
Expand Down
2 changes: 1 addition & 1 deletion source/_blog_large_tile.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<a class="blog-tile blog-large-tile" href="<%= article.url %>">
<a class="blog-tile blog-large-tile" href="<%= article.url %>" data-tile data-tile-width="2" data-tile-height="2" data-tile-row="<%= row %>" data-tile-column="<%= column %>">
<div class="blog-large-tile__container">
<div class="blog-large-tile__article-image-container">
<img class="blog-large-tile__article-image" src="<%= article.data.main_image %>" alt="Article image">
Expand Down
2 changes: 1 addition & 1 deletion source/_blog_medium_tile.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<a class="blog-tile blog-medium-tile" href="<%= article.url %>">
<a class="blog-tile blog-medium-tile" href="<%= article.url %>" data-tile data-tile-width="1" data-tile-height="2" data-tile-row="<%= row %>" data-tile-column="<%= column %>">
<div class="blog-medium-tile__container">
<div class="blog-medium-tile__top-content">
<div class="blog-medium-tile__title">
Expand Down
2 changes: 1 addition & 1 deletion source/_blog_small_tile.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<a class="blog-tile blog-small-tile" href="<%= article.url %>">
<a class="blog-tile blog-small-tile" href="<%= article.url %>" data-tile data-tile-width="1" data-tile-height="1" data-tile-row="<%= row %>" data-tile-column="<%= column %>">
<div class="blog-small-tile__content">
<div class="blog-small-tile__title">
<%= truncate(article.title, length: 70) %>
Expand Down
1 change: 1 addition & 0 deletions source/assets/javascripts/application.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//= require tiler
//= require waypoints.min

var waypointElement = document.querySelector('[data-header-waypoint]');
Expand Down
106 changes: 106 additions & 0 deletions source/assets/javascripts/tiler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
(function() {
"use strict";

var Tiler = function(container) {
// fail early without doing anything if the container is missing...
if (container === null) { return; }
this.container = container;
this.tiles = container.querySelectorAll('[data-tile]');
// ... of if it has no tiles in it
if (this.tiles.length === 0) { return; }
this.layoutTiles();
};

Tiler.prototype.layoutTiles = function() {
var cellDimensions = this.cellDimensions(),
topLeftPosition = this.topLeftPosition(),
tileGap = this.tileGap(),
containerHeight = 0,
containerWidth = 0;
for (var i = 0; i < this.tiles.length; i++) {
var tile = this.tiles[i];
this.layTile(tile, topLeftPosition, cellDimensions, tileGap);
var tileBottom = (tile.offsetTop + tile.offsetHeight),
tileRight = (tile.offsetLeft + tile.offsetWidth);

if (tileBottom > containerHeight) { containerHeight = tileBottom; }
if (tileRight > containerWidth) { containerWidth = tileRight; }
}
this.container.style.width = containerWidth + 'px';
this.container.style.height = containerHeight + 'px';
};

Tiler.prototype.layTile = function(tile, topLeft, dimensions, tileGap) {
var row = this.getNumberFromData(tile, 'tileRow'),
column = this.getNumberFromData(tile, 'tileColumn'),
width = this.getNumberFromData(tile, 'tileWidth', 1),
height = this.getNumberFromData(tile, 'tileHeight', 1);

if ((row === undefined) || (column === undefined)) {
// don't try to lay the tile if we don't know where it goes
return;
}

tile.style.position = 'absolute';
tile.style.top = (topLeft.top + ((dimensions.height + tileGap) * row)) + 'px';
tile.style.left = (topLeft.left + ((dimensions.width + tileGap) * column)) + 'px';
tile.style.width = ((dimensions.width * width) + (tileGap * Math.max(width - 1, 0))) + 'px';
tile.style.height = ((dimensions.width * width) + (tileGap * Math.max(width - 1, 0))) + 'px';
};

Tiler.prototype.topLeftPosition = function() {
if (this._topLeftPosition === undefined) {
for (var i = 0; i < this.tiles.length; i++) {
var tile = this.tiles[i];
if ((tile.dataset.tileRow === "0") && (tile.dataset.tileColumn === "0")) {
this._topLeftPosition = { top: tile.offsetTop, left: tile.offsetLeft };
return this._topLeftPosition;
}
}
}
return this._topLeftPosition;
};

Tiler.prototype.cellDimensions = function() {
if (this._cellDimensions === undefined) {
var aTile = this.container.querySelector('[data-tile]');
if (aTile === null) {
// if there are no tiles in the container, fail fast
return;
}
var cellWidth = Math.ceil(aTile.offsetWidth / this.getNumberFromData(aTile, 'tileWidth', 1)),
cellHeight = Math.ceil(aTile.offsetHeight / this.getNumberFromData(aTile, 'tileHeight', 1));
this._cellDimensions = { width: cellWidth, height: cellHeight };
}
return this._cellDimensions;
};

Tiler.prototype.tileGap = function() {
if (this._tileGap === undefined) {
this._tileGap = this.getNumberFromData(this.container, 'tileGap', 6);
}
return this._tileGap;
};

Tiler.prototype.getNumberFromData = function(element, dataName, defaultValue) {
var value = parseInt(element.dataset[dataName]);
if (isNaN(value)) {
return defaultValue;
} else {
return value;
}
}

var readyFunc = function() {
var mql = window.matchMedia("(min-width: 660px)");
if (mql.matches) {
new Tiler(document.querySelector('[data-tile-layout]'));
}
};

if (document.readyState != 'loading') {
readyFunc();
} else {
document.addEventListener("DOMContentLoaded", readyFunc);
}
}());
4 changes: 3 additions & 1 deletion source/assets/stylesheets/styles/_blog_large_tile.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
text-decoration: none;

@include breakpoint($tablet-breakpoint) {
float: left;
display: inline-block;
width: 66%;
margin-bottom: 0px;
padding-right: 0px;
}
}

Expand Down
4 changes: 3 additions & 1 deletion source/assets/stylesheets/styles/_blog_medium_tile.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
text-decoration: none;

@include breakpoint($tablet-breakpoint) {
float: left;
display: inline-block;
width: 33%;
margin-bottom: 0px;
padding-right: 0px;
}
}

Expand Down
4 changes: 3 additions & 1 deletion source/assets/stylesheets/styles/_blog_small_tile.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
text-decoration: none;

@include breakpoint($tablet-breakpoint) {
float: left;
display: inline-block;
width: 33%;
margin-bottom: 0px;
padding-right: 0px;
}
}

Expand Down

0 comments on commit 6a31d24

Please sign in to comment.