Tuesday, 24 April 2018

Live data to your page using EventSource

In the following example I deliver live data to a web page. It's possible to do this quite easily using node.js and socket.io. However most of the websites I create are delivered through a shared server and the providers won't let me install node.js, so here I provide an alternative.
In this instance I use a combination of HTML, JavaScript and PHP. It would also be possible to use jQuery instead of straight JavaScript and PHP with something like python or indeed any other language. I also use a JSON file which could be replaced by any other data source.

Let's begin with data source tester.json
[
{
"name": "Aragorn",
"race": "Human"
},
{
"name": "Gimli",
"race": "Dwarf"
}
]

Now, the HTML file (index.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Live data connectivity</title>
</head>
<body>
<table id="myTable">
  <thead>
    <tr>
      <th>Name</th>
      <th>Race</th>
    </tr>
  </thead>
  <tbody></tbody>
</table>
<script src="updatetables.js"></script>
<script src="run.js"></script>
</body>
</html>

Basically we need to check if the HTML table has any data inside. if it doesn't we take data from the data source. If the HTML table does contain data, it will be updated with the contents of the data source. To achieve this we'll use a function inside updatetables.js.
function updateTable(jd, id)
{
  var tbody = document.getElementById(id).tBodies[0];
  for (var i = 0; i < jd.length; i++)
  {
    if(tbody.rows[i] == null)
    {
      /* No data in HTML table */
      var row = tbody.insertRow(i);
      var x = row.insertCell(0);
      x.innerHTML = jd[i].name;
      x = row.insertCell(1);
      x.innerHTML = jd[i].race;
    }
    else
    {
      /* Data in HTML table. Needs updating. */
      var row = tbody.rows[i];
      tbody.rows[i].cells[0].innerHTML = jd[i].name;
      tbody.rows[i].cells[1].innerHTML = jd[i].race;
    }
  }
}

Now that we have a means of updating the table, we need to get the data using stream.php
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$JSON = file_get_contents('tester.json');
echo 'data: '.json_encode($JSON).PHP_EOL.PHP_EOL;
flush();
?>

Finally we can use the JavaScript EventSource object to call stream.php and get our data. Once we have our data, we can pass it to updatetables.js. This is done through run.js
var source = new EventSource('stream.php');
var tableid = 'myTable';
source.onmessage = function(event)
{
  var jsonData = JSON.parse(event.data);
  jsonData = JSON.parse(jsonData);
  updateTable(jsonData, tableid);
};

If you have recreated these files, to test it all works, try changing the values of items in tester.json and see the updates on your page without refresh.




Wednesday, 11 April 2018

CSS Grid Layout by example

In this blog entry, I am going to be using the CSS Grid Layout system available as standard, through the W3C.
There are many blog and vlogs about this, so why bother?
I would like to deliver a simple an consistent approach to all CSS Grid Layout challenges.
Before we make our first grid, I'm going to put a couple of things in place:
  • A CSS class called ".grid" thus : .grid { display: grid; grid-gap: 0.5em; } This enable us to create multiple grids in a row and differentiate between each element, thus: <div class="grid"></div> 
  • A CSS class called ".grid-element" thus : .grid-element { background: #555; color: white; padding: 1em; margin: 0.5em 0; } This enable us to create multiple grid elements which can be clearly seen thus: <div class="grid-element">.grid-element</div> 

grid-1

Our first grid is the simplest. It containes only 1 column.

CSS

#grid-1 { grid-template-columns: auto; }

HTML

<div class="grid" id="grid-1">
    <div class="grid-element">.grid-element</div>
</div>

grid-2

Our next grid is also simple. It contains 2 columns of equal width, and 1 row.

CSS

#grid-2 { grid-template-columns: auto auto; }

HTML

<div class="grid" id="grid-2">
    <div class="grid-element">.grid-element</div>
    <div class="grid-element">.grid-element</div>
</div>

grid-3

Our next grid is also simple. It contains 2 columns, one of 66.6% width, and 1 row.

CSS

#grid-3 { grid-template-columns: 66.6% auto; }

HTML

<div class="grid" id="grid-3">
    <div class="grid-element">.grid-element</div>
    <div class="grid-element">.grid-element</div>
</div>

grid-4

Our next grid is slightly more complicated. It contains 2 columns, one of 66.6% width using the fraction (fr) unit. In the first column, there is 1 row. In the second column, there are 2 rows.

CSS

#grid-4 { grid-template-columns: 2fr 1fr; } #grid-4-second-container { grid-template-rows: auto auto; }

HTML

<div class="grid" id="grid-4">
    <div class="grid-element">.grid-element</div>
    <div id="grid-4-second-container">
        <div class="grid-element">.grid-element</div>
        <div class="grid-element">.grid-element</div>
    </div>
</div>

grid-5

Our next grid is a variation on grid-4. It contains 2 columns, one of 66.6% width using the fraction (fr) unit. In the first column, there are 2 rows. In the second column, there is 1 row.

CSS

#grid-5 { grid-template-columns: 2fr 1fr; } #grid-5-first-container { grid-template-rows: auto auto; }

HTML

<div class="grid" id="grid-5">
    <div id="grid-5-first-container">
        <div class="grid-element">.grid-element</div>
        <div class="grid-element">.grid-element</div>
    </div>
    <div class="grid-element">.grid-element</div>
</div>

grid-6

Our next grid is a variation on grid-4. It contains 3 columns of equal width. In the first column, there is 1 row. In the second column, there are 2 row. In the third column there is 1 row.

CSS

#grid-6 { grid-template-columns: auto auto auto; } #grid-6-middle-container { grid-template-rows: auto auto; }

HTML

<div class="grid" id="grid-6">
    <div class="grid-element">.grid-element</div>
    <div id="grid-6-middle-container">
        <div class="grid-element">.grid-element</div>
        <div class="grid-element">.grid-element</div>
    </div>
    <div class="grid-element">.grid-element</div>
</div>

grid-7

Our next grid is slightly more complicated. It contains 3 columns of equal width. In the first column, there is 1 row. In the second column, there are 2 row. In the third column there is 1 row.

CSS

#grid-7 { grid-template-columns: 2fr 1fr; } #grid-7-column-1-container { display: inline-grid; grid-template-rows: auto auto; } #grid-7-row-2-container { display: inline-grid; grid-template-columns: auto auto; grid-gap: 0.5em; }

HTML

<div class="grid" id="grid-7">
    <div id="grid-7-column-1-container">
        <div class="grid-element">.grid-element</div>
        <div id="grid-7-row-2-container">
             <div class="grid-element">.grid-element</div>
            <div class="grid-element">.grid-element</div>
        </div>
    </div>
    <div class="grid-element">.grid-element</div>
</div>

grid-8

Our next grid makes use of the "grid-template-areas" and "grid-area" properties. Here I use it to create a standard layout of Logo (picture), Header, Nav, Main content area, Sidebar and Footer.

CSS

#grid-8 { grid-template-columns: repeat(auto-fill, 1fr); grid-template-areas: "pic hd hd hd hd hd hd hd hd" "nv nv nv nv nv n-home n-about n-portfolio n-contact" "main main main main main main sd sd sd" "ft ft ft ft ft ft ft ft ft"; } picture { grid-area: pic; } header { grid-area: hd; } nav { grid-area: nv; } a#contact, a#about, a#home, a#portfolio { text-align: center; } a#home { grid-area: n-home; } a#about { grid-area: n-about; } a#portfolio { grid-area: n-portfolio; } a#contact { grid-area: n-contact; } main { grid-area: main; } aside { grid-area: sd; } footer { grid-area: ft; }

HTML

<div class="grid" id="grid-8">
    <picture class="grid-element">Picture</picture>
    <header class="grid-element">Header</header>
    <nav class="grid-element">Nav</nav>
    <a href="#" id="home" class="grid-element">Home</a>
    <a href="#" id="about" class="grid-element">About</a>
    <a href="#" id="contact" class="grid-element">Contact</a>
    <a href="#" id="portfolio" class="grid-element">Portfolio</a>
    <main class="grid-element">Main</main>
    <aside class="grid-element">Aside</aside>
    <footer class="grid-element">Footer</footer>
</div>

grid-9

Our next grid is a copy of grid-4. This time I'm applying a little fluidity using a media query.

CSS

#grid-9 { grid-template-columns: 2fr 1fr; } #grid-9-second-container { grid-template-rows: auto auto; } @media (min-width: 768px) and (max-width: 1024px) { #grid-9 { grid-template-columns: auto; } }

HTML

<div class="grid" id="grid-9">
    <div class="grid-element">Doctrina amet deserunt excepteur do est laborum hic excepteur. Labore constias ne tractavissent. Vidisse malis aute litteris magna.Ubi quo sempiternum non doctrina aut export. Ex quae irure sed proident hic malis incurreret sed adipisicing. Minim pariatur ubi cillum quem sed doctrina quid iudicem singulis, de quo consectetur, laborum se nisi incurreret.
    </div>
    <div id="grid-4-second-container">
        <div class="grid-element">Doctrina amet deserunt excepteur do est laborum hic excepteur. Labore constias ne tractavissent. Vidisse malis aute litteris magna.Ubi quo sempiternum non doctrina aut export. Ex quae irure sed proident hic malis incurreret sed adipisicing. Minim pariatur ubi cillum quem sed doctrina quid iudicem singulis, de quo consectetur, laborum se nisi incurreret.
        </div>
        <div class="grid-element">Doctrina amet deserunt excepteur do est laborum hic excepteur. Labore constias ne tractavissent. Vidisse malis aute litteris magna.Ubi quo sempiternum non doctrina aut export. Ex quae irure sed proident hic malis incurreret sed adipisicing. Minim pariatur ubi cillum quem sed doctrina quid iudicem singulis, de quo consectetur, laborum se nisi incurreret.
        </div>
    </div>
</div>


Wednesday, 21 March 2018

Full page background images CSS

If you want to cover the background of your web page, I suggest you do 2 things:
Reduce the file size of the image using the technique shown at https://orbitingweb.com/blog/optimizing-jpeg-images/. You should make sure you are using the correct image format. Here is a guide https://www.diffen.com/difference/JPEG_vs_PNG.
Use the following CSS code in your stylesheet:
html {
  background: url(img/bg.jpg) no-repeat center center fixed;
  -webkit-background-size: cover;
  -moz-background-size: cover;
  -o-background-size: cover;
  background-size: cover;
  -ms-filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='img/bg.jpg', sizingMethod='scale')";
  filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='.img/bg.jpg', sizingMethod='scale');
}

Wednesday, 14 March 2018

Thumbnail images for Vivaldi browser Speed Dial page

I've been using the Vivaldi browser a lot lately. If you don't want screen dumps as the thumbnails for websites on the Speed Dial page, use these as a starting point.
https://github.com/guitarbeerchocolate/vivaldi-thumbnails

Thursday, 8 March 2018

Adding node.js applications to an existing LAMP installation

So you've already been developing lots of LAMP applications on your local server. You've moved into creating node.js applications. You want to continue, as before, with your LAMP applications, but add node.js applications in the same directories i.e /var/www/html/ and so on.
In that case you need to add a little to your Apache setup to help in this process.

Prepare Apache

In your /etc/apache2/apache2.conf file:
Make sure these 2 lines are uncommented (or even exist)
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
Now add the following (it can be at the end if you like)
ProxyPass /mynodesite http://localhost:8000

Restart Apache

systemctl reload apache2

Create the application file

Create a file in /var/www/html/mynodesite called app.js and insert the following:
var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World!\n');
}).listen(8000, '127.0.0.1');

Run the app

node app.js

Now the browser

Open the browser with the address http://localhost/mynodesite
Hey presto!

Saturday, 24 February 2018

How to add a directory to your path in Ubuntu

Open up the terminal
Type the command
echo $PATH
This gives you the current path.
Let's say you want to add the directory /home/mick/temp to the path...
Copy the current path you have just echo'd. Lets's say it's
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin
First make sure you are in your home directory by typing
cd ~
Open the file .bashrc using an editor such as gedit using
gedit .bashrc
Go to the bottom of the file and add a line
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin
Where the existing path is just pasted in.
Now add a colon followed by the path you'd like to add so that it reads
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/home/mick/temp
Save the file and restart your computer.
Now any excecutable placed in can also be available wherever you are on your installation.
This will be useful in following blog entries.

The 2018 Web Developer : Adding node_modules to a project using npm

In the last post, I prepared the ground for adding node_modules to my project. In my simple, learning project I'm going to add 3 modules:

  • bootstrap
  • jquery (which bootstrap needs)
  • popper.js (which bootstrap 4 also needs)

First open the project within the atom browser. Then I open the terminal within the browser (which sets the current working directory to my project). Within the terminal I type:
npm install bootstrap
npm install jquery
npm install popper.js
Job done! Well not quite. The start page for my project is taken from the Twitter Bootstrap starter template. So I now need to change the paths of the scripts and CSS links to :
<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="scss/custom.css" />

<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script src="node_modules/popper.js/dist/umd/popper.min.js"></script>
<script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
Now I'm cooking with gas. I can also start employing the SASS elements of Twitter Bootstrap.

What next?

There is much greater power in using node.js, nvm and npm, but it's a good start.