Skip to content
This repository was archived by the owner on Nov 1, 2017. It is now read-only.

Commit 16541d7

Browse files
committed
Merge pull request #2 from github/changing-event
Defer enabling TaskLists to the app; fire change/d events
2 parents 3db430a + 533421d commit 16541d7

File tree

5 files changed

+143
-55
lines changed

5 files changed

+143
-55
lines changed

app/assets/javascripts/task_lists.coffee

Lines changed: 96 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
#= provides tasklist:enabled
44
#= provides tasklist:disabled
55
#= provides tasklist:change
6+
#= provides tasklist:changed
67
#
8+
#= require crema/element/fire
79
#= require crema/events/pageupdate
810
#
911
# Enables Task List update behavior.
@@ -26,7 +28,7 @@
2628
#
2729
# ### Specification
2830
#
29-
# TaskLists MUST be contained in a `div.js-task-list-container`.
31+
# TaskLists MUST be contained in a `(div).js-task-list-container`.
3032
#
3133
# TaskList Items SHOULD be an a list (`UL`/`OL`) element.
3234
#
@@ -37,19 +39,67 @@
3739
# `value` attribute is the source (Markdown) to be udpated. The source MUST
3840
# follow the syntax guidelines.
3941
#
40-
# TaskList updates trigger `tasklist:change` events.
42+
# TaskList updates trigger `tasklist:change` events. If the change is
43+
# successful, `tasklist:changed` is fired. The change can be canceled.
4144
#
42-
# jQuery is required and the `$.pageUpdate` behavior MUST be available.
45+
# jQuery and crema are required.
4346
#
44-
# ### Events
47+
# ### Methods
4548
#
46-
# When the TaskList field has been changed, a `tasklist:change` event is fired.
49+
# `.taskList('enable')` or `.taskList()`
50+
#
51+
# Enables TaskList updates for the container.
52+
#
53+
# `.taskList('disable')`
54+
#
55+
# Disables TaskList updates for the container.
56+
#
57+
## ### Events
58+
#
59+
# `tasklist:enabled`
60+
#
61+
# Fired when the TaskList is enabled.
62+
#
63+
# * **Synchronicity** Sync
64+
# * **Bubbles** Yes
65+
# * **Cancelable** No
66+
# * **Target** `.js-task-list-container`
67+
#
68+
# `tasklist:disabled`
69+
#
70+
# Fired when the TaskList is disabled.
71+
#
72+
# * **Synchronicity** Sync
73+
# * **Bubbles** Yes
74+
# * **Cancelable** No
75+
# * **Target** `.js-task-list-container`
76+
#
77+
# `tasklist:change`
78+
#
79+
# Fired before the TaskList item change takes affect.
80+
#
81+
# * **Synchronicity** Sync
82+
# * **Bubbles** Yes
83+
# * **Cancelable** Yes
84+
# * **Target** `.js-task-list-field`
85+
#
86+
# `tasklist:changed`
87+
#
88+
# Fired once the TaskList item change has taken affect.
89+
#
90+
# * **Synchronicity** Sync
91+
# * **Bubbles** Yes
92+
# * **Cancelable** No
93+
# * **Target** `.js-task-list-field`
4794
#
4895
# ### NOTE
4996
#
5097
# Task list checkboxes are rendered as disabled by default because rendered
5198
# user content is cached without regard for the viewer. We enable checkboxes
5299
# on `pageUpdate` if the container has a `(textarea).js-task-list-field`.
100+
#
101+
# To automatically enable TaskLists, add the `js-task-list-enable` class to the
102+
# `js-task-list-container`.
53103

54104
incomplete = "[ ]"
55105
complete = "[x]"
@@ -111,44 +161,60 @@ updateTaskListItem = (source, itemIndex, checked) ->
111161
line
112162
result.join("\n")
113163

114-
# Enables task list items to trigger updates.
164+
# Updates the $field value to reflect the state of $item.
165+
# Triggers the `tasklist:change` event before the value has changed, and fires
166+
# a `tasklist:changed` event once the value has changed.
167+
updateTaskList = ($item) ->
168+
$container = $item.closest '.js-task-list-container'
169+
$field = $container.find '.js-task-list-field'
170+
index = 1 + $container.find('.task-list-item-checkbox').index($item)
171+
checked = $item.prop 'checked'
172+
173+
$field.fire 'tasklist:change', [index, checked], ->
174+
$field.val updateTaskListItem($field.val(), index, checked)
175+
$field.trigger 'change'
176+
$field.fire 'tasklist:changed', [index, checked]
177+
178+
# When the task list item checkbox is updated, submit the change
179+
$(document).on 'change', '.task-list-item-checkbox', ->
180+
updateTaskList $(this)
181+
182+
# Enables TaskList item changes.
115183
enableTaskList = ($container) ->
116184
if $container.find('.js-task-list-field').length > 0
117185
$container.
118186
find('.task-list-item').addClass('enabled').
119187
find('.task-list-item-checkbox').attr('disabled', null)
120-
$container.trigger 'tasklist:enabled'
188+
$container.addClass('is-task-list-enabled').
189+
trigger 'tasklist:enabled'
121190

191+
# Enables a collection of TaskList containers.
192+
enableTaskLists = ($containers) ->
193+
for container in $containers
194+
enableTaskList $(container)
195+
196+
# Disable TaskList item changes.
122197
disableTaskList = ($container) ->
123198
$container.
124199
find('.task-list-item').removeClass('enabled').
125200
find('.task-list-item-checkbox').attr('disabled', 'disabled')
126-
$container.trigger 'tasklist:disabled'
127-
128-
# Updates the $field value to reflect the state of $item.
129-
# Triggers the `tasklist:change` event when the value has changed.
130-
updateTaskList = ($item) ->
131-
$container = $item.closest '.js-task-list-container'
132-
$field = $container.find '.js-task-list-field'
133-
index = 1 + $container.find('.task-list-item-checkbox').index($item)
134-
checked = $item.prop 'checked'
135-
136-
disableTaskList $container
201+
$container.removeClass('is-task-list-enabled').
202+
trigger 'tasklist:disabled'
137203

138-
$field.val updateTaskListItem($field.val(), index, checked)
139-
$field.trigger 'change'
140-
$field.trigger 'tasklist:change', [index, checked]
204+
# Disables a collection of TaskList containers.
205+
disableTaskLists = ($containers) ->
206+
for container in $containers
207+
disableTaskList $(container)
141208

142-
# When the task list item checkbox is updated, submit the change
143-
$(document).on 'change', '.task-list-item-checkbox', ->
144-
updateTaskList $(this)
209+
$.fn.taskList = (method) ->
210+
$container = $(this).closest('.js-task-list-container')
145211

146-
$(document).on 'tasklist:disable', '.js-task-list-container', (event) ->
147-
disableTaskList $(this)
212+
methods =
213+
enable: enableTaskLists
214+
disable: disableTaskLists
148215

149-
$(document).on 'tasklist:enable', '.js-task-list-container', (event) ->
150-
enableTaskList $(this)
216+
methods[method || 'enable']($container)
151217

218+
# When the page is updated, enable new TaskList containers.
152219
$.pageUpdate ->
153-
$('.js-task-list-container').each ->
154-
enableTaskList $(this)
220+
$('.js-task-list-container.js-task-list-enable').taskList()

config.ru

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ end
1919

2020
map "/update" do
2121
run lambda { |env|
22+
sleep 0.5
2223
req = Rack::Request.new(env)
2324
[200, {'Content-Type' => 'application/json'}, [req.params.to_json]]
2425
}

test/functional/test_task_lists_behavior.html

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,18 @@
1717
$(document).on('tasklist:enabled', logEvent)
1818
$(document).on('tasklist:disabled', logEvent)
1919
$(document).on('tasklist:change', '.js-task-list-field', function(event){
20+
logEvent(event)
21+
$(this).closest('.js-task-list-container').taskList('disable')
22+
})
23+
$(document).on('tasklist:changed', '.js-task-list-field', function(event){
2024
logEvent(event)
2125
$(this).closest('form').submit()
2226
})
2327

2428
$(document).on('ajaxStart', logEvent)
2529
$(document).on('ajaxSuccess', '.js-task-list-container', function(event){
2630
logEvent(event)
27-
$(this).pageUpdate() // reenables the task lists
31+
$(this).taskList()
2832
})
2933
</script>
3034

@@ -63,7 +67,7 @@
6367
</style>
6468
</head>
6569
<body>
66-
<div class="js-task-list-container">
70+
<div class="js-task-list-container js-task-list-enable">
6771
<div class="markdown">
6872
<ul class="task-list">
6973
<li class="task-list-item">

test/unit/test_events.coffee

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
module "TaskList events",
44
setup: ->
5-
window.linkActivated = false
6-
75
@container = $ '<div>', class: 'js-task-list-container'
86

97
@list = $ '<ul>', class: 'task-list'
@@ -22,14 +20,16 @@ module "TaskList events",
2220

2321
@container.append @field
2422

25-
$('#qunit-fixture').append(@container).pageUpdate()
23+
$('#qunit-fixture').append(@container)
24+
@container.taskList()
2625

2726
teardown: ->
2827
$(document).off 'tasklist:enabled'
2928
$(document).off 'tasklist:disabled'
3029
$(document).off 'tasklist:change'
30+
$(document).off 'tasklist:changed'
3131

32-
asyncTest "triggers a tasklist:change event on task list item changes", ->
32+
asyncTest "triggers a tasklist:change event before making task list item changes", ->
3333
expect 1
3434

3535
@field.on 'tasklist:change', (event, index, checked) ->
@@ -41,38 +41,56 @@ asyncTest "triggers a tasklist:change event on task list item changes", ->
4141

4242
@checkbox.click()
4343

44-
asyncTest "enables task list items when a .js-task-list-field is present", ->
44+
asyncTest "triggers a tasklist:changed event once a task list item changes", ->
4545
expect 1
4646

47-
$(document).on 'tasklist:enabled', (event) ->
47+
@field.on 'tasklist:changed', (event, index, checked) ->
4848
ok true
4949

50-
@container.pageUpdate()
5150
setTimeout ->
5251
start()
5352
, 20
5453

55-
asyncTest "doesn't enable task list items when a .js-task-list-field is absent", ->
56-
expect 0
54+
@checkbox.click()
5755

58-
$(document).on 'tasklist:enabled', (event) ->
56+
asyncTest "can cancel a tasklist:changed event", ->
57+
expect 2
58+
59+
@field.on 'tasklist:change', (event, index, checked) ->
5960
ok true
61+
event.preventDefault()
6062

61-
@field.remove()
63+
@field.on 'tasklist:changed', (event, index, checked) ->
64+
ok false
6265

63-
@container.pageUpdate()
64-
setTimeout ->
66+
before = @checkbox.val()
67+
setTimeout =>
68+
equal before, @checkbox.val()
6569
start()
6670
, 20
6771

68-
asyncTest "disables task list items when changing source", ->
72+
@checkbox.click()
73+
74+
asyncTest "enables task list items when a .js-task-list-field is present", ->
6975
expect 1
7076

71-
$(document).on 'tasklist:disabled', (event) ->
77+
$(document).on 'tasklist:enabled', (event) ->
7278
ok true
7379

80+
@container.taskList()
7481
setTimeout ->
7582
start()
7683
, 20
7784

78-
@checkbox.click()
85+
asyncTest "doesn't enable task list items when a .js-task-list-field is absent", ->
86+
expect 0
87+
88+
$(document).on 'tasklist:enabled', (event) ->
89+
ok true
90+
91+
@field.remove()
92+
93+
@container.taskList()
94+
setTimeout ->
95+
start()
96+
, 20

test/unit/test_updates.coffee

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
module "TaskList updates",
44
setup: ->
5-
window.linkActivated = false
6-
75
@container = $ '<div>', class: 'js-task-list-container'
86

97
@list = $ '<ul>', class: 'task-list'
@@ -13,7 +11,7 @@ module "TaskList updates",
1311
type: 'checkbox'
1412
class: 'task-list-item-checkbox'
1513
disabled: true
16-
checked: true # yup
14+
checked: true
1715

1816
@incompleteItem = $ '<li>', class: 'task-list-item'
1917
@incompleteCheckbox = $ '<input>',
@@ -48,15 +46,16 @@ module "TaskList updates",
4846
@container.append @list
4947
@container.append @field
5048

51-
$('#qunit-fixture').append(@container).pageUpdate()
49+
$('#qunit-fixture').append(@container)
50+
@container.taskList()
5251

5352
teardown: ->
54-
$(document).off 'tasklist:change'
53+
$(document).off 'tasklist:changed'
5554

5655
asyncTest "updates the source, marking the incomplete item as complete", ->
5756
expect 3
5857

59-
@field.on 'tasklist:change', (event, index, checked) =>
58+
@field.on 'tasklist:changed', (event, index, checked) =>
6059
ok checked
6160
equal index, @incompleteItem.expectedIndex
6261
equal @field.val(), @changes.toIncomplete
@@ -70,7 +69,7 @@ asyncTest "updates the source, marking the incomplete item as complete", ->
7069
asyncTest "updates the source, marking the complete item as incomplete", ->
7170
expect 3
7271

73-
@field.on 'tasklist:change', (event, index, checked) =>
72+
@field.on 'tasklist:changed', (event, index, checked) =>
7473
ok !checked
7574
equal index, @completeItem.expectedIndex
7675
equal @field.val(), @changes.toComplete

0 commit comments

Comments
 (0)