Saturday, November 25, 2017

Enable NTFS with No Softwares [Natively] Mac High Sierra 10.13.1 (17B48)

Mac by default disabled the NTFS write support. I am using MacBook Pro 2016 with TouchBar 15 inch.

I updated the Mac with most recent version of OS Mac High Sierra 10.13.1 (17B48).

In this Article I am sharing my experience on How i successfully Enabled NTFS write support natively.

I have a Western Digital HDD (External) with 3 Partitions.

First I renamed the Drive without spaces

WD Drive 1 to Drive1

WD Drive 2 to Drive2

WD Drive 3 to Drive3

Open Terminal

Open spotlight and search for Terminal

then write the following command on the terminal


$ sudo vim /etc/fstab


Write the following where Drive3 is my drive name (Label)

LABEL=Drive3 none ntfs rw,auto,nobrowse

You are done.

Incase if your drive is already connected to computer, then Eject the drive and reconnect it.


You wont see the change anywhere. Just follow the instructions now

Open Finder and choose Go-> Go to Folder

Enter

/Volumes

Now this Drive3 is writable

You can also confirm it by Right click and choose Get Info on the Drive3. It will show "This drive is Writable"



How to Create a Shortcut of Volumes Folder to Desktop

Issue the following command on the Terminal which will create a shortcut to /Volumes Folder


sudo ln -s /Volumes ~/Desktop/Volumes



If you want the Finder Left Side bar to have the /Volumes directory then do the following

Open Your Macintosh HD drive which is (~/)


Then Press Command Shift Dot  ( Command Key + Shift Key + . (Dot Key) ) it will show the hidden files in the above directory


Now drag and drop the Volumes folder to the Left sidebar of Finder





Read more…

Wednesday, November 9, 2016

Laravel in Shared Hosting - Complete Guide

Once you done with development in your local you might move the code to your hosting.
If it is shared hosting your entire laravel behaves differently than what you see in your local development machine.

Problems with Modifying .htaccess and removing public from URL
Simply because of the Security issues. Do you want to know how how many websites are vulnurable and Credentials are public?

https://www.google.com/search?q=intext%3ADB_PASSWORD+ext%3Aenv&gws_rd=ssl

Don't be part of it. Protect your .env file by maintaining the existing laravel 5.3 folder structure.

Removing /public from Laravel 5.3

First question is why you want to remove. Laravel works very well with its existing structure. Do not follow any techniques to remove the .htacess and server.php file (Server.php is not available in laravel 5.3)

All you need to do is modify the document root in your Shared hosting.

I use cPanel for this tutorial.



But if you already created a domain, you can modify its document root path easily.


Edit the Subdomain or Addon domain you need.



Add /public to the end of the URL to support Laravel existing folder structure

Now try to access your .env file it is not accessible for public.

Happy Laravel Coding.

Read more…

Saturday, October 15, 2016

Facebook Accountkit Login using Mobile SMS - Javascript

Facebook's latest AccountKit is a notable feature. It allows you to integrate it on your website, so that you don't need to worry about login using mobile feature, they will handle the Authentication for you.

To put in simple words, Login using Mobile. Enter SMS code. User Verified.

How to integrate AccountKit in your website

Step 1: Get the App ID, and Token from the Facebook Developer portal.

( We are Going to discuss the integration for Web only [Not Android nor iOS] )

AccountKit App Secret and APP ID Created. Here is how to see them.


Step 2: You can follow the simple introductions at this page or download the sample code I developed to start with.

Basically three things needed.

First

<!-- HTTPS required. HTTP will give a 403 forbidden response -->
<script src="https://sdk.accountkit.com/en_US/sdk.js"></script>

Second

Enter country code (e.g. +1):
<input type="text" id="country_code" />
Enter phone number without spaces (e.g. 444555666):
<input type="text" id="phone_num"/>
<button onclick="phone_btn_onclick();">Login via SMS</button>
Enter email address
<input type="text" id="email"/>
<button onclick="email_btn_onclick();">Login via Email</button>

Third

<script>
  // initialize Account Kit with CSRF protection
  AccountKit_OnInteractive = function(){
    AccountKit.init(
      {
        appId:{{FACEBOOK_APP_ID}}, 
        state:"{{csrf}}", 
        version:"{{ACCOUNT_KIT_API_VERSION}}"
      }
    );
  };

  // login callback
  function loginCallback(response) {
    console.log(response);
    if (response.status === "PARTIALLY_AUTHENTICATED") {
      document.getElementById("code").value = response.code;
      document.getElementById("csrf_nonce").value = response.state;
      document.getElementById("my_form").submit();
    }
    else if (response.status === "NOT_AUTHENTICATED") {
      // handle authentication failure
    }
    else if (response.status === "BAD_PARAMS") {
      // handle bad parameters
    }
  }

  // phone form submission handler
  function phone_btn_onclick() {
    var country_code = document.getElementById("country_code").value;
    var ph_num = document.getElementById("phone_num").value;
    AccountKit.login('PHONE', 
      {countryCode: country_code, phoneNumber: ph_num}, // will use default values if this is not specified
      loginCallback);
  }


  // email form submission handler
  function email_btn_onclick() {
    var email_address = document.getElementById("email").value;

    AccountKit.login('EMAIL', {emailAddress: email_address}, loginCallback);
  }

</script>

In My Sample code / Above code you basically need to change

{{csrf}} - ANY Alphanumeric characters. eg: 322323nn2j32jn32jn3
{{ACCOUNT_KIT_API_VERSION}} : v1.0 

You can find the version of accountkit in the above screenshot with APP ID.

The Above Code has two functionalities.

  • Login using SMS
  • Login using Email 


You can remove the login using email button and the function email_btn_onclick()  if not needed. We are focusing on Login using SMS in this Article.

If You run the above code you might experience couple of issues.

1)  Status : BAD_PARAMS
Bad Params error with Account kit.

To see the more details about the error, enable the debug mode as shown in the picture below. debug:true

Debug Mode True for Account kit to see more error info
Now you should see the following if you reexecute the code after a refresh.

2)  Status : NOT_AUTHENTICATED

Not Authenticated Error when debug mode is turned on


If you still getting BAD_PARAMS error, you need to Upload the AccountKit code in your website and add the URL in to the box as shown below.

Add the Website URL where this AccountKit Code is used.
If you are getting this following error, it means the Facebook App configuration is wrong.

{
    error: {
        message: "Error verifying the token in the 'access_token'",
        type: "OAuthException",
        code: 190,
        fbtrace_id: "GNhScPPp22t"
    }
}

To Fix this:
Open your App in facebook developers console.


Enable the Above settings.

Please Note: There is different App Secret if you are using AccountKit. (Correct App Secret is shown below)






Whitelist the URLs from where you are accessing (as shown below)




Hope you received a Authorization Code as shown below



See the {code:.....}
Code is Authorization code, which you need to send to facebook along with APPID and APP Secret to get the AccessToken.

<?php
 $ch = curl_init();
  // Set url elements
  $fb_app_id = '1777284542513521';
  $ak_secret = '0d0be3327a004c29334488cc5c45ffe9';
  $token = 'AA|'.$fb_app_id.'|'.$ak_secret;
  $code = "AQBCk7Fr9RN0st1bvAQIdm8v4OH2phrjn__J2fF0QAtIMAB3stLioGh1XrEV3jqych842LlJkHzJkzTZ3zlLZYZaqJ3UX-piWJEqGeF_4JnhQwVVRp38zzeLRn0cLKgMy1WH6CO0KLnsUCWsHNL4SGEEfSRIoZ6QqoDXcYAVowWlfrKLPw-HMjJwi7d8BorNwpxwg9LVWWcmu5p69xGI3-MZhHEFnAsrT1wWCQw4T9YWhWdP3ubtpHsR0XpOChJfI3Xf_TRYVoLd3K_3JQ3knRiT";
  // Get access token
  $url = 'https://graph.accountkit.com/v1.0/access_token?grant_type=authorization_code&code='.$code.'&access_token='.$token;
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_URL,$url);
  $result=curl_exec($ch);
  curl_close($ch);
  $info = json_decode($result);

print_r($info);

?>

Now you should see the following Output



You successfully received the Access Token


Possible errors here 

stdClass Object
(
    [error] => stdClass Object
        (
            [message] => This authorization code has expired.
            [type] => OAuthException
            [code] => 100
            [fbtrace_id] => BDBlNw9ptK6
        )

)
This means the Authorization Code has expired, you need to regerate new Authorization Code with Above SMS verification process. (Enter Phone, Verify SMS and so..)


Now to retrieve the details of this user

<?php
$access_token = "EMAWdkiDW3MPrLKKAF5Lc0IeXP2qFp4OoZBEwAHgrOavmRl2XgiCMuYySr3cZD";
$app_secret      = "0d0bXXXXXXXXXXXXXc5c45ffe9";
// Get account information
$appsecret_proof = hash_hmac('sha256', $access_token, $app_secret);

$url = 'https://graph.accountkit.com/v1.0/me/?access_token=' . $access_token . 
'&appsecret_proof=' . $appsecret_proof;

echo $url; //View this URL you will get the Following data

?>



Hope, Now it is working.
If you are still facing any issues, comment here, I will help you.

Read more…

Sunday, May 8, 2016

Magento2 Simple Hello World Extension helloworld.zip

Magento2 comes up with little changes as shown in following picture.

Magento 1 to 1.9 vs Magento2 differences.
Source: venustheme.com

From the tutorial here I have created a HelloWorld magento2 Module.

Everytime you develop an app, you can use this app as template or a starter app.

How to install this Sample Starter App in your machine

I am using Ubuntu with magento2. PHP 5.9 and all modules required during Magento2 Install.

Download Magento2 the Sample Extension

If you have the magento2 installed here /var/www/html/magento2

Then copy the extracted file into
/var/www/html/magento2/app/code




Make sure the /var/www/html/magento2/var directory has 777 Permission.

sudo chmod 777 -R /var/www/html/magento2/var

To Install the Magento2 Helloworld Extension run the following command in terminal

sudo php bin/magento setup:upgrade

OR

you can manually to it. Open /var/www/html/magento2/app/etc/config.php

Add 'Ras_HelloWorld' => 1,  line at the end.



Now Point your browser to this URL http://localhost/magento2/helloworld/index/index

Read the tutorial here

To Disable a Plugin

sudo php bin/magento module:disable -c -f Ras_HelloWord

Read more…

Monday, April 25, 2016

How to use PHP SoapClient TLS Request - Advanced Tutorial

Basics
To start with PHPSoap you need a WSDL (Web Service Definition Language) file. Its an XML file looks like following.

WSDL XML File Sample Structure
Unlike REST api, SOAP uses XML file structure.

This article will focus on

  1. How to start with PHP SoapClient
  2. Using SoapUI
  3. Sending First SOAP request
  4. Sending TLS Request with PHP SoapClient

1. Using SoapUI

(Consider You are Developer and you have a Hosting A and you are trying to integrate a ThirdParty Service)

WSDL file (created by ThirdParty) should always be hosted in a publicly accessible URL. Some time WSDL file will be splitted into two, one is hosted locally (Hosting A) and another one will be kept with ThirdParty Service.

For this example I used the WSDL file from here. (Thanks TutorialsPoint)

I hosted it here for your convenience http://code.educationgovt.com/wsdl/sample.wsdl

Step 1: Install SoapUI and Open it.
Step 2: Click File -> New Soap Project   or Ctrl+N. When you click ok, it will load the file.
New SoapUI Project
Step 3: See the Projects Pane. The Requests in the WSDL file are listed here. Right click, Double click and see the available options. It will clear most of your basic Doubts.

Step 4: Double click on Request 1 it will open the Request Pane. It has two sections as shown below. Request and Response (Right Column).

SoapUI Sending Request and Process the Response
Step 5: Click the Green Play button in the top of Request window. It says "Submit request to specific endpoint URL".
You should see the response in the Right column. In this Example, you should see a 404 page .

In the Production WSDL definitions file, this Request pane will create a Request for you.

Soap Request with paramets

<firstName xsi:type="xsd:string">?</firstName>

SoapUI will put ?  for the parameters you need to pass.
Here firstName is expecting a String.

It can be any complex WSDL definition, you just open the SoapUI and Do above, you will see the Request and Variables you need to pass.

I hope i covered a basic understanding you need to start with Soap.

Example 2: use http://www.webservicex.net/globalweather.asmx?WSDL


Simple Soap Response Successful 


2. How to start with PHP SoapClient

PHP Provides a SoapClient class to do the above through php code.

<?php 

//Create the client object
$soapclient = new SoapClient('http://www.webservicex.net/globalweather.asmx?WSDL');

//Use the functions of the client, the params of the function are in 
$params = array('CountryName' => 'India');
$response = $soapclient->GetCitiesByCountry($params);
print_r($response);

If you cannot see complete response, View Source in browser or var_dump

You can do the above in many ways.

<?php 

//Create the client object
$soapclient = new SoapClient('http://www.webservicex.net/globalweather.asmx?WSDL');

//Use the functions of the client, the params of the function are in 
$params = array('CountryName' => 'India');
$response = $soapclient->__soapCall('GetCitiesByCountry', array($params));
print_r($response);

Produces the same above output. Here we have called __soapCall a low level method from SoapClient Class.

Code explanation:
We created the SoapClient object from SoapClient() class. Using that we send the request parameters to the particulat Soap Request Method.

The Basic SoapClient usage is explained here.

3. Advanced Soap Request in PHP

Project like bank B2B and other Transaction related services will usually have a complex SOAP request. 

Start Looking at the functions provided by SoapClient class http://php.net/manual/en/class.soapclient.php

Consider you have a WSDL file, how to know what is the Request End point?
If the Service Provider doesn't provide you document, you can follow below methods to find the Service End point (Request URL's).

Method 1: (Recommended)
In SOAPUI you can see the Service End points. If you double click on request you will see the required parameters for every request.

Soap Service End Points 
Method 2:
Use the following code to list all the available functions inside the WSDL. It list all the functions.

$soapclient->__getFunctions()

Simple Request with Certificate

<?php 
$wsdl = "someURL-with.wsdl";
$local_cert = "YourDirectory\ClientKeyAndCer.pem";

$soapclient = new SoapClient($wsdl, array('local_cert' => $local_cert));

$theResponse = $soapclient->test();

Request with Certificate and Other Parameters

<?php 
$wsdl = "someURL-with.wsdl";
$local_cert = "YourDirectory\ClientKeyAndCer.pem";

$soapclient = new SoapClient($wsdl,array(
        "trace"         => 1, 
        "exceptions"    => true, 
        "local_cert"    => $local_cert, 
        "uri"           => "urn:xmethods-delayed-quotes",
        "style"         => SOAP_RPC,
        "use"           => SOAP_ENCODED,
        "soap_version"  => SOAP_1_2 ,
        "location"      => $this->location
    ));

Using PHP Soap for Request with Certificate and Private Key

PHP SoapClient is limited with functionalities. You can attach a Certificate with SoapClient Request if needed. But Private key cannot be send.

To handle these situation you need to create your own class extending SoapClient functionality.

Creating your Own Soap Class to handle Custom Request
<?php 
class Myclass extends SoapClient{
    
    function __construct($wsdl, $options = null) {
        parent::__construct($wsdl, $options);
    }
    
    function __doRequest($request, $location, $action, $version) {
        return parent::__doRequest($request, $location, $action, $version);        
    }
    
}
Print the parameters and see the individual data like URL, and $request.

If you see the PHP SoapClient Functionality, it actually sends the formatted XML string (same like the ones created through SoapUI) with parameters filled.

Following line is the one which handles the Network Data Transport from You to Other Server.

parent::__doRequest()

Replace this code with cURL or any other code which handles your own Data transport mechanism.

Example 2:

<?php

define('WSDL_URL', 'http://www.webservicex.com/CurrencyConvertor.asmx?wsdl');

class MyOwnSOAPClient extends SoapClient {

    //Required variables
    public $url = "";

    function __construct($wsdl, $options = null) {
        parent::__construct($wsdl, $options);
    }

    function __doRequest($request, $location, $action, $version) {
        $requestDOM = new DOMDocument('1.0');
        $soapHeaderDOM = new DOMDocument('1.0');

        try {
            $requestDOM->loadXML($request);
            $request = $requestDOM->saveXML();
        } catch (DOMException $e) {
            die('Error adding UsernameToken: ' . $e->code);
        }
        return parent::__doRequest($request, $location, $action, $version);
    }

}

    $soapClient = new MyOwnSOAPClient(WSDL_URL, array());
    $ConversionRateObj = new stdClass();
    $ConversionRateObj->FromCurrency = "USD";
    $ConversionRateObj->ToCurrency = "INR";
//    print_r($soapClient->__getFunctions());
    $reply = $soapClient->ConversionRate($ConversionRateObj);
    print_r($reply);


Read more…

Monday, April 20, 2015

Deleting Codeigniter Webpage Cache

Codeigniter Output class provides a way to create HTML cache of the view files loaded through controller.

eg: If the url is example.com/CONTROLLER/FUNCTION23

To cache the view loaded by FUNCTION23, use following code inside FUNCTION23

$this->output->cache(50);
50 in above cache function is 50 minute. Cached file is stored here application/cache. 

How to delete this cache file

$this->output->delete_cache('controller/function22');

Make sure you don't include any slash before or after, because the path is MD5 Encoded.

Delete cache when using custom routing

Consider a case, where you are using custom routing (config/routes.php) for a page, when a user requested URL is

http://www.example.com/CONTROLLER/FUNCTION100 

and you are routing it to a different controller/function200.

To Delete this cached file you need to do as follows

$this->output->delete_cache('controller/function200');

How to delete the home page landing page url

If you are setting routes.php $route['default_controller'] = 'MyController/MyHomePage' which will be shown to user when he enter example.com

Add the following code to system\core\Output.php of codeigniter

    public function delete_cache_path($uri = '')
    {
        $CI =& get_instance();
        $cache_path = $CI->config->item('cache_path');
        if ($cache_path === '')
        {
            $cache_path = APPPATH.'cache/';
        }

        if ( ! is_dir($cache_path))
        {
            log_message('error', 'Unable to find cache path: '.$cache_path);
            return FALSE;
        }

        $cache_path .= md5($uri);

        if ( ! @unlink($cache_path))
        {
            log_message('error', 'Unable to delete cache file for '.$uri);
            return FALSE;
        }

        return TRUE;
    }




Hope this helps.

Read more…

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…