Google Analytics - Get nested span event click without class and id - javascript

I am using Tag manager and Anayltics 360.
My code as follows,
<div rel="ABC_Links" class="ak_widget" >
<!-- BEGIN: Widget - Links -->
<section class="mfb-30">
<div class="widget_links">
<div class="widget_container">
<div class="widget_content">
<button type="button" class="buttonShadow" onclick="window.open('https://somepagelink.aspx); return false;">
<div class="widget_item">
<div class="widget_icon">
<svg>123</svg>
</div>
<div class="widget_text"><span style="overflow-wrap: normal;">ABCD TEXT</span></div>
</div>
</button>
<button type="button" class="buttonShadow" onclick="window.open('https://somepagelink.aspx); return false;">
<div class="widget_item">
<div class="widget_icon">
<svg> 12345</svg>
</div>
<div class="widget_text"><span style="overflow-wrap: normal;">XYZ TEXT</span></div>
</div>
</button>
</div>
</div>
</div>
</section>
<!-- END: Widget Links --></div>
I have 12 buttons in this same format. Here i have given an example of two buttons.
Button name i can change later so i can not take it as hard coded for "Click Text" in tag manager.
I can use only rel= "ABC_Links" as unique identifier. I can not use any of below class as they are not unique.
I have used Custome javascript to get parent child relationship but didn't work.
I have used DOM element variable but it did not work.
Now Question is, Is there any way to trigger event in tag manager when i click on any of the button below and get the info in real time event in Anayltics 360 ???

One way to achieve this would be to create a User-Defined Custom JavaScript variable in GTM to set isABCLink=true on button click.
On the Variables screen under Built-In Variables make sure you have "Click Element" ticked.
Create a User-Defined Variable
Name: isABCLink
Type: Custom JavaScript
Code:
function() {
return {{Click Element}}.matches("div[rel=ABC_Links] button, div[rel=ABC_Links] button *");
}
Create a Trigger
Trigger Type: Click - All Elements
This trigger fires on: Some Clicks
Conditions: isABCLink equals true
Set up your tag firing on above trigger
Once caveat to point out is that the exact element clicked on could be the button or one of the child elements of the button such as the <svg> which might make it hard to set up your tag depending on what exactly you need.

Related

I have a dynamic html template. Which forms when I click on a button. Now, the problem is When I click on one button all buttons are clicked

Here is the html template forms when I click on a button.
<div class="detail">
<h3>${element.name}</h3>
<p>Phone: ${element.phone}</p>
<button onclick="addToHistory()">Call</button>
</div>`
Let's say it creates two template as it is.
<div class="detail">
<h3>Person1</h3>
<p>Phone: 0111111111</p>
<button onclick="addToHistory()">Call</button>
</div>`
<div class="detail">
<h3>Person2</h3>
<p>Phone: 0111111111</p>
<button onclick="addToHistory()">Call</button>
</div>`
Now, I want to click on one button and then according to my click I want the data of clicked divs should store.
I tried this using event handler as you can see with addToHistory() function. But, it stores all the data both I clicked and not clicked also.
Please note: I want to do this only using JavaScript. Thank you for your support.
You can pass this into your method and use that to traverse within the specific detail container where the button was clicked.
this will reference the specific element the event occurs on
function addToHistory(el){
console.log(el.previousElementSibling.textContent);
}
<div class="detail">
<h3>Person1</h3>
<p>Phone: 0999999999</p>
<button onclick="addToHistory(this)">Call</button>
</div>`
<div class="detail">
<h3>Person2</h3>
<p>Phone: 0111111111</p>
<button onclick="addToHistory(this)">Call</button>
</div>`

HTML element in button prevents disabled in the wrapper element

Fiddle: http://jsfiddle.net/0o1mrapd/20/
Angular stackblitz link: https://stackblitz.com/edit/angular-fhtaki?file=src%2Fapp%2Fapp.component.html
I have a complex case which i need some enlightenment. (For angular developers, you can think the wrapper div as a host selector, <my-button></my-button>)
As you can see in the fiddle I have a disabled button with a wrapper div which has a click event.
<div onclick="alert('hey')" style="display:inline-block">
<button disabled>
<span>Click</span>
</button>
</div>
What I expect is that when I click on that area, nothing will happen but alas I get the alert. If I remove the span element and put plain text inside the button, this works.
<div onclick="alert('hey')" style="display:inline-block">
<button disabled>
Click
</button>
</div>
How can I make the div unclickable in this case? I found out that pointer-events: none does the trick but then I lose the curser-event which I need for accessibility
I stumbled upon this issue while creating a custom button component with an ng-content in Angular but then realized this is bigger than the framework.
Some links i checked:
Can you prevent an Angular component's host click from firing?
Add CSS cursor property when using "pointer-events: none"
How to stop event propagation with inline onclick attribute?
https://github.com/angular/angular/issues/9587
Maybe this example will be useful
function clickHandler() {
console.log('Click');
}
<div onclick="return false;">
<button onclick="clickHandler()">
Click
</button>
</div>
You can use this css property to avoid click event be fired in the span tag. It could be a workaround.
<div onclick="alert('hey')" style="display:inline-block">
<button disabled>
<span style="pointer-events:none;">Click</span>
</button>
</div>

Can I trigger xe:namepicker via csjs?

On an xpage I have an editbox control and xe:namepicker nicely grouped beside each other with a Bootstrap add-on component.
However I would like to trigger the xe:namepicker when the cursor enters the editbox.
In the DOM I see that for the namepicker an anchor link is generated such as:
a class="glyphicon glyphicon-user xspPickerLink" href="javascript:;"
And I could trigger the click event via csjs
$("a.xspPickerLink").trigger('click');
But I happen to have multiple xe:namepicker-s on my xpage.
Does anyone have a clue how I can trigger a SPECIFIC xe:namepicker ?
You can work with wrapper elements:
<div id="namePicker1Wrapper">
<xe:namePicker id="namePicker1" pickerText="Select..."></xe:namePicker>
</div>
<div id="namePicker2Wrapper">
<xe:namePicker id="namePicker2" pickerText="Select..."></xe:namePicker>
</div>
Now you have the opportunity to select a SPECIFIC xe:namepicker:
$("#namePicker1Wrapper a.xspPickerLink").trigger('click');

javascript, creating <div> and <button> then clicking on that button

I've been given a widget that sales tickets to specific boat tour,
it needs
<div id="wt_piersWidget" data-api-key="1234" data-tour-id="12"> </div> container
and some <button class="wt-open"></button> ,
after click on the button it opens form to choose data and pier ro sale from. It works fine on the sites with separate pages for each tour. simple html for those pages is:
`<script type="text/javascript" src="/jquery/1.7.1/jquery.min.js"></script>
<link href="/wt_widget/style.css" rel="stylesheet">
<div id="wt_piersWidget" class="wt__start-hide"
data-api-key="1234"
data-program-id="12"
></div>
<button class="wt-open"></button>
<script src="/wt_widget/widget.js"></script>
`
I have some trouble implementing it on the site with special "sales" blocks for 3 different tours on a single page.
I am trying to check what exact button out of 3 possible is clicked, create <div> with attribute values that I need for this tour, then create <button> with correct class and click on it. concole.log() returns correct objects in console, but widget do not recieves any of those attriubute values.
I realise, that at this point I am misunderstanding core principles of how all this code works on the pages, I just do not know where to start to fix it.
<!-- css for widget -->
<link href="wt_widget/style.css" rel="stylesheet">
<!---------------------->
<div id="prices">
<div class="section">
<div class="container-fluid">
<h2 class="section-title">Prices block</h2>
<p class="section-subtitle">
</p>
<div class="row">
<div class="col-lg-3 col-md-6 col-sm-6">
<!-- One of the block with price list for one of the tours (for ex. tour#13) -->
<div class="panel panel__mm-ct">
<div class="cell">
<div class="panel-heading">
<div class="price-icon"
style="background-image: url('/site/assets/files/1111/icon_boat_bus.png');"></div>
<h3>tour title</h3>
<p>ticket info</p>
</div>
<div class="panel-body" id="">
<ul class="list-unstyled">
<li><i class="fa fa-ticket"
aria-hidden="true"></i>ticket type 1</li>
<li><i class="fa fa-ticket"
aria-hidden="true"></i>ticket type2</li>
</ul>
<button id="2" class="btn btn-success" onclick="setProgrammParam(this.id)">Order ticket</button> <!--button inside one o those 3 blocks, button id is how I separate one block from another, it does work -->
<div id="wt_piersWidget" class="wt__start-hide" data-api-key="123"></div> <!--widget template-->
<script>
function setProgrammParam(idCheck) { //idCheck stores value from sales block< so I know which one out of 3 tour blocks is clicked.
var vidgetDiv = document.getElementById("wt_piersWidget");
var attApi = document.createAttribute("data-api-key");
var attId = document.createAttribute("data-tour-id");//creating attributes I need
switch(idCheck) {// trying to set data-tour-id to correc tour, for ex. 12
case '1':
attId.value="12";
vidgetDiv.setAttributeNode(attId);
console.log(vidgetDiv);
var btn = document.createElement("BUTTON"); //creating <button> element I need
btn.setAttribute("id", "widgetButton1"); //with id so I could find it later
btn.setAttribute("class", "wt-open"); //with class widget needs this button to have
document.body.appendChild(btn);
console.log(btn);
document.getElementById('widgetButton1').click(); // and clicking on that button
break;
case '2':
attId.value="13";
vidgetDiv.setAttributeNode(attId);
console.log(vidgetDiv);
var btn = document.createElement("BUTTON"); //creating <button> element I need
btn.setAttribute("id", "widgetButton2"); //with id so I could find it later
btn.setAttribute("class", "wt-open"); //with class widget needs this button to have
document.body.appendChild(btn);
console.log(btn);
document.getElementById('widgetButton2').click(); // and clicking on that button
break;
default:
attId.value="10";
vidgetDiv.setAttributeNode(attId);
console.log(vidgetDiv);
var btn = document.createElement("BUTTON"); //creating <button> element I need
btn.setAttribute("id", "widgetButton0"); //with id so I could find it later
btn.setAttribute("class", "wt-open"); //with class widget needs this button to have
document.body.appendChild(btn);
console.log(btn);
document.getElementById('widgetButton0').click(); // and clicking on that button
break;
</script>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- jquery 1.7.1-->
<script type="text/javascript" src="1.7.1/jquery.min.js"></script>
<!--------------->
<!-- link to a widget-->
<script src="/wt_widget/widget.js"></script>
<!--/link to a widget-->
I posted here only one block, but they are basicly same and go one after another.
I take the trouble of generating those div's on-the-fly, because just copypasting symple html code with different div attributes 3 times results in all buttons working only with attributes from first div, which is how it is supposed to happen, that I understand. I am just having trouble understanding why there is any difference to a widget in the example above. From my understanding, I am generating all I need only after I pressed first button, and it generates only 1 div with attributes for a tour, then a single button pressed, widget should not see difference between this and simple html example, as I see it. Initially I tried to change value of already existing , but it still opened widget with default values.
In your first code block everything makes sense, a button is defined in your html and then js widget script file runs, attaching click event. But when you do it by code, something needs to attach those click handlers. I mean, the script ran before those buttons where created.

Javascript modal that displays list that closes and returns to main html

Rather new to javascript, jquery and bootstrap, etc., so bear with me. I have a situation where I want to present a list of errors in a model dialog after the user hits a "validate" button. Got all the working - I am generating a list of objects that indicate to the user they need more work to the exact spot that needs additional data entry. I have the the DIV "id" that represents the field that needs more data (and each item will jump someplace different).I do not want a drop down list since there are be lots and lots of these items.
A few questions:
How do I go about jumping from the modal to the main html. I believe I have seen scrollIntoView mentioned in a few other posts as I was looking but will that hop to the DIV and also close the modal?
What construct should I use for the list? A list of scrolling button? The size of this can be quite large (hundreds) so it will need a scroll capability.
Finally, the app is "paged" with a next and prev buttons. I assume that will not be a problem from the aspect of jumping to a page not already displayed?
Here is the current modal code:
<script id="template-validation-error" type="text/x-handlebars-template">
<div id="validationErrorModal" class="modal">
<div class="message-container">
<div class="header">
Validation Errors
</div>
<div class="message">
The following fields are required:
</div>
<div class="center">
<input type="button" class="btn btn-solid-green btn-sm" onclick="fffdevice.validationErrorOk();" value="Done" />
</div>
</div>
</div>
</script>
and
showValidationError: function (fieldlist) {
settings.focusedField = $(':focus');
$("#validationErrorModal").detach();
$(".device-container").append(templates.validationerror({ fieldlist }));
$(".message-container input").focus();
},
validationErrorOk: function () {
$("#validationErrorModal").detach();
if (settings.focusedField) {
settings.focusedField.focus();
}
},
The field list is a list of objects that contain the id (field.id) of the DIV and also a description (field.fieldName) that I want to display.
Here is something I mocked up in paint...I am not sold on it but it show in a general sense what I am looking for:
I don't need a full solution rather, just want mechanisms I can use.
UPDATE
Just to help out anyone else in the future, using the info provided in the correct answer below I have a new code as follows:
<script id="template-validation-error" type="text/x-handlebars-template">
<div id="validationErrorModal" class="modal">
<div class="validation-container">
<div class="header" align="center">
Validation Errors
</div>
<div class="message">
<div class="scrolling-container" style="background-color: rgb(238, 238, 238); height:660px">
<div class="grid grid-pad">
{{#each fieldlist}}
<div class="row click-row" onclick="fffdevice.validationErrorFix('{{id}}');">
<div class="col-7-8 field-name">{{fieldName}}</div>
<div class="col-1-8">
<img class="pull-right" src="/mysite/Content/device/images/fix.png" style="width: 40px; position:relative; top: -5px;">
</div>
</div>
{{/each}}
</div>
</div>
</div>
<div><br/></div>
<div class="center">
<input type="button" class="btn btn-solid-green btn-sm" onclick="fffdevice.validationErrorOk();" value="Done" />
</div>
</div>
</div>
Then the Javascript for the onClick is:
validationErrorFix: function (id) {
$("#validationErrorModal").detach();
var x = document.getElementById(id);
x.scrollIntoView({
behavior: "smooth", // or "auto" or "instant"
block: "start" // or "end"
});
},
Which closes the dialog and jumps to the field. It looks like (I know this is ugly and I will clean it up later):
Bind the modal event to the validation code and show the modal if error(s) are found.
Display the modal with the list of errors using an html unordered list, inside the li element an anchor tag where the href attribute will have a value with the id that corresponds to the input field, all this done dynamically from your validation code.
Once an error in the list is clicked hide the modal using bootstrap $('#your-error-modal').modal('hide'); so the code would be something like this:
$('#your-error-modal').on('click', 'a.error-item', function(){
$('#your-error-modal').modal('hide');
});
I haven't tested this code, but if you're having issues with scrolling to the section of the input and closing the modal you can probably do something like this too:
$('#your-error-modal').on('click', 'a.error-item', function(e){ // use this method of onclick because your list will be created dynamically
e.preventDefault(); // prevent the default anchor tag action
var href = $(this).attr('href'); // grab the href value
$('#your-error-modal').modal('hide'); // close the modal first
scrollToDiv(href); // then take the user to the div with error with a nice smooth scroll animation
});
function scrollToDiv(location) {
$('html, body').animate({
scrollTop: $(location).offset().top
}, 2000);
}
Again this is untested code, but the idea is there.
For UX reasons you might also want to create a floating div or something where users can click on it and go back to the modal to continue reading your list of errors.

Categories

Resources