JavaScript functions to escape and unescape HTML

by timvasil 12/28/2008 9:10:00 PM

JavaScript doesn't have built-in functions to escape or unescape HTML, which may come in handy for certain DOM manipulations or AJAX scripting.  Here are the custom functions I wrote to handle these tasks.  I've tested the implementation with both IE and Firefox.

var g_oHtmlEncodeElement;

function htmlEscape(text)
{
    g_oHtmlEncodeElement = g_oHtmlEncodeElement || document.createElement("div");
    g_oHtmlEncodeElement.innerText = g_oHtmlEncodeElement.textContent = text;
    return g_oHtmlEncodeElement.innerHTML;
}

function htmlUnescape(html)
{
    g_oHtmlEncodeElement = g_oHtmlEncodeElement || document.createElement("div");
    g_oHtmlEncodeElement.textContent = g_oHtmlEncodeElement.innerText = "";
    g_oHtmlEncodeElement.innerHTML = html;
    return g_oHtmlEncodeElement.innerText || g_oHtmlEncodeElement.textContent;
}

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

JavaScript | AJAX | IE | Firefox

Converting an Oracle interval to total seconds

by timvasil 12/22/2008 5:19:00 PM

If you subtract one timestamp from another in Oracle, the result is an interval type.  This is similar to how subtracting a DateTime from another in .NET yields a TimeSpan.  Unfortunately, unlike .NET, Oracle provides no simple equivalent to TimeSpan.TotalSeconds.

Here's the SQL to accomplish it.  Note that fractions of a second are included in the result.

declare
  diff interval day to second :=
        cast('18-DEC-08 11.00.00 PM' as timestamp) - cast('18-DEC-08 9.59.58.5 PM' as timestamp);
  secs number;
begin
  select
    extract(day from diff) * 86400
    + extract(hour from diff) * 3600
    + extract(minute from diff) * 60
    + extract(second from diff)
 into
  secs
  from dual;
 dbms_output.put_line(secs);
end;

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Oracle

Setting a sequence's next value in Oracle

by timvasil 11/20/2008 12:10:00 PM

You can't set the next value of a sequence directly in Oracle; you have to drop and recreate the sequence.  Here's a way to do it if you need to set the next value to the largest value in a particular column plus 1:

declare
    nextId number;
begin
    select coalesce(max(PrimaryID), 0) + 1 into nextId from Table;
    execute immediate 'drop sequence PrimaryIDSeq';
    execute immediate 'create sequence PrimaryIDSeq minvalue ' || nextId;
end;

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Oracle

Fixing "Instance names used for writing to custom counters must be 127 characters or less."

by timvasil 11/11/2008 12:39:00 PM

If you've run a unit test in Visual Studio 2008 that utilizes database connectivity, you may have seen this error when creating a connection object:

Instance names used for writing to custom counters must be 127 characters or less.

The problem crops up when you're running the test within a directory structure with a fairly long name, i.e. you're organizing your code well and giving your projects descriptive names.  Well, this error is punishment for being organized.

There are several Microsoft bug reports on the issue.  One has been ignored, the other closed.

There are posts on the web with some workarounds, but none worked for me, perhaps because I'm using Visual Studio 2008?  No matter what I tweaked in .testrunconfig I was still getting the error.  The other approach--shortening the pathname--was really a non-starter.  I wasn't going to compromize well-thought-out organization to get around a Microsoft bug.

So I took a peek at the source of the problem as hinted by the call stack when the error appeared.  It's a method in the internal DbConnectionPoolCounters class in the System.Data.ProviderBase assembly.  Here's the code:

private string GetInstanceName()
{
    string assemblyName = this.GetAssemblyName();
    if (ADP.IsEmpty(assemblyName))
    {
        AppDomain currentDomain = AppDomain.CurrentDomain;
        if (currentDomain != null)
        {
            assemblyName = currentDomain.FriendlyName;
        }
    }
    int currentProcessId = SafeNativeMethods.GetCurrentProcessId();
    return string.Format(null, "{0}[{1}]", new object[] { assemblyName, currentProcessId }).Replace('(', '[').Replace(')', ']').Replace('#', '_').Replace('/', '_').Replace('\\', '_');
}

The instance name of the performance counter is being built, in part, from the name of the AppDomain.  When running tests in Visual Studio, this name can be very, very long, especially if your project's home has a long pathname.

The workaround I pursued, then, is to shorten the name of the app domain.  While AppDomain.FriendlyName is a read-only property, and there's no private field of the AppDomain class to change it, there is a private extern method of AppDomain called nSetupFriendlyName.  And, like magic, if you invoke this method and give the app domain a shorter name, problem solved!

Here's the workaround, utilizing a little reflection magic:

[ClassInitialize]
public static void ClassInitialize(TestContext testContext)
{
    typeof(AppDomain).GetMethod("nSetupFriendlyName", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(AppDomain.CurrentDomain, new object[] { "Test" });
}

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Visual Studio | .NET Framework | C# | ADO.NET | MSTest

Take total control over the head tag in ASP.NET

by timvasil 10/22/2008 2:44:00 AM

When you use the tag, such as on a master page, the HtmlHead control does the rendering work. The results are pretty dreadful; spacing is pretty screwy for one thing. But that's something I can live with.

One thing I can't live with, however, is third party components like DevExpress adding bogus (and redundant!) stylesheet links within the head tag! I wanted to take control of that tag to filter out these tags, but found HtmlHead to be a sealed class. I can't tell you how many times I've tried to correct bad behavior through the well-established OO practice of inheritance only to find a "sealed" wall in my way. Personally, I think that keyword needs to go! But, alas, in this case there is a way to get around the constraint.

I didn't realize this until today, but ASP.NET has a mechanism for overriding how a control renders its content, even if that control is sealed. The magic is in browser adapters. I learned all about it here:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

ASP.NET

Xenocode Software Virtualization

by timvasil 10/11/2008 7:53:00 PM

Well, here's a new one.  Xenocode is offering software virtualization (as opposed to hardware virtualization).  You can use it to render that product installer obsolete.  Bundle all your DLLs, registry changes, and other program files into one self-sufficient EXE.  Pretty cool!

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Virtualization

Converting a Class Library to an MS Test Library

by timvasil 6/10/2008 5:15:00 PM

If you add the [TestMethod] attribute to methods in a regular class library, they won't show up in the test view or test editor.  You may see a message "no tests are loaded."  This happens because Visual Studio doesn't look for the attribute in projects that don't have special "I am a test" markings.  If you create a test project from scratch and add the code the problem will go away, but if you've spent time customizing a project, its references, etc., fear not; you don't need to start over.  Edit the .csproj (or .vbproj) file manually and add the following XML as a child of the first <PropertyGroup> element that appears:

<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Visual Studio | MSTest

WiX: DLL could not be loaded

by timvasil 6/6/2008 7:33:00 PM

Playing around with WiX 3.0, candle.exe started emitting a weird message and failing:

   WixUIExtension.dll could not be loaded

I fixed this by editing the WiX project file by hand and changing the HintPath to remove the ".dll" extension, i.e. instead of this:

   <HintPath>../path/WixUIExtension.dll</HintPath>

Use this:

   <HintPath>../path/WixUIExtension</HintPath>

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

WiX

Form.DefaultButton in Firefox

by timvasil 6/4/2008 11:53:00 AM

Setting the DefaultButton property on a form to an ImageButton, LinkButton, or Button with UseSubmitBehavior=false doesn't work on Firefox because the ASP.NET code hooking the Enter key on form submit looks for a "click" method on the button that Firefox does not support.

If you give your button a name attribute, say name='DefaultButton' for example, then throw the following JavaScript in a file that's included on all pages, it'll work.  The trick is to define the click method on Firefox's behalf.

setTimeout(function() { init(); }, 0);

// Fixup link buttons for FF
function init()
{
    if (document.getElementsByName)
    {
        var aoElements = document.getElementsByName("DefaultButton");
        if (aoElements)
        {
            for (var i = 0; i < aoElements.length; i++)
            {
                if (aoElements[i].click == undefined)
                {
                    aoElements[i].click = aoElements[i].onclick;
                }
            }
        }
    }
}


Update on 6/9/08:

That fix apparently doesn't work completely, as when you hit <Enter> in a textarea the form is submitted.  That's a critical flaw.  I didn't want to wholesale replace ASP.NET's WebForm_FireDefaultButton method, but, c'mon, there's only so much tolerance anyone can have for hunting down and working around other people's bugs. 

So, here's a tweaked version of the function that fixes default button handling and works across browsers.  In order to use this patched function, you need to define it *after* all other JavaScript files and also after <ajaxToolkit:ToolkitScriptManager /> if you happen to be using it.

var __defaultFired;
function WebForm_FireDefaultButton(event, target) {
    var element = event.target || event.srcElement;
    if (!__defaultFired && event.keyCode == 13 && !(element && (element.tagName.toLowerCase() == "textarea"))) {
        var defaultButton;
        if (__nonMSDOMBrowser)
            defaultButton = document.getElementById(target);
        else
            defaultButton = document.all[target];

        if (typeof(defaultButton.click) != "undefined") {
            __defaultFired = true;
            defaultButton.click();
            event.cancelBubble = true;
           
            if (event.stopPropagation) event.stopPropagation();
            return false;
        }
        if (typeof(defaultButton.onclick) != "undefined") {
            __defaultFired = true;
            defaultButton.onclick();
            event.cancelBubble = true;
           
            if (event.stopPropagation) event.stopPropagation();
            return false;
        }

    }
    return true;
}

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

ASP.NET | JavaScript | Firefox

Fix for IE's 'Operation Aborted' error

by timvasil 5/28/2008 11:17:00 PM

If you've done any dynamic manipulation of web pages, especially with AJAX or any other kind of web magic in the mix, you've run into IE's dreaded "Operation Aborted" error.

Here are some official comments on the issue:

The blog post says that if you aren't meeting all 3 conditions, you're OK.  In my case, I believe I wasn't meeting the 3 conditions, and yet the problem persisted.  It was very hard to reproduce, too.  I had to have the offending website in the "Internet Zone" and experience some network lag to make it happen.

In the end, I found that if I replaced this line:

   document.body.appendChild(element);

With this one:

   document.body.insertAdjacentElement('afterBegin', element);

Everything worked fine.  Of course, this trick works only if you're inserting a node whose position isn't important, e.g. it's a div you're going to give an absolute position anyway.

Along the way I had tried wrapping the appendChild calls in a try/catch block, but unfortunatley the append would work fine, and then IE would complain with "Operation Aborted" only after the JavaScript finished.  I was hoping for a global exception handler to trap the problem, but fortunately insertAdjacentElement fixes the issue!

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

JavaScript | IE

 

About the author

Tim Vasil Tim Vasil
I'm a software engineer living in Cambridge, MA.

E-mail me Send mail

Search

Calendar

<<  January 2009  >>
MoTuWeThFrSaSu
2930311234
567891011
12131415161718
19202122232425
2627282930311
2345678

View posts in large calendar

Recent comments