javascript, gists comments edit

I was messing around with relative paths to files (e.g., ../images/error.gif) and needed to convert them to absolute paths (e.g., http://server/images/error.gif) on the client but couldn’t figure out how. Then I saw this nifty trick to HTML encode things using jQuery and it gave me an idea.

String.toAbsolutePath = function(relativePath) {
  /// <summary>
  /// Converts a relative file path into an absolute file path.
  /// </summary>
  /// <param name="relativePath" type="String">
  /// The string with the relative path, like "../foo/bar.gif"
  /// </param>
  /// <returns type="String" />
  var path = $("<div style=\"background-image:url('" + relativePath + "');\"></div>").css("background-image");
  if (path.startsWith("url(")) {
    path = path.substring(4);
  }
  if (path.endsWith(")")) {
    path = path.substring(0, path.length - 1);
  }
  if (path.startsWith("\"")) {
    path = path.substring(1, path.length);
  }
  if (path.endsWith("\"")) {
    path = path.substring(0, path.length - 1);
  }
  return path;
}

Basically, I’m using the CSS style “background-image” and feeding in the relative path, then resolving it immediately. Turns out the browser converts that to an absolute path for you. At least, Firefox 3.5.3 and IE 7 do, which is what I was testing with at the time.

The path.startsWith and path.endsWith checks are because sometimes the URL comes back like:

url("http://server/images/error.gif")

…with the url(“”) wrapper, and sometimes it comes back like:

http://server/images/error.gif

…without the wrapper at all.

Note the String.startsWith and String.endsWith methods come from ASP.NET AJAX so if you wanted to do it in just jQuery, you’d have to regex your way out of it or do a little more brute force work.

Of course, in the end, I figured out a different way to do what I was doing so I didn’t actually need to convert the path at all, but I thought this was sort of neat so I’d post it for folks. I didn’t really test it in a bunch of browsers or anything, so YMMV. “Works on My Machine.”

aspnet, javascript, gists comments edit

I had to parse a culture-sensitive currency value from a string and couldn’t figure out how to do it. I’m using ASP.NET AJAX to do String.localeFormat("{0:c}", value) for writing a currency value to a textbox, but getting it back out… not so easy. The Number.parseLocale extension provided with ASP.NET AJAX is cool for parsing out numbers in a culture-sensitive fashion… if they don’t have a currency symbol.

So, time to hook that up. Here’s what I came out with:

Number.parseCurrency = function Number$parseCurrency(str) {
  /// <summary>
  /// Parses a string containing a culture-sensitive currency value into a number.
  /// </summary>
  /// <param name="str" type="String">
  /// The numeric string with optional currency symbol to convert into a number.
  /// </param>
  /// <returns type="Number" />
  var currencySymbol = Sys.CultureInfo.CurrentCulture.numberFormat.CurrencySymbol;
  var numberOnly = str.replace(/\s+/g, '').replace(eval("/\\" + currencySymbol + "/g"), '');
  var parsed = Number.parseLocale(numberOnly);
  if (isNaN(parsed)) {
    // Try all 5 possible negative number formats.
    var customCi = Sys.CultureInfo.InvariantCulture;
    for (var i = 0; i < 5; i++) {
      customCi.numberFormat.NumberNegativePattern = i;
      parsed = Number._parse(numberOnly, customCi);
      if (!isNaN(parsed)) {
        break;
      }
    }
  }
  return parsed;
}

What it’s doing:

  1. Get the currency symbol for the current culture.
  2. Take the currency-formatted string and remove all whitespace and that currency symbol. Now you have a number that is either positive or ostensibly adheres to one of the known negative number formats.
  3. Parse that string in a culture-sensitive fashion into a number. Usually this will work straight-off. Unfortunately, the negative currency format can sometimes differ from the negative number format. For example, a negative number might be -1.23, but a negative currency format might be like ($1.23). So if the parsing comes back as not-a-number, chances are that’s what you’re hitting.
  4. If the parsed value comes back as not-a-number, we know there are five pre-defined negative number formats that are possible in ASP.NET AJAX: ["(n)","-n","- n","n-","n -"] For each of those possible formats…
    1. Create a temporary culture, based on the Invariant culture, that uses the selected negative number pattern. (When you ask for the Invariant culture it actually creates a brand new instance every time, so doing this won’t change the built-in Invariant culture.)
    2. Try to manually parse the number given your custom culture.
    3. If it succeeded, return that value.

At the end of all that if you still come out with NaN, it’s not a currency value.

If someone knows a better way to do this, I’m all ears.

If you want it, go for it. YMMV, no warranty expressed nor implied. If you find a defect, post to the comments and I’ll update.

downloads, vs, coderush comments edit

This is sort of a niche thing, so if you don’t know what I’m talking about, don’t worry. However, people who write DXCore plugins (CodeRush/Refactor) sometimes need to do some action based on what context the user is currently in. For example, you may need to enable a function or hide a button or something if the user is in a designer screen. The problem is, it’s hard to debug that sort of thing - there’s nothing that says “here’s the context(s) you’re currently in” so when you’re writing your plugin you can do the right thing.

That’s what I made - a plugin that [optionally] polls for the list of contexts the user is currently in so you can debug the plugin you’re writing.

DX_ContextLab
Window

If you want it (or any of the other awesome FREE community plugins), head over to the DXCore Community Plugins site.

aspnet, javascript, gists comments edit

I’m working on a site where we’re using both ASP.NET AJAX and jQuery to get things done. This includes jQuery Validation for client-side validation functionality.

One of the things that comes with jQuery Validation is a $.validator.format method that replaces the {n} style parameters in a string with arguments - basically, a very lightweight String.format.

ASP.NET AJAX provides a really nice implementation of String.format that is pretty full-featured and understands format strings. For example, you can do String.format("{0:d}", mydate) to format a date in short date format. Snazzy stuff. Unfortunately, the jQuery Validation one isn't that robust... so I figured I'd marry the two worlds. Allow you to still use the $.validator.format` method, just like you always do, but under the covers it’ll pass through to ASP.NET AJAX to do the replacement/formatting.

Make sure you’ve got the ASP.NET AJAX, jQuery, and jQuery Validation script libraries registered in your page, then do this:

(function($) {
  if ($.validator) {
    $.validator.format = function(source, params) {
      if (arguments.length == 1)
        return function() {
          var args = $.makeArray(arguments);
          args.unshift(source);
          return $.validator.format.apply(this, args);
        };
      if (arguments.length > 2 && params.constructor != Array) {
        params = $.makeArray(arguments).slice(1);
      }
      if (params.constructor != Array) {
        params = [params];
      }
      var toEval = "String.localeFormat(source, __);";
      var paramEval = new Array();
      for (var i = 0; i < params.length; i++) {
        Array.add(paramEval, "params[" + i + "]");
      }
      toEval = toEval.replace(/__/, paramEval.join(","));
      return eval(toEval);
    };
  }
})(jQuery);

Basically we keep the currying bit that comes out of the box with $.validator.format but replace the bit that does the replacement work with the ASP.NET AJAX String.format. That should replace the existing $.validator.format method with a syntactically-and-functionally-equivalent, but slightly more robust, implementation.

UPDATE 9/30/09: The original version didn’t work if there was more than one parameter value you were validating against, like in a range where there’s a min and a max value. The new version takes that into account. The crazy eval junk at the end is because you can’t do String.localeFormat("...", Array) - the string formatting in ASP.NET AJAX doesn’t like it if you pass an array rather than an explicit list of arguments. The eval thing dynamically builds a valid statement like String.localeFormat(source, params[0], params[1]..., params[n]) and evaluates that so it works.

General Ramblings comments edit

Jenn and I went to see The Killers last night at the Memorial Coliseum. It was awesome.

Now, the opening bands - there were two - not so great. First up was The Nervous Wreckords, which we were a little late for, and Jenn fairly accurately described as “15 minutes of pain.” After that came Mariachi El Bronx, which was sort of modern-ish mariachi music. I didn’t think they were horrible (Jenn did), but it wasn’t great, either.

The Killers, on the other hand, put on an awesome show. They sang all the hits from their albums as well as a few lesser known songs. Jenn and I did our little “stand up by your seat and bob your head” dances for part of it. The thing I noticed was howinto it their drummer gets. The guy’s a wildman - great on the drums and really fun to watch.

The crowd was great, really into the whole thing, and all-in-all it was a fantastic show. Totally worth the price of admission.

Jenn got her very first concert shirt ever at this show, too, so a groundbreaking experience was had by all.