Single page web album

A single page web album is a web application which consists of only one single HTML page. The content gets dynamically loaded into the single page web album. There are two different approaches to implement a single page web album skin for jAlbum. You can save the album data into a JavaScript variable or read it via JavaScript out of JSON files. Saving the album data into a Javascript variable makes the skin way faster, since you do not have to load an extra file. Nevertheless you will have a large initialization page load when having a lot of pictures.


Contents

Advantages of using a single page web application

A single page web application is mostly written in JavaScript. Therefore it is way easier to provide a responsive design as well as embedding. For the embedding you can inject JavaScript code into the website and make the design appropriate to the surroundings. With single web page applications you do not need to use extra queries to the server to download pages. You can easily preload images and make the navigation between different pages as pleasant as possible.

Store album data in a jAlbum variable

In order to be able to save the album data into a JavaScript variable you need to create the album data in a useful format to be able to save it in a JavaScript variable. Therefore we need to tell jAlbum to create an JSON file out of the album data. You can do this in the init.bsh file which gets executed at initialisation time of the skin processing. In this example we save the data into a jAlbum variable called dataTree.

// init.bsh 

jsonmaker = new JSONMaker(engine); // create new JSONMaker object
dataTree = jsonmaker.getTreeAsString(rootFolder); //store JSON file of album data in dataTree variable

Let jAlbum process our JavaScript file

First of all let us create a JavaScript file called main.js which we locate into the the following directory: res/js/main.js

The most important part in this step is to make sure the jAlbum processor runs over your main.js file and replaces the jAlbum variables with the actual value. We do this by extending the code in our init.bsh. First of all the save our main.js into a template file and process it afterwards to the new directory.

// init.bsh
File template = new File(skinDirectory, "res/js/main.js"); // input directory of main.js
engine.processTemplateFile(template, new File(rootOutputDirectory,"main.js")); // output directory after processing

(In this case we output the main.js in the root folder since we do not want to show any directory path in our later embed code.)

Object Orientated JavaScript

Let's write the main.js file. I suggest you to implement it with the module pattern. This makes JavaScript way more object orientated and gives you a better overview over your skin. Here is an example of implementing a class via the module pattern in JavaScript.

// module pattern
var ClassName = (function () {

    var privateVariable = "private";
    var publicVariable = "public";

    function privateMethod (){
        // code here
    }
    function publicMethod (){
        return "Hello World!";
    }
  
    return {
        publicVariable : publicVariable,
        publicMethod : publicMethod 
    };

})();

var temp1 = ClassName.publicVariable;
var temp2 = ClassName.publicMethod();

So what did we do there? We created a scope with a function and pass an empty function in it which we fill with all our functions and variables we want to have in the object. We return the public functions and variables to make them accessible from the outside. This makes our code way more extendable and structured.

Store jAlbum variables in JavaScript

With the following syntax you can tell the jAlbum processor to place the variable at a certain possition.

${jAlbumVariable}

Let us collect all the necessary variables we want to use in our skin. This will be mostly information about skin settings and of course our album data stored in our dataTree variable. If you want to know more about jAlbum variables be free to check out the Variables entry in the Development center. Here is an example how your JavaScript class that stores all the jAlbum variables could look like.

var jAlbumGlobals = (function () {

	var stylePath = '${stylePath}'; //path points to the styles folder
	var resPath = '${resPath}'; // path points to the res folder
	var albumTitle = '${albumTitle}'; // what's the album title?

	var dataTree = ${dataTree}; // includes all the album data in a json tree

	/** returns all the public variables and functions **/
	return {
		stylePath: stylePath,
		resPath: resPath,
		albumTitle: albumTitle,
		dataTree: dataTree
	};
})();

You can also add other global values and parameters which might be necessary for your skin, like for example the current url of the page the skin is embeded, if the skin is viewed over the filesystem or online etc.

Let's write the index.htt

Since we write a single page web application, we stay on one html page. It is pretty simple and basically just needs an script embed for the main.js file. In the main.js file will be another class called jAlbumController which will control the output. We give the script tag an id to be able to check the stuff like the current url of the page where the id jAlbum is located etc.

<!DOCTYPE HTML>
<html>
    <head></head>
    <body>
        <script src="main.js" id="jAlbum"></script>
    </body>
</html>

Understand the structure of the JSON file

To be able to program your controller which reads in the JSON file data out of the dataTree you need to know what the json file looks like. Here is an example with two images. One is in a folder.

{
  "path": "Test%20for%20JSON%20Tree",
  "counters": {
    "total": 2,
    "images": 1,
    "folders": 1,
    "files": 1
  },
  "objects": [
    {
      "path": "picture1.jpg",
      "image": {
        "path": "slides/picture1.jpg",
        "width": 1536,
        "height": 1024
      },
      "thumb": {
        "path": "thumbs/picture1.jpg",
        "width": 256,
        "height": 171
      },
      "fileSize": 405316,
      "name": "picture1.jpg",
      "comment": "Picture1 comment",
      "fileDate": "2014-05-28T19:14:08.292Z",
      "category": "image"
    },
    {
      "path": "Foldername",
      "deepCounters": {
        "total": 1,
        "images": 1,
        "files": 1
      },
      "counters": {
        "total": 1,
        "images": 1,
        "files": 1
      },
      "thumb": {
        "path": "Foldername/thumbs/picture2.jpg",
        "width": 256,
        "height": 171
      },
      "objects": [
        {
          "path": "picture2.jpg",
          "image": {
            "path": "slides/picture2.jpg",
            "width": 1536,
            "height": 1024
          },
          "thumb": {
            "path": "thumbs/picture2.jpg",
            "width": 256,
            "height": 171
          },
          "fileSize": 296046,
          "name": "picture2.jpg",
          "fileDate": "2015-09-27T15:44:08.298Z",
          "category": "image",
          "camera": {
            "resolution": "2074 x 1383"
          }
        }
      ],
      "name": "Foldername",
      "fileDate": "2016-01-29T11:09:56.596Z",
      "category": "folder"
    }
  ],
  "name": "Test for JSON Tree",
  "fileDate": "2016-01-28T17:31:33.727Z"
}

To get the first slide path of the images you can use the following dot notation:

var path = dataTree.objects[0].image.path;

Now here is how to get the path to the thumbnail of the second image:

var thumbnail = dataTree.objects[1].objects[0].thumb.path;

The best way is to iterate through an object array and look in category for the right file type:

for (i = 0; i < dataTree.objects.length; i++) { 
    switch (dataTree.objects[i].category) {
        case 'image':
            document.getElementById("jAlbum").innerHTML += "<img src='" + dataTree.objects[i].image.path + "'>";        
          break;
    }
}

Tips for the controller

The controller will be a new class in main.js. It reads the dataTree variable in and prints the necessary html code into the index.htt. I guess the best way to implement the navigation is to save the current directory path in a JavaScript variable and write a function which takes the dataTree and returns it at the current directory position. If you want to see an implementation of a single page web album look at the source code of the new Responsive skin.