GetRemoteURI(); }
function sajax_handle_client_request() { Sajax::Sajax()->HandleRequest(); }
function sajax_get_common_js() { return Sajax::Sajax()->GetClientJS(); }
function sajax_show_common_js() { echo Sajax::Sajax()->GetClientJS(); }
function sajax_esc($val) { return Sajax::Sajax()->Escape($val); }
function sajax_get_one_stub($func_name) { return Sajax::Sajax()->GetStubJS($func_name); }
function sajax_show_one_stub($func_name) { echo Sajax::Sajax()->GetStubJS($func_name); }
function sajax_export() { $args = func_get_args(); call_user_func_array(array(Sajax::Sajax(), 'Export'), $args); }
function sajax_get_javascript() { return Sajax::Sajax()->GetJS(); }
function sajax_show_javascript($renderScriptTag = false) { Sajax::Sajax()->ExportBlockJS(); }
/**
* Sajax Singleton Implementation.
*/
final class Sajax
{
private static $Sajax = null;
/**
* Additional JavaScript blocks we'll render script include tags for.
*/
private $Scripts = array();
/**
* Additional inline JavaScript blocks to render in HEAD.
*/
private $ScriptBlocks = array();
/**
* Hopefully helpful information to include in responses.
*/
private $DebugMessages = array();
/**
* Construct the Sajax object.
*/
private function __construct()
{
$this->Initialize();
}
/**
* Add a debug message to be included in response.
*/
public function AddDebugMessage($msg = '')
{
if(strlen($msg) > 0)
$this->DebugMessages[] = $msg;
}
/**
* Used internally to add an export.
*/
private function AddExport($export)
{
global $sajax_export_list;
$this->AddDebugMessage("Added $export to list of exports.");
$sajax_export_list[] = $export;
}
/**
* Add a block of JavaScript to render when the main client script is sent
* via ExportBlockJS().
*/
public function AddScriptBlock($block)
{
$this->ScriptBlocks[] = $block;
}
/**
* Add additional externally-referenced JavaScript \n";
$buffer = ob_get_clean();
echo $buffer;
$this->ScriptDisplayed = true;
}
/**
* Creates a JavaScript include tag to include the exported script.
*/
public function ExportIncludeJS()
{
$uri = $this->GetClientScriptURI();
print "\n\t\t\n";
foreach($this->Scripts as $script)
{
print "\n\t\t\n";
}
}
/**
* Returns all of the JavaScript stubs for the exported methods.
*/
public function GetAllStubJS()
{
global $sajax_export_list;
ob_start();
foreach($sajax_export_list as $func_name)
{
echo $this->GetStubJS($func_name);
}
return ob_get_clean();
}
/**
* Renders the main JavasScript content to be used by the client as a string.
*/
public function GetClientJS()
{
global $sajax_debug_mode;
global $sajax_request_type;
global $sajax_remote_uri;
global $sajax_failure_redirect;
$t = strtoupper($sajax_request_type);
if ($t != "" && $t != "GET" && $t != "POST")
return "// Invalid type: $t.. \n\n";
ob_start();
?>
// remote scripting library
// (c) copyright 2005 modernmethod, inc
var sajax_debug_mode = ;
var sajax_request_type = "";
var sajax_target_id = "";
var sajax_failure_redirect = "";
function sajax_debug(text)
{
if (sajax_debug_mode)
alert(text);
}
function sajax_init_object()
{
sajax_debug("sajax_init_object() called..")
var A;
var msxmlhttp = new Array(
'Msxml2.XMLHTTP.5.0',
'Msxml2.XMLHTTP.4.0',
'Msxml2.XMLHTTP.3.0',
'Msxml2.XMLHTTP',
'Microsoft.XMLHTTP');
for (var i = 0; i < msxmlhttp.length; i++)
{
try
{
A = new ActiveXObject(msxmlhttp[i]);
}
catch (e)
{
A = null;
}
}
if(!A && typeof XMLHttpRequest != 'undefined')
A = new XMLHttpRequest();
if (!A)
sajax_debug('Could not create connection object.');
return A;
}
var sajax_requests = new Array();
function sajax_cancel()
{
for (var i = 0; i < sajax_requests.length; i++)
sajax_requests[i].abort();
}
function sajax_get_classname(obj)
{
if (obj && obj.constructor && obj.constructor.toString)
{
var arr = obj.constructor.toString().match( /function\s*(\w+)/);
if (arr && arr.length == 2)
return arr[1];
}
return 0;
}
function sajax_is_object(o)
{
var test = sajax_get_classname(o);
return (typeof o == 'object' && test != 'Array' ? true : false);
}
function sajax_do_call(func_name, args)
{
var i, x, n;
var uri;
var post_data;
var target_id;
sajax_debug("in sajax_do_call().." + sajax_request_type + "/" + sajax_target_id);
target_id = sajax_target_id;
if (typeof(sajax_request_type) == "undefined" || sajax_request_type == "")
sajax_request_type = "GET";
if (typeof args == 'object' && args.length > 1)
{
// Lame attempt at JSON encoding
for (var i=0; i 0) arg += ',';
with(o[j])
{
arg += '"'+escape((name.length == 0 ? '_unknown'+j : name))
+'":"'+o[j].value+'"';
}
}
arg += '}';
args[i] = arg;
}
}
}
uri = "";
if (sajax_request_type == "GET")
{
if (uri.indexOf("?") == -1)
uri += "?rs=" + escape(func_name);
else
uri += "&rs=" + escape(func_name);
uri += "&rst=" + escape(sajax_target_id);
uri += "&rsrnd=" + new Date().getTime();
for (i = 0; i < args.length-1; i++)
uri += "&rsargs[]=" + escape(args[i]);
post_data = null;
}
else if (sajax_request_type == "POST")
{
post_data = "rs=" + escape(func_name);
post_data += "&rst=" + escape(sajax_target_id);
post_data += "&rsrnd=" + new Date().getTime();
for (i = 0; i < args.length-1; i++)
post_data = post_data + "&rsargs[]=" + escape(args[i]);
}
else
{
alert("Illegal request type: " + sajax_request_type);
}
x = sajax_init_object();
if (x == null)
{
if (sajax_failure_redirect != "")
{
location.href = sajax_failure_redirect;
return false;
}
else
{
sajax_debug("NULL sajax object for user agent:\n" + navigator.userAgent);
return false;
}
}
else
{
x.open(sajax_request_type, uri, true);
// window.open(uri);
sajax_requests[sajax_requests.length] = x;
if (sajax_request_type == "POST")
{
x.setRequestHeader("Method", "POST " + uri + " HTTP/1.1");
x.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
}
x.onreadystatechange = function()
{
if (x.readyState != 4)
return;
sajax_debug("received " + x.responseText);
var status;
var data;
var txt = x.responseText.replace(/^\s*|\s*$/g,"");
status = txt.charAt(0);
data = txt.substring(2);
if (status == "")
{
// let's just assume this is a pre-response bailout and let it slide for now
}
else if (status == "-")
alert("Error: " + data);
else
{
if (target_id != "")
document.getElementById(target_id).innerHTML = eval(data);
else
{
try
{
var callback;
var extra_data = false;
if (typeof args[args.length-1] == "object") {
callback = args[args.length-1].callback;
extra_data = args[args.length-1].extra_data;
}
else
{
callback = args[args.length-1];
}
callback(eval(data), extra_data);
}
catch (e)
{
sajax_debug("Caught error " + e + ": Could not eval " + data );
}
}
}
}
}
sajax_debug(func_name + " uri = " + uri + "/post = " + post_data);
x.send(post_data);
sajax_debug(func_name + " waiting..");
delete x;
return true;
}
function sajaxObject()
{
this.version = '0.14';
}
var sajax = new sajaxObject();
ScriptURI))
return $this->ScriptURI;
$uri = $this->GetRemoteURI();
$uri .= (strpos($uri, '?') > 0 ? "&gcs=true" : "?gcs=true");
return $uri;
}
/**
* Used to determine what the JavaScript name for a method is.
*/
private function GetExportName($fname)
{
return str_replace('::', '__', $fname);
}
/**
* Returns a string representing all the JavaScript to be exported
* to the client.
*/
public function GetJS()
{
ob_start();
echo $this->GetClientJS();
echo $this->GetAllStubJS();
foreach($this->ScriptBlocks as $block)
{
print "\n$block\n";
}
return ob_get_clean();
}
/**
* Renders the JavaScript stub for a single exported method.
*/
public function GetStubJS($fname)
{
ob_start();
$func_name = str_replace('::', '__', ($smart_name = $fname));
if(strpos($smart_name, '::') > 0)
{
$smart_name = str_replace('::', '__',
substr($fname, strpos($fname, '::')+2));
}
if(preg_match('/^Sajax.+/', $smart_name))
{
$smart_name = substr($smart_name, 5);
}
?>
// Stub for
function x_()
{
sajax_do_call("", x_.arguments);
}
sajax. = x_;
RemoteURI) ? $this->RemoteURI :
(isset($GLOBALS['sajax_remote_uri']) ?
$GLOBALS['sajax_remote_uri'] :
$_SERVER['REQUEST_URI']));
}
/**
* Handle a method call for the client.
*/
public function HandleRequest()
{
global $sajax_export_list, $sajax_debug_mode;
if (!empty($_GET["gcs"]) && empty($_REQUEST["rs"]))
{
header ("Content-Type: text/javascript;");
echo $this->GetJS();
exit;
}
if (! empty($_GET["rs"]))
$mode = "get";
if (!empty($_POST["rs"]))
$mode = "post";
if (!isset($mode))
return;
$target = "";
if ($mode == "get")
{
// Bust cache in the head
header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header ("Expires: " . gmdate("D, d M Y H:i:s", (time() - 86400)) . " GMT");
// always modified
header ("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header ("Pragma: no-cache"); // HTTP/1.0
$func_name = $_GET["rs"];
if (! empty($_GET["rsargs"]))
$args = $_GET["rsargs"];
else
$args = array();
}
else
{
$func_name = $_POST["rs"];
if (! empty($_POST["rsargs"]))
$args = $_POST["rsargs"];
else
$args = array();
}
// Decode JSON representations of objects.
if(count($args) > 0)
{
for($i=0;$iResponseError($err);
}
else
{
if(strrpos($func_name, '::'))
{
$p = strrpos($func_name, '::');
$ns = substr($func_name, 0, $p);
$mn = substr($func_name, $p+2);
$this->AddDebugMessage("Calling object method: $func_name()");
if(!class_exists($ns))
$this->ResponseError("Class '$ns' not loaded in namespace.");
else
{
$o = new $ns;
$func_name = array(new $ns, $mn);
if(!method_exists($o, $mn))
$this->ResponseError("Method '$mn' not implemented in class '$ns'.");
}
}
if(!is_callable($func_name))
$this->ResponseError("The method ($func_name) was exported, but was NOT callable; verify that it exists.");
$result = call_user_func_array($func_name, $args);
$this->ResponseOK(trim(json_encode($result)));
}
}
public function Initialize()
{
}
/**
* Used to filter Sajax methods from an object.
*/
private function IsSajaxMethod($fname)
{
return (preg_match('/^Sajax.+/', $fname) > 0);
}
/**
* Send the response as an error.
*/
private function ResponseError($response)
{
echo "-:";
foreach($this->DebugMessages as $msg)
{
echo "\n/* $msg */ ";
}
echo "\n$response";
exit();
}
/**
* Send the response as successful.
*/
private function ResponseOK($response)
{
echo "+:";
foreach($this->DebugMessages as $msg)
{
echo "\n/* $msg */ ";
}
echo "\nvar res = " . $response . "; res;";
exit();
}
/**
* Get the singleton instance.
*/
public static function Sajax()
{
if(is_null(Sajax::$Sajax) || !isset(Sajax::$Sajax))
Sajax::$Sajax = new Sajax();
return Sajax::$Sajax;
}
/**
* Set the URI of the resource to dispatch requests.
*/
public function SetRemoteURI($uri = '')
{
if(strlen($uri) > 0)
$this->RemoteURI = $uri;
}
/**
* Set the URI of the JavaScript source for handling client requests.
*/
public function SetScriptURI($uri = '')
{
$this->AddDebugMessage("Setting alternate JS source: $uri");
if(strlen($uri))
$this->ScriptURI = $uri;
}
}
$SAJAX_INCLUDED = 1;
}
?>