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: , ,