fron 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +35 -0
- data/Rakefile +18 -0
- data/docs/configuration.md +8 -8
- data/lib/fron/version.rb +1 -1
- data/opal/fron/core.rb +1 -1
- data/opal/fron/core/adapters/{local-storage.rb → local.rb} +7 -6
- data/opal/fron/core/application.rb +13 -11
- data/opal/fron/core/configuration.rb +3 -4
- data/opal/fron/core/controller.rb +2 -2
- data/opal/fron/core/eventable.rb +5 -2
- data/opal/fron/core/logger.rb +7 -0
- data/opal/fron/core/model.rb +10 -8
- data/opal/fron/core/router.rb +1 -1
- data/opal/fron/dom.rb +1 -0
- data/opal/fron/dom/document.rb +4 -0
- data/opal/fron/dom/element.rb +22 -6
- data/opal/fron/dom/event.rb +71 -68
- data/opal/fron/dom/fragment.rb +1 -3
- data/opal/fron/dom/modules/classlist.rb +2 -2
- data/opal/fron/dom/modules/dimensions.rb +7 -8
- data/opal/fron/dom/modules/events.rb +57 -12
- data/opal/fron/dom/node.rb +45 -11
- data/opal/fron/dom/nodelist.rb +14 -0
- data/opal/fron/dom/style.rb +17 -15
- data/opal/fron/dom/text.rb +2 -4
- data/opal/fron/dom/window.rb +2 -3
- data/opal/fron/request/request.rb +17 -14
- data/opal/fron/storage/local-storage.rb +29 -13
- data/spec/core-ext/hash_spec.rb +18 -0
- data/spec/core/adapter/local_spec.rb +65 -0
- data/spec/core/adapter/rails_spec.rb +72 -0
- data/spec/core/application_spec.rb +35 -0
- data/spec/core/component_spec.rb +107 -0
- data/spec/core/configuration_spec.rb +20 -0
- data/spec/core/controlller_spec.rb +68 -0
- data/spec/core/eventable_spec.rb +74 -0
- data/spec/core/logger_spec.rb +28 -0
- data/spec/core/model_spec.rb +125 -0
- data/spec/core/router_spec.rb +127 -0
- data/spec/dom/document_spec.rb +41 -0
- data/spec/dom/element_spec.rb +164 -0
- data/spec/dom/event_spec.rb +121 -0
- data/spec/dom/fragment_spec.rb +13 -0
- data/spec/dom/modules/classlist_spec.rb +72 -0
- data/spec/dom/modules/dimensions_spec.rb +55 -0
- data/spec/dom/modules/events_spec.rb +73 -0
- data/spec/dom/node_spec.rb +189 -0
- data/spec/dom/nodelist_spec.rb +12 -0
- data/spec/dom/style_spec.rb +31 -0
- data/spec/dom/text_spec.rb +12 -0
- data/spec/dom/window_spec.rb +30 -0
- data/spec/request/request_spec.rb +71 -0
- data/spec/request/response_spec.rb +46 -0
- data/spec/storage/local-storage_spec.rb +58 -0
- metadata +36 -4
data/opal/fron/dom/fragment.rb
CHANGED
@@ -4,34 +4,33 @@ module DOM
|
|
4
4
|
module Dimensions
|
5
5
|
|
6
6
|
def top
|
7
|
-
clientRect
|
7
|
+
`#{clientRect}.top` + Window.scrollY
|
8
8
|
end
|
9
9
|
|
10
10
|
def left
|
11
|
-
clientRect
|
11
|
+
`#{clientRect}.left` + Window.scrollX
|
12
12
|
end
|
13
13
|
|
14
14
|
def right
|
15
|
-
clientRect
|
15
|
+
`#{clientRect}.right` + Window.scrollX
|
16
16
|
end
|
17
17
|
|
18
18
|
def bottom
|
19
|
-
clientRect
|
19
|
+
`#{clientRect}.bottom` + Window.scrollY
|
20
20
|
end
|
21
21
|
|
22
22
|
def width
|
23
|
-
clientRect
|
23
|
+
`#{clientRect}.width`
|
24
24
|
end
|
25
25
|
|
26
26
|
def height
|
27
|
-
|
28
|
-
clientRect[:height]
|
27
|
+
`#{clientRect}.height`
|
29
28
|
end
|
30
29
|
|
31
30
|
private
|
32
31
|
|
33
32
|
def clientRect
|
34
|
-
|
33
|
+
`#{@el}.getBoundingClientRect()`
|
35
34
|
end
|
36
35
|
end
|
37
36
|
end
|
@@ -1,19 +1,64 @@
|
|
1
1
|
module DOM
|
2
2
|
module Events
|
3
|
-
def
|
4
|
-
`#{@el}.addEventListener(#{event},function(e){#{ listener.call Event.new(`e`)}})`
|
5
|
-
self
|
6
|
-
end
|
7
|
-
|
8
|
-
def delegate(event,selector, &listener)
|
3
|
+
def trigger(type, data = {})
|
9
4
|
%x{
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
}
|
14
|
-
|
5
|
+
event = document.createEvent("HTMLEvents");
|
6
|
+
event.initEvent(#{type}, true, true);
|
7
|
+
for (key in #{data}) {
|
8
|
+
value = #{data}[key];
|
9
|
+
event[key] = value;
|
10
|
+
}
|
11
|
+
#{@el}.dispatchEvent(event);
|
15
12
|
}
|
16
|
-
|
13
|
+
end
|
14
|
+
|
15
|
+
def on(type, &listener)
|
16
|
+
klass = if defined? self.class::EVENT_TARGET_CLASS
|
17
|
+
self.class::EVENT_TARGET_CLASS
|
18
|
+
else
|
19
|
+
Hash
|
20
|
+
end
|
21
|
+
method = `function(e){#{ listener.call Event.new(`e`,klass)}}`
|
22
|
+
|
23
|
+
@listeners ||= {}
|
24
|
+
@listeners[type] ||= []
|
25
|
+
@listeners[type] << method
|
26
|
+
|
27
|
+
`#{@el}.addEventListener(#{type},#{method})`
|
28
|
+
method
|
29
|
+
end
|
30
|
+
|
31
|
+
def off(type = nil, method = nil)
|
32
|
+
return unless @listeners
|
33
|
+
|
34
|
+
if type == nil
|
35
|
+
@listeners.keys.each do |type|
|
36
|
+
removeListeners type
|
37
|
+
end
|
38
|
+
elsif method == nil
|
39
|
+
removeListeners type
|
40
|
+
else
|
41
|
+
return unless @listeners[type].index(method)
|
42
|
+
@listeners[type].delete method
|
43
|
+
`#{@el}.removeEventListener(#{type},#{method})`
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def delegate(type,selector, &listener)
|
48
|
+
on type do |event|
|
49
|
+
if event.target.matches selector
|
50
|
+
listener.call event
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def removeListeners(type)
|
58
|
+
@listeners[type].each do |method|
|
59
|
+
@listeners[type].delete method
|
60
|
+
`#{@el}.removeEventListener(#{type},#{method})`
|
61
|
+
end
|
17
62
|
end
|
18
63
|
end
|
19
64
|
end
|
data/opal/fron/dom/node.rb
CHANGED
@@ -1,6 +1,17 @@
|
|
1
|
+
require 'native'
|
2
|
+
|
1
3
|
module DOM
|
2
|
-
|
4
|
+
class NODE
|
5
|
+
EVENT_TARGET_CLASS = self
|
6
|
+
|
3
7
|
include Events
|
8
|
+
include Comparable
|
9
|
+
|
10
|
+
def initialize(node = nil)
|
11
|
+
raise "A node must be provided!" unless node
|
12
|
+
raise "Not a HTML Node given!" unless `#{node} instanceof Node`
|
13
|
+
@el = node
|
14
|
+
end
|
4
15
|
|
5
16
|
# Cloning
|
6
17
|
# ---------------------------------------
|
@@ -15,11 +26,13 @@ module DOM
|
|
15
26
|
# Hierarchy
|
16
27
|
# ---------------------------------------
|
17
28
|
def parentNode
|
18
|
-
|
29
|
+
el = `#{@el}.parentNode || false`
|
30
|
+
el ? DOM::NODE.new(el) : nil
|
19
31
|
end
|
20
32
|
|
21
33
|
def parent
|
22
|
-
|
34
|
+
el = `#{@el}.parentElement || false`
|
35
|
+
el ? DOM::NODE.new(el) : nil
|
23
36
|
end
|
24
37
|
|
25
38
|
def empty?
|
@@ -27,13 +40,13 @@ module DOM
|
|
27
40
|
end
|
28
41
|
|
29
42
|
def children
|
30
|
-
`Array.prototype.slice.call(#{@el}.childNodes)`
|
43
|
+
NodeList.new `Array.prototype.slice.call(#{@el}.childNodes)`
|
31
44
|
end
|
32
45
|
|
33
46
|
# Remove
|
34
47
|
# ---------------------------------------
|
35
48
|
def remove(el)
|
36
|
-
`#{@el}.removeChild(#{
|
49
|
+
`#{@el}.removeChild(#{NODE.getElement el})`
|
37
50
|
end
|
38
51
|
|
39
52
|
def remove!
|
@@ -44,12 +57,11 @@ module DOM
|
|
44
57
|
# Hierarchy Manipulation
|
45
58
|
# ---------------------------------------
|
46
59
|
def << el
|
47
|
-
`#{@el}.appendChild(#{
|
48
|
-
self
|
60
|
+
`#{@el}.appendChild(#{NODE.getElement el})`
|
49
61
|
end
|
50
62
|
|
51
63
|
def >> el
|
52
|
-
`#{
|
64
|
+
`#{NODE.getElement el}.appendChild(#{@el})`
|
53
65
|
end
|
54
66
|
|
55
67
|
def insertBefore(what,where)
|
@@ -66,14 +78,36 @@ module DOM
|
|
66
78
|
`#{@el}.textContent = #{text}`
|
67
79
|
end
|
68
80
|
|
69
|
-
def normalize
|
81
|
+
def normalize!
|
70
82
|
`#{@el}.normalize()`
|
71
83
|
end
|
72
84
|
|
85
|
+
# Comparabe methods
|
86
|
+
# ---------------------------------------
|
87
|
+
def ==(obj)
|
88
|
+
`#{NODE.getElement(obj)} === #{@el}`
|
89
|
+
end
|
90
|
+
|
91
|
+
def <=>(obj)
|
92
|
+
if obj == self then return 0 end
|
93
|
+
if obj.parent != parent then raise 'Nodes not Comparable!' end
|
94
|
+
obj.index <=> index
|
95
|
+
end
|
96
|
+
|
97
|
+
def index
|
98
|
+
parent.children.index self
|
99
|
+
end
|
100
|
+
|
73
101
|
private
|
74
102
|
|
75
|
-
def
|
76
|
-
|
103
|
+
def self.getElement(obj)
|
104
|
+
if `#{obj} instanceof Node`
|
105
|
+
obj
|
106
|
+
elsif obj.is_a?(NODE)
|
107
|
+
obj.instance_variable_get('@el')
|
108
|
+
else
|
109
|
+
nil
|
110
|
+
end
|
77
111
|
end
|
78
112
|
end
|
79
113
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module DOM
|
4
|
+
class NodeList
|
5
|
+
include Enumerable
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def_delegators :@nodes, :length, :include?, :each, :index, :[]
|
9
|
+
|
10
|
+
def initialize(nodes)
|
11
|
+
@nodes = nodes.map { |node| DOM::NODE.new node }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/opal/fron/dom/style.rb
CHANGED
@@ -1,21 +1,23 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module DOM
|
2
|
+
class Style
|
3
|
+
def initialize(el)
|
4
|
+
@el = el
|
5
|
+
end
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
def method_missing(name,value)
|
8
|
+
if name =~ /\=$/
|
9
|
+
self[name[0..-2]] = value
|
10
|
+
else
|
11
|
+
self[name]
|
12
|
+
end
|
11
13
|
end
|
12
|
-
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
def [](prop)
|
16
|
+
`#{@el}.style[#{prop}]`
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
19
|
+
def []=(prop,value)
|
20
|
+
`#{@el}.style[#{prop}] = #{value}`
|
21
|
+
end
|
20
22
|
end
|
21
23
|
end
|
data/opal/fron/dom/text.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
module DOM
|
2
|
-
class Text
|
3
|
-
include Node
|
4
|
-
|
2
|
+
class Text < NODE
|
5
3
|
def initialize(data)
|
6
|
-
|
4
|
+
@el = `typeof #{data} === 'string'` ? `document.createTextNode(#{data})` : data
|
7
5
|
end
|
8
6
|
end
|
9
7
|
end
|
data/opal/fron/dom/window.rb
CHANGED
@@ -11,26 +11,16 @@ module Fron
|
|
11
11
|
self
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
if ready_state == 4
|
16
|
-
response = Response.new `#{@request}.status`, `#{@request}.response`, `#{@request}.getAllResponseHeaders()`
|
17
|
-
@callback.call response
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def ready_state
|
22
|
-
`#{@request}.readyState`
|
23
|
-
end
|
24
|
-
|
25
|
-
def request( method = 'GET',data = nil, &callback)
|
14
|
+
def request( method = 'GET', data = nil, &callback)
|
26
15
|
if ready_state == 0 or ready_state == 4
|
16
|
+
@callback = callback
|
27
17
|
if method.upcase == "GET" && data
|
28
18
|
`#{@request}.open(#{method},#{@url+"?"+data.to_query_string})`
|
19
|
+
`#{@request}.send()`
|
29
20
|
else
|
30
21
|
`#{@request}.open(#{method},#{@url})`
|
22
|
+
`#{@request}.send(#{data.to_form_data if data})`
|
31
23
|
end
|
32
|
-
@callback = callback
|
33
|
-
`#{@request}.send(#{data.to_form_data if data})`
|
34
24
|
else
|
35
25
|
raise "The request is already running!"
|
36
26
|
end
|
@@ -47,5 +37,18 @@ module Fron
|
|
47
37
|
def put(data, &callback)
|
48
38
|
request 'PUT', data, &callback
|
49
39
|
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def ready_state
|
44
|
+
`#{@request}.readyState`
|
45
|
+
end
|
46
|
+
|
47
|
+
def handle_state_change
|
48
|
+
if ready_state == 4
|
49
|
+
response = Response.new `#{@request}.status`, `#{@request}.response`, `#{@request}.getAllResponseHeaders()`
|
50
|
+
@callback.call response if @callback
|
51
|
+
end
|
52
|
+
end
|
50
53
|
end
|
51
54
|
end
|
@@ -1,18 +1,34 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
module Fron
|
2
|
+
module Storage
|
3
|
+
module LocalStorage
|
4
|
+
def self.get(key)
|
5
|
+
value = `window.localStorage.getItem(#{key}) || false`
|
6
|
+
value ? JSON.parse(value) : nil
|
7
|
+
end
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
9
|
+
def self.set(key, data)
|
10
|
+
`window.localStorage.setItem(#{key},#{data.to_json})`
|
11
|
+
end
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
def self.remove(key)
|
14
|
+
`window.localStorage.removeItem(#{key})`
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.keys
|
18
|
+
%x{
|
19
|
+
ret = []
|
20
|
+
for (var key in localStorage){ ret.push(key) }
|
21
|
+
return ret
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.all
|
26
|
+
self.keys.map{ |key| self.get key }
|
27
|
+
end
|
14
28
|
|
15
|
-
|
16
|
-
|
29
|
+
def self.clear
|
30
|
+
`window.localStorage.clear()`
|
31
|
+
end
|
32
|
+
end
|
17
33
|
end
|
18
34
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'fron/core-ext/hash'
|
2
|
+
|
3
|
+
describe Hash do
|
4
|
+
|
5
|
+
subject { { a: 'test', b: 'user' } }
|
6
|
+
|
7
|
+
describe "#to_query_string" do
|
8
|
+
it 'should return the hash in query string format' do
|
9
|
+
subject.to_query_string.should eq 'a=test&b=user'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#to_form_data' do
|
14
|
+
it 'should return the hash in FormData format' do
|
15
|
+
`#{subject.to_form_data} instanceof FormData`.should be true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'fron/storage'
|
2
|
+
require 'fron/core'
|
3
|
+
|
4
|
+
describe Fron::Adapters::LocalAdapter do
|
5
|
+
|
6
|
+
subject { described_class.new({fields: [:name]}) }
|
7
|
+
let(:proc) { Proc.new {} }
|
8
|
+
|
9
|
+
describe "#all" do
|
10
|
+
it "should call localStorage#all" do
|
11
|
+
Fron::Storage::LocalStorage.should receive(:all).once
|
12
|
+
subject.all &proc
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should run the block" do
|
16
|
+
proc.should receive(:call)
|
17
|
+
subject.all &proc
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#get" do
|
22
|
+
it "should call localStorage#get" do
|
23
|
+
Fron::Storage::LocalStorage.should receive(:get).once
|
24
|
+
subject.get 0, &proc
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should run the block" do
|
28
|
+
proc.should receive(:call)
|
29
|
+
subject.get 0, &proc
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#set" do
|
34
|
+
it "should call localStorage#set" do
|
35
|
+
Fron::Storage::LocalStorage.should receive(:set).once
|
36
|
+
subject.set 0, {name: 'test'}, &proc
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should run the block with nil if there are no errors" do
|
40
|
+
proc.should receive(:call).with nil
|
41
|
+
subject.set 0, {name: 'test'}, &proc
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should run the block with erros if ther are any" do
|
45
|
+
proc.should receive(:call).with({name: ["can't be blank"]})
|
46
|
+
subject.set 0, {name: ''}, &proc
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should add id if there isn't any" do
|
50
|
+
result = subject.set nil, {name: ''}, &proc
|
51
|
+
result[:id].should_not be nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#validate" do
|
56
|
+
it "should return errors for undefined fields" do
|
57
|
+
subject.validate.should eq({name: ["can't be blank"]})
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should return errors for empty fields" do
|
61
|
+
subject.validate({name: ''}).should eq({name: ["can't be blank"]})
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|