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.
@@ -0,0 +1,149 @@
1
+ require 'glimmer/opal/element_proxy'
2
+ require 'glimmer/opal/table_column'
3
+
4
+ module Glimmer
5
+ module Opal
6
+ class TableProxy < ElementProxy
7
+ attr_reader :columns, :selection
8
+ attr_accessor :column_properties
9
+ alias items children
10
+
11
+ def initialize(parent, args)
12
+ super(parent, args)
13
+ @columns = []
14
+ @children = []
15
+ @selection = []
16
+ end
17
+
18
+ # Only table_columns may be added as children
19
+ def add_child(child)
20
+ if child.is_a?(TableColumn)
21
+ @columns << child
22
+ columns_dom << child.dom
23
+ else
24
+ @children << child
25
+ items_dom << child.dom
26
+ end
27
+ end
28
+
29
+ def remove_all
30
+ items.clear
31
+ @items_dom = nil
32
+ end
33
+
34
+ def selection=(new_selection)
35
+ changed = (@selection + new_selection) - (@selection & new_selection)
36
+ @selection = new_selection
37
+ changed.each(&:redraw)
38
+ end
39
+
40
+ def items=(new_items)
41
+ @children = new_items
42
+ redraw
43
+ end
44
+
45
+ def search(&condition)
46
+ items.select {|item| condition.nil? || condition.call(item)}
47
+ end
48
+
49
+ def index_of(item)
50
+ items.index(item)
51
+ end
52
+
53
+ def select(index, meta = false)
54
+ new_selection = @selection.clone
55
+ selected_item = items[index]
56
+ if @selection.include?(selected_item)
57
+ new_selection.delete(selected_item) if meta
58
+ else
59
+ new_selection = [] if !meta || (!has_style?(:multi) && @selection.to_a.size >= 1)
60
+ new_selection << selected_item
61
+ end
62
+ self.selection = new_selection
63
+ end
64
+
65
+ def edit_table_item(table_item, column_index)
66
+ table_item.edit(column_index)
67
+ end
68
+
69
+ def selector
70
+ super + ' tbody'
71
+ end
72
+
73
+ def observation_request_to_event_mapping
74
+ {
75
+ 'on_mouse_down' => {
76
+ event: 'mousedown',
77
+ event_handler: -> (event_listener) {
78
+ -> (event) {
79
+ event.singleton_class.send(:define_method, :table_item=) do |item|
80
+ @table_item = item
81
+ end
82
+ event.singleton_class.send(:define_method, :table_item) do
83
+ @table_item
84
+ end
85
+ table_row = event.target.ancestors('tr').first
86
+ table_data = event.target.ancestors('td').first
87
+ event.table_item = items.detect {|item| item.id == table_row.attributes['id']}
88
+ event.singleton_class.send(:define_method, :column_index) do
89
+ (table_data || event.target).attributes['data-column-index']
90
+ end
91
+ event_listener.call(event)
92
+ }
93
+ }
94
+ }
95
+ }
96
+ end
97
+
98
+ def redraw
99
+ if @dom
100
+ old_dom = @dom
101
+ @dom = nil
102
+ old_dom.replace dom
103
+ else
104
+ dom
105
+ end
106
+ if @last_redrawn_children != @children
107
+ items_dom.clear
108
+ @last_redrawn_children = @children
109
+ @children = []
110
+ @last_redrawn_children.each do |child|
111
+ add_child(child)
112
+ end
113
+ end
114
+ end
115
+
116
+ def columns_dom
117
+ @columns_dom ||= DOM {
118
+ tr {
119
+ }
120
+ }
121
+ end
122
+
123
+ def thead_dom
124
+ @thead_dom ||= DOM {
125
+ thead {
126
+ }
127
+ }.tap {|the_dom| the_dom << columns_dom }
128
+ end
129
+
130
+ def items_dom
131
+ @items_dom ||= DOM {
132
+ tbody {
133
+ }
134
+ }
135
+ end
136
+
137
+ def dom
138
+ table_id = id
139
+ table_id_style = css
140
+ table_id_css_classes = css_classes
141
+ table_id_css_classes_string = table_id_css_classes.to_a.join(' ')
142
+ @dom ||= DOM {
143
+ table(id: table_id, style: table_id_style, class: table_id_css_classes_string) {
144
+ }
145
+ }.tap {|the_dom| the_dom >> thead_dom }.tap {|the_dom| the_dom << items_dom }
146
+ end
147
+ end
148
+ end
149
+ end
@@ -81,8 +81,7 @@ class ContactManager
81
81
  @contact_manager_presenter.toggle_sort(:email)
82
82
  }
83
83
  }
84
- items bind(@contact_manager_presenter, :results),
85
- column_properties(:first_name, :last_name, :email)
84
+ items bind(@contact_manager_presenter, :results), column_properties(:first_name, :last_name, :email)
86
85
  on_mouse_down { |event|
87
86
  table_proxy.edit_table_item(event.table_item, event.column_index)
88
87
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-dsl-opal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - AndyMaleh
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-20 00:00:00.000000000 Z
11
+ date: 2020-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: glimmer
@@ -168,18 +168,16 @@ files:
168
168
  - README.md
169
169
  - VERSION
170
170
  - lib/glimmer-dsl-opal.rb
171
- - lib/glimmer/config.rb
172
171
  - lib/glimmer/data_binding/element_binding.rb
173
172
  - lib/glimmer/data_binding/ext/observable_model.rb
174
173
  - lib/glimmer/data_binding/list_selection_binding.rb
175
174
  - lib/glimmer/data_binding/observable_element.rb
176
- - lib/glimmer/dsl/engine.rb
177
- - lib/glimmer/dsl/expression.rb
178
- - lib/glimmer/dsl/expression_handler.rb
175
+ - lib/glimmer/data_binding/table_items_binding.rb
179
176
  - lib/glimmer/dsl/opal/async_exec_expression.rb
180
177
  - lib/glimmer/dsl/opal/bind_expression.rb
181
178
  - lib/glimmer/dsl/opal/browser_expression.rb
182
179
  - lib/glimmer/dsl/opal/button_expression.rb
180
+ - lib/glimmer/dsl/opal/column_properties_expression.rb
183
181
  - lib/glimmer/dsl/opal/combo_expression.rb
184
182
  - lib/glimmer/dsl/opal/combo_selection_data_binding_expression.rb
185
183
  - lib/glimmer/dsl/opal/composite_expression.rb
@@ -196,13 +194,11 @@ files:
196
194
  - lib/glimmer/dsl/opal/shell_expression.rb
197
195
  - lib/glimmer/dsl/opal/tab_folder_expression.rb
198
196
  - lib/glimmer/dsl/opal/tab_item_expression.rb
197
+ - lib/glimmer/dsl/opal/table_column_expression.rb
198
+ - lib/glimmer/dsl/opal/table_expression.rb
199
+ - lib/glimmer/dsl/opal/table_items_data_binding_expression.rb
199
200
  - lib/glimmer/dsl/opal/text_expression.rb
200
201
  - lib/glimmer/dsl/opal/widget_listener_expression.rb
201
- - lib/glimmer/dsl/parent_expression.rb
202
- - lib/glimmer/dsl/static_expression.rb
203
- - lib/glimmer/dsl/top_level_expression.rb
204
- - lib/glimmer/error.rb
205
- - lib/glimmer/invalid_keyword_error.rb
206
202
  - lib/glimmer/opal/display_proxy.rb
207
203
  - lib/glimmer/opal/div_proxy.rb
208
204
  - lib/glimmer/opal/document_proxy.rb
@@ -220,6 +216,9 @@ files:
220
216
  - lib/glimmer/opal/select_proxy.rb
221
217
  - lib/glimmer/opal/tab_folder.rb
222
218
  - lib/glimmer/opal/tab_item.rb
219
+ - lib/glimmer/opal/table_column.rb
220
+ - lib/glimmer/opal/table_item.rb
221
+ - lib/glimmer/opal/table_proxy.rb
223
222
  - lib/samples/elaborate/contact_manager.rb
224
223
  - lib/samples/elaborate/contact_manager/contact.rb
225
224
  - lib/samples/elaborate/contact_manager/contact_manager_presenter.rb
@@ -243,7 +242,7 @@ homepage: http://github.com/AndyObtiva/glimmer-dsl-opal
243
242
  licenses:
244
243
  - MIT
245
244
  metadata: {}
246
- post_install_message:
245
+ post_install_message:
247
246
  rdoc_options: []
248
247
  require_paths:
249
248
  - lib
@@ -259,7 +258,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
259
258
  version: '0'
260
259
  requirements: []
261
260
  rubygems_version: 3.1.2
262
- signing_key:
261
+ signing_key:
263
262
  specification_version: 4
264
263
  summary: Glimmer DSL for Opal
265
264
  test_files: []
@@ -1,22 +0,0 @@
1
- module Glimmer
2
- module Config
3
- class << self
4
- # Returns Glimmer logger (standard Ruby logger)
5
- def logger
6
- # unless defined? @@logger
7
- # @@logger = Logger.new(STDOUT).tap {|logger| logger.level = Logger::WARN}
8
- # end
9
- @@logger if defined? @@logger
10
- end
11
-
12
- def enable_logging
13
- @@logger = Logger.new(STDOUT).tap {|logger| logger.level = Logger::WARN}
14
- end
15
- end
16
- end
17
- end
18
-
19
- if ENV['GLIMMER_LOGGER_LEVEL']
20
- Glimmer::Config.enable_logging
21
- Glimmer::Config.logger.level = ENV['GLIMMER_LOGGER_LEVEL'].downcase
22
- end
@@ -1,193 +0,0 @@
1
- require 'glimmer'
2
- require 'glimmer/dsl/expression_handler'
3
-
4
- module Glimmer
5
- module DSL
6
- # Glimmer DSL Engine
7
- #
8
- # Follows Interpreter and Chain of Responsibility Design Patterns
9
- #
10
- # When DSL engine interprets an expression, it attempts to handle
11
- # with ordered expression array specified via `.expressions=` method.
12
- class Engine
13
- class << self
14
- def dsl=(dsl_name)
15
- dsl_name = dsl_name&.to_sym
16
- if dsl_name
17
- dsl_stack.push(dsl_name)
18
- else
19
- dsl_stack.clear
20
- end
21
- end
22
-
23
- def dsl
24
- dsl_stack.last
25
- end
26
-
27
- def dsls
28
- static_expressions.values.map(&:keys).flatten.uniq
29
- end
30
-
31
- def disable_dsl(dsl_name)
32
- dsl_name = dsl_name.to_sym
33
- disabled_dsls << dsl_name
34
- end
35
-
36
- def enable_dsl(dsl_name)
37
- dsl_name = dsl_name.to_sym
38
- disabled_dsls.delete(dsl_name)
39
- end
40
-
41
- def disabled_dsls
42
- @disabled_dsls ||= []
43
- end
44
-
45
- def enabled_dsls=(dsl_names)
46
- dsls.each {|dsl_name| disable_dsl(dsl_name)}
47
- dsl_names.each {|dsl_name| enable_dsl(dsl_name)}
48
- end
49
-
50
- # Resets Glimmer's engine activity and configuration. Useful in rspec before or after blocks in tests.
51
- def reset
52
- parent_stacks.values.each do |a_parent_stack|
53
- a_parent_stack.clear
54
- end
55
- dsl_stack.clear
56
- disabled_dsls.clear
57
- end
58
-
59
- # Dynamic expression chains of responsibility indexed by dsl
60
- def dynamic_expression_chains_of_responsibility
61
- @dynamic_expression_chains_of_responsibility ||= {}
62
- end
63
-
64
- # Static expressions indexed by keyword and dsl
65
- def static_expressions
66
- @static_expressions ||= {}
67
- end
68
-
69
- # Sets an ordered array of DSL expressions to support
70
- #
71
- # Every expression has an underscored name corresponding to an upper
72
- # camelcase AbstractExpression subclass name in glimmer/dsl
73
- #
74
- # They are used in order following the Chain of Responsibility Design
75
- # Pattern when interpretting a DSL expression
76
- def add_dynamic_expressions(dsl_namespace, expression_names)
77
- dsl = dsl_namespace.name.split("::").last.downcase.to_sym
78
- dynamic_expression_chains_of_responsibility[dsl] = expression_names.reverse.map do |expression_name|
79
- expression_class(dsl_namespace, expression_name).new
80
- end.reduce(nil) do |last_expresion_handler, expression|
81
- Glimmer::Config.logger&.debug "Adding dynamic expression: #{expression.class.name}"
82
- expression_handler = ExpressionHandler.new(expression)
83
- expression_handler.next = last_expresion_handler if last_expresion_handler
84
- expression_handler
85
- end
86
- end
87
-
88
- def add_static_expression(static_expression)
89
- Glimmer::Config.logger&.debug "Adding static expression: #{static_expression.class.name}"
90
- keyword = static_expression.class.keyword
91
- static_expression_dsl = static_expression.class.dsl
92
- static_expressions[keyword] ||= {}
93
- static_expressions[keyword][static_expression_dsl] = static_expression
94
- Glimmer.send(:define_method, keyword) do |*args, &block|
95
- begin
96
- retrieved_static_expression = Glimmer::DSL::Engine.static_expressions[keyword][Glimmer::DSL::Engine.dsl]
97
- static_expression_dsl = (Glimmer::DSL::Engine.static_expressions[keyword].keys - Glimmer::DSL::Engine.disabled_dsls).last if retrieved_static_expression.nil?
98
- interpretation = nil
99
- if retrieved_static_expression.nil? && Glimmer::DSL::Engine.dsl && (static_expression_dsl.nil? || !Glimmer::DSL::Engine.static_expressions[keyword][static_expression_dsl].is_a?(TopLevelExpression))
100
- begin
101
- interpretation = Glimmer::DSL::Engine.interpret(keyword, *args, &block)
102
- rescue => e
103
- Glimmer::DSL::Engine.reset
104
- raise e if static_expression_dsl.nil? || !Glimmer::DSL::Engine.static_expressions[keyword][static_expression_dsl].is_a?(TopLevelExpression)
105
- end
106
- end
107
- if interpretation
108
- interpretation
109
- else
110
- raise Glimmer::Error, "Unsupported keyword: #{keyword}" unless static_expression_dsl || retrieved_static_expression
111
- Glimmer::DSL::Engine.dsl_stack.push(static_expression_dsl || Glimmer::DSL::Engine.dsl)
112
- static_expression = Glimmer::DSL::Engine.static_expressions[keyword][Glimmer::DSL::Engine.dsl]
113
- if !static_expression.can_interpret?(Glimmer::DSL::Engine.parent, keyword, *args, &block)
114
- raise Error, "Invalid use of Glimmer keyword #{keyword} with args #{args} under parent #{Glimmer::DSL::Engine.parent}"
115
- else
116
- Glimmer::Config.logger&.debug "#{static_expression.class.name} will handle expression keyword #{keyword}"
117
- static_expression.interpret(Glimmer::DSL::Engine.parent, keyword, *args, &block).tap do |ui_object|
118
- Glimmer::DSL::Engine.add_content(ui_object, static_expression, &block) unless block.nil?
119
- Glimmer::DSL::Engine.dsl_stack.pop
120
- end
121
- end
122
- end
123
- rescue StandardError => e
124
- # Glimmer::DSL::Engine.dsl_stack.pop
125
- Glimmer::DSL::Engine.reset
126
- raise e
127
- end
128
- end
129
- end
130
-
131
- def expression_class(dsl_namespace, expression_name)
132
- dsl_namespace.const_get(expression_class_name(expression_name).to_sym)
133
- end
134
-
135
- def expression_class_name(expression_name)
136
- "#{expression_name}_expression".camelcase(:upper)
137
- end
138
-
139
- # Interprets Glimmer dynamic DSL expression consisting of keyword, args, and block (e.g. shell(:no_resize) { ... })
140
- def interpret(keyword, *args, &block)
141
- keyword = keyword.to_s
142
- dynamic_expression_dsl = (dynamic_expression_chains_of_responsibility.keys - disabled_dsls).last if dsl.nil?
143
- dsl_stack.push(dynamic_expression_dsl || dsl)
144
- expression = dynamic_expression_chains_of_responsibility[dsl].handle(parent, keyword, *args, &block)
145
- expression.interpret(parent, keyword, *args, &block).tap do |ui_object|
146
- add_content(ui_object, expression, &block)
147
- dsl_stack.pop
148
- end
149
- rescue StandardError => e
150
- # dsl_stack.pop
151
- reset
152
- raise e
153
- end
154
-
155
- # Adds content block to parent UI object
156
- #
157
- # This allows evaluating parent UI object properties and children
158
- #
159
- # For example, a shell widget would get properties set and children added
160
- def add_content(parent, expression, &block)
161
- if block_given? && expression.is_a?(ParentExpression)
162
- dsl_stack.push(expression.class.dsl)
163
- parent_stack.push(parent)
164
- expression.add_content(parent, &block)
165
- parent_stack.pop
166
- dsl_stack.pop
167
- end
168
- end
169
-
170
- # Current parent while evaluating Glimmer DSL (nil if just started or done evaluatiing)
171
- #
172
- # Parents are maintained in a stack while evaluating Glimmer DSL
173
- # to ensure properly ordered interpretation of DSL syntax
174
- def parent
175
- parent_stack.last
176
- end
177
-
178
- def parent_stack
179
- parent_stacks[dsl] ||= []
180
- end
181
-
182
- def parent_stacks
183
- @parent_stacks ||= {}
184
- end
185
-
186
- # Enables multiple DSLs to play well with each other when mixing together
187
- def dsl_stack
188
- @dsl_stack ||= []
189
- end
190
- end
191
- end
192
- end
193
- end