code.nontalk.com

Code snippets for C#, T-SQL and JavaScript

Tuesday, April 24, 2007

Convert Relative Paths to Absolute Using Regular Expressions

I ran into a situation where I needed to screen scrape some content from a site and display it on my own site. This works really well except for dependent files like javascripts, SWFs and images that had src attributes with relative paths. So I figured it wouldn't be that hard to create a helper method to find and replace them using Regular Expressions. So here it is:

public static String ConvertRelativePathsToAbsolute(String text, String absoluteUrl)
{
	String value = Regex.Replace(text,
		"<(.*?)(src|href)=\"(?!http)(.*?)\"(.*?)>",
		"<$1$2=\"" + absoluteUrl + "$3\"$4>",
		RegexOptions.IgnoreCase | RegexOptions.Multiline);
	
	// Now just make sure that there isn't a // because if
	// the original relative path started with a / then the
	// replacement above would create a //.

	return value.Replace(absoluteUrl + "/", absoluteUrl);
}

Sample Usage:

String html = "<p><img src=\"images/dot.gif\" alt=\"test\" /></p>";
String baseUrl = "http//www.nontalk.com/";
String replacedHtml = ConvertRelativePathsToAbsolute(html, baseUrl);
// replacedHtml => <p><img src="http://www.nontalk.com/images/dot.gif" alt=\"test\" /></p> 

Labels: ,

Thursday, November 02, 2006

CSS + Javascript Workaround for Styling Form Inputs in Internet Explorer (IE)

Checkboxes, textboxes, radio buttons and submit buttons all share the same HTML tag name <input>. The type attribute is what distinguishes each element from each other. For example:

Markup Result
<input type="text" />
<input type="checkbox" />
<input type="radio" />
<input type="button" value="button" />

CSS2 gives us the the ability to create style rules based on attributes of elements. So we could create a rule such as:

input[type='button'] {
  border: dashed 2px green;
}
input[type='text'] {
  border: solid 2px red;
}

This would apply a dashed green border around all the buttons on a page and a solid red border around all text boxes. Unfortunately....you guessed it....Internet Explorer does not support attribute selectors in CSS. So if we want apply different styles to each type of input, then we either have to create inline styles like

<input type="text" style="border: solid 2px red;" />
or apply a class to each element and then create a corresponding CSS class definition.
<style type="text/css">
  .textbox { border: solid 2px red; }
</style>
<input type="text" class="textbox" />

Using inline styles is almost never a good idea, and adding a class attribute on every form element is tedious, so I wanted to figure out a way to make this easy on all of us until the day when Microsoft decides to support CSS more fully.

My idea was to create a JavaScript which would find each <input> element on the page and add a class name corresponding to the type of <input> it is.

View an Example

Here is the Javascript code:

<script type="text/javascript">
    function addClassNamesToInputs() {
        var inputs = document.getElementsByTagName("input");
        for (var i=0; i<inputs.length; i++) {
            inputs[i].className = inputs[i].type;
        }
    }
</script>

And here is the CSS which would go along with it:

<style type="text/css">
    body { font-family: sans-serif; font-size: 75%; }
    
    input {
        border: solid 2px red;
        }
    input.radio {
        border: none;
        }
    input.checkbox {
        border: none;
        width: 30px;
        height: 30px;
        }
    input.submit {
        border: solid 2px black;
        font-family: monospace;
        font-size: 18px;
        }
    input.reset {
        border: solid 2px green;
        font-family: Sans-Serif;
        font-size: 11px;
        font-weight: bold;
        }
    input.button {
        border: solid 2px blue;
        font-family: Serif;
        font-size: 25px;
        }
</style>

If you use the prototype.js library, you would want to use the Element.addClassName() function in the script because, the script above will overwrite any existing class name

<script type="text/javascript">
    function addClassNamesToInputs() {
        var inputs = document.getElementsByTagName("input");
        for (var i=0; i<inputs.length; i++) {
            inputs[i].addClassName(inputs[i].type);
        }
    }
</script>

Labels: , ,

Thursday, October 19, 2006

Read/Modify Querystring Variables with Javascript

There are a lot of nice little javascripts out there which allow you to easily read values from the query string, but I wanted a script that would allow you to easily read and modify querystring values. I created the following script which relies on the Prototype library (version 1.5.0_rc0):

/*--------------------------------------------------------------------------*/
/*  QueryString Object
*  (c) 2006 Jesse Gavin http://code.nontalk.com/
*
*  Depends upon:
*  - Prototype JavaScript framework, version 1.5.0_rc0
*    (c) 2005 Sam Stephenson <sam@conio.net>
*
*  This script is freely distributable under the terms of an MIT-style license.
*  For details, see: http://code.nontalk.com/
*
/*--------------------------------------------------------------------------*/

var QueryString = {
   params : $H(window.location.search.toQueryParams()),
  
   get : function(key, defaultValue) {
       if (defaultValue == null) defaultValue = null;
       var value = this.params[key]
       if (value==null) value = defaultValue;
       return value;
   },
  
   set : function(key, value) {
       this.params[key] = value;
   },
  
   remove : function(key) {
       this.params = this.params.collect(function(param) {
           if (key != param.key) return param;
       }).compact();
   },
  
   make : function() {
       return "?" + this.params.collect(function(param) {
           return escape(param.key) +"="+ escape(param.value);
       }).join("&");
   },
  
   go : function() {
       window.location.href = location.pathname + this.make();
   }
}

Download QueryString.js

P.S. I got the idea for this from a CodeProject article written by Uwe Keim. He created a C# class to manage QueryString variables, which does all this and more on the server side.

Labels: