Jan
04
2009
0

jQuery and Event Delegation Example

I wanted to give some examples that actually run. The last post might have been a little abstract and brief.

First, don’t forget to link in the jQuery script.

<script src="jquery-1.2.6.js" type="text/javascript" charset="utf-8"></script>

Some CSS to pretty things up.

	.myContainer{
		width:300px;
		font-family:Arial;
	}

	.fooberry{
		margin:5px;
	}
	.summary{
		background-color:blue;
		color:white;
		padding:3px;
	}

	.details{
		background-color:green;
		color:white;
	}

	.toolbar-details{
		cursor: pointer;
	}

Some HTML to manipulate.

<div class="myContainer">
	<div class="fooberry">
		<div class="summary">
			<div class="summary-text">
				Just a little information.
			</div>
			<div class="toolbar">
				<span class="toolbar-details">details</span> |
				<span>date: 1/3/2009</span>
			</div>
		</div>
		<div class="details">
			More information....
		</div>
	</div>

	<div class="fooberry">
		<div class="summary">
			<div class="summary-text">
				Different information.
			</div>
			<div class="toolbar">
				<span class="toolbar-details">details</span> |
				<span>date: 1/4/2009</span>
			</div>
		</div>
		<div class="details">
			More information....
		</div>
	</div>

</div>

Finally the jQuery.

<script>
	$(document).ready(function(){
		$(".fooberry").click(function(e){
			if($(e.target).is(".toolbar-details")){
				$(this).find(".details").slideToggle(500);
			}
		});
	});
</script>

This layout could probably be adjusted so the problems I mentioned in the previous post aren’t a problem, but let’s just look at the event delegation.

The div with the class “fooberry” contain the physical layout for the items of our list. We use jQuery to attach a click event handler to each “fooberry” div and then use jQuery again to examine the arguments of the event, and yet again to find the div we want to toggle.

I am sure it is possible to attach the event to the “myContainer” div. We would need some additional jQuery since the following line would find all “details” divs.

$(this).find(".details").slideToggle(500);

This happens because the “this” in this statement will now be the “myContainer” div. We could probably write a query to find the parent of the “e.target” who’s class is “fooberry”, and then use that element in place of “this” in the previous statement. This would reduce the overhead of the redundant event handlers, and work with all additional “fooberry” divs added via Ajax.

I hope this is useful for you as it is for me.

Here is the entire HTML.

	<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
	   "http://www.w3.org/TR/html4/strict.dtd">

	<html lang="en">
	<head>

		<script src="jquery-1.2.6.js" type="text/javascript" charset="utf-8"></script>

		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<style>
			.myContainer{
				width:300px;
				font-family:Arial;
			}

			.fooberry{
				margin:5px;
			}
			.summary{
				background-color:#373999;
				color:white;
				padding:3px;
			}

			.details{
				background-color:#689980;
				color:white;
			}

			.toolbar-details{
				cursor: pointer;
			}
		</style>

		<script>
			$(document).ready(function(){

				$(".fooberry").click(function(e){
					if($(e.target).is(".toolbar-details")){
						$(this).find(".details").slideToggle(500);
					}
				});
			});
		</script>

	</head>
	<body>

		<div class="myContainer">
			<div class="fooberry">
				<div class="summary">
					<div class="summary-text">
						Just a little information.
					</div>
					<div class="toolbar">
						<span class="toolbar-details">details</span> |
						<span>date: 1/3/2009</span>
					</div>
				</div>
				<div class="details">
					More information....
				</div>
			</div>

			<div class="fooberry">
				<div class="summary">
					<div class="summary-text">
						Different information.
					</div>
					<div class="toolbar">
						<span class="toolbar-details">details</span> |
						<span>date: 1/4/2009</span>
					</div>
				</div>
				<div class="details">
					More information....
				</div>
			</div>

		</div>

	</body>
	</html>
Written by mark in: .Net, Web Development, jQuery | Tags:
Jan
03
2009
0

jQuery and Event Delegation

We’re currently implementing a collapsible panel in one of our web pages using the ASP.Net Ajax Collapsible Panel Extender. The problem we are having is the Collapsible Panel Extender requires Control ID’s for the expand, collapse and target controls.

Usually this isn’t a problem, but we want to expand a panel inside a ListView control when a something is clicked outside the ListView. So now the problem is he only way to find the control ID is to do a complicated a string of .Parent and .FindControl("") calls to eventually call the .ClientID of the control we want. This becomes very brittle as the code breaks if the UI changes and some expects a parent to be there, when it’s been moved in he markup. This obviously needs to change.

So now to try it (the first way) in jQuery. It should be very easy right?

	$("#" + buttonID).click(function(){
							$("#" + panelID).slideToggle(500);
						  });

Again, we have the same problem. The buttonID and panelID are not easy to get. We need that nasty ClientID; however, what dropping the ASP.Net controls in favor of old school HTML controls. We would end up with something like this?

	$('#button<%# Eval("myPK") %>').click( //...

Ugh…that will work, but it looks nasty too. Generating Javascript on the fly is cool and all I guess, but I don’t like it here.

Here comes Event Delegation to the rescue. Instead of attaching that click event handler to the actual item, let the event delegate up to a parent container, and catch it there. Then, using jQuery to only peer downward is elegant.

	$(document).ready(function(){
		$(".outerDiv").click(function(e){
			if($(e.target).is(".collapseButton")){
				$(this).find(".collapsePanel").slideToggle(500);
			}
		})
	});

That’s it! That’s awesome! It works every time it appears on the page. Remember, we are inside a ListView so we repeat the need for this several times. We don’t care what is between the element with the “outerDiv” CSS class and the other elements because jQuery takes care of finding them. We’re no longer brittle! We don’t need the control ID’s because we only care about the CSS classes now. No more Control ID’s! We no longer have difficulty finding out second cousin twice removed element because we found a common ancestor and look down from there. We don’t need to assign event handles for each button. Sweet! It is a win/win/win.

Written by mark in: .Net, Web Development, jQuery | Tags:
Jan
02
2009
0

One Click Lorem Ipsum

I’m working on layout of new HTML pages and have been adding the Lorem Ipsum filler time and time again. At first I just get a browser window with it open, copy and pasted it whenever I needed, but in keeping the desktop clean of clutter, the browser window was often closed, causing me to search for it, select it, copy, etc. So here’s how to save you time:

  1. Create a toolbox tab for common text.
  2. Select Lorem Ipsum from a file in Visual Studio.
  3. Drag the text to the toolbar.
  4. Done.

Now when you want to inject the lorem ipsum into the text, just click it on the toolbox item.

Even better, for the ReSharper users, make “lorem” a live template for the entire text. Then you just type “lorem” + tab and you get the entire passage.

Dec
29
2008
2

Welcome to jQuery

My first task at my new organization was to verify text being added to a freeform text field is not already associated to a different record of the same type. This would be similar to checking if a username is taken before completing a registration process. As you have probably encountered with the registration process, the typical way to complete this test is to wait for the user to click save button and then test the database for the existing record. It would be a lot nicer if the test would happen automatically as you type, so this is what I set out to do.

Doing this with ASP.Net AJAX would probably be possible, but given we are starting to invest in jQuery, I took this as a great opportunity to learn something new, while still delivering a great user experience. While working through some quick and dirty jQuery examples, I quickly see its potential. It feels nice to be in a dynamic language for a change.

My first task was to fire off a function after a certain amount of time elapses without the user typing into the field. I know Javascript provides a timer mechanism, but I’m hoping jQuery provides a nice abstract to it…and it does. I’m able to find my text box and attach my timers. It was when I first tried to move this out of my static html proof of concept into an ASP.Net application hat I first realized the bane of ASP.Net when using jQuery, control id’s.

All of the examples in jQuery have really nice, hand crafted control id’s.

	$("#myTextbox").keypress(function(){
		$("#myTextbox").oneTime(1000,"mytimer",function(){alert("times up");});
	});

That’s great, but my text box is inside a user control, inside another user control, inside a page. I don’t get id = "myTextbox". I get id = "ctl0__ctl1_ctl1_etc_myTexbox", which makes the selector a little more difficult to write. Luckily, we can use some nasty escaped ASPX code to handle that. I’m not sure this is the best way to handle it, but it is working for now.

	<script type="javascript">
		var controlName = "<%= myTextbox.ClientID %>";
		$("#" + controlName).keypress(function(){"pressed it");});
	</script>

On occasion, the client id is not as easy to come across. For example, in my particular case, I am trying to select a text box inside the InsertItemTemplate of a ListView.

<asp:ListView ID="ListView1" runat="server">
    <!-- ... -->
    <InsertItemTemplate>
        <asp:TextBox ID="myTextbox" runat="server" />
        <script language="javascript" type="text/javascript">
            var controlName = '<%= ListView1.InsertItem.FindControl("myTextbox"); %>';
        </script>
    </InsertItemTemplate>
</asp:ListView>

…OK. I’ve learned not to be too ambitious with my blogs post. I’ll be contributing in smaller chunks form now on.

Written by mark in: .Net, jQuery | Tags: , , ,
Dec
22
2008
0

Return from Hiatus

There has been a lot going on lately that prevented me from posting as often as I should. The good news is I’ve taken a new job which is sure to provide many exciting new challenges to share. The bad news is the new organization isn’t currently using ReSharper. This is something that I hope to remedy, but the ReSharper tips of the day might not return.

Written by mark in: Nonsensical Rant |
Nov
17
2008
0

WPF Toolkit DataGrid, ColumnHeader Style and Blend

I’ve spent the better part of the day trying to figure out how to style the column headers of my WPF Toolkit datagrid through Microsoft Blend. Blend is a great tool and I couldn’t imagine trying to do a WPF application without it; however it is still immature and this could be why I found it so difficult to figure out. It could just be that I’m new to Blend, WPF, and XAML and still have a lot to learn.

I’ll spare you the agony I suffered this morning and jump right into the solution.

We have a pretty basic style for the datagrid at the moment. You’ll have to forgive the visual obfuscation.

Changing the the column header style looked pretty obvious in Blend. The menu walks me through the steps to create a resource for the header style.

Give the style resource a name. In this case I am going to show a pivoted set of data with a set of frozen columns on the left and columns that accept entering data on the right. I give it the name I want and choose its destination.

When the steps are complete, I have a style in the resources dictionary for my window, but something is missing.

I’m not sure if I’m missing a step, but the target type of the resource is the generic IFrameInputElement type. It doesn’t provide any properties to set in the designer.
If I look at the XAML that was created, it doesn’t give it a type.
<Style x:Key="EnterableColumnHeaderStyle"/>

The examples I’ve been seeing have a TargetType property to allow for the attached properties to work properly. I got ahead and add my TargetType property.

As you can see, I’m still learning WPF and XAML.  ReSharper steps in and offers to help out a bit. I am glad to let it. It adds the proper namespace to the resource:

<Style x:Key="EnterableColumnHeaderStyle" TargetType="primitives:DataGridColumnHeader">

It also creates the namespace directive:

I don’t really like the namespace alias, so we’ll change it with the help of ReSharper.

Blend now knows our target type and gives us all the properties we could want to style.

We can do whatever we want with the column header now.

And, just as we’d expect, we get our new style.

We can also apply a style to a particular column.

<wpfToolkit:DataGridTextColumn x:Name="FirstColumn"   Header="Something"  HeaderStyle="{StaticResource FrozenColumnHeaderStyle }" >

Written by mark in: Uncategorized, WPF | Tags: , , ,
Nov
14
2008
1

A Tale of Inconsistency

So in the hard times of our economy, companies cut back on non-essentials. We’ve recently gone from two coffee pots to one.* We have anther pot with an orange handle, but I can’t see the logic in drinking from that one. Only one pot means all those snaky people who leave 2oz of coffee for the person behind them holding a 6oz cup are twice as effective. You can no longer combine the two 2oz pots and get a somewhat satisfying cup of coffee.

Yesterday I was the unfortunate one who came across an empty pot. So after mentally cussing out whomever left it, I started a new one and went to the next floor where I was able to grab the last full cup. Yes! Being the good boy I that am I started yet another pot. I reached into the drawer where the coffee is kept, made the pot and started to leave. As I was leaving the room the label I tossed in the trash caught my eye. There was a little flash of green on the package. I went and looked closer. This floor kept the regular and decaff coffee in opposite drawers as the superior floor above. Luckily I caught my mistake, trashed the pot that was already started and made a proper pot. The poor souls who would have failed to receive their liquid wake up call would weighed against my karma.

It holds true in life, as well as programming. Consistency matters. We develop routines that are habitual and difficult to break. Just as the coffee was always in the same drawer, the parameters are always in the same order. Taking extra care to follow some de facto convention could save slip ups like this.

* The reduction was most likely not related to cut backs, but rather just ended up being broken; however, not replacing it may be related to cut backs.

Written by mark in: Nonsensical Rant |
Nov
13
2008
0

ReSharper Tip of the Day: Put into ‘using’ construct.

There has been some debate if you need every IDisposable should be disposed. From the documentation IDisposable is used to clean up any unmanaged resource.

Use the Dispose method of this interface to explicitly release unmanaged resources in conjunction with the garbage collector.

OK. That’s fine. I totally agree with that until I see DataTable is derived from a class, MarshallByValueComponent, that implements IDisposable. Does that mean DataTable has unmanaged resources? Any way, on to the tip.

ReSharper notices when an object is created that implements IDisposable and it can automatically wrap the usage in a using block. Say you have the following code:

…and want to put it in a using block. Trusty ALT+Enter steps in a gives you the following options:

It is creates a nice using block around the object and all of its usages.

What would really be nice is we could create a warning when we see ourselves using an IDisposible without calling Dispose. That might be more difficult than finding one outside of a using. We could be calling Dispose in a try/finally or somewhere else.

Written by mark in: ReSharper Tip of the Day | Tags: ,
Nov
05
2008
1

WPF Grid and Read Only Columns

In an attempt to provide a total summary column in a WPF data grid, I attempted to bind a read only column of a DataTable to a DataGridTextColumn of the WPFToolkit data grid.

Initially, I tried to do the way I’ve been doing every other column.

<wpfToolkit:DataGridTextColumn
     Header="Total"
     DataFieldBinding="{Binding Total}"  />

Unfortunately that gives us the following error:

A TwoWay or OneWayToSource binding cannot work on the read-only property ‘Total’ of type ‘System.Data.DataRowView’.

OK, that makes sense, we should just adjust the mode of the binding and try again.

<wpfToolkit:DataGridTextColumn
     Header="Total"
     DataFieldBinding="{Binding Total,Mode=OneWay}"  />

….but we get the same error. After a few quick Google searches, I found someone else that already pointed out the issue and a possible workaround.

ReadOnly columns is missing from the CTP, but that is not a huge problem, you can easily accomplish ReadOnly behavior by using DataGridTemplateColumns and replacing the templates with read-only controls ( like TextBlocks).

A quick change of the column to a DataGridTemplateColumn and it looks like we are off to the races.

<wpfToolkit:DataGridTemplateColumn Header="Brand">
    <wpfToolkit:DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=Brand,Mode=OneWay}" />
        </DataTemplate>
    </wpfToolkit:DataGridTemplateColumn.CellTemplate>
</wpfToolkit:DataGridTemplateColumn>

NOTE: After another bit of searching on the web, the WPF Toolkit - October 2008 was released last week. This negates the need for the workaround for read only columns.

<wpfToolkit:DataGridTextColumn
     Header="Total"
     Binding="{Binding Total}"
     IsReadOnly="True" />
Written by mark in: WPF | Tags: , ,
Oct
28
2008
0

The Dvorak Keyboard


I’ve always heard about this mythical keyboard layout that was the apogee of all keyboards, the glowing golden standard to which all others fail to equal, and the other keyboard, designed to be slow and awkward. What might surprise some people is it’s the other, slower keyboard that has sprouted up on desks and laps all over the world and the Secretariat of keyboards never gets its chance to show its true legs.

The Qwerty keyboard was designed to keep the mechanical arms of typewriters from jamming by positioning common successive strokes on either sides of the machine. In contrast the Dvorak keyboard was designed to make the most common letters and
sequences of letters the easiest to type.

While installing Ubuntu this evening I noticed the Dvorak keyboard as an option. Immediately I thought about the several Dell keyboards I have tucked away in drawers gathering dust. Now I love my new slim Apple keyboard, but I’m going to stow it in the drawer for the next few weeks. Tomorrow I plan on laying out a Dvorak and giving it a try. I would like to find a typing speed test and see how it compares to the Qwerty and how it improves over time.

Written by mark in: Nonsensical Rant | Tags:

Powered by WordPress | Kredit | TheBuckmaker