glimmer-dsl-opal 0.0.7 → 0.0.8
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/CHANGELOG.md +30 -0
- data/README.md +475 -25
- data/VERSION +1 -1
- data/lib/glimmer-dsl-opal.rb +2 -0
- data/lib/glimmer/data_binding/ext/observable_model.rb +1 -1
- data/lib/glimmer/data_binding/table_items_binding.rb +67 -0
- data/lib/glimmer/dsl/opal/column_properties_expression.rb +22 -0
- data/lib/glimmer/dsl/opal/dsl.rb +5 -0
- data/lib/glimmer/dsl/opal/table_column_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/table_expression.rb +17 -0
- data/lib/glimmer/dsl/opal/table_items_data_binding_expression.rb +29 -0
- data/lib/glimmer/opal/div_proxy.rb +7 -0
- data/lib/glimmer/opal/document_proxy.rb +15 -6
- data/lib/glimmer/opal/element_proxy.rb +2 -3
- data/lib/glimmer/opal/layout_data_proxy.rb +22 -1
- data/lib/glimmer/opal/list_proxy.rb +1 -1
- data/lib/glimmer/opal/tab_folder.rb +9 -2
- data/lib/glimmer/opal/tab_item.rb +1 -1
- data/lib/glimmer/opal/table_column.rb +50 -0
- data/lib/glimmer/opal/table_item.rb +136 -0
- data/lib/glimmer/opal/table_proxy.rb +149 -0
- data/lib/samples/elaborate/contact_manager.rb +1 -2
- metadata +13 -14
- data/lib/glimmer/config.rb +0 -22
- data/lib/glimmer/dsl/engine.rb +0 -193
- data/lib/glimmer/dsl/expression.rb +0 -42
- data/lib/glimmer/dsl/expression_handler.rb +0 -48
- data/lib/glimmer/dsl/parent_expression.rb +0 -12
- data/lib/glimmer/dsl/static_expression.rb +0 -36
- data/lib/glimmer/dsl/top_level_expression.rb +0 -7
- data/lib/glimmer/error.rb +0 -6
- data/lib/glimmer/invalid_keyword_error.rb +0 -6
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.8
|
data/lib/glimmer-dsl-opal.rb
CHANGED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'glimmer/data_binding/observable_array'
|
2
|
+
require 'glimmer/data_binding/observable_model'
|
3
|
+
require 'glimmer/data_binding/observable'
|
4
|
+
require 'glimmer/data_binding/observer'
|
5
|
+
require 'glimmer/opal/table_proxy'
|
6
|
+
require 'glimmer/opal/table_item'
|
7
|
+
|
8
|
+
module Glimmer
|
9
|
+
module DataBinding
|
10
|
+
class TableItemsBinding
|
11
|
+
include DataBinding::Observable
|
12
|
+
include DataBinding::Observer
|
13
|
+
|
14
|
+
def initialize(parent, model_binding, column_properties)
|
15
|
+
@last_model_collection = nil
|
16
|
+
@table = parent
|
17
|
+
@model_binding = model_binding
|
18
|
+
@column_properties = column_properties
|
19
|
+
if @table.respond_to?(:column_properties=)
|
20
|
+
@table.column_properties = @column_properties
|
21
|
+
##else # assume custom widget
|
22
|
+
## @table.body_root.column_properties = @column_properties
|
23
|
+
end
|
24
|
+
call(@model_binding.evaluate_property)
|
25
|
+
model = model_binding.base_model
|
26
|
+
observe(model, model_binding.property_name_expression)
|
27
|
+
##@table.on_widget_disposed do |dispose_event| # doesn't seem needed within Opal
|
28
|
+
## unregister_all_observables
|
29
|
+
##end
|
30
|
+
end
|
31
|
+
|
32
|
+
def call(new_model_collection=nil)
|
33
|
+
if new_model_collection and new_model_collection.is_a?(Array)
|
34
|
+
observe(new_model_collection, @column_properties)
|
35
|
+
@model_collection = new_model_collection
|
36
|
+
end
|
37
|
+
populate_table(@model_collection, @table, @column_properties)
|
38
|
+
sort_table(@model_collection, @table, @column_properties)
|
39
|
+
end
|
40
|
+
|
41
|
+
def populate_table(model_collection, parent, column_properties)
|
42
|
+
return if model_collection&.sort_by(&:hash) == @last_model_collection&.sort_by(&:hash)
|
43
|
+
@last_model_collection = model_collection
|
44
|
+
# TODO improve performance
|
45
|
+
selected_table_item_models = parent.selection.map(&:get_data)
|
46
|
+
parent.remove_all
|
47
|
+
model_collection.each do |model|
|
48
|
+
table_item = Glimmer::Opal::TableItem.new(parent)
|
49
|
+
for index in 0..(column_properties.size-1)
|
50
|
+
table_item.set_text(index, model.send(column_properties[index]).to_s)
|
51
|
+
end
|
52
|
+
table_item.set_data(model)
|
53
|
+
end
|
54
|
+
selected_table_items = parent.search {|item| selected_table_item_models.include?(item.get_data) }
|
55
|
+
selected_table_items = [parent.items.first] if selected_table_items.empty? && !parent.items.empty?
|
56
|
+
parent.selection = selected_table_items unless selected_table_items.empty?
|
57
|
+
parent.redraw
|
58
|
+
end
|
59
|
+
|
60
|
+
def sort_table(model_collection, parent, column_properties)
|
61
|
+
return if model_collection == @last_model_collection
|
62
|
+
parent.items = parent.items.sort_by { |item| model_collection.index(item.get_data) }
|
63
|
+
@last_model_collection = model_collection
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'glimmer/dsl/static_expression'
|
2
|
+
require 'glimmer/opal/table_proxy'
|
3
|
+
|
4
|
+
module Glimmer
|
5
|
+
module DSL
|
6
|
+
module Opal
|
7
|
+
# Responsible for providing a readable keyword (command symbol) to capture
|
8
|
+
# and return column properties for use in TreeItemsDataBindingCommandHandler
|
9
|
+
class ColumnPropertiesExpression < StaticExpression
|
10
|
+
def can_interpret?(parent, keyword, *args, &block)
|
11
|
+
keyword == 'column_properties' and
|
12
|
+
block.nil? and
|
13
|
+
parent.is_a?(Glimmer::Opal::TableProxy)
|
14
|
+
end
|
15
|
+
|
16
|
+
def interpret(parent, keyword, *args, &block)
|
17
|
+
args
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/glimmer/dsl/opal/dsl.rb
CHANGED
@@ -24,6 +24,10 @@ require 'glimmer/dsl/opal/async_exec_expression'
|
|
24
24
|
require 'glimmer/dsl/opal/observe_expression'
|
25
25
|
require 'glimmer/dsl/opal/layout_data_expression'
|
26
26
|
require 'glimmer/dsl/opal/list_selection_data_binding_expression'
|
27
|
+
require 'glimmer/dsl/opal/table_expression'
|
28
|
+
require 'glimmer/dsl/opal/table_column_expression'
|
29
|
+
require 'glimmer/dsl/opal/table_items_data_binding_expression'
|
30
|
+
require 'glimmer/dsl/opal/column_properties_expression'
|
27
31
|
|
28
32
|
module Glimmer
|
29
33
|
module DSL
|
@@ -32,6 +36,7 @@ module Glimmer
|
|
32
36
|
Opal,
|
33
37
|
%w[
|
34
38
|
widget_listener
|
39
|
+
table_items_data_binding
|
35
40
|
combo_selection_data_binding
|
36
41
|
list_selection_data_binding
|
37
42
|
data_binding
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'glimmer/dsl/static_expression'
|
2
|
+
require 'glimmer/dsl/parent_expression'
|
3
|
+
require 'glimmer/opal/table_column'
|
4
|
+
|
5
|
+
module Glimmer
|
6
|
+
module DSL
|
7
|
+
module Opal
|
8
|
+
class TableColumnExpression < StaticExpression
|
9
|
+
include ParentExpression
|
10
|
+
|
11
|
+
def interpret(parent, keyword, *args, &block)
|
12
|
+
Glimmer::Opal::TableColumn.new(parent, args)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'glimmer/dsl/static_expression'
|
2
|
+
require 'glimmer/dsl/parent_expression'
|
3
|
+
require 'glimmer/opal/table_proxy'
|
4
|
+
|
5
|
+
module Glimmer
|
6
|
+
module DSL
|
7
|
+
module Opal
|
8
|
+
class TableExpression < StaticExpression
|
9
|
+
include ParentExpression
|
10
|
+
|
11
|
+
def interpret(parent, keyword, *args, &block)
|
12
|
+
Glimmer::Opal::TableProxy.new(parent, args)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'glimmer/dsl/expression'
|
2
|
+
require 'glimmer/data_binding/model_binding'
|
3
|
+
require 'glimmer/data_binding/table_items_binding'
|
4
|
+
require 'glimmer/opal/table_proxy'
|
5
|
+
|
6
|
+
module Glimmer
|
7
|
+
module DSL
|
8
|
+
module Opal
|
9
|
+
#Depends on BindCommandHandler and TableColumnPropertiesDataBindingCommandHandler
|
10
|
+
class TableItemsDataBindingExpression < Expression
|
11
|
+
def can_interpret?(parent, keyword, *args, &block)
|
12
|
+
keyword == "items" and
|
13
|
+
block.nil? and
|
14
|
+
parent.is_a?(Glimmer::Opal::TableProxy) and
|
15
|
+
args.size == 2 and
|
16
|
+
args[0].is_a?(DataBinding::ModelBinding) and
|
17
|
+
args[0].evaluate_property.is_a?(Array) and
|
18
|
+
args[1].is_a?(Array)
|
19
|
+
end
|
20
|
+
|
21
|
+
def interpret(parent, keyword, *args, &block)
|
22
|
+
model_binding = args[0]
|
23
|
+
column_properties = args[1]
|
24
|
+
DataBinding::TableItemsBinding.new(parent, model_binding, column_properties)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -10,6 +10,13 @@ module Glimmer
|
|
10
10
|
@layout = GridLayoutProxy.new(self, [])
|
11
11
|
end
|
12
12
|
|
13
|
+
def redraw
|
14
|
+
super()
|
15
|
+
@children.each do |child|
|
16
|
+
add_child(child) # TODO think of impact of this on performance, and of other alternatives
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
13
20
|
def dom
|
14
21
|
div_id = id
|
15
22
|
div_style = css
|
@@ -59,10 +59,6 @@ module Glimmer
|
|
59
59
|
padding-left: 10px;
|
60
60
|
padding-right: 10px;
|
61
61
|
}
|
62
|
-
li.selected-list-item {
|
63
|
-
background: rgb(80, 116, 211);
|
64
|
-
color: white;
|
65
|
-
}
|
66
62
|
li.empty-list-item {
|
67
63
|
color: transparent;
|
68
64
|
}
|
@@ -143,7 +139,6 @@ module Glimmer
|
|
143
139
|
.close {
|
144
140
|
color: #aaaaaa;
|
145
141
|
float: right;
|
146
|
-
# font-size: 18px;
|
147
142
|
font-weight: bold;
|
148
143
|
margin: 5px;
|
149
144
|
}
|
@@ -153,7 +148,21 @@ module Glimmer
|
|
153
148
|
color: #000;
|
154
149
|
text-decoration: none;
|
155
150
|
cursor: pointer;
|
156
|
-
}
|
151
|
+
}
|
152
|
+
|
153
|
+
.selected {
|
154
|
+
background: rgb(80, 116, 211);
|
155
|
+
color: white;
|
156
|
+
}
|
157
|
+
|
158
|
+
table {
|
159
|
+
border-spacing: 0;
|
160
|
+
}
|
161
|
+
|
162
|
+
table tr th,td {
|
163
|
+
cursor: default;
|
164
|
+
}
|
165
|
+
|
157
166
|
</style>
|
158
167
|
CSS
|
159
168
|
}
|
@@ -18,7 +18,7 @@ module Glimmer
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def add_child(child)
|
21
|
-
# return if @children.include?(child) # TODO consider adding an option to enable this if needed to prevent dom repetition
|
21
|
+
# return if @children.include?(child) # TODO consider adding an option to enable this if needed to prevent dom repetition
|
22
22
|
@children << child
|
23
23
|
dom << child.dom
|
24
24
|
end
|
@@ -36,9 +36,8 @@ module Glimmer
|
|
36
36
|
else
|
37
37
|
dom
|
38
38
|
end
|
39
|
-
@children.each do |child|
|
39
|
+
@children.each do |child|
|
40
40
|
child.redraw
|
41
|
-
add_child(child)
|
42
41
|
end
|
43
42
|
end
|
44
43
|
|
@@ -4,7 +4,13 @@ module Glimmer
|
|
4
4
|
module Opal
|
5
5
|
class LayoutDataProxy
|
6
6
|
include PropertyOwner
|
7
|
-
attr_reader :parent,
|
7
|
+
attr_reader :parent,
|
8
|
+
:args,
|
9
|
+
:horizontal_alignment,
|
10
|
+
:vertical_alignment,
|
11
|
+
:grab_excess_horizontal_space,
|
12
|
+
:grab_excess_vertical_space,
|
13
|
+
:height_hint
|
8
14
|
|
9
15
|
def initialize(parent, args)
|
10
16
|
@parent = parent
|
@@ -12,16 +18,31 @@ module Glimmer
|
|
12
18
|
reapply
|
13
19
|
end
|
14
20
|
|
21
|
+
def height_hint=(height_hint)
|
22
|
+
@height_hint = height_hint
|
23
|
+
reapply
|
24
|
+
end
|
25
|
+
|
15
26
|
def horizontal_alignment=(horizontal_alignment)
|
16
27
|
@horizontal_alignment = horizontal_alignment
|
17
28
|
reapply
|
18
29
|
end
|
19
30
|
|
31
|
+
def vertical_alignment=(vertical_alignment)
|
32
|
+
@vertical_alignment = vertical_alignment
|
33
|
+
reapply
|
34
|
+
end
|
35
|
+
|
20
36
|
def grab_excess_horizontal_space=(grab_excess_horizontal_space)
|
21
37
|
@grab_excess_horizontal_space = grab_excess_horizontal_space
|
22
38
|
reapply
|
23
39
|
end
|
24
40
|
|
41
|
+
def grab_excess_vertical_space=(grab_excess_vertical_space)
|
42
|
+
@grab_excess_vertical_space = grab_excess_vertical_space
|
43
|
+
reapply
|
44
|
+
end
|
45
|
+
|
25
46
|
def reapply
|
26
47
|
# @parent.css = <<~CSS
|
27
48
|
# CSS
|
@@ -66,7 +66,7 @@ module Glimmer
|
|
66
66
|
ul(id: list_id, style: list_style) {
|
67
67
|
list_items.to_a.each_with_index do |item, index|
|
68
68
|
li_class = ''
|
69
|
-
li_class += ' selected
|
69
|
+
li_class += ' selected' if list_selection.include?(item)
|
70
70
|
li_class += ' empty-list-item' if item == ITEM_EMPTY
|
71
71
|
li(class: li_class) {
|
72
72
|
item
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'glimmer/opal/
|
1
|
+
require 'glimmer/opal/element_proxy'
|
2
2
|
|
3
3
|
module Glimmer
|
4
4
|
module Opal
|
@@ -15,7 +15,14 @@ module Glimmer
|
|
15
15
|
if @children.size == 1
|
16
16
|
child.show
|
17
17
|
end
|
18
|
-
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def redraw
|
21
|
+
super()
|
22
|
+
@children.each do |child|
|
23
|
+
add_child(child) # TODO think of impact of this on performance
|
24
|
+
end
|
25
|
+
end
|
19
26
|
|
20
27
|
def hide_all_tab_content
|
21
28
|
@children.each(&:hide)
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'glimmer/opal/element_proxy'
|
2
|
+
|
3
|
+
module Glimmer
|
4
|
+
module Opal
|
5
|
+
class TableColumn < ElementProxy
|
6
|
+
include Glimmer
|
7
|
+
attr_reader :text, :width
|
8
|
+
|
9
|
+
def text=(value)
|
10
|
+
@text = value
|
11
|
+
redraw
|
12
|
+
end
|
13
|
+
|
14
|
+
def width=(value)
|
15
|
+
@width = value
|
16
|
+
redraw
|
17
|
+
end
|
18
|
+
|
19
|
+
def css
|
20
|
+
<<~CSS
|
21
|
+
width: #{width};
|
22
|
+
CSS
|
23
|
+
end
|
24
|
+
|
25
|
+
def name
|
26
|
+
'th'
|
27
|
+
end
|
28
|
+
|
29
|
+
def observation_request_to_event_mapping
|
30
|
+
{
|
31
|
+
'on_widget_selected' => {
|
32
|
+
event: 'click'
|
33
|
+
},
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def dom
|
38
|
+
table_column_text = text
|
39
|
+
table_column_id = id
|
40
|
+
table_column_id_style = css
|
41
|
+
table_column_css_classes = css_classes
|
42
|
+
@dom ||= DOM {
|
43
|
+
th(id: table_column_id, style: table_column_id_style, class: table_column_css_classes.to_a.join(' ')) {
|
44
|
+
table_column_text
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'glimmer/opal/element_proxy'
|
2
|
+
|
3
|
+
module Glimmer
|
4
|
+
module Opal
|
5
|
+
class TableItem < ElementProxy
|
6
|
+
attr_reader :data
|
7
|
+
|
8
|
+
def initialize(parent, args)
|
9
|
+
super(parent, args)
|
10
|
+
on_widget_selected { |event|
|
11
|
+
parent.select(parent.index_of(self), event.meta?)
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_text(index)
|
16
|
+
text_array[index]
|
17
|
+
end
|
18
|
+
|
19
|
+
def set_text(index, text_value)
|
20
|
+
text_array[index] = text_value
|
21
|
+
redraw
|
22
|
+
end
|
23
|
+
|
24
|
+
def text_array
|
25
|
+
@text_array ||= []
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_data(key = nil)
|
29
|
+
if key.nil?
|
30
|
+
@data
|
31
|
+
else
|
32
|
+
data_hash[key]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def set_data(key = nil, data_value)
|
37
|
+
if key.nil?
|
38
|
+
@data = data_value
|
39
|
+
else
|
40
|
+
data_hash[key] = data_value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def data_hash
|
45
|
+
@data_hash ||= {}
|
46
|
+
end
|
47
|
+
|
48
|
+
def name
|
49
|
+
'tr'
|
50
|
+
end
|
51
|
+
|
52
|
+
def edit(column_index)
|
53
|
+
return if @edit_column_index == column_index.to_i
|
54
|
+
parent.select(parent.index_of(self), false)
|
55
|
+
@edit_column_index = column_index.to_i
|
56
|
+
redraw
|
57
|
+
end
|
58
|
+
|
59
|
+
def on_widget_selected(&block)
|
60
|
+
event = 'click'
|
61
|
+
delegate = $document.on(event, selector, &block)
|
62
|
+
EventListenerProxy.new(element_proxy: self, event: event, selector: selector, delegate: delegate)
|
63
|
+
end
|
64
|
+
|
65
|
+
def max_column_width(column_index)
|
66
|
+
parent.dom.css("tr td:nth-child(#{column_index + 1})").first.width
|
67
|
+
end
|
68
|
+
|
69
|
+
def dom
|
70
|
+
table_item_id = id
|
71
|
+
table_item_id_style = css
|
72
|
+
table_item_css_classes = css_classes
|
73
|
+
table_item_selection = parent.selection.include?(self)
|
74
|
+
if table_item_selection
|
75
|
+
table_item_css_classes << 'selected'
|
76
|
+
else
|
77
|
+
table_item_css_classes.delete('selected')
|
78
|
+
end
|
79
|
+
table_item_text_array = text_array
|
80
|
+
table_item_edit_column_index = @edit_column_index
|
81
|
+
table_item_max_width = max_column_width(table_item_edit_column_index) if table_item_edit_column_index
|
82
|
+
table_item_edit_handler = lambda do |event, cancel = false|
|
83
|
+
Async::Task.new do
|
84
|
+
text_value = event.target.value
|
85
|
+
edit_property = parent.column_properties[table_item_edit_column_index]
|
86
|
+
edit_model = get_data
|
87
|
+
if !cancel && edit_model.send(edit_property) != text_value
|
88
|
+
edit_model.send("#{edit_property}=", text_value)
|
89
|
+
set_text(table_item_edit_column_index, text_value)
|
90
|
+
end
|
91
|
+
@edit_column_index = nil
|
92
|
+
redraw
|
93
|
+
end
|
94
|
+
end
|
95
|
+
table_item_edit_cancel_handler = lambda do |event|
|
96
|
+
Async::Task.new do
|
97
|
+
table_item_edit_handler.call(event, true)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
table_item_edit_key_handler = lambda do |event|
|
101
|
+
Async::Task.new do
|
102
|
+
if event.code == 13
|
103
|
+
table_item_edit_handler.call(event)
|
104
|
+
elsif event.code == 27
|
105
|
+
table_item_edit_cancel_handler.call(event)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
@dom ||= DOM {
|
110
|
+
tr(id: table_item_id, style: table_item_id_style, class: table_item_css_classes.to_a.join(' ')) {
|
111
|
+
table_item_text_array.each_with_index do |table_item_text, column_index|
|
112
|
+
td('data-column-index' => column_index) {
|
113
|
+
if table_item_edit_column_index == column_index
|
114
|
+
input(type: 'text', value: table_item_text, style: "max-width: #{table_item_max_width - 11}px;")
|
115
|
+
else
|
116
|
+
table_item_text
|
117
|
+
end
|
118
|
+
}
|
119
|
+
end
|
120
|
+
}
|
121
|
+
}.tap do |the_dom|
|
122
|
+
if table_item_edit_column_index
|
123
|
+
table_item_input = the_dom.css("td:nth-child(#{table_item_edit_column_index + 1}) input").first
|
124
|
+
if table_item_input
|
125
|
+
Async::Task.new do
|
126
|
+
table_item_input.focus
|
127
|
+
table_item_input.on('keyup', &table_item_edit_key_handler)
|
128
|
+
table_item_input.on('focusout', &table_item_edit_cancel_handler)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|