Sunday, December 28, 2014

Typeahead.js Autocomplete Suggestion + Bloodhount Remote Data - Tutorial and Demo

Typeahead.js improved version includes Bloodhound suggestion engine which handles filtering and sorting things for you. 

Typeahead Js is similar to google, facebook, twitter, gmail auto suggestion. It completes the full string when you type.

You need

  • JQuery
  • Typeahead JS Plugin
  • BloodHound Suggestion Engine (Part of Typeahead Project)


To initiate Typeahead on any input use $("ELEMENTSELECTOR").typeahead();

Typeahead has following notable options. read all here 

 hint  - If  true  shows the Hint as you Type.

typeahead Hint shown
typeahead autocompletes the word when you type - Hint

 highlight  -  If  true  highlights the options (Bold Text).


Typeahead Highlight Option explained
Highlight Object of Typeahead
If you want to have more control over the result set displayed as suggestions, use templates object.
template object with Typeahead JS
Templates Object with Suggestion function

Check out the working code
 
<!-- Bootstrap core CSS OPTIONAL -->
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
 <!-- JavaScript
 ================================================== -->
 <!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script>
<script src="js/typeahead.bundle.js"></script>
<script src="js/bloodhound.js"></script>

Javascript Array of Country List

var country_list = ["Afghanistan","Albania","Algeria","Andorra","Angola","Anguilla","Antigua &amp; Barbuda","Argentina","Armenia","Aruba","Australia","Austria","Azerbaijan","Bahamas","Bahrain","Bangladesh","Barbados","Belarus","Belgium","Belize","Benin","Bermuda","Bhutan","Bolivia","Bosnia &amp; Herzegovina","Botswana","Brazil","British Virgin Islands","Brunei","Bulgaria","Burkina Faso","Burundi","Cambodia","Cameroon","Cape Verde","Cayman Islands","Chad","Chile","China","Colombia","Congo","Cook Islands","Costa Rica","Cote D Ivoire","Croatia","Cruise Ship","Cuba","Cyprus","Czech Republic","Denmark","Djibouti","Dominica","Dominican Republic","Ecuador","Egypt","El Salvador","Equatorial Guinea","Estonia","Ethiopia","Falkland Islands","Faroe Islands","Fiji","Finland","France","French Polynesia","French West Indies","Gabon","Gambia","Georgia","Germany","Ghana","Gibraltar","Greece","Greenland","Grenada","Guam","Guatemala","Guernsey","Guinea","Guinea Bissau","Guyana","Haiti","Honduras","Hong Kong","Hungary","Iceland","India","Indonesia","Iran","Iraq","Ireland","Isle of Man","Israel","Italy","Jamaica","Japan","Jersey","Jordan","Kazakhstan","Kenya","Kuwait","Kyrgyz Republic","Laos","Latvia","Lebanon","Lesotho","Liberia","Libya","Liechtenstein","Lithuania","Luxembourg","Macau","Macedonia","Madagascar","Malawi","Malaysia","Maldives","Mali","Malta","Mauritania","Mauritius","Mexico","Moldova","Monaco","Mongolia","Montenegro","Montserrat","Morocco","Mozambique","Namibia","Nepal","Netherlands","Netherlands Antilles","New Caledonia","New Zealand","Nicaragua","Niger","Nigeria","Norway","Oman","Pakistan","Palestine","Panama","Papua New Guinea","Paraguay","Peru","Philippines","Poland","Portugal","Puerto Rico","Qatar","Reunion","Romania","Russia","Rwanda","Saint Pierre &amp; Miquelon","Samoa","San Marino","Satellite","Saudi Arabia","Senegal","Serbia","Seychelles","Sierra Leone","Singapore","Slovakia","Slovenia","South Africa","South Korea","Spain","Sri Lanka","St Kitts &amp; Nevis","St Lucia","St Vincent","St. Lucia","Sudan","Suriname","Swaziland","Sweden","Switzerland","Syria","Taiwan","Tajikistan","Tanzania","Thailand","Timor L'Este","Togo","Tonga","Trinidad &amp; Tobago","Tunisia","Turkey","Turkmenistan","Turks &amp; Caicos","Uganda","Ukraine","United Arab Emirates","United Kingdom","Uruguay","Uzbekistan","Venezuela","Vietnam","Virgin Islands (US)","Yemen","Zambia","Zimbabwe"];

Javascript for Typeahead with Local Javascript Array

           $(document).ready(function() {

        // Set the Options for "Bloodhound" Engine
                var my_Suggestion_class = new Bloodhound({
                    limit: 10,
                    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
                    queryTokenizer: Bloodhound.tokenizers.whitespace,
                    local: $.map(country_list, function(item) {
                        //console.log(item);
                        return {value: item};
                    })
                });

        //Initialize the Suggestion Engine
                my_Suggestion_class.initialize();

                var typeahead_elem = $('.typeahead');
                typeahead_elem.typeahead({
                    hint: true,
                    highlight: true,
                    minLength: 1
                },
                {
                    name: 'value',
                    displayKey: 'value',
                    source: my_Suggestion_class.ttAdapter(),
                    templates: {
                        empty: [
                            '<div class="noitems">',
                            'No Items Found',
                            '</div>'
                        ].join('\n')
                    }
                });
            });

Typeahead need array of JSON object to show the suggestion. 

{ "identifier" : "itemvalue}{ "identifier" : "itemvalue} ]

We have prepared above structured array from JQuery map function
                    local: $.map(country_list, function(item) {
                        return {value: item};
                    })

    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
    queryTokenizer: Bloodhound.tokenizers.whitespace,
The above two Tokenizer lines may confuse every one. datumTokenizer needs the array of JSON as shown here

{ "identifier" : "itemvalue}{ "identifier" : "itemvalue} ]

If your array or JSON data structure is same as above then 

datumTokenizer: Bloodhound.tokenizers.obj.whitespace('identifier')

Typeahead shows plain string without any styling if you dont customize the response. You can modifiy the following style as you like.

Stlying the Suggestions

<style>
.typeahead,
.tt-query,
.tt-hint {
  width: 396px;
  height: 30px;
  padding: 8px 12px;
  font-size: 24px;
  line-height: 30px;
  border: 2px solid #ccc;
  -webkit-border-radius: 8px;
     -moz-border-radius: 8px;
          border-radius: 8px;
  outline: none;
}

.typeahead {
  background-color: #fff;
}

.typeahead:focus {
  border: 2px solid #0097cf;
}

.tt-query {
  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
}

.tt-hint {
  color: #999
}

.tt-dropdown-menu {
  width: 422px;
  margin-top: 12px;
  padding: 8px 0;
  background-color: #fff;
  border: 1px solid #ccc;
  border: 1px solid rgba(0, 0, 0, 0.2);
  -webkit-border-radius: 8px;
     -moz-border-radius: 8px;
          border-radius: 8px;
  -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
     -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
          box-shadow: 0 5px 10px rgba(0,0,0,.2);
}

.tt-suggestion {
  padding: 3px 20px;
  font-size: 18px;
  line-height: 24px;
}

.tt-suggestion.tt-cursor {
  color: #fff;
  background-color: #0097cf;

}

.tt-suggestion p {
  margin: 0;
}
tt-highlight{
    color:red;
}
</style>

Output of Typeahead in browser

To modify the result displayed in suggestion you need to add templates object with typeahead.

It has four options
empty - If no result found return this custom text / style.
suggestion - Adding HTML Elements and customizing the result suggestion shown when you type.
header - To add header data for the suggestion list shown
footer - Similar to header, add footer text to result set shown in screen.

Typeahead JS with Bloodhound Remote and Prefetch


            $(document).ready(function() {
        //Set up "Bloodhound" Options 
                var my_Suggestion_class = new Bloodhound({
                    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('vval'),
                    queryTokenizer: Bloodhound.tokenizers.whitespace,
                    prefetch: {
                        url: "countries.json",
                        filter: function(countryArray) {
                            return $.map(countryArray, function(country) {
                                return {vval: country.name};
                            });
                            //return catAR;
                        }
                    },
                    remote: {
                        url: "s.php?s=%QUERY",
                        filter: function(x) {
                            return $.map(x, function(item) {
                                return {vval: item.name};
                            });
                        },
                        wildcard: "%QUERY"
                    }
                    //http://code.educationgovt.com/typeaheadjs/countries.json
                });

                // Initialize Typeahead with Parameters
                my_Suggestion_class.initialize();
                var typeahead_elem = $('.typeahead');
                typeahead_elem.typeahead({
                    hint: false,
                    highlight: true,
                    minLength: 1
                },
                {
                    // `ttAdapter` wraps the suggestion engine in an adapter that
                    // is compatible with the typeahead jQuery plugin
                    name: 'vval',
                    displayKey: 'vval',
                    source: my_Suggestion_class.ttAdapter()
                });

                //Get the Typeahead Value on Following Events
                $('input').on([
                    'typeahead:initialized',
                    'typeahead:initialized:err',
                    'typeahead:selected',
                    'typeahead:autocompleted',
                    'typeahead:cursorchanged',
                    'typeahead:opened',
                    'typeahead:closed'
                ].join(' '), function(x) {
                    //console.log(this.value); 
                });
            });

How to get typeahead Selected input value 

Following events applicable on typeahead input element. I have given the events with complete example below
                $('input').on([
                    'typeahead:initialized',
                    'typeahead:initialized:err',
                    'typeahead:selected',
                    'typeahead:autocompleted',
                    'typeahead:cursorchanged',
                    'typeahead:opened',
                    'typeahead:closed'
                ].join(' '), function(x) {
                    console.log(this.value); 
                });

Prefetch Data will be stored in localstorage

When the page is loaded the response from prefetch will be stored in localstorage.

Fetching Remote JSON Data in suggestion

Check the Demo

<script type='text/javascript'>
var image_url = "http://image.tmdb.org/t/p/original/";
$(window).load(function(){
// Instantiate the Bloodhound suggestion engine
var movies = new Bloodhound({
    datumTokenizer: function (datum) {
        return Bloodhound.tokenizers.whitespace(datum.value);
    },
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    remote: {
        url: 'http://api.themoviedb.org/3/search/movie?query=%QUERY&api_key=470fd2ec8853e25d2f8d86f685d2270e',
        filter: function (movies) {
            return $.map(movies.results, function (movie) {
                return {
                    value: movie.original_title,
                    release_date: movie.release_date,
                    poster_path:image_url+movie.poster_path
                };
            });
        }
    }
});

// Initialize the Bloodhound suggestion engine
movies.initialize();
// Instantiate the Typeahead UI
$('.typeahead').typeahead(null, {
    displayKey: 'value',
    source: movies.ttAdapter(),
    templates: {
        suggestion: Handlebars.compile("<p style='padding:6px'><img width=50 src='{{poster_path}}'> <b>{{value}}</b> - Release date {{release_date}} </p>"),
        footer: Handlebars.compile("<b>Searched for '{{query}}'</b>")
    }
});
});

</script>

The difference is remote data response is JSON array. We use filter function to prepare the data we need to display in suggestion.

Thats it.

Read more…

Wednesday, December 17, 2014

Login using Google Javascript API [Sample Code]

Latest Google Javascript API allow users to fetch their google profile information, circle details. Javscript API is not just limited to this, but it allow us to fetch and upload Google Drive file. Read more

In this tutorial we are utilizing Google+ Javascript API to fetch user Google+ Profile Details and Email address. It is purely OAuth2 Compatible login method and its secure.

Workflow is simple

  1. User Clicks on Login with Google Button on XYZ Website
  2. Google OAuth2 Popup opens and ask the user login to google account first.
  3. If Logged in, it shows the permissions that this website is requesting, then user accept this by pressing button Allow.
  4. Now the website receives the user information which are requested by the XYZ Website ( Login Scope )

Before you begin this tutorial, you actually need to setup a Project through Google Developer Console. You can follow google docs here.

Step 1: Create Project

Step 2: Set the Consent Screen details



Step 3: Create Web application Client Key and Secret



Now Client Key and Secret key successfully created.

Note: For javascript based login, we dont use Secret key, only Client Key is enough.


How to Google+ Javascript Login 

Add Google+ Javascript API Javascript Header
  <script type="text/javascript">
  (function() {
    var po = document.createElement('script');
    po.type = 'text/javascript'; po.async = true;
    po.src = 'https://plus.google.com/js/client:plusone.js';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(po, s);
  })();
  </script>
Add JQuery & Bootstrap for styling
    <!-- Bootstrap core CSS -->
  <link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">

    <!-- Custom styles for this template -->
  <link href="http://getbootstrap.com/examples/signin/signin.css" rel="stylesheet">

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
  <script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script>


Complete HTML Body code for the Form and Google+ Button

   <div class="container">

      <form class="form-signin" role="form">
            <div id="status"></div>
        <h2 class="form-signin-heading">User Registration</h2>
        
        <label for="inputFname" class="sr-only">First Name</label>
            <input type="text" id="inputFullname" class="form-control" placeholder="First Name" required autofocus>
            
        <label for="inputEmail" class="sr-only">Email address</label>
        <input type="email" id="inputEmail" class="form-control" placeholder="Email address" required >
        
        <label for="inputPassword" class="sr-only">Password</label>
        <input type="password" id="inputPassword" class="form-control" placeholder="Password" required>
        
        <div class="row"> 
            <div class="col-md-6">
                <button class="btn btn-sm btn-primary btn-block" type="submit">Sign Up</button>
            </div>
            <div class="col-md-6">
                <button class="g-signin " 
                    data-scope="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email"
                    data-requestvisibleactions="http://schemas.google.com/AddActivity"
                    data-clientId="1049178870057-usbfluijl3qtq3nijmucnsksr9gvkag4.apps.googleusercontent.com"
                    data-accesstype="offline"
                    data-callback="mycoddeSignIn"
                    data-theme="dark"
                    data-cookiepolicy="single_host_origin">
                </button>
            </div>
        </div>
         

      </form>

    </div> <!-- /container -->

Javascript Code for the Google+ API and Fetching User Details, Email from Google Profile

    <script type="text/javascript">
    var gpclass = (function(){
    
    //Defining Class Variables here
    var response = undefined;
    return {
        //Class functions / Objects
        
        mycoddeSignIn:function(response){
            // The user is signed in
            if (response['access_token']) {
            
                //Get User Info from Google Plus API
                gapi.client.load('plus','v1',this.getUserInformation);
                
            } else if (response['error']) {
                // There was an error, which means the user is not signed in.
                //alert('There was an error: ' + authResult['error']);
            }
        },
        
        getUserInformation: function(){
            var request = gapi.client.plus.people.get( {'userId' : 'me'} );
            request.execute( function(profile) {
                var email = profile['emails'].filter(function(v) {
                    return v.type === 'account'; // Filter out the primary email
                })[0].value;
                var fName = profile.displayName;
                $("#inputFullname").val(fName);
                $("#inputEmail").val(email);
            });
        }
    
    }; //End of Return
    })();
    
    function mycoddeSignIn(gpSignInResponse){
        gpclass.mycoddeSignIn(gpSignInResponse);
    }
    </script>


If you click on the Google+ Login Button it will show a popup like below. This means your configuration in google developer console is right.
Login using Google Popup 

Thats it.

Read more…

Tuesday, December 9, 2014

Simple Login and Sign Up using Facebook Javascript SDK

Filling Sign Up and Login form were part of every web application nowadays. Users feel it hard to fill the sign up form again with same information. With Facebook API you can easily collect the basic user information needed for sign up.

This is the simplest working example for facebook based sign up.

This tutorial uses Facebook Javascript SDK v2.2

Demo|   Download

Needables

  • Facebook SDK
  • Facebook Application ID
You can create your application for free from here https://developers.facebook.com/apps


App ID (Application ID) can be obtained from the facebook application page, as show in above screenshot.

 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
 <script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script>

Signup Html Form

      <form class="form-signin" role="form">
            <div id="status"></div>
        <h2 class="form-signin-heading">User Registration</h2>
        
        <label for="inputFname" class="sr-only">First Name</label>
            <input type="text" id="inputFname" class="form-control" placeholder="First Name" required autofocus>
        
        <label for="inputLname" class="sr-only">First Name</label>
            <input type="text" id="inputLname" class="form-control" placeholder="Last Name" required >
            
        <label for="inputEmail" class="sr-only">Email address</label>
        <input type="email" id="inputEmail" class="form-control" placeholder="Email address" required >
        
        <label for="inputPassword" class="sr-only">Password</label>
        <input type="password" id="inputPassword" class="form-control" placeholder="Password" required>
        <div class="checkbox">
          <label>
            <input type="checkbox" value="remember-me"> Remember me
          </label>
        </div>
        
        <button class="btn btn-sm btn-primary btn-block" type="submit">Sign Up</button> <button class="btn btn-sm btn-primary btn-block" onclick="_login();" type="submit">Sign Up using Facebook</button>
      </form>

Javascript

    <script>
  // Load the SDK asynchronously
  (function(thisdocument, scriptelement, id) {
    var js, fjs = thisdocument.getElementsByTagName(scriptelement)[0];
    if (thisdocument.getElementById(id)) return;
    
    js = thisdocument.createElement(scriptelement); js.id = id;
    js.src = "//connect.facebook.net/en_US/sdk.js"; //you can use 
    fjs.parentNode.insertBefore(js, fjs);
  }(document, 'script', 'facebook-jssdk'));
    
  window.fbAsyncInit = function() {
  FB.init({
    appId      : '1449392918617564', //Your APP ID
    cookie     : true,  // enable cookies to allow the server to access 
                        // the session
    xfbml      : true,  // parse social plugins on this page
    version    : 'v2.1' // use version 2.1
  });

  // These three cases are handled in the callback function.
  FB.getLoginStatus(function(response) {
    statusChangeCallback(response);
  });

  };
    
  // This is called with the results from from FB.getLoginStatus().
  function statusChangeCallback(response) {
    if (response.status === 'connected') {
      // Logged into your app and Facebook.
      _i();
    } else if (response.status === 'not_authorized') {
      // The person is logged into Facebook, but not your app.
      document.getElementById('status').innerHTML = 'Please log ' +
        'into this app.';
    }
  }  
  
  function _login() {
    FB.login(function(response) {
       // handle the response
       if(response.status==='connected') {
        _i();
       }
     }, {scope: 'public_profile,email'});
 }
 
 function _i(){
     FB.api('/me', function(response) {
        document.getElementById("inputFname").value = response.first_name;
        document.getElementById("inputLname").value = response.last_name;
        document.getElementById("inputEmail").value = response.email;
    });
 }

</script>

Read more…

Saturday, December 6, 2014

Multiple reCAPTCHA Implementation on Same Page [Sample]

Page with multiple forms always need multiple reCAPTCHA for spam validation.

With Google new reCAPTCHA library "I'm not a robot" and Javascript parameter you can simply implement this multiple validation.

                           View Demo  |   Download Code

Needables:

1) Google reCAPCTHA Javascript URL
2) Following Implementation steps.

The difference between automatic reCAPTCHA loading and explicit manual loading is the following script with onload callback funtion.

For Manual (or Multiple reCAPTCHA's in a page)
<script src="https://www.google.com/recaptcha/api.js?onload=myCallBack&render=explicit" async defer></script>

You need to mention the following in above URL
  • onload = your local javascript callback function
  • render = explicit
Multple reCAPTCHA loaded on same Page

Html Form Code

    <div class="container">
      <div class="col-md-6">
          <form class="form-signin" role="form" action="validateform.php" method="POST">
                <div id="status">
                </div>
            <h2 class="form-signin-heading">Please sign in</h2>
            <label for="inputEmail" class="sr-only">Email address</label>
            <input type="email" id="inputEmail" value="mycodde@test.com" class="form-control" placeholder="Email address" required autofocus>
            <label for="inputPassword" class="sr-only">Password</label>
            <input type="password" id="inputPassword" value="rashid" class="form-control" placeholder="Password" required>
            <div id="recaptcha1"></div>
            <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
          </form>
      </div>
      <div class="col-md-6">
          <form class="form-signin" role="form" action="validateform.php" method="POST">
                <div id="status">
                </div>
            <h2 class="form-signin-heading">Sign Up Form</h2>
            <label for="inputEmail" class="sr-only">Email address</label>
            <input type="email" id="inputEmail" value="mycodde@test.com" class="form-control" placeholder="Email address" required autofocus>
            <label for="inputPassword" class="sr-only">Password</label>
            <input type="password" id="inputPassword" value="rashid" class="form-control" placeholder="Password" required>
        <div id="recaptcha2"></div>
            <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
          </form>
      </div>
    </div> <!-- /container -->

Javscript Code

    <script src="https://www.google.com/recaptcha/api.js?onload=myCallBack&render=explicit" async defer></script>
    <script>
      var recaptcha1;
      var recaptcha2;
      var myCallBack = function() {
        //Render the recaptcha1 on the element with ID "recaptcha1"
        recaptcha1 = grecaptcha.render('recaptcha1', {
          'sitekey' : '6Lc_0f4SAAAAAF9ZA', //Replace this with your Site key
          'theme' : 'light'
        });
        
        //Render the recaptcha2 on the element with ID "recaptcha2"
        recaptcha2 = grecaptcha.render('recaptcha2', {
          'sitekey' : '6Lc_0f4SAAAAAF9ZA', //Replace this with your Site key
          'theme' : 'dark'
        });
      };
    </script>

Thats it.

Read more…