Bootstrap3 and typeahead and remote results from a Neo4j database with php

Bootstrap3 and typeahead and remote results from a Neo4j database with php

  • @Tsartsaris

    Posted on 2014-01-30

    ​​Let's see how we can combine Bootstrap3, typeahead.js, php and Neo4j to create a live search feature. Follow the links to download the necessary libraries  if you haven't done so. To load into our page typeahead and work without any problems this has to be done after we load the jquery library, so at the end of your page you have to do the following

       <script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
        <script src="./js/bootstrap.min.js"></script>
        <script src="./js/typeahead.js"></script>
    After that we need a text input box so we can write and search on the fly. Add somewhere in your page the following
        <input type="text" class="form-control" id="searchposts">
    The key element here is the ID we use since by this ID we will bind later typeahead with this text input. To do that we will add a <script> tag at the end of the page and after the  <script src="./js/typeahead.js"></script>.
        <script type="text/javascript">
        $(document).ready(function() {
        $('#searchposts').typeahead({
            name: 'searchposts',
            remote: './result.php?query=%QUERY',
            minLength: 3, // send AJAX request only after user type in at least 3 characters
            limit: 10 // limit to show only 10 results
        }).on('typeahead:selected', function (obj, datum) {
            window.location = "./"+datum.value;
        });
        });
        </script>
    Let's brake down the above script and see what exactly we are doing with this.
    • First we say typeahead where we are typing $('#searchposts').
    • Next we say that we want to fetch remote data from a page called "result.php" and we send at this page with AJAX the query variable "%QUERY" which at any time will be what we type in the text input we added.
    • The next two lines are some limitations we set to limit our results (play with the values to see different results).
    • Last we bind a function on the "typeahead.selected" event and this is to open a new page with the value selected from the drop down results. We can access this value by adding the datum.value.
    Let's examine our php page that will handle the request for search of the QUERY variable.
        <?php
        require("phar://neo4jphp.phar");
        $client = new Everyman\Neo4j\Client('127.0.0.1', 7474);
        $results = array();
        $query = $_GET['query'];
        $queryString = "MATCH (n) WHERE n.name =~ '(?i).*$query.*' RETURN n";
        $query1 = new Everyman\Neo4j\Cypher\Query($client, $queryString);
        $result = $query1->getResultSet();
        foreach ($result as $row) {
        $result = $row['X']->getProperty('title');
        $results[] = $result;
        }
        return json_encode($results);
        ?>
    • First two lines are to connect to our Neo4j database. We need an array to put in the results and turn it to a Json object that typeahead can accept and read. This array is the third line. A variable to store our get value which we will use to search in our database. And the Cypher query to search in our database.
    • MATCH (n) will match all nodes in our database. To limit our results here if we use labels and we want to search in specific nodes only, this can be like MATCH (n:User) or whatever label you want to use.
    • WHERE n.name= This is the property in which values we search for a match of our GET variable. Whatever we type in the input text box will be searched within this property. You can define your own property based on your database schema setup ex. n.title etc.
    • ~ '(?i).*$query.*' and here is the magic part of our cypher query. We use ~ "regex" to define a regular expression to match our results. If we replace regex with Tsartsaris  ~ 'Tsartsaris' then the query will match all our records in our database with n.name = Tsartsaris .Adding the .* at the end and the start of our regex the search will be done by matching our search variable with whatever comes before and after it, so ~ '.*tsa.*' will return Tsartsaris but also will return if exists batsafos etc. To make our search case insensitive we add to our regex (?i).
    • Next thing we do is to take our results, iterate through them and add the match to our array.
    • Finally we return the json_encode of this array that will be used by typeahead to display our results.
    That is it. We now have a full working typeahead live search feature by searching withing our Neo4j database. There will be some problems with the way results are visible in our page due to latest changes on Bootstrap and typeahead.
    First problem can be with a double word on the input text like the photo below.

    Image title

    To solve this we can add a line after our script to add a class of form-control to our tt-hint like this

        $('.tt-hint').addClass('form-control');

    Another problem we might get is our results to have no style at all like the photo below.

    Image titleto solve this we can add to our CSS file some styling for the dropdown results like so

        .twitter-typeahead .tt-query,
        .twitter-typeahead .tt-hint {
          margin-bottom: 0;
        }
        .tt-dropdown-menu {
          min-width: 160px;
          margin-top: 2px;
          padding: 5px 0;
          background-color: #fff;
          border: 1px solid #ccc;
          border: 1px solid rgba(0,0,0,.2);
          *border-right-width: 2px;
          *border-bottom-width: 2px;
          -webkit-border-radius: 6px;
             -moz-border-radius: 6px;
                  border-radius: 6px;
          -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);
          -webkit-background-clip: padding-box;
             -moz-background-clip: padding;
                  background-clip: padding-box;
        }
        .tt-suggestion {
          display: block;
          padding: 3px 10px;
        }
        .tt-suggestion.tt-is-under-cursor {
          color: #ffffff;
          background-color: #0081c2;
          background-image: -moz-linear-gradient(top, #C2DFEE, #8EC1DA);
          background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#C2DFEE), to(#8EC1DA));
          background-image: -webkit-linear-gradient(top, #C2DFEE, #8EC1DA);
          background-image: -o-linear-gradient(top, #C2DFEE, #8EC1DA);
          background-image: linear-gradient(to bottom, #C2DFEE, #8EC1DA);
          background-repeat: repeat-x;
          filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0)
        }
        .tt-suggestion.tt-is-under-cursor a {
          color: #fff;
        }
        .tt-suggestion p {
          margin: 0;
        }
        .tt-suggestion.tt-is-under-cursor a:hover{
        color: white;
        };

    And we are done. You have a full feature working live search based on typeahead, Bootstrap3 and Neo4j. You can find all working files in tar.gzip to play with here.

Tag-cloud

webNeo4Jphpd3jsubuntuworkcypherinternetbootstrapdevelopmentflaskpython

Social Me!

Twitter Logo LinkedIn Logo Google+ Logo Tumblr Logo