0

I am pulling stock symbols from Yahoo finance in a json object and I am trying to show them as a drop-down menu while the user starts typing the name of the company or the symbol in the search box . Typeahead is not working as a drop down menu from the search box. I think I am doing everything right.This is the code I have so far. Any help is appreciated.

quote.js

$(document).ready(function() {

  // create autocomplete
  $('#form-quote input[name=symbol]').typeahead({

      // load autocomplete data from suggest.php
      source: function(query, callback) {
          $.ajax({
              url: '../suggest.php',
              type: 'POST',
              dataType: 'json',
              data: {
                  symbol: query
              },
              success: function(response) {
                  callback(response.symbols);

              }
          });
      }
  });

  // load data via ajax when form is submitted
  $('#form-quote').on('click', function() {

      // determine symbol
      var symbol = $('#form-quote input[name=symbol]').val();

      // send request to quote.php
      $.ajax({
          url: 'quote.php',
          type: 'POST',
          data: {
              symbol: symbol
          },
          success: function(response) {
              $('#price').text(response);
          }
      });


      return false;
  });

});

quote.php

<?php

//configuration
require("../includes/config.php");

//if form was submitted 

if($_SERVER["REQUEST_METHOD"] == "POST"){

    $stock = lookup(strtoupper($_POST["symbol"]));

    if(empty($_POST["symbol"])){

        //echo "You must enter a stock symbol";

    }else if($_POST["symbol"]){

    $price = number_format($stock['price'], 2);

    echo "A share of {$stock['name']} costs $$price";
    }
}

else{

    // render portfolio
render("stock_search.php", ["title" => "Get Quote"]);
}   
?>

quote_search.php

<form id = "form-quote" action="quote.php" method="post">
<fieldset>     
    <div class="control-group">
        <input name="symbol" autofocus autocomplete="off"  placeholder="Symbol"  type="text"/>
    </div>

    <div class="control-group">
        <button type="submit" class="btn">Get Quote</button>
    </div>

</fieldset>
<div id="price"></div>
<div id="suggestions"></div> 
</form>
<script type="text/javascript" src="js/quote.js" ></script>

suggest.php

 <?php

// configuration
require("../includes/functions.php");

// if form was submitted
if ($_SERVER["REQUEST_METHOD"] == "POST")
{
    // load suggestion data
$data = @file_get_contents("http://d.yimg.com/aq/autoc?query=  {$_POST['symbol']}&region=US&lang=en-US&callback=YAHOO.util.ScriptNodeDataSource.callbacks");

    // parse yahoo data into a list of symbols
$result = [];
    $json = json_decode(substr($data, strlen('YAHOO.util.ScriptNodeDataSource.callbacks('), -1));
    foreach ($json->ResultSet->Result as $stock)
        $result[] = $stock;

    echo json_encode(['symbols' => $result]);
}

?>
tironci
  • 217
  • 1
  • 5
  • 18

4 Answers4

1

Typeahead takes only an array of strings as a source

  // i.e.
  ["INTC", "GOOG", "FB", /* etc */]

What your script does is create an array of the whole objects that Yahoo returns

  // i.e.
  [
    {"symbol":"INTC","name": "Intel Corporation","exch": "NMS","type": "S","exchDisp":"NASDAQ","typeDisp":"Equity"},
    {"symbol":"INTC.MX","name": "Intel Corporation","exch": "MEX","type": "S","exchDisp":"Mexico","typeDisp":"Equity"},
    /* etc */
  ]

What you need to do is change your suggest.php so that the line:

foreach ($json->ResultSet->Result as $stock)
        $result[] = $stock;

becomes for exmaple:

foreach ($json->ResultSet->Result as $stock)
        $result[] = '('.$stock->symbol.') '.$stock->name;
Tsanyo Tsanev
  • 1,159
  • 8
  • 11
  • This works great. Thank you. One more question. How would I get just the symbol of the selected value in order to pass it to the lookup function. I have this `var symbol = $('#form-quote input[name=symbol]').val();` but it gets the whole thing symbol plus company name. – tironci Apr 06 '13 at 21:14
  • 1
    Well there are a few ways. You can return an object instead of an array, and in the JS function you can convert it to an array, and use the original object to look-up the value later. This is the more complex way. The easy way would be to follow a "pattern" in the values like **"(symbol) name"** and than you can just match the symbol like `var symbol = new String($('#form-quote input[name="symbol"]').val())replace(/^\(\s*([A-z0-9\.\-]+)\s*\).*$/gi, '$1');` This code would get only the symbol (whatever is the parentheses) from the string. – Tsanyo Tsanev Apr 08 '13 at 20:01
  • Thank you. What I did was remove the parentheses an get the first word up to the first space. I will give this a try too just to see how it work. – tironci Apr 08 '13 at 23:43
0

Try to add full path of your URL in Ajax like this localhost/app/user/suggest.php

0

Make sure you set the "Content-type" to json before you respond with json_encode.

header("Content-type: application/json");
ceejayoz
  • 165,698
  • 38
  • 268
  • 341
Raphael Caixeta
  • 7,596
  • 9
  • 47
  • 76
  • application/json, not text/json. http://stackoverflow.com/questions/477816/what-is-the-correct-json-content-type – ceejayoz Apr 01 '13 at 13:49
  • I added 'header("Content-type: application/json");' just before the line that says 'echo json_encode(['symbols' => $result]);' and still it won't work. – tironci Apr 01 '13 at 16:05
  • @tironci you have to add before any response, not just before the line. – Raphael Caixeta Apr 01 '13 at 16:11
  • I also added it to the beginning of the suggest.php page and it still doesn't work. – tironci Apr 01 '13 at 16:24
  • If I create another file with an array of all the stocks it works, I do get the drop-down menu. I want to also mention that I am using fedora. – tironci Apr 01 '13 at 16:54
0

Silly question but the json result you are expecting, does this comeback properly even when taking typeahead out of the equation? Because the value passed to file_get_contents might be botched a bit unless that formatting bombed while pasting here.

Myke Bates
  • 99
  • 1
  • 4