Fork me on GitHub

About

Etch is a content editor built on Backbone.js and is designed to be easily plugged into your Backbone app.

Pros:

  • Minimal and Lightweight
  • Utilizes ContentEditable to edit content in place
  • Easy integration with your backbone.js app

Cons:

  • Only tested in modern browsers, some legacy support has been added, but testing is incomplete (help/feedback is needed here)
  • People still use legacy IE browsers :(

Future:

  • Image Uploading, Cropping and Insertion - already built, just needs some work
  • Legacy support for IE7+
  • Unit Tests

Demo

Areas marked with a blue background are editable, try it.

This is an editable title

Text with a light blue background is editable. You will find it easy to use etch to underline text as well as bold and italic. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

'save' event triggered on model

Documentation

Include Dependencies

Etch depends on jQuery, Underscore, Backbone, as well as Rangy if you need support for legacy browsers (IE8 and prior).

You can exclude Rangy and shave 41k off of your footprint if you don't need legacy support.

Once you have the dependencies squared away simply include the etch.js script after them and before the script where you define your Models/Views.

At this point your scripts section should look something like this:


      <script src="/media/scripts/lib/jquery.js"></script>
      <script src="/media/scripts/lib/underscore.js"></script>
      <script src="/media/scripts/lib/backbone.js"></script>
      <script src="/media/scripts/lib/rangy-core.js"></script> <!-- OPTIONAL -->
      <script src="/media/scripts/etch/scripts/etch.js"></script>
      <script src="/media/scripts/article.js"></script> <!-- Models/Views here -->
                            

Ensure that your scripts are in the right order or everything will likely be broken.

Also you need to add etch.css to your stylesheets


      <link rel="stylesheet" href="/media/scripts/etch/styles/etch.css" />
                            

Building the Model

This part is simple, we just define a model and give it a url and some defaults. Your model will probably end up being more complex but this is all it takes to get Etch working.


      var article = Backbone.Model.extend({
        url: '/some/api/url/',

        defaults: {
          title: 'Default Title',
          body: 'Default body text'
        }
      });
                    

Building the View

Basically all we need to do is call etch.editableInit when a user clicks (mousedown) on an editable element. Because of how backbone delegates events we need to call an intermediate function, editableClick, which references etch.editableInit.


      var articleView = Backbone.View.extend({
        events: {
          'mousedown .editable': 'editableClick'
        },

        editableClick: etch.editableInit
      });
                    

etch.editableInit handles everything else for you except for saving. Etch will trigger a 'save' event on your model when the save button is clicked. All we need to do is listen for it by adding a binding to the view like so:


      var articleView = Backbone.View.extend({
        initialize: function() {
          _.bindAll(this, 'save');
          this.model.bind('save', this.model.save);
        },
        
        events: {
          'mousedown .editable': 'editableClick'
        },

        editableClick: etch.editableInit
      });
                    

Customizing

You may have noticed that the demo had different buttons in the editor widget depending on if you were editing the body or the title. Etch allows you to customize which buttons to show on a given 'editable' by adding a data-button-class attribute to the element.

The default classes are:


      etch.config.buttonClasses = {
        'default': ['save'],
        'all': ['bold', 'italic', 'underline', 'unordered-list', 'ordered-list', 'link', 'clear-formatting', 'save'],
        'title': ['bold', 'italic', 'underline', 'save']
      };
                        

The 'default' button class will be used if no button class is defined on the element.

Defining your own button classes can be accomplished by extending etch.config.buttonClasses. Here we override 'default' to add more buttons and add a 'caption' class.


      _.extend(etch.config.buttonClasses, {
        'default': ['bold', 'italic', 'underline', 'save'],
        'caption': ['bold', 'italic', 'underline', 'link', 'save']
      });
                    

The order of buttons in the array is how they will be presented in the editor widget.

If the class '.editable' causes conflicts for you or you need to change it for any reason you can do so by setting etch.config.selector


      etch.config.selector = '.my-new-editable-class';
                    

All functions are public and can be overridden to customize functionality

For instance, if you want to create a custom popup for the link url prompt:


      etch.views.Editor.prototype.urlPrompt = function(callback) {
        // Custom popup code to get url
        callback(url)
      }
                    

Issues and Questions

Contact Josh Nielsen through github issues

API Changelog:

0.6.0 - etch configuration options now are nested under the etch.config namespace.