Code Monkey home page Code Monkey logo

observejs's Introduction

ObserveJS

ObserveJS is an event-based library created for Ruby On Rails to help people build interactive application without committing to a Single Page Application (SPA).

Based on Custom Elements, ObserveJS takes an innovative approach that re-use views and partials and leverages custom events to make you change application to any server response.

This framework is not like any other JS alternative. It brings concepts from different paradigms and merges them together. It's not as simple as building some JS classes and have everything fed via JSON. Obviously, this won't be for everyone.

To understand what ObserveJS is all about, you need to understand the foundation on which ObserveJS was built.

Javascript Classes bound like Custom Elements

You may not know about Custom elements, these guys aren't as popular as React but they aren't useless. Trust me. What you need to know here is that by defining an attribute on an element, you can let ObserveJS instantiate a JavaScript class that will be bound to this object. Here's an example:

<div class='datepicker' as='Datepicker'>
</div>

Here, you defined an element with the as attribute. That attribute is special as it will be detected by ObserveJS. It will locate a Javascript class that has been declared the same name and instantiate it. Here's how it would look in JS:

ObserveJS.bind('Datepicker', class {
  // This method is called after the class is configured and attached to
  // the element
  loaded() {
    console.log("I'm instantiated")
    
    this.element()
    // <div class='datepicker' as='Datepicker'>
    
    //This look for data-loading
    this.observe('loading', this.changeStatus)
  }
  
  changeStatus(mutation) {
  }
})

The object instantiated inherit a few methods that are shown below. The most important method of all is probably the this.element() method. It returns the element that was bound to this class.

Now, if you would have the DOM element rendered in a page, automatically, the associated JavaScript class would get instantiated and initialized. Those objects have default API that makes your life easier.

JS Object's instance methods

this.element()

Returns the element bound to the JS object.

this.on(event_name, callback)

Bind an event to the specified callback. The event is bound to the element associated with the class. In the example above, this would mean that the event would be bound to the div element. The callback will be fired only if an event matching its name bubbles up to the element or if an event is fired directly on this event.

this.on(event_name, target, callback)

Bind an event on a descendant of the element associated with the given class. If the target is not a descendant, an Exception will be raised. This is basically the same thing as the previous method except that you can bind it to a descendant.

this.when(event_name, callback)

Bind an event to document. This should be used only when dealing with server side events or when you need to capture an event from another element that is not a descendant.

All those methods are available to configure your object at any time. You will probably find it useful to setup your callabcks in the loaded() method as it is the callback used by ObserveJS when the object is configured.

this.observe(attribute, callback)

Bind a callback to a change made to data-* attribute on this.element(). You can call this on different attribute.

observejs's People

Contributors

pier-oliviert avatar

Stargazers

Matt Culpepper avatar Max Chernyak avatar Adam Jahnke avatar justin talbott avatar Nemanja Čorlija avatar Ivo Benedito avatar Mason Wiley avatar Vladimir Vinnikov avatar Bill Gloff avatar blahutka avatar Anatoly Chernov avatar Asim Sikka avatar Martin Lensment avatar Matteo Folin avatar Thiago avatar Zaid Akram avatar Weston Ganger avatar Rufo Sanchez avatar Matt Brictson avatar Walter Lee Davis avatar Michal Bernhard avatar Gabriel Mazetto avatar Jonathan Borg avatar

Watchers

 avatar

observejs's Issues

observejs doesn't work properly with jquery_ujs

  1. fires remote query twice or multiple times
  2. code wrapped in (function(target ... nothing change to html

i disabled xhr in observejs.js.coffee & wiped application.js.erb to ->
<%= yield %>

than work fine

Won't do test coverage until a working headless browser exists

I have a branch that should test coverage most of the library but it can't be merge in master because no headless browser I have tried worked.

The issue is that none of them supports MutationObserver API and Ethereal is based off that. Even though all browser now supports it, emulators do not or other, like Phantomjs links against an old version of WebKit.

Create an instance only if it exists

There's an issue where Joint would create an instance when another one is already binded to an element. Such event would happen when an element is removed from the DOM tree and then re-inserted at a later time.

Add Storage using <template>

As of this moment, ObserveJS has an issue when storing DOM elements into JavaScript object. The problem is simple: When the user uses the 'back' button, the browser reload the HTML but doesn't restore JavaScript objects. That means that every state you had stored is wiped clean.

One scenario where this breaks my flow is when I deal with multiple steps that do not require a roundtrip to the server. What I do is I render all the steps and when the matching class is instantiated, I remove the extra steps from the DOM and store it in a variable. Here's an example:

ObserveJS.bind 'Messages', class
  loaded: =>
    @confirmation = @element().querySelector('div.confirmation').remove()
    @on 'click', @element().querySelector('button'), @confirm

  confirm: (e) =>
    @element().appendChild @confirmation

This breaks as soon as you go back one page because the DOM doesn't have the confirmation element anymore and the class expect it to be there.

Templates to the rescue

The idea would be to use to store DOM elements that are unecessary at page load. It should be possible to store DOM inside the template from any place in Rails' view hierarchy. Convention > configuration and all that.

My guess would be to create a new helper or something similar that would allow such a feature. It would take a similar approach to how you bind a JS object to the DOM. Unless people needs more configuration, I think a good approach would be to bind a template to the class you are aiming for. This would make the declaration explicit and would also show the intent of that DOM element. It may not be obvious so here's an example:

<div as='Messages'>
  <section class='step'>
    <h2>First step. Select a user.</h2>
    <ul>
      <li>User 1</li>
    </ul>
  </section>

  <%= content_tag :template, for: 'Messages' do %>
    <section class='step'>
      <h2>Second step. Something!</h2>
    </section>
  <% end %>
</div>

From that point, here's how you could implement this.

ObserveJS.bind 'Messages', class
  loaded: =>
    @on 'click', @element().querySelector('button'), @show

  show: (e) =>
    @element().appendChild(@retrieve('section.step'))

This last method would clone and cache that new step so if the user goes back, the DOM element is always present in the DOM via template.

Ok, this is long enough for now but I wanted to write all of this down so I can look back at this and edit it as/if I see problems.

As usual, if anyone has ideas, feel free to pitch in.

Add selector helper method.

The previous version was to add a @element().on() method. I'm not entirely sure if this is the right approach.

This is polluting HTMLElement and it doesn't have any advantage.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.