Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

TableGrid

4.80/5 (2 votes)
23 Oct 2015CPOL7 min read 10.8K   85  
Google+ listing of posts titles and tags

Introduction

Having been posting to Google+, I found there was no easy way to search for my posts containing specific tags. My idea was for a listing of Google+ posts titles and tags.

Figure 1a: The design of my idea for a listing of Google+ posts titles and tags

Image 1

With this interface, a user can see all the titles of my posts, but also hashtags, so it is relatively easy to follow a topic through the list.

The project consists of a simple HTML UI built and populated with JavaScript; JSON data to hold the titles and tags; in future it could be developed to use the Google+ API to obtain some of the data dynamically. [But a quick review of the Google+ API led me to believe there was no way to generate the data I required, in a simple format. So for this project, I planned first to put the data in by hand, but in format that could be reproduced by automation, from a suitable source later, hence JSON is used.]

The core task is to create a line builder that can generate the HTML for a table or a grid. Hence the main class is called TableGrid. However, there are a couple of helper functions included.

The current project uses this class to build the UI, and styles with CCS.

The git repository is on GitHub, the following tag corresponds to this article:

Background

[You can skip this section if you are only interested in code.]

CodeProject has a lot of great articles, and it seemed that getting involved would be a good way to consolidate my knowledge. However, when doing my own articles, it seemed difficult to develop them, directly, to the point that they conform to Codeproject requirements. I needed a progression.

Occasionally, I could find a Stackoverflow question about a topic I had gathered some info on, then I could post my notes as an answer. [Although Q&A streams are often like stepping into a windtunnel.]

Then I began posting on Googleplus g+, where you can make any post trivial or complex, and re-edit as often as you like. So rather than dropping these ideas as not adequate for an article, they began to fill up g+.

I have now come full circle, because I am going to describe a little project that arose from my attempts to remain in control of my g+ posts.

Article Content

The project consists of the following files:

  • HtmlTools.js - Contains a class TableGrid for building tables and grids and populating them from data
  • googlePostsList.html - This is a simple webpage to demonstrate the UI in this project
  • googlePostsList.css - Accompanying CSS
  • codeBehind.js - Uses the TableGrid class for this demo
  • Data.js - Contains the JSON data for this example

Although this is not a difficult project, there are several topics involved. To consider the topics separately, in this article, the front end UI and styling will be described first. Then the data requirement is discussed, followed by the class TableGrid and its development.

UI and Styling

The final render of the HTML and CSS was shown in Figure 1a. The HTML structure is alternating div so they can form either two columns or a stack of alternating hashtags and titles.

Figure 2a: Alternate layout, posts titles and tags in a stack, compare to Figure 1a

Image 2

Listing 1a: The html for one post

HTML
<div class="list_container">
    <div class="post_tags">
         <span class="hashtag_button">hashtag1</span>
         <span class="hashtag_button">hashtag2</span>
    </div>
    <div class="post_title">
        <a href="https://...">
        Title</a>
    </div>
</div>

In the CSS to get the required layout behaviour of the div, their display attribute is set to inline-block, and the location of the white space under each post in both arrangements is achieved by increasing the line-height in the second div.

CSS
.post_tags {
  display: inline-block;
  vertical-align: top;
}

.post_title {
  display: inline-block;
  line-height: 22px;
  ...
}

The look of the hashtags and titles, which are set in the CSS class hashtag_button and post_title>a are set to give the list items a similar look to Google+.

CSS
.hashtag_button {
  background-color: #EEE;
  border-color: #DDD;
  ...
}

.post_title>a {
  color: #404040;
  font-style: italic;
  ...
}

Notice that hashtag_button is solely dedicated to this look, hence is separated from the container class post_tags.

The hashtags form a horizontal stack inside the div class post_tags the value of text-align controls the stacking direction. Then in a section for responsive layout changes---where various width settings are also defined---the behaviour of text-align is set differently for each layout.

For full size, like Figure 1a, which are the default values.

CSS
.post_tags {
  text-align: right;
  width: 30%
}

For small size, like Figure 2a, which are controlled by a media rule.

CSS
@media screen and (min-width:0em) and (max-width:40em){
...
  .post_tags {
    text-align: left;
    width: 100%;
  }
...
}

Data

The example of the UI in Figure 1a shows some of the data required for each post:

  • hashtags
  • title

In addition, the UI uses the post title as a hyperlink with the url of the post as a link.

  • url to google post

On Google+ to follow a hashtag, it is added to the base url:

  • plus.google.com/explore/

Like so: plus.google.com/explore/hashtag [NB this link is not implemented in the current example.] This does not require extra data for each post, so the JSON data for a single post has the following format.

Listing 2a: JSON data for a single

CSS
{   tagList: ["tag1", "tag2"], 
    title: "Title of post",
    link:"https:\\ ... "
}

Data for each post is thus stored as an element in an array.

TableGrid

As outlined in the introduction, the requirement of the code behind is to build a list of HTML from rows of data. This is a common task, there are many solutions, this solution does it in the browser with JavaScript using a class dedicated to this task TableGrid.

I have shown the specific data I want to use here, but I really want to maximize the reusability of the code I am developing, and hence data I can handle. To identify the best architecture, we'll compare a hierarchy to a simple 2D table.

Starting with the very simple, for example a list of animals that can be rendered as a list in an HTML table, each row would generate an item like this:

HTML
<tr> <td> dog </td> </tr>

Some functionality in this example can be reused in a general case.

  • Iteration over rows of data

Also the table row always starts and ends with the same sequence <tr> ... </tr>. This wrapping of the row can also be separated in more complicated structures.

  • Separate the wrapping of a row, from the data formatting.

However the handling of data in this case is trivial, simply wrapping data with <td>data</td>, but this would not generally be enough. We also want to be able to handle various types of data, from single strings, and arrays, to more complicated hierarchies, and add them to a table or other structure.

Next consider a more complicated example. Such as the previously suggested use of JSON data allowing hierarchical data sets. Then the problem is to find a pattern that satisfies both the simple example and the complex example. In addition, we need to be able to build more complicated structures than the simple table. I chose to leave the developer to define a function that would receive the data row as a variable, then any structure could be built.

  • Customizable function to convert data row to formatted output.

The pattern derived from the above requirements is shown in Figure 3a.

Figure 3a: TableGrid class and usage pattern

Image 3

To demonstrate this, we will continue with the example. From Listing 1a we can identify each row is prefixed by <div class="list_container"> and suffixed by </div>. Then the inner data-containing elements can be built from the JSON data in Listing 2a in a custom line builder function, which is called while iterating through the rows.

HTML
function myLineBuilder(data){
    s = '\n\t<div class="post_tags">\n\t\t'
    s += HtmlBuilder_wrapArray(data.tagList, 
    ' <span class="hashtag_button">', '</span>')
    s += '\n\t</div>'
    s += '\n\t<div class="post_title">'
    s += '\n\t\t<a href="'+data.link+'/">'
    s += '\n\t\t'+data.title+'</a>'
    s += '\n\t</div>'
    return s
}

Note that HtmlBuilder_wrapArray function is a helper function contained in HtmlTools.js and is used here to generate span tags for the hashtags array data.tagList.

Now we can plug these into TableGrid:

JavaScript
tg = new TableGrid()
tg.setLineBuilder( myLineBuilder, 
'\n<div class="list_container">', '\n</div>')

Then do the build and ask for the result:

JavaScript
tg.buildRows(myPostList)
htmlString = tg.getBlock()

Where myPostList is the array of rows of data for each post.

The code implementing TableGrid is:

JavaScript
function TableGrid(){
    this.linebuilder
    this.linePrefix
    this.lineSuffix
    this.block=""
    
    this.setLineBuilder=function(lb,pre,suf){
      this.linebuilder=lb
      this.linePrefix=pre
      this.lineSuffix=suf
      this.block = ""
     }
     
     this.buildRows=function(table){
        //will loop over the top layer and pass each item to line builder
        for(var i=0; i<table.length; i++){
            tg.buildLine(table[i])
        }
    }
    
    this.buildLine=function(data){
        //prefix line
        s = this.linePrefix

        //run the line builder callback
        s += this.linebuilder(data)
        
        //suffix line
        s += this.lineSuffix
        
        this.block += s
    }
    
    this.getBlock=function(){ return this.block; }
}

Review of Usage

  • Build a data structure
  • Design a HTML view of the data
  • Deconstruct the HTML structure, into line wrapper, line content, and table wrapper
  • Write the line builder
  • initialize TableGrid
  • Once this is done, the data can be sent to TableGrid.buildRows

The instance of the TableGrid itself can be reused by sending a new data set.

Obviously, for building simple tables, this has lead to a relatively complicated method. To maintain simplicity, a creator function is available for simple tables. This has the additional benefit that these predefined instances of the class can also be used for testing. This is not covered further in this article but is in the uploaded project.

Summary

This project covered small amounts of HTML, JavaScript, JSON, CCS.

Thanks for reading, please leave a comment.

History

  • Version 1

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)