Skip to content

Commit

Permalink
fix SSE listeners registration
Browse files Browse the repository at this point in the history
  • Loading branch information
Renerick committed Feb 25, 2024
1 parent bf5de25 commit 6272ae4
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 29 deletions.
38 changes: 25 additions & 13 deletions ext/sse.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,9 @@ This extension adds support for Server Sent Events to htmx. See /www/extensions

return

// Try to create EventSources when elements are processed
// Try to create EventSources when elements are processed
case 'htmx:afterProcessNode':
ensureEventSourceOnElement(evt.target)
registerSSE(evt.target)
}
}
})
Expand Down Expand Up @@ -76,19 +75,19 @@ This extension adds support for Server Sent Events to htmx. See /www/extensions
* @param {HTMLElement} elt
*/
function registerSSE(elt) {
// Find closest existing event source
var sourceElement = api.getClosestMatch(elt, hasEventSource)
if (sourceElement == null) {
// api.triggerErrorEvent(elt, "htmx:noSSESourceError")
return null // no eventsource in parentage, orphaned element
}

// Set internalData and source
var internalData = api.getInternalData(sourceElement)
var source = internalData.sseEventSource

// Add message handlers for every `sse-swap` attribute
queryAttributeOnThisOrChildren(elt, 'sse-swap').forEach(function(child) {
// Find closest existing event source
var sourceElement = api.getClosestMatch(child, hasEventSource)
if (sourceElement == null) {
// api.triggerErrorEvent(elt, "htmx:noSSESourceError")
return null // no eventsource in parentage, orphaned element
}

// Set internalData and source
var internalData = api.getInternalData(sourceElement)
var source = internalData.sseEventSource

var sseSwapAttr = api.getAttributeValue(child, 'sse-swap')
var sseEventNames = sseSwapAttr.split(',')

Expand Down Expand Up @@ -122,6 +121,17 @@ This extension adds support for Server Sent Events to htmx. See /www/extensions

// Add message handlers for every `hx-trigger="sse:*"` attribute
queryAttributeOnThisOrChildren(elt, 'hx-trigger').forEach(function(child) {
// Find closest existing event source
var sourceElement = api.getClosestMatch(child, hasEventSource)
if (sourceElement == null) {
// api.triggerErrorEvent(elt, "htmx:noSSESourceError")
return null // no eventsource in parentage, orphaned element
}

// Set internalData and source
var internalData = api.getInternalData(sourceElement)
var source = internalData.sseEventSource

var sseEventName = api.getAttributeValue(child, 'hx-trigger')
if (sseEventName == null) {
return
Expand Down Expand Up @@ -174,6 +184,8 @@ This extension adds support for Server Sent Events to htmx. See /www/extensions

ensureEventSource(child, sseURL, retryCount)
})

registerSSE(elt)
}

function ensureEventSource(elt, url, retryCount) {
Expand Down
33 changes: 17 additions & 16 deletions test/ext/sse.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ describe('sse extension', function() {
'<div id="d1" sse-connect="/event_stream" sse-swap="e1">div1</div>\n' +
'</div>\n'
)
this.eventSource.url = '/event_stream'
this.eventSource.sendEvent('e1', 'Event 1')
byId('d1').innerText.should.equal('Event 1')
})

it('only adds sseEventSource to elements with sse-connect', function() {
Expand Down Expand Up @@ -233,59 +234,59 @@ describe('sse extension', function() {
})

it('raises htmx:sseBeforeMessage when receiving message from the server', function() {
var myEventCalled = false;
var myEventCalled = false

function handle(evt) {
myEventCalled = true;
myEventCalled = true
}

htmx.on('htmx:sseBeforeMessage', handle)

var div = make('<div hx-ext="sse" sse-connect="/event_stream" sse-swap="e1"></div>');
var div = make('<div hx-ext="sse" sse-connect="/event_stream" sse-swap="e1"></div>')

this.eventSource.sendEvent('e1', '<div id="d1"></div>')

myEventCalled.should.be.true;
myEventCalled.should.be.true

htmx.off('htmx:sseBeforeMessage', handle)
})

it('cancels swap when htmx:sseBeforeMessage was cancelled', function() {
var myEventCalled = false;
var myEventCalled = false

function handle(evt) {
myEventCalled = true;
evt.preventDefault();
myEventCalled = true
evt.preventDefault()
}

htmx.on('htmx:sseBeforeMessage', handle)

var div = make('<div hx-ext="sse" sse-connect="/event_stream" sse-swap="e1"><div id="d1">div1</div></div>');
var div = make('<div hx-ext="sse" sse-connect="/event_stream" sse-swap="e1"><div id="d1">div1</div></div>')

this.eventSource.sendEvent('e1', '<div id="d1">replaced</div>')

myEventCalled.should.be.true;
myEventCalled.should.be.true

byId("d1").innerHTML.should.equal('div1');
byId('d1').innerHTML.should.equal('div1')

htmx.off('htmx:sseBeforeMessage', handle)
})

it('raises htmx:sseMessage when message was completely processed', function() {
var myEventCalled = false;
var myEventCalled = false

function handle(evt) {
myEventCalled = true;
myEventCalled = true
}

htmx.on('htmx:sseMessage', handle)

var div = make('<div hx-ext="sse" sse-connect="/event_stream" sse-swap="e1"><div id="d1">div1</div></div>');
var div = make('<div hx-ext="sse" sse-connect="/event_stream" sse-swap="e1"><div id="d1">div1</div></div>')

this.eventSource.sendEvent('e1', '<div id="d1">replaced</div>')

myEventCalled.should.be.true;
byId("d1").innerHTML.should.equal("replaced");
myEventCalled.should.be.true
byId('d1').innerHTML.should.equal('replaced')

htmx.off('htmx:sseMessage', handle)
})
Expand Down

0 comments on commit 6272ae4

Please sign in to comment.