How To Make a Bookmarklet For Your Web Application

Browser buttons (bookmarklets) are shortcuts that act like a simple browser plugin. Their advantages include:

  • Fast installation: Just add a link to your bookmarks
  • Convenient: Use features while on your current page
  • Easy to write: Bookmarklets are just like making a webpage; there’s no need to write a whole browser plugin
  • Cross-browser: The same bookmarklet can work in IE, Firefox, Opera and Safari.

Here’s a few bookmarklets I use regularly:

How easy is it?

Only one way to find out. Try the instacalc bookmarklet right here:

How To Make a Bookmarklet For Your Web Application

  • Click this link: instacalc bookmarklet.
  • A calculator opens in the corner of the page. Type 1 + 1 to see the result.
  • Select this text 15 mph in fps and click the link again. Voila! The text is automatically inserted.
  • Close the window by clicking the red “x”

Neat, eh? No install, just click and go. To save the bookmarklet, right click the link and “add to favorites/bookmarks”. Now you can open the calculator on any page.

Today we’ll walk through the anatomy of a bookmarklet, dissect a few, and give you the tools to build your own.

Bookmarklets 101

Regular bookmarks (aka favorites) are just locations to visit, like “http://gmail.com”. Bookmarklets are javascript code that the browser runs on the current page, and they’re marked by “javascript:” instead of “http://”.

When clicking a bookmarklet, imagine the page author wrote <script>bookmarklet code here</script> — it can do almost anything. There are a few restrictions:

  • Restricted length: Most URLs have a limit around 2000 characters, which limits the amount of code you can run. There’s a way around this.
  • No spaces allowed: Some browsers choke on spaces in a URL, so yourcodelookslikethis. We have a trick for this too.

A simple bookmarklet looks like this:

<a href="javascript:alert('hi');">my link</a>

Click this link to see it in action. This example isn’t too wild, but the key is that bookmarklets let you run code on an existing page.

What do you want to do?

Your bookmarklet should do something useful. Ideas include:

  • Transform the current page. Do find/replace, highlight certain words or images, change CSS styles…
  • Open/overlay a new page. Open a new page or draw a window on the current one, like a sidebar
  • Send data to another site. Post, share, or upload the current URL or selected text (like Google translate).
  • Look at the bookmarklet directories for more inspiration.

People spend most of their time on other sites. Web application authors, think creatively: how can people use your service when away from your site?

Javascript for Bookmarklets

A bookmarklet can use any javascript command, but certain ones are helpful:

Get current page title: document.title Get the current URL: location.href Get the currently selected text:

  // get the currently selected text
  var t;
  try {
    t= ((window.getSelection && window.getSelection()) ||
(document.getSelection && document.getSelection()) ||
(document.selection &&
document.selection.createRange &&
document.selection.createRange().text));
  }
  catch(e){ // access denied on https sites
    t = "";
  }

Make text url-safe: encodeURIComponent(text) (and corresponding decodeURIComponent()). The page title or URL may have invalid characters (spaces, slashes, etc.) so it’s a good habit to encode them before sending them over (spaces become %20, etc.).

Dissecting the Delicious Bookmarklet

Here’s the code for the delicious bookmarklet (spaces added for readability):

javascript:location.href='http://del.icio.us/post?v=4;
url='+encodeURIComponent(location.href)+';
title='+encodeURIComponent(document.title)

And here’s what’s happening:

  • Change to a new URL (to post the item)
  • Specify query parameters for the current document’s url (location.href) and title (document.title)
  • Make the paramaters url-safe with encodeURIComponent

Once you tag and save the post, delicious sends you to the original page. How do they know where? Because it was sent along in the original request!

Bookmarklet Interface Ideas

Imagine this: Your users are browsing for cat photos (or the journals of the American Chemical Society, but probably lolcats) when they click your killer Web 2.0 bookmarklet. What happens?

Bookmarklet interface ideas

Common techniques are:

  • Take the user to a new page. Hopefully, you can use some data from the current page, otherwise it’s a regular bookmark.
  • Frame the current page, like Google translate or Stumbleupon. This is similar to the first technique, but your site displays the old page inside the window.
  • Overlay a new interface. Use CSS absolute positioning to make a window in a set place, or fixed positioning to have the window follow you as you scroll. Beware the CSS bugs.

Overlaid windows are great, but won’t that be hard to cram into a single line?

The Big Trick: Dynamic Javascript

Direct javascript works fine if you just want to redirect the user to another page, like the delicious bookmarklet. The no spaces, 2000 character limit really hurts when you want a more complicated interface.

There’s a fix: Our bookmarklet becomes a stub to load another (regular) javascript file. Here’s the code (spaces added for readability):

javascript:(function(){
  _my_script=document.createElement('SCRIPT');
  _my_script.type='text/javascript';
  _my_script.src='http://mysite.com/script.js?';
  document.getElementsByTagName('head')[0].appendChild(_my_script);
})();

Here’s how it works:

  • Define an anonymous function to download the script
  • Create a script element, type text/javascript. We can’t use var _my_script because of the spaces, so choose a unique name.
  • Set the src of the script to our real javascript file. This file could pull down more javascript also.
  • Add the script element to the current page

And that’s it! Our bookmarklet can now load any javascript we please, without the annoying restrictions. An added bonus: see how many people are using your tool, and you we can change our script (fix bugs or add features) on the server.

Dissecting the Instacalc Bookmarklet

Here’s the steps I went through to make the instacalc bookmarklet

Create a bookmarklet interface

I made a trimmed-down page designed for the bookmarklet. If you click the page it appears fullscreen, but it resizes to the parent container. I planned on hosting this page inside a smaller iframe.

Create a stub bookmarklet

Because I wanted to get the currently selected text and overlay an interface, I knew I couldn’t fit my javascript into 2000 characters. So I used the dynamic javascript technique above to get the real javascript file.

Careful caching

I didn’t want to cache the bookmarklet javascript in case I wanted to change its behavior (but I did cache the other files). I added a dummy query parameter using Math.random(), which forces the browser to download the file each time. Since the script is small, this wasn’t too much of an issue.

instacalc_script.src='http://static.instacalc.com/gadget/instacalc.bookmarklet.js?x='+(Math.random());

Build the interface

The script to build the interface is pretty straightforward. There’s some helper functions for encoding (instacalc stores data using base64). The script gets the selected text, constructs the URL for the iframe, and loads it up. It generates the CSS to have a fixed window on the top right of the screen, and a button to hide the window.

As a slight trick, if the bookmarklet is run again on the same page, it just shows the existing window instead of creating a new iframe.

Tips & Tricks

Keep this in mind when making your bookmarklet:

Make it friendly. Don’t interrupt the user’s flow. Bring up the window on the same page, or a new page that closes. If you must redirect the user to their original page.

This is important: the user was nice enough to use your service, so put ‘em back where they were!

Make it fast. After you’ve got it working, tweak your bookmarklet’s speed using the following techniques

Give people instructions. Bookmarklets aren’t that common, so help people understand your tool. A few instructions (“right click this link and add to bookmarks/favorites”) and a screenshot go a long way.

The gotcha: cross-domain communication

Because of cross-domain security restrictions, your bookmarklets can’t use fancy-pants Ajax techniques to communicate with your site. The easiest way to communicate is through query parameters in a URL.

Debugging

What’s programming without bugs? Use firefox to debug your javascript and CSS. Instead of clicking a bookmarklet each time, just make a page that runs the javascript file directly: <script src="...">. This is what the bookmarklet does.

Once the dummy page is working, try your bookmarklet on other sites. You’d be surprised how other CSS rules can mess up your carefully positioned elements (remember, you’re running in the context of another site).

Links & Resources

I’m sure you’ll come up with crazy ways to use your newfound toy. The main benefits are simple installation, compatibility, and being able to interact with the current page.

  • There are crunching tools to make your javascript bookmarklet-friendly. But it’s nice to just dynamically load the real script and be done with it.

  • People have put the delicious bookmarklet on steroids, such as letting you type the tags in the url before hitting the button.

  • Taking this to the extreme, Greasemonkey is a firefox plugin letting you run really powerful scripts. For example, there was a script to add a “delete” button to Gmail before it was available.

Have fun.

Join 450k Monthly Readers

Enjoy the article? There's plenty more to help you build a lasting, intuitive understanding of math. Join the newsletter for bonus content and the latest updates.

Intermediate Rails: Understanding Models, Views and Controllers

I’m glad people liked the introduction to Rails; now you scallawags get to avoid my headaches with the model-view-controller (MVC) pattern. This isn’t quite an intro to MVC, it’s a list of gotchas as you plod through MVC the first few times.

Here’s the big picture as I understand it:

rails mvc

  • The browser makes a request, such as http://mysite.com/video/show/15

  • The web server (mongrel, WEBrick, etc.) receives the request. It uses routes to find out which controller to use: the default route pattern is “/controller/action/id” as defined in config/routes.rb. In our case, it’s the “video” controller, method “show”, with the id parameter set to “15″. The web server then uses the dispatcher to create a new controller, call the action and pass the parameters.

  • Controllers do the work of parsing user requests, data submissions, cookies, sessions and the “browser stuff”. They’re the pointy-haired manager that orders employees around. The best controller is Dilbert-esque: It gives orders without knowing (or caring) how it gets done. In our case, the show method in the video controller knows it needs to lookup a video. It asks the model to get video 15, and will eventually display it to the user.

  • Models are Ruby classes. They talk to the database, store and validate data, perform the business logic and otherwise do the heavy lifting. They’re the chubby guy in the back room crunching the numbers. In this case, the model retrieves video 15 from the database.

  • Views are what the user sees: HTML, CSS, XML, Javascript, JSON. They’re the sales rep putting up flyers and collecting surveys, at the manager’s direction. Views are merely puppets reading what the controller gives them. They don’t know what happens in the back room. In our example, the controller gives video 15 to the “show” view. The show view generates the HTML: divs, tables, text, descriptions, footers, etc.

  • The controller returns the response body (HTML, XML, etc.) & metadata (caching headers, redirects) to the server. The server combines the raw data into a proper HTTP response and sends it to the user.

It’s more fun to imagine a story with “fat model, skinny controller” instead of a sterile “3-tiered architecture”. Models do the grunt work, views are the happy face, and controllers are the masterminds behind it all.

Many MVC discussions ignore the role of the web server. However, it’s important to mention how the controller magically gets created and passed user information. The web server is the invisible gateway, shuttling data back and forth: users never interact with the controller directly.

SuperModels

Models are fat in Railsville: they do the heavy lifting so the controller stays lean, mean, and ignorant of the details. Here’s a few model tips:

Using ActiveRecord

class User < ActiveRecord::Base
end

The code < ActiveRecord::Base means your lowly User model inherits from class ActiveRecord::Base, and gets Rails magic to query and save to a database.

Ruby can also handle “undefined” methods with ease. ActiveRecord allows methods like “find_by_login”, which don’t actually exist. When you call “find_by_login”, Rails handles the “undefined method” call and searches for the “login” field. Assuming the field is in your database, the model will do a query based on the “login” field. There’s no configuration glue required.


Defining Class and Instance Methods

 def self.foo
    "Class method"    # User.foo
  end

  def bar
   "instance method"  # user.bar
  end

Class and instance methods can cause confusion.

user (lowercase u) is an object, and you call instance methods like user.save.

User (capital U) is a class method – you don’t need an object to call it (like User.find). ActiveRecord adds both instance and class methods to your model.

As a tip, define class methods like User.find_latest rather than explicitly passing search conditions to User.find (thin controllers are better).


Using Attributes

Regular Ruby objects can define attributes like this:

  # attribute in regular Ruby
  attr_accessor :name        # like @name
  def name=(val)             # custom setter method
    @name = val.capitalize   # clean it up before saving
  end

  def name                   # custom getter
   "Dearest " + @name        # make it nice
  end

Here’s the deal:

  • attr_accessor :name creates get and set methods (name= and name) on your model. It’s like having a public instance variable @name.
  • Define method name=(val) to change how @name is saved (such as validating input).
  • Define method name to control how the variable is output (such as changing formatting).

In Rails, attributes can be confusing because of the database magic. Here’s the deal:

  • ActiveRecord grabs the database fields and throws them in an attributes array. It makes default getters and setters, but you need to call user.save to save them.
  • If you want to override the default getter and setter, use this:

    # ActiveRecord: override how we access field
    def length=(minutes)
      self[:length] = minutes * 60
    end
    
    def length
      self[:length] / 60
    end
    

ActiveRecord defines a “[]” method to access the raw attributes (wraps the write_attribute and read_attribute). This is how you change the raw data. You can’t redefine length using

def length          # this is bad
  length / 60
end

because it’s an infinite loop (and that’s no fun). So self[] it is. This was a particularly frustrating Rails headache of mine – when in doubt, use self[:field].


Never forget you’re using a database

Rails is clean. So clean, you forget you’re using a database. Don’t.

Save your models. If you make a change, save it. It’s very easy to forget this critical step. You can also use update_attributes(params) and pass a hash of key -> value pairs.

Reload your models after changes. Suppose a user has_many videos. You create a new video, point it at the right user, and call user.videos to get a list. Will it work?

Probably not. If you already queried for videos, user.videos may have stale data. You need to call user.reload to get a fresh query. Be careful — the model in memory acts like a cache that can get stale.


Making New Models

There’s two ways to create new objects:

joe = User.new( :name => "Sad Joe" )        # not saved
bob = User.create ( :name => "Happy Bob" )  # saved
  • User.new makes a new object, setting attributes with a hash. new does not save to the database: you must call user.save explicitly. Method save can fail if the model is not valid.
  • User.create makes a new model and saves it to the database. Validation can fail; user.errors is a hash of the fields with errors and the detailed message.

Notice how the hash is passed. With Ruby’s brace magic, {} is not explicitly needed so

user = User.new( :name => "kalid", :site => "instacalc.com" )

becomes

User.new( {:name => "kalid", :site => "instacalc.com"} )

The arrow (=>) implies that a hash is being passed.


Using Associations

Quick quiz, hotshot: suppose users have a “status”: active, inactive, pensive, etc. What’s the right association?

class User < ActiveRecord::Base
  belongs_to :status  # this?
  has_one :status     # or this?
end

Hrm. Most likely, you want belongs_to :status. Yeah, it sounds weird. Don’t think about the phrase “has_one” and “belongs_to”, consider the meaning:

  • belongs_to: links_to another table. Each user references (links to) a status.
  • has_one: linked_from another table. A status is linked_from a user. In fact, statuses don’t even know about users – there’s no mention of a “user” in the statuses table at all. Inside class Status we’d write has_many :users (has_one and has_many are the same thing – has_one only returns 1 object that links_to this one).

A mnemonic:

  • “belongs_to” rhymes with “links_to”
  • “has_one” rhymes with “linked_from”

Well, they sort of rhyme. Work with me here, I’m trying to help.

These associations actually define methods used to lookup items of the other class. For example, “user belongs_to status” means that user.status queries the Status for the proper status_id. Also, “status has_many :users” means that status.users queries the user table for everyone with the current status_id. ActiveRecord handles the magic once we declare the relationship.


Using Custom Associations

Suppose I need two statuses, primary and secondary? Use this:

belongs_to :primary_status, :model => 'Status', :foreign_key => 'primary_status_id'
belongs_to :secondary_status, :model => 'Status', :foreign_key => 'secondary_status_id'

You define a new field, and explicitly reference the model and foreign key to use for lookups. For example, user.primary_status returns a Status object with the id of “primary_status_id”. Very nice.

Quick Controllers

This section is short, because controllers shouldn’t do much besides boss the model and view around. They typically:

  • Handle things like sessions, logins/authorization, filters, redirection, and errors.
  • Have default methods (added by ActionController). Visiting http://localhost:3000/user/show will attempt to call the “show” action if there is one, or automatically render show.rhtml if the action is not defined.
  • Pass instance variables like @user get passed to the view. Local variables (those without @) don’t get passed.
  • Are hard to debug. Use render :text => "Error found" and return to do printf-style debugging in your page. This is another good reason to put code in models, which are easy to debug from the console.
  • Use sessions to store data between requests: session[:variable] = “data”.

I’ll say it again because it’s burned me before: use @foo (not “foo”) to pass data to the view.

Using Views

Views are straightforward. The basics:

  • Controller actions use views with the same name (method show loads show.rhtml by default)
  • Controller instance variables (@foo) are available in all views and partials (wow!)

Run code in a view using ERB:

  • <% ... %>: Run the code, but don’t print anything. Used for if/then/else/end and array.each loops. You can comment out sections of HTML using <% if false %> Hi there <% end %>. You get a free blank line, since you probably have a newline after the closing %>.

  • <%- ... %>: Run the code, and don’t print the trailing newline. Use this when generating XML or JSON when breaking up .rhtml code blocks for your readability, but don’t want newlines in the output.

  • <%= ... %>: Run the code and print the return value, for example: <%= @foo %> (You did remember the @ sign for controller variables passed to the view, right?). Don’t put if statements inside the <%=, you’ll get an error.

  • <%= h ... %>: Print the code and html escape the output: > becomes >. h() is actually a Ruby function, but called without parens, as Rubyists are apt to do.

It’s a bit confusing when you start out — run some experiments in a dummy view page.

Take a breather

The MVC pattern is a lot to digest in one sitting. As you become familiar with it, any Rails program becomes easy to dissect: it’s clear how the pieces fit together. MVC keeps your code nice and modular, great for debugging and maintenance.

In future articles I’ll discuss the inner details of MVC and how Rails forms work (another headache of mine). If you want a jumpstart on the nitty gritty, browse the Rails source and try to follow the path of a request:

  • WEBrick server modified to call the Rails routing library and dispatcher.
  • Rails Dispatcher actually creates the controller and passes it data.
  • ActionController Base defines many functions, including those to call a controller action (using appropriate defaults), render text, and return a response.

But all in good time my friends — I’ll explain it as I understand it. And if you had any forehead-slapping moments with MVC, drop me a note below.

Join 450k Monthly Readers

Enjoy the article? There's plenty more to help you build a lasting, intuitive understanding of math. Join the newsletter for bonus content and the latest updates.

Starting Ruby on Rails: What I Wish I Knew

Ruby on Rails is an elegant, compact and fun way to build web applications. Unfortunately, many gotchas await the new programmer. Now that I have a few rails projects under my belt, here’s my shot at sparing you the suffering I experienced when first getting started.

Tools: Just Get Them

Here’s the tools you’ll need. Don’t read endless reviews trying to decide on the best one; start somewhere and get going.

But What Does It All Mean?

“Ruby on Rails” is catchy but confusing. Is Rails some type of magical drug that Ruby is on? (Depending on who you ask, yes.)

Ruby is a programming language, similar to Python and Perl. It is dynamically typed (no need for “int i”), interpreted, and can be modified at runtime (such as adding new methods to classes). It has dozens of shortcuts that make it very clean; methods are rarely over 10 lines. It has good RegEx support and works well for shell scripting.

Rails is a gem, or a Ruby library. Some gems let you use the Win32 API. Others handle networking. Rails helps make web applications, providing classes for saving to the database, handling URLs and displaying html (along with a webserver, maintenance tasks, a debugging console and much more).

IRB is the interactive Ruby console (type “irb” to use). Rails has a special IRB console to access your web app as it is running (excellent for live debugging).

Rake is Ruby’s version of Make. Define and run maintenance tasks like setting up databases, reloading data, backing up, or even deploying an app to your website.

Erb is embedded Ruby, which is like PHP. It lets you mix Ruby with HTML (for example):

<div>Hello there, <%= get_user_name() %></div>

YAML (or YML) means “YAML Ain’t a Markup Language” — it’s a simple way to specify data:

{name: John Smith, age: 33}

It’s like JSON, much leaner than XML, and used by Rails for setting configuration options (like setting the database name and password).

Phew! Once Ruby is installed and in your path, you can add the rails gem using:

gem install rails

In general, use gem install “gem_name”, which searches online sources for that library. Although Rails is “just another gem”, it is the killer library that brought Ruby into the limelight.

Understanding Ruby-Isms

It’s daunting to learn a new library and a new language at the same time. Here are some of the biggest Ruby gotchas for those with a C/C++/Java background.

Ruby removes unnecessary cruft: (){};

  • Parenthesis on method calls are optional; use print "hi".
  • Semicolons aren’t needed after each line (crazy, I know).
  • Use “if then else end” rather than braces.
  • Parens aren’t needed around the conditions in if-then statements.
  • Methods automatically return the last line (call return explicitly if needed)

Ruby scraps the annoying, ubiquitous punctuation that distracts from the program logic. Why put parens ((around),(everything))? Again, if you want parens, put ‘em in there. But you’ll take off the training wheels soon enough.

The line noise (er, “punctuation”) we use in C and Java is for the compiler’s benefit, not ours. Be warned: after weeks with Ruby, other languages become a bit painful to read.

def greet(name)              # simple method
   "Hello, " + name          # returned automatically
end

greet "world"                # ==> "Hello, world"

Those Funny Ruby Variables

  • x = 3 is a local variable for a method or block (gone when the method is done)
  • @x = 3 is a instance variable owned by each object (it sticks around)
  • @@x = 3 is a class variable shared by all objects (it sticks around, too).
  • :hello is a symbol, like a constant string. Useful for indexing hashes. Speaking of which…
  • dictionary = { :cat => "Goes meow", :dog => "Barks loud."} is a hash of key/value pairs. Access elements with dictionary[:cat].

Those Funny Ruby Assignments

Ruby has the || operator which is a bit funky. When put in a chain

x = a || b || c || "default"

it means “test each value and return the first that’s not false.” So if a is false, it tries b. If b is false, it tries c. Otherwise, it returns the string “default”.

If you write x = x || "default" it means “set x to itself (if it has a value), otherwise use the default.” An easier way to write this is

x ||= "default"

which means the same: set x to the default value unless it has some other value. You’ll see this a lot in Ruby programs.

Those Funny Ruby Blocks

Ruby has “blocks”, which are like anonymous functions passed to a loop or another function. These blocks can specify a parameter using |param| and then take actions, call functions of their own, and so on. Blocks are useful when applying some function to each element of an array. It helps to think of them as a type of anonymous function that can, but doesn’t have to, take a parameter.

3.times do |i|
   print i*i
end

In this example, the numbers 0,1 and 2 are passed to a block (do… end) that takes a single parameter (i) and prints i squared. The output would be 0, followed by 1 followed by 4 (and looks like “014″ since we didn’t include spaces). Blocks are common in Ruby but take some getting used to, so be forewarned.

These are the Ruby lessons that were tricky when starting out. Try Why’s Poignant Guide To Ruby for more info (“Why” is the name of the author… it confused me too).

Understanding Rails-isms

Rails has its own peculiarities. “Trust us, it’s good for you.” say the programmers. It’s true – the features/quirks make Rails stand out, but they’re confusing until they click. Remember:

  • Class and table names are important. Rails has certain naming conventions; it expects objects from the class Person to be saved to a database table named people. Yes, Rails has a pluralization engine to figure out what object maps to what table (I kid you not). This magic is great, but scary at first when you’re not sure how classes and tables are getting linked together.
  • Many methods take an “options” hash as a parameter, rather than having dozens of individual parameters. When you see

    link_to “View Post”, :action => ‘show’, :controller => ‘article’, :id => @article

The call is really doing this:

link_to("View Post", {:action => 'show', :controller => 'article', :id => @article})

There are only two parameters: the name (“View Post”) and a hash with 3 key/value pairs. Ruby lets us remove the extra parens and braces, leaving the stripped-down function call above.

Understanding The Model-View-Controller Pattern

Rails is built around the model-view-controller pattern. It’s a simple concept: separate the data, logic, and display layers of your program. This lets you split functionality cleanly, just like having separate HTML, CSS and Javascript files prevents your code from mushing together. Here’s the MVC breakdown:

  • Models are classes that talk to the databse. You find, create and save models, so you don’t (usually) have to write SQL. Rails has a class to handle the magic of saving to a database when a model is updated.
  • Controllers take user input (like a URL) and decide what to do (show a page, order an item, post a comment). They may initially have business logic, like finding the right models or changing data. As your rails ninjitsu improves, constantly refactor and move business logic into the model (fat model, skinny controller). Ideally, controllers just take inputs, call model methods, and pass outputs to the view (including error messages).
  • Views display the output, usually HTML. They use ERB and this part of Rails is like PHP – you use HTML templates with some Ruby variables thrown in. Rails also makes it easy to create views as XML (for web services/RSS feeds) or JSON (for AJAX calls).

The MVC pattern is key to building a readable, maintainable and easily-updateable web app.

Understanding Rails’ Directory Structure

When you create your first rails app, the directories are laid out for you. The structure is well-organized: Models are in app/models, controllers in app/controllers, and views in app/my_local_views (just kidding).

The naming conventions are important – it lets rails applications “find their parts” easily, without additional configuration. Also, it’s very easy for another programmer to understand and learn from any rails app. I can take a look at Typo, the rails blogging software, and have a good idea of how it works in minutes. Consistency creates comprehension.

Understanding Rails’ Scaffolding

Scaffolding gives you default controller actions (URLs to visit) and a view (forms to fill out) to interact with your data — you don’t need to build an interface yourself. You do need to define the Model and create a database table.

Think of scaffolds as the “default” interface you can use to interact with your app – you’ll slowly override parts of the default as your app is built. You specify scaffolds in the controller with a single line:

scaffold :person

and it adds default actions and views for showing, editing, and creating your “Person” object. Rails forms take some getting used to, so scaffolding helps a lot in the initial stages.

More Tips and Tricks

I originally planned on a list of tips & tricks I found helpful when learning rails. It quickly struck me that Ruby on Rails actually requires a lot of background knowledge, and despite (or because of) its “magic”, it can still be confusing. I’ll get into my favorite tricks in an upcoming article.

As you dive further into web development, these guides may be helpful:

Until next time, enjoy these amusing videos:

Join 450k Monthly Readers

Enjoy the article? There's plenty more to help you build a lasting, intuitive understanding of math. Join the newsletter for bonus content and the latest updates.

A Simple, Comprehensive Overview of Javascript

This isn’t a reference guide, programming tutorial or detailed overview. It’s a Javascript refresher, assuming you know another programming language and puts all the information in one place (just ctrl+f to find!). Javascript has nothing to do with Java, is dynamically typed and has C-like syntax.

Enabling Javascript

Include javascript inside HTML:

<script>
  x = 3;
</script>

Reference external file:

<script src="http://example.com/script.js"></script>

Redirect if javascript disabled:

<noscript><meta http-equiv="refresh" content="0; URL=http://example.com/noscript.html"/></noscript>

Using Variables, Objects and Arrays

Deep dive into objects.

var str = "Hello";                // local variable, when inside a function
str2 = "Hello World";             // global variable in default context (window.str2)
str3 = 'My quote char: " ';       // single or double quote
str4 = "My really really really \
really long string broken into \
multiple lines";

str = 19;                         // change to int
str = 0xfe + 2.343 + 2.5e3;       // hex, floats, exp

var newObject = new Object();     // constructor
newObject = {};           // shorthand for same
newObject.name = "bob"            // dynamic attributes
newObject.name = null         // it's there (null item)
delete newObject.name         // it's gone (undefined)
newObject["real age"] = 33;       // array notation/hash table

var obj = {           // create object using JSON
    name: "Bob",          //   aka Javascript Object Notation
    details: {
        age: 33,
        "favorite color": "green"
    }
}
obj.name
obj.details["favorite color"]

var newArray = [];                // no size
newArray[3] = "hi";               // grows dynamically
newArray[2] = 13;                 // any type
newArray.push(newObject);         // add new item
newArray.pop();               // remove it

Comparisons and Manipulations

Javascript has some funky types and comparisons.

/* javascript types */
typeof("string") == "string"
typeof(3) == typeof(3.4) == typeof(0x34) == "number"
typeof(myObject) == typeof(myArray) == "object" // arrays are objects
typeof(true) == typeof(1 == 2) == "boolean"
typeof(Math.sin) == "function"
typeof(notthere) == "undefined"

/* comparisons */
123 == "123"                     // true => converts type
123 === "123"                    // false => checks type
typeof(x) == "undefined"     // x isn't there
x == null            // x is defined, but null

/* Numbers */
parseInt("123")          // base 10 => 123
parseInt("123", 16);         // base 16 => 291
parseFloat("123.43");        // 123.43

isNaN(0/0) == true       // illegal number
3/0 == Infinity          // legal...
-3/0 == -Infinity        //
isFinite(3/0) == false       // ... but not finite

/* regular expression (regex) string comparisons */
matches = "hello".match(/h../)   // returns array ["hel"] or null

re = new RegExp("h..", "ig");    // construct regexp -- no slashes
matches = "hello".match(re);     // use it

"hello".replace(/h/,"b")     // => "bello"

Conditionals and Loops

if (str == "Hello"){    // if-else
  alert("Hi");      // popup dialog
}
else{
  alert("something is wrong!");
}

a = 3, b = 4;       // multi-assigment
c = a > b ? a : b;  // c gets bigger item (b)

switch (name){      // switch statement
  case "Bob":
    alert("Hi Bob!")
    break
  case "Joe":
    alert("Hey Joe.")
    break
  default: alert("Do I know you?")
}

while (i < n){          // the basics
 // do something
 i++;
}

for (var i=0; i<n; i++){
  // do something else
}

for (var key in obj){
  // do something with obj[key]
}

Defining Functions

function foo(a,b){          // global function
  return a + b;
}

var fn = function(a,b){     // save function as variable...
  return foo(a,b);
}

obj.fn = function(a,b){     // ...or as part of object
  return a + b;
}

function bar(a,b){
    var n = 1;                  // local var

    function helper(x) {            // inner function...
        return 1/Math.sqrt(x + n);  // .. can use local vars
    }
    return helper(input);           // avoid need for global function
}

foo(1,2) == fn(1,2) == 3;   // true

Javascript Classes

Javascript doesn’t have formal class notation, but you can create a “constructor” and add methods to it. Examples from here.

function Person(first, last) { // create "constructor"
    this.first = first;        // public variables -- reference current object
    this.last = last;

    var privateFn = function(first, last){  // private function
    // ...
    }

    this.setName = function(first, last){ // public function
        this.first = first;
    this.last = last;
    }

}

Person.prototype.fullName = function() { // extend prototype
    return this.first + ' ' + this.last; //   even at runtime!
}

var bob = new Person("Bob", "Smith"); // "new" creates an object
bob.fullName();               // => "Bob Smith"

Advanced Javascript

function foo(a,b){        // will raise exception
  var c = a + b;
  throw "Error Message"; // your message here
}

try{                     // try dangerous code
   foo(1,2);
}
catch(e){           // catch exception
   alert(e.name + e.message);   // show details
}

eval("x = 3");       // execute arbitrary code

timer = setTimeout("myfunction()", 1000)  // execute in 1 second (1000ms)
clearTimeout(timer);              // cancel event

Browser Document Object Model (DOM), and GUI

Find and change HTML elements.

alert("message");  // messagebox with "OK"
var choice = confirm("message");  // OK/CANCEL true or false
var input = prompt("message", "default value"); // enter a value; null if cancelled

x = document.getElementById("foo");    // finds <div id="foo"></div>

x.style.background = "#333";           // set CSS style
x.style.borderLeft = "1px solid #ccc"; // border-left => borderLeft (camelCase)

x.className = "myclass";           // set CSS class
x.innerHTML = "Hello";             // set html inside div

y = document.getElementById("myinput"); // input area/textarea
y.value = "Hi";                 // get or set text

Keep learning

I made this page as a list of important examples; read the advanced guides if any section is confusing. A later post will cover the helper functions I use in my applications. Good luck.

Join 450k Monthly Readers

Enjoy the article? There's plenty more to help you build a lasting, intuitive understanding of math. Join the newsletter for bonus content and the latest updates.

Using JSON to Exchange Data

Javascript Object Notation (JSON) is a fancy name for a simple idea: A web page can download data stored as javascript variables. It’s caused a buzz in the tech world because JSON is much easier to load, read and manipulate compared to XML. Also, parsing large XML files can be a large performance hit – JSON gives you an object, packaged up and ready to go!

Remember the Script Tag?

In javascript you can import any script using notation like this:

    <script src="http://www.mysite.com/myscript.js"></script>

The browser will pull down the script and run it inside the current page. This is how embeddable widgets like Adsense and InstaCalc work.

The neat thing is that any variables and functions defined inside the script are available to the page. If myscript.js includes a function showMeTheMoney(), your page can call it (and, presumably, get shown the money).

This is all fine and dandy, and been known for a while. A cool use is to provide dynamic data to a page with encoded Javascript variables. If the variables were “objects” and we passed them using their special “notation”, we could call the system JavaScript Object Notation. (Technically, JSON just covers the “object” part; executable functions are dynamic javascript).

In Javascript, you can use objects like this:

var fruit = {}; // create new obj
fruit.name = "apple"; // set properties
fruit.color = "red";

// that is old fashioned! Try my new notation:

var fancyFruit = {"name":"pear", "color": "greenish"};

Javascript has a nice notation where you can define objects using "key":"value" pairs. You can define arrays and functions this way too, so your objects are more like a class, in fact.

So why is this useful again?

So far, passing scripts around is old news. But an idea comes along: what if you load a dynamically generated script, which has data inside of it? Now you can access the data as javascript variables. Here’s what I mean:

<script src="http://www.weathersite.com/latestweather.js"></script>
Today's weather is:
<script>
document.write(Weather.today);
</script>

See what’s happening here? We load the javascript (which could be updated every hour by the server), and access the Weather object it defines. Presumably, Weather.today is a string containing today’s weather. Realistically, we could have Weather[zipcode] or whatever format the site defines.

Cool, huh?

But Why Not XML?

Ah — some programmers will say “Verily, can you not download an XML file, and then process and parse it into Javascript variables?”

Sure, just like you can run a marathon or floss your teeth. Many want to, some try to, not everybody does.

XML is fine for certain things, but it can be quite cumbersome. JSON is great because you can include data in an easy, painless process. There’s no parsing step – you are getting your variables “for free” by just including the javascript file.

Also, JSON lets the site include functions, which may be used to process the data or handle other tasks.

A Few Details (As Always)

There are various ways to use JSON (see links for source of code sample):

  • Include a script tag directly (as above). This means the code inside the script is run immediately as the browser encounters it.

    <script src="http://www.mysite.com/mydata.js"></script>
    
  • Dynamically load the script tag. You can add a javascript tag to the head of a document (from codehouse.com):

    function dhtmlLoadScript(url)
    {
       var e = document.createElement("script");
       e.src = url;
       e.type="text/javascript";
       document.getElementsByTagName("head")[0].appendChild(e);
    }
    dhtmlLoadScript("http://www.mysite.com/mydata.js");
    
  • Use an AJAX library like jQuery to access the information:

    $.getJSON("mydata.js", function(json){
      // access data with json.fieldname
    });
    

Note: The first two methods can load files from any domain; an AJAX request can normally only access files on the same domain. For a cross-domain AJAX request, you may need to use a “callback=?” parameter, like this:

http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?

This tells jQuery to create a temporary callback function to process the data, and tells the endpoint to wrap the JSON response in that callback function (example using jsoncallback=test).

Security, Security, Security

I’m not an expert in Web Security, but I know enough to realize it’s tricky and that there will be things I miss. Even the big boys like Google can get caught in bugs sometimes.

The safest approach is to only store public data with JSON. If you store private data in JSON (or XML for that matter), there are techniques where malicious sites can impersonate logged-on users. Yes, there are complicated workarounds for the security problems (like double-submitting cookies). But if you’re starting out (like me), start off using JSON for public info you don’t mind having disclosed (like weather reports).

Callbacks

The JSON data may not be a raw object; it could be an object passed to a callback function, such as:

specialFunction( {"name" : "Bob", "email": "[email protected]"} );

In this case, the script will run a function called specialFunction that you’ve defined, passing it an anonymous object with a “name” and “email” property. Your specialFunction can then do wild things with this information.

This technique is the same at heart – this is how Google originally passed your Gmail contacts. Sometimes you can specify the name of your callback function in the URL you use to access the JSON data – it depends on the data provider.

Real-life Example: Currency Conversion in InstaCalc

I recently added currency conversion to the InstaCalc Online Calculator, which was a good lesson in importing data:

  • Find your data source. The Federal Bank of New York has an XML file with currency conversion data. That’s good enough for me!

  • Convert data to JSON format. You can convert XML to JSON using XSLT transformations.

  • Install XALAN so you can do XSL transformations using Java. A typical transformation looks like this:

    java org.apache.xalan.xslt.Process -classpath "xalan.jar" -IN in.xml -XSL in.xslt > out.xml
    

Be careful for Java classpath issues, I had trouble and had to include the classpath to xalan.jar manually.

  • Convert XML attributes to elements. Attributes can be difficult to access in the various XML to JSON scripts, so make them elements. Use this XSL to convert attributes to elements:
 
   
    
   
   
   
     
       
         
           
             
           
         
       
       
     
   
 

Then process the XML file using XALAN:

java org.apache.xalan.xslt.Process -classpath "xalan.jar" -IN in.xml -XSL attributes-to-elements.xslt > no-attributes.xml

Finally, convert the XML to JSON using this XSL transformation. There are several XML 2 JSON stylesheets out there if you search.

Run your XML through XALAN to create the final JSON data.

java org.apache.xalan.xslt.Process -classpath "xalan.jar" -IN no-attributes.xml -XSL xml2json.xslt > currencies.json

Clean up your data. You have the raw JSON data as an object, but you may wish to wrap it in a function call. You can use a quick perl script to wrap myFunction( ) around the data above so your file does a callback when executed.

Tada! Now you have JSON data ready to access using one of the techniques above (see the currency JSON data). Inside InstaCalc, I have a static reference to the file:

  <script src="http://instacalc.com/data/currencies.json"><script>

Because the bank has some namespace information, I access variables like this inside the callback function: data["frbny:DataSet"];. Of course, the details of how you access your JSON data will change given the format of your XML and the exact stylesheet you used. Play around. If you look at the raw JSON file you can see the field names you need to use.

Bonus round: Updating the JSON. If your data changes often (like currency data does), you can put the above steps into a script and run it on a schedule. The next time your webpage is loaded, it will get the new JSON data.

Parting Thoughts

JSON is a really easy way to exchange data – just think of it as including extra javascript files in your program. Read more at json.org, learn it, and love it. Good luck.

Join 450k Monthly Readers

Enjoy the article? There's plenty more to help you build a lasting, intuitive understanding of math. Join the newsletter for bonus content and the latest updates.