Skip to content

Commit 1ec412d

Browse files
author
Andres Vargas
committed
update livewire
1 parent 8a1c80b commit 1ec412d

16 files changed

+468
-106
lines changed
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
export default class MessageBag {
3+
constructor() {
4+
this.bag = {}
5+
}
6+
7+
add(name, thing) {
8+
if (! this.bag[name]) {
9+
this.bag[name] = []
10+
}
11+
12+
this.bag[name].push(thing)
13+
}
14+
15+
push(name, thing) {
16+
this.add(name, thing)
17+
}
18+
19+
first(name) {
20+
if (! this.bag[name]) return null
21+
22+
return this.bag[name][0]
23+
}
24+
25+
last(name) {
26+
return this.bag[name].slice(-1)[0]
27+
}
28+
29+
get(name) {
30+
return this.bag[name]
31+
}
32+
33+
shift(name) {
34+
return this.bag[name].shift()
35+
}
36+
37+
call(name, ...params) {
38+
(this.listeners[name] || []).forEach(callback => {
39+
callback(...params)
40+
})
41+
}
42+
43+
has(name) {
44+
return Object.keys(this.listeners).includes(name)
45+
}
46+
}

livewire/static/livewire/component/DisableForms.js

+14-4
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,21 @@ export default function () {
1313

1414
if (! el.el.contains(node)) return
1515

16-
if (node.tagName.toLowerCase() === 'button' && node.type === 'submit') {
17-
// Disabled submit button.
16+
if (
17+
// <button type="submit">
18+
(node.tagName.toLowerCase() === 'button' && node.type === 'submit')
19+
// <select>
20+
|| (node.tagName.toLowerCase() === 'select')
21+
// <input type="checkbox|radio">
22+
|| (node.tagName.toLowerCase() === 'input' && (node.type === 'checkbox' || node.type === 'radio'))
23+
) {
1824
node.disabled = true
19-
} else if (node.tagName.toLowerCase() === 'input') {
20-
// Set any inputs to "read only".
25+
} else if (
26+
// <input type="text">
27+
node.tagName.toLowerCase() === 'input'
28+
// <textarea>
29+
|| node.tagName.toLowerCase() === 'textarea'
30+
) {
2131
node.readOnly = true
2232
}
2333
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import store from '@/Store'
2+
3+
export default function () {
4+
store.registerHook('interceptWireModelAttachListener', (el, directive, component) => {
5+
if (! (el.rawNode().tagName.toLowerCase() === 'input' && el.rawNode().type === 'file')) return
6+
7+
let start = () => el.rawNode().dispatchEvent(new CustomEvent('livewire-upload-start', { bubbles: true }))
8+
let finish = () => el.rawNode().dispatchEvent(new CustomEvent('livewire-upload-finish', { bubbles: true }))
9+
let error = () => el.rawNode().dispatchEvent(new CustomEvent('livewire-upload-error', { bubbles: true }))
10+
let progress = (progressEvent) => {
11+
var percentCompleted = Math.round( (progressEvent.loaded * 100) / progressEvent.total )
12+
13+
el.rawNode().dispatchEvent(
14+
new CustomEvent('livewire-upload-progress', {
15+
bubbles: true, detail: { progress: percentCompleted }
16+
})
17+
)
18+
}
19+
20+
let eventHandler = e => {
21+
if (e.target.files.length === 0) return
22+
23+
start()
24+
25+
if (e.target.multiple) {
26+
component.uploadMultiple(directive.value, e.target.files, finish, error, progress)
27+
} else {
28+
component.upload(directive.value, e.target.files[0], finish, error, progress)
29+
}
30+
}
31+
32+
el.addEventListener('change', eventHandler)
33+
34+
component.addListenerForTeardown(() => {
35+
el.removeEventListener('change', eventHandler)
36+
})
37+
})
38+
}

livewire/static/livewire/component/LoadingStates.js

+34-9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export default function () {
55
component.targetedLoadingElsByAction = {}
66
component.genericLoadingEls = []
77
component.currentlyActiveLoadingEls = []
8+
component.currentlyActiveUploadLoadingEls = []
89
})
910

1011
store.registerHook('elementInitialized', (el, component) => {
@@ -105,13 +106,41 @@ function setLoading(component, actions) {
105106

106107
const allEls = component.genericLoadingEls.concat(actionTargetedEls)
107108

108-
allEls.forEach(({ el, directive }) => {
109+
startLoading(allEls)
110+
111+
component.currentlyActiveLoadingEls = allEls
112+
}
113+
114+
export function setUploadLoading(component, modelName) {
115+
const actionTargetedEls = component.targetedLoadingElsByAction[modelName] || []
116+
117+
const allEls = component.genericLoadingEls.concat(actionTargetedEls)
118+
119+
startLoading(allEls)
120+
121+
component.currentlyActiveUploadLoadingEls = allEls
122+
}
123+
124+
export function unsetUploadLoading(component) {
125+
endLoading(component.currentlyActiveUploadLoadingEls)
126+
127+
component.currentlyActiveUploadLoadingEls = []
128+
}
129+
130+
function unsetLoading(component) {
131+
endLoading(component.currentlyActiveLoadingEls)
132+
133+
component.currentlyActiveLoadingEls = []
134+
}
135+
136+
function startLoading(els) {
137+
els.forEach(({ el, directive }) => {
109138
el = el.el // I'm so sorry @todo
110139

111140
if (directive.modifiers.includes('class')) {
112141
// This is because wire:loading.class="border border-red"
113142
// wouldn't work with classList.add.
114-
const classes = directive.value.split(' ')
143+
const classes = directive.value.split(' ').filter(Boolean)
115144

116145
if (directive.modifiers.includes('remove')) {
117146
el.classList.remove(...classes)
@@ -132,16 +161,14 @@ function setLoading(component, actions) {
132161
}
133162
}
134163
})
135-
136-
component.currentlyActiveLoadingEls = allEls
137164
}
138165

139-
function unsetLoading(component) {
140-
component.currentlyActiveLoadingEls.forEach(({ el, directive }) => {
166+
function endLoading(els) {
167+
els.forEach(({ el, directive }) => {
141168
el = el.el // I'm so sorry @todo
142169

143170
if (directive.modifiers.includes('class')) {
144-
const classes = directive.value.split(' ')
171+
const classes = directive.value.split(' ').filter(Boolean)
145172

146173
if (directive.modifiers.includes('remove')) {
147174
el.classList.add(...classes)
@@ -158,6 +185,4 @@ function unsetLoading(component) {
158185
el.style.display = 'none'
159186
}
160187
})
161-
162-
component.currentlyActiveLoadingEls = []
163188
}
+41-6
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,54 @@
11
import MethodAction from '@/action/method'
2+
import DOMElement from '@/dom/dom_element'
23
import store from '@/Store'
34

45
export default function () {
56
store.registerHook('elementInitialized', (el, component) => {
67
if (el.directives.missing('poll')) return
78

8-
fireActionOnInterval(el, component)
9+
let intervalId = fireActionOnInterval(el.el, component)
10+
11+
component.addListenerForTeardown(() => {
12+
clearInterval(intervalId)
13+
})
14+
15+
el.el.__livewire_polling_interval = intervalId
16+
})
17+
18+
store.registerHook('beforeElementUpdate', (from, to, component) => {
19+
if (from.__livewire_polling_interval !== undefined) return
20+
21+
let fromEl = new DOMElement(from)
22+
let toEl = new DOMElement(to)
23+
24+
if (fromEl.directives.missing('poll') && toEl.directives.has('poll')) {
25+
setTimeout(() => {
26+
let intervalId = fireActionOnInterval(fromEl.el, component)
27+
28+
component.addListenerForTeardown(() => {
29+
clearInterval(intervalId)
30+
})
31+
32+
from.__livewire_polling_interval = intervalId
33+
}, 0)
34+
}
935
})
1036
}
1137

12-
function fireActionOnInterval(el, component) {
13-
const directive = el.directives.get('poll')
14-
const method = directive.method || '$refresh'
38+
function fireActionOnInterval(node, component) {
39+
let interval = (new DOMElement(node)).directives.get('poll').durationOr(2000);
40+
41+
return setInterval(() => {
42+
if (node.isConnected === false) return
43+
44+
let el = new DOMElement(node);
45+
46+
// Don't poll when directive is removed from element.
47+
if (el.directives.missing('poll')) return
48+
49+
const directive = el.directives.get('poll')
50+
const method = directive.method || '$refresh'
1551

16-
setInterval(() => {
1752
// Don't poll when the tab is in the background.
1853
// The "Math.random" business effectivlly prevents 95% of requests
1954
// from executing. We still want "some" requests to get through.
@@ -23,5 +58,5 @@ function fireActionOnInterval(el, component) {
2358
if (store.livewireIsOffline) return
2459

2560
component.addAction(new MethodAction(method, directive.params, el))
26-
}, directive.durationOr(2000));
61+
}, interval);
2762
}

livewire/static/livewire/component/UpdateQueryString.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,6 @@ export default function () {
4343

4444
var stringifiedQueryString = queryString.stringify(queryData)
4545

46-
history.replaceState({turbolinks: {}}, "", window.location.pathname + '?' + stringifiedQueryString)
46+
history.replaceState({turbolinks: {}}, "", [window.location.pathname, stringifiedQueryString].filter(Boolean).join('?'))
4747
})
4848
}

0 commit comments

Comments
 (0)