How can i target appended items one by one in javascript? - javascript

I created a simple new tab page similar to web browsers, but when I create a new tab and press the x icon to triger closetab() it closes all the tabs and does not delete them in order one by one. How do i make each of appended items unique?
JS:
function addTab() {
var img = document.createElement("img");
img.src = "resources/img/delete-icon.svg";
img.className = 'deleteicon';
img.id = "deletetab";
img.onclick = closeTab;
var ulLocation = document.getElementsByClassName('abc')[0];
var whereTab = document.getElementById('listid');
var addTab = document.createElement('li');
addTab.className = 'first-tab';
addTab.id = "listid";
addTab.className = 'active';
addTab.innerHTML = "mozilla-firefox/newtab";
addTab.appendChild(img2);
ulLocation.appendChild(addTab);
addTab.appendChild(img);
}
function closeTab() {
var whereTab = document.getElementById('listid');
if (whereTab.style.display == 'block') {
whereTab.style.display = 'none';
} else {
whereTab.style.display = "none";
}
}

You have at least 2 options. One is to target the active tab and close it when the X is clicked. This is assuming you only have one active tab at a time (denoted by an active class for example).
function closeTab(event) {
document.querySelector('li.tab.active').remove();
}
Another option is to reference the tab relative to the close icon, which you can reference in the event argument of your click listener. Since you're adding these dynamically, you can just remove them with the delete click rather than hide. Something like:
function closeTab(event) {
event.target.closest('li.tab').remove();
}
In these examples, you have set a className for your tab containers to be tab

Related

Mapbox GL JS toggle layers forces a double click on initial event

I am trying to recreate the Mapbox GL JS toggle example here:
https://docs.mapbox.com/mapbox-gl-js/example/toggle-layers/
In the example, when you click on the button it immediately changes its state to non-visible and turns the layer off. In my code you have to initially click on the button twice to get it to change to non-visible and turn the layer off and after that the button behaves normally. Any suggestions on how to get it so you only have to click once initially? This is the section of the code I think is problematic:
for (const id of toggleableLayerIds) {
// Skip layers that already have a button set up.
if (document.getElementById(id)) {
continue;
}
// Create a link.
const link = document.createElement('a');
link.id = id;
link.href = '#';
link.textContent = id;
link.className = 'active';
// Show or hide layer when the toggle is clicked.
link.onclick = function (e) {
const clickedLayer = this.textContent;
e.preventDefault();
e.stopPropagation();
const visibility = map.getLayoutProperty(
clickedLayer,
'visibility'
);

Setting a onClick function to a dynamically created button, the function fires onload

I am currently creating a program which utilizes localStorage to create a site with a wishlist like functionality. However when I go to generate the html page that should create the wishlist with the photo of the item, the name and a button to remove said item from the list. But when I go to assign the onClick functionality to the button, the function fires on page load rather then on click. I have four main java script functions, one to add to the localstorage, one to remove from local storage, a helper function for removing and the one that will generate the wishlist page (where the problem is).
function genWishListPage(){
for (var i = 0; i < localStorage.length; i++) {
var item = getWishlist(i);
var name = document.createElement("p");
var removeButton = document.createElement("button");
var image = document.createElement("img")
image.src = item.image;
removeButton.innerText = "Remove from wishlist";
removeButton.onClick = RemoveFromWishList(item.name);
removeButton.setAttribute("ID","remove");
name.innerText = item.name;
document.body.appendChild(image);
document.body.appendChild(name);
document.body.appendChild(removeButton);
document.body.appendChild(document.createElement("BR"));
//removeButton.setAttribute("onclick", RemoveFromWishList(item.name));
//removeButton.addEventListener('click', RemoveFromWishList(item.name));
//document.getElementById("remove").addEventListener("click",RemoveFromWishList(item.name));
}
}
The commented parts are ways I have already tried and gotten the same bug.
Any help or advice is appreciated.
When you write
removeButton.onClick = RemoveFromWishList(item.name); you are assigning the return value of the function call to the onClick event. Instead you can write
removeButton.onClick = function() { RemoveFromWishList(item.name);}
You should assign a function to the onClick event listener.

make an absolute div hidden when something outside of it is clicked

I have some code for the function that runs when a button is clicked in my site:
function shadow() {
document.getElementById("overlay").style.visibility="visible";
document.getElementById("dim").style.visibility="visible";
document.getElementById("dim").onclick="document.getElementById('dim','overlay').style.visibility='hidden'";
}
With overlay being the overlay div that I want to be re-hide-able, and dim being the lower z-index dimmer over the entire page when the function runs.
The third line is my attempt at making it so that when an area outside of the overlay is clicked, the dim and overlay go away - help on that would be great!
The onclick property expects a function reference, not a string. In addition, the getElementById method only accepts a single id parameter, which means that only the first element id that you passed to it would be selected.
Based on the code you provided, it looks like you want something like this (live example):
function shadow() {
var overlay = document.getElementById('overlay');
var dim = document.getElementById('dim');
overlay.style.visibility = 'visible';
dim.style.visibility = 'visible';
dim.onclick = function() {
overlay.style.visibility = 'hidden';
dim.style.visibility = 'hidden';
};
}
Alternatively, you could also add a click event listener to document and then determine whether event.target is the #overlay element.
For instance, the following would work (live example):
document.addEventListener('click', function (event) {
var overlay = document.getElementById('overlay');
var dim = document.getElementById('dim');
if (event.target !== overlay && !event.target.closest('#overlay')) {
overlay.style.visibility = 'hidden';
dim.style.visibility = 'hidden';
}
});

dynamically added button on click not working

I'm building a function in my own image browser that creates and displays a delete button when the user hovers the cursor over a certain image's div and hides the button when the user hover the mouse out of the div.
this is the code:
function displayImages() {
//run through array of images
for (a = 0; a < images.length; a++) {
var container = document.createElement('div');
container.id = 'container'+images[a];
container.style.width = 120;
container.style.backgroundColor = '#e9e9e9';
container.style.height = 140;
container.style.margin = 5;
container.style.display = 'inline-block';
container.style.float = 'left';
var imageID = images[a];
container.onmouseover = function() {imageRollover(this)};
container.onmouseout = function() {imageMouseOut(this)};
}
}
function imageRollover(image) {
var trashcan = document.createElement('BUTTON');
trashcan.id = 'trash'+image.id;
trashcan.className = 'deleteButton';
trashcan.onclick = function() {deleteImage(image.id);};
document.getElementById(image.id).appendChild(trashcan);
}
function imageMouseOut(image) {
document.getElementById(image.id).removeChild(document.getElementById('trash'+image.id));
}
function deleteImage(image) {
alert(image);
}
My problem is, that when I click trashcan, it calls nothing. I already tried to add the onlick event normally:
trashcan.onclick = deleteImage(image.id);
But then, for some reason, is calls the function when I hover my mouse over the container.
How do I make sure that on click events for dynamically added rollover buttons work?
The function can de viewed on: http://www.imaginedigital.nl/CMS/Editor/ImagePicker.html or http://jsfiddle.net/f239ymos/
Any help would be highly appreciated.
You are forcing me to guess here(not giving a fiddle), and create a scenario of my own but from what I understand, you want a button to appear no hover, and when pressed to delete the image so here its a working fiddle
hover functionality
$((document.body).on('mouseenter', '.test', function(){
console.log('here');
$(this).children('.test .x_butt').show();
});
$(document.body).on('mouseleave', '.test', function(){
$('.test .x_butt').hide();
});
remove functionality
$(document.body).on('click', '.x_butt', function(){
$(this).parent().remove();
});
P.S. as for your dynamically added divs issue, the $(selector1).on('click','selector2', function() {...}); deals with it, as long as selector1 is not added dynamically. (selector2 would be the div you want the function to be on) demo with dynamically added elements ( click clone )
First change
window.onload = loadImages(); to window.onload = loadImages;
Then since you pass an object you can change
function imageMouseOut(image) {
document.getElementById(image.id).removeChild(document.getElementById('trash'+image.id));
}
to
function imageMouseOut(image) {
image.removeChild(image.childNodes[0]);
}
However why not just hide and show the trashcan? Much cleaner

Trying to generate a button-based interface in javascript

I am trying to build an interface with javascript. The interface is a grid of buttons. Each row is a different musical instrument and on each column you have a rhythm pattern you can trigger.
When the user click on a button, I want it to change its class so the background-color changes, telling to user it's been activated.
The problem is, my script is always targeting the last button of a row. When I try to force it to target a specific button (which is NOT the last button), it says the button in "undefined".
pattern1 = ["Clave 1",[1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0],"description"];
pattern2 = ["Clave 2",[1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,0,1],"description"];
pattern3 = ["Clave 3",[1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1],"description"];
pattern4 = ["Clave 4",[1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0],"description"];
pattern5 = ["Clave 5",[1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1],"description"];
pattern6 = ["Clave 6",[1,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0],"description"];
pattern7 = ["Clave 7",[1,0,1,1,1,0,1,1,1,1,0,1,1,1,0,1,1,1,1,0,1,1,1,0,1,1,1,1,0,1,1,1],"description"];
pattern8 = ["Clave 8",[1,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0],"description"];
var pattern_collection = [pattern1, pattern2, pattern3, pattern4, pattern5, pattern7, pattern8];
function generate_buttons(instrument_id) {
for (var key in pattern_collection)
{
//creating an array of button for each instrument
var button = new Array();
//creating the button label
var button_text;
button_text = document.createTextNode(pattern_collection[key][0]);
//creating the button in the DOM
button[key] = document.createElement('div');
//by default, the first pattern is shown as playing
if (pattern_collection[key]==pattern1)
button[key].className = "isplaying_pattern_button";
else
button[key].className = "notplaying_pattern_button";
button[key].onclick = function() {
//picking the currently playing button to change its class to not playing
var playing_button = document.querySelector("#"+instrument_id+" .isplaying_pattern_button");
playing_button.className = "notplaying_pattern_button";
//this is where the problem occurs: the script is always targeting the last button of the row
button[key].className = "isplaying_pattern_button";
};
button[key].appendChild(button_text);
var instrument_patterns = document.getElementById(instrument_id);
instrument_patterns.appendChild(button[key]);
}
}

Categories

Resources