what is the event listener that can be used after dialog content loaded.? - aem

Am trying to use $document.on("dialog-ready", function() { .. } for touch UI dialog customization. Where as i can see the dialog-ready event fires before the dialog content is fully loaded which gives me a unavailability of tags for traversal of dialog html.
Is there any event listener that i can use for triggering a call after my
dialog is fully loaded with all widgets and its values.?
Is there any documentation link where i can find these event
listeners apart from Adobe Experience Manager Help | Using Event
Handlers in Adobe Experience Manager Touch UI Components .?
Also what is the order of sequence AEM loads $document.on("dialog-ready", function() { .. } when compares with $(document).on("foundation-contentloaded", function (e) { .. }.
?

Dialog ready is fired when a dialog is opened. Not necessarily after all values are populated.
Foundation contentloaded is fired when new fields are injected into the dialog. More specifically, according to the documentation, "it should be triggered when a container is injected".
So using foundation-contentloaded is ideal when working with multifields where new fields get added much later. Also, dialog-ready will not be fired in page creation wizard. We have to use foundation-contentloaded here.
Neither of the two will guarantee that all content will be populated for us to start using their values in JavaScript. Especially when we have RTE/multifields in our dialog.
To answer your question,
There are no event listeners that you can use that indicates the dialog is fully loaded.
I noticed foundation-contentloaded fires before dialog-ready
Coral.commons.ready ensures initialization. Especially helpful when working with multifields and RTEs.
Coral.commons.ready(this, () => {
/*
logic to run once coral element 'this' is pointing to is initialized (initialize or _render methods are invoked)
*/
});
More information on foundation-contentloaded and Coral.commons.ready

You can use:
$(document).on("foundation-contentloaded", function(e) {
var container = e.target;
});
Check this link.
Here are more examples:
https://helpx.adobe.com/experience-manager/using/creating-touchui-events.html

Related

Where can I found documentation about page lifecycle events?

I am using cdp (https://github.com/mafredri/cdp) in order to use devtools protocol to generate a pdf of a page. But first I need to know when the page is completely loaded. I found that the networkIdle event can help me to know when this occurs. But, I have troubles because the networkIdle event sometimes fired twice. Then I need to know when this one is fired
There are two parts for what you're looking for.
First of all, the reason the event is fired twice. When a new tab (target) is created, the first page it loads is about:blank. You get lifecycle events for this page as well. The second time the load event is fired is the one you're looking for (if you're using Page.lifecycleEvent).
Now, to handle the second matter - there are also other events you can use. The basic one for page loading is Page.loadEventFired, which, as far as I recall, will only be fired for the actual page (but I could be wrong about this one).
Important note: If you're using lifecycle events, they are fired for each frame separately, meaning that the main frame might finish loading before the sub frames are loaded. Page.loadEventFired has a different behavior and waits for all frames to fire their load event.
Here is a good article on the page lifecycle api.
Another possible solution could be:
document.onreadystatechange = function () {
if (document.readyState === 'complete') {
run the screenshot code...
}
}

analytics script is not sending data from shadow DOM

We are working on tracking a site which has components built using Shadow DOM concepts, when we are creating a rule in launch to add tagging to these components it’s not working.
Can you guide us with best practice on tagging components in Shadow DOM?
I found unanswered questions about google analytics Google analytics inside shadow DOM doesn't work is this true for adobe analytics also?
Best Practice
Firstly, the spirit of using Shadow DOM concepts is to provide scope/closure for web components, so that people can't just go poking at them and messing them up. In principle, it is similar to having a local scoped variable inside a function that a higher scope can't touch. In practice, it is possible to get around this "wall" and have your way with it, but it breaks the "spirit" of shadow DOM, which IMO is bad practice.
So, if I were to advise some best practice about any of this, my first advice is to as much as possible, respect the spirit of web components that utilize shadow DOM, and treat them like the black box they strive to be. Meaning, you should go to the web developers in charge of the web component and ask them to provide an interface for you to use.
For example, Adobe Launch has the ability to listen for custom events broadcast to the (light) DOM, so the site developers can add to their web component, create a custom event and broadcast it on click of the button.
Note: Launch's custom event listener will only listen for custom event broadcasts starting at document.body, not document, so make sure to create and broadcast custom events on document.body or deeper.
"But the devs won't do anything so I have to take matters into my own hands..."
Sadly, this is a reality more often than not, so you gotta do what you gotta do. If this is the case, well, Launch does not currently have any native features to really make life easier for you in this regard (for the "core" part of the below stuff, anyways), and as of this post, AFAIK there are no public extensions that offer anything for this, either. But that doesn't mean you're SoL.
But I want to state that I'm not sure I would be quick to call the rest of this answer "Best Practice" so much as "It's 'a' solution..". Mostly because this largely involves just dumping a lot of pure javascript into a custom code box and calling it a day, which is more of a "catch-all, last resort" solution.
Meanwhile, in general, it's best practice to avoid using custom code boxes when it comes to tag managers unless you have to. The whole point of tag managers is to abstract away the code.
I think the TL;DR here is basically me reiterating this something that should ideally be put on the site devs' plate to do. But if you still really need to do it all in Launch because ReasonsTM, keep on reading.
'A' Solution...
Note: This is a really basic example with a simple open-mode shadow DOM scenario - in reality your scenario is almost certainly a lot more complex. I expect you to know what you're doing with javascript if you're diving into this!
Let's say you have the following on the page. Simple example of a custom html element with a button added to its shadow DOM.
<script>
class MyComponent extends HTMLElement {
constructor() {
super();
this._shadowRoot = this.attachShadow({
mode: 'open'
});
var button = document.createElement('button');
button.id = 'myButton';
button.value = 'my button value';
button.innerText = 'My Button';
this._shadowRoot.appendChild(button);
}
}
customElements.define('my-component', MyComponent);
</script>
<my-component id='myComponentContainer'></my-component>
Let's say you want to trigger a rule when a visitor clicks on the button.
Quick Solution Example
At this point I should probably say that you can get away with doing a Launch click event rule with query selector my-component#myComponentContainer with a custom code condition along the lines of:
return event.nativeEvent.path[0].matches('button#myButton');
Something like this should work for this scenario because there are a lot of stars aligned here:
The shadow dom is open mode, so no hacks to overwrite things
There are easily identifiable unique css selectors for both light and shadow DOM levels
You just want to listen for the click event, which bubbles up and
acts like a click happened on the shadow root's light DOM root.
In practice though, your requirements probably aren't going to be this easy. Maybe you need to attach some other event listener, such as a video play event. Unfortunately, there is no "one size fits all" solution at this point; it just depends on what your actual tracking requirements are.
But in general, the goal is pretty much the same as what you would have asked the devs to do: create and broadcast a custom (light) DOM event within the context of the shadow DOM.
Better Solution Example
Using the same component example and requirement as above, you could for example create a rule to trigger on DOM Ready. Name it something like "My Component Tracking - Core" or whatever. No conditions, unless you want to do something like check if the web component's root light DOM element exists or whatever.
Overall, this is the core code for attaching the event listener to the button and dispatching a custom event for Launch to listen for. Note, this code is based on our example component and tracking requirements above. It is unique to this example. You will need to write similar code based on your own setup.
Add a custom js container with something along the lines of this:
// get the root (light dom) element of the component
var rootElement = document.querySelector('#myComponentContainer');
if (rootElement && rootElement.shadowRoot) {
// get a reference to the component's shadow dom
var rootElementDOM = rootElement.shadowRoot;
// try and look for the button
var elem = rootElementDOM.querySelector('button#myButton');
if (elem) {
// add a click event listener to the button
elem.addEventListener('click', function(e) {
// optional payload of data to send to the custom event, e.g. the button's value
var data = {
value: e.target.value
};
// create a custom event 'MyButtonClick' to broadcast
var ev = new CustomEvent('MyButtonClick', {
detail: data
});
// broadcast the event (remember, natively, Launch can only listen for custom events starting on document.body, not document!
document.body.dispatchEvent(ev);
}, false);
}
}
From here, you can create a new rule that listens for the custom event broadcast.
Custom Event Rule Example
Rule name: My Button clicks
Events
Extension: Core
Event Type: Custom Event
Name: MyButtonClick
Custom Event Type: MyButtonClick
Elements matching the CSS selector: body
Conditions
*None for this scenario*
From here, you can set whatever Actions you want (set Adobe Analytics variables, send beacon, etc.).
Note:
In this example, I sent a data payload to the custom event. You can reference the payload in any custom (javascript) code box with event.detail, e.g. event.detail.value. You can also reference them in Launch fields with the % syntax, e.g. %event.detail.value%.

Hook into onExecCommand event with TinyMCE 4

I am using TinyMCE 4 but the documentation is terrible. I am trying to provide a live preview of the content in another div (outside of the editor). Right now I am listening to these events:
$(document).on('tinymce:changed tinymce:init', ...)
This is working when text is entered, but it does not trigger when commands are executed (changing existing text to bold for example).
It looks like in TinyMCE 3.x there is an onExecCommand event that does what I want. But I can't find any documentation on how to listen to the global jQuery event like I am doing with with change and init. Does anyone know what event it is firing?
In the migration guide you can find the following example:
// Old event
editor.onInit(editor, args) {
// Custom logic
});
// New event
editor.on('init', function(args) {
// Custom logic
});
So the one problem is to get right event name and the right editor instance :)
The onExecCommand() event becomes 'ExecCommand' in v4.
So adding a handler on command execution should be like this (be sure that editors are already initialized when executing code below):
for (ed_id in tinymce.editors) {
tinymce.editors[ed_id].on('ExecCommand', function(args) {
alert(1);
});
}
For some reason this event fires twice when command is executed. I think you will overcome this issue.
Though this method does not uses jQuery bindings, it works for me and possibly will solve your problem too.
In case this helps anyone else, here is a list of all the events tinymce 4 allows:
http://www.tinymce.com/wiki.php/api4:class.tinymce.Editor

jquery live click event stopPropagation

I have a dropdown menu which contains a input and several buttons. The dropdown should hide when I click one of the buttons or somewhere else, but don't hide when keypress on the input. I use the following code, it doesn't work. Though it works when I use
$('.dropdown input').click(function(e){
})
instead of live.
But I do need live, so is there any solution for this?
/* dropdown menu */
$('.dropdown input').live('click', function(e) {
e.stopPropagation();
});
$(document).click(function(e){
if(e.isPropagationStopped()) return; //important, check for it!
});
e.stopPropagation() will do no good for you in .live(), because the handler is bound to the document, so by the time the handler is invoked, the event has already bubbled.
You should stopPropagation from a more local ancestor of the element being clicked.
Since you were using .live(), I assume there are some dynamic elements being created. If so, the proper element to bind to will depend on the rest of your code.
Side note, but you never "need" .live(). There are other ways to handle dynamically created elements.
did you try:
$('.dropdown').on('click', 'input', function(e) {
e.stopPropagation();
});
OR
$('.dropdown').delegate('input', 'click', function(e) {
e.stopPropagation();
});
NOTE: e.stopPropagation(); is not effective for live event
According to you question I have a dropdown menu which contains a input and several buttons. The dropdown should hide... means that dropdown is already exists within you DOM. If it already exists then you don't need live event.
what version of jQuery are you using? > 1.7 then:
$(document).on({"click":function(e){
//do your work, only input clicks will fire this
}},".dropdown input",null);
notes:
properly paying attention to event.target should help out with overlapping 'click' definitions using .on();

google wave: how did they make divs clickable

As we are facing GWT performance issues in a mobile app I peeked into Google Wave code since it is developed with GWT.
I thought that all the buttons there are widgets but if you look into generated HTML with firebug you see no onclick attribute set on clickable divs. I wonder how they achieve it having an element that issues click or mousedown events and seemingly neither being a widget nor injected with onclick attribute.
Being able to create such components would surely take me one step further to optimizing performance.
Thanks.
ps: wasnt google going to open source client code too. Have not been able to find it.
You don't have to put an onclick attribute on the HTML to make it have an onclick handler. This is a very simple example:
<div id="mydiv">Regular old div</div>
Then in script:
document.getElementById('mydiv').onclick = function() {
alert('hello!');
}
They wouldn't set the onclick property directly, it would have been set in the GWT code or via another Javascript library.
The GWT documentation shows how to create handlers within a GWT Java app:
public void anonClickHandlerExample() {
Button b = new Button("Click Me");
b.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// handle the click event
}
});
}
This will generate an HTML element and bind a click handler to it. However, in practice this has the same result as using document.getElementById('element').onclick() on an existing element in your page.
You can hook functions to the onclick event using JavaScript. Here's an example using jQuery:
$(document).ready(function(){
$("#div-id").click(function(){
/* Do something */
});
});
If you're interested in optimizing performance around this, you may need to investigate event delegation, depending on your situation.
A click event is generated for every DOM element within the Body. The event travels from the Body down to the element clicked (unless you are using Internet Explorer), hits the element clicked, and then bubbles back up. The event can be captured either through DOM element attributes, event handlers in the javascript, or attributes at any of the parent levels (the bubbling or capturing event triggers this).
I'd imagine they've just set it in a .js file.
Easily done with say jQuery with $(document).ready() for example.