<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Not Just a Hat Rack &#187; AJAX</title>
	<atom:link href="http://notjustahatrack.com/posts/category/ajax/feed/" rel="self" type="application/rss+xml" />
	<link>http://notjustahatrack.com</link>
	<description>Development, design, etc.</description>
	<lastBuildDate>Mon, 18 Apr 2011 16:05:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.4</generator>
		<item>
		<title>Cross-Domain AJAX with DOMAssistant</title>
		<link>http://notjustahatrack.com/posts/cross-domain-ajax-with-domassistant/</link>
		<comments>http://notjustahatrack.com/posts/cross-domain-ajax-with-domassistant/#comments</comments>
		<pubDate>Fri, 22 Aug 2008 19:37:20 +0000</pubDate>
		<dc:creator>andrew</dc:creator>
				<category><![CDATA[(X)HTML]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://notjustahatrack.com/?p=28</guid>
		<description><![CDATA[In a previous post I mentioned that I would revisit cross-domain AJAX calls to measure the helpfulness of JavaScript frameworks like DOMAssistant and Prototype. In this post I&#8217;ll use DOMAssistant to perform the same basic tests I did previously, while evaluating the potential increase in efficiency. Creating a XMLHttp Object The first thing you&#8217;ll notice [...]]]></description>
			<content:encoded><![CDATA[<p>In a <a href="/posts/cross-domain-ajax-without-javascript-frameworks/">previous post</a> I mentioned that I would revisit cross-domain AJAX calls to measure the helpfulness of JavaScript frameworks like <a href="http://www.domassistant.com/">DOMAssistant</a> and <a href="http://www.prototypejs.org/">Prototype</a>.  In this post I&#8217;ll use DOMAssistant to perform the same basic tests I did previously, while evaluating the potential increase in efficiency.<span id="more-28"></span></p>
<h3>Creating a <code>XMLHttp</code> Object</h3>
<p>The first thing you&#8217;ll notice when using the aid of a JavaScript framework AJAX library is that you don&#8217;t have to bother creating a <code>XMLHttp</code> object.  That means right off the bat you&#8217;ll save yourself some (often painful) cross-browser scripting.  You can also be assured that any future improvements to this object implementation will be delivered to your code as long as you keep the framework updated.  Thank you JavaScript frameworks!</p>
<h3>Setting Up and Sending the Request</h3>
<p>Here&#8217;s the code I wrote earlier to perform both get and post requests without the help of a framework:</p>
<pre><code>
// Create and send an XMLHttp request
function doRequest(url, postVars) {
	// Get the request object (see previous function)
	req = getReqObject()
	// Make sure we have a XMLHttp object created
	if (req) {
		// If it's a post, we have to create and send the request slightly differently.
		if (postVars) {
			req.open('POST', url, true);
			req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			req.send(postVars);
		} else {
			req.open('GET', url, true);
			req.send(null);
		}
		// Set the function that handles the results
		req.onreadystatechange = function () { displayContents(req) };
	}
}

// Request via GET
doRequest('test.php?var=1', null);

// Request via POST
doRequest('test.php', 'var=1');
</code></pre>
<p>With DOMAssistant, you have to decide before your call what you are going to do with the data.  For simple calls where you just need to return the text, you can use the library&#8217;s <code>get</code> or <code>post</code> methods:</p>
<pre><code>
// Request via GET
DOMAssistant.AJAX.get('test.php?var=1', displayContents);

// Request via POST
DOMAssistant.AJAX.post('test.php?var=1', displayContents);
</code></pre>
<p>However, if you need an XML result that you can parse (like in our working example), you&#8217;ll need to make more complex calls:</p>
<pre><code>
// Create and send an XMLHttp request
function doRequest(url, postVars) {
	// If it's a post, we have to create and send the request slightly differently.
	if (postVars) {
		DOMAssistant.AJAX.ajax({
			url: url,
			method: "POST",
			params : postVars,
			callback: displayContents,
			responseType: "xml",
			headers : {
				"Content-type" : "application/x-www-form-urlencoded"
			}
		});
	} else {
		DOMAssistant.AJAX.ajax({
			url: url,
			method: "GET,
			callback: displayContents,
			responseType: "xml"
		});
	}
	// Set the function that handles the results
	req.onreadystatechange = function () { displayContents(req) };
}

// Request via GET
doRequest('test.php?var=1', null);

// Request via POST
doRequest('test.php', 'var=1');
</code></pre>
<p>As you can see, if you need an XML document for additional post-processing, you&#8217;ll end up with almost as much code with DOMAssistant!</p>
<h3>Handling the Result</h3>
<p>Here&#8217;s the function I wrote to alert specific data from the response content:</p>
<pre><code>
// Display resulting content from req
function displayContents(req) {
	// Only do something when the request is done
	if (req.readyState == 4) {
		// Make sure it was a success
		if (req.status == 200) {
			// Traverse the resulting XML, alerting titles of items
			var xml = req.responseXML;
			var items = xml.getElementsByTagName("item");
			for (var i = 0; i &lt; items.length; i++) {
				alert(items[i].getElementsByTagName('title').item(0).firstChild.nodeValue);
			}
		} else {
			alert('Problem with the request.');
		}
	}
}
</code></pre>
<p>An odd thing about DOMAssistant is that your specified callback function is hardcoded in the framework to be executed after the request is complete.  This means you won&#8217;t be able to troubleshoot based on the ready state of the request.  I also found that the callback function doesn&#8217;t have access to the status of the completed request, meaning you won&#8217;t know if your request was successful or not.  I&#8217;m sure there were logical reasons by the developers for this, but in the meantime all you can do is work with the response text.</p>
<p>If you used the <code>get</code> or <code>post</code> methods, you&#8217;ll be provided the text of the response:</p>
<pre><code>
// Display resulting content from responseText
function displayContents(rText) {
	alert(rText);
}
</code></pre>
<p>For our example, we needed an XML document, and as such we need to loop through and extract the information in much the same manner as we did before:</p>
<pre><code>
// Display resulting content from req
function displayContents(rXML) {
	var items = rXML.getElementsByTagName("item");
	for (var i = 0; i &lt; items.length; i++) {
		alert(items[i].getElementsByTagName('title').item(0).firstChild.nodeValue);
	}
}
</code></pre>
<p>As you can see there really isn&#8217;t <em>any</em> difference here except that DOMAssistant actually limits our troubleshooting capabilities.</p>
<h3>Cross-Domain Requests</h3>
<p>JavaScript frameworks don&#8217;t provide a built-in solution for addressing cross-domain request security issues.  In fact, the Prototype documentation makes this extremely prominent at the top of their documentation:</p>
<blockquote><p>
Remember that for security reasons (that is preventing cross-site scripting attacks) Ajax requests can only be made to URLs of the same protocol, host and port of the page containing the Ajax request. Some browsers might allow arbitrary URLs, but you shouldn&#8217;t rely on support for this.
</p></blockquote>
<h3>Conclusion</h3>
<p>All in all I&#8217;m rather disappointed with DOMAssistant&#8217;s AJAX library.  For very simple tasks like grabbing, posting and printing text it works great.  But for complicated cases, it offers little to no benefit.  It could be effective if used in conjunction with a more complex server-side proxy, so that the proxy could handle parsing and the DOMAssistant would just have to retrieve and display text.  Next time I&#8217;ll take a look at Prototype, and see if it offers more flexible and comprehensive functionality.</p>
]]></content:encoded>
			<wfw:commentRss>http://notjustahatrack.com/posts/cross-domain-ajax-with-domassistant/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cross-Domain AJAX without JavaScript Frameworks</title>
		<link>http://notjustahatrack.com/posts/cross-domain-ajax-without-javascript-frameworks/</link>
		<comments>http://notjustahatrack.com/posts/cross-domain-ajax-without-javascript-frameworks/#comments</comments>
		<pubDate>Tue, 05 Aug 2008 03:24:07 +0000</pubDate>
		<dc:creator>andrew</dc:creator>
				<category><![CDATA[(X)HTML]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://notjustahatrack.com/?p=23</guid>
		<description><![CDATA[Update (8/22/2008): Evaluated Cross-Domain AJAX with DOMAssistant. AJAX applications have become commonplace, but many of the tutorials for developing them lean heavily on the help of JavaScript frameworks like DOMAssistant or Prototype. So I figured I would take a look at the standard AJAX-related properties and methods, see how cross-domain calls make the whole process [...]]]></description>
			<content:encoded><![CDATA[<div class="callout">
<p>Update (8/22/2008): Evaluated <a href="http://notjustahatrack.dev.com/posts/cross-domain-ajax-with-domassistant/">Cross-Domain AJAX with DOMAssistant</a>.</p>
</div>
<p>AJAX applications have become commonplace, but many of the tutorials for developing them lean heavily on the help of JavaScript frameworks like <a href="http://www.domassistant.com/">DOMAssistant</a> or <a href="http://www.prototypejs.org/">Prototype</a>.  So I figured I would take a look at the standard AJAX-related properties and methods, see how cross-domain calls make the whole process slightly more complicated, and find out how much the frameworks can actually help.  Without the help of a framework, you basically have three steps to display content obtained via AJAX:<span id="more-23"></span></p>
<ul>
<li>Create a <code>XMLHttp</code> object</li>
<li>Setup and send the request</li>
<li>Display the resulting content</li>
</ul>
<p><!--more--></p>
<h3>Creating a <code>XMLHttp</code> Object</h3>
<p><code>XMLHTTP</code> was <a href="http://en.wikipedia.org/wiki/XMLHttpRequest">originally created by Microsoft</a> and is still in use today.  Other major browsers have adopted the same functionality, but in their <code>XMLHttpRequest</code> object.  Since the functionality of both objects is almost identical, we only need to take the separate initialization into account for our code to work cross-browser:</p>
<pre><code>
var req;
// Get the XMLHttp object based on browser support
function getReqObject() {
	// If it supports XMLHttpRequest, use that
	if (window.XMLHttpRequest) {
		req = new XMLHttpRequest();
		// Fix a bug for certain browsers that support this object
		if (req.overrideMimeType) {
			req.overrideMimeType('text/xml');
		}
	}
	// Otherwise (IE)
	else if (window.ActiveXObject) {
		// Try two versions
		try {
			req = new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch (e) {
			try {
				req = new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch (e) {}
		}
	}
	// Make sure we have the object
	if (!req) {
		alert('Could not create an XMLHTTP instance.');
		return false
	} else {
		return req
	}
}
</code></pre>
<h3>Setting Up and Sending the Request</h3>
<p>The next step is to set up the request, send it, and specify a function to handle the result:</p>
<pre><code>
// Create and send an XMLHttp request
function doRequest(url, postVars) {
	// Get the request object (see previous function)
	req = getReqObject()
	// Make sure we have a XMLHttp object created
	if (req) {
		// If it's a post, we have to create and send the request slightly differently.
		if (postVars) {
			req.open('POST', url, true);
			req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			req.send(postVars);
		} else {
			req.open('GET', url, true);
			req.send(null);
		}
		// Set the function that handles the results
		req.onreadystatechange = function () { displayContents(req) };
	}
}

// Request via GET
doRequest('test.php?var=1', null);

// Request via POST
doRequest('test.php', 'var=1');
</code></pre>
<p>Notice that the code is slightly different depending on whether you submit using <code>GET</code> or <code>POST</code>.  You can read more about <a href="http://javascript.about.com/od/ajax/a/ajaxgp.htm">the merits of using <code>GET</code> vs. <code>POST</code></a>, but basically use <code>GET</code> unless the submission updates a data source, or if it is very large.</p>
<p>We also specified a function to fire whenever the &#8220;ready state,&#8221; of the request changes.  This is the function that will handle the result.</p>
<h3>Handling the Result</h3>
<p>We&#8217;ve sent the request, now we need to create the function to do something with the result:</p>
<pre><code>
// Display resulting content from req
function displayContents(req) {
	// Only do something when the request is done
	if (req.readyState == 4) {
		// Make sure it was a success
		if (req.status == 200) {
			// Traverse the resulting XML, alerting titles of items
			var xml = req.responseXML;
			var items = xml.getElementsByTagName("item");
			for (var i = 0; i < items.length; i++) {
				alert(items[i].getElementsByTagName('title').item(0).firstChild.nodeValue);
			}
		} else {
			alert('Problem with the request.');
		}
	}
}
</code></pre>
<p>This function ensures the request is completed and that is successful, then traverses the resulting document, alerting the "titles" of "items." Obviously you'll have to substitute the method of crawling the <code>DOM</code> depending on the resulting document.  But that should be it right?  Well, not exactly.</p>
<h3>Cross-Domain Requests</h3>
<p>Due to <a href="http://developer.yahoo.com/javascript/howto-proxy.html">security concerns</a>, the previous code will only work for requests within your particular domain.  So what if you want to grab data from an RSS feed hosted on an outside site?  You've got a couple of options:</p>
<ul>
<li>Create a server-side proxy to grab content</li>
<li>Use apache's <code>mod_rewrite</code> or <code>mod_proxy</code> to mask outside requests</li>
<li>Hope the service you're trying to access can output JSON</li>
<li>Digitally sign your scripts.</li>
</ul>
<p>We can't rely on services providing JSON output because it's not widely adopted yet, and we can't digitally sign our scripts, because browser support for that is limited.  Using <code>mod_rewrite</code> is definitely an option, but a server-side proxy is more extensible given the additional options for server-side processing before the content gets back to our JavaScript.  Here's a basic PHP proxy, which will accept a URL and (optionally) post variables from a JavaScript call, and return the content.</p>
<pre><code>
&lt;?php
// Set URL we want to access
$url = ( $_POST['url'] ? $_POST['url'] : $_GET['url'] );

// Open Curl session
$session = curl_init($url);

// Set params if posted
if ($_POST['params']) {
	$postvars = '';
	foreach ($_POST['params'] as $postkey=>$postvalue) {
		$postvars .= $postkey . '=' . $postvalue . '&#038;';
	}
	curl_setopt($session, CURLOPT_POST, true);
	curl_setopt($session, CURLOPT_POSTFIELDS, $postvars);
}

// Don't return HTTP headers, do return contents
curl_setopt($session, CURLOPT_HEADER, false);
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);

// Get the file
$xml = curl_exec($session);

// Display content
if ($xml) {
	header("Content-Type: text/xml");
	echo $xml;
} else {
	echo 'No response';
}

// Clean up
curl_close($session)
?&gt;
</code></pre>
<p>Now we can make external requests with our JavaScript:</p>
<pre><code>
// External request using proxy via GET
doRequest('proxy.php?url=http://externalsite.com/feed.php', null);

// External request using proxy via POST
doRequest('proxy.php', 'url=http://externalsite.com/feed.php');
</code></pre>
<p>That's it!  Next time I'll take a look at some JavaScript frameworks and see how they can be used to simplify some of this process.</p>
]]></content:encoded>
			<wfw:commentRss>http://notjustahatrack.com/posts/cross-domain-ajax-without-javascript-frameworks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

