Ractive.extend()

edit this page

Ractive is more than a library; it is a platform. It makes it easier to create reusable, but specialised, blocks of functionality such as to-do lists, slideshows, bar charts, text editors, and so on.

Default options can also be provided using Ractive.extend(). While the result is a fully instantiable on its own, the main value is that they can then be used as components within your templates:

var MyRactive = Ractive.extend({
  template: 'I can be instantiated _or_ be a component!'
});

var ractive = new MyRactive({
  el: 'container'
});

var ractive2 = new Ractive({
  el: 'container2',
  template: '<widget/>',
  components: {
    widget: MyRactive
  }
});

Though it's technically incorrect, we'll refer to these as subclasses of the Ractive base class. In order to create them, we use Ractive.extend().

Here's a simple example - we'll create a Modal subclass which has a default template, and which always stays centred on the page:

.modal-background {
  position: fixed;
  top: 0; left: 0; width: 100%; height: 100%;
  background-color: rgba(0,0,0,0.5);
  padding: 0.5em;
  text-align: center;
  -moz-box-sizing: border-box; box-sizing: border-box;
}

.modal-outer {
  position: relative;
  width: 100%;
  height: 100%;
}

.modal {
  position: relative;
  background-color: white;
  padding: 2em;
  box-shadow: 1px 1px 3px rgba(0,0,0,0.1);
  margin: 0 auto;
  display: inline-block;
  max-width: 100%;
  max-height: 100%;
  overflow-y: auto;
  -moz-box-sizing: border-box; box-sizing: border-box;
}

.modal-button {
  text-align: center;
  background-color: rgb(70,70,180);
  color: white;
  padding: 0.5em 1em;
  display: inline-block;
  cursor: pointer;
}
<div class='modal-background' on-tap='close' intro='fade' outro='fade'>
  <div class='modal-outer'>
    <div class='modal'>
      {{>modalContent}}
    </div>
  </div>
</div>
// Create our Modal subclass
Modal = Ractive.extend({
  // by default, the modal should sit atop the <body>...
  el: document.body,

  // ...but it should append to it rather than overwriting its contents
  append: true,

  // all Modal instances will share a template (though you can override it
  // on a per-instance basis, if you really want to)
  template: modalTemplate,

  // the onrender function will be called as soon as the instance has
  // finished rendering
  onrender: function () {
    var self = this, resizeHandler;

    // store references to the background, and to the modal itself
    // we'll assume we're in a modern browser and use querySelector
    this.outer = this.find( '.modal-outer' );
    this.modal = this.find( '.modal' );

    // if the user taps on the background, close the modal
    this.on( 'close', function ( event ) {
      if ( !this.modal.contains( event.original.target ) ) {
        this.teardown();
      }
    });

    // when the window resizes, keep the modal horizontally and vertically centred
    window.addEventListener( 'resize', resizeHandler = function () {
      self.center();
    }, false );

    // clean up after ourselves later
    this.on( 'teardown', function () {
      window.removeEventListener( 'resize', resizeHandler );
    }, false );

    // manually call this.center() the first time
    this.center();
  },

  center: function () {
    var outerHeight, modalHeight, verticalSpace;

    // horizontal centring is taken care of by CSS, but we need to
    // vertically centre
    outerHeight = this.outer.clientHeight;
    modalHeight = this.modal.clientHeight;

    verticalSpace = ( outerHeight - modalHeight ) / 2;

    this.modal.style.top = verticalSpace + 'px';
  }
});

// We can now instantiate our modal
basicModal = new Modal({
  partials: {
    modalContent: '<p>This is some important content!</p><a class="modal-button" on-tap="okay">Okay</a>'
  }
});

basicModal.on( 'okay', function () {
  this.teardown();
});

Subclasses can themselves be extended. Lets say we wanted to be able to create lots of modals similar to this one:

BasicModal = Modal.extend({
  partials: {
    modalContent: '<p>This is some important content!</p><a class="modal-button" on-tap="okay">Okay</a>'
  },

  onrender: function ( options ) {
    this.on( 'okay', function () {
      this.teardown();
    });
  }
});

basicModal = new BasicModal();

Ractive.extend() can be used with multiple prototypes, which will be applied from left to right.

var Foo = Ractive.extend({
    template: 'I am effectively overridden'
  }, {
    template: 'I win'
  });