- September 20, 2008
At first glance, undertaking a task such as this may appear somewhat daunting. Indeed - without some knowledge of the inner workings of Digipage, it could become quite time-consuming. However, the process is actually quite simple - I built the example code for this tutorial in only a couple hours.
With this tutorial, we'll begin to unlock some of the inner workings of Digipage.
http://view.digipage.net/?id=searchyahoo - click to see this example in action.
NOTE: Since writing this tutorial, I have added some extra functionality to the live example, one of which is the ability to display thumbnails with each search result. This isn't actually part of Yahoo!'s SDKs - it's something I've developed internally here and falls outside the scope of this tutorial.
click here to download the supporting files.
Using Yahoo! APIs
In order to build this example, some understanding of Yahoo!'s APIs would be helpful - they actually provide a large number of programming tools for building various Yahoo! functionality into your own web application.
For more information, please see:
http://developer.yahoo.com/
The actual web service we want to use is Yahoo! Search BOSS (Build your Own Search Service), available at the following address:
http://developer.yahoo.com/search/boss
In order to build this example, you'll need to sign up to the BOSS service by getting an App ID - the link is available from the above site. Please note you'll need a 'Browser Base Authentication' App ID when signing up.
I should also point out that this is a very quick example which enables us to get things up-and-running as quickly as possible. I'm sure someone could find ways to improve it though!
Creating the front page
The first thing we'll need is a page containing the Yahoo! search dialog box. We'll be using Flash to create this, and the results pages that follow.
In Flash (CS3 Professional), create a new ActionScript 2 Flash File and add a text box and search button graphic to the stage. This section is very simple and only needs a minimal amount of code, so click here to download the .fla file I created, or open it from the download package. You may want to view this file alongside reading the following.
On the front page, obviously what we want is to turn the page over and start getting the search results when the user clicks the 'search' button. However, at this point we don't actually need to do anything to find the search results - the subsequent pages will handle that. Instead, all we need to do is set a global value with the search keywords - so the other pages can find it - and then get the page to turn over.
The code I've used for this is as follows:
btnSearch.onRelease = function() {
_global.yahooSearch = txtSearch.text;
_global.digipage.nextPage();
}
The second line - '_global.yahooSearch = ...' simply sets a global variable with the search keywords in it (provided you have an input text box on stage called 'txtSearch').
The third line - '_global.digipage.nextPage();' tells Digipage to turn the page over. There are a large number of other functions within digipage, and I'll be going into more depth over what's possible in later tutorials.
There is some other code I've added for the purposes of usability - I'd like it if the search would activate when the enter key is pressed and the search text box currently has focus. Therefore, I've added the following code:
Selection.setFocus(txtSearch); // set the focus to the text box when we enter the frame
var enterFocus:String = Selection.getFocus(); // get the selection path
var btnSearch:MovieClip;
var kL:Object = new Object(); // set up our keyboard listener object
Key.addListener(kL); // add the keyboard listener
kL.onKeyDown = function() {
if(Key.isDown(13)) {
// the enter key was pressed
if(Selection.getFocus() == enterFocus) {
// the current focus is the text box focus variable we stored earlier,
// therefore we should turn the page over.
btnSearch.onRelease(); // fire the search button's onRelease function
}
}
}
The results list
The next thing we'll need is a Flash file that will display the search results. If you're familiar with XML in AS2, it's a relatively simple procedure. First off, you'll need your BBAuth AppID from Yahoo - then we can get our XML-based list of search results back from Yahoo!
click here to download the yahooSearch.fla file.
var page:Number;
if(page == undefined) page = pagenumber - 1;
var numresults:Number = 6;
var sResults:XML = new XML();
var query:String = _global.yahooSearch;
var appid:String = YOUR_APP_ID;
var searchURL:String = "http://boss.yahooapis.com/ysearch/web/v1/" + query + "?format=xml&count=" + numresults + "&start=" + (numresults * page) + "&appid=" + appid;
sResults.ignoreWhite = true;
sResults.load(searchURL);
sResults.onLoad = function(success:Boolean) {
trace(success);
if(success) {
for(var xNode:XMLNode = sResults.firstChild.firstChild; xNode != null; xNode = xNode.nextSibling) {
if(xNode.nodeName == "resultset_web") processResultset(xNode); // we found a resultset node, so process it
}
}
}
This initial code will simply attempt to get the search results from Yahoo!'s servers. There are a few of points to note at this stage:
1. The 'pagenumber' variable on line 2. This tells us what page we're actually on of the search results, and we'll need to calculate that. I'll explain how in a minute.
2. The appid var on line 6. You'll need to replace YOUR_APP_ID with the AppID you've received from Yahoo!
3. Line 15 - when we find a node called 'resultset_web', we need to begin processing it. Rather than complicate the code and put all the processing in here, at this point I've called up another function, which we'll pick up a little later on under the heading 'Processing the results XML'.
Getting the current page number
Although Digipage is obviously quite fantastic ;-) , it does have a few 'quirks' for the programmer. One is that if you place a SWF file on a page in Digipage, it is actually a bit difficult to find out what page it's actually on from within the SWF. I'm sure we'll be fixing that at some point, but in the meantime I've created some code which will actually get the page number for you.
(yes, I admit, this is a complete hack!)
var pathStr:String = String(this);
var pathArr:Array = pathStr.split(".");
var pindex:String = pathArr[4];
var pnum:String = pathArr[5];
var index:Number = Number(pindex.slice(1));
var num:Number = Number(pnum.slice(5, pnum.length - 2));
var pagenumber:Number = (index * 2) + num - 1;
In terms of an explanation, well it's probably best left until the code gets superceeded by a simple function call back to digipage. Having said that, what we're doing here in basic terms is finding the actual path of the current MovieClip and then disassembling it to get the current page number. This code should be placed above the code shown previous to this.
Processing the results XML
function processResultset(xN:XMLNode) {
var resultCount:Number = 0;
for(var xNode:XMLNode = xN.firstChild; xNode != null; xNode = xNode.nextSibling) {
resultsMC.attachMovie("result", "res" + resultCount, resultsMC.getNextHighestDepth(), {xData: xNode, _y: resultCount * resultSpacing});
resultCount++;
}
}
This is where things get a little more complex, but again I'm splitting the code up in order to keep things simple. This function loops through the XML nodes in the resultset and creates a MovieClip for each result. The MovieClip we create is a pre-determined asset in the movie's library (called 'result') - this MovieClip contains all our formatting information and also the code which will process the result and display something on-screen.
At this point it's probably best to simple take a look at the .FLA file to see how this is created (linked above) - remember to set the linkage properties to 'Export for ActionScript' and 'Export in first frame'.
Here is our 'result' MovieClip:
... and the code - there's quite a lot of this, so I've commented it rather than explain the individual sections:
var xData:XMLNode; // the XML node which contains the current result
var txtTitle:TextField; // the text field that will hold the title of this result
var txtDesc:TextField; // the text field that will hold the description of the result
var txtURL:TextField; // the text field that will hold the URL of this result
var clickURL:String; // the clickURL - the URL to browse to when clicked.
var hl:MovieClip; // the highlight MovieClip - this should appear when the link is rolled over
hl._visible = false; // hide the highlight at the start
// now start looping through the result XML
for(var xNode:XMLNode = xData.firstChild; xNode != null; xNode = xNode.nextSibling) {
// we need to find each node we're interested in, so with each node we'll just check the nodeName
// and see if it's something we want to store.
switch(xNode.nodeName) {
case "abstract":
txtDesc.htmlText = xNode.firstChild.nodeValue;
break;
case "title":
txtTitle.htmlText = xNode.firstChild.nodeValue;
break;
case "url":
// the 'url' node is the actual web address of the result
txtURL.text = xNode.firstChild.nodeValue;
var url:String = xNode.firstChild.nodeValue;
break;
case "clickurl":
// the 'clickurl' is the web address we should use when the item is clicked.
// This is different to the 'url', and contains a link through to Yahoo!
var curl:String = xNode.firstChild.nodeValue;
clickURL = curl;
break;
}
}
// The onRelease function will fire when clicked, and will open the clickURL for this item
onRelease = function() {
if(clickURL != undefined) {
getURL(clickURL, "_blank");
}
}
// show the highlight MovieClip when this MC is rolled over
onRollOver = function() {
hl._visible = true;
}
// hide the highlight MovieClip on RollOut or DragOut
onRollOut = onDragOut = function() {
hl._visible = false;
}
Putting it all into Digipage
That wraps up all the code we need; now all we have to do is get it into Digipage. This is relatively straightforward - the only catch is you do actually need a page to put it on. Therefore, if you were embedding this into an existing publication somehow, that's fine, but if you want a new, blank publication (which in this case we do), you're going to need some blank pages on the system.
Again, I'm sure we'll get something better sorted out in the near future, but until then, the only way to do this is upload a blank brochure onto the system. We only need two pages; one to hold the front page, and then another page with the results list on it.
So, create two PDFs with a single blank page in each. This might sound like a challenge if you are unfamiliar with PDF creation, but there are several free tools that can do this for you. Two good ones are Open Office (the word-style document editor can save to PDF) and also Bullzip PDF printer, which allows you to save to a PDF when you print a document.
I created two files called 'blank.pdf' and 'blank_2.pdf'.
Now, in the control panel, simply use the upload wizard to upload the two files in the usual way:
Once uploaded, you can close down the upload wizard and open the eBook editor. Click through to your new eBook using the file browser and then upload the two SWF files we've created to the brochure using the 'upload files' button.
Once uploaded, we can close down the upload dialog and edit the two pages. All we need to do is add the SWFs onto the page. Depending on your design, you may want to resize or move the SWFs. I moved them in slightly and set the xscale and yscale variable to '2'. Sometimes a SWF file may not be clickable (if it is empty, for example) - in these cases I find this easier do using the XML button on the page editor.
Once saved, we can now compile this brochure and preview it:
That's it for this tutorial! You can of course duplicate the second page to build extra pages of results - no extra coding should be required. Another possibility would be to implement Yahoo!'s image search and news search facilities, which I may deal with in another tutorial.
Chris Barnard is lead developer at DigiVu Systems and creator of Digipage.
To contact Chris, you can email contact@digivu.com
|