No More Freeloading - Creating My First AjaxControlToolkit Patch
I use Yahoo! for my email client. The main screen has the standard email client three section layout. One area for selecting a folder (Inbox, Drafts, Sent Items, etc...), another area that displays the messages in a table or grid, and the last region shows a preview of the selected message. You can select messages to delete, forward, move by clicking a checkbox to select the messages, and then by clicking the button that corresponds to the action you want taken.
Live Demo (IE6, IE7 and FF) | Download (This includes the complete AjaxControlToolkit solution plus the code for my patch)
I am currently building a new screen for a project I am working on and I would like to use a similar design. I want to allow the user to use checkboxes to select rows. Once one or more rows are selected, clicking a command button (Delete, Copy, Export) will execute the actions on the selected rows. One of the features I had planned on implementing was applying custom images to the checkbox for both the checked/unchecked states as well as for checked/unchecked mouseovers. I like mouseover effects because they are an easy way to keep the UI interactive. I figured I would use the AjaxControlToolkit's ToggleButton for this ...
It turns out, the ToggleButton is pretty close to what I want, but it doesn't support the mouseover states. I did a little more digging to see if it was coming in a future release. It turns out there is an issue for this item, but it has only 1 vote, its not currently assigned to anyone and has release of: WishlistVotes Production. I am not so sure this enhancement is coming anytime soon.
So I figured I would make the change myself and submit a patch to the toolkit team (something I knew virtually nothing about 10 hours ago)
Getting Started
I have never created a toolkit patch before. So I got started by reading the patch documentation on the toolkits codeplex site. It turns out that Microsoft has a tool that you can use to pull the latest toolkit code, apply your changes, and submit them back to the toolkit team. After your changes are reviewed and approved they will be applied to the codebase and included in the next toolkit release. You will want to read the patch documentation yourself (here, here and here), but here are a few key points:
- Microsoft has a tool for pulling code and submitting changes. Its wizard based, just answer the questions and next your way through the screens.
- Microsoft's Toolkit team will review and verify to ensure the quality of the fix before the changeset is applied
- The patching process is designed for bug fixes and enhancements to existing components - not for adding any new components
After reading through the documentation, I followed the steps for downloading the latest code and started making my changes. The AjaxControlToolkit solution contains the following projects (see screenshot below). The extender controls are contained in the AjaxControlToolkit project, the pages for the interactive demo's are contained in the SampleWebSite project, I believe the Test.Client project is for the manual test pages. The ToolkitTests project is for running the toolkits unit tests (just open Default.aspx, select all of the tests and click run).
Understanding the ToggleButtonExtender
After the code was downloaded, I opened the AjaxControlToolkit solution file and headed for the ToggleButton code. The code for this control is separated into 3 files: classes for the .Net control and designer as well as a JavaScript file for the control's client side behavior. The class for the control's server side component contains only the properties that are exposed via the control markup. These property values are passed to the client side behavior and are used to control how the checkbox behaves on the client.
Because my changes will require adding additional client side functionality, I spent some time reviewing the ToggleButton's existing JavaScript code. The technique this behavior uses is to hide the original checkbox and render one of the provided images depending upon the state of the checkbox in its place. The images are displayed as the background of a div that is dynamically created and added to the page. The div's click event is captured and forwarded to the underlying checkbox.
My ToggleButtonExtender Changes
Once I understood how the control worked, I started making my changes. First I added 4 new attributes:
- CheckedImageOverUrl : Image that is displayed when the item is checked and the user mouse's over the element
- CheckedImageOverAlternateText : Alternate text for the CheckedImageOverUrl
- UncheckedImageOverUrl : Image that is displayed when the item is unchecked and the user mouse's over the element
- UncheckedImageOverAlternateText : Alternate text for the UncheckedImageOverUrl
These attributes were added to both the class for the server side control as well as the JavaScript behavior. I was not exactly sure of the coding guidelines, so I just followed as close as I could with what was already there. Here is the property getter/setter for the CheckedImageOverUrl:
After I added my 4 new properties, I next started working on adding logic to the behavior for applying these ImageOver's to the checkbox. I added 2 new handlers to the behavior, one handles the checkboxes mouseover event, the other handles the mouseout event. When the mouseover event fires, I run the code that determines if the element needs to have the CheckedImageOver or UncheckedImageOver images applied. Here is the logic for this handler:
When this handler fires, the CheckedImageOverUrl image is applied if:
- The underlying checkbox is enabled AND
- The underlying checkbox is checked AND
- A CheckedImageOverUrl value is provided
To remove the checked/unchecked mouseover images, I have the mouseout handler reapply the original images by calling the behaviors already defined _onClick method. I figured this is how the original control developer would handle this since this is how the images are originally applied in the behavior's initialize function.
Testing My ToggleButtonExtender Changes
After I added my changes, I opened the solutions Testing.Client website and added a new aspx page to the ToggleButton folder. In this page, I created a simple test page (MouseOver.aspx) for manually testing my new features. The page is pretty simple, it contains 4 checkboxes. Each one has a CheckedImageOverUrl and UncheckedImageOverUrl defined for it. The screenshot below shows 2 unchecked checkboxes, a checked one, and an unchecked one that the mouse is currently hovering over (the mouse cursor isn't visible because my image snagging software doesn't capture it).
The solution also contains a website for automated unit tests. So I next went and checked out what tests existed for the ToggleButton. There were 4 existing unit tests that verified checking/unchecked and posting back the page (you can read more about toolkit unit tests here). I would have liked to add a couple tests for verifying the correct mouseover image was being applied, but that would have required my to obtain a reference to the behaviors div element that displays the image (there is no public member that does this). The existing tests do not verify the other image states, so I didn't do it either. I also loaded the sample demo site and made sure the original sample was working properly. My last step was to run all of the existing unit tests - I want to make sure my code changes didn't break any of the other unit tests.
To do this, I ran the Default.aspx page of the ToolkitTests website. I selected all unit tests and ran them in both IE and FF.
Submitting My ToggleButtonExtender Changes
After I had made my changes and had everything tested, I proceeded to run the patch tool and submit the changes back to the toolkit team. One of the wizard steps allowed me to use Windiff to view my modifications - very cool.
The last step of the wizard zips up the changes. To get the patch applied, you need to either open a new codeplex work item, or attach the zipped patch file to an existing one. For my case I already had a work item (#11825), so I just attached the file.
Conclusion
I have no idea when or if my patch will be applied. But I figure I should probably stop being a freeloader and start at least trying to contribute to the toolkit.
That's it. Enjoy!
Comments
Great Work !!!
I agree with you, that you should contribute to toolkit.
But, Beginners like me need articles like
1) Using Image Sprite
2) Theming AJAX Tab Control
3) Theming Grid View
etc.
Youll be headhunted soon Matt.
@vish -
Thanks for the comment vish.
I agree, fixing toolkit extender bugs may not be for everyone. However, the demo web site is included in the codeplex project. One could contribute by enhancing the demos or fixing documentation errors.
I personally think more time needs to be spent on this. The examples are functional, but not polished. This is where other ajax toolkits like YUI have the AjaxControlToolkit beat.
Matt.
Great work!
Hi Matt,
Thanks for the patch! We appreciate your contribution. It has just been checked in as ChangeSet 28964. Anyone getting the latest source from http://www.codeplex.com/AtlasControlToolkit/SourceControl/ListDownloadableCommits.aspx will have the new features.
Also - Testing.Client is actually our new automated client-side testing framework. Take a look at the AppCode folder for the actual tests and run Default.aspx to see them in action. To test just your new page you could run something like: http://localhost:1234/Testing.Client/Tag/ToggleButton.MouseOver/Filter/Verbose/Run
Thanks,
@Ted -
Thanks for the update. I appreciate the quick turn around.
Matt.
Hi mat,
As a beginner, may I know how to install/use the patch. Thanks
Matt,
Nice patch. I just wanted to add that you should extend this control so that when you hover over the text of the checkbox it will also give you the hover effect on the checkbox.
I say this because you can click on the checkbox or the text and have the checkbox checked. This being said you would expect to see the hover effect when you hover over the checkbox as well as the text.
Nothing major but I thought I would toss that out there.