Tuesday 14 March 2017

Web Tutorial: Hacker Republic Login Sequence (Part 1/4)

Following my review of The Girl Who Kicked The Hornet's Nest, I'd like to present a truly awesome (by my humble standards) web tutorial. There was a login sequence on page 319, which the heroine of the story uses to gain access to the Hacker Republic site.

And that's what we're going to do today - a simulation of that kick-ass login sequence. For this, we'll be using a PHP backend with JavaScript and AJAX. HTML and CSS will make up the view, of course.

The sequence starts off like this.
She started by going on to a website that advertised rather uninteresting pictures by an unknown and not especially skilled amateur photographer called Gil Bates in Jobsville, Pennsylvania. Salander had once checked it out and confirmed that the town of Jobsville did not exist. Nevertheless, Bates had taken more than 200 photographs of the community and created a gallery of small thumbnails. She scrolled down to image 167 and clicked to enlarge it. It showed the church in Jobsville.


We're going to start off by creating that gallery of pictures. According to the text, there are more than 200 pictures, so we will create a gallery of 210 pictures - 21 rows featuring 10 photographs each.

For the photographs themselves, I downloaded 209 random pictures off the internet to serve as dummies...

Hold on, wasn't there supposed to be 210 photographs?

Why, the odd one out is that of the church, of course! I selected one with a church tower and spire.

Original image at
http://www.zionfriedheim.org/
images/
gifs/zion%20church%20new.jpg

Each image is renamed using the following formula: img_x.jpg, where x represents the number of the picture.

The images are all saved in the img subfolder.



So here goes. Create index.html and enter in the basic HTML layout for the gallery. The div gallery holds the (duh) gallery. You'll notice that the HTML references tt_millenniumlogin.js from the js folder. We'll create that later.

index.html
<!DOCTYPE html>
<html>
    <head>
        <title>Photo Gallery of Gil Bates</title>

        <script type="text/javascript" src="js/tt_millenniumlogin.js"></script>
    </head>

    <body>
        <div id="gallery">

        </div>
    </body>
</html>


Style gallery as follows and create the CSS class gallery_row. With over 200 thumbnails, the gallery is expected to scroll, so we need to set the height of gallery to 200% of the screen size. There are expected to be 20 rows in the gallery, so let's just set the height of each row to 5%. Then give the gallery_row CSS class a tiny margin of 10 pixels at the top.

index.html
    <head>
        <title>Photo Gallery of Gil Bates</title>

        <style>
            body, html {height:100%;}

            #gallery
            {
                width:100%;
                height:200%;
            }

            .gallery_row
            {
                width:100%;
                height:5%;
                margin-top:10px;
            }

            .gallery_row .thumbnail
            {
                width:9.5%;
                height:100%;
                float:left;
                margin-left:5px;
                background-size:cover;
                background-position:center center;
                cursor:pointer;
            }
        </style>

        <script type="text/javascript" src="js/tt_millenniumlogin.js"></script>
    </head>


Also create the thumbnail CSS class. There'll be 10 thumbails on each row, so give each thumbnail a width just shy of 10%. 9.5% should do it. The height will be 100% of the row, of course. Set the float property to left and give the margin on the left 5 pixels. cursor:pointer  makes it apparent that the thumbnail can be clicked, and the background properties will be useful for ensuring that the images fit somewhat nicely into the thumbnails.

index.html
    <head>
        <title>Photo Gallery of Gil Bates</title>

        <style>
            body, html {height:100%;}

            #gallery
            {
                width:100%;
                height:200%;
            }

            .gallery_row
            {
                width:100%;
                height:5%;
                margin-top:10px;
            }

            .gallery_row .thumbnail
            {
                width:9.5%;
                height:100%;
                float:left;
                margin-left:5px;
                background-size:cover;
                background-position:left top;
                cursor:pointer;
            }
        </style>

        <script type="text/javascript" src="js/tt_millenniumlogin.js"></script>
    </head>


However, we will not be writing this into the HTML, not manually, anyway. No, we'll use JavaScript to accomplish this. Alter your HTML...

index.html
    <body onload="load_gallery();">


And then create tt_millenniumlogin.js and save in in the js folder. In this file, create the load_gallery() function.

Declare the variables row, thumbnail and gallery. Set gallery to reference the gallery div.

tt_millenniumlogin.js
function load_gallery()
{
    var row,thumbnail;
    var gallery=document.getElementById("gallery");
}


We're going to create a gallery with 21 rows and 10 columns, so create a nested For loop.

tt_millenniumlogin.js
function load_gallery()
{
    var row,thumbnail;
    var gallery=document.getElementById("gallery");

    for (var i=0;i<21;i++)
    {
        for (var j=0;j<10;j++)
        {

        }
    }
}


Create a div element and assign it to the row variable. Set its class to gallery_row.

tt_millenniumlogin.js
function load_gallery()
{
    var row,thumbnail;
    var gallery=document.getElementById("gallery");

    for (var i=0;i<21;i++)
    {
        row=document.createElement("div");
        row.className="gallery_row";

        for (var j=0;j<10;j++)
        {

        }
    }
}


In the inner loop, create a div element and assign it to the variable thumbnail. Set its class to thumbnail.

tt_millenniumlogin.js
function load_gallery()
{
    var row,thumbnail;
    var gallery=document.getElementById("gallery");

    for (var i=0;i<21;i++)
    {
        row=document.createElement("div");
        row.className="gallery_row";

        for (var j=0;j<10;j++)
        {
            thumbnail=document.createElement("div");
            thumbnail.className="thumbnail";
        }
    }
}


Set the id of the thumbnail, and the background image.

tt_millenniumlogin.js
function load_gallery()
{
    var row,thumbnail;
    var gallery=document.getElementById("gallery");

    for (var i=0;i<21;i++)
    {
        row=document.createElement("div");
        row.className="gallery_row";

        for (var j=0;j<10;j++)
        {
            thumbnail=document.createElement("div");
            thumbnail.className="thumbnail";
            thumbnail.id="img_"+((i*10)+j);
            thumbnail.style.backgroundImage="url(img/img_"+((i*10)+j)+".jpg)";
        }
    }
}


Append the thumbnail to the row using the appendChild() method.

tt_millenniumlogin.js
function load_gallery()
{
    var row,thumbnail;
    var gallery=document.getElementById("gallery");

    for (var i=0;i<21;i++)
    {
        row=document.createElement("div");
        row.className="gallery_row";

        for (var j=0;j<10;j++)
        {
            thumbnail=document.createElement("div");
            thumbnail.className="thumbnail";
            thumbnail.id="img_"+((i*10)+j);
            thumbnail.style.backgroundImage="url(img/img_"+((i*10)+j)+".jpg)";
            row.appendChild(thumbnail);
        }
    }
}


Again using the appendChild() method, append the row to the gallery div.

tt_millenniumlogin.js
function load_gallery()
{
    var row,thumbnail;
    var gallery=document.getElementById("gallery");

    for (var i=0;i<21;i++)
    {
        row=document.createElement("div");
        row.className="gallery_row";

        for (var j=0;j<10;j++)
        {
            thumbnail=document.createElement("div");
            thumbnail.className="thumbnail";
            thumbnail.id="img_"+((i*10)+j);
            thumbnail.style.backgroundImage="url(img/img_"+((i*10)+j)+".jpg)";
            row.appendChild(thumbnail);
        }

        gallery.appendChild(row);
    }
}


If you've used the entire directory of images I've provided in the example, you should see this. But this is confusing because you need to see the numbers.


So add this line to your code. It will calculate the appropriate number and insert it into the thumbnail.

tt_millenniumlogin.js
function load_gallery()
{
    var row,thumbnail;
    var gallery=document.getElementById("gallery");

    for (var i=0;i<21;i++)
    {
        row=document.createElement("div");
        row.className="gallery_row";

        for (var j=0;j<10;j++)
        {
            thumbnail=document.createElement("div");
            thumbnail.className="thumbnail";
            thumbnail.id="img_"+((i*10)+j);
            thumbnail.style.backgroundImage="url(img/img_"+((i*10)+j)+".jpg)";
            thumbnail.innerHTML="#"+((i*10)+j+1);
            row.appendChild(thumbnail);
        }

        gallery.appendChild(row);
    }
}


Here's your gallery! Look at picture number 167. It's a church!


Now let's make this sucker clickable. Set a listener for onclick to call the function open_overlay(), which will take in two string parameters. In this case, "gallery_overlay" and the current thumbnail id are passed in as arguments.

And of course, create the open_overlay() function.

tt_millenniumlogin.js
function load_gallery()
{
    var row,thumbnail;
    var gallery=document.getElementById("gallery");

    for (var i=0;i<21;i++)
    {
        row=document.createElement("div");
        row.className="gallery_row";

        for (var j=0;j<10;j++)
        {
            thumbnail=document.createElement("div");
            thumbnail.className="thumbnail";
            thumbnail.id="img_"+((i*10)+j);
            thumbnail.style.backgroundImage="url(img/img_"+((i*10)+j)+".jpg)";
            thumbnail.innerHTML="#"+((i*10)+j+1);
            thumbnail.onclick=function(){open_overlay("gallery_overlay",this.id);};
            row.appendChild(thumbnail);
        }

        gallery.appendChild(row);
    }
}

function open_overlay(ovid,imgid)
{

}


But before we do anything else, let's set up the HTML elements. We have a gallery_overlay div and inside it, we have a gallery_actual div. gallery_overlay is the overlay that the enlarged photo will sit on, and gallery_actual is the placeholder for the photo itself.

index.html
    <body onload="load_gallery();">
        <div id="gallery_overlay">
            <div id="gallery_actual">

            </div>
        </div>

        <div id="gallery">

        </div>
    </body>
</html>


Here's the styling.

index.html
        <style>
            body, html {height:100%;}

            #gallery
            {
                width:100%;
                height:200%;
            }

            .gallery_row
            {
                width:100%;
                height:5%;
                margin-top:10px;
            }

            .gallery_row .thumbnail
            {
                width:9.5%;
                height:100%;
                float:left;
                margin-left:5px;
                background-size:cover;
                background-position:center center;
                cursor:pointer;
            }

            #gallery_overlay
            {
                position:fixed;
                left:0;
                top:0;
                width:100%;
                height:100%;
                display:none;
                z-index:100;
                background-color:rgba(0,0,0,0.9);
            }

            #gallery_actual
            {
                width:500px;
                height:500px;
                margin-top:5%;
                margin-left:auto;
                margin-right:auto;
                background-size:cover;
                background-position:left top;
                cursor:pointer;
            }
        </style>


For gallery_overlay, we have...
position:fixed, left:0, right:0, width:100%, height:100% - makes the div cover the entire screen.
display:none - makes it invisible, which is the default state.
z-index:100 - sends it to the front of the display.
background-color:rgba(0,0,0,0.9) - makes the div translucent.

For gallery_actual...
width:500px, height:500px - because each picture is at least that big.
margin-top:5%, margin-left:auto, margin-right:auto - sets the gallery_actual div squarely in the middle of its parent, the gallery_overlay div.
background-size:cover, background-position:left top - ensures the correct positioning of whatever image we set as its background.
cursor:pointer - makes the photo appear clickable.

Now back to your JavaScript.

Start off by using a variable, overlay, to reference the element whose id is passed in as the first argument.

tt_millenniumlogin.js
function open_overlay(ovid,imgid)
{
    var overlay=document.getElementById(ovid);
    overlay.style.display="block";
}


Try it. Click on any of the pics. You should see a big grey overlay!

We'll be reusing this function for other stuff, so let's just create an If conditional for this use case.
Reference the gallery_actual div with the variable img_actual, then set the background image to the url of the image to be displayed. The filename (sans extension) is provided by the second argument to open_overlay().

tt_millenniumlogin.js
function open_overlay(ovid,imgid)
{
    var overlay=document.getElementById(ovid);
    overlay.style.display="block";

    if (ovid=="gallery_overlay")
    {
        var img_actual=document.getElementById("gallery_actual");
        img_actual.style.backgroundImage="url(img/"+imgid+".jpg)";
    }
}


Try it. Click on any of the images. You should get the enlarged version!



To keep things clean, let's create the close_overlay() function. This is simple enough - it accepts the id of the element to be "closed",  references the element with the variable overlay, and then sets the display property to none.

tt_millenniumlogin.js
function open_overlay(ovid,imgid)
{
    var overlay=document.getElementById(ovid);
    overlay.style.display="block";

    if (ovid=="gallery_overlay")
    {
        var img_actual=document.getElementById("gallery_actual");
        img_actual.style.backgroundImage="url(img/"+imgid+".jpg)";
    }
}

function close_overlay(ovid)
{
    var overlay=document.getElementById(ovid);
    overlay.style.display="none";
}


Just alter your HTML code and we're good. Try this. Open up the image by clicking on any of the thumbnails, then close by clicking anywhere else.

index.html
        <div id="gallery_overlay" onclick="close_overlay(this.id);">
            <div id="gallery_actual">

            </div>
        </div>

Next

We're going to implement some funky clicky goodness on the gallery you've just created. Watch this space!

No comments:

Post a Comment