Steve Wellens

Programming in the .Net environment

Sponsors

Links

January 2011 - Posts

The jQuery ‘live(…)’ Function

[UPDATE]

The live function has been deprecated: "As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers."

 http://api.jquery.com/live/

 

On the Asp.Net forums where I am a moderator, a developer was having a problem hooking up click events to the rows of a dynamically created html table. He didn't want to embed the onclick handler in the table rows as each row was created so he tried using jQuery. The problem was he was trying to hook up the click event before the table was created. How to help him?

The jQuery live(…) function comes to the rescue!

What can I say about jQuery and the live(…) function? It's like falling in love with a beautiful woman, who is kind, can cook and keeps a tidy house. So you marry her and then you find out that she's heiress to a trust fund worth millions!

The jQuery live(…) function is an esoteric function; in fact, you may never find cause to use it in your entire career. But if you do use it, it can solve some problems very elegantly.

To put it succinctly, instead of this:

    $('#MyTable tr').click(function()
    {
        alert("Table row clicked");
    })

Use this:

    $('#MyTable tr').live('click', function()
    {
        alert("Table row clicked");
    })

The live(…) function causes the event handler to be automatically assigned to elements matching the selector…including elements that haven't been created yet. You heard that correctly. It assigns events to elements that don't exist.

As rows are created and added to the table element in question, they automatically get the event handler assigned.

While working on this I became curious and looked at the source code for the jQuery live(…) function. That was a mistake. A big mistake. There is a quote from Otto von Bismark that goes something like, "…two things you don't want to see made are sausage and legislation." I think we can add the jQuery source code to that list.  To be fair, I understand that jquery code runs on millions of browsers daily.  Sacrificing some readability and maintainability for performance is perfectly reasonable under these circumstances. 

Fortunately, the online documentation provides a good description of how the function works: http://api.jquery.com/live/

Bonus Information: While I was poking around in the jQuery source code (with a safety rope, hard hat and air-sickness bag) I happened across some lines like these:

    if ( name === "find" ) 
    if ( arguments.length === 2 )

I'd never seen this before and it's not even mentioned in a book called The JavaScript Bible. It's called the Identity Equal Operator (there is also an Identity Not Equal operator !==). It checks both type and value. In other words, it does not do a type conversion before checking for equality. Here's an illustration of how it works compared to the equality operator:

    var x = 3;

    // equality
    x == 3 is true
    x == '3' is true
    x == "3" is true

    // identity equality
    x === 3 is true
    x === '3' is false
    x === "3" is false

[Edit/Update]

It has been pointed out to me that jQuery 1.4 introduced the delegate(...) function which does the same thing as the live(...) function but inserts the event handler closer to the selected elements rather than at the root of the DOM so it's performance is better.  However, another person pointed out if you are attaching events to dozens of elements (say anchors) it's better to have a single handler at the top of the DOM.  Here is the best article I found discussing the differences: http://test.kingdesk.com/jquery/bind_live_delegate.php

 

I hope someone finds this useful.

Steve Wellens.

Posted: Jan 24 2011, 12:40 PM by SGWellens | with 2 comment(s)
Filed under: ,
Web.Config is Cached

There was a question from a student over on the Asp.Net forums about improving site performance. The concern was that every time an app setting was read from the Web.Config file, the disk would be accessed. With many app settings and many users, it was believed performance would suffer.

Their intent was to create a class to hold all the settings, instantiate it and fill it from the Web.Config file on startup. Then, all the settings would be in RAM. I knew this was not correct and didn't want to just say so without any corroboration, so I did some searching.

Surprisingly, this is a common misconception. I found other code postings that cached the app settings from Web.Config. Many people even thanked the posters for the code.

In a later post, the student said their text book recommended caching the Web.Config file.

OK, here's the deal. The Web.Config file is already cached. You do not need to re-cache it.

From this article http://msdn.microsoft.com/en-us/library/aa478432.aspx

It is important to realize that the entire <appSettings> section is read, parsed, and cached the first time we retrieve a setting value. From that point forward, all requests for setting values come from an in-memory cache, so access is quite fast and doesn't incur any subsequent overhead for accessing the file or parsing the XML.

The reason the misconception is prevalent may be because it's hard to search for Web.Config and cache without getting a lot of hits on how to setup caching in the Web.Config file.

So here's a string for search engines to index on: "Is the Web.Config file Cached?"

A follow up question was, are the connection strings cached?

Yes. http://msdn.microsoft.com/en-us/library/ms178683.aspx

At run time, ASP.NET uses the Web.Config files to hierarchically compute a unique collection of configuration settings for each incoming URL request. These settings are calculated only once and then cached on the server.

And, as everyone should know, if you modify the Web.Config file, the web application will restart.

I hope this helps people to NOT write code!  

Steve Wellens

Passing Strings by Ref

Humbled yet again…DOH! No matter how much experience you acquire, no matter how smart you may be, no matter how hard you study, it is impossible to keep fully up to date on all the nuances of the technology we are exposed to. There will always be gaps in our knowledge: Little 'dead zones' of uncertainty. For me, this time, it was about passing string parameters to functions. I thought I knew this stuff cold. First, a little review...

Value Types and Ref

Integers and structs are value types (as opposed to reference types). When declared locally, their memory storage is on the stack; not on the heap. When passed to a function, the function gets a copy of the data and works on the copy. If a function needs to change a value type, you need to use the ref keyword.  Here's an example:

    // ---- declaration -----------------
 
    public struct MyStruct
    {
        public string StrTag;
    }
 
    // ---- functions -----------------------
 
    void SetMyStruct(MyStruct myStruct)     // pass by value
    {
        myStruct.StrTag = "BBB";
    }
 
    void SetMyStruct(ref MyStruct myStruct)  // pass by ref
    {
        myStruct.StrTag = "CCC";
    }
 
    // ---- Usage -----------------------
 
    protected void Button1_Click(object sender, EventArgs e)
    {
        MyStruct Data;
        Data.StrTag = "AAA";
 
        SetMyStruct(Data);
        // Data.StrTag is still "AAA"
 
        SetMyStruct(ref Data);
        // Data.StrTag is now "CCC"
    }

No surprises here. All value types like ints, floats, datetimes, enums, structs, etc. work the same way.

And now on to...

Class Types and Ref

    // ---- Declaration -----------------------------
 
    public class MyClass
    {
        public string StrTag;
    }
 
    // ---- Functions ----------------------------
 
    void SetMyClass(MyClass myClass)  // pass by 'value'
    {
        myClass.StrTag = "BBB";
    }
 
    void SetMyClass(ref MyClass myClass)   // pass by ref
    {
        myClass.StrTag = "CCC";
    }
 
    // ---- Usage ---------------------------------------
 
    protected void Button2_Click(object sender, EventArgs e)
    {
        MyClass Data = new MyClass();
        Data.StrTag = "AAA";
 
        SetMyClass(Data);  
        // Data.StrTag is now "BBB"
 
        SetMyClass(ref Data);
        // Data.StrTag is now "CCC"
    }
 

No surprises here either. Since Classes are reference types, you do not need the ref keyword to modify an object. What may seem a little strange is that with or without the ref keyword, the results are the same: The compiler knows what to do.

So, why would you need to use the ref keyword when passing an object to a function?

Because then you can change the reference itself…ie you can make it refer to a completely different object. Inside the function you can do: myClass = new MyClass() and the old object will be garbage collected and the new object will be returned to the caller.

That ends the review. Now let's look at passing strings as parameters.

The String Type and Ref

Strings are reference types. So when you pass a String to a function, you do not need the ref keyword to change the string. Right? Wrong. Wrong, wrong, wrong.

When I saw this, I was so surprised that I fell out of my chair. Getting up, I bumped my head on my desk (which really hurt). My bumping the desk caused a large speaker to fall off of a bookshelf and land squarely on my big toe. I was screaming in pain and hopping on one foot when I lost my balance and fell. I struck my head on the side of the desk (once again) and knocked myself out cold. When I woke up, I was in the hospital where due to a database error (thanks Oracle) the doctors had put casts on both my hands. I'm typing this ever so slowly with just my ton..tong ..tongu…tongue.

But I digress. Okay, the only true part of that story is that I was a bit surprised.

Here is what happens passing a String to a function.

    // ---- Functions ----------------------------
 
    void SetMyString(String myString)   // pass by 'value'
    {
        myString = "BBB";
    }
 
    void SetMyString(ref String myString)  // pass by ref
    {
        myString = "CCC";
    }
 
    // ---- Usage ---------------------------------
 
    protected void Button3_Click(object sender, EventArgs e)
    {
        String MyString = "AAA";
 
        SetMyString(MyString);
        // MyString is still "AAA"  What!!!!
 
        SetMyString(ref MyString);
        // MyString is now "CCC"
    }

What the heck. We should not have to use the ref keyword when passing a String because Strings are reference types. Why didn't the string change? What is going on?  

I spent hours unssuccessfully researching this anomaly until finally, I had a Eureka moment:

This code:

String MyString = "AAA";

Is semantically equivalent to this code (note this code doesn't actually compile):

String MyString = new String();

MyString = "AAA";

Key Point: In the function, the copy of the reference is pointed to a new object and THAT object is modified. The original reference and what it points to is unchanged.

You can simulate this behavior by modifying the class example code to look like this: 

    void SetMyClass(MyClass myClass)  // call by 'value'
    {
        //myClass.StrTag = "BBB";
        myClass = new MyClass();
        myClass.StrTag = "BBB";
    }

Now when you call the SetMyClass function without using ref, the parameter is unchanged...just like the string example. 

I hope someone finds this useful.

Steve Wellens

Posted: Jan 09 2011, 02:40 PM by SGWellens | with 12 comment(s) |
Filed under:
More Posts