I am using the below code in the google tag manager custom JavaScript variable, but it returns same index value for every line item, what can be the issue?
Web page link: https://www.amity.edu/programe-list.aspx?fd=all
function() {
var elements = document.querySelectorAll('.staff-container');
for (var i = 0; i < elements.length; i++){
(function(index){
elements[i].children[0].children[0].addEventListener("click", myScript);
function myScript(){
return("Clicked : ",index);
}
})(i);
}
}
There is an error in the 5th line.
It should be elements[index].children... in that case.
The updated code:
function() {
var elements = document.querySelectorAll('.staff-container');
for (var i = 0; i < elements.length; i++){
(function(index){
elements[index].children[0].children[0].addEventListener("click", myScript);
function myScript(){
return("Clicked : ",index);
}
})(i);
}
}
Here is an alternative way from Simo's blog
Blog link
Although the post is say about visibility element. I test it with click on my website.
This might work
function() {
var list = document.querySelectorAll('.staff-container a'),
el = {{Click Element}};
return [].indexOf.call(list, el) + 1;
}
If it is not working, you might need to provide the screenshot about the click element from your GTM preview.
Related
I have a script that I'm running to detect a line break in a flex-wrapped UL.
I have this javascript function at the top of my scripts.js file outside of the $(document).ready call.
var detectWrap = function(className) {
var wrappedItems = [];
var prevItem = {};
var currItem = {};
var items = document.getElementsByClassName(className);
for (var i = 0; i < items.length; i++) {
currItem = items[i].getBoundingClientRect();
if (prevItem && prevItem.top < currItem.top) {
wrappedItems.push(items[i]);
}
prevItem = currItem;
};
return wrappedItems;
}
Inside of a $(document).ready call, I have this:
$( ".menu-item-has-children" ).click(function() {
var wrappedItems = detectWrap('menu-item-object-practice-area');
for (var k = 0; k < wrappedItems.length; k++) {
wrappedItems[k].className = "wrapped";
}
});
If I load the page and click the "Practice Areas", I get nothing. If I open up the console and drop in the following it works fine:
var wrappedItems = detectWrap('menu-item-object-practice-area');
for (var k = 0; k < wrappedItems.length; k++) {
wrappedItems[k].className = "wrapped";
}
I'm assuming this has something to do with the timing and/or what is loaded up but I'm not adding content into the DOM...I'm just adding a class.
For reference, here is the site: https://myersbrierkelly.djykrmv8-liquidwebsites.com/
When you click the drop-down menu, two separate event handlers respond:
Yours, to measure for wrapped items
The library you're using, to toggle the display of the submenu
However, as there is nothing to manage the order of these, what ends up happening is that your wrap-detector runs before the submenu is shown, and if the submenu isn't shown yet then you can't measure getBoundingClientRect() since it doesn't exist. A simple console.log(currItem) would have revealed this.
If you can't guarantee the order of events (which may well be the case when using a library), then you should delay your code by a frame.
$(".menu-item-has-children").click(function() {
requestAnimationFrame(function() {
var wrappedItems...
});
});
This is supposed to be a very simple dropdown FAQ system, I know how to do this in jQuery but I want to learn plain JS.
I just want the individual clicked triggers to toggle the is-visible class to the content divs next to the clicked trigger. Like $(this).next addClass — just in JS.
I've really tried to search for this issue but 90% that shows up is how to do it in jQuery :-p
https://jsfiddle.net/48ea3ruz/
var allTriggers = document.querySelectorAll('.faq-trigger');
for (var i = 0; i < allTriggers.length; i++) {
// access to individual triggers:
var trigger = allTriggers[i];
}
var allContent = document.querySelectorAll('.faq-content');
for (var i = 0; i < allContent.length; i++) {
// access to individual content divs:
var content = allContent[i];
}
// I don't know how to target the faq-content div next to the clicked faq-trigger
this.addEventListener('click', function() {
content.classList.toggle('is-visible');
});
Would really appreciate some advice! :-)
Use nextSibling, when you are iterating .faq-trigger
var allTriggers = document.querySelectorAll('.faq-trigger');
for (var i = 0; i < allTriggers.length; i++) {
allTriggers[i].addEventListener('click', function() {
this.nextSibling.classList.toggle('is-visible');
});
}
nextSibling will also consider text-nodes, try nextElementSibling also
var allTriggers = document.querySelectorAll('.faq-trigger');
for (var i = 0; i < allTriggers.length; i++) {
allTriggers[i].addEventListener('click', function() {
this.nextElementSibling.classList.toggle('is-visible');
});
}
Having an issue with a for loop in jQuery only running once. Users is a array containing 4 items, and for each, it should append that item as a list element to userList, which is a ul. It appends the first element in the array as expected, but only that one. Not sure why it isn't running through the entire array?
$(document).ready(function() {
var $currentUser = $('<li class="user"></li>');
for(var i = 0; i < users.length; i++) {
$currentUser.text(users[i]);
$currentUser.appendTo('.userList');
}
//alert(users.length) returns "4".
});
Try this
$(document).ready(function(){
for(var i = 0; i < users.length; i++) {
var $currentUser = $('<li class="user"></li>');
$currentUser.text(users[i]);
$currentUser.appendTo('.userList');
}
});
You're overwriting the element, instead of creating a new one for each user. Try the code above.
More jQuery'ish
$('.userList').append(function() {
return $.map(users, function(user) {
return $('<li />', {
'class' : 'user',
text : user
})
});
});
FIDDLE
You aren't adding a new <li> for each iteration:
Here's a working solution:
for (var i = 0; i < users.length; i++) {
$('<li class="user"></li>'
.text(users[i])
.appendTo('.userList');
}
https://jsfiddle.net/2abqa5us/1/
You create the li on the outside of the loop, then try to set the text of the same element to each user so you will overwrite it every iteration. Are you sure the last entry is not the one you see?
.text will overwrite previous text which looks like you got one users only
try this.
$(document).ready(function(){
for(var i = 0; i < users.length; i++) {
var $currentUser = $('<li class="user"></li>');
$currentUser.text(users[i]);
$currentUser.appendTo('.userList');
}
});
I have generated a dynamic html table using java script. Now I need to get the css class of the cell clicked by the user.
How am I supposed to do this?
Here is the code:
function generateSeatMatrix() {
var rows = parseInt(document.getElementById('txtRows').value);
var cols = parseInt(document.getElementById('txtCols').value);
if (!validateMatrixInput(rows, cols)) {
// TODO display error message
return;
}
var matrixTable = document.getElementById('tblMatrix');
if (matrixTable.rows.length > 0) {
for (var k = matrixTable.rows.length - 1; k >= 0; k--) {
matrixTable.deleteRow(k);
}
}
for (var i = 0; i < rows; i++) {
matrixTable.insertRow(i);
for (var j = 0; j < cols; j++) {
matrixTable.rows[i].insertCell(j);
matrixTable.rows[i].cells[j].className = 'matrix-cell';
matrixTable.rows[i].cells[j].setAttribute('onclick', 'hello()');
}
}
}
The 'hello()' function is supposed to handle the required logic. Right now, the function is called properly but I have no idea how to get the selected cell css class. Actually, i tried to send the position as declaring the event (using setAttribute), but then an error raised.
I see you are trying to add a onclick as you built but if you create some jquery like so you can do it. But you would have to have jQuery loaded. Although if you are building this dynamically you may need to use $('document').find('td'). This may not be the solution you are looking for but will get the job done.
$('td').on('click', function(){
var myClass = this.className;
})
Tried adding in comment but wouldn't show code view.
Here is how easily this could be handled..
matrixTable.rows[i].cells[j].setAttribute('onclick', 'hello(' + i + ',' + j + ')');
Well done!
I have an array of image .png files and a matching array of .mp3s. Clicking on the image should play the audio by passing the index from one array to the other, however I am getting the "undefined" error for the last line.
$(document).ready(function () {
var starting_pics = ["CN.gif", "EN.gif", "GN.gif"];
var starting_sounds = ["CN.mp3", "EN.mp3", "GN.mp3"];
var i = 0;
for (i = 0; i < starting_pics.length; i++) {
$("<img/>").attr("src", "images/" + starting_pics[i]).load(function () {
$(this).appendTo("#main");
$(this).addClass("pics");
});
}
for (i = 0; i < starting_sounds.length; i++) {
$("<audio/>").attr("src", "audio/" + starting_sounds[i]).load(function () {
$(this).appendTo("#main");
$(this).addClass("sound");
});
}
$("#main").on("click", ".pics", function () {
var i = $(this).index();
alert(i);
$(".sound").get(i).play();
});
});
The elements are not properly appended by using .load(), do the following modifications.
for (i = 0; i < starting_pics.length; i++) {
$("<img/>").attr("src", "" + starting_pics[i])
.appendTo("#main")
.addClass("pics");
}
for (i = 0; i < starting_sounds.length; i++) {
$("<audio/>").attr("src", "" + starting_sounds[i])
.appendTo("#main")
.addClass("sound");
}
UPDATE:
That version of .load() is deprecated since jQuery 1.8 - use $("selector").on("load, func.... And make sure you bind the load event before you set the src attribute - some browsers will fire the load event immediately when the `src is set, if it's been cached.
In addition, <audio> elements don't seem to have a load event. That's why the elements weren't being found - the load event never executed, so they weren't appended. The events you want to look into are canplay or canplaythrough, or something from this list: https://developer.mozilla.org/en-US/docs/Web/Guide/DOM/Events/Media_events