ethereal 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 285353e09738b1de4ca744c90c0ae9adf8946cbd
4
+ data.tar.gz: ae0b4d6959fde680a366e03678c9e88ddffb20c3
5
+ SHA512:
6
+ metadata.gz: fc6149905f25a6d5c5313638300bb963c28d73b41e4dce11c39221cbcbad476716dc6e206cda5e2c8f7665352d3b1271c62787999735044b2371ade76ce9f142
7
+ data.tar.gz: 632710b135f3a2ff699ab6f3aebb3451b39068e2775f74a43b7476cdc40ece04da7562a9603afbafade5be9c639776694c3cbe1773c32900c4f25f398e9991a6
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ethereal.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Pier-Olivier Thibault
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,64 @@
1
+ # Ethereal
2
+
3
+ Event based JavaScript framework tailored made for Ruby on rails.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'ethereal'
11
+ ```
12
+
13
+ Then add this line to application.js
14
+
15
+ ```js
16
+ //= require 'ethereal'
17
+ ```
18
+ ## Usage
19
+
20
+ Ethereal is an event based framework that manages the life cycle of JavaScript objects. Here's a simple Todo where you can dynamically add/remove items on the list.
21
+
22
+ ```erb
23
+ <%= content_tag :ol, as: 'Todo.List, do %>
24
+ <%= render @todos %>
25
+ <% end %>
26
+ ```
27
+
28
+ ```coffee
29
+ class Todos
30
+ # @element() always return the element to which your object is bound.
31
+
32
+ loaded: =>
33
+ @element().on 'todos:create', @add
34
+ @element().on 'todos:destroy', @delete
35
+
36
+ add: (e) =>
37
+ @element().appendChild(e.html)
38
+
39
+ delete: (e) =>
40
+ @element().querySelector("[tid=#{e.todoId}]")?.remove()
41
+
42
+ Ethereal.Models.add Todos, 'Todo.List'
43
+ ```
44
+
45
+ ```ruby
46
+ #views/todos/create.js.erb
47
+ e.html = "<%= j render @todo %>".toHTML()
48
+ ```
49
+
50
+ ```ruby
51
+ #views/todos/destroy.js.erb
52
+ e.todoId = <%= @todo.id %>
53
+ ```
54
+
55
+ Some notes:
56
+
57
+ - Automatic instantiation. No need to wrap things in DOMContentReady anymore.
58
+ - Events are built following the "controller:action" pattern.
59
+ - A callback (@loaded) is called right after Ethereal has instantiated an object.
60
+ - In *.js.erb, an event is created. You can set HTML to the event object.
61
+ - To ease the process, a toHTML() method has been added to the String object (JS).
62
+ - You need to register any class you create through the ```Ethereal.Models.add Class, 'name'````. The name is the attribute you set in your DOM.
63
+
64
+
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ethereal/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ethereal"
8
+ spec.version = Ethereal::VERSION
9
+ spec.authors = ["Pier-Olivier Thibault"]
10
+ spec.email = ["pothibo@gmail.com"]
11
+ spec.summary = %q{Event based JavaScript framework tailored for Ruby on rails.}
12
+ spec.license = "MIT"
13
+
14
+ spec.files = `git ls-files -z`.split("\x0")
15
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "bundler", "~> 1.7"
20
+ spec.add_development_dependency "rake", "~> 10.0"
21
+ end
@@ -0,0 +1,5 @@
1
+ require "ethereal/version"
2
+
3
+ module Ethereal
4
+ require 'ethereal/railtie'
5
+ end
@@ -0,0 +1,6 @@
1
+ #= require 'ethereal/ext'
2
+ #= require 'ethereal/base'
3
+ #= require 'ethereal/god'
4
+ #= require 'ethereal/model'
5
+ #= require 'ethereal/watcher'
6
+ #= require 'ethereal/xhr'
@@ -0,0 +1,50 @@
1
+ @Ethereal = {
2
+ attributeName: 'as'
3
+ }
4
+
5
+ @Ethereal.isDOM = (el) ->
6
+ el instanceof HTMLDocument ||
7
+ el instanceof HTMLElement
8
+
9
+ listen = (e) ->
10
+ if e.type && e.type == 'DOMContentLoaded'
11
+ document.removeEventListener('DOMContentLoaded', listen)
12
+
13
+ Ethereal.Watcher(document, {
14
+ attributes: true,
15
+ subtree: true,
16
+ childList: true,
17
+ attributeFilter: [Ethereal.attributeName],
18
+ characterData: true
19
+ })
20
+
21
+ Ethereal.Watcher().inspect(document.body)
22
+
23
+ document.addEventListener 'submit', (e) ->
24
+ if e.target.getAttribute('disabled')? || e.target.dataset['remote'] != 'true'
25
+ return
26
+
27
+ Ethereal.XHR.Form(e.target)
28
+
29
+ e.preventDefault()
30
+ return false
31
+
32
+ document.addEventListener 'click', (e) ->
33
+
34
+ if e.target.getAttribute('disabled')? || e.target.dataset['remote'] != 'true'
35
+ return
36
+
37
+ xhr = new Ethereal.XHR(e.target)
38
+ xhr.send(e.target.getAttribute('href'))
39
+
40
+ e.preventDefault()
41
+ return false
42
+
43
+
44
+ if document.readyState == 'complete'
45
+ listen()
46
+ else
47
+ document.addEventListener('DOMContentLoaded', listen)
48
+
49
+
50
+
@@ -0,0 +1,7 @@
1
+ String::toHTML = ->
2
+ el = document.createElement('div')
3
+ el.innerHTML = this
4
+ if el.children.length > 1
5
+ el.children
6
+ else
7
+ el.children[0]
@@ -0,0 +1,43 @@
1
+ class God
2
+ update: (el) =>
3
+ model = el.getAttribute(Ethereal.attributeName)
4
+ if model?
5
+ @create(el, model)
6
+ else
7
+ @destroy(el)
8
+
9
+ create: (el) =>
10
+ model = el.getAttribute(Ethereal.attributeName)
11
+ if @modelExists(model)
12
+ el.instance = new Ethereal.Models.klass[model](el)
13
+
14
+ el.instance.element = ->
15
+ el
16
+
17
+ el.instance.on = (event, target, callback) ->
18
+ if callback?
19
+ el.instance.on.events.push([event, target, callback])
20
+ else
21
+ callback = target
22
+ target = el
23
+ target.addEventListener(event, callback)
24
+
25
+ el.instance.on.events = []
26
+
27
+ if el.instance.loaded?
28
+ el.instance.loaded()
29
+
30
+ else
31
+ throw "error: #{model} is not registered. Add your model with Ethereal.Models.add(#{model})"
32
+
33
+ destroy: (el) =>
34
+ el.instance.on.events?.forEach (event) ->
35
+ event[1].removeEventListener(event[0], event[2])
36
+
37
+
38
+ modelExists: (name) =>
39
+ Ethereal.Models.klass[name]?
40
+
41
+
42
+ Ethereal.God = new God
43
+
@@ -0,0 +1,8 @@
1
+ class Models
2
+ klass: {}
3
+ add: (kls, name) ->
4
+ unless name?
5
+ name = kls.name
6
+ @klass[name] = kls
7
+
8
+ Ethereal.Models = new Models
@@ -0,0 +1,50 @@
1
+ instance = undefined
2
+
3
+ class Watcher
4
+ constructor: (target, config = {}) ->
5
+ @observer = new MutationObserver(@observed)
6
+ @observer.observe(target, config)
7
+
8
+ observed: (mutations) =>
9
+ mutations.forEach (mutation) =>
10
+ if mutation.type == 'attributes'
11
+ Ethereal.God.update(target)
12
+ else
13
+ @add(mutation.addedNodes)
14
+ @destroy(mutation.removedNodes)
15
+
16
+
17
+ add: (nodes) =>
18
+ for node in nodes
19
+ continue unless Ethereal.isDOM(node)
20
+ if node.hasAttribute(Ethereal.attributeName)
21
+ Ethereal.God.create(node, node.getAttribute(Ethereal.attributeName))
22
+
23
+ for child in node.querySelectorAll("[#{Ethereal.attributeName}]")
24
+ Ethereal.God.create(child, child.getAttribute(Ethereal.attributeName))
25
+
26
+ destroy: (nodes) =>
27
+ for node in nodes
28
+ continue unless Ethereal.isDOM(node)
29
+ if node.hasAttribute(Ethereal.attributeName)
30
+ Ethereal.God.destroy(node)
31
+
32
+ for child in node.querySelectorAll("[#{Ethereal.attributeName}]")
33
+ Ethereal.God.destroy(child)
34
+
35
+ inspect: (node) ->
36
+ if Ethereal.isDOM(node)
37
+ found = node.querySelectorAll("[#{Ethereal.attributeName}]")
38
+ Ethereal.God.create(el) for el in found
39
+
40
+ # !! **************************************** !! #
41
+
42
+ Ethereal.Watcher = ->
43
+ unless instance?
44
+ i = 0
45
+ target = null
46
+ target = if Ethereal.isDOM(arguments[i]) then arguments[i++] else document
47
+ instance = new Watcher(target, arguments[i])
48
+
49
+ instance
50
+
@@ -0,0 +1,32 @@
1
+ class XHR
2
+ constructor: (el) ->
3
+ @element(el)
4
+ @request = new XMLHttpRequest()
5
+ @request.addEventListener('load', @completed)
6
+
7
+
8
+ element: (el) ->
9
+ @element = ->
10
+ el
11
+
12
+ completed: (e) =>
13
+ if e.target.responseText.length > 1
14
+ eval(e.target.responseText)(@element())
15
+
16
+ send: (src, method = 'GET', data) =>
17
+ @request.open(method, src)
18
+ @request.setRequestHeader('X-Requested-With', "XMLHttpRequest")
19
+
20
+ @request.send(data)
21
+
22
+ @Form: (element) =>
23
+ xhr = new XHR(element)
24
+ data = new FormData(element)
25
+ param = document.querySelector('meta[name=csrf-param]').getAttribute('content')
26
+ token = document.querySelector('meta[name=csrf-token]').getAttribute('content')
27
+ data.append(param, token)
28
+ xhr.send(element.getAttribute('action'), element.getAttribute('method'), data)
29
+ xhr
30
+
31
+
32
+ Ethereal.XHR = XHR
@@ -0,0 +1,6 @@
1
+ (function(target) {
2
+ var e = new CustomEvent("<%= j "#{controller_name}:#{action_name}" %>", {bubbles: true})
3
+ <%= yield %>
4
+ target.dispatchEvent(e)
5
+ })
6
+
@@ -0,0 +1,11 @@
1
+ module Ethereal
2
+ class Railtie < Rails::Railtie
3
+ initializer 'ethereal.assets.paths', before: :add_view_paths do |app|
4
+ ethereal_assets_path = File.dirname(__FILE__) + '/app/assets/'
5
+ app.paths['vendor/assets'] << ethereal_assets_path
6
+ app.config.assets.precompile << ethereal_assets_path
7
+
8
+ app.paths['app/views'] << File.dirname(__FILE__) + '/app/views/'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module Ethereal
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,33 @@
1
+ // Generated by CoffeeScript 1.6.3
2
+ (function() {
3
+ var listen;
4
+
5
+ this.Shiny = {
6
+ attributeName: 'as'
7
+ };
8
+
9
+ this.Shiny.isDOM = function(el) {
10
+ return el instanceof HTMLDocument || el instanceof HTMLElement;
11
+ };
12
+
13
+ listen = function(e) {
14
+ if (e.type && e.type === 'DOMContentLoaded') {
15
+ document.removeEventListener('DOMContentLoaded', listen);
16
+ }
17
+ Shiny.Watcher(document, {
18
+ attributes: true,
19
+ subtree: true,
20
+ childList: true,
21
+ attributeFilter: [Shiny.attributeName],
22
+ characterData: true
23
+ });
24
+ return Shiny.Watcher().inspect(document.body);
25
+ };
26
+
27
+ if (document.readyState === 'complete') {
28
+ listen();
29
+ } else {
30
+ document.addEventListener('DOMContentLoaded', listen);
31
+ }
32
+
33
+ }).call(this);
@@ -0,0 +1,67 @@
1
+ // Generated by CoffeeScript 1.6.3
2
+ (function() {
3
+ var God,
4
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
5
+
6
+ God = (function() {
7
+ function God() {
8
+ this.modelExists = __bind(this.modelExists, this);
9
+ this.destroy = __bind(this.destroy, this);
10
+ this.create = __bind(this.create, this);
11
+ this.update = __bind(this.update, this);
12
+ }
13
+
14
+ God.prototype.update = function(el) {
15
+ var model;
16
+ model = el.getAttribute(Shiny.attributeName);
17
+ if (model != null) {
18
+ return this.create(el, model);
19
+ } else {
20
+ return this.destroy(el);
21
+ }
22
+ };
23
+
24
+ God.prototype.create = function(el) {
25
+ var model;
26
+ model = el.getAttribute(Shiny.attributeName);
27
+ if (this.modelExists(model)) {
28
+ el.instance = new Shiny.Models.klass[model](el);
29
+ el.instance.element = function() {
30
+ return el;
31
+ };
32
+ el.instance.on = function(event, target, callback) {
33
+ if (callback != null) {
34
+ el.instance.on.events.push([event, target, callback]);
35
+ } else {
36
+ callback = target;
37
+ target = el;
38
+ }
39
+ return target.addEventListener(event, callback);
40
+ };
41
+ el.instance.on.events = [];
42
+ if (el.instance.loaded != null) {
43
+ return el.instance.loaded();
44
+ }
45
+ } else {
46
+ throw "error: " + model + " is not registered. Add your model with Shiny.Models.add(" + model + ")";
47
+ }
48
+ };
49
+
50
+ God.prototype.destroy = function(el) {
51
+ var _ref;
52
+ return (_ref = el.instance.on.events) != null ? _ref.forEach(function(event) {
53
+ return event[1].removeEventListener(event[0], event[2]);
54
+ }) : void 0;
55
+ };
56
+
57
+ God.prototype.modelExists = function(name) {
58
+ return Shiny.Models.klass[name] != null;
59
+ };
60
+
61
+ return God;
62
+
63
+ })();
64
+
65
+ Shiny.God = new God;
66
+
67
+ }).call(this);
@@ -0,0 +1,21 @@
1
+ (function() {
2
+
3
+ function List() {
4
+
5
+ this.loaded = function() {
6
+
7
+ this.on('click', this.remove)
8
+ this.on('click', document, this.hello)
9
+ }
10
+
11
+ this.remove = function() {
12
+ this.remove()
13
+ }
14
+
15
+ this.hello = function() {
16
+ console.log('hello')
17
+ }
18
+ }
19
+
20
+ Shiny.Models.add(List, "List")
21
+ })()
@@ -0,0 +1,23 @@
1
+ // Generated by CoffeeScript 1.6.3
2
+ (function() {
3
+ var Models;
4
+
5
+ Models = (function() {
6
+ function Models() {}
7
+
8
+ Models.prototype.klass = {};
9
+
10
+ Models.prototype.add = function(kls, name) {
11
+ if (name == null) {
12
+ name = kls.name;
13
+ }
14
+ return this.klass[name] = kls;
15
+ };
16
+
17
+ return Models;
18
+
19
+ })();
20
+
21
+ Shiny.Models = new Models;
22
+
23
+ }).call(this);
@@ -0,0 +1,110 @@
1
+ // Generated by CoffeeScript 1.6.3
2
+ (function() {
3
+ var Watcher, instance,
4
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
5
+
6
+ instance = void 0;
7
+
8
+ Watcher = (function() {
9
+ function Watcher(target, config) {
10
+ if (config == null) {
11
+ config = {};
12
+ }
13
+ this.destroy = __bind(this.destroy, this);
14
+ this.add = __bind(this.add, this);
15
+ this.observed = __bind(this.observed, this);
16
+ this.observer = new MutationObserver(this.observed);
17
+ this.observer.observe(target, config);
18
+ }
19
+
20
+ Watcher.prototype.observed = function(mutations) {
21
+ var _this = this;
22
+ return mutations.forEach(function(mutation) {
23
+ if (mutation.type === 'attributes') {
24
+ return Shiny.God.update(target);
25
+ } else {
26
+ _this.add(mutation.addedNodes);
27
+ return _this.destroy(mutation.removedNodes);
28
+ }
29
+ });
30
+ };
31
+
32
+ Watcher.prototype.add = function(nodes) {
33
+ var child, node, _i, _len, _results;
34
+ _results = [];
35
+ for (_i = 0, _len = nodes.length; _i < _len; _i++) {
36
+ node = nodes[_i];
37
+ if (!Shiny.isDOM(node)) {
38
+ continue;
39
+ }
40
+ if (node.hasAttribute(Shiny.attributeName)) {
41
+ Shiny.God.create(node, node.getAttribute(Shiny.attributeName));
42
+ }
43
+ _results.push((function() {
44
+ var _j, _len1, _ref, _results1;
45
+ _ref = node.querySelectorAll("[" + Shiny.attributeName + "]");
46
+ _results1 = [];
47
+ for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
48
+ child = _ref[_j];
49
+ _results1.push(Shiny.God.create(child, child.getAttribute(Shiny.attributeName)));
50
+ }
51
+ return _results1;
52
+ })());
53
+ }
54
+ return _results;
55
+ };
56
+
57
+ Watcher.prototype.destroy = function(nodes) {
58
+ var child, node, _i, _len, _results;
59
+ _results = [];
60
+ for (_i = 0, _len = nodes.length; _i < _len; _i++) {
61
+ node = nodes[_i];
62
+ if (!Shiny.isDOM(node)) {
63
+ continue;
64
+ }
65
+ if (node.hasAttribute(Shiny.attributeName)) {
66
+ Shiny.God.destroy(node);
67
+ }
68
+ _results.push((function() {
69
+ var _j, _len1, _ref, _results1;
70
+ _ref = node.querySelectorAll("[" + Shiny.attributeName + "]");
71
+ _results1 = [];
72
+ for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
73
+ child = _ref[_j];
74
+ _results1.push(Shiny.God.destroy(child));
75
+ }
76
+ return _results1;
77
+ })());
78
+ }
79
+ return _results;
80
+ };
81
+
82
+ Watcher.prototype.inspect = function(node) {
83
+ var el, found, _i, _len, _results;
84
+ if (Shiny.isDOM(node)) {
85
+ found = node.querySelectorAll("[" + Shiny.attributeName + "]");
86
+ _results = [];
87
+ for (_i = 0, _len = found.length; _i < _len; _i++) {
88
+ el = found[_i];
89
+ _results.push(Shiny.God.create(el));
90
+ }
91
+ return _results;
92
+ }
93
+ };
94
+
95
+ return Watcher;
96
+
97
+ })();
98
+
99
+ Shiny.Watcher = function() {
100
+ var i, target;
101
+ if (instance == null) {
102
+ i = 0;
103
+ target = null;
104
+ target = Shiny.isDOM(arguments[i]) ? arguments[i++] : document;
105
+ instance = new Watcher(target, arguments[i]);
106
+ }
107
+ return instance;
108
+ };
109
+
110
+ }).call(this);
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE>
2
+ <html>
3
+ <head>
4
+ <script src="js/base.js"></script>
5
+ <script src="js/god.js"></script>
6
+ <script src="js/models.js"></script>
7
+ <script src="js/watcher.js"></script>
8
+
9
+ <script src="js/list.js"></script>
10
+ </head>
11
+ <body>
12
+
13
+ <ol as="List">
14
+ <li>Hello</li>
15
+ </ol>
16
+
17
+ </body>
18
+ </html>
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ethereal
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Pier-Olivier Thibault
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description:
42
+ email:
43
+ - pothibo@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - ethereal.gemspec
54
+ - lib/ethereal.rb
55
+ - lib/ethereal/app/assets/javascripts/ethereal.js.coffee
56
+ - lib/ethereal/app/assets/javascripts/ethereal/base.js.coffee
57
+ - lib/ethereal/app/assets/javascripts/ethereal/ext.js.coffee
58
+ - lib/ethereal/app/assets/javascripts/ethereal/god.js.coffee
59
+ - lib/ethereal/app/assets/javascripts/ethereal/model.js.coffee
60
+ - lib/ethereal/app/assets/javascripts/ethereal/watcher.js.coffee
61
+ - lib/ethereal/app/assets/javascripts/ethereal/xhr.js.coffee
62
+ - lib/ethereal/app/views/layouts/application.js.erb
63
+ - lib/ethereal/railtie.rb
64
+ - lib/ethereal/version.rb
65
+ - test/js/base.js
66
+ - test/js/god.js
67
+ - test/js/list.js
68
+ - test/js/models.js
69
+ - test/js/watcher.js
70
+ - test/test.html
71
+ homepage:
72
+ licenses:
73
+ - MIT
74
+ metadata: {}
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubyforge_project:
91
+ rubygems_version: 2.2.2
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: Event based JavaScript framework tailored for Ruby on rails.
95
+ test_files:
96
+ - test/js/base.js
97
+ - test/js/god.js
98
+ - test/js/list.js
99
+ - test/js/models.js
100
+ - test/js/watcher.js
101
+ - test/test.html