Friday, December 23, 2005

GROUP BY techniques

Useful GROUP BY techniques (source: Jeff's Blog (SQLTeam hosted)) for SQL Server developers. Rather than grouping unneccesarily columns, use a derived table. i.e. (SELECT ... FROM ... WHERE ... GROUP BY ...) AggregateTableName. Plus don't group expressions, but the columns that make up the expression.


Tags: , ,

Tuesday, December 20, 2005

PHP Email Encode

Function to encode an email address to help protect against spamming.

function mailto_link($email)
{
 $encoded = bin2hex($email);
 $encoded = chunk_split($encoded, 2, '%');
 $encoded = '%'.substr($encoded, 0, strlen($encoded) - 1);
 $htmlencoded = substr(chunk_split(bin2hex(" $email"), 2, ";&#x"), 3,-3);
 return "<a href=\"mailto:$encoded\">$htmlencoded</a>";
}

Takes an email address as the parameter and outputs an encoded mailto link. You could use this while looping through email records in a database for example.

<?php echo mailto_link("user@example.com"); ?>

Tags: ,

Sunday, December 11, 2005

PortableApps.com

PortableApps.com is the new site for Portable Firefox / Thunderbird / FileZilla / OpenOffice etc. All of the applications on this site can be run from an external flash/hard drive. No installation neccessary. Just unzip and go. More applications will be on the site in the future. From operating systems and office suites to image editors and games.


Tags: ,

Tuesday, December 06, 2005

Extensions for Web Developers (Firefox / Internet Explorer)

A list of Firefox extensions that are useful for web development. The Web Developer Extension is a 'must have' for web developers (i.e. if you could only have one, it would be it). Some haven't been updated for Firefox 1.5 (or you may have to go to the extension authors homepage to get an updated version).

Update (07 Dec 2005): Add N Edit Cookies, DevBoi, Screen grab!, MozRef Sidebar.
Update (20 Jan 2006): Console², FireBug, View Cookies, View Rendered Source Chart.
Update (25 Jan 2006): IE View Lite.

And for Internet Explorer:

There may be others for Internet Explorer that I do not know of (I have also not listed anything that you have to pay for).


Tags: , , , ,

Monday, December 05, 2005

getElementDimensions (JavaScript)

This function returns the dimensions of an element (left, right, top, bottom, width and height). You can pass on either a string (which gets the element by ID), or the element itself.

function getElementDimensions(el)
{
 if(typeof(el) == "string")
 {
  el = document.getElementById(el);
 }
 if(!el || !el.offsetParent) return false;
 var left = el.offsetLeft, top = el.offsetTop, width = el.offsetWidth, height = el.offsetHeight;
 do
 {
  el = el.offsetParent, left+= el.offsetLeft, top+= el.offsetTop;
 }
 while (el.offsetParent);
 return {"left" : left, "right" : left + width, "top" : top, "bottom" : top + height, "width" : width, "height" : height};
}

Example use:

var foo = document.getElementById("foo");
var fooDim = getElementDimensions(foo);
if(fooDim)
{
  alert(fooDim.left);
} 
var barDim = getElementDimensions("bar");
if(barDim)
{
  alert(barDim.top);
} 

Tags: , ,

Wednesday, November 30, 2005

removeAllChildNodes, getImmediateChildren (JavaScript)

Two functions for working with nodes via the W3C DOM (while they have only been tested on web pages, there is no reason why they won't work (with minor modifications) with anything that implements the W3C DOM and uses JavaScript/ECMAScript).

function removeAllChildNodes(node)
{
  if(!node || !node.childNodes) return;
  var nodeCount = node.childNodes.length;
  for(var i=nodeCount-1;i>=0;i--)
  {
    node.removeChild(node.childNodes[i]);
  }
}
function getImmediateChildren(node, tagName)
{
  if(!node || !node.childNodes) return;
  if(!tagName) tagName = "*";
  var elements = document.getElementsByTagName(tagName);
  var nodeCount = elements.length;
  var children = new Array();
  for(var i=0;i<nodeCount;i++)
  {
    if(elements[i].parentNode == node)
    {
      children[children.length] = elements[i];
    }
  }
  return children;
}

Imagine the following HTML:

<div id="foo">
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3
      <ul>
        <li>Item 3.1</li>
        <li>Item 3.2</li>
      </ul>
    </li>
    <li>Item 4</li>
  </ul>
</div>

If you then did removeAllChildNodes(document.getElementById("foo")) you would end up with an empty <div id="foo"></div>.

var foo = document.getElementById("foo");
var ul = foo.getElementsByTagName("ul")[0];
var ulitems = getImmediateChildren(ul, "li");

Would return the list items Item 1, Item 2, Item 3 and Item 4 (not Item 3.1 and Item 3.2 as they are not directly descended from ul)


Tags: ,

Saturday, November 26, 2005

The Uniform Server - Portable Apache / MySQL / PHP/Perl

The Uniform Server - run a web server off your external drive (for Windows based PC's). A useful way of developing your websites, no matter what PC you are using. No need to install anything. Server is Apache and includes MySQL, PHP and Perl. Can be used as a production/live web server (just copy the files over to the server hard drive).

Edit (17-Jan-06): Site is down, but you can still get it from SourceForge.net: Uniform Server.


Tags: , ,

Friday, November 25, 2005

ipconfig /all

If you run ipconfig /all in the command prompt in Windows it shows detailed info about your network adaptors. You may want to then print that information off. However it is in a command prompt window (where copying and pasting isn't exactly easy). Here is a batch file that opens up notepad with the information. When you close notepad, it then deletes the ipconfig.txt file that was created.

ip.cmd

ipconfig /all > ipconfig.txt & start /wait notepad ipconfig.txt & del ipconfig.txt

Edit (27 Nov 2005):

This can be set up as a doskey macro to replace existing command, can pass on parameters that ipconfig accepts. So if you run this in the command prompt window, then type in ipconfig /?, it will show the help in notepad.

doskey ipconfig=ipconfig $* $g ipconfig.txt $T start /wait notepad ipconfig.txt $T del ipconfig.txt

Tags: ,

Wednesday, November 23, 2005

Validating with the W3C

The W3C has several useful validation services. Most are for the standards they have developed, but there is also one for web feeds (Atom / RSS). These are the ones I know of.

  • (X)HTML / MathML (plus some favelets you can add to your bookmarks)
  • Link Checker (checks for broken links)
  • CSS (Cascading Style Sheets)
  • Feeds (Atom / RSS)
  • P3P (Platform for Privacy Preferences)
  • RDF (Resource Description Framework)
  • XSV (XML Schema Validator)
  • SVG (Scalable Vector Graphics)

Tags: ,

Tuesday, November 15, 2005

Portable Development

There are quite a few freeware applications that run on an external drive. These sites have a list of them. The advantage of them is that you do not need to install anything (except maybe to get the files to copy to the drive). When you use these applications you can develop your applications or websites on any (Windows 2000/XP) PC that can read your drive.

An example of how portable development can be done is web development. If you follow the instructions at Apache/MySQL/PHP on a usb flash drive, you can run an Apache Server off of your drive, so you have a portable web development environment. If there is a text editor you like and it is portable (for example SciTE) you can edit your pages and test them with PortableFirefox without ever installing anything, then upload them to your site using PortableFileZilla.

Console is also a good application that improves you experience with the command prompt, mostly cosmetic changes (tranparent console background, background image, change font). You can set a batch script to run when it loads (by creating a batch script containing start \Console\console.exe -c "/e:on /f:on /k \Console\config.cmd", so you can add macros (that you could use to run your portable applications).

Example config.cmd

@echo off
doskey /insert
doskey filezilla = %cd%PortableApps\PortableFileZilla.exe $*
doskey firefox = %cd%PortableApps\PortableFirefox.exe $*

Another example of a useful application is MPUI - it allows you to play many video and audio formats, regardless of codecs installed on the host PC.


Tags: ,

Tuesday, November 08, 2005

The Ultimate getElementsByClassName

The Ultimate getElementsByClassName. Originally written by Jonathan Snook, this function has been improved by Robert Nyman. A very useful function if you want to get elements that all have the same class name. Supports searching for elements with multiple class names (i.e. class="one two").


Tags: , ,

Monday, November 07, 2005

PDF Database Report (MyGeneration)

PDF Database Report is a template for the MyGeneration code generator. It uses iTextSharp to generate the document. The report includes tables, foreign keys, indexes and views. Details for each column (name, data type, is nullable etc) is shown for each table and view selected.


Tags: , ,

Saturday, October 29, 2005

JavaScript Effects (drag/drop, animation etc)

Thinking of adding effects to your web pages using JavaScript? Jonathan Snook has comprised a list of useful ones you can use: JavaScript Effect Libraries.

Moo.fx (simple animations, small download), script.aculo.us (more powerful, has AJAX capabilities, drag/drop, visual effects, auto-complete controls) and Rico (AJAX, drag/drop, cinematic effects, behaviours). Use the Prototype JavaScript Framework, which can make developing JavaScript web applications easier. script.aculo.us is probably the most powerful. There is also a mention of Walter Zorn, whose libraries support more browsers (doesn't use Prototype, drag-and-drop works even with Netscape 4 and Internet Explorer 4).


Tags: ,

Friday, October 21, 2005

addEvent() recoding contest

Adding events to elements via javascript should be easy but is not. Each browser has different methods of adding events, most standards compliant ones would use addEventLister() (as defined by the W3C), but Internet Explorer uses attachEvent(). That is why Scott Andrew LePera created functions to add and remove events, regardless of browser: Crossbrowser DOM Scripting: Event Handlers.

However, Peter-Paul Koch of QuirksMode found a problem with it: addEvent() considered harmful. So he set up a recoding contest for developers to improve on it. Eventually a winner was declared, but there are still problems with it. It does not work on IE5 Mac or Netscape 4 (although with the number of people still using them dropping, it may not cause a problem as long as you have a fallback, like server-side processing), plus there can still be a memory leak with Internet Explorer for Windows.

One of the judges, Dean Edwards decided to write his own solution. It is different, as it does not use addEventLister or attachEvent. But it does work cross browser and does not leak memory. It may not be scalable as addEventLister/attachEvent and also may not work in the future (if element.onclick is no longer supported).


Tags: , ,

Saturday, October 15, 2005

Update to JavaScript DOM Text Clips

Many more objects properties and methods have been added to JavaScript DOM Text Clips. As well as being useful as text clips, it also serves like a reference - it can be used to see if a certain element supports a method or property as defined by the W3C. Any of these properties or methods, if used appropriately (i.e. don't use 'href' on a 'table' element for instance), should work in any DOM1 compliant browser.


Tags: ,

Tabbed Search v2 (JavaScript)

An alternative javascript file for Tabbed Search. Instead of changing the form action when clicking a table, it changes the action when clicking the submit button, so it does not impact on other possible submit buttons in the form. HTML and CSS pages remain the same.

The script: tabbedsearch.js

// http://simon.incutio.com/archive/2004/05/26/addLoadEvent
function addLoadEvent(func)
{
 var oldonload = window.onload;
 if (typeof window.onload != 'function')
 {
  window.onload = func;
 }
 else
 {
  window.onload = function()
  {
   oldonload();
   func();
  }
 }
}
// this sets up the forms for search
// tested and works in IE 5+, Firefox 1.0+
function setupForms(method)
{
 // get all forms and loop through them
 var forms = document.getElementsByTagName("form");
 for(i=0; i<forms.length;i++)
 {
  if(forms[i].id == "")
  {
   forms[i].id = "form" + i;
  }
  var formid = forms[i].id;
  // get list
  var list = forms[i].getElementsByTagName("ul");
  // loop through items in list
  for(j=0; j<list.length;j++)
  {
   //alert(list[j].className);
   if(list[j].className == "formpages")
   {
    var items = list[j].getElementsByTagName("li");
    for(k=0; k<items.length;k++)
    {
     var link = items[k].getElementsByTagName("a")[0];
     if (link)
     {
      if(link.id == "")
      {
       link.id = formid + "Link" + k;
      }
      // this stores the links to the search
      if(forms[i].searchlinkids)
      {
       forms[i].searchlinkids = forms[i].searchlinkids + "," + link.id;
      }
      else
      {
       forms[i].searchlinkids = link.id;
      }
      link.onclick = function()
      { 
       removeLinkClassNames(formid);
       this.className = "active";
       return false;
      };
     }
    }
   }
  }
  // find submit button
  var divs = forms[i].getElementsByTagName("div");
  for(j=0; j<divs.length;j++)
  {
   if (divs[j].className == "searchbox")
   {
    var inputs = divs[j].getElementsByTagName("input");
    for(k=0; k<inputs.length;k++)
    {
     if(inputs[k].type == "submit")
     {
      inputs[k].onclick = function()
      {
       changeFormAction(formid, method);
      }
     }
    }
    break;
   }
  }
 }
}

function removeLinkClassNames(form)
{
 if(typeof(form) == 'string')
 {
  form = document.getElementById(form);
 }
 var f = form.searchlinkids.split(",");
 for (i=0; i<f.length; i++)
 {
  document.getElementById(f[i]).className = "";
 }
}

function changeFormAction(form,method)
{
 if(typeof(form) == 'string')
 {
  form = document.getElementById(form);
 }
 var action = form.action;
 form.oldaction = action;
 // get list
 var list = form.getElementsByTagName("ul");
 // loop through items in list
 for(i=0; i<list.length;i++)
 {
  //alert(list[i].className);
  if(list[i].className == "formpages")
  {
   var items = list[i].getElementsByTagName("li");
   for(j=0; j<items.length;j++)
   {
    var link = items[j].getElementsByTagName("a")[0];
    if (link)
    {
     if(link.className == "active")
     {
      action = link.href;
      break;
     }
    }
   }
  }
 }
 // change action and method
 if(action)
 {
  form.action = action;
 }
 if(method)
 {
  form.method = method;
 }
}



//addLoadEvent(setupForms);
//addLoadEvent(function(){setupForms("post")});
addLoadEvent(function(){setupForms("get")});

Tags: , ,

Sunday, October 09, 2005

Tabbed Search (JavaScript)

If you look at Google or other popular search engines, you notice that they use tabs to indicate what you are searching. What they do not do though, is change the forms action without going to a new page. With this script and accompanying CSS, it changes the parent forms action page and sets focus on a tab. The pages are contained in an unordered list that is then formatted to look like tabs.

Uses W3C DOM level 1 methods and properties, so should work in any complaint browser. Tested and works in IE5+, Firefox 1.0 and Opera 8.50. If JavaScript is disabled, it simply goes to the page linked to.

The script: tabbedsearch.js

// http://simon.incutio.com/archive/2004/05/26/addLoadEvent
function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      oldonload();
      func();
    }
  }
}
// this sets up the forms for search
// tested and works in IE 5+, Firefox 1.0+, Opera 8.50
function setupForms(method) {
 // get all forms and loop through them
 var forms = document.getElementsByTagName("form");
 for(i=0; i<forms.length;i++) {
  if(forms[i].id == "") {
   forms[i].id = "form" + i;
  }
  var formid = forms[i].id;
  // get list
  var list = forms[i].getElementsByTagName("ul");
  // loop through items in list
  for(j=0; j<list.length;j++) {
   //alert(list[j].className);
   if(list[j].className == "formpages") {
    var items = list[j].getElementsByTagName("li");
    for(k=0; k<items.length;k++) {
     if (items[k].getElementsByTagName("a")[0]) {
      var link = items[k].getElementsByTagName("a")[0];
      if(link.id == "") {
       link.id = formid + "Link" + k;
      }
      // this stores the links to the search
      if(forms[i].searchlinkids) {
       forms[i].searchlinkids = forms[i].searchlinkids + "," + link.id;
      }
      else {
       forms[i].searchlinkids = link.id;
      }
      link.onclick = function() { 
       changeFormAction(formid, this.href, method);
       this.className = "active";
       return false;
      };
     }
    }
   }
  }
 }
}

function changeFormAction(form,action,method) {
 if(typeof(form) == 'string') {
  form = document.getElementById(form);
 }
 var f = form.searchlinkids.split(",");
 for (i=0; i<f.length; i++) {
  document.getElementById(f[i]).className = "";
 }
 // change action and method
 if(form.action) {
  form.action = action; 
 }
 if(form.method) {
  form.method = method;
 }
}

// use normal form method
addLoadEvent(setupForms);
// change method to 'get'
//addLoadEvent(function(){setupForms("get")});
// change method to 'post'
//addLoadEvent(function(){setupForms("post")});

The CSS: tabbedsearch.css

body {
  font: 0.8em Verdana;
}
ul.formpages {
  list-style-type: none;
  padding: 0;
  margin: 0;
  /* fix for IE 5 margin div bug */
  _display: inline;
}
ul.formpages li {
  float: left;
  display: inline;
  background-color: #C2DDFE;
  margin: 0 3px 0 0;
  border-top: 1px solid #000;
  border-right: 1px solid #000;
  border-left: 1px solid #000;
  /* fix for Opera margin div bug */
  position: relative;
  top: 1px;
}
ul.formpages a:link, ul.formpages a:visited {
  text-decoration: none;
  padding: 5px;
  color: #008;
  border-bottom: 1px solid #000;
  display: block;
}
ul.formpages a:hover {
  background: #009;
  color: #fff;
}
ul.formpages a.active:link, ul.formpages a.active:hover, ul.formpages a.active:visited {
  background: #eee;
  color: #000;
}
div.searchbox {
  background: #eee; 
  border: 1px solid #000;
  margin: 0px;
  padding: 12px;
  width: 300px;
  clear: both;
}

Demo page: tabbedsearch.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Tabbed Search</title>
<script type="text/javascript" src="tabbedsearch.js"></script>
<style type="text/css">
<!--
 @import url("tabbedsearch.css");
//-->
</style>
</head>
<body>
<form action="search1.aspx" method="post">
<p>Clicking on any of the below links will change the forms action.</p>
<ul class="formpages">
 <li><a href="search1.aspx" class="active">Search 1</a></li>
 <li><a href="search2.aspx">Search 2</a></li>
 <li><a href="search3.aspx">Search 3</a></li>
</ul>
<div class="searchbox">Search: <input type="text" name="keywords" />
<input type="submit" value="Search" />
</div>
</form>
<p>Content after</p>
</body>
</html>

Tags: , , ,

Monday, October 03, 2005

JavaScript DOM Text Clips (PN2)

More Text Clips for PN2. Work in progress. Useful when developing web pages, or any scripting that uses the W3C DOM and JavaScript.

<?xml version="1.0"?>
<clips name="JavaScript DOM">
<!-- reference DOM 1 latest: http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html -->
<!-- reference DOM 2 core latest: http://www.w3.org/TR/DOM-Level-2-Core/ecma-script-binding.html -->
<!-- reference DOM 2 html latest: http://www.w3.org/TR/DOM-Level-2-HTML/ecma-script-binding.html -->
<clip name="------ Document properties ------"></clip>
<clip name="anchors">document.anchors</clip>
<clip name="applets">document.applets</clip>
<clip name="body">document.body</clip>
<clip name="cookie">document.cookie</clip>
<clip name="domain">document.domain</clip>
<clip name="forms">document.forms</clip>
<clip name="images">document.images</clip>
<clip name="links">document.links</clip>
<clip name="referrer">document.referrer</clip>
<clip name="title">document.title</clip>
<clip name="URL">document.URL</clip>
<clip name="------ Document methods ------"></clip>
<clip name="close">document.close()</clip>
<clip name="createElement">document.createElement("|")</clip>
<clip name="createTextNode">document.createTextNode("|")</clip>
<clip name="getElementById">document.getElementById("|")</clip>
<clip name="getElementsByTagName">document.getElementsByTagName("|")</clip>
<clip name="open">document.open()|</clip>
<clip name="write">document.write("|")</clip>
<clip name="writeln">document.writeln("|")</clip>
<clip name="------ Node properties ------"></clip>
<clip name=".attributes">|.attributes</clip>
<clip name=".childNodes">|.childNodes</clip>
<clip name=".firstChild">|.firstChild</clip>
<clip name=".lastChild">|.lastChild</clip>
<clip name=".nextSibling">|.nextSibling</clip>
<clip name=".nodeName">|.nodeName</clip>
<clip name=".nodeType">|.nodeType</clip>
<clip name=".nodeValue">|.nodeValue</clip>
<clip name=".ownerDocument">|.ownerDocument</clip>
<clip name=".parentNode">|.parentNode</clip>
<clip name=".previousSibling">|.previousSibling</clip>
<clip name="------ Node methods ------"></clip>
<clip name=".appendChild(newChild)">|.appendChild(newChild)</clip>
<clip name=".cloneNode(deep)">|.cloneNode(deep)</clip>
<clip name=".hasChildNodes()">|.hasChildNodes()</clip>
<clip name=".insertBefore(newChild, refChild)">|.insertBefore(newChild, refChild)</clip>
<clip name=".removeChild(oldChild)">|.removeChild(oldChild)</clip>
<clip name=".replaceChild(newChild, oldChild)">|.replaceChild(newChild, oldChild)</clip>
<clip name="------ Attr object ------"></clip>
<clip name=".name">|.name</clip>
<clip name=".specified">|.specified</clip>
<clip name=".value">|.value</clip>
<clip name="------ Element object ------"></clip>
<clip name=".getAttribute(name)">|.getAttribute(name)</clip>
<clip name=".getAttributeNode(name)">|.getAttributeNode(name)</clip>
<clip name=".normalize()">|.normalize()</clip>
<clip name=".getElementsByTagName(name)">|.getElementsByTagName(name)</clip>
<clip name=".removeAttributeNode(oldAttr)">|.removeAttributeNode(oldAttr)</clip>
<clip name=".setAttribute(name, value)">|.setAttribute(name, value)</clip>
<clip name=".setAttributeNode(newAttr)">|.setAttributeNode(newAttr)</clip>
<clip name=".tagName">|.tagName</clip>
<clip name="------ HTMLElement object ------"></clip>
<clip name=".className">|.className</clip>
<clip name=".dir">|.dir</clip>
<clip name=".id">|.id</clip>
<clip name=".lang">|.lang</clip>
<clip name=".title">|.title</clip>
<clip name="------ HTMLHtmlElement object ------"></clip>
<clip name=".version">|.version</clip>
<clip name="------ HTMLHeadElement object ------"></clip>
<clip name=".profile">|.profile</clip>
<clip name="------ HTMLLinkElement object ------"></clip>
<clip name=".charset">|.charset</clip>
<clip name=".disabled">|.disabled</clip>
<clip name=".href">|.href</clip>
<clip name=".hreflang">|.hreflang</clip>
<clip name=".media">|.media</clip>
<clip name=".rel">|.rel</clip>
<clip name=".rev">|.rev</clip>
<clip name=".target">|.target</clip>
<clip name=".type">|.type</clip>
<clip name="------ HTMLTitleElement object ------"></clip>
<clip name=".text">|.text</clip>
<clip name="------ HTMLMetaElement object ------"></clip>
<clip name=".content">|.content</clip>
<clip name=".httpEquiv">|.httpEquiv</clip>
<clip name=".name">|.name</clip>
<clip name=".scheme">|.scheme</clip>
<clip name="------ HTMLBaseElement object ------"></clip>
<clip name=".href">|.href</clip>
<clip name=".target">|.target</clip>
<clip name="------ HTMLIsIndexElement object ------"></clip>
<clip name=".form">|.form</clip>
<clip name=".prompt">|.prompt</clip>
<clip name="------ HTMLStyleElement object ------"></clip>
<clip name=".disabled">|.disabled</clip>
<clip name=".media">|.media</clip>
<clip name=".type">|.type</clip>
<clip name="------ HTMLBodyElement object ------"></clip>
<clip name=".aLink">|.aLink</clip>
<clip name=".background">|.background</clip>
<clip name=".bgColor">|.bgColor</clip>
<clip name=".link">|.link</clip>
<clip name=".text">|.text</clip>
<clip name=".vLink">|.vLink</clip>
<clip name="------ HTMLFormElement properties ------"></clip>
<clip name=".acceptCharset">|.acceptCharset</clip>
<clip name=".action">|.action</clip>
<clip name=".elements">|.elements</clip>
<clip name=".enctype">|.enctype</clip>
<clip name=".length">|.length</clip>
<clip name=".method">|.method</clip>
<clip name=".name">|.name</clip>
<clip name=".target">|.target</clip>
<clip name="------ HTMLFormElement methods ------"></clip>
<clip name=".reset()">|.reset()</clip>
<clip name=".submit()">|.submit()</clip>
<clip name="------ HTMLSelectElement properties ------"></clip>
<clip name=".disabled">|.disabled</clip>
<clip name=".form">|.form</clip>
<clip name=".length">|.length</clip>
<clip name=".multiple">|.multiple</clip>
<clip name=".name">|.name</clip>
<clip name=".options">|.options</clip>
<clip name=".selectedIndex">|.selectedIndex</clip>
<clip name=".size">|.size</clip>
<clip name=".tabIndex">|.tabIndex</clip>
<clip name=".type">|.type</clip>
<clip name=".value">|.value</clip>
<clip name="------ HTMLSelectElement methods ------"></clip>
<clip name=".add(element, before)">|.add(element, before)</clip>
<clip name=".blur()">|.blur()</clip>
<clip name=".focus()">|.focus()</clip>
<clip name=".remove(index)">|.remove(index)</clip>
<clip name="------ HTMLOptGroupElement object ------"></clip>
<clip name=".disabled">|.disabled</clip>
<clip name=".label">|.label</clip>
<clip name="------ HTMLOptionElement object ------"></clip>
<clip name=".defaultSelected">|.defaultSelected</clip>
<clip name=".disabled">|.disabled</clip>
<clip name=".form">|.form</clip>
<clip name=".index">|.index</clip>
<clip name=".label">|.label</clip>
<clip name=".selected">|.selected</clip>
<clip name=".text">|.text</clip>
<clip name=".value">|.value</clip>
<clip name="------ HTMLInputElement properties ------"></clip>
<clip name=".accept">|.accept</clip>
<clip name=".accessKey">|.accessKey</clip>
<clip name=".align">|.align</clip>
<clip name=".alt">|.alt</clip>
<clip name=".checked">|.checked</clip>
<clip name=".defaultChecked">|.defaultChecked</clip>
<clip name=".defaultValue">|.defaultValue</clip>
<clip name=".disabled">|.disabled</clip>
<clip name=".form">|.form</clip>
<clip name=".maxLength">|.maxLength</clip>
<clip name=".name">|.name</clip>
<clip name=".readOnly">|.readOnly</clip>
<clip name=".size">|.size</clip>
<clip name=".src">|.src</clip>
<clip name=".tabIndex">|.tabIndex</clip>
<clip name=".type">|.type</clip>
<clip name=".useMap">|.useMap</clip>
<clip name=".value">|.value</clip>
<clip name="------ HTMLInputElement methods ------"></clip>
<clip name=".blur()">|.blur()</clip>
<clip name=".click()">|.click()</clip>
<clip name=".focus()">|.focus()</clip>
<clip name=".select()">|.select()</clip>
<clip name="------ HTMLTextAreaElement properties ------"></clip>
<clip name=".accessKey">|.accessKey</clip>
<clip name=".cols">|.cols</clip>
<clip name=".defaultValue">|.defaultValue</clip>
<clip name=".disabled">|.disabled</clip>
<clip name=".form">|.form</clip>
<clip name=".name">|.name</clip>
<clip name=".readOnly">|.readOnly</clip>
<clip name=".rows">|.rows</clip>
<clip name=".tabIndex">|.tabIndex</clip>
<clip name=".type">|.type</clip>
<clip name=".value">|.value</clip>
<clip name="------ HTMLTextAreaElement methods ------"></clip>
<clip name=".blur()">|.blur()</clip>
<clip name=".focus()">|.focus()</clip>
<clip name=".select()">|.select()</clip>
<clip name="------ HTMLButtonElement object ------"></clip>
<clip name=".accessKey">|.accessKey</clip>
<clip name=".disabled">|.disabled</clip>
<clip name=".form">|.form</clip>
<clip name=".name">|.name</clip>
<clip name=".tabIndex">|.tabIndex</clip>
<clip name=".type">|.type</clip>
<clip name=".value">|.value</clip>
<clip name="------ HTMLLabelElement object ------"></clip>
<clip name=".accessKey">|.accessKey</clip>
<clip name=".form">|.form</clip>
<clip name=".htmlFor">|.htmlFor</clip>
<clip name="------ HTMLFieldSetElement object ------"></clip>
<clip name=".form">|.form</clip>
<clip name="------ HTMLLegendElement object ------"></clip>
<clip name=".accessKey">|.accessKey</clip>
<clip name=".align">|.align</clip>
<clip name=".form">|.form</clip>
<clip name="------ HTMLUListElement object ------"></clip>
<clip name=".compact">|.compact</clip>
<clip name=".type">|.type</clip>
<clip name="------ HTMLOListElement object ------"></clip>
<clip name=".compact">|.compact</clip>
<clip name=".start">|.start</clip>
<clip name=".type">|.type</clip>
<clip name="------ HTMLDList/Directory/MenuElement object ------"></clip>
<clip name=".compact">|.compact</clip>
<clip name="------ HTMLLIElement object ------"></clip>
<clip name=".type">|.type</clip>
<clip name=".value">|.value</clip>
<clip name="------ HTMLBlockquote/QuoteElement object ------"></clip>
<clip name=".cite">|.cite</clip>
<clip name="------ HTMLDiv/Paragraph/HeadingElement object ------"></clip>
<clip name=".align">|.align</clip>
<clip name="------ HTMLPreElement object ------"></clip>
<clip name=".width">|.width</clip>
<clip name="------ HTMLBRElement object ------"></clip>
<clip name=".clear">|.clear</clip>
<clip name="------ HTMLBaseFont/FontElement object ------"></clip>
<clip name=".color">|.color</clip>
<clip name=".face">|.face</clip>
<clip name=".size">|.size</clip>
<clip name="------ HTMLHRElement object ------"></clip>
<clip name=".align">|.align</clip>
<clip name=".noShade">|.noShade</clip>
<clip name=".size">|.size</clip>
<clip name=".width">|.width</clip>
<clip name="------ HTMLModElement object ------"></clip>
<clip name=".cite">|.cite</clip>
<clip name=".dateTime">|.dateTime</clip>
<clip name="------ HTMLAnchorElement properties ------"></clip>
<clip name=".accessKey">|.accessKey</clip>
<clip name=".charset">|.charset</clip>
<clip name=".coords">|.coords</clip>
<clip name=".href">|.href</clip>
<clip name=".hreflang">|.hreflang</clip>
<clip name=".name">|.name</clip>
<clip name=".rel">|.rel</clip>
<clip name=".rev">|.rev</clip>
<clip name=".shape">|.shape</clip>
<clip name=".tabIndex">|.tabIndex</clip>
<clip name=".target">|.target</clip>
<clip name=".type">|.type</clip>
<clip name="------ HTMLAnchorElement methods ------"></clip>
<clip name=".blur()">|.blur()</clip>
<clip name=".focus()">|.focus()</clip>
<clip name="------ HTMLImageElement object ------"></clip>
<clip name=".align">|.align</clip>
<clip name=".alt">|.alt</clip>
<clip name=".border">|.border</clip>
<clip name=".height">|.height</clip>
<clip name=".hspace">|.hspace</clip>
<clip name=".isMap">|.isMap</clip>
<clip name=".longDesc">|.longDesc</clip>
<clip name=".lowSrc">|.lowSrc</clip>
<clip name=".name">|.name</clip>
<clip name=".src">|.src</clip>
<clip name=".useMap">|.useMap</clip>
<clip name=".vspace">|.vspace</clip>
<clip name=".width">|.width</clip>
<clip name="------ HTMLObjectElement object ------"></clip>
<clip name=".align">|.align</clip>
<clip name=".archive">|.archive</clip>
<clip name=".border">|.border</clip>
<clip name=".code">|.code</clip>
<clip name=".codeBase">|.codeBase</clip>
<clip name=".codeType">|.codeType</clip>
<clip name=".data">|.data</clip>
<clip name=".declare">|.declare</clip>
<clip name=".form">|.form</clip>
<clip name=".height">|.height</clip>
<clip name=".hspace">|.hspace</clip>
<clip name=".name">|.name</clip>
<clip name=".standby">|.standby</clip>
<clip name=".tabIndex">|.tabIndex</clip>
<clip name=".type">|.type</clip>
<clip name=".useMap">|.useMap</clip>
<clip name=".vspace">|.vspace</clip>
<clip name=".width">|.width</clip>
<clip name="------ HTMLParamElement object ------"></clip>
<clip name=".name">|.name</clip>
<clip name=".type">|.type</clip>
<clip name=".value">|.value</clip>
<clip name=".valueType">|.valueType</clip>
<clip name="------ HTMLAppletElement object ------"></clip>
<clip name=".align">|.align</clip>
<clip name=".alt">|.alt</clip>
<clip name=".archive">|.archive</clip>
<clip name=".code">|.code</clip>
<clip name=".codeBase">|.codeBase</clip>
<clip name=".height">|.height</clip>
<clip name=".hspace">|.hspace</clip>
<clip name=".name">|.name</clip>
<clip name=".object">|.object</clip>
<clip name=".vspace">|.vspace</clip>
<clip name=".width">|.width</clip>
<clip name="------ HTMLMapElement object ------"></clip>
<clip name=".areas">|.areas</clip>
<clip name=".name">|.name</clip>
<clip name="------ HTMLAreaElement object ------"></clip>
<clip name=".accessKey">|.accessKey</clip>
<clip name=".alt">|.alt</clip>
<clip name=".coords">|.coords</clip>
<clip name=".href">|.href</clip>
<clip name=".noHref">|.noHref</clip>
<clip name=".shape">|.shape</clip>
<clip name=".tabIndex">|.tabIndex</clip>
<clip name=".target">|.target</clip>
<clip name="------ HTMLScriptElement object ------"></clip>
<clip name=".charset">|.charset</clip>
<clip name=".defer">|.defer</clip>
<clip name=".event">|.event</clip>
<clip name=".htmlFor">|.htmlFor</clip>
<clip name=".src">|.src</clip>
<clip name=".text">|.text</clip>
<clip name=".type">|.type</clip>
<clip name="------ HTMLTableElement properties ------"></clip>
<clip name=".align">|.align</clip>
<clip name=".bgColor">|.bgColor</clip>
<clip name=".border">|.border</clip>
<clip name=".caption">|.caption</clip>
<clip name=".cellPadding">|.cellPadding</clip>
<clip name=".cellSpacing">|.cellSpacing</clip>
<clip name=".frame">|.frame</clip>
<clip name=".rows">|.rows</clip>
<clip name=".rules">|.rules</clip>
<clip name=".summary">|.summary</clip>
<clip name=".tFoot">|.tFoot</clip>
<clip name=".tHead">|.tHead</clip>
<clip name=".width">|.width</clip>
<clip name="------ HTMLTableElement methods ------"></clip>
<clip name=".createCaption()">|.createCaption()</clip>
<clip name=".createTFoot()">|.createTFoot()</clip>
<clip name=".createTHead()">|.createTHead()</clip>
<clip name=".deleteCaption()">|.deleteCaption()</clip>
<clip name=".deleteTFoot()">|.deleteTFoot()</clip>
<clip name=".deleteTHead()">|.deleteTHead()</clip>
<clip name=".deleteRow(index)">|.deleteRow(index)</clip>
<clip name=".insertRow(index)">|.insertRow(index)</clip>
<clip name="------ HTMLTableCaptionElement object ------"></clip>
<clip name=".align">|.align</clip>
<clip name="------ HTMLTableColElement object ------"></clip>
<clip name=".align">|.align</clip>
<clip name=".ch">|.ch</clip>
<clip name=".chOff">|.chOff</clip>
<clip name=".span">|.span</clip>
<clip name=".vAlign">|.vAlign</clip>
<clip name=".width">|.width</clip>
<clip name="------ HTMLTableSectionElement properties ------"></clip>
<clip name=".align">|.align</clip>
<clip name=".ch">|.ch</clip>
<clip name=".chOff">|.chOff</clip>
<clip name=".vAlign">|.vAlign</clip>
<clip name=".width">|.width</clip>
<clip name="------ HTMLTableSectionElement methods ------"></clip>
<clip name=".deleteRow(index)">|.deleteRow(index)</clip>
<clip name=".insertRow(index)">|.insertRow(index)</clip>
<clip name="------ HTMLTableRowElement properties ------"></clip>
<clip name=".align">|.align</clip>
<clip name=".bgColor">|.bgColor</clip>
<clip name=".cells">|.cells</clip>
<clip name=".ch">|.ch</clip>
<clip name=".chOff">|.chOff</clip>
<clip name=".rowIndex">|.rowIndex</clip>
<clip name=".sectionRowIndex">|.sectionRowIndex</clip>
<clip name=".vAlign">|.vAlign</clip>
<clip name="------ HTMLTableRowElement methods ------"></clip>
<clip name=".deleteCell(index)">|.deleteCell(index)</clip>
<clip name=".insertCell(index)">|.insertCell(index)</clip>
<clip name="------ HTMLTableCellElement object ------"></clip>
<clip name=".abbr">|.abbr</clip>
<clip name=".align">|.align</clip>
<clip name=".axis">|.axis</clip>
<clip name=".bgColor">|.bgColor</clip>
<clip name=".cellIndex">|.cellIndex</clip>
<clip name=".ch">|.ch</clip>
<clip name=".chOff">|.chOff</clip>
<clip name=".colSpan">|.colSpan</clip>
<clip name=".headers">|.headers</clip>
<clip name=".height">|.height</clip>
<clip name=".noWrap">|.noWrap</clip>
<clip name=".rowSpan">|.rowSpan</clip>
<clip name=".scope">|.scope</clip>
<clip name=".vAlign">|.vAlign</clip>
<clip name=".width">|.width</clip>
<clip name="------ HTMLFrameSetElement object ------"></clip>
<clip name=".cols">|.cols</clip>
<clip name=".rows">|.rows</clip>
<clip name="------ HTMLFrameElement object ------"></clip>
<clip name=".frameBorder">|.frameBorder</clip>
<clip name=".longDesc">|.longDesc</clip>
<clip name=".marginHeight">|.marginHeight</clip>
<clip name=".marginWidth">|.marginWidth</clip>
<clip name=".name">|.name</clip>
<clip name=".noResize">|.noResize</clip>
<clip name=".scrolling">|.scrolling</clip>
<clip name=".src">|.src</clip>
<clip name="------ HTMLIFrameElement object ------"></clip>
<clip name=".align">|.align</clip>
<clip name=".frameBorder">|.frameBorder</clip>
<clip name=".height">|.height</clip>
<clip name=".longDesc">|.longDesc</clip>
<clip name=".marginHeight">|.marginHeight</clip>
<clip name=".marginWidth">|.marginWidth</clip>
<clip name=".name">|.name</clip>
<clip name=".scrolling">|.scrolling</clip>
<clip name=".src">|.src</clip>
<clip name=".width">|.width</clip>
</clips>

Tags: ,

getInnerText (JavaScript)

This function gets the inner text of the supplied node. It is recursive, so includes inner text of any child nodes. <br /> tags will be converted to linebreaks. Whitespace can be optionally excluded.

Should work in any W3C DOM level 1 compliant browser.

Simple to use - just do:

myNode = document.getElementById("myNode");
// include whitespace
var text = getInnerText(myNode);
var textNoWhiteSpace = getInnerText(myNode,true);

And the script itself:

function getInnerText(node,ignorewhitespace)
{
 var text = "";
 // if the node has children, loop through them
 if(node.hasChildNodes())
 {
  var children = node.childNodes;
  for(var i=0; i<children.length; i++)
  {
   // if node is a text node append it
   if(children[i].nodeName == "#text")
   {
    if(ignorewhitespace)
    {
     if(!/^\s+$/.test(children[i].nodeValue))
     {
      text = text.concat(children[i].nodeValue);
     }
    }
    else
    {
     text = text.concat(children[i].nodeValue);
    }
   }
   // if node is a line break append \n
   else if(children[i].nodeName == "BR")
   {
    text = text.concat("\n");
   }
   // otherwise call this function again to get the text
   else
   {
    text = text.concat(getInnerText(children[i]));
   }
  }
 }
 // it has no children, so get the text
 else
 {
  // if node is a text node append it
  if(node.nodeName == "#text")
  {
   text = text.concat(node.nodeValue);
  }
  // if node is a line break append \n
  else if(node.nodeName == "BR")
  {
   text = text.concat("\n");
  }
 }
 return text;
}

Tags: ,

Friday, September 30, 2005

Updated C# Text Clips (PN2)

Updated Text Clips for Programmers Notepad 2 (C#). ASP.NET Snippets and Miscellaneous Snippets (properties) added.


Tags: ,

Wednesday, September 21, 2005

Programmers Notepad 2 User Tools

Programmers Notepad 2 has a very useful tools feature. The configuration is kept in the %APPDATA%\Echo Software\PN2 folder as UserTools.xml

The format is fairly simple. Here is my UserTools.xml file:

<schemetools>
    <global>
        <tool command="C:\Program Files\Scintilla Text Editor\SciTE.exe" flags="40" folder="" index="0" name="SciTE" params="&quot;%d%f&quot;" parsepattern="" shortcut="0"></tool>
        <tool command="C:\Program Files\FileZilla\FileZilla.exe" flags="40" folder="%d" index="1" name="FileZilla" params="" parsepattern="" shortcut="0"></tool>
        <tool command="explorer.exe" flags="40" folder="" index="2" name="Windows Explorer" params="%d" parsepattern="" shortcut="0"></tool>
        <tool command="cmd" flags="40" folder="" index="3" name="Command Prompt" params="/k cd %d" parsepattern="" shortcut="0"></tool>
        <tool command="mmc" flags="40" folder="" index="4" name="IIS" params="C:\WINNT\System32\Inetsrv\iis.msc" parsepattern="" shortcut="0"></tool>
        <tool command="svn" flags="33" folder="%d" index="5" name="svn add" params="add &quot;%f&quot;" parsepattern="" shortcut="0"></tool>
        <tool command="svn" flags="33" folder="%d" index="6" name="svn add (all in folder)" params="add *" parsepattern="" shortcut="0"></tool>
        <tool command="svn" flags="97" folder="%d" index="7" name="svn commit" params="commit &quot;%f&quot; --message &quot;%?&quot;" parsepattern="" shortcut="0"></tool>
        <tool command="svn" flags="33" folder="%d" index="8" name="svn commit (folder)" params="commit --message &quot;%?&quot;" parsepattern="" shortcut="0"></tool>
        <tool command="svn" flags="33" folder="%d" index="9" name="svn commit (folder, non-recursive)" params="commit --non-recursive --message &quot;%?&quot;" parsepattern="" shortcut="0"></tool>
        <tool command="svn" flags="33" folder="%d" index="10" name="svn diff" params="diff &quot;%f&quot;" parsepattern="" shortcut="0"></tool>
        <tool command="svn" flags="33" folder="%d" index="11" name="svn info" params="info &quot;%f&quot;" parsepattern="" shortcut="0"></tool>
        <tool command="svn" flags="33" folder="%d" index="12" name="svn status" params="status &quot;%f&quot;" parsepattern="" shortcut="0"></tool>
        <tool command="svn" flags="33" folder="%d" index="13" name="svn status (folder)" params="status" parsepattern="" shortcut="0"></tool>
        <tool command="svn" flags="33" folder="%d" index="14" name="svn status (folder, non-recursive)" params="status --non-recursive" parsepattern="" shortcut="0"></tool>
        <tool command="svn" flags="35" folder="%d" index="15" name="svn update" params="update &quot;%f&quot;" parsepattern="" shortcut="0"></tool>
    </global>
    <scheme name="csharp">
        <tool command="C:\Program Files\SharpDevelop\bin\SharpDevelop.exe" flags="41" folder="" index="0" name="SharpDevelop" params="&quot;%d%f&quot;" parsepattern="" shortcut="0"></tool>
    </scheme>
    <scheme name="web">
        <tool command="tidy" flags="1569" folder="" index="0" name="Tidy" params="-i -asxhtml -wrap 230 --indent-spaces 4 -q" parsepattern="" shortcut="0"></tool>
    </scheme>
    <scheme name="xml">
        <tool command="tidy" flags="1569" folder="" index="0" name="Tidy" params="-i -xml -wrap 230 --indent-spaces 4 -q" parsepattern="" shortcut="0"></tool>
    </scheme>
</schemetools>

As you can see, the root tag is '<schemetools>'. There is one '<global>' tag under this with tools common to all files. There are also several '<scheme>' tags with tools for each scheme.

Under '<global>' and '<scheme>' you can have '<tool>', with the following attributes:

  • command: path to the executable to run, include full path if not in any of the folders listed in the PATH environment variable.
  • flags: various preferences set using checkboxes and dropdowns in the tool properties (i.e. those that are not set with any other attributes for the '<tool>' tag)
  • folder: which folder the tool starts in
  • index: where it appears in the tool list
  • name: what you see when you use the Tools menu
  • params: parameters you pass on the the command
  • parsepattern: pattern for custom output parsing
  • shortcut: keyboard shortcut for the tool. 0 means no shortcut. Calculate by adding one or more modifiers to numbers, numpad, cursor, letter or function key values.
    • Modifiers: SHIFT = 256, CTRL = 512, ALT = 1024
    • Numbers: 0 = 48, 1 = 49, 2 = 50, 3 = 51, 4 = 52, 5 = 53, 6 = 54, 7 = 55, 8 = 56, 9 = 57
    • Numpad: 0 = 96, 1 = 97, 2 = 98, 3 = 99, 4 = 100, 5 = 101, 6 = 102, 7 = 103, 8 = 104, 9 = 105, * = 106, + = 107, - = 109, . = 110, / = 2159
    • Cursor: UP = 2086, DOWN = 2088, LEFT = 2085, RIGHT = 2087
    • Letters: A = 65, B = 66, C = 67, D = 68, E = 69, F = 70, G = 71, H = 72, I = 73, J = 74, K = 75, L = 76, M = 77, N = 78, O = 79, P = 80, Q = 81, R = 82, S = 83, T = 84, U = 85, V = 86, W = 87, X = 88, Y = 89, Z = 90
    • Function Keys: F1 = 112, F2 = 113, F3 = 114, F4 = 115, F5 = 116, F6 = 117, F7 = 118, F8 = 119, F9 = 120, F10 = 121, F11 = 122, F12 = 123

You cannot use a modifier on its own. You can combine modifiers with numbers, letters or function keys. You can have only one number, letter, or function key in a shortcut (so no F1 + A).

For example, CTRL + ALT + Numpad * = 512 + 1024 + 106 = 1642


Tags: , ,

Tuesday, September 20, 2005

Opera now free (no banner ads)

The Opera browser is now available without banner ads. Has fairly good standards support and is a very small download, also very fast at loading and displaying web pages. Now if only it had an extensions mechanism like Firefox. A three way battle between Firefox, IE and Opera (which was only really two way before as Opera had ads).


Tags: ,

Thursday, September 15, 2005

Text Clips for Programmers Notepad 2 (C#)

Edit (30 Sep 2005): ASP.NET Snippets and Miscellaneous Snippets (properties) added.

More Text Clips for Programmers Notepad 2. Useful for when working with C#.

Create a file in the clips sub directory of the Programmers Notepad directory, with the extension .clips (i.e. csclips.clips) and paste in the following code:

<?xml version="1.0"?>
<clips name="C# Clips">
<clip name="------ Exception handling ------"></clip>
<clip name="throw"><![CDATA[throw(new |Exception());]]></clip>
<clip name="try-catch"><![CDATA[try
{
|
}
catch(Exception e)
{

}]]></clip>
<clip name="try-finally"><![CDATA[try
{
|
}
finally
{

}]]></clip>
<clip name="try-catch-finally"><![CDATA[try
{
|
}
catch(Exception e)
{

}
finally
{

}]]></clip>
<clip name="------ Iteration ------"></clip>
<clip name="do"><![CDATA[do 
{

}
while(|);]]></clip>
<clip name="for"><![CDATA[for (int i = 0; i <= |; i++)
{

}]]></clip>
<clip name="foreach"><![CDATA[foreach (int i in |)
{

}]]></clip>
<clip name="while"><![CDATA[while(|) 
{

}]]></clip>
<clip name="------ Reference type declaration ------"></clip>
<clip name="class"><![CDATA[public class |
{

}]]></clip>
<clip name="delegate"><![CDATA[delegate void |();]]></clip>
<clip name="delegate (event handling)"><![CDATA[public delegate void |ChangedEventHandler();
public event ChangedEventHandler Changed;
protected virtual void OnChanged() 
{
 if (Changed != null)
 {
  Changed();
 }
}]]></clip>
<clip name="interface"><![CDATA[public interface I|
{

}]]></clip>
<clip name="------ Selection ------"></clip>
<clip name="?:"><![CDATA[| = (bar == baz) ? footrue : foofalse]]></clip>
<clip name="if"><![CDATA[if(|) 
{

}]]></clip>
<clip name="if-else"><![CDATA[if(|) 
{

}
else
{

}]]></clip>
<clip name="if-else if"><![CDATA[if(|) 
{

}
else if()
{

}]]></clip>
<clip name="switch case"><![CDATA[switch(|) 
{
 case 1:
  break;
 default:
  break;
}]]></clip>
<clip name="------ Documentation Comments ------"></clip>
<clip name="/// "><![CDATA[///|]]></clip>
<clip name="&lt;c&gt; (inline code)"><![CDATA[<c>|</c>]]></clip>
<clip name="&lt;code&gt; (multiline code)"><![CDATA[/// <code>
/// |
/// </code>]]></clip>
<clip name="&lt;example&gt; (method example)"><![CDATA[/// <example>
/// |
/// </example>]]></clip>
<clip name="&lt;example&gt; (method example, includes &lt;code&gt;)"><![CDATA[/// <example>
///  <code>
/// |
///  </code>
/// </example>]]></clip>
<clip name="&lt;exception&gt;"><![CDATA[/// <exception cref="System.Exception">Thrown when... |.</exception>]]></clip>
<clip name="&lt;include&gt;"><![CDATA[//// <include file='|.xml' path='MyDocs/MyMembers[@name="test"]/*' />]]></clip>
<clip name="&lt;list&gt; (bullet, with items)"><![CDATA[/// <list type="bullet">
///  <listheader>
///   <term>List Header</term>
///   <description>|.</description>
///  </listheader>
///  <item>
///   <term>Term 1</term>
///   <description>Item 1.</description>
///  </item>
///  <item>
///   <term>Term 2</term>
///   <description>Item 2.</description>
///  </item>
/// </list>]]></clip>
<clip name="&lt;list&gt; (number, with items)"><![CDATA[/// <list type="number">
///  <listheader>
///   <term>List Header</term>
///   <description>|.</description>
///  </listheader>
///  <item>
///   <term>Term 1</term>
///   <description>Item 1.</description>
///  </item>
///  <item>
///   <term>Term 2</term>
///   <description>Item 2.</description>
///  </item>
/// </list>]]></clip>
<clip name="&lt;list&gt; (table, with items)"><![CDATA[/// <list type="table">
///  <listheader>
///   <term>List Header</term>
///   <description>|.</description>
///  </listheader>
///  <item>
///   <term>Term 1</term>
///   <description>Item 1.</description>
///  </item>
///  <item>
///   <term>Term 2</term>
///   <description>Item 2.</description>
///  </item>
/// </list>]]></clip>
<clip name="&lt;list&gt; (bullet, without items)"><![CDATA[/// <list type="bullet">
/// |
/// </list>]]></clip>
<clip name="&lt;list&gt; (number, without items)"><![CDATA[/// <list type="number">
/// |
/// </list>]]></clip>
<clip name="&lt;list&gt; (table, without items)"><![CDATA[/// <list type="table">
/// |
/// </list>]]></clip>
<clip name="&lt;list&gt; - &lt;item&gt;"><![CDATA[///  <item>
///   <term>List Header</term>
///   <description>|.</description>
///  </item>]]></clip>
<clip name="&lt;list&gt; - &lt;listheader&gt;"><![CDATA[///  <listheader>
///   <term>List Header</term>
///   <description>|.</description>
///  </listheader>]]></clip>
<clip name="&lt;para&gt; (paragraph)"><![CDATA[/// <para>
///  |
/// </para>]]></clip>
<clip name="&lt;param&gt; (parameter)"><![CDATA[/// <param name='|'>Description.</param>]]></clip>
<clip name="&lt;paramref&gt; (parameter reference)"><![CDATA[<paramref name="|"/>]]></clip>
<clip name="&lt;permission&gt;"><![CDATA[/// <permission cref="System.Security.PermissionSet">|.</permission>]]></clip>
<clip name="&lt;remarks&gt;"><![CDATA[/// <remarks>
/// |
/// </remarks>]]></clip>
<clip name="&lt;returns&gt;"><![CDATA[/// <returns>
/// |
/// </returns>]]></clip>
<clip name="&lt;see&gt;"><![CDATA[<see cref="|"/>]]></clip>
<clip name="&lt;seealso&gt;"><![CDATA[<seealso cref="|"/>]]></clip>
<clip name="&lt;summary&gt;"><![CDATA[/// <summary>
/// |
/// </summary>]]></clip>
<clip name="&lt;value&gt;"><![CDATA[/// <value>|.</value>]]></clip>
<clip name="------ ASP.NET Snippets ------"></clip>
<clip name="Page CodeBehind"><![CDATA[using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace MyNamespace
{
 public class MyPage : Page
 {
  #region Web Form Designer generated code
  override protected void OnInit(EventArgs e)
  {
   //
   // CODEGEN: This call is required by the ASP.NET Web Form Designer.
   //
   InitializeComponent();
  }
  /// <summary>
  ///  Required method for Designer support - do not modify
  ///  the contents of this method with the code editor.
  /// </summary>
  private void InitializeComponent()
  {
   this.Load += new System.EventHandler(this.LoadPage);
  }
  #endregion
  
  private void LoadPage(object sender, EventArgs e)
  {
   |
  }
 }
}]]></clip>
<clip name="UserControl CodeBehind"><![CDATA[using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace MyNamespace
{
 public class MyControl : UserControl
 {
  #region Web Form Designer generated code
  override protected void OnInit(EventArgs e)
  {
   //
   // CODEGEN: This call is required by the ASP.NET Web Form Designer.
   //
   InitializeComponent();
  }
  /// <summary>
  ///  Required method for Designer support - do not modify
  ///  the contents of this method with the code editor.
  /// </summary>
  private void InitializeComponent()
  {
   this.Load += new System.EventHandler(this.LoadUserControl);
  }
  #endregion
  
  private void LoadUserControl(object sender, EventArgs e)
  {
   |
  }
 }
}]]></clip>
<clip name="WebHandler"><![CDATA[<%@ WebHandler Language="C#" Class="MyNamespace.MyHandler" %>
using System;
using System.IO;
using System.Web;
namespace MyNamespace
{
 public class MyHandler: IHttpHandler 
 {
  
  public bool IsReusable
  {
   get
   {
    return true;
   }
  }
  
  public void ProcessRequest(HttpContext ctx)
  {
   ctx.Response.ContentType = "text/plain";
   ctx.Response.Write("|");
   ctx.Response.End();
  }
 }
}]]></clip>
<clip name="------ Miscellaneous Snippets ------"></clip>
<clip name="Property (bool)"><![CDATA[private bool |myBool;
public bool MyBool
{
 get
 {
  return myBool;
 }
 set
 {
  myBool = value;
 }
}]]></clip>
<clip name="Property (DateTime)"><![CDATA[private DateTime |myDate;
public DateTime MyDate
{
 get
 {
  return myDate;
 }
 set
 {
  myDate = value;
 }
}]]></clip>
<clip name="Property (decimal)"><![CDATA[private decimal |myDecimal;
public decimal MyDecimal
{
 get
 {
  return myDecimal;
 }
 set
 {
  myDecimal = value;
 }
}]]></clip>
<clip name="Property (double)"><![CDATA[private double |myDouble;
public double MyDouble
{
 get
 {
  return myDouble;
 }
 set
 {
  myDouble = value;
 }
}]]></clip>
<clip name="Property (float)"><![CDATA[private float |myFloat;
public float MyFloat
{
 get
 {
  return myFloat;
 }
 set
 {
  myFloat = value;
 }
}]]></clip>
<clip name="Property (int)"><![CDATA[private int |myInt;
public int MyInt
{
 get
 {
  return myInt;
 }
 set
 {
  myInt = value;
 }
}]]></clip>
<clip name="Property (long)"><![CDATA[private long |myLong;
public long MyLong
{
 get
 {
  return myLong;
 }
 set
 {
  myLong = value;
 }
}]]></clip>
<clip name="Property (short)"><![CDATA[private short |myShort;
public short MyShort
{
 get
 {
  return myShort;
 }
 set
 {
  myShort = value;
 }
}]]></clip>
<clip name="Property (string)"><![CDATA[private string |myString;
public string MyString
{
 get
 {
  return myString;
 }
 set
 {
  myString = value;
 }
}]]></clip>
</clips>

Tags: , , ,

Wednesday, September 14, 2005

Google Blog Search

Search weblogs with Google Blog Search. If a site has an RSS feed and 'pings' a site (like Weblogs.com) when it is updated, it should become searchable through this. In some ways better than Google Search as it is likely to be more up to date and have less spam. You can have your results as an Atom or RSS feed. No ads (yet).


Tags: , ,

Thursday, September 08, 2005

Tamper proof URL's, Expiring Web Pages

Passing Tamper-Proof QueryString Parameters and Creating Expiring Web Pages cover how you can improve the security of your web application. While the example code is in VB.NET, the idea can be applied to any web programming language (PHP, Perl, VBScript etc). Basically you pass a hash (of the parameters plus a 'secret salt' (a custom string added to the start/finish)) only known to those that need to connect to the page (often just pages on the same website, but maybe used by other sites), along with the parameters and the current time and date.


Tags: ,

Web Standards Are Your Responsibility

7nights - Web Standards Are Your Responsibility. It may be a challenge to get an uncompliant site recoded to standards, but will save time in maintenance in the future (if you pages are semantically well done), plus the pages will work as expected (except perhaps a few CSS quirks) in any browser that is compliant with the standard. Standards can also be a selling point for an application - a bigger market can be targetted than if you coded just for the dominant browser (i.e. Internet Explorer). Plus there is no guarantee that your site will work in the future (if IE lost its dominant market share).


Tags: ,

Runasspc - run programs with admin rights

Runasspc allows limited account users to run programs with admin rights. Better than runas as it saves the credentials encrypted in a file and you decide which programs can be run as admin, no need to give out the password.


Tags: ,

Sunday, September 04, 2005

Standards-schmandards

Standards-schmandards is a site about developing accessible web pages. Despite its name, standards are important to its authors. It is the home of FANGS, a screen reader emulator for Firefox.


Tags: ,

CSS 2.1 parser in IE 7

Looks like many pages will not be broken when the CSS in IE7 is improved. So by implemented hacks that use child selectors and the * html hack to work round IE, the * html will be ignored while the child selector processed (like what other browsers do).

"We've already started talking about a few of the CSS changes that are going to be available in IE 7 when we release, but there are a few hanging points that we haven't talked about yet or haven't covered completely. There are 3 specific items I'd like to talk about:
  • Using the root node wild card selector for IE only rules (* HTML) [strict mode only fix]
  • Multi-class selectors as defined by CSS 2.1 (.floral.pastel) [strict mode only fix]
  • Pseudo-element parsing sometimes flags rules as invalid (P:first-letter{ color: red; }) [strict/quirks mode fix]"
Improving the CSS 2.1 strict parser for IE 7

Tags: , ,

Wednesday, August 31, 2005

Google Desktop and Firefox

Some may have figured this out already, or use the GDS install tool at Horopter.com (which also contains instruction on how to do it manually). There is an easier way than this (the files are actually part of the Google Desktop install):

  • Go to C:\Program Files\Google\Google Desktop Search
  • Copy the files GoogleDesktopMozilla.src and GoogleDesktopMozilla.png
  • Go to C:\Program Files\Mozilla Firefox\searchplugins
  • Then paste the files into this folder

You can also create a batch script to do it as well:

@echo off
cd "%ProgramFiles%\Google\Google Desktop Search\"
echo Copying GoogleDesktopMozilla.src
copy GoogleDesktopMozilla.src "%ProgramFiles%\Mozilla Firefox\searchplugins\"
echo Copying GoogleDesktopMozilla.png
copy GoogleDesktopMozilla.png "%ProgramFiles%\Mozilla Firefox\searchplugins\"

Tags: , ,

Friday, August 26, 2005

LinkList Class (JavaScript, HTML)

Client-side version of LinkList Class (C#, ASP.NET). Works in a similar way:

var links = new WebDeveloperBlog.LinkList();
links.Add("Home", "home.aspx", "Home Page");
links.Add("Page 1", "test.html");
links.Add("Page 2", "page2.aspx");
links.Add("Page 3", "page3.aspx");
// need to set CssClass for 'Inline' and 'Block' types
links.CssClass = "myclass";
// use inline type (surround with span tags)
links.ListType = "Inline";
document.write("<p>Inline ListType<\/p>" + links.ToString());
// use block type (surround with div tags)
links.ListType = "Block";
// change separator
links.Separator = " | ";
document.write("<p>Block ListType<\/p>" + links.ToString());
// use ordered list type (surround with ol, li tags)
links.ListType = "OrderedList";
document.write("<p>OrderedList ListType<\/p>" + links.ToString());
// use unordered list type (surround with ul, li tags)
links.ListType = "UnorderedList";
document.write("<p>UnorderedList ListType<\/p>" + links.ToString());

The code:

if(typeof WebDeveloperBlog != "object") {
 var WebDeveloperBlog = new Object();
}

WebDeveloperBlog.LinkList = function()
{
 // keeps track of the links, not the be modified
 this.Links = new Array();
 this.CssClass = null;
 this.Separator = " > ";
 // ListType can be "Block", "Inline", "UnorderedList" or "OrderedList"
 this.ListType = "UnorderedList";
}
WebDeveloperBlog.LinkList.prototype =
{
 Add : function(text,url,tooltip) {
  if(this.Links) {
   this.Links.push(new Array(text,url,tooltip));
  }
  return new Array(text,url,tooltip);
 },
 ToString : function() {
  var sb = new String();
  if(this.ListType == "UnorderedList" || this.ListType == "OrderedList" ) {
   if(this.ListType == "UnorderedList") {
    sb = sb.concat("<ul");
   } else {
    sb = sb.concat("<ol");
   }
   if(this.CssClass) {
    sb = sb.concat(" class=\"" + this.CssClass + "\"");
   }
   sb = sb.concat(">");
  }
  if (this.CssClass && this.ListType == "Inline") {
   sb = sb.concat("<span class=\"" + this.CssClass + "\">");
  }
  if (this.CssClass && this.ListType == "Block")  {
   sb = sb.concat("<div class=\"" + this.CssClass + "\">");
  }
  for(i=0;i<links.Links.length;i++) {
   if(i!=0 && (this.ListType == "Inline" || this.ListType == "Block")) {
    sb = sb.concat(this.Separator);
   }
   if(this.ListType == "UnorderedList" || this.ListType == "OrderedList" ) {
    sb = sb.concat("<li>");
   }
   if(this.Links[i][1] != location.href) {
    sb = sb.concat("<a href=\"" + this.Links[i][1] + "\"");
    // if a tooltip is defined, add it
    if(this.Links[i][2]) {
     sb = sb.concat(" tooltip=\"" + this.Links[i][2] + "\"");
    }
    sb = sb.concat(">" + this.Links[i][0] + "<\/a>");
   } else {
    sb = sb.concat(this.Links[i][0]);
   }
   if(this.ListType == "UnorderedList" || this.ListType == "OrderedList" ) {
    sb = sb.concat("<\/li>");
   }
  }
  if (this.CssClass && this.ListType == "Inline") {
   sb = sb.concat("<\/span>");
  }
  if (this.CssClass && this.ListType == "Block") {
   sb = sb.concat("<\/div>");
  }
  if (this.ListType == "OrderedList") {
   sb = sb.concat("<\/ol>");
  }
  if (this.ListType == "UnorderedList") {
   sb = sb.concat("<\/ul>");
  }
  return sb;
 }
}

Tags: , ,

Wednesday, August 24, 2005

Google Talk

Seems Google Talk, Google's instant messenger service, is now available. Uses the open source Jabber/XMPP protocol. Because of this, it is more cross platform friendy - i.e. you can cmmunicate with users on Mac, Linux etc - but not with AIM or MSN Messenger users. Requires a Gmail account. Very basic, no rich text or smilies. Links to Gmail inbox and allows you to email by clicking the familiar Gmail logo next to a name.


Tags: ,

Tuesday, August 23, 2005

Get tags using CSS selectors (Javascript)

These functions query a web page and gets all elements using CSS selectors. Could be seen as more powerful versions of getElementByTagName. cssQuery is by the author of IE7 (not the new browser being developed by Microsoft, but a hack to improve CSS support in IE 5 or later). It has recently had an update to cssQuery Version 2 to support more selectors. getElementsBySelector is similar to this and is less powerful and is used via document.getElementsBySelector.

An example of where this might be useful is if you wanted to change all links that opened in a new window to open in the current window instead and be made bold:

var tags = cssQuery("a[target='_blank']");
for(i=0;i<tags.length;i++) {
  tags[i].setAttribute("target", "");
  tags[i].style.fontWeight = "bold";
}


Tags: , ,

Thursday, August 18, 2005

LinkList Class (C#, ASP.NET)

This class can be used to generate a list of links that could be used for breadcrumbs or menu navigation. Add items to the list as follows (1st parameter is text, 2nd is the page url and 3rd is the tooltip, which is optional):

LinkList links = new LinkList();
links.Add(new LinkList.Link("Home", ResolveUrl("home.aspx"), "Home Page"));
links.Add(new LinkList.Link("Page 1", ResolveUrl("page1.aspx")));
links.Add(new LinkList.Link("Page 2", ResolveUrl("page2.aspx")));
links.Add(new LinkList.Link("Page 3", ResolveUrl("page3.aspx")));
// need to set CssClass for 'Inline' and 'Block' types
links.CssClass = "myclass";

There are four types of list types. Shown in the order they are added in. Also, if the current page you are on is the same as one in the list, the text is displayed instead of the link.

One is 'Inline', which surrounds the links with a span tag (only if you set the CssClass to a non-blank string) and separates the links with whatever you define (the default is the > symbol):

// use inline type (surround with span tags)
links.ListType = LinkList.ListTypes.Inline;
this.Controls.Add(new LiteralControl("<p>Inline ListType</p>"));
this.Controls.Add(new LiteralControl(links.ToString()));

Inline ListType

Home > Page 1 > Page 2 > Page 3

Another is 'Block' (works in same way as 'Inline', but uses a div tag):

// use block type (surround with div tags)
links.ListType = LinkList.ListTypes.Block;
// change separator
links.Separator = " | ";
this.Controls.Add(new LiteralControl("<p>Block ListType</p>"));
this.Controls.Add(new LiteralControl(links.ToString()));

Block ListType

Another is 'OrderedList':

// use ordered list type (surround with ol, li tags)
links.ListType = LinkList.ListTypes.OrderedList;
this.Controls.Add(new LiteralControl("<p>OrderedList ListType</p>"));
this.Controls.Add(new LiteralControl(links.ToString()));

OrderedList ListType

  1. Home
  2. Page 1
  3. Page 2
  4. Page 3

Finally 'UnorderedList':

// use unordered list type (surround with ul, li tags)
links.ListType = LinkList.ListTypes.UnorderedList;
this.Controls.Add(new LiteralControl("<p>UnorderedList ListType</p>"));
this.Controls.Add(new LiteralControl(links.ToString()));

UnorderedList ListType

The code that actually does the work is as follows:

using System;
using System.Collections;
using System.Text;
using System.Web;

namespace WebDeveloperBlog
{  
 public class LinkList : CollectionBase
 {
  public class Link
  {
   private string url;
   public string Url
   {
    get
    {
     return url;
    }
    set
    {
     url = value;
    }
   }
   private string text;
   public string Text
   {
    get
    {
     return text;
    }
    set
    {
     text = value;
    }
   }
   private string tooltip;
   public string Tooltip
   {
    get
    {
     return tooltip;
    }
    set
    {
     tooltip = value;
    }
   }
   public Link(string text, string url)
   {
    this.Text = text;
    this.Url = url;
   }
   public Link(string text, string url, string tooltip)
   {
    this.Text = text;
    this.Url = url;
    this.Tooltip = tooltip;
   }
  }
  
  public string cssClass = string.Empty;
  public string CssClass
  {
   get
   {
    return (cssClass);
   }
   set
   {
    this.cssClass = value;
   }
  }
  
  public enum ListTypes
  {
   Inline, Block, OrderedList, UnorderedList
  }
  
  public ListTypes listType = ListTypes.Inline;
  public ListTypes ListType
  {
   get
   {
    return (listType);
   }
   set
   {
    this.listType = value;
   }
  }
  
  public string separator = " > ";
  public string Separator
  {
   get
   {
    return (separator);
   }
   set
   {
    this.separator = value;
   }
  }
  
  public override string ToString()
  {
   StringBuilder sb = new StringBuilder();
   if (ListType == ListTypes.OrderedList)
   {
    sb.Append("<ol");
    if (CssClass != string.Empty)
    {
     sb.Append(" class=\"" + CssClass + "\"");
    }
    sb.Append(">");
   }
   if (ListType == ListTypes.UnorderedList)
   {
    sb.Append("<ul");
    if (CssClass != string.Empty)
    {
     sb.Append(" class=\"" + CssClass + "\"");
    }
    sb.Append(">");
   }
   if (CssClass != string.Empty && ListType == ListTypes.Inline)
   {
    sb.Append("<span class=\"" + CssClass + "\">");
   }
   if (CssClass != string.Empty && ListType == ListTypes.Block)
   {
    sb.Append("<div class=\"" + CssClass + "\">");
   }
   foreach(Link item in this)
   {
    if(this.IndexOf(item)!=0 && (ListType == ListTypes.Inline || ListType == ListTypes.Block))
    {
     sb.Append(HttpContext.Current.Server.HtmlEncode(Separator));
    }
    if (ListType == ListTypes.OrderedList || ListType == ListTypes.UnorderedList)
    {
     sb.Append("<li>");
    }
    if(item.Url != HttpContext.Current.Request.Url.AbsolutePath)
    {
     sb.Append("<a href=\"" + item.Url + "\"");
     if (item.Tooltip != null)
     {
      sb.Append(" title=\"" + item.Tooltip + "\"");
     }
     sb.Append(">" + item.Text + "</a>");
    }
    else
    {
     sb.Append(item.Text);
    }
    if (ListType == ListTypes.OrderedList || ListType == ListTypes.UnorderedList)
    {
     sb.Append("</li>");
    }
   }
   if (CssClass != string.Empty && ListType == ListTypes.Inline)
   {
    sb.Append("</span>");
   }
   if (CssClass != string.Empty && ListType == ListTypes.Block)
   {
    sb.Append("</div>");
   }
   if (ListType == ListTypes.OrderedList)
   {
    sb.Append("</ol>");
   }
   if (ListType == ListTypes.UnorderedList)
   {
    sb.Append("</ul>");
   }
   return sb.ToString();
  }
  
  public Link this[int index]
  {
   get
   {
    return ((Link)(this.List[index]));
   }
   set
   {
    this.List[index] = value;
   }
  }
  
  public int Add(Link value)
  {
   return this.List.Add(value);
  }
  
  public void Insert(int index, Link value)
  {
   this.List.Insert(index, value);
  }
  
  public int IndexOf(Link value)
  {
   return this.List.IndexOf(value);
  }
  
  public bool Contains(Link value)
  {
   return this.List.Contains(value);
  }
  
  public void Remove(Link value)
  {
   this.List.Remove(value);
  }
  
  public void CopyTo(Link[] array, int index)
  {
   this.List.CopyTo(array, index);
  }
 }
}

Tags: , ,

Tuesday, August 16, 2005

Recursive File List Control v2 (ASP.NET)

Much like the original Recursive File List Control, this user control lists files and folders within a virtual web folder. Improvements include - excludes directories ending in '_file' (i.e. those created by Internet Explorer when you download a web page), excludes files beginning with '~$' (i.e. temporary documents generated by Microsoft Office applications), multiple instances can be placed on a web page, postback does not end up causing duplication of list and it takes into account other querystring parameters that may be passed on to the page.

Control (filelist.ascx)

<%@ Control Language="C#" src="filelist.ascx.cs" Inherits="WebDeveloperBlog.RecursiveFileList" %>

Code behind (filelist.ascx.cs)

using System;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebDeveloperBlog
{
 public class RecursiveFileList : UserControl
 {
  protected HyperLink lnkReset;
  protected Literal FileList;
  
  /// <summary>
  ///  The virtual folder is the initial folder to start with, default root of application, but can be overridden by calling page
  /// </summary>
  public string VirtualFolder
  {
   get 
   {
    if (ViewState["virtualFolder"]==null)
    {
     ViewState["virtualFolder"] = "~/";
    }
    return ViewState["virtualFolder"].ToString();
   }
   set
   {
    ViewState["virtualFolder"] = value;
   }
  }
  /// <summary>
  ///  List of file types to show. Set up in the Control_Load function
  /// </summary>
  private ArrayList fileTypes = new ArrayList();
  
  /// <summary>
  ///  For internal use only
  /// </summary>
  private ArrayList folders;
   
  /// <summary>
  ///  List of folders to be show files/folders in
  /// </summary>
  protected ArrayList Folders
  {
   get
   {
    if (folders == null)
    {
     if (UrlPathInfo != null)
     {
      folders = new ArrayList(UrlPathInfo.Split(';'));
     }
     else
     {
      folders = new ArrayList();
     }
    }
    return folders;
   }
   set
   {
    folders = value;
   }
  }
  
  /// <summary>
  ///  The path to the aspx page calling this control
  /// </summary>
  private string UrlPath
  {
   get
   {
    return HttpContext.Current.Request.Path;
   }
  }
  
  /// <summary>
  ///  The folders that are to be filtered. Used getting the folders from the Folders array list
  /// </summary>
  private string UrlPathInfo
  {
   get
   {
    return HttpContext.Current.Request.QueryString[FilterFolderParameter];
   }
  }
  
  /// <summary>
  ///  The query parameter to use when checking which folders to display the folder/file contents of
  /// </summary>
  private string FilterFolderParameter
  {
   get
   {
    return this.ClientID.ToString() + "folders";
   }
  }
  
  /// <summary>
  ///  Builds a list of folders from the Folders array list using ; as the deliminator
  /// </summary>
  private string BuildFolderList
  {
   get
   {
    string strList = string.Empty;
    for(int i=0; i<Folders.Count; i++)
    {
     strList += HttpContext.Current.Server.UrlEncode(Folders[i].ToString()) + ";";
    }
    if (strList != string.Empty)
    {
     strList = strList.Substring(0, strList.LastIndexOf(';'));
    }
    return strList;
   }
  }
  #region Web Form Designer generated code
  override protected void OnInit(EventArgs e)
  {
   //
   // CODEGEN: This call is required by the ASP.NET Web Form Designer.
   //
   InitializeComponent();
  }
  /// <summary>
  ///  Required method for Designer support - do not modify
  ///  the contents of this method with the code editor.
  /// </summary>
  private void InitializeComponent()
  {
   this.Load += new System.EventHandler(this.Control_Load);
  }
  #endregion
  private void Control_Load(object sender, EventArgs e)
  {
   // add file types
   fileTypes.Add("doc");
   fileTypes.Add("rtf");
   fileTypes.Add("xls");
   fileTypes.Add("pdf");
   // add reset list link if not already added
   if (lnkReset == null)
   {
    lnkReset = new HyperLink();
    lnkReset.Text = "Reset list '" + VirtualFolder + "'";
    this.Controls.Add(lnkReset);
   }
   // set result link to path of current page
   string resetUrl = UrlPath;
   NameValueCollection q = new NameValueCollection(HttpContext.Current.Request.QueryString);
   q.Remove(FilterFolderParameter);
   for (int i = 0; i <= q.Count - 1; i++)
   {
    if (i != 0)
    {
     resetUrl += "&amp;";
    }
    else
    {
     resetUrl += "?";
    }
    resetUrl += q.GetKey(i) + "=" + q.Get(i);
   }
   lnkReset.NavigateUrl = resetUrl;
   // add file list Literal control if not on page
   if (FileList == null)
   {
    FileList = new Literal();
    this.Controls.Add(FileList);
   }
   // recurse folder starting with the supplied virtual folder
   if (!Page.IsPostBack)
   {
    RecurseFolders(VirtualFolder);
   }
  }
  
  /// <summary>
  ///  Check if in Folders array list
  /// </summary>
  private bool InFolders(string s)
  {
   for(int i=0; i<Folders.Count; i++)
   {
    if(Folders[i].ToString() == s)
    {
     return true;
    }
   }
   return false;
  }
  
  /// <summary>
  ///  Check if file is one that is allowed
  /// </summary>
  private bool AllowedFileType(string fileExt)
  {
   for(int i=0; i<fileTypes.Count; i++)
   {
    if(fileTypes[i].ToString() == fileExt.ToLower())
    {
     return true;
    }
   }
   return false;
  }
  
  /// <summary>
  ///  Recurse folders in path, excluding those that aren't in the Folders array list
  /// </summary>
  private void RecurseFolders(string path)
  {
   // Open the list
   FileList.Text += "<ul>";
   string mappedRoot = HttpContext.Current.Server.MapPath(path);
   HttpContext.Current.Trace.Write("WebDeveloperBlog.RecursiveFileList", "Folder: " + mappedRoot);
   string[] folders = null;
   try
   {
    folders = Directory.GetDirectories(mappedRoot);
    // Iterate through each folder
    foreach (string folder in folders)
    {
     // ignore folders ending in _files (these are folders used when saving web pages from Internet Explorer)
     if (folder.Substring(folder.Length - 6) == "_files")
     {
      continue;
     }
     string virtfolder = folder.Replace(mappedRoot, string.Empty);
     string subFolder = path + virtfolder + "/";
     string[] subfolders = Directory.GetDirectories(folder);
     string[] files = Directory.GetFiles(folder);
     string whichfolders = string.Empty;
     HttpContext.Current.Trace.Write("WebDeveloperBlog.RecursiveFileList", folder + "\n Sub folder count: " + subfolders.Length + "\n File count: " + files.Length);
     if (InFolders(subFolder))
     {
      Folders.Remove(subFolder);
      whichfolders = BuildFolderList;
      Folders.Add(subFolder);
     }
     else
     {
      Folders.Add(subFolder);
      whichfolders = BuildFolderList;
      Folders.Remove(subFolder);
     }
     NameValueCollection q = new NameValueCollection(HttpContext.Current.Request.QueryString);
     q[FilterFolderParameter] = whichfolders;
     if (q[FilterFolderParameter] == string.Empty)
     {
      q.Remove(FilterFolderParameter);
     }
     FileList.Text += "<li><a href=\"" + UrlPath;
     for (int i = 0; i <= q.Count - 1; i++)
     {
      if (i != 0)
      {
       FileList.Text += "&amp;";
      }
      else
      {
       FileList.Text += "?";
      }
      FileList.Text += q.GetKey(i) + "=" + q.Get(i);
     }
     FileList.Text += "\">" + HttpContext.Current.Server.HtmlEncode(virtfolder) + "</a>";
     if (InFolders(subFolder))
     {
      // recurse sub folder
      FileList.Text += Environment.NewLine;
      RecurseFolders(subFolder);
     }
     FileList.Text += "</li>" + Environment.NewLine;
    } 
   }
   catch (System.Exception ex)
   {
    HttpContext.Current.Trace.Warn("WebDeveloperBlog.RecursiveFileList", ex.Source, ex);
   }
   try
   {
    string[] files = Directory.GetFiles(mappedRoot);
    // Iterate through the files in this folder
    if(files.Length == 0)
    {
     if (folders.Length == 0)
     {
      FileList.Text += "<li>No files</li>" + Environment.NewLine;
     }
    }
    else
    {
     foreach (string file in files)
     {
      string fileName = file.Replace(mappedRoot, string.Empty);
      // ignore files beginning with ~$ (these are files generated by Microsoft Office applications)
      if (fileName.Substring(0,2) == "~$")
      {
       continue;
      }
      if (!AllowedFileType(GetExt(fileName))) continue;
      // link to file
      FileList.Text += "<li> File: " + "<a href=\"" + path + fileName + "\">" + HttpContext.Current.Server.HtmlEncode(RemoveExt(fileName)) + "</a></li>";
      // Put the fileName in the textbox
      FileList.Text += Environment.NewLine;
     }
    }
   }
   catch (System.Exception ex)
   {
    HttpContext.Current.Trace.Warn("WebDeveloperBlog.RecursiveFileList", ex.Source, ex);
   }
   // Close the list
   FileList.Text += "</ul>" + Environment.NewLine;
  }
  
  /// <summary>
  ///  Remove file extension from the supplied file name
  /// </summary>
  private string RemoveExt(string fileName)
  {
   return fileName.Substring(0,fileName.LastIndexOf('.'));
  }
  
  /// <summary>
  ///  Get the extension from the supplied file name
  /// </summary>
  private string GetExt(string fileName)
  {
   int dot = fileName.LastIndexOf('.') + 1;
   return fileName.Substring(dot, fileName.Length - dot);
  }
 }
}

Sample page (filelist.aspx)

<%@ Page Language="C#" Trace="False" ContentType="text/html" ResponseEncoding="iso-8859-1" %>
<%@ Register TagPrefix="Files" TagName="List" Src="filelist.ascx" %>
<html>
<head>
<title>File listing</title>
</head>
<body>
<form runat="server">
 <Files:List runat="server" VirtualFolder="/virtualdir/" />
 <Files:List runat="server" VirtualFolder="/virtualdir2/" />
</form>
</body>
</html>

Tags: , ,