<?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; PHP</title>
	<atom:link href="http://notjustahatrack.com/posts/category/php/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>Embeddable WYSIWYG Editors</title>
		<link>http://notjustahatrack.com/posts/embeddable-wysiwyg-editors/</link>
		<comments>http://notjustahatrack.com/posts/embeddable-wysiwyg-editors/#comments</comments>
		<pubDate>Wed, 20 Aug 2008 20:36:14 +0000</pubDate>
		<dc:creator>andrew</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://notjustahatrack.com/?p=27</guid>
		<description><![CDATA[I&#8217;ve had several projects in the past few months which have called for some limited content management capabilities. In cases like these, where only small sections of the site need to be handled by an administrator, it seems silly to build the entire site on top of existing CMS platforms like Joomla or Drupal. The [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve had several projects in the past few months which have called for some limited content management capabilities.  In cases like these, where only small sections of the site need to be handled by an administrator, it seems silly to build the entire site on top of existing CMS platforms like <a href="http://joomla.org/">Joomla</a> or <a href="http://drupal.org/">Drupal</a>. The problem is, if you build a small administration area, you&#8217;ll have to have some mechanism for specifying simple HTML content for the non-tech savvy.<span id="more-27"></span></p>
<p>A co-worker recommended <a href="http://fckeditor.net/">FCKeditor</a>, so I implemented it in a recent administration interface to control text for a few pages.  So far it&#8217;s worked extremely well, and was a breeze to implement.  Here&#8217;s a summary of my implementation:</p>
<ul>
<li><a href="http://www.fckeditor.net/download">Downloaded</a>, unzipped, and stored the FCKeditor files</li>
<li>Created a custom editor style file (myeditorstyles.css), and put the site&#8217;s content styling rules in it so the editor would mimic the site&#8217;s style</li>
<li>Created a custom configuration file (myconfig-default.js), which serves to remove a bunch of the unnecessary functionality, and reference the style:</li>
</ul>
<pre><code>
FCKConfig.FontFormats = 'h1;h2;h3;p';
FCKConfig.ToolbarCanCollapse = false;
FCKConfig.EditorAreaCSS = '/lib/includes/FCKeditor/myeditorstyles.css';
FCKConfig.ToolbarSets[&quot;Default&quot;] = [
	['Save'],
	['Undo','Redo'],
	['Bold','Italic','Underline'],
	['OrderedList','UnorderedList','-','Outdent','Indent'],
	['JustifyLeft','JustifyCenter','JustifyRight','JustifyFull'],
	['Link','Unlink'],
	['FontFormat'],
	['About', 'Source']
];
</code></pre>
<ul>
<li>Included the initialization files on the pages I put the editor:</li>
</ul>
<pre><code>
&lt;?php
include_once(&quot;[myeditorpath]/fckeditor.php&quot;) ;
?&gt;
</code></pre>
<ul>
<li>Then referenced the editor where I wanted to add it in my code:</li>
</ul>
<pre><code>
$oFCKeditor = new FCKeditor([myeditorid]);
$oFCKeditor-&gt;BasePath = '/[myeditorpath]/';
$oFCKeditor-&gt;Config[&quot;CustomConfigurationsPath&quot;] = &quot;/[myeditorpath]/myconfig-default.js&quot;;
$oFCKeditor-&gt;Height = '500';
$oFCKeditor-&gt;Create();
</code></pre>
<p>That&#8217;s it!  There&#8217;s a ton of other customization options, help with implementation, and general resources in <a href="http://docs.fckeditor.net/">the documentation</a>.</p>
<h3>Other Options</h3>
<p>I highly recommend FCKeditor, but if it doesn&#8217;t work for some reason you can always try <a href="http://tinymce.moxiecode.com/">TinyMCE</a> or <a href="http://openwebware.com/">openwysiwyg</a>.  Both seem full-featured and easy to implement, and both have significant recent activity.  </p>
<p>If you think content won&#8217;t require any additional HTML formatting, you could always just programmatically replace line breaks in text areas with HTML line breaks and vice versa.  This would allow the administrator to use carriage returns to separate text, but would require some HTML knowledge for additional formatting.</p>
]]></content:encoded>
			<wfw:commentRss>http://notjustahatrack.com/posts/embeddable-wysiwyg-editors/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>

