glimmer-dsl-web 0.4.2 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +283 -56
- data/VERSION +1 -1
- data/glimmer-dsl-web.gemspec +3 -2
- data/lib/glimmer/data_binding/element_binding.rb +10 -4
- data/lib/glimmer/dsl/web/class_name_inclusion_data_binding.rb +21 -0
- data/lib/glimmer/dsl/web/dsl.rb +2 -0
- data/lib/glimmer/web/component.rb +8 -2
- data/lib/glimmer/web/element_proxy.rb +29 -2
- data/lib/glimmer-dsl-web/samples/hello/hello_style.rb +24 -25
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/edit_todo_input.rb +19 -10
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/new_todo_form.rb +8 -8
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/new_todo_input.rb +8 -5
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_filters.rb +64 -51
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_input.rb +14 -14
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_list.rb +33 -37
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_list_item.rb +62 -59
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_mvc_footer.rb +9 -9
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc.rb +20 -20
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 757705f381e25fbeb5666fd26b544cece14ed84cb335f6b1f7e6a4c273bac53f
|
4
|
+
data.tar.gz: 6a5b9416eb62f2b823f1357c813ee18e417df6e769ae57dcb8704bb8079a31bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d1c13a1b7199085718ccb37158232874a0599eee6bac22036ee86aa0d29ae2cdaf404a1ab701b5a9060cedbb4b846f00750a97a17760430a0731cb2a53e4e65
|
7
|
+
data.tar.gz: 0cd1b2ab98e2abab219c9d5dcbbb49dbf9c5c5f8bfa9b6f8a764589aa3d65dac991a77bd1b865d1f616db5ca82c2eb05b239a60a27b8f6f17a81cdd03365937e
|
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,17 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.4.3
|
4
|
+
|
5
|
+
- Support element class name inclusion data-binding (e.g. `class_name('pushed') <= [@button_model, :pushed]`)
|
6
|
+
- Refactor Todo MVC sample to simplify and utilize new element inline style data-binding and element class name inclusion data-binding features
|
7
|
+
- Fix issue with component removal removing its style element even if other instances of the same component still exist (this was breaking TodoMVC when clearly Todo items)
|
8
|
+
|
3
9
|
## 0.4.2
|
4
10
|
|
5
11
|
- Support element inline style data-binding (e.g. `style(:background_color) <= [@button_model, :background_color]`)
|
6
12
|
- Support SVG element keywords
|
7
13
|
- Hello, SVG! Sample: `require 'glimmer-dsl-web/samples/hello/hello_svg'`
|
14
|
+
- Upgrade to glimmer-dsl-css 1.5.1 to get support for `px`, `in`, `pt`, `cm`, `mm`, `em` methods on `Numeric` (e.g. `14.px` => `"14px"` / `2.em` => `"2em"`) and support for `%` method on `Integer`/`Float` to allow producing `%` CSS values (e.g. `90.%` => `"90%"`)
|
8
15
|
|
9
16
|
## 0.4.1
|
10
17
|
|
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.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.4.3 (Beta)
|
2
2
|
## Ruby-in-the-Browser Web Frontend Framework
|
3
3
|
### Finally, Ruby Developer Productivity, Happiness, and Fun in the Frontend!!!
|
4
4
|
[![Gem Version](https://badge.fury.io/rb/glimmer-dsl-web.svg)](http://badge.fury.io/rb/glimmer-dsl-web)
|
@@ -12,7 +12,7 @@
|
|
12
12
|
|
13
13
|
You can finally have Ruby developer happiness and productivity in the Frontend! No more wasting time splitting your resources across multiple languages, using badly engineered, over-engineered, or premature-optimization-obsessed JavaScript libraries, fighting JavaScript build issues (e.g. webpack), or rewriting Ruby Backend code in Frontend JavaScript. With [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c), you can have an exponential jump in development productivity (2x or higher), time-to-release (1/2 or less time), cost (1/2 or cheaper), and maintainability (~50% the code that is simpler and more readable) over JavaScript libraries like React, Angular, Ember, Vue, and Svelte, while being able to reuse Backend Ruby code as is in the Frontend for faster interactions when needed. Also, with Frontend Ruby, companies can cut their hiring budget in half by having Backend Ruby Software Engineers do Frontend Development in Ruby! [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c) finally fulfills every smart highly-productive Rubyist's dream by bringing Ruby productivity fun to Frontend Development, the same productivity fun you had for years and decades in Backend Development.
|
14
14
|
|
15
|
-
[Glimmer](https://github.com/AndyObtiva/glimmer) DSL for Web enables building Web 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 supports Rails' principle of the One Person Framework by not requiring any extra developers with JavaScript expertise, yet enabling Ruby (Backend) Software Engineers to develop the Frontend with Ruby code that is better than any JavaScript code produced by JS developers. It aims at providing the simplest, most intuitive, most straight-forward, and most productive frontend framework in existence. The framework follows the Ruby way (with [DSLs](https://martinfowler.com/books/dsl.html) and [TIMTOWTDI](https://en.wiktionary.org/wiki/TMTOWTDI#English)) and the Rails way ([Convention over Configuration](https://rubyonrails.org/doctrine)) in building Isomorphic Ruby on Rails Applications. It provides a Ruby [HTML DSL](#usage), which uniquely enables writing both structure code and logic code in one language. It supports both Unidirectional (One-Way) [Data-Binding](#hello-data-binding) (using `<=`) and Bidirectional (Two-Way) [Data-Binding](#hello-data-binding) (using `<=>`). Dynamic rendering (and re-rendering) of HTML content is also supported via [Content Data-Binding](#hello-content-data-binding). Modular design is supported with [Glimmer Web Components](#hello-component). And, a Ruby CSS DSL is supported with the included [Glimmer DSL for CSS](https://github.com/AndyObtiva/glimmer-dsl-css). To automatically convert legacy HTML & CSS code to Glimmer DSL Ruby code, Software Engineers could use the included [`html_to_glimmer`](https://github.com/AndyObtiva/glimmer-dsl-xml#html-to-glimmer-converter) and [`css_to_glimmer`](https://github.com/AndyObtiva/glimmer-dsl-css#css-to-glimmer-converter) commands. Many [samples](#samples) are demonstrated in the [Rails sample app](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app) (there is a very minimal [Standalone [No Rails] static site sample app](https://github.com/Largo/glimmer-dsl-web-standalone-demo) too). 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)!
|
15
|
+
[Glimmer](https://github.com/AndyObtiva/glimmer) DSL for Web enables building Web 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 supports Rails' principle of the One Person Framework by not requiring any extra developers with JavaScript expertise, yet enabling Ruby (Backend) Software Engineers to develop the Frontend with Ruby code that is better than any JavaScript code produced by JS developers. It aims at providing the simplest, most intuitive, most straight-forward, and most productive frontend framework in existence. The framework follows the Ruby way (with [DSLs](https://martinfowler.com/books/dsl.html) and [TIMTOWTDI](https://en.wiktionary.org/wiki/TMTOWTDI#English)) and the Rails way ([Convention over Configuration](https://rubyonrails.org/doctrine)) in building Isomorphic Ruby on Rails Applications. It provides a Ruby [HTML DSL](#usage) (including full support for [SVG](#hello-svg)), which uniquely enables writing both structure code and logic code in one language. It supports both Unidirectional (One-Way) [Data-Binding](#hello-data-binding) (using `<=`) and Bidirectional (Two-Way) [Data-Binding](#hello-data-binding) (using `<=>`). Dynamic rendering (and re-rendering) of HTML content is also supported via [Content Data-Binding](#hello-content-data-binding). Modular design is supported with [Glimmer Web Components](#hello-component). And, a Ruby CSS DSL is supported with the included [Glimmer DSL for CSS](https://github.com/AndyObtiva/glimmer-dsl-css). To automatically convert legacy HTML & CSS code to Glimmer DSL Ruby code, Software Engineers could use the included [`html_to_glimmer`](https://github.com/AndyObtiva/glimmer-dsl-xml#html-to-glimmer-converter) and [`css_to_glimmer`](https://github.com/AndyObtiva/glimmer-dsl-css#css-to-glimmer-converter) commands. Many [samples](#samples) are demonstrated in the [Rails sample app](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app) (there is a very minimal [Standalone [No Rails] static site sample app](https://github.com/Largo/glimmer-dsl-web-standalone-demo) too). 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)!
|
16
16
|
|
17
17
|
[Glimmer DSL for Web](https://rubygems.org/gems/glimmer-dsl-web) aims to be a very simple Ruby-based drop-in replacement for your existing JavaScript Frontend library (e.g. React, Angular, Vue, Ember, Svelte) or your JavaScript Frontend layer in general. It does not change how your Frontend interacts with the Backend, meaning you can continue to write Rails Backend API endpoints as needed and make HTTP/Ajax requests or read data embedded in elements, but from [Ruby in the Browser](https://www.youtube.com/watch?v=4AdcfbI6A4c). Whatever is possible in JavaScript is possible when using Glimmer DSL for Web as it integrates with any existing JavaScript library. The [Rails sample app](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app) demonstrates how to [make HTTP calls](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/sample_selector/models/sample_api.rb) and how to [integrate with a JavaScript library](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/views/layouts/application.html.erb) (highlightjs) that performs [code syntax highlighting](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/assets/opal/sample_selector.rb).
|
18
18
|
|
@@ -1243,10 +1243,6 @@ class TodoMvc
|
|
1243
1243
|
todo_list(presenter: @presenter)
|
1244
1244
|
|
1245
1245
|
todo_filters(presenter: @presenter)
|
1246
|
-
|
1247
|
-
style {
|
1248
|
-
todo_mvc_styles
|
1249
|
-
}
|
1250
1246
|
}
|
1251
1247
|
|
1252
1248
|
todo_mvc_footer
|
@@ -1257,46 +1253,46 @@ class TodoMvc
|
|
1257
1253
|
}
|
1258
1254
|
}
|
1259
1255
|
|
1260
|
-
|
1261
|
-
|
1262
|
-
margin
|
1263
|
-
padding
|
1256
|
+
style {
|
1257
|
+
r('body, button, html') {
|
1258
|
+
margin 0
|
1259
|
+
padding 0
|
1264
1260
|
}
|
1265
1261
|
|
1266
|
-
|
1267
|
-
_webkit_font_smoothing
|
1268
|
-
_webkit_appearance
|
1269
|
-
appearance
|
1270
|
-
background
|
1271
|
-
border
|
1272
|
-
color
|
1273
|
-
font_family
|
1262
|
+
r('button') {
|
1263
|
+
_webkit_font_smoothing :antialiased
|
1264
|
+
_webkit_appearance :none
|
1265
|
+
appearance :none
|
1266
|
+
background :none
|
1267
|
+
border 0
|
1268
|
+
color :inherit
|
1269
|
+
font_family :inherit
|
1274
1270
|
font_size '100%'
|
1275
|
-
font_weight
|
1276
|
-
vertical_align
|
1271
|
+
font_weight :inherit
|
1272
|
+
vertical_align :baseline
|
1277
1273
|
}
|
1278
1274
|
|
1279
|
-
|
1275
|
+
r('.todoapp') {
|
1280
1276
|
background '#fff'
|
1281
1277
|
margin '130px 0 40px 0'
|
1282
|
-
position
|
1278
|
+
position :relative
|
1283
1279
|
box_shadow '0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1)'
|
1284
1280
|
}
|
1285
1281
|
|
1286
1282
|
media('screen and (-webkit-min-device-pixel-ratio:0)') {
|
1287
|
-
|
1283
|
+
r('body') {
|
1288
1284
|
font "14px 'Helvetica Neue', Helvetica, Arial, sans-serif"
|
1289
|
-
line_height
|
1285
|
+
line_height 1.4.em
|
1290
1286
|
background '#f5f5f5'
|
1291
1287
|
color '#111111'
|
1292
|
-
min_width
|
1293
|
-
max_width
|
1288
|
+
min_width 230
|
1289
|
+
max_width 550
|
1294
1290
|
margin '0 auto'
|
1295
|
-
_webkit_font_smoothing
|
1291
|
+
_webkit_font_smoothing :antialiased
|
1296
1292
|
font_weight '300'
|
1297
1293
|
}
|
1298
1294
|
}
|
1299
|
-
|
1295
|
+
}
|
1300
1296
|
end
|
1301
1297
|
|
1302
1298
|
Document.ready? do
|
@@ -1340,6 +1336,8 @@ Learn more about the differences between various [Glimmer](https://github.com/An
|
|
1340
1336
|
- [Hello, Component!](#hello-content-data-binding)
|
1341
1337
|
- [Hello, glimmer_component Rails Helper!](#hello-glimmer_component-rails-helper)
|
1342
1338
|
- [Hello, Paragraph!](#hello-paragraph)
|
1339
|
+
- [Hello, Style!](#hello-style)
|
1340
|
+
- [Hello, SVG!](#hello-svg)
|
1343
1341
|
- [Hello, Input (Date/Time)!](#hello-input-datetime)
|
1344
1342
|
- [Button Counter](#button-counter)
|
1345
1343
|
- [Todo MVC](#todo-mvc)
|
@@ -1392,7 +1390,7 @@ rails new glimmer_app_server
|
|
1392
1390
|
Add the following to `Gemfile`:
|
1393
1391
|
|
1394
1392
|
```
|
1395
|
-
gem 'glimmer-dsl-web', '~> 0.4.
|
1393
|
+
gem 'glimmer-dsl-web', '~> 0.4.3'
|
1396
1394
|
```
|
1397
1395
|
|
1398
1396
|
Run:
|
@@ -1621,7 +1619,7 @@ Disable the `webpacker` gem line in `Gemfile`:
|
|
1621
1619
|
Add the following to `Gemfile`:
|
1622
1620
|
|
1623
1621
|
```ruby
|
1624
|
-
gem 'glimmer-dsl-web', '~> 0.4.
|
1622
|
+
gem 'glimmer-dsl-web', '~> 0.4.3'
|
1625
1623
|
```
|
1626
1624
|
|
1627
1625
|
Run:
|
@@ -3141,6 +3139,239 @@ Screenshot:
|
|
3141
3139
|
|
3142
3140
|
![Hello, Paragraph!](/images/glimmer-dsl-web-samples-hello-hello-paragraph.png)
|
3143
3141
|
|
3142
|
+
#### Hello, Style!
|
3143
|
+
|
3144
|
+
Every Glimmer Web Component can have a `style {}` block that contains CSS styles common to all instances of that element. That block is evaluated against the component class as such.
|
3145
|
+
|
3146
|
+
Also, within every element, you can add `style(:property) <= [model, attribute]` element inline style data-binding statements to dynamically alter a CSS style property based on some changes to a model attribute.
|
3147
|
+
|
3148
|
+
[lib/glimmer-dsl-web/samples/hello/hello_style.rb](/lib/glimmer-dsl-web/samples/hello/hello_style.rb)
|
3149
|
+
|
3150
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
3151
|
+
|
3152
|
+
```ruby
|
3153
|
+
require 'glimmer-dsl-web'
|
3154
|
+
|
3155
|
+
class ButtonModel
|
3156
|
+
WIDTH_MIN = 160
|
3157
|
+
WIDTH_MAX = 960
|
3158
|
+
HEIGHT_MIN = 100
|
3159
|
+
HEIGHT_MAX = 600
|
3160
|
+
FONT_SIZE_MIN = 40
|
3161
|
+
FONT_SIZE_MAX = 200
|
3162
|
+
|
3163
|
+
attr_accessor :text, :pushed, :background_color, :width, :height, :font_size
|
3164
|
+
|
3165
|
+
def initialize
|
3166
|
+
@text = 'Push'
|
3167
|
+
@width = WIDTH_MIN
|
3168
|
+
@height = HEIGHT_MIN
|
3169
|
+
@font_size = FONT_SIZE_MIN
|
3170
|
+
@background_color = '#add8e6'
|
3171
|
+
end
|
3172
|
+
|
3173
|
+
def push
|
3174
|
+
self.pushed = !pushed
|
3175
|
+
end
|
3176
|
+
|
3177
|
+
def text
|
3178
|
+
pushed ? 'Pull' : 'Push'
|
3179
|
+
end
|
3180
|
+
|
3181
|
+
def width=(value)
|
3182
|
+
@width = value
|
3183
|
+
self.font_size = @width/4 if @font_size > @width/4
|
3184
|
+
end
|
3185
|
+
|
3186
|
+
def height=(value)
|
3187
|
+
@height = value
|
3188
|
+
self.font_size = @height/2.5 if @font_size > @height/2.5
|
3189
|
+
end
|
3190
|
+
|
3191
|
+
def font_size=(value)
|
3192
|
+
@font_size = value
|
3193
|
+
self.width = @font_size*4 if @height < @font_size*4
|
3194
|
+
self.height = @font_size*2.5 if @height < @font_size*2.5
|
3195
|
+
end
|
3196
|
+
|
3197
|
+
def border_color
|
3198
|
+
red = background_color[1..2].hex
|
3199
|
+
green = background_color[3..4].hex
|
3200
|
+
blue = background_color[5..6].hex
|
3201
|
+
new_red = red - 10
|
3202
|
+
new_green = green - 10
|
3203
|
+
new_blue = blue - 10
|
3204
|
+
"##{new_red.to_s(16)}#{new_green.to_s(16)}#{new_blue.to_s(16)}"
|
3205
|
+
end
|
3206
|
+
end
|
3207
|
+
|
3208
|
+
class StyledButton
|
3209
|
+
include Glimmer::Web::Component
|
3210
|
+
|
3211
|
+
option :button_model
|
3212
|
+
|
3213
|
+
markup {
|
3214
|
+
button {
|
3215
|
+
inner_text <= [button_model, :text, computed_by: :pushed]
|
3216
|
+
|
3217
|
+
class_name(:pushed) <= [button_model, :pushed]
|
3218
|
+
class_name(:pulled) <= [button_model, :pushed, on_read: :!]
|
3219
|
+
|
3220
|
+
style(:width) <= [button_model, :width, on_read: :px]
|
3221
|
+
style(:height) <= [button_model, :height, on_read: :px]
|
3222
|
+
style(:font_size) <= [button_model, :font_size, on_read: :px]
|
3223
|
+
style(:background_color) <= [button_model, :background_color]
|
3224
|
+
style(:border_color) <= [button_model, :border_color, computed_by: :background_color]
|
3225
|
+
|
3226
|
+
onclick do
|
3227
|
+
button_model.push
|
3228
|
+
end
|
3229
|
+
}
|
3230
|
+
}
|
3231
|
+
|
3232
|
+
style {
|
3233
|
+
r(component_element_selector) {
|
3234
|
+
font_family 'Courrier New, Courrier'
|
3235
|
+
border_radius 5
|
3236
|
+
border_width 17
|
3237
|
+
margin 5
|
3238
|
+
}
|
3239
|
+
|
3240
|
+
r("#{component_element_selector}.pulled") {
|
3241
|
+
border_style :outset
|
3242
|
+
}
|
3243
|
+
|
3244
|
+
r("#{component_element_selector}.pushed") {
|
3245
|
+
border_style :inset
|
3246
|
+
}
|
3247
|
+
}
|
3248
|
+
end
|
3249
|
+
|
3250
|
+
class StyledButtonRangeInput
|
3251
|
+
include Glimmer::Web::Component
|
3252
|
+
|
3253
|
+
option :button_model
|
3254
|
+
option :property
|
3255
|
+
option :property_min
|
3256
|
+
option :property_max
|
3257
|
+
|
3258
|
+
markup {
|
3259
|
+
input(type: 'range', min: property_min, max: property_max) {
|
3260
|
+
value <=> [button_model, property]
|
3261
|
+
}
|
3262
|
+
}
|
3263
|
+
end
|
3264
|
+
|
3265
|
+
class StyledButtonColorInput
|
3266
|
+
include Glimmer::Web::Component
|
3267
|
+
|
3268
|
+
option :button_model
|
3269
|
+
option :property
|
3270
|
+
|
3271
|
+
markup {
|
3272
|
+
input(type: 'color') {
|
3273
|
+
value <=> [button_model, property]
|
3274
|
+
}
|
3275
|
+
}
|
3276
|
+
end
|
3277
|
+
|
3278
|
+
class HelloStyle
|
3279
|
+
include Glimmer::Web::Component
|
3280
|
+
|
3281
|
+
before_render do
|
3282
|
+
@button_model = ButtonModel.new
|
3283
|
+
end
|
3284
|
+
|
3285
|
+
markup {
|
3286
|
+
div {
|
3287
|
+
div(class: 'styled-button-form') {
|
3288
|
+
label('Styled Button Width:', class: 'property-label', for: 'styled-button-width-input')
|
3289
|
+
styled_button_range_input(button_model: @button_model, property: :width, property_min: ButtonModel::WIDTH_MIN, property_max: ButtonModel::WIDTH_MAX, id: 'styled-button-width-input')
|
3290
|
+
|
3291
|
+
label('Styled Button Height:', class: 'property-label', for: 'styled-button-height-input')
|
3292
|
+
styled_button_range_input(button_model: @button_model, property: :height, property_min: ButtonModel::HEIGHT_MIN, property_max: ButtonModel::HEIGHT_MAX, id: 'styled-button-height-input')
|
3293
|
+
|
3294
|
+
label('Styled Button Font Size:', class: 'property-label', for: 'styled-button-font-size-input')
|
3295
|
+
styled_button_range_input(button_model: @button_model, property: :font_size, property_min: ButtonModel::FONT_SIZE_MIN, property_max: ButtonModel::FONT_SIZE_MAX, id: 'styled-button-font-size-input')
|
3296
|
+
|
3297
|
+
label('Styled Button Background Color:', for: 'styled-button-background-color-input')
|
3298
|
+
styled_button_color_input(button_model: @button_model, property: :background_color, id: 'styled-button-background-color-input')
|
3299
|
+
}
|
3300
|
+
|
3301
|
+
styled_button(button_model: @button_model)
|
3302
|
+
}
|
3303
|
+
}
|
3304
|
+
|
3305
|
+
style {
|
3306
|
+
r('.styled-button-form') {
|
3307
|
+
padding 20
|
3308
|
+
display 'inline-grid'
|
3309
|
+
grid_template_columns 'auto auto'
|
3310
|
+
}
|
3311
|
+
|
3312
|
+
r('.styled-button-form label, input') {
|
3313
|
+
display :block
|
3314
|
+
margin '5px 5px 5px 0'
|
3315
|
+
}
|
3316
|
+
|
3317
|
+
r("#{component_element_selector} .styled-button") {
|
3318
|
+
display :block
|
3319
|
+
}
|
3320
|
+
}
|
3321
|
+
end
|
3322
|
+
|
3323
|
+
Document.ready? do
|
3324
|
+
HelloStyle.render
|
3325
|
+
end
|
3326
|
+
```
|
3327
|
+
|
3328
|
+
Screenshot:
|
3329
|
+
|
3330
|
+
--
|
3331
|
+
|
3332
|
+
![Hello, Style!](/images/glimmer-dsl-web-samples-hello-hello-style.gif)
|
3333
|
+
|
3334
|
+
#### Hello, SVG!
|
3335
|
+
|
3336
|
+
[SVG](https://developer.mozilla.org/en-US/docs/Web/SVG) (Scalable Vector Graphics) is fully supported and can be utilized by simply embedding [SVG elements](https://developer.mozilla.org/en-US/docs/Web/SVG/Element) (all lower-case in Ruby) via the Glimmer HTML DSL syntax, just like any other HTML elements.
|
3337
|
+
|
3338
|
+
[lib/glimmer-dsl-web/samples/hello/hello_svg.rb](/lib/glimmer-dsl-web/samples/hello/hello_svg.rb)
|
3339
|
+
|
3340
|
+
Glimmer HTML DSL Ruby code in the frontend:
|
3341
|
+
|
3342
|
+
```ruby
|
3343
|
+
require 'glimmer-dsl-web'
|
3344
|
+
|
3345
|
+
class HelloSvg
|
3346
|
+
include Glimmer::Web::Component
|
3347
|
+
|
3348
|
+
markup {
|
3349
|
+
div {
|
3350
|
+
svg(width: '100%', height: '100') {
|
3351
|
+
circle(cx: '50', cy: '50', r: '50', style: 'fill:blue;') {
|
3352
|
+
animate(attributename: 'cx', begin: '0s', dur: '8s', from: '50', to: '90%', repeatcount: 'indefinite')
|
3353
|
+
}
|
3354
|
+
}
|
3355
|
+
svg(width: '200', height: '180') {
|
3356
|
+
rect(x: '30', y: '30', height: '110', width: '110', style: 'stroke:green;fill:red') {
|
3357
|
+
animatetransform(attributename: 'transform', begin: '0.1s', dur: '10s', type: 'rotate', from: '0 85 85', to: '360 85 85', repeatcount: 'indefinite')
|
3358
|
+
}
|
3359
|
+
}
|
3360
|
+
}
|
3361
|
+
}
|
3362
|
+
end
|
3363
|
+
|
3364
|
+
Document.ready? do
|
3365
|
+
HelloSvg.render
|
3366
|
+
end
|
3367
|
+
```
|
3368
|
+
|
3369
|
+
Screenshot:
|
3370
|
+
|
3371
|
+
--
|
3372
|
+
|
3373
|
+
![Hello, SVG!](/images/glimmer-dsl-web-samples-hello-hello-svg.gif)
|
3374
|
+
|
3144
3375
|
--
|
3145
3376
|
|
3146
3377
|
#### Hello, Input (Date/Time)!
|
@@ -3366,10 +3597,6 @@ class TodoMvc
|
|
3366
3597
|
todo_list(presenter: @presenter)
|
3367
3598
|
|
3368
3599
|
todo_filters(presenter: @presenter)
|
3369
|
-
|
3370
|
-
style {
|
3371
|
-
todo_mvc_styles
|
3372
|
-
}
|
3373
3600
|
}
|
3374
3601
|
|
3375
3602
|
todo_mvc_footer
|
@@ -3380,46 +3607,46 @@ class TodoMvc
|
|
3380
3607
|
}
|
3381
3608
|
}
|
3382
3609
|
|
3383
|
-
|
3384
|
-
|
3385
|
-
margin
|
3386
|
-
padding
|
3610
|
+
style {
|
3611
|
+
r('body, button, html') {
|
3612
|
+
margin 0
|
3613
|
+
padding 0
|
3387
3614
|
}
|
3388
3615
|
|
3389
|
-
|
3390
|
-
_webkit_font_smoothing
|
3391
|
-
_webkit_appearance
|
3392
|
-
appearance
|
3393
|
-
background
|
3394
|
-
border
|
3395
|
-
color
|
3396
|
-
font_family
|
3616
|
+
r('button') {
|
3617
|
+
_webkit_font_smoothing :antialiased
|
3618
|
+
_webkit_appearance :none
|
3619
|
+
appearance :none
|
3620
|
+
background :none
|
3621
|
+
border 0
|
3622
|
+
color :inherit
|
3623
|
+
font_family :inherit
|
3397
3624
|
font_size '100%'
|
3398
|
-
font_weight
|
3399
|
-
vertical_align
|
3625
|
+
font_weight :inherit
|
3626
|
+
vertical_align :baseline
|
3400
3627
|
}
|
3401
3628
|
|
3402
|
-
|
3629
|
+
r('.todoapp') {
|
3403
3630
|
background '#fff'
|
3404
3631
|
margin '130px 0 40px 0'
|
3405
|
-
position
|
3632
|
+
position :relative
|
3406
3633
|
box_shadow '0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1)'
|
3407
3634
|
}
|
3408
3635
|
|
3409
3636
|
media('screen and (-webkit-min-device-pixel-ratio:0)') {
|
3410
|
-
|
3637
|
+
r('body') {
|
3411
3638
|
font "14px 'Helvetica Neue', Helvetica, Arial, sans-serif"
|
3412
|
-
line_height
|
3639
|
+
line_height 1.4.em
|
3413
3640
|
background '#f5f5f5'
|
3414
3641
|
color '#111111'
|
3415
|
-
min_width
|
3416
|
-
max_width
|
3642
|
+
min_width 230
|
3643
|
+
max_width 550
|
3417
3644
|
margin '0 auto'
|
3418
|
-
_webkit_font_smoothing
|
3645
|
+
_webkit_font_smoothing :antialiased
|
3419
3646
|
font_weight '300'
|
3420
3647
|
}
|
3421
3648
|
}
|
3422
|
-
|
3649
|
+
}
|
3423
3650
|
end
|
3424
3651
|
|
3425
3652
|
Document.ready? do
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.3
|
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.4.
|
5
|
+
# stub: glimmer-dsl-web 0.4.3 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "glimmer-dsl-web".freeze
|
9
|
-
s.version = "0.4.
|
9
|
+
s.version = "0.4.3"
|
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]
|
@@ -66,6 +66,7 @@ Gem::Specification.new do |s|
|
|
66
66
|
"lib/glimmer/data_binding/element_binding.rb",
|
67
67
|
"lib/glimmer/dsl/web/a_expression.rb",
|
68
68
|
"lib/glimmer/dsl/web/bind_expression.rb",
|
69
|
+
"lib/glimmer/dsl/web/class_name_inclusion_data_binding.rb",
|
69
70
|
"lib/glimmer/dsl/web/component_expression.rb",
|
70
71
|
"lib/glimmer/dsl/web/content_data_binding_expression.rb",
|
71
72
|
"lib/glimmer/dsl/web/data_binding_expression.rb",
|
@@ -10,7 +10,9 @@ module Glimmer
|
|
10
10
|
attr_reader :element, :property, :translator, :sub_property
|
11
11
|
def initialize(element, property, translator: nil)
|
12
12
|
@element = element
|
13
|
-
if (property_parts = property.to_s.match(Glimmer::Web::ElementProxy::
|
13
|
+
if (property_parts = property.to_s.match(Glimmer::Web::ElementProxy::REGEX_CLASS_NAME_SUB_PROPERTY))
|
14
|
+
@property, @sub_property = property_parts.to_a.drop(1)
|
15
|
+
elsif (property_parts = property.to_s.match(Glimmer::Web::ElementProxy::REGEX_STYLE_SUB_PROPERTY))
|
14
16
|
@property, @sub_property = property_parts.to_a.drop(1)
|
15
17
|
@sub_property = @sub_property.gsub('_', '-')
|
16
18
|
else
|
@@ -27,9 +29,11 @@ module Glimmer
|
|
27
29
|
def call(value)
|
28
30
|
evaluated_property_value = evaluate_property
|
29
31
|
converted_value = @translator&.call(value, evaluated_property_value) || value
|
30
|
-
|
32
|
+
if converted_value != evaluated_property_value
|
31
33
|
if @sub_property
|
32
|
-
if @property.to_s == '
|
34
|
+
if @property.to_s == 'class_name'
|
35
|
+
@element.class_name_included(@sub_property, converted_value)
|
36
|
+
elsif @property.to_s == 'style'
|
33
37
|
@element.style_property(@sub_property, converted_value)
|
34
38
|
end
|
35
39
|
else
|
@@ -40,7 +44,9 @@ module Glimmer
|
|
40
44
|
|
41
45
|
def evaluate_property
|
42
46
|
if @sub_property
|
43
|
-
if @property.to_s == '
|
47
|
+
if @property.to_s == 'class_name'
|
48
|
+
@element.class_name_included(@sub_property)
|
49
|
+
elsif @property.to_s == 'style'
|
44
50
|
@element.style_property(@sub_property)
|
45
51
|
end
|
46
52
|
else
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'glimmer/dsl/expression'
|
2
|
+
|
3
|
+
module Glimmer
|
4
|
+
module DSL
|
5
|
+
module Web
|
6
|
+
class ClassNameInclusionDataBindingExpression < Expression
|
7
|
+
def can_interpret?(parent, keyword, *args, &block)
|
8
|
+
keyword == 'class_name' &&
|
9
|
+
block.nil? &&
|
10
|
+
args.size == 1 &&
|
11
|
+
textual?(args.first)
|
12
|
+
end
|
13
|
+
|
14
|
+
def interpret(parent, keyword, *args, &block)
|
15
|
+
parent_attribute = "#{keyword}_#{args.first.to_s}"
|
16
|
+
Glimmer::DataBinding::Shine.new(parent, parent_attribute)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/glimmer/dsl/web/dsl.rb
CHANGED
@@ -28,6 +28,7 @@ require 'glimmer/dsl/web/a_expression'
|
|
28
28
|
require 'glimmer/dsl/web/span_expression'
|
29
29
|
require 'glimmer/dsl/web/style_element_expression'
|
30
30
|
require 'glimmer/dsl/web/inline_style_data_binding_expression'
|
31
|
+
require 'glimmer/dsl/web/class_name_inclusion_data_binding'
|
31
32
|
require 'glimmer/dsl/web/bind_expression'
|
32
33
|
require 'glimmer/dsl/web/data_binding_expression'
|
33
34
|
require 'glimmer/dsl/web/content_data_binding_expression'
|
@@ -45,6 +46,7 @@ module Glimmer
|
|
45
46
|
style_element
|
46
47
|
content_data_binding
|
47
48
|
inline_style_data_binding
|
49
|
+
class_name_inclusion_data_binding
|
48
50
|
component
|
49
51
|
formatting_element
|
50
52
|
data_binding
|
@@ -102,6 +102,11 @@ module Glimmer
|
|
102
102
|
self.keyword.gsub('_', '-')
|
103
103
|
end
|
104
104
|
|
105
|
+
def component_element_selector
|
106
|
+
".#{component_element_class}"
|
107
|
+
end
|
108
|
+
alias component_markup_root_selector component_element_selector
|
109
|
+
|
105
110
|
def component_shortcut_element_class
|
106
111
|
self.shortcut_keyword.gsub('_', '-')
|
107
112
|
end
|
@@ -203,7 +208,8 @@ module Glimmer
|
|
203
208
|
end
|
204
209
|
|
205
210
|
def remove_component_style(component)
|
206
|
-
|
211
|
+
# We must not remove the head style element until all components are removed of a component class
|
212
|
+
if Glimmer::Web::Component.component_count(component.class) == 0 && Glimmer::Web::Component.any_component_style?(component.class)
|
207
213
|
# TODO in the future, you would need to remove style using a jQuery call if you created head element in bulk
|
208
214
|
Glimmer::Web::Component.component_styles[component.class].remove
|
209
215
|
Glimmer::Web::Component.component_styles.delete(component.class)
|
@@ -219,7 +225,7 @@ module Glimmer
|
|
219
225
|
end
|
220
226
|
|
221
227
|
def component_count(component_class)
|
222
|
-
component_class_to_components_map[component_class]
|
228
|
+
component_class_to_components_map[component_class]&.size || 0
|
223
229
|
end
|
224
230
|
|
225
231
|
def components
|
@@ -144,6 +144,7 @@ module Glimmer
|
|
144
144
|
REGEX_FORMAT_DATE = /^\d{4}-\d{2}-\d{2}$/
|
145
145
|
REGEX_FORMAT_TIME = /^\d{2}:\d{2}$/
|
146
146
|
REGEX_STYLE_SUB_PROPERTY = /^(style)_(.*)$/
|
147
|
+
REGEX_CLASS_NAME_SUB_PROPERTY = /^(class_name)_(.*)$/
|
147
148
|
|
148
149
|
attr_reader :keyword, :parent, :parent_component, :component, :args, :options, :children, :enabled, :foreground, :background, :removed, :rendered
|
149
150
|
alias rendered? rendered
|
@@ -309,6 +310,24 @@ module Glimmer
|
|
309
310
|
end
|
310
311
|
end
|
311
312
|
|
313
|
+
def class_name_included(one_class_name, value = nil)
|
314
|
+
if rendered?
|
315
|
+
if value.nil?
|
316
|
+
class_name.include?(one_class_name)
|
317
|
+
else
|
318
|
+
if value
|
319
|
+
add_css_class(one_class_name)
|
320
|
+
else
|
321
|
+
remove_css_class(one_class_name)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
else
|
325
|
+
enqueue_args = ['class_name_included', one_class_name]
|
326
|
+
enqueue_args << value unless value.nil?
|
327
|
+
enqueue_post_render_method_call(*enqueue_args)
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
312
331
|
def style_property(property, value = nil)
|
313
332
|
if rendered?
|
314
333
|
property = property.to_s.gsub('_', '-')
|
@@ -657,14 +676,22 @@ module Glimmer
|
|
657
676
|
(!dom_element.prop(property_name).nil? && !dom_element.prop(property_name).is_a?(Proc)) ||
|
658
677
|
(!dom_element.prop(unnormalized_property_name).nil? && !dom_element.prop(unnormalized_property_name).is_a?(Proc)) ||
|
659
678
|
method_name.to_s.start_with?('on_') ||
|
660
|
-
method_name.to_s.start_with?('style_')
|
679
|
+
method_name.to_s.start_with?('style_') ||
|
680
|
+
method_name.to_s.start_with?('class_name_')
|
661
681
|
end
|
662
682
|
|
663
683
|
def method_missing(method_name, *args, &block)
|
664
684
|
# TODO consider doing more correct checking of availability of properties/methods using native ticks
|
665
685
|
property_name = property_name_for(method_name)
|
666
686
|
unnormalized_property_name = unnormalized_property_name_for(method_name)
|
667
|
-
if method_name.to_s.start_with?('
|
687
|
+
if method_name.to_s.start_with?('class_name_')
|
688
|
+
property, sub_property = method_name.to_s.match(REGEX_CLASS_NAME_SUB_PROPERTY).to_a.drop(1)
|
689
|
+
if args.empty?
|
690
|
+
class_name_included(sub_property)
|
691
|
+
else
|
692
|
+
class_name_included(sub_property, args.first)
|
693
|
+
end
|
694
|
+
elsif method_name.to_s.start_with?('style_')
|
668
695
|
property, sub_property = method_name.to_s.match(REGEX_STYLE_SUB_PROPERTY).to_a.drop(1)
|
669
696
|
sub_property = sub_property.gsub('_', '-')
|
670
697
|
if args.empty?
|