Skip to content

Rails 3 walkthrough part 2

dturnbull edited this page Dec 25, 2010 · 8 revisions

This builds on the project we created in Rails 3 Walkthrough Part 1.

In part 1 we used a pre-compiled javascript to add support for Rails' default unobtrusive javascript markup. In this section we will create our own custom javascript that includes the unobtrusive defaults and upgrades text areas to wysiwyg editing.

In Googlyscript, compilation is performed by a template with embedded ruby. Driving development with templates like these is fundamental to developing with Googlyscript. The classic approach use static files and command line tools to drive development. Plovr does a little of what Googlyscript does, but lacks a Ruby environment and doesn't embrace templates.

Here we build a Googlyscript template to run our compile job. The compiling page demonstrates how these can be built. You're just putting the options for compiler.jar into a template. The only thing different is added support for the '--ns' namespace option.

Create app/javascripts/myapp.js.erb.

<% @response = goog.compile(%w{
  --compilation_level ADVANCED_OPTIMIZATIONS    
  --js_output_file ../../public/javascripts/myapp.js
  --summary_detail_level 3
  --define goog.DEBUG=false
  --ns myapp
}).to_response_with_console -%>

Go back to the application layout and remove the link to '/dev/googly/rails_ujs.js'. Replace it with a link to the compiler you just created. The wysiwyg editor needs some stylesheets, so we add those too.

Edit app/views/layouts/application.html.erb

<%= javascript_include_tag '/dev/myapp/myapp.js' %>
<link rel="stylesheet" href="/dev/goog/demos/css/demo.css" />
<link rel="stylesheet" href="/dev/goog/css/button.css" />
<link rel="stylesheet" href="/dev/goog/css/dialog.css" />
<link rel="stylesheet" href="/dev/goog/css/linkbutton.css" />
<link rel="stylesheet" href="/dev/goog/css/menu.css">
<link rel="stylesheet" href="/dev/goog/css/menuitem.css">
<link rel="stylesheet" href="/dev/goog/css/menuseparator.css">
<link rel="stylesheet" href="/dev/goog/css/tab.css" />
<link rel="stylesheet" href="/dev/goog/css/tabbar.css" />
<link rel="stylesheet" href="/dev/goog/css/toolbar.css" />
<link rel="stylesheet" href="/dev/goog/css/colormenubutton.css" />
<link rel="stylesheet" href="/dev/goog/css/palette.css" />
<link rel="stylesheet" href="/dev/goog/css/colorpalette.css" />
<link rel="stylesheet" href="/dev/goog/css/editor/bubble.css" />
<link rel="stylesheet" href="/dev/goog/css/editor/dialog.css" />
<link rel="stylesheet" href="/dev/goog/css/editor/linkdialog.css" />
<link rel="stylesheet" href="/dev/goog/css/editortoolbar.css" />

Here's the application we need to build for the editor. All it does is instantiate an editor with all the plugins we want. I literally went to the Closure Library demo page and wrapped the example in my own function.

Create app/javascripts/base.js.

goog.provide('myapp')
// This imports the unobtrusive Googlyscript behavior for Rails 3
goog.require('googly.rails.ujs');
// These are
goog.require('goog.dom');
goog.require('goog.editor.Command');
goog.require('goog.editor.Field');
goog.require('goog.editor.plugins.BasicTextFormatter');
goog.require('goog.editor.plugins.EnterHandler');
goog.require('goog.editor.plugins.HeaderFormatter');
goog.require('goog.editor.plugins.LinkBubble');
goog.require('goog.editor.plugins.LinkDialogPlugin');
goog.require('goog.editor.plugins.ListTabHandler');
goog.require('goog.editor.plugins.LoremIpsum');
goog.require('goog.editor.plugins.RemoveFormatting');
goog.require('goog.editor.plugins.SpacesTabHandler');
goog.require('goog.editor.plugins.UndoRedo');
goog.require('goog.ui.editor.DefaultToolbar');
goog.require('goog.ui.editor.ToolbarController');
// This is what we'll call to upgrade a text field to wysiwyg.
myapp.wysiwyg = function(field_id, toolbar_id, opt_doc) {
  // Create an editable field.
  var myField = new goog.editor.Field(field_id, opt_doc);
  // Create and register all of the editing plugins you want to use.
  myField.registerPlugin(new goog.editor.plugins.BasicTextFormatter());
  myField.registerPlugin(new goog.editor.plugins.RemoveFormatting());
  myField.registerPlugin(new goog.editor.plugins.UndoRedo());
  myField.registerPlugin(new goog.editor.plugins.ListTabHandler());
  myField.registerPlugin(new goog.editor.plugins.SpacesTabHandler());
  myField.registerPlugin(new goog.editor.plugins.EnterHandler());
  myField.registerPlugin(new goog.editor.plugins.HeaderFormatter());
  myField.registerPlugin(new goog.editor.plugins.LoremIpsum('Click here to edit'));
  myField.registerPlugin(new goog.editor.plugins.LinkDialogPlugin());
  myField.registerPlugin(new goog.editor.plugins.LinkBubble());
  // Specify the buttons to add to the toolbar, using built in default buttons.
  var buttons = [
    goog.editor.Command.BOLD,
    goog.editor.Command.ITALIC,
    goog.editor.Command.UNDERLINE,
    goog.editor.Command.FONT_COLOR,
    goog.editor.Command.BACKGROUND_COLOR,
    goog.editor.Command.FONT_FACE,
    goog.editor.Command.FONT_SIZE,
    goog.editor.Command.LINK,
    goog.editor.Command.UNDO,
    goog.editor.Command.REDO,
    goog.editor.Command.UNORDERED_LIST,
    goog.editor.Command.ORDERED_LIST,
    goog.editor.Command.INDENT,
    goog.editor.Command.OUTDENT,
    goog.editor.Command.JUSTIFY_LEFT,
    goog.editor.Command.JUSTIFY_CENTER,
    goog.editor.Command.JUSTIFY_RIGHT,
    goog.editor.Command.SUBSCRIPT,
    goog.editor.Command.SUPERSCRIPT,
    goog.editor.Command.STRIKE_THROUGH,
    goog.editor.Command.REMOVE_FORMAT
  ];
  var myToolbar = goog.ui.editor.DefaultToolbar.makeToolbar(
    buttons, goog.dom.getElement(toolbar_id)
  );
  // Hook the toolbar into the field.
  var myToolbarController = new goog.ui.editor.ToolbarController(myField, myToolbar);
  // Make editable.
  myField.makeEditable(); 
}
// Closure Compiler will rename and flatten everything,
// this is how we preserve the symbol that is called from our application.
goog.exportSymbol('myapp.wysiwyg', myapp.wysiwyg);

Finally, we modify the form template to include a div for the toolbar and call the function that activates the editor. It doesn't mater where you put the toolbar, but the script must be after both the field and the toolbar.

There is no need to run the script on document ready. Components in Closure Library don't require this in order to be performant.

Edit app/views/employees/_form.html.erb

<div id="toolbar"></div>
<script>myapp.wysiwyg('employee_notes', 'toolbar')</script>

That's it! Visit http://localhost:3000/employees/new and you should have a wysiwyg editor on the text field.

If you look in public/javascripts you will find myapp.js which is the compiled version of your javascript. This is the script you want to use in production. Instead of calling the compiler from Rails, you create a Googlyscript template in like the demos in Closure Library.

Check out the demos: (and this isn't everything)

http://localhost:3000/dev/goog/demos/index
Clone this wiki locally