Skip to content

Web nourishment by John Ford and crew

Archive for the 'Example Code' Category

Plugin Update: PDF Bookmark for Adobe Reader 8

John Ford Dec 21, 2007

Some of you may already be using the PDF bookmark plugin I put together for Adobe Reader. It provides a quick and easy way to bookmark the page your on and return back to that spot later. It’s especially handy when reading large PDF books.

Thanks to the input of Michael Hartl, I updated the plugin to work properly with Adobe Reader 8. Adobe turned on some security settings by default in the new Adobe Reader which broke the previous version of the plugin.

See the full details and download the plugin.

script.aculo.us Slider Demo : Update Text Field and Change Slider

John Ford Jul 16, 2007

For those of you using the script.aculo.us Slider demos I’ve just added a new one. Sometimes you may have a slider and a text field to show the value. This example lets you change the value in the text box and the slider will update to match the value.

Example: Change Slider Value by Changing Text Input Field

script.aculo.us Slider Demos and Example Code

John Ford Nov 12, 2006

I’ve been following along the script.aculo.us Slider Demo discussion area recently and have tried to answer questions when possible. Since it’s difficult to post examples to the discussion I’ve compiled a more extensive set of Slider demos. Some are examples that I’ve wanted and others are in response to questions in the discussion area.

The demo code includes the following slider examples:

  • Standard Slider
  • Reversed Slider
  • Slider Controlled with Mouse Wheel
  • One Slider Controlling Multiple Sliders
  • Using Images to Spruce Up a Slider
  • Two Colored Slider
  • Submit the Slider Value in a Form
  • Use a Slider as a Scrollbar (added Nov 21, 2006)
  • Change Slider Value by Changing Text Input Field (added Jul 16, 2007)

It’s really amazing what you can do with the script.aculo.us library. Please let me know what you think!

has_many :through Self-referential Example

John Ford Nov 10, 2006

While using an association table for the first time with Ruby On Rails I had a bit of trouble finding an easy to understand example of has_many :through. I needed to build a self-referencing table where People could have other People as friends through a Friendship. I was getting “stack too deep” errors, “could not find the association” errors, and also crashing Webrick before I figured out the correct setup. Here’s how I did it:

# the people table
create_table :people do |t|
  t.column :name, :string
end

# the friendships association table
create_table :friendships do |t|
  t.column :person_id, :integer
  t.column :friend_id, :integer
  t.column :authorized, :boolean, :default => false
end

class Friendship < ActiveRecord::Base
  # don't have to give class_name or foreign_key b/c ActiveRecord reflection works here
  belongs_to :person

  # make sure to give class_name and foreign_key b/c ActiveRecord doesn't know what friend is
  belongs_to :friend, :class_name => "Person", :foreign_key => "friend_id"
end

class Person < ActiveRecord::Base
  # tell ActiveRecord that a person has_many friendships or :through won't work
  has_many :friendships

  # create the has_many :through relationship
  has_many :friends, :through => :friendships

  # an example of how to get only the authorized friends
  has_many :authorized_friends, :through => :friendships, :source => :friend, :conditions => [ "authorized = ?", true ]

  # an example of how to get only the unauthorized friends
  has_many :unauthorized_friends, :through => :friendships, :source => :friend, :conditions => [ "authorized = ?", false ]
end

Using Mouse Wheel to Control script.aculo.us Slider

John Ford Sep 30, 2006

You may have noticed that Google Maps will zoom in and out when you use your mouse wheel (or trackpad scrolling). If you want to do the same thing using the script.aculo.us JavaScript Slider here is an example to get you started.

The example uses a slightly modified version of Adomas Paltanavicius’ mouse wheel event code. Firefox 1.5 seems to work fine but not Safari 1.3. Please let me know how it handles in other browsers.

Example: Using Mouse Wheel to Control Slider

Update: I’ve created a more extensive set of Slider demos which includes the mouse wheel demo. (Nov. 12, 2006)

Execute Rails Code Before the View is Rendered

John Ford Sep 25, 2006

At one time, I was looking for a way to execute code for every action in my controller before the view was rendered. I saw this come up again yesterday in the #rubyonrails IRC channel so I looked at it a bit more. Currently, Rails provides a before_filter method which will “run before actions on this controller are performed” or an after_filter which will “run after actions on this controller are performed.” What I wanted was a before_render filter which would run right at the end of the action but before render/view was executed.

Here is one idea how to do this. Since you want the code to run right before render is executed just override the render method that’s in ActionController. You can put the following code inside any of your individual controllers or add it to your ApplicationController and it will run in all of your controllers.

protected
  def render(options = nil, deprecated_status = nil, &block)
    # your code goes here
    @rockon = "rock and roll!"

    # call the ActionController::Base render to show the page
    super
  end

This is just an example, and maybe someone will take this a step further and actually create a before_render filter plugin. It would be nice to have the same flexibility as before_filter and after_filter which allows you to include “:only” or “:exclude” certain actions.

Writing a Custom FormBuilder in Rails

John Ford Sep 19, 2006

I’m currently working on a Ruby on Rails application where I need lots of text fields that have the same properties. I decided to override text_field and have it output all of the extra attribues automatically. This helps keep the view code cleaner, lets me change all of these text fields in one place, and also helps me avoid typing mistakes (at least in this section of the code). Thanks to Ruby on Rails core team member Rick Olson (aka technoweenie) for pointing me to his LabeledFormHelper plugin, which taught me this technique.

Before the custom FormBuilder my initial view code looked something like:

<% form_for(:spreadsheet, @spreadsheet, :url => { :action => 'create' }) do |s| %>

    <% fields_for :numbers, @spreadsheet.numbers do |f| %>

      <%= f.text_field :field1, :onkeypress => 'return isNumberKey(event);', :maxlength => 3 %>
      <%= f.text_field :field2, :onkeypress => 'return isNumberKey(event);', :maxlength => 3 %>

      ... and so on

    <% end %>
<% end %>

So I created a custom FormBuilder in my helper to do the extra text_field work for me:

module SpeadsheetsHelper

  # tell all of these methods to use my custom FormBuilder
  [:form_for, :fields_for, :form_remote_for, :remote_form_for].each do |meth|
    src = <<-end_src
      def speadsheets_#{meth}(object_name, *args, &proc)
        options = args.last.is_a?(Hash) ? args.pop : {}
        options.update(:builder => SpeadsheetsFormBuilder)
        #{meth}(object_name, *(args << options), &proc)
      end
    end_src
    module_eval src, __FILE__, __LINE__
  end

  # the custom FormBuilder
  class SpeadsheetsFormBuilder < ActionView::Helpers::FormBuilder    

    # add onkeypress and set maxlength of field to 3 to all text fields
    def text_field(method, options={})
      super(method, options.merge(:onkeypress => ‘return isNumberKey(event);’, :maxlength => 3))
    end

  end
end

Now my view code is much simpler and helps avoid goofups:

<% spreadsheets_form_for(:spreadsheet, @spreadsheet, :url => { :action => 'create' }) do |s| %>

    <% spreadsheets_fields_for :numbers, @spreadsheet.numbers do |f| %>

      <%= f.text_field :field1 %>
      <%= f.text_field :field2 %>

      ... and so on

    <% end %>
<% end %>

Notice in the view that instead of using form_for and fields_for you need to use the custom methods spreadsheets_form_for and spreadsheets_fields_for which were created in SpeadsheetsHelper.

Plugin: Bookmark A Page In Your PDF

John Ford Sep 15, 2006

With the long, yet wonderful, books in PDF format these days (Agile Web Development with Rails by Dave Thomas and David Heinemeier Hansson with Leon Breedt, Mike Clark, Thomas Fuchs, and Andreas Schwarz [570 pages]; Programming Ruby by Dave Thomas, with Chad Fowler and Andy Hunt [864 pages]) there needs to be a better way to digitally bookmark where you left off. For some reason Adobe Reader (Acrobat Reader) doesn’t have this capability built in. I found a plugin for Acrobat Reader to do multiple bookmarks per document from PDF Hacks. However, I really just want it to be simple like a physical book - you bookmark the page you’re on when you stop and go to that page when you pick back up. So here is my plugin to bookmark your page in Adobe Reader.

Download:

PDF Bookmark 1.1

Change Log:

  • 1.1 - Dec 20, 2007 - Update to work with Adobe Reader 8 due to security changes (app.trustedFunction)
  • 1.0 - Sep 15, 2006 - Initial release

Installation:

Adobe Reader 8 - copy pdf_bookmark.js to:

  • Mac: ~/Library/Acrobat User Data/8.0_x86/JavaScripts (or similar)
  • Windows: C:\Documents and Settings\[User Name]\Application Data\Adobe\Acrobat\8.0\JavaScripts (or similar)

Adobe Reader 7 - copy pdf_bookmark.js to:

  • Mac: ~/Library/Acrobat User Data/7.0/JavaScripts (or similar)
  • Windows: C:\Documents and Settings\[User Name]\Application Data\Adobe\Acrobat\7.0\JavaScripts (or similar)

Note: you may have to create the JavaScripts folder

Usage:

Open your document in Adobe Reader. Then choose Tools -> Bookmark from the menu. “Bookmark This Page” adds the bookmark. “Go To Bookmark” sends you to the bookmark you created. It remembers which PDF document you bookmarked so it works on all of your PDFs simultaneously. (Tested with Acrobat Reader 7 and Adobe Reader 8 (thanks Michael) on Mac OS X and Windows)

PDF Bookmark Plugin Screenshot (8.0)