fron 0.1.4 → 0.2.0rc1
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/.gitignore +3 -0
- data/.reek +11 -0
- data/.rubocop.yml +54 -0
- data/.travis.yml +11 -0
- data/.yardopts +4 -0
- data/Changelog.md +7 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +106 -15
- data/Rakefile +19 -15
- data/Readme.md +23 -0
- data/fron.gemspec +2 -2
- data/lib/fron/version.rb +2 -1
- data/opal/fron.rb +5 -5
- data/opal/fron/core.rb +3 -10
- data/opal/fron/core/behaviors/components.rb +42 -0
- data/opal/fron/core/behaviors/events.rb +27 -0
- data/opal/fron/core/behaviors/routes.rb +59 -0
- data/opal/fron/core/component.rb +64 -90
- data/opal/fron/core/eventable.rb +18 -0
- data/opal/fron/core/logger.rb +10 -1
- data/opal/fron/core_ext.rb +9 -0
- data/opal/fron/core_ext/array.rb +12 -0
- data/opal/fron/core_ext/date.rb +57 -0
- data/opal/fron/core_ext/hash.rb +52 -0
- data/opal/fron/core_ext/kernel.rb +57 -0
- data/opal/fron/core_ext/nil.rb +7 -0
- data/opal/fron/core_ext/numeric.rb +19 -0
- data/opal/fron/core_ext/object.rb +11 -0
- data/opal/fron/core_ext/proc.rb +19 -0
- data/opal/fron/{core-ext → core_ext}/string.rb +4 -0
- data/opal/fron/dom.rb +15 -13
- data/opal/fron/dom/document.rb +22 -6
- data/opal/fron/dom/element.rb +105 -67
- data/opal/fron/dom/event.rb +110 -40
- data/opal/fron/dom/{file-reader.rb → file_reader.rb} +6 -1
- data/opal/fron/dom/fragment.rb +2 -0
- data/opal/fron/dom/modules/attributes.rb +43 -0
- data/opal/fron/dom/modules/classlist.rb +26 -13
- data/opal/fron/dom/modules/dimensions.rb +79 -9
- data/opal/fron/dom/modules/element_accessor.rb +35 -0
- data/opal/fron/dom/modules/events.rb +67 -20
- data/opal/fron/dom/node.rb +98 -39
- data/opal/fron/dom/nodelist.rb +9 -2
- data/opal/fron/dom/style.rb +23 -2
- data/opal/fron/dom/text.rb +4 -0
- data/opal/fron/dom/window.rb +31 -2
- data/opal/fron/event_mock.rb +54 -0
- data/opal/fron/js/syntetic_event.js +16 -0
- data/opal/fron/request.rb +2 -2
- data/opal/fron/request/request.rb +77 -14
- data/opal/fron/request/response.rb +33 -6
- data/opal/fron/storage.rb +1 -1
- data/opal/fron/storage/local_storage.rb +54 -0
- data/opal/fron/utils/drag.rb +135 -0
- data/opal/fron/utils/keyboard.rb +70 -0
- data/opal/fron/utils/point.rb +78 -0
- data/opal/fron/utils/render_proc.rb +27 -0
- data/spec/core-ext/array_spec.rb +15 -0
- data/spec/core-ext/date_spec.rb +54 -0
- data/spec/core-ext/hash_spec.rb +18 -2
- data/spec/core-ext/kernel_spec.rb +57 -0
- data/spec/core-ext/nil_spec.rb +9 -0
- data/spec/core-ext/numeric_spec.rb +25 -0
- data/spec/core-ext/proc_spec.rb +15 -0
- data/spec/core-ext/string_spec.rb +11 -0
- data/spec/core/behaviors/events_spec.rb +25 -0
- data/spec/core/behaviors/routes_spec.rb +59 -0
- data/spec/core/component_inheritance_spec.rb +26 -16
- data/spec/core/component_spec.rb +25 -29
- data/spec/core/eventable_spec.rb +19 -19
- data/spec/core/logger_spec.rb +5 -6
- data/spec/dom/document_spec.rb +4 -5
- data/spec/dom/element_spec.rb +106 -15
- data/spec/dom/event_spec.rb +101 -61
- data/spec/dom/file_reader_spec.rb +11 -0
- data/spec/dom/fragment_spec.rb +3 -4
- data/spec/dom/instance_retaining_spec.rb +58 -0
- data/spec/dom/modules/classlist_spec.rb +18 -19
- data/spec/dom/modules/dimensions_spec.rb +87 -22
- data/spec/dom/modules/events_spec.rb +22 -8
- data/spec/dom/node_spec.rb +25 -17
- data/spec/dom/nodelist_spec.rb +2 -3
- data/spec/dom/style_spec.rb +6 -5
- data/spec/dom/text_spec.rb +4 -3
- data/spec/dom/window_spec.rb +24 -9
- data/spec/js/mocks.js +14 -0
- data/spec/request/request_spec.rb +34 -15
- data/spec/request/response_spec.rb +9 -10
- data/spec/spec_helper.rb +11 -0
- data/spec/storage/{local-storage_spec.rb → local_storage_spec.rb} +6 -7
- data/spec/utils/drag_spec.rb +136 -0
- data/spec/utils/keyboard_spec.rb +75 -0
- data/spec/utils/point_spec.rb +55 -0
- data/spec/utils/render_proc_spec.rb +18 -0
- metadata +58 -36
- data/docs/application.md +0 -7
- data/docs/configuration.md +0 -29
- data/docs/controllers.md +0 -35
- data/docs/routing.md +0 -63
- data/opal/fron/core-ext.rb +0 -5
- data/opal/fron/core-ext/hash.rb +0 -31
- data/opal/fron/core-ext/kernel.rb +0 -10
- data/opal/fron/core-ext/numeric.rb +0 -9
- data/opal/fron/core-ext/proc.rb +0 -9
- data/opal/fron/core/adapters/local.rb +0 -43
- data/opal/fron/core/adapters/rails.rb +0 -65
- data/opal/fron/core/application.rb +0 -42
- data/opal/fron/core/configuration.rb +0 -29
- data/opal/fron/core/controller.rb +0 -41
- data/opal/fron/core/model.rb +0 -90
- data/opal/fron/core/router.rb +0 -86
- data/opal/fron/storage/local-storage.rb +0 -34
- data/spec/core/adapter/local_spec.rb +0 -65
- data/spec/core/adapter/rails_spec.rb +0 -77
- data/spec/core/application_spec.rb +0 -35
- data/spec/core/configuration_spec.rb +0 -20
- data/spec/core/controlller_spec.rb +0 -68
- data/spec/core/model_spec.rb +0 -125
- data/spec/core/router_spec.rb +0 -124
data/opal/fron/dom/nodelist.rb
CHANGED
@@ -1,14 +1,21 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
|
3
3
|
module DOM
|
4
|
+
# Node List
|
4
5
|
class NodeList
|
5
6
|
include Enumerable
|
6
7
|
extend Forwardable
|
7
8
|
|
8
|
-
|
9
|
+
# @return [Array] The nodes
|
10
|
+
attr_reader :nodes
|
9
11
|
|
12
|
+
def_delegators :@nodes, :length, :include?, :each, :index, :[], :to_a, :last, :empty?
|
13
|
+
|
14
|
+
# Initializes the node list
|
15
|
+
#
|
16
|
+
# @param nodes [Array] Array of nodes
|
10
17
|
def initialize(nodes)
|
11
|
-
@nodes = nodes.map { |node| DOM::
|
18
|
+
@nodes = nodes.map { |node| DOM::Element.from_node node }
|
12
19
|
end
|
13
20
|
end
|
14
21
|
end
|
data/opal/fron/dom/style.rb
CHANGED
@@ -1,10 +1,22 @@
|
|
1
|
+
# rubocop:disable MethodName
|
2
|
+
|
1
3
|
module DOM
|
4
|
+
# Style
|
2
5
|
class Style
|
6
|
+
# Initializes the style
|
7
|
+
#
|
8
|
+
# @param el [DOM::Element] The element
|
3
9
|
def initialize(el)
|
4
10
|
@el = el
|
5
11
|
end
|
6
12
|
|
7
|
-
|
13
|
+
# Sets or gets a given CSS property
|
14
|
+
#
|
15
|
+
# @param name [String] The property
|
16
|
+
# @param value [String] The value
|
17
|
+
#
|
18
|
+
# @return [String] The value of the property
|
19
|
+
def method_missing(name, value)
|
8
20
|
if name =~ /\=$/
|
9
21
|
self[name[0..-2]] = value
|
10
22
|
else
|
@@ -12,11 +24,20 @@ module DOM
|
|
12
24
|
end
|
13
25
|
end
|
14
26
|
|
27
|
+
# Gets a CSS property value
|
28
|
+
#
|
29
|
+
# @param prop [String] The property
|
30
|
+
#
|
31
|
+
# @return [String] The value of the property
|
15
32
|
def [](prop)
|
16
33
|
`#{@el}.style[#{prop}]`
|
17
34
|
end
|
18
35
|
|
19
|
-
|
36
|
+
# Sets the given CSS property with the given value
|
37
|
+
#
|
38
|
+
# @param prop [String] The property
|
39
|
+
# @param value [String] The value
|
40
|
+
def []=(prop, value)
|
20
41
|
`#{@el}.style[#{prop}] = #{value}`
|
21
42
|
end
|
22
43
|
end
|
data/opal/fron/dom/text.rb
CHANGED
data/opal/fron/dom/window.rb
CHANGED
@@ -1,21 +1,50 @@
|
|
1
1
|
module DOM
|
2
|
+
# Window
|
2
3
|
module Window
|
3
4
|
extend Events
|
4
5
|
@el = `window`
|
5
6
|
|
7
|
+
# Sets the url via pushState
|
8
|
+
#
|
9
|
+
# @param url [String] The url
|
10
|
+
def self.state=(url)
|
11
|
+
return if url == state
|
12
|
+
`window.history.pushState({},'',#{url})`
|
13
|
+
timeout { trigger 'popstate' }
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the locations pathname as state
|
17
|
+
#
|
18
|
+
# @return [String] The pathname
|
19
|
+
def self.state
|
20
|
+
`window.location.pathname`
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns the locations hash
|
24
|
+
#
|
25
|
+
# @return [String] The hash
|
6
26
|
def self.hash
|
7
27
|
`window.location.hash.slice(1)`
|
8
28
|
end
|
9
29
|
|
30
|
+
# Sets the locations hash with the given value
|
31
|
+
#
|
32
|
+
# @param value [String] The value
|
10
33
|
def self.hash=(value)
|
11
34
|
`window.location.hash = #{value}`
|
12
35
|
end
|
13
36
|
|
14
|
-
|
37
|
+
# Returns the Y scroll position of the window
|
38
|
+
#
|
39
|
+
# @return [Numeric] The position
|
40
|
+
def self.scroll_y
|
15
41
|
`window.scrollY || document.documentElement.scrollTop`
|
16
42
|
end
|
17
43
|
|
18
|
-
|
44
|
+
# Returns the X scroll position of the window
|
45
|
+
#
|
46
|
+
# @return [Numeric] The position
|
47
|
+
def self.scroll_x
|
19
48
|
`window.scrollX || document.documentElement.scrollTop`
|
20
49
|
end
|
21
50
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'fron/js/syntetic_event'
|
2
|
+
|
3
|
+
# Event Mock module for mocking events
|
4
|
+
module EventMock
|
5
|
+
class << self
|
6
|
+
# Sets / gets the whether or not
|
7
|
+
# log event triggers
|
8
|
+
#
|
9
|
+
# @param value [Boolean] The verbosity
|
10
|
+
# @return [Boolean] The verbosity
|
11
|
+
attr_accessor :verbose
|
12
|
+
|
13
|
+
# Triggers a syntetic event.
|
14
|
+
#
|
15
|
+
# @param element [DOM::Element] The element
|
16
|
+
# @param type [String] Event type
|
17
|
+
# @param data [Hash] The data for the event
|
18
|
+
def trigger_event(element, type, data = {})
|
19
|
+
event = `new SynteticEvent(#{element.instance_variable_get('@el')}, #{data.to_n})`
|
20
|
+
dispath_event element, event, type
|
21
|
+
end
|
22
|
+
|
23
|
+
# Dispatches a sytetic event
|
24
|
+
#
|
25
|
+
# @param element [DOM::Element] The element
|
26
|
+
# @param event [SynteticEvent] The event
|
27
|
+
# @param type [String] Event type
|
28
|
+
#
|
29
|
+
# @return [type] [description]
|
30
|
+
def dispath_event(element, event, type)
|
31
|
+
if `#{element.listeners} || Opal.nil`
|
32
|
+
element.listeners[type].to_a.each do |method|
|
33
|
+
break unless `#{event}.immediatePropagate`
|
34
|
+
method.call event
|
35
|
+
end
|
36
|
+
end
|
37
|
+
return unless `#{event}.propagate`
|
38
|
+
return unless element.parent
|
39
|
+
dispath_event element.parent, event, type
|
40
|
+
end
|
41
|
+
|
42
|
+
# Mocks triggers on DOM::Events
|
43
|
+
def mock_events
|
44
|
+
DOM::Events.alias_method :old_trigger, :trigger
|
45
|
+
DOM::Events.define_method :trigger do |type, data = {}|
|
46
|
+
puts "Triggered syntetic event \"#{type}\" for \"#{path}\"" if EventMock.verbose
|
47
|
+
EventMock.trigger_event self, type, data
|
48
|
+
end
|
49
|
+
yield
|
50
|
+
ensure
|
51
|
+
DOM::Events.alias_method :trigger, :old_trigger
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
SynteticEvent = function(target, data){
|
2
|
+
this.target = target
|
3
|
+
this.defaultPrevented = false
|
4
|
+
this.immediatePropagate = true
|
5
|
+
this.propagate = true
|
6
|
+
this.data = data
|
7
|
+
}
|
8
|
+
SynteticEvent.prototype.stopImmediatePropagation = function(){
|
9
|
+
this.immediatePropagate = false
|
10
|
+
}
|
11
|
+
SynteticEvent.prototype.stopPropagation = function(){
|
12
|
+
this.propagate = false
|
13
|
+
}
|
14
|
+
SynteticEvent.prototype.preventDefault = function(){
|
15
|
+
this.defaultPrevented = true
|
16
|
+
}
|
data/opal/fron/request.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
1
|
+
require 'fron/request/response'
|
2
|
+
require 'fron/request/request'
|
@@ -1,9 +1,29 @@
|
|
1
1
|
require 'json'
|
2
2
|
|
3
3
|
module Fron
|
4
|
+
# Request
|
4
5
|
class Request
|
5
|
-
|
6
|
+
extend Eventable
|
7
|
+
extend Forwardable
|
6
8
|
|
9
|
+
# Sets / gets the URL
|
10
|
+
#
|
11
|
+
# @param value [String] The URL
|
12
|
+
# @return [String] The URL
|
13
|
+
attr_accessor :url
|
14
|
+
|
15
|
+
# Sets / gets the headers for the request
|
16
|
+
#
|
17
|
+
# @param value [Hash] The headers
|
18
|
+
# @return [Hash] The headers
|
19
|
+
attr_accessor :headers
|
20
|
+
|
21
|
+
def_delegators :class, :trigger
|
22
|
+
|
23
|
+
# Initialies the request
|
24
|
+
#
|
25
|
+
# @param url [String] The url
|
26
|
+
# @param headers [Hash] The headers
|
7
27
|
def initialize(url, headers = {})
|
8
28
|
@url = url
|
9
29
|
@headers = headers
|
@@ -12,50 +32,93 @@ module Fron
|
|
12
32
|
self
|
13
33
|
end
|
14
34
|
|
15
|
-
|
16
|
-
|
35
|
+
# Runs a request
|
36
|
+
#
|
37
|
+
# @param method [String] The method
|
38
|
+
# @param data [Hash] The data
|
39
|
+
#
|
40
|
+
# @yieldparam response [Response] The response
|
41
|
+
def request(method = 'GET', data = nil, &callback)
|
42
|
+
if ready_state == 0 || ready_state == 4
|
17
43
|
@callback = callback
|
18
|
-
if method.upcase ==
|
19
|
-
|
20
|
-
|
21
|
-
|
44
|
+
if method.upcase == 'UPLOAD'
|
45
|
+
send 'POST', @url, data.to_form_data
|
46
|
+
elsif method.upcase == 'GET' && data
|
47
|
+
send method, @url + '?' + data.to_query_string.to_s, nil
|
22
48
|
else
|
23
|
-
|
24
|
-
|
25
|
-
`#{@request}.send(#{data.to_json if data})`
|
49
|
+
data = data.to_json if data
|
50
|
+
send method, @url, data
|
26
51
|
end
|
52
|
+
trigger :loading
|
27
53
|
else
|
28
|
-
|
54
|
+
fail 'The request is already running!'
|
29
55
|
end
|
30
56
|
end
|
31
57
|
|
58
|
+
# Runs a GET request
|
59
|
+
#
|
60
|
+
# @param data [Hash] The data
|
61
|
+
#
|
62
|
+
# @yieldparam response [Response] The response
|
32
63
|
def get(data, &callback)
|
33
64
|
request 'GET', data, &callback
|
34
65
|
end
|
35
66
|
|
67
|
+
# Runs a POST request
|
68
|
+
#
|
69
|
+
# @param data [Hash] The data
|
70
|
+
#
|
71
|
+
# @yieldparam response [Response] The response
|
36
72
|
def post(data, &callback)
|
37
73
|
request 'POST', data, &callback
|
38
74
|
end
|
39
75
|
|
76
|
+
# Runs a PUT request
|
77
|
+
#
|
78
|
+
# @param data [Hash] The data
|
79
|
+
#
|
80
|
+
# @yieldparam response [Response] The response
|
40
81
|
def put(data, &callback)
|
41
82
|
request 'PUT', data, &callback
|
42
83
|
end
|
43
84
|
|
44
85
|
private
|
45
|
-
|
46
|
-
|
86
|
+
|
87
|
+
# Sends the given data to the given URL
|
88
|
+
# with the given method
|
89
|
+
#
|
90
|
+
# @param method [String] The method
|
91
|
+
# @param url [String] The URL
|
92
|
+
# @param data [*] The data
|
93
|
+
def send(method, url, data)
|
94
|
+
`#{@request}.open(#{method}, #{url})`
|
95
|
+
`#{@request}.withCredentials = true`
|
96
|
+
set_headers
|
97
|
+
`#{@request}.send(#{data})`
|
98
|
+
end
|
99
|
+
|
100
|
+
# Sets the headers
|
101
|
+
def set_headers
|
102
|
+
@headers.each_pair do |header, value|
|
47
103
|
`#{@request}.setRequestHeader(#{header},#{value})`
|
48
104
|
end
|
49
105
|
end
|
50
106
|
|
107
|
+
# Returns the ready state of the request
|
108
|
+
#
|
109
|
+
# @return [Numeric] The ready state
|
51
110
|
def ready_state
|
52
111
|
`#{@request}.readyState`
|
53
112
|
end
|
54
113
|
|
114
|
+
# Handles the hash change
|
55
115
|
def handle_state_change
|
56
|
-
|
116
|
+
return unless ready_state == 4
|
117
|
+
begin
|
57
118
|
response = Response.new `#{@request}.status`, `#{@request}.response`, `#{@request}.getAllResponseHeaders()`
|
58
119
|
@callback.call response if @callback
|
120
|
+
ensure
|
121
|
+
trigger :loaded
|
59
122
|
end
|
60
123
|
end
|
61
124
|
end
|
@@ -1,7 +1,22 @@
|
|
1
1
|
module Fron
|
2
|
+
# Response
|
2
3
|
class Response
|
3
|
-
|
4
|
+
# @return [String] The response body
|
5
|
+
attr_reader :body
|
4
6
|
|
7
|
+
# @return [Hash] The response headers
|
8
|
+
attr_reader :headers
|
9
|
+
|
10
|
+
# @return [Numeric] The response status code
|
11
|
+
attr_reader :status
|
12
|
+
|
13
|
+
# Initializes the response
|
14
|
+
#
|
15
|
+
# @param status [Numeric] The status
|
16
|
+
# @param body [String] The response body
|
17
|
+
# @param headers [Hash] The headers
|
18
|
+
#
|
19
|
+
# @return [type] [description]
|
5
20
|
def initialize(status, body, headers)
|
6
21
|
@body = body
|
7
22
|
@status = status
|
@@ -13,24 +28,36 @@ module Fron
|
|
13
28
|
end
|
14
29
|
end
|
15
30
|
|
31
|
+
# Returns the content type of the response
|
32
|
+
#
|
33
|
+
# @return [String] The content type
|
16
34
|
def content_type
|
17
35
|
@headers['Content-Type']
|
18
36
|
end
|
19
37
|
|
38
|
+
# Returns whether the request was successfull
|
39
|
+
#
|
40
|
+
# @return [Boolean] True if it was false if not
|
20
41
|
def ok?
|
21
42
|
@status == 200
|
22
43
|
end
|
23
44
|
|
45
|
+
# Returns the response body as json
|
46
|
+
#
|
47
|
+
# @return [Hash] The body
|
24
48
|
def json
|
25
49
|
JSON.parse @body
|
26
50
|
end
|
27
51
|
|
52
|
+
# Returns the response body as DOM::Fragment
|
53
|
+
#
|
54
|
+
# @return [DOM::Fragment] The body
|
28
55
|
def dom
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
56
|
+
div = DOM::Element.new 'div'
|
57
|
+
div.html = @body
|
58
|
+
fragment = DOM::Fragment.new
|
59
|
+
fragment << div
|
60
|
+
fragment
|
34
61
|
end
|
35
62
|
end
|
36
63
|
end
|
data/opal/fron/storage.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require '
|
1
|
+
require 'fron/storage/local_storage'
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Fron
|
2
|
+
module Storage
|
3
|
+
# Local Storage wrapper and adapter
|
4
|
+
module LocalStorage
|
5
|
+
# Gets a value from local storage with the given key
|
6
|
+
#
|
7
|
+
# @param key [String] The key
|
8
|
+
#
|
9
|
+
# @return [Object] The value
|
10
|
+
def self.get(key)
|
11
|
+
value = `window.localStorage.getItem(#{key}) || false`
|
12
|
+
value ? JSON.parse(value) : nil
|
13
|
+
end
|
14
|
+
|
15
|
+
# Sets a value to local storage with the given key
|
16
|
+
#
|
17
|
+
# @param key [String] The key
|
18
|
+
# @param data [Object] The value
|
19
|
+
def self.set(key, data)
|
20
|
+
`window.localStorage.setItem(#{key},#{data.to_json})`
|
21
|
+
end
|
22
|
+
|
23
|
+
# Removes a value from local storage with the given key
|
24
|
+
#
|
25
|
+
# @param key [String] The key
|
26
|
+
def self.remove(key)
|
27
|
+
`window.localStorage.removeItem(#{key})`
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns the all keys present in local storage
|
31
|
+
#
|
32
|
+
# @return [Array] Array of keys
|
33
|
+
def self.keys
|
34
|
+
%x{
|
35
|
+
ret = []
|
36
|
+
for (var key in localStorage){ ret.push(key) }
|
37
|
+
return ret
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns all values from local storage
|
42
|
+
#
|
43
|
+
# @return [Array] Array of values
|
44
|
+
def self.all
|
45
|
+
keys.map { |key| get key }
|
46
|
+
end
|
47
|
+
|
48
|
+
# Clears local storage removeing all values
|
49
|
+
def self.clear
|
50
|
+
`window.localStorage.clear()`
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|