;(function($,window,document,undefined){"use strict";var pluginName="tileWall",defaults={debounceTime:100,debug:0,hideNavTilesOnViewportWidthSmallerThan:0,maxNumCols:12,minNumCols:3,minTileWidth:130,shrinkTilesOnViewportWidthSmallerThan:0,tileClassName:"tile",tileMargin:2,transition:0};var tileDimensions={},tiles=[],numCols=0,numRows=0,overallTileSize=0,tileGrid=[],properPositionAllTilesPossible,self;function Plugin(element,options){this.element=element;this.settings=$.extend({},defaults,options);this._defaults=defaults;this._name=pluginName;this.init();this.reformatTiles();this.reformatTiles();var cachedWidth=$(window).width();$(window).resize(this.debouncer(function(){if($(window).width()!==cachedWidth){cachedWidth=$(window).width();self.reformatTiles();}},this.settings.debounceTime));}
$.extend(Plugin.prototype,{init:function(){self=this;if(this.settings.debug){this.debugLog("settings:\n"+JSON.stringify(this.settings,null,2));}
if(this.settings.debug&&this.settings.shrinkTilesOnViewportWidthSmallerThan){var msg="Automatically shrinking tiles because viewport width is smaller than ";msg+=this.settings.shrinkTilesOnViewportWidthSmallerThan+"px disregarding the fix positioning of tiles.";this.debugLog(msg);}
this.setTileWallPositionRelative();},getTileWallWrapperWidth:function(){var viewPortWidth=$(window).outerWidth(),tileWallWrapperWidth=$(this.element).width();return(viewPortWidth>tileWallWrapperWidth)?tileWallWrapperWidth:viewPortWidth;},calculateNumCols:function(){numCols=this.settings.maxNumCols;while(((this.getTileWallWrapperWidth()-numCols*2*this.settings.tileMargin)/ numCols)<this.settings.minTileWidth){numCols--;if(numCols===this.settings.minNumCols){break;}}},calculateIdealNumRows:function(){numRows=Math.ceil(overallTileSize / numCols);},calculateTileDimensions:function(){tileDimensions.width=tileDimensions.height=(this.getTileWallWrapperWidth()-numCols*2*this.settings.tileMargin)/ numCols;},setTileWallPositionRelative:function(){$(this.element).css("position","relative");},setTileWallWrapperHeight:function(){$(this.element).css("height",numRows*(tileDimensions.height+(this.settings.tileMargin*2))+"px");},setTileDimensions:function(){overallTileSize=0;tiles=[];var tile,tileId=1,tileElements=$(this.element).find("."+this.settings.tileClassName),self=this;if(tileElements.length===0&&this.settings.debug){this.debugLog("No DOM elements with class '"+this.settings.tileClassName+"' to use as tiles found.");return false;}
tileElements.each(function(){tile=$(this);if(tile.data("nav")&&self.settings.hideNavTilesOnViewportWidthSmallerThan&&self.getTileWallWrapperWidth()<self.settings.hideNavTilesOnViewportWidthSmallerThan){tile.css("display","none");return true;}
var width=parseInt(tile.data("width"))?parseInt(tile.data("width")):1,height=parseInt(tile.data("height"))?parseInt(tile.data("height")):1,positionX=parseInt(tile.data("position-x"))?parseInt(tile.data("position-x")):undefined,positionY=parseInt(tile.data("position-y"))?parseInt(tile.data("position-y")):undefined;if(self.settings.shrinkTilesOnViewportWidthSmallerThan&&self.getTileWallWrapperWidth()<self.settings.shrinkTilesOnViewportWidthSmallerThan){width=1;height=1;}
tile.css("position","absolute");tile.css("display","block");tile.css("width",(tileDimensions.width*width)+((width-1)*self.settings.tileMargin*2)+"px");tile.css("height",(tileDimensions.height*height)+((height-1)*self.settings.tileMargin*2)+"px");tile.css("margin",self.settings.tileMargin+"px");if(self.settings.transition){tile.css("transition","0.2s ease-out");}
tiles[tileId]={ref:tile,width:width,height:height,size:width*height,priority:tile.data("priority")?tile.data("priority"):0,positionX:positionX,positionY:positionY,nav:tile.data("nav")?true:undefined};overallTileSize+=width*height;tileId++;});},sortTilesBySizeAndCurrentness:function(){var sortedTiles=[];for(var i=1;i<tiles.length;i++){if(tiles[i].nav!==undefined||tiles[i].positionX!==undefined){continue;}
for(var j=0;j<tiles.length;j++){if(sortedTiles[j]===undefined||(tiles[i].priority>sortedTiles[j].priority&&tiles[i].size===sortedTiles[j].size)||(tiles[i].size>sortedTiles[j].size&&tiles[i].priority===sortedTiles[j].priority))
{sortedTiles.splice(j,0,tiles[i]);break;}}}
for(i=1;i<tiles.length;i++){if(tiles[i].nav===true&&tiles[i].positionX===undefined){sortedTiles.splice(0,0,tiles[i]);}}
for(i=1;i<tiles.length;i++){if(tiles[i].positionX!==undefined){sortedTiles.splice(0,0,tiles[i]);}}
var arr=[];for(i=0;i<sortedTiles.length;i++){arr[i+1]=sortedTiles[i];}
tiles=arr;if(this.settings.debug){var sortedTilesString="";for(var k=0;k<sortedTiles.length;k++){sortedTilesString+="priority: "+sortedTiles[k].priority+" | ";sortedTilesString+="size: "+sortedTiles[k].size+" | ";sortedTilesString+="positionX: "+sortedTiles[k].positionX+" | ";sortedTilesString+="positionY: "+sortedTiles[k].positionY+" | ";sortedTilesString+="nav: "+sortedTiles[k].nav+"\n";}
this.debugLog("sorted tiles:\n"+sortedTilesString);}},reformatTiles:function(){this.calculateNumCols();this.calculateTileDimensions();this.setTileDimensions();this.sortTilesBySizeAndCurrentness();this.calculateIdealNumRows();this.setTileWallWrapperHeight();if(this.settings.debug){this.debugLog("initial overallTileSize: "+overallTileSize);this.debugLog("initial numRows: "+numRows);this.debugLog("initial numCols: "+numCols);}
var numTries=0;properPositionAllTilesPossible=false;while(!properPositionAllTilesPossible){numTries++;tileGrid=this.initTileGridArray();properPositionAllTilesPossible=true;$.each(tiles,this.placeTile);if(numTries>50){numTries=0;numRows++;this.setTileWallWrapperHeight();if(this.settings.debug){this.debugLog("increased number of rows: "+numRows);}}}
if(this.settings.debug){this.debugLog("number of tries to position all tiles properly: "+numTries);}},placeTile:function(index,element){var tilePlaced,randX,randY,occupiedGridCoordinates,total,i,loopCount;if(index===0){return;}
tilePlaced=false;loopCount=0;do{loopCount++;if(loopCount>200){if(element.ref!==undefined){properPositionAllTilesPossible=false;}
break;}
if(element.positionX+element.width-1>numCols){element.positionX=undefined;}
if(element.positionX!==undefined){occupiedGridCoordinates=[{x:element.positionX,y:element.positionY}];occupiedGridCoordinates=self.addTileSurfaceCoordinates(this,occupiedGridCoordinates);total=0;for(i=0;i<occupiedGridCoordinates.length;i++){total+=tileGrid[occupiedGridCoordinates[i].y][occupiedGridCoordinates[i].x];}}
else{randX=Math.floor((Math.random()*(numCols-(element.width-1)))+1);if(loopCount<25){randY=Math.floor((Math.random()*(Math.ceil(numRows / 2)-(element.height-1)))+1);}else if(loopCount<50){randY=Math.floor((Math.random()*(Math.ceil(numRows / 1.6)-(element.height-1)))+1);}else if(loopCount<75){randY=Math.floor((Math.random()*(Math.ceil(numRows / 1.2)-(element.height-1)))+1);}else{randY=Math.floor((Math.random()*(numRows-(element.height-1)))+1);}
occupiedGridCoordinates=[{x:randX,y:randY}];occupiedGridCoordinates=self.addTileSurfaceCoordinates(this,occupiedGridCoordinates);total=0;for(i=0;i<occupiedGridCoordinates.length;i++){total+=tileGrid[occupiedGridCoordinates[i].y][occupiedGridCoordinates[i].x];}}
if(total===0){$.each(occupiedGridCoordinates,function(){tileGrid[this.y][this.x]=index;});element.ref.css("left",(occupiedGridCoordinates[0].x-1)*(tileDimensions.width+(self.settings.tileMargin*2))+"px");element.ref.css("top",(occupiedGridCoordinates[0].y-1)*(tileDimensions.height+(self.settings.tileMargin*2))+"px");tilePlaced=true;}}while(!tilePlaced);},initTileGridArray:function(){tileGrid=[];for(var i=1;i<=numRows;i++){tileGrid[i]=[];for(var j=1;j<=numCols;j++){tileGrid[i][j]=0;}}
return tileGrid;},addTileSurfaceCoordinates:function(tile,occupiedGridCoordinates){var i,j;if(tile.width>1){for(i=occupiedGridCoordinates[0].x+1;i<occupiedGridCoordinates[0].x+tile.width;i++){occupiedGridCoordinates.push({y:occupiedGridCoordinates[0].y,x:i});}}
if(tile.height>1){for(i=occupiedGridCoordinates[0].y+1;i<occupiedGridCoordinates[0].y+tile.height;i++){occupiedGridCoordinates.push({y:i,x:occupiedGridCoordinates[0].x});}}
if(tile.width>1&&tile.height>1){for(i=occupiedGridCoordinates[0].y+1;i<occupiedGridCoordinates[0].y+tile.height;i++){for(j=occupiedGridCoordinates[0].x+1;j<occupiedGridCoordinates[0].x+tile.width;j++){occupiedGridCoordinates.push({y:i,x:j});}}}
return occupiedGridCoordinates;},debouncer:function(func,_timeout){var timeoutID,timeout=_timeout||200;return function(){var scope=this,args=arguments;clearTimeout(timeoutID);timeoutID=setTimeout(function(){func.apply(scope,Array.prototype.slice.call(args));},timeout);};},debugLog:function(msg){console.log("["+this._name+" debug] "+msg);}});$.fn[pluginName]=function(options){return this.each(function(){if(!$.data(this,"plugin_"+pluginName)){$.data(this,"plugin_"+pluginName,new Plugin(this,options));}});};})(jQuery,window,document);
|