glimmer-dsl-web 0.0.4 → 0.0.5

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: 64730435caff848fd16bfad099963c9c3d6298da78af51bb0bbcbd9c41ed5ca9
4
- data.tar.gz: 80cb8d417c40726210eab103ace178016c9595b2d123f931ab9dd2e6469e37ac
3
+ metadata.gz: a9250414d9d8804f3af1ddf5cc083ce9e06ff87e3a57e1686c1e9bb7cb1ee847
4
+ data.tar.gz: f9312dfb0e0a87a047b4b25216031587f965b70d8059a7de6d670105b2ce41ca
5
5
  SHA512:
6
- metadata.gz: 4964424f7ccc8b35257d5c28b28749f8ee9fcc0be889d498c17ff3a81faac173fc9d3ae2d1d4a0818a0af7685a3e88dd2885b4733cc213995a54c7d76a6f3443
7
- data.tar.gz: 4d9cb434aa3d62053f98351ec38c821198f2426cdc00503d6a0f2eefd402377a4158f80a504942e966df2c95f7b2ee1644bea199c1f63011fe0c719e9cb27628
6
+ metadata.gz: 05be5bd7202f612582819cf970eb8185e530c2dff83e90caae1e3d5b09ad18d1aad44cd622e5b1b6d17f5afd83eb61762af2a941ab7bc77ea39b409e81ce4e6c
7
+ data.tar.gz: 6a979d023e5faf0b78656ca332bf6593ea33ed224ab8f1f06490767466dd62861e6a560fec63be25352500e0e2fde92cfa9d31e47089a6f5a629f7546816c283
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.0.5
4
+
5
+ - Support `p` element as it was overriden by Ruby's `p` method.
6
+ - Update listener syntax to be the original HTML event name (e.g. `onclick`) without being underscored to keep the transition to the Glimmer GUI DSL simple (e.g. `onclick` not `on_click`)
7
+ - Wrap listener `event` argument with `Glimmer::Web::Event` object, which proxies calls to JS event when needed
8
+ - Rename Hello Button! Sample to Hello, Form! Sample: `require 'glimmer-dsl-web/samples/hello/hello_form'`
9
+ - Update Hello, Form! Sample to display browser native validation errors and have automatic focus support on the name field
10
+ - Event listeners do not call `prevent_default` by default anymore, leaving it to the consumer of the library to decide
11
+ - New Hello, Button! Sample (replacing older one): `require 'glimmer-dsl-web/samples/hello/hello_button'`
12
+
3
13
  ## 0.0.4
4
14
 
5
15
  - Support nesting attributes/properties under element (e.g. `input { value 'something'; dir 'rtl' }`)
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.4 (Early Alpha)
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
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
 
@@ -81,7 +77,43 @@ That produces the following under `<body></body>`:
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
- 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;
145
- }
146
- .field {
147
- margin-left: 5px;
181
+ input {
182
+ margin: 5px;
148
183
  }
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)
231
-
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)
265
+ Screenshot:
249
266
 
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
  }
@@ -349,7 +366,7 @@ Learn more about the differences between various [Glimmer](https://github.com/An
349
366
  - [Samples](#samples)
350
367
  - [Hello Samples](#hello-samples)
351
368
  - [Hello, World!](#hello-world)
352
- - [Hello, Button!](#hello-button)
369
+ - [Hello, Form!](#hello-form)
353
370
  - [Button Counter](#button-counter)
354
371
  - [Glimmer Process](#glimmer-process)
355
372
  - [Help](#help)
@@ -363,11 +380,12 @@ Learn more about the differences between various [Glimmer](https://github.com/An
363
380
 
364
381
  ## Prerequisites
365
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
+
366
385
  - Ruby 3.0 (newer Ruby versions are not supported at this time)
367
386
  - Rails 6-7: [https://github.com/rails/rails](https://github.com/rails/rails)
368
- - 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)
369
- - 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)
370
- - 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)
371
389
 
372
390
  ## Setup
373
391
 
@@ -398,7 +416,7 @@ gem 'opal', '1.4.1'
398
416
  gem 'opal-rails', '2.0.2'
399
417
  gem 'opal-async', '~> 1.4.0'
400
418
  gem 'opal-jquery', '~> 0.4.6'
401
- gem 'glimmer-dsl-web', '~> 0.0.4'
419
+ gem 'glimmer-dsl-web', '~> 0.0.5'
402
420
  gem 'glimmer-dsl-xml', '~> 1.3.1', require: false
403
421
  gem 'glimmer-dsl-css', '~> 1.2.1', require: false
404
422
  ```
@@ -543,7 +561,7 @@ gem 'opal', '1.4.1'
543
561
  gem 'opal-rails', '2.0.2'
544
562
  gem 'opal-async', '~> 1.4.0'
545
563
  gem 'opal-jquery', '~> 0.4.6'
546
- gem 'glimmer-dsl-web', '~> 0.0.4'
564
+ gem 'glimmer-dsl-web', '~> 0.0.5'
547
565
  gem 'glimmer-dsl-xml', '~> 1.3.1', require: false
548
566
  gem 'glimmer-dsl-css', '~> 1.2.1', require: false
549
567
  ```
@@ -669,19 +687,19 @@ Otherwise, if you still cannot setup successfully (even with the help of the sam
669
687
 
670
688
  Glimmer DSL for Web offers a GUI DSL for building HTML Web User Interfaces declaratively in Ruby.
671
689
 
672
- 1- Keywords (HTML Elements)
690
+ 1- **Keywords (HTML Elements)**
673
691
 
674
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`.
675
693
 
676
694
  Under the hood, HTML element DSL keywords are invoked as Ruby methods.
677
695
 
678
- 2- Arguments (HTML Attributes + Text Content)
696
+ 2- **Arguments (HTML Attributes + Text Content)**
679
697
 
680
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)`
681
699
 
682
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')`
683
701
 
684
- 3- Content Block (Properties + Listeners + Nested Elements + Text Content)
702
+ 3- **Content Block (Properties + Listeners + Nested Elements + Text Content)**
685
703
 
686
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.
687
705
 
@@ -693,11 +711,11 @@ input(type: 'text') {
693
711
  }
694
712
  ```
695
713
 
696
- You can nest HTML event listeners under an element by using a more friendly underscored version of listener properties (e.g. `onclick` becomes `on_click`):
714
+ You can nest HTML event listeners under an element by using the HTML event listener name (e.g. `onclick`, `onchange`, `onblur`):
697
715
 
698
716
  ```ruby
699
717
  button('Add') {
700
- on_click do
718
+ onclick do
701
719
  @model.add_selected_element
702
720
  end
703
721
  }
@@ -718,7 +736,7 @@ form {
718
736
  input(id: 'email-field', class: 'field', type: 'email', required: true)
719
737
  }
720
738
  button('Add Contact', class: 'submit-button') {
721
- on_click do
739
+ onclick do
722
740
  ...
723
741
  end
724
742
  }
@@ -728,17 +746,23 @@ form {
728
746
  You can nest text content underneath an element's Ruby block, like:
729
747
 
730
748
  ```ruby
731
- span(class: 'summary') {
749
+ p(class: 'summary') {
732
750
  'This text content is going into the body of the span element'
733
751
  }
734
752
  ```
735
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
+
736
758
  ## Supported Glimmer DSL Keywords
737
759
 
738
760
  [All HTML elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element).
739
761
 
740
762
  [All HTML attributes](https://www.w3schools.com/html/html_attributes.asp).
741
763
 
764
+ [All HTML events](https://www.w3schools.com/tags/ref_eventattributes.asp).
765
+
742
766
  ## Samples
743
767
 
744
768
  This external sample app contains all the samples mentioned below configured inside a Rails [Opal](https://opalrb.com/) app with all the prerequisites ready to go for convenience:
@@ -806,47 +830,85 @@ require 'glimmer-dsl-web'
806
830
 
807
831
  include Glimmer
808
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
+
809
865
  Document.ready? do
810
866
  div {
811
867
  h1('Contact Form')
868
+
812
869
  form {
813
- div(class: 'field-row') {
870
+ div {
814
871
  label('Name: ', for: 'name-field')
815
- @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)
816
873
  }
817
- div(class: 'field-row') {
874
+
875
+ div {
818
876
  label('Email: ', for: 'email-field')
819
- @email_input = input(id: 'email-field', class: 'field', type: 'email', required: true)
877
+ @email_input = input(type: 'email', id: 'email-field', required: true)
820
878
  }
821
- button('Add Contact', class: 'submit-button') {
822
- on_click do
823
- if ([@name_input, @email_input].all? {|input| input.check_validity })
824
- @table.content {
825
- tr {
826
- td { @name_input.value }
827
- 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
+ }
828
890
  }
829
- }
830
- @email_input.value = @name_input.value = ''
831
- else
832
- error_messages = []
833
- error_messages << "Name is not valid! Make sure it is filled." if !@name_input.check_validity
834
- error_messages << "Email is not valid! Make sure it is filled and has a valid format." if !@email_input.check_validity
835
- $$.alert(error_messages.join("\n"))
891
+ @email_input.value = @name_input.value = ''
892
+ @name_input.focus
893
+ end
836
894
  end
837
- end
895
+ }
838
896
  }
839
897
  }
898
+
840
899
  h1('Contacts Table')
900
+
841
901
  @table = table {
842
902
  tr {
843
903
  th('Name')
844
904
  th('Email')
845
905
  }
906
+
846
907
  tr {
847
908
  td('John Doe')
848
909
  td('johndoe@example.com')
849
910
  }
911
+
850
912
  tr {
851
913
  td('Jane Doe')
852
914
  td('janedoe@example.com')
@@ -856,15 +918,11 @@ Document.ready? do
856
918
  # CSS Styles
857
919
  style {
858
920
  <<~CSS
859
- .field-row {
860
- margin: 10px 5px;
861
- }
862
- .field {
863
- margin-left: 5px;
921
+ input {
922
+ margin: 5px;
864
923
  }
865
- .submit-button {
866
- display: block;
867
- margin: 10px 5px;
924
+ input[type=submit] {
925
+ margin: 5px 0;
868
926
  }
869
927
  table {
870
928
  border:1px solid grey;
@@ -887,83 +945,66 @@ That produces the following under `<body></body>`:
887
945
  ```html
888
946
  <div data-parent="body" class="element element-1">
889
947
  <h1 class="element element-2">Contact Form</h1>
948
+
890
949
  <form class="element element-3">
891
- <div class="field-row element element-4">
950
+ <div class="element element-4">
892
951
  <label for="name-field" class="element element-5">Name: </label>
893
- <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">
894
953
  </div>
895
- <div class="field-row element element-7">
954
+
955
+ <div class="element element-7">
896
956
  <label for="email-field" class="element element-8">Email: </label>
897
- <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">
898
962
  </div>
899
- <button class="submit-button element element-10">Add Contact</button>
900
963
  </form>
901
- <h1 class="element element-11">Contacts Table</h1>
902
- <table class="element element-12">
903
- <tr class="element element-13">
904
- <th class="element element-14">Name</th>
905
- <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>
906
971
  </tr>
907
- <tr class="element element-16">
908
- <td class="element element-17">John Doe</td>
909
- <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>
910
976
  </tr>
911
- <tr class="element element-19">
912
- <td class="element element-20">Jane Doe</td>
913
- <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>
914
981
  </tr>
915
982
  </table>
916
- <style class="element element-22">.field-row {
917
- margin: 10px 5px;
918
- }
919
- .field {
920
- margin-left: 5px;
921
- }
922
- .submit-button {
923
- display: block;
924
- margin: 10px 5px;
925
- }
926
- table {
927
- border:1px solid grey;
928
- border-spacing: 0;
929
- }
930
- table tr td, table tr th {
931
- padding: 5px;
932
- }
933
- table tr:nth-child(even) {
934
- background: #ccc;
935
- }
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
+ }
936
1001
  </style>
937
1002
  </div>
938
1003
  ```
939
1004
 
940
- Screenshots:
941
-
942
- ---
943
-
944
- ***Hello, Button!***
945
-
946
- ![Hello, Button!](/images/glimmer-dsl-web-samples-hello-hello-button.png)
947
-
948
- ---
949
-
950
- ***Hello, Button! Submitted Invalid Data***
951
-
952
- ![Hello, Button! Invalid Data](/images/glimmer-dsl-web-samples-hello-hello-button-invalid-data.png)
953
-
954
- ---
955
-
956
- ***Hello, Button! Filled Valid Name and Email***
957
-
958
- ![Hello, Button! Filled](/images/glimmer-dsl-web-samples-hello-hello-button-filled-name-and-email.png)
959
-
960
- ---
961
-
962
- ***Hello, Button! Added Contact***
963
-
964
- ![Hello, Button! Added Contact](/images/glimmer-dsl-web-samples-hello-hello-button-added-contact.png)
1005
+ Screenshot:
965
1006
 
966
- ---
1007
+ ![Hello, Form!](/images/glimmer-dsl-web-samples-hello-hello-form.gif)
967
1008
 
968
1009
  #### Button Counter
969
1010
 
@@ -995,7 +1036,7 @@ class HelloButton
995
1036
 
996
1037
  markup {
997
1038
  # This will hook into element #app-container and then build HTML inside it using Ruby DSL code
998
- div(root_css_selector) {
1039
+ div(parent: parent_selector) {
999
1040
  text 'Button Counter'
1000
1041
 
1001
1042
  button {
@@ -1004,7 +1045,7 @@ class HelloButton
1004
1045
  # copied to button innerText (content) to display to the user
1005
1046
  inner_text <= [@counter, :count, on_read: ->(value) { "Click To Increment: #{value} " }]
1006
1047
 
1007
- on_click {
1048
+ onclick {
1008
1049
  @counter.increment!
1009
1050
  }
1010
1051
  }
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.4
1
+ 0.0.5
@@ -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.0.4 ruby lib
5
+ # stub: glimmer-dsl-web 0.0.5 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "glimmer-dsl-web".freeze
9
- s.version = "0.0.4".freeze
9
+ s.version = "0.0.5".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]
@@ -31,18 +31,20 @@ Gem::Specification.new do |s|
31
31
  "lib/glimmer-dsl-web/ext/date.rb",
32
32
  "lib/glimmer-dsl-web/ext/exception.rb",
33
33
  "lib/glimmer-dsl-web/samples/hello/hello_button.rb",
34
+ "lib/glimmer-dsl-web/samples/hello/hello_form.rb",
34
35
  "lib/glimmer-dsl-web/samples/hello/hello_world.rb",
35
36
  "lib/glimmer-dsl-web/vendor/jquery.js",
36
37
  "lib/glimmer/config/opal_logger.rb",
37
38
  "lib/glimmer/data_binding/element_binding.rb",
38
- "lib/glimmer/data_binding/observable_element.rb",
39
39
  "lib/glimmer/dsl/web/dsl.rb",
40
40
  "lib/glimmer/dsl/web/element_expression.rb",
41
41
  "lib/glimmer/dsl/web/listener_expression.rb",
42
+ "lib/glimmer/dsl/web/p_expression.rb",
42
43
  "lib/glimmer/dsl/web/property_expression.rb",
43
44
  "lib/glimmer/util/proc_tracker.rb",
44
45
  "lib/glimmer/web.rb",
45
46
  "lib/glimmer/web/element_proxy.rb",
47
+ "lib/glimmer/web/event_proxy.rb",
46
48
  "lib/glimmer/web/listener_proxy.rb",
47
49
  "lib/glimmer/web/property_owner.rb"
48
50
  ]
@@ -3,6 +3,7 @@ require 'glimmer/dsl/engine'
3
3
  require 'glimmer/dsl/web/element_expression'
4
4
  require 'glimmer/dsl/web/listener_expression'
5
5
  require 'glimmer/dsl/web/property_expression'
6
+ require 'glimmer/dsl/web/p_expression'
6
7
 
7
8
  module Glimmer
8
9
  module DSL
@@ -11,7 +11,7 @@ module Glimmer
11
11
  def can_interpret?(parent, keyword, *args, &block)
12
12
  # TODO automatically pass parent option as element if not passed instead of rejecting elements without a paraent nor root
13
13
  # TODO raise a proper error if root is an element that is not found (maybe do this in model)
14
- !keyword.to_s.start_with?('on_')
14
+ !keyword.to_s.start_with?('on')
15
15
  end
16
16
 
17
17
  def interpret(parent, keyword, *args, &block)
@@ -0,0 +1,31 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/parent_expression'
3
+
4
+ require 'glimmer/web/element_proxy'
5
+
6
+ module Glimmer
7
+ module DSL
8
+ module Web
9
+ class PExpression < StaticExpression
10
+ include ParentExpression
11
+
12
+ def interpret(parent, keyword, *args, &block)
13
+ Glimmer::Web::ElementProxy.for(keyword, parent, args, block)
14
+ end
15
+
16
+ def add_content(parent, keyword, *args, &block)
17
+ if parent.rendered? || parent.skip_content_on_render_blocks?
18
+ return_value = super(parent, keyword, *args, &block)
19
+ if return_value.is_a?(String) && parent.dom_element.text.to_s.empty?
20
+ parent.add_text_content(return_value)
21
+ end
22
+ parent.post_add_content
23
+ return_value
24
+ else
25
+ parent.add_content_on_render(&block)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -74,7 +74,7 @@ module Glimmer
74
74
 
75
75
  GLIMMER_ATTRIBUTES = [:parent]
76
76
 
77
- attr_reader :keyword, :parent, :args, :options, :children, :enabled, :foreground, :background, :focus, :removed?, :rendered
77
+ attr_reader :keyword, :parent, :args, :options, :children, :enabled, :foreground, :background, :removed?, :rendered
78
78
  alias rendered? rendered
79
79
 
80
80
  def initialize(keyword, parent, args, block)
@@ -176,16 +176,6 @@ module Glimmer
176
176
  dom_element.css('background-color', background.to_css) unless background.nil?
177
177
  end
178
178
 
179
- def focus=(value)
180
- @focus = value
181
- dom_element.focus # TODO consider if a delay or async_exec is needed here
182
- end
183
-
184
- def set_focus
185
- self.focus = true
186
- end
187
- alias setFocus set_focus
188
-
189
179
  def parent_selector
190
180
  @parent&.selector
191
181
  end
@@ -226,7 +216,7 @@ module Glimmer
226
216
  end
227
217
  end
228
218
  end
229
- alias redraw render
219
+ alias rerender render
230
220
 
231
221
  def attach(the_parent_dom_element)
232
222
  the_parent_dom_element.append(@dom)
@@ -743,7 +733,7 @@ module Glimmer
743
733
  def can_handle_observation_request?(keyword)
744
734
  # TODO sort this out for Opal
745
735
  keyword = keyword.to_s
746
- keyword.start_with?('on_')
736
+ keyword.start_with?('on')
747
737
  # if keyword.start_with?('on_swt_')
748
738
  # constant_name = keyword.sub(/^on_swt_/, '')
749
739
  # SWTProxy.has_constant?(constant_name)
@@ -765,10 +755,10 @@ module Glimmer
765
755
 
766
756
  def handle_javascript_observation_request(keyword, original_event_listener)
767
757
  listener = ListenerProxy.new(
768
- element_proxy: self,
758
+ element: self,
769
759
  selector: selector,
770
760
  dom_element: dom_element,
771
- event: keyword.sub(/^on_/, ''),
761
+ event_attribute: keyword,
772
762
  listener: original_event_listener,
773
763
  original_event_listener: original_event_listener
774
764
  )
@@ -827,6 +817,7 @@ module Glimmer
827
817
  end
828
818
 
829
819
  def respond_to_missing?(method_name, include_private = false)
820
+ # TODO consider doing more correct checking of availability of properties/methods using native `` ticks
830
821
  property_name = property_name_for(method_name)
831
822
  super(method_name, include_private) ||
832
823
  (dom_element && dom_element.length > 0 && Native.call(dom_element, '0').respond_to?(method_name.to_s.camelcase, include_private)) ||
@@ -836,6 +827,7 @@ module Glimmer
836
827
  end
837
828
 
838
829
  def method_missing(method_name, *args, &block)
830
+ # TODO consider doing more correct checking of availability of properties/methods using native `` ticks
839
831
  property_name = property_name_for(method_name)
840
832
  if method_name.to_s.start_with?('on_')
841
833
  handle_observation_request(method_name, block)
@@ -0,0 +1,59 @@
1
+ # Copyright (c) 2023 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ module Glimmer
23
+ module Web
24
+ class EventProxy
25
+ attr_reader :js_event, :listener
26
+
27
+ def initialize(js_event:, listener:)
28
+ @js_event = js_event
29
+ @listener = listener
30
+ end
31
+
32
+ def element = listener.element
33
+ def event_name = listener.event_name
34
+ def event_attribute = listener.event_attribute
35
+
36
+ def original_event
37
+ Native(`#{js_event.to_n}.originalEvent`)
38
+ end
39
+
40
+ def respond_to_missing?(method_name, include_private = false)
41
+ property_name = method_name.to_s.camelcase
42
+ super(method_name, include_private) ||
43
+ js_event.respond_to?(method_name, include_private) ||
44
+ `#{property_name} in #{original_event.to_n}`
45
+ end
46
+
47
+ def method_missing(method_name, *args, &block)
48
+ property_name = method_name.to_s.camelcase
49
+ if js_event.respond_to?(method_name, true)
50
+ js_event.send(method_name, *args, &block)
51
+ elsif `#{property_name} in #{original_event.to_n}`
52
+ original_event[property_name]
53
+ else
54
+ super(method_name, *args, &block)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -1,36 +1,58 @@
1
+ # Copyright (c) 2023 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer/web/event_proxy'
23
+
1
24
  module Glimmer
2
25
  module Web
3
26
  class ListenerProxy
4
- attr_reader :element_proxy, :event, :dom_element, :selector, :listener, :original_event_listener
27
+ attr_reader :element, :event_attribute, :event_name, :dom_element, :selector, :listener, :js_listener, :original_event_listener
5
28
 
6
- def initialize(element_proxy:, event:, dom_element:, selector:, listener:)
7
- @element_proxy = element_proxy
8
- @event = event
29
+ def initialize(element:, event_attribute:, dom_element:, selector:, listener:)
30
+ @element = element
31
+ @event_attribute = event_attribute
32
+ @event_name = event_attribute.sub(/^on/, '')
9
33
  @dom_element = dom_element
10
34
  @selector = selector
11
35
  @listener = listener
12
- @js_listener = lambda do |event|
13
- event.prevent
14
- event.prevent_default
15
- event.stop_propagation
16
- event.stop_immediate_propagation
36
+ @js_listener = lambda do |js_event|
17
37
  # TODO wrap event with a Ruby Event object before passing to listener
18
- listener.call(event)
19
- false
38
+ event = EventProxy.new(js_event: js_event, listener: self)
39
+ result = listener.call(event)
40
+ result = true if result.nil?
41
+ result
20
42
  end
21
43
  @original_event_listener = original_event_listener
22
44
  end
23
45
 
24
46
  def register
25
- @dom_element.on(@event, &@js_listener)
47
+ @dom_element.on(@event_name, &@js_listener)
26
48
  end
27
49
  alias observe register
28
50
  alias reregister register
29
51
 
30
52
  def unregister
31
53
  # TODO contribute fix to opal to allow passing observer with & to off with selector not specified as nil
32
- @dom_element.off(@event, @js_listener)
33
- @element_proxy.listeners_for(@event).delete(self)
54
+ @dom_element.off(@event_name, @js_listener)
55
+ @element.listeners_for(@event_attribute).delete(self)
34
56
  end
35
57
  alias unobserve unregister
36
58
  alias deregister unregister
@@ -25,75 +25,10 @@ include Glimmer
25
25
 
26
26
  Document.ready? do
27
27
  div {
28
- h1('Contact Form')
29
- form {
30
- div(class: 'field-row') {
31
- label('Name: ', for: 'name-field')
32
- @name_input = input(id: 'name-field', class: 'field', type: 'text', required: true)
33
- }
34
- div(class: 'field-row') {
35
- label('Email: ', for: 'email-field')
36
- @email_input = input(id: 'email-field', class: 'field', type: 'email', required: true)
37
- }
38
- button('Add Contact', class: 'submit-button') {
39
- on_click do
40
- if ([@name_input, @email_input].all? {|input| input.check_validity })
41
- @table.content {
42
- tr {
43
- td { @name_input.value }
44
- td { @email_input.value }
45
- }
46
- }
47
- @email_input.value = @name_input.value = ''
48
- else
49
- error_messages = []
50
- error_messages << "Name is not valid! Make sure it is filled." if !@name_input.check_validity
51
- error_messages << "Email is not valid! Make sure it is filled and has a valid format." if !@email_input.check_validity
52
- $$.alert(error_messages.join("\n"))
53
- end
54
- end
55
- }
56
- }
57
- h1('Contacts Table')
58
- @table = table {
59
- tr {
60
- th('Name')
61
- th('Email')
62
- }
63
- tr {
64
- td('John Doe')
65
- td('johndoe@example.com')
66
- }
67
- tr {
68
- td('Jane Doe')
69
- td('janedoe@example.com')
70
- }
71
- }
72
-
73
- # CSS Styles
74
- style {
75
- <<~CSS
76
- .field-row {
77
- margin: 10px 5px;
78
- }
79
- .field {
80
- margin-left: 5px;
81
- }
82
- .submit-button {
83
- display: block;
84
- margin: 10px 5px;
85
- }
86
- table {
87
- border:1px solid grey;
88
- border-spacing: 0;
89
- }
90
- table tr td, table tr th {
91
- padding: 5px;
92
- }
93
- table tr:nth-child(even) {
94
- background: #ccc;
95
- }
96
- CSS
28
+ button('Greet') {
29
+ onclick do
30
+ $$.alert('Hello, Button!')
31
+ end
97
32
  }
98
33
  }.render
99
34
  end
@@ -0,0 +1,102 @@
1
+ # Copyright (c) 2023 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer-dsl-web'
23
+
24
+ include Glimmer
25
+
26
+ Document.ready? do
27
+ div {
28
+ h1('Contact Form')
29
+
30
+ form {
31
+ div {
32
+ label('Name: ', for: 'name-field')
33
+ @name_input = input(type: 'text', id: 'name-field', required: true, autofocus: true)
34
+ }
35
+
36
+ div {
37
+ label('Email: ', for: 'email-field')
38
+ @email_input = input(type: 'email', id: 'email-field', required: true)
39
+ }
40
+
41
+ div {
42
+ input(type: 'submit', value: 'Add Contact') {
43
+ onclick do |event|
44
+ if ([@name_input, @email_input].all? {|input| input.check_validity })
45
+ event.prevent_default
46
+ # re-open table content and add row
47
+ @table.content {
48
+ tr {
49
+ td { @name_input.value }
50
+ td { @email_input.value }
51
+ }
52
+ }
53
+ @email_input.value = @name_input.value = ''
54
+ @name_input.focus
55
+ end
56
+ end
57
+ }
58
+ }
59
+ }
60
+
61
+ h1('Contacts Table')
62
+
63
+ @table = table {
64
+ tr {
65
+ th('Name')
66
+ th('Email')
67
+ }
68
+
69
+ tr {
70
+ td('John Doe')
71
+ td('johndoe@example.com')
72
+ }
73
+
74
+ tr {
75
+ td('Jane Doe')
76
+ td('janedoe@example.com')
77
+ }
78
+ }
79
+
80
+ # CSS Styles
81
+ style {
82
+ <<~CSS
83
+ input {
84
+ margin: 5px;
85
+ }
86
+ input[type=submit] {
87
+ margin: 5px 0;
88
+ }
89
+ table {
90
+ border:1px solid grey;
91
+ border-spacing: 0;
92
+ }
93
+ table tr td, table tr th {
94
+ padding: 5px;
95
+ }
96
+ table tr:nth-child(even) {
97
+ background: #ccc;
98
+ }
99
+ CSS
100
+ }
101
+ }.render
102
+ end
@@ -76,12 +76,7 @@ if RUBY_ENGINE == 'opal'
76
76
  require 'glimmer-dsl-xml'
77
77
  require 'glimmer-dsl-css'
78
78
 
79
- # TODO double check if alias native calls below have been added to jQuery-Opal (remove if so)
80
- Element.alias_native :replace_with, :replaceWith
81
- Element.alias_native :select
82
- # Element.alias_native :dialog
83
-
84
- Glimmer::Config.loop_max_count = 150 # TODO disable
79
+ Glimmer::Config.loop_max_count = 150 # TODO consider disabling if preferred
85
80
 
86
81
  original_logger_level = Glimmer::Config.logger.level
87
82
  Glimmer::Config.logger = Glimmer::Config::OpalLogger.new(STDOUT)
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.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
@@ -259,18 +259,20 @@ files:
259
259
  - lib/glimmer-dsl-web/ext/date.rb
260
260
  - lib/glimmer-dsl-web/ext/exception.rb
261
261
  - lib/glimmer-dsl-web/samples/hello/hello_button.rb
262
+ - lib/glimmer-dsl-web/samples/hello/hello_form.rb
262
263
  - lib/glimmer-dsl-web/samples/hello/hello_world.rb
263
264
  - lib/glimmer-dsl-web/vendor/jquery.js
264
265
  - lib/glimmer/config/opal_logger.rb
265
266
  - lib/glimmer/data_binding/element_binding.rb
266
- - lib/glimmer/data_binding/observable_element.rb
267
267
  - lib/glimmer/dsl/web/dsl.rb
268
268
  - lib/glimmer/dsl/web/element_expression.rb
269
269
  - lib/glimmer/dsl/web/listener_expression.rb
270
+ - lib/glimmer/dsl/web/p_expression.rb
270
271
  - lib/glimmer/dsl/web/property_expression.rb
271
272
  - lib/glimmer/util/proc_tracker.rb
272
273
  - lib/glimmer/web.rb
273
274
  - lib/glimmer/web/element_proxy.rb
275
+ - lib/glimmer/web/event_proxy.rb
274
276
  - lib/glimmer/web/listener_proxy.rb
275
277
  - lib/glimmer/web/property_owner.rb
276
278
  homepage: http://github.com/AndyObtiva/glimmer-dsl-web
@@ -1,14 +0,0 @@
1
- module Glimmer
2
- module DataBinding
3
- module ObservableElement
4
- def method_missing(method, *args, &block)
5
- method_name = method.to_s
6
- if method_name.start_with?('on_')
7
- handle_observation_request(method_name, block)
8
- else
9
- super
10
- end
11
- end
12
- end
13
- end
14
- end