Sort Your Data Using Javascript

Introduction

Javascript has basic sorting built into the language, but it also has the flexibility to do any kind of sorting you want. Read on and find out more about how you can customize your sorting tasks with Javascript.

Basic sorting

The Javascript array sort method performs an alphabetic sort of an array. Here are some examples:

[cc lang=”javascript”]
var wordList = new Array( “red”, “green”, “blue”);
wordList.sort();
[/cc]

Printing wordList gives the list {“blue, “green”, “red”} (see Example 1 web page).

[cc lang=”javascript”]
var wordList2 = new Array(“tiger”, “cat”, “dog”);
wordList2.sort();
[/cc]

Printing wordList2 gives the list “cat”, “dog”, “tiger” (see Example 2 web page).

Sorting using comparison functions

To perform sorting of an array using some other method besides alphabetical sorting, a comparison function must be passed to the sort method. This function can be included in the sort method as an unnamed function, or it can be a separate named function which can be called by the sort method. Here is an example of a template for a separate function:

[cc lang=”javascript”]
function numberTest (a, b) {

}
var numberList = {5, 4444, 333, 22222, 11};

numberList.sort(numberTest);
[/cc]

The sort method calls the function numberTest, working through all of the elements in the array. The arguments a and b in the function represent two elements in the array. The body of the function should return one of three values:

1. a goes before b = return a negative number
2. a goes after b = return a positive number
3. a is the same as b = return a zero

A simple comparison function for a numeric sort would be:

[cc lang=”javascript”]
function numberTest (a, b) {
return a – b;
}
[/cc]

This function will perform a numeric sort in increasing order. Printing the numberList array after sorting will display the following:

5 11 333 4444 22222 (see Example 3 web page).

To perform a numeric sort in decreasing order, the line within the function should be changed to the following:

[cc lang=”javascript”]
return b – a;
[/cc]

Printing the numberList array after sorting will display the following:

22222 4444 3333 11 5 (see Example 4 web page).

To perform a reverse alphabetic sort, the comparison function must explicitly return a -1, 0, or 1 depending on the alphabetic order. Returning the value of the direct comparison as for numeric sorting will not work. An example comparison function is shown below:

[cc lang=”javascript”]
function reverseAlphabeticTest(a, b) {
if (a < b) return 1; if (a > b) return -1;
return 0;
}
[/cc]

(see Example 5 web page).

Sorting lists of objects

Next, let us examine sorting an array of objects, where each object has two fields. A set of objects could be as follows:

[cc lang=”javascript”]
var testObject1 = {item: 5, note: “aaa”};
var testObject2 = {item: 4, note: “bbb”};
var testObject3 = {item: 3, note: “ccc”};
var testObject4 = {item: 2, note: “ddd”};
var testObject5 = {item: 1, note: “eee”};
[/cc]

These object can then be added to an array as follows:

[cc lang=”javascript”]
var testArray = new Array(); // Create a test array

// Add objects to testArray
testArray[testArray.length] = testObject1;
testArray[testArray.length] = testObject2;
testArray[testArray.length] = testObject3;
testArray[testArray.length] = testObject4;
testArray[testArray.length] = testObject5;
[/cc]

where the length property of the array is used as the index (it increases as more objects are added to the array).

The numeric sort comparison function used for examples 3 and 4 can be reused for sorting on any field in the object, but the field must be specified using a dot structure as shown below:

[cc lang=”javascript”]
function compareItems (a, b) {
return a.item – b.item;
}
testArray.sort(compareItems);
[/cc]

Printing the list of items and notes in the array after sorting gives the following:

Items: 1 2 3 4 5
Notes: eee ddd ccc bbb aaa
(see Example 6 web page).

As shown before, the order can be reversed by reversing the order of the elements in the comparison function.

Finally, let us look at how a comparison function can be more complex. This example will assume that Javascript is being used to read RSS feeds using the XMLHttpRequest function, and that the news items in the RSS feed need to be sorted by the pubDate element for use in a “River of News” RSS reader application. The application has already extracted the news items from RSS feeds as individual objects in an array with the following fields for each RSS item: title, link, description, pubDate, and guid. An example object could be as follows:

[cc lang=”javascript”]
var testObject1 = {title: “Star City”,
link: “http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp”,
description: “How do Americans get ready to work with Russians aboard the space station?”,
pubDate: “Tue, 03 Jun 2003 09:39:21 GMT”,
guid: “http://liftoff.msfc.nasa.gov/2003/06/03.html#item573”};
[/cc]

To perform a sort on pubDate, the text string describing the publication date of the item needs to be converted to a number for comparison. We can use the parse method included with the Javascript Date object to create the following comparison function:

[cc lang=”javascript”]
function comparepubDates(a, b) {
var pubDateValue1 = Date.parse(a.pubDate); // Get milliseconds for date/time string
var pubDateValue2 = Date.parse(b.pubDate); // Get milliseconds for date/time string
return pubDateValue1 – pubDateValue2;
}
[/cc]

This function will parse the pubDate field and convert the date string to a value in milliseconds, then use that value for the comparison to sort the objects.

(see Example 7 web page).

Summary

Javascript can sort arrays of data and arrays of objects in flexible ways. Use these examples to start sorting your data today!

References

RSS specification – hosted at Harvard University

Stack Overflow – discussion on sorting of Javascript objects

Getting started with Javascript

When I start to learn a new language or framework, creating a small application really helps accelerate the learning process. Using the work I did for a MacTech article on test-driven development, I created a simple number guessing game as a Javascript web application (game page is here). I also used the YUI 2 YUITest testing framework to check out my Javascript functions as I developed them (test page is here). My next steps with this will be to try creating some browser extensions using this game as a starting point.

Developing OPML Editor Tools – Part 7

Part 7 – Conclusion

This series has provided an introduction to developing Tools for the OPML Editor. However, the topics covered in this series have not even scratched the surface of the capabilities within the OPML Editor. Dave Winer has compiled a list of resources on the OPML Editor HowTo web site, but here are some additional pointers and guidance for learning the OPML Editor development environment:

I hope this series will “whet your appetite” to explore the power and possibilities of the OPML Editor. Feel free to leave comments on these weblog posts if you have questions or problems, or consult the About page for contact information. Good luck!

Series Table of Contents:

  • Part 1 – Installing the OPML Editor and creating a “Hello World” Tool
  • Part 2 – Creating web pages and scripts
  • Part 3 – Running a script from a web page
  • Part 4 – Saving data in the tool database
  • Part 5 – Creating an application
  • Part 6 – Creating an application – Windows updates
  • Part 7 – Conclusion

Developing OPML Editor Tools – Part 6

Part 6 – Creating an application – Windows Updates

As mentioned in the previous part of this series, some additional applications and Tool changes are required to support calling the Delicious API for Windows users. The following steps were followed on a ASUS EeePC 1000HD running Windows XP.

Step 1 – cURL installation and setup

Download a Windows version of cURL with SSL support. You can use the Download Wizard or pick one of the Win32 – Generic versions with SSL (this version was used in development of this tutorial). Once you have downloaded a version, unzip the file and copy the curl.exe file to a directory for use. In testing of this tutorial, curl.exe was copied to C:\bin. Next, the path C:\bin was added to the PATH environment variable. To do this, perform the following steps:

  • Click Start, then double-click on Control Panel, then double-click on System (opens System Properties window)
  • Click on Advanced tab, then click on Environment Variables button (opens Environment Variables window)
  • In System variables area of window, scroll down and click on the Path variable entry, then click on the Edit button (opens Edit System Variable window)
  • Click in the Variable value text box, press the End button to move the cursor to the end of the field, then enter ;C:\bin
  • Click OK (closes Edit System Variable window)
  • Click OK (closes Environment Variables window)
  • Click OK (closes System Properties window)
  • You may have to perform a restart of the PC for the change to take effect.

Step 2 – Other SSL support installation and setup

As mentioned at the bottom of the cURL download page, the OpenSSL binaries/DLLs are required for the cURL versions with SSL support. The OpenSSL binary and Visual C++ Executables from Shining Light Software should be installed (the versions installed for this series were Win32OpenSSL_Light-0_9_8k.exe and vcredits_x86.exe). Next, copy cacert.pem from C:\Program Files\OpenSSL\bin to C:\bin where the cURL executable file was copied, and then copy cacert.pem to curl-ca-bundle.crt in that directory. The Windows version of cURL will automatically look for a CA certs file named ‘curl-ca-bundle.crt’, either in the same directory as curl.exe, or in the Current Working Directory, or in any folder along your PATH. This is why cacert.pem needs to be copied and renamed as curl-ca-bundle.crt (see this reference for more information). As mentioned in step 1 above, a restart of the PC may be required.

Step 3 – Windows updates for MyDeliciousTool

After installing the cURL and SSL tools, the MyDeliciousTool Tool needs some modifications to be able to call the Delicious API using cURL. The Windows version of the OPML Editor supports the Windows Component Object Model (COM) interface. The curlDelicious script from part 5 will be modified to call cURL using a COM command shell object. In the Macintosh version of the MyDeliciousTool, the OPML Editor was able to receive the response from the cURL application and assign it directly to a string. In the Windows version, the output from cURL will be written to a file. The contents of the file will then be read and assigned to the string.

To be able to create the COM command shell object, a Visual Basic script will be used. This will be created using the outline object type. From the Window menu, select the “MyDeliciousTool.root” menu item. Next, press the Control key and double-click on the black triangle next to the MyDeliciousToolSuite entry in the table. A new window will open with the MyDeliciousToolSuite table. Click in the table, then go to the Table menu and select the New Outline menu item. A dialog box will appear asking for the name of the new outline. Type the name “createCommandPrompt” without quotes and click OK. A new window will open that looks similar to a script. Enter the following text into the outline:

Sub Main (myCommand)
   Dim shell

   Set shell = CreateObject ("Wscript.Shell")

   shell.run "curl " & myCommand

   Set shell = Nothing
End Sub

The script should appear as follows:

createcommandprompt.jpg

Next, update the curlDelicious script in the MyDeliciousToolSuite table as follows:

on curlDelicious ()
   local (s, s1, curlCommand)
   local (scriptCode = string (MyDeliciousToolSuite.createCommandPrompt))
   new (tableType, @MyDeliciousToolData.userdata.apiResponseCompile)
   s = "-o C:\test.txt https://" + MyDeliciousToolData.userdata.username + ":"
   s = s + MyDeliciousToolData.userdata.password
   s = s + "@api.del.icio.us/v1/posts/recent?count="
   s = s + MyDeliciousToolData.userdata.bookmarks
   result = com.callScript (scriptCode, "VBScript", "Main", {s})
   s1 = file.readWholeFile("C:\test.txt")
   wp.newTextObject (s1, @MyDeliciousToolData.userdata.apiResponse)
   xml.compile (s1, @MyDeliciousToolData.userdata.apiResponseCompile)

The rest of the logic from part 5 of this series remains the same.

To view Delicious bookmarks, make sure that you have entered the username and password for your Delicious account and that you have set the number of bookmarks to retrieve (it must be less than 100). Go to the main page of the application (http://127.0.0.1:5335/MyDeliciousTool/) and click on the Get Bookmarks link. Within a few seconds you should see a display of the bookmarks you have retrieved. Here is the bookmark display from the example XML shown in part 5 of this series:

deliciousbookmarks.jpg

Further reading

The following links go into more detail on this part of this series.

  • COM Client – Describes COM client support built into Frontier, which is the kernal of the OPML Editor.

Series Table of Contents:

  • Part 1 – Installing the OPML Editor and creating a “Hello World” Tool
  • Part 2 – Creating web pages and scripts
  • Part 3 – Running a script from a web page
  • Part 4 – Saving data in the tool database
  • Part 5 – Creating an application
  • Part 6 – Creating an application – Windows updates
  • Part 7 – Conclusion

Developing OPML Editor Tools – Part 5

Part 5 – Creating an application

In this part of this series, an OPML Editor Tool will be developed to interact with the Delicious social bookmarking service. You will need to have an active Delicious account with several entries to be able to use this application.

Delicious supports an Application Program Interface (API) which allows users of the service to get information on their bookmarks. Here are some requirements for a simple use of the recent bookmarks API.

Requirements

  • Ability to enter username/password for Delicious account
  • Ability to change default number of bookmarks to retrieve
  • Ability to call Delicious API and retrieve bookmarks
  • Ability to display retrieved bookmarks

From these requirements, a user interface, data design, and logic design for the application could be as follows:

User Interface Design

  • Welcome page introducing the application and providing links to pages for viewing last x bookmarks, for updating username/password, and for updating default number of bookmarks to retrieve
  • Page for updating username/password
  • Page to confirm that username/password has been updated
  • Page for updating default number of bookmarks to retrieve
  • Page for confirming that default number of bookmarks has been updated
  • Page for viewing last x bookmarks

Data Design

The application needs to save the following data:

  • Delicious username
  • Delicious password
  • Number of bookmarks to retrieve
  • Data received from call to Delicious API

Logic Design

The application should be able to call the Delicious API for recent bookmarks, get the bookmark data, save the data to the Tool database, and process the data to show the description for the bookmark and the URL. This logic should be activated by the web page that allows the user to view the number of recent bookmarks.

Creating the User Interface

To begin, create a new Tool database for the application. As covered in part 1 of this series, to create a new Tool, click on the Tools menu in the OPML Editor application, then select “New Tool…”. A dialog box will appear asking you to name the tool, and suggesting the name “untitled.root”. Enter the name “MyDeliciousTool.root” in the dialog box and click the OK button. The OPML Editor will then create a new tool and store it in the Guest Databases/apps/Tools folder within the OPML folder. After several seconds, a new window will then open:

mydelicioustool.jpg

This example will start with the initial web pages for the user interface. As mentioned in part 1 of this series, the website table contains the web page data for the Tool. To view the website table for MyDeliciousTool, go to the Window menu and select the “MyDeliciousTool.root” menu option. After selecting the Tool, a window will open showing a list of tables making up the Tool. Hold down the Apple or Control key and double-click on the black triangle next to the text “MyDeliciousToolWebsite”. The following window will appear:

mydelicioustoolwebsite.jpg

The table element “index” will be used to display the welcome page for our application. Double-click on the gray triangle to open the wp text object. The following window will appear:

mydelicioustoolindexpage.jpg

Replace the text in the window with the following text:

#title "MyDeliciousTool Home Page"
<center>My Delicious Tool Menu</center><br>
<br>

<ul>
<li><a href="updatepw.html">Update Passwords</a> - Enter your Delicious account username and password</li>
<li><a href="updatebk.html">Update Bookmarks</a> - Change the number of Delicious bookmarks to retrieve</li>
<li><a href="bookmarks.html">Get Bookmarks</a> - Get bookmarks from your Delicious account and display them.</li>
</ul>

Close the window, then go to http://127.0.0.1:5335/MyDeliciousTool/ in a browser window. The home page should appear as follows:

apphomepage.jpg

The login page from part 4 of this series will be used as a starting point for the username/password and bookmark pages. Open the MyTestTool Tool database by going to the Window menu and select the “MyTestTool.root” menu option. A window will open showing the tables in the MyTestTool Tool database. Hold down the Apple or Control key and double-click on the black triangle next to the “MyTestToolWebsite” table entry. This will open the MyTestToolWebsite table in a new window. Next, click on the login entry in the table to select it (scroll down to find the entry if you need to), then go to the Edit menu and select Copy. Now, switch back to the MyDeliciousToolWebsite window. You can do this by clicking on the window if it is visible, or you can bring it to the front by going to the Window menu and selecting the “MyDeliciousToolWebsite” entry. When you have selected the window, click on the “index” item in the table, then go to the Edit menu and select Paste. You should see the “login” entry appear in the table. Go to the Edit menu and select Paste again to make another copy. A dialog box will appear saying “An item named login already exists in this location”. Click on the “Duplicate” button to create a copy of the login entry, which will be called “login #1”. To rename the entries, click on the name, which will highlight the name of the table entry, then type the new name. For our application, the names should be changed to “updatepw” and “updatebk” (without quotes) to match the links in the home page. The table should appear as follows:

mydelicioustoolwebsitea.jpg

Open the “updatepw” wp text object in the MyDeliciousToolWebsite table to view the text. You can open the entry by double-clicking on the black triangle next to the entry name. Edit the text to match the following text:

#title "Update Username and Password"
<p>Please update the MyDeliciousTool database with your Delicious username and password.</p>
<form method="post" action="confirmpw">
<p>
<INPUT TYPE=text NAME="username" SIZE=50>
</p>
<p>
<INPUT TYPE=text NAME="password" SIZE=50>
</p>

<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0" WIDTH="100" cols=2>
<TR ALIGN="CENTER">
<TD><INPUT TYPE="submit" VALUE="Submit"></TD>
<TD><INPUT TYPE="reset" VALUE="Reset"></TD>
</TR>
</TABLE>
</form>

The main changes from the login entry are the title text, the first sentence of the page, and the action attribute in the form line (changing “confirm” to “confirmpw”). Next, open the “updatebk” entry and edit the text as follows:

#title "Update Number of Bookmarks"
<p>Enter the number of bookmarks to retrieve from your Delicious account.</p>
<form method="post" action="confirmbk">
<p>
<INPUT TYPE=text NAME="bookmarks" SIZE=50>
</p>

<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0" WIDTH="100" cols=2>
<TR ALIGN="CENTER">
<TD><INPUT TYPE="submit" VALUE="Submit"></TD>
<TD><INPUT TYPE="reset" VALUE="Reset"></TD>
</TR>
</TABLE>
</form>

The main changes from the login entry are the title text, the first sentence of the page, the action attribute in the form line (changing “confirm” to “confirmbk”), changing the first field from “username” to “bookmarks”, and deleting the field for “password”.

To test these entries, go to http://127.0.0.1:5335/MyDeliciousTool/ in a browser window, then click on the links for updating the username/password and updating the number of bookmarks. You should see the following web pages:

updateusernamepage.jpg

updatebookmarkspage.jpg

As in part 4 of this series, when the user enters the information in the text fields for these pages and clicks the “Submit” button, a confirmation page will appear to let the user know that the data has been updated. The confirmation page script from part 4 will be reused to create the confirmation pages for the MyDeliciousTool application. Bring the MyTestToolWebsite window to the front, select the “confirm” entry, then go to the Edit menu and select the Copy menu item. Bring the My DeliciousToolWebsite window to the front, then go to the Edit menu and select the Paste menu item. You should see the “confirm” entry appear in the table. Go to the Edit menu and select Paste again to make another copy. A dialog box will appear saying “An item named confirm already exists in this location”. Click on the “Duplicate” button to create a copy of the confirm entry, which will be called “confirm #1”. To rename the entries, click on the name, which will highlight the name of the table entry, then type the new name. The names should be changed to “confirmpw” and “confirmbk” (without quotes) to match the links in the web pages that were just created. The website table should appear as follows:

confirmationpages.jpg

Open the “confirmpw” entry in the MyDeliciousToolWebsite table to view the script. You can open the entry by double-clicking on the black triangle next to the entry name. Edit the script to match the following text:

local (pta = html.getpagetableaddress ());
pta^.title = "Confirm Password Updates";
pta^.flShowTitle = true; //the page looks better with a title
return (MyDeliciousToolSuite.passwordConfirmation ())

The main change from the confirm entry is the name of the script being called. Next, open the “confirmbk” script and edit the text as follows:

local (pta = html.getpagetableaddress ());
pta^.title = "Confirm Bookmark Updates";
pta^.flShowTitle = true; //the page looks better with a title
return (MyDeliciousToolSuite.bookmarkConfirmation ())

The main changes from the confirm entry are the title text and the name of the script being called.

The confirmation script from part 4 of this series will be reused to complete the confirmation pages for the MyDeliciousTool application. Bring the MyTestTool window to the front, Hold down the Apple or Control key and double-click on the black triangle next to the text “MyTestToolSuite”. This will open the MyTestToolSuite table in a new window. Next, click on the ConfirmationScript entry in the table to select it (scroll down to find the entry if you need to), then go to the Edit menu and select Copy. Bring the MyDeliciousTool window to the front and double-click on the black triangle next to the “MyDeliciousToolSuite” entry. This will open the MyDeliciousToolSuite window. When you have selected the window, click on an item in the table, then go to the Edit menu and select Paste. You should see the “ConfirmationScript” entry appear in the table. Go to the Edit menu and select Paste again to make another copy. A dialog box will appear saying “An item named login already exists in this location”. Click on the “Duplicate” button to create a copy of the ConfirmationScript entry, which will be called “ConfirmationScript #1”. To rename the entries, click on the name, which will highlight the name of the table entry, then type the new name. For our application, the names should be changed to “passwordConfirmation” and “bookmarkConfirmation” (without quotes) to match the script names given above. The MyDeliciousSuite window should appear as follows:

newconfirmationscripts.jpg

Next, the scripts need to be updated to change the script names and to access data in the MyDeliciousTool data tables. Make the following updates to the passwordConfirmation and bookmarkConfirmation scripts:

on passwordConfirmation()
   local (pta = html.getpagetableaddress ())
   local (s1, s2, s3)
   new (tabletype, @pta^.searchArgTable)
   new (tableType, @MyDeliciousToolData.userdata)
   new (stringType, @MyDeliciousToolData.userdata.username)
   new (stringType, @MyDeliciousToolData.userdata.password)
   webserver.parseargs (pta^.searchargs, @pta^.searchArgTable)
   if pta^.method == "POST"
      new (tabletype, @pta^.postArgs)
      webserver.parseArgs (pta^.requestBody, @pta^.postArgs)
   s1 = pta^.postArgs.username
   s2 = pta^.postArgs.password
   MyDeliciousToolData.userdata.username = s1
   MyDeliciousToolData.userdata.password = s2
   s3 = "The username is " + MyDeliciousToolData.userdata.username + " and the password is " + MyDeliciousToolData.userdata.password
   s3 = s3 + "<br><br>Return to the <a href=" + "\"" + "http://127.0.0.1:5335/MyDeliciousTool/"+ "\""
   s3 = s3 + ">home page</a><br>"
   return (s3)
on bookmarkConfirmation()
   local (pta = html.getpagetableaddress ())
   local (s1, s2)
   new (tabletype, @pta^.searchArgTable)
   new (stringType, @MyDeliciousToolData.userdata.bookmarks)
   webserver.parseargs (pta^.searchargs, @pta^.searchArgTable)
   if pta^.method == "POST"
      new (tabletype, @pta^.postArgs)
      webserver.parseArgs (pta^.requestBody, @pta^.postArgs)
   s1 = pta^.postArgs.bookmarks
   MyDeliciousToolData.userdata.bookmarks = s1
   s2 = "The number of bookmarks is " + MyDeliciousToolData.userdata.bookmarks
   s2 = s2 + "<br><br>Return to the <a href=" + "\"" + "http://127.0.0.1:5335/MyDeliciousTool/"+ "\""
   s2 = s2 + ">home page</a><br>"
   return (s2)

As in the MyTestTool tool, these scripts will parse data from the OPML Editor web server when the user clicks on the button to enter the username/password combination or the number of bookmarks to retrieve. The scripts will then clear the table entries in the database, store the new values, then echo those values to the web browser. To test these updates, go to http://127.0.0.1:5335/MyDeliciousTool/ in a browser window, then click on the “Update Passwords” link. You should see the following web page:

updateusernamepage.jpg

Enter a username and password, then click the Submit button. The web page will clear and display a text message echoing the username and password that you have entered. Click on the “Return to the home page” link to return to the tool home page. Next, click on the “Update Password” link. You should see the following web page:

updatebookmarkspage.jpg

Enter a value for the number of bookmarks to retrieve from your Delicious account, then click the Submit button. The web page will clear and display a text message echoing the number of bookmarks that you have entered. Click on the “Return to the home page” link to return to the tool home page.

Now, check to see that the values entered on the web pages are in the tool data table. Bring the MyDeliciousToolData window to the front, then select the username entry in the table and double-click on the black triangle. You should see the new entries for your username, password, and number of bookmarks to be retrieved (the following picture is an example):

updatedusernametable.jpg

The final function to implement is to retrieve some bookmarks from your Delicious account. To do this, the OPML Editor will need to make a call to the Delicious API. This API requires a HTTPS call, which is not supported natively in the OPML Editor. However, the OPML Editor can call other programs or system functions to perform tasks. The cURL application will be used to perform the HTTPS call. The OPML Editor will parse the XML response from the API and display the bookmarks in the web browser. On the Macintosh, this can be accessed using a system command. On Windows, the cURL application will need to be installed if it is not present. Both Macintosh and Windows users should follow the rest of the instructions in this part of the series, but Windows users will need to wait to implement the changes in part 6 of this series before testing.

First, a script is needed to call the Delicious API and store the response. This script will be stored in the MyDeliciousTool Suite sub-table, and the response from the API will be stored in the MyDeliciousToolData sub table. To create the script, bring the MyDeliciousTool.root window to the front, then click on the triangle next to the MyDeliciousToolSuite entry in the tool table to select the sub-table. Next, hold down the Apple or Control key and double-click on the entry to open the MyDeliciousToolSuite table in another window. The following window should appear:

mydelicioustoolsuitetable.jpg

To add a script to the table, click in the table, then go to the Table menu and select the “New Script” entry. A dialog box will appear asking for the name of the script. Enter the text “curlDelicious” without quotes and click the OK button. A new script window will open as shown below:

curldelicious.jpg

Enter the following text into the script window:

on curlDelicious ()
   local (s, curlCommand)
   s = "curl -u " + MyDeliciousToolData.userdata.username + ":"
   s = s + MyDeliciousToolData.userdata.password
   s = s + " https://api.del.icio.us/v1/posts/recent?count="
   s = s + MyDeliciousToolData.userdata.bookmarks
   curlCommand = s
   s = sys.unixShellCommand (curlCommand)
   wp.newTextObject (s, @MyDeliciousToolData.userdata.apiResponse)
   xml.compile (s, @MyDeliciousToolData.userdata.apiResponseCompile)

This script first creates a text string with the command for cURL. Notice how the data from the MyDeliciousToolData table can be retrieved by simply giving the name of the table path down to the cell containing the data. Next, the command string is passed to the cURL application using an OPML Editor command to tell the Macintosh to treat this as a command being entered at the command line. The response from cURL is stored as a string in the variable s. The response from the Delicious API is then stored in a new element in the MyDeliciousToolData table. Again, notice how the new element’s name is defined by a path in the table. Finally, an OPML Editor command is used to read the XML response from the Delicious API and store it in a table for further processing.

If you have completed entering the earlier scripts for adding your Delicious username and password, and have entered the username/password for your account, and have entered the number of bookmarks to retrieve, you can test this script in a standalone way. To do this test, double-click on the triangle next to the “on curlDelicious()” line to collapse the outline. Next, add another line with the text “curlDelicious()”. Click on the Compile button, then click on the Run button in the script window, then go to the userdata table and look at the apiResponse and apiResponseCompile entries. Make sure to remove the call to curlDelicious before moving on with this example.

Here is an example of the XML received from the Delicious API that was stored in the apiResponse entry in the table:

<?;xml version="1.0" encoding="UTF-8"?>
<posts user="andysylvester" tag="">
  <post href="http://www.frontierkernel.org/" hash="07aaaacf8d979a61f5d4cfecd4813f18" description="Frontier Kernel Project" tag="userland frontier" time="2007-11-28T07:14:39Z" extended="Home page for the open-source version of the Frontier scripting/development environment originally developed by UserLand Software."/>
  <post href="http://www.shinywhitebox.com/home/home.html" hash="5f8975874dfb433b4ee8cedbb0610fc7" description="iShowU Home Page" tag="mac software screencast screencasting" time="2007-11-28T07:12:33Z" extended="This is a new Mac OS X application for capturing on-screen video for screencasts and other applications."/>
</posts>
<!-- fe02.api.del.ac4.yahoo.net uncompressed/chunked Tue Jul 14 06:38:59 PDT 2009 -->

When the xml.compile command is executed by the OPML Editor, it structures the XML into a table as follows:

apiresponsecompile.jpg

Next, the results from this script need to be displayed. To do this, another script will call the curlDelicious script and create a web page displaying the bookmarks within an HTML table. As before, this script will be in the MyDeliciousToolSuite table. Bring this table to the front, click within the table, then go to the Table menu and select the “New Script” item. At the dialog box prompt, enter “displayBookmarks” without quotes, then click the OK button. A new script window will appear as follows:

displaybookmarkswindow.jpg

Enter the following text into the script window:

on displayBookmarks ()
   local (adr=html.table.new(border:3, cellspacing:6, cellpadding:8))
   html.table.addColumn(adr, "Description")
   html.table.addColumn(adr, "Link")
   MyDeliciousToolSuite.curlDelicious()
   myPosts = xml.getAddress(@MyDeliciousToolData.userdata.apiResponseCompile, "posts")
   myList = xml.getAddressList(myPosts, "post")
   for x = 1 to MyDeliciousToolData.userdata.bookmarks
      description = xml.getAttributeValue(myList[x], "description")
      link = xml.getAttributeValue(myList[x], "href")
      html.table.addRow(adr)^.cells={description, link}
   html.table.render (adr)

This script makes use of several OPML Editor commands to create an HTML table and display the results. The first three lines create an address to render the table and some attributes of the table. Next, the curlDelicious script is called to get the Delicious bookmark data. After that, an OPML Editor command is used to get the table address for the “posts” sub-table within the apiResponseCompile table. In the example XML response given earlier, the bookmark information is enclosed within a <posts> tag. The OPML Editor creates a table with the information enclosed within this tag. The xml.getAddress command retrieves the address of this table. Next, the address of the posts table is used to get a list of all of the entries within that table that have the value of “post”. In the Delicious XML data, each bookmark is separated by a <post> tag. When the XML is compiled into a table, a sub-table is created for each bookmark with its attributes stored in the subtable. The xml.getAddressList command creates a list of the table addresses for each of the bookmark entries. Finally, the script runs a loop in which the description and link for each bookmark entry is retrieved from the table and added to the rows in the table. The last step in the script is to render the table, which appears in the web browser.

The final step in adding this feature is to connect the web page link to these scripts. As was done for the username/password and bookmark functions, the web page will call a script to display the data from the Delicious API call. The confirmpw script willl be used as a starting point for this script. Bring the MyDeliciousTool.root window to the front, select the MyDeliciousToolWebsite entry, then hold the Apple or Control key down and double-click on the black triangle for the MyDeliciousToolWebsite entry. A window will open containing the MyDeliciousToolWebsite table as follows:

mydelicioustoolwebsiteb.jpg

Select the confirmpw script entry, then go to the Edit menu and select Copy, then go to the Edit menu and select Paste. A dialog box will appear saying “An item named confirmpw already exists in this location”. Click on the “Duplicate” button to create a copy of the confirmpw script, which will be called “confirmpw #1”. To rename the entry, click on the name, which will highlight the name of the table entry, then type “bookmarks” without quotes. Double-click on the bookmarks item to open the script, then edit it to appear as follows:

local (pta = html.getpagetableaddress ())
pta^.title = "Display Delicious Bookmarks"
pta^.flShowTitle = true; //the page looks better with a title
return (MyDeliciousToolSuite.displayBookmarks ())

To view the bookmarks, make sure that you have entered the username and password for your Delicious account and that you have set the number of bookmarks to retrieve (it must be less than 100). Go to the main page of the application (http://127.0.0.1:5335/MyDeliciousTool/) and click on the Get Bookmarks link. Within a few seconds you should see a display of the bookmarks you have retrieved. Here is the bookmark display from the example XML shown earlier:

deliciousbookmarks.jpg

For Windows users of the OPML Editor, some additional steps are needed to be able to complete the MyDelicious Tool. First, cURL and several additional applications and files need to be installed on your computer. Next, some setup is required to support https transfers. Finally, some changes will be required for the scripts used in the Tool. These steps will be covered in the next part of this series.

Further Reading

The following links go into more detail on this part of this series.

  • XML-Database – This page walks you thru techniques for managing XML-structured information in the OPML Editor object database.

Series Table of Contents:

  • Part 1 – Installing the OPML Editor and creating a “Hello World” Tool
  • Part 2 – Creating web pages and scripts
  • Part 3 – Running a script from a web page
  • Part 4 – Saving data in the tool database
  • Part 5 – Creating an application
  • Part 6 – Creating an application – Windows updates
  • Part 7 – Conclusion