glimmer-dsl-opal 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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