glimmer-dsl-web 0.10.2 → 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 +4 -4
- data/CHANGELOG.md +16 -1
- data/README.md +47 -1
- data/VERSION +1 -1
- data/glimmer-dsl-web.gemspec +5 -3
- data/lib/glimmer/dsl/web/general_element_expression.rb +8 -0
- data/lib/glimmer/web/component.rb +17 -0
- data/lib/glimmer/web/element_proxy.rb +54 -6
- data/lib/glimmer-dsl-web/samples/hello/hello_component_slots.rb +109 -105
- data/lib/glimmer-dsl-web/samples/hello/hello_mutation.rb +95 -0
- data/lib/glimmer-dsl-web/samples/hello/hello_mutation_content_data_binding.rb +125 -0
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 64fc435ce1a727a890882f43c0851f932f699a610fbfea88041e0606f1fac8b7
|
|
4
|
+
data.tar.gz: da253a9bccb769f519c20f53810410360cd45034722fbe5083f2847c8e5f3080
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f67ac1fc2adadfd190106296d70fec7aa267368a7d33660836dde5198f9e4ad05942674707758ae10293c9c2213ad7031fd0f9ab9fc8a0ca75dd7cb8f1a75fa4
|
|
7
|
+
data.tar.gz: aa2115656cc49ec3eafe7f2717051dd6fda8bec038906fcbc574d25265a094231b7409ecd2c49ada131515365729f2bf6fc0331bc5cbe68e07b69cb35967307c
|
data/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
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
|
+
|
|
11
|
+
## 0.10.3
|
|
12
|
+
|
|
13
|
+
- Support `parent.prepend {}` on `ElementProxy` and `Glimmer::Web::Component`, which is a method that prepends elements to the content of a parent element
|
|
14
|
+
- Support `element.focused` & `element.focused=` methods, including `focused` data-binding support. Note that setting `element.focused=` as `true` gives an element focus, but setting it to `false` does not change focus (you would have to set another element as focused to remove focus from a previous element).
|
|
15
|
+
- Hello, Mutation! sample: `require 'glimmer-dsl-web/samples/hello/hello_mutation.rb'`
|
|
16
|
+
- Hello, Mutation Content Data-Binding! sample: `require 'glimmer-dsl-web/samples/hello/hello_mutation_content_data_binding.rb'`
|
|
17
|
+
|
|
3
18
|
## 0.10.2
|
|
4
19
|
|
|
5
|
-
- Support `
|
|
20
|
+
- Support `parent.append {}` as an alias for `content {}` on `ElementProxy` and `Glimmer::Web::Component`, which is a method that appends elements to the content of a parent element
|
|
6
21
|
|
|
7
22
|
## 0.10.1
|
|
8
23
|
|
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.
|
|
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.
|
|
1
|
+
0.10.4
|
data/glimmer-dsl-web.gemspec
CHANGED
|
@@ -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.
|
|
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.
|
|
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]
|
|
@@ -50,6 +50,8 @@ Gem::Specification.new do |s|
|
|
|
50
50
|
"lib/glimmer-dsl-web/samples/hello/hello_input_date_time.rb",
|
|
51
51
|
"lib/glimmer-dsl-web/samples/hello/hello_input_date_time_data_binding.rb",
|
|
52
52
|
"lib/glimmer-dsl-web/samples/hello/hello_modal.rb",
|
|
53
|
+
"lib/glimmer-dsl-web/samples/hello/hello_mutation.rb",
|
|
54
|
+
"lib/glimmer-dsl-web/samples/hello/hello_mutation_content_data_binding.rb",
|
|
53
55
|
"lib/glimmer-dsl-web/samples/hello/hello_observer.rb",
|
|
54
56
|
"lib/glimmer-dsl-web/samples/hello/hello_observer_data_binding.rb",
|
|
55
57
|
"lib/glimmer-dsl-web/samples/hello/hello_page_component_link/conference_talk_page.rb",
|
|
@@ -117,7 +119,7 @@ Gem::Specification.new do |s|
|
|
|
117
119
|
|
|
118
120
|
s.specification_version = 4
|
|
119
121
|
|
|
120
|
-
s.add_runtime_dependency(%q<glimmer>.freeze, ["~> 2.8.
|
|
122
|
+
s.add_runtime_dependency(%q<glimmer>.freeze, ["~> 2.8.3".freeze])
|
|
121
123
|
s.add_runtime_dependency(%q<glimmer-dsl-xml>.freeze, ["~> 1.4.0".freeze])
|
|
122
124
|
s.add_runtime_dependency(%q<glimmer-dsl-css>.freeze, ["~> 1.5.2".freeze])
|
|
123
125
|
s.add_runtime_dependency(%q<opal>.freeze, [">= 1.8.2".freeze, "< 2.0.0".freeze])
|
|
@@ -12,6 +12,11 @@ module Glimmer
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def add_content(parent, keyword, *args, &block)
|
|
15
|
+
options = args.last.is_a?(Hash) ? args.last : {}
|
|
16
|
+
parent_original_add_child_mutation = parent&.add_child_mutation
|
|
17
|
+
parent_original_insert_index = parent&.insert_index
|
|
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]
|
|
15
20
|
if parent.bulk_render? || parent.rendered? || parent.skip_content_on_render_blocks?
|
|
16
21
|
return_value = super(parent, keyword, *args, &block)
|
|
17
22
|
parent.add_text_content(return_value, on_empty: true) if return_value.is_a?(String)
|
|
@@ -20,6 +25,9 @@ module Glimmer
|
|
|
20
25
|
else
|
|
21
26
|
parent.add_content_on_render(&block)
|
|
22
27
|
end
|
|
28
|
+
ensure
|
|
29
|
+
parent&.add_child_mutation = parent_original_add_child_mutation
|
|
30
|
+
parent&.insert_index = parent_original_insert_index
|
|
23
31
|
end
|
|
24
32
|
end
|
|
25
33
|
end
|
|
@@ -512,11 +512,28 @@ module Glimmer
|
|
|
512
512
|
end
|
|
513
513
|
alias append content
|
|
514
514
|
|
|
515
|
+
def prepend(bulk_render: false, &block)
|
|
516
|
+
@markup_root.prepend(bulk_render:, &block)
|
|
517
|
+
end
|
|
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
|
+
|
|
515
524
|
def remove_all_listeners
|
|
516
525
|
data_bindings.each do |option_binding, model_binding|
|
|
517
526
|
option_binding.unregister_all_observables
|
|
518
527
|
end
|
|
519
528
|
end
|
|
529
|
+
|
|
530
|
+
def add_child_mutation
|
|
531
|
+
markup_root.add_child_mutation
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
def add_child_mutation=(value)
|
|
535
|
+
markup_root.add_child_mutation = value
|
|
536
|
+
end
|
|
520
537
|
|
|
521
538
|
def method_missing(method_name, *args, &block)
|
|
522
539
|
if can_handle_observation_request?(method_name)
|
|
@@ -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
|
-
|
|
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)
|
|
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,14 +466,36 @@ module Glimmer
|
|
|
458
466
|
end
|
|
459
467
|
alias rerender render
|
|
460
468
|
|
|
461
|
-
def attach(the_parent_dom_element)
|
|
462
|
-
|
|
469
|
+
def attach(the_parent_dom_element, add_child_mutation: :append, insert_index: nil)
|
|
470
|
+
case add_child_mutation
|
|
471
|
+
when :prepend
|
|
472
|
+
the_parent_dom_element.prepend(@dom)
|
|
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
|
|
480
|
+
the_parent_dom_element.append(@dom)
|
|
481
|
+
end
|
|
463
482
|
end
|
|
464
483
|
|
|
465
484
|
def reattach(old_element)
|
|
466
485
|
old_element.replace_with(@dom)
|
|
467
486
|
end
|
|
468
487
|
|
|
488
|
+
def focused
|
|
489
|
+
@focused = `#{dom_element}[0] == document.activeElement`
|
|
490
|
+
@focused
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
def focused=(value)
|
|
494
|
+
@focused = value
|
|
495
|
+
focus if @focused
|
|
496
|
+
@focused
|
|
497
|
+
end
|
|
498
|
+
|
|
469
499
|
def mark_rendered
|
|
470
500
|
@rendered = true
|
|
471
501
|
children.each(&:mark_rendered) if bulk_render?
|
|
@@ -545,15 +575,33 @@ module Glimmer
|
|
|
545
575
|
html_options
|
|
546
576
|
end
|
|
547
577
|
|
|
548
|
-
def
|
|
578
|
+
def add_child_mutation
|
|
579
|
+
@add_child_mutation || :append
|
|
580
|
+
end
|
|
581
|
+
|
|
582
|
+
def add_child_mutation=(value)
|
|
583
|
+
@add_child_mutation = value
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
def content(bulk_render: false, add_child_mutation: :append, insert_index: nil, &block)
|
|
549
587
|
original_bulk_render = options[:bulk_render]
|
|
550
588
|
options[:bulk_render] = bulk_render if rendered?
|
|
551
|
-
return_value = Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Web::ElementExpression.new, keyword, &block)
|
|
589
|
+
return_value = Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Web::ElementExpression.new, keyword, add_child_mutation:, insert_index:, &block)
|
|
552
590
|
options[:bulk_render] = original_bulk_render if rendered?
|
|
553
591
|
return_value
|
|
554
592
|
end
|
|
555
593
|
alias append content
|
|
556
594
|
|
|
595
|
+
def prepend(bulk_render: false, &block)
|
|
596
|
+
content(bulk_render:, add_child_mutation: :prepend, &block)
|
|
597
|
+
end
|
|
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
|
+
|
|
557
605
|
# Subclasses must override with their own mappings
|
|
558
606
|
def observation_request_to_event_mapping
|
|
559
607
|
{}
|
|
@@ -38,131 +38,135 @@ end
|
|
|
38
38
|
# generates a new Glimmer HTML DSL keyword that matches the lowercase underscored version
|
|
39
39
|
# of the name of the class. AddressForm generates address_form_with_slots keyword, which can be used
|
|
40
40
|
# elsewhere in Glimmer HTML DSL code as done inside HelloComponentSlots below.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
div(class: 'address-field-container', style: {display: :grid, grid_auto_columns: '80px 260px'}) {
|
|
54
|
-
label('Full Name: ', for: 'full-name-field')
|
|
55
|
-
input(id: 'full-name-field') {
|
|
56
|
-
value <=> [address, :full_name]
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
@somelabel = label('Street: ', for: 'street-field')
|
|
60
|
-
input(id: 'street-field') {
|
|
61
|
-
value <=> [address, :street]
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
label('Street 2: ', for: 'street2-field')
|
|
65
|
-
textarea(id: 'street2-field') {
|
|
66
|
-
value <=> [address, :street2]
|
|
67
|
-
}
|
|
41
|
+
unless Object.const_defined?(:AddressFormWithSlots)
|
|
42
|
+
class AddressFormWithSlots
|
|
43
|
+
include Glimmer::Web::Component
|
|
44
|
+
|
|
45
|
+
option :address
|
|
46
|
+
|
|
47
|
+
# markup block provides the content of the
|
|
48
|
+
markup {
|
|
49
|
+
div {
|
|
50
|
+
# designate this div as a slot with the slot name :address_header to enable
|
|
51
|
+
# consumers to contribute elements to `address_header {...}` slot
|
|
52
|
+
div(slot: :address_header, class: 'address-form-header')
|
|
68
53
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
54
|
+
div(class: 'address-field-container', style: {display: :grid, grid_auto_columns: '80px 260px'}) {
|
|
55
|
+
label('Full Name: ', for: 'full-name-field')
|
|
56
|
+
input(id: 'full-name-field') {
|
|
57
|
+
value <=> [address, :full_name]
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@somelabel = label('Street: ', for: 'street-field')
|
|
61
|
+
input(id: 'street-field') {
|
|
62
|
+
value <=> [address, :street]
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
label('Street 2: ', for: 'street2-field')
|
|
66
|
+
textarea(id: 'street2-field') {
|
|
67
|
+
value <=> [address, :street2]
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
label('City: ', for: 'city-field')
|
|
71
|
+
input(id: 'city-field') {
|
|
72
|
+
value <=> [address, :city]
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
label('State: ', for: 'state-field')
|
|
76
|
+
select(id: 'state-field') {
|
|
77
|
+
Address::STATES.each do |state_code, state|
|
|
78
|
+
option(value: state_code) { state }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
value <=> [address, :state_code]
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
label('Zip Code: ', for: 'zip-code-field')
|
|
85
|
+
input(id: 'zip-code-field', type: 'number', min: '0', max: '99999') {
|
|
86
|
+
value <=> [address, :zip_code,
|
|
87
|
+
on_write: :to_s,
|
|
88
|
+
]
|
|
89
|
+
}
|
|
72
90
|
}
|
|
73
91
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
value <=> [address, :state_code]
|
|
92
|
+
div(style: {margin: 5}) {
|
|
93
|
+
inner_text <= [address, :summary,
|
|
94
|
+
computed_by: address.members + ['state_code'],
|
|
95
|
+
]
|
|
81
96
|
}
|
|
82
97
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
on_write: :to_s,
|
|
87
|
-
]
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
div(style: {margin: 5}) {
|
|
92
|
-
inner_text <= [address, :summary,
|
|
93
|
-
computed_by: address.members + ['state_code'],
|
|
94
|
-
]
|
|
98
|
+
# designate this div as a slot with the slot name :address_footer to enable
|
|
99
|
+
# consumers to contribute elements to `address_footer {...}` slot
|
|
100
|
+
div(slot: :address_footer, class: 'address-form-footer')
|
|
95
101
|
}
|
|
96
|
-
|
|
97
|
-
# designate this div as a slot with the slot name :address_footer to enable
|
|
98
|
-
# consumers to contribute elements to `address_footer {...}` slot
|
|
99
|
-
div(slot: :address_footer, class: 'address-form-footer')
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
style {
|
|
104
|
-
r('.address-field-container *') {
|
|
105
|
-
margin 5
|
|
106
102
|
}
|
|
107
|
-
|
|
108
|
-
|
|
103
|
+
|
|
104
|
+
style {
|
|
105
|
+
r('.address-field-container *') {
|
|
106
|
+
margin 5
|
|
107
|
+
}
|
|
108
|
+
r('.address-field-container input, .address-field-container select') {
|
|
109
|
+
grid_column '2'
|
|
110
|
+
}
|
|
109
111
|
}
|
|
110
|
-
|
|
112
|
+
end
|
|
111
113
|
end
|
|
112
114
|
|
|
113
115
|
# HelloComponentSlots Glimmer Web Component (View component)
|
|
114
116
|
#
|
|
115
117
|
# This View component represents the main page being rendered,
|
|
116
118
|
# as done by its `render` class method below
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
119
|
+
unless Object.const_defined?(:HelloComponentSlots)
|
|
120
|
+
class HelloComponentSlots
|
|
121
|
+
include Glimmer::Web::Component
|
|
122
|
+
|
|
123
|
+
before_render do
|
|
124
|
+
@shipping_address = Address.new(
|
|
125
|
+
full_name: 'Johnny Doe',
|
|
126
|
+
street: '3922 Park Ave',
|
|
127
|
+
street2: 'PO BOX 8382',
|
|
128
|
+
city: 'San Diego',
|
|
129
|
+
state: 'California',
|
|
130
|
+
zip_code: '91913',
|
|
131
|
+
)
|
|
132
|
+
@billing_address = Address.new(
|
|
133
|
+
full_name: 'John C Doe',
|
|
134
|
+
street: '123 Main St',
|
|
135
|
+
street2: 'Apartment 3C',
|
|
136
|
+
city: 'San Diego',
|
|
137
|
+
state: 'California',
|
|
138
|
+
zip_code: '91911',
|
|
139
|
+
)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
markup {
|
|
143
|
+
div {
|
|
144
|
+
address_form_with_slots(address: @shipping_address) {
|
|
145
|
+
address_header { # contribute elements to the address_header component slot
|
|
146
|
+
h1('Shipping Address')
|
|
147
|
+
legend('This is the address that is used for shipping your purchase.', style: {margin_bottom: 10})
|
|
148
|
+
}
|
|
149
|
+
address_footer { # contribute elements to the address_footer component slot
|
|
150
|
+
p {
|
|
151
|
+
sub("#{strong('Note:')} #{em('Purchase will be returned if the Shipping Address does not accept it in one week.')}")
|
|
152
|
+
}
|
|
149
153
|
}
|
|
150
154
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
155
|
+
|
|
156
|
+
address_form_with_slots(address: @billing_address) {
|
|
157
|
+
address_header { # contribute elements to the address_header component slot
|
|
158
|
+
h1('Billing Address')
|
|
159
|
+
legend('This is the address that is used for your billing method (e.g. credit card).', style: {margin_bottom: 10})
|
|
160
|
+
}
|
|
161
|
+
address_footer { # contribute elements to the address_footer component slot
|
|
162
|
+
p {
|
|
163
|
+
sub("#{strong('Note:')} #{em('Payment will fail if payment method does not match the Billing Address.')}")
|
|
164
|
+
}
|
|
161
165
|
}
|
|
162
166
|
}
|
|
163
167
|
}
|
|
164
168
|
}
|
|
165
|
-
|
|
169
|
+
end
|
|
166
170
|
end
|
|
167
171
|
|
|
168
172
|
Document.ready? do
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
require 'glimmer-dsl-web'
|
|
2
|
+
|
|
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!')
|
|
14
|
+
|
|
15
|
+
p {
|
|
16
|
+
'Add items to a list via element DOM mutations.'
|
|
17
|
+
}
|
|
18
|
+
|
|
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
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@list = ul
|
|
74
|
+
}
|
|
75
|
+
}
|
|
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
|
+
}
|
|
89
|
+
}
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
Document.ready? do
|
|
94
|
+
HelloMutation.render
|
|
95
|
+
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
require 'glimmer-dsl-web'
|
|
2
|
+
|
|
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
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
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).'
|
|
57
|
+
}
|
|
58
|
+
|
|
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
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
ul {
|
|
98
|
+
content(@list_presenter, :list) {
|
|
99
|
+
@list_presenter.list.each do |list_item|
|
|
100
|
+
li { list_item }
|
|
101
|
+
end
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
style {
|
|
108
|
+
r('.actions input, .actions button') {
|
|
109
|
+
margin '10px 10px 10px 0'
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
r('.actions input#insert-index-input') {
|
|
113
|
+
width 40
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
r('.actions label[for=insert-index-input]') {
|
|
117
|
+
margin_left -5
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
Document.ready? do
|
|
124
|
+
HelloMutationContentDataBinding.render
|
|
125
|
+
end
|
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.
|
|
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.
|
|
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.
|
|
25
|
+
version: 2.8.3
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: glimmer-dsl-xml
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -323,6 +323,8 @@ files:
|
|
|
323
323
|
- lib/glimmer-dsl-web/samples/hello/hello_input_date_time.rb
|
|
324
324
|
- lib/glimmer-dsl-web/samples/hello/hello_input_date_time_data_binding.rb
|
|
325
325
|
- lib/glimmer-dsl-web/samples/hello/hello_modal.rb
|
|
326
|
+
- lib/glimmer-dsl-web/samples/hello/hello_mutation.rb
|
|
327
|
+
- lib/glimmer-dsl-web/samples/hello/hello_mutation_content_data_binding.rb
|
|
326
328
|
- lib/glimmer-dsl-web/samples/hello/hello_observer.rb
|
|
327
329
|
- lib/glimmer-dsl-web/samples/hello/hello_observer_data_binding.rb
|
|
328
330
|
- lib/glimmer-dsl-web/samples/hello/hello_page_component_link/conference_talk_page.rb
|