Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Javascript events on dynamic content insertion #151

Closed
alexhillel opened this issue Dec 18, 2019 · 12 comments
Closed

Javascript events on dynamic content insertion #151

alexhillel opened this issue Dec 18, 2019 · 12 comments
Labels
enhancement New feature or request

Comments

@alexhillel
Copy link

Is your feature request related to a problem? Please describe.

It would be great to have Javascript events available to run before/after Blitz's dynamic content insertion, so custom Javascript can be run once the dynamic content is available in the DOM.

Describe the solution you would like

Event(s) available and documented that can be listened for. Maybe with some parameters around which URL/template has been inserted, what parameters were passed etc.

Describe alternatives you have considered

I'm having to add event listeners on the document instead which is fine but would be good to have this other option.

@alexhillel alexhillel added the enhancement New feature or request label Dec 18, 2019
@bencroker
Copy link
Collaborator

Thanks for the suggestion! How does something like this look?

element.innerHTML = this.responseText;

var event = new CustomEvent('blitzInject', { detail: {
    uri: uri,
    params: params,
    text: responseText,
});

// Event is dispatched on the element that the resonse was just injected into
element.dispatchEvent(event);

You'd then listen to it as follows:

element.addEventListener('blitzInject', function (event) { 
    ...
}, false);

The event is dispatched after the response text is injected into the element, which seems to suffice. I'm wondering if there might be any benefit to dispatching an event beforehand too?

@alexhillel
Copy link
Author

alexhillel commented Dec 18, 2019

That looks perfect! I can't think of anything I'd want to do before insertion and mentioned it only for completeness - an after event only would certainly give me everything I need.

@bencroker
Copy link
Collaborator

bencroker commented Dec 18, 2019

Added a cancelable before and an after event, to mimic how events work in Craft.
https://github.com/putyourlightson/craft-blitz/blob/develop/src/resources/js/blitzInjectScript.js

Callable as follows:

document.addEventListener('beforeBlitzInject', function (event) { 
    if (event.detail.element.hasClass('shoot-me-down') {
        // Cancel event
        event.preventDefault();
    }
});

document.addEventListener('afterBlitzInject', function (event) { 
    if (event.detail.element.hasClass('mark-me-red') {
        event.detail.element.addClass('red');
    }
});

@jsmrtn
Copy link

jsmrtn commented Dec 23, 2019

Any idea when this will be merged into master, @bencroker? Amazingly I'm after the same thing so always good to see that the problem has been solved!

@bencroker
Copy link
Collaborator

We're still experimenting with the best way to make this work. If you have a use-case then please describe it so we can evaluate the method we've used so far.

You can also test it as follows:

composer require putyourlightson/craft-blitz:dev-develop

@jsmrtn
Copy link

jsmrtn commented Dec 23, 2019

We have a listing that contains members and non-members content, so although we want to add these pages to the cache, we also show different things on the listing item based on whether the user is logged in or not. We're using it in this way, we check with a controller endpoint that the user is logged in and then modify the DOM.

var checkAuth = $.get("/actions/scaramanga/login/checklogin");

document.addEventListener('afterBlitzInject', function (event) { 
    if (checkAuth[0] == [...]) {
        // do bits
    }
});

I've just tested your updates and they're working successfully for our use-case above.

@bencroker
Copy link
Collaborator

bencroker commented Dec 23, 2019

Any reason you would do that over checking the user status in the injected twig template?

{% if currentUser %}
    Welcome, {{ currentUser.friendlyName }}!
{% else %}
    Welcome, guest!
{% endif %}

@jsmrtn
Copy link

jsmrtn commented Dec 23, 2019

I've actually done a bit more refactoring now and in this use-case I actually don't need to use the new event listener.

The reason we couldn't do it in the injected twig template is because we need some content to be immediately available, so we opt for the non-member content and then toggle it out to the member content if the above call returns truthy. We did originally have it the way you have described, but because they were all AJAX calls the page built erratically and had no content on page load.

I do still think that the method you have added is a suitable option (and I can see use-cases for this in the future), though I do wonder if it might be worth firing the event once after all XHR's are completed, instead of per individual completion (or maybe both, if that's a viable option).

@bencroker
Copy link
Collaborator

I do wonder if it might be worth firing the event once after all XHR's are completed, instead of per individual completion (or maybe both, if that's a viable option).

Thanks for the suggestion, will look into what would be required to make this possible.

@bencroker
Copy link
Collaborator

I've switched to using Promise.all() which allows us to have an afterBlitzInjectAll event in addition to individual afterBlitzInject events. The latest version is pushed in case you'd like to give it a whirl.

@bencroker
Copy link
Collaborator

@bencroker
Copy link
Collaborator

@alexhillel @joshua-martin as of 7c7499a, the dynamic content inject script only makes a single AJAX request per unique URL, including CSRF inputs and tokens. Since you are taking advantage of the JavaScript events that Blitz triggers, if you could help test this on your end then that would be much appreciated. See #329 for more context.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants