On the click of addField_1 button, I have to clone the container div(id = 'projection') and append it right below it.
I am doing this in jquery like this:
$('[id^="addField"]').click(() => {
var containerDiv = $(this).parent();
console.log(containerDiv.attr('id'));
containerDiv.after(containerDiv.clone());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row" id="projection" >
<select class="form-control" aria-placeholder="Select field"></select>
<button type="button" class="btn btn-light" id="addField_1" name="mybutton">+</button>
</div>
There is no error when the button is clicked. But the div is not being copied. I also tried to log the parent div's id. It is also undefined. Please tell me what am I doing wrong.
Notice that you have used arrow function because of which this is referring to the window.
There are two solutions for it :
1. Using event.target in the arrow function to get the targeted element.
$('[id^="addField"]').click((event) => {
let containerDiv = $(event.target).parent();
console.log(containerDiv.attr('id'));
containerDiv.after(containerDiv.clone());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row" id="projection" >
<select class="form-control" aria-placeholder="Select field"></select>
<button type="button" class="btn btn-light" id="addField_1" name="mybutton">+</button>
</div>
2. To not use arrow function but anonymous function and use this :
$('[id^="addField"]').click(function() {
let containerDiv = $(this).parent();
console.log(containerDiv.attr('id'));
containerDiv.after(containerDiv.clone());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row" id="projection" >
<select class="form-control" aria-placeholder="Select field"></select>
<button type="button" class="btn btn-light" id="addField_1" name="mybutton">+</button>
</div>
With this keyword, you will reference to Window object.
That why you should use something like that:
$('[id^="addField"]').on('click', event => {
const parentDiv = $(event.target).closest('.row');
console.log(parentDiv.html());
});
Related
I'm trying to make a copy of the original container div with the cloneNode method in javascript inside the container there are 3 buttons with btn class, when I make a copy of the original one the last only the last element in the copied item is only printing hello in the console, any ideas?
let add = document.querySelector('.add-button');
const item = document.querySelector('.container');
let btn = document.querySelectorAll('.btn');
add.addEventListener('click', function() {
makecopy();
});
btn.forEach(el => {
el.addEventListener('click', function() {
console.log("hello")
})
});
function makecopy() {
let copiedItem = item.cloneNode(true);
item.parentNode.insertBefore(copiedItem, item);
}
<div class="add-panel">
<button type="button" class="add-button">Create new</button>
</div>
<div class="container">
<div>
<button type="button" class="btn">+</button>
</div>
<div>
<button type="button" class="btn">+</button>
</div>
<div>
<button type="button" class="btn">+</button>
</div>
You are only setting up event listeners on the first set of buttons, not the cloned ones. Instead of setting up listeners on each button, use "event delegation" to allow the event to "bubble" up to a common ancestor and handle the event there. This way, all the newly added elements will immediately work without needing their own handler and there is only one handler that needs to be set up instead of many.
You've also got some redundant code and code that will no longer be needed when you take this approach.
// No need to set up an anonymous handler that calls the real one. Just
// register the real one
document.querySelector('.add-button').addEventListener('click', makecopy);
const item = document.querySelector('.container');
function makecopy() {
let copiedItem = item.cloneNode(true);
item.parentNode.insertBefore(copiedItem, item);
}
// Listen for clicks on the document:
document.addEventListener('click', function(event) {
// Check to see if it was a button that was clicked:
if(event.target.classList.contains("btn")){
console.log("hello");
};
});
<div class="add-panel">
<button type="button" class="add-button">Create new</button>
</div>
<div class="container">
<div>
<button type="button" class="btn">+</button>
</div>
<div>
<button type="button" class="btn">+</button>
</div>
<div>
<button type="button" class="btn">+</button>
</div>
</div>
Just appears you weren't adding new listeners when you made new buttons. Some adjustments.
let add = document.querySelector('.add-button');
const item = document.querySelector('.container');
let btn = document.querySelectorAll('.btn');
add.addEventListener('click', function() {
makecopy();
});
btn.forEach(el => {
el.addEventListener('click', function() {
console.log("hello")
})
});
function makecopy() {
let copiedItem = item.cloneNode(true);
item.parentNode.insertBefore(copiedItem, item);
copiedItem.addEventListener('click', function() {
console.log("hello")
})
}
<div class="add-panel">
<button type="button" class="add-button">Create new</button>
</div>
<div class="container">
<div>
<button type="button" class="btn">+</button>
</div>
<div>
<button type="button" class="btn">+</button>
</div>
<div>
<button type="button" class="btn">+</button>
</div>
I'm writing the code to edit a database table.
I have the following HTML:
<div id="1">
<div contenteditable>aaa</div>
<div contenteditable>bbb</div>
<div contenteditable>ccc</div>
<button onClick="a('save')">SAVE</button>
<button onClick="a('delete')">DELETE</button>
</div>
<div id="2">
<div contenteditable>ddd</div>
<div contenteditable>eee</div>
<div contenteditable>fff</div>
<button onClick="a('save')">SAVE</button>
<button onClick="a('delete')">DELETE</button>
</div>
<div id="3">
<div contenteditable>ggg</div>
<div contenteditable>hhh</div>
<div contenteditable>iii</div>
<button onClick="a('save')">SAVE</button>
<button onClick="a('delete')">DELETE</button>
</div>
And so on.
Using the following function, I can get the clicked button:
function a(value) {
console.log(value);
}
When a button (SAVE or DELETE) is clicked, I need to retrieve:
the id of the "parent" div;
the content of each of the three contenteditable divs inside the same "parent" div.
Is it possible using pure Javascript?
Any suggestion will be very appreciated.
Thanks in advance.
What I would do is implement click listeners in JS, that way I can query elements easily.
Here is the example:
// Query all div.div-editable elements
document.querySelectorAll('div.div-editable')
.forEach((div) => {
// The id of the parent
const divId = div.id;
// Each of content editable divs inside the parent div
const editables = div.querySelectorAll('div[contenteditable]');
// The buttons Save and Delete
const saveBtn = div.querySelector('button.button-save');
const deleteBtn = div.querySelector('button.button-delete');
// Add click listeners to buttons
saveBtn.addEventListener('click', function() {
console.log('Saved: ' + divId);
const contentOfEditableDivs = Array.from(editables).map((div) => div.innerText);
console.log('Values of divs:', contentOfEditableDivs);
});
deleteBtn.addEventListener('click', function() {
console.log('Deleted: ' + divId);
const contentOfEditableDivs = Array.from(editables).map((div) => div.innerText);
console.log('Values of divs:', contentOfEditableDivs);
});
});
<div id="1" class="div-editable">
<div contenteditable>aaa</div>
<div contenteditable>bbb</div>
<div contenteditable>ccc</div>
<button class="button-save">SAVE</button>
<button class="button-delete">DELETE</button>
</div>
<div id="2" class="div-editable">
<div contenteditable>ddd</div>
<div contenteditable>eee</div>
<div contenteditable>fff</div>
<button class="button-save">SAVE</button>
<button class="button-delete">DELETE</button>
</div>
<div id="3" class="div-editable">
<div contenteditable>ggg</div>
<div contenteditable>hhh</div>
<div contenteditable>iii</div>
<button class="button-save">SAVE</button>
<button class="button-delete">DELETE</button>
</div>
EDIT 1: Added code snippet
EDIT 2: Simplified explanation
You can send this keyword in the argument of click's event handler and then access the parent div's id.
So your HTML would look something like:
// rest of the code here
<button onClick="a(this, 'save')">SAVE</button>
<button onClick="a(this, 'delete')">DELETE</button>
// rest of the code here
And your JS code would change to:
function a(elem, value) {
console.log(elem.parentNode.id);
}
More details on the following link:
how i get parent id by onclick Child in js
I'm encountering a typical situation while accessing the innerHTML property using jQuery. I've fetched the target button using the jQuery attribute selector.
Below is the snippet of jQuery attribute selector.
jQuery('button[type="button"][class="btn btn-primary"]').each(function () {
var btn = jQuery(this);
console.log(btn);
if (btn[0].innerHTML === "OK") {
console.log("ok");
jQuery(this).click();
}
});
Following is the screenshot of the console log of the target button. It's innerHTML property is set to OK.
Following is the screenshot of the value of the innerHTML while debugging the target button object. In this case the value is "".
Ideally, the values of the innerHTML should be the same for both the cases.
EDIT
Why does this behavior differ that the ideal one? For both of the cases, the value of the innerHTML should be the same.
Also, there were multiple buttons. I have taken screenshots of different buttons. Thus their ID's are different. But still, the behavior is same.
Try something like this.
function SomeEvent($ele) {
alert($ele.html());
return false;
}
function invokeBtnEvents() {
$("[data-action=some-event]").off(); // clear old events
$("[data-action=some-event]").on("click", function() {
var $this = $(this);
return SomeEvent($this);
}) // define event(s)
return false;
}
$(document).ready(function() {
invokeBtnEvents();
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="col-12">
<br />
<button data-action="some-event" class="btn btn-primary">Button 1</button>
<button data-action="some-event" class="btn btn-primary">Button 2</button>
<button data-action="some-event" class="btn btn-primary">Button 3</button>
<button data-action="some-event" class="btn btn-primary">Button 4</button>
</div>
</div>
</div>
Your issue
What you are doing that I think is your main issue is the $.each() method.
Store the buttons in a variable,
let $button = $("button"); // this returns an array of all the buttons on the DOM
You can then use the $.each() method to get the clicked element
$.each($button, function(index, btn){
const $this = $(btn);
$this.off();
$this.click(function(){someEvent($this)});
});
I would not invoke button clicks like this because every time you click a button, this each loop gets ran. It will then send all of the buttons to that action unless you parse by an ID or something (you are using the innerText).
If you use the code in my snippet, only the clicked button will be triggered.
An alternative approach to my first snippet is using something like a dispatcher.
function DoActionOneClick($ele){
alert("Action 1 " + $ele.html());
}
function DoDefaultClick($ele){
alert("Default Action " + $ele.html());
}
function DispatchEvent(action, $ele){
switch(action){
case "some-event-1":
DoActionOneClick($ele);
break;
default:
DoDefaultClick($ele);
break;
}
}
function invokeActions(){
$("[data-action]").off();
$("[data-action]").on("click", function(){
// get this
var $this = $(this);
// get action
var action = $this.data().action;
DispatchEvent(action, $this);
});
}
$(document).ready(function(){
invokeActions();
})
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="col-12">
<br />
<button data-action="some-event-1" class="btn btn-primary">Button 1</button>
<button data-action="some-event-2" class="btn btn-primary">Button 2</button>
<button data-action="some-event-2" class="btn btn-primary">Button 3</button>
<button data-action="some-event-2" class="btn btn-primary">Button 4</button>
</div>
</div>
</div>
I want to get a text from a textarea after clicking on button that is next to the textarea.
The problem is that I will have many textareas and every button must returns the text of the textarea that corresponds to it.
This is my code
function btnmodif(){
var mod = $(this).prev().val();
alert(mod);
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<div class="list-item-edit">
<textarea class="list_input">eggs</textarea>
<button class="btn btn-modify-item" onClick="btnmodif()">get text</button>
</div>
<div class="list-item-edit">
<textarea class="list_input">water</textarea>
<button class="btn btn-modify-item" onClick="btnmodif()">get text</button>
</div>
You have to pass object clicked to btnmodif function.
<button class="btn btn-modify-item" onClick="btnmodif(this)">get text</button>
JS
function btnmodif(button){
var mod = $(button).prev().val();
alert(mod);
};
Also, you should use .prev function.
Read more about .prev() function, here.
function btnmodif(button){
var mod = $(button).prev().val();
alert(mod);
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<div class="list-item-edit">
<textarea class="list_input">eggs</textarea>
<button class="btn btn-modify-item" onClick="btnmodif(this)">get text</button>
</div>
<div class="list-item-edit">
<textarea class="list_input">water</textarea>
<button class="btn btn-modify-item" onClick="btnmodif(this)">get text</button>
</div>
Firstly, you need to pass the clicked element as context to the function:
onClick="btnmodif(this)"
...
function btnmodif(button){
Second, if the HTML structure will remain the same (i.e. the textarea is always going to be the element immediately before the button), then you can use prev()
var mod = $(button).prev('textarea').val();
https://api.jquery.com/prev/
If that structure isn't guaranteed to be maintained, then .siblings() gives you a bit more flexibility, as it searches through all the elements at the same hierarchical level in the DOM to find what you want:
var mod = $(button).siblings('textarea').val();
https://api.jquery.com/siblings/
Here is what are you looking for.
Add this as parameter to your button.onclick
Thanks to jQuery:
Using $(element).parent(), you get your div element.
Using $(element).parent().find('.list_input'), you get your textarea element.
Using $(element).parent().find('.list_input').text() gives you the value of the textarea "related to" the clicked button.
function btnmodif(element){
var result = $(element).parent().find('.list_input').text();
alert(result);
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<div class="list-item-edit">
<textarea class="list_input">eggs</textarea>
<button class="btn btn-modify-item" onClick="btnmodif(this)">get text</button>
</div>
<div class="list-item-edit">
<textarea class="list_input">water</textarea>
<button class="btn btn-modify-item" onClick="btnmodif(this)">get text</button>
</div>
You're missing the this from the inline handler specification:
https://jsfiddle.net/3mvod6ux/
Use siblings with a selector to get the textarea's value that belong to the same block of the button clicked.
function btnmodif(button){
var mod = $(button).siblings("textarea").val();
alert(mod);
};
Another way to do this task .
Instead to use HTML event attribute this is better approach.
var btnModifyItem = $('.btn-modify-item');
btnModifyItem.click(function(){
var mod = $(this).prev().val();
alert(mod);
})
This way you can get the parent of button (and textarea) and then can get the text from child textarea:
$('button').on('click', function () {
console.log(($(this).parent().find("textarea").text()));
});
I have a number of buttons within a section, each with an id of the form #balls-left-n, where n ranges from 1 to 15.
When one of these buttons is clicked, I want to grab the number from the id that was clicked and hide all of the buttons with ids that have names including numbers that are greater than the one clicked on.
So, if #balls-left-13 is clicked, I want to hide #balls-left-14 and #balls-left-15. But if #balls-left-3 is clicked I want to hide all the buttons from #balls-left-4 through #balls-left-15.
I'm a novice at web-dev so if I've made other mistakes or taken a poor approach don't hesitate to point that out.
I have a handler for each of the buttons (which if I knew more could probably be one function) that look like this:
$("#balls-left-14").click(function() {
var num_balls = $(this).attr('id').match(/[\d]/);
j_end_balls_on_table = 14;
$("#balls-left button:gt(num_balls-2)").hide;
...
other stuff
...
});
This didn't work and I get an error that num_balls is undefined, which I don't understand.
#balls-left is the section all of the buttons are inside of.
relevant HTML as requested
<section id="balls-left">
<h2>How Many Balls are Left on the Table?</h2>
<button type="button" id="balls-left-2" class="x-balls-left">2</button>
<button type="button" id="balls-left-3" class="x-balls-left">3</button>
<button type="button" id="balls-left-4" class="x-balls-left">4</button>
<button type="button" id="balls-left-5" class="x-balls-left">5</button>
<button type="button" id="balls-left-6" class="x-balls-left">6</button>
<button type="button" id="balls-left-7" class="x-balls-left">7</button>
<button type="button" id="balls-left-8" class="x-balls-left">8</button>
<button type="button" id="balls-left-9" class="x-balls-left">9</button>
<button type="button" id="balls-left-10" class="x-balls-left">10</button>
<button type="button" id="balls-left-11" class="x-balls-left">11</button>
<button type="button" id="balls-left-12" class="x-balls-left">12</button>
<button type="button" id="balls-left-13" class="x-balls-left">13</button>
<button type="button" id="balls-left-14" class="x-balls-left">14</button>
<button type="button" id="balls-left-15" class="x-balls-left">15</button>
</section>
Hope this helps.
var exploded = id.split("-");
alert(exploded.pop());
Now, to use that concept on your HTML structure, you can do something like this:
$(document).ready(function() {
$(".x-balls-left").click(function(e) {
e.preventDefault();
var exploded = this.id.split("-");
alert(exploded.pop());
});
});
And here's a Fiddle you can play around with.
You might don't even need all of these if your elements to hide share the same parent. Just set class on click .selected and hide the rest using CSS .selected.x-balls-left ~ .x-balls-left {display: none;}
$('.x-balls-left').click(function() {
$(this).toggleClass('selected');
})
.selected.x-balls-left ~ .x-balls-left {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section id="balls-left">
<h2>How Many Balls are Left on the Table?</h2>
<button type="button" id="balls-left-2" class="x-balls-left">2</button>
<button type="button" id="balls-left-3" class="x-balls-left">3</button>
<button type="button" id="balls-left-4" class="x-balls-left">4</button>
<button type="button" id="balls-left-5" class="x-balls-left">5</button>
<button type="button" id="balls-left-6" class="x-balls-left">6</button>
<button type="button" id="balls-left-7" class="x-balls-left">7</button>
<button type="button" id="balls-left-8" class="x-balls-left">8</button>
<button type="button" id="balls-left-9" class="x-balls-left">9</button>
<button type="button" id="balls-left-10" class="x-balls-left">10</button>
<button type="button" id="balls-left-11" class="x-balls-left">11</button>
<button type="button" id="balls-left-12" class="x-balls-left">12</button>
<button type="button" id="balls-left-13" class="x-balls-left">13</button>
<button type="button" id="balls-left-14" class="x-balls-left">14</button>
<button type="button" id="balls-left-15" class="x-balls-left">15</button>
</section>
$(document).on('click', '.balls-left', function() {
var num = getNum(this);
$('.balls-left').each(function() {
var that = $(this);
var bnum = getNum(that);
if (bnum > num) {
that.show();
} else {
that.hide();
}
});
});
var getNum = function(elem) {
if (elem) {
return $(elem).attr('id').replace('balls-left-', '');
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="balls-left-1" class="balls-left">Ball 1</div>
<div id="balls-left-2" class="balls-left">Ball 2</div>
<div id="balls-left-3" class="balls-left">Ball 3</div>
<div id="balls-left-4" class="balls-left">Ball 4</div>
<div id="balls-left-5" class="balls-left">Ball 5</div>
$("#balls-left button:gt(num_balls-2)").hide;
This is an invalid CSS selector, and only gets the hide method, without calling it. You want something like:
$("#balls-left button:gt("+(num_balls-2)+")").hide();
First you should put a class on each object so you can reference them all at once, and the simplest way to understand is to just put the ball number right in the tag as a custom attribute if you can:
<input type="button" id="balls-left-1" class="left-ball" num="1"/>
<input type="button" id="balls-left-2" class="left-ball" num="2"/>
etc...
Then you can write the javascript as follows:
$('.left-ball').click(function () {
var BallNum = $(this).attr('num');
$('.left-ball').each(function () {
if ($(this).attr('num') > BallNum) {
$(this).hide();
}
});
});
You can use RegEx match like this. This might resolve your undefined num_balls error message.
$("#balls-left-14").click(function() {
var ret = $(this).attr('id').match("[0-9]+");
var num_balls = ret[0];
j_end_balls_on_table = 14;
$("#balls-left button:gt(num_balls-2)").hide;
...
other stuff
...
});
Another way of doing it using your original HTML:
$('.x-balls-left').click(function () {
var BallNum = $(this)[0].innerHTML;
$('.x-balls-left').each(function () {
if ($(this)[0].innerHTML > BallNum) {
$(this).hide();
}
});
});
I just did it like this:
$('button[id^=balls-left-]').click(function(){
var num_balls = $(this).attr('id').match(/[\d]/);
$('#balls-left button:gt(' + num_balls + ')').hide();
});
Keep in mind that :gt select by index, it means that $('#balls-left button:gt(2)') will not select the button with id balls-left-2 but the one with id balls-left-4 (according to the html you posted).