<?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>WebProNews &#187; VAR</title>
	<atom:link href="http://www.webpronews.com/tag/var/feed" rel="self" type="application/rss+xml" />
	<link>http://www.webpronews.com</link>
	<description>Breaking News in Tech, Search, Social, &#38; Business</description>
	<lastBuildDate>Mon, 13 Feb 2012 00:02:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Form Post in Spry</title>
		<link>http://www.webpronews.com/form-post-in-spry-2007-01</link>
		<comments>http://www.webpronews.com/form-post-in-spry-2007-01#comments</comments>
		<pubDate>Wed, 31 Jan 2007 15:58:24 +0000</pubDate>
		<dc:creator>Raymond Camden</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[ONE]]></category>
		<category><![CDATA[Spry]]></category>
		<category><![CDATA[VAR]]></category>

		<guid isPermaLink="false">http://www.webpronews.com/?p=34920</guid>
		<description><![CDATA[Last week or so I <a href="http://ray.camdenfamily.com/index.cfm/2007/1/14/Doing-a-form-POST-in-Spry" class="bluelink">blogged</a> about doing form postings with Spry.
]]></description>
			<content:encoded><![CDATA[<p>Last week or so I <a href="http://ray.camdenfamily.com/index.cfm/2007/1/14/Doing-a-form-POST-in-Spry" class="bluelink">blogged</a> about doing form postings with Spry.</p>
<p>I was asked to provide a bit more documentation so I thought I&#8217;d show a slightly more detailed example. </p>
<p>First lets start with a very simple form: </p>
<p><code>&lt;form&gt;<br />
number one: &lt;input type="text" name="one" id="one"&gt;&lt;br&gt;<br />
number two: &lt;input type="text" name="two" id="two"&gt;&lt;br&gt;<br />
&lt;/form&gt;</code></p>
<p>This form has two simple text fields named one and two. I want to use Spry to send the values of these two fields to the server. First lets add a simple button: </p>
<p><code>&lt;input type="button" value="Add" onClick="doAddPost()"&gt;</code></p>
<p>This simply fires off a JavaScript function. I&#8217;m going to break the function up and explain each and every line to make it as clear as possible. First, start the function. </p>
<p><code>function doAddPost() {</code></p>
<p>We need to know <i>where</i> we will be posting the form, so next I define the URL: </p>
<p><code>var url = "moon.cfm";</code></p>
<p>Now I need to grab the values I want to post. Normally with a submit button you don&#8217;t have to worry about this. The browser simply sends all the form fields. In this case though I have to specify the fields manually. First I&#8217;ll grab the value of the form field, one, using the Spry/Prototype $() shortcut: </p>
<p><code>var one = $("one").value;</code></p>
<p>Then I&#8217;ll grab the value from the second form field: </p>
<p><code>var two = $("two").value;</code></p>
<p>The form post data must be sent like a query string: foo1=value1&#038;foo2=value2. Again, I have to do this by hand: </p>
<p><code>var formData = 'one='+one+'&#038;two='+two;</code></p>
<p>Next I encode any values in the string, like spaces or other special characters: </p>
<p><code>formData = encodeURI(formData);</code></p>
<p>So the last thing we do is run the Spry code that will handle the form post. I talked about this more in the <a href="http://ray.camdenfamily.com/index.cfm/2007/1/14/Doing-a-form-POST-in-Spry" class="bluelink">last post</a> so I won&#8217;t spend a lot of time on it. </p>
<p>Spry.Utils.loadURL(&#8216;POST&#8217;, url, true, resFunc, {postData: formData, headers: {&#8220;Content-Type&#8221;: &#8220;application/x-www-form-urlencoded; charset=UTF-8&#8243;}});</p>
<p>The first argument defines the type of request (GET or POST). The second argument is the URL value I defined earlier. The third argument defines if the call is asynchronous or not. The fourth argument defines a function to run with the result of the HTTP call. </p>
<p>Lastly there is a structure of arguments that define the request. Again I have to thank Keith for figuring this out. </p>
<p>So here is the function again all in one code block: </p>
<p><code>function doAddPost() {<br />
&nbsp; &nbsp;   var url = "moon.cfm";<br />
&nbsp; &nbsp;    var one = $("one").value;<br />
&nbsp; &nbsp;    var two = $("two").value;<br />
&nbsp; &nbsp;    var formData = 'one='+one+'&#038;two='+two;<br />
&nbsp; &nbsp;    formData = encodeURI(formData);<br />
&nbsp; &nbsp;    Spry.Utils.loadURL('POST', url, true, resFunc, {postData: formData, headers: {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}});<br />
}</code></p>
<p>So how do we handle this server side? We have a few options. As I mentioned, the loadURL function lets you define code to run with the result. So whatever the server returned I can work with in JavaScript. This can be either a string or XML or WDDX. To make it easier I&#8217;ll just return a simple string: </p>
<p><code>&lt;cfsetting enablecfoutputonly=true&gt;<br />
&lt;cfparam name="form.one" default="0"&gt;<br />
&lt;cfparam name="form.two" default="0"&gt;</p>
<p>&lt;cfif isNumeric(form.one) and isNumeric(form.two)&gt;<br />
&nbsp; &nbsp;    &lt;cfoutput&gt;#form.one+form.two#&lt;/cfoutput&gt;<br />
&lt;cfelse&gt;<br />
&nbsp; &nbsp;    &lt;cfoutput&gt;0&lt;/cfoutput&gt;<br />
&lt;/cfif&gt;</code></p>
<p>Obviously there isn&#8217;t anything too complex here, just the addition of two numbers. I take the result and simply output it directly to the client requesting the data. With me so far? </p>
<p>Now let&#8217;s return to JavaScript and work with the result. I had specified the a function named resFunc would handle the result. The function is all of 4 lines: </p>
<p><code>function resFunc(request) {<br />
&nbsp; &nbsp;    var result = request.xhRequest.responseText;<br />
&nbsp; &nbsp;    $("result").innerHTML = "Result was: " + result;<br />
}</code></p>
<p>Spry automatically passes a collection of data back. The information I&#8217;m interested in resides in xhRequest.responseText. Once I have that, I can write out the result in the browser. </p>
<p>So I had mentioned more than once I wanted to make this process a bit simpler. Here is my first draft at it: </p>
<p><code>function doFormPost(url,formlist,resfunc) {<br />
&nbsp; &nbsp;    var formdata = '';<br />
&nbsp; &nbsp;    var formarray = formlist.split(',');<br />
&nbsp; &nbsp;    for(var i=0; i &lt; formarray.length; i++) {<br />
&nbsp; &nbsp; &nbsp;       formdata+='&#038;'+formarray[i]+'=';<br />
&nbsp; &nbsp; &nbsp;       var fValue = $(formarray[i]).value;<br />
&nbsp; &nbsp; &nbsp;       formdata+=fValue;<br />
&nbsp; &nbsp;    }<br />
&nbsp; &nbsp;    formData = encodeURI(formdata);<br />
&nbsp; &nbsp;    Spry.Utils.loadURL('POST', url, true, resfunc, {postData: formdata, headers: {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}});<br />
}</code></p>
<p>This lets you pass in a url and a list of form fields to post. The third argument is optional. So to do a Spry post you can do this instead of the button and custom function I had before: </p>
<p><code>&lt;input type="button" value="Add3" onClick="doFormPost('moon.cfm', 'one,two',resFunc)"&gt;</code></p>
<p>As I said though this is just a first draft. Right now it assumes just text fields. </p>
<p><a href="http://ray.camdenfamily.com/index.cfm/2007/1/29/Doing--form-Post-in-Spry-2#comments" class="bluelink">Comments</a></p>
<p>Tag:   </p>
<p><a href="javascript:void   window.open('http://digg.com/submit?phase=2&#038;url='+encodeURIComponent(window.   location.href)+'&#038;ei=UTF-8','popup','width=520px,height=420px,status=0,location=0,resizable=1,scrollbars=1,left=100,top=50',0)"><img   src="http://images.ientrymail.com/webpronews/digg-pic.png" border=0> Digg</a> | <a href="javascript:location.href='http://reddit.com/submit?url='+encodeURIComponent(location.href)+'&#038;title='+encodeURIComponent(document.title)"><img  src="http://images.ientrymail.com/webpronews/reddit.png" border=0>Reddit</a> | <a href="javascript:location.href='http://www.furl.net/storeIt.jsp?u='+encodeURIComponent(document.location.href)+'&#038;t='+encodeURIComponent(document.title)+ '   '"><img src="http://images.ientrymail.com/webpronews/furl-pic.png" border=0> Furl</a> </p>
<p> Bookmark WebProNews: <a href="http://www.webpronews.com"><img src="http://images.ientrymail.com/webpronews/wpn-readit.jpg" border=0></a></p>
<p>Raymond Camden, ray@camdenfamily.com<br />
<a href="http://ray.camdenfamily.com">http://ray.camdenfamily.com</a></p>
<p>Raymond Camden is Vice President of Technology for roundpeg, Inc. A long<br />
time ColdFusion user, Raymond has worked on numerous ColdFusion books<br />
and is the creator of many of the most popular ColdFusion community web<br />
sites. He is an Adobe Community Expert, user group manager, and the<br />
proud father of three little bundles of joy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webpronews.com/form-post-in-spry-2007-01/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Europe: VARs Win With Software, Services</title>
		<link>http://www.webpronews.com/europe-vars-win-with-software-services-2006-09</link>
		<comments>http://www.webpronews.com/europe-vars-win-with-software-services-2006-09#comments</comments>
		<pubDate>Wed, 27 Sep 2006 22:26:16 +0000</pubDate>
		<dc:creator>WebProNews Staff</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Europe]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[VAR]]></category>

		<guid isPermaLink="false">http://www.webpronews.com/?p=31730</guid>
		<description><![CDATA[Solution VARs in Europe have found a bounty of over $22 billion in sales last year through services and software.
]]></description>
			<content:encoded><![CDATA[<p>Solution VARs in Europe have found a bounty of over $22 billion in sales last year through services and software.</p>
<p>Once upon a time, software used to be something to be purchased shrinkwrapped from value-added resellers, and many times the purchase coincided with a hardware purchase of substantial margins.</p>
<p>Fast forward to the 21st Century. On the VAR side, those that have shifted to focus on solutions and not hardware are seeing the growth. </p>
<p>Tekrati <a href=http://www.tekrati.com/research/News.asp?id=7859 class=bluelink>reported</a> how IT Europa&#8217;s research of the top growing VARs has found the solution side enjoying an average growth rate of nearly 12 percent.</p>
<p>&#8220;Solution VARs are showing the way for the channel model of the future, with 67 percent of their staff involved in support services, software development, and solution delivery,&#8221; Alan Norman, Managing Director of IT Europa, said in the report.</p>
<p>IT Europa also found that consulting and project management have commanded much better revenues than the typical support and service contracts. </p>
<p>Businesses have a greater need for implementation and development of better and newer business processes than for hardware-related services.</p>
<p>That may be due to on-site personnel being able to support such hardware instead of paying someone else to be the on-call service department. </p>
<p>The ability to make a legacy system into a more productive, cost effective process can profit a firm well beyond the fees it would pay the VAR for solutions.</p>
<p>Tekrati noted the solution VARs in the IT Europa report generate 54% of their income from the SME sector, (with 50 to 1000 employees) and 27% from the Enterprise sector (1000+).</p>
<p>The biggest gainers proved to be in Russia and Turkey. Both countries demonstrated about 50 percent growth. The U.K. likewise had an impressive average growth rate, which IT Europa pegged at 15.4 percent.</p>
<p>&#8212;<br />
Tag: </p>
<p>Add to <a href="http://del.icio.us/post" onclick="window.open('http://del.icio.us/post?v=4&#038;partner=wpn&#038;noui&#038;jump=close&#038;url='+encodeURIComponent(location.href)+'&#038;title='+encodeURIComponent(document.title),'delicious','toolbar=no,width=700,height=400'); return false;" CLASS="printMailTop"><img src=http://images.ientrymail.com/webpronews/delicious-pic.png border=0> Del.icio.us</a> | <a href="javascript:void window.open('http://digg.com/submit?phase=2&#038;url='+encodeURIComponent(window.location.href)+'&#038;ei=UTF-8','popup','width=520px,height=420px,status=0,location=0,resizable=1,scrollbars=1,left=100,top=50',0)"><img src=http://images.ientrymail.com/webpronews/digg-pic.png border=0> Digg</a>  | <a href="javascript:void window.open('http://myweb2.search.yahoo.com/myresults/bookmarklet?t='+encodeURIComponent(document.title)+'&#038;u='+encodeURIComponent(window.location.href)+'&#038;tag=VAR','popup','width=520px,height=420px,status=0,location=0,resizable=1,scrollbars=1,left=100,top=50',0)"><img src=http://images.ientrymail.com/webpronews/yahoo-pic.png border=0> Yahoo! My Web</a> | <a href="javascript:location.href='http://www.furl.net/storeIt.jsp?u='+encodeURIComponent(document.location.href)+'&#038;t='+encodeURIComponent(document.title)+' '"><img src=http://images.ientrymail.com/webpronews/furl-pic.png border=0> Furl</a></p>
<p>Bookmark WebProNews: <a href=http://www.webpronews.com><img src=http://images.ientrymail.com/webpronews/wpn-readit.jpg border=0></a> </p>
<p><script language=JavaScript src="http://aj.600z.com/aj/1095/0/vj?z=1&#038;dim=1088&#038;pos=15"></script></p>
<p>David Utter is a staff writer for WebProNews covering technology and business. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.webpronews.com/europe-vars-win-with-software-services-2006-09/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>No Soup For You!</title>
		<link>http://www.webpronews.com/no-soup-for-you-2006-04</link>
		<comments>http://www.webpronews.com/no-soup-for-you-2006-04#comments</comments>
		<pubDate>Tue, 11 Apr 2006 20:33:28 +0000</pubDate>
		<dc:creator>Christopher Carfi</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[VAR]]></category>

		<guid isPermaLink="false">http://www.webpronews.com/?p=28430</guid>
		<description><![CDATA[A missive from the "sales follies" department. <a href="http://www.networkworld.com/Home/jsnyder.html" class="bluelink">Joel Snyder</a>, from <a href="http://www.networkworld.com/" class="bluelink">NetworkWorld</a>, was trying to help a consulting client of his choose an email security system.
]]></description>
			<content:encoded><![CDATA[<p>A missive from the &#8220;sales follies&#8221; department. <a href="http://www.networkworld.com/Home/jsnyder.html" class="bluelink">Joel Snyder</a>, from <a href="http://www.networkworld.com/" class="bluelink">NetworkWorld</a>, was trying to help a consulting client of his choose an email security system.</p>
<p>One of the vendors under consideration at the time was CipherTrust, and Joel was going to purchase a number of systems in order to evaluate them firsthand prior to making a final recommendation to his client.</p>
<p>Here&#8217;s what happened:</p>
<blockquote><p> <i><a href="http://www.networkworld.com/columnists/2006/041006snyder.html" class="bluelink">Joel</a>: &#8220;The salesperson was ready to give us a local value-added reseller (VAR) so we could buy the $5,000 unit. But then he passed me over to CipherTrust PR, which passed me over to the vice president of sales, who passed me to a fourth person so we could apply to be a member of their partner program. This was getting ridiculous, so I explained again that I simply wanted to buy a box for my own company to use. This time, silence. No reply.<br />
After waiting a week, I found a VAR and ordered a system. Then the VAR called back: CipherTrust refused to fill the order. Why is CipherTrust unwilling to sell me a box? I don&#8217;t know; they aren&#8217;t talking.</p>
<p>More frightening than my experience is the possibility that the company might do this to an existing customer. What good is a security product if the vendor refuses to sell you service on it? Without updates, most of these products are barely useful as doorstops.</p>
<p>In our tests, we look at products, not companies. Things such as training, finances and corporate style don&#8217;t come into it. <b>But when it comes to buying products, our tests aren&#8217;t enough. It&#8217;s important to investigate all those peripheral aspects of the vendor before you sign a purchase order. I was reminded of that the hard way.&#8221;</b> (emphasis added)</i> </p></blockquote>
<p><a href="http://www.networkworld.com/columnists/2006/041006snyder.html" class="bluelink">Here&#8217;s the full story</a>.</p>
<p>Any other good stories out there of cases where a vendor simply chose not to show up?</p>
<p><i>(hat tip: <a href="http://techdirt.com/articles/20060411/0244221.shtml" class="bluelink">mike</a>)</i></p>
<p>Add to <script language='javascript'> document.write("<a   href='http://del.icio.us/post?url="+encodeURIComponent(document.location.href)+"&#038;title="+encodeURIComponent(document.title)+"  '>Del.icio.us</a>")</script> | <a href="javascript:void   window.open('http://digg.com/submit?phase=2&#038;url='+encodeURIComponent(window.location.href)+'&#038;ei=UTF-8','popup','width=520px,h  eight=420px,status=0,location=0,resizable=1,scrollbars=1,left=100,top=50',0)">Digg</a>  | <a href="javascript:void   window.open('http://myweb2.search.yahoo.com/myresults/bookmarklet?t='+encodeURIComponent(document.title)+'&#038;u='+encodeURICompo  nent(window.location.href)+'&#038;ei=UTF-8','popup','width=520px,height=420px,status=0,location=0,resizable=1,scrollbars=1,left=10  0,top=50',0)">Yahoo! My Web</a></p>
<p>Technorati: </p>
<p>Christopher Carfi, CEO and co-founder of Cerado, looks at sales, marketing, and the business experience from the customers point of view. He currently is focused on understanding how emerging social technologies such as blogs, wikis, and social networking are enabling the creation of new types of customer-driven communities. He is the author of the <a href="http://www.socialcustomer.com/">Social Customer Manifesto</a> weblog, and has been occasionally told that he drives and snowboards just a little too quickly.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webpronews.com/no-soup-for-you-2006-04/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple Schedule</title>
		<link>http://www.webpronews.com/simple-schedule-2006-03</link>
		<comments>http://www.webpronews.com/simple-schedule-2006-03#comments</comments>
		<pubDate>Tue, 07 Mar 2006 13:53:06 +0000</pubDate>
		<dc:creator>A.P. Lawrence</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[VAR]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.webpronews.com/?p=27400</guid>
		<description><![CDATA[I often get asked for web-based scheduling programs. I've done quite a few of them over the years, sometimes using scripts available from the web, but more often writing my own simply because I don't like modifying other people's code.
]]></description>
			<content:encoded><![CDATA[<p>I often get asked for web-based scheduling programs. I&#8217;ve done quite a few of them over the years, sometimes using scripts available from the web, but more often writing my own simply because I don&#8217;t like modifying other people&#8217;s code.</p>
<p>All of the calendar based schedules I&#8217;ve done start with the very simple files presented here. This base version doesn&#8217;t have much flexibility: it lets you put in one note per day, and anyone who can access the schedule can overwrite that with new information. Obviously most businesses need additional features like multiple items, control of access, and probably much more. But this is the starting point we can build from.</p>
<p>As shown here, your web server needs to support SSI (Server Side Includes). Nowadays most of us would do this with php instead, but I still use the Perl methods because I&#8217;m old and stuck in my ways. Maybe I&#8217;ll show a php version later.</p>
<p>The entire scheduling program consists of one web page. You can call it whatever you want, but the cgi-bin perl script needs to know where it can find it in your filesystem. The cgi script uses a Perl database to store scheduled events; that can be located anywhere also but of course has to be accessible by the user Apache is running as.</p>
<p>Note that the script serves two purposes: it is called to add items to the schedule and as a server side include to display scheduled events. In this version we have no pretty formatting or other niceties that almost certainly would be needed in a production version.</p>
<p>The script reads the web page and displays it when it is called for a specific day; this could have been done differently with a basically empty web page depending on a cgi script to provide the contents. However, this design lets unskilled people edit the web page without affecting the script.</p>
<p><a name="Code"></a>The web page and associated script follow:</p>
<p><code># sched.html<br />
&lt;html&gt;&lt;head&gt;&lt;title&gt;Schedule&lt;/title&gt;&lt;/head&gt;&lt;body bgcolor="lightgreen"&gt;<br />
&lt;h2&gt;Schedule&lt;/h2&gt;</p>
<p>&lt;script language="JavaScript"&gt;<br />
&lt;!-- yes this should look like this<br />
function calendar() {<br />
var now=today.getDate();<br />
var tmonth=today.getMonth();<br />
var tyear=today.getYear();<br />
if (tyear &lt; 1000) { tyear += 1900};<br />
var d=new Date(year,month,"1");<br />
var dd=new Date(year,nextmonth,"1");<br />
var aday=(1000 * 60 * 60 * 24);<br />
var ms=dd.getTime();<br />
ms -= aday;<br />
dd.setTime(ms);<br />
var lastday=dd.getDate();</p>
<p>var sd=d.getDay();<br />
pmonth=month-1;<br />
pyear=year;<br />
nmonth=month+1;<br />
nyear=year;</p>
<p>if (pmonth &lt; 0) { pmonth=11; pyear--;}<br />
if (nmonth &gt; 11) {nmonth=0; nyear++;}<br />
dnmonth=nmonth+1;<br />
dpmonth=pmonth+1;<br />
document.write("&lt;h2&gt;Calendar for  ");<br />
document.write(names[month] + " " + year);<br />
document.write("&lt;/h2&gt;");</p>
<p>document.write("&lt;TABLE BORDER width=\"50%\" cellwidth=\"14%\" CELLpadding=8&gt;");<br />
var y=1;<br />
document.write("&lt;TR&gt;");<br />
document.write("&lt;td&gt;S&lt;/td&gt;&lt;td&gt;M&lt;/td&gt;&lt;td&gt;T&lt;/td&gt;&lt;td&gt;W&lt;/td&gt;<br />
&lt;td&gt;T&lt;/td&gt;&lt;td&gt;F&lt;/td&gt;&lt;td&gt;S&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;");<br />
for ( x=0; x &lt; sd ; x++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;        document.write("&lt;TD&gt;&lt;/TD&gt;");<br />
}<br />
t=sd;<br />
var prinmonth=month+1;</p>
<p>for ( x=sd; x &lt; lastday + sd; x++) {<br />
document.write("&lt;TD width=\"100\" &gt;" +   "&lt;a href=\"/cgi-bin/sched.pl?" +<br />
prinmonth + "/" + y + "/" + year + "\"&gt;" + y + "&lt;/a&gt;"  + "&lt;/td&gt;");<br />
y++;t++;<br />
if ((t % 7) == 0) { document.write("&lt;/TR&gt;&lt;tr&gt;")};<br />
}<br />
document.write("&lt;/TR&gt;&lt;TR&gt;");<br />
document.write("&lt;/table&gt;");<br />
}</p>
<p>var argstr=location.search.substring(1,location.search.length);<br />
var args= argstr.split('/');<br />
var today=new Date();<br />
if ( args[0] != "" ) {<br />
&nbsp; var rmonth=args[0];<br />
&nbsp; rmonth--;<br />
&nbsp; today=new Date(args[2],rmonth,args[1]);<br />
}<br />
var month=today.getMonth();<br />
var nextmonth=month+1;<br />
var nxmonth=month+2;<br />
var prmonth=month;<br />
var year=today.getYear();<br />
if (year &lt; 1000) { year += 1900};<br />
var nxyear=year;<br />
var pryear=year;<br />
if (nextmonth &gt; 12) {nextmonth=1};<br />
if (nxmonth &gt; 12) {nxmonth=1;nxyear++};<br />
if (prmonth &lt; 1) {prmonth=12;pryear--};<br />
$bstart="";<br />
$bend="";<br />
names=new Array("January","February","March","April","May","June","July",<br />
"August","September","October","November","December");<br />
var x=0;<br />
calendar();<br />
document.write("&lt;p&gt;&lt;a href=\"/sched.html?");<br />
document.write(prmonth + "/" + "01/" + pryear + "\"&gt;Previous&lt;/a&gt;");<br />
document.write("&lt;---------&gt;&lt;a href=\"/sched.html?");<br />
document.write(nxmonth + "/" + "01/" + nxyear + "\"&gt;Next&lt;/a&gt;");</p>
<p>// and this should look like this --&gt;<br />
&lt;/script&gt;<br />
&lt;p&gt;<br />
&lt;!--#include virtual="/cgi-bin/sched.pl" --&gt;</p>
<p>&lt;/body&gt;&lt;/html&gt;<br />
 -----------------</p>
<p>#!/usr/bin/perl<br />
use CGI qw(:standard);<br />
use  Time::Local;<br />
$posting=param('posting');<br />
$date=shift @ARGV;<br />
$date=param('date') if not $date;<br />
print "Content-TYPE: text/html\n\n";<br />
if ($date) {<br />
open(I,"/var/www/html/sched.html");<br />
@stuff=&lt;I&gt;;<br />
foreach (@stuff) {<br />
  print if not /&lt;.body&gt;&lt;.html&gt;/;<br />
}<br />
}<br />
$today=time();<br />
$delete=$today;<br />
$delete -= (3600 * 24 * 90);<br />
@d=split /\//,$date;<br />
eval {$filedate=timelocal(0,0,0,$d[1],$d[0]-1,$d[2]-1900);} ;<br />
dbmopen(%sched,"/home/schedules/schedules",0666) or print $!;<br />
$lastdate=$filedate;<br />
$firstdate=$filedate;<br />
if (not $date ) {<br />
&nbsp;&nbsp;&nbsp;    @d=localtime($today);<br />
&nbsp;&nbsp;&nbsp;   eval {$firstdate=timelocal(0,0,0,1,$d[4],$d[5]);} ;<br />
&nbsp;&nbsp;&nbsp;   eval {$lastdate=timelocal(0,0,0,1,$d[4]+1,$d[5]+1);} ;<br />
&nbsp;&nbsp;&nbsp;   print "&lt;hr&gt;";<br />
}<br />
$schedule=param('schedule');<br />
$sched{$firstdate}=$schedule if $schedule;<br />
print "&lt;p&gt;Listings for $date&lt;/p&gt;";<br />
foreach(sort keys %sched) {<br />
&nbsp; delete $sched{$_} if $_ &lt; $delete;<br />
&nbsp; #delete $sched{$_};<br />
&nbsp; next if $_ &lt; $firstdate;<br />
&nbsp; next if $_ &gt; $lastdate;<br />
&nbsp; $now=localtime($_) if not $date;<br />
&nbsp; $now=~ s/00:00:00//;<br />
&nbsp; print "&lt;br&gt; $now $sched{$_}";</p>
<p>}<br />
dbmclose %sched;<br />
if ($date) {<br />
print &lt;&lt;EOF;<br />
&lt;p&gt;&lt;a href="/sched.html"&gt;Return to Full<br />
Calendar&lt;/a&gt;&lt;/p&gt;<br />
&lt;form method=post action="/cgi-bin/sched.pl"&gt;<br />
&lt;p&gt;Add note for $date: &lt;input type=text size=60 name="schedule"&gt;<br />
&lt;input type=hidden name="date" value="$date"&gt;<br />
&lt;p&gt;&lt;input type=submit name="posting" value="Add"&gt;<br />
&lt;/form&gt;<br />
EOF<br />
}</p>
<p>print "&lt;/body&gt;&lt;/html&gt;" if ($date);</code></p>
<p>That&#8217;s all of it. It&#8217;s simple, but can actually be easily expanded to much more complexity without a great deal of effort.</p>
<p>*Originally published at <a href="http://www.aplawrence.com" class="bluelink">APLawrence.com</a></p>
<p>Add to <script language='javascript'> document.write("<a   href='http://del.icio.us/post?url="+encodeURIComponent(document.location.href)+"&#038;title="+encodeURIComponent(document.title)+"  '>Del.icio.us</a>")</script> | <a href="javascript:void   window.open('http://digg.com/submit?phase=2&#038;url='+encodeURIComponent(window.location.href)+'&#038;ei=UTF-8','popup','width=520px,h  eight=420px,status=0,location=0,resizable=1,scrollbars=1,left=100,top=50',0)">DiggThis</a>  | <a href="javascript:void   window.open('http://myweb2.search.yahoo.com/myresults/bookmarklet?t='+encodeURIComponent(document.title)+'&#038;u='+encodeURICompo  nent(window.location.href)+'&#038;ei=UTF-8','popup','width=520px,height=420px,status=0,location=0,resizable=1,scrollbars=1,left=10  0,top=50',0)">Yahoo! My Web</a></p>
<p>Technorati: </p>
<p>A.P. Lawrence provides SCO Unix and Linux consulting services http://www.pcunix.com</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webpronews.com/simple-schedule-2006-03/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Kaspersky Lab Takes Best VAR Software Solution</title>
		<link>http://www.webpronews.com/kaspersky-lab-takes-best-var-software-solution-2005-10</link>
		<comments>http://www.webpronews.com/kaspersky-lab-takes-best-var-software-solution-2005-10#comments</comments>
		<pubDate>Mon, 24 Oct 2005 15:04:55 +0000</pubDate>
		<dc:creator>John Stith</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[VAR]]></category>

		<guid isPermaLink="false">http://www.webpronews.com/?p=24016</guid>
		<description><![CDATA[Internet security software company Kaspersky Lab announced they received the "Best VAR Software Solution" award at the IT ChannelVision Event and was a finalist for the "Best VAR Presentation" and "Best System Builder Channel Strategy."
]]></description>
			<content:encoded><![CDATA[<p>Internet security software company Kaspersky Lab announced they received the &#8220;Best VAR Software Solution&#8221; award at the IT ChannelVision Event and was a finalist for the &#8220;Best VAR Presentation&#8221; and &#8220;Best System Builder Channel Strategy.&#8221;</p>
<p>These awards are significant because they&#8217;re voted on and awarded by people and groups within the value-added reseller (VAR) industry.  This means that professionals are evaluating the entries and judging them based on high levels of knowledge about the industry.</p>
<p>	&#8220;Being voted the Best VAR Software Solution at IT ChannelVision underscores our commitment to the 100% dedication we have to our channel partners,&#8221; said Steve Orenberg, President, Kaspersky Lab, Inc. &#8220;When it comes to fighting Internet crime with our top rated anti-virus, anti-spam, anti-spyware and anti-hacker solutions, we see Kaspersky Lab as a very real win-win proposition &#8211; the highest quality and lowest cost solution for our customers and the best possible margins and support in the industry for our partners.&#8221;</p>
<p>	The IT ChannelVision puts together three events into one groovy event. Those events include the VARVision for value-added resellers; System Builder summit, a white box marketing event; and EnterpriseVision, an event for solution providers serving enterprise customers.</p>
<p>	&#8220;IT ChannelVision attendees are senior decision-makers who directly influence their customers&#8217; technology buying decisions,&#8221; said Eric Lesonsky, senior global director for IT ChannelVision. &#8220;Vendor winners and nominees of the IT ChannelVision awards should all be proud to be recognized as among the finest channel solutions in the North American IT marketplace today and for the year to come.&#8221;</p>
<p>	Kaspersky Lab is known for their complete package of security software. Their software packages provide anti-virus, anti-spyware, anti-spam and firewall capabilities for their customers.  Vision Events are put together by Gartner.</p>
<p>John Stith is a staff writer for WebProNews covering technology and business. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.webpronews.com/kaspersky-lab-takes-best-var-software-solution-2005-10/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Microsoft Business Solutions VAR/Partner Selection  Overview for IT Director/Manager/Controller</title>
		<link>http://www.webpronews.com/microsoft-business-solutions-varpartner-selection-overview-for-it-directormanagercontroller-2005-06</link>
		<comments>http://www.webpronews.com/microsoft-business-solutions-varpartner-selection-overview-for-it-directormanagercontroller-2005-06#comments</comments>
		<pubDate>Wed, 08 Jun 2005 15:19:40 +0000</pubDate>
		<dc:creator>Andrew Karasev</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[business]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[VAR]]></category>

		<guid isPermaLink="false">http://www.webpronews.com/?p=19338</guid>
		<description><![CDATA[Microsoft Great Plains and Microsoft CRM become more and more popular, partly because of Microsoft muscles behind them. Now Great Plains is targeted to the whole spectrum of horizontal and vertical market clientele. Small companies use Small Business Manager (which is based on the same technology - Great Plains Dexterity dictionary and runtime), Great Plains Standard on MSDE is for small to midsize clients, and then Great Plains serves the rest of the market up to big corporations. Microsoft CRM is extremely scalable and fits to all the market niches.
]]></description>
			<content:encoded><![CDATA[<p>Microsoft Great Plains and Microsoft CRM become more and more popular, partly because of Microsoft muscles behind them. Now Great Plains is targeted to the whole spectrum of horizontal and vertical market clientele. Small companies use Small Business Manager (which is based on the same technology &#8211; Great Plains Dexterity dictionary and runtime), Great Plains Standard on MSDE is for small to midsize clients, and then Great Plains serves the rest of the market up to big corporations. Microsoft CRM is extremely scalable and fits to all the market niches.</p>
<p>It is always good idea to install everything on your own &#8211; however Great Plains requires combination of computer networking, some programming, good accounting/distribution/logistics/reporting background &#8211; so it is not a surprise that Microsoft Business Solutions requires their customers to have specially assigner Microsoft Great Plains Partner/VAR/Reseller to serve the account. </p>
<p>If you are IT Director/Controller who has the dilemma of proper partner selection &#8211; read this and you will have the clues on where to look further. </p>
<p><b>1. </b>Local partners &#8211; if you are in the remote area &#8211; there is often seen the opinion that local partner is the best choice. Consider this however as a contra argument &#8211; local partners maybe tiny with one/few consultants and they may not serve you adequately when you have somewhat complex &#8211; such as Manufacturing, complex Project Accounting needs, integration with UNIX-based legacy system, etc. </p>
<p><b>2. </b>Mid-Size partners in Major Business Metros &#8211; these companies were classical Great Plains VARS/Resellers with balanced application consulting and technical expertise. Please, consider these points, however: in recent recession most of such partners were bought or merged with big auditing companies and lost their flexibility, plus their consulting fee went up due to the fact of belonging to big conglomerates. </p>
<p><b>3. </b>Nation-wide partners with local representative offices. This maybe a very good option, if you need kind of reliability and complete expertise &#8211; missing parts could be taken from different location with this specialization. However the hourly rates are probably the highest among the first three. </p>
<p><b>4. </b>One-Project-Manager partner with Offshore consultants &#8211; Well &#8211; this is very new type of partners &#8211; and you potentially can save a lot of money if you are risk taker &#8211; hourly rate is usually lower, price of the failure maybe higher. </p>
<p><b>5.</b> Nation-wide partner with tiny local representation, serving via remote support. We are in this category, so let me tell you couple of good points here. Companies like ours &#8211; have to specialize in order to do excellent job in what we claim is our specialization (technology challenging projects with heavy customization needs). Serving via remote support lets us keep reasonably low rates and often go for fixed bids. </p>
<p>Also couple of hints about how do you switch the partner. It is actually more easy than you may think &#8211; you just send the new proposed partner the letter in free format saying that you would like to switch to you as my Microsoft Business Solutions partner &#8211; and this is it. </p>
<p>Happy shopping! if you want us to help you &#8211; give us a call 1-866-528-0577! <a href="mailto:help@albaspectrum.com">help@albaspectrum.com</a></p>
<p>Andrew Karasev is Chief Technology Officer in Alba Spectrum Technologies  USA nationwide Microsoft CRM, Microsoft Great Plains customization company, based in Chicago, California, Texas, New York, Georgia and Florida and having locations in multiple states and internationally (<a href="http://www.albaspectrum.com">www.albaspectrum.com</a>), he is Dexterity, SQL, C#.Net, Crystal Reports and Microsoft CRM SDK developer.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webpronews.com/microsoft-business-solutions-varpartner-selection-overview-for-it-directormanagercontroller-2005-06/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>XML Data Traversal</title>
		<link>http://www.webpronews.com/xml-data-traversal-2003-09</link>
		<comments>http://www.webpronews.com/xml-data-traversal-2003-09#comments</comments>
		<pubDate>Thu, 18 Sep 2003 21:37:18 +0000</pubDate>
		<dc:creator>Premshree Pillai</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[VAR]]></category>
		<category><![CDATA[Websites]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.webpronews.com/?p=7644</guid>
		<description><![CDATA[In this article, I present a XML based client-side JavaScript that reads data from an external XML file, traverses the XML data and displays the same in a tree format. I'll use the XMLDOM ActiveX object built into Microsoft Internet Explorer for the same.
]]></description>
			<content:encoded><![CDATA[<p>In this article, I present a XML based client-side JavaScript that reads data from an external XML file, traverses the XML data and displays the same in a tree format. I&#8217;ll use the XMLDOM ActiveX object built into Microsoft Internet Explorer for the same.</p>
<p><b>Details :</b></p>
<p>Consider the following XML file: </p>
<table width="240" border="0" cellpadding="0" cellspacing="0" bgcolor="#D3DFEB">
<tr>
<td><font size="1" face="Verdana, Arial, Helvetica, sans-serif"><strong>&lt;?xml version=&quot;1.0&quot;?&gt;<br />&lt;personal&gt;Personal Details<br /> &#038;nbsp&#038;nbsp	&lt;name&gt;Premshree Pillai&lt;/name&gt;<br />&#038;nbsp&#038;nbsp	&lt;sex&gt;male&lt;/sex&gt;<br />&#038;nbsp&#038;nbsp	&lt;websites&gt;Websites<br />&#038;nbsp&#038;nbsp		&lt;ws1&gt;http://www.qiksearch.com&lt;/ws1&gt;<br />	&#038;nbsp&#038;nbsp	&lt;ws2&gt;http://premshree.resource-locator.com&lt;/ws2&gt;<br />	&lt;/websites&gt;<br />&lt;/personal&gt;</strong></font></td>
</tr>
</table>
<p>Now, what we want the script to do is, display the above XML data in the following manner : </p>
<table width="400" border="0" cellpadding="0" cellspacing="0" bgcolor="#D3DFEB">
<tr>
<td><font size="1" face="Verdana, Arial, Helvetica, sans-serif"></p>
<ul>
<li><b>personal : </b>Personal Details
<ul>
<li><b>name : </b>Premshree Pillai</li>
</ul>
<ul>
<li><b>sex : </b>male</li>
</ul>
<ul>
<li><b>websites : </b>Websites
<ul>
<li><b>ws1 : </b>http://www.qiksearch.com</li>
</ul>
<ul>
<li><b>ws2 : </b>http://premshree.resource-locator.com</li>
</ul>
</li>
</ul>
</li>
</ul>
<p></font></td>
</tr>
</table>
<p><b>Algorithm : </b></p>
<ul>
<li>Read the XML file  </li>
<li>We point a variable, tree to the first node (XML tag) of the XML data.  </li>
<li>If the node has child nodes :  </li>
<ul>
<li>Print &#8221; &lt;ul&gt;&lt;li&gt; &#8220;;</li>
<li>For each child node, traverse(tree.childNodes(nodeNum))  </li>
<li>Print &#8221; &lt;/li&gt;&lt;/ul&gt; &#8220;;  </li>
</ul>
<li>If the node does not have any child :  </li>
<ul>
<li>Print the node&#8217;s value. </li>
</ul>
</ul>
<p><b>Script and explanation :</b> </p>
<p>Now let us take a look at the script : </p>
<table width="350" border="0" cellpadding="0" cellspacing="0" bgcolor="#D3DFEB">
<tr>
<td><font size="1" face="Verdana, Arial, Helvetica, sans-serif"><strong>   var xmlDoc=new ActiveXObject(&quot;Microsoft.XMLDOM&quot;);      </strong></font></td>
</tr>
</table>
<p>The above code creates a new instance of the Microsoft.XMLDOM ActiveX object.</p>
<table width="400" border="0" cellpadding="0" cellspacing="0" bgcolor="#D3DFEB">
<tr>
<td>
<pre><font size="1" face="Verdana, Arial, Helvetica, sans-serif"><strong>function loadXML(xmlFile) {
	xmlDoc.async="false";
	xmlDoc.onreadystatechange=verify;
	xmlDoc.load(xmlFile);
}   </strong></font></pre>
</td>
</tr>
</table>
<p>The loadXML() function is used to load a particular .xml file. This function makes reference to the verify() function, which is as follows : </p>
<table width="400" border="0" cellpadding="0" cellspacing="0" bgcolor="#D3DFEB">
<tr>
<td>
<pre><font size="1" face="Verdana, Arial, Helvetica, sans-serif"><strong>function verify() {
	if(xmlDoc.readyState!=4)
		return false;
}   </strong></font></pre>
</td>
</tr>
</table>
<p>The loading of a XML file goes through 5 stages : </p>
<ul>
<li>0 &#8211; Object is not initialized </li>
<li>1 &#8211; Loading object is loading data </li>
<li>2 &#8211; Loaded object has loaded data </li>
<li>3 &#8211; Data from object can be worked with </li>
<li>4 &#8211; Object completely initialized </li>
</ul>
<p>The state of loading of a XML file is accessible through the XMLDOM&#8217;s readyState property. If suppose a file (object) is not initialized then xmlDoc.readyState will return 0 and so on. Thus, in the loadXML() function we verify the status of loading of the XML document because we do not want to use a partially or uninitialized object.</p>
<p>Now, we will see the main function that does the XML data traversal, traverse() : </p>
<table width="400" border="0" cellpadding="0" cellspacing="0" bgcolor="#D3DFEB">
<tr>
<td><font size="1" face="Verdana, Arial, Helvetica, sans-serif">function traverse(tree) {<br />&#038;nbsp	if(tree.hasChildNodes()) {<br />&#038;nbsp&#038;nbsp	&#038;nbsp&#038;nbsp	document.write(&#8216;&lt;ul&gt;&lt;li&gt;&#8217;);<br />	&#038;nbsp&#038;nbsp&#038;nbsp&#038;nbsp	document.write(&#8216;&lt;b&gt;&#8217;+tree.tagName+&#8217; : &lt;/b&gt;&#8217;);<br />&#038;nbsp&#038;nbsp&#038;nbsp&#038;nbsp		var nodes=tree.childNodes.length;<br />	&#038;nbsp&#038;nbsp&#038;nbsp&#038;nbsp	for(var i=0; i&lt;tree.childNodes.length; i++)<br />	&#038;nbsp&#038;nbsp&#038;nbsp&#038;nbsp&#038;nbsp		traverse(tree.childNodes(i));<br />	&#038;nbsp&#038;nbsp&#038;nbsp&#038;nbsp	document.write(&#8216;&lt;/li&gt;&lt;/ul&gt;&#8217;);<br />&#038;nbsp&#038;nbsp	}<br />&#038;nbsp&#038;nbsp	else<br />	&#038;nbsp&#038;nbsp&#038;nbsp&#038;nbsp	document.write(tree.text);<br />}</font></td>
</tr>
</table>
<p>The traverse() function is a recursive function that takes a node as it&#8217;s argument.</p>
<p>As explained earlier in the algorithm, first the function checks if the node has any childs. If the node has any childs, necessary indentation is done using HTML lists ( &lt;ul&gt;,&lt;li&gt; tags). Next, for each child node of this node, the function traverse() is called (recursively) with the argument as that child node.</p>
<p>If the node (argument passed to traverse()) has no child nodes, then the function prints the value held by that node (tag). In this way, the tree structure for the XML file is generated. Now, we will take a look at the initTraverse() function : </p>
<table width="400" border="0" cellpadding="0" cellspacing="0" bgcolor="#D3DFEB">
<tr>
<td>
<pre><font size="1" face="Verdana, Arial, Helvetica, sans-serif"><strong>function initTraverse(file) {
	loadXML(file);
	var doc=xmlDoc.documentElement;
	traverse(doc);
}   </strong></font></pre>
</td>
</tr>
</table>
<p>The initTraverse() function takes a XML filename as it&#8217;s argument. This function first loads the XML file, sets the variable doc to the root node of the XML data and then traverses the XML data using the traverse() function with argument as the root node, i.e doc. </p>
<p>This function is the one that is called when you want to generate the tree structure of a XML file. </p>
<p>All the above code may be placed in an external .js file. The following code must be placed where the tree form of a XML file has to be generated : </p>
<table width="210" border="0" cellpadding="0" cellspacing="0" bgcolor="#D3DFEB">
<tr>
<td>
<pre><font size="1" face="Verdana, Arial, Helvetica, sans-serif"><strong>initTraverse("anyXMLfile.xml"); </strong></font></pre>
</td>
</tr>
</table>
<p><b>Script listing :</b></p>
<table width="400" border="0" cellpadding="0" cellspacing="0" bgcolor="#D3DFEB">
<tr>
<td>
<pre><font size="1" face="Verdana, Arial, Helvetica, sans-serif"><strong>&lt;script language="JavaScript"&gt;
//////////////////////////////////////////////////
//	XML Data Traversal			//
// 	(c) 2003 Premshree Pillai		//
//	http://www.qiksearch.com		//
//	http://premshree.resource-locator.com	//
//	Email : qiksearch@rediffmail.com	//
//////////////////////////////////////////////////

var xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
function loadXML(xmlFile) {
	xmlDoc.async="false";
	xmlDoc.onreadystatechange=verify;
	xmlDoc.load(xmlFile);
}

function verify() {
	if(xmlDoc.readyState!=4)
		return false;
}

function traverse(tree) {
	if(tree.hasChildNodes()) {
		document.write('&lt;ul&gt;&lt;li&gt;');
		document.write('&lt;b&gt;'+tree.tagName+' : &lt;/b&gt;');
		var nodes=tree.childNodes.length;
		for(var i=0; i&lt;tree.childNodes.length; i++)
			traverse(tree.childNodes(i));
		document.write('&lt;/li&gt;&lt;/ul&gt;');
	}
	else
		document.write(tree.text);
}

function initTraverse(file) {
	loadXML(file);
	var doc=xmlDoc.documentElement;
	traverse(doc);
}
&lt;/script&gt;   </strong></font></pre>
</td>
</table>
<p>You can find this XML based JavaScript, &#8220;XML Data Traversal&#8221; at<br />
<a href="http://premshree.resource-locator.com/javascripts/xml/traversal/traversal.htm">http://premshree.resource-locator.com/javascripts/xml/traversal/traversal.htm</a>. </p>
<p>I hope, this article has explained &#8220;XML Data Traversal&#8221;. Your comments and suggestions are welcome. </p>
<p><b> 2003</b> <a href="http://premshree.resource-locator.com/cgi-bin/contact.pl">Premshree Pillai</a>.<br />
<b>Websites: </b><a href="http://www.qiksearch.com/">http://www.qiksearch.com</a>, <a href="http://premshree.resource-locator.com/">http://premshree.resource-locator.com</a></p>
<p>Premshree Pillai studies engineering in Information Technology at<br />
Mumbai University, Mumbai, India. He is a programming enthusiast<br />
and maintains a Website (http://www.qiksearch.com), where he posts<br />
his scripts. He is also a freelance writer and has written for a<br />
range of popular Indian magazines.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webpronews.com/xml-data-traversal-2003-09/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Adding Automatic Update Support to your Application</title>
		<link>http://www.webpronews.com/adding-automatic-update-support-to-your-application--2003-09</link>
		<comments>http://www.webpronews.com/adding-automatic-update-support-to-your-application--2003-09#comments</comments>
		<pubDate>Tue, 09 Sep 2003 17:28:59 +0000</pubDate>
		<dc:creator>Sergey S.</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Support]]></category>
		<category><![CDATA[Update]]></category>
		<category><![CDATA[VAR]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.webpronews.com/?p=7567</guid>
		<description><![CDATA[We would like to introduce a simple component which retrieves version information from the website and if there is a newer version available it will download update files via HTTP/HTTPS/FTP and run the update.
]]></description>
			<content:encoded><![CDATA[<p>We would like to introduce a simple component which retrieves version information from the website and if there is a newer version available it will download update files via HTTP/HTTPS/FTP and run the update.</p>
<p><b>Abstract </b></p>
<p>There are many algorithms of automating the process of receiving web updates.<br />
But most of them have the same simple steps:</p>
<p>Connect to the web server and retrieve information about updates available for downloading.<br />
Check whether the version available on the web is up-to-date comparing to the version of your program.<br />
If the web version is up-to-date then download update file(s).<br />
Process downloaded update file(s) with appropriate method: unpacking, copying, executing etc. </p>
<p>Also there are some additional requirements for web update process:</p>
<p>Updated application should have possibility for updating own exe file which it has been run from.<br />
Downloading process should not interfere with main application process and should allow a user to continue his usual work.<br />
Downloading process can be interrupted by a user at any moment and later continued from the last stop place. </p>
<p><b>Implementation </b></p>
<p>To implement the first step of web update we need to place some resource (file for example), which contains information about last update, on the website. In our case we use <b>XML</b>-based resource file <a href="http://www.clevercomponents.com/articles/article011/webupdate.xml">webupdate.xml</a>. If you like you can use old fashioned TXT file instead of fancy XML format &#8211; this is just a matter of your personal preferences.</p>
<p>The main reason why we use XML format is simplicity of parsing information. Since we need to check for matching between your actual program version and version of update available on the web (step 2) we have to save and store information about last update to the local disk.</p>
<p>There are two methods for loading and storing of update information by using the Microsoft Document Object Model (<b>DOM</b>) library:<br />
<table width="400" border="0" cellpadding="0" cellspacing="0" bgcolor="#D3DFEB">
<tr>
<td>
<pre><font size="1" face="Verdana, Arial, Helvetica, sans-serif"><strong>procedure TclWebUpdate.GetUpdateInfo();
var
   Dom: IXMLDomDocument;
begin
   Dom := CoDOMDocument.Create();
   Dom.load(FDownloader.LocalFile);
   UpdateInfo.FURL := Dom.selectSingleNode('updateinfo/update/@url').text;
   UpdateInfo.FRunParameters := Dom.selectSingleNode('updateinfo/update/@runparameters').text;
   UpdateInfo.FVersion := Dom.selectSingleNode('updateinfo/update/@version').text;
   UpdateInfo.FSize := Dom.selectSingleNode('updateinfo/update/@size').text;
   UpdateInfo.FProductURL := Dom.selectSingleNode('updateinfo/product/@url').text;
   UpdateInfo.FProductName := Dom.selectSingleNode('updateinfo/product/@name').text;
   UpdateInfo.FAuthor := Dom.selectSingleNode('updateinfo/product/@author').text;
   UpdateInfo.FEmail := Dom.selectSingleNode('updateinfo/product/@email').text; 

   Dom.load(LastUpdateInfoFile);
   ActualInfo.FSuccess := Dom.selectSingleNode('update/@success').text;
   ActualInfo.FUpdateDate := Dom.selectSingleNode('update/@updatedate').text;
   ActualInfo.FVersion := Dom.selectSingleNode('update/@version').text;
   ActualInfo.FFileName := Dom.selectSingleNode('update/@file').text;
end; </strong></font></pre>
</td>
</tr>
</table>
<table width="400" border="0" cellpadding="0" cellspacing="0" bgcolor="#D3DFEB">
<tr>
<td>
<pre><font size="1" face="Verdana, Arial, Helvetica, sans-serif"><strong>procedure TclWebUpdate.StoreLastUpdateInfo(ASuccess: Boolean);
var
   Dom: IXMLDomDocument;
   Node: IXMLDomElement;
begin
   Dom := CoDOMDocument.Create();
   Node := Dom.createElement('update');
   Dom.appendChild(Node);
   Node.setAttribute('file', ActualInfo.FileName);
   Node.setAttribute('version', ActualInfo.Version);
   Node.setAttribute('success', ActualInfo.Success);
   Node.setAttribute('updatedate', ActualInfo.UpdateDate);
   Dom.save(LastUpdateInfoFile);
end; </strong></font></pre>
</td>
</tr>
</table>
<p>Here are the&nbsp;<b><font color="#000090">ActualInfo</font></b>&nbsp;and the&nbsp;<b><font color="#000090">UpdateInfo</font></b>&nbsp;properties which represent structures corresponding to current application version and version of update available on the web. If the downloading process has been completed successfully the update information has been saved to the local file (<i>lastupdate.xml</i>&nbsp;by default). So if you want to run web update one more time using our demo programs (<b><a border="0" hspace="0" href="http://www.clevercomponents.com/articles/article011/demo1src.zip">demo1src.zip</a></b>,&nbsp;<b><a border="0" hspace="0" href="http://www.clevercomponents.com/articles/article011/demo2src.zip">demo2src.zip</a></b>) you may delete this file or modify the version parameter to the previous value (in our case just replace the version attribute with the&nbsp;<i>&#8220;1.0&#8243;</i>&nbsp;value).<br />
<br />After the whole update info is received we need to compare versions and determine whether should we download and finally apply the update available on the web. If you are using simple enumeration for your updates (like 1, 2, 3 &#8230;. ) then the comparing method looks very simple:<br />
<table width="400" border="0" cellpadding="0" cellspacing="0" bgcolor="#D3DFEB">
<tr>
<td>
<pre><font size="1" face="Verdana, Arial, Helvetica, sans-serif"><strong>function TclWebUpdate.CheckUpdateVersion(const ANewVersion, ActualVersion: string): Boolean;
begin
   Result := StrToIntDef(ANewVersion, 0) > StrToIntDef(ActualVersion, 0);
end;</strong></font></pre>
</td>
</tr>
</table>
<p>This function returns True if the web version is up-to-date and needed to be downloaded.<br />In case of using the standard version format which consists of the following parts:&nbsp;<i>major version.minor version.release.build</i>&nbsp;(2.5.0.33 e.g.) then you need to perform some additional calculations.<br />
<br />This function converts each component version to the corresponding tens place:</p>
<table width="400" border="0" cellpadding="0" cellspacing="0" bgcolor="#D3DFEB">
<tr>
<td>
<pre><font size="1" face="Verdana, Arial, Helvetica, sans-serif"><strong>function MakeCompleteNumber(S: string): Integer;
var
   i, Cnt, Len, OldPos: Integer;
begin
   S := Trim(S);
   Result := 0;
   Len := Length(S);
   Cnt := 0;
   OldPos := Len + 1;
   for i := Len downto 1 do
   begin
      if (S[i] = '.') then
      begin
         Result := Result + StrToIntDef('0' + system.Copy(S, i + 1, OldPos - i - 1), 0) * Round(Power(1000, Cnt));
         Inc(Cnt);
         OldPos := i;
      end else
      if (i = 1) then
      begin
         Result := Result + StrToIntDef('0' + system.Copy(S, i, OldPos - i), 0) * Round(Power(1000, Cnt));
      end;
   end;
end; </strong></font></pre>
</td>
</tr>
</table>
<p>After all checks completed and web update is up-to-date then the update file downloading process begins. In order to perform the downloading in the background mode without interfering with main application process we use the&nbsp;<b><a border="0" hspace="0" href="http://www.clevercomponents.com/products/inetsuite/downloader.asp">Clever Downloader</a></b>&nbsp;component from the&nbsp;<b><font color="#000090">Clever Internet Suite</font></b>&nbsp;library. Following code sample shows how easy downloading process can be implemented:<br />
<table width="400" border="0" cellpadding="0" cellspacing="0" bgcolor="#D3DFEB">
<tr>
<td>
<pre><font size="1" face="Verdana, Arial, Helvetica, sans-serif"><strong>...
FDownloader: TclDownloader;
...
FDownloader := TclDownloader.Create(nil);
FDownloader.OnProcessCompleted := DoOnProcessCompleted;
...
procedure TclWebUpdate.StartDownloading();
begin
   FDownloader.URL := UpdateInfo.URL;
   FDownloader.UserName := UserName;
   FDownloader.Password := Password;
   FDownloader.Start(True);
end; </strong></font></pre>
</td>
</tr>
</table>
<p>Since the Start downloader method is called with&nbsp;<b><font color="#000090">Async</font></b>&nbsp;parameter which equal to&nbsp;<b><font color="#000090">True</font></b>&nbsp;the component returns control immediately after calling of this method. So to find out the time when the downloading process is completed we use the&nbsp;<b><font color="#000090">OnProcessCompleted</font></b>&nbsp;downloader event.<br />
<br />To process downloaded update file(s) we implement simple algorithm with using of&nbsp;<b><font color="#000090">ShellExecute</font></b>&nbsp;WinApi function. So if you are about to extract archived update files you can simple call this function as follows:<br />
<table width="400" border="0" cellpadding="0" cellspacing="0" bgcolor="#D3DFEB">
<tr>
<td>
<pre><font size="1" face="Verdana, Arial, Helvetica, sans-serif"><strong>ShellExecute(Application.Handle, 'open', 'webupdate.zip', nil, nil, SW_SHOWNORMAL); </strong></font></pre>
</td>
</tr>
</table>
<p>This function opens your archive with application which assigned as default one for such a file type. If you have WinZip installed and it is assigned as default application for the&nbsp;<i>&#8216;*.zip&#8217;</i>&nbsp;files then the&nbsp;<b><a border="0" hspace="0" href="http://www.clevercomponents.com/articles/article011/webupdate.zip">webupdate.zip</a></b>&nbsp;archive will be opened and unpacked. You can specify your own method of handling and applying updates to suit your own needs.</p>
<p>Full component source code is available at&nbsp;<b><a border="0" hspace="0" href="http://www.clevercomponents.com/articles/article011/component.zip">component.zip</a></b>&nbsp;and allows you to customize the executing process with specifying the run application and its run parameters. This can be useful if you want to run a custom application with its specific command line parameters.</p>
<p>It&#8217;s well known that to replace running application you have to terminate it before. You can make the update process more comfortable and include the code which closes the application just after&nbsp;<b><font color="#000090">ShellExecute</font></b>&nbsp;call:<br />
<table width="400" border="0" cellpadding="0" cellspacing="0" bgcolor="#D3DFEB">
<tr>
<td>
<pre><font size="1" face="Verdana, Arial, Helvetica, sans-serif"><strong>...
var
CanTerminate: Boolean;
...
if NeedTerminate then
begin
   CanTerminate := True;
   DoTerminating(CanTerminate); //

raises an event which user can overwrite in order to
perform some custom actions on application terminating request or cancel closing

   if CanTerminate then
   begin
      Application.Terminate();
   end;
end; </strong></font></pre>
</td>
</tr>
</table>
<p><b>Requirements </b></p>
<p>You must have installed the <b>Internet Explorer</b> version 3.0 or higher on the client computer.</p>
<p>This code is constantly improved and your comments and suggestions are always welcome.</p>
<p>Please write us at <a href="mailto:info@clevercomponents.com">info@clevercomponents.com</a></p>
<p>With best regards,<br />
Sergey S<br />
Clever Components team.<br />
<a href="http://www.clevercomponents.com">www.clevercomponents.com</a></p>
<p>For your convenience we provide following downloads:</p>
<p><a href="http://www.clevercomponents.com/articles/article011/component.zip">component.zip</a> &#8211; an archive with WebUpdate component. Delphi 5, 6, 7 packages are available at this moment.<br />
<a href="http://www.clevercomponents.com/articles/article011/demo1src.zip">demo1src.zip</a> &#8211; an archive with source code for the first sample.<br />
<a href="http://www.clevercomponents.com/articles/article011/demo2src.zip">demo2src.zip</a> &#8211; an archive with source code for the second sample.<br />
<a href="http://www.clevercomponents.com/articles/article011/demo1exe.zip">demo1exe.zip</a> &#8211; an archive with compiled executable file for the first sample.<br />
<a href="http://www.clevercomponents.com/articles/article011/demo2exe.zip">demo2exe.zip</a> &#8211; archive with compiled executable file for the second sample.<br />
<a href="http://www.clevercomponents.com/articles/article011/demo2exe.zip">webupdate.xml</a> &#8211; web resource which provides the update information.<br />
<a href="http://www.clevercomponents.com/articles/article011/demo2exe.zip">Clever Internet Suite downloads </a>- demo version of Clever Internet Suite.</p>
<p>Sergey S. is a member of the <a href="http://www.clevercomponents.com">Clever Components Team</a>.  The history of our site began from an Interbase DataPump and the original idea was to provide Delphi / Borland C++ and Interbase developers with high quality consultations.  Nowadays we have many satisfied customers and can offer some excellent tools and utilities.  We wish to maintain the highest standards in our service and keep our customers happy.  Please feel free to contact us at info@clevercomponents.com</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webpronews.com/adding-automatic-update-support-to-your-application--2003-09/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adding and displaying data easily via ASP and XML/XSL</title>
		<link>http://www.webpronews.com/adding-and-displaying-data-easily-via-asp-and-xmlxsl-2003-08</link>
		<comments>http://www.webpronews.com/adding-and-displaying-data-easily-via-asp-and-xmlxsl-2003-08#comments</comments>
		<pubDate>Wed, 13 Aug 2003 18:17:26 +0000</pubDate>
		<dc:creator>Sonu Kapoor</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[ASP]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[VAR]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[XSL]]></category>

		<guid isPermaLink="false">http://www.webpronews.com/?p=6917</guid>
		<description><![CDATA[Storing and displaying data is a  common and essential task, if you are working with Applications. It doesn't matter whether you are working with desktop Applications or WebApplications.
]]></description>
			<content:encoded><![CDATA[<p>Storing and displaying data is a  common and essential task, if you are working with Applications. It doesn&#8217;t matter whether you are working with desktop Applications or WebApplications.</p>
<p>The saving and displaying process is nearly always required. In this article I will show you how you can easily use an ASP form to add data into a XML file and how you can retrieve this data to display it in a well formed table. We will create an example ASP page, in which the user will be able to enter his Name, Age, Gender and a Postalcode. This data will be stored in a XML file. To display the data we will use XSL. The example ASP page and the resulting table look like this:</p>
<p><img border="0" src="http://images.ientrymail.com/webproasp/form.gif" width="423" height="297"></p>
<p>Its has always been important for me to divide the ASP Page in two parts and I would suggest you to do the same. Some people are mixing the asp and html code, but I would not recommend it to you. But sometimes it isn`t possible to spilt the ASP Page in two parts, in this case you will need to find your own and best suitable way. But anyway, try it! Here an image of the structure how my ASP page always looks like:</p>
<p><img border="0" src="http://images.ientrymail.com/webproasp/2Parts.gif" width="358" height="147"></p>
<p>The first part contains a simple Form, and the second part contains the  ASP Code which will do the saving for us. For a better understanding we will start with the Form.</p>
<p><b><u>Part I the Form:</u></b></p>
<p>You can create any simple form, with any controls you like. In addition to the other controls, we also need a submit and a reset button.</p>
<p>In my example I have created a simple form called <b>frmPerson</b>, which contains three textfields and a drop down field.</p>
<p>This form will use the post method to process the entered data.</p>
<p><u><b>Here is the code of my form:</b></u></font></p>
<pre>&lt;form action=&quot;VerifyPerson.asp&quot; method=&quot;post&quot; name=&quot;frmPerson&quot; id=&quot;frmPerson&quot;&gt;
&lt;INPUT name=Name&gt;
&lt;INPUT name=Age&gt;
&lt;SELECT style=&quot;WIDTH: 154px&quot; name=Gender&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;OPTION value=Male selected&gt;Male&lt;/OPTION&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;OPTION value=Female&gt;Female&lt;/OPTION&gt;
&lt;/SELECT&gt;
&lt;INPUT name=Postalcode&gt;
&lt;INPUT type=submit value=Submit name=submit&gt;&lt;INPUT type=reset value=Reset name=reset&gt;
&lt;/form&gt;
</pre>
<p>It is very important to give each used TAG which will hold the data, a variable name.</p>
<p>For Example: The name textfield &lt;INPUT name=<Font color=red><u><b>Name</b></u></Font>&gt; contains the variable <Font color=red><u><b>Name</b></u></Font>. In order to retrieve the data from the form we will use this and other variables in the next ASP paragraph.</p>
<p>You dont need to write down this code, because the examples covered in this Article are available for download. To get familar with ASP and XML I suggest you download the examples and try to work with it. To give the form a better and professional look I have included a table with some effects, so dont get worried about the whole code. As you can see this was the first <b>easy</b> part of the ASP page and the second part will be even easier.</p>
<p><b><u>Part II the ASP code:</u></b></p>
<p>In this paragraph I will show you in 7 easy steps how you can retrieve the data from the form and how you can save the data to a XML<br />
file.</p>
<p>1. The first step is to check whether the user has pressed the <b>submit</b> button or not! For this we will use the JScript function <b>count</b>.</p>
<pre>
var submit = Request.Form(&quot;submit&quot;).Count;
if( submit &gt; 0 ){
  // The user has pressed the submit button
  // So the code to save the data will take place here.
}
else{
  // We could also place our form in this part of code, which must be then written in JScript.
  //But I would not recommend that !!!
}
</pre>
<p>2. Now we need to retrieve the data from the form. This data will be stored in some variables. To retrieve the data we will use the <b>Request.Form(&quot;variable_name&quot;);</b><br />
function. So let us create 4 variables and retrieve the required data.</p>
<pre>
var name = Request.Form(&quot;Name&quot;);
var age = Request.Form(&quot;Age&quot;);
var gender	= Request.Form(&quot;Gender&quot;);
var pcode	= Request.Form(&quot;PostalCode&quot;);
</pre>
<p>
3.The third step is to check whether the user has entered some data, or not. For this we can just check whether the variables in step 2 are still empty or not.</p>
<pre>
var error = &quot;&quot;;
if ( name == &quot;&quot; )
  error = &quot;Name &quot;;
if ( age == &quot;&quot; )
  error += &quot;Age &quot;;
if ( pcode == &quot;&quot;)
  error += &quot;PostalCode &quot;;
</pre>
<p>4. In step 3 we have saved the result in the var <b>error</b>. Now we need to check, if &quot;error&quot; consists some data or not. If yes, then we have found an error, and we will display it. If not, then we will start with the saving procedure.</p>
<pre>
if(error!=&quot;&quot;){
  //We have found an error, so display this to the user!
  Response.Write(&quot;Please enter the following data:&lt;br&gt;&quot;);
  Response.Write(&lt;b&gt;);
  Response.Write(error);
  Response.Write(&quot;&lt;/b&gt;&quot;);
}
else{
//Everything is fine, so let us start to save the data.
</pre>
<p>5. Now we have done the nessesary checks and can start with saving the data. For that we will load the <b>Person.xml</b> in a xmlDocument. Then we will load the current node list to get the current root node. To get the current root node, we will use the function <b>xmlDoc.getElementsByTagName</b>. After that we need to create the required nodes, this can be achived with the function <b>xmlDoc.createElement(&quot;AnyNodeName&quot;)</b>. At last we only need to save the entered data from the form to the approriate xml variables. So here is the code, how it could look like:</p>
<pre>
.
.
.
else{
  // here we are loading the requried xml file
  var xmlDoc=Server.CreateObject(&quot;MICROSOFT.FreeThreadedXMLDOM&quot;);
  xmlDoc.async=&quot;false&quot;;
  xmlDoc.load(Server.MapPath(&quot;Person.xml&quot;));
  // Get the current root
  var nodeList = xmlDoc.getElementsByTagName(&quot;PersonList&quot;);
  if(nodeList.length &gt; 0){
    var parentNode = nodeList(0) ;
    // Create the required nodes
    var personNode = xmlDoc.createElement(&quot;Person&quot;);
    var nameNode   = xmlDoc.createElement(&quot;Name&quot;);
    var ageNode    = xmlDoc.createElement(&quot;Age&quot;);
    var genderNode = xmlDoc.createElement(&quot;Gender&quot;);
    var pcodeNode  = xmlDoc.createElement(&quot;PostalCode&quot;);
    // Assign the variables, which we have retrieved in step 2 to the xml variables.
    nameNode.text  = name;
    ageNode.text   = age;
    genderNode.text= gender;
    pcodeNode.text = pcode;
	.
	.
	.
</pre>
<p>6. We have done nearly everything to save the data, but there are still two steps left. In this step we will append the created nodes to the parent node. This can be done with the function <b>parentNode.appendChild(&quot;personNode&quot;);</b></p>
<pre>
   .
   .
   .
   parentNode.appendChild(personNode);
   personNode.appendChild(nameNode);
   personNode.appendChild(ageNode);
   personNode.appendChild(genderNode);
   personNode.appendChild(pcodeNode);
   .
   .
   .
</pre>
<p>7. Finally we only need to save the nodes to the xml file. For this you can use the function <b>xmlDoc.save(Server.MapPath(&quot;Person.xml&quot;));</b>.</p>
<pre>
   // 7) Now save the nodes to the file
   xmlDoc.save(Server.MapPath(&quot;Person.xml&quot;));
</pre>
<p><u><b>XSL:</b></u></p>
<p>With this example you can save easily the data of any Person into a XML file.&nbsp;Right now we have only seen how to save the data, but how do we display it ? The answer is again easy. We will use ASP and XSL to display the data. The first thing you need to do is to load the XML file, this can be achieved with a XML Parser. The XML parser from Microsoft is available directly with Internet Explorer 5.0. After you have loaded the XML file in the document Object, you can retrieve the XML data with the help of a DOM Object. In the same way you must load the XSL file.&nbsp;</p>
<pre>
   // This part is used to display the data&nbsp;
   var objXMLDoc = Server.CreateObject(&quot;MICROSOFT.FreeThreadedXMLDOM&quot;);
   objXMLDoc.async = false;
   objXMLDoc.load(Server.MapPath(&quot;person.xml&quot;));
   var xsl=Server.CreateObject(&quot;MICROSOFT.FreeThreadedXMLDOM&quot;);
   xsl.async = false;
   xsl.load(Server.MapPath(&quot;person.xsl&quot;));
</pre>
<p>Now you have loaded both files, each one DOM Object. Now you only need to create a query which will select the nodes for us. Of course we could select some specific nodes, but for our needs we will just select the root node, so all other nodes will be selected automatically.</p>
<pre>
   var xmlQuery=&quot;//Person&quot;;
   var docHeadlines=objXMLDoc.documentElement.selectNodes(xmlQuery);
</pre>
<p>After that you only need to iterate through the nodes to display each stored item.</p>
<pre>
   var numNodes;
   numNodes=docHeadlines.length;
   var nn;
   for(var i=0;i&lt;numNodes;i++){
     nn = docHeadlines.nextNode();
     Response.Write(nn.transformNode(xsl));
   }
</pre>
<p><u><b>Conclusion:</b></u></p>
<p>That&#8217;s it ! Now you have created a fully functional system which can save, read and display data from a form. You have learned the advantages of ASP,XML and XSL. To practice a little bit more, I suggest you to modify the ASP page, to create your own Address book. Once you have mastered and created your own ASP page you will understand much more.</p>
<p><a href="http://images.ientrymail.com/webproasp/example.zip">Download examples</a></p>
<p>First published at <a href="http://www.sitepoint.com">SitePoint.com</a></p>
<p>Codefinger was founded 2000 by Sonu Kapoor. Sonu has studied E-Commerce in India and currently lives in Germany. After graduation he worked for several companies in Germany. He currently works as a Network Consultant and Software Developer. He has written many applications in various programming languages like VC++, ASP, ASP.NET, XML or XSL. Besides his passion for developing applications, Sonu writes articles for several major websites like <a href="http://www.developer.com">Developer.com</a>. He also works as a freelancer for <a href="http://www.codeguru.com/">CodeGuru</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.webpronews.com/adding-and-displaying-data-easily-via-asp-and-xmlxsl-2003-08/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Optimizing JavaScript for Execution Speed</title>
		<link>http://www.webpronews.com/optimizing-javascript-for-execution-speed-2003-05</link>
		<comments>http://www.webpronews.com/optimizing-javascript-for-execution-speed-2003-05#comments</comments>
		<pubDate>Wed, 14 May 2003 17:25:12 +0000</pubDate>
		<dc:creator>Andy King</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[3]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Local]]></category>
		<category><![CDATA[Offline]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Time]]></category>
		<category><![CDATA[VAR]]></category>

		<guid isPermaLink="false">http://www.webpronews.com/?p=4199</guid>
		<description><![CDATA[JavaScript can benefit from many of the same speed-optimization techniques    that are used in other languages, like C<sup><a href="#1" target="new">1</a>,<a href="#2" target="new">2</a></sup>    and Java. Algorithms and data structures, caching frequently used values, loop    unrolling and hoisting, removing tail recursion, and strength-reduction techniques    all have a place in your JavaScript optimization toolbox. However, how you interact    with the Document Object Model (DOM) in large part determines how efficiently your code executes.
]]></description>
			<content:encoded><![CDATA[<p>JavaScript can benefit from many of the same speed-optimization techniques    that are used in other languages, like C<sup><a href="#1" target="new">1</a>,<a href="#2" target="new">2</a></sup>    and Java. Algorithms and data structures, caching frequently used values, loop    unrolling and hoisting, removing tail recursion, and strength-reduction techniques    all have a place in your JavaScript optimization toolbox. However, how you interact    with the Document Object Model (DOM) in large part determines how efficiently your code executes.</p>
<p>Unlike other programming languages, JavaScript manipulates web pages through a relatively sluggish API, the DOM. Interacting with the DOM is almost always more expensive than straight computations. After choosing the right algorithm and data structure and refactoring, your next consideration should be minimizing DOM interaction and I/O operations. </p>
<p> With most programming languages, you can trade space for time complexity and    vice versa.<sup><a href="#3" target="new">3</a></sup> But on the    web, JavaScripts must be downloaded. Unlike desktop applications where you can    trade another kilobyte or two for speed, with JavaScript you have to balance    execution speed versus file size. </p>
<p>  <b>How Fast Is JavaScript?</b> </p>
<p> Unlike C, with its optimizing compilers that increase execution speed and      decrease file size, JavaScript is an interpreted language that usually is      run over a network connection (unless you count Netscape&#039;s Rhino, which      can compile and optimize JavaScript into Java byte code for embedded applications<sup><a href="#4" target="new">4</a></sup>).      This makes JavaScript relatively slow compared to compiled languages.<sup><a href="#5" target="new">5</a></sup>      However, most scripts are usually so small and fast that users won&#039;t      notice any speed degradation. Longer, more complex scripts are where this      chapter can help jumpstart your JavaScript. </div>
<h3>Design Levels</h3>
<p> A hierarchy of optimization levels exists for JavaScript, what Bentley and    others call <i>design levels</i>.<sup><a href="#6" target="new">6</a></sup>    First comes the global changes like using the right algorithms and data structures    that can speed up your code by orders of magnitude. Next comes refactoring that    restructures code in a disciplined way into a simpler, more efficient form<sup><a href="#7" target="new">7</a></sup>).    Then comes minimizing DOM interaction and I/O or HTTP requests. Finally, if    performance is still a problem, use local optimizations like caching frequently    used values to save on recalculation costs. Here is a summary of the optimization    process:
<ol>
<li>Choose the right algorithm and data structure.</li>
<p> 
<li>Refactor to simplify code.</li>
<p> 
<li>Minimize DOM and I/O interaction.</li>
<p> 
<li>Use local optimizations last.</li>
</ol>
<p>  When optimizing your code, start at the highest level and work your way down until the code executes fast enough. For maximum speed, work at multiple levels.<br />
<h3>Measure Your Changes</h3>
<p>  Measurement is a key part of the optimization process. Use the simplest algorithms and data structures you can, and measure your code&#039;s performance to see whether you need to make any changes. Use timing commands or profilers to locate any bottlenecks. Optimize these hot spots one at a time, and measure any improvement. You can use the <tt>date</tt> object to time individual snippets:</p>
<pre>&lt;script type=&quot;text/javascript&quot;&gt;
function DoBench(x){
  var startTime,endTime,gORl=&#039;local&#039;;
  if(x==1){
    startTime=new Date().getTime();
    Bench1();
    endTime=new Date().getTime();
  }else{
    gORl=&#039;global&#039;;
    startTime=new Date().getTime();
    Bench2();
    endTime=new Date().getTime();
  }
alert(&#039;Elapsed time using &#039;+gORl+&#039; variable: &#039;+((endTime-startTime)/1000)+&#039; seconds.&#039;);
}
...
&lt;/script&gt;</pre>
<p>This is useful when comparing one technique to another. But for larger projects, only a profiler will do. Mozilla.org includes the Venkman profiler in the Mozilla browser distribution to help optimize your JavaScript. </p>
<p> <b>The Venkman JavaScript Profiler</b> </p>
<p> For more information on the Venkman profiler, see the following web sites:
<ul>
<li> <a href="http://mozilla.org/performance/jsprofiler.html" target="new">http://mozilla.org/performance/jsprofiler.html</a></li>
<li><a href="http://www.hacksrus.com/~ginda/venkman/profiles/" target="new">http://www.hacksrus.com/~ginda/venkman/profiles/</a></li>
</ul>
<p>  <b>The Pareto Principle</b> </p>
<p> Economist Vilfredo Pareto found in 1897 that about 80 percent of Italy&#039;s      wealth was owned by about 20 percent of the population.<sup><a href="#8" target="new">8</a></sup>      This has become the 80/20 rule or the Pareto principle, which is often applied      to a variety of disciplines. Although some say it should be adjusted to a      90/10 rule, this rule of thumb applies to everything from employee productivity      and quality control to programming. </p>
<p> Barry Boehm found that 20 percent of a program consumes 80 percent of the      execution time.<sup><a href="#9" target="new">9</a></sup> He also      found that 20 percent of software modules are responsible for 80 percent of      the errors.<sup><a href="#10" target="new">10</a></sup> Donald Knuth      found that more than 50 percent of a program&#039;s run time is usually due      to less than 4 percent of the code.<sup><a href="#11" target="new">11</a></sup>      Clearly, a small portion of code accounts for the majority of program execution      time. Concentrate your efforts on these hot areas.<br />
<h3>Algorithms and Data Structures</h3>
<p>  As we learn in computer science classes, global optimizations (such as algorithm and data structure choices) determine in large part the overall performance of our programs. For larger values of &quot;n,&quot; or the number of input elements, the complexity of running time can dominate any local optimization concerns. This complexity is expressed in O-notation, where complexity or &quot;order&quot; is expressed as a function of n. Table 10.1 shows some examples.<br />
<h4>Table 10.1 Run-Time Complexity of Classic Algorithms<sup><a href="#12" target="new">12</a>,    <a href="#13" target="new">13</a></sup></h4>
<table border="2" cellspacing="2" cellpadding="2" style="font-family: Verdana, Arial, Helvetica, sans-serif;font-size: 9px;font-style: normal;font-weight: normal;font-variant: normal; color: #000000;">
<col width="49" />
<col width="63" />
<col width="88" />
<tr valign="TOP">
<td colspan="1" rowspan="1" valign="TOP" width="49">
<p><b>Notation</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="63">
<p><b>Name</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="88">
<p><b>Example</b></p>
</td>
</tr>
<tr valign="TOP">
<td colspan="1" rowspan="1" valign="TOP" width="49">
<p>O(1)</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="63">
<p>constant</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="88">
<p>array index, simple statements</p>
</td>
</tr>
<tr valign="TOP">
<td colspan="1" rowspan="1" valign="TOP" width="49">
<p>O(log<i>n</i>)</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="63">
<p>logarithmic</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="88">
<p>binary search</p>
</td>
</tr>
<tr valign="TOP">
<td colspan="1" rowspan="1" valign="TOP" width="49">
<p>O(<i>n</i>)</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="63">
<p>linear</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="88">
<p>string comparison, sequential search</p>
</td>
</tr>
<tr valign="TOP">
<td colspan="1" rowspan="1" valign="TOP" width="49">
<p>O(<i>n</i>log<i>n</i>)</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="63">
<p><i>n</i>log<i>n</i></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="88">
<p>quicksort and heapsort</p>
</td>
</tr>
<tr valign="TOP">
<td colspan="1" rowspan="1" valign="TOP" width="49">
<p>O(<i>n</i><sup>2</sup>)</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="63">
<p>quadratic</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="88">
<p>simple selection and insertion sorting methods (two loops)</p>
</td>
</tr>
<tr valign="TOP">
<td colspan="1" rowspan="1" valign="TOP" width="49">
<p>O(<i>n</i><sup>3</sup>)</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="63">
<p>cubic</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="88">
<p>matrix multiplication of nxn matrices</p>
</td>
</tr>
<tr valign="TOP">
<td colspan="1" rowspan="1" valign="TOP" width="49">
<p>O(2<sup><i>n</i></sup>)</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="63">
<p>exponential</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="88">
<p>set partitioning (traveling salesman)</p>
</td>
</tr>
</table>
<p> 
<p>Array access or simple statements are constant-time operations, or O(1). Well-crafted quicksorts run in <i>n</i>log<i>n</i> time or O(<i>n</i>log<i>n)</i>. Two nested <tt>for</tt> loops take on the order of nxn or O(<i>n</i><sup>2</sup>) time. For low values of n, choose simple data structures and algorithms. As your data grows, use lower-order algorithms and data structures that will scale for larger inputs.</p>
<p>Use built-in functions whenever possible (like the <tt>Math</tt> object), because these are generally faster than custom replacements. For critical inner loops, measure your changes because performance can vary among different browsers.</p>
<h3>Refactor to Simplify Code</h3>
<p><i>Refactoring</i> is the art of reworking your code to a more simplified or efficient form in a disciplined way. Refactoring is an iterative process: </p>
<ol>
<li>
<p>Write correct, well-commented code that works.</p>
</li>
<li>
<p>Get it debugged.</p>
</li>
<li>
<p>Streamline and refine by refactoring the code to replace complex sections with shorter, more efficient code.</p>
</li>
<li>
<p>Mix well, and repeat.</p>
</li>
</ol>
<p>Refactoring clarifies, refines, and in many cases speeds up your code. Here&#039;s a simple example that replaces an assignment with an initialization. So instead of this:</p>
<pre>function foo() {
  var i;
  // ....
  i = 5;
}</pre>
<p>Do this:</p>
<pre>function foo() {
  var i = 5;
  // ....
}</pre>
<div class="note">
<p class="normaltitle"><b>For More Information</b></p>
<p>Refactoring is a discipline unto itself. In fact, entire books have been written on the subject. See Martin Fowler&#039;s book, <i>Refactoring: Improving the Design of Existing Code</i> (Addison-Wesley, 1999). See also his catalog of refactorings at <a href="http://www.refactoring.com/" target="new">http://www.refactoring.com/</a>. </p>
<p>
<h3>Minimize DOM Interaction and I/O</h3>
<p>Interacting with the DOM is significantly more complicated than arithmetic computations, which makes it slower. When the JavaScript interpreter encounters a scoped object, the engine resolves the reference by looking up the first object in the chain and working its way through the next object until it finds the referenced property. To maximize object resolution speed, minimize the scope chain of objects. Each node reference within an element&#039;s scope chain means more lookups for the browser. Keep in mind that there are exceptions, like the window object, which is faster to fully reference. So instead of this:</p>
<pre>var link = location.href;</pre>
<p>Do this:</p>
<pre>var link = window.location.href;</pre>
<h4>Minimize Object and Property Lookups</h4>
<p>Object-oriented techniques encourage encapsulation by tacking sub-nodes and methods onto objects. However, object-property lookups are slow, especially if there is an evaluation. So instead of this:</p>
<pre>for(var i = 0; i &lt; 1000; i++)
  a.b.c.d(i);</pre>
<p>Do this:</p>
<pre>var e = a.b.c.d;
for(var i = 0; i &lt; 1000; i++)
  e(i);</pre>
<p>Reduce the number of dots (<tt>object.property</tt>) and brackets (<tt>object[</tt>&quot;<tt>property</tt>&quot;<tt>]</tt>) in your program by caching frequently used objects and properties. Nested properties are the worst offenders (<tt>object.property.property.property</tt>). </p>
<p>Here is an example of minimizing lookups in a loop. Instead of this:</p>
<pre>for (i=0; i&lt;someArrayOrObject.length; i++)</pre>
<p>Do this:</p>
<pre>for (i=0, var n=someArrayOrObject.length; i&lt;n; i++)</pre>
<p>Also, accessing a named property or object requires a lookup. When possible, refer to the object or property directly by using an index into an object array. So instead of this:</p>
<pre>var form = document.f2; // refer to form by name</pre>
<p>Do this:</p>
<pre>var form = document.forms[1]; // refer to form by position</pre>
<h4>Shorten Scope Chains</h4>
<p>Every time a function executes, JavaScript creates an <i>execution context</i> that defines its own little world for local variables. Each execution context has an associated <i>scope chain</i> object that defines the object&#039;s place in the document&#039;s hierarchy. The scope chain lists the objects within the global namespace that are searched when evaluating an object or property. Each time a JavaScript program begins executing, certain built-in objects are created.</p>
<p>The <i>global object</i> lists the properties (global variables) and predefined values and functions (<tt>Math</tt>, <tt>parseInt()</tt>, etc.) that are available to all JavaScript programs. </p>
<p>Each time a function executes, a temporary <i>call object</i> is created. The function&#039;s arguments and variables are stored as properties of its call object. Local variables are properties of the call object. </p>
<p>Within each call object is the <i>calling scope</i>. Each set of brackets recursively defines a new child of that scope. When JavaScript looks up a variable (called <i>variable name resolution</i>), the JavaScript interpreter looks first in the local scope, then in its parent, then in the parent of that scope, and so on until it hits the global scope. In other words, JavaScript looks at the first item in the scope chain, and if it doesn&#039;t find the variable, it bubbles up the chain until it hits the global object. </p>
<p>That&#039;s why global scopes are slow. They are worst-case scenarios for object lookups.</p>
<p>During execution, only <tt>with</tt> statements and <tt>catch</tt> clauses affect the scope chain. </p>
<div class="note">
<p class="normaltitle"><b>Avoid <i>with</i> Statements</b></p>
<p>The <tt>with</tt> statement extends the scope chain temporarily with a computed object, executes a statement with this longer scope chain, and then restores the original scope chain. This can save you typing time, but cost you execution time. Each additional child node you refer to means more work for the browser in scanning the global namespace of your document. So instead of this:</p>
</p></div>
<pre>with (document.formname) {
field1.value = &quot;one&quot;;
field2.value = &quot;two&quot;;...
}</pre>
<p>Do this:</p>
<pre>var form = document.formname;
form.field1.value = &quot;one&quot;;
form.field2.value = &quot;two;</pre>
<p>Cache the object or property reference instead of using <tt>with</tt>, and use this variable for repeated references. <tt>with</tt> also has been deprecated, so it is best avoided.</p>
<h4>Add Complex Subtrees Offline</h4>
<p>When you are adding complex content to your page (like a table), you will find it is faster to build your DOM node and all its sub-nodes offline before adding it to the document. So instead of this (see Listing 10.1):</p>
<h5><b>Listing 10.1</b> Adding Complex Subtrees Online</h5>
<pre>var tableEl, rowEl, cellEl;
var numRows = 10;
var numCells = 5;

tableEl = document.createElement(&quot;TABLE&quot;);
tableEl = document.body.appendChild(tableEl);
for (i = 0; i &lt; numRows; i++) {
  rowEl = document.createElement(&quot;TR&quot;);
  for (j = 0; j &lt; numCells;j++) {
    cellEl = document.createElement(&quot;TD&quot;);
    cellEl.appendChild(document.createTextNode(&quot;[row &quot;+i+&quot; cell &quot;+j+ &quot;]&quot;));
    rowEl.appendChild(cellEl);
  }
  tableEl.appendChild(rowEl);
}</pre>
<p>Do this (see Listing 10.2):</p>
<h5><b>Listing 10.2</b> Adding Complex Subtrees Offline</h5>
<pre>var tableEl, rowEl, cellEl;
var numRows = 10;
var numCells = 5;

tableEl = document.createElement(&quot;TABLE&quot;);
for (i = 0; i &lt; numRows; i++) {
  rowEl = document.createElement(&quot;TR&quot;);
  for (j = 0; j &lt; numCells;j++) {
    cellEl = document.createElement(&quot;TD&quot;);
    cellEl.appendChild(document.createTextNode(&quot;[row &quot; +i+ &quot; cell &quot;+j+&quot;]&quot;));
    rowEl.appendChild(cellEl);
  }
  tableEl.appendChild(rowEl);
 }
document.body.appendChild(tableEl);</pre>
<p>Listing 10.1 adds the table object to the page immediately after it is created and adds the rows afterward. This runs much slower because the browser must update the page display every time a new row is added. Listing 10.2 runs faster because it adds the resulting table object last, via <tt>document.body.appendChild()</tt>.</p>
<h4>Edit Subtrees Offline</h4>
<p>In a similar fashion, when you are manipulating subtrees of a document, first remove the subtree, modify it, and then re-add it. DOM manipulation causes large parts of the tree to recalculate the display, slowing things down. Also, <tt>createElement()</tt> is slow compared to <tt>cloneNode()</tt>. When possible, create a template subtree, and then clone it to create others, only changing what is necessary. Let&#039;s combine these two optimizations into one example. So instead of this (see Listing 10.3):</p>
<h5><b>Listing 10.3</b> Editing Subtrees Online</h5>
<pre>var ul = document.getElementById(&quot;myUL&quot;);
for (var i = 0; i &lt; 200; i++) {
  ul.appendChild(document.createElement(&quot;LI&quot;));
}</pre>
<p>Do this (see Listing 10.4):</p>
<h5><b>Listing 10.4</b> Editing Subtrees Offline</h5>
<pre>var ul = document.getElementById(&quot;myUL&quot;);
var li = document.createElement(&quot;LI&quot;);
var parent = ul.parentNode;

parent.removeChild(ul);

for (var i = 0; i &lt; 200; i++) {
  ul.appendChild(li.cloneNode(true));
}

parent.appendChild(ul);</pre>
<p>By editing your subtrees offline, you&#039;ll realize significant performance gains. The more complex the source document, the better the gain. Substituting <tt>cloneNode</tt> instead of <tt>createElement</tt> adds an extra boost.</p>
<h4>Concatenate Long Strings</h4>
<p>By the same token, avoid multiple <tt>document.writes</tt> in favor of one <tt>document.write</tt> of a concatenated string. So instead of this:</p>
<pre>document.write(&#039; string 1&#039;);
document.write(&#039; string 2&#039;);
document.write(&#039; string 3&#039;);
document.write(&#039; string 4&#039;);</pre>
<p>Do this:</p>
<pre>var txt = &#039; string 1&#039;+
&#039; string 2&#039;+
&#039; string 3&#039;+
&#039; string 4&#039;;
document.write(txt);</pre>
<h4>Access NodeLists Directly</h4>
<p>NodeLists are lists of elements from object properties like <tt>.childNodes</tt> and methods like <tt>getElementsByTagName()</tt>. Because these objects are live (updated immediately when the underlying document changes), they are memory intensive and can take up many CPU cycles. If you need a NodeList for only a moment, it is faster to index directly into the list. Browsers are optimized to access node lists this way. So instead of this:</p>
<pre>nl = document.getElementsByTagName(&quot;P&quot;);
for (var i = 0; i &lt; nl.length; i++) {
  p = nl[i];
}</pre>
<p>Do this:</p>
<pre>for (var i = 0; (p = document.getElementsByTagName(&quot;P&quot;)[i]); i++)</pre>
<p>In most cases, this is faster than caching the NodeList. In the second example, the browser doesn&#039;t need to create the node list object. It needs only to find the element at index <tt>i</tt> at that exact moment.</p>
<h4>Use Object Literals</h4>
<p>Object literals work like array literals by assigning entire complex data types to objects with just one command. So instead of this:</p>
<pre>car = new Object();
car.make = &quot;Honda&quot;;
car.model = &quot;Civic&quot;;
car.transmission = &quot;manual&quot;;
car.miles = 1000000;
car.condition = &quot;needs work&quot;;</pre>
<p>Do this:</p>
<pre>car = {
  make: &quot;Honda&quot;,
  model: &quot;Civic&quot;,
  transmission: &quot;manual&quot;,
  miles: 1000000,
  condition: &quot;needs work&quot;
}</pre>
<p>This saves space and unnecessary DOM references.</p>
<h3>Local Optimizations</h3>
<p>Okay, you&#039;ve switched to a better algorithm and revamped your data structure. You&#039;ve refactored your code and minimized DOM interaction, but speed is still an issue. It is time to tune your code by tweaking loops and expressions to speed up hot spots. In his classic book, <i>Writing Efficient Programs</i> (Prentice Hall, 1982), Jon Bentley revealed 27 optimization guidelines for writing efficient programs. These code-tuning rules are actually low-level refactorings that fall into five categories: space for time and vice versa, loops, logic, expressions, and procedures. In this section, I touch on some highlights.</p>
<h4>Trade Space for Time</h4>
<p>Many of the optimization techniques you can read about in Bentley&#039;s book and elsewhere trade space (more code) for time (more speed). You can add more code to your scripts to achieve higher speed by &quot;defactoring&quot; hot spots to run faster. By augmenting objects to store additional data or making it more easily accessible, you can reduce the time required for common operations.</p>
<p>In JavaScript, however, any additional speed should be balanced against any additional program size. Optimize hot spots, not your entire program. You can compensate for this tradeoff by packing and compressing your scripts. </p>
<h5>Augment Data Structures</h5>
<p>Douglas Bagnall employed data structure augmentation in the miniscule 5K chess game that he created for the 2002 5K contest (<a href="http://www.the5k.org/" target="new">http://www.the5k.org/</a>). Bagnall used augmented data structures and binary arithmetic to make his game fast and small. The board consists of a 120-element array, containing numbers representing either pieces, empty squares, or &quot;off-the-board&quot; squares. The off-the-board squares speed up the testing of the sides&#8212;preventing bishops, etc., from wrapping from one edge to the other while they&#039;re moving, without expensive positional tests.</p>
<p>Each element in his 120-item linear array contains a single number that represents the status of each square. So instead of this:</p>
<pre>board=[16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,2,3,4,5,6,2,3,4,5,16,....]</pre>
<p>He did this:</p>
<pre>bstring=&quot;ggggggggggggggggggggg23456432gg11111111gg0000 ... g&quot;;
for (z=0;z&lt;120;z++){
   board[z]=parseInt(bstring.charAt(z),35);
}</pre>
<p>This base-35 value represents the squares on the board (<tt>parseInt</tt> using a radix of 35). As alpha &quot;g&quot; corresponds to 16 (the 5th bit; that is, bit 4), Bagnall says he actually could have used base-17 instead of 35. Perhaps this will leave room for future enhancements. </p>
<p>Each position on the board is encoded like this:</p>
<pre>bit 4 (16):	0 = on board, 1 = off board.
bit 3  (8):	0 = white, 1 = black.
bits 0-2(7):	0 = empty, non-zero = the piece type:

1 - pawn
2 - rook
3 - knight
4 - bishop
5 - queen
6 - king</pre>
<p>So to test the color of a piece, <tt>movingPiece</tt>, you&#039;d use the following:</p>
<pre>ourCol=movingPiece &amp; 8;	// what color is it? 8=black, 0=white
    movingPiece &amp;= 7;	// now we have the color info, dump it.
   if(movingPiece &gt; 1){	// If it is not a pawn.</pre>
<p>Bagnall also checks that the piece exists (because the preceding code will return <tt>white</tt> for an empty square), so he checks that <tt>movingPiece</tt> is non-empty. To see his code and the game in action, visit the following sites:</p>
<ul>
<li>
<p><a href="http://halo.gen.nz/chess/" target="new">http://halo.gen.nz/chess/</a></p>
</li>
<li>
<p><a href="http://halo.gen.nz/chess/main-branch/" target="new">http://halo.gen.nz/chess/main-branch/</a> (the actual code)</p>
</li>
</ul>
<h5>Cache Frequently Used Values</h5>
<p>One of the most effective techniques you can use to speed up your JavaScripts is to cache frequently used values. When you cache frequently used expressions and objects, you do not need to recompute them. So instead of this (see Listing 10.5):</p>
<h5>Listing 10.5</b> A Loop That Needs Caching and Fewer Evaluations</h5>
<pre>var d=35;
for (var i=0; i&lt;1000; i++) {
  y += Math.sin(d)*10;
}</pre>
<p>Do this (see Listing 10.6):</p>
<h5>Listing 10.6</b> Caching Complex Calculations Out of a Loop</h5>
<pre>var d=35;
var math_sind = Math.sin(d)*10;

for (var i=0; i&lt;1000; i++) {
  y += math_sind;
}</pre>
<p>Because <tt>Math</tt> is a global object, declaring the <tt>math_sind</tt> variable also avoids resolving to a global object for each iteration. You can combine this technique with minimizing DOM interaction by caching frequently used object or property references. Simplify the calculations within your loops and their conditionals.</p>
<h5>Store Precomputed Results</h5>
<p>For expensive functions (like <tt>sin()</tt>), you can precompute values and store the results. You can use a lookup table (O(1)) to handle any subsequent function calls instead of recomputing the function (which is expensive). So instead of this:</p>
<pre>function foo(i) {
  if (i &lt; 10) {return <i>i * i - i;</i>}
}</pre>
<p>Do this:</p>
<pre>values = [0*0-0, 1*1-1, 2*2-2, ..., 9*9-9];

function foo(i) {
  if (i &lt; 10) {return values[i];}
}</pre>
<p>This technique is often used with trigonometric functions for animation purposes. A sine wave makes an excellent approximation of the acceleration and deceleration of a body in motion:</p>
<pre>for (var i=1; i&lt;=360; i++) {
  sin[i] = Math.sin(i);
}</pre>
<p>In JavaScript, this technique is less effective than it is in a compiled language like C. Unchanging values are computed at compile time in C, while in an interpreted language like JavaScript, they are computed at runtime.</p>
<h5>Use Local versus Global Variables</h5>
<p>Reducing the scope of your variables is not only good programming practice, it is faster. So instead of this (see Listing 10.7):</p>
<h5>Listing 10.7</b> Loop with Global Variable</h5>
<pre>function MyInnerLoop(){
  for(i=0;i&lt;1000;i++);
}</pre>
<p>Do this (see Listing 10.8):</p>
<h5>Listing 10.8</b> Loop with Local Variable</h5>
<pre>function MyInnerLoop(){
  for(var i=0;i&lt;1000;i++);
}</pre>
<p>Local variables are 60 percent to 26 times faster than global variables for tight inner loops. This is due in part to the fact that global variables require more time to search up the function&#039;s scope chain. Local variables are properties of the function&#039;s call object and are searched first. Netscape 6 in particular is slow in using global variables. Mozilla 1.1 has improved speed, but this technique is relevant to all browsers. See Scott Porter&#039;s local versus global test at <a href="http://javascript-games.org/articles/local_global_bench.html" target="new">http://javascript-games.org/articles/local_global_bench.html</a>.</p>
<h4>Trade Time for Space</h4>
<p>Conversely, you can trade time for space complexity by densely packing your data and code into a more compact form. By recomputing information, you can decrease the space requirements of a program at the cost of increased execution time.</p>
<h5>Packing</h5>
<p>Packing decreases storage and transmission costs by increasing the time to compact and retrieve the data. Sparse arrays and overlaying data into the same space at different times are two examples of packing. Removing spaces and comments are two more examples of packing. Substituting shorter strings for longer ones can also help pack data into a more compact form.</p>
<h5>Interpreters</h5>
<p>Interpreters reduce program space requirements by replacing common sequences with more compact representations.</p>
<p>Some 5K competitors (<a href="http://www.the5k.org/" target="new">http://www.the5k.org/</a>) combine these two techniques to create self-extracting archives of their JavaScript pages, trading startup speed for smaller file sizes (<a href="http://www.dithered.com/experiments/compression/" target="new">http://www.dithered.com/experiments/compression/</a>). See Chapter 9, &quot;Optimizing JavaScript for Download Speed,&quot; for more details.</p>
<h4>Optimize Loops</h4>
<p>Most hot spots are inner loops, which are commonly used for searching and sorting. There are a number of ways to optimize the speed of loops: removing or simplifying unnecessary calculations, simplifying test conditions, loop flipping and unrolling, and loop fusion. The idea is to reduce the cost of loop overhead and to include only repeated calculations within the loop.</p>
<h5>Combine Tests to Avoid Compound Conditions</h5>
<p>&quot;An efficient inner loop should contain as few tests as possible, and    preferably only one.&quot;<sup><a href="#14" target="new">14</a></sup>    Try to simulate exit conditions of the loop by other means. One technique is    to embed sentinels at the boundary of data structures to reduce the cost of    testing searches. Sentinels are commonly used for arrays, linked lists, and    binary search trees. In JavaScript, however, arrays have the length property    built-in, at least after version 1.2, so array boundary sentinels are more useful    for arrays in languages like C.</p>
<p>One example from Scott Porter of JavaScript-Games.org is splitting an array of numeric values into separate arrays for extracting the data for a background collision map in a game. The following example of using sentinels also demonstrates the efficiency of the <tt>switch</tt> statement:</p>
<pre>var serialData=new;
Array(-1,10,23,53,223,-1,32,98,45,32,32,25,-1,438,54,26,84,-1,487,43,11);
var splitData=new Array();
function init(){
  var ix=-1,n=0,s,l=serialData.length;
  for(;n&lt;l;n++){
    s=serialData[n];
    switch(s){ // switch blocks are much more efficient
      case -1 : // than if... else if... else if...
        splitData[++ix]=new Array();
        break;
      default :
        splitData[ix].push(s);
    }
  }
  alert(splitData.length);
}</pre>
<p>Scott Porter explains the preceding code using some assembly language and the advantage of using the <tt>switch</tt> statement:</p>
<dd>
<p>&quot;Here, -1 is the sentinel value used to split the data blocks. Switch blocks should always be used where possible, as it&#039;s so much faster than an if&#8212;else series. This is because with the if else statements, a test must be made for each &quot;if&quot; statement, whereas switch blocks generate vector jump tables at compile time so NO test is actually required in the underlying code! It&#039;s easier to show with a bit of assembly language code. So an if/else statement:</p>
</dd>
<dd>
<pre>  if(n==12)
    someBlock();
  else if(n==26)
    someOtherBlock();</pre>
</dd>
<dd>becomes something like this in assembly:</dd>
<dd>
<pre>  cmp eax,12;
  jz  someBlock;
  cmp eax,26;
  jz  someOtherBlock;</pre>
</dd>
<dd>Whereas a switch statement:</dd>
<dd>
<pre>switch(a){
  case 12 :
    someBlock();
    break;
  case 26 :
    someOtherBlock();
    break;
}</pre>
</dd>
<dd>becomes something like this in assembly:</dd>
<dd>
<pre>  jmp [VECTOR_LIST+eax];</pre>
</dd>
<dd>where <tt>VECTOR_LIST</tt> would be a list of pointers to the address of the start of the <tt>someBlock</tt> and <tt>someOtherBlock</tt> functions. At least this would be the method if the switch were based on a numeric value. For string values I&#039;d imagine <tt>eax</tt> would be replaced by a pointer to the location of a string for the comparison.</dd>
<dd>As you can see, the longer the <tt>if...else if...</tt> block became, the more efficient the switch block would become in comparison.&quot;<sup><a href="#15" target="new">15</a></sup></dd>
<p>Next, let&#039;s look at some ways to minimize loop overhead. Using the right techniques, you can speed up a <tt>for</tt> loop by two or even three times.</p>
<h5>Hoist Loop-Invariant Code</h5>
<p>Move loop-invariant code out of loops (otherwise called <i>coding motion out of loops</i>) to speed their execution. Rather than recomputing the same value in each iteration, move it outside the loop and compute it only once. So instead of this:</p>
<pre>for (i=0;i&lt;iter;i++) {
  d=Math.sqrt(y);
  j+=i*d;
}</pre>
<p>Do this:</p>
<pre>d=Math.sqrt(y);
for (i=0;i&lt;iter;i++) {
  j+=i*d;
}</pre>
<h5>Reverse Loops</h5>
<p>Reversing loop conditions so that they count down instead of up can double the speed of loops. Counting down to zero with the decrement operator (<tt>i--</tt>) is faster than counting up to a number of iterations with the increment operator (<tt>i++</tt>). So instead of this (see Listing 10.9):</p>
<h5>Listing 10.9</b> A Normal <tt>for</tt> Loop Counts Up</h5>
<pre>function loopNormal() {
  for (var i=0;i&lt;iter;i++) {
    // do something here
  }
}</pre>
<p>Do this (see Listing 10.10):</p>
<h5>Listing 10.10</b> A Reversed <tt>for</tt> Loop Counts Down</h5>
<pre>function loopReverse() {
  for (var i=iter;i&gt;0;i--) {
    // do something here
  }
}</pre>
<h5>Flip Loops</h5>
<p>Loop flipping moves the loop conditional from the top to the bottom of the loop. The theory is that the <tt>do while</tt> construct is faster than a <tt>for</tt> loop. So a normal loop (see Listing 10.9) would look like this flipped (see Listing 10.11):</p>
<h5>Listing 10.11</b> A Flipped Loop Using <tt>do while</tt></h5>
<pre>function loopDoWhile() {
var i=0;
do
{
  i++;
}
while (i&lt;iter);
}</pre>
<p>In JavaScript, however, this technique gives poor results. IE 5 Mac gives inconsistent results, while IE and Netscape for Windows are 3.7 to 4 times slower. The problem is the complexity of the conditional and the increment operator. Remember that we&#039;re measuring loop overhead here, so small changes in structure and conditional strength can make a big difference. Instead, combine the flip with a reverse count (see Listing 10.12):</p>
<h5>Listing 10.12</b> Flipped Loop with Reversed Count</h5>
<pre>function loopDoWhileReverse() {
var i=iter;
do
{
  i--;
}
while (i&gt;0);
}</pre>
<p>This technique is more than twice as fast as a normal loop and slightly faster than a flipped loop in IE5 Mac. Even better, simplify the conditional even more by using the decrement as a conditional like this (see Listing 10.13):</p>
<h5>Listing 10.13</b> Flipped Loop with Improved Reverse Count</h5>
<pre>function loopDoWhileReverse2() {
var i=iter-1;
do
{
  // do something here
}
while (i--);
}</pre>
<p>This technique is over three times faster than a normal <tt>for</tt> loop. Note the decrement operator doubles as a conditional; when it gets to zero, it evaluates as false. One final optimization is to substitute the pre-decrement operator for the post-decrement operator for the conditional (see Listing 10.14).</p>
<h5>Listing 10.14</b> Flipped Loop with Optimized Reverse Count</h5>
<pre>function loopDoWhileReverse3() {
var i=iter;
do
{
  // do something here
}
while (--i);
}</pre>
<p>This technique is over four times faster than a normal <tt>for</tt> loop. This last condition assumes that i is greater than zero. Table 10.2 shows the results for each loop type listed previously for IE5 on my Mac PowerBook.</p>
<h5>Table 10.2 Loop Optimizations Compared</h5>
<table border="2" cellspacing="1" cellpadding="1" style="font-family: Verdana, Arial, Helvetica, sans-serif;font-size: 9px;font-style: normal;font-weight: normal;font-variant: normal; color: #000000;">
<col width="17" />
<col width="34" />
<col width="26" />
<col width="29" />
<col width="33" />
<col width="67" />
<col width="67" />
<tr valign="TOP">
<td colspan="1" rowspan="1" valign="TOP" width="17">
<p><b> </b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="34">
<p><b>Normal</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="26">
<p><b>Do While</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="29">
<p><b>Reverse</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="33">
<p><b>Do While Reverse</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="67">
<p><b>Do While Reverse2</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="67">
<p><b>Do While Reverse3</b></p>
</td>
</tr>
<tr valign="TOP">
<td colspan="1" rowspan="1" valign="TOP" width="17">
<p><b>Total time (ms)</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="34">
<p>2022</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="26">
<p>1958</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="29">
<p>1018</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="33">
<p>932</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="67">
<p>609</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="67">
<p>504</p>
</td>
</tr>
<tr valign="TOP">
<td colspan="1" rowspan="1" valign="TOP" width="17">
<p><b>Cycle time (ms)</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="34">
<p>0.0040</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="26">
<p>0.0039</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="29">
<p>0.0020</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="33">
<p>0.0018</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="67">
<p>0.0012</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="67">
<p>0.0010</p>
</td>
</tr>
</table>
<p>
<h5>Unroll or Eliminate Loops</h5>
<p>Unrolling a loop reduces the cost of loop overhead by decreasing the number of times you check the loop condition. Essentially, loop unrolling increases the number of computations per iteration. To unroll a loop, you perform two or more of the same statements for each iteration, and increment the counter accordingly. So instead of this:</p>
<pre>var iter = number_of_iterations;

for (var i=0;i&lt;iter;i++) {
  foo();
}</pre>
<p>Do this:</p>
<pre>var iter = multiple_of_number_of_unroll_statements;

for (var i=0;i&lt;iter;) {
  foo();i++;
  foo();i++;
  foo();i++;
  foo();i++;
  foo();i++;
  foo();i++;
}</pre>
<p>I&#039;ve unrolled this loop six times, so the number of iterations must be a multiple of six. The effectiveness of loop unrolling depends on the number of operations per iteration. Again, the simpler, the better. For simple statements, loop unrolling in JavaScript can speed inner loops by as much as 50 to 65 percent. But what if the number of iterations is not known beforehand? That&#039;s where techniques like Duff&#039;s Device come in handy.</p>
<h5>Duff&#039;s Device</h5>
<p>Invented by programmer Tom Duff while he was at Lucasfilm Ltd. in 1983,<sup>16</sup> Duff&#039;s Device generalizes the loop unrolling process. Using this technique, you can unroll loops to your heart&#039;s content without knowing the number of iterations beforehand. The original algorithm combined a <tt>do-while</tt> and a <tt>switch</tt> statement. The technique combines loop unrolling, loop reversal, and loop flipping. So instead of this (see Listing 10.15):</p>
<h5>Listing 10.15</b> Normal <tt>for</tt> Loop</h5>
<pre>testVal=0;
iterations=500125;

for (var i=0;i&lt;iterations;i++) {
  // modify testVal here
}</pre>
<p>16. 	Tom Duff, &quot;Tom Duff on Duff&#039;s Device&quot; [electronic mailing list], (Link&ouml;ping, Sweden: Lysator Academic Computer Society, 10 November 1983 [archived reproduction]), available from the Internet at <a href="http://www.lysator.liu.se/c/duffs-device.html" target="new">http://www.lysator.liu.se/c/duffs-device.html</a>. Duff describes the loop unrolling technique he developed while at Lucasfilm Ltd.</p>
<p>Do this (see Listing 10.16):</p>
<h5>Listing 10.16</b> Duff&#039;s Device</h5>
<pre>function duffLoop(iterations) {

  var testVal=0;

  // Begin actual Duff&#039;s Device
  // Original JS Implementation by Jeff Greenberg 2/2001

  var n = iterations / 8;
  var caseTest = iterations % 8;  

  do {
    switch (caseTest)
    {
    case 0: [modify testVal here];
    case 7: [ditto];
    case 6: [ditto];
    case 5: [ditto];
    case 4: [ditto];
    case 3: [ditto];
    case 2: [ditto];
    case 1: [ditto];
    }
    caseTest=0;
  }
  while (--n &gt; 0);
}</pre>
<p>Like a normal unrolled loop, the number of loop iterations (<tt>n = iterations/8</tt>) is a multiple of the degree of unrolling (8, in this example). Unlike a normal unrolled loop, the modulus (<tt>caseTest = iterations % 8</tt>) handles the remainder of any leftover iterations through the switch/case logic. This technique is 8 to 44 percent faster in IE5+, and it is 94 percent faster in NS 4.7.</p>
<h5>Fast Duff&#039;s Device</h5>
<p>You can avoid the complex <tt>do/switch</tt> logic by unrolling Duff&#039;s Device into two loops. So instead of the original, do this (see Listing 10.17):</p>
<h5>Listing 10.17</b> Fast Duff&#039;s Device</h5>
<pre>function duffFastLoop8(iterations) {

// from an anonymous donor to Jeff Greenberg&#039;s site

  var testVal=0;
  var n = iterations % 8;
  while (n--)
  {
    testVal++;
  }

  n = parseInt(iterations / 8);
  while (n--)
  {
    testVal++;
    testVal++;
    testVal++;
    testVal++;
    testVal++;
    testVal++;
    testVal++;
    testVal++;
  }
}</pre>
<p>This technique is about 36 percent faster than the original Duff&#039;s Device on IE5 Mac. Even better, optimize the loop constructs by converting the <tt>while</tt> decrement to a <tt>do while</tt> pre-decrement like this (see Listing 10.18):</p>
<h5>Listing 10.18</b> Faster Duff&#039;s Device</h5>
<pre>function duffFasterLoop8(iterations) {

  var testVal=0;
  var n = iterations % 8;

  if (n&gt;0) {
    do
    {
      testVal++;
    }
    while (--n); // n must be greater than 0 here
  }

  n = parseInt(iterations / 8);
  do
  {
    testVal++;
    testVal++;
    testVal++;
    testVal++;
    testVal++;
    testVal++;
    testVal++;
    testVal++;
  }
  while (--n);
}</pre>
<p>This optimized Duff&#039;s Device is 39 percent faster than the original and 67 percent faster than a normal <tt>for</tt> loop (see Table 10.3).</p>
<h5>Table 10.3 Duff&#039;s Device Improved</h5>
<table border="2" cellspacing="2" cellpadding="2" style="font-family: Verdana, Arial, Helvetica, sans-serif;font-size: 9px;font-style: normal;font-weight: normal;font-variant: normal; color: #000000;">
<col width="33" />
<col width="39" />
<col width="53" />
<col width="41" />
<col width="100" />
<tr valign="TOP">
<td colspan="1" rowspan="1" valign="TOP" width="33">
<p><b>500,125 Iterations</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="39">
<p><b>Normal <tt>for</tt> Loop</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="53">
<p><b>Duff&#039;s Device</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="41">
<p><b>Duff&#039;s Fast</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="100">
<p><b>Duff&#039;s Faster</b></p>
</td>
</tr>
<tr valign="TOP">
<td colspan="1" rowspan="1" valign="TOP" width="33">
<p><b>Total time (ms)</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="39">
<p>1437</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="53">
<p>775</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="41">
<p>493</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="100">
<p>469</p>
</td>
</tr>
<tr valign="TOP">
<td colspan="1" rowspan="1" valign="TOP" width="33">
<p><b>Cycle time (ms)</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="39">
<p>0.00287</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="53">
<p>0.00155</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="41">
<p>0.00099</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="100">
<p>0.00094</p>
</td>
</tr>
</table>
<p> <br />
<h5>How Much to Unroll?</h5>
<p>To test the effect of different degrees of loop unrolling, I tested large iteration loops with between 1 and 15 identical statements for the Faster Duff&#039;s Device. Table 10.4 shows the results.</p>
<h5>Table 10.4 Faster Duff&#039;s Device Unrolled</h5>
<table border="1" cellspacing="1" cellpadding="1" style="font-family: Verdana, Arial, Helvetica, sans-serif;font-size: 9px;font-style: normal;font-weight: normal;font-variant: normal; color: #000000;">
<col width="18" />
<col width="24" />
<col width="24" />
<col width="24" />
<col width="24" />
<col width="24" />
<col width="24" />
<col width="24" />
<col width="24" />
<col width="24" />
<col width="24" />
<col width="24" />
<col width="24" />
<col width="24" />
<col width="24" />
<col width="24" />
<tr valign="TOP">
<td colspan="1" rowspan="1" valign="TOP" width="38">
<p><b>Duff&#039;s Faster</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p><b>1 Degree</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p><b>2</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p><b>3</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p><b>4</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p><b>5</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p><b>6</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p><b>7</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p><b>8</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p><b>9</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p><b>10</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p><b>11</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p><b>12</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p><b>13</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p><b>14</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p><b>15</b></p>
</td>
</tr>
<tr valign="TOP">
<td colspan="1" rowspan="1" valign="TOP" width="38">
<p><b>Total time (ms)</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>925</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>661</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>576</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>533</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>509</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>490</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>482</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>469</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>467</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>457</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>453</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>439</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>437</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>433</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>433</p>
</td>
</tr>
<tr valign="TOP">
<td colspan="1" rowspan="1" valign="TOP" width="38">
<p><b>Cycle time (ms)</b></p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>0.00184</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>0.00132</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>0.00115</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>0.00106</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>0.00101</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>0.00097</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>0.00096</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>0.00093</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>0.00093</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>0.00091</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>0.00090</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>0.00087</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>0.00087</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>0.00086</p>
</td>
<td colspan="1" rowspan="1" valign="TOP" width="44">
<p>0.00086</p>
</td>
</tr>
</table>
<p>
<p>As you can see in Table 10.4, the effect diminishes as the degree of loop unrolling increases. Even after two statements, the time to loop through many iterations is less than 50 percent of a normal <tt>for</tt> loop. Around seven statements, the time is cut by two-thirds. Anything over eight reaches a point of diminishing returns. Depending on your requirements, I recommend that you choose to unroll critical loops by between four and eight statements for Duff&#039;s Device.</p>
<h5>Fuse Loops</h5>
<p>If you have two loops in close proximity that use the same number of iterations (and don&#039;t affect each other), you can combine them into one loop. So instead of this:</p>
<pre>for (i=0; i&lt;j; i++) {
  sumserv += serv(i);
}

for (i=0; i&lt;j; i++) {
  prodfoo *= foo(i);
}</pre>
<p>Do this:</p>
<pre>for (i=0; i&lt;j; i++) {
  sumserv += serv(i);
  prodfoo *= foo(i);
}</pre>
<p>Fusing loops avoids the additional overhead of another loop control structure and is more compact.<br />
<h3>Expression Tuning</h3>
<p> As regular expression connoisseurs can attest, tuning expressions themselves can speed up things considerably. Count the number of operations within critical loops and try to reduce their number and strength.</p>
<p>If the evaluation of an expression is costly, replace it with a less-expensive operation. Assuming that <tt>a</tt> is greater than <tt>0</tt>, instead of this:</p>
<pre>a &gt; Math.sqrt(b);</pre>
<p>Do this:</p>
<pre>a*a &gt; b;</pre>
<p>Or even better:</p>
<pre>var c = a*a;
c&gt;b; </pre>
<p> <i>Strength reduction</i> is the process of simplifying expensive operations like multiplication, division, and modulus into cheap operations like addition, <tt>OR</tt>, <tt>AND</tt>, and shifting. Loop conditions and statements should be as simple as possible to minimize loop overhead. Here&#039;s an example from Listing 10.10. So instead of this:</p>
<pre>for (var i=iter;i&gt;0;i--)</pre>
<p>Do this:</p>
<pre>var i=iter-1;
do {} while (i--);</pre>
<p> This technique simplifies the test condition from an inequality to a decrement, which also doubles as an exit condition once it reaches zero.<br />
<h4>Miscellaneous Tuning Tips</h4>
<p> You can use many techniques to &quot;bum&quot; CPU cycles from your code to cool down hot spots. Logic rules include short-circuiting monotone functions, reordering tests to place the least-expensive one first, and eliminating Boolean variables with if/else logic. You also can shift bits to reduce operator strength, but the speed-up is minimal and not consistent in JavaScript. </p>
<p> Be sure to pass arrays by reference because this method is faster in JavaScript. If a routine calls itself last, you can adjust the arguments and branch back to the top, saving the overhead of another procedure call. This is called <i>removing tail recursion</i>.</p>
<p><b>For More Information</b></p>
<p> For more tuning tips, see the following sites:</p>
<p> <a href="http://www.cs.bell-labs.com/cm/cs/pearls/apprules.html" target="new">http://www.cs.bell-labs.com/cm/cs/pearls/apprules.html</a>&#8212;Jon Bentley&#039;s rules for code tuning.</p>
<p> <a href="http://www.refactoring.com/catalog/" target="new">http://www.refactoring.com/catalog/</a>&#8212;Martin Fowler&#039;s catalog of refactoring techniques.</p>
<p> <a href="http://home.earthlink.net/~kendrasg/info/js_opt/" target="new">http://home.earthlink.net/~kendrasg/info/js_opt/</a>&#8212;Jeff Greenburg&#039;s JavaScript speed-optimization tests. <a href="http://www.xp123.com/xplor/xp0002d/" target="new">http://www.xp123.com/xplor/xp0002d/</a>&#8212;William Wake&#039;s refactorings from Bentley&#039;s <i>Writing EfficientPrograms.</i></p>
<p><b>Flash ActionScript Optimization</b> </p>
<p> Like JavaScript, ActionScript is based on the ECMAScript standard. Unlike JavaScript, the ActionScript interpreter is embedded within Macromedia&#039;s popular Flash plug-in and has different performance characteristics than JavaScript. Although the techniques used in this chapter will work for Flash, two additional approaches are available to Flash programmers. You can speed up Flash performance by replacing slower methods with the prototype command and hand-tune your code with Flasm.</p>
<p> Flasm is a command-line assembler/disassembler of Flash ActionScript bytecode. It disassembles your entire SWF file, allowing you to perform optimizations by hand and replace all actions in the original SWF with your optimized routines. See <a href="http://flasm.sourceforge.net/#optimization" target="new">http://flasm.sourceforge.net/#optimization</a> for more information.</p>
<p> You can replace slower methods in ActionScript by rewriting these routines and replacing the originals with the prototype method. The Prototype site (<a href="http://www.layer51.com/proto/" target="new">http://www.layer51.com/proto/</a>) provides free Flash functions redefined for speed or flexibility. These functions boost performance for versions up to Flash 5. Flash MX has improved performance, but these redefined functions can still help.<br />
<h3>Summary</h3>
<p> To speed execution, optimize your code at the right design level or combination of levels. Start with global optimizations first (for example, algorithm and data structure choices), and then move down toward more local optimizations until your program is fast enough. Refactor to simplify your code, and then minimize DOM interaction and I/O requests. Finally, if all else fails, tune your code locally with the techniques outlined in this chapter. Measure each change, and cool hot spots one at a time. Here is a summary of the optimization techniques discussed in this chapter:
<ul>
<li>Avoid optimization if at all possible.</li>
<li>Optimize globally to locally until the code is fast enough.</li>
<li>Measure your changes.</li>
<li>Keep Pareto in mind.</li>
<li>Cool hot spots one at a time.</li>
<li>Minimize DOM and I/O interaction (object and property lookups, create and        edit subtrees offline).</li>
<li>Shorten scope chains to maximize lookup speed. Avoid <tt>with</tt> statements        because they extend scope chains.</li>
<li>Cache frequently used values.</li>
<li>
<p>Simplify loop conditions, hoist loop-invariant code, flip and reverse,        and unroll loops with an optimized Duff&#039;s Device.</li>
<li>Use local optimizations last.</li>
<li>
<p>Tune expressions for speed.</p>
</li>
</ul>
<p> <b>Recommended Reading</b></p>
<p> If you want to learn more about optimizing JavaScript, I recommend these sources:
<ul>
<li>Jon Bentley&#039;s <i>Programming Pearls</i>, <i>2nd ed.</i> (Addison-Wesley,          1999) and <i>More Programming Pearls:</i> <i>Confessions of a Coder </i>(Addison-Wesley,          1988). These books include many examples of code tuning and recap the          27 code-tuning rules in his out-of-print classic, <i>Writing Efficient          Programs</i>. </li>
<li> Brian Kernighan and Rob Pike&#039;s <i>The Practice of Programming </i>(Addison-Wesley,          1999) describes best programming practices, including Chapter 7 on performance.</li>
<li>Donald Knuth&#039;s <i>The Art of Computer Programming </i>series (Addison-Wesley,          1998)<i>.</i></li>
<li>Steve C. McConnell&#039;s <i>Code Complete:</i> <i>A Practical Handbook          of Software Construction</i> (Microsoft Press, 1993), especially Chapters          28 and 29. </li>
</ul>
<p><b>Footnotes:</b> </p>
<p> <a name="1">[ref 1]</a> Jon Bentley, <i>Programming Pearls</i>, 2d ed. (Boston, MA: Addison-Wesley, 1999). </p>
<p> <a name="2">[ref 2]</a> Brian W. Kernighan and Rob Pike, <i>The Practice of Programming</i> (Boston, MA: Addison-Wesley, 1999). See the &quot;Performance&quot; chapter, 165-188. </p>
<p> <a name="3">[ref 3]</a> Bentley, <i>Programming Pearls</i>, 7. The space-time tradeoff does not always hold. The ideal situation is mutual improvement. Bentley found that often &quot;reducing a program&#039;s space requirements also reduces its run time.&quot; </p>
<p> <a name="4">[ref 4]</a> Mozilla.org, &quot;Rhino: JavaScript for Java&quot; [online], (Mountain View, CA: The Mozilla Organization, 1998), available from the Internet at <a href="http://www.mozilla.org/rhino/" target="new">http://www.mozilla.org/rhino/</a>. </p>
<p> <a name="5">[ref 5]</a> Geoffrey Fox, &quot;JavaScript Performance Issues,&quot; Online Seminar, Northeast Parallel Architectures Center [online], (Syracuse, NY: Syracuse University, 1999), available from the Internet at <a href="http://www.npac.syr.edu/users/gcf/forcps616javascript/msrcobjectsapril99/tsld022.htm" target="new">http://www.npac.syr.edu/users/gcf/forcps616javascript/msrcobjectsapril99/tsld022.htm</a>. According to Fox, JavaScript is about 5,000 times slower than C, 100 times slower than interpreted Java, and 10 times slower than Perl. </p>
<p> <a name="6">[ref 6]</a> Bentley, <i>Programming Pearls</i>. </p>
<p> <a name="7">[ref 7]</a> Martin Fowler, <i>Refactoring: Improving the Design of Existing Code</i> (Boston, MA: Addison-Wesley, 1999). </p>
<p> <a name="8">[ref 8]</a> Vilfredo Pareto, <i>Cours d&#039;&eacute;conomie politique profess&eacute; &agrave; l&#039;Universit&eacute; de Lausanne</i>, 2 vols. (Lausanne, Switzerland: F. Rouge, 1896-97). </p>
<p> <a name="9">[ref 9]</a> Barry W. Boehm, &quot;Improving Software Productivity,&quot; <i>IEEE Computer</i> 20, no. 9 (1987): 43-57. </p>
<p> <a name="10">[ref 10]</a> Barry W. Boehm and Philip N. Papaccio, &quot;Understanding and Controlling Software Costs,&quot; <i>IEEE Transactions on Software Engineering</i> 14, no. 10 (1988): 1462-1477. </p>
<p> <a name="11">[ref 11]</a> Donald E. Knuth, &quot;An Empirical Study of FORTRAN Programs,&quot; <i>Software&#8212;Practice and Experience</i> 1, no. 2 (1971): 105-133. Knuth analyzed programs found by sifting through wastebaskets and directories on the computer center&#039;s machines. </p>
<p> <a name="12">[ref 12]</a> Kernighan and Pike, <i>The Practice of Programming</i>, 41. </p>
<p> <a name="13">[ref 13]</a> Andrew Hunt and David Thomas, <i>The Pragmatic Programmer: From Journeyman to Master</i> (Boston, MA: Addison-Wesley, 1999), 179.</p>
<p> <a name="14">[ref 14]</a> Bentley, <i>Programming Pearls</i>, 192. </p>
<p> <a name="15">[ref 15]</a> Scott Porter, email to author, 16 July 2002.</p>
<p>Andy King, author of the popular book titled &#8220;Speed Up Your Site  Web Site Optimization&#8221;. Web Site Optimization, LLC is a leading provider of web site optimization and search engine marketing services that &#8220;tune up&#8221; web sites for increased usability, conversion rates, traffic, and profitability. For more information about Web Site Optimization visit http://www.websiteoptimization.com </p>
]]></content:encoded>
			<wfw:commentRss>http://www.webpronews.com/optimizing-javascript-for-execution-speed-2003-05/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using memcached
Database Caching 1/45 queries in 0.022 seconds using memcached
Object Caching 607/707 objects using memcached

Served from: webpronews.com @ 2012-02-12 19:04:23 -->
