|
| 1 | +(function() { |
| 2 | + "use strict"; |
| 3 | + |
| 4 | + var Tiler = function(container) { |
| 5 | + // fail early without doing anything if the container is missing... |
| 6 | + if (container === null) { return; } |
| 7 | + this.container = container; |
| 8 | + this.tiles = container.querySelectorAll('[data-tile]'); |
| 9 | + // ... of if it has no tiles in it |
| 10 | + if (this.tiles.length === 0) { return; } |
| 11 | + this.layoutTiles(); |
| 12 | + }; |
| 13 | + |
| 14 | + Tiler.prototype.layoutTiles = function() { |
| 15 | + var cellDimensions = this.cellDimensions(), |
| 16 | + topLeftPosition = this.topLeftPosition(), |
| 17 | + tileGap = this.tileGap(), |
| 18 | + containerHeight = 0, |
| 19 | + containerWidth = 0; |
| 20 | + for (var i = 0; i < this.tiles.length; i++) { |
| 21 | + var tile = this.tiles[i]; |
| 22 | + this.layTile(tile, topLeftPosition, cellDimensions, tileGap); |
| 23 | + var tileBottom = (tile.offsetTop + tile.offsetHeight), |
| 24 | + tileRight = (tile.offsetLeft + tile.offsetWidth); |
| 25 | + |
| 26 | + if (tileBottom > containerHeight) { containerHeight = tileBottom; } |
| 27 | + if (tileRight > containerWidth) { containerWidth = tileRight; } |
| 28 | + } |
| 29 | + this.container.style.width = containerWidth + 'px'; |
| 30 | + this.container.style.height = containerHeight + 'px'; |
| 31 | + }; |
| 32 | + |
| 33 | + Tiler.prototype.layTile = function(tile, topLeft, dimensions, tileGap) { |
| 34 | + var row = this.getNumberFromData(tile, 'tileRow'), |
| 35 | + column = this.getNumberFromData(tile, 'tileColumn'), |
| 36 | + width = this.getNumberFromData(tile, 'tileWidth', 1), |
| 37 | + height = this.getNumberFromData(tile, 'tileHeight', 1); |
| 38 | + |
| 39 | + if ((row === undefined) || (column === undefined)) { |
| 40 | + // don't try to lay the tile if we don't know where it goes |
| 41 | + return; |
| 42 | + } |
| 43 | + |
| 44 | + tile.style.position = 'absolute'; |
| 45 | + tile.style.top = (topLeft.top + ((dimensions.height + tileGap) * row)) + 'px'; |
| 46 | + tile.style.left = (topLeft.left + ((dimensions.width + tileGap) * column)) + 'px'; |
| 47 | + tile.style.width = ((dimensions.width * width) + (tileGap * Math.max(width - 1, 0))) + 'px'; |
| 48 | + tile.style.height = ((dimensions.width * width) + (tileGap * Math.max(width - 1, 0))) + 'px'; |
| 49 | + }; |
| 50 | + |
| 51 | + Tiler.prototype.topLeftPosition = function() { |
| 52 | + if (this._topLeftPosition === undefined) { |
| 53 | + for (var i = 0; i < this.tiles.length; i++) { |
| 54 | + var tile = this.tiles[i]; |
| 55 | + if ((tile.dataset.tileRow === "0") && (tile.dataset.tileColumn === "0")) { |
| 56 | + this._topLeftPosition = { top: tile.offsetTop, left: tile.offsetLeft }; |
| 57 | + return this._topLeftPosition; |
| 58 | + } |
| 59 | + } |
| 60 | + } |
| 61 | + return this._topLeftPosition; |
| 62 | + }; |
| 63 | + |
| 64 | + Tiler.prototype.cellDimensions = function() { |
| 65 | + if (this._cellDimensions === undefined) { |
| 66 | + var aTile = this.container.querySelector('[data-tile]'); |
| 67 | + if (aTile === null) { |
| 68 | + // if there are no tiles in the container, fail fast |
| 69 | + return; |
| 70 | + } |
| 71 | + var cellWidth = Math.ceil(aTile.offsetWidth / this.getNumberFromData(aTile, 'tileWidth', 1)), |
| 72 | + cellHeight = Math.ceil(aTile.offsetHeight / this.getNumberFromData(aTile, 'tileHeight', 1)); |
| 73 | + this._cellDimensions = { width: cellWidth, height: cellHeight }; |
| 74 | + } |
| 75 | + return this._cellDimensions; |
| 76 | + }; |
| 77 | + |
| 78 | + Tiler.prototype.tileGap = function() { |
| 79 | + if (this._tileGap === undefined) { |
| 80 | + this._tileGap = this.getNumberFromData(this.container, 'tileGap', 6); |
| 81 | + } |
| 82 | + return this._tileGap; |
| 83 | + }; |
| 84 | + |
| 85 | + Tiler.prototype.getNumberFromData = function(element, dataName, defaultValue) { |
| 86 | + var value = parseInt(element.dataset[dataName]); |
| 87 | + if (isNaN(value)) { |
| 88 | + return defaultValue; |
| 89 | + } else { |
| 90 | + return value; |
| 91 | + } |
| 92 | + } |
| 93 | + |
| 94 | + var readyFunc = function() { |
| 95 | + var mql = window.matchMedia("(min-width: 660px)"); |
| 96 | + if (mql.matches) { |
| 97 | + new Tiler(document.querySelector('[data-tile-layout]')); |
| 98 | + } |
| 99 | + }; |
| 100 | + |
| 101 | + if (document.readyState != 'loading') { |
| 102 | + readyFunc(); |
| 103 | + } else { |
| 104 | + document.addEventListener("DOMContentLoaded", readyFunc); |
| 105 | + } |
| 106 | +}()); |
0 commit comments