Remote JavaScripting Example – Part I

[[innerindex]]At Plymouth State we work in a multi-server environment and often wish to display dynamic content from one server in an Ajax-like fashion on another server’s website. My co-worker, Zach Tirrell, and I have drummed up a solution that works to keep our layout and logic separate, while still serving our end users in a smooth, seamless, non-iFramed manner.

I’ll walk through the creation of a simple search ‘widget’ that relies on dynamic data to populate a drop-down box.

The Tools

- PHP
- JavaScript
- XTemplate
- RemoteJSOutput: a simple script by Matthew Batchelder (me) and Zach Tirrell

Step 1: create your template

This widget is fairly simple and thus has a simple template. The template syntax is simply XTemplate syntax.

I’ll name it widget.tpl and store it in a templates directory.

<!-- BEGIN: main -->
<div id="sweet_borkweb_widget" style="background:#eee;border:1px solid #ccc;text-align:center;">
  <div style="color:#000;">A Couple JavaScript Posts at BorkWeb</div>
  <select id="borkweb_posts">
    <option value=""></option>
  <!-- BEGIN: post -->
    <option value="{post.url}">{post.title}</option>
  <!-- END: post -->
  </select>
</div>
<!-- END: main -->

Step 2: simple template output

First we’ll just spit out the template. Lets create a PHP file to do this. We’ll call it widget.php

< ?php
include('includes/xtemplate.php');
$xtpl = new XTemplate('templates/widget.tpl');

$xtpl->parse('main');
$xtpl->out('main');
?>

Check out your widget so far. Its plain. Lets change that.

Step 3: add dynamic content

We want the drop down list to hold BorkWeb articles. We’ll add that in now.

Note: this is where you would normally pull from a database, an RSS feed, or some other source. For simplicty, we’ll be using a simple PHP array. Whoop-de-doo. Here it is:

< ?php
include('includes/xtemplate.php');
$xtpl = new XTemplate('templates/widget.tpl');

//get list of articles
$articles=array(
  array('title'=>'Ajax, More Than A Buzz Word','url'=>'http://borkweb.com/story/ajax-more-than-a-buzz-word'),
  array('title'=>'Ajax; Templating; and the Separation of Layout and Logic','url'=>'http://borkweb.com/story/ajax-templating-and-the-separation-of-layout-and-logic'),
  array('title'=>'Deleting the Internet','url'=>'http://borkweb.com/story/deleting-the-internet'),
  array('title'=>'Node Manipulation in the DOM','url'=>'http://borkweb.com/story/node-manipulation-in-the-dom'),
  array('title'=>'Prototype Cheat Sheets','url'=>'http://borkweb.com/story/prototype-cheat-sheets'),
  array('title'=>'Script.aculo.us Is My New Best Friend','url'=>'http://borkweb.com/story/scriptaculous-is-my-new-best-friend'),
  array('title'=>'The Case For JSON: What Is It and Why Use It?','url'=>'http://borkweb.com/story/the-case-for-json-what-is-it-and-why-use-it')
);

//loop over articles and place in template
foreach($articles as $article)
{
  $xtpl->assign('post',$article);
  $xtpl->parse('main.post');
}//end foreach

$xtpl->parse('main');
$xtpl->out('main');
?>

Check out your widget now. It has been populated with some data! w00t! Now to make it work, we return to our beloved widget.tpl template file.

Step 4: make the template work

We’re going to add in some javascript. Lets make the dropdown list redirect the user to the selected article when the drop-down box changes.

I’m going to add this on our select box:

 onchange="if(document.getElementById('borkweb_posts').value!='') document.location=document.getElementById('borkweb_posts').value;"

The template should now look like this:

<!-- BEGIN: main -->
<div id="sweet_borkweb_widget" style="background:#eee;border:1px solid #ccc;text-align:center;">
  <div style="color:#000;">A Couple JavaScript Posts at BorkWeb</div>
  <select id="borkweb_posts" onchange="if(document.getElementById('borkweb_posts').value!='') document.location=document.getElementById('borkweb_posts').value;">
    <option value=""></option>
  <!-- BEGIN: post -->
    <option value="{post.url}">{post.title}</option>
  <!-- END: post -->
  </select>
</div>
<!-- END: main -->

Step 5: prepare script for remoting

Now that our lovely widget is functioning, lets prepare it for inclusion in other locations. This is simple using RemoteJSOutput (a simple script written by Zach Tirrell and myself).

We’ll include that PHP class and use it as follows:

< ?php
include('includes/RemoteJSOutput.class.php');
$remoteOutput=new RemoteJSOutput();

//start output buffering via 
$remoteOutput->start();

include('includes/xtemplate.php');
$xtpl = new XTemplate('templates/widget.tpl');

//get list of articles
$articles=array(
  array('title'=>'Ajax, More Than A Buzz Word','url'=>'http://borkweb.com/story/ajax-more-than-a-buzz-word'),
  array('title'=>'Ajax; Templating; and the Separation of Layout and Logic','url'=>'http://borkweb.com/story/ajax-templating-and-the-separation-of-layout-and-logic'),
  array('title'=>'Deleting the Internet','url'=>'http://borkweb.com/story/deleting-the-internet'),
  array('title'=>'Node Manipulation in the DOM','url'=>'http://borkweb.com/story/node-manipulation-in-the-dom'),
  array('title'=>'Prototype Cheat Sheets','url'=>'http://borkweb.com/story/prototype-cheat-sheets'),
  array('title'=>'Script.aculo.us Is My New Best Friend','url'=>'http://borkweb.com/story/scriptaculous-is-my-new-best-friend'),
  array('title'=>'The Case For JSON: What Is It and Why Use It?','url'=>'http://borkweb.com/story/the-case-for-json-what-is-it-and-why-use-it')
);

//loop over articles and place in template
foreach($articles as $article)
{
  $xtpl->assign('post',$article);
  $xtpl->parse('main.post');
}//end foreach

$xtpl->parse('main');
$xtpl->out('main');

//spit out script encased in JS
$remoteOutput->puke();
?>

Now check out your widget. Ugly, huh? Well, don’t worry, thats the way its supposed to look for now.

Step 6: place your widget somewhere

Now that we have that beautiful chunk of code in operation, place it on a webpage somewhere.

Put this:

<script type="text/javascript" src="http://url.to/your/widget.php"></script>

on any page you wish to test your widget!

Optional Step 7: create a wrapper

If, like me, you aren’t a fan of including RemoteJSOutput.class.php all over hell’s half acre, you can create a wrapper. This not only allows you to minimize the code you have to repeatedly place everywhere, but it also keeps your widget.php script functional on its own!

Here’s an example wrapper I’ll call get_script.php which will display wrapper_widget.php (step 3′s PHP file, renamed):

< ?php
include('includes/RemoteJSOutput.class.php');
$remoteOutput=new RemoteJSOutput();

//start output buffering via 
$remoteOutput->start();

//create a list of allowable widgets/scripts/yadda yadda
$allow=array('wrapper_widget');

//does the passed variable exist in the allowable widgets?
if(in_array($_GET['script'],$allow))
{
  //include the wrapper
  include($_GET['script'].'.php');
}//end if

//spit out script encased in JS
$remoteOutput->puke();
?>

So rather than using the script tag that Step 6 suggests, we’d use:

<script type="text/javascript" src="http://url.to/your/get_script.php?script=wrapper_widget"></script>

Conclusion

This method is simplistic and is simply touching on the topic of widgetization. I will be following up with dynamic user interactions in Part II, and finally discuss an open-standard widget library with xml definitions. Stay tuned :)

Download

Oh, and here’s the code used in this tutorial all zipped up.