Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Client-Side:
* XUL
* JavaScript
Server Side:
* PHP
* MySQL
Data Transport:
* XML-RPC
* JSON
Both administrators and end-user can access the same business hub
●
Administrator's View:
Example, Part II
End-user site
Recap: The Application
* Two views:
Rich Client for Admin (XUL + JS + PHP + MySQL)
– Status: Beta
* Open the 'content' packet, and pour it into the MySQL DB.
<?xml version="1.0"?>
<methodCall>
<methodName>system.listMethods</methodName>
</methodCall>
HTTP Response:
// Check the telephone number for valid syntax before performing a lookup
$tel_parts = extract_tel_digits($tel_no);
if ( ! is_array($tel_parts) )
{
return new XML_RPC_Response(0, $XML_RPC_erruser + 1, "Error: phone number invalid.");
}
if (! empty($response2) )
{
$num_lookups = 0;
$our_matches_all = array();
$response_no_tags = strip_tags($response2);
$response_no_tags = str_replace(' & ', ' and ', $response_no_tags);
// Make space after Mapquest links so that after HTML tags have been stripped, there is a space
// before the business name
/*
More stuff happens here ...
*/
// Populate and return new array with relevant information from $our_matches_all
}
}
Code for Auto-address Lookup (III)
XUL widgets population / JavaScript code
function getTelLookupData(tel_no)
{
set_waitbox('-- please wait --');
var methods = [];
try
{
var server = new xmlrpc.ServerProxy(globalXmlRpcServer, methods);
var lookup_data = server.getTelLookupData(tel_no); // calling remote XML_RPC function here!
// Automatic type conversion here from PHP assoc array to JS object
if ( lookup_data['rpc_msg'] != 'No reverse lookup matches found.' && lookup_data['rpc_msg'] !=
'Reverse Lookup: an error has occured.' )
{
document.getElementById('b_name').value = lookup_data['b_name'];
document.getElementById('b_phone').value = lookup_data['b_phone'];
last_phone_num_lookup = lookup_data['b_phone'];
document.getElementById('b_street_address').value = lookup_data['b_street_address'];
document.getElementById('b_city').value = lookup_data['b_city'];
document.getElementById('b_state').value = lookup_data['b_state'];
document.getElementById('b_zip').value = lookup_data['b_zip'];
}
else
{
// Turn off auto lookup if no phone number has been found, or if an error has occured
toggleReverseLookup();
toggleALButton();
}
set_waitbox( lookup_data['rpc_msg'] );
}
catch(e)
{
set_waitbox('Error:' . e);
alert(e);
}
}
Automagical zip population
Similarly, when an entry is made and both zip codes are left blank, they are
looked up.
<hbox>
<label control="b_neighborhood" value="Neighborhood:"
style="width:100px;" />
</menupopup>
</menulist>
</hbox>
Note: neighborhood values are dynamically added using the DOM via
JavaScript
JavaScript Code for Dynamic Neighborhood
Drop-down Population
//Get a list of distinct neighborhoods from the entries table
function getAllNeighborhoods()
{
var methods = [];
try
{
var server = new xmlrpc.ServerProxy(globalXmlRpcServer, methods);
var all_neighborhoods = server.getAllNeighborhoods(); // calling remote XML_RPC function here!
if (neighborhood)
{
menuList.appendItem(neighborhood, neighborhood);
menuList2.appendItem(neighborhood, neighborhood);
}
catch(e)
{
alert(e);
}
}
PHP Code for Dynamic Neighborhood
Drop-down Population
//Get a list of all distinct neighborhoods in the entries table
function get_all_neighborhoods()
{
global $username, $password, $server, $database, $mailing_table;
global $XML_RPC_erruser;
$dbh = DB::connect("mysql://$username:$password@$server/$database");
if ( DB::isError($dbh) )
// CHECK PEAR DB CONNECTION ERRORS
{
// Return XML-RPC fault
return new XML_RPC_Response(0, $XML_RPC_erruser + 1, "DB Error: Could not connect to server.");
}
else
{
// Retrieve list of distinct neighborhoods
$dbh->setFetchMode(DB_FETCHMODE_ASSOC);
if ( DB::isError($mlist_neigh) )
// CHECK FOR PEAR DB / QUERY RUN ERRORS
{
return new XML_RPC_Response(0, $XML_RPC_erruser + 2, "DB Error: Could not run query.");
}
else
{
$retval = XML_RPC_encode($mlist_neigh);
return new XML_RPC_Response($retval);
}
}
}
Nice feature: PEAR QF-like hier-select menus
Step 1: select category from editable-dropdown
Hierselect (Part II)
Step 2: select from list of subcategories pertaining to this category
Code for XUL Hierselect Menus
Code Link :
http://www.moztips.com/wiki/index.pcgi?page=XuLHierMenulists
Live Demo:
http://www.moztips.com/code/mozbugs/menulist/menulist_bug.php
Capitalizing on MySQL's FULLTEXT indexing
for listings search
● MySQL is great at storing, searching through and filtering data
●Japanese restaurants
●Vegetarian
More info.:
http://dev.mysql.com/doc/mysql/en/fulltext-search.html
MySQL FULLTEXT Search Example (I)
Content Administrator's View
MySQL FULLTEXT Search Example (II)
End User's View
Problem with rich web applications and large datasets:
things can slow down, instead of speeding up
●Use an alternative data transport format, such as JSON (JavaScript Object Notation)
Techniques for Optimizing Rich Web Applications for Speed
(On to-do list)
●Intelligently cache data locally in either JavaScript arrays or XML files
●Local XML file caching is more complicated, as Firefox requires local file access
●Ensure that JSolait library does not request list of remote methods on each web service request
●When data for one listing is retrieved, also preload data into JavaScript array for surrounding 10 listings
●Only reload data from remote DB when data on the client side is stale
Example:
{"myname":"Jay","place":"New York"}
PHP Equivalent:
array('myname' => 'Jay', 'place' => 'New York')
How to Get Data via JSON
* Mozilla reads this object literal string from the PHP-generated page,
converts it into a JavaScript Object / Assocative Array,
using the eval() function
init_urllib.js
// init_urllib.js
var urllib=null;
try
{
var urllib = importModule("urllib");
}
catch(e)
{
reportException(e);
throw "importing of urllib module failed.";
}
Some JSON Request Code (II)
HTML / PHP Page:
<!--
This page is:
http://localhost/json/test_json.html /
http://localhost/json/test_json.php
-->
<script type="application/x-javascript" src="jsolait/init.js"> </script>
<script type="application/x-javascript" src="jsolait/init_urllib.js"> </script>
<script type="application/x-javascript" src="jsolait/lib/urllib.js"> </script>
<script type="application/x-javascript">
var rslt = urllib.sendRequest("get", "http://localhost/json/test_json.php");
if (rslt.status == '200')
{
jsonSerialized = rslt.responseText;
<?php
// test_json.php
require_once('JSON.php');
$json = new JSON();
(bonus material)
Powering the End-User Site with PEAR XML-RPC Client
and PEAR Sigma Templating System (II)
(bonus material)
if ( strlen($s) > 0 )
{
$client = new XML_RPC_Client($xmlrpcpath, $xmlrpcserver, 80);
$client->setCredentials($xmlrpcusername, $xmlrpcpassword);
$return_value = $response->value();
$search_results = XML_RPC_decode($return_value);
$num_s = count($search_results);
for ($j = 0; $j < $num_s; $j++)
{
$row = $search_results[$j];
$tpl->setVariable(
array(
'name' => $name,
'id' => $row['id'],
'street_address' => $row['street_address'],
'address2' => $row['address2'],
'cross_streets' => $row['cross_streets'],
'city' => $row['city'],
'state' => $row['state'],
'neighborhood' => $row['neighborhood']) );
$tpl->parse('sitem_block');
}
$tpl->show(); // Display the newly created HTML file
}
else {$tpl->show(); // Display the newly created HTML file}
?>
Powering the End-User Site with PEAR XML-RPC Client
and PEAR Sigma Templating System (III)
(bonus material) S
Sigma Template Code Excerpt i
<html>
g
<head>
<title>Brooklyn and Beyond </title> m
</head>
<body>
<div class="mainbody">
a
<h3> Search Listings </h3>
<p>{num_results_msg}</p>
<p>{no_results_msg}</p> g
<p> {search_tip} </p> h
<!-- BEGIN sitem_block -->
<ul>
<li>
<strong><a href="detail.php?id={id}">{name}</a></strong>
<br />
{street_address}
<br />
{cross_streets}
<br />
{city}
<br />
{state}
<br />
{neighborhood}
</li>
</ul>
<!-- END sitem_block -->
</div>
</body>
</html>
Conclusions
●Having each component separated from the other makes for 'hot-swappable'
Suppose you would like to migrate from MySQL to PostgresQL for the datastore. Simply
import your data into PostgresQL, change the PEAR DB DSN strings in the central
business hub, and modify queries slightly to account for the differences between
MySQL and PostgresQL.