In this article we’ll walk through building a simple browser app that connects to the Pearson API to access content from the Longman Dictionary of Contemporary English. The simple user interface allows users to lookup words and displays the entries along with any rich media, example sentences or other information that may be available.

Little knowledge is assumed and we will be using basic HTML5, JavaScript and jQuery to access the service and display the results. You should be familiar with HTML and programming, although no in-depth knowledge is assumed.

The Longman Dictionary API

This is one of three APIs currently available from the Pearson Developer website (http://developer.pearson.com). We will only use one of the available methods:

The “search for entries” API provide all of the functionality we need and gives you a good introduction to understanding how the Longman Dictionary API and other Pearson APIs work.

 

jQuery

In simple terms, jQuery is a JavaScript library that dramatically reduces the amount of code we’ll need to write and is used by vast numbers of web developers. It is described on the JQuery website as:

“A fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript.”

 We’ll only be using a small subset of jQuery to invoke the Pearson API and update the web page, so there is no need to be daunted by this powerful and rich library.

 

 Before you can invoke the APIs, you will need a sandbox key, this is automatically issued to you once you have registered on the developer.pearson.com website.

Steps

  1. Go to http://developer.pearson.com/user/register
  2. Fill in your details, agree to the terms and conditions & click register
  3. Verify your account and set a password by clicking on the link in an email that will be sent

Checkpoint

Sign in and navigate to the ‘My APIs’ page, you should see a 16 digit hexadecimal number that is your key (https://developer.pearson.com/sdm/myprofile). In the example bellow I have removed part of my key:

1. Setting up your environment

Before we begin coding let’s setup a minimal development environment, you will need is:

  • a text editor
  • an html5 capable web browser 

I’d recommend using Chrome as it has great built in debugging support, but the code should work fine in the latest release of any web browser (Opera, Firefox, Safari or Internet Explorer, to name but a few). You will also need to download:

The hasAttr plug-in is a very tiny extension to jQuery that makes it easy to test if an attribute is defined, we could have written this function ourselves but since someone else has let’s just reuse their code :)

Steps

  1. Create a folder/directory called ‘ldoce’ on your computer
  2. Go to the webpage: http://code.jquery.com/jquery-1.6.3.js and save the page (File -> Save As, or control-S on most browsers) as ‘jquery.js’ in the ‘ldoce’ folder you created in the previous step.
  3. Download http://plugins.jquery.com/files/hasAttr_0.zip and unzip it into the project folder.

Checkpoint

As shown in the screenshot bellow, your project folder should contain two JavaScript files:

2. Creating the User Interface

First we’ll create a very simple webpage that will serve as the basis for the user interface. All we need is a simple input field, a button and some placeholders that we’ll populate with data from the API. Because the “Search for Entries” method may return more than one entry, the UI needs to be able to display a list of entries as well as just a single entry. 

We’ll HTML5 as it makes including multimedia much easier, but don’t let this put you off it’s all very simple. To hide and show an entry in the result list we’ll use a separate <div> sections and also display a log of events to show how the app is responding to user input etc. 

Steps

  1. Create a file called ldoce.html in your project folder and open it in the editor of your choice.
  2. Enter the following

<!DOCTYPE html>

<head>

       <meta charset="UTF-8">

       <title>Longman Dictionary API</title>

       <script src="jquery.js"></script>         

       <script src="hasAttr.js"></script>

       <script src="app.js"></script>

       <script type="text/javascript">                                        

              $(function() {

                      init()

              })              

       </script>   

 </head>

 <body>

 <article>

       <h1>Longman Dictionary API Example</h1>

       <section id="input">

              <h2>Search</h2>

              <form action="#">

                      <p>Enter a word of phrase to search for:

              <input id="searchText" type=text/>

              <button id="search">Search</button></p>

              </form>

       </section>

       <section id="results">

              <h2>Results</h2>

              <ul id="resultList"></ul>

       </section>

       <section id="debug">

              <h2>Debug Log</h2>

              <p id="log"></p>

       </section>

 </article>

 </body>

  1. Save the modified file

 

The first three <script> elements are used to include JavaScript libraries that our app will use and we’ll create the app.js library shortly. The last <script> element is used to call an initialize function, which is called when the page loads and this will be contained in the app.js library. 

Checkpoint

Open the ldoce.html file in a web browser and you should see something similar to the screenshot bellow:

 

If you are using Chrome, then try showing the developer console (View -> Developer -> JavaScript console) and you will notice that there are two errors, as shown bellow:

 

 

These errors will be fixed in just a moment

3. Initial JavaScript

In order to initialize and setup the UI we’ll need to write a little JavaScript to:

  • Hide parts of the UI.
  • Define a function to be called when the user clicks on the “Lookup entry” button.

Steps

  1. Open your editor and create a new file called app.js in your project directory.
  2. Declare the following global variables, replacing the value of the apiKey variable with your API key.

var apiKey = '10****************************ff';

var baseUrl = 'https://api.pearson.com/longman/dictionary/0.1';

var dataFmt = '.json';

var searchUrl = baseUrl + '/entry' + dataFmt;

var debugLog;

  1. Add the following initialization function to be called when the page loads.

function init(){

       $('#list_div').hide();

       $('#entry_div').hide();

       $('#search').click(function(event){

              event.preventDefault();

              doSearch($('#searchText').val());

       });

       debugLog = $('#log');

}

  1. Add the following search() function, for now we’ll just write a message to the log to show it’s been called and code the call to the API in a moment.

function doSearch(){

debugLog.append('Looking up ' + searchFor + ' using  ' + searchUrl +

'<br/>');

}

  1. Save the file

Checkpoint

Open the ldoce.html file in your web browser, or reload it if it’s still open, and click on the search button. You’ll see a message written bellow the ‘Log’ heading:

 

4. Invoking the API

We’re now ready to invoke the API and where the code starts to get a bit more exciting. The jQuery library function we will use is called ajax which, by default, performs an asynchronous call to invoke a service. When the service is successfully invoked it calls a function to handle the response. It’s also possible to have other functions invoked when an error occurs, but for now we’ll just deal a successful call to the service.

 

Steps

  1. Open the app.js file and modify the search() function to the following:

function doSearch(searchFor){

       debugLog.append('Looking up ' + searchFor + ' using  ' + searchUrl

+ '<br/>');

       var data = 'apikey=' + apiKey + '&q=' + searchFor

       $.ajax({

       type: 'GET',

       url: searchUrl,

       data: data,

       dataType: 'jsonp',

       jsonp: 'jsonp',

       success: function(data){

                      handleResponse(data);

              },

       error: function(req, err, text ) {

              debugLog.append('Error: ' + status + '(' + text + ')<br/>');

              }

       });   

}

This code will invoke the service, and when a successful response is received invoke the handleResponse() function. The type parameter specifies the HTTP method used, our APIs currently only use HTTP GET methods. For a complete description of the parameters see http://api.jquery.com/jQuery.ajax/.

  1. We’ll delegate most of the actual result processing to other methods and in this method deal mostly with the UI. Add the following function to the app.js file:

function handleResponse(data){

       debugLog.append('Response received <br/>');

       var results = data.Entries.Entry;

       var html = entry(results);

       $('#resultList').html(html);

$('li>a').click(function(){                              

 $(this).parent().find("div").toggle(); 

       });

       $('#resultList > li > div').hide();

       $('#resultList > li:first > div').show();

       debugLog.append('Response processed <br/>');

}

The above code passes the results from the API to an entry() method, which will build the html elements which we simply add to the resultList html element. It then adds a onClick() method to each of the entries so each entry can be hidden or shown by clicking on the word. Finally we hide all result list elements and expand the first.

  1. The call to the enty() method above needs to be defined so that it processes the data and we’ll move onto this in the next section. For now we’ll just write a skeleton method and test we can invoke the API. Add the following:

function entry(from){

       html = '<li><a>Dummy Entry 1</a><div>Dummy Details 1</div>';

       html += '<li><a>Dummy Entry 2</a><div>Dummy Details 2</div>';

       return html;

}

Checkpoint

Open, or reload your browser and enter a word (e.g. ‘cat’) and click search. Assuming you have an active Internet connection and a valid API key, you should see the following after a brief delay:

 

If you click on ‘Dummy Entry n’ then the details visibility should toggle.

 

5. Processing the results

The results we get back from invoking the API need to be converted in to html elements so they can be displayed. The Longman Dictionary API returns a very rich and structured dataset, for the purpose of this tutorial we’ll focus on the following elements of the data structure:

  • Sense and subsense – the sense or meaning of an entry
  • Multimedia – images, mp3 pronunciation and example sentences
  • Example – Example sentences

 

 Some words have multiple entries and most entries have multiple senses, multimedia and examples. In order to handle this situation we’ll use a simple bit of recursion depending on whether a single element or an array of elements is returned.

 

Steps

1.     First we need to replace the entry() method we stubbed out on the previous section. The first thing we’ll do is check if we are dealing with an array of entries or a single entry. If it’s an array we’ll simply iterate through the array and invoke the entry() function passing each element from the array. Add the following function to the app.js file:

function entry(from){

       var html = '';

       if ($.isArray(from)){

              for (var idx in from){

                      html += entry(from[idx]);

              }

       } else {

              debugLog.append("Processing Entry: " + from.Head.HWD['#text']

+ '<br/>');

              html += '<li><a>';

              html += from.Head.HWD['#text'];

              html += '</a><div>';

              if ($(from).hasAttr('multimedia')) {

                      html += multimedia(from.multimedia);

              }

              html += '<ol id="sense">';

              html += sense(from.Sense);

              html += '</ol>';

              html += '</div></li>\n';

              debugLog.append("<br/>Processed Entry: " +

from.Head.HWD['#text'] + '<br/>');

       }

       return html;

 }

The else code block builds the html that shows the name of the entry, followed by any multimedia items and finally the meaning(s) of the entries. The multimedia() and sense() functions build the html for these parts of the entry.

 

2.     To parse the multimedia of an entry, or a sense, we take a similar approach. First we see if the multimedia is an array, if it is then the multimedia() function calls itself again with passing each element from the array. The @type attribute of the multimedia element tells us what type of multimedia, to make it more human readable we’ll use a simple switch statement. If the multimedia item is a sound clip we need to use the new html5 <audio> element, whereas a picture can be included using the well known <img> tag. We’ll decide which tag to use based on whether the @href attribute ends in ‘.mp3’. Append the following function to the app.js file:

 

function multimedia(from){

       debugLog.append('multimedia ');

       var html='';

       if ($.isArray(from)) {

              for (var idx in from){

                      html += multimedia(from[idx]);

              }

       } else {

              var mm_href = from['@href'];

              var mm_type = from['@type'];

              if (mm_type =='EXA_PRON'){

                     mm_type ='';

              }

              switch (mm_type){

                      case 'EX_PRON':

                             mm_type = '';

                             break;

                      case 'US_PRON':

                             mm_type = 'American pronunciation';

                             break;

                      case 'GB_PRON':

                             mm_type = 'British pronunciation';

                             break;

                      case 'SOUND_EFFECTS':

                             mm_type = 'Sound effect';

                             break;

              }

              if (mm_href.match(/\.mp3$/)) {

                      html = mm_type + ' <audio controls="controls"> +

'<source src="' + baseUrl + mm_href + '?apikey=' + apiKey +'" type="audio/mpeg"/> </audio>';

              } else if (mm_type == 'DVD_PICTURES') {

                      html = '<img src="' + baseUrl + mm_href + '?apikey='

+ apiKey +'"> </img>';

              }

              html += '<br/>';

       }

       return html;

}

 

3.     Next we need to extract the sense, or meaning, of the entry. This is contained in the sense element for a given entry. Again an entry may have more than one sense and a sense can be a composition of subsenses. Senses and subsenses are structurally very similar and both can have examples associated with them. The following code extracts the meaning and handles subsenses and examples, append the following to the app.js file:

 

function sense(from){

       debugLog.append('sense ');

       var html='';

       if ($.isArray(from)) {

              for (var idx in from){

                      html += sense(from[idx]);

              }

       } else if ($(from).hasAttr('Subsense')) {

              html += sense(from.Subsense);

       } else {

              html += '<li>' + text(from.DEF) + '<br/>';

              if ($(from).hasAttr('EXAMPLE')){

                      html += example(from.EXAMPLE);

              } else if ($(from).hasAttr('LEXUNIT')){

                      html += example(from.LEXUNIT);

              }

              html += '</li>';

       }

       return html;

}

 

4.     Extracting examples, potentially containing multimedia items is relatively simple and follows the same pattern as all the other functions so far. Append the following function to the app.js file:

function example(from){

       debugLog.append('example ');

       var html ='';

       if ($.isArray(from)){

              for (var idx in from){

                      html+= example(from[idx]);

              }

       } else {

              html += '<q>' + text(from) + '</q>';

              if ($(from).hasAttr('multimedia')){

                      html += multimedia(from.multimedia);

              }

       }

       return html;

}

5.     You may have notices in all the above code that we call a text() function at various times. The reason for this is that the actual text associated with an element can be arrays of text that contain other entries or be paired with (colligated) other words. As such extracting the text to display takes a little more work. Add the following code to extract the text associated with an element to the app.js file:

 

function text(from){

       debugLog.append('text ');

       var result = '';

       var text = from['#text'];

       var nonDv;

       var hasNonDv = $(from).hasAttr('NonDV');

       if ($.isArray(text)){

              for (var idx in text) {

                      result += text[idx];

                      if (hasNonDv){

                             nonDv = from.NonDV[idx];

                             if (nonDv != undefined){

                                    result += nonDv.REFHWD['#text'];

                             }

                      }

              }

       } else {

              result += text;

              if (hasNonDv){

                      result += from.NonDV.REFHWD['#text'];

              } else if ($(from).hasAttr('COLLOINEXA')){

                      result += from.COLLOINEXA['#text'];

              }

       }

       return result;

}

 

6.     Save the file, we are done J

 

Checkpoint

We have finished the app, so when you enter a word you should be presented with a list of one of more entries from the Longman Dictionary of Contemporary English. Remember if you are using a sandbox key you can only find entries that begin with the letters a, b, c. For example, if you lookup ‘cat’ you should get a page similar to the one bellow:

 

Summary

In this article, we’ve taken a brief look at just one of the APIs available for the Longman Dictionary of Contemporary English available from Pearson PLC. We’ve seen how using jQuery can make invoking the API very simple and how to navigate the structure returned by the API and present the results in a simple html page.

If you have any questions or comments about this tutorial, please append them to this forum post. 

Many thanks

 

Dan
30/04/2012 13:23:03

Hi, the code can be downloaded from https://github.com/PearsonAPI/Dictionary-Web-App
Thanks

ziaur18
03/04/2012 05:11:32

I am using it on simulator and getting error Failed to load resource: Proxy requires authentication in json.entry.please help me.