jQuery function .one is not woking - javascript

Every time I click the add icon, the addFunction() in javascript file invokes. And each time the function invokes, it attaches a click function to the unordered list.
To avoid attachment of multiple click functions I used .one instead of .on but this approach is not working.
HTML:
ul#classesAndSubjectsList
each value, index in user.classesAndSubjects
li !{value}
a.ml-4#classesAndSubjects(href='javascript:;')
i.fa.fa-plus(aria-hidden="true")
Javascript:
addFunction = function() {
const txt = prompt(promptMsg1, promptMsg2);
if (!(txt == null || txt == "")) {
const i = document.createElement("i");
i.classList.add("fa");
i.classList.add("fa-times");
i.classList.add('red-cross');
const a = document.createElement("a");
a.classList.add("ml-4");
a.append(i);
const t = document.createTextNode(txt)
const newItem = document.createElement("li");
newItem.append(t);
newItem.append(a);
var final = $("ul#classesAndSubjectsList");
// No idea why .one is not working
final.one('click', 'li a', function () {
//other code
});
$(final).append(newItem);
}
}
$("a#classesAndSubjects").click(function(){
addFunction();
});

Related

Javascript create looping variables

my javascript variables
var select1 = document.getElementById('status-kehadiran1');
select1.onchange = function () {
select1.classList.remove("hijau");
select1.classList.remove("merah");
select1.classList.add(this.options[this.selectedIndex].className);
}
var select2 = document.getElementById('status-kehadiran2');
select2.onchange = function () {
select2.classList.remove("hijau");
select2.classList.remove("merah");
select2.classList.add(this.options[this.selectedIndex].className);
}
var select3 = document.getElementById('status-kehadiran3');
select3.onchange = function () {
select3.classList.remove("hijau");
select3.classList.remove("merah");
select3.classList.add(this.options[this.selectedIndex].className);
}
var select4 = document.getElementById('status-kehadiran4');
select4.onchange = function () {
select4.classList.remove("hijau");
select4.classList.remove("merah");
select4.classList.add(this.options[this.selectedIndex].className);
}
var select5 = document.getElementById('status-kehadiran5');
select5.onchange = function () {
select5.classList.remove("hijau");
select5.classList.remove("merah");
select5.classList.add(this.options[this.selectedIndex].className);
}
var select6 = document.getElementById('status-kehadiran6');
select6.onchange = function () {
select6.classList.remove("hijau");
select6.classList.remove("merah");
select6.classList.add(this.options[this.selectedIndex].className);
}
var select7 = document.getElementById('status-kehadiran7');
select7.onchange = function () {
select7.classList.remove("hijau");
select7.classList.remove("merah");
select7.classList.add(this.options[this.selectedIndex].className);
}
var select8 = document.getElementById('status-kehadiran8');
select8.onchange = function () {
select8.classList.remove("hijau");
select8.classList.remove("merah");
select8.classList.add(this.options[this.selectedIndex].className);
}
var select9 = document.getElementById('status-kehadiran9');
select9.onchange = function () {
select9.classList.remove("hijau");
select9.classList.remove("merah");
select9.classList.add(this.options[this.selectedIndex].className);
}
var select10 = document.getElementById('status-kehadiran10');
select10.onchange = function () {
select10.classList.remove("hijau");
select10.classList.remove("merah");
select10.classList.add(this.options[this.selectedIndex].className);
}
is there a way to create a looping for those variable to make it more simple?
my html select elements
because i have 10 select element with different id
view
the purpose of each variable is to change the text color of each select when there is a change of selected option
i hope you can understand my explanation
Don't use IDs, use a common selector instead for all of those selects - such as [name^="pertemuan"] (name attribute starts with pertemuan):
for (const select of document.querySelectorAll('[name^="pertemuan"]')) {
select.addEventListener('change', () => {
select.classList.remove("hijau", "merah");
select.classList.add(select.options[select.selectedIndex].className);
});
}
You could drop the ids and move status-kehadiran to the selects class list. The you can select all of them with .querySelectorAll() and loop over them with .forEach()
document.querySelectorAll('.status-kehadiran')
.forEach(function(select) {
select.addEventListener('change', function() {
this.classList.remove('hijau', 'merah');
this.classList.add(this.selectedOptions[0].className);
});
});
As mentioned by others you can use query selector with name and ids, but you can also assign them a common class and use -
document.getElementsByClassName('.name of class')
.forEach(function(select) {
select.addEventListener('change', function() {
this.classList.remove('hijau', 'merah');
this.classList.add(this.selectedOptions[0].className);
});
});
You can first select all the elements with ids using Document.querySelectorAll() and then loop through them and attach the event (change) one by one using EventTarget.addEventListener().
You can try the following way:
//you can select by exact id
//var sel = document.querySelectorAll('#status-kehadiran1, #status-kehadiran2, #status-kehadiran3, #status-kehadiran4, #status-kehadiran5, #status-kehadiran6, #status-kehadiran7, #status-kehadiran8, #status-kehadiran9, #status-kehadiran10');
//you can select by id startsWith selector by matching the common part of each id
var sel = document.querySelectorAll('[id^=status-kehadiran]');
sel.forEach(function(el){
el.addEventListener('change', function(){
el.classList.remove("hijau", "merah"); //you can remove multiple class separating them with comma
el.classList.add(el.options[el.selectedIndex].className);
});
});

TamperMonkey EventListener on button not working

I created this snippet:
function addClick(button, container) {
console.log("In add click");
const data = container.nextElementSibling.childNodes[0].innerHTML;
button.addEventListener('click', ()=>{
alert('clicked')
console.log("Clicked");
})
}
function createCopyButtons(array){
array.forEach(element => {
const container = document.createElement('div');
const button = document.createElement('button');
button.innerHTML = "Copy"
styleContainer(container);
styleButton(button, element);
stylePrevious(element);
container.innerHTML = element.outerHTML + button.outerHTML;
element.parentNode.replaceChild(container, element);
addClick(button, container);
});
}
Now in here the array is the array of DOM elements I want this property to apply and I call the createCopyButtons() function down with some more stuff. Now the thing is that this event listener does not apply or does not work. I tried to wait till the document is loaded by these answers and only then apply my javascript snippet but the event listener doesn't seems to work.
document.addEventListener("DOMContentLoaded", function(event) {
//do work
});
if (document.readyState == "complete") {
// document is ready. Do your stuff here
}
Please help.
update:
function addClick(button) {
button.addEventListener('click', ()=>{
console.log("Clicked");
})
}
let p = document.querySelectorAll('p');
// innerHTML not work
let btn1 = document.createElement('button');
btn1.innerHTML = "Not work";
p[0].innerHTML = btn1.outerHTML;
addClick(btn1)
// work
let btn2 = document.createElement('button');
btn2.innerHTML = "work";
p[1].appendChild(btn2);
addClick(btn2)
<p></p>
<p></p>
because you append the button to the container using string (.innerHTML) not DOM or using appendChild()
container.innerHTML = element.outerHTML + button.outerHTML
the following function will not apply the event
addClick(button, container);
I don't know why you need to wrap target element and the button inside div, why not just append the button after target element using or insertBefore() or insertAdjacentHTML() but below is working code that follow yours.
it find the button inside the container for using as addClick() parameters
function addClick(button, container) {
console.log("In add click");
const data = container.nextElementSibling.childNodes[0].innerHTML;
button.addEventListener('click', () => {
alert('clicked')
console.log("Clicked");
})
}
function createCopyButtons(array) {
array.forEach(element => {
const container = document.createElement('div');
let button = document.createElement('button');
button.innerHTML = "Copy"
container.innerHTML = element.outerHTML + button.outerHTML;
element.parentNode.replaceChild(container, element);
let btn = container.querySelector('button'); // <== find the button
addClick(btn, btn.parentNode);
});
}
createCopyButtons(document.querySelectorAll('input'))
<div>
<input type="text">
<p><span>test</span></p>
</div>

Javascript - Click event dosen't work on dynamically added elements

How can I run an event on dynamically added elements, because my click event doesn't work on new elements.
I found some answer in here but all about jQuery so I'm coding with vanilla javascript. So do you have any advice ?
document.querySelectorAll('.galeri-cart').forEach(function (cart) {
cart.addEventListener('click', function () {
// something awesome happening in here
})
});
creating element codes;
success: function () {
let imageData = JSON.parse(this.files[i].xhr.response);
let img = document.createElement('img');
img.setAttribute('src', imageData.url);
img.setAttribute('data-id',imageData.id);
img.setAttribute('alt', imageData.alt);
let subDiv = document.createElement('div');
subDiv.className = "galeri-cart";
subDiv.appendChild(img);
let midDiv = document.createElement('div');
midDiv.className = "col-md-4";
midDiv.appendChild(subDiv);
let div = document.querySelector('.row');
div.insertBefore(midDiv, div.childNodes[0]);
i++
}
Since you are adding the elements to the DOM manually, you can simply attach the event listener after you create the element and before you append it to the DOM, like so:
function galeriClickHandler () {
// something awesome happening in here
}
success: function () {
let imageData = JSON.parse(this.files[i].xhr.response);
let img = document.createElement('img');
img.setAttribute('src', imageData.url);
img.setAttribute('data-id',imageData.id);
img.setAttribute('alt', imageData.alt);
let subDiv = document.createElement('div');
subDiv.className = "galeri-cart";
// add event listener here
subDiv.addEventListener('click', galeriClickHandler);
subDiv.appendChild(img);
let midDiv = document.createElement('div');
midDiv.className = "col-md-4";
midDiv.appendChild(subDiv);
let div = document.querySelector('.row');
div.insertBefore(midDiv, div.childNodes[0]);
i++
}
Alternatively, you can use event delegation on the static parent element and listen for clicks on specific children, like so:
function galeriClickHandler () {
// something awesome happening in here
}
// Get the parent DIV, add click listener...
document.querySelector(".row").addEventListener("click",function(e) {
// e.target was the clicked element
if (e.target && e.target.matches(".galeri-cart")) {
galeriClickHandler();
}
});
Since you didn't give any info on how you're adding the elements, the only direct code solution to give would be one that delegates the event handling to some container element.
var par = document.querySelector("#parent");
var button = document.querySelector("button");
button.addEventListener("click", function() {
par.insertAdjacentHTML("beforeend", `<p class=galeri-cart>cart ${getCarts().length+1}</p>`)
});
par.addEventListener('click', function(event) {
var cart = event.target.closest(".galeri-cart")
if (cart)
cart.textContent += " clicked!"
});
function getCarts() {
return par.querySelectorAll(".galeri-cart");
}
<button>Add Cart</button>
<div id=parent>
<p class=galeri-cart>cart 1</p>
<p class=galeri-cart>cart 2</p>
<p class=galeri-cart>cart 3</p>
</div>
You added your code. You're already adding attributes and properties to the element, so you just do what you're already doing... bind the handler.
Here's a rewrite that makes your code much more concise and readable.
First, create the event handler.
function clickHandler() {
// your handler code
}
Then create the element and bind the handler to it.
success: function() {
let imageData = JSON.parse(this.files[i].xhr.response);
let div = document.querySelector('.row');
div.insertAdjacentHTML("afterbegin", `
<div class="col-md-4">
<div class="galeri=cart">
<img src="${imageData.url}" data-id="${imageData.id}" alt="${imageData.alt}">
</div>
</div>`);
div.firstElementChild
.firstElementChild
.addEventListener("click", clickHandler);
i++;
}

How to hide dynamically created div on ready?

I have a scenario where I need to create a div dynamically, so I created on-ready of document. But it should be displayed on-selection. I am facing the issue, that on page load, the empty div is created. So I need to hide that div and should be shown on-select of text.
JavaScript
$(document).ready(function () {
closePopUp();
var replaceDiv = document.createElement('div');
replaceDiv.id = 'rplceTxtDiv';
document.getElementsByTagName('body')[0].appendChild(replaceDiv);
var innerspan = document.createElement('span');
replaceDiv.appendChild(innerspan);
innerspan.innerHTML += '˟';
var innerDiv = document.createElement('div');
replaceDiv.appendChild(innerDiv);
innerspan.addEventListener("click", closePopUp, false);
replaceDiv.addEventListener("click", getSel, false);
var rplceTxtDiv = $('#rplceTxtDiv');
$('#mytextarea').on('select', function (e) {
var txtarea = document.getElementById("mytextarea");
var start = txtarea.selectionStart;
var finish = txtarea.selectionEnd;
rplceTxtDiv.offset(getCursorXY(txtarea, start, 20)).show();
rplceTxtDiv.find('div').text('replace with stars');
}).on('input', function () {
if (interval) {
interval = false;
edits.push($(this).val());
if (edits.length > maxHistorySize) edits.shift();
setTimeout(() => interval = true, saveInterval);
}
});
document.onkeydown = undo;
});
Here is my plunker
The issue is shown in below image:
Hide the DIV before appending it to the HTML by
replaceDiv.style.display = "none";
and I recommend showing it after you have updated the text by
replaceDiv.style.display = "block";
Set a CSS class as:
.MyClass {
display: none;
}
and with jQuery:
$('#myDivIDorClass').addClass('MyClass');
just hide all div having class name "yourclass" with hide()
like this on ready
$('div.yourclass').css("display","none");

Events and handlers JavaScript

I am writing a code in which I want to display a word and sentence to my webpage when clicked(button). So far I have one text being displayed onto the page.I want to display the sentence after the text.The sentence is not displaying... anyone know why?
function handleButtonClick(){
var button = document.getElementById("addButton");
button.onclick = handleButtonClick;
var textInput = document.getElementById("word");
var termName = textInput.value;
var dt = document.createElement("dt");
dt.innerHTML = termName;
var dl = document.getElementById("p");
dl.appendChild(dt);
var textInput = document.getElementById("sentence");
var termDefine = textInput.value;
var dd = document.createElement("dd");
dd.innerHTML = termDefine;
var dl = document.getElementById("define");
dl.appendChild(d);
}
window.onload = handleButtonClick;
button.onclick = handleButtonClick;
supposed to be
button.addEventListener('click', handleButtonClick);
The second point is that the click event handler should be bound outside the function scope. Otherwise a new event will be bound every single time the function handleButtonClick fires.
var button = document.getElementById("addButton");
button.addEventListener('click', handleButtonClick);
function handleButtonClick() {
// Your other code here
// that excludes the click handler
}
And developer tools is your friend. Always use it to check for any errors.
In addition to what #sushanth already mentioned there is a typo in your code:
Instead of
dl.appendChild(d);
It should be
dl.appendChild(dd);

Categories