Get data of specific node element on click - javascript

I'm trying to get specific data depending on which node element the user is clicking. I have 4 elements that I have targeted using the querySelectorAll code. What I want to accomplish is that if I click the first element I will console.log that specific data, and if I select the third element I will get that data logged. I've tried a couple of things, but haven't got it to work yet.
function selectedSplit() {
var macroSplits = document.querySelectorAll(".card");
console.log(macroSplits[0].childNodes[3].childNodes[1].innerHTML);
}

It's unclear where you are using selectedSplit - Wether or not it is being used as the event listener return function. But using an onClick event listener, you're return function will be passed the information you need.
If you want to accomplish this in the markup, you could do -
<div class='card' onClick="selectedSplit"></div>
Then you can simply access it via event.target
function selectedSplit(event) {
var thisCard=event.target;
console.log(thisCard.innerHTML);
}

event.target has the clicked element:
d.onclick = e => console.log(e.target)
<div id=d>
<button><b>b</b></button>
<button><i>i</i></button>
<button><u>u</u></button>
<button><s>s</s></button>
</div>

Related

How to add a onclick event on an element with custom input for the function

So i have a HTML element and i have a lot of them but i am only showing one because it is easier the only difference between them is the number in the id <div class="block" id="block0"></div>
and i want to give it a onclick with a javascript so i get this
<div class="block" id="block0" onclick="blockClicked(0)"></div>
and what i mean by custom input i what the input for the function to be the id of the div or just the number in the id. what i mean is that if i have another element with the id of block1 the onclick should be onclick="blockClicked(1)". but all pages i've found so far only shows how to give it a function with a input that is the same everytime. This might have already been answered if it has i couldn't find it.
You should select all your block elements with querySelectorAll() and loop over them with a forEach() method. For each block listen for the click event with addEventListener(). When the click event happens you'll want to figure out which element was clicked and get the id property of that element.
This way you can add more data in the form of data attributes to your block element and read the data from the onBlockClick function with the dataset property on the block element.
// Select all block elements.
const blocks = document.querySelectorAll('.block');
// Is called when a block is clicked.
const onBlockClick = event => {
const { currentTarget } = event; // currentTarget is element we are listening to, so the block element.
const { id } = currentTarget; // Get the id from the block element.
console.log(id); // Now you have an id variable which you can do something with.
});
// Loop over each block and listen for the click event.
blocks.forEach(block => {
block.addEventListener('click', onBlockClick);
});
Try this :
const block = document.getElementById('block0')
block.addEventListener('click',(mouseEvent) => { /* whatever you want to do on click */
blockClicked(0) })
If you want you can loop through all your elements and add them an event listener if they do have the same behavior
const elements = [...document.getElementsByClass('block')]
elements.foreach((el,i) => {
el.addEventListener('click',
mouseEvent => {
/* your event managment */
blockClicked(i)
})
})
Check this link to learn more : https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
You can use this to access the element the handler is bound to and therefore you can use this.id to access it's ID.
While binding event handlers with addEventListener is better overall, the minimal changes to your current code would be something like:
<div
class="block"
id="block0"
onclick="blockClicked(Number(this.id.replace('block')))">
</div>
No matter the way you choose, something to consider is to not use id just for piggybacking data, but use a data-* property instead:
<div
class="block"
data-id="0"
onclick="blockClicked(Number(this.dataset.id))">
</div>

Detect length div after append

I'm having trouble detecting length and index of the appended div, I dug through a lot of things, and there's a solution with MutationObservers but somehow I'm continuously asking myself do I need it for this kind of problem,
However, let's get to the issue. I have a div populated dynamically structured like this,
<div class="array-placeholder">
<div id="tagContainer" class="row tag">
<!-- dynamic elements -->.....
</div>
</div>
when I click to this button it appends another dynamic element, see the code below :
$('body').off('click.addCollection').on('click.addCollection', function () {
//list and new widgets are just containers and datalist inside the array-placeholder div
let newElem = $(list.attr('data-widget-tags')).html(newWidget);
newElem.appendTo(list);
})
I've tried this solution to get the length of the array-placeholder div but it doesn't seem to work, the function is never launched:
$('body').on('DOMSubtreeModified', '.array-placeholder', function (event) {
console.log( $(".array-placeholder > div").length);
})
result
//nothing and when you click to the appended element via moveUpButton.closest(".tag") you 0 as index
do I have to implement MutationObserver to solve this if yes, could you guide me through this, thanks
DOMSubtreeModified
This event has been deprecated in favor of the Mutation Observer API
Yes you have to use Mutation Observer API. To implement that you can refer This
You can get all children using jquery's find('*') and then count their length;
$(".array-placeholder").find('*').length;
Or if you want only divs then do:
$(".array-placeholder").find('div').length;

.appendChild() an HTML element on click

I wanted to copy an entire row including its' siblings and contents on button click. When I click the button the element, it appears in the console but doesn't append to the page. This is my code:
It doesn't show any error messages. I've tried innerHTML/outerHTML or append() it doesn't work.
$(document).ready(function() {
$('#addSubFBtn').on('click', function() {
var itm = document.getElementById("trFb");
var wrapper = document.createElement('div');
var el = wrapper.appendChild(itm);
document.getElementById("tbFb").append(el);
console.log(el);
});
});
Seems like what you're trying to do is clone the item after you get it from your document. W3schools website explains how to accomplish this. Check out the link: https://www.w3schools.com/jsref/met_node_clonenode.asp
Once you clone the node, [appendchild] should work as intended
Not sure (as said without seeing related HTML) but i see flaw in your logic:
var itm = document.getElementById("trFb");
still exist on the document(so in the page) so you've to retrieve it before you want to add/move it to another place.
using .removeElement will return you removed element(or null if no element matche the selector) so correct script should be:
var itm=document.getElementById("trFb").parentNode.removeChild(document.getElementById("trFb"));
as shown here to remove element you've to use method on to parent element.
So you can add it to any other element existing.
For more specific use or element created in global JS variable (such an createElement not yet appended) you can see :document.createDocumentFragment(); as explained here https://developer.mozilla.org/en-US/docs/Web/API/Document/createDocumentFragment

How do I make the checkbox work on newly created task?

I am writing a todo app using vanilla JavaScript to learn the language without using a library.
In the app, you can add a task, complete task or un-complete task, edit and delete task. I have sample tasks that show the functionality in HTML.
I have a function that adds a task to incomplete tasks section—each task item is wrapped in an li tag and has a checkbox, edit and delete buttons. The addTask function works perfectly.
The problem I am having is in the selectbox part. The app is designed in a way that when checkbox of a task is selected, it indicates a task is completed and thus the item is shown in the completed tasks section. The function works for the items available on the page but not the ones added using the add functionality. How do I make the new task work? Thanks. Here is my HTML Code:
<h3>Todo</h3>
<ul id="incomplete-tasks">
<li><input type="checkbox"><label>Pay Bills</label><button>Edit</button><button>Delete</button></li>
</ul>
<h3>Completed</h3>
<ul id="completed-tasks">
<li><input type="checkbox" checked></input><label>See Doctor</label><button>Edit</button><button>Delete</button></li>
And here is my JS code:
var incompleteTasksHolder = document.getElementById("incomplete-tasks");
var completedTasksHolder = document.getElementById("competed-tasks");
var incompleteTextboxes = incompleteTasksHolder.querySelectorAll("input[type=checkbox]");
for (var i = 0; i < incompleteTextboxes.length; i++) {
incompleteTextboxes[i].onfocus = function() {
var item = this.parentNode;
this.setAttribute("checked", "checked");
completedTasksHolder.appendChild(item);
}
}
You are probably using some event listeners to mark the task as completed when the checkbox changes value.
I think that you just forgot the bind this listener to the new item that you created via Javascript.
When creating your new element bind your listener to it:
taskCB.addEventListener('change', toggleCompleted);
Where taskCB is the checkbox element and toggleCompleted is the name of the function that is fired when a task checkbox is checked or unchecked.
This probably happens because the incompleteTextboxes variable only gets assigned a collection of DOM nodes once. Each time you add a new task, that ends up inside incompleteTasksHolder you should also re-assign an updated collection by re-running the assignment: incompleteTextboxes = incompleteTasksHolder.querySelectorAll("input[type=checkbox]");.
That could look something like this:
var incompleteTasksHolder = document.getElementById("incomplete-tasks"),
completedTasksHolder = document.getElementById("competed-tasks");
// Initialize variable, but create a function for the assignment:
var incompleteTextboxes;
// This function searches the DOM for all checkboxes inside incompleteTasksHolder, and assigns the collection of found elements to incompleteTextboxes:
function refreshIncompleteTasksCollection() {
incompleteTextboxes = incompleteTasksHolder.querySelectorAll("input[type=checkbox]");
}
// You can now re-assign all currently existing checkboxes by calling this function:
refreshIncompleteTasksCollection();
Now, each time there are new elements inside incompletetextboxes, you can run that function to add those to your collection. Note, you'll probably want to re-run your for-loop as well, for binding the focus event handler to your new elements.
A whole different (and in my opinion cleaner) approach would be to use event delegation for your onfocus handlers. Since incompletetextboxes only contains checkboxes inside #incomplete-tasks (by the way you set up your variables), you could use that element to delegate the event handling to. This can be done with addEventListener. You can read more about that here: https://davidwalsh.name/event-delegate.
The main reason I bring this up is because this would solve the problem of missing event handlers for your new elements. What event delegation basically means is, instead of saying:
listen at each incompleteTextbox for a focus event (which means that, when you add new elements you have to say that again for each new element)
you now say:
listen at incompleteTasksHolder for a focus event, and then determine whether that event was fired by a incompleteTextbox. That is possible because your checkboxes live INSIDE #incomplete-tasks. That could look something like this:
incompleteTasksHolder.addEventListener("focus", function(eventObject) {
if (eventObject.target && eventObject.target.matches("input[type=checkbox]")) {
// eventObject.target is the checkbox you want to work with
var checkbox = eventObject.target;
// YOUR CODE:
var item = checkbox.parentNode;
checkbox.setAttribute("checked", "checked");
completedTasksHolder.appendChild(item);
}
});
That means only one listener, that will always work, even for incompleteTextboxes that are inserted after that listener was set.

Javascript/jQuery - How do I obtain name of the class of clicked element?

I googled and googled and I concluded that it's very hard to get answer on my own.
I am trying to use jquery or JavaScript to get a property of clicked element. I can use "this.hash" for example - it returns hash value I presume.
Now I would like to get name of the class of clicked element.
Is it even possible? How? And where would I find this kind of information?
jQuery documentation? - All I can find is methods and plugins, no properties.. if its there - please provide me with link.
JavaScript documentation? - is there even one comprehensive one? again please a link.
DOM documentation? - the one on W3C or where (link appreciated).
And what is this.hash? - DOM JavaScript or jQuery?
In jQuery, if you attach a click event to all <div> tags (for example), you can get it's class like this:
Example: http://jsfiddle.net/wpNST/
$('div').click(function() {
var theClass = this.className; // "this" is the element clicked
alert( theClass );
});
This uses jQuery's .click(fn) method to assign the handler, but access the className property directly from the DOM element that was clicked, which is represented by this.
There are jQuery methods that do this as well, like .attr().
Example: http://jsfiddle.net/wpNST/1/
$('div').click(function() {
var theClass = $(this).attr('class');
alert( theClass );
});
Here I wrapped the DOM element with a jQuery object so that it can use the methods made available by jQuery. The .attr() method here gets the class that was set.
This example will work on every element in the page. I'd recommend using console.log(event) and poking around at what it dumps into your console with Firebug/Developer tools.
jQuery
​$(window).click(function(e) {
console.log(e); // then e.srcElement.className has the class
});​​​​
Javascript
window.onclick = function(e) {
console.log(e); // then e.srcElement.className has the class
}​
Try it out
http://jsfiddle.net/M2Wvp/
Edit
For clarification, you don't have to log console for the e.srcElement.className to have the class, hopefully that doesn't confuse anyone. It's meant to show that within the function, that will have the class name.
$(document).click(function(e){
var clickElement = e.target; // get the dom element clicked.
var elementClassName = e.target.className; // get the classname of the element clicked
});
this supports on clicking anywhere of the page. if the element you clicked doesn't have a class name, it will return null or empty string.
$('#ele').click(function() {
alert($(this).attr('class'));
});
And here are all of the attribute functions.
http://api.jquery.com/category/attributes/
You can use element.className.split(/\s+/); to get you an array of class names, remember elements can have more than one class.
Then you can iterate all of them and find the one you want.
window.onclick = function(e) {
var classList = e.srcElement.className.split(/\s+/);
for (i = 0; i < classList.length; i++) {
if (classList[i] === 'someClass') {
//do something
}
}
}
jQuery does not really help you here but if you must
$(document).click(function(){
var classList =$(this).attr('class').split(/\s+/);
$.each( classList, function(index, item){
if (item==='someClass') {
//do something
}
});
});
There's a way to do this without coding. Just open the console of your browser (f12?) and go to element you want. After that, hover or click the item you want to track.
Every change done on the DOM will be for a few seconds marked (or lightened) as another color on the console. (Watch the screen capture)
On the example, each time I hover a "colorItem", the 'div' parent and the "colorItem" class appears lightened. So in this case the clicked class will be 'swiper-model-watch' or 'swiper-container' (class of the lightened div)

Categories