Vixiom Axioms

March 5, 2008

Interesting Links: YUIRails, Ebb faster than Mongrel and thin

Filed under: Ajax, JavaScript, Merb, Ruby on Rails Alastair @ 7:23 am

The JavaScript library I use most after prototype is YUI so a big thanks to Chetan Patil for making it much easier to use in Rails.

Ruby Inside has a post on Ebb a small and fast web server for hosting Rails and Merb applications (and soon Django).

Ebb is a small, extremely high performance Web / HTTP server designed specifically for hosting applications built upon Web frameworks such as Rails and Merb (and, in future, apps on other non-Ruby frameworks.) The design is event based (similar to that used by Ruby daemons that use EventMachine) but Ebb itself is written in C and dispatches requests to Rack adapters. This is a real leapfrog over the popular Mongrel and Thin daemons which are primarily written in Ruby, and results in scary levels of performance.

Digg! submit Interesting Links: YUIRails, Ebb faster than Mongrel and thin to stumbleupon.com submit Interesting Links: YUIRails, Ebb faster than Mongrel and thin to del.icio.us submit Interesting Links: YUIRails, Ebb faster than Mongrel and thin to reddit.com Like this post? subscribe to the feed.

January 18, 2008

Rails 2.0 and link_to_remote :with

Filed under: Ajax, JavaScript, Ruby, Ruby on Rails Alastair @ 11:22 am

I’m moving an old app to Rails 2.0 and other than fixing some routes Ajax calls with link_to_remote and the :with parameter was the only thing that gave me some trouble. In the old version I was grabbing the current value of a drop down list with Prototype and passing it along using :with like this

<%= link_to_remote image_tag(cms/add_16.gif, :id => color_add),
      :url => { :controller => colors, :action => new_ajax,
      :id => @product.id },
      :with => { color_id: $F(’color_id’) }
%>

But in Rails 2.0 the parameter wouldn’t go along for the ride, it seemed that the new authenticity_token that gets sent with Ajax calls was messing things up. Here’s the fix

<%= link_to_remote image_tag(cms/add_16.gif, :id => color_add),
      :url => { :controller => colors, :action => new_ajax,
      :id => @product.id },
      :with => ‘color_id=’+$F(’color_id’)
%>

I freely admit JavaScript/Ajax is my weakest language so if I was doing it wrong the entire time let me know :)

Digg! submit Rails 2.0 and link_to_remote :with to stumbleupon.com submit Rails 2.0 and link_to_remote :with to del.icio.us submit Rails 2.0 and link_to_remote :with to reddit.com Like this post? subscribe to the feed.

June 5, 2007

Rails helper for SWFObject

Filed under: ActionScript, Flash, Flex, JavaScript, Ruby on Rails Alastair @ 2:57 pm

SWFObject (formally know as FlashObject) is a javascript file that unobtrusively embeds flash in a web page. It works by replacing a holder div with Flash content, if the end user doesn’t have Flash or the targeted Flash player SWFObject will ‘fail’ silently and keep the original div. Here’s a Rails helper that let’s you use SWFObject in your views.

The steps are:

1) download SWFObject, and place it in ‘public/javascripts’

2) include it in your layout file

<%= javascript_include_tag "swfobject" %>

3) put the helper in ‘app/helpers/application_helper.rb’:

# swf_object
  def swf_object(swf, id, width, height, flash_version, background_color, params = {}, vars = {}, create_div = false)
    # create div ?
    create_div ? output = "<div id=’#{id}‘>This website requires <a href=’http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash&promoid=BIOW’ target=’_blank’>Flash player</a> #{flash_version} or higher.</div><script type=’text/javascript’>" : output = "<script type=’text/javascript’>"
    output << "var so = new SWFObject(’#{swf}‘, ‘#{id}‘, ‘#{width}‘, ‘#{height}‘, ‘#{flash_version}‘, ‘#{background_color}‘);"
    params.each  {|key, value| output << "so.addParam(’#{key}‘, ‘#{value}‘);"}
    vars.each    {|key, value| output << "so.addVariable(’#{key}‘, ‘#{value}‘);"}
    output << "so.write(’#{id}‘);"
    output << "</script>"
  end

4) Then in any rhtml page you can use the helper like so (note: place your SWFs in ‘public/swfs’):

<%= swf_object("/swfs/myswf.swf", "flash_id", "550", "400", "9", "#000000",
        {:wmode => "transparent", :quality => "high"},
        {:myvar1 => "foo1", :myvar2 => "foo2"}) %>

In the above code the flash content will replace a div with the id ‘flash_id’, the required arguments are (SWF File location, holder div to replace, width, height, flash version, background color) it also shows two parameters being set ‘wmode’ to transparent (for those annoying flash overlay ads) and ‘quality’ to high, it also passes two variables to the SWF ‘myvar1′ and ‘myvar2′ which are then available at root level of your SWF (’_level0.myvar’ in AS2, a bit trickier in AS3, and ‘Application.application.parameters.myvar’ with Flex).

4b) I, being a lazy/absent-minded programmer, included an option to programmatically create the holder div, just add true as the last argument:

<%= swf_object("/swfs/myswf.swf", "flash_id", "550", "400", "9", "#000000",
        {:wmode => "transparent", :quality => "high"},
        {:myvar1 => "foo1", :myvar2 => "foo2"},
        true) %>
Digg! submit Rails helper for SWFObject to stumbleupon.com submit Rails helper for SWFObject to del.icio.us submit Rails helper for SWFObject to reddit.com Like this post? subscribe to the feed.

May 11, 2007

Calling JavaScript from Flex with External Interface

Filed under: ActionScript, Flex, JavaScript Alastair @ 3:52 pm

The Flex Ajax Bridge, which for some reason you can only download with Flex Data Services (a 150mb+ download for a 16k file), isn’t the only way to send data from Flex to JavaScript there’s also the External Interface API. I’m working on a Rails project tracker application for a construction company and need to set start and end dates for each project. To make sure dates are entered without mistakes I needed a calendar widget that I could easily drop in a form and customize. I tried out some of the Ajax libraries calendars but they where either a) hard to figure out or b) hard to customize or c) both.

I was worried the Flex solution would be a large file at 152k but was surprised to find the files needed for the best Ajax Calendar I found, the Yahoo! UI one, were double in size at 292k (js, css, and gifs). You can download the source here.

A live example is here.

Here’s the MXML code to layout the calendars:

<mx:HBox horizontalAlign="center" verticalAlign="middle" horizontalGap="10" x="0" y="0" width="375">
    <mx:VBox verticalGap="0">
        <mx:Label text="Start Date" color="#333333" fontSize="13" fontWeight="bold" width="100%" textAlign="center" height="25"/>
        <mx:DateChooser id="startDate" yearNavigationEnabled="true"
            change="setDate(DateChooser(event.target))"
            height="175" width="175"
            borderColor="#006600" borderThickness="3"
            cornerRadius="10"
            selectionColor="#99FF33"/>
    </mx:VBox>
    <mx:VBox verticalGap="0">
        <mx:Label text="End Date" color="#333333" fontSize="13" fontWeight="bold" width="100%" textAlign="center" height="25"/>
        <mx:DateChooser id="endDate" yearNavigationEnabled="true"
            change="setDate(DateChooser(event.target))"
            height="175" width="175"
            cornerRadius="10"
            borderColor="#990000" borderThickness="3"
            selectionColor="#FF9999"
            enabled="false"/>
    </mx:VBox>
</mx:HBox>

Here’s the ActionScript to validate the dates and send the data to JavaScript. ExternallInterface.call() is the method that sends the data:

import flash.external.*;
import mx.controls.Alert;

public var startDate_reset:Date     = undefined;
public var endDate_reset:Date       = undefined;

public function setDate(calendar:DateChooser) : void
{
    // start date
    if (calendar.id == "startDate")
    {
        if (endDate.enabled && endDate.selectedDate <= startDate.selectedDate)
        {
            Alert.show("Start Date must be before End Date");
            startDate.selectedDate = startDate_reset;
        }
        else
        {
            endDate.enabled = true;
            startDate_reset = startDate.selectedDate;
            setDateJS(calendar);
        }
    }
    // end date
    else
    {
        if (endDate.selectedDate <= startDate.selectedDate)
        {
            Alert.show("End Date must be after Start Date");
            endDate.selectedDate = endDate_reset;
        }
        else
        {
            endDate_reset = endDate.selectedDate;
            setDateJS(calendar);
        }
    }
}

public function setDateJS(calendar:DateChooser) : void
{
   var s:String;
   if (ExternalInterface.available)
   {
      var eventObj:Object = new Object();
      eventObj.id = calendar.id;
      eventObj.date = calendar.selectedDate;
      var wrapperFunction:String = "setDate";
      s = ExternalInterface.call(wrapperFunction, eventObj);
   }
   else
   {
      s = "Wrapper not available";
   }
}

And finally the JavaScript and markup on the page, Prototype is used to set the input values (they have ids to match their Flex counterparts):

<html>
<head>
<title>Flex to JavaScript, Calendar Example</title>
<script src="javascripts/AC_RunActiveContent.js" type="text/javascript"></script>
<script src="javascripts/prototype.js" type="text/javascript"></script>
</head>
<body>

<SCRIPT LANGUAGE="JavaScript">
    function setDate(eventObj)
    {
        var date = new Date(eventObj.date);
        $(eventObj.id).value = eventObj.date.getMonth() + 1 + "/" + eventObj.date.getDate() + "/" + eventObj.date.getFullYear();
    }
</SCRIPT>

<div>
    <script type="text/javascript">
AC_FL_RunContent( id,mySwf,codebase,http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0,height,200,width,375,name,mySwf,src,Calendar,pluginspage,http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash,flashvars, ); //end AC code
</script><noscript><object id=mySwf classid=clsid:D27CDB6E-AE6D-11cf-96B8-444553540000 codebase=http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0 height=200 width=375>
<param name=src value=Calendar.swf/>
        <param name=flashVars value=/>
        <embed name=mySwf src=Calendar.swf pluginspage=http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash height=200 width=375 flashVars=/>
    </object></noscript>
</div>

<form id="dateForm" action="#" method="post">
    <p>
        Start Date: <input id="startDate" type="text" />
    </p>
    <p>
        End Date: <input id="endDate" type="text" />
    </p>
</form>

</body>
</html>

Digg! submit Calling JavaScript from Flex with External Interface to stumbleupon.com submit Calling JavaScript from Flex with External Interface to del.icio.us submit Calling JavaScript from Flex with External Interface to reddit.com Like this post? subscribe to the feed.

New Google Analytics Mixes up Flash and Ajax

Filed under: ActionScript, JavaScript Alastair @ 12:17 am

Just checked my sites stats and noticed that Google, the Ajax kings, have added some Flash spice to Google Analytics. Each technology handling what it does best, Flash as the presentation layer and Ajax as the data workhorse.

More on the analytics blog.

Flash/Flex has been blowing up lately, it’s faster growing book category for O’Reilly (via Ryan Stewart), and every Flex developer I know has projects flying at them left and right. Come on you Ajax folk you know you want some AS.

Digg! submit New Google Analytics Mixes up Flash and Ajax to stumbleupon.com submit New Google Analytics Mixes up Flash and Ajax to del.icio.us submit New Google Analytics Mixes up Flash and Ajax to reddit.com Like this post? subscribe to the feed.

October 19, 2006

Use javascript/prototype to get a text field value for link_to_remote

Filed under: JavaScript, Ruby on Rails Alastair @ 6:16 pm

This one was a headache, and by headache I mean I was literally pounding my head on the desk trying to figure it out.

I wanted to use link_to_remote to create a model from another model’s form. The example being a ‘Product’ model that belongs to a ‘Group’, the user would select which group a product belonged to within the Product form. Within being the key word because you can’t use ‘remote_form_for’ because it will submit the ‘master’ form.

The solution I came up with was to use link_to_remote instead, but how to pass a text_field’s value to link_to_remote’s arguments. After hacking away I gave up and shot an email off to the AHG Software folks who have worked with me on a couple of Rails projects.

The answer was to use prototype’s $F() function which returns the value of any field input control.

<div id=group>
    <ul id=group_list>
        <%= render :partial => ‘groups/group_list’, :collection =>