<?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>scriptNode &#187; script-sunday</title>
	<atom:link href="http://scriptnode.com/tag/script-sunday/feed/" rel="self" type="application/rss+xml" />
	<link>http://scriptnode.com</link>
	<description>Tips and tricks for web developers.</description>
	<lastBuildDate>Tue, 01 Sep 2009 18:46:41 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Making @Twitter Names Clickable</title>
		<link>http://scriptnode.com/article/making-twitter-names-clickable/</link>
		<comments>http://scriptnode.com/article/making-twitter-names-clickable/#comments</comments>
		<pubDate>Mon, 31 Aug 2009 07:10:32 +0000</pubDate>
		<dc:creator>Matt Hackett</dc:creator>
				<category><![CDATA[Novice]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[regex]]></category>
		<category><![CDATA[script-sunday]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://scriptnode.com/?p=334</guid>
		<description><![CDATA[
Here&#8217;s a super quick Script Sunday for you: making @Twitter usernames clickable. Here&#8217;s an example:


@scriptnode

Should be:

@&#60;href="http://twitter.com/scriptnode"&#62;scriptnode&#60;/a&#62;

Which looks like:

@scriptnode


And here&#8217;s how to do it in PHP and JavaScript:

PHP

$text = preg_replace(&#8217;#@([a-z0-9_]+)#i&#8217;, &#8216;@&#60;a href=&#8221;http://twitter.com/\\1&#8243;&#62;\\1&#60;/a&#62;&#8217;, $text);


That was easy! Now let&#8217;s get to the more interesting JavaScript, which allows us to test inline!

JavaScript

text = text.replace(/@([a-z0-9_]+)/gi, &#8216;@&#60;a href=&#8221;http://twitter.com/$1&#8243;&#62;$1&#60;/a&#62;&#8217;);


You can run this [...]]]></description>
			<content:encoded><![CDATA[<p>
Here&#8217;s a super quick Script Sunday for you: making @Twitter usernames clickable. Here&#8217;s an example:
</p>
<p>
<code>@scriptnode</code>
</p>
<p>Should be:</p>
<p>
<code>@&lt;href="http://twitter.com/scriptnode"&gt;scriptnode&lt;/a&gt;</code>
</p>
<p>Which looks like:</p>
<p>
@<a href="http://twitter.com/scriptnode">scriptnode</a>
</p>
<p>
And here&#8217;s how to do it in PHP and JavaScript:
</p>
<h3>PHP</h3>
<p><textarea class="php" cols="50" name="code" rows="10"><br />
$text = preg_replace(&#8217;#@([a-z0-9_]+)#i&#8217;, &#8216;@&lt;a href=&#8221;http://twitter.com/\\1&#8243;&gt;\\1&lt;/a&gt;&#8217;, $text);<br />
</textarea></p>
<p>
That was easy! Now let&#8217;s get to the more interesting JavaScript, which allows us to test inline!
</p>
<h3>JavaScript</h3>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
text = text.replace(/@([a-z0-9_]+)/gi, &#8216;@&lt;a href=&#8221;http://twitter.com/$1&#8243;&gt;$1&lt;/a&gt;&#8217;);<br />
</textarea></p>
<p>
You can run this code right here:
</p>
<div class="section">
<p id="example-twitter-output">Some @<a href="http://twitter.com/test">test</a> code</p>
<input id="example-twitter-input" type="text" value="Some @test code">
</div>
<p>
<button onclick="YAHOO.twitterExample();">Format</button>
</p>
<p><script type="text/javascript">
<!--//
YAHOO.twitterExample = function() {
var text = document.getElementById('example-twitter-input').value;
text = text.replace(/@([a-z0-9_]+)/gi, '@<a href="http://twitter.com/$1">$1</a>');
document.getElementById('example-twitter-output').innerHTML = text;
};
//-->
</script></p>
<p>
I&#8217;m awful at regular expressions; please do let me know if I could optimize somewhere or if I missed something.<br />
<strong>Edit:</strong> <code>+</code> instead of <code>*</code></p>
]]></content:encoded>
			<wfw:commentRss>http://scriptnode.com/article/making-twitter-names-clickable/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Simple Loading Bar</title>
		<link>http://scriptnode.com/article/simple-loading-bar/</link>
		<comments>http://scriptnode.com/article/simple-loading-bar/#comments</comments>
		<pubDate>Mon, 03 Aug 2009 06:56:36 +0000</pubDate>
		<dc:creator>Matt Hackett</dc:creator>
				<category><![CDATA[Novice]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[lab]]></category>
		<category><![CDATA[script-sunday]]></category>

		<guid isPermaLink="false">http://scriptnode.com/?p=316</guid>
		<description><![CDATA[
Haven&#8217;t had a Script Sunday for a while, so here&#8217;s a quick, simple script for you. Ever see those Loading … overlay images and wonder if JavaScript can handle it? Turns out it&#8217;s extremely simple:


animate = (function() {
  var busy;
  return function(id) {
    if (busy) return;
    busy [...]]]></description>
			<content:encoded><![CDATA[<p>
Haven&#8217;t had a <a href="/tag/script-sunday/">Script Sunday</a> for a while, so here&#8217;s a quick, simple script for you. Ever see those <strong>Loading …</strong> overlay images and wonder if JavaScript can handle it? Turns out it&#8217;s extremely simple:
</p>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
animate = (function() {</p>
<p>  var busy;</p>
<p>  return function(id) {</p>
<p>    if (busy) return;</p>
<p>    busy = true;<br />
    var width = 0;<br />
    var interval = setInterval(function() {</p>
<p>      var el = document.getElementById(id);<br />
      el.innerHTML = &#8216;@%
<div style="width: @px;"><span>@%</span></div>
<p>&#8216;.replace(/@/g, width);</p>
<p>      if (width++ >= 100) {<br />
        busy = false;<br />
        clearInterval(interval);<br />
      }</p>
<p>    }, 50);</p>
<p>  };</p>
<p>})();<br />
</textarea></p>
<p>
You can view this by itself <a href="/lab/bar/">in the lab</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://scriptnode.com/article/simple-loading-bar/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JSQL: JavaScript Query Language</title>
		<link>http://scriptnode.com/article/jsql-javascript-query-language/</link>
		<comments>http://scriptnode.com/article/jsql-javascript-query-language/#comments</comments>
		<pubDate>Mon, 23 Mar 2009 06:12:20 +0000</pubDate>
		<dc:creator>Matt Hackett</dc:creator>
				<category><![CDATA[Advanced]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[lab]]></category>
		<category><![CDATA[script-sunday]]></category>

		<guid isPermaLink="false">http://scriptnode.com/?p=286</guid>
		<description><![CDATA[About JSQL

When I started my new job, I had to make the transition from YUI to jQuery. I&#8217;d seen some jQuery code before (in fact, its terseness and use of $ as both an object and a function were easy to spot), but I wasn&#8217;t familiar with it. I actually thought that the query part [...]]]></description>
			<content:encoded><![CDATA[<h3>About JSQL</h3>
<p>
When I started <a href="http://richter.paletteswap.com/why-i-left-yahoo-for-a-startup/">my new job</a>, I had to make the transition from <a href="http://developer.yahoo.com/yui/">YUI</a> to <a href="http://jquery.com/">jQuery</a>. I&#8217;d seen some jQuery code before (in fact, its terseness and use of <code>$</code> as both an object and a function were easy to spot), but I wasn&#8217;t familiar with it. I actually thought that the <em>query</em> part of jQuery meant there was some kind of <a href="http://mysql.com/">Standard Query Language</a> interface. There isn&#8217;t, but there is a really cool <a href="http://www.css3.info/">CSS3</a> selector instead.
</p>
<p>
Turns out, I was a little disappointed; I wanted to use something query-based. So, I started to throw this script together. I call it <acronym title="JavaScript Query Language">JSQL</acronym>. Below are some quick examples of what it looks like in action:
</p>
<p><script src="/assets/js/jsql/jsql-min.js" type="text/javascript"></script></p>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
var results = JSQL(&#8217;SELECT * FROM #ft WHERE nodeName = &#8220;LI&#8221;);<br />
</textarea></p>
<p>
JSQL always returns an object with an <code>error</code> property that&#8217;s either <code>Boolean false</code> or a <code>String</code> stating what error occurred (for example, &#8220;Unknown command UPDAT3&#8243;). If it successfully retrieves or operates on elements, it returns a <code>count:Number</code> property with the number of elements and an <code>elements:Array</code> property with those elements.
</p>
<p>
Here are some interactive examples:
</p>
<h3>Example 1: Checkboxes</h3>
<div class="section" id="jsql-example-1">
<div>
<input type="checkbox" value=""/> Option number 1
		</div>
<div>
<input type="checkbox" value=""/> Option number 2
		</div>
<div>
<input type="checkbox" value=""/> Option number 3
		</div>
</p></form>
</div>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
JSQL(&#8217;UPDATE #jsql-example-1 SET checked = true WHERE type = &#8220;checkbox&#8221;&#8216;);<br />
</textarea></p>
<p>
<button id="jsql-button-1">Set Checked</button>
</p>
<p><script type="text/javascript">
document.getElementById('jsql-button-1').onclick = function() {
JSQL('UPDATE #jsql-example-1 SET checked = true WHERE type = "checkbox"');
};
</script><br />
<textarea class="javascript" cols="50" name="code" rows="10"><br />
JSQL(&#8217;UPDATE #jsql-example-1 SET checked = false WHERE type = &#8220;checkbox&#8221;&#8216;);<br />
</textarea></p>
<p>
<button id="jsql-button-1a">Uncheck</button>
</p>
<p><script type="text/javascript">
document.getElementById('jsql-button-1a').onclick = function() {
JSQL('UPDATE #jsql-example-1 SET checked = false WHERE type = "checkbox"');
};
</script></p>
<h3>Example 2: Form Validation</h3>
<div class="section" id="jsql-example-2">
<p>
			First name:</p>
<input type="text" value=""/>
<p>
			Last name:</p>
<input type="text" value=""/>
<p>
			Email:</p>
<input type="text" value=""/>
</div>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
JSQL(&#8217;UPDATE #jsql-example-2 SET parentNode.className = &#8220;error&#8221; WHERE value = &#8220;&#8221;&#8216;);<br />
</textarea></p>
<p>
<button id="jsql-button-2">Highlight empty fields</button>
</p>
<p><script type="text/javascript">
document.getElementById('jsql-button-2').onclick = function() {
JSQL('UPDATE #jsql-example-2 SET parentNode.className = "error" WHERE value = ""');
};
</script><br />
<textarea class="javascript" cols="50" name="code" rows="10"><br />
JSQL(&#8217;UPDATE #jsql-example-2 SET parentNode.className = &#8220;&#8221; WHERE value = &#8220;&#8221;&#8216;);<br />
</textarea></p>
<p>
<button id="jsql-button-2a">Reset</button>
</p>
<p><script type="text/javascript">
document.getElementById('jsql-button-2a').onclick = function() {
JSQL('UPDATE #jsql-example-2 SET parentNode.className = "" WHERE value = ""');
};
</script></p>
<h3>Example 3: Removing Elements</h3>
<div class="section" id="jsql-example-3">
<strong>Lorem</strong> Ipsum is simply dummy text of the <strong>printing and</strong> typesetting industry. <strong>Lorem</strong> Ipsum has been the <strong>industry&#8217;s</strong> standard dummy text <strong>ever</strong> since the 1500s, when an unknown printer took a galley of type and scrambled it to make a <strong>type specimen</strong> book. It has survived not only <strong>five</strong> centuries, but also the leap into <strong>electronic</strong> typesetting<strong>, remaining essentially unchanged</strong>. It was popularised in the 1960s with the release of <strong>Letraset</strong> sheets containing <strong>Lorem Ipsum</strong> passages, and more recently with <strong>desktop publishing</strong> software like Aldus PageMaker including versions of <strong>Lorem</strong> Ipsum.
</div>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
JSQL(&#8217;DELETE FROM #jsql-example-3 WHERE nodeName = &#8220;STRONG&#8221;&#8216;);<br />
</textarea></p>
<p>
<button id="jsql-button-3">Remove strong tags</button>
</p>
<p><script type="text/javascript">
document.getElementById('jsql-button-3').onclick = function() {
JSQL('DELETE FROM #jsql-example-3 WHERE nodeName = "STRONG"');
};
</script></p>
<p>
In the spirit of jQuery, I also stuck in a quick <code>each</code> method which you can use to iterate through the returned elements immediately instead of setting up your own loop. The context is the current element (like jQuery) and the return value is still the same:</p>
<h3>Example 4: Selecting Elements</h3>
<div class="section" id="jsql-example-4">
Give him that <em>gun</em>. Give him <em>ALL</em> the guns.
</div>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
JSQL(&#8221;SELECT * FROM #jsql-example-4 WHERE nodeName = &#8216;EM&#8217;&#8221;).each(function() {<br />
	this.style.background = &#8216;#ffff00&#8242;;<br />
});<br />
</textarea></p>
<p>
<button id="jsql-button-4">Select &amp; Operate</button>
</p>
<p><script type="text/javascript">
document.getElementById('jsql-button-4').onclick = function() {
JSQL("SELECT * FROM #jsql-example-4 WHERE nodeName = 'EM'").each(function() {
	this.style.background = '#ffff00';
});
};
</script><br />
<textarea class="javascript" cols="50" name="code" rows="10"><br />
JSQL(&#8221;SELECT * FROM #jsql-example-4 WHERE nodeName = &#8216;EM&#8217;&#8221;).each(function() {<br />
	this.style.background = &#8221;;<br />
});<br />
</textarea></p>
<p>
<button id="jsql-button-4a">Undo</button>
</p>
<p><script type="text/javascript">
document.getElementById('jsql-button-4a').onclick = function() {
JSQL("SELECT * FROM #jsql-example-4 WHERE nodeName = 'EM'").each(function() {
	this.style.background = '';
});
};
</script></p>
<p>
I started coding this several months ago, and just recently decided to revisit it. I found the code hard to read myself when making some modifications before publishing it here. That typically means it&#8217;s poorly written. And I&#8217;m admittedly lousy at writing parsing code&#8230; so there&#8217;s that. I also doubt it&#8217;s realistic for any real-world websites (other libraries handle those jobs quite well), but I thought it would be fun to play with.
</p>
<p>
Some noticeable features lacking are equivalents to <code>ALTER</code> and <code>INSERT INTO</code>. I&#8217;ve also got it <a href="http://github.com/richtaur/jsql/tree/master">up on GitHub</a>, so feel free to fork it, and maybe add those methods yourself!
</p>
<ul>
<li><a href="/assets/js/jsql/jsql.js">[Download jsql.js]</a> (11k)</li>
<li><a href="/assets/js/jsql/jsql-min.js">[Download jsql-min.js]</a> (3,661 bytes)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://scriptnode.com/article/jsql-javascript-query-language/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Simple Cookie Script</title>
		<link>http://scriptnode.com/article/simple-cookie-script/</link>
		<comments>http://scriptnode.com/article/simple-cookie-script/#comments</comments>
		<pubDate>Sun, 19 Oct 2008 09:22:23 +0000</pubDate>
		<dc:creator>Matt Hackett</dc:creator>
				<category><![CDATA[Novice]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[script-sunday]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://scriptnode.com/?p=222</guid>
		<description><![CDATA[
I often chat with a lot of new JavaScript developers. Many of their questions are really easy and can be answered with single-line responses, such as, &#8220;How do you append to an array?&#8221;


myArray.push(thevalue);


Easy stuff. What&#8217;s unfortunate, though, is when the questions are a bit more involved, and these developers have already searched around a bit [...]]]></description>
			<content:encoded><![CDATA[<p>
I often <a href="irc://irc.freenode.org/#javascript">chat</a> with a lot of new JavaScript developers. Many of their questions are really easy and can be answered with single-line responses, such as, &#8220;How do you append to an array?&#8221;
</p>
<p><textarea class="javascript" cols="50" name="code" rows="5"><br />
myArray.push(thevalue);<br />
</textarea></p>
<p>
Easy stuff. What&#8217;s unfortunate, though, is when the questions are a bit more involved, and these developers have already searched around a bit and found lousy code to read and learn from. The problem is that there&#8217;s much ancient, <a href="http://www.w3schools.com/js/default.asp">awful JavaScript code</a> out there, and when performing simple search queries, these sites come up. My goal is to improve this process.
</p>
<p>
One common topic is that of cookies. Dealing with cookies is really basic stuff, but hey, that&#8217;s what the <a href="http://scriptnode.com/category/novice/">novice category</a> is for. So here&#8217;s a simple script to assist with managing cookies:
</p>
<p><textarea class="javascript" cols="50" name="code" rows="5"><br />
/**<br />
 * Global cookies object to manage cookies<br />
 * @return {Object} The exposed methods<br />
 * @public<br />
 */<br />
var cookies = (function() {</p>
<p>	/**<br />
	 * Gets a cookie&#8217;s value<br />
	 * @param {String} name The name of the cookie to get<br />
	 * @return {String} The cookie&#8217;s value, or false if it can&#8217;t find the cookie<br />
	 * @member cookies<br />
	 * @public<br />
	 */<br />
	var get = function(name) {</p>
<p>		var cookie = document.cookie,<br />
			end,<br />
			pre = name + &#8216;=&#8217;,<br />
			begin  = cookie.indexOf(&#8217;; &#8216; + pre);</p>
<p>		if (begin == -1) {<br />
			begin = cookie.indexOf(pre);<br />
			if (begin !== 0) return false;<br />
		} else {<br />
			begin += 2;<br />
		}</p>
<p>		end = document.cookie.indexOf(&#8217;;', begin);<br />
		if (end == -1) end = cookie.length;</p>
<p>		return decodeURIComponent(cookie.substring(begin + pre.length, end));</p>
<p>	};</p>
<p>	/**<br />
	 * Removes a cookie that has already been set<br />
	 * @param {String} name The name of the cookie to remove<br />
	 * @param {String} path The path of the cookie to remove<br />
	 * @param {String} domain The domain of the cookie to remove<br />
	 * @member cookies<br />
	 * @public<br />
	 */<br />
	var remove = function(name, path, domain) {</p>
<p>		var cookie = name + &#8216;=&#8217;;</p>
<p>		if (!get(name)) return;<br />
		if (path) cookie += &#8216;; path=&#8217; + path;<br />
		if (domain) cookie += &#8216;; domain=&#8217; + domain;<br />
		cookie += &#8216;; expires=Thu, 01-Jan-70 00:00:01 GMT&#8217;;</p>
<p>		document.cookie = cookie;</p>
<p>	};</p>
<p>	/**<br />
	 * Tells the browser to set a cookie<br />
	 * @param {String} name The name of the cookie to set<br />
	 * @param {String} value The value to set in the cookie<br />
	 * @param {String} expires The date that the cookie expires (must be a valid date string)<br />
	 * @param {String} path The path of the cookie to set<br />
	 * @param {String} domain The domain of the cookie to set<br />
	 * @param {Boolean} secure Whether to make the cookie secure or not<br />
	 * @member cookies<br />
	 * @public<br />
	 */<br />
	var set = function(name, value, expires, path, domain, secure) {</p>
<p>		var cookie = name + &#8216;=&#8217; + encodeURIComponent(value);</p>
<p>		if (expires) cookie += &#8216;; expires=&#8217; + expires.toGMTString();<br />
		if (path) cookie += &#8216;; path=&#8217; + path;<br />
		if (domain) cookie += &#8216;; domain=&#8217; + domain;<br />
		if (secure) cookie += &#8216;; secure&#8217;;</p>
<p>		document.cookie = cookie;</p>
<p>	};</p>
<p>	return {<br />
		get : get,<br />
		remove : remove,<br />
		set : set<br />
	};</p>
<p>})();<br />
</textarea></p>
<p>
You can download this script below:
</p>
<ul>
<li><a href="/assets/js/cookies/cookies.js">[Download cookies.js]</a> (2,160 bytes)</li>
<li><a href="/assets/js/cookies/cookies-min.js">[Download cookies-min.js]</a> (634 bytes; compressed)</li>
</ul>
<p>
Also, PPK has an in-depth <a href="http://www.quirksmode.org/js/cookies.html">article about cookies</a>. His code examples get the job done, but unfortunately create too many functions in the global scope (which, as we all know, <a href="http://yuiblog.com/blog/2006/06/01/global-domination/">should be avoided</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://scriptnode.com/article/simple-cookie-script/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dynamically Load CSS and JS Files</title>
		<link>http://scriptnode.com/article/dynamically-load-css-and-js-files/</link>
		<comments>http://scriptnode.com/article/dynamically-load-css-and-js-files/#comments</comments>
		<pubDate>Sun, 28 Sep 2008 08:04:29 +0000</pubDate>
		<dc:creator>Matt Hackett</dc:creator>
				<category><![CDATA[Novice]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[script-sunday]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://scriptnode.com/?p=183</guid>
		<description><![CDATA[
I hear a lot of developers asking about loading
CSS and JS files dynamically.
Surprisingly, creating script and link nodes is just like creating any other nodes.
All you have to do is create them using DOM methods and append to the head:

The Script

var loadCSS = function(file) {
	var link = document.createElement(&#8217;link&#8217;);
	link.href = file;
	link.rel = &#8217;stylesheet&#8217;;
	link.type = &#8216;text/css&#8217;;
	document.getElementsByTagName(&#8217;head&#8217;)[0].appendChild(link);
};
var loadJS [...]]]></description>
			<content:encoded><![CDATA[<p>
I hear a lot of developers asking about loading<br />
<a href="/tag/css/" title="Cascading Style Sheets">CSS</a> and <a href="/tag/javascript/" title="JavaScript">JS</a> files dynamically.<br />
Surprisingly, creating <code>script</code> and <code>link</code> nodes is just like creating any other nodes.<br />
All you have to do is create them using <a href="http://www.w3.org/DOM/" title="Document Object Model">DOM</a> methods and append to the <code>head</code>:
</p>
<h3>The Script</h3>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
var loadCSS = function(file) {<br />
	var link = document.createElement(&#8217;link&#8217;);<br />
	link.href = file;<br />
	link.rel = &#8217;stylesheet&#8217;;<br />
	link.type = &#8216;text/css&#8217;;<br />
	document.getElementsByTagName(&#8217;head&#8217;)[0].appendChild(link);<br />
};</p>
<p>var loadJS = function(file) {<br />
	var script = document.createElement(&#8217;script&#8217;);<br />
	script.src = file;<br />
	script.type = &#8216;text/javascript&#8217;;<br />
	document.getElementsByTagName(&#8217;head&#8217;)[0].appendChild(script);<br />
};<br />
</textarea></p>
<h3>Example 1 &#8211; JavaScript</h3>
<p>
First let&#8217;s load up a JavaScript file. Here&#8217;s what the <a href="/assets/misc/dynamic-load/example-1.js">external JS file</a> looks like:
</p>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
alert(&#8217;Loaded!&#8217;);<br />
</textarea></p>
<p>
And by using the above script, loading it is easy:
</p>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
loadJS(&#8217;/assets/misc/dynamic-load/example-1.js&#8217;);<br />
</textarea></p>
<p>
<button id="example-dynamic-load-1">Load JS file</button>
</p>
<h3>Example 2 &#8211; CSS</h3>
<p>
Loading CSS is not much different. Here are the contents of the <a href="/assets/misc/dynamic-load/example-2.css">external CSS file</a>:
</p>
<p><textarea class="css" cols="50" name="code" rows="10"><br />
body {<br />
	border: 3px solid red;<br />
}<br />
</textarea></p>
<p>
Note that you can also use relative <acronym title="Uniform Resource Locators">URLs</acronym> or even files on another server:
</p>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
loadCSS(&#8217;http://scriptnode.com/assets/misc/dynamic-load/example-2.css&#8217;);<br />
</textarea></p>
<p>
<button id="example-dynamic-load-2">Load CSS file</button>
</p>
<p>
This has been tested and works in all of the <a href="http://developer.yahoo.com/yui/articles/gbs/">standard browsers</a> including<br />
Firefox, Chrome, Internet Explorer, Opera and Safari.
</p>
<p><script type="text/javascript">
<!--//</p>
<p>var loadCSS = function(file) {
	var link = document.createElement('link');
	link.href = file;
	link.rel = 'stylesheet';
	link.type = 'text/css';
	document.getElementsByTagName('head')[0].appendChild(link);
};</p>
<p>var loadJS = function(file) {
	var script = document.createElement('script');
	script.src = file;
	script.type = 'text/javascript';
	document.getElementsByTagName('head')[0].appendChild(script);
};</p>
<p>YAHOO.util.Event.addListener('example-dynamic-load-1', 'click', function() {
	loadJS('/assets/misc/dynamic-load/example-1.js');
});</p>
<p>YAHOO.util.Event.addListener('example-dynamic-load-2', 'click', function() {
	loadCSS('http://scriptnode.com/assets/misc/dynamic-load/example-2.css');
});</p>
<p>//-->
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://scriptnode.com/article/dynamically-load-css-and-js-files/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Evaluating Script Tags Dynamically</title>
		<link>http://scriptnode.com/article/evaluating-script-tags-dynamically/</link>
		<comments>http://scriptnode.com/article/evaluating-script-tags-dynamically/#comments</comments>
		<pubDate>Sun, 21 Sep 2008 08:00:30 +0000</pubDate>
		<dc:creator>Matt Hackett</dc:creator>
				<category><![CDATA[Advanced]]></category>
		<category><![CDATA[code-style]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[script-sunday]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://scriptnode.com/?p=142</guid>
		<description><![CDATA[
First, a disclaimer: dynamically evaluating scripts is not recommended! Indeed, if your application requires the usage of this script, chances are you&#8217;re doing it wrong. The separation of design and logic likely hasn&#8217;t been properly enforced if you&#8217;re using this method. It&#8217;s just an awkward use-case that should be avoided. That said, here it is&#8230;


Many [...]]]></description>
			<content:encoded><![CDATA[<p>
First, a disclaimer: <strong>dynamically evaluating scripts is not recommended!</strong> Indeed, if your application requires the usage of this script, chances are <em>you&#8217;re doing it wrong</em>. The separation of design and logic likely hasn&#8217;t been properly enforced if you&#8217;re using this method. It&#8217;s just an awkward use-case that should be avoided. That said, here it is&#8230;
</p>
<p>
Many JavaScript libraries support the evaluating of data returned via <a href="http://www.w3.org/TR/XMLHttpRequest/" title="XML Http Request">XHR</a>. Some, like <a href="http://developer.yahoo.com/yui/">YUI</a>, do not (yet). In other cases, folks have rolled their own <a href="http://en.wikipedia.org/wiki/List_of_Ajax_frameworks">&#8220;<acronym title="Asynchronous JavaScript and XML">AJAX</acronym> library&#8221;</a> but still want this behavior. The below script supports searching <acronym title="Hypertext Markup Language">HTML</acronym> for scripts and evaluating them:
</p>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
/**<br />
 * Evaluate the passed content for &lt;script&gt; tags<br />
 * @param {String} html The string to parse<br />
 */<br />
var evalHTML = function(html) {</p>
<p>	var piece,<br />
		res = html.split(/&lt;script/);</p>
<p>	res.shift();</p>
<p>	for (var i = 0, len = res.length; i &lt; len; i++) {</p>
<p>		(piece = res[i].split(/&gt;/)).shift();</p>
<p>		try {<br />
			eval(piece.join(&#8217;>').split(&#8217;&lt;/scr&#8217; + &#8216;ipt&gt;&#8217;).shift());<br />
		} catch (e) {}</p>
<p>	}</p>
<p>};<br />
</textarea></p>
<p>You can execute some examples yourself below:</p>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
// Example 1 &#8211; script inside of a div<br />
evalHTML(&#8217;&lt;div&gt;&lt;scr&#8217; +<br />
&#8216;ipt&gt;alert(&#8221;Hello, JavaScript!&#8221;);&lt;/scr&#8217; +<br />
&#8216;ipt&gt;&#8217;);<br />
</textarea></p>
<p>
<button id="example-eval-1">Execute example 1</button>
</p>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
// Example 2 &#8211; script sets a global variable then displays it<br />
evalHTML(&#8217;&lt;scr&#8217; + &#8216;ipt&gt;var foo = &#8220;bar&#8221;;&lt;/scr&#8217; +&#8217;ipt&gt;&#8217; +<br />
&#8216;&lt;scr&#8217; + &#8216;ipt&gt;alert(foo);&lt;/scr&#8217; +&#8217;ipt&gt;&#8217;);<br />
</textarea></p>
<p>
<button id="example-eval-2">Execute example 2</button>
</p>
<p><script type="text/javascript">
<!--//
var evalHTML=function(html){var piece,res=html.split(/<script/);res.shift();for(var i=0,len=res.length;i<len;i++){(piece=res[i].split(/>/)).shift();try{eval(piece.join(">").split("<\/script>").shift())}catch(e){}}};</p>
<p>YAHOO.util.Event.addListener('example-eval-1', 'click', function() {
evalHTML('
<div><scr' + 
'ipt>alert("Hello, JavaScript!");</scr' +
'ipt>');
});</p>
<p>YAHOO.util.Event.addListener('example-eval-2', 'click', function() {
evalHTML('<scr' + 'ipt>var foo = "bar";</scr' +'ipt>' +
'<scr' + 'ipt>alert(foo);</scr' +'ipt>');
});</p>
<p>//-->
</script></p>
<ul class="download">
<li><a href="/assets/js/dynamic-eval/eval.js">[Download eval.js]</a> (376 bytes)</li>
<li><a href="/assets/js/dynamic-eval/eval-min.js">[Download eval-min.js]</a> (214 bytes; compressed)</li>
</ul>
<p>
<strong>Update 9/28/08:</strong> Fixed a bug thanks to <a href="http://foohack.com/">Isaac Schlueter</a> (see <a href="/article/evaluating-script-tags-dynamically/#comment-197">comments</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://scriptnode.com/article/evaluating-script-tags-dynamically/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>MySQL Database Class</title>
		<link>http://scriptnode.com/article/mysql-database-class/</link>
		<comments>http://scriptnode.com/article/mysql-database-class/#comments</comments>
		<pubDate>Mon, 25 Aug 2008 04:19:11 +0000</pubDate>
		<dc:creator>Matt Hackett</dc:creator>
				<category><![CDATA[Intermediate]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[script-sunday]]></category>

		<guid isPermaLink="false">http://scriptnode.com/?p=76</guid>
		<description><![CDATA[
I&#8217;ve been spending loads of time recently with a new project that&#8217;s supposed to be comprised mostly of
what I love doing the most: hardcore JavaScript.
Unfortunately, most front-ends aren&#8217;t much without a back-end to fall on, so I&#8217;ve had to hit the PHP pretty hard too.


When modifying the framework I had built, I noticed that the [...]]]></description>
			<content:encoded><![CDATA[<p>
I&#8217;ve been spending <strong>loads</strong> of time recently with a <a href="http://valadria.com/">new project</a> that&#8217;s supposed to be comprised mostly of<br />
what I love doing the most: hardcore <a href="/tag/javascript/">JavaScript</a>.<br />
Unfortunately, most front-ends aren&#8217;t much without a back-end to fall on, so I&#8217;ve had to hit the <a href="/tag/php">PHP</a> pretty hard too.
</p>
<p>
When modifying the framework I had built, I noticed that the old database class I was using was a little out of date. PHP5 is the new standard, shouldn&#8217;t we all<br />
be using <a href="http://us3.php.net/manual/en/book.pdo.php" title="PHP Data Object">PDO</a>? So I added migrating to PDO to my to-do list. But really, the class<br />
is a pretty good one. It&#8217;s certainly been <a href="http://dirtybeta.com/">useful</a> to me for, well, almost a few years now, give or take a few dozen tweaks.
</p>
<p>
So given the longevity of the script, I thought I&#8217;d offer it up for this week&#8217;s <a href="/tag/script-sunday/">Script Sunday</a>:
</p>
<p><textarea class="php" cols="50" name="code" rows="10"><br />
/**<br />
 * Database constructor<br />
 */<br />
class Database {</p>
<p>	protected<br />
		$connection,<br />
		$debug,<br />
		$debug_func;</p>
<p>	/**<br />
	 * Constructor method. Connects to the database<br />
	 * @public<br />
	 */<br />
    function __construct() {</p>
<p>		$this-&gt;debug = Array();<br />
		$this-&gt;debug_func = &#8216;debugNone&#8217;;</p>
<p>    }</p>
<p>	/**<br />
	 * Gets the number of affected rows from the last query<br />
	 * @return integer Number of affected rows<br />
	 * @public<br />
	 */<br />
    function affectedRows() {<br />
        return mysql_affected_rows($this-&gt;connection);<br />
    }</p>
<p>	/**<br />
	 * Checks a table to see if a key/value pair exists<br />
	 * @param string table The table to check<br />
	 * @param string field The field in the table<br />
	 * @param string value The value of the field to check<br />
	 * @return bool Returns true if it found a matching row<br />
	 * @public<br />
	 */<br />
    function checkField($table, $field, $value, $and = &#8221;) {</p>
<p>		$qry = sprintf(&#8217;<br />
			SELECT<br />
				%s<br />
			FROM<br />
				%s<br />
			WHERE<br />
				%s = &#8220;%s&#8221;<br />
				%s<br />
			&#8216;,<br />
			$field,<br />
			$table,<br />
			$field,<br />
			$value,<br />
			$and<br />
		);</p>
<p>        $res = $this-&gt;query($qry);<br />
		$row = $this-&gt;fetchRow($res);</p>
<p>        return ($row ? true : false);</p>
<p>    }</p>
<p>	/**<br />
	 * Cleans a value for the DB<br />
	 * @param str $value The value to clean<br />
	 * @return str The cleaned string<br />
	 */<br />
	function clean($value) {</p>
<p>		$value = stripslashes($value);<br />
		$value = trim($value);<br />
		$value = str_replace(&#8221;&#8216;&#8221;, &#8220;\&#8217;&#8221;, $value);</p>
<p>		return $value;</p>
<p>	}</p>
<p>	/**<br />
	 * Connect to the database<br />
	 * @param string db_server The database server to connect to (often localhost)<br />
	 * @param string db_user The user to send to the server<br />
	 * @param string db_password The user&#8217;s password<br />
	 * @param string db_name The name of the database to use<br />
	 * @public<br />
	 */<br />
    function connect($db_server, $db_user, $db_password, $db_name) {</p>
<p>        $this-&gt;connection = mysql_connect($db_server, $db_user, $db_password);<br />
        $this-&gt;select($db_name, $this-&gt;connection);</p>
<p>        return ($this-&gt;connection ? true : false);</p>
<p>    }</p>
<p>	function debugNone() {}</p>
<p>	/**<br />
	 * Adds a debug message to $debug<br />
	 * @param str The debug message<br />
	 * @public<br />
	 */<br />
	function debugPut($debug) {<br />
		$this-&gt;debug[] = $debug;<br />
	}</p>
<p>	/**<br />
	 * Deletes rows from the database<br />
	 * @param string table The table to query<br />
	 * @param string where There WHERE clause in the query<br />
	 * @param integer limit How many rows to limit (default is 1)<br />
	 * @return integer Number of affected rows<br />
	 * @public<br />
	 */<br />
    function deleteRows($table, $where, $limit = 1) {</p>
<p>		$limit = ($limit ? &#8216;LIMIT &#8216; . $limit : &#8221;);</p>
<p>        $qry = &#8216;DELETE FROM &#8216; . $table . &#8216;<br />
				WHERE &#8216; . $where . &#8216;<br />
				&#8216; . $limit;</p>
<p>        $this-&gt;query($qry);</p>
<p>		return $this-&gt;affectedRows();</p>
<p>    }</p>
<p>	/**<br />
	 * Retrieves a row from the database<br />
	 * @param string result The result set returned from the query<br />
	 * @return array Associatve index of the retrieved row<br />
	 */<br />
    function fetchRow($res) {<br />
        return @mysql_fetch_assoc($res);<br />
    }</p>
<p>	/**<br />
	 * Get a single row from the database<br />
	 * @param qry The query to send<br />
	 * @return array Associative array of the row<br />
	 */<br />
	function getRow($qry) {</p>
<p>		$res = $this-&gt;query($qry);<br />
		$row = $this-&gt;fetchRow($res);</p>
<p>		return $row;</p>
<p>	}</p>
<p>	/**<br />
	 * Retreive rows from the database<br />
	 * @param qry The query to get the rows<br />
	 * @param array Numeric array of the rows<br />
	 */<br />
	function getRows($qry) {</p>
<p>		$rows = Array();<br />
		$res  = $this-&gt;query($qry);</p>
<p>		while ($row = $this-&gt;fetchRow($res)) {<br />
			$rows[] = $row;<br />
		}</p>
<p>		return $rows;</p>
<p>	}</p>
<p>	/**<br />
	 * Format a query for insertion into the database<br />
	 * @param string table The table to insert into<br />
	 * @param array pairs Key value pairs of the fields and values to insert<br />
	 * @return string The prepared query, ready to insert<br />
	 */<br />
    function formatInsert($table, $pairs) {</p>
<p>        foreach ($pairs as $field =&gt; $value) {</p>
<p>			$fields .= $field . &#8216;,&#8217;;</p>
<p>			if (!is_numeric($value)) {<br />
				$value = $this-&gt;clean($value);<br />
			}</p>
<p>			$values .= &#8220;&#8216;$value&#8217;,&#8221;;</p>
<p>        }</p>
<p>		$fields = substr($fields, 0, -1);<br />
		$values = substr($values, 0, -1);</p>
<p>		$qry = sprintf(&#8221;<br />
			INSERT INTO<br />
				$table<br />
			($fields)<br />
			VALUES<br />
				($values)<br />
		&#8220;);</p>
<p>        return $qry;</p>
<p>    }</p>
<p>	/**<br />
	 * Formats an update query based on a key/value array<br />
	 * @param string table The name of the table<br />
	 * @param array pairs The key/value pair of the fields/values<br />
	 * @param string where The WHERE clause of the array (default: 1)<br />
	 * @param integer limit The limit on tbe query<br />
	 * @return string The prepared query<br />
	*/<br />
    function formatUpdate($table, $pairs, $where = &#8216;1&#8242;, $limit = false) {</p>
<p>        foreach ($pairs as $key =&gt; $value) {</p>
<p>			if (!is_numeric($value)) {<br />
				$value = $this-&gt;clean($value);<br />
			}</p>
<p>			$set .= &#8220;$key = &#8216;$value&#8217;, &#8220;;</p>
<p>        }</p>
<p>        $set   = substr($set, 0, -2);<br />
		$limit = ($limit ? &#8216; LIMIT &#8216; . $limit : &#8221;);</p>
<p>		$qry = sprintf(&#8221;<br />
			UPDATE<br />
				$table<br />
			SET<br />
				$set<br />
			WHERE<br />
				$where<br />
			$limit<br />
		&#8220;);</p>
<p>        return $qry;</p>
<p>    }</p>
<p>	/**<br />
	 * Get the id of the last inserted row<br />
	 * @return integer They id (if it exists) of the last inserted row<br />
	*/<br />
    function getID() {<br />
        return mysql_insert_id($this-&gt;connection);<br />
    }</p>
<p>	/**<br />
	 * Inserts rows into the database<br />
	 * @param string table The table to send the query to<br />
	 * @param array pairs The key/value pairs to insert into the database<br />
	 * @return integer Number of affected rows<br />
	*/<br />
	function insertRows($table, $pairs) {<br />
		return $this-&gt;query($this-&gt;formatInsert($table, $pairs));<br />
	}</p>
<p>	/**<br />
	 * Gets the number of rows from a result set<br />
	 * @return integer Number of rows<br />
	*/<br />
    function numRows($res) {<br />
        return mysql_num_rows($res);<br />
    }</p>
<p>	/**<br />
	 * Send a query to the database<br />
	 * @param string qry The query to send<br />
	 * @return string A reference to the result set<br />
	*/<br />
    function query($qry) {</p>
<p>		$func = $this-&gt;debug_func;<br />
		$this-&gt;$func($qry);</p>
<p>        return mysql_query($qry, $this-&gt;connection);</p>
<p>    }</p>
<p>	/**<br />
	 * Select a database on the server<br />
	 * @param string db_name The name of the database<br />
	 * @return bool Returns true on success and false on failure<br />
	*/<br />
    function select($db_name, $connection = null) {</p>
<p>		if ($connection) {<br />
			$this-&gt;connection = &amp;$connection;<br />
		}</p>
<p>        return mysql_select_db($db_name, $this-&gt;connection);</p>
<p>    }</p>
<p>	/**<br />
	 * Turns on or off the debug option<br />
	 * @param bool debug The new value of the debug option<br />
	*/<br />
	function setDebug($debug) {<br />
		if ($debug) {<br />
			$this-&gt;debug_func = &#8216;debugPut&#8217;;<br />
		} else {<br />
			$this-&gt;debug_func = &#8216;debugNone&#8217;;<br />
		}<br />
	}</p>
<p>	/**<br />
	 * Updates rows in the database<br />
	 * @param string table The table to send the query to<br />
	 * @param array pairs The key/value pairs to insert into the database<br />
	 * @param string where The WHERE clause of the array (default: 1)<br />
	 * @param integer limit The limit on tbe query<br />
	 * @return integer Number of affected rows<br />
	*/<br />
	function updateRows($table, $pairs, $where = &#8216;1&#8242;, $limit = false) {<br />
		return $this-&gt;query($this-&gt;formatUpdate($table, $pairs, $where, $limit));<br />
	}</p>
<p>}<br />
</textarea></p>
<p>
And here&#8217;s a quick example of how to use it:
</p>
<p><textarea class="php" cols="50" name="code" rows="10"><br />
$db = new Database();<br />
$db-&gt;connect($server, $user, $password, $db_name);</p>
<p>$query = &#8216;SELECT * FROM users&#8217;;<br />
$users = $db-&gt;getRows($query);</p>
<p>foreach ($users as $user) {<br />
	echo &#8216;Username: &#8216; . $user['username'] . &#8216;&lt;br&gt;&#8217;;<br />
}<br />
</textarea></p>
<ul>
<li><a href="/assets/php/db-class/database.php.txt">[Download database.php.txt]</a> (6,848 bytes)</li>
<li><a href="/assets/php/db-class/db-class.zip">[Download db-class.zip]</a> (1,966 bytes)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://scriptnode.com/article/mysql-database-class/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Quickly Update DocumentRoot in Apache2</title>
		<link>http://scriptnode.com/article/quickly-update-documentroot-in-apache2/</link>
		<comments>http://scriptnode.com/article/quickly-update-documentroot-in-apache2/#comments</comments>
		<pubDate>Sun, 10 Aug 2008 19:33:50 +0000</pubDate>
		<dc:creator>Matt Hackett</dc:creator>
				<category><![CDATA[Intermediate]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[code-style]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[script-sunday]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://scriptnode.com/?p=63</guid>
		<description><![CDATA[
For today&#8217;s Script Sunday I thought I&#8217;d take a go back in time a little and provide an old utility that I still to this day find useful.
It&#8217;s a script I wrote called ChangeLocalHost which alters the DocumentRoot in apache2. An example of its use would be:


./clh.php local-site.com/public_html/


Note: you must be root to run it


Given [...]]]></description>
			<content:encoded><![CDATA[<p>
For today&#8217;s <a href="/tag/script-sunday/">Script Sunday</a> I thought I&#8217;d take a go back in time a little and provide an old utility that I still to this day find useful.<br />
It&#8217;s a script I wrote called <code>ChangeLocalHost</code> which alters the <code>DocumentRoot</code> in <code>apache2</code>. An example of its use would be:
</p>
<p>
<code>./clh.php local-site.com/public_html/</code>
</p>
<p>
<em>Note: you must be <code>root</code> to run it</em>
</p>
<p>
Given this command, the script will change <code>DocumentRoot</code> to <strong>local-site.com/public_html/</strong> and restart <code>apache2</code>.<br />
I work on <a href="http://dirtybeta.com/">a lot</a> of <a href="http://valadria.com/">websites</a> (developing most of them on my laptop running <code>apache2</code>)<br />
so I use this script constantly.
</p>
<p>
Here&#8217;s the code:
</p>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
#!/usr/bin/php<br />
&lt;?php</p>
<p>/*<br />
ChangeLocalHost v0.1 &#8211; last updated Mar 07 2007<br />
Must be root to execute. Alters the DocumentRoot in Apache2&#8217;s conf file, then restarts Apache2.<br />
*/</p>
<p>$obj_clh = new ChangeLocalHost(&#8217;/etc/apache2/sites-available/&#8217;, &#8216;default&#8217;, &#8216;/home/www/&#8217;);</p>
<p>$obj_clh-&gt;setArgs($_SERVER['argv']);<br />
$obj_clh-&gt;run();</p>
<p>/**<br />
 * CLH class constructor<br />
 * @constructor<br />
 */<br />
class ChangeLocalHost {</p>
<p>	private $arr_args,<br />
			$bit_msgs,<br />
			$str_dir,<br />
			$str_file,<br />
			$str_pre;</p>
<p>	protected $str_version;</p>
<p>	/**<br />
	 * Constructor method<br />
	 * @param string str_dir The location of the Apache conf file to mod<br />
	 * @param string str_file The name of the Apache conf file to mod<br />
	 * @param string str_pre The needle to search for in the conf file<br />
	 */<br />
	function __construct($str_dir, $str_file, $str_pre) {</p>
<p>		$this-&gt;str_version = &#8216;ChangeLocalHost v0.1&#8242;;</p>
<p>		$this-&gt;arr_args = Array();<br />
		$this-&gt;bit_msgs = true;<br />
		$this-&gt;str_dir  = $str_dir;<br />
		$this-&gt;str_file = $str_file;<br />
		$this-&gt;str_pre  = $str_pre;</p>
<p>	}</p>
<p>	/**<br />
	 * Modify Apache&#8217;s DocumentRoot<br />
	 * @param string str_file The (conf) file to mod<br />
	 * @param string str_new_dir The new directory to set as DocumentRoot<br />
	 * @private<br />
	 */<br />
	private function alterLocalHost($str_file, $str_new_dir) {</p>
<p>		$str_contents = file_get_contents($str_file);</p>
<p>		if (!$str_contents) {<br />
			$this-&gt;showError(&#8217;Could not read &#8216; . $str_file);<br />
		}</p>
<p>		$int_begin    = strpos($str_contents, $this-&gt;str_pre);<br />
		$int_end      = strpos(substr($str_contents, $int_begin), &#8220;\n&#8221;);<br />
		$str_search   = substr($str_contents, $int_begin, $int_end);<br />
		$str_contents = str_replace($str_search, $str_new_dir, $str_contents);<br />
		$bit_written  = file_put_contents($str_file, $str_contents);</p>
<p>		if ($bit_written) {<br />
			$this-&gt;showMessage(&#8217;Successfully set DocumentRoot to &#8216; . $str_new_dir);<br />
		} else {<br />
			$this-&gt;showError(&#8217;Could not write &#8216; . $str_file);<br />
		}</p>
<p>	}</p>
<p>	/**<br />
	 * Validates the new directory to set<br />
	 * @param string str_new_dir The potential new directory<br />
	 * @private<br />
	 */<br />
	private function checkLocalHost($str_new_dir) {</p>
<p>		$str_set_to = $this-&gt;str_pre . $str_new_dir;</p>
<p>		if (is_dir($str_set_to)) {</p>
<p>			$this-&gt;setLocalHost($str_set_to);<br />
			$this-&gt;restartApache2();</p>
<p>		} else {<br />
			$this-&gt;showError($str_set_to . &#8216; is not a valid directory.&#8217;);<br />
		}</p>
<p>	}</p>
<p>	/**<br />
	 * Ensures this app is being executed as root<br />
	 * @private<br />
	 */<br />
	private function checkRoot() {</p>
<p>		// Make sure user is root<br />
		$str_command = &#8216;whoami&#8217;;</p>
<p>		exec($str_command, $arr_output, $int_return);</p>
<p>		if ($arr_output[0] != &#8216;root&#8217;) {<br />
			$this-&gt;showError(&#8217;You must be root to run this program.&#8217;);<br />
		}</p>
<p>	}</p>
<p>	/**<br />
	 * Makes a backup of the Apache conf file<br />
	 * @param string str_source The original to copy<br />
	 * @param string str_new The location of the backup<br />
	 * @return bool Whether the copy was successful or not<br />
	 * @private<br />
	 */<br />
	private function makeCopy($str_source, $str_new) {</p>
<p>		$bit_copy = copy($str_source, $str_new);</p>
<p>		if (!$bit_copy) {<br />
			$this-&gt;showError(&#8217;Could not make copy of &#8216; . $str_source);<br />
		}</p>
<p>		return true;</p>
<p>	}</p>
<p>	/**<br />
	 * Restarts Apache2<br />
	 * @private<br />
	 */<br />
	private function restartApache2() {</p>
<p>		$str_command = &#8216;apache2ctl restart&#8217;;</p>
<p>		exec($str_command, $arr_output, $int_return);</p>
<p>		if ($int_return &gt; 0) {<br />
			$this-&gt;showError(&#8217;Could not restart Apache2.&#8217; . $str_source);<br />
		}</p>
<p>		$this-&gt;showMessage(&#8217;Successfully restarted Apache2.&#8217;);</p>
<p>	}</p>
<p>	/**<br />
	 * Executes the script<br />
	 */<br />
	function run() {</p>
<p>		$this-&gt;checkRoot();</p>
<p>		$str_new_dir = $this-&gt;arr_args[1];</p>
<p>		switch ($this-&gt;arr_args[1]) {</p>
<p>			case &#8216;-c&#8217; :<br />
			case &#8216;&#8211;current&#8217; :<br />
				$this-&gt;showCurrent();<br />
				break;</p>
<p>			case &#8221; :<br />
			case &#8216;-h&#8217; :<br />
			case &#8216;&#8211;help&#8217; :<br />
				$this-&gt;showHelp();<br />
				break;</p>
<p>			case &#8216;-q&#8217; :<br />
			case &#8216;&#8211;quiet&#8217; :<br />
				$str_new_dir    = $this-&gt;arr_args[2];<br />
				$this-&gt;bit_msgs = false;<br />
				break;</p>
<p>			case &#8216;-v&#8217; :<br />
			case &#8216;&#8211;version&#8217; :<br />
				$this-&gt;showVersion();<br />
				break;</p>
<p>			default :<br />
				break;</p>
<p>		}</p>
<p>		$this-&gt;checkLocalHost($str_new_dir);<br />
		exit(0);</p>
<p>	}</p>
<p>	/**<br />
	 * Create a copy of the arguments global<br />
	 * @param array array_args The arguments to set<br />
	 */<br />
	function setArgs($arr_args) {<br />
		$this-&gt;arr_args = &amp;$arr_args;<br />
	}</p>
<p>	/**<br />
	 * Call the other methods to initiate the altering of the DocumentRoot<br />
	 * @param string str_new_dir The new value of DocumentRoot<br />
	 * @private<br />
	 */<br />
	private function setLocalHost($str_new_dir) {</p>
<p>		$str_ext    = &#8216;.bak&#8217;;<br />
		$str_file   = ($this-&gt;str_dir . $this-&gt;str_file);<br />
		$str_backup = $str_file . $str_ext;</p>
<p>		if (is_file($str_file)) {</p>
<p>			if ($this-&gt;makeCopy($str_file, $str_backup)) {<br />
				$this-&gt;showMessage(&#8217;Copied backup of &#8216; . $this-&gt;str_file . &#8216; to &#8216; . $this-&gt;str_file . $str_ext);<br />
			}</p>
<p>			$this-&gt;alterLocalHost($str_file, $str_new_dir);</p>
<p>		} else {<br />
			$this-&gt;showError($str_file . &#8216; cannot be found.&#8217;);<br />
		}</p>
<p>	}</p>
<p>	/**<br />
	 * Show what DocumentRoot is currently set to<br />
	 * @private<br />
	 */<br />
	private function showCurrent() {</p>
<p>		$str_file = ($this-&gt;str_dir . $this-&gt;str_file);</p>
<p>		if (is_file($str_file)) {</p>
<p>			$str_contents = file_get_contents($str_file);</p>
<p>			if (!$str_contents) {<br />
				$this-&gt;showError(&#8217;Could not read &#8216; . $str_file);<br />
			}</p>
<p>			$int_begin  = strpos($str_contents, $this-&gt;str_pre);<br />
			$int_end    = strpos(substr($str_contents, $int_begin), &#8220;\n&#8221;);<br />
			$str_search = substr($str_contents, $int_begin, $int_end);</p>
<p>			$this-&gt;showMessage(&#8217;The current DocumentRoot is: &#8216; . $str_search);<br />
			exit;</p>
<p>		} else {<br />
			$this-&gt;showError($str_file . &#8216; cannot be found.&#8217;);<br />
		}</p>
<p>	}</p>
<p>	/**<br />
	 * Display a message and exit<br />
	 * @param string str_error The message to display<br />
	 * @private<br />
	 */<br />
	private function showError($str_error) {</p>
<p>		echo &#8216;Error: &#8216; . $str_error . &#8220;\n&#8221;;</p>
<p>		exit(1);</p>
<p>	}</p>
<p>	/**<br />
	 * Show the help text and exit<br />
	 * @private<br />
	 */<br />
	private function showHelp() {</p>
<p>		$str_help .= &#8216;Usage: clh [DIRECTORY]&#8230; [OPTIONS]&#8216; . &#8220;\n&#8221;;<br />
		$str_help .= &#8216;Alter the DocumentRoot in Apache2.&#8217; . &#8220;\n&#8221;;<br />
		$str_help .= &#8220;\n&#8221;;<br />
		$str_help .= &#8216;  -c, &#8211;current  display current DocumentRoot and exit&#8217; . &#8220;\n&#8221;;<br />
		$str_help .= &#8216;  -h, &#8211;help     display this help and exit&#8217; . &#8220;\n&#8221;;<br />
		$str_help .= &#8216;  -q, &#8211;quiet    suppress most messages&#8217; . &#8220;\n&#8221;;<br />
		$str_help .= &#8216;  -v, &#8211;version  output version information and exit&#8217; . &#8220;\n&#8221;;<br />
		$str_help .= &#8220;\n&#8221;;<br />
		$str_help .= &#8216;Report bugs to &lt;scriptnode@gmail.com&gt;.&#8217; . &#8220;\n&#8221;; // Hahahaha</p>
<p>		echo $str_help;</p>
<p>		exit(0);</p>
<p>	}</p>
<p>	/**<br />
	 * Display a message to the user<br />
	 * @param string str_message The message to show<br />
	 * @private<br />
	 */<br />
	private function showMessage($str_message) {</p>
<p>		if ($this-&gt;bit_msgs) {<br />
			echo $str_message . &#8220;\n&#8221;;<br />
		}</p>
<p>	}</p>
<p>	/**<br />
	 * Attempt to be more like a real application by displaying the version<br />
	 * @private<br />
	 */<br />
	private function showVersion() {</p>
<p>		echo $this-&gt;str_version . &#8220;\n&#8221;;</p>
<p>		exit(0);</p>
<p>	}</p>
<p>}<br />
</textarea></p>
<p>
You&#8217;ll notice that the script is at least a year and a half old.<br />
Usually if code of mine is more than a year old, it&#8217;s completely unusuable because my <a href="/article/my-new-coding-habits/">habits change pretty often</a>.<br />
But I think I&#8217;ve finally gotten to that sweet spot where it&#8217;s not total garbage, it just needs tweaking.
</p>
<p>
I was surprised that the code isn&#8217;t too bad really. It&#8217;s easily readable and well organized. There are many things that I wouldn&#8217;t have done were I to write this again;<br />
for example, I stopped using type prefixes long ago (such as an array of users as <code>$arr_users</code>). I understand why I used to do this, but it&#8217;s not necessary<br />
and only clutters up the code.
</p>
<p>
Anyway, I find this script useful and I thought someone else might too. Enjoy!
</p>
<ul>
<li><a href="/assets/php/clh/clh.php.txt">[Download clh.php.txt]</a> (6,614 bytes)</li>
<li><a href="/assets/php/clh/clh.zip">[Download clh.zip]</a> (1,975 bytes)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://scriptnode.com/article/quickly-update-documentroot-in-apache2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Shark!</title>
		<link>http://scriptnode.com/article/shark/</link>
		<comments>http://scriptnode.com/article/shark/#comments</comments>
		<pubDate>Sun, 03 Aug 2008 10:56:42 +0000</pubDate>
		<dc:creator>Matt Hackett</dc:creator>
				<category><![CDATA[Advanced]]></category>
		<category><![CDATA[games]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[just-for-fun]]></category>
		<category><![CDATA[lab]]></category>
		<category><![CDATA[script-sunday]]></category>
		<category><![CDATA[yui]]></category>

		<guid isPermaLink="false">http://scriptnode.com/?p=48</guid>
		<description><![CDATA[
Well, this year&#8217;s Shark Week is over. In its memory, I offer up a script that makes sharks swim around on the screen. You should see a few sharks swimming about right now! Here&#8217;s the source code:


/**
 * Global Shark constructor
 * Options for ops: dir, speed, url, x, y, zIndex
 * @constructor
 * @public
 [...]]]></description>
			<content:encoded><![CDATA[<p>
Well, this year&#8217;s <a href="http://discovery.com/sharkweek/">Shark Week</a> is over. In its memory, I offer up a script that makes sharks swim around on the screen. You should see a few sharks swimming about right now! Here&#8217;s the source code:
</p>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
/**<br />
 * Global Shark constructor<br />
 * Options for ops: dir, speed, url, x, y, zIndex<br />
 * @constructor<br />
 * @public<br />
 */<br />
Shark = function(ops) {</p>
<p>	var Y = YAHOO.util,<br />
		DEFAULT_SPEED = 2,<br />
		DEFAULT_ZINDEX = 1000,<br />
		DELAY = 25,<br />
		LEFT = &#8216;l&#8217;,<br />
		RIGHT = &#8216;r&#8217;,<br />
		SCREEN_WIDTH = Y.Dom.getViewportWidth(),<br />
		SCREEN_HEIGHT = Y.Dom.getViewportHeight(),<br />
		SHARK_WIDTH = 242,<br />
		SHARK_HEIGHT = 82;</p>
<p>	var interval,<br />
		that = this;</p>
<p>	that.active = true;<br />
	that.dir = LEFT;<br />
	that.el = {};<br />
	that.onOutLeft = function(){};<br />
	that.onOutRight = function(){};<br />
	that.x = 0;<br />
	that.y = 0;</p>
<p>	/**<br />
	 * Initializes the shark variables<br />
	 * @private<br />
	 */<br />
	var init = function() {</p>
<p>		ops = ops || {};<br />
		ops.speed = ops.speed || rand(DEFAULT_SPEED, (DEFAULT_SPEED * 2));<br />
		ops.url = ops.url || &#8216;./&#8217;;<br />
		ops.zIndex = ops.zIndex || DEFAULT_ZINDEX;</p>
<p>		if (ops.dir) {<br />
			that.dir = ops.dir;<br />
		} else {<br />
			that.dir = [LEFT, RIGHT][rand(0, 1)];<br />
		}</p>
<p>		if (ops.x === undefined) {<br />
			if (that.dir == LEFT) {<br />
				that.x = (SCREEN_WIDTH &#8211; 1);<br />
			} else {<br />
				that.x = -SHARK_WIDTH;<br />
			}<br />
		} else {<br />
			that.x = ops.x;<br />
		}</p>
<p>		that.el = document.createElement(&#8217;div&#8217;);<br />
		that.el.className = &#8217;shark&#8217;; // Doesn&#8217;t do anything. Just in case you want to use it<br />
		that.el.style.position = &#8216;absolute&#8217;;<br />
		that.el.style.height = SHARK_HEIGHT + &#8216;px&#8217;;<br />
		that.el.style.zIndex = ops.zIndex;</p>
<p>		Y.Event.addListener(that.el, &#8216;click&#8217;, onclick);</p>
<p>		document.body.appendChild(that.el);<br />
		reset();</p>
<p>		if (ops.y !== undefined) {<br />
			that.y = ops.y<br />
			plot();<br />
		}</p>
<p>		that.start();</p>
<p>	};</p>
<p>	/**<br />
	 * Kills the shark<br />
	 * @param {Boolean} fade Whether to fade the shark in or not<br />
	 */<br />
	that.kill = function(fade) {</p>
<p>		that.active = false;</p>
<p>		var done = function() {<br />
			document.body.removeChild(that.el);<br />
			stop();<br />
		};</p>
<p>		if (fade) {</p>
<p>			var anim = new Y.Anim(that.el, {opacity : {to : 0}}, 0.5);</p>
<p>			anim.onComplete.subscribe(done);<br />
			anim.animate();</p>
<p>		} else {<br />
			done();<br />
		}</p>
<p>	};</p>
<p>	/**<br />
	 * Move the shark<br />
	 */<br />
	var move = function() {</p>
<p>		if (!that.active) {<br />
			return;<br />
		}</p>
<p>		if (that.dir == LEFT) {</p>
<p>			that.x -= ops.speed;</p>
<p>			if (that.x &lt; -SHARK_WIDTH) {<br />
				that.dir = RIGHT;<br />
				that.onOutLeft();<br />
				reset();<br />
			}</p>
<p>		} else {</p>
<p>			that.x += ops.speed;</p>
<p>			if (that.x &gt; (SCREEN_WIDTH &#8211; 1)) {<br />
				that.dir = LEFT;<br />
				that.x = (SCREEN_WIDTH &#8211; 1);<br />
				that.onOutRight();<br />
				reset();<br />
			}</p>
<p>		}</p>
<p>		if (that.x &gt; (SCREEN_WIDTH &#8211; SHARK_WIDTH)) {<br />
			that.el.style.width = (SHARK_WIDTH &#8211; (that.x &#8211; (SCREEN_WIDTH &#8211; SHARK_WIDTH))) + &#8216;px&#8217;;<br />
		} else {<br />
			that.el.style.width = SHARK_WIDTH + &#8216;px&#8217;;<br />
		}</p>
<p>		plot();</p>
<p>	};</p>
<p>	/**<br />
	 * Kills the shark. Note: intended to be overwritten<br />
	 */<br />
	var onclick = function() {<br />
		that.onclick();<br />
	};</p>
<p>	/**<br />
	 * Default onclick behavior<br />
	 */<br />
	that.onclick = function() {<br />
		that.kill(true);<br />
	};</p>
<p>	/**<br />
	 * Moves the shark element to the XY coordinates<br />
	 */<br />
	var plot = function() {<br />
		that.el.style.left = that.x + &#8216;px&#8217;;<br />
		that.el.style.top = that.y + &#8216;px&#8217;;<br />
	};</p>
<p>	/**<br />
	 * Returns a random number<br />
	 * @param {Number} from The starting point<br />
	 * @param {Number} to The stopping point<br />
	 * @return {Number} A random number within the range<br />
	 */<br />
	var rand = function(from, to) {<br />
		return (from + Math.floor((to &#8211; from + 1) * Math.random()));<br />
	}; </p>
<p>	/**<br />
	 * Sets the background based on direction and randomizes the Y position<br />
	 */<br />
	var reset = function() {</p>
<p>		that.el.style.background = &#8216;url(&#8217; + ops.url + &#8217;shark_&#8217; + that.dir + &#8216;.gif)&#8217;;<br />
		that.y = rand(0, (SCREEN_HEIGHT &#8211; SHARK_HEIGHT &#8211; 1));</p>
<p>		plot();</p>
<p>	};</p>
<p>	/**<br />
	 * Starts the move interval<br />
	 */<br />
	that.start = function() {</p>
<p>		if (interval) {<br />
			return;<br />
		}</p>
<p>		interval = setInterval(move, DELAY);</p>
<p>	};</p>
<p>	/**<br />
	 * Stops the move interval<br />
	 */<br />
	that.stop = function() {<br />
		if (interval) {<br />
			clearInterval(interval);<br />
			interval = false;<br />
		}<br />
	};</p>
<p>	init();</p>
<p>};<br />
</textarea></p>
<p>
You can create new sharks like this:
</p>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
var myShark = new Shark();</p>
<p>// Or setup some basics, like having him swim to the left<br />
var anotherShark = new Shark({dir : &#8216;l&#8217;});<br />
anotherShark.onclick = function() {<br />
alert(&#8221;I&#8217;m a shaaaaaaark!&#8221;);<br />
myShark.kill(true); // Kill it with a fade<br />
};</p>
<p>// You may also want to host the shark images yourself:<br />
var hostedShark = new Shark({url : &#8216;http://mydomain.com/shark/&#8217;});<br />
</textarea></p>
<p>
The last example above shows setting a custom <acronym title="Uniform Resource Locator">URL</acronym> for the shark images. You can download those here:
</p>
<p>
<a href="/lab/shark/shark_l.gif"><img alt="Shark!" src="/lab/shark/shark_l.gif"/></a><br />
<a href="/lab/shark/shark_r.gif"><img alt="Shark!" src="/lab/shark/shark_r.gif"/></a>
</p>
<p>
<a class="after" href="/lab/shark/"><img alt="Shark!" src="/assets/img/shark_thumbnail.jpg"/></a><br />
There are a few different events you can subscribe to including <code>onclick</code>, <code>onOutLeft</code> and <code>onOutRight</code>, which I think are pretty self-explanatory.<br />
Using these events, I put together <a href="http://scriptnode.com/lab/shark/">a very simple game</a> involving sharks, clicking and hopelessly trying to save a doomed diver. The ocean graphics came from one of my <a href="http://csszengarden.com/?cssfile=http://www.css-praxis.de/cssocean/zenocean.css">favorite CSS Zen Garden examples</a>.
</p>
<p>
The shark script requires <a href="http://developer.yahoo.com/yui/">YUI</a> (Animation, DOM and Event). I&#8217;ve included it in the third download option below:
</p>
<ul>
<li><a href="/assets/js/shark/shark.js">[Download shark.js]</a> (3,747 bytes)</li>
<li><a href="/assets/js/shark/shark-min.js">[Download shark-min.js]</a> (1,550 bytes; compressed)</li>
<li><a href="/assets/js/shark/shark-min-yui.js">[Download shark-min-yui.js]</a> (46k; compressed with YUI)</li>
</ul>
<p>
I&#8217;d love to see if anybody else has cool ideas of what to do with the shark script!
</p>
<p><script src="/assets/js/shark/shark-min-yui.js" type="text/javascript"></script><br />
<script type="text/javascript">
(function() {
new Shark({url : '/lab/shark/'});
new Shark({url : '/lab/shark/'});
})();
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://scriptnode.com/article/shark/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Bresenham&#8217;s Line Algorithm In JavaScript</title>
		<link>http://scriptnode.com/article/bresenhams-line-algorithm-in-javascript/</link>
		<comments>http://scriptnode.com/article/bresenhams-line-algorithm-in-javascript/#comments</comments>
		<pubDate>Sun, 06 Jul 2008 22:03:40 +0000</pubDate>
		<dc:creator>Matt Hackett</dc:creator>
				<category><![CDATA[Intermediate]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[just-for-fun]]></category>
		<category><![CDATA[math]]></category>
		<category><![CDATA[script-sunday]]></category>

		<guid isPermaLink="false">http://scriptnode.com/?p=37</guid>
		<description><![CDATA[
Today for Script Sunday I implemented Bresenham&#8217;s line algorithm
in the web browser. If you&#8217;ve got JavaScript enabled, you should see a red square in the upper-left hand corner
of the box below.
Clicking anywhere within the box should send the square to that location.



Here&#8217;s the source code:


/**
 * Bresenham&#8217;s line algorithm function
 * by Matt Hackett [scriptnode.com]
 [...]]]></description>
			<content:encoded><![CDATA[<p>
Today for <a href="/tag/script-sunday/">Script Sunday</a> I implemented <a href="http://en.wikipedia.org/wiki/Bresenham's_line_algorithm">Bresenham&#8217;s line algorithm</a><br />
in the web browser. If you&#8217;ve got <a href="/article/how-to-enable-javascript/">JavaScript enabled</a>, you should see a red square in the upper-left hand corner<br />
of the box below.<br />
Clicking anywhere within the box should send the square to that location.
</p>
<div id="example" style="border: 1px dashed #000; height: 200px; margin-bottom: 1em; position: relative;"></div>
<p>
Here&#8217;s the source code:
</p>
<p><textarea class="javascript" cols="50" name="code" rows="10"><br />
/**<br />
 * Bresenham&#8217;s line algorithm function<br />
 * by Matt Hackett [scriptnode.com]<br />
 * @param {Object} el The element to target (accepts both strings for id&#8217;s and element objects themselves)<br />
 * @param {Number} x1 The starting X coordinate<br />
 * @param {Number} y1 The starting Y coordinate<br />
 * @param {Number} x2 The finishing X coordinate<br />
 * @param {Number} y2 The finishing Y coordinate<br />
 * @param {Object} params Additional parameters [delay, onComplete, speed]<br />
 */<br />
var bresenham = function(el, x1, y1, x2, y2, params) {</p>
<p>	var<br />
		interval,<br />
		b,<br />
		m,<br />
		sx,<br />
		y;</p>
<p>	var init = function() {</p>
<p>		var dx, dy, sy;</p>
<p>		// Default parameters<br />
		params = params || {};<br />
		params.delay = params.delay || 10;<br />
		params.onComplete = params.onComplete || function(){};<br />
		params.speed = params.speed || 5;</p>
<p>		// No point in doing anything if we&#8217;re not actually moving<br />
		if ((x1 == x2) &amp;&amp; (y1 == y2)) {<br />
			plot(x1, y);<br />
			params.onComplete();<br />
			return;<br />
		}</p>
<p>		el = ((typeof el === &#8217;string&#8217;) ? document.getElementById(el) : el);</p>
<p>		// Initalize the math<br />
		dx = x2 &#8211; x1;<br />
		sx = (dx &lt; 0) ? -1 : 1;<br />
		dy = y2 &#8211; y1;<br />
		sy = (dy &lt; 0) ? -1 : 1;<br />
		m = dy / dx;<br />
		b = y1 &#8211; (m * x1);</p>
<p>		interval = setInterval(next, params.delay);</p>
<p>	};</p>
<p>	/**<br />
	 * Execute the algorithm and move the element<br />
	*/<br />
	var next = function() {</p>
<p>		y = Math.round((m * x1) + b);<br />
		plot(x1, y);<br />
		x1 += (sx * params.speed);</p>
<p>		if (x1 &gt;= x2) {<br />
			clearInterval(interval);<br />
			params.onComplete();<br />
		}</p>
<p>	};</p>
<p>	/**<br />
	 * Move the target element to the given coordinates<br />
	 * @param float x The horizontal coordinate<br />
	 * @param float y The vertical coordinate<br />
	*/<br />
	var plot = function(x, y) {<br />
		el.style.left = x + &#8216;px&#8217;;<br />
		el.style.top = y + &#8216;px&#8217;;<br />
	};</p>
<p>	init();</p>
<p>};<br />
</textarea></p>
<p>
The parameters are self-explanatory except for the (optional) <code>params</code> object. Here&#8217;s a breakdown:
</p>
<ul>
<li><code>delay</code>: The interval that the <code>setInterval</code> call uses [default: 10]</li>
<li><code>onComplete</code>: An optional function to call when the algorithm is finished</li>
<li><code>speed</code>: How quickly to move the element down the line [default: 5]</li>
</ul>
<p>
I&#8217;m not sure how much use this has in the &#8220;real world&#8221; but it&#8217;s typically pretty neat to see elements dancing around the page,<br />
and I always love to see classic algorithms put to good use.<br />
Enjoy!
</p>
<ul>
<li><a href="/assets/js/bresenhams-line-algorithm/bresenhams-line-algorithm.js">[Download bresenhams-line-algorithm.js]</a> (1,769 bytes)</li>
<li><a href="/assets/js/bresenhams-line-algorithm/bresenhams-line-algorithm-min.js">[Download bresenhams-line-algorithm-min.js]</a> (516 bytes; compressed)</li>
</ul>
<p><script src="/assets/js/bresenhams-line-algorithm/bresenhams-line-algorithm-min.js" type="text/javascript"></script><br />
<script type="text/javascript">
<!--//	
YAHOO.util.Event.onDOMReady(function() {</p>
<p>	var
		busy = false,
		con = document.getElementById('example'),
		el = document.createElement('div'),
		x = 0,
		y = 0;</p>
<p>	el.style.border = '1px solid red';
	el.style.left = '0px';
	el.style.top = '0px';
	el.style.position = 'absolute';
	el.style.width = '25px';
	el.style.height = '25px';</p>
<p>	con.appendChild(el);</p>
<p>	// Listen for the click event
	YAHOO.util.Event.addListener(con, 'click', function(e) {</p>
<p>		if (busy) {
			return;
		}</p>
<p>		var coords = YAHOO.util.Event.getXY(e);
		busy = true;
		x = coords[0] - YAHOO.util.Dom.getX(con);
		y = coords[1] - YAHOO.util.Dom.getY(con);</p>
<p>		bresenham(el, 0, 0, x, y, {
			onComplete : function() {
				busy = false;
			}
		});</p>
<p>	});</p>
<p>});
//-->
</script></p>
]]></content:encoded>
			<wfw:commentRss>http://scriptnode.com/article/bresenhams-line-algorithm-in-javascript/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
