Blog

May
29

Getting JQuery and Prototype to place nice

Posted by Michael Cindric in development, javascript, jquery | No Comments »

If you want to use JQuery in your rails application but still want prototype working as well there is a simple way to make sure they play nice and work side by side. All you have to do after you include your JQuery includes code is have the following

  <script>
   var $j = jQuery.noConflict();
  </script>

Now all you have to do to use jquery is use “$j” instead of just “$” and your good to go. To use just the standard prototype library is still just “$”. Simple isn’t it

May
08

Application templates in Ruby on Rails

Posted by Michael Cindric in development, javascript, jquery, ruby on rails | 4 Comments »

Here is the latest application template we have put together. It removes all the usual items and adds the base gems that we use for all our applications. It also creates the files needed for deployment and runs “Capify” on the project, plus a few other things such as sass etc.

# Remove unnecessary Rails files
run 'rm README'
run 'rm public/index.html'
run 'rm public/favicon.ico'
run 'rm public/images/rails.png'
run 'rm -f public/javascripts/*'

# Download JQuery
run "curl -s -L http://jqueryjs.googlecode.com/files/jquery-1.3.1.min.js > public/javascripts/jquery.js"
run "curl -s -L http://jqueryjs.googlecode.com/svn/trunk/plugins/form/jquery.form.js > public/javascripts/jquery.form.js"

#Configure required gems
gem "haml", :version => "2.0.4"
gem 'thoughtbot-shoulda', :lib => 'shoulda', :source => 'http://gems.github.com'
gem "thoughtbot-factory_girl", :lib => "factory_girl", :source => "http://gems.github.com"

#Create Sass directory
run 'mkdir public/stylesheets/sass'

#Capify and create production environment.rb
run 'mkdir config/deploy'
run 'touch config/deploy/production.rb'

#Add UAT environment and settings
file 'config/environments/uat.rb', <<-CODE
# Settings specified here will take precedence over those in config/environment.rb

# Code is not reloaded between requests. Server needs to be restarted.
config.cache_classes = true

# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true

# Show full error reports and disable caching
config.action_controller.consider_all_requests_local = false
config.action_controller.perform_caching             = true
config.action_view.cache_template_loading            = true

# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false
CODE

#Create gitignore file and setup base ignores
run "touch tmp/.gitignore log/.gitignore vendor/.gitignore"
file '.gitignore', <<-FILE
.DS_Store
log/*.log
tmp/**/*
db/*.sqlite3
public/stylesheets/*.css
FILE

# Set up git repository
git :init
git :add => '.'
git :commit => "-a -m 'Initial commit'"

# Success!
puts "SUCCESS!"
Mar
05

Fixing the enter key in ASP.NET with jQuery

Posted by Michael Cindric in asp.net, jquery | 4 Comments »

One of the fundamental problems with ASP.NET WebForms is the fact that you can only have one form per page. This jumps up and bites you when you have a set of fields and a button and you want the enter key to submit the form.

In ASP.NET 2.0 they came out with a “fix” for this. You can wrap your fields in a Panel and set the default button:

<asp:Panel ID="_pnlLogin" DefaultButton="_btnLogin" runat="server">
    UserName: <asp:TextBox ID="_txtUserName" runat="server" />
    Password: <asp:TextBox ID="_txtPassword" runat="server" />
    <asp:LinkButton ID="_btnLogin" Text="Login" runat="server"/>
</asp:Panel>

Some of you will know limitation here. This works with a Button, but not a LinkButton. Let’s see why.
Here is the resulting HTML:

<div id="_pnlLogin" onkeypress="javascript:return WebForm_FireDefaultButton(event, &amp;#x27;_btnLogin&amp;#x27;)">
    UserName: <input name="_txtUsername" type="text" id="_txtUsername" />
    Password: <input name="ctl00$mainContent$_txtPassword" type="text" id="_txtPassword" />
    <a id="_btnLogin" href="javascript:__doPostBack('_btnLogin','')">Login</a>
</div>


The Panel renders as a div, and on any key pressed will call WebForm_FireDefaultButton:

function WebForm_FireDefaultButton(event, target) {
    if (!__defaultFired &amp;&amp; event.keyCode == 13 &amp;&amp; !(event.srcElement &amp;&amp; (event.srcElement.tagName.toLowerCase() == "textarea"))) {
        var defaultButton;
        if (__nonMSDOMBrowser) {
            defaultButton = document.getElementById(target);
        } else {
            defaultButton = document.all[target];
        }
        if (defaultButton &amp;&amp; typeof(defaultButton.click) != "undefined") {
            __defaultFired = true;
            defaultButton.click();
            event.cancelBubble = true;
        if (event.stopPropagation) event.stopPropagation();
            return false;
        }
    }
    return true;
}


This method checks for the enter key and then calls click on the default button. All good except for one thing: the LinkButton renders as an “a” tag. Anchor tags don’t have a click() method unfortunately. At least not in Firefox.

So let’s fix it! I’ve recently been reading “Learning jQuery”
which is a great book on this cool javascript library. I’ll use jQuery instead of straight javascript as it is much easier to write cross browser code and it’s a lot more concise. Plus there are heaps of plugins for it, and it’s a pretty small download for your page.

I want to improve the markup of my page at the same time so I’ll try to minimise the amount of server controls I use and get rid of that inline javascript call. My new aspx looks like this:

<div class="form">
    UserName: <asp:TextBox ID="_txtUsername" runat="server" />
    Password: <asp:TextBox ID="_txtPassword" runat="server" />
    <asp:LinkButton ID="_btnLogin" Text="Login" runat="server" CssClass="form_submit"/>
</div>


So if I have a div with the class “form”, the default submit button is the first element with the “form_submit” class. Nice, simple and unobtrusive.

Here’s the javascript I ended up with:

$(document).ready(function(){
    var $btn = $('.form_submit');
    var $form = $btn.parents('.form');

    $form.keypress(function(e){
        if (e.which == 13 &amp;&amp; e.target.type != 'textarea') {
            if ($btn[0].type == 'submit')
                $btn[0].click();
            else
                eval($btn[0].href);
            return false;
        }
    });
});

Basically it’s going to find any .form_submit elements, find a parent form, and add a keypress handler for the form. When the keypress is triggered, if it’s the enter key and we’re not in a textarea, we’ll click the default submit button if it IS a button, if it’s a link we’ll Eval the href attribute, which is going to be our javascript postback call.

Cool, I can keep it tucked away in an js file include, and i’ve improved my markup.