glimmer-dsl-web 0.0.3 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,15 +1,11 @@
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.0.3 (Early Alpha)
2
- ## Ruby in the Browser Web GUI Library
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.0.5 (Early Alpha)
2
+ ## Ruby in the Browser Web GUI Frontend Library
3
3
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-web.svg)](http://badge.fury.io/rb/glimmer-dsl-web)
4
4
  [![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
5
5
 
6
- This project is inspired-by [Glimmer DSL for Opal](https://github.com/AndyObtiva/glimmer-dsl-opal) and is similar in enabling frontend GUI development with Ruby, but it mainly differs from Glimmer DSL for Opal by adopting a DSL that follows web-like HTML syntax in Ruby (enabling transfer of HTML/CSS/JS skills) instead of adopting a desktop GUI DSL that is webified. Also, it will begin by supporting [Opal Ruby](https://opalrb.com/), but it might grow to support [Ruby WASM](https://github.com/ruby/ruby.wasm) as an alternative to [Opal Ruby](https://opalrb.com/) that could be switched to with a simple configuration change.
6
+ [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for Web enables building Web GUI frontends using [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c), as per [Matz's recommendation in his RubyConf 2022 keynote speech to replace JavaScript with Ruby](https://youtu.be/knutsgHTrfQ?t=789). It aims at providing the simplest frontend library in existence. You can finally live in pure Rubyland on the Web in both the frontend and backend with [Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web)!
7
7
 
8
- Note that the library is an Early Alpha and its APIs might change frequently until hitting a minor release at least.
9
-
10
- ### You can finally live in pure Rubyland on the web!
11
-
12
- [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for Web is an upcoming **pre-alpha** [gem](https://rubygems.org/gems/glimmer-dsl-web) that enables building web GUI in pure Ruby via [Opal](https://opalrb.com/) on [Rails](https://rubyonrails.org/) (and potentially [Ruby WASM](https://github.com/ruby/ruby.wasm) in the future).
8
+ This project is inspired by [Glimmer DSL for Opal](https://github.com/AndyObtiva/glimmer-dsl-opal) and is similar in enabling frontend GUI development with Ruby. [Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) mainly differs from Glimmer DSL for Opal by adopting a DSL that follows web-like HTML syntax in Ruby to facilitate leveraging existing HTML/CSS/JS skills instead of adopting a desktop GUI DSL that is webified.
13
9
 
14
10
  **Sample**
15
11
 
@@ -44,7 +40,7 @@ That produces:
44
40
  ```html
45
41
  ...
46
42
  <div id="app-container">
47
- <div parent="#app-container" class="element element-1">
43
+ <div data-parent="#app-container" class="element element-1">
48
44
  <label class="greeting element element-2">
49
45
  Hello, World!
50
46
  </label>
@@ -74,14 +70,50 @@ end
74
70
  That produces the following under `<body></body>`:
75
71
 
76
72
  ```html
77
- <div parent="body" class="element element-1">
73
+ <div data-parent="body" class="element element-1">
78
74
  Hello, World!
79
75
  </div>
80
76
  ```
81
77
 
82
78
  ![setup is working](/images/glimmer-dsl-web-setup-example-working.png)
83
79
 
84
- **Hello, Button! Sample**
80
+ **Hello, Button!**
81
+
82
+ Event listeners can be setup on any element using the same event names used in HTML (e.g. `onclick`) while passing in a standard Ruby block to handle behavior. `$$` gives access to `window` to invoke functions like `alert`.
83
+
84
+ Glimmer GUI code:
85
+
86
+ ```ruby
87
+ require 'glimmer-dsl-web'
88
+
89
+ include Glimmer
90
+
91
+ Document.ready? do
92
+ div {
93
+ button('Greet') {
94
+ onclick do
95
+ $$.alert('Hello, Button!')
96
+ end
97
+ }
98
+ }.render
99
+ end
100
+ ```
101
+
102
+ That produces the following under `<body></body>`:
103
+
104
+ ```html
105
+ <div data-parent="body" class="element element-1">
106
+ <button class="element element-2">Greet</button>
107
+ </div>
108
+ ```
109
+
110
+ Screenshot:
111
+
112
+ ![Hello, Button!](/images/glimmer-dsl-web-samples-hello-hello-button.gif)
113
+
114
+ **Hello, Form!**
115
+
116
+ [Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) gives access to all Web Browser built-in features like HTML form validations, input focus, events, and element functions from a very terse and productive Ruby GUI DSL.
85
117
 
86
118
  Glimmer GUI code:
87
119
 
@@ -93,44 +125,50 @@ include Glimmer
93
125
  Document.ready? do
94
126
  div {
95
127
  h1('Contact Form')
128
+
96
129
  form {
97
- div(class: 'field-row') {
130
+ div {
98
131
  label('Name: ', for: 'name-field')
99
- @name_input = input(id: 'name-field', class: 'field', type: 'text', required: true)
132
+ @name_input = input(type: 'text', id: 'name-field', required: true, autofocus: true)
100
133
  }
101
- div(class: 'field-row') {
134
+
135
+ div {
102
136
  label('Email: ', for: 'email-field')
103
- @email_input = input(id: 'email-field', class: 'field', type: 'email', required: true)
137
+ @email_input = input(type: 'email', id: 'email-field', required: true)
104
138
  }
105
- @add_button = button('Add Contact', class: 'submit-button') {
106
- on_click do
107
- if ([@name_input, @email_input].all? {|input| input.check_validity })
108
- @table.content {
109
- tr {
110
- td { @name_input.value }
111
- td { @email_input.value }
139
+
140
+ div {
141
+ input(type: 'submit', value: 'Add Contact') {
142
+ onclick do |event|
143
+ if ([@name_input, @email_input].all? {|input| input.check_validity })
144
+ # re-open table content and add row
145
+ @table.content {
146
+ tr {
147
+ td { @name_input.value }
148
+ td { @email_input.value }
149
+ }
112
150
  }
113
- }
114
- @email_input.value = @name_input.value = ''
115
- else
116
- error_messages = []
117
- error_messages << "Name is not valid! Make sure it is filled." if !@name_input.check_validity
118
- error_messages << "Email is not valid! Make sure it is filled and has a valid format." if !@email_input.check_validity
119
- $$.alert(error_messages.join("\n"))
151
+ @email_input.value = @name_input.value = ''
152
+ @name_input.focus
153
+ end
120
154
  end
121
- end
155
+ }
122
156
  }
123
157
  }
158
+
124
159
  h1('Contacts Table')
160
+
125
161
  @table = table {
126
162
  tr {
127
163
  th('Name')
128
164
  th('Email')
129
165
  }
166
+
130
167
  tr {
131
168
  td('John Doe')
132
169
  td('johndoe@example.com')
133
170
  }
171
+
134
172
  tr {
135
173
  td('Jane Doe')
136
174
  td('janedoe@example.com')
@@ -140,15 +178,11 @@ Document.ready? do
140
178
  # CSS Styles
141
179
  style {
142
180
  <<~CSS
143
- .field-row {
144
- margin: 10px 5px;
181
+ input {
182
+ margin: 5px;
145
183
  }
146
- .field {
147
- margin-left: 5px;
148
- }
149
- .submit-button {
150
- display: block;
151
- margin: 10px 5px;
184
+ input[type=submit] {
185
+ margin: 5px 0;
152
186
  }
153
187
  table {
154
188
  border:1px solid grey;
@@ -171,83 +205,66 @@ That produces the following under `<body></body>`:
171
205
  ```html
172
206
  <div data-parent="body" class="element element-1">
173
207
  <h1 class="element element-2">Contact Form</h1>
208
+
174
209
  <form class="element element-3">
175
- <div class="field-row element element-4">
210
+ <div class="element element-4">
176
211
  <label for="name-field" class="element element-5">Name: </label>
177
- <input id="name-field" class="field element element-6" type="text" required="true">
212
+ <input type="text" id="name-field" required="true" autofocus="true" class="element element-6">
178
213
  </div>
179
- <div class="field-row element element-7">
214
+
215
+ <div class="element element-7">
180
216
  <label for="email-field" class="element element-8">Email: </label>
181
- <input id="email-field" class="field element element-9" type="email" required="true">
217
+ <input type="email" id="email-field" required="true" class="element element-9">
218
+ </div>
219
+
220
+ <div class="element element-10">
221
+ <input type="submit" value="Add Contact" class="element element-11">
182
222
  </div>
183
- <button class="submit-button element element-10">Add Contact</button>
184
223
  </form>
185
- <h1 class="element element-11">Contacts Table</h1>
186
- <table class="element element-12">
187
- <tr class="element element-13">
188
- <th class="element element-14">Name</th>
189
- <th class="element element-15">Email</th>
224
+
225
+ <h1 class="element element-12">Contacts Table</h1>
226
+
227
+ <table class="element element-13">
228
+ <tr class="element element-14">
229
+ <th class="element element-15">Name</th>
230
+ <th class="element element-16">Email</th>
190
231
  </tr>
191
- <tr class="element element-16">
192
- <td class="element element-17">John Doe</td>
193
- <td class="element element-18">johndoe@example.com</td>
232
+
233
+ <tr class="element element-17">
234
+ <td class="element element-18">John Doe</td>
235
+ <td class="element element-19">johndoe@example.com</td>
194
236
  </tr>
195
- <tr class="element element-19">
196
- <td class="element element-20">Jane Doe</td>
197
- <td class="element element-21">janedoe@example.com</td>
237
+
238
+ <tr class="element element-20">
239
+ <td class="element element-21">Jane Doe</td>
240
+ <td class="element element-22">janedoe@example.com</td>
198
241
  </tr>
199
242
  </table>
200
- <style class="element element-22">.field-row {
201
- margin: 10px 5px;
202
- }
203
- .field {
204
- margin-left: 5px;
205
- }
206
- .submit-button {
207
- display: block;
208
- margin: 10px 5px;
209
- }
210
- table {
211
- border:1px solid grey;
212
- border-spacing: 0;
213
- }
214
- table tr td, table tr th {
215
- padding: 5px;
216
- }
217
- table tr:nth-child(even) {
218
- background: #ccc;
219
- }
243
+
244
+ <style class="element element-23">
245
+ input {
246
+ margin: 5px;
247
+ }
248
+ input[type=submit] {
249
+ margin: 5px 0;
250
+ }
251
+ table {
252
+ border:1px solid grey;
253
+ border-spacing: 0;
254
+ }
255
+ table tr td, table tr th {
256
+ padding: 5px;
257
+ }
258
+ table tr:nth-child(even) {
259
+ background: #ccc;
260
+ }
220
261
  </style>
221
262
  </div>
222
263
  ```
223
264
 
224
- Screenshots:
225
-
226
- ---
227
-
228
- ***Hello, Button!***
229
-
230
- ![Hello, Button!](/images/glimmer-dsl-web-samples-hello-hello-button.png)
265
+ Screenshot:
231
266
 
232
- ---
233
-
234
- ***Hello, Button! Submitted Invalid Data***
235
-
236
- ![Hello, Button! Invalid Data](/images/glimmer-dsl-web-samples-hello-hello-button-invalid-data.png)
237
-
238
- ---
239
-
240
- ***Hello, Button! Filled Valid Name and Email***
241
-
242
- ![Hello, Button! Filled](/images/glimmer-dsl-web-samples-hello-hello-button-filled-name-and-email.png)
243
-
244
- ---
245
-
246
- ***Hello, Button! Added Contact***
247
-
248
- ![Hello, Button! Added Contact](/images/glimmer-dsl-web-samples-hello-hello-button-added-contact.png)
249
-
250
- ---
267
+ ![Hello, Form!](/images/glimmer-dsl-web-samples-hello-hello-form.gif)
251
268
 
252
269
  **Button Counter Sample**
253
270
 
@@ -279,7 +296,7 @@ class HelloButton
279
296
 
280
297
  markup {
281
298
  # This will hook into element #app-container and then build HTML inside it using Ruby DSL code
282
- div(root_css_selector) {
299
+ div(parent: parent_selector) {
283
300
  text 'Button Counter'
284
301
 
285
302
  button {
@@ -288,7 +305,7 @@ class HelloButton
288
305
  # copied to button innerText (content) to display to the user
289
306
  inner_text <= [@counter, :count, on_read: ->(value) { "Click To Increment: #{value} " }]
290
307
 
291
- on_click {
308
+ onclick {
292
309
  @counter.increment!
293
310
  }
294
311
  }
@@ -344,11 +361,12 @@ Learn more about the differences between various [Glimmer](https://github.com/An
344
361
  - [Background](#background)
345
362
  - [Prerequisites](#prerequisites)
346
363
  - [Setup](#setup)
364
+ - [Usage](#usage)
347
365
  - [Supported Glimmer DSL Keywords](#supported-glimmer-dsl-keywords)
348
366
  - [Samples](#samples)
349
367
  - [Hello Samples](#hello-samples)
350
368
  - [Hello, World!](#hello-world)
351
- - [Hello, Button!](#hello-button)
369
+ - [Hello, Form!](#hello-form)
352
370
  - [Button Counter](#button-counter)
353
371
  - [Glimmer Process](#glimmer-process)
354
372
  - [Help](#help)
@@ -362,10 +380,12 @@ Learn more about the differences between various [Glimmer](https://github.com/An
362
380
 
363
381
  ## Prerequisites
364
382
 
383
+ [Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) will begin by supporting [Opal Ruby](https://opalrb.com/) on [Rails](https://rubyonrails.org/). [Opal](https://opalrb.com/) is a lightweight Ruby to JavaScript transpiler that results in small downloadables compared to WASM. In the future, the project might grow to support [Ruby WASM](https://github.com/ruby/ruby.wasm) as an alternative to [Opal Ruby](https://opalrb.com/) that could be switched to with a simple configuration change.
384
+
385
+ - Ruby 3.0 (newer Ruby versions are not supported at this time)
365
386
  - Rails 6-7: [https://github.com/rails/rails](https://github.com/rails/rails)
366
- - Opal 1.4.1 for Rails 6-7 or Opal 1.0.5 for Rails 5: [https://github.com/opal/opal](https://github.com/opal/opal)
367
- - Opal-Rails 2.0.2 for Rails 6-7 or Opal-Rails 1.1.2 for Rails 5: [https://github.com/opal/opal-rails](https://github.com/opal/opal-rails)
368
- - jQuery 3 (included): [https://code.jquery.com/](https://code.jquery.com/) (jQuery 3.6.0 is included in the [glimmer-dsl-web](https://rubygems.org/gems/glimmer-dsl-web) gem)
387
+ - Opal 1.4.1 for Rails 6-7: [https://github.com/opal/opal](https://github.com/opal/opal)
388
+ - Opal-Rails 2.0.2 for Rails 6-7: [https://github.com/opal/opal-rails](https://github.com/opal/opal-rails)
369
389
 
370
390
  ## Setup
371
391
 
@@ -396,7 +416,7 @@ gem 'opal', '1.4.1'
396
416
  gem 'opal-rails', '2.0.2'
397
417
  gem 'opal-async', '~> 1.4.0'
398
418
  gem 'opal-jquery', '~> 0.4.6'
399
- gem 'glimmer-dsl-web', '~> 0.0.3'
419
+ gem 'glimmer-dsl-web', '~> 0.0.5'
400
420
  gem 'glimmer-dsl-xml', '~> 1.3.1', require: false
401
421
  gem 'glimmer-dsl-css', '~> 1.2.1', require: false
402
422
  ```
@@ -488,7 +508,7 @@ That produces:
488
508
  ```html
489
509
  ...
490
510
  <div id="app-container">
491
- <div parent="#app-container" class="element element-1">
511
+ <div data-parent="#app-container" class="element element-1">
492
512
  <label class="greeting element element-2">
493
513
  Hello, World!
494
514
  </label>
@@ -541,7 +561,7 @@ gem 'opal', '1.4.1'
541
561
  gem 'opal-rails', '2.0.2'
542
562
  gem 'opal-async', '~> 1.4.0'
543
563
  gem 'opal-jquery', '~> 0.4.6'
544
- gem 'glimmer-dsl-web', '~> 0.0.3'
564
+ gem 'glimmer-dsl-web', '~> 0.0.5'
545
565
  gem 'glimmer-dsl-xml', '~> 1.3.1', require: false
546
566
  gem 'glimmer-dsl-css', '~> 1.2.1', require: false
547
567
  ```
@@ -637,7 +657,7 @@ That produces:
637
657
  ```html
638
658
  ...
639
659
  <div id="app-container">
640
- <div parent="#app-container" class="element element-1">
660
+ <div data-parent="#app-container" class="element element-1">
641
661
  <label class="greeting element element-2">
642
662
  Hello, World!
643
663
  </label>
@@ -663,11 +683,85 @@ If you run into any issues in setup, refer to the [Sample Glimmer DSL for Web Ra
663
683
 
664
684
  Otherwise, if you still cannot setup successfully (even with the help of the sample project, or if the sample project stops working), please do not hesitate to report an [Issue request](https://github.com/AndyObtiva/glimmer-dsl-web/issues) or fix and submit a [Pull Request](https://github.com/AndyObtiva/glimmer-dsl-web/pulls).
665
685
 
686
+ ## Usage
687
+
688
+ Glimmer DSL for Web offers a GUI DSL for building HTML Web User Interfaces declaratively in Ruby.
689
+
690
+ 1- **Keywords (HTML Elements)**
691
+
692
+ You can declare any HTML element by simply using the lowercase underscored version of its name (Ruby convention for method names) like `div`, `span`, `form`, `input`, `button`, `table`, `tr`, `th`, and `td`.
693
+
694
+ Under the hood, HTML element DSL keywords are invoked as Ruby methods.
695
+
696
+ 2- **Arguments (HTML Attributes + Text Content)**
697
+
698
+ You can set any HTML element attributes by passing as keyword arguments to element methods like `div(id: 'container', class: 'stack')` or `input(type: 'email', required: true)`
699
+
700
+ Also, if the element has a little bit of text content that can fit in one line, it can be passed as the 1st argument like `label('Name: ', for: 'name_field')`, `button('Calculate', class: 'round-button')`, or `span('Mr')`
701
+
702
+ 3- **Content Block (Properties + Listeners + Nested Elements + Text Content)**
703
+
704
+ Element methods can accept a Ruby content block. It intentionally has a `{...}` style even as a multi-line block to indicate that the code is declarative GUI structure code.
705
+
706
+ You can nest HTML element properties under an element like:
707
+
708
+ ```ruby
709
+ input(type: 'text') {
710
+ content_editable false
711
+ }
712
+ ```
713
+
714
+ You can nest HTML event listeners under an element by using the HTML event listener name (e.g. `onclick`, `onchange`, `onblur`):
715
+
716
+ ```ruby
717
+ button('Add') {
718
+ onclick do
719
+ @model.add_selected_element
720
+ end
721
+ }
722
+ ```
723
+
724
+ Given that listener code is imperative, it uses a `do; end` style for Ruby blocks to separate it from declarative GUI structure code and enable quicker readability of the code.
725
+
726
+ You can nest other HTML elements under an HTML element the same way you do so in HTML, like:
727
+
728
+ ```ruby
729
+ form {
730
+ div(class: 'field-row') {
731
+ label('Name: ', for: 'name-field')
732
+ input(id: 'name-field', class: 'field', type: 'text', required: true)
733
+ }
734
+ div(class: 'field-row') {
735
+ label('Email: ', for: 'email-field')
736
+ input(id: 'email-field', class: 'field', type: 'email', required: true)
737
+ }
738
+ button('Add Contact', class: 'submit-button') {
739
+ onclick do
740
+ ...
741
+ end
742
+ }
743
+ }
744
+ ```
745
+
746
+ You can nest text content underneath an element's Ruby block, like:
747
+
748
+ ```ruby
749
+ p(class: 'summary') {
750
+ 'This text content is going into the body of the span element'
751
+ }
752
+ ```
753
+
754
+ 4- **Operations (Properties + Functions)**
755
+
756
+ 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`.
757
+
666
758
  ## Supported Glimmer DSL Keywords
667
759
 
668
- All HTML elements.
760
+ [All HTML elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element).
761
+
762
+ [All HTML attributes](https://www.w3schools.com/html/html_attributes.asp).
669
763
 
670
- All HTML attributes.
764
+ [All HTML events](https://www.w3schools.com/tags/ref_eventattributes.asp).
671
765
 
672
766
  ## Samples
673
767
 
@@ -698,11 +792,35 @@ end
698
792
  That produces the following under `<body></body>`:
699
793
 
700
794
  ```html
701
- <div parent="body" class="element element-1">
795
+ <div data-parent="body" class="element element-1">
796
+ Hello, World!
797
+ </div>
798
+ ```
799
+
800
+ ![setup is working](/images/glimmer-dsl-web-setup-example-working.png)
801
+
802
+ Alternative syntax when an element only has text content:
803
+
804
+ ```ruby
805
+ require 'glimmer-dsl-web'
806
+
807
+ include Glimmer
808
+
809
+ Document.ready? do
810
+ div('Hello, World!').render
811
+ end
812
+ ```
813
+
814
+ That produces the following under `<body></body>`:
815
+
816
+ ```html
817
+ <div data-parent="body" class="element element-1">
702
818
  Hello, World!
703
819
  </div>
704
820
  ```
705
821
 
822
+ ![setup is working](/images/glimmer-dsl-web-setup-example-working.png)
823
+
706
824
  #### Hello, Button!
707
825
 
708
826
  Glimmer GUI code:
@@ -712,47 +830,85 @@ require 'glimmer-dsl-web'
712
830
 
713
831
  include Glimmer
714
832
 
833
+ Document.ready? do
834
+ div {
835
+ button('Greet') {
836
+ onclick do
837
+ $$.alert('Hello, Button!')
838
+ end
839
+ }
840
+ }.render
841
+ end
842
+ ```
843
+
844
+ That produces the following under `<body></body>`:
845
+
846
+ ```html
847
+ <div data-parent="body" class="element element-1">
848
+ <button class="element element-2">Greet</button>
849
+ </div>
850
+ ```
851
+
852
+ Screenshot:
853
+
854
+ ![Hello, Button!](/images/glimmer-dsl-web-samples-hello-hello-button.gif)
855
+
856
+ #### Hello, Form!
857
+
858
+ Glimmer GUI code:
859
+
860
+ ```ruby
861
+ require 'glimmer-dsl-web'
862
+
863
+ include Glimmer
864
+
715
865
  Document.ready? do
716
866
  div {
717
867
  h1('Contact Form')
868
+
718
869
  form {
719
- div(class: 'field-row') {
870
+ div {
720
871
  label('Name: ', for: 'name-field')
721
- @name_input = input(id: 'name-field', class: 'field', type: 'text', required: true)
872
+ @name_input = input(type: 'text', id: 'name-field', required: true, autofocus: true)
722
873
  }
723
- div(class: 'field-row') {
874
+
875
+ div {
724
876
  label('Email: ', for: 'email-field')
725
- @email_input = input(id: 'email-field', class: 'field', type: 'email', required: true)
877
+ @email_input = input(type: 'email', id: 'email-field', required: true)
726
878
  }
727
- @add_button = button('Add Contact', class: 'submit-button') {
728
- on_click do
729
- if ([@name_input, @email_input].all? {|input| input.check_validity })
730
- @table.content {
731
- tr {
732
- td { @name_input.value }
733
- td { @email_input.value }
879
+
880
+ div {
881
+ input(type: 'submit', value: 'Add Contact') {
882
+ onclick do |event|
883
+ if ([@name_input, @email_input].all? {|input| input.check_validity })
884
+ # re-open table content and add row
885
+ @table.content {
886
+ tr {
887
+ td { @name_input.value }
888
+ td { @email_input.value }
889
+ }
734
890
  }
735
- }
736
- @email_input.value = @name_input.value = ''
737
- else
738
- error_messages = []
739
- error_messages << "Name is not valid! Make sure it is filled." if !@name_input.check_validity
740
- error_messages << "Email is not valid! Make sure it is filled and has a valid format." if !@email_input.check_validity
741
- $$.alert(error_messages.join("\n"))
891
+ @email_input.value = @name_input.value = ''
892
+ @name_input.focus
893
+ end
742
894
  end
743
- end
895
+ }
744
896
  }
745
897
  }
898
+
746
899
  h1('Contacts Table')
900
+
747
901
  @table = table {
748
902
  tr {
749
903
  th('Name')
750
904
  th('Email')
751
905
  }
906
+
752
907
  tr {
753
908
  td('John Doe')
754
909
  td('johndoe@example.com')
755
910
  }
911
+
756
912
  tr {
757
913
  td('Jane Doe')
758
914
  td('janedoe@example.com')
@@ -762,15 +918,11 @@ Document.ready? do
762
918
  # CSS Styles
763
919
  style {
764
920
  <<~CSS
765
- .field-row {
766
- margin: 10px 5px;
921
+ input {
922
+ margin: 5px;
767
923
  }
768
- .field {
769
- margin-left: 5px;
770
- }
771
- .submit-button {
772
- display: block;
773
- margin: 10px 5px;
924
+ input[type=submit] {
925
+ margin: 5px 0;
774
926
  }
775
927
  table {
776
928
  border:1px solid grey;
@@ -793,83 +945,66 @@ That produces the following under `<body></body>`:
793
945
  ```html
794
946
  <div data-parent="body" class="element element-1">
795
947
  <h1 class="element element-2">Contact Form</h1>
948
+
796
949
  <form class="element element-3">
797
- <div class="field-row element element-4">
950
+ <div class="element element-4">
798
951
  <label for="name-field" class="element element-5">Name: </label>
799
- <input id="name-field" class="field element element-6" type="text" required="true">
952
+ <input type="text" id="name-field" required="true" autofocus="true" class="element element-6">
800
953
  </div>
801
- <div class="field-row element element-7">
954
+
955
+ <div class="element element-7">
802
956
  <label for="email-field" class="element element-8">Email: </label>
803
- <input id="email-field" class="field element element-9" type="email" required="true">
957
+ <input type="email" id="email-field" required="true" class="element element-9">
958
+ </div>
959
+
960
+ <div class="element element-10">
961
+ <input type="submit" value="Add Contact" class="element element-11">
804
962
  </div>
805
- <button class="submit-button element element-10">Add Contact</button>
806
963
  </form>
807
- <h1 class="element element-11">Contacts Table</h1>
808
- <table class="element element-12">
809
- <tr class="element element-13">
810
- <th class="element element-14">Name</th>
811
- <th class="element element-15">Email</th>
964
+
965
+ <h1 class="element element-12">Contacts Table</h1>
966
+
967
+ <table class="element element-13">
968
+ <tr class="element element-14">
969
+ <th class="element element-15">Name</th>
970
+ <th class="element element-16">Email</th>
812
971
  </tr>
813
- <tr class="element element-16">
814
- <td class="element element-17">John Doe</td>
815
- <td class="element element-18">johndoe@example.com</td>
972
+
973
+ <tr class="element element-17">
974
+ <td class="element element-18">John Doe</td>
975
+ <td class="element element-19">johndoe@example.com</td>
816
976
  </tr>
817
- <tr class="element element-19">
818
- <td class="element element-20">Jane Doe</td>
819
- <td class="element element-21">janedoe@example.com</td>
977
+
978
+ <tr class="element element-20">
979
+ <td class="element element-21">Jane Doe</td>
980
+ <td class="element element-22">janedoe@example.com</td>
820
981
  </tr>
821
982
  </table>
822
- <style class="element element-22">.field-row {
823
- margin: 10px 5px;
824
- }
825
- .field {
826
- margin-left: 5px;
827
- }
828
- .submit-button {
829
- display: block;
830
- margin: 10px 5px;
831
- }
832
- table {
833
- border:1px solid grey;
834
- border-spacing: 0;
835
- }
836
- table tr td, table tr th {
837
- padding: 5px;
838
- }
839
- table tr:nth-child(even) {
840
- background: #ccc;
841
- }
983
+
984
+ <style class="element element-23">
985
+ input {
986
+ margin: 5px;
987
+ }
988
+ input[type=submit] {
989
+ margin: 5px 0;
990
+ }
991
+ table {
992
+ border:1px solid grey;
993
+ border-spacing: 0;
994
+ }
995
+ table tr td, table tr th {
996
+ padding: 5px;
997
+ }
998
+ table tr:nth-child(even) {
999
+ background: #ccc;
1000
+ }
842
1001
  </style>
843
1002
  </div>
844
1003
  ```
845
1004
 
846
- Screenshots:
847
-
848
- ---
849
-
850
- ***Hello, Button!***
851
-
852
- ![Hello, Button!](/images/glimmer-dsl-web-samples-hello-hello-button.png)
853
-
854
- ---
855
-
856
- ***Hello, Button! Submitted Invalid Data***
857
-
858
- ![Hello, Button! Invalid Data](/images/glimmer-dsl-web-samples-hello-hello-button-invalid-data.png)
859
-
860
- ---
861
-
862
- ***Hello, Button! Filled Valid Name and Email***
863
-
864
- ![Hello, Button! Filled](/images/glimmer-dsl-web-samples-hello-hello-button-filled-name-and-email.png)
865
-
866
- ---
867
-
868
- ***Hello, Button! Added Contact***
869
-
870
- ![Hello, Button! Added Contact](/images/glimmer-dsl-web-samples-hello-hello-button-added-contact.png)
1005
+ Screenshot:
871
1006
 
872
- ---
1007
+ ![Hello, Form!](/images/glimmer-dsl-web-samples-hello-hello-form.gif)
873
1008
 
874
1009
  #### Button Counter
875
1010
 
@@ -901,7 +1036,7 @@ class HelloButton
901
1036
 
902
1037
  markup {
903
1038
  # This will hook into element #app-container and then build HTML inside it using Ruby DSL code
904
- div(root_css_selector) {
1039
+ div(parent: parent_selector) {
905
1040
  text 'Button Counter'
906
1041
 
907
1042
  button {
@@ -910,7 +1045,7 @@ class HelloButton
910
1045
  # copied to button innerText (content) to display to the user
911
1046
  inner_text <= [@counter, :count, on_read: ->(value) { "Click To Increment: #{value} " }]
912
1047
 
913
- on_click {
1048
+ onclick {
914
1049
  @counter.increment!
915
1050
  }
916
1051
  }