Responses to this:
How to remove elements except any specific id
are close to what I want but not quite.
In my case I am asking how I can remove all elements under parent id except id_n and its children: test1 and test2. The elements need to be removed, not just hidden.
<div id = "parent_id">
<div id = "id_1">
<div id = "id_11"> test</div>
<div id = "id_12">test </div>
</div>
<div id = "id_2"> test</div>
<div id = "id_n">id_n<br>
<div id='test1'>test1<br><div>
<div id='test2'>test2<br><div>
</div>
</div>
The result should be:
<div id = "parent_id">
<div id = "id_n">id_n<br>
<div id='test1'>test1<br><div>
<div id='test2'>test2<br><div>
</div>
</div>
Thanks for looking at this. Your suggestions are appreciated.
Using jQuery's siblings you remove all of it's children:
$('#id_n').siblings().remove();
Okay after thinking about this, there is another approach using Array manipulation:
var parentElement = document.getElementById('#parent_id');
parentElement.innerHtml = [].splice.call(parentElement.children).filter(item, function() {
return item.id === childId;
}).reduce((collatedHtml, item, function() {
return collatedHtml + item.innerHtml;
});
This grabs all the direct children of the parentElement and returns a new array (using Array.filter) before using Array.Reduce to collate the innerHtml of all the children.
Note: the reason i'm not using the ... prefix to convert to an Array is because it is not supported in IE 11 and below
Related
I have a function which accepts two parameters, each of type HTML element. It is supposed to return which element appears first in the document order. Is there any simple way to determine this?
Template -
<body>
<div id="div1">
<div id="div2">
</div>
</div>
<div id="div3">
<div id="div4">
</div>
</div>
</body>
JS -
const elem1 = document.getElementById('div2');
const elem2 = document.getElementById('div4');
const firstAppearingElement = checkOrder(elem1, elem2); // it should return elem1
function checkOrder(element1, element2) {
// check which one appears first in dom tree
}
You can try with Node.compareDocumentPosition()
The Node.compareDocumentPosition() method compares the position of the
given node against another node in any document.
The syntax is object.compareDocumentPosition (nodeToCompare);
let first = document.getElementById('a');
let second=document.getElementById('b');
// Because the result returned by compareDocumentPosition() is a bitmask, the bitwise AND operator has to be used for meaningful results.See link above for more
if (first.compareDocumentPosition(second) & Node.DOCUMENT_POSITION_FOLLOWING) {
console.log('element with id a is before element with id b'); //
} else {
console.log('element with id a is after element with id b');
}
<div id="a"></div>
<div id="b"></div>
<body>
<div class = "order-1-a">
<div class = "order 2-a">
<div class = "order 3-a"></div>
</div>
<div class = "order 2-b"></div>
<div class = "order 2-c"></div>
<div class = "order 2-d"></div>
</div>
<div class = "order-1-b"></div>
</body>
If I want a div to wrap only class "order-2-a" + being the first child of "class-1-a", how should I script the div with JavaScript?
Probably your best bet is to:
Create a new Element with .createElement().
Append 2-a to the new Element with .appendChild().
Insert the new element before 2b with .insertBefore().
var one_a = document.getElementsByClassName("order-1-a")[0];
var two_a = document.getElementsByClassName("order-2-a")[0];
var two_b = document.getElementsByClassName("order-2-b")[0];
var new_node = document.createElement("div");
new_node.appendChild(two_a);
one_a.insertBefore(new_node, two_b);
console.log(one_a.innerHTML);
<body>
<div class="order-1-a">
<div class="order-2-a">
<div class="order-3-a"></div>
</div>
<div class="order-2-b"></div>
<div class="order-2-c"></div>
<div class="order-2-d"></div>
</div>
<div class="order-1-b"></div>
</body>
This provides the structure you're looking for (albeit not displayed well with console.log()).
Also, please be aware that class names cannot start with numbers, and may yield unexpected results. I've updated most of your classes to start with order in my example, as is with your order-1-a class.
Hope this helps!
You can create a general wrapping function based on a selector. It should get the subject node, then its parent and either it's next sibling or null if there isn't one.
Then create an element of the required type, append the subject node and insert it before the next sibling or as the last node if there wasn't one.
PS.
I've modified the class names to be valid, they can't start with a digit.
// Wrap element with selector in element with tagName
function wrapEl(selector, tagName) {
var node = document.querySelector(selector);
// If there is no subject node, return
if (!node) return;
// Get parent and sibling (or null if there isn't one)
var parent = node.parentNode;
var sibling = node.nextSibling;
// Append stuff
var wrapper = document.createElement('tagName');
wrapper.textContent = 'inserted wrapper'; // Just to show it's there
wrapper.appendChild(node);
parent.insertBefore(wrapper, sibling);
}
window.onload = function() {
wrapEl('.order-2-a', 'div');
}
<body>
<div class = "order-1-a">
<div class = "order-2-a">
<div class = "order-3-a"></div>
</div>
<div class = "order-2-b"></div>
<div class = "order 2-c"></div>
<div class = "order 2-d"></div>
</div>
<div class = "order-1-b"></div>
</body>
I add a data attribute to an element via jquery data() function.
I want to use find() function to get the element. But obviously, it does not work.
What I want to do is caching the element's parent element and do a lot of things.
Like this:
var $parent = $('#parent');
var $dataElement = $parent.findByData('whatever');
$parent.xxx().xxx().xxx()....;
I don't want this:
var $parent = $('#parent');
var $dataElement = $("#parent [data-whatever='whatever']");
$parent.xxx().xxx().xxx()....;
//It looks like find the parent twice.
Can any function do this?
I add a data attribute to an element via jquery data() function.
As you mentioned you are setting the data to the element with data() method of jQuery. Which doesn't adds any attribute in the DOM. So you can't find it with .find() that way because it's in memory*.
Instead you should use .attr() method to set the data attribute and then you can read it from the DOM with .find() method.
* don't have proper word for it
below is an example of setting the data with .data() and trying to find it.
$('#parent').find('.two').data('test', 'myTest');
var div = $('#parent').find('.child[data-test="myTest"]').length;
alert(div);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='parent'>
<div class='child one'></div>
<div class='child two'></div>
</div>
below is an example of setting the data with .attr() and trying to find it.
$('#parent').find('.two').attr('data-test', 'myTest');
var div = $('#parent').find('.child[data-test="myTest"]').length;
alert(div);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='parent'>
<div class='child one'></div>
<div class='child two'></div>
</div>
below is an example as per your comment:
$('#parent').find('.two').data('test', 'myTest');
var div = $('#parent').find('.child').filter(function(){
return $(this).data('test') == 'myTest'
}).text();
console.log(div);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='parent'>
<div class='child one'>One</div>
<div class='child two'>Two</div>
</div>
You can try $(child,parent) way and attribute selector $('[attribute-name]') as parameter,
var $parent = $('#parent');
var $dataElement = $parent.children().filter(function(){
return $(this).data('whatever') !== undefined
});
If you need a function findByData(),
$.fn.findByData = function(dataAttribute){
return $(this).children().filter(function(){
return $(this).data(dataAttribute) !== undefined
});
}
var $parent = $('#parent')
var $dataElement = $parent.findByData('whatever');
Fiddle Demo
If you want to get the parent element only when it has data attribute value equals to somevalue, you need to use filter function:
$parent.filter(function(){
return $(this).data('whatever') == "whatever"
});
If you want to find child element of parent that has data attribute value equals to somevalue:
$parent.find("*").filter(function(){
return $(this).data('whatever') == "whatever"
});;
<div id="parent">
<p data-whatever='whatever'>Whatever1</p>
<p data-whatever='whatever'>Whatever2</p>
<p data-whatever='whereever'>Whereever1</p>
</div>
var $parent = $('#parent');
var $dataElements = $parent.find("*[data-whatever='whatever']");
This will return an array of decedent elements inside the "#parent" element having data-whatever='whatever'.
$.each($dataElements,function(key,val){
console.log( $($dataElements[key]).html());
});
Demo
example,
<div id = "test1">test1</div>
<div id = "test2">test2</div>
i want to wrap a parent div like this,
<div id="parent_test">
<div id = "test1">test1</div>
<div id = "test2">test2</div>
</div>
I tried to use jquery wrap(), but it only wraps one by one:(
You need wrapAll:
$("#test1, #test2").wrapAll($("<div>", { id: "parent_test" }));
jsFiddle
use .wrapAll():
$('#test1,#test2').wrapAll('<div id="parent_test" style="color:red;"></div>');
Working Demo
Use jQuery WrapAll method
<div id = "test1" class="my-div">test1</div>
<div id = "test2" class="my-div">test2</div>
$('.my-div').wrapAll("<div class='my-wrap'></div>");
http://jsfiddle.net/6eGuG/
let say there is a parent id which contains many elements and i want to remove all elements except one.
ex. :
<div id = "parent_id">
<div id = "id_1">
<div id = "id_11"> </div>
<div id = "id_11"> </div>
</div>
<div id = "id_2"> </div>
<div id = "id_n"> </div> // No need to remove this id_n only
</div>
As i can remove innerHTML like this document.getElementId('parent_id').innerHTML = ''; but i need not to remove id_n. is there any way to do that using javascript or jQuery.
$("#parent_id").children(":not(#id_n)").remove();
$("#parent_id > :not(#id_n)").remove();
No jQuery required:
const parent = document.querySelector('#parent_id');
const keepElem = document.querySelector('#id_n');
[...parent.children]
.forEach(child => child !== keepElem ? parent.removeChild(child) : null);
I think the Attribute Not Equals selector makes sense here.
$("#parent_id div[id!='id_n']").remove();
Demo.
For fun, POJS is a tad more code, but no jQuery :-)
var p = document.getElementById('parent_id');
var d = document.getElementById('id_n');
p.innerHTML = '';
p.appendChild(d);
A lot faster too. ;-)
Deleting all children other than id_n with jQuery:
$('#parent_id div').not('#id_n').remove();
If you'are going to delete the parent_id as well:
$('#id_n').insertAfter('#parent_id');
$('#parent_id').remove();