glimmer-dsl-web 0.10.3 → 0.10.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9612f4c1844bb9ccf62e32d1682a71bb933268fc9e9a74837a89a558001b96b0
4
- data.tar.gz: c6bffc8d775f74c96f13cad87702648f2da115fd7da7de998946a7dc33572410
3
+ metadata.gz: 64fc435ce1a727a890882f43c0851f932f699a610fbfea88041e0606f1fac8b7
4
+ data.tar.gz: da253a9bccb769f519c20f53810410360cd45034722fbe5083f2847c8e5f3080
5
5
  SHA512:
6
- metadata.gz: 5747a2f6092a03c2c0ae35c666f615aca23eac99b6b98eed533bf2876e747ca97bb33bd6a2f89285f34dcd0520873c2538e85306149cfbe5184fb921e4128928
7
- data.tar.gz: 381d39d680af48941b8282aa180e4f6cd6641f7c79e408739c4e2e4838507f7e084011408f59dc09c5183c39912ec8b1cf6abbdadcff0f0587ec6d9151104d82
6
+ metadata.gz: f67ac1fc2adadfd190106296d70fec7aa267368a7d33660836dde5198f9e4ad05942674707758ae10293c9c2213ad7031fd0f9ab9fc8a0ca75dd7cb8f1a75fa4
7
+ data.tar.gz: aa2115656cc49ec3eafe7f2717051dd6fda8bec038906fcbc574d25265a094231b7409ecd2c49ada131515365729f2bf6fc0331bc5cbe68e07b69cb35967307c
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.10.4
4
+
5
+ - Support `parent.insert_at(index) {}` on `ElementProxy` and `Glimmer::Web::Component`, which is a method that inserts elements to the content of a parent element at a specified index
6
+ - Support `parent.insert(index) {}` alias for `parent.insert_at(index) {}`
7
+ - Update Hello, Mutation! sample with "Insert list item" functionality
8
+ - Update Hello, Mutation Content Data-Binding! sample with "Insert list item" functionality
9
+ - Document DOM mutation operations in README
10
+
3
11
  ## 0.10.3
4
12
 
5
13
  - Support `parent.prepend {}` on `ElementProxy` and `Glimmer::Web::Component`, which is a method that prepends elements to the content of a parent element
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Web 0.10.3 (Beta)
1
+ # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for Web 0.10.4 (Beta)
2
2
  ## Ruby-in-the-Browser Web Frontend Framework
3
3
  ### The "Rails" of Frontend Frameworks!!! ([Fukuoka Award Winning](https://andymaleh.blogspot.com/2025/01/glimmer-dsl-for-web-wins-in-fukuoka.html))
4
4
  #### Finally, Ruby Developer Productivity, Happiness, and Fun in the Frontend!!!
@@ -1498,6 +1498,52 @@ p(class: 'summary') {
1498
1498
 
1499
1499
  You can get/set any element property or invoke any element function by simply calling the lowercase underscored version of their name in Ruby like `input.check_validity`, `input.value`, and `input.id`.
1500
1500
 
1501
+ Additionally, these DOM mutation operations are available as methods on elements/components acting as parents:
1502
+ - `parent.append { }` : apprends elements inside the content of the parent
1503
+ - `parent.prepend { }` : prepends elements inside the content of the parent
1504
+ - `parent.insert_at(index) { }` : inserts elements inside the content of the parent (`insert` is an alias for `insert_at`)
1505
+
1506
+ Example:
1507
+
1508
+ ```ruby
1509
+ div {
1510
+ div(class: 'actions') {
1511
+ @input = input(placeholder: 'Enter list item content')
1512
+
1513
+ @append_button = button('Append list item') {
1514
+ onclick do
1515
+ @list.append { # DOM mutation operation
1516
+ li { @input.value }
1517
+ }
1518
+ @input.value = ''
1519
+ @input.focus
1520
+ end
1521
+ }
1522
+ }
1523
+
1524
+ @list = ul
1525
+ }
1526
+ ```
1527
+
1528
+ Specifically, this line:
1529
+
1530
+ ```ruby
1531
+ @list.append {
1532
+ li { @input.value }
1533
+ }
1534
+ ```
1535
+
1536
+ You can append multiple elements too. Here is a different hypothetical example:
1537
+
1538
+ ```ruby
1539
+ @some_div.append {
1540
+ h1 { @post.title }
1541
+ p { @post.content }
1542
+ }
1543
+ ```
1544
+
1545
+ DOM mutation operations are useful for adding elements after the fact of initial rendering of the page as triggered by a user action or some system timer.
1546
+
1501
1547
  Next, check out [Samples](#samples).
1502
1548
 
1503
1549
  Note that for serious app usage, it is recommended to build [components](#hello-component) and use the [`glimmer_component` Rails Helper](#hello-glimmer_component-rails-helper) to embed the top-level Web Frontend component in a Rails View.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.10.3
1
+ 0.10.4
@@ -2,11 +2,11 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: glimmer-dsl-web 0.10.3 ruby lib
5
+ # stub: glimmer-dsl-web 0.10.4 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "glimmer-dsl-web".freeze
9
- s.version = "0.10.3".freeze
9
+ s.version = "0.10.4".freeze
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
@@ -119,7 +119,7 @@ Gem::Specification.new do |s|
119
119
 
120
120
  s.specification_version = 4
121
121
 
122
- s.add_runtime_dependency(%q<glimmer>.freeze, ["~> 2.8.2".freeze])
122
+ s.add_runtime_dependency(%q<glimmer>.freeze, ["~> 2.8.3".freeze])
123
123
  s.add_runtime_dependency(%q<glimmer-dsl-xml>.freeze, ["~> 1.4.0".freeze])
124
124
  s.add_runtime_dependency(%q<glimmer-dsl-css>.freeze, ["~> 1.5.2".freeze])
125
125
  s.add_runtime_dependency(%q<opal>.freeze, [">= 1.8.2".freeze, "< 2.0.0".freeze])
@@ -14,7 +14,9 @@ module Glimmer
14
14
  def add_content(parent, keyword, *args, &block)
15
15
  options = args.last.is_a?(Hash) ? args.last : {}
16
16
  parent_original_add_child_mutation = parent&.add_child_mutation
17
+ parent_original_insert_index = parent&.insert_index
17
18
  parent&.add_child_mutation = options[:add_child_mutation] if options[:add_child_mutation]
19
+ parent&.insert_index = options[:insert_index] if options[:insert_index]
18
20
  if parent.bulk_render? || parent.rendered? || parent.skip_content_on_render_blocks?
19
21
  return_value = super(parent, keyword, *args, &block)
20
22
  parent.add_text_content(return_value, on_empty: true) if return_value.is_a?(String)
@@ -25,6 +27,7 @@ module Glimmer
25
27
  end
26
28
  ensure
27
29
  parent&.add_child_mutation = parent_original_add_child_mutation
30
+ parent&.insert_index = parent_original_insert_index
28
31
  end
29
32
  end
30
33
  end
@@ -516,6 +516,11 @@ module Glimmer
516
516
  @markup_root.prepend(bulk_render:, &block)
517
517
  end
518
518
 
519
+ def insert_at(index, bulk_render: false, &block)
520
+ @markup_root.insert_at(index, bulk_render:, &block)
521
+ end
522
+ alias insert insert_at
523
+
519
524
  def remove_all_listeners
520
525
  data_bindings.each do |option_binding, model_binding|
521
526
  option_binding.unregister_all_observables
@@ -176,6 +176,7 @@ module Glimmer
176
176
  REGEX_CLASS_NAME_SUB_PROPERTY = /^(class_name)_(.*)$/
177
177
 
178
178
  attr_reader :keyword, :parent, :parent_component, :ancestor_component, :component, :args, :options, :slot, :children, :enabled, :foreground, :background, :removed, :rendered
179
+ attr_accessor :insert_index # to be used when add_child_mutation is insert_at
179
180
  alias rendered? rendered
180
181
  alias removed? removed
181
182
 
@@ -223,7 +224,14 @@ module Glimmer
223
224
 
224
225
  # Executes for the parent of a child that just got added
225
226
  def post_initialize_child(child)
226
- @children << child
227
+ case parent&.add_child_mutation
228
+ when :prepend
229
+ @children.prepend(child)
230
+ when :insert_at
231
+ @children.insert(parent&.insert_index, child)
232
+ else # append
233
+ @children << child
234
+ end
227
235
  child.render if !bulk_render? && !render_after_create?
228
236
  end
229
237
 
@@ -445,7 +453,7 @@ module Glimmer
445
453
  brand_new ||= @dom.nil? || !options[:parent].to_s.empty? || (old_element = dom_element).empty?
446
454
  build_dom(layout: !custom_parent_dom_element) # TODO handle custom parent layout by passing parent instead of parent dom element
447
455
  if brand_new
448
- attach(the_parent_dom_element, add_child_mutation: self.parent&.add_child_mutation || :append)
456
+ attach(the_parent_dom_element, add_child_mutation: self.parent&.add_child_mutation, insert_index: self.parent&.insert_index)
449
457
  else
450
458
  reattach(old_element)
451
459
  end
@@ -458,10 +466,17 @@ module Glimmer
458
466
  end
459
467
  alias rerender render
460
468
 
461
- def attach(the_parent_dom_element, add_child_mutation: :append)
462
- if add_child_mutation == :prepend
469
+ def attach(the_parent_dom_element, add_child_mutation: :append, insert_index: nil)
470
+ case add_child_mutation
471
+ when :prepend
463
472
  the_parent_dom_element.prepend(@dom)
464
- else
473
+ when :insert_at
474
+ if insert_index == the_parent_dom_element.children.size
475
+ the_parent_dom_element.append(@dom)
476
+ else
477
+ the_parent_dom_element.children.eq(insert_index).before(@dom)
478
+ end
479
+ else # append
465
480
  the_parent_dom_element.append(@dom)
466
481
  end
467
482
  end
@@ -568,10 +583,10 @@ module Glimmer
568
583
  @add_child_mutation = value
569
584
  end
570
585
 
571
- def content(bulk_render: false, add_child_mutation: :append, &block)
586
+ def content(bulk_render: false, add_child_mutation: :append, insert_index: nil, &block)
572
587
  original_bulk_render = options[:bulk_render]
573
588
  options[:bulk_render] = bulk_render if rendered?
574
- return_value = Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Web::ElementExpression.new, keyword, add_child_mutation:, &block)
589
+ return_value = Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Web::ElementExpression.new, keyword, add_child_mutation:, insert_index:, &block)
575
590
  options[:bulk_render] = original_bulk_render if rendered?
576
591
  return_value
577
592
  end
@@ -581,6 +596,12 @@ module Glimmer
581
596
  content(bulk_render:, add_child_mutation: :prepend, &block)
582
597
  end
583
598
 
599
+ def insert_at(index, bulk_render: false, &block)
600
+ index = index.to_i if index.is_a?(String) && index.match(/^\d+$/)
601
+ content(bulk_render:, add_child_mutation: :insert_at, insert_index: index, &block)
602
+ end
603
+ alias insert insert_at
604
+
584
605
  # Subclasses must override with their own mappings
585
606
  def observation_request_to_event_mapping
586
607
  {}
@@ -1,49 +1,93 @@
1
1
  require 'glimmer-dsl-web'
2
2
 
3
- class HelloMutation
4
- include Glimmer::Web::Component
5
-
6
- markup {
7
- div {
8
- h1('Hello, Mutation!')
9
-
10
- p {
11
- 'Add items to a list via element DOM mutations.'
12
- }
13
-
14
- div(class: 'actions') {
15
- @input = input(placeholder: 'Enter list item content')
3
+ unless Object.const_defined?(:HelloMutation) # this is only needed in sample selector app due to file reloading, but not in real apps.
4
+ class HelloMutation
5
+ include Glimmer::Web::Component
6
+
7
+ after_render do
8
+ @append_button.disabled = @prepend_button.disabled = @insert_button.disabled = true
9
+ end
10
+
11
+ markup {
12
+ div {
13
+ h1('Hello, Mutation!')
16
14
 
17
- button('Append list item') {
18
- onclick do
19
- @list.append {
20
- li { @input.value }
21
- }
22
- @input.value = ''
23
- @input.focus
24
- end
15
+ p {
16
+ 'Add items to a list via element DOM mutations.'
25
17
  }
26
18
 
27
- button('Prepend list item') {
28
- onclick do
29
- @list.prepend {
30
- li { @input.value }
31
- }
32
- @input.value = ''
33
- @input.focus
34
- end
19
+ div(class: 'actions') {
20
+ @input = input(placeholder: 'Enter list item content') {
21
+ oninput do
22
+ if @input.value.to_s.strip == ''
23
+ @append_button.disabled = @prepend_button.disabled = @insert_button.disabled = true
24
+ else
25
+ @append_button.disabled = @prepend_button.disabled = @insert_button.disabled = false
26
+ end
27
+ end
28
+ }
29
+
30
+ @append_button = button('Append list item') {
31
+ onclick do
32
+ @list.append {
33
+ li { @input.value }
34
+ }
35
+ @append_button.disabled = @prepend_button.disabled = @insert_button.disabled = true
36
+ @input.value = ''
37
+ @input.focus
38
+ end
39
+ }
40
+
41
+ @prepend_button = button('Prepend list item') {
42
+ onclick do
43
+ @list.prepend {
44
+ li { @input.value }
45
+ }
46
+ @append_button.disabled = @prepend_button.disabled = @insert_button.disabled = true
47
+ @input.value = ''
48
+ @input.focus
49
+ end
50
+ }
51
+
52
+ @insert_button = button('Insert list item') {
53
+ onclick do
54
+ index = [@insert_index_input.value.to_i, @list.children.size].min
55
+ @list.insert_at(index) {
56
+ li { @input.value }
57
+ }
58
+ @append_button.disabled = @prepend_button.disabled = @insert_button.disabled = true
59
+ @input.value = ''
60
+ @input.focus
61
+ end
62
+ }
63
+
64
+ label(for: 'insert-index-input') { 'at index: ' }
65
+ @insert_index_input = input(id: 'insert-index-input', type: 'number', value: 0, min: 0) {
66
+ oninput do
67
+ max_value = @list.children.size
68
+ @insert_index_input.value = max_value if @insert_index_input.value.to_i > max_value
69
+ end
70
+ }
35
71
  }
72
+
73
+ @list = ul
36
74
  }
37
-
38
- @list = ul
39
75
  }
40
- }
41
-
42
- style {
43
- r('.actions input, .actions button') {
44
- margin '10px 10px 10px 0'
76
+
77
+ style {
78
+ r('.actions input, .actions button') {
79
+ margin '10px 10px 10px 0'
80
+ }
81
+
82
+ r('.actions input#insert-index-input') {
83
+ width 40
84
+ }
85
+
86
+ r('.actions label[for=insert-index-input]') {
87
+ margin_left -5
88
+ }
45
89
  }
46
- }
90
+ end
47
91
  end
48
92
 
49
93
  Document.ready? do
@@ -1,81 +1,123 @@
1
1
  require 'glimmer-dsl-web'
2
2
 
3
- class ListPresenter
4
- attr_accessor :list, :new_list_item
5
-
6
- def initialize
7
- @list = []
8
- @new_list_item = ''
9
- end
10
-
11
- def append_list_item
12
- list.push(new_list_item)
13
- clear_new_list_item
14
- end
15
-
16
- def prepend_list_item
17
- list.prepend(new_list_item)
18
- clear_new_list_item
19
- end
20
-
21
- def clear_new_list_item
22
- self.new_list_item = ''
23
- end
24
-
25
- def entering_new_list_item?
26
- new_list_item.empty?
3
+ unless Object.const_defined?(:ListPresenter) # this is only needed in sample selector app due to file reloading, but not in real apps.
4
+ class ListPresenter
5
+ attr_accessor :list, :new_list_item, :insert_index
6
+
7
+ def initialize
8
+ @list = []
9
+ @new_list_item = ''
10
+ @insert_index = 0
11
+ end
12
+
13
+ def append_list_item
14
+ list.push(new_list_item)
15
+ clear_new_list_item
16
+ end
17
+
18
+ def prepend_list_item
19
+ list.prepend(new_list_item)
20
+ clear_new_list_item
21
+ end
22
+
23
+ def insert_list_item
24
+ list.insert(insert_index, new_list_item)
25
+ clear_new_list_item
26
+ end
27
+
28
+ def clear_new_list_item
29
+ self.new_list_item = ''
30
+ end
31
+
32
+ def entering_new_list_item?
33
+ new_list_item.empty?
34
+ end
35
+ alias edit_list_disabled? entering_new_list_item?
36
+
37
+ def max_insert_index
38
+ list.size
39
+ end
27
40
  end
28
41
  end
29
42
 
30
- class HelloMutationContentDataBinding
31
- include Glimmer::Web::Component
32
-
33
- before_render do
34
- @list_presenter = ListPresenter.new
35
- end
36
-
37
- markup {
38
- div {
39
- h1('Hello, Mutation Content Data-Binding!')
40
-
41
- p {
42
- 'Add items to a list via content data-binding (which performs implicit DOM mutations).'
43
- }
44
-
45
- div(class: 'actions') {
46
- @input = input(placeholder: 'Enter list item content') {
47
- value <=> [@list_presenter, :new_list_item]
48
- focused <= [@list_presenter, :entering_new_list_item?, computed_by: :new_list_item]
43
+ unless Object.const_defined?(:HelloMutationContentDataBinding) # this is only needed in sample selector app due to file reloading, but not in real apps.
44
+ class HelloMutationContentDataBinding
45
+ include Glimmer::Web::Component
46
+
47
+ before_render do
48
+ @list_presenter = ListPresenter.new
49
+ end
50
+
51
+ markup {
52
+ div {
53
+ h1('Hello, Mutation Content Data-Binding!')
54
+
55
+ p {
56
+ 'Add items to a list via content data-binding (which performs implicit DOM mutations).'
49
57
  }
50
58
 
51
- button('Append list item') {
52
- onclick do
53
- @list_presenter.append_list_item
54
- end
59
+ div(class: 'actions') {
60
+ input(placeholder: 'Enter list item content') {
61
+ value <=> [@list_presenter, :new_list_item]
62
+ focused <= [@list_presenter, :entering_new_list_item?, computed_by: :new_list_item]
63
+ }
64
+
65
+ button('Append list item') {
66
+ disabled <= [@list_presenter, :edit_list_disabled?, computed_by: :new_list_item]
67
+
68
+ onclick do
69
+ @list_presenter.append_list_item
70
+ end
71
+ }
72
+
73
+ button('Prepend list item') {
74
+ disabled <= [@list_presenter, :edit_list_disabled?, computed_by: :new_list_item]
75
+
76
+ onclick do
77
+ @list_presenter.prepend_list_item
78
+ end
79
+ }
80
+
81
+ button('Insert list item') {
82
+ disabled <= [@list_presenter, :edit_list_disabled?, computed_by: :new_list_item]
83
+
84
+ onclick do
85
+ @list_presenter.insert_list_item
86
+ end
87
+ }
88
+
89
+ label(for: 'insert-index-input') { 'at index: ' }
90
+ input(id: 'insert-index-input', type: 'number') {
91
+ value <=> [@list_presenter, :insert_index]
92
+ min 0
93
+ max <= [@list_presenter, :max_insert_index, computed_by: :list]
94
+ }
55
95
  }
56
96
 
57
- button('Prepend list item') {
58
- onclick do
59
- @list_presenter.prepend_list_item
60
- end
97
+ ul {
98
+ content(@list_presenter, :list) {
99
+ @list_presenter.list.each do |list_item|
100
+ li { list_item }
101
+ end
102
+ }
61
103
  }
62
104
  }
105
+ }
106
+
107
+ style {
108
+ r('.actions input, .actions button') {
109
+ margin '10px 10px 10px 0'
110
+ }
63
111
 
64
- ul {
65
- content(@list_presenter, :list) {
66
- @list_presenter.list.each do |list_item|
67
- li { list_item }
68
- end
69
- }
112
+ r('.actions input#insert-index-input') {
113
+ width 40
114
+ }
115
+
116
+ r('.actions label[for=insert-index-input]') {
117
+ margin_left -5
70
118
  }
71
119
  }
72
- }
73
-
74
- style {
75
- r('.actions input, .actions button') {
76
- margin '10px 10px 10px 0'
77
- }
78
- }
120
+ end
79
121
  end
80
122
 
81
123
  Document.ready? do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-dsl-web
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.3
4
+ version: 0.10.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 2.8.2
18
+ version: 2.8.3
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: 2.8.2
25
+ version: 2.8.3
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: glimmer-dsl-xml
28
28
  requirement: !ruby/object:Gem::Requirement