<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Zach Hunter&#039;s Busy Life &#187; Web Development</title>
	<atom:link href="http://www.zachhunter.com/category/web-development/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.zachhunter.com</link>
	<description>Random Brain Drool</description>
	<lastBuildDate>Tue, 02 Aug 2011 17:39:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>JSON to HTML Form Using jQuery dForm Plug-in</title>
		<link>http://www.zachhunter.com/2011/06/json-to-html-form-using-jquery-dform-plug-in/</link>
		<comments>http://www.zachhunter.com/2011/06/json-to-html-form-using-jquery-dform-plug-in/#comments</comments>
		<pubDate>Wed, 29 Jun 2011 19:19:40 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=478</guid>
		<description><![CDATA[In a previous posts, I&#8217;ve showed how to go from a JSON array of objects/values, to a HTML table. This is great when you want to display a bunch of data in column and rows, but what happens if you want to interact with the data. No problem, there is the jQuery dForm plug-in for [...]]]></description>
			<content:encoded><![CDATA[<p>In a previous posts, I&#8217;ve showed how to go from a JSON array of objects/values, to a HTML table.  This is great when you want to display a bunch of data in column and rows, but what happens if you want to interact with the data.  No problem, there is the <a href="https://github.com/daffl/jquery.dform">jQuery dForm plug-in</a> for that.  In order to generate the form, you&#8217;ll need to redesign your server side / inline objects to provide the required rendering data for dForms.  It&#8217;s pretty straight forward and there is a ton of options with the plug-in, <a href="http://neyeon.com/p/jquery.dform/doc/files2/examples-txt.html">see here</a>.</p>
<p><strong>Demo Screenshot</strong></p>
<p><a href="http://www.zachhunter.com/wp-content/uploads/jQuery-dForm-Demo-Screenshot.png"><img src="http://www.zachhunter.com/wp-content/uploads/jQuery-dForm-Demo-Screenshot.png" alt="" title="jQuery dForm Demo Screenshot" width="640" height="787" class="alignnone size-full wp-image-479" /></a></p>
<p>In the image above, we use an inline object that will feed the dForm &#8220;buildForm()&#8221; method.  I&#8217;m using a static value here, but you could have easily setup dForm to load the data remotely using ajax.</p>
<p>Here is the <a href='http://www.zachhunter.com/wp-content/uploads/jQuery_dForm_Demo.zip'>jQuery dForm 0.1.3 Plug-in Demo</a> used in the screenshot above, which includes everything you need to get up and running fast.  If you have problems making dForm work, make sure you have included &#8220;ALL&#8221; the dForm libraries.  The dForm.js file has dependencies on the other libraries, if you don&#8217;t load the correct libraries, you&#8217;ll end up with a blank form.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2011/06/json-to-html-form-using-jquery-dform-plug-in/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reusable ASP.NET MessageBox UserControl</title>
		<link>http://www.zachhunter.com/2011/06/asp-net-messagebox-usercontrol/</link>
		<comments>http://www.zachhunter.com/2011/06/asp-net-messagebox-usercontrol/#comments</comments>
		<pubDate>Wed, 29 Jun 2011 18:38:38 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[C# Development]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=462</guid>
		<description><![CDATA[All systems need a way to share status messages with a user, without giving them feedback they don&#8217;t what has or what will happen. There are so many different ways to send an alert (modal window, JavaScript alert, inline HTML, etc&#8230;), regardless of what you use it always help to be consistent. I built this [...]]]></description>
			<content:encoded><![CDATA[<p>All systems need a way to share status messages with a user, without giving them feedback they don&#8217;t what has or what will happen.  There are so many different ways to send an alert (modal window, JavaScript alert, inline HTML, etc&#8230;), regardless of what you use it always help to be consistent.  I built this control based on a few different ideas/examples a long time ago, and I seem to find more uses for it all the time.  You can call it from the server or from the client using JavaScript, making it the perfect single solution &#8220;notification&#8221; solution.</p>
<p>Here is an example of what it looks like.</p>
<p><a href="http://www.zachhunter.com/wp-content/uploads/ASPNET_UserControl_MessageBox.png"><img src="http://www.zachhunter.com/wp-content/uploads/ASPNET_UserControl_MessageBox.png" alt="ASP.NET MessageBox User Control Screenshot" title="ASP.NET MessageBox User Control Screenshot" width="930" height="313" class="alignnone size-full wp-image-468" /></a></p>
<p><em>** The text after the heading, is the code that was used to trigger the message box.</em></p>
<p>The control is pretty straight forward, on the server it works by &#8220;re-injecting&#8221; the rendered control when you call Show<type> function.  Since the control does not use viewstate, every time you post back to the server and call show again, the last message disappears and the new message is displayed.  If you want the message to disappear &#8220;automatically&#8221; after a few seconds, you can can set the timeout in milliseconds.  On the client (via JavaScript), you can create a simple function that will provide access to throwing alerts from the client without a postback.</p>
<p><strong>Client Side Example</strong></p>
<pre class="brush: jscript; title: ; notranslate">
    &lt;script type=&quot;text/javascript&quot;&gt;
        function ShowSuccess(message) {
            $alert = $('#MBWrapper1');

            $alert.removeClass().addClass('MessageBoxInterface');
            $alert.children('p').remove();
            $alert.append('&lt;p&gt;' + message + '&lt;/p&gt;').addClass('successMsg').show().delay(8000).slideUp(300);
        }
    &lt;/script&gt;
</pre>
<p><strong>Server Side Example</strong></p>
<pre class="brush: csharp; title: ; notranslate">
    public partial class _Default : System.Web.UI.Page
    {
        protected void Success_Click(object sender, EventArgs e)
        {
            MessageBox1.ShowSuccess(&quot;Success, page processed.&quot;, 5000);
        }
    }
</pre>
<p><a href='http://www.zachhunter.com/wp-content/uploads/ASPNET_UserControl_MessageBox_FullDemo.zip'>ASP.NET MessageBox User Control &#8211; Full Working Demo</a></p>
<p>Download and try the demo, if you like what you see&#8230;  Here is what you need to include to make the control work in your project.</p>
<ul>
<li>MessageBox User Control (ASMX &#038; CS)</li>
<li><a href="http://code.jquery.com/">jQuery </a></li>
<li>IMessageBox.css stylesheet</li>
<li>All the graphics from the Images folder</li>
</ul>
<p><em>** Note: If you move the images into a different directory, you&#8217;ll need to update the CSS to use the correct path to the images.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2011/06/asp-net-messagebox-usercontrol/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>ASP.NET Lists Elements and Client Side Updates</title>
		<link>http://www.zachhunter.com/2011/06/asp-net-lists-elements-and-client-side-updates/</link>
		<comments>http://www.zachhunter.com/2011/06/asp-net-lists-elements-and-client-side-updates/#comments</comments>
		<pubDate>Fri, 24 Jun 2011 20:03:39 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=455</guid>
		<description><![CDATA[A common issue I see people run into with Web Forms is the inability for client side changes to LIST elements (ListBox, DropDownList, etc&#8230;) to be passed back during POSTBACK. This is due to the how the viewstate is assigned/process, and there is no simple &#8220;hack&#8221; to bypass this. As for other non-list elements that [...]]]></description>
			<content:encoded><![CDATA[<p>A common issue I see people run into with Web Forms is the inability for client side changes to LIST elements (ListBox, DropDownList, etc&#8230;) to be passed back during POSTBACK.  This is due to the how the viewstate is assigned/process, and there is no simple &#8220;hack&#8221; to bypass this.  As for other non-list elements that typically implement a Text property, this isn&#8217;t an issue.  Here are 3 common ways to get around the limitation in seeing changes to your LIST elements that were made on the client using jQuery/JavaScript.</p>
<p><strong>1. Create a hidden field (that has a text property)</strong></p>
<pre class="brush: xml; title: ; notranslate">
&lt;select size=&quot;5&quot; id=&quot;users&quot;&gt;
    &lt;option value=&quot;Kelly&quot;&gt;Kelly&lt;/option&gt;
    &lt;option value=&quot;Kylee&quot;&gt;Kylee&lt;/option&gt;
    &lt;option value=&quot;Nathan&quot;&gt;Nathan&lt;/option&gt;
&lt;/select&gt;

&lt;input type=&quot;hidden&quot; id=&quot;userList&quot; runat=&quot;server&quot; value=&quot;Kelly,Kylee,Nathan&quot;/&gt;
</pre>
<p>Here is how you would add/parse the client side change.</p>
<pre class="brush: jscript; title: ; notranslate">
var $users = $('#users');
var $usersList = $('#usersList');

$users.append($('&lt;option&gt;&lt;/option&gt;').val('New Entry Value').html('New Entry Text'));

var newUserList = '';
var $options = $('#users').children('option');

$.each($options, function(index, value) {
	newUserList = newUserList + $options[index].value + ',';
}); 			

$usersList.val(newUserList.substr(0, newUserList.length-1));
</pre>
<p><em>** In this example, you maintain a hidden input element that matches the items in the select list.  When you change the select list in JavaScript, you change the value of the hidden element.  During post back, you read and parse this list to make your updates.<br />
</em></p>
<p><strong>2.  Wrap your lists in an update panel</strong></p>
<pre class="brush: xml; title: ; notranslate">
&lt;asp:UpdatePanel ID=&quot;UpdateRoles&quot; runat=&quot;server&quot;&gt;
    &lt;ContentTemplate&gt;
        &lt;table&gt;
            &lt;tr&gt;
                &lt;td style=&quot;height: 180px; vertical-align: top;&quot;&gt;
                    Active Roles&lt;br /&gt;
                    &lt;asp:ListBox ID=&quot;lstAdd&quot; runat=&quot;server&quot; Width=&quot;300px&quot; OnSelectedIndexChanged=&quot;lstAdd_SelectedIndexChanged&quot; Rows=&quot;10&quot;&gt;&lt;/asp:ListBox&gt;
                &lt;/td&gt;
                &lt;td style=&quot;height: 180px&quot;&gt;
                    &lt;asp:Button ID=&quot;AddRole&quot; runat=&quot;server&quot; Text=&quot;-&gt;&quot; OnClick=&quot;AddRole_Click1&quot; /&gt;
                    &lt;br /&gt;
                    &lt;asp:Button ID=&quot;RemoveRole&quot; runat=&quot;server&quot; Text=&quot;&lt;-&quot; OnClick=&quot;RemoveRole_Click&quot; /&gt;
                &lt;/td&gt;
                &lt;td style=&quot;height: 180px; vertical-align: top;&quot;&gt;
                    InActive Roles&lt;br /&gt;
                    &lt;asp:ListBox ID=&quot;lstRemove&quot; runat=&quot;server&quot; Width=&quot;300px&quot; OnSelectedIndexChanged=&quot;lstRemove_SelectedIndexChanged&quot; Rows=&quot;10&quot;&gt;&lt;/asp:ListBox&gt;
                &lt;/td&gt;
            &lt;/tr&gt;
        &lt;/table&gt;
    &lt;/ContentTemplate&gt;
&lt;/asp:UpdatePanel&gt;
</pre>
<p>Here are the events that are fired when you click the Add / Remove buttons the move items between the lists.</p>
<pre class="brush: csharp; title: ; notranslate">
        protected void AddRole_Click1(object sender, EventArgs e)
        {
            if (lstAdd.SelectedIndex &gt; -1)
            {
                lstRemove.Items.Add(lstAdd.SelectedItem);
                lstAdd.Items.RemoveAt(lstAdd.SelectedIndex);
            }
        }

        protected void RemoveRole_Click(object sender, EventArgs e)
        {
            if (lstRemove.SelectedIndex &gt; -1)
            {
                lstAdd.Items.Add(lstRemove.SelectedItem);
                lstRemove.Items.RemoveAt(lstRemove.SelectedIndex);
            }
        }
</pre>
<p><em><br />
** You could fire the events using any type of event, in the sample I highlighting a item in one of the two lists and click Add/Remove to switch the items between the lists.</em></p>
<p><strong>3. Post back using Ajax</strong></p>
<p>This is currently my preferred approach, since it ride on top of jQuery Ajax and follows my normal design approach to building widgets (ajax load / add / edit / delete).  Using this approach you can do real-time updates as they edit the list, or you can post back your entire form including all your list changes without a post back.  There are so many options when you start using ajax calls to pass data back and forth between the client and server.</p>
<p>My example below is using a WCF service, you can also use ASMX to do this in earlier versions of .NET.  This solution has a lot more steps, but it really encompasses a whole &#8220;form submit&#8221; vs. propagating your LIST changes to the server.</p>
<p>To start, I also build some simple objects to pass between the client &#038; server.  The objects go both ways and are defined as a DataContract in C#.</p>
<pre class="brush: csharp; title: ; notranslate">
    [DataContract]
    public class Member
    {
        [DataMember]
        public int MemberId;

        [DataMember]
        public string CustomerCode;

        [DataMember]
        public string DelToCode;
    }

    [DataContract]
    public class Rule
    {
        [DataMember]
        public int RuleId;

        [DataMember]
        public string Name;

        [DataMember]
        public bool Enabled;

        [DataMember]
        public List&lt;Member&gt; Members;
    }
</pre>
<p>One we have an opject to pass, we define a method that will use this object.</p>
<pre class="brush: csharp; title: ; notranslate">
    [OperationContract]
    [WebInvoke(
        RequestFormat = WebMessageFormat.Json,
        ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.WrappedRequest)
    ]
    bool UpdateRule(Rule rule);

    public bool UpdateRule(Rule rule)
    {
        // Do Update Using Object
    }
</pre>
<p>Next we build a form that will be used with our server, everything on the form can be build during page load or it can be populate via Ajax.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;fieldset class=&quot;withborder&quot; id=&quot;manageRule&quot;&gt;
&lt;legend&gt;Rule Update&lt;/legend&gt;
&lt;ol&gt;
	&lt;li&gt;
		&lt;label class=&quot;left&quot;&gt;
			Rule ID&lt;em&gt;*&lt;/em&gt;&lt;/label&gt;
		&lt;input type=&quot;text&quot; class=&quot;medium disabled&quot; id=&quot;ruleId&quot;&gt;
	&lt;/li&gt;
	&lt;li&gt;
		&lt;label class=&quot;left&quot;&gt;
			Name&lt;em&gt;*&lt;/em&gt;&lt;/label&gt;
		&lt;input type=&quot;text&quot; class=&quot;medium&quot; maxlength=&quot;5&quot; id=&quot;ruleName&quot;&gt;
	&lt;/li&gt;
	&lt;li&gt;
		&lt;label class=&quot;left&quot;&gt;
			Enabled&lt;em&gt;*&lt;/em&gt;&lt;/label&gt;
		&lt;input type=&quot;checkbox&quot; class=&quot;checkBox&quot; id=&quot;ruleEnabled&quot; checked=&quot;checked&quot;&gt;
	&lt;/li&gt;
	&lt;li&gt;
		&lt;label class=&quot;left&quot;&gt;
			Assigned&lt;em&gt;*&lt;/em&gt;&lt;/label&gt;
		&lt;div&gt;
			&lt;div class=&quot;dropZone available&quot;&gt;
				&lt;ul class=&quot;connectedSortable ui-sortable&quot; id=&quot;available&quot; style=&quot;&quot;&gt;
					&lt;li id=&quot;MemberId_1&quot; class=&quot;ui-state-highlight&quot;&gt;Red&lt;/li&gt;
					&lt;li id=&quot;MemberId_2&quot; class=&quot;ui-state-highlight&quot;&gt;Green&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/div&gt;
			&lt;div class=&quot;dropZone included&quot;&gt;
				&lt;ul class=&quot;connectedSortable ui-sortable&quot; id=&quot;included&quot; style=&quot;&quot;&gt;
					&lt;li id=&quot;MemberId_3&quot; class=&quot;ui-state-highlight&quot;&gt;Blue&lt;/li&gt;
					&lt;li id=&quot;MemberId_4&quot; class=&quot;ui-state-highlight&quot;&gt;Yellow&lt;/li&gt;
					&lt;li id=&quot;MemberId_5&quot; class=&quot;ui-state-highlight&quot;&gt;Orange&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/div&gt;
		&lt;/div&gt;
	&lt;/li&gt;
	&lt;li style=&quot;text-align: right;&quot;&gt;
		&lt;input type=&quot;button&quot; value=&quot;Update Rule&quot; text=&quot;Add&quot; id=&quot;updateRule&quot;&gt;
	&lt;/li&gt;
&lt;/ol&gt;
&lt;/fieldset&gt;
</pre>
<p>Finally, we put it all together with JavaScript function that uses <a href="http://jquery.com/">jQuery </a>and <a href="http://www.json.org/">JSON.org&#8217;s</a> libraries to build and transfer data between the client and sever.</p>
<pre class="brush: jscript; title: ; notranslate">
    function UpdateRule() {
        var rule;

        rule.RuleId = parseInt($('#ruleId').val());
        rule.Name = $('#ruleName').val();
        rule.Enabled = $('#ruleEnabled').is(':checked');

        var $includedMembers = $('#included &gt; li');

        rule.Members = [];

        // This is where you parse / add the values of your list (listbox, li, etc...)
        if ($includedMembers.length &gt; 0) {
            $.each($includedMembers, function (index, value) {
                var id = $includedMembers[index].id.replace('MemberId_', '');
                var name = $includedMembers[index].firstChild.data.split(' - ');
                var member = { 'CustomerCode': name[0], 'DelToCode': name[1], 'MemberId': id };
                rule.Members.push(member);
            });
        }

        $.ajax({
            url: '/Service/ExampleWCFService.svc/UpdateRule',
            contentType: 'application/json; charset=utf-8',
            dataType: 'json',
            type: 'POST',
            data: JSON.stringify({ 'rule': rule }),
            success: function (rule) {
                // Do Something On Success
            }
        });
    }
</pre>
<p><em>** Don&#8217;t forget, you could have your service store this data in the cache/session/etc&#8230; if you don&#8217;t want to store it real-time.  In my sample, I send the whole form to be process and not just the list.  This gets rid of the entire post back process.<br />
</em></p>
<p>Each has it&#8217;s own unique requirements, the only one I tend not to use anymore is #2 since it requires the addition of the ASP.NET Ajax Library.  Having an additional library and added content in a project for this one feature isn&#8217;t worth it to me.  I know the library has got more compact, but in general it&#8217;s quite heavy (size wise), and since I already &#8220;always&#8221; include jQuery there really isn&#8217;t a need for this baggage.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2011/06/asp-net-lists-elements-and-client-side-updates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JSON to CSV</title>
		<link>http://www.zachhunter.com/2011/06/json-to-csv/</link>
		<comments>http://www.zachhunter.com/2011/06/json-to-csv/#comments</comments>
		<pubDate>Wed, 01 Jun 2011 19:23:39 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=422</guid>
		<description><![CDATA[I created a helper a few months back that used DATA URIs to download JSON to CSV, but due to IE&#8217;s implementation of DATA URIs (or lack of), it does not work for IE (all versions). Here is the same helper that will just convert the data, which you can use anyway you want (example: [...]]]></description>
			<content:encoded><![CDATA[<p>I created a helper a few months back that used DATA URIs to download JSON to CSV, but due to IE&#8217;s implementation of DATA URIs (or lack of), it does not work for IE (all versions).  Here is the same helper that will just convert the data, which you can use anyway you want (example: in a popup, to display in a modal window, etc&#8230;).</p>
<pre class="brush: xml; title: ; notranslate">
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Demo - Covnert JSON to CSV&lt;/title&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;http://code.jquery.com/jquery-latest.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;https://github.com/douglascrockford/JSON-js/raw/master/json2.js&quot;&gt;&lt;/script&gt;

    &lt;script type=&quot;text/javascript&quot;&gt;
		// JSON to CSV Converter
        function ConvertToCSV(objArray) {
            var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
            var str = '';

            for (var i = 0; i &lt; array.length; i++) {
                var line = '';
                for (var index in array[i]) {
                    if (line != '') line += ','

                    line += array[i][index];
                }

                str += line + '\r\n';
            }

            return str;
        }

		// Example
        $(document).ready(function () {

			// Create Object
            var items = [
				  { name: &quot;Item 1&quot;, color: &quot;Green&quot;, size: &quot;X-Large&quot; },
				  { name: &quot;Item 2&quot;, color: &quot;Green&quot;, size: &quot;X-Large&quot; },
				  { name: &quot;Item 3&quot;, color: &quot;Green&quot;, size: &quot;X-Large&quot; }];

			// Convert Object to JSON
			var jsonObject = JSON.stringify(items);

			// Display JSON
            $('#json').text(jsonObject);

			// Convert JSON to CSV &amp; Display CSV
            $('#csv').text(ConvertToCSV(jsonObject));
        });
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;
        JSON&lt;/h1&gt;
    &lt;pre id=&quot;json&quot;&gt;&lt;/pre&gt;
    &lt;h1&gt;
        CSV&lt;/h1&gt;
    &lt;pre id=&quot;csv&quot;&gt;&lt;/pre&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Here is the output using the script and above.</p>
<h1>
        JSON</h1>
<h3>Created with &#8220;JSON.stringify()&#8221; function from <a href="https://github.com/douglascrockford/JSON-js/raw/master/json2.js">json.org</a>.</h3>
<pre id="json">[{"name":"Item 1","color":"Green","size":"X-Large"},{"name":"Item 2","color":"Green","size":"X-Large"},{"name":"Item 3","color":"Green","size":"X-Large"}]</pre>
<h1>
        CSV</h1>
<h3>Created with &#8220;ConvertToCSV()&#8221; function I created above.</h3>
<pre id="csv">Item 1,Green,X-Large
Item 2,Green,X-Large
Item 3,Green,X-Large
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2011/06/json-to-csv/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>jQuery Validation &#8211; Show &amp; Focus on first error only!</title>
		<link>http://www.zachhunter.com/2010/11/jquery-validation-show-focus-on-first-error-only/</link>
		<comments>http://www.zachhunter.com/2010/11/jquery-validation-show-focus-on-first-error-only/#comments</comments>
		<pubDate>Thu, 11 Nov 2010 16:48:34 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=359</guid>
		<description><![CDATA[Have you ever wanted to show one error message at a time, or create a different type of visual queue for a specific invalid element on a form? Using the validate options, you can easily create any effect you want. The example below, is designed to show the first error message in a form and [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever wanted to show one error message at a time, or create a different type of visual queue for a specific invalid element on a form?  Using the <a href="http://docs.jquery.com/Plugins/Validation/validate#toptions">validate options, </a>you can easily create any effect you want.  </p>
<p>The example below, is designed to show the first error message in a form and to set focus on that first element.  The message is displayed in a basic JavaScript alert box, not very elegant but it makes for a simple demo.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
    &lt;title&gt;Show JS Alert - First Validation Error&lt;/title&gt;
    &lt;script src=&quot;Scripts/jquery-1.4.2.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;Scripts/jquery.validate.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
        $(document).ready(function() {
            $(&quot;#elForm&quot;).validate({
                onfocusout: false,
                invalidHandler: function(form, validator) {
                    var errors = validator.numberOfInvalids();
                    if (errors) {
                        alert(validator.errorList[0].message);
                        validator.errorList[0].element.focus();
                    }
                },
                rules: {
                    TextBox1: { required: true, minlength: 2 },
                    TextBox2: { required: true, minlength: 2 },
                    TextBox3: { required: true, minlength: 2 }
                },
                messages: {
                    TextBox1: { required: &quot;TextBox1 Required&quot;, minlength: &quot;TextBox1 MinLength&quot; },
                    TextBox2: { required: &quot;TextBox2 Required&quot;, minlength: &quot;TextBox2 MinLength&quot; },
                    TextBox3: { required: &quot;TextBox3 Required&quot;, minlength: &quot;TextBox3 MinLength&quot; }
                },
                errorPlacement: function(error, element) {
                    // Override error placement to not show error messages beside elements //
                }
            });
        });
    &lt;/script&gt;

    &lt;style type=&quot;text/css&quot;&gt;
        label { width: 90px; display: block; float: left; }
        ul { list-style: none; }
        ul li { line-height: 1.8; }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form id=&quot;elForm&quot; action=&quot;#&quot;&gt;
    &lt;div&gt;
        &lt;h1&gt;jQuery Validation - Show First Error Only&lt;/h1&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;label&gt;Text Box 1&lt;/label&gt;&lt;input type=&quot;text&quot; name=&quot;TextBox1&quot; id=&quot;TextBox1&quot; value=&quot;&quot; /&gt;&lt;/li&gt;
            &lt;li&gt;&lt;label&gt;Text Box 2&lt;/label&gt;&lt;input type=&quot;text&quot; name=&quot;TextBox2&quot; id=&quot;TextBox2&quot; value=&quot;&quot; /&gt;&lt;/li&gt;
            &lt;li&gt;&lt;label&gt;Text Box 3&lt;/label&gt;&lt;input type=&quot;text&quot; name=&quot;TextBox3&quot; id=&quot;TextBox3&quot; value=&quot;&quot; /&gt;&lt;/li&gt;
        &lt;/ul&gt;
        &lt;input type=&quot;submit&quot; id=&quot;submit&quot; value=&quot;Validate&quot; /&gt;
    &lt;/div&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Here are the important parts to focus on.</p>
<p>1. <strong>invalidHandler</strong>, this option give you access to the current validator and all the errors messages/items via the &#8220;validator.errorlist&#8221;.</p>
<pre class="brush: jscript; title: ; notranslate">
                invalidHandler: function(form, validator) {
                    var errors = validator.numberOfInvalids();
                    if (errors) {
                        alert(validator.errorList[0].message);  //Only show first invalid rule message!!!
                        validator.errorList[0].element.focus(); //Set Focus
                    }
                }
</pre>
<p>2. <strong>errorPlacement</strong>, this function controls how error messages are displayed.  Since we don&#8217;t want any error messages displayed by default, we can override the default errorPlacement with a empty method call.</p>
<pre class="brush: jscript; title: ; notranslate">
                errorPlacement: function(error, element) {
                    // Override error placement to not show error messages beside elements //
                }
</pre>
<p>The end result is a alert box showing the first broken rule for the first invalid element on the page.  In the example each input has 2 rules (required and minLength), if you enter a single character into the first text box the message will change from &#8220;TextBox1 Required&#8221; to &#8220;TextBox1 MinLength&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2010/11/jquery-validation-show-focus-on-first-error-only/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Download JSON to CSV using JavaScript</title>
		<link>http://www.zachhunter.com/2010/11/download-json-to-csv-using-javascript/</link>
		<comments>http://www.zachhunter.com/2010/11/download-json-to-csv-using-javascript/#comments</comments>
		<pubDate>Tue, 09 Nov 2010 07:19:38 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=355</guid>
		<description><![CDATA[Here is a simple way to convert your JSON to CSV, if your using FF or Chrome that supports data URI&#8217;s then this function convert your data and tell your browser to download the results as a text file. If you are using Internet Explorer (&#8220;IE&#8221;), a new window will popup so you can copy [...]]]></description>
			<content:encoded><![CDATA[<p>Here is a simple way to convert your JSON to CSV, if your using FF or Chrome that supports <a href="http://en.wikipedia.org/wiki/Data_URI_scheme">data URI&#8217;s</a> then this function convert your data and tell your browser to download the results as a text file.  If you are using Internet Explorer (&#8220;IE&#8221;), a new window will popup so you can copy &#038; paste or to use File -> Save As to download the results as text.  The JSON parsing is done with json.org&#8217;s open source JSON parser, which you can download <a href="http://www.json.org/js.html">here</a>.</p>
<p>Why can&#8217;t IE download the file to CSV like FireFox?  The long answer is due to IE&#8217;s data URI support that was missing until IE8, and when implemented in IE8+, the security restrictions are set to prevent solutions like this from working!  To force a download of your JSON data in CSV via IE, you&#8217;ll need to use an alternative technique like Server Side Parsing.</p>
<pre class="brush: jscript; title: ; notranslate">
		function DownloadJSON2CSV(objArray)
		{
			var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
			var str = '';

			for (var i = 0; i &lt; array.length; i++) {
				var line = '';
				for (var index in array[i]) {
					if(line != '') line += ','

					line += array[i][index];
				}

				str += line + '\r\n';
			}

			if (navigator.appName != 'Microsoft Internet Explorer')
			{
				window.open('data:text/csv;charset=utf-8,' + escape(str));
			}
			else
			{
				var popup = window.open('','csv','');
				popup.document.body.innerHTML = '&lt;pre&gt;' + str + '&lt;/pre&gt;';
			}
		}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2010/11/download-json-to-csv-using-javascript/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>WordPress 3.0 &#8211; A CMS Solution?</title>
		<link>http://www.zachhunter.com/2010/07/wordpress-3-0-a-cms-solution/</link>
		<comments>http://www.zachhunter.com/2010/07/wordpress-3-0-a-cms-solution/#comments</comments>
		<pubDate>Wed, 28 Jul 2010 22:01:08 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=338</guid>
		<description><![CDATA[I started working on a project site that is going to use WordPress as the CMS engine. I wasn&#8217;t sure if this was going to work, but after a little time I found this was pretty easy to do. You start by deleting all the default content and disabling the default plug-ins and management screen [...]]]></description>
			<content:encoded><![CDATA[<p>I started working on a project site that is going to use WordPress as the CMS engine.  I wasn&#8217;t sure if this was going to work, but after a little time I found this was pretty easy to do.  You start by deleting all the default content and disabling the default plug-ins and management screen options.  Once everything is removed/disabled, you start by creating pages (e.g. Home, About, News, etc&#8230;) that will display all the content you need on the website.  One you have your main page setup (e.g. Home), you need to change the default home page from a dynamic page of blog posts to a static page.  You change the default home page under Settings &#8211;> Reading &#8211;> Front Page Display &#8211;> A Static Page &#8211;> Choose an option from the Front Page drop down list.  That&#8217;s it, you now have WordPress running as a basic CMS soltuion.</p>
<p>I wish I could say that&#8217;s it, but most likely you&#8217;ll need to download and install some additional plug-ins.  I found many plug-ins still do not support WordPress 3.0, so you&#8217;ll need to be careful!  If you happen to install a bad plug-in, there is an easy fix to get you site back online&#8230;  Delete the plug-in folder (via FTP or Hosting Control Panel) and WordPress will automatically disable the plug-in.</p>
<p>Here is the list of plug-ins I added for my project:</p>
<ol>
<li>Contact Form 7<br/>This is a great plug-in, it provides a easy way to create forms that get emailed to you.  You create the forms using HTML online and a shortcode style syntax for the input fields.  The shortcode inputs are then accessible in your email, that you also create using HTML.</li>
<li>WP Google Maps<br />This is a very basic Google Maps plug-in, the is about 10 options and the only think extra you need is a GoogleMaps API key.</li>
<li>WordPress.com Stats<br />I&#8217;ve been using this on my blog and love the UI.  I wish this was all being done client-side, but for some reason it was created as service.  By default it injects a smiley face into your page, so make sure you disable this in your themes style sheet.</li>
</ol>
<p>The only other thing I added was a SSL plug-in that I created based on 3 other plug-ins.  I created my own, so I could force WP to load specific pages as HTTPS and then default back to HTTP if it was not explicitly set to support SSL.  I found most of the default plug-ins will leave the user browsing in SSL after they visit a SSL page, I didn&#8217;t want this and my plug-ins solves this problem.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
/*
Plugin Name: WPSSL Force SSL
Plugin URI:
Description: This plug-in is based on WPSSL, forcessl and various other posts/comments I found while searching for a soltuion.  The plug-in is used by adding the meta tag &quot;force_ssl&quot; with any value to any pages where you want SSL (&quot;HTTPS&quot;) enabled.  If the page does NOT have this set and your not looking at an admin page (you can enable SSL for admin/login page in wpconfig.php), then display as HTTP.  This prevent links on the SSL page from displaying as SSL for non-secure pages.  This plug-in was tested on WordPress 3.0.
Author: Zachary Hunter (based on Austin Web Development)
Version: 1.0
Author URI: 

*/

function wpssl_forcessl()
{
	global $post;

    $post_id = $post;

    if (is_object($post_id))
    {
		$post_id = $post_id-&gt;ID;
	}

    $force_ssl  = get_post_meta($post_id, 'force_ssl');

    if(!empty($force_ssl))
    {
    	if(!stristr($_SERVER['REQUEST_URI'], 'wp-admin')) {
			if($_SERVER[&quot;HTTPS&quot;] != &quot;on&quot;) {
				$newurl = &quot;https://&quot; . $_SERVER[&quot;SERVER_NAME&quot;] . $_SERVER[&quot;REQUEST_URI&quot;];
            	header(&quot;Location: $newurl&quot;);
            	exit();
        	}
     	}
    } else {
		if(!stristr($_SERVER['REQUEST_URI'], 'wp-admin')) {
			if($_SERVER[&quot;HTTPS&quot;] == &quot;on&quot;) {
				$newurl = &quot;http://&quot; . $_SERVER[&quot;SERVER_NAME&quot;] . $_SERVER[&quot;REQUEST_URI&quot;];
				header(&quot;Location: $newurl&quot;);
				exit();
			}
	}	}
}

add_action('wp', 'wpssl_forcessl');
?&gt;
</pre>
<p>To use the plug-in follow these steps.</p>
<p>1. Copy the code above into a file in your plugin folder (e.g. /wp-content/plugins/wpssl/wpssl.php).<br />
2. Go to the Plugins -> Plugins and enable &#8220;WPSSL Force SSL&#8221;.<br />
2. Go to the Page you want to force SSL and open the &#8220;Custom Fields&#8221; section.<br />
3. Click &#8220;Add Custom Field&#8221;, and use the settings below (name = force_ssl, value = true).<br />
** DONE **</p>
<p><img src="http://www.zachhunter.com/wp-content/uploads/force_ssl.png" alt="" title="WordPress Custom Force SSL Plug-in" class="alignnone wp-image-343" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2010/07/wordpress-3-0-a-cms-solution/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Improved NPOI ExportToExcel Function</title>
		<link>http://www.zachhunter.com/2010/06/improved-npoi-exportdatatabletoexcel-function/</link>
		<comments>http://www.zachhunter.com/2010/06/improved-npoi-exportdatatabletoexcel-function/#comments</comments>
		<pubDate>Wed, 16 Jun 2010 19:43:41 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=330</guid>
		<description><![CDATA[I was looking over my generic export DataTable to Excel function the other day and noticed an issue. My default method was throwing everything into a string format, which was preventing users from highlighting number columns for subtotals. To fix the problem they could use &#8220;Text to Columns&#8221;, but this was becoming a common complaint [...]]]></description>
			<content:encoded><![CDATA[<p>I was looking over my generic export DataTable to Excel function the other day and noticed an issue.  My default method was throwing everything into a string format, which was preventing users from highlighting number columns for subtotals.  To fix the problem they could use &#8220;Text to Columns&#8221;, but this was becoming a common complaint I wanted to resolve.  I came up with an improved &#8220;ExportToExcel&#8221; function that will insert the correct data type.</p>
<pre class="brush: csharp; title: ; notranslate">
        /// &lt;summary&gt;
        ///   Render DataTable to Excel File
        /// &lt;/summary&gt;
        /// &lt;param name = &quot;sourceTable&quot;&gt;Source DataTable&lt;/param&gt;
        /// &lt;param name = &quot;fileName&quot;&gt;Destination File Name&lt;/param&gt;
        public static void ExportToExcel(DataTable sourceTable, string fileName)
        {
            HSSFWorkbook workbook = new HSSFWorkbook();
            Sheet sheet = workbook.CreateSheet(&quot;Sheet1&quot;);
            Row headerRow = sheet.CreateRow(0);

            // Create Header Style
            CellStyle headerCellStyle = workbook.CreateCellStyle();
            headerCellStyle.FillForegroundColor = HSSFColor.GREY_25_PERCENT.index;
            headerCellStyle.FillPattern = FillPatternType.SOLID_FOREGROUND;

            // Create Date Style
            CellStyle dateCellStyle = workbook.CreateCellStyle();
            dateCellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat(&quot;m/d/yy&quot;);

            // Build Header
            foreach (DataColumn column in sourceTable.Columns)
            {
                Cell headerCell = headerRow.CreateCell(column.Ordinal);
                headerCell.SetCellValue(column.ColumnName);
                headerCell.CellStyle = headerCellStyle;
            }

            // Build Details (rows)
            int rowIndex = 1;
            int sheetIndex = 1;
            const int maxRows = 65536;

            foreach (DataRow row in sourceTable.Rows)
            {
                // Start new sheet max rows reached
                if (rowIndex % maxRows == 0)
                {
                    // Auto size columns on current sheet
                    for (int h = 0; h &lt; headerRow.LastCellNum; h++)
                    {
                        sheet.AutoSizeColumn(h);
                    }

                    sheetIndex++;
                    sheet = workbook.CreateSheet(&quot;Sheet&quot; + sheetIndex);
                    Row additionalHeaderRow = sheet.CreateRow(0);

                    for (int h = 0; h &lt; headerRow.LastCellNum; h++)
                    {
                        Cell additionalHeaderColumn = additionalHeaderRow.CreateCell(h);
                        additionalHeaderColumn.CellStyle = headerRow.GetCell(h).CellStyle;
                        additionalHeaderColumn.SetCellValue(headerRow.GetCell(h).RichStringCellValue);
                    }

                    rowIndex = 1;
                }

                // Create new row in sheet
                Row dataRow = sheet.CreateRow(rowIndex);

                foreach (DataColumn column in sourceTable.Columns)
                {
                    Cell dataCell = dataRow.CreateCell(column.Ordinal);

                    switch (column.DataType.FullName)
                    {
                        case &quot;System.String&quot;:
                            dataCell.SetCellValue(row[column].ToString());
                            break;
                        case &quot;System.Int&quot;:
                        case &quot;System.Int32&quot;:
                        case &quot;System.Int64&quot;:
                        case &quot;System.Double&quot;:
                        case &quot;System.Decimal&quot;:
                            double val;
                            dataCell.SetCellValue(Double.TryParse(row[column].ToString(), out val) ? val : 0);
                            break;
                        case &quot;System.DateTime&quot;:
                            DateTime dt = new DateTime(1900, 01, 01);
                            DateTime.TryParse(row[column].ToString(), out dt);

                            dataCell.SetCellValue(dt);
                            dataCell.CellStyle = dateCellStyle;
                            break;
                        default:
                            dataCell.SetCellValue(row[column].ToString());
                            break;
                    }
                }

                rowIndex++;
            }

            for (int h = 0; h &lt; headerRow.LastCellNum; h++)
            {
                sheet.AutoSizeColumn(h);
            }

            ExportToExcel(workbook, fileName);
        }
</pre>
<p>The key part of the function above to review is the &#8220;switch (column.DataType.FullName)&#8221; code block.  This grabs the DataTable&#8217;s column data type to use in the SetCellValue() call.</p>
<p>Once the workbook is built, we call a overload of the same function that expects a NPOI workbook.  This overload will send a XLS file back to the user via their web browser using the <strong>HttpResponse</strong> stream.</p>
<pre class="brush: csharp; title: ; notranslate">
        /// &lt;summary&gt;
        /// Render Excel File to HttpResponse (Browser)
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;workbook&quot;&gt;NPOI Workbook&lt;/param&gt;
        /// &lt;param name=&quot;fileName&quot;&gt;Destination File Name&lt;/param&gt;
        public static void ExportToExcel(HSSFWorkbook workbook, string fileName)
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                workbook.Write(memoryStream);
                memoryStream.Flush();

                try
                {
                    HttpResponse response = HttpContext.Current.Response;
                    response.ClearContent();
                    response.ClearHeaders();
                    response.Buffer = true;
                    response.ContentType = &quot;application/vnd.ms-excel&quot;;
                    response.AddHeader(&quot;Content-Length&quot;, memoryStream.Length.ToString());
                    response.AddHeader(&quot;Content-Disposition&quot;, string.Format(&quot;attachment;filename={0}&quot;, fileName));
                    response.BinaryWrite(memoryStream.GetBuffer());
                    response.Flush();
                    response.End();
                }
                catch
                {
                    // Do nothing, error expected due to Flush();
                }
            }
        }
</pre>
<p>I&#8217;ve used the above function to send files with 3-4 sheets full of data back to the browser&#8230; but the file size is usually &#8220;VERY LARGE&#8221;.  To work around this, I have a helper function which will add the excel file to a zip (in memory) before sending back to the client.</p>
<p>In my last test, a 17.5MB document with 2 sheets of data was compressed to 3.5MB with my zip utility.  There was still a ~13 second delay to generate the XLS file, but once prompted to download form the browser the file download completed in a few seconds.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2010/06/improved-npoi-exportdatatabletoexcel-function/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>jQuery Validation with ASP.NET</title>
		<link>http://www.zachhunter.com/2010/06/jquery-validation-with-asp-net/</link>
		<comments>http://www.zachhunter.com/2010/06/jquery-validation-with-asp-net/#comments</comments>
		<pubDate>Wed, 09 Jun 2010 04:20:48 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=314</guid>
		<description><![CDATA[Over the past few weeks I&#8217;ve been working to migrate away from the Ajax Control Toolkit &#38; various other ASP.NET built-in controls. My goal has been to get every page of our intranet portal down around 100K, with a maximum load time of &#60; 1 second. I&#8217;ve made a lot of progress, but after cleaning [...]]]></description>
			<content:encoded><![CDATA[<p>Over the past few weeks I&#8217;ve been working to migrate away from the Ajax Control Toolkit &amp; various other ASP.NET built-in controls.  My goal has been to get every page of our intranet portal down around 100K, with a maximum load time of &lt; 1 second.  I&#8217;ve made a lot of progress, but after cleaning up all the basic stuff (excess view state, duplicate references, compressed JS/CSS, sprites, etc&#8230;), I had to start looking for additional items&#8230;</p>
<p>Using <a href="http://www.fiddler2.com/fiddler2/">Fiddler</a> and <a href="http://getfirebug.com/">FireBug</a>, I started looking for resources that were increasing my download sizes and found that the ASP.NET validation controls were generating ~10K each time they were used in a module.  Since my portal consists of injecting multiple user controls into a page, this number would vary page-by-page based on the number of modules that used the library on one page.  Since I was using jQuery for all my scripting, I decided to implement <a href="http://bassistance.de/jquery-plugins/jquery-plugin-validation/">jQuery Validation Plugin</a> as a replacement for the built-in ASP.NET validation controls.</p>
<p>The idea was simple enough, but since I&#8217;m living in <strong>ASP.NET Web Form</strong> world (aka: <em>One form per/page</em>) this was a bit more difficult to implement.</p>
<h2>Issue #1 &#8211; jQuery Validation by FIELDSET</h2>
<p>As noted, the default setup of the validation plug in is to validate a FORM which isn&#8217;t possible with ASP.NET Web Forms.  To get around this, I decided I was going to wrap all my forms in a FIELDSET with the class &#8220;validationGroup&#8221;.  Using this class as my selection, I&#8217;m able to have multiple groups of controls wrapped in a FIELDSET validated separately.</p>
<p>To get started, you need to create a custom validation function that will recursively move up the elements/groups to find a FIELDSET with the class &#8220;validationGroup&#8221;, and then check all the input elements against the rules assigned.</p>
<p>Here is my custom validation function:</p>
<pre class="brush: jscript; title: ; notranslate">
function ValidateAndSubmit(evt) {
    var isValid = true;

    // Get Validator &amp; Settings
    var validator = $(&quot;#aspnetForm&quot;).validate();
    var settings = validator.settings;

    // Find the parent control that contains the elements to be validated
    var $group = $(evt.currentTarget).parents('.validationGroup');

    // Grab all the input elements (minus items listed below)
    $group
        .find(&quot;:input&quot;)
        .not(&quot;:submit, :reset, :image, [disabled]&quot;)
        .not(settings.ignore)
        .each(function (i, item) {
            // Don't validate items without rules
            if (!validator.objectLength($(item).rules()))
                return true;

            if (!$(item).valid())
                isValid = false;
        });

    // If any control is the group fails, prevent default actions (aka: Submit)
    if (!isValid)
        evt.preventDefault();
}
</pre>
<p>Next, I need to trigger the validation for the current FIELDSET I&#8217;m working in based on on some action&#8230; like the click of a submit button.  Since the default setting is to validation on submit, you need to disable this and register your <strong>ValidateAndSubmit</strong> function call when your event is triggered.</p>
<pre class="brush: jscript; title: ; notranslate">
        // Disable default/auto binding of all buttons
        $(&quot;#aspnetForm&quot;).validate({
            onsubmit: false,
            ignore: ':hidden',
            focusInvalid: true
        });

        // Bind the ASP.NET button with the ID &quot;Search&quot; to the &quot;ValidateAndSubmit&quot; custom validation function.
        $('#&lt;%= Search.ClientID %&gt;').click(ValidateAndSubmit);
</pre>
<p>That&#8217;s it, with those three little little steps (Custom Validate Method, Disable Default/Auto Bind, Manual bind button to custom event), you now have a working validate by FIELDSET (or any other grouping control) solution.</p>
<h2>Issue #2 &#8211; How to validate a group of ASP.NET Check Boxes</h2>
<p>By default, ASP.NET will render a CheckBox or a CheckBoxList with an auto generated unique name attribute.  This becomes a problem when you want to validate the group, since you can&#8217;t set a common name attribute for all the elements.</p>
<p>Here is an example of the HTML that would be rendered by a CheckBoxList with a layout of &#8220;Flow&#8221;.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;span id=&quot;CheckBoxGroup&quot;&gt;
  &lt;input id=&quot;cbk1&quot; name=&quot;cbk1&quot; type=&quot;checkbox&quot;&gt;Check Box 1&lt;/input&gt;
  &lt;input id=&quot;cbk2&quot; name=&quot;cbk2&quot; type=&quot;checkbox&quot;&gt;Check Box 2&lt;/input&gt;
  &lt;input id=&quot;cbk3&quot; name=&quot;cbk3&quot; type=&quot;checkbox&quot;&gt;Check Box 3&lt;/input&gt;
&lt;/span&gt;
&lt;span class=&quot;jQueryValError&quot;&gt;&lt;/span&gt;
</pre>
<p>My solution to the problem required a custom validator and a custom errorPlacement function, for the jQuery validaiton plug-in.</p>
<p>First, I added a custom validator that looked at a group of check boxes that are inside a wrapping &#8220;Parent()&#8221; element.  I then count the number of checked check boxes to make sure the limit required (e.g. Must check at least 3 check boxes) is greater than the minimum we set.</p>
<pre class="brush: jscript; title: ; notranslate">
    jQuery.validator.addMethod(&quot;minChecked&quot;,
     function(value, element, param) {
        var $p = $(element).parent();
        var selected = $p.children('input[type=checkbox]:checked').length;

        if (selected &gt;= param) {
            $p.children().removeClass('error');
            $p.siblings('.error').remove();
            return true;
            }

        $p.children('input[type=checkbox]').addClass('error');
</pre>
<p>In order to hookup this custom event to all the controls inside of a wrapping &#8220;Parent()&#8221; control, we use jQuery&#8217;s $().each function to call the validator&#8217;s rules() function.</p>
<pre class="brush: jscript; title: ; notranslate">
$(&quot;.checkBoxGroup&quot;).children('input[type=checkbox]').each(function(){ $(this).rules(&quot;add&quot;, { minChecked: 3}); });
</pre>
<p>Second, our plug-in will by default put an error message next to the control(s) that triggered the error.  I over ride the default behavior, we setup a &#8220;errorPlacement&#8221; function to put one error beside the wrapping &#8220;Parent()&#8221; control. </p>
<pre class="brush: jscript; title: ; notranslate">
            $(&quot;#&lt;%= form1.ClientID %&gt;&quot;).validate({
                errorPlacement: function(error, element){
                    if(element.rules().minChecked &gt; 0) {
                        var $p = $(element).parent();
                        if($p.siblings().hasClass(&quot;error&quot;) == false) {
                            error.insertAfter($p);
                        }
                    }
                    else {
                        error.insertAfter(element);
                    }
                }
            });
</pre>
<p>Here is what the form looks like when you have a error with your check boxes.</p>
<p><a href="http://www.zachhunter.com/wp-content/uploads/jQueryValidation_ASPNET_CheckBoxes.jpg"><img src="http://www.zachhunter.com/wp-content/uploads/jQueryValidation_ASPNET_CheckBoxes-300x97.jpg" alt="jQuery Validation of ASP.NET CheckBoxes" title="jQuery Validation of ASP.NET CheckBoxes" width="300" height="97" class="alignnone size-medium wp-image-332" /></a></p>
<p>Here is source code used to create the example above.</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head runat=&quot;server&quot;&gt;
    &lt;title&gt;Contact Form Demo&lt;/title&gt;

    &lt;script src=&quot;styles/jQuery.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;

    &lt;script src=&quot;styles/jQuery.Validate.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;

    &lt;script src=&quot;styles/jQuery.Validate.AddOns.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;

    &lt;script type=&quot;text/javascript&quot;&gt;

    jQuery.validator.addMethod(&quot;minChecked&quot;,
     function(value, element, param) {
        var $p = $(element).parent();
        var selected = $p.children('input[type=checkbox]:checked').length;

        if (selected &gt;= param) {
            $p.children().removeClass('error');
            $p.siblings('.error').remove();
            return true;
            }

        $p.children('input[type=checkbox]').addClass('error');

        return false;}, jQuery.validator.format(&quot;Please check at least {0} items.&quot;)); 

        $(document).ready(function(){
            $(&quot;#&lt;%= form1.ClientID %&gt;&quot;).validate({
                rules: {
                    &lt;%= FirstName.UniqueID %&gt;: { required: true },
                    &lt;%= LastName.UniqueID %&gt;: { required: true },
                    &lt;%= Email.UniqueID %&gt;: { required: true, email: true },
                    &lt;%= Phone.UniqueID %&gt;: { required: true, phoneUS: true }
                },
                errorPlacement: function(error, element){
                    if(element.rules().minChecked &gt; 0) {
                        var $p = $(element).parent();
                        if($p.siblings().hasClass(&quot;error&quot;) == false) {
                            error.insertAfter($p);
                        }
                    }
                    else {
                        error.insertAfter(element);
                    }
                }
            });

            $(&quot;.checkBoxGroup&quot;).children('input[type=checkbox]').each(function(){ $(this).rules(&quot;add&quot;, { minChecked: 3}); });

            $(&quot;.myGroupRandom&quot;).children('input[type=checkbox]').each(function(){ $(this).rules(&quot;add&quot;, { minChecked: 1}); });
        });
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form id=&quot;form1&quot; runat=&quot;server&quot;&gt;
    &lt;div&gt;
        &lt;fieldset&gt;
            &lt;ol&gt;
                &lt;li&gt;
                    &lt;label class=&quot;left&quot;&gt;
                        First Name
                    &lt;/label&gt;
                    &lt;input type=&quot;text&quot; id=&quot;FirstName&quot; runat=&quot;server&quot; /&gt;&lt;/li&gt;
                &lt;li&gt;
                    &lt;label class=&quot;left&quot;&gt;
                        Last Name
                    &lt;/label&gt;
                    &lt;input type=&quot;text&quot; id=&quot;LastName&quot; runat=&quot;server&quot; /&gt;&lt;/li&gt;
                &lt;li&gt;
                    &lt;label class=&quot;left&quot;&gt;
                        Email
                    &lt;/label&gt;
                    &lt;input type=&quot;text&quot; id=&quot;Email&quot; runat=&quot;server&quot; /&gt;&lt;/li&gt;
                &lt;li&gt;
                    &lt;label class=&quot;left&quot;&gt;
                        Phone
                    &lt;/label&gt;
                    &lt;input type=&quot;text&quot; id=&quot;Phone&quot; runat=&quot;server&quot; /&gt;&lt;/li&gt;
                &lt;li&gt;
                    &lt;label class=&quot;left&quot;&gt;
                        Contact Method
                    &lt;/label&gt;
                    &lt;span class=&quot;checkBoxGroup&quot;&gt;
                        &lt;input type=&quot;checkbox&quot; id=&quot;ReqEmail&quot; runat=&quot;server&quot; /&gt;&lt;label&gt;Email&lt;/label&gt;
                        &lt;input type=&quot;checkbox&quot; id=&quot;ReqMail&quot; runat=&quot;server&quot; /&gt;&lt;label&gt;Mail&lt;/label&gt;
                        &lt;input type=&quot;checkbox&quot; id=&quot;ReqPhone&quot; runat=&quot;server&quot; /&gt;&lt;label&gt;Phone&lt;/label&gt;
                        &lt;input type=&quot;checkbox&quot; id=&quot;ReqNoContact&quot; runat=&quot;server&quot; /&gt;&lt;label&gt;No Contact&lt;/label&gt;
                    &lt;/span&gt;&lt;/li&gt;
                &lt;li&gt;
                    &lt;label class=&quot;left&quot;&gt;
                        New Letter Type
                    &lt;/label&gt;
                    &lt;span class=&quot;myGroupRandom&quot; &gt;
                        &lt;input type=&quot;checkbox&quot; id=&quot;Checkbox1&quot; runat=&quot;server&quot; /&gt;&lt;label&gt;Company News&lt;/label&gt;
                        &lt;input type=&quot;checkbox&quot; id=&quot;Checkbox2&quot; runat=&quot;server&quot; /&gt;&lt;label&gt;Press Releases&lt;/label&gt;
                        &lt;input type=&quot;checkbox&quot; id=&quot;Checkbox3&quot; runat=&quot;server&quot; /&gt;&lt;label&gt;Deals&lt;/label&gt;
                        &lt;input type=&quot;checkbox&quot; id=&quot;Checkbox4&quot; runat=&quot;server&quot; /&gt;&lt;label&gt;Employement&lt;/label&gt;
                    &lt;/span&gt;&lt;/li&gt;
                &lt;li&gt;
                    &lt;input type=&quot;submit&quot; id=&quot;Submit&quot; value=&quot;Submit&quot; /&gt;&lt;/li&gt;
            &lt;/ol&gt;
        &lt;/fieldset&gt;
    &lt;/div&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2010/06/jquery-validation-with-asp-net/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>Using jQuery to prevent &#8220;Delete&#8221; mistakes</title>
		<link>http://www.zachhunter.com/2010/05/using-jquery-to-prevent-delete-mistakes/</link>
		<comments>http://www.zachhunter.com/2010/05/using-jquery-to-prevent-delete-mistakes/#comments</comments>
		<pubDate>Thu, 20 May 2010 06:06:22 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://www.zachhunter.com/?p=268</guid>
		<description><![CDATA[Using the Poka-Yoke principal to prevent accidental "Deletes" using jQuery]]></description>
			<content:encoded><![CDATA[<p>A few days ago I was reading a web design article that talked about the &#8220;<a href="http://en.wikipedia.org/wiki/Poka-yoke">Poka-Yoke</a>&#8221; principle.  It was such a funny phrase that I had to go to Wikipedia to figure out the definition.  In a nutshell, the principle refers to the process of &#8220;idiot-proofing&#8221; human interaction with a process.  This term is based on the Japanese words &#8220;yokeru&#8221; avoid and &#8220;poka&#8221; mistake, this is rather funny for me since I work for a Japanese company that has clearly never heard of this principle!</p>
<p>This term came to mind today while helping another programmer develop a system to prevent accidental in their UI.  After discussing what needed to be done, it was clear that we needed to implement some client side logic to &#8220;prevent&#8230; guide&#8230;&#8221; the user into making the correct choices.</p>
<p>The UI was pretty straight forward, there will be a few buttons to do various actions on rows in a table.  The users will select one or more rows for the table and then click the button of the action they want to perform.  Sounds simple, right&#8230; We&#8217;ll it is and it&#8217;s also really easy to select the wrong row and/or the wrong button.  Training is a big help in any process, but one you leave the users alone the system will be the only thing enforcing the rules.</p>
<p>Here is an example of a table where rows will be selected for deletion.  I used a &#8220;asp:Table&#8221; to simulate the markup for a table that will be generated with a &#8220;asp:GridView&#8221;.  In my past 5 years of working with ASP.NET, this was the first time I ever used or seen this control used.</p>
<pre class="brush: xml; title: ; notranslate">
    &lt;div class=&quot;mediumTable&quot;&gt;
        &lt;asp:Button ID=&quot;DeleteButton&quot; runat=&quot;server&quot; Text=&quot;Delete&quot; /&gt;
        &lt;asp:Table ID=&quot;Table1&quot; runat=&quot;server&quot;&gt;
            &lt;asp:TableHeaderRow&gt;
                &lt;asp:TableHeaderCell&gt;Chk&lt;/asp:TableHeaderCell&gt;
                &lt;asp:TableHeaderCell&gt;Product&lt;/asp:TableHeaderCell&gt;
                &lt;asp:TableHeaderCell&gt;Stock&lt;/asp:TableHeaderCell&gt;
            &lt;/asp:TableHeaderRow&gt;
            &lt;asp:TableRow&gt;
                &lt;asp:TableCell&gt;
                    &lt;asp:CheckBox ID=&quot;CheckBox1&quot; runat=&quot;server&quot; /&gt;&lt;/asp:TableCell&gt;
                &lt;asp:TableCell&gt;Apples&lt;/asp:TableCell&gt;
                &lt;asp:TableCell&gt;0&lt;/asp:TableCell&gt;
            &lt;/asp:TableRow&gt;
            &lt;asp:TableRow&gt;
                &lt;asp:TableCell&gt;
                    &lt;asp:CheckBox ID=&quot;CheckBox2&quot; runat=&quot;server&quot; /&gt;&lt;/asp:TableCell&gt;
                &lt;asp:TableCell&gt;Oranges&lt;/asp:TableCell&gt;
                &lt;asp:TableCell&gt;100&lt;/asp:TableCell&gt;
            &lt;/asp:TableRow&gt;
            &lt;asp:TableRow&gt;
                &lt;asp:TableCell&gt;
                    &lt;asp:CheckBox ID=&quot;CheckBox3&quot; runat=&quot;server&quot; /&gt;&lt;/asp:TableCell&gt;
                &lt;asp:TableCell&gt;Pears&lt;/asp:TableCell&gt;
                &lt;asp:TableCell&gt;150&lt;/asp:TableCell&gt;
            &lt;/asp:TableRow&gt;
            &lt;asp:TableRow&gt;
                &lt;asp:TableCell&gt;
                    &lt;asp:CheckBox ID=&quot;CheckBox4&quot; runat=&quot;server&quot; /&gt;&lt;/asp:TableCell&gt;
                &lt;asp:TableCell&gt;Watermelon&lt;/asp:TableCell&gt;
                &lt;asp:TableCell&gt;2&lt;/asp:TableCell&gt;
            &lt;/asp:TableRow&gt;
        &lt;/asp:Table&gt;
    &lt;/div&gt;
    &lt;/form&gt;
</pre>
<p>Here is the delete &#8220;prevention&#8221; system we came up.  We had a few other ideas like, but after doing a few demos of each solution we decided on the following code that will be discussed below.</p>
<pre class="brush: jscript; title: ; notranslate">
        $(document).ready(function() {
            $('#&lt;%= DeleteButton.ClientID %&gt;').click(function() {
                // Find all selected items
                var CheckedCheckBoxes = $('#&lt;%= Table1.ClientID %&gt;').find(&quot;input[type='checkbox']:checked&quot;);
                // If there are no selected items, exit
                if (CheckedCheckBoxes.length == 0) {
                    alert(&quot;You must make a selection before you can delete an item.&quot;);
                    return false;
                }
                // If there are selected items, loop
                CheckedCheckBoxes.each(function() {
                    var isProcessed = $(this).parent().parent().find('td:last').text();
                    // If current item is already processed, set flat to true
                    if (jQuery.trim(isProcessed) &gt; 0) {
                        deletedProcessed = true;
                    }
                });
                // Check flag, if true stop ALL deletes and notify user
                if (deletedProcessed) {
                    alert(&quot;You can't delete a product with stock!&quot;);
                    return false;
                }
                else {
                    // Do a final confirmation the user wants to delete the selection
                    var answer = confirm('Are you sure you want to delete your selection?');
                    return answer
                }
            });
        });
</pre>
<p>Since selection box was used for a few different functions (process orders, hold orders and edit orders) we needed a way to add a little extra checking to only the delete button.  Our goals with the logic above was the following.</p>
<ol style="margin-left:40px;">
<li>Disables &#8220;Delete&#8221; if nothing has been selected.</li>
<li>Disables &#8220;Delete&#8221; if the user selected a item should not be deleted (e.g. Has Inventory).</li>
<li>Prompts the user to confirm the really want to delete the item.</li>
</ol>
<p>In addition to these ideas, we also had the following ideas&#8230;</p>
<ol style="margin-left:40px;">
<li>Alert row # of items that don&#8217;t meet the business rule</li>
<li>Highlight the row in &#8220;red&#8221; that don&#8217;t meet the business rule</li>
<li>Physically &#8220;Disable&#8221; the delete button if they select an item that don&#8217;t meet the business rules</li>
</ol>
<p>Mistakes are human nature and by double and triple checking what they are doing we can save the users and ourselves from many emails/phone calls/visits about how the system &#8220;deleted the data all by itself&#8221;.</p>
<p>Mistake proofing is such an easy idea to grasp and agree with, that it&#8217;s surprising that we don&#8217;t see more of it in the systems we using everyday.  I&#8217;m sure I&#8217;ve developed a few bad ones, hopefully the audience using it was small and it didn&#8217;t mitigate itself into other things.  Working for a Japanese company who has developed some of the worst internal tools I&#8217;ve ever seen (0 UI design effort), I&#8217;m sure to bring up the new Japanese &#8220;Poka-Yoke&#8221; principle that next time I talk to one of the developers in Japan.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachhunter.com/2010/05/using-jquery-to-prevent-delete-mistakes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

