Get all parents of an element including the element itself - javascript

I am trying to create an array of all the elements to where the user clicked in a content editable div. I have this working with the following code.
var els = [];
var target = event.target;
while (target){ //Create an array of parent elements
els.push(target); //Push target to the back of the array
target = target.parentNode;
}
But I was wondering if I could reduce this to one line with jQuery. jQuery .parents() almost gets me there but it doesn't include the first event.target
var els = $(event.target).parents();
Is there a way to include the element itself with .parents() or is there a better way of doing this?

How about andSelf ?
var els = $(event.target).parents().andSelf();
Mine would get you, great-grandparent, grandparent, parent, self.
If you want: self, parent, grandparent, great-grandparent, try extending Jquery with this:
$.fn.reverse = [].reverse;
and then doing:
var els = `$(event.target).parents().andSelf().reverse();
Example: jsFiddle

You can use add :
var els = $(event.target).parents().add(event.target);
or, if you want them in a different order :
var els = $(event.target).add($(event.target).parents());
If what you need is an array (ie not a jQuery object), you can use reverse :
var els = $(event.target).parents().add(event.target).get().reverse();

Related

Trying to clear some fields with JS by selecting elements with the same id, perl hangup

I am trying to clear some (10 of 50) fields by selecting elements by their shared id. The problem is that I can only select one at a time with getElementById()
Here is the jsFiddle demonstrating the single element grab. jsFiddle
function toggleBankCount() {
secBankFields = document.getElementById('2ndBankFields');
secBankFields.value = '';
}
I am fairly certain I can do what I want with getElementsByName() which returns an array of elements. However, I am using Perl and the name of the elements must be different in order for %fdat to work properly on submit. Can you help me?
Here's how you can do it:
toggleBankCount = function () {
secBankFields = document.getElementsByTagName('input');
for (var i = 0; i < secBankFields.length; ++i) {
if(secBankFields[i].id === '2ndBankFields')
secBankFields[i].value = '';
}
}
though ids should be unique, consider using classes instead. Also, classes and ids shouldn't begin with a digit.
Check it out: JSFiddle
There are some Javascript functions which should help you.
Get element by ID attribute
Id should be unique.
var elm = document.getElementById("some_id");
Get elements by Tag name
// get all div elements
var elms = document.getElementsByTagName("div");
Get element by Class attribute
// get all elements with class .some_class
var elms = document.getElementsByClassName("some_class");
Get element by Name attribute
// get all elements with attribute name some_name
var elms = document.getElementsByName("some_name");
Get element by CSS selector
var elms = document.querySelectorAll("div.box, span.title");
for (var i = 0; i < elms.length; i++) {
var elm = elms[i];
console.log(elm);
}

How to add a new element to the top of a table-jscript-jquery

I am working on a project and I am supposed to add a new element to the top of a table, right now the new element is getting added according to the preexisting order. Can anyone at least tell me what this function is doing?
$.fn.addCellInfoActionItem = function(nRow, aData, iDisplayIndex ) {
rows.push(nRow);
var isEditable = aData[0];
var isStatusEditable = aData[1];
var moduleId = aData[3];
var dueDateOverDue = aData[4];
var aimManaged = aData[5];
var isLastResponseEditable = aData[6];
var readOnlyToolTipText = aData[8];
var actionItemId = aData[10];
var actionItemstatus = aData[14];
var parenttr = $(nRow).closest('tr')[0];
var rowCellObjs = datatable.fnGetTds(parenttr);
var settingSize = datatable.dataTableSettings.length;
var headerCols;
You mean a function like table.push(e), but putting e at 0 index ?
try this :
table=[e].concat(table)
That function is not complete.. what is it doing in the missing code? But it seems it's a "preparing work" for what is there. Variable initializations and a adding of a element to a array.
You can use jquery's prepend() and append() to do dom-manipulations and to add e.g. like in your case a row (dom-element) wherever you exactly want..
See here:
http://api.jquery.com/prepend/
There it says:
The .prepend() method inserts the specified content as the first child
of each element in the jQuery collection (To insert it as the last
child, use .append()

XPathResult and invalid iterator state

I have a relatively large (500-100 rows) HTML table with a bunch of <a> elements. I would like to add a <select> to the top of the page, and populate it by creating an <option> for each <a> in the table.
My first approach looked something like this:
var initSelect = function () {
var select = document.getElementById('mySelect');
var items = document.evaluate('//a', document, null, XPathResult.ANY_TYPE, null);
var item = items.iterateNext();
while (item) {
var elem = document.createElement("option");
var val = document.createAttribute("value");
val.value = elem.nodeValue;
elem.setAttributeNode(val);
elem.innerHTML = item.innerHTML;
select.appendChild(elem);
item = items.iterateNext();
}
};
window.onload = initSelect;
As soon as I tried to appendChild() to the <select> I got an UncaughtInvalidStateError. I figured that modifying the DOM was invalidating my XPathResult iterator, so I tried to add all of the <option> elements to an array first, and then appending them after iterating through all of the results.
var initSelect = function () {
var select = document.getElementById('src_select');
var items = document.evaluate('//a', document, null, XPathResult.ANY_TYPE, null);
var elems = [];
var item = items.iterateNext();
while (item) {
var elem = document.createElement("option");
var val = document.createAttribute("value");
val.value = elem.nodeValue;
elem.setAttributeNode(val);
elem.innerHTML = item.innerHTML;
elems.push(elem);
item = items.iterateNext();
}
for (var i = 0; i < elems.length; i++) {
select.appendChild(elems[i]);
}
};
window.onload = initSelect;
If I step through the code in the debugger, I see items.invalidIteratorState go to true after executing the elem.innerHTML = item.innerHTML line. Then I get the same error on the next call to items.iterateNext().
The first thing I'd like to get working is to just see the <select> populated. After that, the goal is to be able to select an element in the drop down, and have the page navigate to the same link that the corresponding <a> element would have taken me to.
This is the first JavaScript I've written, so I appreciate any and all feedback. At this point, I'm looking for a pure JavaScript solution. Once I get it working I'm going to try to pull JQuery in and revise it.
document.links gives you all a href elements in the document so there is no need to use the XPath API to access those elements. And if you are looking for elements in a particular parent then use e.g. document.getElementById('foo').getElementsByTagName('a') to find all a elements in that element with id attribute being foo. I don't see why you would need the DOM Level 3 XPath API for that, which is not supported in IE anyways. And neither document.links nor the result of getElementsByTagName can be invalidated like an XPath iterator result.
If you really want to use the XPath API then try a snapshot as the result type, it should not fail the way the iterator fails due to document manipulation.

Why jquery return Object in attr('src')

This return me object Object. how can make an array of src?
$('#mainContainerPortfolio #activateBox').click(function(){
var clickedAlt = $(this).children('img').attr('alt');
var imgs = $('#mainContainerPortfolio #projectImg[alt="'+clickedAlt+'"]');
imgs.src;
var i = [];
i.push(imgs);
console.log(i);
});
In your code, imgs is a jQuery object, not a DOM element. As such, it does not have a .src property.
If you want the .src property of an image in that jQuery object, then you need to do one of the following:
var src = imgs.attr("src");
or, get the first DOM element from the jQuery object:
var src = imgs[0].src
Also, there are several other errors in your code. If you want to accumulate the src value of all elements that are clicked on into an array, you could do something like this:
$('#mainContainerPortfolio #activateBox').click(function(){
var clickedAlt = $(this).children('img').attr('alt');
var imgs = $('#mainContainerPortfolio #projectImg[alt="'+clickedAlt+'"]');
var srcs = imgs.map(function(index, elem) {
return(elem.src);
}).get();
console.log(srcs);
});
I think there is also a problem with your selector because you can only have one element with an id="projectImg" so there should be no reason to be using the attribute [alt="'+clickedAlt+'"] with it.
Similarly, '#mainContainerPortfolio #activateBox' could just be changed to '#activateBox' since there can only be one object with an id of activateBox.
Because imgs is an object. This line:
imgs.src;
does nothing at all. It just returns that. Nothing is done with the returned value. Change that to:
imgs = imgs.attr("src");
and it should work fine
You could use .map to get an array.
i = imgs.map(function() {
return $(this).attr('src');
});

Remove multiple elements with same name using removeChild?

I have an element with multiple elements inside. All of the elements inside have the same name. Is there any way to remove them using one function?
(refer to this question for example Remove multiple children from parent?
Here's a solution that removes the first level children with the specified name for the parent with the specified id. If you want to go deeper, you can recursively call it on the child elements you get inside (you'll have to add a parent parameter as well).
function removeChildren (params){
var parentId = params.parentId;
var childName = params.childName;
var childNodes = document.getElementById(parentId).childNodes;
for(var i=childNodes.length-1;i >= 0;i--){
var childNode = childNodes[i];
if(childNode.name == 'foo'){
childNode.parentNode.removeChild(childNode);
}
}
}
And to call it:
removeChildren({parentId:'div1',childName:'foo'});
And a fiddle for testing:
Notes: You can only access the name element dependably in JavaScript when it supported on your element (e.g. NOT on DIVs!). See here for why.
UPDATE:
Here's a solution using className based on our conversation:
function removeChildren (params){
var parentId = params.parentId;
var childName = params.childName;
var childNodesToRemove = document.getElementById(parentId).getElementsByClassName('foo');
for(var i=childNodesToRemove.length-1;i >= 0;i--){
var childNode = childNodesToRemove[i];
childNode.parentNode.removeChild(childNode);
}
}
2021 Answer:
Perhaps there are lots of way to do it, such as Element.replaceChildren().
I would like to show you an effective solution with only one redraw & reflow supporting all ES6+ browsers.
function removeChildren(cssSelector, parentNode){
var elements = parentNode.querySelectorAll(cssSelector);
let fragment = document.createDocumentFragment();
fragment.textContent=' ';
fragment.firstChild.replaceWith(...elements);
}
Usage: removeChildren('.foo',document.body);: remove all elements with className foo in <body>
ok this should be easy. First get the parent element:
var theParent = document.getElementById("notSoHappyFather");
then get an array of the nodes that you want to remove:
var theChildren = theParent.getElementsByName("unluckyChild");
Lastly, remove them with a loop:
for (var i = 0; i < theChildren.length; i++)
{
theParent.removeChild(theChildren[i]);
}
A sample of your HTML would get you a more complete answer, but one can fairly easy call DOM functions to get the list of children and just remove them. In jQuery, remove all children would be something like this:
$("#target > *").remove();
or
$("#target").html("");
And, you can see a demo here: http://jsfiddle.net/jfriend00/ZBYCh/
Or, not using jQuery you could also do:
document.getElementById("target").innerHTML = "";
If you're trying to only remove a subset of the children (and leave others intact), then you need to be more specific how one would determine which children to leave and which to remove. In jQuery, you could use a .find() select or a filter() selector to narrow the list of children to just the children you wanted to target for removal.

Categories