Showing posts with label twitter. Show all posts
Showing posts with label twitter. Show all posts

Saturday 24 February 2018

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.

Monday 25 July 2016

Ratings field within Bootstrap using Font Awesome stars

I looked around for a nice easy rating field using stars. Just like the ones you find on tripAdvisor. All the solutions looked a little CSS or JS heavy and needed images which are more HTTP connections.
So my solution uses only a little CSS, a small amount of jQuery and font-awesome. You'll have to get font-awesome for it to work.
See below.
<!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">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <title>Font awesome stars</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
    <link rel="stylesheet" href="font-awesome/css/font-awesome.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]-->
    <style>
    .star-selected
    {
      color:pink;
    }
    </style>

  </head>
  <body>
<form method="POST" action="someaction.php">
      <div class="form-group">
        <input type="hidden" name="stars">
        <i class="fa fa-star" aria-hidden="true" value="1"></i>
        <i class="fa fa-star" aria-hidden="true" value="2"></i>
        <i class="fa fa-star" aria-hidden="true" value="3"></i>
        <i class="fa fa-star" aria-hidden="true" value="4"></i>
        <i class="fa fa-star" aria-hidden="true" value="5"></i>
      </div>
      <button type="submit">Submit</button>
    </form>

   
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
    <script>
    (function()
    {
      var theStars = $('form').find('i');
      $('i').on('click', function()
      {
        theStars.removeClass('star-selected');
        var theStarIclicked = $(this);
        var highVal = theStarIclicked.attr('value');
        theStarIclicked.addClass('star-selected');
        $("input[name='stars']").attr('value',highVal);
        theStars.each(function(i)
        {
          if($(this).attr('value') < highVal)
          {
            $(this).addClass('star-selected');
          }
        });       
        console.log('Star selected '+$("input[name='stars']").attr('value'));
      });
    })();
    </script>

  </body>
</html>

Wednesday 6 April 2016

jQuery plugin to insert external content

This jQuery plugin takes 2 parameters:
  1. The location of an external website
  2. The element within that location which contains content you would like to insert in yours
See the code here

Wednesday 23 March 2016

jQuery plugin which takes and receives form data

This jQuery plugin to take all form data, pass it to a named script and return a message to a named HTML element. Particularly good with Twitter Bootstrap.
See the code here.

Use jQuery to handle GET requests in a Twitter Bootstrap page

Today, I created a jQuery plugin. It takes GET requests via apage URL and passes the content to declared HTML elements.
See the code here.

Dynamically make items active in Twitter Bootstrap navigation using jQuery

Here, I have created a jQuery plugin. It takes as its parameter the elements containing navigation items from a Twitter Bootstrap page. The plugin then matches the page URL with a navigation item and makes it active.
Find the code here.

Tuesday 22 March 2016

Search multiple database tables using PDO

I have created a PHP class based on PDO. It searches multiple database tables. It handles boolean and normal string queries. Results are displayed as Twitter Bootstrap tables. Find it here.

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>

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);

Tuesday 10 February 2015

Using Font Awesome icons and jQuery to show form loading in Twitter Bootstrap page

Font Awesome is a really useful tool for adding icons to your website. It also comes with animated icons which can be used to show when your form is waiting for a response. In the example below, I have created a basic Twitter Bootstrap page. The page has a form. When the form is submitted, there is a delay in its response. During the delay, I use jQuery to show a Font Awesome animated icon.
First the Twitter Bootstrap page with the differences 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>Font Awesome Animated Icons</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.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>
  <i class="fa fa-circle-o-notch fa-spin"></i>  
  <form action="response.php" method="POST">
    <input type="text" name="yourname" id="yourname" placeholder="Enter your name" />
    <button type="submit">Submit</button>
  </form>
  <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()
  {
    var thisForm = $('form');
    var i = $('i');
    i.hide();
    thisForm.submit(function()
    {
      i.show();
      thisForm.hide();
      $.post(thisForm.attr('action'),thisForm.serialize(), 
      function(data)
      {
        thisForm.empty().html(data);
        i.hide();
        thisForm.show();
      });  
      return false;
    });
  })();
  </script>
  </body>
</html>
Now my response.php
<?php
sleep(2);
echo 'Hello '.$_POST['yourname'];
?>

Thursday 5 February 2015

JS and CSS fall back using PHP

There are several solutions to JS and CSS out there on the web. I've tried quite a few, but I find that if I take my network connection out, they don't work. They don't fall back. Recently, maxcdn.bootstrapcdn.com went down causing websites, including my own, to suffer from a lack of bootstrap. Even though I'd put in some fall back code.
This prompted me to write the following code. Now I know I'll be criticised for using PHP as the solution, but if you've suffered as I have, you may consider this worth a try. Below is the PHP class followed by the HTML page which makes use of the class with the calls highlighted in red. In this case I'm calling Twitter Bootstrap.
callfallback.class.php
<?php
class callfallback
{
function __construct()
{

}

function getCSS($remote, $local)
{
if($this->testExists($remote) == TRUE)
{
echo '<link rel="stylesheet" href="'.$remote.'" />'.PHP_EOL;
}
else
{
echo '<link rel="stylesheet" href="'.$local.'" />'.PHP_EOL;
}
}

function getJS($remote, $local)
{
if($this->testExists($remote) == TRUE)
{
echo '<script src="'.$remote.'"></script>'.PHP_EOL;
}
else
{
echo '<script src="'.$local.'"></script>'.PHP_EOL;
}
}

function testExists($url)
{
$file_headers = @get_headers($url);
if($file_headers[0] == 'HTTP/1.1 200 OK')
{  
 return TRUE;
}
else
{
 return FALSE;
}
}

function __destruct()
{

}
}
?>
index.html
<!DOCTYPE html>
<?php
require_once 'callfallback.class.php';
$cfb = new callfallback;
?>
<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 Fallback Template</title>
  <?php
  $cfb->getCSS('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css','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>
 
  <?php
  $cfb->getJS('https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js','js/jquery-1.11.2.min.js');
  $cfb->getJS('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js','js/bootstrap.min.js');
  ?>
</body>
</html>

Monday 8 December 2014

Dynamically activate navigation items in Bootstrap using my jQuery plugin

My challenge was to write a piece of jQuery which:

  • Takes note of the page path.
  • Compares it with the Bootstrap navigation.
  • Makes the navigation element 'active' to remind the users where they are in relation to the site.

First the HTML. Notice, that I have not set any navigation item as active. The plugin will do this. The plugin call is 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>Activate Navigation Entry</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[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>
    <nav class="navbar navbar-default" role="navigation">
      <div class="container">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">Brand</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
          <ul class="nav navbar-nav">
            <li><a href="index.php">Home</a></li>
            <li><a href="about.php">About</a></li>
            <li class="dropdown">
              <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Dropdown <span class="caret"></span></a>
              <ul class="dropdown-menu" role="menu">
                <li><a href="action.php">Action</a></li>
                <li><a href="anotheraction.php">Another action</a></li>              
              </ul>
            </li>
          </ul>
        </div><!-- /.navbar-collapse -->
      </div><!-- /.container -->
    </nav>
    <div class="row">
      <div class="container">
        <div class="col-md-12">
          <h1>Home</h1>
        </div>
      </div>
    </div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
    <script src="activatenav.plugin.js"></script>
    <script>
    (function()
    {
      $(document).activatenav(
      {
        toplevel:'ul.nav.navbar-nav > li > a',
        dropdown:'ul.nav.navbar-nav > li.dropdown > ul.dropdown-menu > li > a'
      });
    })();
    </script>
  </body>
</html>
Next the jQuery plugin named 'activatenav.plugin.js'.
First calculate the end of the path. If there is no name, it must be the home page, so set that as active.
I also check if the current page is from the drop down menu. If so, set both the drop down heading and the corresponding navigation item as 'active'.
(function($)
{
    $.fn.extend(
    {
        activatenav:function(options)
        {
        var pname = window.location.pathname;
        var pArr = pname.split('/');        
            var defaults =
            {
                toplevel:'',
        dropdown:''
            };
            options = $.extend(defaults, options);
if(options.toplevel)
{
handled = $(this).handleTopLevel(options.toplevel, pArr[pArr.length-1]);
if(handled == false)
{
$(this).handleDropdown(options.dropdown, pArr[pArr.length-1]);
}
}
        }
    });

    $.fn.handleTopLevel = function(str, pth)
    {
    var hd = false;  
    if(!pth)
    {
    $(str).first().parent().addClass('active');
    }
    else
    {
    $(str).each(function()
    {
    if($(this).attr('href') == pth)
    {
    $(this).parent().addClass('active');
    hd = true;
    }    
    });
    }
    return hd;  
    };

    $.fn.handleDropdown = function(str, pth)
    {
        $(str).each(function()
    {
    if($(this).attr('href') == pth)
    {
    $(this).parent().addClass('active');
    $(this).closest('li.dropdown').addClass('active');
    }    
    });
    };
})(jQuery);

Tuesday 4 November 2014

Twitter Bootstrap Simple One Page Template

The code below will give you a good starting position if you need to create a one page website using Twitter Bootstrap. It uses basic jQuery animation techniques so there's no need to load another library. The most important elements which get it to work are 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 One Pager</title>
    <!-- Bootstrap -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
    <style>
    .row
    {
      padding-top:4em;
    }
    figure > img
    {
      width:100%;
    }    
    </style>
    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[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>
    <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">My Website</a>
        </div><!-- .navbar-header -->
        <div id="navbar" class="collapse navbar-collapse">
          <ul class="nav navbar-nav">
            <li><a href="#home">Home</a></li>
            <li><a href="#about">About</a></li>
            <li><a href="#contact">Contact</a></li>
          </ul>
        </div><!-- .nav-collapse -->
      </div><!-- .container -->
    </nav>

    <div class="container">
      <div class="row" name="home" id="home">
        <article class="col-md-6">
          <h2>Home</h2>
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quid ad utilitatem tantae pecuniae? Age, inquies, ista parva sunt. Quibus ego vehementer assentior. Quae cum essent dicta, discessimus.</p>  
          <p>Invidiosum nomen est, infame, suspectum. Duo Reges: constructio interrete. Quibus ego vehementer assentior. Non igitur bene.</p>
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Estne, quaeso, inquam, sitienti in bibendo voluptas? Servari enim iustitia nisi a forti viro, nisi a sapiente non potest. Cum salvum esse flentes sui respondissent, rogavit essentne fusi hostes. Audax negotium, dicerem impudens, nisi hoc institutum postea translatum ad philosophos nostros esset. Obsecro, inquit, Torquate, haec dicit Epicurus? Quamquam haec quidem praeposita recte et reiecta dicere licebit. Non dolere, inquam, istud quam vim habeat postea videro; Nobis Heracleotes ille Dionysius flagitiose descivisse videtur a Stoicis propter oculorum dolorem. Duo Reges: constructio interrete. Dici enim nihil potest verius.</p>
          <p>Quid ergo attinet dicere: Nihil haberem, quod reprehenderem, si finitas cupiditates haberent? Deprehensus omnem poenam contemnet. Ego vero volo in virtute vim esse quam maximam; Omnis enim est natura diligens sui. Semper enim ex eo, quod maximas partes continet latissimeque funditur, tota res appellatur. Graecum enim hunc versum nostis omnes-: Suavis laborum est praeteritorum memoria. Hoc loco tenere se Triarius non potuit.</p>
          <p>Tu quidem reddes; Dicet pro me ipsa virtus nec dubitabit isti vestro beato M.</p>
          <p>Quod iam a me expectare noli. Hoc est dicere: Non reprehenderem asotos, si non essent asoti. Saepe ab Aristotele, a Theophrasto mirabiliter est laudata per se ipsa rerum scientia; Alterum significari idem, ut si diceretur, officia media omnia aut pleraque servantem vivere. Nec vero sum nescius esse utilitatem in historia, non modo voluptatem. Cur iustitia laudatur?</p>
          <p>Atque hoc loco similitudines eas, quibus illi uti solent, dissimillimas proferebas. Quamquam ab iis philosophiam et omnes ingenuas disciplinas habemus; Neque enim disputari sine reprehensione nec cum iracundia aut pertinacia recte disputari potest. Ita enim vivunt quidam, ut eorum vita refellatur oratio. Unum est sine dolore esse, alterum cum voluptate. Qua tu etiam inprudens utebare non numquam. An est aliquid per se ipsum flagitiosum, etiamsi nulla comitetur infamia? Intrandum est igitur in rerum naturam et penitus quid ea postulet pervidendum; Quod ea non occurrentia fingunt, vincunt Aristonem;</p>
        </article>
        <figure class="col-md-6">  
          <img src="http://lorempixel.com/400/200/sports" alt="sports" class="img-responsive" />
          <figcaption>Invidiosum nomen est, infame, suspectum. Duo Reges: constructio interrete. Quibus ego vehementer assentior. Non igitur bene.</figcaption>
        </figure>
      </div><!-- .row -->
      <div class="row" name="about" id="about">
        <article class="col-md-6">
          <h2>About</h2>
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quid ad utilitatem tantae pecuniae? Age, inquies, ista parva sunt. Quibus ego vehementer assentior. Quae cum essent dicta, discessimus.</p>  
          <p>Invidiosum nomen est, infame, suspectum. Duo Reges: constructio interrete. Quibus ego vehementer assentior. Non igitur bene.</p>
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Estne, quaeso, inquam, sitienti in bibendo voluptas? Servari enim iustitia nisi a forti viro, nisi a sapiente non potest. Cum salvum esse flentes sui respondissent, rogavit essentne fusi hostes. Audax negotium, dicerem impudens, nisi hoc institutum postea translatum ad philosophos nostros esset. Obsecro, inquit, Torquate, haec dicit Epicurus? Quamquam haec quidem praeposita recte et reiecta dicere licebit. Non dolere, inquam, istud quam vim habeat postea videro; Nobis Heracleotes ille Dionysius flagitiose descivisse videtur a Stoicis propter oculorum dolorem. Duo Reges: constructio interrete. Dici enim nihil potest verius.</p>
          <p>Quid ergo attinet dicere: Nihil haberem, quod reprehenderem, si finitas cupiditates haberent? Deprehensus omnem poenam contemnet. Ego vero volo in virtute vim esse quam maximam; Omnis enim est natura diligens sui. Semper enim ex eo, quod maximas partes continet latissimeque funditur, tota res appellatur. Graecum enim hunc versum nostis omnes-: Suavis laborum est praeteritorum memoria. Hoc loco tenere se Triarius non potuit.</p>
          <p>Tu quidem reddes; Dicet pro me ipsa virtus nec dubitabit isti vestro beato M.</p>
          <p>Quod iam a me expectare noli. Hoc est dicere: Non reprehenderem asotos, si non essent asoti. Saepe ab Aristotele, a Theophrasto mirabiliter est laudata per se ipsa rerum scientia; Alterum significari idem, ut si diceretur, officia media omnia aut pleraque servantem vivere. Nec vero sum nescius esse utilitatem in historia, non modo voluptatem. Cur iustitia laudatur?</p>
          <p>Atque hoc loco similitudines eas, quibus illi uti solent, dissimillimas proferebas. Quamquam ab iis philosophiam et omnes ingenuas disciplinas habemus; Neque enim disputari sine reprehensione nec cum iracundia aut pertinacia recte disputari potest. Ita enim vivunt quidam, ut eorum vita refellatur oratio. Unum est sine dolore esse, alterum cum voluptate. Qua tu etiam inprudens utebare non numquam. An est aliquid per se ipsum flagitiosum, etiamsi nulla comitetur infamia? Intrandum est igitur in rerum naturam et penitus quid ea postulet pervidendum; Quod ea non occurrentia fingunt, vincunt Aristonem;</p>
        </article>
        <figure class="col-md-6">  
          <img src="http://lorempixel.com/400/200/cats" alt="sports" class="img-responsive" />
          <figcaption>Invidiosum nomen est, infame, suspectum. Duo Reges: constructio interrete. Quibus ego vehementer assentior. Non igitur bene.</figcaption>
        </figure>
      </div><!-- .row -->
      <div class="row" name="contact" id="contact">
        <article class="col-md-6">
          <h2>Contact</h2>
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quid ad utilitatem tantae pecuniae? Age, inquies, ista parva sunt. Quibus ego vehementer assentior. Quae cum essent dicta, discessimus.</p>  
          <p>Invidiosum nomen est, infame, suspectum. Duo Reges: constructio interrete. Quibus ego vehementer assentior. Non igitur bene.</p>
          <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Estne, quaeso, inquam, sitienti in bibendo voluptas? Servari enim iustitia nisi a forti viro, nisi a sapiente non potest. Cum salvum esse flentes sui respondissent, rogavit essentne fusi hostes. Audax negotium, dicerem impudens, nisi hoc institutum postea translatum ad philosophos nostros esset. Obsecro, inquit, Torquate, haec dicit Epicurus? Quamquam haec quidem praeposita recte et reiecta dicere licebit. Non dolere, inquam, istud quam vim habeat postea videro; Nobis Heracleotes ille Dionysius flagitiose descivisse videtur a Stoicis propter oculorum dolorem. Duo Reges: constructio interrete. Dici enim nihil potest verius.</p>
          <p>Quid ergo attinet dicere: Nihil haberem, quod reprehenderem, si finitas cupiditates haberent? Deprehensus omnem poenam contemnet. Ego vero volo in virtute vim esse quam maximam; Omnis enim est natura diligens sui. Semper enim ex eo, quod maximas partes continet latissimeque funditur, tota res appellatur. Graecum enim hunc versum nostis omnes-: Suavis laborum est praeteritorum memoria. Hoc loco tenere se Triarius non potuit.</p>
          <p>Tu quidem reddes; Dicet pro me ipsa virtus nec dubitabit isti vestro beato M.</p>
          <p>Quod iam a me expectare noli. Hoc est dicere: Non reprehenderem asotos, si non essent asoti. Saepe ab Aristotele, a Theophrasto mirabiliter est laudata per se ipsa rerum scientia; Alterum significari idem, ut si diceretur, officia media omnia aut pleraque servantem vivere. Nec vero sum nescius esse utilitatem in historia, non modo voluptatem. Cur iustitia laudatur?</p>
          <p>Atque hoc loco similitudines eas, quibus illi uti solent, dissimillimas proferebas. Quamquam ab iis philosophiam et omnes ingenuas disciplinas habemus; Neque enim disputari sine reprehensione nec cum iracundia aut pertinacia recte disputari potest. Ita enim vivunt quidam, ut eorum vita refellatur oratio. Unum est sine dolore esse, alterum cum voluptate. Qua tu etiam inprudens utebare non numquam. An est aliquid per se ipsum flagitiosum, etiamsi nulla comitetur infamia? Intrandum est igitur in rerum naturam et penitus quid ea postulet pervidendum; Quod ea non occurrentia fingunt, vincunt Aristonem;</p>
        </article>
        <figure class="col-md-6">  
          <img src="http://lorempixel.com/400/200/people" alt="people" class="img-responsive" />
          <figcaption>Invidiosum nomen est, infame, suspectum. Duo Reges: constructio interrete. Quibus ego vehementer assentior. Non igitur bene.</figcaption>
        </figure>
      </div><!-- .row -->
    </div><!-- .container -->

    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
    <script>
    (function()
    {
      $('.navbar-inverse .navbar-nav > li > a').click(function()
      {
        var target = $(this).attr('href');
        var targetLoc = $(target).offset().top;        
        $('html, body').stop().animate(
        {
          scrollTop:targetLoc,
          easing:'swing'
        }, 1000);
        return false;
      });
    })();
    </script>
  </body>
</html>

Monday 6 October 2014

Using PHP to get YouTube Channel feed into Twitter Bootstrap thumbnails

I've been working on a Twitter Bootstrap site. The client created a YouTube channel and wanted the feed coming into the site. Some of the videos added are uploaded by the users, some come from subscriptions. There is a nice class called thumbnail in Twitter Bootstrap for such things, so I thought I'd use that. I'm happiest getting external data using PHP. Here's how it's done.
Replace the word 'Google' with the name of your channel.
<?php
$url = 'https://gdata.youtube.com/feeds/api/videos?q=Google&max-re%20sults=5&v=2&alt=jsonc&orderby=published';
$json = file_get_contents($url);
$data = json_decode($json);
$items = $data->data->items;
foreach($items as $child)
{
echo '<a href="'.$child->player->default.'" class="thumbnail">';
echo '<h4>'.$child->title.'</h4>';
echo '<img src="'.$child->thumbnail->sqDefault.'" alt="'.$child->title.'" />';
echo '<footer>'.date("jS F Y",strtotime($child->updated)).'</footer>';
echo '</a>';
}
?>

Wednesday 1 October 2014

jQuery file upload in Twitter Bootstrap modal

For a recent project, I have needed to add a file upload form to a modal. This has required me to perform the upload through jQuery in order to avoid the page reloading when the form is submitted.
To accomplish this I have used the jQuery form plugin at http://malsup.com/jquery/form/.
Here's the code with the important bits 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 101 Template</title>
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <style>
    body
    {
    padding-top:2em;
    }
    </style>
    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[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="container">
  <div class="col-md-6">
  <button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">Launch demo modal</button>
 
  </div>
  <div id="myResult" class="col-md-6 alert alert-success" role="alert">
 
  </div><!-- myResult -->
  </div><!-- .container -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
 <div class="modal-dialog">
   <div class="modal-content">
     <div class="modal-header">
       <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
       <h4 class="modal-title">Modal title</h4>
     </div>
     <div class="modal-body">
       <form action="uploadfile.php" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="file">File input</label>
<input type="file" name="file">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
     </div>
   </div><!-- /.modal-content -->
 </div><!-- /.modal-dialog -->
</div><!-- /.modal -->
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="js/bootstrap.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery.form/3.50/jquery.form.min.js"></script>
    <script>
(function()
{
$('#myResult').hide();
$('form').submit(function()
{
$(this).ajaxSubmit(
{
url:$(this).attr('action'),
method:$(this).attr('method'),
target: '#myResult'
});
$('#myModal').modal('hide');
$('#myResult').show();
return false;
});
})();
</script>
  </body>
</html>

Tuesday 30 September 2014

Forms within modal-body in Twitter Bootstrap.

I've been working on a Twitter Bootstrap site recently. It contains modal which require a little interaction within the modal box itself. So here is an example of how to achieve this, this time using forms. First, I load the form into the modal, then I handle the form still within the modal. Most of the code is taken directly from the Twitter Bootstrap website. The only real difference is that I've loaded jQuery and the bootstrap.min.js before the body. I've highlighted the important parts 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 101 Template</title>

    <!-- Bootstrap -->
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="js/bootstrap.min.js"></script>
    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[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>  
    <!-- Button trigger modal -->
    <button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">    Launch demo modal</button>
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
        <h4 class="modal-title">Modal title</h4>
      </div>
      <div class="modal-body">      
        <form class="form-inline" role="form" method="POST" action="http.php">
  <div class="form-group">
    <label class="sr-only" for="exampleInputEmail2">Email address</label>
    <input type="email" class="form-control" name="exampleInputEmail2" placeholder="Enter email">
  </div>  
  <button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
      </div>
    </div><!-- /.modal-content -->
  </div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<script>
(function()
{
  $('form').submit(function()
  {
    $.post($(this).attr('action'),$(this).serialize(), function(data)
    {
      $('#myModal .modal-body').append(data);
    });
    return false;
  });
})();
</script>
</body>
</html>

Get links to target modal-body in Twitter Bootstrap

I've been working on a Twitter Bootstrap site recently. It contains modal which require a little interaction within the modal box itself. So here is an example of how to achieve this, first using links (hyperlinks). Most of the code is taken directly from the Twitter Bootstrap website. The only real difference is that I've loaded jQuery and the bootstrap.min.js before the body. I've highlighted the important parts 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 101 Template</title>

    <!-- Bootstrap -->
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="js/bootstrap.min.js"></script>
    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[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>  
    <!-- Button trigger modal -->
    <button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">    Launch demo modal</button>
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
        <h4 class="modal-title">Modal title</h4>
      </div>
      <div class="modal-body">
        <a href="hello.php" data-target="#myModal">Click me</a>
       </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
      </div>
    </div><!-- /.modal-content -->
  </div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<script>
(function()
{
  $('a[data-target=#myModal]').click(function()
  {
    var target = $(this).attr('href');
    $('#myModal .modal-body').load(target);
    return false;
  });  
})();
</script>  </body>
</html>

Monday 7 April 2014

Simple pagination plugin for Twitter Bootstrap

Let's say you have content in a Twitter Bootstrap web page and you want to paginate through it. If you've ever tried looking for examples on doing this, you would know that very few of them contain content. Or in other words the examples contain all the numbers at the bottom but none of the content at the top and how to paginate through it.
I then found plugins which looked very clever, but didn't actually work.
So I have created a jQuery plugin (which works) and an example of how it could be used.
First the HTML page which I took form getbootstrap.com, then added the necessary code for the pagination which I highlight below.
Actually, it works for any site which uses jQuery. Another strength to this simplified method is that you can name the content IDs whatever you like and the plugin with still pick them up as labels.

<!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 101 Template</title>

    <!-- Bootstrap -->
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <style>
    body
    {
      padding-top:2em;
    }
    #mickspagination #navigation a
    {
      background:#e5e5e5;
      margin:0.1em;
      padding:0.5em;
    }
    </style>
    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
      <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>
  <body>
    <div class="row">
      <div class="container">
        <div class="col-md-12">
          <div id="mickspagination">
            <div id="content">
              <div id="1" class="active">
                <p>Content for 1</p>
              </div>
              <div id="2">
                <p>Content for 2</p>
              </div>
              <div id="3">
                <p>Content for 3</p>
              </div>
              <div id="4">
                <p>Content for 4</p>
              </div>
            </div>
            <div id="navigation"></div>
          </div>
        </div>
      </div>
    </div>  
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="js/bootstrap.min.js"></script>
    <script src="pagination.plugin.js"></script>
    <script>
    (function()
    {
      $('#mickspagination').pagination();
    })();
    </script>
  </body>
</html>

Now the jQuery plugin contained in pagination.plugin.js

(function($)
{
    $.fn.extend(
    {
        pagination:function(options)
        {
            var defaults = 
            {
                showarrows:false,                
                classesext:null,
                alignment:'center',
                navigationtag:'#navigation'
            }

            var options = $.extend(defaults, options);

            return this.each(function() 
            {
                var o = options;                

                var content = $(this).find('#content');
                var contentDivs = content.find(' > div');
                var firstDiv = content.children().first();
                var lastDiv = content.children().last();    
                var leftDiv = content.children().first();    
                var rightDiv = content.children().eq(1);
                var leftArrow, rightArrow;
                var activeDiv  = content.find('.active');
                var navigation = null;
                var contentArr = Array();

                contentDivs.not('.active').hide();

                /* Provide option for navigation outside the pagination */
                if(o.navigationtag == '#navigation')
                {
                  navigation = $(this).find('#navigation');
                }
                else
                {

                  navigation = $(document).find(o.navigationtag);
                }

                /* Show the first arrows */
                if(o.showarrows == true)
                {
                  link = $(this).arrowlink(firstDiv.attr('id').replace(/ /g,''),'«', o.classesext);
                  navigation.append(link);
                  link = $(this).arrowlink(leftDiv.attr('id'),'<', o.classesext);
                  navigation.append(link);                  
                  leftArrow = navigation.find("a:contains('<')"); 
                }    

                /* Show all the pagination navigation */
                contentDivs.each(function()
                {
                  encodedID = $(this).attr('id').replace(/ /g,'');
                  $(this).attr('title', $(this).attr('id'));                  
                  $(this).attr('id', encodedID);                  
                  contentArr.push($(this).attr('id'));
                  link = $(this).buildlink(o.classesext);
                  navigation.append(link);
                });

                /* Show the last arrows */
                if(o.showarrows == true)
                {
                  link = $(this).arrowlink(rightDiv.attr('id'),'>', o.classesext);
                  navigation.append(link);
                  link = $(this).arrowlink(lastDiv.attr('id'),'»', o.classesext);
                  navigation.append(link);                  
                  rightArrow = navigation.find("a:contains('>')");                  
                }

                /* Centre the pagination navigation. May wish to set this as an option */
                navigation.css('text-align',o.alignment);

                /* Handle what happens when someone clicks on a navigation link */
                $(navigation).on('click', 'a', function()
                {
                  /* Make the currently clicked ID the active one */
                  activeDiv  = content.find('.active');
                  activeDiv.removeClass('active');
                  currentID = $(this).attr('href');
                  newActiveDiv = content.find(' > div'+currentID);
                  newActiveDiv.addClass('active');

                  /* Change what the arrows now point at */
                  if(o.showarrows == true)
                  {
                    leftArrow.updateleftlink(newActiveDiv, contentArr);
                    rightArrow.updaterightlink(newActiveDiv, contentArr);
                  }

                  /* Show the newly selected content */
                  contentDivs.not('.active').hide();
                  newActiveDiv.show();      
                });
            });
        }
    }); /* End of pagination plugin. Other function may go below this */

    /* Create the pagination navigation links */    
    $.fn.buildlink = function(classesext)
    {
        var ct = $.trim(classesext);
        link = '<a href="#';
        link += $(this).attr('id')+'"';        
        if(classesext !== null)
        {
            link += ' class="'+ct+'"';
        }
        link += '>';        
        link += $(this).attr('title');
        link += '</a>';
        return link;
    };

    $.fn.arrowlink = function(dynamicloc, linkchar, classesext)
    {
        var ct = $.trim(classesext);
        link = '<a href="#';        
        link += dynamicloc+'"';        
        link += ' class="pagarrow';
        if(classesext !== null)
        {
            link += ' '+ct;
        }        
        link += '">';
        link += linkchar;
        link += '</a>';
        return link;
    };

    /* Update the first arrow link */
    $.fn.updateleftlink = function(ad,cr)
    {
        var ov = 0;
        var hrefstring = '#';
        var ap = cr.indexOf(ad.attr('id'));
        if((ap-1) <= 0)
        {
            ov = 0;
        }
        else
        {
            ov = (ap-1);
        }
        hrefstring += cr[ov];
        $(this).attr('href',hrefstring);    
    };

    $.fn.updaterightlink = function(ad,cr)
    {
        var ov = 0;
        var hrefstring = '#';
        var ap = cr.indexOf(ad.attr('id'));    
        if((ap+1) >= cr.length)
        {
            ov = cr.length-1;      
        }
        else
        {
            ov = (ap+1);
        }
        hrefstring += cr[ov];    
        $(this).attr('href',hrefstring);    
    };

})(jQuery);