<?xml version="1.0" encoding="ISO-8859-1"?><rss version="2.0"><channel><title>OpenHosting Articles and Tutorials</title><link>http://www.openhosting.co.uk/articles/</link><description>User-submitted articles and tutorials</description><copyright>Copyright 2012 OpenHosting UK Internet Solutions. All rights reserved.</copyright><lastBuildDate>Tue, 24 May 2006 09:21:02 GMT</lastBuildDate><item>
<title>Consuming Flickr RSS feeds using ASP</title>
<link>http://www.openhosting.co.uk/articles/serverside/6055/</link>
<description><![CDATA[<p><span style="display:none;"><strong>Consuming Flickr RSS feeds using ASP</strong></span></p><p>This article will show you how to display thumbnails of your newest Flickr photos on your site. The HTML output and each thumbnail image is cached on your site to improve performance.</p><p><a href="http://flickr.com/" title="Flickr.com">Flickr.com</a> is one of my favourite websites. It allows me to upload all of my digital photos, tag them, categorise them, and share them with my contacts. After using Flickr for a short while you will notice that almost every page has an RSS feed associated with it. This means that you can subscribe to anyone's photo gallery, photo comments, group discussions, photos tagged with a certain keyword, and so on.</p><p>This article will show you how to use the RSS feed of your own photostream, and display thumbnails of your latest photos on your own website.</p><p><strong>Finding the RSS feed</strong><br/>The feed itself is linked at the foot of your main photos page. It follows the following format:</p><p><div class="bb-code-container"><pre class="bb-code">http&#58;//flickr.com/services/feeds/photos_public.gne?id=&#91;userid&#93;&amp;format=rss_200</pre></div></p><p><strong>The full code</strong><br/>The full code is quite long (78 lines, including comments). I'm not going to break the whole code down into chunks and explain it, since it has been stripped back into several functions and is fairly difficult to explain linearly. I have added comments where necessary.</p><p><div class="bb-code-container"><pre class="bb-code">&lt;%<br/>'URL of your RSS feed &#40;copy from the &quot;Feed&quot; link of your Flickr gallery<br/>Dim strXMLURL &#58; strXMLURL = &quot;http&#58;//flickr.com/services/feeds/photos_public.gne?id=&#91;userid&#93;&amp;format=rss_200&quot;</p><p>'The name of the file to which the HTML is cached<br/>Dim strCacheHTML &#58; strCacheHTML = &quot;flickr.htm&quot;</p><p>'The local path to the folder you will cache photos to, e.g.<br/>Dim strCachePath &#58; strCachePath = &quot;d&#58;\webs\mydomain.com\wwwroot\cache\&quot;</p><p>'The public URL to the above cache directory, e.g.<br/>Dim strCacheURL &#58; strCacheURL = &quot;http&#58;//www.mydomain.com/cache/&quot;</p><p>'This function takes the URL of the RSS feed, and the XML node name of each photo<br/>Function getXMLNode&#40;strURL, strNode&#41;<br/>	Dim objXML &#58; Set objXML = Server.CreateObject&#40;&quot;MSXML2.FreeThreadedDOMDocument&quot;&#41;<br/>	objXML.Async = False<br/>	objXML.setProperty &quot;ServerHTTPRequest&quot;, True<br/>	objXML.Load&#40;strURL&#41;<br/>	'Returns a collection of nodes to be looped through<br/>	Set getXMLNode = objXML.getElementsByTagName&#40;strNode&#41;<br/>	Set objXML = Nothing<br/>End Function</p><p>'This function pulls the thumbnail images frm Flickr and saves them to the local web server<br/>Function cacheImage&#40;imageURL&#41;<br/>	Dim cacheFSO &#58; Set cacheFSO = CreateObject&#40;&quot;Scripting.FileSystemObject&quot;&#41;<br/>	Dim aFileName &#58; aFileName = Split&#40;imageURL,&quot;/&quot;&#41;<br/>	Dim strFileName &#58; strFileName = aFileName&#40;UBound&#40;aFileName&#41;&#41;<br/>	'Check to see if the photo has been cached already<br/>	If Not cacheFSO.FileExists&#40;strCachePath &amp; strFileName&#41; Then<br/>		Dim objXMLHTTP &#58; Set objXMLHTTP = Server.CreateObject&#40;&quot;MSXML2.ServerXMLHTTP&quot;&#41;<br/>		Dim objJpeg &#58; Set objJpeg = Server.CreateObject&#40;&quot;Persits.Jpeg&quot;&#41;<br/>		objXMLHTTP.Open &quot;GET&quot;, imageURL<br/>		objXMLHTTP.Send<br/>		'Reads the image from Flickr.com<br/>		objJpeg.OpenBinary&#40;objXMLHTTP.ResponseBody&#41;		<br/>		'And saves it to the local web server<br/>		objJpeg.Save strCachePath &amp; strFileName<br/>		Set objXMLHTTP = Nothing<br/>		Set objJpeg = Nothing<br/>	End If<br/>	Set cacheFSO = Nothing<br/>	Set aFileName = Nothing<br/>	'Returns the filename, e.g. &quot;myphoto.jpg&quot;<br/>	cacheImage = strFileName<br/>	Set strFileName = Nothing<br/>End Function</p><p>'Checks to see whether the cached HTML has expired<br/>If cacheFileIsExpired&#40;strCacheHTML, 12, &quot;hours&quot;&#41; Then<br/>	'Creates a collection of XML nodes. The getXMLNode function is passed the URL<br/>	'of the Flickr RSS feed, and the node name for each photo record &#40;&quot;item&quot;&#41;<br/>	Dim objItemList &#58; Set objItemList = getXMLNode&#40;strXMLURL, &quot;item&quot;&#41;<br/>	Dim objItem, strHTML<br/>	'Loops through each photo<br/>	For Each objItem In objItemList<br/>		strHTML = strHTML &amp; &quot;&lt;div class=&quot;&quot;flickr-tn&quot;&quot;&gt;&quot; &amp; vbCrLf<br/>		'Writes the photo title. The safeHTML function converts some possibly dodgy characters<br/>		'that might be in your title, into valid XHTML &#40;ampersands, accents etc.&#41;<br/>		strHTML = strHTML &amp; vbTab &amp; &quot;&lt;span&gt;&quot; &amp; safeHTML&#40;objItem.childNodes&#40;0&#41;.Text&#41; &amp; &quot;&lt;/span&gt;&quot; &amp; vbCrLf<br/>		'Writes a link pointing to the photo page on Flickr.com, and writes the URL of the newly cached photo<br/>		strHTML = strHTML &amp; vbTab &amp; &quot;&lt;a href=&quot;&quot;&quot; &amp; objItem.childNodes&#40;1&#41;.Text &amp; &quot;&quot;&quot;&gt;&lt;img src=&quot;&quot;&quot; &amp; strCacheURL &amp; cacheImage&#40;objItem.selectSingleNode&#40;&quot;media&#58;thumbnail&quot;&#41;.getAttribute&#40;&quot;url&quot;&#41;&#41; &amp; &quot;&quot;&quot; alt=&quot;&quot;&quot; &amp; safeHTML&#40;Replace&#40;objItem.childNodes&#40;0&#41;.Text &amp; &quot;&quot;,&quot;&quot;&quot;&quot;,&quot;&quot;&#41;&#41; &amp; &quot;&quot;&quot; title=&quot;&quot;&quot; &amp; safeHTML&#40;Replace&#40;objItem.childNodes&#40;0&#41;.Text,&quot;&quot;&quot;&quot;,&quot;&quot;&#41;&#41; &amp; &quot;&quot;&quot;/&gt;&lt;/a&gt;&quot; &amp; vbCrLf<br/>		strHTML = strHTML &amp; &quot;&lt;/div&gt;&quot; &amp; vbCrLf<br/>	Next	<br/>	Set objItemList = Nothing<br/>	Set objItem = Nothing<br/>	'Update the HTML cache, and write output to the page<br/>	Response.Write&#40;writeCachedFile&#40;strCacheHTML, strHTML&#41;&#41;<br/>	Set strHTML = Nothing<br/>Else<br/>	'If cache is not out of date, server up the cached HTML file<br/>	Response.Write&#40;getCachedFile&#40;strCacheHTML&#41;&#41;<br/>End If</p><p>Set strURL = Nothing<br/>Set strCacheHTML = Nothing<br/>%&gt;</pre></div></p><p><strong>Something's missing!</strong><br/>If you read that carefully, then you will realise that three functions are missing from the code. These three functions perform the HTML output caching, and can be found in my <a href="http://www.openhosting.co.uk/articles/serverside/5853/" title="Data Caching Using Text Files in ASP">Data Caching Using Text Files in ASP</a> article. From this page, copy the first three functions into a new ASP file, and include it with the above code.</p><p><strong>Configuring the script</strong><br/>The code will not work straight away. You will need to edit the first four variables:</p><p><div class="bb-code-container"><pre class="bb-code">Dim strXMLURL &#58; strXMLURL = &quot;http&#58;//flickr.com/services/feeds/photos_public.gne?id=&#91;userid&#93;&amp;format=rss_200&quot;</pre></div><br/>This line should contain the path to the RSS feed of your photos. Just browse to your main photo page and copy the URL from the feed link at the bottom.</p><p><div class="bb-code-container"><pre class="bb-code">Dim strCacheHTML &#58; strCacheHTML = &quot;flickr.htm&quot;</pre></div><br/>This is the name of the HTML output cache file. It can be left as it is, or changed to your liking.</p><p><div class="bb-code-container"><pre class="bb-code">Dim strCachePath &#58; strCachePath = &quot;d&#58;\webs\mydomain.com\wwwroot\cache\&quot;</pre></div><br/>This is the local path to the cache folder. You should create a folder named "cache" in the root of your wwwroot directory, and replace "mydomain.com" with your domain name.<br/>Note: this is the local path used on OpenHosting's servers. Other web hosts may use a slightly different configuration, so it's best to check first!</p><p><div class="bb-code-container"><pre class="bb-code">Dim strCacheURL &#58; strCacheURL = &quot;http&#58;//www.mydomain.com/cache/&quot;</pre></div><br/>This is simply the URL pointing to the aforementioned cache folder. Again, replace "mydomain.com" with your domain name.</p><p><strong>How long until the cache refreshes?</strong><br/>The default is 12 hours. If you do not upload photos very often, then you can increase this value (found on this line):<br/><div class="bb-code-container"><pre class="bb-code">If cacheFileIsExpired&#40;strCacheHTML, 12, &quot;hours&quot;&#41; Then</pre></div><br/>The number "12" can be any number. Setting it to 0 will force a cache refresh every time the script loads. The "hours" string can also be changed to "minutes" or "days", to fine tune your cache length.</p><p><strong>Caching photo thumbnails</strong><br/>I've found Flickr to be <em>very</em> slow sometimes. For this reason, this script actually downloads the thumbnails from Flickr and stores them on your own site. This means that if Flickr is suffering from downtime or slow speeds, your photos will still load with the lightning speed of your own web page. Hurray!</p><p>Thumbnails are only ever downloaded once, and are stored in the cache folder. To refresh a thumbnail image, simply delete it from the cache folder, and the script will download it again when it runs next.</p><p><strong>Adding the script to your own site</strong><br/>I have found that this script works well for showing the thumbnails on a sidebar on my sites. To use it in your own pages, save all of the code as an ASP page named "flickr.asp". You can then include it in your site as follows:</p><p><div class="bb-code-container"><pre class="bb-code">&lt;h2&gt;My latest Flickr uploads&lt;/h2&gt;<br/>&lt;div id=&quot;flickr-photos&quot;&gt;<br/>&lt;!--#include file=&quot;flickr.asp&quot; --&gt;<br/>&lt;/div&gt;</pre></div></p><p><strong>Questions or comments?</strong><br/>Head over to <a href="http://forums.openhosting.co.uk/viewtopic.php?t=6055" title="the article page">the article page</a> in the friendly support forums, and post away </p>]]></description>
<pubDate>Tue, 24 May 2006 09:21:02 GMT</pubDate>
</item>
<item>
<title>Auto-refreshing dynamic content using AJAX</title>
<link>http://www.openhosting.co.uk/articles/webdev/6004/</link>
<description><![CDATA[<p><span style="display:none;"><strong>Auto-refreshing dynamic content using AJAX</strong></span></p><p>Using AJAX, it is possible to regularly auto-refresh a section of a webpage containing dynamic content without reloading the whole page.</p><p>The script uses an XMLHTTPRequest to retrieve a dynamic page which is then inserted into the output page.<br/>This content is then refreshed automatically using the Javascript setTimeout() function.</p><p>First of all you need a dynamic content page.<br/>I've used a simple ASP date &amp; time script as an example and named the page time.asp:<br/><div class="bb-code-container"><pre class="bb-code">&lt;% Response.CacheControl = &quot;no-cache&quot; %&gt;<br/>&lt;%= Date %&gt; @ &lt;%= Time %&gt;</pre></div><br/>You need to include the line:<br/><div class="bb-code-container"><pre class="bb-code">&lt;% Response.CacheControl = &quot;no-cache&quot; %&gt;</pre></div>As Internet Explorer will cache this page otherwise, and the content will not be updated on the output page.</p><p>Next, place the following script in the head of the output page:<br/><div class="bb-code-container"><pre class="bb-code">&lt;script type=&quot;text/javascript&quot;&gt;<br/>var page = &quot;time.asp&quot;;<br/>function ajax&#40;url,target&#41;<br/> &#123;<br/>    // native XMLHttpRequest object<br/>   document.getElementById&#40;target&#41;.innerHTML = 'sending...';<br/>   if &#40;window.XMLHttpRequest&#41; &#123;<br/>       req = new XMLHttpRequest&#40;&#41;;<br/>       req.onreadystatechange = function&#40;&#41; &#123;ajaxDone&#40;target&#41;;&#125;;<br/>       req.open&#40;&quot;GET&quot;, url, true&#41;;<br/>       req.send&#40;null&#41;;<br/>   // IE/Windows ActiveX version<br/>   &#125; else if &#40;window.ActiveXObject&#41; &#123;<br/>       req = new ActiveXObject&#40;&quot;Microsoft.XMLHTTP&quot;&#41;;<br/>       if &#40;req&#41; &#123;<br/>           req.onreadystatechange = function&#40;&#41; &#123;ajaxDone&#40;target&#41;;&#125;;<br/>           req.open&#40;&quot;GET&quot;, url, true&#41;;<br/>           req.send&#40;&#41;;<br/>       &#125;<br/>   &#125;<br/>		   setTimeout&#40;&quot;ajax&#40;page,'scriptoutput'&#41;&quot;, 10000&#41;;<br/>&#125;</p><p>function ajaxDone&#40;target&#41; &#123;<br/>   // only if req is &quot;loaded&quot;<br/>   if &#40;req.readyState == 4&#41; &#123;<br/>       // only if &quot;OK&quot;<br/>       if &#40;req.status == 200 || req.status == 304&#41; &#123;<br/>           results = req.responseText;<br/>           document.getElementById&#40;target&#41;.innerHTML = results;<br/>       &#125; else &#123;<br/>           document.getElementById&#40;target&#41;.innerHTML=&quot;ajax error&#58;\n&quot; +<br/>               req.statusText;<br/>       &#125;<br/>   &#125;<br/>&#125;<br/>&lt;/script&gt;</pre></div><br/>Set the variable for your dynamic content page at the top of the script:<br/><div class="bb-code-container"><pre class="bb-code">var page = &quot;time.asp&quot;;</pre></div><br/>Adjust the content reload time (currently set at 10000 milli-seconds or 10 seconds):<br/><div class="bb-code-container"><pre class="bb-code">setTimeout&#40;&quot;ajax&#40;page,'scriptoutput'&#41;&quot;, 10000&#41;;</pre></div><br/>Add an onload event to the page's body tag to call the script:<br/><div class="bb-code-container"><pre class="bb-code">&lt;body onload=&quot;ajax&#40;page,'scriptoutput'&#41;&quot;&gt;</pre></div><br/>Define an area for the content - in this case is just a span within a paragraph:<br/><div class="bb-code-container"><pre class="bb-code">&lt;p&gt;Current Server date &amp; time &#40;updated every 10 seconds&#41;&#58;&lt;br /&gt;<br/>&lt;span id=&quot;scriptoutput&quot;&gt;&lt;/span&gt;&lt;/p&gt;</pre></div></p><p>Finally, save the page and upload it along with time.asp to the same folder in your webspace.</p>]]></description>
<pubDate>Wed, 04 May 2006 12:28:55 GMT</pubDate>
</item>
<item>
<title>Unobtrusive JavaScript Popup Windows</title>
<link>http://www.openhosting.co.uk/articles/webdev/5918/</link>
<description><![CDATA[<p><span style="display:none;"><strong>Unobtrusive JavaScript Popup Windows</strong></span></p><p>Learn how to use JavaScript events and triggers without using inline scripting, therefore allowing visitors to use your site even with JavaScript disabled. </p><p><strong>Introduction</strong><br/>In this new regenerated world of web development there is a desire to use advanced features on sites, yet maintain usability, accessibility and backwards compatability. Many "advanced" features, such as image galleries, form validation and pop-up windows require JavaScript to function properly. This means that users with JavaScript disabled (they do exist!) are unable to use your site. And when these advanced features make up critical paths for your visitors, you're destroying usability and accessibility.</p><p><strong>A quick and dirty JavaScript example</strong><br/>Let's look at the JavaScript we so often use to create pop-up windows. Love 'em or hate 'em, they do have their place in our arsenal if used meaningfully to enhance the browsing experience. The following example is how a developer might code a pop-up window event.<br/><div class="bb-code-container"><pre class="bb-code">&lt;a href=&quot;#&quot; onclick=&quot;javascript&#58;window.open&#40;'page.html','popup','width=400,height=200'&#41;;&quot;&gt;View new page&lt;/a&gt;</pre></div></p><p><strong>What's wrong with that?</strong><br/>The only good thing about the example above is that it works. However, there are a number of problems with this code:</p><p><em>a) Maintainability of inline JavaScript</em><br/>The raw JavaScript code is inserted "inline" to an element in the page HTML. If you want to update the widths of your pop-ups, or change the way your window opens, you are going to have to edit this code in every page of your site. Moving the JavaScript code to an external .js file will improve maintainability.</p><p><em>b) If JavaScript is disabled...</em><br/>The "onclick" event will not be triggered, and the link reference has been set effectively to nowhere ("#"). To a browser with JavaScript disabled (whether it be a visitor or a search engine robot) this link is now useless. It goes nowhere.</p><p><strong>Improving the markup</strong><br/>Problems are solved most easily when the (X)HTML markup is simple and clean. Keep It Simple, Stupid. Here is a suggested simplified link. Notice I have added a class attribute to the anchor element. You'll see why later. <br/><div class="bb-code-container"><pre class="bb-code">&lt;a href=&quot;page.html&quot; class=&quot;popup&quot;&gt;View new page&lt;/a&gt;</pre></div></p><p><strong>Using JavaScript to add the pop-up event</strong></p><p>The following JavaScript function will create our popup actions once the page has been loaded. The script looks through our document (Document Object Model) for all link (anchor) elements. For each link, the script checks to see whether this link is to be opened as a pop-up (i.e. whether it has been assigned a class of "popup"). If so, an onclick event is added to the link element which triggers a new function containing our original pop-up code (from the inline example at the top of the article).</p><p><div class="bb-code-container"><pre class="bb-code">window.onload = function&#40;&#41; &#123;<br/>	// check to see that the browser supports the getElementsByTagName method<br/>	// if not, exit the loop <br/>	if &#40;!document.getElementsByTagName&#41; &#123;<br/>		return false; <br/>	&#125; <br/>	// create an array of objects of each link in the document <br/>	var popuplinks = document.getElementsByTagName&#40;&quot;a&quot;&#41;;<br/>	// loop through each of these links &#40;anchor tags&#41; 	<br/>	for &#40;var i=0; i &lt; popuplinks.length; i++&#41; &#123;	<br/>		// if the link has a class of &quot;popup&quot;...	<br/>		if &#40;popuplinks&#91;i&#93;.getAttribute&#40;&quot;class&quot;&#41; == &quot;popup&quot;&#41; &#123;	<br/>			// add an onclick event on the fly to pass the href attribute	<br/>			// of the link to our second function, openPopUp 	<br/>			popuplinks&#91;i&#93;.onclick = function&#40;&#41; &#123;	<br/>			openPopUp&#40;this.getAttribute&#40;&quot;href&quot;&#41;&#41;;	<br/>			return false; 	<br/>			&#125; 	<br/>		&#125;<br/>	&#125; <br/>&#125; </p><p>function openPopUp&#40;linkURL&#41; &#123;<br/>	window.open&#40;linkURL,'popup','width=400,height=200'&#41;<br/>&#125;</pre></div><br/>Ideally this code should be saved to a separate file to your HTML document, say popup.js. Then import the JavaScript in your document link this:</p><p><div class="bb-code-container"><pre class="bb-code">&lt;script type=&quot;text/javascript&quot; src=&quot;popup.js&quot;&gt;&lt;/script&gt;</pre></div></p><p><strong>Conclusion</strong><br/>Using the DOM (Document Object Model) we have successfully read the page for anchor tags. If the link needs to be opened in a popup, the we have added an event to the link. If JavaScript is disabled, then the link tag will act as a normal hyperlink, allowing our visitors to continue browsing the new page in the main browser window. This implements the concept of 'progressive enhancement' using unobtrusive JavaScript techniques - functionality that adds value to pages, but isn't a requirement.</p><p><strong>Further reading</strong><br/>This article was inspired by examples in Jeremy Keith's fantastic <a href="http://domscripting.com/" title="DOM Scripting">DOM Scripting</a> book. The book offers a brief history and introduction of JavaScript and begins with simple examples to teach best practices and unobtrusive scripting. I would recommend it to anyone.</p>]]></description>
<pubDate>Mon, 02 Apr 2006 18:34:51 GMT</pubDate>
</item>
<item>
<title>Ajax &quot;Hello World&quot; Example</title>
<link>http://www.openhosting.co.uk/articles/webdev/5899/</link>
<description><![CDATA[<p><span style="display:none;"><strong>Ajax "Hello World" Example</strong></span></p><p>An introduction to what Ajax is and a basic "Hello World" example. Includes a downloadable example and suggests areas for further examples.</p><p><strong>What is Ajax?</strong><br/>There's a growing momentum behind newly-launched websites at the moment. Part of the rise of <a href="http://www.oreillynet.com/pub/a/oreilly/tim/news/2005/09/30/what-is-web-20.html" title="the Web 2.0 concept">the Web 2.0 concept</a> has been the mainstream adoption of <a href="http://adaptivepath.com/publications/essays/archives/000385.php" title="AJAX">AJAX</a> (Asynchronous JavaScript And XML). Ajax isn't anything new, nor are the technologies behind the name, but they've found a new lease of life on trendy new sites. So what is Ajax exactly? Put very simply, it's a combination of XHTML, CSS and most importantly JavaScript and XMLHttpRequest that allows you to update your web page content without refreshing the page.</p><p>Of course, this is an over-simplified example and the funtionality of the Ajax technologies has a far wider scope. But this article will show you the bare structure of an Ajax-type request, and will show you how to use it on your own site.</p><p><strong>The Code</strong><br/>The <a href="http://www.xml.com/pub/a/2005/02/09/xml-http-request.html" title="XMLHttpRequest">XMLHttpRequest</a> object effectively allows you to GET or POST to a remote script using JavaScript. In our example we will use this object to open a text file and read back its contents. The code that follows creates an XMLHttpRequest object ready for us to use. We check for Internet Explorer since IE uses its own XMLHttpRequest object that is different from other browsers. When the page loads, the createRequestObject function is called and an instance of the XMLHttpRequest object is stored in the variable "http". <br/><div class="bb-code-container"><pre class="bb-code">&lt;script type=&quot;text/javascript&quot;&gt;<br/>var http = createRequestObject&#40;&#41;;<br/>function createRequestObject&#40;&#41; &#123;<br/>	var objAjax;<br/>	var browser = navigator.appName;<br/>	if&#40;browser == &quot;Microsoft Internet Explorer&quot;&#41;&#123;<br/>		objAjax = new ActiveXObject&#40;&quot;Microsoft.XMLHTTP&quot;&#41;;<br/>	&#125;else&#123;<br/>		objAjax = new XMLHttpRequest&#40;&#41;;<br/>	&#125;<br/>	return objAjax;<br/>&#125;</p><p>function getNewContent&#40;&#41;&#123;<br/>	http.open&#40;'get','newcontent.txt'&#41;;<br/>	http.onreadystatechange = updateNewContent;<br/>	http.send&#40;null&#41;;<br/>	return false;<br/>&#125;</p><p>function updateNewContent&#40;&#41;&#123;<br/>	if&#40;http.readyState == 4&#41;&#123;<br/>		document.getElementById&#40;'mySentence'&#41;.innerHTML = http.responseText;<br/>	&#125;<br/>&#125;<br/>&lt;/script&gt;</pre></div></p><p>The second function should be called from a page element, such as a hyperlink or a button. This element will trigger the Ajax event (getNewContent), which reads the content text file. The third and final function (updateNewContent) checks the result of the XMLHttpRequest and updates the page accordingly.</p><p><strong>A Hello World example</strong><br/>The JavaScript above should be placed within your HTML page, or included as an external .js file. You should create a text file named "newcontent.txt" containing the words "Hello World" and save it in the same folder as your HTML page. Your event trigger element should call the second function, like this:<br/><div class="bb-code-container"><pre class="bb-code">&lt;p id=&quot;mySentence&quot;&gt;<br/>&lt;a href=&quot;#&quot; onclick=&quot;javascript&#58;getNewContent&#40;&#41;;&quot;&gt;Click here to update the page&lt;/a&gt;.<br/>When you click the link, this content will be replaced.&lt;/p&gt;</pre></div></p><p>When the link is clicked, the getNewContent function is triggered. It calls a text file named "newcontent.txt". The function updateNewContent monitors the progress of the request, and when it is complete, the HTML element with an id of "mySentence" is updated with the text file contents.</p><p><a href="http://www.openhosting.co.uk/articlefiles/ajax-introduction/" title="Try out a live example!">Try out a live example!</a></p><p><strong>Download all files as a Zip file</strong><br/>To make things a bit easier, you can also <a href="http://www.openhosting.co.uk/articlefiles/ajax-introduction/ajax-introduction.zip" title="download the live example">download the live example</a> and all code referenced in this article as a Zip file.</p><p><strong>Further applications</strong><br/>This is the simplest Ajax example I could think of. If you want to make the "Hello World" content dynamic, you can use the code to request an ASP or PHP page rather than a text file. With some simple modification you could pass some parameters to this request and start to interface with a database. In its most complex form, Ajax has been used to build entire interfaces. <a href="http://mail.google.com" title="Gmail">Gmail</a> and <a href="http://maps.google.com" title="Google Maps">Google Maps</a> for example, use Ajax heavily to create navigation and page content without refreshing the entire browser page. On your own sites it is likely that you will find Ajax useful for the following common features:<br/><ul><li>Validating form fields<br/><li>Auto-complete form fields<br/><li>Updating content based on timers (e.g. an auction)<br/><li>Performing real-time spell checking of form fields<br/><li>Dynamically loading list/select boxes based on other form choices</ul></p><p><strong>Benefits of using Ajax</strong><br/><ul><li>Just a small section of a page can be updated without having to reload the entire page. This saves on bandwidth and loading times, and reduces server load.<br/><li>The code is lightweight and not very complex.<br/><li>JavaScript and the XMLHttpRequest object are supported in all modern browsers<br/><li>It's got the geeky cool factor ;-)</ul></p><p><strong>Potential disadvantages of using Ajax</strong><br/><ul><li>Not everybody has JavaScript enabled in their browser (by choice, or otherwise). You should make sure that your site functionality does not <em>require</em> Ajax and that the site is usable without the Ajax fanciness<br/><li>Breaks the back button. Try the example above and click the back button. The original content isn't replaced, as a normal page in your History is. Therefore you should make plans for a function to also reverse any content replacement if necessary<br/><li>If content is embedded within JavaScript code then this can reduce the effective accessibility of your site.</ul></p>]]></description>
<pubDate>Fri, 27 Mar 2006 17:33:23 GMT</pubDate>
</item>
<item>
<title>Capturing Remote Images Using ASPJpeg</title>
<link>http://www.openhosting.co.uk/articles/serverside/5854/</link>
<description><![CDATA[<p><span style="display:none;"><strong>Capturing Remote Images Using ASPJpeg</strong></span></p><p>ASPJpeg is a fantastic way of manipulating images on the server. But what if the image is on another server completely?</p><p><strong>Introduction</strong><br/>This problem reared its ugly head when developing the <a href="http://www.openhosting.co.uk/" title="OpenHosting website">OpenHosting website</a>. On the new <a href="http://www.openhosting.co.uk/status/" title="Status page">Status page</a> we wanted to have a graph of the current network throughput. The only problem was that the software generating this graph sits on a separate web server to the OpenHosting website. We wanted to be able to grab this image and use ASPJpeg to clean it, resize it, and most importantly, cache it.</p><p><strong>How it's done...</strong><br/>Thankfully there's a simple solution to grabbing an image from a remote server. Using the XMLHTTP object (commonly used to request remote documents such as XML files) we request the PNG image file, and use ASPJpeg's OpenBinary method to read the incoming byte stream. The image is then saved as a JPEG on the web server. A simple ASP script works out whether the cached image needs updating. If so, the above routine is executed. If not, the page simply returns the cached JPEG image. Here's the (modified) code.</p><p><div class="bb-code-container"><pre class="bb-code">&lt;%<br/>If cacheFileIsExpired&#40;&quot;statusgraph.jpg&quot;, 4,&quot;hours&quot;&#41; Then<br/>   Response.Write&#40;&quot;&lt;img src=&quot;&quot;getRemoteImage.asp&quot;&quot; alt=&quot;&quot;Updated image&quot;&quot; /&gt;&quot;&#41;<br/>Else<br/>  Response.Write&#40;&quot;&lt;img src=&quot;&quot;cachedImage.jpg&quot;&quot; alt=&quot;&quot;Image loaded from cache&quot;&quot; /&gt;&quot;&#41;<br/>End If<br/>%&gt;</pre></div></p><p>And the getRemoteImage page that works the XMLHTTP magic:<br/><div class="bb-code-container"><pre class="bb-code">&lt;%<br/>Dim objXMLHTTP &#58; Set objXMLHTTP = Server.CreateObject&#40;&quot;MSXML2.ServerXMLHTTP&quot;&#41;<br/>Dim objJpeg &#58; Set objJpeg = Server.CreateObject&#40;&quot;Persits.Jpeg&quot;&#41;<br/>objXMLHTTP.Open &quot;GET&quot;, &quot;http&#58;//www.domain2.com/theImage.jpg&quot;<br/>objXMLHTTP.Send<br/>objJpeg.OpenBinary&#40;objXMLHTTP.ResponseBody&#41;<br/>objJpeg.Save &quot;d&#58;\webs\domain1.com\wwwroot\cachedImage.jpg&quot;<br/>objJpeg.SendBinary<br/>Set objXMLHTTP = Nothing<br/>Response.End<br/>%&gt;</pre></div></p><p>Note that the "cacheFileIsExpired" function in the first code example is the same that is used in my <a href="http://newsite.openhosting.co.uk/articles/serverside/5853/" title="Data caching using text files">Data caching using text files</a> article.</p>]]></description>
<pubDate>Thu, 19 Mar 2006 01:27:51 GMT</pubDate>
</item>
<item>
<title>Data Caching Using Text Files in ASP</title>
<link>http://www.openhosting.co.uk/articles/serverside/5853/</link>
<description><![CDATA[<p><span style="display:none;"><strong>Data Caching Using Text Files in ASP</strong></span></p><p>If your web application regularly performs complex database queries, you might be able to improve performance by caching the results.</p><p><strong>Introduction</strong><br/>There are numerous ways of speeding up your web applications, and improving data access efficiency is one of them. A method of increasing data access efficiency is to cache frequently accessed data. This would be a list of forum posts, populating a drop down menu with country names, or performing complex cross-table queries in large databases. There are three main ways of caching data. In this article I document the third method.</p><p><em>a) Caching within the database.</em><br/>More advanced database servers such as MySQL and SQL Server (not Access) support indexing. Frequenty run queries are effectively cached within the database itself. However this isn't always easy to implement.</p><p><em>b) Caching in the web server memory.</em><br/>Data can be stored in the web server session or application memory state. This is great for small, temporary pieces of data such as a username login session, but for larger datasets you may be putting the shared web server under strain.</p><p><em>c) Cache to a file.</em><br/>Once your data is selected, you save its contents, including HTML formatting, to a text file. This can simply be written back to the browser at runtime, bypassing the database query completely.</p><p><strong>The concept</strong><br/>Firstly we need to decide what type of file we are going to store our cached data in. In an ideal world we would use XML, or some type of CSV database, just storing the raw data. However this data would still require iterations and HTML formatting. My own method is to query the database once, format into HTML once, save it as a text file, and write it back to the browser when required. To do so we need three functions: to read our cached file, to check if our cached version has expired, and to create a new refreshed cached file.</p><p>The first function is used to check whether our cached data has expired or not. It would be rare to never want your cache to be updated, so this function accepts parameters to allow you to decide how often the cache should be updated (a value and a time unit). The first parameter is the name of the cache file you are checking, for example "latestPosts.txt". The other two parameters determine the cache expiry time, for example "2" and "hours". <br/><div class="bb-code-container"><pre class="bb-code">Function cacheFileIsExpired&#40;strFileName, cacheInterval, cacheIntervalUnit&#41;<br/>If cacheInterval = 0 Then<br/>  cacheFileIsExpired = True<br/>  Exit Function<br/>End If</p><p>On Error Resume Next<br/>Dim cacheFSO &#58; Set cacheFSO = CreateObject&#40;&quot;Scripting.FileSystemObject&quot;&#41;<br/>Dim cacheFile &#58; Set cacheFile = cacheFSO.GetFile&#40;&quot;d&#58;\webs\mydomain.com\cache\&quot; &amp; strFileName&#41;<br/>Dim strDate &#58; strDate = cacheFile.DateLastModified<br/>Set objFile = Nothing</p><p>Select Case cacheIntervalUnit<br/>  Case &quot;minutes&quot; &#58; strUnit = &quot;n&quot; <br/>  Case &quot;hours&quot; &#58; strUnit = &quot;h&quot; <br/>  Case &quot;days&quot; &#58; strUnit = &quot;d&quot;<br/>End Select</p><p>cacheFileIsExpired = &#40;DateDiff&#40;strUnit,CDate&#40;strDate&#41;, Now&#40;&#41;&#41; &gt; cacheInterval&#41;</p><p>If err.Number &lt;&gt; 0 Then<br/>  cacheFileIsExpired = True<br/>End If</p><p>Set cacheFile = Nothing<br/>Set cacheFSO = Nothing<br/>End Function</pre></div><br/>If the cached file has expired, or doesn't exist, the function returns True. If so, we need to refresh our cache.</p><p>The following function accepts two parameters. The first is the cache file we are updating ("latestPosts.txt"), and the second is the complete contents of the cache. For example, if we want to cache a list of the ten latest forum posts, we would query the database, loop through records, format with HTML and add the contents to strText. The function itself merely creates a new text file.<br/><div class="bb-code-container"><pre class="bb-code">Function writeCachedFile&#40;strFileName, strText&#41;<br/>  Dim cacheFSO &#58; Set cacheFSO = CreateObject&#40;&quot;Scripting.FileSystemObject&quot;&#41;<br/>  Dim cacheFile &#58; Set cacheFile = cacheFSO.CreateTextFile&#40;&quot;d&#58;\webs\mydomain.com\cache\&quot; &amp; strFileName, True, True&#41;<br/>  cacheFile.Write&#40;strText&#41;<br/>  cacheFile.Close <br/>  Set cacheFile = Nothing<br/>  Set cacheFSO = Nothing<br/>  writeCachedFile = strText<br/>End Function</pre></div><br/>The final function is similar to the one above. However instead of creating a new text file, we pass the function the name of the cache file we want to retrieve, and it returns its contents.<br/><div class="bb-code-container"><pre class="bb-code">Function getCachedFile&#40;strFileName&#41;<br/>  Dim cacheFSO &#58; Set cacheFSO = CreateObject&#40;&quot;Scripting.FileSystemObject&quot;&#41;<br/>  Dim cacheFile &#58; Set cacheFile = cacheFSO.OpenTextFile&#40;&quot;d&#58;\webs\mydomain.com\cache\&quot; &amp; strFileName,1,False,-1&#41;<br/>  getCachedFile = cacheFile.ReadAll<br/>  Set cacheFile = Nothing<br/>  Set cacheFSO = Nothing<br/>End Function</pre></div></p><p><strong>Putting it all together</strong><br/>Let's run through an example of how to use these functions together. Keeping with the example above of compiling a list of the top 10 forum posts, let's cache the results. This example assumes you have saved the above three functions into a new ASP file named "caching.asp", which we will call as an include file in the following example.<br/><div class="bb-code-container"><pre class="bb-code">&lt;!--#include file=&quot;caching.asp&quot;--&gt;<br/>&lt;%</p><p>If cacheFileIsExpired&#40;&quot;latestPosts.txt&quot;, 2, &quot;hours&quot;&#41; Then<br/>  Dim objConn &#58; Set objConn = Server.CreateObject&#40;&quot;ADODB.Connection&quot;&#41;<br/>  With objConn<br/>    .Provider = &quot;Microsoft.Jet.OLEDB.4.0&quot; <br/>    .Open &quot;d&#58;\webs\mydomain.com\db\forum.mdb&quot; <br/>  End With</p><p>  Dim objPosts &#58; Set objPosts = Server.CreateObject&#40;&quot;ADODB.Recordset&quot;&#41;<br/>  objPosts.Open &quot;Select Top 10 * From tblPosts&quot;, 0, 1, objConn</p><p>  Do Until objPosts.EOF<br/>    strPosts = strPosts &amp; &quot;&lt;li&gt;&quot; &amp; objPosts&#40;&quot;PostTitle&quot;&#41; &amp; &quot;&lt;/li&gt;&quot;<br/>    objPosts.MoveNext<br/>  Loop</p><p>  strPosts = &quot;&lt;ul&gt;&quot; &amp; strPosts &amp; &quot;&lt;/ul&gt;&quot;</p><p>  objPosts.Close<br/>  Set objPosts = Nothing<br/>  objConn.Close<br/>  Set objConn = Nothing</p><p>  Response.Write&#40;writeCachedFile&#40;&quot;latestPosts.txt&quot;, strPosts&#41;&#41;<br/>Else<br/>  Response.Write&#40;getCachedFile&#40;&quot;latestPosts.txt&quot;&#41;&#41;<br/>End If<br/>%&gt;</pre></div><br/>The first function call checks whether the cache is more than 2 hours old. If not, we don't touch the database at all, and simply write the contents of the cache text file. If the cache needs updating, we query the database and create the new cached file.</p><p>This is a relatively simple concept, and I hope these functions make it easier for you to start caching your data right away! I've found that it massively increases page speeds often by a matter of several full seconds (for particularly data-heavy applications). Give it a go :-)</p>]]></description>
<pubDate>Thu, 19 Mar 2006 00:49:08 GMT</pubDate>
</item>
<item>
<title>Search Engine Optimisation (SEO) Basics</title>
<link>http://www.openhosting.co.uk/articles/seo/5838/</link>
<description><![CDATA[<p><span style="display:none;"><strong>Search Engine Optimisation (SEO) Basics</strong></span></p><p>A brief skip through the first things you should check when you first start to optimise your site. </p><p>Optimising your website for the search engines need not be a difficult task. If you have written some decent content, and use your HTML markup sensibly, then you've already done most of the hard work. In my view, there are three main parts of ?optimising? your pages. </p><p><strong>1. Getting your pages into the search engines</strong><br/>This basically means that you need to have your web pages live on the Web where the search engines can see them. Two ways of getting your pages indexed/crawled by the engines are:</p><p>a) Using the specific submission tool for each engine (<a href="http://www.google.com/addurl/?continue=/addurl" title="here's Google's">here's Google's</a>)<br/>b) Have other sites link to yours, so your site is picked up naturally by the search engine spiders </p><p><strong>2. Optimising your pages for efficient performance</strong><br/>Your links need to be crawlable by search engine spiders (don't hide links in JavaScript or Flash), and your HTML markup should be as clean as possible. However just being in the search engine index won't generate high traffic. You need to optimise your content for specific keywords. I'm not going to go into keyword optimisation here, since it's a very broad topic covered well elsewhere: <br/><ul><li><a href="http://www.websitemarketingplan.com/Whalen/KeywordTargeting.htm" title="Choosing Keywords That Attract A Target Audience">Choosing Keywords That Attract A Target Audience</a><br/><li><a href="http://www.seochat.com/c/b/Choosing-Keywords-Help/" title="Choosing Keywords Help, Choosing Search Keywords">Choosing Keywords Help, Choosing Search Keywords</a></ul><br/>Once you've chosen your keywords, you need to consider keyword placement on your page. Generally speaking, you should aim to get your keywords appearing as near to the top of your page as you can. This means they should appear in your &lt;title&gt; tag, your &lt;meta&gt; keywords tag, and your page content. The following list is a selection of well-documented tips for optimising for specific keywords.</p><p><em>a) Using the &lt;title&gt; tag</em><br/>If your site content is created from a content management system or e-commerce package, you may find that every page in your site has the same Title. You're wasting valuable real estate. Ideally your chosen keywords should be as close to the beginning of the title as possible. It's fine to include things like your company name in the title, but look at the following example and decide which is the more appropriate. <br/><div class="bb-code-container"><pre class="bb-code">Nick &amp; Son's Art Gallery</pre></div><br/><div class="bb-code-container"><pre class="bb-code">Rare Illustrations, Paintings and Prints from Nick &amp; Son's Art Gallery, London</pre></div><br/><em>b) &lt;meta&gt; tags</em><br/>Meta tags are rarely used by the major search engines now. They do not need to rely on these tags to describe your page content. However it is still good practice to include these, since there are bound to be indexing systems looking at your pages that *do* like to munch on meta tag content. <br/><ul><li><a href="http://searchenginewatch.com/webmasters/article.php/2167931" title="How To Use HTML Meta Tags">How To Use HTML Meta Tags</a></ul><br/><em>c) Heading tags</em><br/>Heading tags are your friend, and as such they are not to be abused! Putting keywords in your heading tags gives them more prominence on a page, but use them wisely. The practice of <a href="http://en.wikipedia.org/wiki/Keyword_stuffing" title="keyword stuffing">keyword stuffing</a> can reap penalties and banning from the search engine Gods. As Mike Pepper points out ("Site and Page Structure"), your heading tags should reflect the organic structure of content on your document.</p><p><em>d) Efficient linking techniques</em><br/>Search engines can only index your pages if there are links to the pages themselves. Text links (hyperlinks) are arguably the best. However, the simple link can be a powerful SEO tool, for the actual clickable text of a link can have a bearing on the relevant of a web page. The concept is simple. Search engines (Google for one) find all of the links to a web page, and evaluate the clickable hyperlink text of each of these links. If there is a consistent keyword featuring in the links, then it will push this page higher up the results for that keyword. Conclusive evidence of this concept comes in the form of the practice known as <a href="http://en.wikipedia.org/wiki/Google_bomb" title="Google Bombing">Google Bombing</a>. As such, when forging links from other websites to your own, you should try and get your keywords included in the links too. </p><p><strong>3. Patience, monitoring and updating</strong><br/>Making changes to your pages will not have an immediate impact on your site's performance. It can take weeks, even months, for the fruits of your labour to ripen and spread through all of the search engines. Thus it is vital that you monitor your site traffic; where people come from, what links are they clicking on, what they're looking for; and update your site accordingly.</p><p>Search engines are constantly evolving and changing the way they rank our sites. Working your way to the top for a specific keyword isn't difficult, but one change in the search engine algorithm, and you can be knocked off the top spot without warning. It's a good idea to keep tabs on industry sites and resources/articles for the latest updates.</p><p><strong>Useful further reading</strong><br/><ul><li><a href="http://www.seowebsitepromotion.com/basic_seo.htm" title="Search Engine Optimisation - Getting into the Search Engines">Search Engine Optimisation - Getting into the Search Engines</a><br/><li><a href="http://www.search-this.com" title="http://www.search-this.com">http://www.search-this.com</a><br/><li><a href="http://www.seobook.com" title="http://www.seobook.com">http://www.seobook.com</a><br/><li><a href="http://www.seochat.com" title="http://www.seochat.com">http://www.seochat.com</a><br/><li><a href="http://www.google.com/webmasters/seo.html" title="http://www.google.com/webmasters/seo.html">http://www.google.com/webmasters/seo.html</a></ul></p>]]></description>
<pubDate>Sat, 14 Mar 2006 19:09:58 GMT</pubDate>
</item>
<item>
<title>More Than One Link Style (CSS)</title>
<link>http://www.openhosting.co.uk/articles/webdev/5816/</link>
<description><![CDATA[<p><span style="display:none;"><strong>CSS: More Than One Link Style</strong></span></p><p>Using CSS (Cascading Style Sheets) you can have more than one style of link on web page. This is handy if you want, for example, the links on a menu to look one way and the links in the text to look another.</p><p>You can set the default links on a page by adding the following to the<br/>&lt;head&gt;  tag of your page:</p><p><div class="bb-code-container"><pre class="bb-code">&lt;style type=&quot;text/css&quot;&gt;<br/>a&#58;link       &#123;color&#58; red;&#125;<br/>a&#58;visited    &#123;color&#58; red;&#125;<br/>a&#58;hover      &#123;color&#58; green;&#125;<br/>a&#58;active     &#123;color&#58; red;&#125;<br/>&lt;/style&gt;</pre></div><br/>Note: The different link states must be defined in the above order to work.</p><p>Next you can define alternative styles for other links, for example those in a menu. Add these to the others between the &lt;style&gt;  tags.</p><p><div class="bb-code-container"><pre class="bb-code">.themenu a&#58;link       &#123;color&#58; orange;&#125;<br/>.themenu a&#58;visited    &#123;color&#58; blue;&#125;<br/>.themenu a&#58;hover      &#123;color&#58; orange;&#125;<br/>.themenu a&#58;active     &#123;color&#58; orange;&#125;</pre></div></p><p>.themenu is the class name we are going to give the links to tell them to use that style not the default one.</p><p>The html code for the link looks like this:</p><p><div class="bb-code-container"><pre class="bb-code">&lt;span class=&quot;themenu&quot;&gt;&lt;a href=&quot;#&quot;&gt;Example Link&lt;/a&gt;&lt;/span&gt;</pre></div></p><p>All the links between the span tags will have the same style. </p><p>To add another style of link add the CSS again with a different class name.</p>]]></description>
<pubDate>Mon, 09 Mar 2006 15:37:18 GMT</pubDate>
</item>
<item>
<title>Adding Captions to Images (CSS)</title>
<link>http://www.openhosting.co.uk/articles/webdev/5815/</link>
<description><![CDATA[<p><span style="display:none;"><strong>Adding Captions to Images</strong></span></p><p>CSS can be used to add captions below (or above) your images without having to use tables.</p><p>Lets start by adding an image to the page that we want to caption.</p><p><div class="bb-code-container"><pre class="bb-code">&lt;img src=&quot;image.jpg&quot; width=&quot;220&quot; height=&quot;172&quot; alt=&quot;Rabbit&quot;&gt;</pre></div></p><p>The next step is to wrap this in a div, which will contain the caption and the image. The div is given the class 'rabbitbox' and the image the class 'rabbitimage' so we can style them seperately.</p><p><div class="bb-code-container"><pre class="bb-code">&lt;div class=&quot;rabbitbox&quot;&gt;<br/>&lt;img src=&quot;image.jpg&quot; width=&quot;220&quot; height=&quot;172&quot; alt=&quot;Rabbit&quot; class=&quot;rabbitimage&quot;&gt;<br/>This is a dwarf lop rabbit called Jasper. He is 6 years old and likes to eat apples.<br/>&lt;/div&gt;</pre></div></p><p>The first thing we are going to do is tell the div how wide we want it to be, if we don't specify a width it with stretch across the full page to accomodate the text. <br/>This code goes in the &lt;head&gt; section of your page or in a seperate stylesheet if you have one.</p><p><div class="bb-code-container"><pre class="bb-code">&lt;style type=&quot;text/css&quot;&gt;<br/>.rabbitbox &#123;width&#58;220px;&#125;<br/>&lt;/style&gt;</pre></div></p><p>Already we have the appearance of an image with a caption. The captioned image can be aligned to the left or right with the remaining page text flowing around it or placed on the page with the body text wrapping above and below. <br/>If the image is to have text wrapped around it we'll add a margin on the appropriate side so there is a gap between the image and the text.</p><p><div class="bb-code-container"><pre class="bb-code">To align right add&#58;<br/>.rabbitbox &#123;width&#58;220px;float&#58;right;margin-left&#58;10px;&#125;</p><p>To align left add&#58;<br/>.rabbitbox &#123;width&#58;220px;float&#58;left;margin-right&#58;10px;&#125;</p><p>To wrap text top and bottom&#58;<br/>.rabbitbox &#123;width&#58;220px;clear&#58;both;&#125;</pre></div><br/>We can add abit more style to our captioned image, for example, styling the text and adding borders. To style the text add properties to the 'rabbitbox' class. The example below makes the text italic, smaller than the default, aligned right and uses the font family arial.</p><p><div class="bb-code-container"><pre class="bb-code">.rabbitbox &#123;font-style&#58;italic;font-family&#58;arial;font-size&#58;smaller;text-align&#58;right;&#125;</pre></div></p><p>Borders can be added either to the image or the div around both the image and the caption.</p><p><div class="bb-code-container"><pre class="bb-code">To add a border to the image add&#58;<br/>.rabbitimage &#123;border&#58;1px solid black;&#125;</p><p>To add a border to the div add&#58;<br/>.rabbitbox &#123;border&#58;1px solid black;&#125;</p><p>To add a border to one side&#58;<br/>.rabbitbox &#123;border-right&#58;1px solid black;&#125;</pre></div></p><p>Putting it all together you should end up with something like this...</p><p><div class="bb-code-container"><pre class="bb-code">&lt;style type=text/css&gt;<br/>.rabbitbox &#123;width&#58;220px;width&#58;220px;float&#58;right;margin-left&#58;10px;<br/>font-style&#58;italic;font-family&#58;arial;font-size&#58;smaller;text-align&#58;right;&#125;<br/>.rabbitimage &#123;border&#58;1px solid green;&#125;<br/>&lt;/style&gt;</pre></div></p>]]></description>
<pubDate>Mon, 09 Mar 2006 15:32:34 GMT</pubDate>
</item>
<item>
<title>Taming Dates in ASP</title>
<link>http://www.openhosting.co.uk/articles/serverside/5811/</link>
<description><![CDATA[<p><span style="display:none;"><strong>Taming Dates in ASP</strong></span></p><p>A function to save dates into a generic format, regardless of database type or server localised settings.</p><p><strong>Introduction</strong></p><p>When you?re using dates in calculations in ASP, or saving them to Access or SQL databases, you can often encounter very bizarre and illogical results. Don?t use messy Session.LCID hacks. Here are some reusable functions which should solve all of your date problems forever...</p><p>I have found that the best way to achieve uniform results when saving and retrieving dates to and from a database, is to store a date as an integer (number) value. The obvious way is to store in the following format:</p><p><div class="bb-code-container"><pre class="bb-code">yyyymmddhhmmss</pre></div></p><p>Therefore the latest date is always the largest number (useful for ordering and selecting newest records).</p><p><strong>How it's done</strong></p><p>Here's the function I use to create a number in the above format. Make sure you pass the full current date AND time (Now()) and not just the current date (Date()):<br/><div class="bb-code-container"><pre class="bb-code">Function saveDate&#40;theDate&#41;<br/>If isNull&#40;theDate&#41; or CStr&#40;theDate&#41; = &quot;&quot; Then<br/>saveDate = &quot;&quot;<br/>Else<br/>strMonth = Month&#40;theDate&#41;<br/>strDay = Day&#40;theDate&#41;<br/>strHour = Hour&#40;theDate&#41;<br/>strMinute = Minute&#40;theDate&#41;<br/>strSecond = Second&#40;theDate&#41;<br/>If Len&#40;strMonth&#41; = 1 Then strMonth = &quot;0&quot; &amp; strMonth End If<br/>If Len&#40;strDay&#41; = 1 Then strDay = &quot;0&quot; &amp; strDay End If<br/>If Len&#40;strHour&#41; = 1 Then strHour = &quot;0&quot; &amp; strHour End If<br/>If Len&#40;strMinute&#41; = 1 Then strMinute = &quot;0&quot; &amp; strMinute End If<br/>If Len&#40;strSecond&#41; = 1 Then strSecond = &quot;0&quot; &amp; strSecond End If</p><p>If IsDate&#40;theDate&#41; Then<br/>saveDate = Year&#40;theDate&#41; &amp; strMonth &amp; strDay &amp; strHour &amp; strMinute &amp; strSecond<br/>End If<br/>End If<br/>End Function</pre></div></p><p>When it comes to display the date on a page I pass the retrieved database integer and a pre-defined format type to a "formatDate" function:<br/><div class="bb-code-container"><pre class="bb-code">Function formatDate&#40;theDate, displayType&#41;<br/>If isDate&#40;theDate&#41; Then<br/>returnDate = True<br/>strYear = Year&#40;theDate&#41;<br/>strMonth = Month&#40;theDate&#41;<br/>strDay = Day&#40;theDate&#41;<br/>strHour = Hour&#40;theDate&#41;<br/>strMinute = Minute&#40;theDate&#41;<br/>strSecond = Second&#40;theDate&#41;<br/>If Len&#40;strMonth&#41; = 1 Then strMonth = &quot;0&quot; &amp; strMonth End If<br/>If Len&#40;strDay&#41; = 1 Then strDay = &quot;0&quot; &amp; strDay End If<br/>If Len&#40;strHour&#41; = 1 Then strHour = &quot;0&quot; &amp; strHour End If<br/>If Len&#40;strMinute&#41; = 1 Then strMinute = &quot;0&quot; &amp; strMinute End If<br/>If Len&#40;strSecond&#41; = 1 Then strSecond = &quot;0&quot; &amp; strSecond End If<br/>ElseIf len&#40;theDate&#41; = 14 Then<br/>returnDate = True<br/>strYear = Left&#40;thedate,4&#41;<br/>strMonth = Mid&#40;theDate,5,2&#41;<br/>strDay = Mid&#40;theDate,7,2&#41;<br/>strHour = Mid&#40;theDate,9,2&#41;<br/>strMinute = Mid&#40;theDate,11,2&#41;<br/>strSecond = Mid&#40;theDate,13,2&#41;<br/>Else<br/>returnDate = False<br/>End If</p><p>If returnDate Then<br/>Select Case displayType<br/>Case 0<br/>If Left&#40;strDay,1&#41; = &quot;0&quot; Then strDay = Right&#40;strDay,1&#41; End If<br/>formatDate = WeekDayName&#40;WeekDay&#40;strDay&#41;&#41; &amp; &quot; &quot; &amp; strDay &amp; &quot;&lt;sup&gt;&quot; &amp; formatDateAbbrev&#40;strDay&#41; &amp; &quot;&lt;/sup&gt; &quot; &amp; MonthName&#40;strMonth&#41; &amp; &quot;, &quot; &amp; strYear<br/>Case 1<br/>formatDate = strDay &amp; &quot;/&quot; &amp; strMonth &amp; &quot;/&quot; &amp; strYear<br/>Case 2<br/>formatDate = strDay &amp; &quot;/&quot; &amp; strMonth &amp; &quot;/&quot; &amp; strYear &amp; &quot; &quot; &amp; strHour &amp; &quot;&#58;&quot; &amp; strMinute<br/>Case 3<br/>formatDate = strHour &amp; &quot;&#58;&quot; &amp; strMinute<br/>End select<br/>End If<br/>End Function</pre></div></p><p>This also makes use of a "formatDateAbbrev" function which returns the "st", "nd", "rd" and "th" day abbreviations:<br/><div class="bb-code-container"><pre class="bb-code">Function formatDateAbbrev&#40;theDay&#41;<br/>If isNull&#40;theDay&#41; Or cstr&#40;theDay&#41; = &quot;&quot; Or Not isNumeric&#40;theDay&#41; Then<br/>formatDateAbbrev = &quot;&quot;<br/>Else<br/>If theDay = 1 Or theDay = 21 Or theDay = 31 Then<br/>formatDateAbbrev = &quot;st&quot;<br/>ElseIf theDay = 2 Or theDay = 22 Then<br/>formatDateAbbrev = &quot;nd&quot;<br/>ElseIf theDay = 3 Or theDay = 23 Then<br/>formatDateAbbrev = &quot;rd&quot;<br/>Else<br/>formatDateAbbrev =&quot;th&quot;<br/>End If<br/>End If<br/>End Function</pre></div></p><p>There is also an optional function which allows me to pull out a specific part of a date when it's needed:<br/><div class="bb-code-container"><pre class="bb-code">Function getDatePart&#40;theDate,thePart&#41;<br/>Select Case thePart<br/>Case &quot;year&quot;<br/>getDatePart = left&#40;thedate,4&#41;<br/>Case &quot;month&quot;<br/>getDatePart = mid&#40;theDate,5,2&#41;<br/>Case &quot;day&quot;<br/>getDatePart = mid&#40;theDate,7,2&#41;<br/>Case &quot;hour&quot;<br/>getDatePart = mid&#40;theDate,9,2&#41;<br/>Case &quot;minute&quot;<br/>getDatePart = mid&#40;theDate,11,2&#41;<br/>Case &quot;second&quot;<br/>getDatePart = mid&#40;theDate,13,2&#41;<br/>End Select<br/>End Function</pre></div></p><p>On the forums <a href="http://forums.openhosting.co.uk/viewtopic.php?p=41126#41126" title="Paul Creedy points out">Paul Creedy points out</a> an alternative method of storing dates in a normal Date field in the format "yyyy/mm/dd" which should also achieve the same results, but I've not tried it. One slight caveat may be compatibility with different database types. When querying an Access database we must surround our dates using a hash (#), e.g.</p><p><div class="bb-code-container"><pre class="bb-code">Select * From tblData Where fldDate = #11/01/2005#</pre></div></p><p>But it is entirely possible that other databases (SQL server, MySQL etc) use different characters for selecting dates in SQL. I'm fairly certain they use uniform syntax for selecing numerical values, so the method described above may be best applied in situations where you may need to change between two or more database types. The best way, of course, is to experiment for yourself ;-)</p>]]></description>
<pubDate>Sun, 08 Mar 2006 15:46:35 GMT</pubDate>
</item>
<item>
<title>Send CDO Email Using an External SMTP Server (ASP)</title>
<link>http://www.openhosting.co.uk/articles/serverside/5810/</link>
<description><![CDATA[<p><span style="display:none;"><strong>Send CDO Email Using an External SMTP Server (ASP)</strong></span></p><p>Sending a CDO email using an external SMTP server using ASP (can also be used to send using an internal SMTP email server).</p><p><strong>Introduction</strong></p><p>It is sometimes advantageous to use an external mail server for the following reasons:<ul><li>You want to keep your web hosting and email separate (not to have all your eggs in one basket) <li>Your host doesn't allow bulk sending of emails (see your host for their definition of bulk) <li>Reducing server load on the web site when the email are being sent <li>If the SMTP server?s IP gets blacklisted, it won?t effect normal web site hosted email.</ul><br/>Before you start you need access to an external SMTP server and have the domain name, username and password given to you by the server host.</p><p>In the following example substitute your details as follows:<br/>Smtp.yoursever.com = your server domain name<br/>Yourusername = the username given to you by the host<br/>Yourpassword = the password given to you by the host</p><p><strong>The Code</strong></p><p>An example of calling the function follows. The function will return and errorcode of &gt;0 if an error was generated. This allows you to trap and deal with the error instead of throwing a server error page at your user.</p><p><div class="bb-code-container"><pre class="bb-code">&lt;%<br/>Dim errorcode<br/>errorcode=SendCDOEmail&#40;&quot;smtp.yourserver.com&quot;,&quot;yourusername&quot;,&quot;yourpassword&quot;,&quot;subject goes here&quot;,&quot;message goes here&quot;,&quot;from email address&quot;,&quot;to email address&quot;,&quot;&quot;,&quot;priority eg 1&quot;,&quot;email format&quot;&#41;<br/>Response.Write&#40;errorcode&#41;<br/>%&gt;</pre></div></p><p>The function itself:<br/><div class="bb-code-container"><pre class="bb-code">&lt;%<br/>Function SendCDOEmail&#40;smtpserver,username,password, strSubject, strBody,strFromAddress,strToAddress,strCc, intpriority, strBodyFormat&#41;<br/>'smtpserver = your smtp server name<br/>'username = the username required for smtp authorisation<br/>'password= the password required for smtp autorisation<br/>'strSubject= subject text<br/>'strBody = body text / html<br/>'strFromAddress= from whom the email will be sent<br/>'strToAddress= who the email will be sent to<br/>'strCc= to who the email will be Cc'd to<br/>'intpriority= importance of email &#40;0=low, 1=normal, 2=high&#41;<br/>'strBodyFormat= either HTML or text<br/>' response.Write&#40;&quot;&lt;b&gt;Debug Code&#58;&lt;/b&gt; subject = &quot; &amp; strSubject &amp; &quot; , Body = &quot;&amp; strBody &amp; &quot;From = &quot; &amp; strFromAddress &amp; &quot; ,To= &quot; &amp; strToAddress &amp; &quot; , cc= &quot; &amp; strCc &amp; &quot; , priority = &quot; &amp; intpriority &amp; &quot; , Body Format = &quot; &amp; strBodyFormat &amp; &quot;&lt;br&gt;&quot; &amp; vbcrlf&#41; 'debug code<br/>'set up connection<br/>' send email using cdosys<br/>dim objCDOSysCon, objCDOSysMail<br/>'Create the e-mail server object<br/>Set objCDOSYSMail = Server.CreateObject&#40;&quot;CDO.Message&quot;&#41;<br/>Set objCDOSYSCon = Server.CreateObject &#40;&quot;CDO.Configuration&quot;&#41;<br/>'Set and update fields properties<br/>With objCDOSYSCon<br/>'Outgoing SMTP server<br/>.Fields&#40;&quot;http&#58;//schemas.microsoft.com/cdo/configuration/smtpserver&quot;&#41; = smtpserver<br/>.Fields&#40;&quot;http&#58;//schemas.microsoft.com/cdo/configuration/smtpauthenticate&quot;&#41; = 1<br/>.Fields&#40;&quot;http&#58;//schemas.microsoft.com/cdo/configuration/sendusername&quot;&#41; = username<br/>.Fields&#40;&quot;http&#58;//schemas.microsoft.com/cdo/configuration/sendpassword&quot;&#41; = password</p><p>.Fields&#40;&quot;http&#58;//schemas.microsoft.com/cdo/configuration/smtpserverport&quot;&#41; = 25<br/>'CDO Port<br/>.Fields&#40;&quot;http&#58;//schemas.microsoft.com/cdo/configuration/sendusing&quot;&#41; = 2<br/>'Timeout<br/>.Fields&#40;&quot;http&#58;//schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout&quot;&#41; = 60<br/>.Fields.Update<br/>End With<br/>'Update the CDOSYS Configuration<br/>Set objCDOSYSMail.Configuration = objCDOSYSCon<br/>'Set and update email properties<br/>With objCDOSYSMail<br/>'0=Low, 1=Normal, 2=High<br/>.Fields&#40;&quot;urn&#58;schemas&#58;httpmail&#58;importance&quot;&#41;.Value = intpriority '0=low, 1=normal, 2=high<br/>.From = strFromAddress 'who the email is from<br/>.To = strToAddress 'who the email is sent to<br/>.Cc = strCc 'who the email is Cc'd to<br/>'The subject of the email<br/>.subject = strSubject<br/>'set the email body format<br/>if ucase&#40;strBodyFormat&#41; =&quot;HTML&quot; then<br/>.HTMLBody = strBody<br/>else<br/>.textbody = strbody<br/>end if<br/>.fields.update<br/>On Error Resume Next<br/>.send<br/>SendCDOEmail=Err<br/>end with<br/>'clean up<br/>set objCDOSysMail = nothing<br/>set objCDOSysCon = nothing<br/>End Function<br/>%&gt;</pre></div></p>]]></description>
<pubDate>Sun, 08 Mar 2006 15:42:59 GMT</pubDate>
</item>
<item>
<title>Adding the Realtime Date to Your ASP Site</title>
<link>http://www.openhosting.co.uk/articles/serverside/5809/</link>
<description><![CDATA[<p><span style="display:none;"><strong>Adding the Realtime Date to Your ASP Site</strong></span></p><p>A small simple line of code in ASP to add the real date to your site, give it that professional look!</p><p>If you wish to have the date on your site, and have not got the time to write all those complicated ASP, VB or PHP statements - then give this a try! Its a simple yet effective line of code to give you site a little professional touch where you want it.</p><p>To use this line write your normal HTML tages such as &amp;</p><p>tages as normal and then just insert this line of code inbetween these tags:<br/><div class="bb-code-container"><pre class="bb-code">&lt;% Response.Write FormatDateTime&#40;date, 1&#41; %&gt;</pre></div></p><p>So, the finshed line should look something like this:<br/><div class="bb-code-container"><pre class="bb-code">&lt;font size=&quot;2&quot; color=BLACK&gt;&lt;b&gt;&lt;% Response.Write FormatDateTime&#40;date, 1&#41; %&gt;&lt;/b&gt;&lt;/font&gt;</pre></div></p><p>Its that easy - give it a try! Just remember, for this to work - you need to save the page with the .asp file extension to make the ASP code work. If you leave it as .HTM or .HTML it will not work.</p>]]></description>
<pubDate>Sun, 08 Mar 2006 15:38:59 GMT</pubDate>
</item>
<item>
<title>Convert Querystrings to Flat Keyword URLs (ASP)</title>
<link>http://www.openhosting.co.uk/articles/serverside/5808/</link>
<description><![CDATA[<p><span style="display:none;"><strong>Convert Querystrings to Flat Keyword URLs (ASP)</strong></span></p><p>Use custom 404 error pages and ASP to create pseudo-URLs for your site, and hopefully help your visitors, and the search engines in the process.</p><p><strong>Introduction</strong></p><p>A lot of search engine optimisation (SEO) techniques can be frowned upon. The method I'm about to describe and develop could be considered as "spamming" if used in the wrong manner, so there is no guarantee made by this application. However, if you interpret this method as a way to make your URLs more logical, memorable and crawlable, you shouldn't have any problems.</p><p><strong>The problem</strong></p><p>Do you run a database-driven website? If so, you may well have ended up with page URLs with a mass of name/value pairs in the querystring.</p><p>Let's take an example of a store selling music CDs. A typical URL may look like this:</p><p>http://www.mydomain.com/product.asp?genreID=12&amp;artistID=34&amp;albumID=56</p><p>Fine, it works, and you may be crawled by the search engines, but the above address shows no logical structure to your online shop. Similarly, do you expect anybody to remember that address?</p><p>Search engines (SEs) *will* crawl these (although there is debate about the use of "ID" in querystrings), however, if you run a search through Google and you spot your search matches in the actual URL of the page, you may well be more likely to click through, as compared to a site linked as an address full of ID values.</p><p><strong>mod_rewrite</strong><br/>Here's where Apache webservers have an advantage over Windows IIS systems. Using Apache, we can use the mod_rewrite module to powerfully manipulate URLs. This module takes the requested URL and translates it into a valid path to a page, passing the querystring data to the page. It does this according to a set of rules the webmaster writes into the .htaccess file.</p><p><strong>ASP to the rescue</strong><br/>Unfortunately we can't use this on a Windows host. It just isn't supported. So, I've come up with some basic ASP logic to attempt to emulate this module. The following is only a basic example of what can be done. It can be adapted and made more powerful to fit your specific site needs.</p><p>So, back to our CD store example, how could we generate a more "friendly" URL. Wouldn't it be more user-friendly (and cooler, right?) to have something like this?</p><p>http://www.mydomain.com/products/rock/dire_straits/money_for_nothing/56</p><p>This way, people looking at the URL instantly know the content of the page, your shop's structure (products &gt; genre &gt; artist &gt; album) therefore giving your URLs a real context. The extra advantage is that your URL now contains keywords, potentially increasing its chances of being picked out in the SERPs (Search Engine Results Pages). Bonus!</p><p>The above example, in literal terms, actually points to the root of a directory named "56", which sits within a directory named "money_for_nothing" which in turn is a sub-directory of "dire_straits", as a sub-directory of "rock", as a sub-directory of "products". Maintaining a structure of this kind would be a nightmare. Imagine browsing your site using FTP, having to click through all of those directories to reach the files! In reality, those directories don't exist. They never will. Here's where the fun begins.</p><p>A request of the suggested URL will flag a "404 Not Found" error, naturally. The structure doesn't exist. So, we can apply some cunning ASP code into our custom 404 page to interpret the request. Here is the code for our custom 404 error page. It needs to be saved as an ASP page.<br/><div class="bb-code-container"><pre class="bb-code">&lt;%<br/>Dim strQuerystring, aParameters<br/>strQuerystring = Mid&#40;Request.ServerVariables&#40;&quot;QUERY_STRING&quot;&#41;,12&#41;<br/>aParameters = Split&#40;strQuerystring,&quot;/&quot;&#41;</p><p>On Error Resume Next</p><p>Server.Transfer&#40;aParameters&#40;1&#41; &amp; &quot;.asp&quot;&#41;</p><p>If Err Then<br/>Response.Status = &quot;404 Not Found&quot;<br/>Server.Transfer&#40;&quot;404message.htm&quot;&#41;<br/>End If<br/>%&gt;</pre></div></p><p>Let's go through it line by line:</p><p><div class="bb-code-container"><pre class="bb-code">Option Explicit</pre></div>This ensures we declare all of our variables explicitly, to prevent renaming. Makes debugging a lot easier, and is good practice.</p><p><div class="bb-code-container"><pre class="bb-code">Dim strQuerystring, aParameters</pre></div>Declares a variable, and an array, which we will be using later.</p><p><div class="bb-code-container"><pre class="bb-code">strQuerystring = Mid&#40;Request.ServerVariables&#40;&quot;QUERY_STRING&quot;&#41;,12&#41;</pre></div>Sets the value of our strQuerystring variable. When a custom 404 error page is requested, it is done so with the requested (not found) URL in the querystring. This line strips the "404;http://" from this string.</p><p><div class="bb-code-container"><pre class="bb-code">aParameters = Split&#40;strQuerystring,&quot;/&quot;&#41;</pre></div>Creates an array of each value found in the querystring. So, using our example, the first value of the array is "mydomain.com". The second is "products", and so on.</p><p><div class="bb-code-container"><pre class="bb-code">On Error Resume Next</pre></div>Activates error handling...</p><p><div class="bb-code-container"><pre class="bb-code">Server.Transfer&#40;aParameters&#40;1&#41; &amp; &quot;.asp&quot;&#41;</pre></div>Tries calling our products page. The Server.Transfer page effectively processes the requested page and places the results into the page it was requested from. It's almost like a 'dynamic server side include'. The benefits of this are that they can use the POST or GET data submitted to the parent page (in this case, the custom 404 page).</p><p>In this case, we attempt to load an ASP page. The path of this page is created by the second value in the aParameters array. For this reason, we pass "products" in the example URL. This way, it processes "products.asp". If your site also has an Articles section, you could pass "articles" in the URL and it will process "articles.asp".<br/><div class="bb-code-container"><pre class="bb-code">If Err Then<br/>Response.Status = &quot;404 Not Found&quot;<br/>Server.Transfer&#40;&quot;404message.htm&quot;&#41;<br/>End If</pre></div></p><p>If an error is flagged, i.e. the Server.Transfer fails, load in our '404 message' HTML page. This page usually displays an apology for the page not being found.</p><p>Phew!</p><p>So, we now have a custom 404 page set up. If the first Server.Transfer works (i.e. we are using it to 'mask our URL), the corresponding ASP page is called. If it is a genuine 404 error, then the visitor is still given a 404 page by means of including 404message.htm.</p><p><strong>What about the rest of the querystring?</strong><br/>So far we have only looked at the first part of the querystring. More importantly, the very first querystring value ("products") needs to be the same name as our ASP page which does all of the database processing and so on.</p><p>So how do we pass a value to this page so it can select the desired record?</p><p>For this, we need to make a slight adaptation to our products page.</p><p><strong>Product record page</strong><br/>Our normal product record page would have taken the "productID" from the querystring, and selected this record from the database.</p><p>Now we're using Server.Transfer, this ID is no longer passed. If you look at our URL example again, you'll see the very last 'querystring' value is the albumID ("56").</p><p>As I said earlier, using Server.Transfer means that our "products.asp" loaded into our 404 custom error page inherits the Form and Querystring values. So by putting some code into products.asp we can grab this ID value.</p><p>It is here I need to stress this example was created as a generic handler page, designed to pass ONE value to a page. This one value must always be the LAST value in the querystring. Make sense? Here's an example.</p><p>http://www.mydomain.com/products/56</p><p>http://www.mydomain.com/products/1/2/3/4/56</p><p>http://www.mydomain.com/products/rock/dire_straits/money_for_nothing/56</p><p>In all instances, only the "products" and "56" values are important. Everything else is discarded.</p><p>Therefore our products.asp page only needs to grab this final "56". By doing so, all we have to do is ake the querystring again, create an array using each "/" as the delimeter as before, and take the final value.<br/><div class="bb-code-container"><pre class="bb-code">&lt;%<br/>Option Explicit<br/>Dim strQuerystring, aParameters<br/>strQuerystring = Mid&#40;Request.ServerVariables&#40;&quot;QUERY_STRING&quot;&#41;,12&#41;<br/>aParameters = Split&#40;strQuerystring,&quot;/&quot;&#41;</p><p>strFinalValue = aParameters&#40;Ubound&#40;aParameters&#41;&#41;</p><p>If strFinalValue = &quot;&quot; Then<br/>strFinalValue = aParameters&#40;Ubound&#40;aParameters&#41;-1&#41;<br/>End If<br/>%&gt;</pre></div></p><p>The above should go into the top of products.asp. It selects the final value in our querystring. If a trailing "/" is found, it merely back-steps to obtain the previous, intended value.</p><p>Our SQL to select the product should now use "strFinalValue" instead of "Request.Querystring("productID")" as before.</p><p><strong>Conclusions</strong><br/>Obviously there are some advantages, and indeed possible disadvantages in using this method.<br/><ul><li>Pack your URLs full of keywords<br/><li>It's been suggested that .htm pages are prefered to .asp extensions. This way, links can be .htm but actually point to an ASP file.</p><p><li>It can get very confusing. Almost all links won't actually point to 'real' URLs, so any off-line link checkers or WYSIWYG editors for links will be useless.<br/><li>Is there an extra server load using this method?<br/><li>Your logs will be filled with 404 errors, and may not give nice statistics for real page impressions. I've not had the time to see if this is true or not.</ul></p><p>A point worthy of note is that because you're creating a pseudo-URL, your browser will have a hard time locating external files, for example relative paths to images. However, including the BASE tag in your HTML will mean you can keep all of your pages the same, leaving the relative links the same.</p><p><div class="bb-code-container"><pre class="bb-code">&lt;base href=&quot;http&#58;//www.mydomain.com&quot;&gt;</pre></div></p><p>This means that although your page may look as if it is several layers deep through your structure, your paths can still be relative in the HTML. Sorted.</p>]]></description>
<pubDate>Sun, 08 Mar 2006 14:51:52 GMT</pubDate>
</item>
<item>
<title>Include Files - Write Once, Use Many Times (ASP)</title>
<link>http://www.openhosting.co.uk/articles/serverside/5807/</link>
<description><![CDATA[<p><span style="display:none;"><strong>Include Files - Write Once, Use Many Times</strong></span></p><p>As you may know, it is possible in ASP to include one file within another. There are two ways to do that - one of which has potential pitfalls.</p><p>As you may know, it is possible in ASP to include one file within another. The benefit of doing this is that you can put common code routines into a single file and then include that file in any other code files that need to use it. This means that you can have a central code library and you don't have to keep replicating subs and functions all over the place (in the different files that need to use them).</p><p>Imagine I've now written all my common string handling routines into StringRoutines.asp and placed that file in a special folder (off the web root) called 'common'. I would typically do this because there are other common files I might want to write later (such as EmailRoutines.asp, and DatabaseRoutines.asp etc). But for now I just have StringRoutines.asp - so how do I make use of it from within other ASP files such as the default.asp file for example?</p><p>Very simple - you place a statement in the default.asp file that tells IIS to include StringRoutines.asp, and then later on down in default.asp, you can just call any of the subs and functions that are contained in StringRoutines.asp. Note: Although I said 'later on down', you can place the call to a sub/function either above or below the include statement. But you will help IIS compile the page faster if you make sure that subs and functions that are going to be called by other code appear in the file higher up from where they are called.</p><p>There are two different include statements that you can use. They are slightly different from one another, but one of them has potential pitfalls.</p><p>First, there is this way...<br/><div class="bb-code-container"><pre class="bb-code">&lt;!--#Include File =&quot;common\StringRoutines.asp&quot;--&gt;</pre></div></p><p>IIS will look for a folder called 'common' on the same level as the script it is about to execute (in this case default.asp) and look for StringRoutines.asp and slap the whole contents of that file right where you put the include statement (the actual physical file is not affected - just IIS's temporary copy). At this point IIS has a big text file with all the code in it, and it proceeds to compile it and send the results to the browser.</p><p>This method is OK until you come to wanting to include the file in an ASP page that is inside another folder off the root of the web. Let's say, the ListGuests.asp file in the 'guestbook' folder for example. You will have to remember to change the path to the include such that IIS will find it, otherwise you will get an error.</p><p>It would have to look like this...<br/><div class="bb-code-container"><pre class="bb-code">&lt;!--#Include File =&quot;..\common\StringRoutines.asp&quot;--&gt;</pre></div></p><p>But even if you do remember to set the path correctly, you will soon find that moving an ASP page that uses include files will stop working unless you change the path in the above statement.</p><p>Another downside is that if your scripts are executing on a host's server that has the 'no parent paths' security policy switched on (the default on IIS 6) - your include statements that use '..' to access the parent path of the current folder will not work at all.</p><p>The answer is to employ the alternative version of the statement that uses the keyword 'Virtual'...<br/><div class="bb-code-container"><pre class="bb-code">&lt;!--#Include Virtual =&quot;common\routines.asp&quot;--&gt;</pre></div></p><p>This will work no matter where your script is that contains the statement because you are instructing IIS where the common folder is relative to the web root.</p><p>It really is worth organising your code in this way, because as your site becomes bigger, the use of 'include files' will help you manage it more efficiently and with less possibility of error on your part.</p>]]></description>
<pubDate>Sun, 08 Mar 2006 14:45:47 GMT</pubDate>
</item>
<item>
<title>Highlighting Search Keywords in ASP</title>
<link>http://www.openhosting.co.uk/articles/serverside/5806/</link>
<description><![CDATA[<p><span style="display:none;"><strong>Highlighting Search Keywords in ASP</strong></span></p><p>Highlight occurance of a string within another string. Very useful for displaying matching keywords in database search results.</p><p>After creating a basic site search I wanted to highlight the occurance of the search keywords in the results displayed.</p><p>The normal Replace function in ASP is not sufficient because it is case sensitive and is really unsatisfactory. I've adapted some code into a reusable function that can be used on a search page.<br/><div class="bb-code-container"><pre class="bb-code">&lt;%<br/>Function stringReplace&#40;strSearchWithin,strSearchFor&#41;</p><p>If Len&#40;strSearchWithin&#41; &gt; 0 And Len&#40;strSearchFor&#41; &gt; 0 Then<br/>intStart = 1<br/>intFound = InStr&#40;intStart,strSearchWithin,strSearchFor,1&#41;</p><p>Do While intFound &gt; 0<br/>strReplaced = strReplaced &amp; Mid&#40;strSearchWithin,intStart,intFound - intStart&#41; &amp; &quot;&lt;span style='background-color&#58;yellow'&gt;&quot; &amp; mid&#40;strSearchWithin,intFound,len&#40;strSearchFor&#41;&#41; &amp; &quot;&lt;/span&gt;&quot;<br/>intStart = intFound + len&#40;strSearchFor&#41;<br/>intFound = InStr&#40;intStart,strSearchWithin,strSearchFor,1&#41;<br/>Loop</p><p>stringReplace = strReplaced &amp; Mid&#40;strSearchWithin,intStart&#41;<br/>Else<br/>stringReplace = strSearchWithin<br/>End If</p><p>End Function<br/>%&gt;</pre></div></p><p>The matching string to be highlighted is passed to the page using a querystring parameter "search", for example:</p><p><div class="bb-code-container"><pre class="bb-code">searchPage.asp?search=word</pre></div></p><p>The function is therefore called using the following syntax.<br/><div class="bb-code-container"><pre class="bb-code">&lt;%<br/>Response.Write stringReplace&#40;&quot;This is a very useful script for displaying highlighted search keywords.&quot;,Request.QueryString&#40;&quot;search&quot;&#41;&#41;<br/>%&gt;</pre></div></p>]]></description>
<pubDate>Sun, 08 Mar 2006 14:43:40 GMT</pubDate>
</item>
</channel></rss>
