JQuery - Unwrap only one element - javascript

I have got such situation:
<div>
<span id="x1"></span>
<span id="x2"></span>
<span id="x3"></span>
</div>
And I am trying to get something like this:
<div>
<span id="x1"></span>
</div>
<span id="x2"></span>
<div>
<span id="x3"></span>
</div>
I have tried to do that using unwrap() function like this:
$('#x2').unwrap();
But this function removes whole <div>. So how can I do that using jQuery/JavaScript? Thanks for help.

You can unwrap the spans from the common div wrapper and then just wrap x1 and x3 in their own new divs.
$('span').unwrap();
$('#x1,#x3').wrap('<div>');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<span id="x1">x1</span>
<span id="x2">x2</span>
<span id="x3">x3</span>
</div>
If your spans don't have IDs, you could do something like
$('div > span:even').wrap('<div>').parent().unwrap()

Get the all siblings after the target element, wrap them in a new div and put them after the original container.
put the target element between both divs.
This will work for any number of items in the container and will only unwrap the target element.
const el=$("#x2")
const parent =el.parent()
const nextSiblings=el.nextAll()
const newWrap=$("<div>").append(nextSiblings)
parent.after(newWrap)
parent.after(el)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<style>
div{border:solid 1px red;}
span{display:block}
</style>
<div>
<span id="x1">1</span>
<span id="x2">2</span>
<span id="x3">3</span>
</div>
EDIT
add possibility of unwraping more than one element and also handle removal from first or last positions.
const unWrapOne=el=>{
const parent =el.parent()
const nextSiblings=el.last().nextAll()
if(nextSiblings.length>0){
const newWrap=$("<div>").append(nextSiblings)
parent.after(newWrap)
}
parent.after(el)
if(parent.children().length===0)
parent.remove()
}
const unwrapSome = elements => elements.each((index,el)=>unWrapOne($(el)))
unwrapSome($("#x3,#x5")) //unwrap 2 non contiguous elements
//unwrapSome($("#x2,#x3")) //unwrap 2 contiguous elements
//unwrapSome($("#x2")) //unwrap 1 element from middle
//unwrapSome($("#x1")) //unwrap 1 element from begining
//unwrapSome($("#x6")) //unwrap 1 element from end
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<style>
div{border:solid 1px red;}
span{display:block}
</style>
<div>
<span id="x1">1</span>
<span id="x2">2</span>
<span id="x3">3</span>
<span id="x4">4</span>
<span id="x5">5</span>
<span id="x6">6</span>
</div>

Here are two of javascript ways:
First one:
Wrap a given element in a new container element using plain JavaScript:
// element that will be wrapped
var el = document.querySelector('#x1');
// create wrapper container
var wrapper = document.createElement('div');
// insert wrapper before el in the DOM tree
el.parentNode.insertBefore(wrapper, el);
// move el into wrapper
wrapper.appendChild(el);
var el2 = document.querySelector('#x3');
var wrapper2 = document.createElement('div');
el2.parentNode.insertBefore(wrapper2, el2);
wrapper2.appendChild(el2);
<div>
<span id="x1">x1</span>
<span id="x2">x2</span>
<span id="x3">x3</span>
</div>
Second one:
Using getElementById
HTMLElement.prototype.wrap = function(wrapper){
this.parentNode.insertBefore(wrapper, this);
wrapper.appendChild(this);
}
var element = document.getElementById('x1');
element.wrap(document.createElement('div'));
var elementx3 = document.getElementById('x3');
elementx3.wrap(document.createElement('div'));
<div>
<span id="x1">x1</span>
<span id="x2">x2</span>
<span id="x3">x3</span>
</div>

//some DOM1 vanilla...
var parent = x1.parentElement;
//var cntnt = parent.children;
//unwrapping the container div with ancient dhtml method
parent.outerHTML = parent.innerHTML;
// wrapping selected elements with jQuery
$("#x1,#x3").wrap('<div>');
// show the end-result HTML
console.log(document.body.innerHTML);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<span id="x1"></span>
<span id="x2"></span>
<span id="x3"></span>
</div>

.wrap() and .unwrap() have never worked too well for me. Instead, I usually just wrap the elements outerHTML to wrap and use the innerHTML to unwrap. You mention a list in your comment, that's why I have a select here. Regardless how you select the spans, I think my button handler demonstrates what you are trying to achieve. This also doesn't require unique ids for each span nor does it matter how many you have.
PopulateSelect();
$('button').on('click', function() {
$('select option:selected').each(function(offset, span) {
let $span = $(`span.unwrapped:eq(${span.index - offset})`);
$span.removeClass('unwrapped')[0].outerHTML = `<div>${$span.html()}</div>`;
});
PopulateSelect();
});
function PopulateSelect() {
let options = '';
$('span.unwrapped').each(function() {
options += `<option>${this.textContent}</option>`;
});
$('select').html(options);
}
https://jsfiddle.net/8429pcpu/2/
This is a bit involved, so rather than spamming a bunch of links, feel free to ask about anything you don't understand.

Related

Add class to highlighted/selected spans, but not if mouseout happens outside of the target div

I have some spans inside of a div. The spans contain a mixture of text and emojis and each span has a unique ID.
My end-goal is to add a class to the range of spans I drag/highlight select. This would happen at mouseout I presume.
With my current code, this works fine as long as I mouseout within the container that houses the spans.
However, if I accidentally overdrag and mouseout on the text outside of the box, the final element is undefined, which is something I can easily see an end-user doing on accident.
Is there a way to ensure that even if the user mouse-outs outside of the div that contains the relevant spans, that the only "selections" recognized are the selected elements within the container div?
jQuery(document).ready(function($) {
jQuery(document).on('mouseup', function(e) {
const sel = document.getSelection();
if(jQuery(sel.focusNode.parentElement).hasClass('subword')) {
var lastnodeid = jQuery(sel.focusNode.parentElement).attr('id');
} else if(jQuery(sel.focusNode).hasClass('subemoji')) {
var lastnodeid = jQuery(sel.focusNode).attr('id');
}
if(jQuery(sel.anchorNode.parentElement).hasClass('subword')) {
var firstnodeid = jQuery(sel.anchorNode.parentElement).attr('id');
} else if(jQuery(sel.anchorNode).hasClass('subemoji')) {
var firstnodeid = jQuery(sel.anchorNode).attr('id');
}
console.log('FIRST NODE ID');
console.log(firstnodeid);
console.log('LAST NODE ID');
console.log(lastnodeid);
$("#"+firstnodeid).nextUntil("#"+lastnodeid).addClass("subselected");
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div style="padding:10px;background-color:red" id="maindiv">
<div style="padding:10px;background:green" id="innerbox">
<span>If accidentally mouseout on this text, no good as the final "selection" will be undefined so I can't get the correct range..</span>
<div style="padding:10px; border: solid 1px #333333;width:100px;background-color:white" class="subbox">
<span id="item1" class="subword">Drag</span>
<span class="swspc" data-type="space"> </span>
<span id="item2" class="subword">Select</span>
<span class="swspc" data-type="space"> </span>
<span id="item3" class="subemoji"><img style="width:10px" src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ftse1.mm.bing.net%2Fth%3Fid%3DOIP.PwF3M5BEW5hKPHFvl2l0ogHaHa%26pid%3DApi&f=1&ipt=1eb8cf6043603bf3df6cccf015fe4c37ebae980a8ad6c9ac7e04ebf8c7f6bad0&ipo=images"></span>
<span class="swspc" data-type="space"> </span>
<span id="item4" class="subword">These</span>
</div>
</div>
</div>

Is there any inbuild function in javascript to select last element with using class selector or element selector?

similar type of question is already asked link.but my question is bit diffrent.
in my program frequently occur new element with using dom. here my question is
is there any built in function in javascript that i can select last element frequently?
here is an example
var para = document.createElement("div");
var node = document.createTextNode("This is new.");
para.appendChild(node);
var element = document.getElementById("div1");
element.appendChild(para);
given program append div element frequently and also i want to select div element frequently. similar with a class
thankyou in advance
Use querySelectorAll and pass the class selector. Then target the last element and do whatever
let getAllElem = document.querySelectorAll('.test');
getAllElem[getAllElem.length - 1].classList.add('green')
.green {
color: green
}
<div class="test">1</div>
<div class="test">2</div>
<div class="test">3</div>
<div class="test">4</div>
<div class="test">5</div>
<div class="test">6</div>
no there is not any built in function in java script but u should try below logic and use it with jquery like $(last_selector(".lastclass")).click(); for select last class and $(last_selector("div")).click(); for elect last element
function last_selector(select){
if(select[0]=="."){
var allSelect = document.getElementsByClassName(select.slice(1));
}
else{
var allSelect = document.getElementsByTagName(select);
}
return allSelect[allSelect.length-1];
}
console.log(last_selector("div"))
console.log(last_selector(".last"))
<div>hello</div>
<div>hello</div>
<div class="last">last class</div>
<div>last element</div>
It will give last span text inside every Div using $(elementName).children("span:last").text()
$(document).ready(function(){
console.log($('div').children("span:last").text())
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<span class="time">2016</span><br>
<span class="time">2017</span><br>
<span class="time">2018</span><br>
<span class="time">2019</span><br>
<span class="time">2020</span><br>
<span class="time">2021</span><br>
<span class="time">2022</span><br>
<span class="time">2023</span><br>
<span class="time">2024</span> <br>
</div>

Combine different content inside tag

I want to build such construction using jQuery:
<i class="fa fa-shopping-cart"></i>Add to cart
My jQuery code, which is responsible for this line, looks like that:
var a2 = $('<a>').attr("href", "add_to_cart:" + item['id']).text('Add to cart');
a2.addClass("btn btn-default add-to-cart");
var i1 = $('<i></i>');
i1.addClass("fa fa-shopping-cart");
a2.append(i1);
But result does not contain <i> element.
I tried to append <i> using .html function, but in this case text disappears.
How to make <a> element contain both tag and text after it?
Thanks for your answers
hahaha you forgot the last one...
$(".test").html(a2);
and the parent content
<div class="test"></div>
$(document).ready(function() {
var a2 = $('<a>').attr("href", "add_to_cart:").text('Add to cart');
a2.addClass("btn btn-default add-to-cart");
var i1 = $('<i>iiiiiiiiiiii</i>');
i1.addClass("fa fa-shopping-cart");
a2.prepend(i1);
$(".test").html(a2);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test"></div>

JQuery - Detecting which div box was clicked

I'm trying to detect which div box was clicked with JQuery and I'm not sure what I am doing wrong. I'm aware that I can approach this in a different method by directly calling functions if a div box is clicked, but I wish to do it this way by first determining what was clicked.
$(document).ready(function() {
$(document).click(function(event){
var id = event.target.id; //looks for the id of what was clicked
if (id != "myDivBox"){
callAFunction();
} else {
callSomeOtherFunction();
}
});
});
Thank you for any suggestions!
You could use the closest function to get the first ancestor element with tag div, see following example:
$(document).ready(function() {
$(document).click(function(event){
var parentDiv = $(event.target).closest("div");
console.log(parentDiv.prop("id"));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div1">
<span id="span1">Test1</span>
</div>
<div id="div2">
<span id="span2">Test2</span>
</div>
I hope it helps you. Bye.
No matter what you click, you will always know the element that was clicked:
$("#myDiv").click(function(e){
alert("I was pressed by " + e.target.id);
});
Knowing that you don't want to add this to every div, and you have your click on your document, you'll need to figure out what divs can be reported as "clicked".
In order to do this you'll either need a strict hierarchy of elements in your DOM (which is anoyingly bad) or you can decorate "clickable" div's with a specific class.
Fiddle - similar to below. https://jsfiddle.net/us6968Ld/
I would use closest in Jquery to get the result you want.
$(document).ready(function() {
$(document).click(function(event){
var id = event.target.id;
var clickDiv = $(event.target).closest('div[class="clickable"]');
alert(clickDiv[0].id);
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div class="clickable" id="clickable1">
<span id="foo"> click me - Foo - clickable 1</span>
</div>
<div id="notClickable1">
<div class="clickable" id="clickable2">
<span id="span1">
Click Me Inside Span 1 - clickable 2
</span>
</div>
<div class="clickable" id="clickable3">
<div id="notClickable2">
<div id="notClickable3">
<span id="click me">Click Me - clickable 3</span>
</div>
</div>
</div>
</div>
try this:
$('div').click(function() {
alert($(this).attr('id'));
});
https://jsfiddle.net/1ct0kv55/1/

AppendChild a element above a cerain element

So i have a div element which will be filled dynamically with others divs using the appendChild Method, this should display a list. The User is now able to sort that list with the JqueryUI Sortable option.I also added some sortable option attribues like follows:
Options:
$("#NameContainer").sortable("option", "axis", "y");
$("#NameContainer").sortable( "option", "containment", "parent" );
LIST
<div id="NameContainer" class="ui-widget">
<div id="Name_1">John</div>
<div id="Name_2">Jack</div>
<div id="Name_3">Charlie</div>
<div id="Name_4">Sawyer</div>
<div id="Name_5">Yin</div>
<div id="Name_6">Ben</div>
</div>
Now comes my problem. The appendChild always inserts the new div at the bottom of the container but i want to to add some space at the bottom of to the Container Div with a "br" or something like that. I want to add that space to make sure that when the user sorts the last item of that list it will get sorted correctly because the "containment" bounds sometimes wont allow to sort under the last item.
<div id="NameContainer" class="ui-widget">
<div id="Name_1">John</div>
<div id="Name_2">Jack</div>
<div id="Name_3">Charlie</div>
<div id="Name_4">Sawyer</div>
<div id="Name_5">Yin</div>
<div id="Name_6">Ben</div>
<br><!--SPACEHOLDER-->
</div>
So here comes my Question is there away to appendChild above a certain element? Like a "br" "div" or "p"?
Try this instead of appendChild:
Please note I have used random value to add in div as I don't have your dynamic value.
check fiddle: https://jsfiddle.net/dqx9nbcy/
<div id="NameContainer" class="ui-widget">
<div id="divspacer"></div>
</div>
<button id="btn">ADD Element</button>
$(document).ready(function(){
$("#btn").click(function(){
var parentnode = document.getElementById("NameContainer");
var existnode = document.getElementById("divspacer");
var rand = Math.floor((Math.random() * 10) + 1);
var newName = document.createElement("div");
newName.setAttribute("id", rand);
newName.setAttribute("value", rand);
newName.setAttribute("class","ui-widget-content");
newName.innerHTML = rand;
parentnode.insertBefore(newName,existnode);
});
});
refer http://api.jquery.com/appendto/ but you need to make sure that your are targeting right tag.
You can try with this code snippet.
HTML Snippet
<div id="NameContainer" class="ui-widget">
<div id="Name1">Name1</div>
<div id="Name2">Name2</div>
<div id="Name3">Name3</div>
<div id="Name4">Name4</div>
<br>
<br>
</div>
Javascript Snippet
$(document).ready(function(){
$("#btn").click(function(){
var containerDiv= $("#NameContainer");
var childList = containerDiv.children("div");
var newElementid = childList.length;
var newName = document.createElement("div");
newName.setAttribute("id", "Name"+(newElementid+1));
newName.setAttribute("value", "Name"+(newElementid+1));
newName.setAttribute("class","ui-widget-content");
newName.innerHTML = "Name"+(newElementid+1);
$(childList[childList.length-1]).after(newName);
});
});
This is specific to a situation where there are some elements in the initial list. The same can be modified for dynamic list of implementation by validating that childList.length is != 0 before using the same.

Categories

Resources