glimmer-dsl-opal 0.0.4 → 0.0.9

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/README.md +983 -34
  4. data/VERSION +1 -1
  5. data/lib/glimmer-dsl-opal.rb +5 -2
  6. data/lib/glimmer/data_binding/ext/observable_model.rb +40 -0
  7. data/lib/glimmer/data_binding/table_items_binding.rb +70 -0
  8. data/lib/glimmer/dsl/opal/async_exec_expression.rb +17 -0
  9. data/lib/glimmer/dsl/opal/browser_expression.rb +17 -0
  10. data/lib/glimmer/dsl/opal/column_properties_expression.rb +22 -0
  11. data/lib/glimmer/dsl/opal/dsl.rb +11 -0
  12. data/lib/glimmer/dsl/opal/message_box_expression.rb +20 -0
  13. data/lib/glimmer/dsl/opal/observe_expression.rb +32 -0
  14. data/lib/glimmer/dsl/opal/tab_folder_expression.rb +17 -0
  15. data/lib/glimmer/dsl/opal/tab_item_expression.rb +17 -0
  16. data/lib/glimmer/dsl/opal/table_column_expression.rb +17 -0
  17. data/lib/glimmer/dsl/opal/table_expression.rb +17 -0
  18. data/lib/glimmer/dsl/opal/table_items_data_binding_expression.rb +29 -0
  19. data/lib/glimmer/opal/display_proxy.rb +23 -0
  20. data/lib/glimmer/opal/div_proxy.rb +11 -2
  21. data/lib/glimmer/opal/document_proxy.rb +124 -4
  22. data/lib/glimmer/opal/element_proxy.rb +45 -14
  23. data/lib/glimmer/opal/grid_layout_proxy.rb +3 -1
  24. data/lib/glimmer/opal/iframe_proxy.rb +23 -0
  25. data/lib/glimmer/opal/input_proxy.rb +8 -4
  26. data/lib/glimmer/opal/label_proxy.rb +1 -1
  27. data/lib/glimmer/opal/layout_data_proxy.rb +23 -2
  28. data/lib/glimmer/opal/list_proxy.rb +2 -2
  29. data/lib/glimmer/opal/modal.rb +94 -0
  30. data/lib/glimmer/opal/point.rb +5 -0
  31. data/lib/glimmer/opal/select_proxy.rb +1 -1
  32. data/lib/glimmer/opal/tab_folder.rb +53 -0
  33. data/lib/glimmer/opal/tab_item.rb +98 -0
  34. data/lib/glimmer/opal/table_column.rb +50 -0
  35. data/lib/glimmer/opal/table_item.rb +136 -0
  36. data/lib/glimmer/opal/table_proxy.rb +149 -0
  37. data/lib/samples/elaborate/contact_manager.rb +1 -2
  38. data/lib/samples/elaborate/login.rb +0 -1
  39. data/lib/samples/elaborate/tic_tac_toe.rb +5 -5
  40. data/lib/samples/hello/hello_tab.rb +2 -2
  41. metadata +28 -16
  42. data/lib/glimmer/config.rb +0 -22
  43. data/lib/glimmer/dsl/engine.rb +0 -193
  44. data/lib/glimmer/dsl/expression.rb +0 -42
  45. data/lib/glimmer/dsl/expression_handler.rb +0 -48
  46. data/lib/glimmer/dsl/parent_expression.rb +0 -12
  47. data/lib/glimmer/dsl/static_expression.rb +0 -36
  48. data/lib/glimmer/dsl/top_level_expression.rb +0 -7
  49. data/lib/glimmer/error.rb +0 -6
  50. data/lib/glimmer/invalid_keyword_error.rb +0 -6
@@ -5,26 +5,54 @@ module Glimmer
5
5
  class ElementProxy
6
6
  include Glimmer
7
7
  include PropertyOwner
8
- attr_reader :parent, :args, :css_classes, :style
8
+ attr_reader :parent, :args, :css_classes, :css, :children, :enabled
9
+
10
+ class << self
11
+ def next_id_number_for(name)
12
+ @max_id_numbers[name] = max_id_number_for(name) + 1
13
+ end
14
+
15
+ def max_id_number_for(name)
16
+ @max_id_numbers[name] = max_id_numbers[name] || 0
17
+ end
18
+
19
+ def max_id_numbers
20
+ @max_id_numbers ||= {}
21
+ end
22
+ end
9
23
 
10
24
  def initialize(parent, args)
11
25
  @parent = parent
12
26
  @args = args
13
- @children = []
14
- @parent.add_child(self)
27
+ @children = Set.new
15
28
  @css_classes = Set.new
29
+ @css = ''
30
+ @enabled = true
31
+ @parent.add_child(self)
16
32
  end
17
33
 
18
34
  def add_child(child)
19
- return if @children.include?(child)
35
+ # return if @children.include?(child) # TODO consider adding an option to enable this if needed to prevent dom repetition
20
36
  @children << child
21
37
  dom << child.dom
22
38
  end
39
+
40
+ def enabled=(value)
41
+ @enabled = value
42
+ redraw
43
+ end
23
44
 
24
45
  def redraw
25
- old_dom = @dom
26
- @dom = nil
27
- old_dom.replace dom
46
+ if @dom
47
+ old_dom = @dom
48
+ @dom = nil
49
+ old_dom.replace dom
50
+ else
51
+ dom
52
+ end
53
+ @children.each do |child|
54
+ child.redraw
55
+ end
28
56
  end
29
57
 
30
58
  # Subclasses must override with their own mappings
@@ -37,9 +65,14 @@ module Glimmer
37
65
  end
38
66
 
39
67
  def id
40
- "#{name}-#{hash}"
68
+ @id ||= "#{name}-#{ElementProxy.next_id_number_for(name)}"
41
69
  end
42
-
70
+
71
+ # Sets id explicitly. Useful in cases of wanting to maintain a stable id
72
+ def id=(value)
73
+ @id = value
74
+ end
75
+
43
76
  # Subclasses can override with their own selector
44
77
  def selector
45
78
  "#{name}##{id}"
@@ -70,10 +103,8 @@ module Glimmer
70
103
  redraw
71
104
  end
72
105
 
73
- # TODO rename to avoid conflict with SWT Style verbiage
74
-
75
- def style=(css)
76
- @style = css
106
+ def css=(css)
107
+ @css = css
77
108
  redraw
78
109
  end
79
110
 
@@ -181,7 +212,7 @@ module Glimmer
181
212
  # },
182
213
  InputProxy => {
183
214
  :text => lambda do |observer|
184
- on_modify_text { |modify_event|
215
+ on_modify_text { |modify_event|
185
216
  observer.call(text)
186
217
  }
187
218
  end,
@@ -10,7 +10,9 @@ module Glimmer
10
10
  @parent = parent
11
11
  @args = args
12
12
  @parent.add_css_class('grid-layout')
13
+ @horizontal_spacing = 10
13
14
  @vertical_spacing = 10
15
+ @num_columns = @args.first || 1
14
16
  reapply
15
17
  end
16
18
 
@@ -39,7 +41,7 @@ module Glimmer
39
41
  end
40
42
 
41
43
  def reapply
42
- @parent.style = <<~CSS
44
+ @parent.css = <<~CSS
43
45
  display: grid;
44
46
  grid-template-columns: #{'auto ' * @num_columns.to_i};
45
47
  grid-row-gap: #{@vertical_spacing}px;
@@ -0,0 +1,23 @@
1
+ require 'glimmer/opal/element_proxy'
2
+
3
+ module Glimmer
4
+ module Opal
5
+ class IframeProxy < ElementProxy
6
+ attr_reader :url
7
+
8
+ def url=(value)
9
+ @url = value
10
+ redraw
11
+ end
12
+
13
+ def dom
14
+ iframe_id = id
15
+ iframe_url = url
16
+ @dom ||= DOM {
17
+ iframe(src: iframe_url, frameBorder: 0) {
18
+ }
19
+ }
20
+ end
21
+ end
22
+ end
23
+ end
@@ -19,8 +19,10 @@ module Glimmer
19
19
  event: 'keyup',
20
20
  event_handler: -> (event_listener) {
21
21
  -> (event) {
22
- @text = event.target.value
23
- event_listener.call(event)
22
+ if args.last[:type] == 'text'
23
+ @text = event.target.value
24
+ event_listener.call(event)
25
+ end
24
26
  }
25
27
  }
26
28
  }
@@ -30,10 +32,12 @@ module Glimmer
30
32
  def dom
31
33
  input_text = @text
32
34
  input_id = id
33
- input_style = style
35
+ input_style = css
34
36
  input_args = @args.last
37
+ input_disabled = @enabled ? {} : {'disabled': 'disabled'}
38
+ input_args = input_args.merge(type: 'password') if has_style?(:password)
35
39
  @dom ||= DOM {
36
- input input_args.merge(id: input_id, style: input_style, value: input_text)
40
+ input input_args.merge(id: input_id, style: input_style, value: input_text, style: 'min-width: 27px;').merge(input_disabled)
37
41
  }
38
42
  end
39
43
  end
@@ -13,7 +13,7 @@ module Glimmer
13
13
  def dom
14
14
  label_text = @text
15
15
  label_id = id
16
- label_style = style
16
+ label_style = css
17
17
  @dom ||= DOM {
18
18
  label(id: label_id, style: label_style) {
19
19
  label_text
@@ -4,7 +4,13 @@ module Glimmer
4
4
  module Opal
5
5
  class LayoutDataProxy
6
6
  include PropertyOwner
7
- attr_reader :parent, :args, :horizontal_alignment, :grab_excess_horizontal_space
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,18 +18,33 @@ 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
- # @parent.style = <<~CSS
47
+ # @parent.css = <<~CSS
27
48
  # CSS
28
49
  end
29
50
  end
@@ -60,13 +60,13 @@ module Glimmer
60
60
  def dom
61
61
  list_items = @items
62
62
  list_id = id
63
- list_style = style
63
+ list_style = css
64
64
  list_selection = selection
65
65
  @dom ||= DOM {
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-list-item' if list_selection.include?(item)
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
@@ -0,0 +1,94 @@
1
+ require 'glimmer/opal/element_proxy'
2
+
3
+ module Glimmer
4
+ module Opal
5
+ class Modal < ElementProxy
6
+ attr_reader :text, :message
7
+
8
+ def initialize(parent, args)
9
+ i = 0
10
+ @parent = parent
11
+ @args = args
12
+ @children = Set.new
13
+ @css_classes = Set.new(['modal'])
14
+ @css = ''
15
+ @enabled = true
16
+ content do
17
+ on_widget_selected {
18
+ hide
19
+ }
20
+ end
21
+ end
22
+
23
+ def text=(txt)
24
+ @text = txt
25
+ redraw if @dom
26
+ end
27
+
28
+ def message=(msg)
29
+ @message = msg
30
+ redraw if @dom
31
+ end
32
+
33
+ def document
34
+ element = self
35
+ begin
36
+ element = element.parent
37
+ end while(element.parent)
38
+ element
39
+ end
40
+
41
+ def open
42
+ document.add_child(self)
43
+ end
44
+
45
+ def hide
46
+ dom.remove
47
+ end
48
+
49
+ def content(&block)
50
+ Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Opal::MessageBoxExpression.new, &block)
51
+ end
52
+
53
+ def name
54
+ 'div'
55
+ end
56
+
57
+ def selector
58
+ super + ' .close'
59
+ end
60
+
61
+ def observation_request_to_event_mapping
62
+ {
63
+ 'on_widget_selected' => {
64
+ event: 'click'
65
+ },
66
+ }
67
+ end
68
+
69
+ def dom
70
+ modal_id = id
71
+ modal_style = css
72
+ modal_text = text
73
+ modal_message = message
74
+ modal_css_classes = css_classes
75
+ modal_class = modal_css_classes.to_a.join(' ')
76
+ @dom ||= DOM {
77
+ div(id: modal_id, style: modal_style, class: modal_class) {
78
+ div(class: 'modal-content') {
79
+ header.text {
80
+ modal_text
81
+ }
82
+ p.message {
83
+ modal_message
84
+ }
85
+ input(type: 'button', class: 'close', autofocus: 'autofocus', value: 'OK')
86
+ }
87
+ }
88
+ }
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ require 'glimmer/dsl/opal/message_box_expression'
@@ -0,0 +1,5 @@
1
+ module Glimmer
2
+ module Opal
3
+ Point = Struct.new(:x, :y)
4
+ end
5
+ end
@@ -41,7 +41,7 @@ module Glimmer
41
41
  select_text = @text
42
42
  items = @items
43
43
  select_id = id
44
- select_style = style
44
+ select_style = css
45
45
  @dom ||= DOM {
46
46
  select(id: select_id, style: select_style) {
47
47
  items.to_a.each do |item|
@@ -0,0 +1,53 @@
1
+ require 'glimmer/opal/element_proxy'
2
+
3
+ module Glimmer
4
+ module Opal
5
+ class TabFolder < ElementProxy
6
+ attr_reader :tabs
7
+
8
+ def initialize(parent, args)
9
+ super(parent, args)
10
+ @tabs = []
11
+ end
12
+
13
+ def add_child(child)
14
+ super(child)
15
+ if @children.size == 1
16
+ child.show
17
+ 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
26
+
27
+ def hide_all_tab_content
28
+ @children.each(&:hide)
29
+ end
30
+
31
+ def name
32
+ 'div'
33
+ end
34
+
35
+ def tabs_dom
36
+ tabs_id = id + '-tabs'
37
+ @tabs_dom ||= DOM {
38
+ div(id: tabs_id, class: 'tabs')
39
+ }
40
+ end
41
+
42
+ def dom
43
+ tab_folder_id = id
44
+ tab_folder_id_style = css
45
+ @dom ||= DOM {
46
+ div(id: tab_folder_id, style: tab_folder_id_style, class: 'tab-folder') {
47
+
48
+ }
49
+ }.tap {|the_dom| the_dom << tabs_dom }
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,98 @@
1
+ require 'glimmer/opal/div_proxy'
2
+
3
+ module Glimmer
4
+ module Opal
5
+ class TabItem < DivProxy
6
+ include Glimmer
7
+ attr_reader :text, :content_visible
8
+
9
+ def initialize(parent, args)
10
+ super(parent, args)
11
+ css_classes << 'tab-item'
12
+ content do
13
+ on_widget_selected {
14
+ @parent.hide_all_tab_content
15
+ show
16
+ }
17
+ end
18
+ end
19
+
20
+ def content(&block)
21
+ Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Opal::TabItemExpression.new, &block)
22
+ end
23
+
24
+ def show
25
+ @content_visible = true
26
+ redraw
27
+ end
28
+
29
+ def hide
30
+ @content_visible = false
31
+ redraw
32
+ end
33
+
34
+ def text=(value)
35
+ @text = value
36
+ redraw
37
+ end
38
+
39
+ def name
40
+ 'button'
41
+ end
42
+
43
+ def selector
44
+ super + '-tab'
45
+ end
46
+
47
+ def observation_request_to_event_mapping
48
+ {
49
+ 'on_widget_selected' => {
50
+ event: 'click'
51
+ },
52
+ }
53
+ end
54
+
55
+ def redraw
56
+ if @tab_dom
57
+ old_tab_dom = @tab_dom
58
+ @tab_dom = nil
59
+ old_tab_dom.replace tab_dom
60
+ else
61
+ tab_dom
62
+ end
63
+ super
64
+ end
65
+
66
+ def tab_dom
67
+ tab_id = id + '-tab'
68
+ tab_text = text
69
+ tab_active = content_visible ? 'active' : ''
70
+ @tab_dom ||= DOM {
71
+ button(id: tab_id, class: "tab #{tab_active}") {
72
+ tab_text
73
+ }
74
+ }
75
+ end
76
+
77
+ def dom
78
+ tab_item_id = id
79
+ tab_item_id_style = css
80
+ tab_item_css_classes = css_classes
81
+ if content_visible
82
+ tab_item_css_classes.delete('hide')
83
+ else
84
+ tab_item_css_classes << 'hide'
85
+ end
86
+ if !@parent.tabs.include?(self)
87
+ @parent.tabs_dom << tab_dom
88
+ @parent.tabs << self
89
+ end
90
+ @dom ||= DOM {
91
+ div(id: tab_item_id, style: tab_item_id_style, class: tab_item_css_classes.to_a.join(' ')) {
92
+ }
93
+ }
94
+ end
95
+ end
96
+ end
97
+ end
98
+ require 'glimmer/dsl/opal/tab_item_expression'