CHAPTER 5

image

Spicing Up Your Image Gallery with JavaScript and CSS

This chapter is completely optional reading! You can consider it an invitation to a small detour from PHP. This chapter explores a way to integrate JavaScript into your PHP projects. In the process, you will have to learn some JavaScript to develop an interactive image gallery. You may explore this detour or skip it altogether.

If you follow any blogs about web design and web development, you are bound to come across something that involves JavaScript. Perhaps you will come across something you would like to implement in your PHP projects. This is not really a book about JavaScript, but I will show you some examples of using JavaScript. My goal is to show you an approach to integrating JavaScript in your PHP projects. If you really want to learn JavaScript, you’ll have to consult other resources.

Image Note  Want to learn more about JavaScript in the browser? Consider picking up a copy of Foundation Game Design with HTML5 and JavaScript by Rex van der Spuy (Apress, 2012). You’ll be building games for the browser using HTML5, CSS, and JavaScript. It is a fun way to learn!

Client-Side vs. Server-Side Programming

PHP is a great language for web development. It is extremely popular for many good reasons. But PHP is just one server-side scripting language out of many. Server-side languages only run on your server; there is no way to execute PHP code in a browser. So far, you have written PHP code to output HTML, which is sent to a browser.

In order to change anything in the generated HTML, the browser must send an HTTP request to the server, so PHP can run and send back an HTTP response. But it takes time and bandwidth to send an HTTP request, wait while PHP runs, and finally receive an HTTP response.

In some situations, it would be better to simply run some code when your system needs it. Luckily, there is a way: It is possible to manipulate HTML programmatically in the browser, using JavaScript, which happens to be the only scripting language that runs natively in the browser. You can choose between many different languages on the server side. On the client side, i.e., in the browser, there is only one: JavaScript.

JavaScript is a wonderful language, but different versions of different browsers have implemented different parts of JavaScript in different ways. So, the JavaScript that runs beautifully in one browser might trigger embarrassing errors in another.

A common approach to dealing with these differences is to use progressive enhancement, which basically means that you write your code in such a way that your beautiful JavaScript only runs in browsers that fully understand it.

Progressive enhancement with JavaScript provides an optimal user experience to modern browsers with JavaScript enabled. Older browsers or browsers with JavaScript disabled still get all the content served. The extra JavaScript features should remain hidden from incapable browsers, so that JavaScript errors are avoided. The image gallery covered in this chapter uses progressive enhancement.

Coding a Lightbox Gallery

Let’s code a so-called lightbox for the image gallery, to present the images in an aesthetically pleasing way. A lightbox is a very common approach to displaying images. When a user clicks a small image on a web page, JavaScript will place a semitransparent overlay on top of all page content. A large version of the clicked image will be displayed on top of the overlay.

From PHP on the server side, you’ll continue to serve every visiting browser a list of all JPEG images. But if a user comes along with a top-notch browser, you can serve an even better solution: small thumbnails of all images, so the user can quickly navigate the entire gallery. If a user clicks a thumbnail, you can really bring focus to that particular picture. You can hide all other content behind a semitransparent overlay and really highlight the selected picture. You can even display a bigger version of the clicked image: that is a lightbox gallery.

That is what progressive enhancement is all about: serve all content to all browsers but provide a better user experience for capable browsers. Let’s get started!

Embedding an External JavaScript File

It is possible, but not recommended, to write JavaScript code directly in your HTML. A better approach is to keep your HTML and your JavaScript decoupled. It is possible to embed several JavaScript files in one HTML file, just as you can link multiple style sheets to a single HTML file. To link a JavaScript to an HTML file, you can use a <script> element:

<script src="path/to/Javascript-file.js"></script>

The src attribute should point to an existing JavaScript file, so it is important that the path is correct. You may wonder why the <script> element is a container tag? It is because you can decide to write JavaScript code directly in your HTML file, inside a <script> element.

Image Note  Using external JavaScript files and carefully avoiding any JavaScript code in HTML is also known as unobtrusive JavaScript.

You already have a PHP-driven, dynamic image gallery from Chapter 4. Adding some JavaScript to that project should give you a good idea of some of the things you can do with JavaScript. The code examples in this chapter rely on your having the PHP source code for the gallery developed in Chapter 4.

Preparing the Page_Data Class for JavaScript Files

You can change your PHP code to prepare for one or more JavaScript files. The existing Page_Data class needs a property to hold one or more <script> elements. You can also declare a new method in the Page_Data class for adding a new JavaScript file. It will be very similar to the property for <link> elements holding style sheet references and the method for adding new style sheets. I propose you continue working with the project you started in Chapter 4, so the file to update is ch4/classes/Page_Data.class.php. Here’s the complete code for it:

<?php
//complete code listing for classes/Page_Data.class.php
class Page_Data {
    public $title = "";
    public $content = "";
    public $css = "";
    public $embeddedStyle = "";
    //declare a new property for script elements
    public $scriptElements = "";
    
    //declare a new method for adding Javascript files
    public function addScript( $src ){
        $this->scriptElements .= "<script src='$src'></script>";
    }
    
    public function addCSS( $href ){
        $this->css .= "<link href='$href' rel='stylesheet' />";
    }
}

Notice the new public property called $scriptElements. It will hold however many <script> elements you require for the page. Also note the public function addScript(). See how it takes a $src as argument. The $src should hold a path to a JavaScript file. The received path will be used to create a <script> element. The created <script> element will be stored, together with any previously added <script> elements, by way of incremental concatenation.

Preparing the Page Template for JavaScript Files

You have to update the page template file to accept <script> elements for JavaScript, just as you did when you updated the page template to accept <link> elements for CSS. Edit template/page.php:

<?php
//complete code listing for templates/page.php
return "<!DOCTYPE html>
<html>
<head>
<title>$pageData->title</title>
<meta http-equiv='Content-Type' content='text/html;charset=utf-8' />
    $pageData->css
    $pageData->embeddedStyle
</head>
<body>
    $pageData->content
    $pageData->scriptElements
</body>
</html>";

The script elements will be embedded by PHP by way of $pageData->scriptElements. Note that any <script> elements will be placed after any other content on the page. When you do that, you can be sure that all HTML elements are loaded into browser memory before your JavaScript starts executing. That is exactly what we want!

JavaScript is often used to manipulate HTML. It is necessary to have the HTML loaded into browser memory before we can manipulate it.

Writing and Running an External JavaScript File

I like to keep my JavaScript files in a designated folder, to maintain a well-organized file structure. I propose you get used to doing the same. Create a new folder called js. Use your editor to create a new JavaScript file called lightbox.js. Save it in your js folder.

//complete code listing for js/lightbox.js
window.console.log("Hello from Javascript");

To run JavaScript code, you must tell the browser that there is a JavaScript to run. You can point to an external JavaScript file from index.php. The JavaScript you’ll be writing will manipulate your HTML, so that certain attributes are changed dynamically.

You will also require an external style sheet. Following is a little code from index.php that shows how to point to an external style sheet and how to point to an external JavaScript. These lines of code belong in index.php somewhere after a new $pageData object is created and before the generated $page is echoed:

//partial code listing for index.php
//this line of code you already have. It creates a Page_Data object
$pageData = new Page_Data();
//new code below
//add this new line to embed an external Javascript file to your index.php
$pageData->addScript("js/lightbox.js");
//no other changes in index.php

You have an external JavaScript, and you have linked to it from index.php. Any JavaScript code you write should run perfectly now. It is quite simple to test, if you use the Google Chrome browser or another browser with a similar JavaScript console. I suggest you use Google Chrome, unless you are already used to another browser with a JavaScript console.

First, open Google Chrome. Next, open the Chrome menu, by clicking the image in the top-right corner of the browser. Select Tools image JavaScript Console. When the console is open, you simply load http://localhost/ch4/index.php in your Chrome browser. You should see a message in the console, as shown in Figure 5-1.

9781430268154_Fig05-01.jpg

Figure 5-1. The JavaScript Console in Google Chrome

Using window.console.log()

As you can see, the message in the console is identical to what you wrote in the JavaScript code:

window.console.log("Hello from Javascript");

In JavaScript, window is an object representing an open browser window. Inside the window object, you can find the console object. The console object has a method log() that outputs messages in the JavaScript console window. Logging to the console is often used to check that some JavaScript works as intended.

In this example, you use it to check if JavaScript runs at all. If you don’t see a message in your console, you know that your JavaScript does not run. In that case, you can inspect the HTML source code of index.php, to see if you find a <script> element that links to an existing JavaScript file. Perhaps there is no <script> element, or its src attribute doesn’t point to your JavaScript file. Please make sure that you have completed all previous steps correctly.

From the single line of JavaScript you have written, you can infer that JavaScript is like PHP, in that it has objects and methods. You can also see that JavaScript syntax is a little different. JavaScript’s object operator is a ., whereas PHP uses ->. If JavaScript had exactly the same syntax as PHP, you should have written the following:

//If Javascript had PHP’s object operator
window->console->log("hello");

I’d like you to notice both the functional similarities and the syntactical differences. JavaScript is very similar to PHP in many ways, but the syntax differs slightly. In some ways, JavaScript is really different from PHP, but that’s another story.

JavaScript Arrays

You have already tried to work with arrays in PHP: $_GET and $_POST are superglobal arrays. Let’s take a closer look at arrays and see how they can be used in JavaScript. Open your lightbox.js file and write some JavaScript, as follows:

var pets = new Array("cat", "dog", "canary");
var firstPet = pets[0];
window.console.log( "The first pet is at index 0. It is a " +  firstPet);

Using var to Declare a Variable

First you declare a variable pets and assign it to hold a new array object. You use the keyword var to declare a JavaScript variable. The new array object holds a list of three string values. That’s what arrays can do: they can hold a list of items.

In order to do anything meaningful with arrays, you have to be able to get the right array item at the right time. Array items are remembered by their position in the list. The technical term for such a position is index. The first item in an array has an index of 0, the second an index of 1, and so on. The general syntax for getting an item from an array is as follows:

arrayName[index];

If you look back into the code for the pets example, you can see that the variable firstPet holds the item found at index 0 in the pets array. Once again, JavaScript is very similar to PHP. To get an item from a PHP array, we could use exactly the same syntax.

Looping Through Array Items

Loops are very commonly used together with arrays. With a simple while loop you can iterate through all items in an array:

var pets = new Array("cat", "dog", "canary");
var index = 0;
while ( index < pets.length ) {
    window.console.log( pets[index] );
    index = index + 1;
}

Once again, you can see that JavaScript and PHP are quite similar languages: they can both work with while loops. The preceding loop will iterate through every item in the pets array and output each one item to the console.

In the first iteration, the variable index will hold the value 0 and, therefore, the code outputs “cat,” which is the item found at pets[0].

The condition for the while loop stipulates that the loop will continue as long as index is smaller than the length of the pets array, in other words, as long as index is smaller than 3.

At the end of the first iteration, the value of index is changed. It began with a value of 0, now it becomes 1, because index = 0 + 1. In the next iteration, the code will output “dog” to the console, because dog is found at pets[1]. The variable index becomes 2, and the loop continues, so “canary” appears in the console.

Now, index becomes 3, and so the while loop terminates, because 3 is not smaller than 3.

Simple Progressive Enhancement

In this lightbox script, you want JavaScript to provide a better experience to users with new browsers. You can do that by responding to an event that is only understood by relatively new browsers. You can do that in js/lightbox.js, as follows:

//complete code for js/lightbox.js
function init(){
    window.console.log("Welcome, user with a new browser");
}
document.addEventListener("DOMContentLoaded", init, false);

Notice the document object used in the code above. The document is a native JavaScript object. Every HTML web page loaded in a browser has its own document object. You can use the document object to retrieve and manipulate HTML content in the loaded page.

The preceding code assigns the function init to be called automatically when the event DOMContentLoaded is dispatched. The DOMContentLoaded event will be dispatched when the browser has finished loading the DOM (Document Object Model). The DOM is a representation of the HTML on the page. Only new browsers dispatch the DOMContentLoaded event. Therefore, any JavaScript code you write or call from inside the function init() will only run if the user has a relatively new browser.

Using Event Listeners

Event listeners are native to JavaScript. This is one point where JavaScript and PHP really are different, as there are no event listeners in PHP. Event listeners are used to associate an event with a function. The idea is that every time a certain event occurs, a particular function should run. The general syntax for adding an event listener is as follows:

object.addEventListener(event, event handler, useCapture);

As you can see, the addEventListener takes three arguments: an event, an event handler, and useCapture.

The Event

The first argument specifies which event to listen for. Different objects can respond to different events. In the preceding example, you are listening for the document object’s DOMContentLoaded event. The browser will dispatch the event, and the document object can respond to the event, but only if you specifically tell it to listen for the event.

The Event Handler

The second argument specifies which function to run when the event is heard. The addEventListener registers an event-handling function to a specific event. In your example, you have registered the function init as event handler for the document object’s DOMContentLoaded event.

The Optional useCapture

The third argument of the addEventListener indicates an advanced topic known as useCapture. For most modern browsers, this is an optional argument, meaning you don’t have to specify it. Most browsers will simply assume it to be false, if it is not specifically set to true. But some browsers and browser versions require this parameter to be set, so you might as well get into the habit of setting it.

As a rule of thumb, you can declare the third argument and set it to false. You may come across a special situation that requires you to set it to true, but it will not be in the code examples in this book. It is one of those JavaScript topics you can explore on your own by consulting other resources.

Creating Markup for the Overlay and Big Image

You have established a very basic skeleton for progressive enhancement: the init function will only run if the browser is capable.

It’s time to get started with the lightbox gallery. Begin by adding some JavaScript to create a little HTML dynamically, to provide markup structures for displaying a big image on top of a transparent overlay. You have to update the init() function in js/lightbox.js, as follows:

//edit existing function
function init() {
    var lightboxElements = "<div id='lightbox'>";
    lightboxElements  += "<div id='overlay' class='hidden'></div>";
    lightboxElements  += "<img class='hidden' id='big-image' />";
    lightboxElements  += "</div>";
    document.querySelector("body").innerHTML += lightboxElements;
}

This code will create a string of HTML elements and add them after the HTML elements already found inside the <body>. Note especially the <img> element. It is missing an src attribute, so it doesn’t show a picture at this point. If you save your work and load http://localhost/ch4 in your browser, you may be surprised that nothing seems to have changed, despite all your JavaScript efforts. If your JavaScript works, you should have a page with a few HTML elements added at the end. But they hold no content, so you can see nothing—yet!

You can see, in the preceding code example, that JavaScript can concatenate strings just like PHP can. Please notice that JavaScript’s incremental concatenation operator is different from PHP. It is another case of same functionality, different syntax.

//Javascript's incremental concatenation operator
+=
//PHP's incremental concatenation operator
.=

document.querySelector( )

The last line in the function looks like nothing you have used so far in the book. The querySelector() is a method of the document object. It is an absolutely wonderful method, if you are comfortable with CSS selectors. With the querySelector(), you can select HTML elements from the loaded page using CSS selector syntax.

document.querySelector("body").innerHTML += lightboxElements;

The preceding line uses the querySelector to get the <body> element and all its content. JavaScript adds the HTML string stored in the variable lightboxElements, after the existing content inside <body>. To get access to the HTML content inside the <body>, you use the innerHTML property.

Showing the Overlay

I suppose it is very rewarding to have created a <div> element with JavaScript. But it would be a lot more rewarding if you could see it working as an overlay. You can achieve that by adding a bit of CSS to your existing style sheet. I keep mine in css/layout.css.

/*declare a new style rule in css/layout.css */
div#overlay{
    position: absolute;
    width: 100%;
    height:100%;
    top:0px;
    left:0px;
    background:black;
    opacity: 0.85;
}

If you save that and reload http://localhost/ch4 in your browser, you should see a semitransparent overlay covering all the content visible in the browser’s viewport. If you scroll down, you can see that the overlay only covers the viewport, not the entire page content. It is as it should be. Seeing the overlay is a visual confirmation that the JavaScript code is doing something. But you only want the overlay to be displayed when a user has clicked a particular image. Also, you would want the clicked image to be displayed on top of the overlay. You still have some work to do.

Hiding the Overlay and Resize Thumbnails

By default, you would want the images to be displayed as small thumbnails. When a thumbnail is clicked, the overlay should appear to hide the other thumbnails, and the clicked image should be displayed in almost full screen. To achieve this, you need both CSS and JavaScript. You can begin by preparing a few CSS rules, which you can use later by way of JavaScript. Here are a few more rules for your style sheet in css/layout.css:

/*hide overlay and big-image*/
div#overlay.hidden, img#big-image.hidden{ opacity: 0; left:-200%; }
 
/*resize images and display them as a horisontal list*/
li.lightbox img{ height: 100px; }
li.lightbox{ display: inline-block; margin: 10px; }

If you refresh the browser, you can see that the overlay is hidden. You can also see that thumbnails are not resized yet, despite the CSS. Don’t be too surprised. It is simply because the <li> elements do not have a class attribute set to lightbox yet. You will set the class dynamically, using JavaScript. But before writing any more JavaScript, I’d like you to look into the CSS that hides the image and the overlay. You can see that both elements are styled to be completely transparent and positioned so far to the left that the elements would be invisible, even if they weren’t completely transparent. Keep in mind that it is important for the overlay and the big image to each have a class attribute set to hidden. If the class is not set to hidden, both elements would show.

By default, there are no <li> elements with a class attribute set to lightbox. So, the CSS rules written above don’t apply to anything at the moment. You can change that by writing some JavaScript to declare a class attribute with a value set to lightbox on all <li> elements used for your gallery images, but only for capable browsers. Update js/lightbox.js as follows:

//complete code listing for js/lightbox.js
//edit existing function
function init(){
    var lightboxElements = "<div id='lightbox'>";
    lightboxElements    += "<div id='overlay' class='hidden'></div>";
    lightboxElements    += "<img class='hidden' id='big-image' />";
    lightboxElements    += "</div>";
    document.querySelector("body").innerHTML += lightboxElements;
    //add a new function call here
    prepareThumbs();
}
 
//declare a new function
function toggle(){
    window.console.log("show or hide a big image");
}
 
//declare new function
function prepareThumbs() {
    var liElements = document.querySelectorAll("ul#images li");
    var i = 0;
    var image, li;
    //loop through all <li> elements
    while ( i < liElements.length ) {
        li = liElements[i];
        //set class='lightbox'
        li.setAttribute("class", "lightbox");
        image = li.querySelector("img");
        //register a click event handler for the <img> elements
        image.addEventListener("click", toggle, false);
        i += 1;
    }
}
 
document.addEventListener("DOMContentLoaded", init, false);

Save this code and refresh your browser. You should expect to see a horizontal list of small thumbnail images. When you click one image, you should expect to see a message in the console window saying “show or hide a big image.”

That was a big chunk of code in one step. Let’s look into it and figure out what’s really going on there.

Only Showing Thumbnails to Capable Browsers

The JavaScript uses progressive enhancement and effectively hides JavaScripted features from browsers that might not understand. Remember how the function init() only runs if the browser dispatches a DOMContentLoaded event? Only relatively new browsers dispatch that event. As already mentioned, it is dispatched when all HTML elements of a given page are loaded into the browser’s memory.

The function prepareThumbs() is called from inside the function init(), so prepareThumbs() will only run in new browsers. You have effectively hidden your JavaScript from older browsers: You have progressive enhancement!

Getting an Array of HTML Elements with querySelectorAll( )

Next, take a look at how class attributes are added on all <li> elements for the gallery. The first task is to select all <li> elements. You’ve used the method querySelectorAll() for that task. The querySelectorAll() is just like querySelector(), except it returns not just one HTML element but all HTML elements that match the used CSS selector.

var liElements = document.querySelectorAll("ul#images li");

In the preceding line, the variable liElements will hold an array of all <li> elements found inside the <ul>, with an id attribute set to images.

Image Note  You can learn more about using querySelector() and querySelectorAll() at www.kirupa.com/html5/finding_elements_dom_using_querySelector.htm.

You have already seen how to loop through an array of pets. Looping through an array of HTML elements is just like that. Inside prepareThumbs(), you can see a while loop. It will loop for as long as the variable i holds a value smaller than the number of <li> elements found. That effectively means you’ll loop through every <li> item inside the <ul> element with an id attribute of images.

The variable i can be used as index to get one particular <li> element from the array of all the <li> elements. Each one <li> will be remembered in the variable li, and each <li> will get a class attribute of lightbox. There is a CSS rule for such <li> elements, and that is why thumbnails are displayed as a horizontal list in your browser. There is another CSS rule selecting <img> elements inside such <li> elements. The rule resizes the width of the thumbnail images to 100px.

Still inside the while loop, you use querySelector() to select the <img> element inside the <li> element. You assign an event listener to each <img> element. So, whenever a user clicks an <img>, the function toggle() will be called. In other words, you register an event handling function called toggle() to each <img> element.

Showing a Big Image

Whenever a user clicks one of your <img> elements, the function toggle() will run. At this point, it doesn’t do much. It simply outputs a message in the console window. You are looking for a different behavior. If a thumbnail is clicked, you want the transparent overlay to hide all thumbnails, and you want a big version of the clicked image displayed. If a big image is clicked, you want the overlay and the big image to disappear, so all thumbnails once again become clearly visible. You will need a CSS rule for styling the big image, and you will require some JavaScript for manipulating HTML class attributes. You can begin with the CSS. Add one more rule to css/layout.css:

/*partial code listing for css/layout.css*/
/*new CSS rule for showing the big-image*/
#big-image.showing{
    max-width: 80%;
    max-height:90%;
    position:absolute;
    background-color: white;
    padding: 10px;
    top:5%;
    left: 10%;
}

To see some action in your browser, you also have to add some code to the toggle() function declared in js/lightbox.js, as follows:

//edit existing function
function toggle( event ){
    //which image was clicked
    var clickedImage = event.target;
    var bigImage = document.querySelector("#big-image");
    var overlay = document.querySelector("#overlay");
    bigImage.src = clickedImage.src;
    //if overlay is hidden, we can assume the big image is hidden
    if ( overlay.getAttribute("class") === "hidden" ) {
        overlay.setAttribute("class", "showing");
        bigImage.setAttribute("class", "showing");
    } else {
        overlay.setAttribute("class", "hidden");
        bigImage.setAttribute("class", "hidden");
    }
}

You can see that JavaScript doesn’t really show or hide the big image or the overlay as such. All JavaScript does is manipulate class attributes of the #overlay and the #big-image. You can check in your browser that overlay and image are in fact hidden to begin with. If you click a thumbnail, the overlay will appear on top of the thumbnails, and the big image will appear on top of the overlay.

This effect is achieved by uniting CSS and JavaScript. In CSS, you keep rules dictating how to render #overlay and #big-image. If a class is set to hidden on these elements, they will be hidden from view. If a class hidden is not set, the elements will be displayed. JavaScript manipulates the class attribute dynamically. CSS declares how to render #big-image and #overlay, depending on the current value of the class attribute.

JavaScript has a quite simple job: it is only responsible for setting class attributes on the overlay and the big image. If the class attribute is currently set to hidden, it will be changed to showing. Otherwise, if the class is not set to hidden, it will be set to hidden.

Let’s inspect the code inside toggle in greater detail to understand it—and JavaScript—better.

Using the MouseEvent Object

The first thing to note is the event argument added to the toggle() function. The function toggle() is called, because it is registered as event handler for click events on the <img> elements. It is called from an event listener. When that happens, an Event object is passed along when the event is triggered. A click is triggered when a user clicks on a mouse button and, consequently, the Event object sent along is a MouseEvent object.

Event objects have quite a few very useful properties that you can use in code. The MouseEvent object has a target property, which holds a reference to the clicked HTML element.

Image Note  You can see the other available properties in your console window, if you add the following line of code inside the toggle() function: window.console.log(event);.

You use the MouseEvent.target property to get the clicked <img> element. You use that to replace the src attribute of the big image with the src attribute of the clicked image. Essentially, you use it to display a big version of the clicked thumbnail, seen in the following code:

bigImage.src = clickedImage.src;

Toggling

To toggle means to change between two states. You toggle a light switch when you turn on the light, and you toggle the same light switch to turn off the same light. In this piece of JavaScript, you want to toggle the overlay and the big image.

If the class attribute of the overlay element is set to hidden, you want to hide the overlay and the big image. If the class attribute of the overlay is set to showing, you want the overlay and big image to show. If you look in the toggle function, you can see the same idea expressed in code.

if ( overlay.getAttribute("class") === "hidden" ) {
    //code to show overlay and image
} else {
    //code to hide overlay and image
}

Manipulating Attributes

To read the value of the class attribute, you use the getAttribute() method. It is a standard JavaScript method found on all HTML objects. The getAttribute() method can be used to read the value of any attribute. The general syntax is as follows:

element.getAttribute( whichAttribute );

The getAttribute() method will return the value of the requested attribute found in the specified element. There is a similar method, called setAttribute(), for changing attribute values. The general syntax is the following:

element.setAttribute( whichAttribute, newValue );

The setAttribute() method can set a new value for a specified attribute on a particular HTML element. In the preceding toggle() function, you use it to change the attribute values of the overlay and the big image.

Hiding the Big Image

At this moment, you can click a thumbnail to have the overlay and big image displayed. This is great. But you cannot hide the overlay or the big image again, which is not so great. To enable hiding, you simply have to register the toggle() function as the event handler to be triggered when the big image is clicked. It can be done with the following (boldfaced) two extra lines of code in the init() function:

//edit existing function
function init(){
    var lightboxElements = "<div id='lightbox'>";
    lightboxElements    += "<div id='overlay' class='hidden'></div>";
    lightboxElements    += "<img class='hidden' id='big-image' />";
    lightboxElements    += "</div>";
    document.querySelector("body").innerHTML += lightboxElements;
    
    //new code: register toggle as event handler
    var bigImage = document.querySelector("#big-image")
    bigImage.addEventListener("click",toggle, false);
    //end of changes
    prepareThumbs();
}

Test it for yourself. At this point, you should be able to click a thumbnail to show the big image on top of the overlay. If you click the big image, both the big image and overlay will be hidden again, thus revealing the thumbnails underneath.

Using a CSS Animation

Wouldn’t it be nice if the semitransparent overlay would fade in to hide thumbnails? It could be a final touch to make the lightbox gallery even nicer. You can create a CSS animation by adding the following (boldfaced) single line of CSS in css/layout.css:

#overlay{
    position: absolute;
    width: 100%;
    height:100%;
    top:0px;
    background:black;
    opacity: 0.85;
    left:0px;
    /*this is the animation to fade the overlay in gradually over 1 second*/
    transition: opacity 1s ease-in;
}

Coding Challenge

The lightbox gallery is complete now. You can easily find many more examples of JavaScript-powered image galleries, if you browse the Internet. Perhaps you will come across a behavior you would like to implement in your gallery.

A very common feature involves clicking the overlay when the big image is displayed. Most galleries will toggle when the overlay is clicked. It is not incredibly hard to achieve, so perhaps this is a task you can tackle on your own. You’ll simply want to register toggle as event handler for click events detected on the overlay. This approach will work, and it will trigger a JavaScript error. You can see the error message in your console. An extra coding challenge could be for you to figure out what the error message means and how you can change your code to avoid the error.

You can find a tutorial for another JavaScript gallery at www.webmonkey.com/2010/02/make_a_javascript_slideshow/ with Next and Previous buttons. Perhaps you can figure out how to implement such buttons in your lightbox gallery. It could be an interesting learning experience and also a nice addition for your lightbox gallery.

Summary

You have covered a lot of ground in relatively few pages. The primary goal was to provide an approach for you to integrate JavaScript solutions in your PHP projects. In the process, you worked through a relatively simple lightbox image gallery.

You have seen that the PHP and JavaScript languages are similar in many ways. Often, it is only syntax that differs, and sometimes not even that. This is great news for you. Once you have learned PHP, you can learn JavaScript relatively easily.

On the other hand, you have also seen that there are notable differences between JavaScript and PHP. To be really proficient in both languages, you’ll eventually want to pay close attention to these differences.

Perhaps the most significant difference to note is that JavaScript is a client-side scripting language, whereas PHP is a server-side scripting language. Your JavaScript code runs in your users’ browsers. PHP only runs on your server, so browsers will never see your PHP. Browsers will only be served the result created by PHP.

Image Note  Actually, JavaScript can run on servers. Search the Internet for node.js to learn more. Also, PHP can run without a web server. But JavaScript is mostly used client-side, and PHP is mostly used server-side.

So far, you have seen that when PHP has done its thing, it will create an output. The output is often an HTML file, which is sent to the browser. JavaScript can manipulate the HTML in the browser, without any need for contacting the server. You will probably want to learn more JavaScript eventually, but that is beyond the scope for this book.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.49.247