volt 0.6.5 → 0.7.0
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 +47 -40
- data/VERSION +1 -1
- data/app/volt/controllers/notices_controller.rb +3 -3
- data/app/volt/tasks/live_query/data_store.rb +2 -2
- data/app/volt/tasks/live_query/live_query.rb +20 -20
- data/app/volt/tasks/live_query/live_query_pool.rb +6 -6
- data/app/volt/tasks/live_query/query_tracker.rb +15 -15
- data/app/volt/tasks/query_tasks.rb +13 -13
- data/app/volt/tasks/store_tasks.rb +7 -7
- data/app/volt/views/notices/index.html +17 -18
- data/lib/volt/assets/test.rb +2 -2
- data/lib/volt/benchmark/benchmark.rb +25 -23
- data/lib/volt/cli/asset_compile.rb +11 -0
- data/lib/volt/cli/new_gem.rb +16 -16
- data/lib/volt/cli.rb +14 -12
- data/lib/volt/console.rb +5 -6
- data/lib/volt/controllers/model_controller.rb +18 -18
- data/lib/volt/extra_core/array.rb +4 -4
- data/lib/volt/extra_core/hash.rb +3 -3
- data/lib/volt/extra_core/object.rb +6 -6
- data/lib/volt/extra_core/string.rb +6 -6
- data/lib/volt/extra_core/symbol.rb +5 -5
- data/lib/volt/extra_core/time.rb +4 -4
- data/lib/volt/extra_core/true_false.rb +6 -6
- data/lib/volt/extra_core/try.rb +9 -9
- data/lib/volt/models/array_model.rb +26 -26
- data/lib/volt/models/model.rb +35 -35
- data/lib/volt/models/model_hash_behaviour.rb +15 -15
- data/lib/volt/models/model_helpers.rb +8 -8
- data/lib/volt/models/model_wrapper.rb +6 -6
- data/lib/volt/models/persistors/array_store.rb +36 -36
- data/lib/volt/models/persistors/base.rb +6 -6
- data/lib/volt/models/persistors/flash.rb +5 -5
- data/lib/volt/models/persistors/model_identity_map.rb +2 -2
- data/lib/volt/models/persistors/model_store.rb +22 -22
- data/lib/volt/models/persistors/params.rb +3 -3
- data/lib/volt/models/persistors/query/query_listener.rb +14 -14
- data/lib/volt/models/persistors/query/query_listener_pool.rb +2 -2
- data/lib/volt/models/persistors/store.rb +8 -8
- data/lib/volt/models/persistors/store_factory.rb +2 -2
- data/lib/volt/models/url.rb +37 -37
- data/lib/volt/page/bindings/attribute_binding.rb +14 -14
- data/lib/volt/page/bindings/base_binding.rb +9 -9
- data/lib/volt/page/bindings/component_binding.rb +7 -7
- data/lib/volt/page/bindings/content_binding.rb +3 -3
- data/lib/volt/page/bindings/each_binding.rb +13 -13
- data/lib/volt/page/bindings/event_binding.rb +4 -4
- data/lib/volt/page/bindings/if_binding.rb +12 -12
- data/lib/volt/page/bindings/template_binding.rb +30 -30
- data/lib/volt/page/channel.rb +19 -19
- data/lib/volt/page/channel_stub.rb +6 -6
- data/lib/volt/page/document.rb +2 -2
- data/lib/volt/page/document_events.rb +4 -4
- data/lib/volt/page/draw_cycle.rb +3 -3
- data/lib/volt/page/memory_test.rb +6 -6
- data/lib/volt/page/page.rb +19 -19
- data/lib/volt/page/reactive_template.rb +9 -9
- data/lib/volt/page/sub_context.rb +5 -5
- data/lib/volt/page/targets/attribute_section.rb +9 -9
- data/lib/volt/page/targets/attribute_target.rb +3 -3
- data/lib/volt/page/targets/base_section.rb +2 -2
- data/lib/volt/page/targets/binding_document/component_node.rb +23 -23
- data/lib/volt/page/targets/binding_document/html_node.rb +2 -2
- data/lib/volt/page/targets/dom_section.rb +40 -38
- data/lib/volt/page/targets/dom_target.rb +2 -2
- data/lib/volt/page/tasks.rb +12 -12
- data/lib/volt/page/template_renderer.rb +4 -4
- data/lib/volt/page/url_tracker.rb +6 -6
- data/lib/volt/reactive/array_extensions.rb +2 -2
- data/lib/volt/reactive/destructive_methods.rb +5 -5
- data/lib/volt/reactive/event_chain.rb +25 -25
- data/lib/volt/reactive/events.rb +33 -33
- data/lib/volt/reactive/object_tracker.rb +21 -21
- data/lib/volt/reactive/object_tracking.rb +2 -2
- data/lib/volt/reactive/reactive_array.rb +57 -57
- data/lib/volt/reactive/reactive_tags.rb +16 -16
- data/lib/volt/reactive/reactive_value.rb +72 -72
- data/lib/volt/reactive/string_extensions.rb +3 -3
- data/lib/volt/router/routes.rb +22 -23
- data/lib/volt/server/component_handler.rb +5 -5
- data/lib/volt/server/component_templates.rb +14 -11
- data/lib/volt/server/html_parser/attribute_scope.rb +116 -0
- data/lib/volt/server/html_parser/each_scope.rb +18 -0
- data/lib/volt/server/html_parser/if_view_scope.rb +71 -0
- data/lib/volt/server/html_parser/sandlebars_parser.rb +219 -0
- data/lib/volt/server/html_parser/textarea_scope.rb +31 -0
- data/lib/volt/server/html_parser/view_handler.rb +82 -0
- data/lib/volt/server/html_parser/view_parser.rb +23 -0
- data/lib/volt/server/html_parser/view_scope.rb +145 -0
- data/lib/volt/server/rack/asset_files.rb +17 -17
- data/lib/volt/server/rack/component_paths.rb +18 -18
- data/lib/volt/server/rack/index_files.rb +8 -8
- data/lib/volt/server/rack/opal_files.rb +11 -11
- data/lib/volt/server/socket_connection_handler.rb +13 -13
- data/lib/volt/server/socket_connection_handler_stub.rb +2 -2
- data/lib/volt/server.rb +18 -18
- data/lib/volt/tasks/dispatcher.rb +5 -5
- data/lib/volt/utils/ejson.rb +2 -2
- data/lib/volt/utils/generic_counting_pool.rb +8 -8
- data/lib/volt/utils/generic_pool.rb +16 -16
- data/lib/volt/volt/environment.rb +4 -4
- data/lib/volt.rb +6 -6
- data/spec/integration/test_integration_spec.rb +2 -2
- data/spec/models/event_chain_spec.rb +38 -38
- data/spec/models/model_spec.rb +128 -128
- data/spec/models/old_model_spec.rb +17 -17
- data/spec/models/persistors/params_spec.rb +3 -3
- data/spec/models/persistors/store_spec.rb +7 -7
- data/spec/models/reactive_array_spec.rb +82 -82
- data/spec/models/reactive_generator_spec.rb +11 -11
- data/spec/models/reactive_tags_spec.rb +6 -6
- data/spec/models/reactive_value_spec.rb +70 -70
- data/spec/models/store_spec.rb +4 -4
- data/spec/models/string_extensions_spec.rb +13 -13
- data/spec/page/bindings/content_binding_spec.rb +6 -6
- data/spec/page/sub_context_spec.rb +1 -1
- data/spec/router/routes_spec.rb +3 -3
- data/spec/server/html_parser/sample_page.html +595 -0
- data/spec/server/html_parser/sandlebars_parser_spec.rb +192 -0
- data/spec/server/html_parser/view_parser_spec.rb +286 -0
- data/spec/server/rack/asset_files_spec.rb +6 -6
- data/spec/server/rack/component_paths_spec.rb +5 -5
- data/spec/spec_helper.rb +4 -5
- data/spec/store/mongo_spec.rb +3 -3
- data/spec/tasks/live_query_spec.rb +6 -6
- data/spec/tasks/query_tasks.rb +4 -4
- data/spec/tasks/query_tracker_spec.rb +20 -20
- data/spec/templates/targets/binding_document/component_node_spec.rb +4 -4
- data/spec/templates/template_binding_spec.rb +28 -28
- data/spec/utils/generic_counting_pool_spec.rb +5 -5
- data/spec/utils/generic_pool_spec.rb +14 -14
- data/templates/newgem/app/newgem/views/index/index.html +1 -2
- data/templates/project/app/home/config/dependencies.rb +1 -1
- data/templates/project/app/home/controllers/index_controller.rb +1 -1
- data/templates/project/app/home/views/index/about.html +4 -6
- data/templates/project/app/home/views/index/home.html +4 -5
- data/templates/project/app/home/views/index/index.html +8 -9
- data/templates/project/spec/spec_helper.rb +1 -1
- metadata +17 -8
- data/lib/volt/server/binding_setup.rb +0 -2
- data/lib/volt/server/if_binding_setup.rb +0 -31
- data/lib/volt/server/scope.rb +0 -43
- data/lib/volt/server/template_parser.rb +0 -453
- data/spec/server/template_parser_spec.rb +0 -50
|
@@ -7,20 +7,20 @@ class Test
|
|
|
7
7
|
listener = a.on('changed') { puts "CHANGED" }
|
|
8
8
|
a.cur = 5
|
|
9
9
|
listener.remove
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
ObjectTracker.process_queue
|
|
12
12
|
end
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
def self.test
|
|
15
15
|
a = ReactiveValue.new(Model.new)
|
|
16
16
|
a._cool = [1,2,3]
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
listener = a._cool.on('added') { puts "ADDED" }
|
|
19
19
|
a._cool << 4
|
|
20
20
|
puts a._cool[3]
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
listener.remove
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
ObjectTracker.process_queue
|
|
25
25
|
end
|
|
26
|
-
end
|
|
26
|
+
end
|
data/lib/volt/page/page.rb
CHANGED
|
@@ -38,19 +38,19 @@ class Page
|
|
|
38
38
|
# debugger
|
|
39
39
|
puts "------ Page Loaded -------"
|
|
40
40
|
@model_classes = {}
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
# Run the code to setup the page
|
|
43
43
|
@page = ReactiveValue.new(Model.new)
|
|
44
44
|
@flash = ReactiveValue.new(Model.new({}, persistor: Persistors::Flash))
|
|
45
45
|
@store = ReactiveValue.new(Model.new({}, persistor: Persistors::StoreFactory.new(tasks)))
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
@url = ReactiveValue.new(URL.new)
|
|
48
48
|
@params = @url.params
|
|
49
49
|
@url_tracker = UrlTracker.new(self)
|
|
50
50
|
|
|
51
51
|
@events = DocumentEvents.new
|
|
52
52
|
@draw_cycle = DrawCycle.new
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
if RUBY_PLATFORM == 'opal'
|
|
55
55
|
# Setup escape binding for console
|
|
56
56
|
%x{
|
|
@@ -59,21 +59,21 @@ class Page
|
|
|
59
59
|
Opal.gvars.page.$launch_console();
|
|
60
60
|
}
|
|
61
61
|
});
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
$(document).on('click', 'a', function(event) {
|
|
64
64
|
return Opal.gvars.page.$link_clicked($(this).attr('href'), event);
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
def tasks
|
|
71
71
|
@tasks ||= Tasks.new(self)
|
|
72
72
|
end
|
|
73
|
-
|
|
73
|
+
|
|
74
74
|
def link_clicked(url='', event=nil)
|
|
75
75
|
# Skip when href == ''
|
|
76
|
-
return if url.blank?
|
|
76
|
+
return false if url.blank?
|
|
77
77
|
|
|
78
78
|
# Normalize url
|
|
79
79
|
# Benchmark.bm(1) do
|
|
@@ -85,21 +85,21 @@ class Page
|
|
|
85
85
|
|
|
86
86
|
# Clear the flash
|
|
87
87
|
flash.clear
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
# return false to stop the event propigation
|
|
90
90
|
return false
|
|
91
91
|
end
|
|
92
92
|
# end
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
# Not stopping, process link normally
|
|
95
95
|
return true
|
|
96
96
|
end
|
|
97
|
-
|
|
97
|
+
|
|
98
98
|
# We provide a binding_name, so we can bind events on the document
|
|
99
99
|
def binding_name
|
|
100
100
|
'page'
|
|
101
101
|
end
|
|
102
|
-
|
|
102
|
+
|
|
103
103
|
def launch_console
|
|
104
104
|
puts "Launch Console"
|
|
105
105
|
end
|
|
@@ -117,10 +117,10 @@ class Page
|
|
|
117
117
|
def events
|
|
118
118
|
@events
|
|
119
119
|
end
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
def add_model(model_name)
|
|
122
122
|
# puts "ADD MODEL: #{model_name.inspect} - #{model_name.camelize.inspect}"
|
|
123
|
-
|
|
123
|
+
|
|
124
124
|
@model_classes[["*", "_#{model_name}"]] = Object.const_get(model_name.camelize)
|
|
125
125
|
end
|
|
126
126
|
|
|
@@ -130,7 +130,7 @@ class Page
|
|
|
130
130
|
@templates[name] = {'html' => template, 'bindings' => bindings}
|
|
131
131
|
# puts "Add Template: #{name}"
|
|
132
132
|
end
|
|
133
|
-
|
|
133
|
+
|
|
134
134
|
def add_routes(&block)
|
|
135
135
|
@routes = Routes.new.define(&block)
|
|
136
136
|
@url.cur.router = @routes
|
|
@@ -157,18 +157,18 @@ class Page
|
|
|
157
157
|
`document.title = title;`
|
|
158
158
|
end
|
|
159
159
|
TemplateRenderer.new(self, title_target, main_controller, "main", "home/index/index/title")
|
|
160
|
-
|
|
160
|
+
|
|
161
161
|
# TODO: this dom ready should really happen in the template renderer
|
|
162
162
|
main_controller.dom_ready if main_controller.respond_to?(:dom_ready)
|
|
163
163
|
end
|
|
164
|
-
|
|
164
|
+
|
|
165
165
|
# When the page is reloaded from the backend, we store the $page.page, so we
|
|
166
166
|
# can reload the page in the exact same state. Speeds up development.
|
|
167
167
|
def load_stored_page
|
|
168
168
|
if Volt.client?
|
|
169
169
|
if `sessionStorage`
|
|
170
170
|
page_obj_str = nil
|
|
171
|
-
|
|
171
|
+
|
|
172
172
|
`page_obj_str = sessionStorage.getItem('___page');`
|
|
173
173
|
`if (page_obj_str) {`
|
|
174
174
|
`sessionStorage.removeItem('___page');`
|
|
@@ -188,7 +188,7 @@ if Volt.client?
|
|
|
188
188
|
$page = Page.new
|
|
189
189
|
|
|
190
190
|
# Call start once the page is loaded
|
|
191
|
-
Document.ready? do
|
|
191
|
+
Document.ready? do
|
|
192
192
|
$page.start
|
|
193
193
|
end
|
|
194
|
-
end
|
|
194
|
+
end
|
|
@@ -1,39 +1,39 @@
|
|
|
1
1
|
class ReactiveTemplate
|
|
2
2
|
include Events
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
def initialize(page, context, template_path)
|
|
5
5
|
# puts "New Reactive Template: #{context.inspect} - #{template_path.inspect}"
|
|
6
6
|
@template_path = template_path
|
|
7
7
|
@target = AttributeTarget.new
|
|
8
8
|
@template = TemplateRenderer.new(page, @target, context, "main", template_path)
|
|
9
9
|
end
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
def event_added(event, scope_provider, first)
|
|
12
12
|
if first && !@template_listener
|
|
13
13
|
@template_listener = @target.on('changed') { update }
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
def event_removed(event, last)
|
|
18
18
|
if last && @template_listener
|
|
19
19
|
@template_listener.remove
|
|
20
20
|
@template_listener = nil
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
# Render the template and get the current value
|
|
25
25
|
def cur
|
|
26
26
|
@target.to_html
|
|
27
27
|
end
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
# TODO: improve
|
|
30
30
|
def skip_current_queue_flush
|
|
31
31
|
true
|
|
32
32
|
end
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
|
|
34
|
+
|
|
35
35
|
def update
|
|
36
36
|
trigger!('changed')
|
|
37
37
|
end
|
|
38
|
-
|
|
39
|
-
end
|
|
38
|
+
|
|
39
|
+
end
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
# A sub context takes in a hash of local variables that should be available
|
|
2
|
-
# in front of the current context. It basically proxies the local variables
|
|
2
|
+
# in front of the current context. It basically proxies the local variables
|
|
3
3
|
# first, then failing those proxies the context.
|
|
4
4
|
|
|
5
5
|
class SubContext
|
|
6
6
|
attr_reader :locals
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
def initialize(locals, context=nil)
|
|
9
9
|
@locals = locals.stringify_keys
|
|
10
10
|
@context = context
|
|
11
11
|
end
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
def respond_to?(method_name)
|
|
14
14
|
!!(@locals[method_name.to_s] || (@context && @context.respond_to?(method_name)) || super)
|
|
15
15
|
end
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
def method_missing(method_name, *args, &block)
|
|
18
18
|
method_name = method_name.to_s
|
|
19
19
|
if @locals[method_name]
|
|
@@ -24,4 +24,4 @@ class SubContext
|
|
|
24
24
|
|
|
25
25
|
raise NoMethodError.new("undefined method `#{method_name}' for \"#{self.inspect}\":#{self.class.to_s}")
|
|
26
26
|
end
|
|
27
|
-
end
|
|
27
|
+
end
|
|
@@ -9,29 +9,29 @@ class AttributeSection
|
|
|
9
9
|
@binding_name = binding_name
|
|
10
10
|
# puts "init attr section on #{binding_name}"
|
|
11
11
|
end
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
def text=(text)
|
|
14
14
|
set_content_and_rezero_bindings(text, {})
|
|
15
15
|
end
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
def html=(value)
|
|
18
18
|
set_content_and_rezero_bindings(value, {})
|
|
19
19
|
end
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
|
|
21
|
+
# Takes in our html and bindings, and rezero's the comment names, and the
|
|
22
|
+
# bindings. Returns an updated bindings hash
|
|
23
|
+
def set_content_and_rezero_bindings(html, bindings)
|
|
24
24
|
if @binding_name == 'main'
|
|
25
25
|
@target.html = html
|
|
26
26
|
else
|
|
27
27
|
@target.find_by_binding_id(@binding_name).html = html
|
|
28
28
|
end
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
return bindings
|
|
31
31
|
end
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
def remove
|
|
34
34
|
node = @target.find_by_binding_id(@binding_name)
|
|
35
35
|
node.remove
|
|
36
36
|
end
|
|
37
|
-
end
|
|
37
|
+
end
|
|
@@ -6,13 +6,13 @@ require 'volt/page/targets/binding_document/html_node'
|
|
|
6
6
|
# AttributeTarget's provide an interface that can render bindings into
|
|
7
7
|
# a string that can then be used to update a attribute binding.
|
|
8
8
|
|
|
9
|
-
class AttributeTarget < ComponentNode
|
|
9
|
+
class AttributeTarget < ComponentNode
|
|
10
10
|
# TODO: improve
|
|
11
11
|
def skip_current_queue_flush
|
|
12
12
|
true
|
|
13
13
|
end
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
def section(*args)
|
|
16
16
|
return AttributeSection.new(self, *args)
|
|
17
17
|
end
|
|
18
|
-
end
|
|
18
|
+
end
|
|
@@ -7,13 +7,13 @@ require 'volt/reactive/events'
|
|
|
7
7
|
# the html from templates outside of a normal dom.
|
|
8
8
|
class ComponentNode < BaseNode
|
|
9
9
|
include Events
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
attr_accessor :parent, :binding_id, :nodes
|
|
12
12
|
def initialize(binding_id=nil, parent=nil)
|
|
13
13
|
@nodes = []
|
|
14
14
|
@binding_id = binding_id
|
|
15
15
|
@parent = parent
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
@change_listener = on('changed') do
|
|
18
18
|
if @parent
|
|
19
19
|
@parent.trigger!('changed')
|
|
@@ -25,88 +25,88 @@ class ComponentNode < BaseNode
|
|
|
25
25
|
def skip_current_queue_flush
|
|
26
26
|
true
|
|
27
27
|
end
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
def text=(text)
|
|
30
30
|
self.html = text
|
|
31
31
|
end
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
def html=(html)
|
|
34
34
|
parts = html.split(/(\<\!\-\- \$\/?[0-9]+ \-\-\>)/).reject {|v| v == '' }
|
|
35
|
-
|
|
35
|
+
|
|
36
36
|
# Clear current nodes
|
|
37
37
|
@nodes = []
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
current_node = self
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
parts.each do |part|
|
|
42
42
|
case part
|
|
43
43
|
when /\<\!\-\- \$[0-9]+ \-\-\>/
|
|
44
44
|
# Open
|
|
45
45
|
binding_id = part.match(/\<\!\-\- \$([0-9]+) \-\-\>/)[1].to_i
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
sub_node = ComponentNode.new(binding_id, current_node)
|
|
48
48
|
current_node << sub_node
|
|
49
49
|
current_node = sub_node
|
|
50
50
|
when /\<\!\-\- \$\/[0-9]+ \-\-\>/
|
|
51
51
|
# Close
|
|
52
52
|
# binding_id = part.match(/\<\!\-\- \$\/([0-9]+) \-\-\>/)[1].to_i
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
current_node = current_node.parent
|
|
55
55
|
else
|
|
56
56
|
# html string
|
|
57
57
|
current_node << HtmlNode.new(part)
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
trigger!('changed')
|
|
62
62
|
end
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
def <<(node)
|
|
65
65
|
@nodes << node
|
|
66
66
|
end
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
def to_html
|
|
69
69
|
str = []
|
|
70
70
|
@nodes.each do |node|
|
|
71
71
|
str << node.to_html
|
|
72
72
|
end
|
|
73
|
-
|
|
73
|
+
|
|
74
74
|
return str.join('')
|
|
75
75
|
end
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
def find_by_binding_id(binding_id)
|
|
78
78
|
if @binding_id == binding_id
|
|
79
79
|
return self
|
|
80
80
|
end
|
|
81
|
-
|
|
81
|
+
|
|
82
82
|
@nodes.each do |node|
|
|
83
83
|
if node.cur.is_a?(ComponentNode)
|
|
84
84
|
val = node.find_by_binding_id(binding_id)
|
|
85
85
|
return val if val
|
|
86
86
|
end
|
|
87
87
|
end
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
return nil
|
|
90
90
|
end
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
def remove
|
|
93
93
|
@nodes = []
|
|
94
|
-
|
|
94
|
+
|
|
95
95
|
trigger!('changed')
|
|
96
96
|
end
|
|
97
|
-
|
|
97
|
+
|
|
98
98
|
def remove_anchors
|
|
99
99
|
raise "not implemented"
|
|
100
100
|
|
|
101
101
|
@parent.nodes.delete(self)
|
|
102
|
-
|
|
102
|
+
|
|
103
103
|
@change_listener.remove
|
|
104
104
|
@change_listener = nil
|
|
105
|
-
|
|
105
|
+
|
|
106
106
|
trigger!('changed')
|
|
107
107
|
end
|
|
108
|
-
|
|
108
|
+
|
|
109
109
|
def inspect
|
|
110
110
|
"<ComponentNode:#{@binding_id} #{@nodes.inspect}>"
|
|
111
111
|
end
|
|
112
|
-
end
|
|
112
|
+
end
|
|
@@ -5,15 +5,15 @@ class DomSection < BaseSection
|
|
|
5
5
|
@start_node = find_by_comment("$#{binding_name}")
|
|
6
6
|
@end_node = find_by_comment("$/#{binding_name}")
|
|
7
7
|
end
|
|
8
|
-
|
|
9
|
-
def find_by_comment(text, in_node=`document`)
|
|
10
|
-
node = nil
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
def find_by_comment(text, in_node=`document`)
|
|
10
|
+
node = nil
|
|
11
|
+
|
|
12
|
+
%x{
|
|
13
|
+
node = document.evaluate("//comment()[. = ' " + text + " ']", in_node, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null).iterateNext();
|
|
14
|
+
}
|
|
15
|
+
return node
|
|
16
|
+
end
|
|
17
17
|
|
|
18
18
|
def text=(value)
|
|
19
19
|
%x{
|
|
@@ -21,7 +21,7 @@ class DomSection < BaseSection
|
|
|
21
21
|
this.$range().insertNode(document.createTextNode(#{value}));
|
|
22
22
|
}
|
|
23
23
|
end
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
def html=(value)
|
|
26
26
|
set_content_and_rezero_bindings(value, {})
|
|
27
27
|
end
|
|
@@ -33,8 +33,8 @@ class DomSection < BaseSection
|
|
|
33
33
|
range.deleteContents();
|
|
34
34
|
}
|
|
35
35
|
end
|
|
36
|
-
|
|
37
|
-
def remove_anchors
|
|
36
|
+
|
|
37
|
+
def remove_anchors
|
|
38
38
|
%x{
|
|
39
39
|
this.start_node.parentNode.removeChild(this.start_node);
|
|
40
40
|
this.end_node.parentNode.removeChild(this.end_node);
|
|
@@ -42,16 +42,16 @@ class DomSection < BaseSection
|
|
|
42
42
|
@start_node = nil
|
|
43
43
|
@end_node = nil
|
|
44
44
|
end
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
def insert_anchor_before_end(binding_name)
|
|
47
47
|
Element.find(@end_node).before("<!-- $#{binding_name} --><!-- $/#{binding_name} -->")
|
|
48
48
|
end
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
def insert_anchor_before(binding_name, insert_after_binding)
|
|
51
51
|
node = find_by_comment("$#{insert_after_binding}")
|
|
52
52
|
Element.find(node).before("<!-- $#{binding_name} --><!-- $/#{binding_name} -->")
|
|
53
53
|
end
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
# Takes in an array of dom nodes and replaces the current content
|
|
56
56
|
# with the new nodes
|
|
57
57
|
def nodes=(nodes)
|
|
@@ -68,23 +68,23 @@ class DomSection < BaseSection
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
end
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
# Returns the nearest DOM node that contains all of the section.
|
|
73
73
|
def container_node
|
|
74
74
|
range = self.range()
|
|
75
75
|
return `range.commonAncestorContainer`
|
|
76
76
|
end
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
77
|
+
|
|
78
|
+
# Takes in our html and bindings, and rezero's the comment names, and the
|
|
79
|
+
# bindings. Returns an updated bindings hash
|
|
80
|
+
def set_content_and_rezero_bindings(html, bindings)
|
|
81
|
+
sub_nodes = nil
|
|
82
82
|
temp_div = nil
|
|
83
83
|
|
|
84
84
|
%x{
|
|
85
85
|
temp_div = document.createElement('div');
|
|
86
86
|
var doc = jQuery.parseHTML(html);
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
if (doc) {
|
|
89
89
|
for (var i=0;i < doc.length;i++) {
|
|
90
90
|
temp_div.appendChild(doc[i]);
|
|
@@ -104,7 +104,7 @@ class DomSection < BaseSection
|
|
|
104
104
|
var node = temp_div.querySelector('#' + name);
|
|
105
105
|
node.setAttribute('id', 'id' +new_name);
|
|
106
106
|
}
|
|
107
|
-
|
|
107
|
+
|
|
108
108
|
new_bindings["id#{new_name}"] = binding
|
|
109
109
|
else
|
|
110
110
|
# Assume a fixed id
|
|
@@ -112,6 +112,8 @@ class DomSection < BaseSection
|
|
|
112
112
|
new_bindings[name] = binding
|
|
113
113
|
end
|
|
114
114
|
else
|
|
115
|
+
# puts "----- #{name.inspect} - #{new_name}"
|
|
116
|
+
# `console.log(temp_div);`
|
|
115
117
|
# Change the comment ids
|
|
116
118
|
start_comment = find_by_comment("$#{name}", temp_div)
|
|
117
119
|
end_comment = find_by_comment("$/#{name}", temp_div)
|
|
@@ -130,33 +132,33 @@ class DomSection < BaseSection
|
|
|
130
132
|
|
|
131
133
|
|
|
132
134
|
children = nil
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
%x{
|
|
136
|
+
children = temp_div.childNodes;
|
|
137
|
+
}
|
|
138
|
+
|
|
137
139
|
# Update the nodes
|
|
138
140
|
self.nodes = children
|
|
139
|
-
|
|
141
|
+
|
|
140
142
|
%x{
|
|
141
143
|
temp_div = null;
|
|
142
144
|
}
|
|
143
145
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
146
|
+
return new_bindings
|
|
147
|
+
end
|
|
148
|
+
|
|
147
149
|
def range
|
|
148
150
|
return @range if @range
|
|
149
151
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
152
|
+
range = nil
|
|
153
|
+
%x{
|
|
154
|
+
range = document.createRange();
|
|
155
|
+
range.setStartAfter(this.start_node);
|
|
156
|
+
range.setEndBefore(this.end_node);
|
|
157
|
+
}
|
|
156
158
|
|
|
157
159
|
@range = range
|
|
158
160
|
|
|
159
|
-
|
|
161
|
+
return range
|
|
160
162
|
end
|
|
161
163
|
|
|
162
|
-
end
|
|
164
|
+
end
|
|
@@ -3,9 +3,9 @@ require 'volt/page/targets/dom_section'
|
|
|
3
3
|
|
|
4
4
|
# DomTarget's provide an interface that can render bindings into
|
|
5
5
|
# the dom. Currently only one "dom" is supported, but multiple
|
|
6
|
-
# may be allowed in the future (iframes?)
|
|
6
|
+
# may be allowed in the future (iframes?)
|
|
7
7
|
class DomTarget < BaseSection
|
|
8
8
|
def section(*args)
|
|
9
9
|
return DomSection.new(*args)
|
|
10
10
|
end
|
|
11
|
-
end
|
|
11
|
+
end
|
data/lib/volt/page/tasks.rb
CHANGED
|
@@ -5,12 +5,12 @@ class Tasks
|
|
|
5
5
|
@page = page
|
|
6
6
|
@callback_id = 0
|
|
7
7
|
@callbacks = {}
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
page.channel.on('message') do |_, *args|
|
|
10
10
|
received_message(*args)
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
def call(class_name, method_name, *args, &callback)
|
|
15
15
|
if callback
|
|
16
16
|
callback_id = @callback_id
|
|
@@ -22,11 +22,11 @@ class Tasks
|
|
|
22
22
|
else
|
|
23
23
|
callback_id = nil
|
|
24
24
|
end
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
@page.channel.send_message([callback_id, class_name, method_name, *args])
|
|
27
27
|
end
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
|
|
29
|
+
|
|
30
30
|
def received_message(name, callback_id, *args)
|
|
31
31
|
case name
|
|
32
32
|
when 'added', 'removed', 'updated', 'changed'
|
|
@@ -37,12 +37,12 @@ class Tasks
|
|
|
37
37
|
reload
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
# When a request is sent to the backend, it can attach a callback,
|
|
42
42
|
# this is called from the backend to pass to the callback.
|
|
43
43
|
def response(callback_id, result, error)
|
|
44
44
|
callback = @callbacks.delete(callback_id)
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
if callback
|
|
47
47
|
if error
|
|
48
48
|
# TODO: full error handling
|
|
@@ -52,7 +52,7 @@ class Tasks
|
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
# Called when the backend sends a notification to change the results of
|
|
57
57
|
# a query.
|
|
58
58
|
def notify_query(method_name, collection, query, *args)
|
|
@@ -60,19 +60,19 @@ class Tasks
|
|
|
60
60
|
# puts "FOUND QUERY: #{collection.inspect} - #{query.inspect} - #{query_obj.inspect} - #{method_name} - #{query_obj.instance_variable_get('@stores').inspect}"
|
|
61
61
|
query_obj.send(method_name, *args)
|
|
62
62
|
end
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
def reload
|
|
65
65
|
puts "RELOAD"
|
|
66
66
|
# Stash the current page value
|
|
67
67
|
value = JSON.dump($page.page.cur.to_h.reject {|k,v| v.reactive? })
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
# If this browser supports session storage, store the page, so it will
|
|
70
70
|
# be in the same state when we reload.
|
|
71
71
|
if `sessionStorage`
|
|
72
72
|
`sessionStorage.setItem('___page', value);`
|
|
73
73
|
end
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
$page.page._reloading = true
|
|
76
76
|
`window.location.reload(false);`
|
|
77
77
|
end
|
|
78
|
-
end
|
|
78
|
+
end
|