# Thursday, 11 October 2012

Have you heard about the Succinctly Series? Syncfusion has produced a number of free e-Books on various subjects ranging from source control to jQuery to HTTP.  I highly recommend you pick up these free books. You’ll have to register but it’s worth it. This is an unsolicited review. Smile

So far I’ve read the Knockout.js Succintly, ASP.NET MVC 4 Mobile Websites Succinctly, PDF Succinctly and JavaScript Succinctly. They are great beginner books and very quick reads especially if you are beyond the basic level. They average around 60 pages per book with 150 pages being the biggest I’ve seen.

They seem to be rolling out a new book every few months. So far they have:

Knockout.js Succinctly

C++ Succinctly

ASP.NET MVC 4 Mobile Websites Succinctly

LightSwitch Succinctly

Javascript Succinctly

HTTP Succinctly

PDF Succinctly

Git Succinctly

jQuery Succinctly

Happy Coding! Smile

Books | Git | JavaScript | jQuery | Knockout | review
Posted 10.11.2012  #    Comments [0]  | 
# Wednesday, 03 October 2012

I upgraded a project recently from 1.7.2 of jQuery to 1.8.2 and began testing my pages.  On one of my pages I was getting the following error:

unrecognized expression

Doing a little research I discovered that in the 1.8 release of jQuery they deprecated the :radio and other such pseudo-class selectors.  The preferred method moving forward is to use the equivalent CSS selector of [type=radio].

Here’s the jQuery 1.8 release notes and the ticket describing this change.

Why the removal?

From their radio selector page under the Additional Notes section:

Because :radio is a jQuery extension and not part of the CSS specification, queries using :radio cannot take advantage of the performance boost provided by the native DOM querySelectorAll() method. For better performance in modern browsers, use [type="radio"] instead.

And from the ticket page:

Deprecate (for eventual removal) the input type selectors: :file :image :password :radio :reset :submit :text -- They are basically aliases to [type="file"] [type="image"] but can't use querySelectorAll - I think having these selectors around in the long term future is entirely unnecessary and confusing.

Happy Coding! Smile

:radio | 1.8 | jQuery
Posted 10.03.2012  #    Comments [3]  | 
# Thursday, 24 March 2011

One of the awesome features in MVC is Unobtrusive JavaScript.  In MVC 3 apps you can set this in the web.config.  It’s on by default.

I have a legacy database that has a field that is required and doesn’t allow nulls but the application allows for empty strings to be entered into the field.  I know, what’s the point of requiring a field and allowing empty strings (if empty string actually means something, OK). 

When I set the Required Data Annotation with the AllowEmptyString=true on the field the validator was still returning an error.  On a hunch I set UnobtrusiveJavaScriptEnabled=false and then field began working as expected.

What gives?

MVC 3 uses jQuery validators when UnobtrusiveJavaScriptEnabled is true.  For the Required annotation it uses the jQuery required validator which doesn’t have the AllowEmptyString parameter or one like it.  Essentially, the validator ignores this parameter. Thanks to @srkirkland for pointing this out. And he would know, he runs the OSS Data Annotations Extensions project.

Happy Coding!

Posted 03.24.2011  #    Comments [2]  | 
# Wednesday, 20 October 2010

We had a situation with one of our applications were the team felt it was easier to use straight html to do some work in a form.  All went pretty well until we created a checkbox input array:

<input type="checkbox" name="CheckboxArray" />
<input type="checkbox" name="CheckboxArray" />
<input type="checkbox" name="CheckboxArray" />
<input type="checkbox" name="CheckboxArray" />

and we retrieved them via the Request.Form(“CheckboxArray”).

image

We discovered when we tried to retrieve the array only the checked items were being returned and their position in the array is lost. 

image

Which ones are on? We can’t assume it’s the first and second one.

Solution:

Give the checkboxes a value that uniquely identifies it.

<input type="checkbox" name="CheckboxArray" value="1" />
<input type="checkbox" name="CheckboxArray" value="2" />
<input type="checkbox" name="CheckboxArray" value="3" />
<input type="checkbox" name="CheckboxArray" value="4" />

Now when you retrieve the array it returns the values of the checkboxes that are checked.

image

What if you want to return all the checkboxes whether they are on or off?  A little more work is needed in this case.  We’ll add a hidden field array for each of our checkboxes and will have these fields keep the status of our checkboxes.

<input type="checkbox" name="CheckboxArray2" /><input type="hidden" name="CheckboxFix" value="false" />
<input type="checkbox" name="CheckboxArray2" /><input type="hidden" name="CheckboxFix" value="false" />
<input type="checkbox" name="CheckboxArray2" /><input type="hidden" name="CheckboxFix" value="false" />
<input type="checkbox" name="CheckboxArray2" /><input type="hidden" name="CheckboxFix" value="false"/>

We’ll use jQuery to help with keeping the status.

<script type="text/javascript">
    $(document).ready(function () {
      $("[name=CheckboxArray2]").click(function () {
        $(this).next("[name=CheckboxFix]").val($(this).attr("checked"));
    });
}); 
</script>

Now in the code behind we’ll use the CheckboxFix instead of using the CheckboxArray2 in the Request.Forms call.

image

In our case we went with this second option because we were using jQuery on the client to enable the user to add, delete and reorder the rows of information.  Using the latter technique allowed us to easily work with the submitted data in a similar manner with the rest of the items in each row.

Happy Coding!

Posted 10.20.2010  #    Comments [0]  | 
# Wednesday, 04 August 2010

Normally forms don’t have much of a visual queue to the end user showing them where they are on a page.

image

Wouldn’t it be nice though?

image

That just seems like a step in the right direction.  Making this happen is a lot easier than I thought.  Most browsers can handle this with the css pseudo-class selector.  The css to make this happen for all your inputs would look like this:

input:focus
{
    background-color:LightYellow;
    border-color:Red;
    border-style:dotted;
    border-width:2px;
}

Pretty simple.  However, If you are need to support IE7 and lower the css above won’t do anything. IE7 doesn’t respect the focus selector.  Don’t fret. jQuery to the rescue.

if ($.browser.msie && $.browser.version == "7.0") {
    $("input").focus(function() {
        $(this).addClass('FocusFix');
    }).blur(function() {
      $(this).removeClass('FocusFix');
  });
}

Be sure to add the FocusFix class to your css:

input:focus, input.FocusFix
{
    background-color:LightYellow;
    border-color:Red;
    border-style:dotted;
    border-width:2px;
}

That should get you going in IE7.  You might notice though all your input types are doing this even buttons for example.  You can fix this by telling jQuery and css to select on certain types of inputs.

CSS:

input[type="text"]:focus, input[type="password"]:focus
And with jQuery:
if ($.browser.msie && $.browser.version == "7.0") {
  $("input[type='text'], input[type='password']").focus(function() {
      $(this).addClass('FocusFix');
  }).blur(function() {
    $(this).removeClass('FocusFix');
});

I have done all my targeting with the input element. You can just as easily have done this with classes for your elements. In my case, the application is already well underway and it seemed an easier approach to select the input types I wanted. You could also add your textareas easily this way.

Happy Coding!

Posted 08.04.2010  #    Comments [0]  | 
# Monday, 02 August 2010

Over the past week our team has been crunching out an asp.net webforms app to help manage our flood response situation that has been a very unfortunate side effect of the fire here in Coconino County.  We have been going pretty fast, releasing one to two updates a day in order to get functionality out quickly to those who need it.

Today, we had a breather and I decided to go back and spruce up our work.  One item on my plate was to help the users more easily enter dates.  The main entry form has over 10 date fields.  A little excessive but it’s what they need.  I could just use the AJAX calendar extender but that would mean quite a bit of clicking and properties to set manually.

I had a hunch that the jQuery way may have an easier solution.  Using Selectors, the solution ended up being one line of code.

<script type="text/javascript">
    $(function() {
        $("input[name*='dte']").datepicker();
    });
</script>

How awesome is that. All of our date inputs have a prefix of 'dte' allowing a simple selector over all inputs with 'dte' in the name attribute.  Normally, one would give all date inputs a class that can be use instead but they all already had this in common.

With the same idea in mind, I decided to change all of our buttons to use the jQuery button widget to get a nice and quick improvement on the look and feel.

<script type="text/javascript">
    $(function() {
        $(":submit, :button").button();
    });
</script>

In our case, we defined buttons two different ways in our code.  Again, with selectors we can handle this with one line of code.

Downloading and using jQuery UI couldn’t be simpler.  I customized the download (you don’t have to) to only use the date picker and button widgets and added the customized jQuery to a script tag.  jQuery UI depends on jQuery but instead of using the version downloaded I used the google CDN to help speed things up a bit.  Last, I added the theme for the controls to the app and referenced the stylesheet.

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="scripts/jquery-ui-1.8.2.custom.min.js"></script>
<link href="~/stylesheets/jqueryUIcss/ui-lightness/jquery-ui-1.8.2.custom.css" rel="Stylesheet" type="text/css" /> 

The ability to do this so easily and quickly with jQuery is a big WIN.  I wonder if this is easily replicated with MS AJAX?  My hunch is it’s probably doable but can’t possibly be easier and I imagine it’s not nearly as easy.  I could be wrong though…

Happy Coding!

Posted 08.02.2010  #    Comments [0]  | 
# Friday, 07 May 2010

A few posts back I wrote about adding character counting to the .Net AJAX HTML Editor.  Recently, I received a question asking how to hide and show the character count element for the .Net AJAX HTML Editor when the editor goes in and out of focus.  The short and sweet answer is to wire up a function on the focus and blur events of the editor control and call the hide / show methods in jQuery on your count element.

$(GetEditor()).focus(function() {
  $(Editor1InfoArea).show();
}).blur(function() {
  $(Editor1InfoArea).hide();
});

Just add the above code in the $(document).ready function and away you go.  The GetEditor function and Editor1InfoArea variable are referenced in code in the original post.

However, jQuery has a lot to offer and I wanted to show some of these offerings.  I took advantage of method chaining to save myself having to call $(GetEditor()) twice as shown below.

$(GetEditor()).focus(function() { $(Editor1InfoArea).show();  });
$(GetEditor()).blur(function() { $(Editor1InfoArea).hide(); });

If your new to jQuery chaining may throw you a bit but it works great for saving keystrokes and once you get used to the syntax can be easy to follow. 

Beyond the show and hide methods you could call on many other methods to add some panache (Come on, give this one to me,  I am French after all).

You could replace show/hide with some of these combinations:

Nothing like making your app a little more appealing with some animation.  But wait! There’s more.

You can also change the style with the css method:

$(Editor1InfoArea).css("display", "block");
$(Editor1InfoArea).css("display", "none");
Or
$(Editor1InfoArea).css("visibility", "");
$(Editor1InfoArea).css("visibility", "hidden");

Of course, you are using classes to make easier management of your styling right?  You can use the addClass/removeClass methods:

$(Editor1InfoArea).addClass("showCounter");
$(Editor1InfoArea).removeClass("showCounter");

* What about the toggle method? Ah, I’m glad you asked. In this case since we are tracking the focus and blur events you may end up with the toggle working the opposite as you expect.  This is because toggle does the opposite of what the targeted element’s visible value is when called.  You can fix this by calling the show or hide on your element after the focus/bind methods are setup.  Toggle is really designed for the click event but can be used in this situation.

So there you have it.  More ways than you probably care to know and I wouldn’t be surprised if there were more. 

A parting thought.  Earlier this week I read a great post on the performance of show/hide vs. toggle, css and addClass/removeClass.  Check it out if you want to read more on it but the basic answer is calling the css method is the best.  However, there is one more way that’s even faster but you’ll just have to read the article to find out what it is.

Happy Coding! :-)

Posted 05.07.2010  #    Comments [0]  | 
# Friday, 08 January 2010

In a couple of earlier posts I used jQuery to add a character counter to the ASP.Net AJAX HTML Editor.  I was contacted by a reader stating that when they modified the editor’s toolbar items the character counter stopped working.  After a small bit of troubleshooting I noticed the toolbar items drive the number of IFrames created.

The fix is small but requires some sleuthing that we can do with firebug to identify the correct IFrame we should be targeting.  With firebug console and our browser open to the url for our application we can type in $('#Editor1').contents().find('iframe').eq(0).  This grabs the first IFrame.  Be sure to change "Editor1" to the name of your control.

FirebugShot1

If we hover over the item in the brackets it will highlight the IFrame selected.  If the text area for the control isn’t highlighted then change the index value and try again until the text area is highlighted.

FirebugShot2

To be sure we have the right IFrame, click on the item in the brackets and it shows the HTML.  Look for the text you typed in to be sure.

FirebugShot3

Now that we’ve identified the correct index for the IFrame based on a customized editor we’ll need to change the GetEditor Function with this correct value.

function GetEditor() {
    return editor = $(Editor1).contents().find('iframe').eq(0);
}

You should be ready to go now! But wait! There’s more…

I was dissatisfied with having to hunt for the correct index value and thankfully there is a better way.  I noticed while trying this out on several scenarios that the IFrame we want is given the same ID.  At first, I didn’t think this would work since the ID is assigned by ASP.Net but it seems in this case we can trust it (could be my famous last words).  The IFrame is always given an ID of ControlName_ctl02_ctl00 or in this case Editor1_ctl02_ctl00.

Armed with this we can change the code to:

function GetEditor() {
    return editor = $(Editor1 + '_ctl02_ctl00')
}

That's a little better. We don't have to hunt for the correct index value for the IFrame used for the text.

Please download the code and give it a spin! AjaxHtmlEditorV3.zip (1.01 MB)

Happy Coding!

Read the earlier posts.

Posted 01.08.2010  #    Comments [2]  | 
# Friday, 11 December 2009

In an earlier post I added character counting functionality to the ASP.Net AJAX HTML Editor with jQuery.  Soon after posting the entry I noticed that cutting and pasting text into the editor via the context menu did not change the character count immediately.  I enhanced the jQuery code in my last post to do this.

var Editor1 = '#Editor1';
var Editor1CountLimit = 50
var Editor1InfoArea = '#Info';

$(document).ready(function() {
    TrackCharacterCount(Editor1, Editor1CountLimit, Editor1InfoArea);
});

function TrackCharacterCount(ctl, limit, info) {
    var editor = GetEditor();
    $(editor).load(function() {

    var body = $(this).contents().find('body');
    var txt = $(body).text();
    $(info).html(txt.length); //set initial value 

    $(body).bind('cut paste', function(e) {
            setTimeout(function() {
                var txt = $(body).text();
                UpdateTextCounter(txt,limit,info);
            }, 150)
        });
        
        $(this).contents().keyup(function() {
            var txt = $(this).contents().find('body').text();
            UpdateTextCounter(txt,limit,info);
        });
    });
}

function UpdateTextCounter(txt,limit,counter) {
    if (txt.length > limit)
        $(counter).html(txt.length).css("color", "red");
    else
        $(counter).html(txt.length).css("color", "");
} 

I added the bind code on line 17 to handle the cut and paste functionality.  I went through a couple iterations of the cut & paste functionality to count the characters correctly.  I was running into an issue where the textbox value was not being updated immediately with what was pasted.  Then I stumbled upon a nice stackoverflow answer that used a timeout to wait for the textbox to be updated.  This little jewel allowed me to simplify the code to what it is now.

I refactored the code to decrease duplication of code by creating the UpdateTextCounter function. 

I also noticed a subtle difference between IE7 and IE8 that stopped the counter from working and have corrected that in this version with a browser check.

function GetEditor() {
    if ($.browser.msie == 'true' && $.browser.version == '7.0')
        return editor = $(Editor1).contents().find('iframe').eq(1);
    else
        return editor = $(Editor1).contents().find('iframe').eq(2);
}

I verified the code runs on IE7, IE8, FF 3.5.5 & Chrome 3.0.

Enjoy!

AjaxHtmlEditorV2.zip (1.28 MB)

Read the first post.

Read the next post where I fix a bug when using a customized toolbox with the editor and find a better way to locate the IFrame that our text editor is in.

Posted 12.11.2009  #    Comments [0]  | 
# Saturday, 14 November 2009

Recently, one of our ASP.Net WebForm app’s had a new requirement for formatted text entry. No problem, the HTML Editor control from the AJAX control toolkit would fit the bill nicely.

In this new version, we were asked to show the count of characters used as a user types and enforce a maximum character count allowed.  Unfortunately, the HTML Editor doesn't have anything built in to give this information and it's a conglomerate of many controls such as iframes and hidden text area's that make this a slightly less than trivial task (at least it felt that way initially).

After some thought on this and seeing a lot of great stuff from jQuery I figured it was up to the task. It didn't disappoint.  Here's what I came up with.

var Editor1 = '#Editor1';
var Editor1CountLimit = 50
var Editor1InfoArea = '#Info';

$(document).ready(function() {
  TrackCharacterCount(Editor1, Editor1CountLimit, Editor1InfoArea);
});

function TrackCharacterCount(ctl, limit, info) {
  var editor = $(ctl)contents().find('iframe').eq(1);
  $(editor).load(function() {
      var txt = $(this).contents().find('body').text();
      $(info).html(txt.length); //set initial value 
    $(this).contents().keyup(function() {
      var txt = $(this).contents().find('body').text();
      
      if (txt.length > limit)
        $(info).html(txt.length).css("color", "red");
      else
        $(info).html(txt.length).css("color", "");
     });  
   });
}

My HTML looks like this:

Info

When the document is ready we call the TrackCharacterCount function that takes the ID of the HTML Editor control, then the character limit, and last the element you want to have the character count displayed in.   Be sure to replace these parameters with your values.  

The second iframe contains the contents of the text typed.  The iframe contains a document and the text we are after is in the body tag.  I did some jQuery spelunking in firebug’s console to figure this out.  I added a little touch to have the div element turn red if the user goes over the limit passed into the function. 

In order to enforce the maximum length allowed, I set a custom validator to call the below function.

function ValidateEditor1Length(source, args) {
  var editor = $(Editor1).contents().find('iframe').eq(1);
  var txt = editor.contents().find('body').text();
  var isValid = txt.length > 0 && txt.length <= Editor1CountLimit;
    args.IsValid = isValid;
}

Some jQuery goodness I found along the way.  My first attempt at counting the characters retrieved the entire HTML (used .html()) and then removed the HTML with a regular expression.  It was a little later that I found .text() which simply returns all of the text without markup.  Thank you jQuery!!!!

Here’s a shot of what it looks like before they go over the limit:

HTMLEditor1

And after the go over the limit…

HTMLEditor2

Now, I’m not a jQuery wizard.  In fact, this is my first jQuery foray and I am extremely impressed with jQuery so far.

AjaxHtmlEditor.zip (1.28 MB)

Read my second post where I add functionality to capture the context menu’s cut and paste.

Posted 11.14.2009  #    Comments [0]  |