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

Mar
31

Open source flash charts like google analytics

Posted by Michael Cindric in development, open source, plugins, ruby on rails | No Comments »

We all want our charts to look like the ones in google analytics. Well know there is a way the “Open Flash Chart” project. The guys over at pull monkey have released a plugin for rails that helps you get in these great charts. Ill be testing this plugin very soon and ill put up my experience and a little walk through. In the mean time if you want to check out the project have a look here

Here is an example of what the charts look like

Flash Chart

Mar
29

Using Javascript Code for RJS Instead of IDs

Posted by Michael Cindric in development, ruby on rails | 22 Comments »

UPDATE: JavascriptGenerator has a method name literal that will do the exact same thing, so the code below should do the trick:

 page.insert_html :bottom, page.literal("$$('p.welcome b').first()"), "Some item"

Bill Burhcam over at Meme Rocket made a post that *almost* solved a problem for me the other day. We’re currently doing some work that ends up creating html. Pretty standard stuff, but for a few reasons that aren’t really worth going into we can’t easily rely on our element ids being unique. The prototype functions ‘up’ and ‘down’ are perfect for this situation though.

So our problem basically boils down to this – RJS converts this code:

page.insert_html :bottom, "$$('p.welcome b').first()", "Some item"

into this javascript:

 new Insertion.Bottom("$$('p.welcome b').first()", "Some item"

Because the $$(’p…’) is in quotes, Insertion.Bottom just looks for an element with that id. Which isn’t what we really wanted.

After digging around in the ActionView source for a while I found JavascriptGenerator::GeneratorMethods and its javascript_object_for method. It turns out that if you pass in a ActiveSupport::JSON::Variable then insert_html will behave how we want. So for the example above, the code below will work as expected.

 js_literal = "$$('p.welcome b').first()" js_literal = ActiveSupport::JSON::Variable.new(js_literal) page.insert_html :bottom, js_literal, "Some item"

will output:

 new Insertion.Bottom($$('p.welcome b').first(), "Some item"

Thank you open source.

Mar
17

Ajax.Updater and javascript

Posted by Michael Cindric in javascript, ruby on rails | 2 Comments »

Ran into a little problem today which made me think for a second. I have a Javascript function that runs once a calendar control is closed. It just passes a parameter to a action which renders a view nothing fancy.

So my onClose function looks like so

function onClose(cal) {
	var p = cal.params;
	new Ajax.Updater('overlapping', '/visits/new', {
	  parameters: { start_date:  p.inputField.value; },
	  evalScripts: true
	});
	cal.hide();
};

This will fire once the calendar is closed. ‘Overlapping’ is the ID of the Div ill be updating and ‘/visits/new’ is the path of the action in your controller. This will then pass the start date param to the action which can then be used in the view. The problem l had is that l had some javascript on the partial that was not executing. Had to think for a minute and then it turned out that evalScripts is false by default thus the javascript was not executing.

So its as simple as having the following as a param in your Ajax.updater

 evalScripts: true

Once you have done that your good to go.

Mar
05

Fixing the enter key in ASP.NET with jQuery

Posted by Michael Cindric in asp.net, jquery | 2 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.