This morning I saw an email asking about enabling the in-place editable label experience using Atlas. It provided a nice catalyst for something I was planning on doing: publishing an Atlas component authoring post. I wrote a script component in the form of a behavior to encapsulate the functionality, and an extender control that makes it very easy to use on the server. It took me just an hour to get both of these developed. This post is focused on using this functionality, and the intent is to show how easy it is to develop using Atlas, esp. as the toolbox of Atlas components becomes more mature, as well as the possibilities for extending it with new scenarios.
Server-centric Approach
The idea here is to create a model very familiar to ASP.NET page developers, using the standard controls. Extender controls, as described earlier, enable attaching "AJAX" functionality to existing controls. I chose to build an InPlaceEditExtender control that extends <asp:TextBox> controls.
Here is some sample markup demonstrating the usage:
<atlas:ScriptManager runat="server">
<Scripts>
<atlas:ScriptReference Path="InPlaceEdit.js" />
</Scripts>
</atlas:ScriptManager>
<asp:TextBox runat="server" id="nameTextBox" Text="Enter your name" />
<asp:TextBox runat="server" id="emailTextBox" Text="Enter your email address" />
<asp:TextBox runat="server" id="commentsTextBox Text="Comments go here"
TextMode="MultiLine" Rows="5" Columns="80" />
<nk:InPlaceEditExtender runat="server" id="ipe1"
LabelCssClass="inPlaceEditLabel" LabelHoverCssClass="inPlaceEditLabelHover">
<nk:InPlaceEditProperties TargetControlID="nameTextBox" Enabled="true" />
<nk:InPlaceEditProperties TargetControlID="emailTextBox" Enabled="true" />
<nk:InPlaceEditProperties TargetControlID="commentsTextBox" Enabled="true" />
</nk:InPlaceEditExtender>
Simple as that! One thing to notice here is that the same extender control can be used to extend multiple textbox controls. This helps reduce the clutter of extender controls on your page, and in design view. Speaking of design view, each TextBox now as a new property called "InPlaceEditing" which can be used to set up in-place editing.
Client-centric Approach
In this approach, the assumption is you have static HTML, using standard <input> and <textarea> tags. You could use imperative script to hook things up to each other, but XML Script makes this so much easier, and readable. Here's a sample:
<input type="text" id="nameTextBox" value="Enter your name" />
<input type="text" id="emailTextBox" value="Enter your email address" />
<textarea id="commentsTextBox" rows="5" cols="80">
Comments go here
</textarea>
<script type="text/javascript" src="/ScriptLibrary/Atlas/Release/Atlas.js" />
<script type="text/xml-script">
<page xmlns="http://schemas.microsoft.com/xml-script/2005" xmlns:nk="nk">
<references>
<add src="InPlaceEdit.js" />
</references>
<components>
<textBox id="nameTextBox">
<behaviors>
<nk:inPlaceEdit
labelCssClass="inPlaceEditLabel" labelHoverCssClass="inPlaceEditLabelHover" />
</behaviors>
</textBox>
<textBox id="emailTextBox">
<behaviors>
<nk:inPlaceEdit
labelCssClass="inPlaceEditLabel" labelHoverCssClass="inPlaceEditLabelHover" />
</behaviors>
</textBox>
<textBox id="commentsTextBox">
<behaviors>
<nk:inPlaceEdit
labelCssClass="inPlaceEditLabel" labelHoverCssClass="inPlaceEditLabelHover" />
</behaviors>
</textBox>
</components>
</page>
</script>
As you can see, no messy event-handling code or initialization/hookup logic in the page itself. The idea is this XML Script will eventually be designable and tool-able, so you won't have to author it by hand, like I just did. I love the ability to encapsulate code so the page is fully declarative, and Atlas enables me to do that on the client as well.
The script brings in the script files via a reference, declares a TextBox component for each input/textarea tag, and then adds an instance of my InPlaceEditBehavior class to the behaviors collection of each TextBox. The Atlas framework and the behavior implementation work together to do the initial hookup, and subsequent event handling.
You can download the script code for the behavior, the extender control and a couple of sample pages, and run them locally (against the December Atlas CTP). A brief description of the functionality would be useful:
- The TextBox controls are dynamically replaced with Labels. The text from the textbox is copied into the Labels.
- The Labels can be styled using a CSS class specified by the LabelCssClass property. They can display a different look when the mouse hovers over them via the LabelHoverCssClass property.
- The Label is hidden and the textbox is restored, either when you click the label, or when you tab into it (so it is more accessible, which is something I think a bunch of implementations out there don't handle). Note that apparently Firefox doesn't raise focus events for labels, so for that browser you must click on the Label. In IE you do get the nice tab-based activation as well.
- The textbox is replaced with the label when you move out of it.
- Hitting Esc cancels the changes (this is standard HTML behavior).
- The behavior integrates with the Validation feature of Atlas, so that if the textbox in question is in an invalid state, it remains a textbox even after you move away from it. Again, the samples out there miss this scenario. The sample page demonstrates this.
You might notice the page actually contains an <input> and not a label to begin with, despite the fact that the textbox appears to be transient. This is contrary to various samples out there. As a result, InPlaceEdit might be a misnomer, but I chose to go with it, since that is the concept people associate the functionality with. Why did I choose to go down this route? Various reasons:
- First the input element will remain in the absence of scripting capabilities
- Second the developer will likely want the textbox to be present to customize with additional behavior such as validation. As such extending an <asp:TextBox> made more sense in the extender control scenario.
- Finally, the input element will be present in the form, so that its value can be submitted along with a form post.
In all honesty, I didn't think of these reasons before I started the implementation. These reasons were justifications for my approach that dawned upon me as I worked on the code. How I decided on this approach actually provides some insight into designing Atlas components. I'll share them in a subsequent post, when I cover how to get down and dirty with C# and JavaScript to build the actual functionality running behind the scenes.
Here's a quick video of the demo. I am experimenting with the video thing - let me know if it works, helps, or distracts.
Posted on Tuesday, 12/27/2005 @ 2:49 PM
| #
ASP.NET