fie 0.3.0 → 0.3.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/README.md +4 -6
- data/lib/fie/version.rb +1 -1
- data/lib/javascript/fie.js +49 -0
- data/lib/javascript/fie/action_cable/channel.js +25 -0
- data/lib/javascript/fie/cable.js +72 -0
- data/lib/javascript/fie/commander.js +46 -0
- data/lib/javascript/fie/listeners.js +117 -0
- data/lib/javascript/fie/pool.js +7 -0
- data/lib/javascript/fie/timer.js +15 -0
- data/lib/javascript/fie/util.js +25 -0
- data/vendor/javascript/fie.js +1 -10
- metadata +10 -15
- data/lib/opal/fie.rb +0 -24
- data/lib/opal/fie/cable.rb +0 -63
- data/lib/opal/fie/commander.rb +0 -50
- data/lib/opal/fie/diff_setup.rb +0 -31
- data/lib/opal/fie/expose_methods.rb +0 -27
- data/lib/opal/fie/listeners.rb +0 -129
- data/lib/opal/fie/native.rb +0 -5
- data/lib/opal/fie/native/action_cable_channel.rb +0 -35
- data/lib/opal/fie/native/element.rb +0 -116
- data/lib/opal/fie/native/event.rb +0 -17
- data/lib/opal/fie/native/timeout.rb +0 -24
- data/lib/opal/fie/pool.rb +0 -9
- data/lib/opal/fie/util.rb +0 -23
data/lib/opal/fie.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'opal/base'
|
2
|
-
require 'opal/mini'
|
3
|
-
|
4
|
-
require 'corelib/io'
|
5
|
-
require 'corelib/dir'
|
6
|
-
require 'corelib/file'
|
7
|
-
|
8
|
-
require 'corelib/unsupported'
|
9
|
-
|
10
|
-
module Fie
|
11
|
-
require_tree './fie'
|
12
|
-
|
13
|
-
include Fie::Native
|
14
|
-
|
15
|
-
DiffSetup.run
|
16
|
-
|
17
|
-
Element.document.add_event_listener('DOMContentLoaded') do
|
18
|
-
cable = Cable.new
|
19
|
-
|
20
|
-
ExposeMethods.run
|
21
|
-
|
22
|
-
Listeners.new(cable)
|
23
|
-
end
|
24
|
-
end
|
data/lib/opal/fie/cable.rb
DELETED
@@ -1,63 +0,0 @@
|
|
1
|
-
require 'securerandom'
|
2
|
-
require 'fie/native'
|
3
|
-
require 'json'
|
4
|
-
|
5
|
-
module Fie
|
6
|
-
class Cable
|
7
|
-
include Fie::Native
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
connection_uuid = SecureRandom.uuid
|
11
|
-
commander_name = "#{ camelize(controller_name) }Commander"
|
12
|
-
|
13
|
-
@commander = Commander.new(channel_name: commander_name, identifier: connection_uuid, cable: self)
|
14
|
-
@pools = {}
|
15
|
-
end
|
16
|
-
|
17
|
-
def call_remote_function(element:, event_name:, function_name:, parameters:)
|
18
|
-
log_event(element: element, event_name: event_name, function_name: function_name, parameters: parameters)
|
19
|
-
|
20
|
-
function_parameters = {
|
21
|
-
caller: {
|
22
|
-
id: element.id,
|
23
|
-
class: element.class_name,
|
24
|
-
value: element.value
|
25
|
-
},
|
26
|
-
controller_name: controller_name,
|
27
|
-
action_name: action_name
|
28
|
-
}.merge(parameters)
|
29
|
-
|
30
|
-
@commander.perform(function_name, function_parameters)
|
31
|
-
end
|
32
|
-
|
33
|
-
def subscribe_to_pool(subject)
|
34
|
-
@pools[subject] = Pool.new(channel_name: 'Fie::Pools', identifier: subject, cable: self)
|
35
|
-
end
|
36
|
-
|
37
|
-
def commander
|
38
|
-
@commander
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
def log_event(element:, event_name:, function_name:, parameters:)
|
43
|
-
parameters = parameters.to_json
|
44
|
-
puts "Event #{ event_name } triggered by element #{ element.descriptor } is calling function #{ function_name } with parameters #{ parameters }"
|
45
|
-
end
|
46
|
-
|
47
|
-
def action_name
|
48
|
-
view_name_element['fie-action']
|
49
|
-
end
|
50
|
-
|
51
|
-
def controller_name
|
52
|
-
view_name_element['fie-controller']
|
53
|
-
end
|
54
|
-
|
55
|
-
def view_name_element
|
56
|
-
Element.body.query_selector('[fie-controller]:not([fie-controller=""])');
|
57
|
-
end
|
58
|
-
|
59
|
-
def camelize(string)
|
60
|
-
string.split('_').collect(&:capitalize).join
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
data/lib/opal/fie/commander.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
require 'fie/native'
|
2
|
-
require 'diffhtml/dist/diffhtml.min'
|
3
|
-
|
4
|
-
module Fie
|
5
|
-
class Commander < Fie::Native::ActionCableChannel
|
6
|
-
include Fie::Native
|
7
|
-
|
8
|
-
def connected
|
9
|
-
super
|
10
|
-
|
11
|
-
@cable.call_remote_function \
|
12
|
-
element: Element.body,
|
13
|
-
function_name: 'initialize_state',
|
14
|
-
event_name: 'Upload State',
|
15
|
-
parameters: { view_variables: Util.view_variables }
|
16
|
-
end
|
17
|
-
|
18
|
-
def received(data)
|
19
|
-
process_command(data['command'], data['parameters'])
|
20
|
-
end
|
21
|
-
|
22
|
-
def process_command(command, parameters = {})
|
23
|
-
case command
|
24
|
-
when 'refresh_view'
|
25
|
-
$$.diff.innerHTML Element.fie_body.unwrapped_element, parameters['html']
|
26
|
-
@event.dispatch
|
27
|
-
when 'subscribe_to_pools'
|
28
|
-
parameters['subjects'].each do |subject|
|
29
|
-
@cable.subscribe_to_pool(subject)
|
30
|
-
end
|
31
|
-
when 'publish_to_pool'
|
32
|
-
subject = parameters['subject']
|
33
|
-
object = parameters['object']
|
34
|
-
sender_uuid = parameters['sender_uuid']
|
35
|
-
|
36
|
-
perform("pool_#{ subject }_callback", { object: object, sender_uuid: sender_uuid })
|
37
|
-
when 'publish_to_pool_lazy'
|
38
|
-
subject = parameters['subject']
|
39
|
-
object = parameters['object']
|
40
|
-
sender_uuid = parameters['sender_uuid']
|
41
|
-
|
42
|
-
perform("pool_#{ subject }_callback", { object: object, sender_uuid: sender_uuid, lazy: true })
|
43
|
-
when 'execute_function'
|
44
|
-
Util.exec_js(parameters['name'], parameters['arguments'])
|
45
|
-
else
|
46
|
-
puts "Command: #{ command }, Parameters: #{ parameters }"
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
data/lib/opal/fie/diff_setup.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'es6-object-assign/dist/object-assign.min'
|
2
|
-
|
3
|
-
class DiffSetup
|
4
|
-
class << self
|
5
|
-
include Fie::Native
|
6
|
-
|
7
|
-
def run
|
8
|
-
$$.ObjectAssign.polyfill()
|
9
|
-
|
10
|
-
Native \
|
11
|
-
`diff.use(
|
12
|
-
Object.assign(_ => {}, {
|
13
|
-
syncTreeHook: (oldTree, newTree) => {
|
14
|
-
if (newTree.nodeName === 'input') {
|
15
|
-
let oldElement = document.querySelector('[name="' + newTree.attributes.name + '"]');
|
16
|
-
|
17
|
-
if (oldElement != undefined && oldElement.attributes['fie-ignore'] != undefined) {
|
18
|
-
newTree.nodeValue = oldElement.value;
|
19
|
-
newTree.attributes.value = oldElement.value;
|
20
|
-
newTree.attributes.autofocus = '';
|
21
|
-
newTree.attributes['fie-ignore'] = oldElement.attributes['fie-ignore'];
|
22
|
-
}
|
23
|
-
|
24
|
-
return newTree;
|
25
|
-
}
|
26
|
-
}
|
27
|
-
})
|
28
|
-
)`
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
class ExposeMethods
|
2
|
-
class << self
|
3
|
-
def run
|
4
|
-
Native(`window.Fie = {}`)
|
5
|
-
|
6
|
-
Native \
|
7
|
-
`window.Fie.executeCommanderMethod =
|
8
|
-
#{
|
9
|
-
-> (function_name, parameters = {}) do
|
10
|
-
cable.call_remote_function \
|
11
|
-
element: Element.body,
|
12
|
-
event_name: 'calling remote function',
|
13
|
-
function_name: function_name,
|
14
|
-
parameters: Hash.new(parameters)
|
15
|
-
end
|
16
|
-
}`
|
17
|
-
|
18
|
-
Native \
|
19
|
-
`window.Fie.addEventListener =
|
20
|
-
#{
|
21
|
-
-> (event_name, selector, block) do
|
22
|
-
Element.fie_body.add_event_listener(event_name, selector, &block)
|
23
|
-
end
|
24
|
-
}`
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
data/lib/opal/fie/listeners.rb
DELETED
@@ -1,129 +0,0 @@
|
|
1
|
-
require 'fie/native'
|
2
|
-
require 'securerandom'
|
3
|
-
|
4
|
-
module Fie
|
5
|
-
class Listeners
|
6
|
-
include Fie::Native
|
7
|
-
|
8
|
-
def initialize(cable)
|
9
|
-
@cable = cable
|
10
|
-
@timer = Timeout.new(0) { 'hello' }
|
11
|
-
|
12
|
-
initialize_input_elements
|
13
|
-
initialize_fie_events [:click, :submit, :scroll, :keyup, :keydown, :enter]
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
def initialize_fie_events(event_names)
|
18
|
-
event_names.each do |fie_event_name|
|
19
|
-
selector = "[fie-#{ fie_event_name }]:not([fie-#{ fie_event_name }=''])"
|
20
|
-
|
21
|
-
event_name = fie_event_name
|
22
|
-
event_name = :keydown if event_name == :enter
|
23
|
-
|
24
|
-
Element.fie_body.add_event_listener(event_name, selector) do |event|
|
25
|
-
handle_fie_event(fie_event_name, event_name, event)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def handle_fie_event(fie_event_name, event_name, event)
|
31
|
-
event_is_valid = (fie_event_name == :enter && event.keyCode == 13) || fie_event_name != :enter
|
32
|
-
|
33
|
-
if event_is_valid
|
34
|
-
element = Element.new(element: event.target)
|
35
|
-
remote_function_name = element["fie-#{ fie_event_name }"]
|
36
|
-
function_parameters = JSON.parse(element['fie-parameters'] || {})
|
37
|
-
|
38
|
-
@timer.fast_forward
|
39
|
-
|
40
|
-
@cable.call_remote_function \
|
41
|
-
element: element,
|
42
|
-
function_name: remote_function_name,
|
43
|
-
event_name: event_name,
|
44
|
-
parameters: function_parameters
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def initialize_input_elements
|
49
|
-
typing_input_types = ['text', 'password', 'search', 'tel', 'url']
|
50
|
-
|
51
|
-
typing_input_selector = (['textarea'] + typing_input_types).reduce do |selector, input_type|
|
52
|
-
selector += ", input[type=#{ input_type }]"
|
53
|
-
end
|
54
|
-
|
55
|
-
non_typing_input_selector = (['input'] + typing_input_types).reduce do |selector, input_type|
|
56
|
-
selector += ":not([type=#{ input_type }])"
|
57
|
-
end
|
58
|
-
|
59
|
-
Element.fie_body.add_event_listener('keydown', typing_input_selector) do |event|
|
60
|
-
if event.keyCode == 13
|
61
|
-
event.target.blur
|
62
|
-
else
|
63
|
-
@timer.clear
|
64
|
-
|
65
|
-
input_element = Element.new(element: event.target)
|
66
|
-
|
67
|
-
@timer = Timeout.new(300) do
|
68
|
-
update_state_using_changelog(input_element)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
Element.fie_body.add_event_listener('focusin', typing_input_selector) do |event|
|
74
|
-
event.target.setAttribute('fie-ignore', SecureRandom.uuid)
|
75
|
-
end
|
76
|
-
|
77
|
-
Element.fie_body.add_event_listener('focusout', typing_input_selector) do |event|
|
78
|
-
event.target.removeAttribute('fie-ignore')
|
79
|
-
end
|
80
|
-
|
81
|
-
Element.fie_body.add_event_listener('change', non_typing_input_selector) do |event|
|
82
|
-
input_element = Element.new(element: event.target)
|
83
|
-
update_state_using_changelog(input_element)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def update_state_using_changelog(input_element)
|
88
|
-
objects_changelog = {}
|
89
|
-
|
90
|
-
changed_object_name = input_element.name.split('[')[0]
|
91
|
-
changed_object_key_chain = input_element.name.scan(Regexp.new '\[(.*?)\]').flatten
|
92
|
-
|
93
|
-
is_form_object = !changed_object_key_chain.empty? && !changed_object_name.nil?
|
94
|
-
is_fie_nested_object = Util.view_variables.include? changed_object_name
|
95
|
-
is_fie_form_object = is_form_object && is_fie_nested_object
|
96
|
-
|
97
|
-
is_fie_non_nested_object = Util.view_variables.include? input_element.name
|
98
|
-
|
99
|
-
if is_fie_form_object
|
100
|
-
build_changelog(changed_object_key_chain, changed_object_name, objects_changelog, input_element)
|
101
|
-
elsif is_fie_non_nested_object
|
102
|
-
objects_changelog[input_element.name] = input_element.value;
|
103
|
-
end
|
104
|
-
|
105
|
-
@cable.call_remote_function \
|
106
|
-
element: input_element,
|
107
|
-
function_name: 'modify_state_using_changelog',
|
108
|
-
event_name: 'Input Element Change',
|
109
|
-
parameters: { objects_changelog: objects_changelog }
|
110
|
-
end
|
111
|
-
|
112
|
-
def build_changelog(object_key_chain, object_name, changelog, input_element)
|
113
|
-
is_final_key = -> (key) { key == object_key_chain[-1] }
|
114
|
-
object_final_key_value = input_element.value
|
115
|
-
|
116
|
-
changelog[object_name] = {}
|
117
|
-
changelog = changelog[object_name]
|
118
|
-
|
119
|
-
object_key_chain.each do |key|
|
120
|
-
if is_final_key.call(key)
|
121
|
-
changelog[key] = object_final_key_value
|
122
|
-
else
|
123
|
-
changelog[key] = {}
|
124
|
-
changelog = changelog[key]
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
data/lib/opal/fie/native.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'fie/native'
|
2
|
-
|
3
|
-
module Fie
|
4
|
-
module Native
|
5
|
-
class ActionCableChannel
|
6
|
-
def initialize(channel_name:, identifier:, cable:)
|
7
|
-
@channel_name = channel_name
|
8
|
-
@identifier = identifier
|
9
|
-
@cable = cable
|
10
|
-
@event = Event.new('fieChanged')
|
11
|
-
|
12
|
-
@subscription = $$.App.cable.subscriptions.create(
|
13
|
-
{ channel: @channel_name, identifier: @identifier },
|
14
|
-
{
|
15
|
-
connected: -> { connected },
|
16
|
-
received: -> (data) { received Native(`#{data}`) }
|
17
|
-
}
|
18
|
-
)
|
19
|
-
end
|
20
|
-
|
21
|
-
def responds_to?(t)
|
22
|
-
true
|
23
|
-
end
|
24
|
-
|
25
|
-
def connected
|
26
|
-
perform('initialize_pools')
|
27
|
-
puts "Connected to #{ @channel_name } with identifier #{ @identifier }"
|
28
|
-
end
|
29
|
-
|
30
|
-
def perform(function_name, parameters = {})
|
31
|
-
@subscription.perform(function_name, parameters);
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,116 +0,0 @@
|
|
1
|
-
require 'native'
|
2
|
-
|
3
|
-
module Fie
|
4
|
-
module Native
|
5
|
-
class Element
|
6
|
-
include Native
|
7
|
-
|
8
|
-
def initialize(element: nil, selector: nil)
|
9
|
-
if selector.nil?
|
10
|
-
@element = element
|
11
|
-
elsif element.nil?
|
12
|
-
if selector == 'document'
|
13
|
-
@element = $$.document
|
14
|
-
else
|
15
|
-
@element = $$.document.querySelector(selector)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def [](name)
|
21
|
-
@element.getAttribute(name)
|
22
|
-
end
|
23
|
-
|
24
|
-
def []=(name, value)
|
25
|
-
@element.setAttribute(name, value)
|
26
|
-
end
|
27
|
-
|
28
|
-
def add_event_listener(event_name, selector = nil, &block)
|
29
|
-
@element.addEventListener(event_name) do |event|
|
30
|
-
event = Native(`#{ event }`)
|
31
|
-
|
32
|
-
if selector.nil?
|
33
|
-
yield event
|
34
|
-
else
|
35
|
-
if event.target.matches(selector)
|
36
|
-
yield event
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def innerHTML
|
43
|
-
@element.innerHTML
|
44
|
-
end
|
45
|
-
|
46
|
-
def query_selector(selector)
|
47
|
-
Element.new(element: @element.querySelector(selector))
|
48
|
-
end
|
49
|
-
|
50
|
-
def query_selector_all(selector)
|
51
|
-
entries = Native(`Array.prototype.slice.call(document.querySelectorAll(#{ selector }))`)
|
52
|
-
|
53
|
-
entries.map do |element|
|
54
|
-
Element.new(element: element)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def name
|
59
|
-
@element.name
|
60
|
-
end
|
61
|
-
|
62
|
-
def id
|
63
|
-
@element.id
|
64
|
-
end
|
65
|
-
|
66
|
-
def class_name
|
67
|
-
@element.className
|
68
|
-
end
|
69
|
-
|
70
|
-
def descriptor
|
71
|
-
descriptor = @element.tagName
|
72
|
-
|
73
|
-
id_is_blank =
|
74
|
-
id.nil? || id == ''
|
75
|
-
|
76
|
-
class_name_is_blank =
|
77
|
-
class_name.nil? || class_name == ''
|
78
|
-
|
79
|
-
if !id_is_blank
|
80
|
-
descriptor + "##{ id }"
|
81
|
-
elsif !class_name_is_blank
|
82
|
-
descriptor + ".#{ class_name }"
|
83
|
-
else
|
84
|
-
descriptor
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def value
|
89
|
-
@element.value
|
90
|
-
end
|
91
|
-
|
92
|
-
def unwrapped_element
|
93
|
-
@element
|
94
|
-
end
|
95
|
-
|
96
|
-
private
|
97
|
-
def node_list_to_array(node_list)
|
98
|
-
$$.Array.prototype.slice.call(node_list)
|
99
|
-
end
|
100
|
-
|
101
|
-
class << self
|
102
|
-
def document
|
103
|
-
Element.new(selector: 'document')
|
104
|
-
end
|
105
|
-
|
106
|
-
def body
|
107
|
-
Element.new(selector: 'body')
|
108
|
-
end
|
109
|
-
|
110
|
-
def fie_body
|
111
|
-
Element.new(selector: '[fie-body=true]')
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|