{"id":206,"date":"2009-06-06T11:55:09","date_gmt":"2009-06-06T19:55:09","guid":{"rendered":"http:\/\/www.zackgrossbart.com\/hackito\/?p=206"},"modified":"2011-03-11T06:41:39","modified_gmt":"2011-03-11T14:41:39","slug":"jsgrid","status":"publish","type":"post","link":"http:\/\/www.zackgrossbart.com\/hackito\/jsgrid\/","title":{"rendered":"Dynamic Grid Layout In JavaScript"},"content":{"rendered":"<p><script type=\"text\/javascript\" src=\"\/extras\/touchslider\/jquery-1.4.4.min.js\"><\/script><\/p>\n<div>\n<p>\n                You don&#8217;t see layout managers much in web applications.  Most web pages are positioned with a combination of CSS and <code>&lt;table&gt;<\/code> tags.  Higher end sites are switching to totally <a href=\"http:\/\/www.alistapart.com\/articles\/prettyaccessibleforms\">CSS based layouts<\/a>, but it is still a pretty fixed layout.  These mechanisms work reasonably well when you know what you are going to show and how big it is ahead of time, but they are lacking when it comes to dynamic contents.\n            <\/p>\n<p>            <script src=\"\/hackito\/multigrid.js\" type=\"text\/javascript\"><\/script><\/p>\n<style type=\"text\/css\" media=\"all\">\n            @import \"\/hackito\/multigrid.css\";\n        <\/style>\n<p>        <script type=\"text\/javascript\">\n            jQuery(document).ready(function() {\n                alignGrid(\"basicgrid\", 2, 5, 5, 1);\n                alignMultiGrid(2, 5, 5, 1);\n            });\n        <\/script><\/p>\n<div class=\"infobar\" style=\"width: 200px; border: none;\">\n<blockquote><p>\n                    This layout manager was originally developed for a new site I am making called <a href=\"http:\/\/www.gettheeye.com\">Get The Eye<\/a>.  That site (like this one) is a WordPress blog and I wanted to make each article automatically appear on a grid.  I combined JavaScript with PHP to generate a dynamic grid that grows for each new article.\n                <\/p><\/blockquote><\/div>\n<h2>Core Technologies<\/h2>\n<p>\n                This program uses the following core technologies:<\/p>\n<ul>\n<li>JavaScript with <a href=\"http:\/\/jquery.com\/\">JQuery<\/a><\/li>\n<li>CSS<\/li>\n<\/ul>\n<p>\n                This sample is a JavaScript application that makes heavy use of the JQuery library.  It is a good introduction to basic <a href=\"http:\/\/jquery.com\/\">JQuery<\/a>.  It also requires basic understanding of CSS.\n            <\/p>\n<p>\n                The code in this application is free and is released under the <a href=\"http:\/\/www.apache.org\/licenses\/LICENSE-2.0\">Apache 2.0 license<\/a>.  That means you are welcome to use, copy, and change this code as much as you would like. If you find any bugs, have any comments, or make any improvements I would love to hear from you.  This example has been tested in Firefox, IE, Safari, and Chrome.\n            <\/p>\n<h2>A simple example<\/h2>\n<div id=\"basicgrid\" style=\"margin: 0 auto; width: 19.5em; height: 12em;\">\n<div class=\"cell\" style=\"background: lightgreen;\"><span class=\"celltext\">1<\/span><\/div>\n<div class=\"cell\" style=\"background: orange;\"><span class=\"celltext\">2<\/span><\/div>\n<div class=\"cell\" style=\"background: wheat;\"><span class=\"celltext\">3<\/span><\/div>\n<div class=\"cell\" style=\"background: lightblue;\"><span class=\"celltext\">4<\/span><\/div>\n<\/p><\/div>\n<p>\n                In this simple example we line up four items in a two by two grid.  Here the items are simple text, but they are just <code>&lt;div&gt;<\/code> tags and you can put whatever content you want into them.  The grid is aligned with a simple call to the <code>alignGrid<\/code> function.  It looks like this:\n            <\/p>\n<table class=\"code_table\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n<tr>\n<td class=\"code-outline\">\n<pre class=\"displaycode\">jQuery(document).ready(function() {\r\n    alignGrid(\"basicgrid\", 2, 5, 5, 1);\r\n});<\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>\n                This single function call tells the JavaScript code what to do by giving it a series of arguments.  First we tell the code which item to align by specifying the ID of the tag we are using.  Then we give it a little information about how the grid should look.  The next arguments specify the number of the columns, the width of each cell, the height of each cell, and the space in between them.  All of the units are in EMs, but we&#8217;ll look into that later.  This makes it very easy to dynamically change the size and shape of the grid.\n            <\/p>\n<p>\n                You can place this function in a <code>&lt;script&gt;<\/code> tag on the top of an HTML document or in a separate JavaScript file.\n            <\/p>\n<h3>The JavaScript<\/h3>\n<div class=\"sourcebox\">\n                Get the <br \/><a href=\"\/hackito\/multigrid.js\">source code<\/a>\n            <\/div>\n<p>\n                The <code>alignGrid<\/code> function is defined in the multigrid.js file.  Let&#8217;s take a look at how it actually works.\n            <\/p>\n<table class=\"code_table\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n<tr>\n<td class=\"code-outline\">\n<pre class=\"displaycode\">function alignGrid(<span class=\"codecomment\">\/*string*\/<\/span> id, <span class=\"codecomment\">\/*int*\/<\/span> cols, <span class=\"codecomment\">\/*int*\/<\/span> cellWidth, \r\n    <span class=\"codecomment\">\/*int*\/<\/span> cellHeight, <span class=\"codecomment\">\/*int*\/<\/span> padding) {\r\n    \r\nvar x = 0;\r\nvar y = 0;\r\nvar count = 1;\r\n\r\njQuery(\"#\" + id).each(function() {<span class=\"footnote\"><a href=\"#basicnote1\">1<\/a><\/span>\r\n    jQuery(this).css(\"position\", \"relative\");<span class=\"footnote\"><a href=\"#basicnote2\">2<\/a><\/span>\r\n    \r\n    jQuery(this).children(\"div\").each(function() {<span class=\"footnote\"><a href=\"#basicnote3\">3<\/a><\/span>\r\n        jQuery(this).css(\"width\", cellWidth + \"em\");\r\n        jQuery(this).css(\"height\", cellHeight + \"em\");\r\n        jQuery(this).css(\"position\", \"absolute\");\r\n        \r\n        jQuery(this).css(\"left\", x + \"em\");\r\n        jQuery(this).css(\"top\", y + \"em\");\r\n        \r\n        if ((count % cols) == 0) {<span class=\"footnote\"><a href=\"#basicnote4\">4<\/a><\/span>\r\n            x = 0;\r\n            y += cellHeight + padding;\r\n        } else {\r\n            x += cellWidth + padding;\r\n        }\r\n        \r\n        count++;\r\n    });\r\n});\r\n}<\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>\n                This function is calling the most common function in the JQuery library simply called <code>jQuery<\/code>.  You can also use a dollar sign (<code>$<\/code>) instead, but I spelled it out to make everything a little clearer.  You could replace every <code>jQuery<\/code> with a dollar sign and this would still work.\n            <\/p>\n<div class=\"infobar\" style=\"width: 200px; border: none;\">\n<blockquote><p>\n                    An EM is a special unit of measure in CSS.  It is literally the height and width of an uppercase <b>M<\/b> in the current fonts.  EMs are a much more dynamic unit than pixels because they change size when the font size changes.\n                <\/p><\/blockquote><\/div>\n<p>\n                The first step is to find the item we are going to align<span class=\"footnote\"><a name=\"basicnote1\">1<\/a><\/span>.  Then we set a CSS property for that element telling it to use the relative positioning model<span class=\"footnote\"><a name=\"basicnote2\">2<\/a><\/span>.  This is important because we are using absolute positioning within the grid.  That means we specify the exactly where each item should go.  Making the container relative means each of the grid cells is relative to the grid itself.\n            <\/p>\n<p>\n                Once the grid is properly positioned and styled we loop through the cells<span class=\"footnote\"><a name=\"basicnote3\">3<\/a><\/span> and position them.  We then have a little logic to bump down to the next row when we get to the specified number of columns<span class=\"footnote\"><a name=\"basicnote4\">4<\/a><\/span>.\n            <\/p>\n<p>\n                Basically we are finding each cell and setting CSS properties to tell it exactly where to position itself.  The important properties we set are <code>left<\/code>, <code>top<\/code>, <code>width<\/code>, and <code>height<\/code>.  The properties specify where the upper left corner of the cell should be positioned and how large the cell should be.  The unit we are using is EMs.\n            <\/p>\n<h3>The HTML<\/h3>\n<p>\n                Since our JavsScript is doing all of the work the HTML is very simple.\n            <\/p>\n<table class=\"code_table\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n<tr>\n<td class=\"code-outline\">\n<pre class=\"displaycode\">&lt;div id=\"basicgrid\"&gt;\r\n    &lt;div class=\"cell\"&gt;1&lt;\/div&gt;\r\n    &lt;div class=\"cell\"&gt;2&lt;\/div&gt;\r\n    &lt;div class=\"cell\"&gt;3&lt;\/div&gt;\r\n    &lt;div class=\"cell\"&gt;4&lt;\/div&gt;\r\n&lt;\/div&gt;<\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<h2>The multi-grid<\/h2>\n<p>\n                The grid is nice for basic uses, but it has no room to grow.  As the grid gets larger the items will fill up the entire screen.  It needs some way to switch from one set of grid cells to the next; a navigation mechanism.  That is what the multi-grid provides.  Take a look at the example:\n            <\/p>\n<div class=\"maingridcontainer\" style=\"margin: 0 auto; width: 700px; height:14em\">\n<div class=\"multigridcontainer\">\n<div class=\"multigrid\">\n<div class=\"cell\" style=\"background: red;\"><span class=\"celltext\">1<\/span><\/div>\n<div class=\"cell\" style=\"background: gray;\"><span class=\"celltext\">2<\/span><\/div>\n<div class=\"cell\" style=\"background: green;\"><span class=\"celltext\">3<\/span><\/div>\n<div class=\"cell\" style=\"background: yellow;\"><span class=\"celltext\">4<\/span><\/div>\n<div class=\"cell\" style=\"background: lightgreen;\"><span class=\"celltext\">5<\/span><\/div>\n<div class=\"cell\" style=\"background: orange;\"><span class=\"celltext\">6<\/span><\/div>\n<div class=\"cell\" style=\"background: wheat;\"><span class=\"celltext\">7<\/span><\/div>\n<div class=\"cell\" style=\"background: lightblue;\"><span class=\"celltext\">8<\/span><\/div>\n<div class=\"cell\" style=\"background: cyan;\"><span class=\"celltext\">9<\/span><\/div>\n<div class=\"cell\" style=\"background: deeppink;\"><span class=\"celltext\">10<\/span><\/div>\n<div class=\"cell\" style=\"background: gold;\"><span class=\"celltext\">11<\/span><\/div>\n<div class=\"cell\" style=\"background: plum;\"><span class=\"celltext\">12<\/span><\/div>\n<div class=\"cell\" style=\"background: powderblue;\"><span class=\"celltext\">13<\/span><\/div>\n<div class=\"cell\" style=\"background: greenyellow;\"><span class=\"celltext\">14<\/span><\/div>\n<div class=\"cell\" style=\"background: springgreen;\"><span class=\"celltext\">15<\/span><\/div>\n<div class=\"cell\" style=\"background: palevioletred;\"><span class=\"celltext\">16<\/span><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<p>\n                The multi-grid provides three ways to navigate:  the arrow buttons on either side, the navigation bar at the bottom, and your keyboard.  The multi-grid responds to the right arrow, left arrow, HOME, and END keys on your keyboard.  For this reason there can only be one multi-grid per page.\n            <\/p>\n<h2>How it works<\/h2>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"http:\/\/www.zackgrossbart.com\/hackito\/wp-content\/uploads\/2009\/06\/grid_example.gif\" alt=\"grid_example\" title=\"grid_example\" width=\"715\" height=\"219\" class=\"aligncenter size-full wp-image-195\" srcset=\"http:\/\/www.zackgrossbart.com\/hackito\/wp-content\/uploads\/2009\/06\/grid_example.gif 715w, http:\/\/www.zackgrossbart.com\/hackito\/wp-content\/uploads\/2009\/06\/grid_example-300x91.gif 300w\" sizes=\"(max-width: 715px) 100vw, 715px\" \/><\/p>\n<p>\n                The multi-grid is a view port.  Kind of like looking into a room through a keyhole.  You only see a small part of the whole.  The entire grid is always there, but most of the time only part of it is visible.  When you press the next or previous buttons it slides the grid so you are seeing a different part.\n            <\/p>\n<p>\n                This application uses JavaScript and CSS.  There is no Flash, Silverlight, or any other plugin.  It gets all the data from the server and displays it in a way to looks like multiple pages.  Moving within the grid doesn&#8217;t need to contact the server.\n            <\/p>\n<p>\n                The rest of this article will show how this mechanism works and how you can implement it for yourself.  It isn&#8217;t super techy, but it does take some code.\n            <\/p>\n<h2>Making it work<\/h2>\n<p>\n                You call the multi-grid in almost the same way as the basic grid.\n            <\/p>\n<table class=\"code_table\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n<tr>\n<td class=\"code-outline\">\n<pre class=\"displaycode\">jQuery(document).ready(function() {\r\n    alignMultiGrid(2, 5, 5, 1);\r\n});<\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>\n                The function arguments are almost the same, but the multi-grid just allows one per pages so you don&#8217;tt need to specify the tag ID.\n            <\/p>\n<h3>The HTML<\/h3>\n<p>\n                The multi-grid needs to align the navigation buttons and the navigation bar as well as the cells within the grid.  To support that we add a little more structure to our HTML.  It looks like this.\n            <\/p>\n<table class=\"code_table\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n<tr>\n<td class=\"code-outline\">\n<pre class=\"displaycode\">&lt;div class=\"maingridcontainer\"&gt;\r\n    &lt;div class=\"multigridcontainer\"&gt;\r\n        &lt;div class=\"multigrid\"&gt;\r\n            &lt;div class=\"cell\"&gt;1&lt;\/div&gt;\r\n            &lt;div class=\"cell\"&gt;2&lt;\/div&gt;\r\n            &lt;div class=\"cell\"&gt;3&lt;\/div&gt;\r\n            &lt;div class=\"cell\"&gt;4&lt;\/div&gt;\r\n            \r\n            &lt;div class=\"cell\"&gt;5&lt;\/div&gt;\r\n            &lt;div class=\"cell\"&gt;6&lt;\/div&gt;\r\n            &lt;div class=\"cell\"&gt;7&lt;\/div&gt;\r\n            &lt;div class=\"cell\"&gt;8&lt;\/div&gt; \r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/div&gt;<\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>\n                The extra <code>&lt;div&gt;<\/code> tags give us a place to add the extra navigation pieces.  If you&#8217;re familiar with HTML you&#8217;ll notice that there is a lot missing here.  There are no buttons and no button bar.  It all get added by the JavaScript code.  We just need the placeholder for them.\n            <\/p>\n<h3>The JavaScript<\/h3>\n<p>\n                The alignMultiGrid function is a little long so we&#8217;ll look at it in parts.  First we need some variables.\n            <\/p>\n<table class=\"code_table\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n<tr>\n<td class=\"code-outline\">\n<pre class=\"displaycode\">var xoffset = padding;\r\nvar x = xoffset;    <span class=\"codecomment\">\/\/The X position of the current cell<\/span>\r\nvar y = padding;    <span class=\"codecomment\">\/\/The Y position of the current cell<\/span>\r\nvar cellcount = 1;  <span class=\"codecomment\">\/\/The total number of cells<\/span>\r\nvar rowcount = 1;   <span class=\"codecomment\">\/\/The total number of rows<\/span>\r\nvar maxrows = 2;    <span class=\"codecomment\">\/\/The number of rows in each view of the grid<\/span>\r\n\r\n<span class=\"codecomment\">\/\/The width of the grid<\/span>\r\ngridwidth = (cols * (cellWidth + padding)) + padding;\r\n                    \r\n<span class=\"codecomment\">\/\/The height of thr grid<\/span>\r\ngridheight = (maxrows * (cellHeight + padding)) + padding;\r\n\r\n<span class=\"codecomment\">\/\/The position of the grid.  This is used in the navigation.<\/span>\r\ncurrentgrid = 0;<\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>\n                Once the variables are declared we need to set styles on each of the three <code>&lt;div&gt;<\/code> tags.  We handle each tag separately starting with the outer most tag and working our way down to the children.\n            <\/p>\n<table class=\"code_table\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n<tr>\n<td class=\"code-outline\">\n<pre class=\"displaycode\">jQuery(\".maingridcontainer\").each(function() {<span class=\"footnote\"><a href=\"#multinote1\">1<\/a><\/span>\r\n    jQuery(this).css(\"position\", \"relative\");\r\n    jQuery(this).css(\"width\", (gridwidth + 5) + \"em\");\r\n    jQuery(this).css(\"height\", (gridheight + 5) + \"em\");\r\n    \r\n    \r\n    jQuery(this).append(&lt;div class=\\\"nextprev\\\" id=\\\"nextcontainer\\\"&gt;\" + <span class=\"footnote\"><a href=\"#multinote2\">2<\/a><\/span>\r\n        \"&lt;a href=\\\"#\\\" id=\\\"next\\\"&gt;&lt;img src=\\\"nav\/next.gif\\\" border=\\\"0\\\" \/&gt;&lt;\/a&gt;\" + \r\n        \"&lt;\/div&gt;\");\r\n    jQuery(this).append(\"&lt;div class=\\\"nextprev\\\" id=\\\"prevcontainer\\\"&gt;\" + \r\n        \"&lt;a href=\\\"#\\\" id=\\\"prev\\\"&gt;&lt;img src=\\\"nav\/prev.gif\\\" border=\\\"0\\\" \/&gt;&lt;\/a&gt;\" + \r\n        \"&lt;\/div&gt;\");\r\n    \r\n    jQuery(\"#prevcontainer\").each(function() {<span class=\"footnote\"><a href=\"#multinote3\">3<\/a><\/span>\r\n        jQuery(this).css(\"width\", \"4em\");\r\n        jQuery(this).css(\"height\", \"2em\");\r\n        jQuery(this).css(\"position\", \"absolute\");\r\n        \r\n        jQuery(this).css(\"top\", ((maxrows \/ 2) \r\n                    * (cellHeight + padding) - 0.5) + \"em\");<span class=\"footnote\"><a href=\"#multinote4\">4<\/a><\/span>\r\n        jQuery(this).css(\"left\", \"0em\");\r\n    });\r\n    \r\n    jQuery(\"#nextcontainer\").each(function() {\r\n        jQuery(this).css(\"width\", \"4em\");\r\n        jQuery(this).css(\"height\", \"2em\");\r\n        jQuery(this).css(\"position\", \"absolute\");\r\n        \r\n        jQuery(this).css(\"top\", ((maxrows \/ 2) \r\n                    * (cellHeight + padding) - 0.5) + \"em\");\r\n        jQuery(this).css(\"left\", (gridwidth + 2) + \"em\");\r\n    });\r\n});<\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>\n                We start by aligning the next and previous buttons.  First we find the <code>maingridcontainer<\/code><span class=\"footnote\"><a name=\"multinote1\">1<\/a><\/span>.  Then we append the HTML content for the cuttons<span class=\"footnote\"><a name=\"multinote2\">2<\/a><\/span>.  Once we&#8217;ve added the content we can find it and style it<span class=\"footnote\"><a name=\"multinote3\">3<\/a><\/span>.  We set each button to be halfway down the grid<span class=\"footnote\"><a name=\"multinote4\">4<\/a><\/span>.\n            <\/p>\n<p>\n                Now that we&#8217;ve added the next and previous buttons we need to add the navigation grid.  We don&#8217;t know how many cells are in the grid yet so we just add the container for them and we&#8217;ll add the cells later.\n            <\/p>\n<table class=\"code_table\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n<tr>\n<td class=\"code-outline\">\n<pre class=\"displaycode\">jQuery(\".multigridcontainer\").each(function() {\r\n    jQuery(this).css(\"overflow\", \"hidden\");<span class=\"footnote\"><a href=\"#multinote5\">1<\/a><\/span>\r\n    jQuery(this).css(\"position\", \"relative\");\r\n    jQuery(this).css(\"left\", \"2em\");\r\n    jQuery(this).css(\"width\", gridwidth + \"em\");\r\n    jQuery(this).css(\"height\", (gridheight + 5) + \"em\");\r\n    \r\n    jQuery(this).append(\"&lt;div id=\\\"gridnavcontainer\\\"&gt;\" + \r\n                    \"&lt;div id=\\\"gridnav\\\" class=\\\"grid\\\"&gt;&lt;\/div&gt;&lt;\/div&gt;\");<span class=\"footnote\"><a href=\"#multinote6\">2<\/a><\/span>\r\n    jQuery(\"#gridnavcontainer\").each(function() {\r\n        jQuery(this).css(\"position\", \"absolute\");\r\n        jQuery(this).css(\"top\", (gridheight + 3) +  \"em\");<span class=\"footnote\"><a href=\"#multinote7\">3<\/a><\/span>\r\n    });\r\n});<\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>\n                This is also the part of the code where we set the style for the <code>&lt;div&gt;<\/code> tag that directly contains the grid<span class=\"footnote\"><a name=\"multinote5\">1<\/a><\/span>.  We set the <code>overflow<\/code> property to <code>hidden<\/code>.  This is a fundamental part of the multi-grid.  The grid is always there.  Every cell is always rendered, some of them are just off the screen.  This property tells the browser to only show what is visible and not use scroll bars.\n            <\/p>\n<p>\n                After that we add the container for the navigation bar<span class=\"footnote\"><a name=\"multinote6\">2<\/a><\/span> and position it using CSS<span class=\"footnote\"><a name=\"multinote7\">3<\/a><\/span>.\n            <\/p>\n<p>\n                The last part of the alignment process is to align the cells within the grid.  This code looks very similar to the <code>alignGrid<\/code> function from earlier.\n            <\/p>\n<table class=\"code_table\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n<tr>\n<td class=\"code-outline\">\n<pre class=\"displaycode\">jQuery(\".multigrid\").each(function() {\r\njQuery(this).css(\"position\", \"relative\");\r\n\r\njQuery(this).children(\"div\").each(function() {\r\n    jQuery(this).css(\"width\", cellWidth + \"em\");\r\n    jQuery(this).css(\"height\", cellHeight + \"em\");\r\n    jQuery(this).css(\"position\", \"absolute\");\r\n    \r\n    jQuery(this).css(\"left\", x + \"em\");\r\n    jQuery(this).css(\"top\", y + \"em\");\r\n    \r\n    if ((cellcount % cols) == 0) {\r\n        if ((rowcount % maxrows) == 0) {<span class=\"footnote\"><a href=\"#multinote8\">1<\/a><\/span>\r\n            y = padding;\r\n            xoffset += gridwidth;\r\n            x = xoffset;\r\n            gridcount++;\r\n            addNavItem(gridcount);<span class=\"footnote\"><a href=\"#multinote9\">2<\/a><\/span>\r\n            \r\n        } else {\r\n            x = xoffset;\r\n            y += cellHeight + padding;\r\n        }\r\n        \r\n        rowcount++;\r\n    } else {\r\n        x += cellWidth + padding;\r\n    }\r\n    \r\n    cellcount++;\r\n});<\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>\n                We are once again looping through the cells in the grid and setting their position.  We also need to adjust for the maximum number of rows in each grid<span class=\"footnote\"><a name=\"multinote8\">1<\/a><\/span>.  We also call a function to add an item to the navigation bar when there is a new grid<span class=\"footnote\"><a name=\"multinote9\">2<\/a><\/span>.\n            <\/p>\n<p>\n                After this we do a little extra like adding listeners for the button clicks.  It is also interesting to note that we&#8217;ll use the <code>alignGrid<\/code> function from earlier to align the items in the navigation bar.  You can see those functions by looking at the source code.\n            <\/p>\n<h2>The slide<\/h2>\n<p>\n                The other interesting function to look at is <code>positionGrid<\/code>.  This function responds to the navigation buttons and positions the grid using the slide effect.  The slide is a custom effect, but JQuery makes creating those types of effects very easy.\n            <\/p>\n<table class=\"code_table\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n<tr>\n<td class=\"code-outline\">\n<pre class=\"displaycode\">function positionGrid(<span class=\"codecomment\">\/* int *\/<\/span> gridpos) {\r\n    jQuery(\"#gridnav\" + currentgrid).removeClass(\"gridnavitemselected\");\r\n    currentgrid = gridpos;\r\n    jQuery(\".multigrid\").each(function() {<span class=\"footnote\"><a href=\"#multinote10\">1<\/a><\/span>\r\n        jQuery(this).animate({ \r\n            left: \"-\" + (gridwidth * currentgrid) + \"em\"\r\n            }, 1500 );\r\n    });\r\n    \r\n    if (currentgrid == 0) {<span class=\"footnote\"><a href=\"#multinote11\">2<\/a><\/span>\r\n        jQuery(\"#prevcontainer\").hide(0);\r\n    } else {\r\n        jQuery(\"#prevcontainer\").show(0);\r\n    }\r\n    \r\n    if (currentgrid == (gridcount - 1)) {\r\n        jQuery(\"#nextcontainer\").hide(0);\r\n    } else {\r\n        jQuery(\"#nextcontainer\").show(0);\r\n    }\r\n    \r\n    jQuery(\"#gridnav\" + currentgrid).addClass(\"gridnavitemselected\");<span class=\"footnote\"><a href=\"#multinote12\">3<\/a><\/span>\r\n    \r\n    return false;\r\n}<\/pre>\n<\/td>\n<\/tr>\n<\/table>\n<p>\n                All of the mechanisms that reposition the grid eventually call this function which contains the slide animation<span class=\"footnote\"><a name=\"multinote10\">1<\/a><\/span>.  Really.  That is all there is to it.  I just tell JQuery to animate a transition from the current CSS properties to the one I specified and tell it how long to take.  That&#8217;s all there is to it.\n            <\/p>\n<p>\n                After that I do a little cleaning up like making sure the next and previous buttons are only showing if there is a next or previous page<span class=\"footnote\"><a name=\"multinote11\">2<\/a><\/span> and setting the CSS class that gives the selected navigation item the green background<span class=\"footnote\"><a name=\"multinote12\">3<\/a><\/span>.\n            <\/p>\n<h2>Conclusion<\/h2>\n<p>\n                Web applications are still catching up to their desktop counter parts.  These types of layout managers get us a small step closer to a fully-featured web.\n            <\/p>\n<p>\n                Feel free to use this technique and this code on your site.  If you do please leave a comment and let us know.  We&#8217;d love to hear about you.\n            <\/p>\n<\/p><\/div>\n<p>        <input type=\"text\" id=\"tag\" style=\"display: none;\"\/><\/p>\n<div id=\"output_msg\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>You don&#8217;t see layout managers much in web applications. Most web pages are positioned with a combination of CSS and &lt;table&gt; tags. Higher end sites are switching to totally CSS based layouts, but it is still a pretty fixed layout. These mechanisms work reasonably well when you know what you are going to show and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[24,6,7,20],"tags":[],"_links":{"self":[{"href":"http:\/\/www.zackgrossbart.com\/hackito\/wp-json\/wp\/v2\/posts\/206"}],"collection":[{"href":"http:\/\/www.zackgrossbart.com\/hackito\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.zackgrossbart.com\/hackito\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.zackgrossbart.com\/hackito\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.zackgrossbart.com\/hackito\/wp-json\/wp\/v2\/comments?post=206"}],"version-history":[{"count":16,"href":"http:\/\/www.zackgrossbart.com\/hackito\/wp-json\/wp\/v2\/posts\/206\/revisions"}],"predecessor-version":[{"id":1007,"href":"http:\/\/www.zackgrossbart.com\/hackito\/wp-json\/wp\/v2\/posts\/206\/revisions\/1007"}],"wp:attachment":[{"href":"http:\/\/www.zackgrossbart.com\/hackito\/wp-json\/wp\/v2\/media?parent=206"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.zackgrossbart.com\/hackito\/wp-json\/wp\/v2\/categories?post=206"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.zackgrossbart.com\/hackito\/wp-json\/wp\/v2\/tags?post=206"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}