glimmer-dsl-web 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -1
- data/README.md +11 -7
- data/VERSION +1 -1
- data/glimmer-dsl-web.gemspec +5 -5
- data/lib/glimmer/web/component.rb +4 -0
- data/lib/glimmer/web/element_proxy.rb +1 -1
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/models/todo.rb +3 -22
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/presenters/todo_presenter.rb +44 -31
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_filters.rb +5 -3
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_list.rb +27 -7
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_list_item.rb +12 -12
- data/lib/glimmer-dsl-web/samples/regular/todo_mvc/views/todo_mvc_footer.rb +2 -2
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 162d98e6fa4d8eefcec1f4edb2f5af6c3d5d3a88aaa01704ded825b982aabbd9
|
4
|
+
data.tar.gz: 8c133105ac1cf160658c476771a9b58c0ac351116a1b919cdef37db19bd085e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5bc70f98db8b2fec83310e789967447663f9d1d7017ad6dd8b1984ce5e520ef835430d5f5b8c885fa92282d63617a58ba42cb30dda6b0212cafd63e3ce378b93
|
7
|
+
data.tar.gz: 75561cba8a7a7d61e71e286e197dbbb80879261715500249ddd565f0833273777039632f2553a1cb5e0e3c4c1258704fc83f73ea7e163c1d4ab64a0af0e2f307
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,17 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 0.3.1
|
4
|
+
|
5
|
+
- Optimize Todo MVC performance for filtering between all, active, and completed (it happens instantly now)
|
6
|
+
- Append Todo MVC todos at the bottom instead of prepending them at the top (I copied the ES6 version initially which did things the opposite way from how Todo MVC behaves normally in other versions)
|
7
|
+
- Make Todo MVC "items left" text show "item left" if there is only 1 todo (I missed this detail before)
|
8
|
+
- Make Todo MVC footer links open a new tab/window (with `target: '_blank'` option)
|
9
|
+
- Refactor/Simplify Todo MVC sample code
|
10
|
+
- Upgrade to glimmer 2.7.8
|
11
|
+
|
3
12
|
## 0.3.0
|
4
13
|
|
5
|
-
- Optimize performance (~170%-226% faster) by building GUI
|
14
|
+
- Optimize performance (~170%-226% faster) of rendering by building GUI in bulk, assembling html as a string from all nested elements and mounting all HTML at once (instead of making many small DOM mount calls). The trade-off is not being able to interact with elements until rendering of the complete hierarchy is complete, which is acceptable because interactions do not happen till after everything is rendered anyways. Can be disabled by passing the `bulk_render: false` option to the top-level component/element of a frontend app.
|
6
15
|
- Fix issue with not being able to add content to a custom control by opening a block that should add content inside its markup root element
|
7
16
|
|
8
17
|
## 0.2.8
|
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.3.
|
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.3.1 (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)
|
@@ -1154,6 +1154,10 @@ Screenshot:
|
|
1154
1154
|
|
1155
1155
|
[Todo MVC Ruby Edition Is the One Todo MVC To Rule Them All!!!](https://andymaleh.blogspot.com/2024/06/todo-mvc-in-ruby-is-one-todo-mvc-to.html)
|
1156
1156
|
|
1157
|
+
[lib/glimmer-dsl-web/samples/regular/todo_mvc.rb](/lib/glimmer-dsl-web/samples/regular/todo_mvc.rb)
|
1158
|
+
|
1159
|
+
[lib/glimmer-dsl-web/samples/regular/todo_mvc](/lib/glimmer-dsl-web/samples/regular/todo_mvc)
|
1160
|
+
|
1157
1161
|
```ruby
|
1158
1162
|
require 'glimmer-dsl-web'
|
1159
1163
|
|
@@ -1329,7 +1333,7 @@ rails new glimmer_app_server
|
|
1329
1333
|
Add the following to `Gemfile`:
|
1330
1334
|
|
1331
1335
|
```
|
1332
|
-
gem 'glimmer-dsl-web', '~> 0.3.
|
1336
|
+
gem 'glimmer-dsl-web', '~> 0.3.1'
|
1333
1337
|
```
|
1334
1338
|
|
1335
1339
|
Run:
|
@@ -1521,6 +1525,8 @@ module ApplicationHelper
|
|
1521
1525
|
end
|
1522
1526
|
```
|
1523
1527
|
|
1528
|
+
By default, elements are rendered in bulk for faster performance, meaning you cannot interact with element objects until rendering is done. This is a sensible default because most of the time, there is no need to interact with elements until the full frontend application is fully rendered. That said, if it is preferred every once in a while to render elements piecemeal instead of in bulk, this behavior can be adjusted by passing the option `bulk_render: false` to the top-level component or top-level element (if there is no component).
|
1529
|
+
|
1524
1530
|
Note that Turbo is disabled on Glimmer elements/components. You can still use Turbo/Hotwire side by side with Glimmer DSL for Web by using one of the two technologies in every page. But, mixing them in the same pages is not recommended at the moment, so any pages loaded with Glimmer DSL for Web must be loaded without Turbo (e.g. by putting "data-turbo"="false" on anchor "a" tag links to Glimmer pages).
|
1525
1531
|
|
1526
1532
|
If you run into any issues in setup, refer to the [Sample Glimmer DSL for Web Rails 7 App](https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app) project (in case I forgot to include some setup steps by mistake).
|
@@ -1556,7 +1562,7 @@ Disable the `webpacker` gem line in `Gemfile`:
|
|
1556
1562
|
Add the following to `Gemfile`:
|
1557
1563
|
|
1558
1564
|
```ruby
|
1559
|
-
gem 'glimmer-dsl-web', '~> 0.3.
|
1565
|
+
gem 'glimmer-dsl-web', '~> 0.3.1'
|
1560
1566
|
```
|
1561
1567
|
|
1562
1568
|
Run:
|
@@ -3262,6 +3268,8 @@ Screenshot:
|
|
3262
3268
|
|
3263
3269
|
[lib/glimmer-dsl-web/samples/regular/todo_mvc.rb](/lib/glimmer-dsl-web/samples/regular/todo_mvc.rb)
|
3264
3270
|
|
3271
|
+
[lib/glimmer-dsl-web/samples/regular/todo_mvc](/lib/glimmer-dsl-web/samples/regular/todo_mvc)
|
3272
|
+
|
3265
3273
|
```ruby
|
3266
3274
|
require 'glimmer-dsl-web'
|
3267
3275
|
|
@@ -3354,10 +3362,6 @@ end
|
|
3354
3362
|
|
3355
3363
|
![Todo MVC](/images/glimmer-dsl-web-samples-regular-todo-mvc.gif)
|
3356
3364
|
|
3357
|
-
The rest of the files are found at:
|
3358
|
-
|
3359
|
-
[lib/glimmer-dsl-web/samples/regular/todo_mvc](/lib/glimmer-dsl-web/samples/regular/todo_mvc)
|
3360
|
-
|
3361
3365
|
## Design Principles
|
3362
3366
|
|
3363
3367
|
- The Ruby Way (including TIMTOWTDI: There Is More Than One Way To Do It)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.1
|
data/glimmer-dsl-web.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
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.3.
|
5
|
+
# stub: glimmer-dsl-web 0.3.1 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "glimmer-dsl-web".freeze
|
9
|
-
s.version = "0.3.
|
9
|
+
s.version = "0.3.1"
|
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]
|
13
13
|
s.authors = ["Andy Maleh".freeze]
|
14
|
-
s.date = "2024-
|
14
|
+
s.date = "2024-07-01"
|
15
15
|
s.description = "Glimmer DSL for Web (Ruby in the Browser Web Frontend Framework) enables building Web Frontends using Ruby in the Browser, as per Matz's recommendation in his RubyConf 2022 keynote speech to replace JavaScript with Ruby. 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 and TIMTOWTDI) and the Rails way (Convention over Configuration) in building Isomorphic Ruby on Rails Applications. It provides a Ruby HTML DSL, which uniquely enables writing both structure code and logic code in one language. It supports both Unidirectional (One-Way) Data-Binding (using <=) and Bidirectional (Two-Way) Data-Binding (using <=>). Dynamic rendering (and re-rendering) of HTML content is also supported via Content Data-Binding. Modular design is supported with Glimmer Web Components. And, a Ruby CSS DSL is supported with the included Glimmer DSL for CSS. Many samples are demonstrated in the Rails sample app (there is a very minimal Standalone [No Rails] sample app too). You can finally live in pure Rubyland on the Web in both the frontend and backend with Glimmer DSL for Web! This gem relies on Opal Ruby.".freeze
|
16
16
|
s.email = "andy.am@gmail.com".freeze
|
17
17
|
s.extra_rdoc_files = [
|
@@ -93,7 +93,7 @@ Gem::Specification.new do |s|
|
|
93
93
|
|
94
94
|
s.specification_version = 4
|
95
95
|
|
96
|
-
s.add_runtime_dependency(%q<glimmer>.freeze, ["~> 2.7.
|
96
|
+
s.add_runtime_dependency(%q<glimmer>.freeze, ["~> 2.7.8"])
|
97
97
|
s.add_runtime_dependency(%q<glimmer-dsl-xml>.freeze, ["~> 1.4.0"])
|
98
98
|
s.add_runtime_dependency(%q<glimmer-dsl-css>.freeze, ["~> 1.4.0"])
|
99
99
|
s.add_runtime_dependency(%q<opal>.freeze, ["= 1.8.2"])
|
@@ -101,7 +101,7 @@ Gem::Specification.new do |s|
|
|
101
101
|
s.add_runtime_dependency(%q<opal-async>.freeze, ["~> 1.4.1"])
|
102
102
|
s.add_runtime_dependency(%q<opal-jquery>.freeze, ["~> 0.5.1"])
|
103
103
|
s.add_runtime_dependency(%q<to_collection>.freeze, [">= 2.0.1", "< 3.0.0"])
|
104
|
-
s.add_development_dependency(%q<puts_debuggerer>.freeze, [">= 1.0.
|
104
|
+
s.add_development_dependency(%q<puts_debuggerer>.freeze, [">= 1.0.1"])
|
105
105
|
s.add_development_dependency(%q<rake>.freeze, [">= 10.1.0", "< 14.0.0"])
|
106
106
|
s.add_development_dependency(%q<rake-tui>.freeze, [">= 0"])
|
107
107
|
s.add_development_dependency(%q<jeweler>.freeze, [">= 2.3.9", "< 3.0.0"])
|
@@ -316,6 +316,10 @@ module Glimmer
|
|
316
316
|
@markup_root&.render(parent: parent, custom_parent_dom_element: custom_parent_dom_element, brand_new: brand_new)
|
317
317
|
end
|
318
318
|
|
319
|
+
def remove
|
320
|
+
@markup_root&.remove
|
321
|
+
end
|
322
|
+
|
319
323
|
# Returns content block if used as an attribute reader (no args)
|
320
324
|
# Otherwise, if a block is passed, it adds it as content to this Glimmer web component
|
321
325
|
def content(*args, &block)
|
@@ -542,9 +542,9 @@ module Glimmer
|
|
542
542
|
element_binding_translator = value_converters_for_input_type(type)[:model_to_view]
|
543
543
|
element_binding_parameters = [self, property, element_binding_translator]
|
544
544
|
element_binding = DataBinding::ElementBinding.new(*element_binding_parameters)
|
545
|
-
element_binding.call(model_binding.evaluate_property)
|
546
545
|
#TODO make this options observer dependent and all similar observers in element specific data binding handlers
|
547
546
|
element_binding.observe(model_binding)
|
547
|
+
element_binding.call(model_binding.evaluate_property)
|
548
548
|
data_bindings[element_binding] = model_binding
|
549
549
|
unless model_binding.binding_options[:read_only]
|
550
550
|
# TODO add guards against nil cases for hash below
|
@@ -1,28 +1,9 @@
|
|
1
|
-
Todo = Struct.new(:task, :completed, :editing, keyword_init: true) do
|
2
|
-
class << self
|
3
|
-
attr_writer :all
|
4
|
-
|
5
|
-
def all
|
6
|
-
@all ||= []
|
7
|
-
end
|
8
|
-
|
9
|
-
def active
|
10
|
-
all.select(&:active?)
|
11
|
-
end
|
12
|
-
|
13
|
-
def completed
|
14
|
-
all.select(&:completed?)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
FILTERS = [:all, :active, :completed]
|
19
|
-
|
1
|
+
Todo = Struct.new(:task, :completed, :editing, :deleted, keyword_init: true) do
|
20
2
|
alias completed? completed
|
21
3
|
alias editing? editing
|
4
|
+
alias deleted? deleted
|
22
5
|
|
23
|
-
def active
|
24
|
-
!completed
|
25
|
-
end
|
6
|
+
def active = !completed
|
26
7
|
alias active? active
|
27
8
|
|
28
9
|
def start_editing
|
@@ -3,53 +3,54 @@ require 'glimmer/data_binding/observer'
|
|
3
3
|
require_relative '../models/todo'
|
4
4
|
|
5
5
|
class TodoPresenter
|
6
|
+
FILTERS = [:all, :active, :completed]
|
6
7
|
FILTER_ROUTE_REGEXP = /\#\/([^\/]*)$/
|
7
8
|
|
8
|
-
attr_accessor :
|
9
|
-
attr_reader :new_todo, :filter
|
9
|
+
attr_accessor :can_clear_completed, :active_todo_count, :created_todo
|
10
|
+
attr_reader :todos, :new_todo, :filter
|
10
11
|
|
11
12
|
def initialize
|
12
|
-
@todos =
|
13
|
+
@todos = []
|
13
14
|
@new_todo = Todo.new(task: '')
|
14
15
|
@filter = :all
|
15
|
-
|
16
|
+
@can_clear_completed = false
|
17
|
+
@active_todo_count = 0
|
18
|
+
todo_stat_refresh_observer.observe(todos) # refresh stats if todos array adds/removes todo objects
|
16
19
|
end
|
17
20
|
|
18
|
-
def
|
19
|
-
|
20
|
-
|
21
|
-
observers_for_todo_stats[todo.object_id] = todo_stat_observer.observe(todo, :completed) unless observers_for_todo_stats.has_key?(todo.object_id)
|
22
|
-
refresh_todos_with_filter
|
23
|
-
refresh_todo_stats
|
24
|
-
new_todo.task = ''
|
25
|
-
end
|
21
|
+
def active_todos = todos.select(&:active?)
|
22
|
+
|
23
|
+
def completed_todos = todos.select(&:completed?)
|
26
24
|
|
27
|
-
def
|
28
|
-
|
25
|
+
def create_todo
|
26
|
+
todo = new_todo.clone
|
27
|
+
todos.append(todo)
|
28
|
+
observe_todo_completion_to_update_todo_stats(todo)
|
29
|
+
new_todo.task = ''
|
30
|
+
self.created_todo = todo # notifies View observer indirectly to add created todo to todo list
|
29
31
|
end
|
30
32
|
|
31
33
|
def filter=(filter)
|
32
34
|
return if filter == @filter
|
33
35
|
@filter = filter
|
34
|
-
refresh_todos_with_filter
|
35
36
|
end
|
36
37
|
|
37
38
|
def destroy(todo)
|
38
39
|
delete(todo)
|
39
|
-
refresh_todos_with_filter
|
40
|
-
refresh_todo_stats
|
41
40
|
end
|
42
41
|
|
43
42
|
def clear_completed
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
refresh_todo_stats do
|
44
|
+
completed_todos.each { |todo| delete(todo) }
|
45
|
+
end
|
47
46
|
end
|
48
47
|
|
49
48
|
def toggle_all_completed
|
50
|
-
target_completed_value =
|
51
|
-
todos_to_update = target_completed_value ?
|
52
|
-
|
49
|
+
target_completed_value = active_todos.any?
|
50
|
+
todos_to_update = target_completed_value ? active_todos : completed_todos
|
51
|
+
refresh_todo_stats do
|
52
|
+
todos_to_update.each { |todo| todo.completed = target_completed_value }
|
53
|
+
end
|
53
54
|
end
|
54
55
|
|
55
56
|
def setup_filter_routes
|
@@ -73,30 +74,42 @@ class TodoPresenter
|
|
73
74
|
|
74
75
|
private
|
75
76
|
|
77
|
+
def observe_todo_completion_to_update_todo_stats(todo)
|
78
|
+
# saving observer registration object to deregister when deleting todo
|
79
|
+
observers_for_todo_stats[todo.object_id] = todo_stat_refresh_observer.observe(todo, :completed)
|
80
|
+
end
|
81
|
+
|
82
|
+
def todo_stat_refresh_observer
|
83
|
+
@todo_stat_refresh_observer ||= Glimmer::DataBinding::Observer.proc { refresh_todo_stats }
|
84
|
+
end
|
85
|
+
|
76
86
|
def delete(todo)
|
77
|
-
|
87
|
+
todos.delete(todo)
|
78
88
|
observer_registration = observers_for_todo_stats.delete(todo.object_id)
|
79
89
|
observer_registration&.deregister
|
90
|
+
todo.deleted = true # notifies View observer indirectly to delete todo
|
80
91
|
end
|
81
92
|
|
82
93
|
def observers_for_todo_stats
|
83
94
|
@observers_for_todo_stats = {}
|
84
95
|
end
|
85
96
|
|
86
|
-
def
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
97
|
+
def refresh_todo_stats(&work_before_refresh)
|
98
|
+
if work_before_refresh
|
99
|
+
@do_not_refresh_todo_stats = true
|
100
|
+
work_before_refresh.call
|
101
|
+
@do_not_refresh_todo_stats = nil
|
102
|
+
end
|
103
|
+
return if @do_not_refresh_todo_stats
|
91
104
|
refresh_can_clear_completed
|
92
105
|
refresh_active_todo_count
|
93
106
|
end
|
94
107
|
|
95
108
|
def refresh_can_clear_completed
|
96
|
-
self.can_clear_completed =
|
109
|
+
self.can_clear_completed = todos.any?(&:completed?)
|
97
110
|
end
|
98
111
|
|
99
112
|
def refresh_active_todo_count
|
100
|
-
self.active_todo_count =
|
113
|
+
self.active_todo_count = active_todos.count
|
101
114
|
end
|
102
115
|
end
|
@@ -5,7 +5,7 @@ class TodoFilters
|
|
5
5
|
|
6
6
|
markup {
|
7
7
|
footer(class: 'todo-filters') {
|
8
|
-
style <= [
|
8
|
+
style <= [ presenter, :todos,
|
9
9
|
on_read: ->(todos) { todos.empty? ? 'display: none;' : '' }
|
10
10
|
]
|
11
11
|
|
@@ -14,12 +14,14 @@ class TodoFilters
|
|
14
14
|
inner_text <= [presenter, :active_todo_count]
|
15
15
|
}
|
16
16
|
span {
|
17
|
-
|
17
|
+
inner_text <= [presenter, :active_todo_count,
|
18
|
+
on_read: -> (active_todo_count) { " item#{'s' if active_todo_count != 1} left" }
|
19
|
+
]
|
18
20
|
}
|
19
21
|
}
|
20
22
|
|
21
23
|
ul(class: 'filters') {
|
22
|
-
|
24
|
+
TodoPresenter::FILTERS.each do |filter|
|
23
25
|
li {
|
24
26
|
a(filter.to_s.capitalize, href: "#/#{filter unless filter == :all}") {
|
25
27
|
class_name <= [ presenter, :filter,
|
@@ -5,9 +5,17 @@ class TodoList
|
|
5
5
|
|
6
6
|
option :presenter
|
7
7
|
|
8
|
+
after_render do
|
9
|
+
observe(presenter, :created_todo) do |todo|
|
10
|
+
@todo_ul.content { # re-open todo ul content to add created todo
|
11
|
+
todo_list_item(presenter:, todo:)
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
8
16
|
markup {
|
9
17
|
main(class: 'main') {
|
10
|
-
style <= [
|
18
|
+
style <= [ presenter, :todos,
|
11
19
|
on_read: ->(todos) { todos.empty? ? 'display: none;' : '' }
|
12
20
|
]
|
13
21
|
|
@@ -21,12 +29,14 @@ class TodoList
|
|
21
29
|
}
|
22
30
|
}
|
23
31
|
|
24
|
-
ul
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
32
|
+
@todo_ul = ul {
|
33
|
+
class_name <= [presenter, :filter,
|
34
|
+
on_read: ->(filter) { "todo-list #{filter}" }
|
35
|
+
]
|
36
|
+
|
37
|
+
presenter.todos.each do |todo|
|
38
|
+
todo_list_item(presenter:, todo:)
|
39
|
+
end
|
30
40
|
}
|
31
41
|
|
32
42
|
style {
|
@@ -84,5 +94,15 @@ class TodoList
|
|
84
94
|
margin '0'
|
85
95
|
padding '0'
|
86
96
|
}
|
97
|
+
|
98
|
+
rule('.todo-list.active li.completed') {
|
99
|
+
display 'none'
|
100
|
+
}
|
101
|
+
|
102
|
+
rule('.todo-list.completed li.active') {
|
103
|
+
display 'none'
|
104
|
+
}
|
105
|
+
|
106
|
+
TodoListItem.todo_list_item_styles
|
87
107
|
end
|
88
108
|
end
|
@@ -6,20 +6,25 @@ class TodoListItem
|
|
6
6
|
option :presenter
|
7
7
|
option :todo
|
8
8
|
|
9
|
+
after_render do
|
10
|
+
# after rendering markup, observe todo deleted attribute and remove component when deleted
|
11
|
+
observe(todo, :deleted) do |deleted|
|
12
|
+
self.remove if deleted
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
9
16
|
markup {
|
10
17
|
li {
|
11
18
|
class_name <= [ todo, :completed,
|
12
|
-
on_read: ->
|
19
|
+
on_read: -> { li_class_name(todo) }
|
13
20
|
]
|
14
21
|
class_name <= [ todo, :editing,
|
15
|
-
on_read: ->
|
22
|
+
on_read: -> { li_class_name(todo) }
|
16
23
|
]
|
17
24
|
|
18
25
|
div(class: 'view') {
|
19
26
|
input(class: 'toggle', type: 'checkbox') {
|
20
|
-
checked <=> [
|
21
|
-
after_write: -> (_) { presenter.refresh_todos_with_filter if presenter.filter != :all }
|
22
|
-
]
|
27
|
+
checked <=> [todo, :completed]
|
23
28
|
}
|
24
29
|
|
25
30
|
label {
|
@@ -38,23 +43,18 @@ class TodoListItem
|
|
38
43
|
}
|
39
44
|
|
40
45
|
edit_todo_input(presenter:, todo:)
|
41
|
-
|
42
|
-
if todo == presenter.todos.first
|
43
|
-
style {
|
44
|
-
todo_list_item_styles
|
45
|
-
}
|
46
|
-
end
|
47
46
|
}
|
48
47
|
}
|
49
48
|
|
50
49
|
def li_class_name(todo)
|
51
50
|
classes = []
|
52
51
|
classes << 'completed' if todo.completed?
|
52
|
+
classes << 'active' if !todo.completed?
|
53
53
|
classes << 'editing' if todo.editing?
|
54
54
|
classes.join(' ')
|
55
55
|
end
|
56
56
|
|
57
|
-
def todo_list_item_styles
|
57
|
+
def self.todo_list_item_styles
|
58
58
|
rule('.todo-list li.completed label') {
|
59
59
|
color '#949494'
|
60
60
|
text_decoration 'line-through'
|
@@ -7,10 +7,10 @@ class TodoMvcFooter
|
|
7
7
|
"Double-click to edit a todo"
|
8
8
|
}
|
9
9
|
p {
|
10
|
-
"Created by #{a('Andy Maleh', href: 'https://github.com/AndyObtiva')}"
|
10
|
+
"Created by #{a('Andy Maleh', href: 'https://github.com/AndyObtiva', target: '_blank')}"
|
11
11
|
}
|
12
12
|
p {
|
13
|
-
"Part of #{a('TodoMVC', href: 'http://todomvc.com')}"
|
13
|
+
"Part of #{a('TodoMVC', href: 'http://todomvc.com', target: '_blank')}"
|
14
14
|
}
|
15
15
|
|
16
16
|
style {
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: glimmer-dsl-web
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Maleh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-07-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: glimmer
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 2.7.
|
19
|
+
version: 2.7.8
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 2.7.
|
26
|
+
version: 2.7.8
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: glimmer-dsl-xml
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -134,14 +134,14 @@ dependencies:
|
|
134
134
|
requirements:
|
135
135
|
- - ">="
|
136
136
|
- !ruby/object:Gem::Version
|
137
|
-
version: 1.0.
|
137
|
+
version: 1.0.1
|
138
138
|
type: :development
|
139
139
|
prerelease: false
|
140
140
|
version_requirements: !ruby/object:Gem::Requirement
|
141
141
|
requirements:
|
142
142
|
- - ">="
|
143
143
|
- !ruby/object:Gem::Version
|
144
|
-
version: 1.0.
|
144
|
+
version: 1.0.1
|
145
145
|
- !ruby/object:Gem::Dependency
|
146
146
|
name: rake
|
147
147
|
requirement: !ruby/object:Gem::Requirement
|