volt 0.8.14 → 0.8.15
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 +1 -1
- data/Readme.md +8 -2
- data/VERSION +1 -1
- data/app/volt/controllers/notices_controller.rb +1 -1
- data/app/volt/models/user.rb +2 -2
- data/app/volt/tasks/live_query/live_query_pool.rb +1 -1
- data/app/volt/tasks/query_tasks.rb +1 -1
- data/app/volt/tasks/store_tasks.rb +1 -1
- data/app/volt/tasks/user_tasks.rb +2 -2
- data/lib/volt/boot.rb +2 -2
- data/lib/volt/cli/asset_compile.rb +31 -27
- data/lib/volt/cli.rb +64 -65
- data/lib/volt/config.rb +25 -23
- data/lib/volt/console.rb +17 -16
- data/lib/volt/controllers/model_controller.rb +82 -80
- data/lib/volt/data_stores/data_store.rb +2 -2
- data/lib/volt/data_stores/mongo_driver.rb +2 -2
- data/lib/volt/extra_core/inflections.rb +2 -2
- data/lib/volt/extra_core/inflector/inflections.rb +185 -183
- data/lib/volt/extra_core/inflector/methods.rb +50 -48
- data/lib/volt/extra_core/string.rb +2 -2
- data/lib/volt/models/array_model.rb +93 -92
- data/lib/volt/models/cursor.rb +3 -2
- data/lib/volt/models/model.rb +248 -251
- data/lib/volt/models/model_hash_behaviour.rb +44 -44
- data/lib/volt/models/model_helpers.rb +38 -36
- data/lib/volt/models/model_state.rb +16 -17
- data/lib/volt/models/model_wrapper.rb +25 -24
- data/lib/volt/models/persistors/array_store.rb +145 -143
- data/lib/volt/models/persistors/base.rb +18 -16
- data/lib/volt/models/persistors/flash.rb +24 -22
- data/lib/volt/models/persistors/local_store.rb +46 -44
- data/lib/volt/models/persistors/model_identity_map.rb +10 -8
- data/lib/volt/models/persistors/model_store.rb +76 -76
- data/lib/volt/models/persistors/params.rb +19 -17
- data/lib/volt/models/persistors/query/query_listener.rb +65 -63
- data/lib/volt/models/persistors/query/query_listener_pool.rb +12 -10
- data/lib/volt/models/persistors/store.rb +28 -28
- data/lib/volt/models/persistors/store_factory.rb +12 -10
- data/lib/volt/models/persistors/store_state.rb +33 -31
- data/lib/volt/models/url.rb +96 -104
- data/lib/volt/models/validations.rb +56 -54
- data/lib/volt/models/validators/length_validator.rb +24 -22
- data/lib/volt/models/validators/presence_validator.rb +14 -12
- data/lib/volt/page/bindings/attribute_binding.rb +106 -106
- data/lib/volt/page/bindings/base_binding.rb +23 -21
- data/lib/volt/page/bindings/component_binding.rb +3 -1
- data/lib/volt/page/bindings/content_binding.rb +34 -34
- data/lib/volt/page/bindings/each_binding.rb +113 -113
- data/lib/volt/page/bindings/event_binding.rb +38 -34
- data/lib/volt/page/bindings/if_binding.rb +56 -54
- data/lib/volt/page/bindings/template_binding/grouped_controllers.rb +24 -22
- data/lib/volt/page/bindings/template_binding.rb +182 -185
- data/lib/volt/page/channel.rb +79 -77
- data/lib/volt/page/channel_stub.rb +29 -27
- data/lib/volt/page/document.rb +6 -5
- data/lib/volt/page/document_events.rb +54 -52
- data/lib/volt/page/page.rb +139 -138
- data/lib/volt/page/string_template_renderer.rb +36 -36
- data/lib/volt/page/sub_context.rb +26 -25
- data/lib/volt/page/targets/attribute_section.rb +27 -25
- data/lib/volt/page/targets/attribute_target.rb +7 -6
- data/lib/volt/page/targets/base_section.rb +27 -26
- data/lib/volt/page/targets/binding_document/base_node.rb +3 -1
- data/lib/volt/page/targets/binding_document/component_node.rb +85 -82
- data/lib/volt/page/targets/binding_document/html_node.rb +11 -9
- data/lib/volt/page/targets/dom_section.rb +78 -77
- data/lib/volt/page/targets/dom_target.rb +8 -6
- data/lib/volt/page/targets/dom_template.rb +90 -88
- data/lib/volt/page/targets/helpers/comment_searchers.rb +51 -49
- data/lib/volt/page/tasks.rb +59 -57
- data/lib/volt/page/template_renderer.rb +17 -14
- data/lib/volt/page/url_tracker.rb +26 -24
- data/lib/volt/reactive/computation.rb +87 -88
- data/lib/volt/reactive/dependency.rb +30 -28
- data/lib/volt/reactive/eventable.rb +64 -62
- data/lib/volt/reactive/hash_dependency.rb +25 -23
- data/lib/volt/reactive/reactive_accessors.rb +34 -32
- data/lib/volt/reactive/reactive_array.rb +162 -162
- data/lib/volt/reactive/reactive_hash.rb +37 -35
- data/lib/volt/router/routes.rb +99 -101
- data/lib/volt/server/component_handler.rb +20 -21
- data/lib/volt/server/component_templates.rb +72 -70
- data/lib/volt/server/html_parser/attribute_scope.rb +109 -99
- data/lib/volt/server/html_parser/each_scope.rb +17 -16
- data/lib/volt/server/html_parser/if_view_scope.rb +51 -49
- data/lib/volt/server/html_parser/sandlebars_parser.rb +184 -177
- data/lib/volt/server/html_parser/textarea_scope.rb +24 -22
- data/lib/volt/server/html_parser/view_handler.rb +66 -65
- data/lib/volt/server/html_parser/view_parser.rb +23 -21
- data/lib/volt/server/html_parser/view_scope.rb +142 -141
- data/lib/volt/server/rack/asset_files.rb +81 -79
- data/lib/volt/server/rack/component_code.rb +17 -15
- data/lib/volt/server/rack/component_html_renderer.rb +14 -12
- data/lib/volt/server/rack/component_paths.rb +72 -71
- data/lib/volt/server/rack/index_files.rb +36 -39
- data/lib/volt/server/rack/opal_files.rb +43 -41
- data/lib/volt/server/rack/source_map_server.rb +23 -21
- data/lib/volt/server/socket_connection_handler.rb +46 -45
- data/lib/volt/server/socket_connection_handler_stub.rb +21 -19
- data/lib/volt/server.rb +60 -58
- data/lib/volt/spec/setup.rb +3 -3
- data/lib/volt/tasks/dispatcher.rb +24 -23
- data/lib/volt/tasks/task_handler.rb +35 -33
- data/lib/volt/utils/ejson.rb +8 -6
- data/lib/volt/utils/generic_counting_pool.rb +33 -31
- data/lib/volt/utils/generic_pool.rb +73 -70
- data/lib/volt/utils/local_storage.rb +42 -38
- data/lib/volt/volt/environment.rb +1 -1
- data/lib/volt.rb +44 -42
- data/spec/apps/kitchen_sink/app/main/assets/css/todos.css +28 -0
- data/spec/apps/kitchen_sink/app/main/config/routes.rb +1 -0
- data/spec/apps/kitchen_sink/app/main/controllers/main_controller.rb +2 -2
- data/spec/apps/kitchen_sink/app/main/controllers/todos_controller.rb +17 -0
- data/spec/apps/kitchen_sink/app/main/views/main/main.html +1 -0
- data/spec/apps/kitchen_sink/app/main/views/todos/index.html +24 -0
- data/spec/apps/kitchen_sink/config.ru +1 -1
- data/spec/controllers/reactive_accessors_spec.rb +5 -5
- data/spec/extra_core/inflector_spec.rb +2 -2
- data/spec/integration/list_spec.rb +68 -0
- data/spec/models/model_spec.rb +57 -57
- data/spec/models/persistors/params_spec.rb +6 -6
- data/spec/models/persistors/store_spec.rb +7 -7
- data/spec/models/validations_spec.rb +3 -3
- data/spec/page/bindings/content_binding_spec.rb +7 -7
- data/spec/page/bindings/template_binding_spec.rb +4 -5
- data/spec/page/sub_context_spec.rb +2 -2
- data/spec/reactive/computation_spec.rb +10 -10
- data/spec/reactive/dependency_spec.rb +2 -2
- data/spec/reactive/eventable_spec.rb +4 -4
- data/spec/reactive/reactive_array_spec.rb +13 -13
- data/spec/router/routes_spec.rb +5 -5
- data/spec/server/html_parser/sandlebars_parser_spec.rb +9 -9
- data/spec/server/html_parser/view_parser_spec.rb +27 -27
- data/spec/server/rack/asset_files_spec.rb +5 -5
- data/spec/server/rack/component_paths_spec.rb +2 -2
- data/spec/tasks/live_query_spec.rb +2 -2
- data/spec/tasks/query_tasks.rb +1 -1
- data/spec/tasks/query_tracker_spec.rb +1 -1
- data/spec/templates/targets/binding_document/component_node_spec.rb +2 -2
- data/spec/utils/generic_counting_pool_spec.rb +2 -2
- data/spec/utils/generic_pool_spec.rb +2 -2
- data/templates/component/controllers/main_controller.rb +1 -1
- data/templates/model/model.rb.tt +2 -2
- data/templates/newgem/app/newgem/controllers/main_controller.rb.tt +2 -2
- data/templates/project/app/main/controllers/main_controller.rb +1 -1
- data/templates/project/config.ru +1 -1
- metadata +10 -3
- data/app/volt/assets/js/vertxbus.js +0 -216
data/lib/volt/page/document.rb
CHANGED
|
@@ -1,77 +1,79 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
module Volt
|
|
2
|
+
class DocumentEvents
|
|
3
|
+
def initialize
|
|
4
|
+
@events = {}
|
|
5
|
+
end
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
def add(event, binding, handler)
|
|
8
|
+
# Track each document event based on the event, element id, then binding.object_id
|
|
9
|
+
unless @events[event]
|
|
10
|
+
# We haven't defined an event of type event yet, lets attach it to the
|
|
11
|
+
# document.
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
@events[event] = {}
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
that = self
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
%x{
|
|
17
18
|
$('body').on(event, function(e) {
|
|
18
19
|
that.$handle(event, e, e.target || e.originalEvent.target);
|
|
19
20
|
});
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
@events[event][binding.binding_name] ||= {}
|
|
26
|
+
@events[event][binding.binding_name][binding.object_id] = handler
|
|
22
27
|
end
|
|
23
28
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
end
|
|
29
|
+
def handle(event_name, event, target)
|
|
30
|
+
element = Element.find(target)
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
loop do
|
|
33
|
+
# Lookup the handler, make sure to not assume the group
|
|
34
|
+
# exists.
|
|
35
|
+
# TODO: Sometimes the event doesn't exist, but we still get
|
|
36
|
+
# an event.
|
|
37
|
+
handlers = @events[event_name]
|
|
38
|
+
handlers = handlers[element.id] if handlers
|
|
30
39
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
handlers = handlers[element.id] if handlers
|
|
40
|
+
if handlers
|
|
41
|
+
handlers.values.each do |handler|
|
|
42
|
+
# Call each handler for this object
|
|
43
|
+
handler.call(event)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
38
46
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
47
|
+
if element.size == 0
|
|
48
|
+
break
|
|
49
|
+
else
|
|
50
|
+
element = element.parent
|
|
43
51
|
end
|
|
44
52
|
end
|
|
45
53
|
|
|
46
|
-
|
|
47
|
-
break
|
|
48
|
-
else
|
|
49
|
-
element = element.parent
|
|
50
|
-
end
|
|
54
|
+
nil
|
|
51
55
|
end
|
|
52
56
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def remove(event, binding)
|
|
57
|
-
# Remove the event binding
|
|
58
|
-
@events[event][binding.binding_name].delete(binding.object_id)
|
|
57
|
+
def remove(event, binding)
|
|
58
|
+
# Remove the event binding
|
|
59
|
+
@events[event][binding.binding_name].delete(binding.object_id)
|
|
59
60
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
# if there are no more handlers for this binding_name (the html id), then
|
|
62
|
+
# we remove the binding name hash
|
|
63
|
+
if @events[event][binding.binding_name].size == 0
|
|
64
|
+
@events[event].delete(binding.binding_name)
|
|
65
|
+
end
|
|
65
66
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
# if there are no more handlers in this event, we can unregister the event
|
|
68
|
+
# from the document
|
|
69
|
+
if @events[event].size == 0
|
|
70
|
+
@events.delete(event)
|
|
70
71
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
# Remove the event from the body
|
|
73
|
+
%x{
|
|
74
|
+
$('body').unbind(event);
|
|
75
|
+
}
|
|
76
|
+
end
|
|
75
77
|
end
|
|
76
78
|
end
|
|
77
79
|
end
|
data/lib/volt/page/page.rb
CHANGED
|
@@ -29,181 +29,182 @@ require 'volt/page/url_tracker'
|
|
|
29
29
|
require 'volt/benchmark/benchmark'
|
|
30
30
|
require 'volt/page/tasks'
|
|
31
31
|
|
|
32
|
+
module Volt
|
|
33
|
+
class Page
|
|
34
|
+
attr_reader :url, :params, :page, :templates, :routes, :events, :model_classes
|
|
35
|
+
|
|
36
|
+
def initialize
|
|
37
|
+
@model_classes = {}
|
|
38
|
+
|
|
39
|
+
# Run the code to setup the page
|
|
40
|
+
@page = Model.new
|
|
41
|
+
|
|
42
|
+
@url = URL.new
|
|
43
|
+
@params = @url.params
|
|
44
|
+
@url_tracker = UrlTracker.new(self)
|
|
45
|
+
|
|
46
|
+
@events = DocumentEvents.new
|
|
47
|
+
|
|
48
|
+
if RUBY_PLATFORM == 'opal'
|
|
49
|
+
# Setup escape binding for console
|
|
50
|
+
%x{
|
|
51
|
+
$(document).keyup(function(e) {
|
|
52
|
+
if (e.keyCode == 27) {
|
|
53
|
+
Opal.gvars.page.$launch_console();
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
$(document).on('click', 'a', function(event) {
|
|
58
|
+
return Opal.gvars.page.$link_clicked($(this).attr('href'), event);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
end
|
|
32
62
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def initialize
|
|
37
|
-
@model_classes = {}
|
|
38
|
-
|
|
39
|
-
# Run the code to setup the page
|
|
40
|
-
@page = Model.new
|
|
41
|
-
|
|
42
|
-
@url = URL.new
|
|
43
|
-
@params = @url.params
|
|
44
|
-
@url_tracker = UrlTracker.new(self)
|
|
45
|
-
|
|
46
|
-
@events = DocumentEvents.new
|
|
63
|
+
# Initialize tasks so we can get the reload message
|
|
64
|
+
self.tasks if Volt.env.development?
|
|
47
65
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
$(document).keyup(function(e) {
|
|
52
|
-
if (e.keyCode == 27) {
|
|
53
|
-
Opal.gvars.page.$launch_console();
|
|
54
|
-
}
|
|
55
|
-
});
|
|
66
|
+
if Volt.client?
|
|
67
|
+
channel.on('reconnected') do
|
|
68
|
+
@page._reconnected = true
|
|
56
69
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
70
|
+
`setTimeout(function() {`
|
|
71
|
+
@page._reconnected = false
|
|
72
|
+
`}, 2000);`
|
|
73
|
+
end
|
|
74
|
+
end
|
|
61
75
|
end
|
|
62
76
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if Volt.client?
|
|
67
|
-
channel.on('reconnected') do
|
|
68
|
-
@page._reconnected = true
|
|
77
|
+
def flash
|
|
78
|
+
@flash ||= Model.new({}, persistor: Persistors::Flash)
|
|
79
|
+
end
|
|
69
80
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
`}, 2000);`
|
|
73
|
-
end
|
|
81
|
+
def store
|
|
82
|
+
@store ||= Model.new({}, persistor: Persistors::StoreFactory.new(tasks))
|
|
74
83
|
end
|
|
75
|
-
end
|
|
76
84
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
85
|
+
def local_store
|
|
86
|
+
@local_store ||= Model.new({}, persistor: Persistors::LocalStore)
|
|
87
|
+
end
|
|
80
88
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
89
|
+
def tasks
|
|
90
|
+
@tasks ||= Tasks.new(self)
|
|
91
|
+
end
|
|
84
92
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
93
|
+
def link_clicked(url='', event=nil)
|
|
94
|
+
# Skip when href == ''
|
|
95
|
+
return false if url.blank?
|
|
88
96
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
97
|
+
# Normalize url
|
|
98
|
+
# Benchmark.bm(1) do
|
|
99
|
+
if @url.parse(url)
|
|
100
|
+
if event
|
|
101
|
+
# Handled new url
|
|
102
|
+
`event.stopPropagation();`
|
|
103
|
+
end
|
|
92
104
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return false if url.blank?
|
|
105
|
+
# Clear the flash
|
|
106
|
+
flash.clear
|
|
96
107
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if @url.parse(url)
|
|
100
|
-
if event
|
|
101
|
-
# Handled new url
|
|
102
|
-
`event.stopPropagation();`
|
|
108
|
+
# return false to stop the event propigation
|
|
109
|
+
return false
|
|
103
110
|
end
|
|
111
|
+
# end
|
|
104
112
|
|
|
105
|
-
#
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
# return false to stop the event propigation
|
|
109
|
-
return false
|
|
113
|
+
# Not stopping, process link normally
|
|
114
|
+
return true
|
|
110
115
|
end
|
|
111
|
-
# end
|
|
112
|
-
|
|
113
|
-
# Not stopping, process link normally
|
|
114
|
-
return true
|
|
115
|
-
end
|
|
116
116
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
117
|
+
# We provide a binding_name, so we can bind events on the document
|
|
118
|
+
def binding_name
|
|
119
|
+
'page'
|
|
120
|
+
end
|
|
121
121
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
def launch_console
|
|
123
|
+
puts "Launch Console"
|
|
124
|
+
end
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
126
|
+
def channel
|
|
127
|
+
@channel ||= begin
|
|
128
|
+
if Volt.client?
|
|
129
|
+
Channel.new
|
|
130
|
+
else
|
|
131
|
+
ChannelStub.new
|
|
132
|
+
end
|
|
132
133
|
end
|
|
133
134
|
end
|
|
134
|
-
end
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
def events
|
|
137
|
+
@events
|
|
138
|
+
end
|
|
139
139
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
140
|
+
def add_model(model_name)
|
|
141
|
+
model_name = model_name.camelize.to_sym
|
|
142
|
+
@model_classes[model_name] = Object.const_get(model_name)
|
|
143
|
+
end
|
|
144
144
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
145
|
+
def add_template(name, template, bindings)
|
|
146
|
+
@templates ||= {}
|
|
147
|
+
@templates[name] = {'html' => template, 'bindings' => bindings}
|
|
148
|
+
# puts "Add Template: #{name}"
|
|
149
|
+
end
|
|
150
150
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
151
|
+
def add_routes(&block)
|
|
152
|
+
@routes = Routes.new.define(&block)
|
|
153
|
+
@url.router = @routes
|
|
154
|
+
end
|
|
155
155
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
def start
|
|
157
|
+
# Setup to render template
|
|
158
|
+
Element.find('body').html = "<!-- $CONTENT --><!-- $/CONTENT -->"
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
load_stored_page
|
|
161
161
|
|
|
162
|
-
|
|
163
|
-
|
|
162
|
+
# Do the initial url params parse
|
|
163
|
+
@url_tracker.url_updated(true)
|
|
164
164
|
|
|
165
|
-
|
|
165
|
+
main_controller = MainController.new
|
|
166
166
|
|
|
167
|
-
|
|
168
|
-
|
|
167
|
+
# Setup main page template
|
|
168
|
+
TemplateRenderer.new(self, DomTarget.new, main_controller, 'CONTENT', 'main/main/main/body')
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
|
|
170
|
+
# Setup title reactive template
|
|
171
|
+
@title_template = StringTemplateRender.new(self, main_controller, "main/main/main/title")
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
173
|
+
# Watch for changes to the title template
|
|
174
|
+
Proc.new do
|
|
175
|
+
title = @title_template.html.gsub(/\n/, ' ')
|
|
176
|
+
`document.title = title;`
|
|
177
|
+
end.watch!
|
|
178
|
+
end
|
|
179
179
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
180
|
+
# When the page is reloaded from the backend, we store the $page.page, so we
|
|
181
|
+
# can reload the page in the exact same state. Speeds up development.
|
|
182
|
+
def load_stored_page
|
|
183
|
+
if Volt.client?
|
|
184
|
+
if `sessionStorage`
|
|
185
|
+
page_obj_str = nil
|
|
186
|
+
|
|
187
|
+
`page_obj_str = sessionStorage.getItem('___page');`
|
|
188
|
+
`if (page_obj_str) {`
|
|
189
|
+
`sessionStorage.removeItem('___page');`
|
|
190
|
+
|
|
191
|
+
JSON.parse(page_obj_str).each_pair do |key, value|
|
|
192
|
+
self.page.send(:"_#{key}=", value)
|
|
193
|
+
end
|
|
194
|
+
`}`
|
|
195
|
+
end
|
|
195
196
|
end
|
|
197
|
+
rescue => e
|
|
198
|
+
puts "Unable to restore: #{e.inspect}"
|
|
196
199
|
end
|
|
197
|
-
rescue => e
|
|
198
|
-
puts "Unable to restore: #{e.inspect}"
|
|
199
200
|
end
|
|
200
|
-
end
|
|
201
201
|
|
|
202
|
-
if Volt.client?
|
|
203
|
-
|
|
202
|
+
if Volt.client?
|
|
203
|
+
$page = Page.new
|
|
204
204
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
205
|
+
# Call start once the page is loaded
|
|
206
|
+
Document.ready? do
|
|
207
|
+
$page.start
|
|
208
|
+
end
|
|
208
209
|
end
|
|
209
210
|
end
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
|
|
2
|
-
# to
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
class StringTemplateRender
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
module Volt
|
|
2
|
+
# StringTemplateRender are used to render a template to a string. Call .html
|
|
3
|
+
# to get the string. Be sure to call .remove when complete.
|
|
4
|
+
#
|
|
5
|
+
# StringTemplateRender will intellegently update the string in the same way
|
|
6
|
+
# a normal bindings will update the dom.
|
|
7
|
+
class StringTemplateRender
|
|
8
|
+
def initialize(page, context, template_path)
|
|
9
|
+
@dependency = Dependency.new
|
|
10
|
+
|
|
11
|
+
@template_path = template_path
|
|
12
|
+
@target = AttributeTarget.new(nil, nil, self)
|
|
13
|
+
@template = TemplateRenderer.new(page, @target, context, "main", template_path)
|
|
14
|
+
end
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
# Render the template and get the current value
|
|
17
|
+
def html
|
|
18
|
+
@dependency.depend
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
html = nil
|
|
21
|
+
Computation.run_without_tracking do
|
|
22
|
+
html = @target.to_html
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
return html
|
|
23
26
|
end
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
def changed!
|
|
29
|
+
# if @dependency is missing, this template has been removed
|
|
30
|
+
@dependency.changed! if @dependency
|
|
31
|
+
end
|
|
27
32
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
end
|
|
33
|
+
def remove
|
|
34
|
+
@dependency.remove
|
|
35
|
+
@dependency = nil
|
|
32
36
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
Computation.run_without_tracking do
|
|
38
|
+
@template.remove
|
|
39
|
+
@template = nil
|
|
40
|
+
end
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
@
|
|
39
|
-
@template = nil
|
|
42
|
+
@target = nil
|
|
43
|
+
@template_path = nil
|
|
40
44
|
end
|
|
41
|
-
|
|
42
|
-
@target = nil
|
|
43
|
-
@template_path = nil
|
|
44
45
|
end
|
|
45
|
-
|
|
46
46
|
end
|
|
@@ -1,33 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
#
|
|
3
|
-
#
|
|
1
|
+
module Volt
|
|
2
|
+
# A sub context takes in a hash of local variables that should be available
|
|
3
|
+
# in front of the current context. It basically proxies the local variables
|
|
4
|
+
# first, then failing those proxies the context.
|
|
5
|
+
class SubContext
|
|
6
|
+
attr_reader :locals
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
@locals = locals.stringify_keys
|
|
10
|
-
@context = context
|
|
11
|
-
end
|
|
8
|
+
def initialize(locals, context=nil)
|
|
9
|
+
@locals = locals.stringify_keys
|
|
10
|
+
@context = context
|
|
11
|
+
end
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
def respond_to?(method_name)
|
|
14
|
+
!!(@locals[method_name.to_s] || (@context && @context.respond_to?(method_name)) || super)
|
|
15
|
+
end
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
def method_missing(method_name, *args, &block)
|
|
18
|
+
method_name = method_name.to_s
|
|
19
|
+
if @locals.has_key?(method_name)
|
|
20
|
+
obj = @locals[method_name]
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
# TODORW: Might get a normal proc, flag internal procs
|
|
23
|
+
if obj.is_a?(Proc)
|
|
24
|
+
obj = obj.call(*args)
|
|
25
|
+
end
|
|
26
|
+
return obj
|
|
27
|
+
elsif @context
|
|
28
|
+
return @context.send(method_name, *args, &block)
|
|
25
29
|
end
|
|
26
|
-
return obj
|
|
27
|
-
elsif @context
|
|
28
|
-
return @context.send(method_name, *args, &block)
|
|
29
|
-
end
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
raise NoMethodError.new("undefined method `#{method_name}' for \"#{self.inspect}\":#{self.class.to_s}")
|
|
32
|
+
end
|
|
32
33
|
end
|
|
33
34
|
end
|
|
@@ -3,35 +3,37 @@
|
|
|
3
3
|
|
|
4
4
|
require 'volt/page/targets/base_section'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def text=(text)
|
|
13
|
-
set_content_and_rezero_bindings(text, {})
|
|
14
|
-
end
|
|
6
|
+
module Volt
|
|
7
|
+
class AttributeSection < BaseSection
|
|
8
|
+
def initialize(target, binding_name)
|
|
9
|
+
@target = target
|
|
10
|
+
@binding_name = binding_name
|
|
11
|
+
end
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
def text=(text)
|
|
14
|
+
set_content_and_rezero_bindings(text, {})
|
|
15
|
+
end
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def set_content_and_rezero_bindings(html, bindings)
|
|
23
|
-
if @binding_name == 'main'
|
|
24
|
-
@target.html = html
|
|
25
|
-
else
|
|
26
|
-
@target.find_by_binding_id(@binding_name).html = html
|
|
17
|
+
def html=(value)
|
|
18
|
+
set_content_and_rezero_bindings(value, {})
|
|
27
19
|
end
|
|
28
20
|
|
|
29
|
-
|
|
30
|
-
|
|
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
|
+
if @binding_name == 'main'
|
|
25
|
+
@target.html = html
|
|
26
|
+
else
|
|
27
|
+
@target.find_by_binding_id(@binding_name).html = html
|
|
28
|
+
end
|
|
31
29
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
return bindings
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def remove
|
|
34
|
+
# TODO: is this getting run for no reason?
|
|
35
|
+
node = @target.find_by_binding_id(@binding_name)
|
|
36
|
+
node.remove if node
|
|
37
|
+
end
|
|
36
38
|
end
|
|
37
39
|
end
|