Appended button only works on first div appended to - javascript

I'm trying to get each button that is appened to ('avatar-container comment ng-scope'), to be fully functional. Currently, only the top button is the button that is functional, and I'm not sure exactly why. Here's my code :
Also, I've already tried using addEventListener, but I was still running into the same problem :(.
$(document).ready(function () {
var groupcomments = $('.group-comments') // Container "Group Comments" are in
$(groupcomments).ready(function () {
function ucall(user) {
window.open('derp.com/userid=' + user, 'popup', 'width=600', 'height=600')
};
if (groupcomments[0]) {
var comments = groupcomments[0].getElementsByClassName('avatar-container comment ng-scope') // This gathers all of the comments themselves
$.each(comments, function () { // (you know this) but, this is looping over each comment.
var user = $(this).find('a')[0].href.toString();
user = user.replace(/[^\d]/g, '')
$(this).append('<button id=btnn>Click</button>') // using $(this) (which i assume are the comments, it appends the button to the comment)
var btn = document.getElementById('btnn') // getting the button
$(btn).click(function () {
ucall(user) // when button is clicked, call ucall function.
})
})
}
})
})
I commented in everything that should be useful, the button being appended worked, but it being clicked does not. Only on the first one appended. I'm just stuck right here.

You are adding a button <button id=btnn">Click</button> inside a loop. This means that you are adding several buttons all with the same ID. So, when you call document.getElementById('btnn'), you are only getting the first match in the list of buttons with the same ID.
You are only allowed to have one element with an ID. IDs are unique.

Related

Loop through gallery images as links not console logging onclick, but becoming active via css

I am trying to loop through a gallery of gradient swathes, to highlight them so they can be edited back in the main image, but hitting a roadblock when clicking them to test they are working. They are in a bootstrap row, as col-md-3's, and each swatch bg has an id of bg-gradient (row id is gallery). The below code works in as much as they become active via the css when hovered, but wont console log a test message on click.
html structure is a bootstrap row with id of "gallery", then 4 col-md-3's with id of "swatch", then the actual bg-gradient is what is being looped through. These become active on hover via css settings not via the JavaScript, but wont console log test message on click.
Demo
Code:
editSwatch() {
let swatchs = document.querySelectorAll('swatch'),
//let swatchs = document.getElementById('gallery'),
links = swatchs.getElementsByTagName('bg-gradient'),
i;
for (i = 0; i < links.length; i += 1) {
links[i].addEventListener('click', function () { console.log('click works') });
}
Updated code as per comments below, but still exactly the same result, tried tagName on the links var and still same.
Seems to be finding the swatches, but not working on click.
Need to get that click working to carry on?
Any tips welcome.
Thanks.
You can not keep same id for swatchs, also you can use below query selector with appropriate selector as parameter and loop through swatchs
var swatchs= document.querySelectorAll(".swatchs");
Technically onclick needs to be a function instead. Currently you are passing the return value of console.log() which is undefined I believe. A function needs to be attached to click event in order to make it work.
You can use addEventListener as the following:
links[i].addEventListener('click', function () { console.log('click works') });
Please see a working example how to attach a click event to a <div>:
const div = document.getElementById('elem');
div.addEventListener('click', function () { console.log('hey hello'); });
<div id="elem">Click me!</div>
I hope this helps!

Jquery remove item from localstorage if the link is already clicked

I have a page with a few filters for search results. These filters are links and upon clicking, I am adding the id to localstorage. When the page reloads it looks in the localstorage if the id of the link exists, it modifies the css of that particular link. I am able to achieve this.
Now, when the same link is clicked again, I need to be able to remove the id of the link from localstoarage so it does not change the css when the page reloads.
Before Clicking
After clicking
Here is my code. Some kind people from StackOverflow helped me get this piece of code together. I need it to extend. Please let me know if any of this doesn't make sense. Would gladly rewrite my sentences.
$(document).ready(function() {
//localStorage.clear();
var cached = localStorage.getItem('filters');
var filters = (cached) ? JSON.parse(cached) : {};
for (id in filters) {
$('#' + id).addClass('li-checked');
}
$('.li-filter').click(function(e) {
//event.preventDefault();
$(e.target).addClass('li-checked');
$(e.target).removeClass('li-unchecked');
var id = $(e.target).attr('id').toString();
if (filters[id]) {
filters[id] += 1;
//filters = $.grep(filters, function(e) { return e.id!=id });
} else {
filters[id] = 1;
}
console.log(JSON.stringify(filters));
localStorage.setItem('filters', JSON.stringify(filters));
});
});
#Rohit If I understood your question correctly, onclick you have to add a class and remove it in case it is already clicked.
For this scenario, I will suggest writing functionality to toggle classes that can help.
You need to get class on the element while li is clicked.
if($(e.target).attr("class").contains("li-checked"))
{
$(e.target).removeClass('li-checked');
$(e.target).addClass('li-unchecked');
}
else if((e.target).attr("class").contains("li-unchecked"))
{
$(e.target).removeClass('li-unchecked');
$(e.target).addClass('li-checked');
}
If the class is 'li-checked' then remove it and add 'li-unchecked'
and if the class is 'li-unchecked' then remove it and add 'li-checked'
I hope it helps.

How to store JS slideToggle in localStorage only for clicked button

I have several buttons including divs which they have the same name. unfortunately I can not change the names, they are generated by cms.
So for example when I click only on first button, only the first div is hidden or displayed, and that's fine.
But after refresh page it opens or closes all divs depending is the first div closed or opened, and that I do not want it.
here is the code:
<button class="a">Button</button>
<div class="target"></div>
<button class="a">Button</button>
<div class="target"></div>
$('.a').click(function() {
$(this).next(".target").slideToggle(function() {
localStorage.setItem('visible', $(this).is(":visible"));
});
});
$('.target').toggle(localStorage.getItem('visible') === 'true');
here you can see jsfiddle example: https://jsfiddle.net/pj3gs0z9/3/
So my question is, is it possible to store only clicked button information, and after page refresh display or hide div from only clicked button ?
Thank you
It is possible, but probably not in your case. If you tell us you can't change your button properties, and they are exactly the same, then you won't be able to store different data in your localStorage.
Isn't there any way where you can add some additional information to your button ? It could be a class, an id, a name, or even a data-XXX attribute.
By the way, how are your buttons generated ? are they hard coded, or fetched from a database, or ... ?
EDIT
Here is a way of adding different classes to all of your buttons (althoguh I recommend adding data attributes, but whatever floats your boat) :
let buttons = document.getElementsByTagName('button'); // Array of your buttons
let index = 0;
for (let button of buttons) {
button.className += 'myCustomClass-' + ++index; // Add a custom class to your buttons
}
// Now in your local storage, you can store the class of the button !
EDIT 2 I would store it like this :
// On click, in VanillaJS (sorry, haven't used JQuery in a while)
button.onclick = () => {
let visibleButtons = localStorage.getItem('visible-buttons') || [];
visibleButtons.push(button.className.match(/(myCustomClass-[0-9]*)/)[0]);
}
This is one quick solution, but because of a slideToggle you gonna have a small flash of milliseconds of a visible div unless you first have them hidden and then based on localStorage display them.
$('.a').click(function() {
$(this).next(".target").slideToggle(function() {
localStorage.setItem('visible-' + $(this).index(), $(this).is(":visible"));
});
});
$.each($('.target'), function(k, trg) {
$(trg).toggle(localStorage.getItem('visible-' + $(trg).index()) === 'true');
});

CasperJS click is leads to error even when the element exists

I'm trying to click on a logout button, which I have retrieved from the current page. I successfully got the id of the logout link. But when I click on it, an error occurs
Cannot dispatch mousedown event on nonexistent selector
function getLogoutId()
{
var logoutid = "";
$(document).find("a").each(function(key,value){
var id = $(this).attr("id");
if(id.toLowerCase().indexOf("logout") > -1)
{
__utils__.echo("insidelogout" + id);
logoutid = id;
}
});
return logoutid;
}
var logoutid = this.evaluate(getLogoutId);
fs.write("logout.txt", this.getHTML(), 'w');
this.thenClick("#"+logoutid, function(){});
I have written the html content to a file, in which I checked for the id and it is there. The id attribute in question looks like this:
et-ef-content-ftf-flowHeader-logoutAction
I see nothing wrong with your code aside from strange usage of jQuery.
You can try other CSS selectors for clicking:
casper.thenClick("[id*='logout']"); // anywhere
or
casper.thenClick("[id$='logoutAction']"); // ending
or
casper.thenClick("[id|='logoutAction']"); // dash-separated
Maybe it is an issue with the code that follows the shown code. You can try to change thenClick to click.
Have you tried using just this.click("#"+logoutid);?
Also have you considered using jQuery to click on the button? Something like this...(first make a variable of your id so you can pass into jQuery).
var id = "#"+logoutid;
this.evaluate(function(id){
jQuery(id).click();
},id);

casperjs: how do I click a remote div and then update it's class name?

As a way of learning CasperJS, I am trying to initiate a click event on a div on a remote page, and then change the class name of the div after I have clicked it. The idea is to find the first clickable div, click it, and then mark it as clicked so I can skip over it to other clickable divs. The markup for the div tag on the remote page looks like:
<div class='clickable_div'></div>
I have tried the following casperjs code:
...
casper.then(function() {
if( this.exists( 'div.clickable_div' ) ) {
this.evaluate(function() {
this.click(document.querySelector('div.clickable_div'));
return document.querySelector('div.clickable_div').setAttribute("className","clicked");
});
}
});
...
It doesn't seem to work. First, I don't think I am initiating the mouse click event on the div correctly. What am I missing? Second, when I fetch the updated html, I don't see any changes in the div's class name. Am I going about this step in the wrong way?
You're calling this.click within evaluate(), it just can't work as evaluate() executes code within the page DOM context where there's probably no window.click method.
Here's a possibly working script:
var linkSelector = 'div.clickable_div';
casper.then(function() {
if (!this.exists(linkSelector)) return;
this.click(linkSelector);
this.evaluate(function(linkSelector) {
__utils__.findOne(linkSelector).setAttribute("className", "clicked");
}, linkSelector);
});
You may want to have better handling of errors and edge cases, but you get the idea.

Categories

Resources