Monday 30 March 2015

Simple Twitter Bootstrap with Knockout

The code below demonstrates some simple features of Knockout (or knockout.js) within a Twitter Bootstrap page. The funny thing is, you need jQuery for Twitter Bootstrap, so you're forced to get the best of both worlds, at the cost of your page loading speed.

The page does 3 things:
As you put text into the input box, the text is synchronised with the H1 tag
When you're happy, you can click the "I'm happy" button
Clicking the button adds the text to the list group below

I've put the Knockout items in red.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">  
    <title>Bootstrap with Knockout</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>
    <div class="row">
      <div class="container">
        <div class="col-md-6">
          <!-- This is used for adding text from the input box to the title -->
          <h1 data-bind="text:title"></h1>
          <form class="form-inline">
            <input type="text" class="form-control" data-bind="value:title, valueUpdate:'afterkeydown'">
            <!-- This is used to kick off the 'addOlEntry' function when the button is clicked -->
            <button type="submit" class="btn btn-primary" data-bind="click:addOlEntry">I'm happy</button>
          </form>
          <hr />
          <!-- Loop through the olArray -->
          <ol class="list-group" data-bind="foreach:olArray">
            <!-- Add a list item for each entry in the olArray -->
            <li class="list-group-item" data-bind="text:$data"></li>
          </ol>
        </div>
      </div>
    </div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>  
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
    <script>
   /* Create a title variable and make it observable. This becomes synced to the input box within the      HTML.
Create an array and make that also observable.
Create a function which is called when the button is clicked and adds the title text to the array.#
Bind it all together. */
    var vm = 
    {
      title:ko.observable(),
      olArray:ko.observableArray(),
      addOlEntry:function()
      {
        this.olArray.push(this.title());
      }
    }    
    ko.applyBindings(vm);
    </script>
  </body>
</html>

Wednesday 11 March 2015

Twitter Bootstrap carousel gallery with thumbnails and modals using jQuery

The challenge is to create a Twitter Bootstrap carousel with the following attributes:

  • Thumbnails of each image as the indicators.
  • Hovering over images highlights the fact that you can click on them.
  • Clicking on an image will display them in a modal window.

The solution lies below with areas of interest highlighted in red.
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap thumbnail gallery</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
    <style>
    img
    {
      width:6em;
    }
    img:hover
    {
      opacity: 0.4;
      filter: alpha(opacity=40);
    }
    #exampleModal > div.modal-dialog > div > div.modal-body > img, #carousel-example-generic > div.carousel-inner > div.item > img
    {
      width:100%;
    }
    #carousel-example-generic > ol.carousel-indicators > img, #carousel-example-generic > ol.carousel-indicators > img.active
    {
      width:2em;
    }
    #carousel-example-generic > ol.carousel-indicators > img.active
    {
      height:3em;
    }
    </style>
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>
    <div class="row">
      <div class="container">
        <div class="col-md-4">
          <div id="carousel-example-generic" class="carousel slide" data-ride="carousel">

            <!-- Start of Indicators -->
            <ol class="carousel-indicators">
              <img src="derek.jpg" data-target="#carousel-example-generic" data-slide-to="0" class="active">
              <img src="jimmy.jpg" data-target="#carousel-example-generic" data-slide-to="1">
              <img src="peter.jpg" data-target="#carousel-example-generic" data-slide-to="2">
              <img src="johnnie.jpg" data-target="#carousel-example-generic" data-slide-to="3">
              <img src="steve.jpg" data-target="#carousel-example-generic" data-slide-to="4">
              <img src="mick.jpg" data-target="#carousel-example-generic" data-slide-to="5">
            </ol>
            <!-- End of Indicators -->

            <!-- Start of Wrapper for slides -->
            <div class="carousel-inner" role="listbox">
              <div class="item active">
                <img src="derek.jpg" alt="Derek" data-toggle="modal" data-target="#exampleModal">          
              </div><!-- .item -->
              <div class="item">
                <img src="jimmy.jpg" alt="Jimmy" data-toggle="modal" data-target="#exampleModal">          
              </div><!-- .item -->
              <div class="item">
                <img src="peter.jpg" alt="Peter" data-toggle="modal" data-target="#exampleModal">          
              </div><!-- .item -->
              <div class="item">
                <img src="johnnie.jpg" alt="Johnnie" data-toggle="modal" data-target="#exampleModal">          
              </div><!-- .item -->
              <div class="item">
                <img src="steve.jpg" alt="Steve" data-toggle="modal" data-target="#exampleModal">          
              </div><!-- .item -->
              <div class="item">
                <img src="mick.jpg" alt="Mick" data-toggle="modal" data-target="#exampleModal">          
              </div><!-- .item -->        
            </div><!-- .carousel-inner -->
            <!-- End of Wrapper for slides -->

            <!-- Start of Controls -->
            <a class="left carousel-control" href="#carousel-example-generic" role="button" data-slide="prev">
            <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
            <span class="sr-only">Previous</span>
            </a>
            <a class="right carousel-control" href="#carousel-example-generic" role="button" data-slide="next">
            <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
            <span class="sr-only">Next</span>
            </a>
            <!-- end of Controls -->
          </div><!-- #carousel-example-generic -->    
        </div>
        <aside class="col-md-8">
         
        </aside>
      </div>
    </div>

    <div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <h4 class="modal-title"></h4>
          </div>
          <div class="modal-body"></div>
        <div class="modal-footer"></div>
        </div><!-- /.modal-content -->
      </div><!-- /.modal-dialog -->
    </div><!-- /.modal -->

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
    <script>
    (function()
    {
      $('#exampleModal').on('show.bs.modal', function (event)
      {
        var img = $(event.relatedTarget);
        var alt = img.attr('alt');
        var src = img.attr('src');
        var modal = $(this);
        modal.find('.modal-title').text(alt);
        modal.find('.modal-body').html('<img src="'+src+'" />');
      });
    })();
    </script>
  </body>
</html>

Launch images in modal windows within Twitter Bootstrap using jQuery

So the challenge has 4 parts:
Make the image appear in thumbnail size on the page before it appears in the modal.
Change the opacity of the image on hover, so that users know if they click on it something may happen.
When the image is clicked, take information from the image tag and pass it to the modal window.
Make the image take up the whole modal window when launched.
Below is how to do it. I've highlighted the code in red.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Image to modal</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
    <style>
    img
    {
      width:6em;
    }
    img:hover
    {
      opacity: 0.4;
      filter: alpha(opacity=40);
    }
    #exampleModal > div.modal-dialog > div > div.modal-body > img
    {
      width:100%;
    }
    </style>
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>
    <img src="mick.png" alt="A picture of Mick" data-toggle="modal" data-target="#exampleModal"><br />
    <img src="rojin.jpg" alt="A picture of Rojin" data-toggle="modal" data-target="#exampleModal">

    <!-- Now the modal window -->
    <div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <h4 class="modal-title"></h4>
          </div>
          <div class="modal-body"></div>
        <div class="modal-footer"></div>
        </div><!-- /.modal-content -->
      </div><!-- /.modal-dialog -->
    </div><!-- /.modal -->

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
    <script>
    (function()
    {
      $('#exampleModal').on('show.bs.modal', function (event)
      {
        var img = $(event.relatedTarget);
        var alt = img.attr('alt');
        var src = img.attr('src');
        var modal = $(this);
        modal.find('.modal-title').text(alt);
        modal.find('.modal-body').html('<img src="'+src+'" />');
      });
    })();
    </script>
  </body>
</html>

Monday 23 February 2015

Basic HTML5 web app template which works online and offline

Here I provide the code for 3 main files in the creation of a web app. This obviously remains working when there is no internet connection, but differently since back end databases etc. would no longer be available.
In order for this to work, you should also download jQuery.
First we will need an appcache file (in this case mobile.appcache) which tells the browser what to store locally. It should look like this:
CACHE MANIFEST
# 2015-02-23 v1.0.0
index.html
html5shiv/3.7.2/html5shiv.min.js
respond/1.4.2/respond.min.js
jquery/1.11.2/jquery.min.js
onlineoffline.plugin.js

NETWORK:
*
Every time you make a change, update the date and version numbers in order for receivers of the web app to get the updated version.
Next we'll need a jQuery plugin (onlineoffline.plugin.js) to handle differences in web app behaviour when online or offline:
(function($)
{
    $.fn.extend(
    {
        onlineoffline:function(options)
        {
            
        }
    });

    $.fn.handleOnline = function()
    {
        console.log('Handling online');
    };

    $.fn.handleOffline = function()
    {
        console.log('Handling offline');
    };
})(jQuery);
Finally, the HTML file (index.html). This makes a reference to the appcache and detects if the web app is online or offline. I've kept the CSS in this file too in order to reduce the number of files needed in this example.
<!DOCTYPE html>
<html lang="en" manifest="mobile.appcache">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">    
    <title>Simple online/offline</title>
    <style>
    body
    {
      font:0.9em/1.5em Sans-serif;
    }
    </style>
  </head>
  <body>
    <h1>Hello world!</h1>
    <script src="jquery/1.11.2/jquery.min.js"></script>    
    <script src="onlineoffline.plugin.js"></script>
    <script>
    setInterval(function()
    {
      if(navigator.onLine == true)
      {
        $(this).handleOnline();
      }
      else
      {
        $(this).handleOffline();
      }      
    }, 250);
    </script>
  </body>
</html>

Friday 20 February 2015

Match the current URL with the responding navigation items of a Twitter Bootstrap site

So, you've got a Twitter Bootstrap website and you want the navigation items to become active when you're in the corresponding page. Below I wrote the jQuery plugin to do just that.
First the HTML
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">  
    <title>jQuery navigation plugin for bootstrap</title>
    <link href="bootstrap-3.3.2-dist/css/bootstrap.min.css" rel="stylesheet">      
  </head>
  <body>
    <nav class="navbar navbar-default">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse-1">
            Menu          
          </button>
          <a class="navbar-brand" href="#"><span class="glyphicon glyphicon-education" aria-hidden="true"></span></a>
      </div><!-- .navbar-header -->
      <div class="collapse navbar-collapse" id="navbar-collapse-1">
        <ul class="nav navbar-nav">
          <li><a href="index.html">Home</a></li>
          <li><a href="irrigation.html">Irrigation</a></li>
          <li><a href="pump.html">Pump</a></li>
        </ul>
      </div><!-- #navbar-collapse-1 -->
    </div><!-- /.container -->
  </nav>
    <script src="jquery/1.11.2/jquery.min.js"></script>  
    <script src="bootstrap-3.3.2-dist/js/bootstrap.min.js"></script>  
    <script src="js/matchactive.plugin.js"></script>
    <script>
    (function()
    {
       $('ul.nav > li > a').matchactive();
    }();
    </script>
  </body>
</html>

And now the matchactive.plugin.js
(function($)
{
    $.fn.extend(
    {
        matchactive:function(getvar)
        {
            var pathArray = window.location.pathname.split( '/' );
            var sn = pathArray[pathArray.length - 1];
            var setOfAnchors = $(this);
            $(setOfAnchors).each(function()
            {
            if($(this).attr('href') == sn)
            {
            $(this).parent().addClass('active');
            }
            });
        }
    });
})(jQuery);

Thursday 19 February 2015

jQuery plugin for content shared by multiple pages

Often content will appear in multiple pages in your website. For example, headers and footers will be the same on all pages. This is easily done using PHP, but it can also be done using jQuery, in fact better. Below is a Twitter Bootstrap page. As you can see I have a nav, a header and a footer. All of which have nothing in them, but I do have 3 things in my armoury:

  • A directory called 'includes/' which contains navbar.html, header.html and footer.html. They hold the content I need to fill these empty elements.
  • A plugin called 'include.plugin.js' (shown in red) which applies external file content to these empty elements.
  • A 'custom.js' (shown in red) which can be loaded on every new page I create.


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">  
    <title>jQuery includes</title>
    <link href="bootstrap-3.3.2-dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="css/custom.css" rel="stylesheet">
    <!--[if lt IE 9]>
    <script src="html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="respond/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>
    <nav class="navbar navbar-default"></nav>

    <div class="row">
      <div class="container">
        <header class="col-md-12"></header>
      </div><!-- .container -->
    </div><!-- .row -->  

    <div class="row">
      <div class="container">
        <div class="col-md-12">
          <p>Use the navigation.</p>
        </div>
      </div><!-- .container -->
    </div><!-- .row -->
   
    <div class="row">
      <div class="container">
        <footer class="col-md-12"></footer>
      </div><!-- .container -->
    </div><!-- .row -->

    <script src="jquery/1.11.2/jquery.min.js"></script>  
    <script src="bootstrap-3.3.2-dist/js/bootstrap.min.js"></script>
    <script src="js/receiveget.plugin.js"></script>
    <script src="js/include.plugin.js"></script>
    <script src="js/custom.js"></script>
  </body>
</html>

Now let's have a look at the include.plugin.js. It does a simple load, but while we're waiting for the content to come through a loader gif is put inside the calling element. This is overwritten when the content arrives.
(function($)
{
    $.fn.extend(
    {
        include:function(includefn)
        {
            $(this).append($('<img>',{src:'img/loading.gif'}));            
            $(this).load(includefn);
        }
    });
})(jQuery);

Finally, custom.js which contains the calls we need.
(function()
{
$('nav.navbar.navbar-default').include('includes/navbar.html');
$('header').include('includes/header.html');
$('footer').include('includes/footer.html');
})();

jQuery plugin to receive GET parameters and add them to an element

Below is my simple page. What I'd like to do, as you can see from the code in red is to call a jQuery plugin. The plugin find the message parameter sent to a page and apply its value to the #message div. So the call to the page would be something like this mypage.html?message=Hello+world
Then the words 'Hello world' would appear inside the div.

<!DOCTYPE html>
<html lang="en">
<head>  
<body>  
  <div class="id="message"></div>
  <script src="jquery/1.11.2/jquery.min.js"></script>
  <script src="js/receiveget.plugin.js"></script>
  <script>
  (function()
  {
    $('#message').receiveget('message');
  })();
  </script>
  </body>
</html>

So here is my receiveget.plugin.js
(function($)
{
    $.fn.extend(
    {
        receiveget:function(getvar)
        {
            var sPageURL = window.location.search.substring(1);
            var sURLVariables = sPageURL.split('&');
            for (var i = 0; i < sURLVariables.length; i++)
            {
                var sParameterName = sURLVariables[i].split('=');
                if (sParameterName[0] == getvar)
                {
                    $(this).text(decodeURIComponent(sParameterName[1].replace('+', ' ')));
                }
            }
        }
    });
})(jQuery);