How do I change the last textual node child in JavaScript - javascript

My Solution (EDIT : 2015-12-08) :
// FIRST WE GET THE PARENT ELEMENT
var parentEstim = document.getElementById("onglet_estim");
// MAKE A TABLE OF HIS CHILD
var enfantsEstim = parentEstim.childNodes;
// KNOW HOW MANY CHILDREN THE PARENT ELEMENT HAVE WITH .length
var Nbenfants = enfantsEstim.length;
....
for (var i = 0; i <= Nbenfants; i++) {
// IF THE CHILD ELEMENT [i] IS A HTML ELEMENT
if (enfantsEstim[i].nodeType === 1) {
enfantsEstim[i].lastChild.data = ''; // REMOVE LAST TEXT NODE
enfantsEstim[i].classList.remove('isActive');
}
document.getElementById('onglet_estim').style.width = '220px';
ClickedElement.className = 'isActive';
// ADD NEW VALUE IN THE LAST TEXT NODE FOR THE CLICKED ELEMENT
ClickedElement.lastChild.data = ' Gares';
}
DEMO : http://codepen.io/Zedash/details/pjMEMY
The Problem :
I have a little problem, I want to change the last textual node child value of a link <a> element.
For exemple, for the first link, we see the word "Saisie" wrote in it and I want to remove the text in this element if the user click on an other link and add a right text for the clicked element.
function changeInputAdresse(ClassName) {
if (ClassName.className !== 'isActive') {
ClassName.className = 'isActive';
switch(ClassName.id) {
case 'linkGares' :
ClassName.insertAdjacentHTML('beforeEnd',' Gares');
ClassName.previousElementSibling.classList.remove('isActive');
ClassName.nextElementSibling.classList.remove('isActive');
ClassName.previousElementSibling.insertAdjacentHTML('beforeEnd','');
ClassName.nextElementSibling.insertAdjacentHTML('beforeEnd','');
break;
}
}
};
// THE CODE IS NOT FINISHED OF COURSE !
a {
text-decoration:none;
color:#000;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet"/>
<a id="linkSaisie" class="isActive" href="#n" onclick="changeInputAdresse(this);"><i class="fa fa-map-marker"></i> Adresse</a>
<a id="linkGares" href="#n" onclick="changeInputAdresse(this);"><i class="fa fa-train"></i></a>
<a id="linkAeroports" href="#n" onclick="changeInputAdresse(this);"><i class="fa fa-plane"></i></a>
<a id="linkLoisirs" href="#n" onclick="changeInputAdresse(this);"><i class="fa fa-fort-awesome"></i></a>
<!--THE PART OF CODE WHERE I HAVE SOME PROBLEMS-->
Thanks for your ansewers ! :)

I don't quite get what you exactly would like, but to target and change the element after an italic I would use this jQuery and vanilla JS combination:
$("#myLink").find(">i").get(0).nextSibling.nodeValue = "Changed text";
DEMO: http://jsfiddle.net/u9jq2bvy/
IIRC there is no jQuery method to target a text node, so you need some native JS.
Please let me know if I misunderstood the question and I'm gonna delete my answer.
UPDATE
Based on the comment here is a possible solution.
$(document).on("click", ".myLink", function() {
// clear all texts
$(this).parent().find("a>span").text("");
$(this).addClass("active");
$(this).children("span").text("Active text");
});
DEMO http://jsfiddle.net/u9jq2bvy/1
And here is a modified version which simply shows/hides the spans.
DEMO http://jsfiddle.net/u9jq2bvy/3/

You can use jQuery siblings
changeInputAdresse(element){
element = $(element)
if(!element.hasClass('isActive')){
element.addClass('isActive');
element.siblings().removeClass('isActive');
element.text(element.attr('id').replace('link','')) //if that's the way you get value
element.siblings().text('')
}
}

Related

Individually change element inside of a class through their ID [duplicate]

I am wanting something similar to this person, except the element I want to match might not be a direct sibling.
If I had this HTML, for example,
<h3>
<span>
<b>Whaddup?</b>
</span>
</h3>
<h3>
<span>
<b>Hello</b>
</span>
</h3>
<div>
<div>
<img />
</div>
<span id="me"></span>
</div>
<h3>
<span>
<b>Goodbye</b>
</span>
</h3>
I would want to be able to do something like this:
var link = $("#me").closestPreviousElement("h3 span b");
console.log(link.text()); //"Hello"
Is there an easy way to do this in jQuery?
EDIT: I should have made my specification a little bit clearer. $("#me") may or may not have a parent div. The code should not assume that it does. I don't necessarily know anything about the surrounding elements.
var link = $("#me").closest(":has(h3 span b)").find('h3 span b');
Example: http://jsfiddle.net/e27r8/
This uses the closest()[docs] method to get the first ancestor that has a nested h3 span b, then does a .find().
Of course you could have multiple matches.
Otherwise, you're looking at doing a more direct traversal.
var link = $("#me").closest("h3 + div").prev().find('span b');
edit: This one works with your updated HTML.
Example: http://jsfiddle.net/e27r8/2/
EDIT: Updated to deal with updated question.
var link = $("#me").closest("h3 + *").prev().find('span b');
This makes the targeted element for .closest() generic, so that even if there is no parent, it will still work.
Example: http://jsfiddle.net/e27r8/4/
see http://api.jquery.com/prev/
var link = $("#me").parent("div").prev("h3").find("b");
alert(link.text());
see http://jsfiddle.net/gBwLq/
I know this is old, but was hunting for the same thing and ended up coming up with another solution which is fairly concise andsimple. Here's my way of finding the next or previous element, taking into account traversal over elements that aren't of the type we're looking for:
var ClosestPrev = $( StartObject ).prevAll( '.selectorClass' ).first();
var ClosestNext = $( StartObject ).nextAll( '.selectorClass' ).first();
I'm not 100% sure of the order that the collection from the nextAll/prevAll functions return, but in my test case, it appears that the array is in the direction expected. Might be helpful if someone could clarify the internals of jquery for that for a strong guarantee of reliability.
No, there is no "easy" way. Your best bet would be to do a loop where you first check each previous sibling, then move to the parent node and all of its previous siblings.
You'll need to break the selector into two, 1 to check if the current node could be the top level node in your selector, and 1 to check if it's descendants match.
Edit: This might as well be a plugin. You can use this with any selector in any HTML:
(function($) {
$.fn.closestPrior = function(selector) {
selector = selector.replace(/^\s+|\s+$/g, "");
var combinator = selector.search(/[ +~>]|$/);
var parent = selector.substr(0, combinator);
var children = selector.substr(combinator);
var el = this;
var match = $();
while (el.length && !match.length) {
el = el.prev();
if (!el.length) {
var par = el.parent();
// Don't use the parent - you've already checked all of the previous
// elements in this parent, move to its previous sibling, if any.
while (par.length && !par.prev().length) {
par = par.parent();
}
el = par.prev();
if (!el.length) {
break;
}
}
if (el.is(parent) && el.find(children).length) {
match = el.find(children).last();
}
else if (el.find(selector).length) {
match = el.find(selector).last();
}
}
return match;
}
})(jQuery);
var link = $("#me").closest(":has(h3 span b)").find('span b').text();

changing innerHTML of child element using javascript

I would like to change my icon from expand_more to expand_less in following code
<li class="dropdown-bt" onclick="dropdown('content');">
<a>dropdown-content <i class="material-icons">expand_more</i></a>
</li>
I am going to use same code multiple times so it would be better to using function multiple times. I thought of using ID for every piece of code but it would be to hectic. So I want to write single function do it but I don't know how, so please help.
Just pass an object event as a parameter, say e to your dropdown() and use the textContent property to retrieve the current element content, check it's value and replace the content with another text content like this:
var btn = document.getElementById("dropdownBt");
function dropdown(e) {
var innerText = e.target.children[0];
if(innerText.textContent == "expand_more") {
innerText.textContent = "expand_less";
} else {
innerText.textContent = "expand_more";
}
}
btn.addEventListener('click', dropdown);
<li class="dropdown-bt" id="dropdownBt"><a>dropdown-content <i class="material-icons">expand_more</i></a></li>

Using jQuery to load icon based on <label> contents

I have a website where the content is dynamically loaded from a database. The contents varies for each label.
One may be generated as General:, whilst another may be generated as TV:.
My question is, is there any way that jQuery could (based on the HTML output for the label) replace the NAME: with a font awesome icon?
So for example:
<label>TV:</label>
Would become:
<i class="fa fa-film fa-2x"></i>
Try
var icons = {
'tv:': 'film',
'edit:': 'edit'
};
$('label').replaceWith(function () {
var text = $(this).text().trim().toLowerCase(),
icon = icons[text];
return icon ? '<i class="fa fa-' + icon + ' fa-2x"></i>' : undefined;
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.css">
<label>TV:</label>
<label>TsV:</label>
<label>EDIT:</label>
You could use the :contains selector http://api.jquery.com/contains-selector/
$("label:contains('TV')").html('<i class="fa fa-film fa-2x"></i>');
$("label:contains('TV')").html('<i class="YOUR CLASS"></i>');
or if you could add class or id in that label you could change it easily like
$("#ID").html('<i class="YOUR CLASS"></i>');
$(".CLASS").html('<i class="YOUR CLASS"></i>');
You can replace them with JQuery for example
var icons = {
"TV:" : "film"
};
var $labels = $('label');
$labels.each(function(index){
var icon = icons[$(this).text()];
$(this).replaceWith($("<i>").addClass('fa').addClass('fa-' + icon).addClass('fa-2x'));
});
And see Fiddle: http://jsfiddle.net/m19hjnoa/
You could take different aproaches on that.
My personal favorite would be to just send the right label from the server.
otherwise you could run this jQuery Script: http://jsfiddle.net/ehdgL6so/
// try to select as less elements as possible for speed
// for example if they are in a div with class foo try jQuery('div.foo label') instead
var labels = jQuery('label');
// loop throu all labels
labels.each(function() {
// get single label element
var label = jQuery(this);
// get the content (for example "TV:"
var labelContent = label.text();
// replace if the label matches
switch(labelContent) {
case 'TV:':
// if the label contains "TV:" replace the <label> with the <i> element
label.replaceWith('<i class="fa fa-film fa-2x"></i>');
break;
case 'Foo':
// if the label contains "Foo" replace foo with the <i> element
label.html('<i class="fa fa-film fa-2x"></i>');
break;
}
});
Edit:
Or as #cforcloud suggests a short Form like
// note: .html does just replace the string "TV:" but leaves the label element in the DOM, while replaceWith is the way to replace an element
// http://api.jquery.com/replacewith/
jQuery("label:contains('TV:')").replaceWith('<i class="fa fa-film fa-2x"></i>');

How to replace anchor element with the innerHTML of itself

I try to write a script based on JavaScript for replacing the current selected anchor element with it's inner HTML.
You can also find a simple running example in JSFiddle. To run the example, click on the first link, and the click the button.
So, for example, if I have the following HTML:
<p>
Wawef awef <em>replace</em> <strong>me</strong>
falwkefi4hjtinyoh gf waf eerngl nregsl ngsekdng selrgnlrekg slekngs ekgnselrg nselrg
<a href="http://www.anothersite.com/>replace me</a> klserng sreig klrewr
</p>
and I like when I click on some of the two anchors to remove the anchor with it's inner HTML. This mean, that if I click on the first anchor element, and click the appropriate button to replace the anchor the result should be like that:
<p>
Wawef awef <em>replace</em> <strong>me</strong> falwkefi4hjtinyoh gf waf eerngl
nregsl ngsekdng selrgnlrekg slekngs ekgnselrg nselrg <a href="http://www.anothersite.com/>replace me</a>
klserng sreig klrewr
</p>
My JavaScript code for this functionality is the following:
// Start tracking the click event on the document
document.addEventListener(
'click',
function(event)
{
// If right click, return
if(event.button == 2)
{
return;
}
// Get the current clicked document element
var link = event.target;
while(link && !(link instanceof HTMLAnchorElement))
{
link = link.parentNode;
}
// Get the element with ID wpf-remove-element-now
var clickedLink = document.getElementById("wpf-remove-element-now");
// If the element exists
if(clickedLink !== null)
{
// By executing this code, I am ensuring that I have only
// one anchor element in my document with this ID
// Remove the id attribute
clickedLink.removeAttribute('id');
}
// If ther is no link element
if(!link)
{
// Disable my "unlink" button
editor.commands.customunlinkcmd.disable();
// and return
return;
}
event.preventDefault();
event.stopPropagation();
// If the user has clickde on an anchor element then
// enable my "unlink" button in order to allow him to
// to replace the link if he like to.
editor.commands.customunlinkcmd.enable();
// Set the id attribute of the current selected anchor
// element to wpf-remove-element-now
link.setAttribute('id', 'wpf-remove-element-now');
}
);
var $unlink_button = document.getElementById('unlink');
$unlink_button.addEventListener(
'click',
function(event)
{
// Get the element with ID wpf-remove-element-now
var link = document.getElementById("wpf-remove-element-now");
// Create a new text node that contains the link inner HTML
var text = document.createTextNode(link.innerHTML);
// Make the replacement
link.parentNode.replaceChild(text, link);
}
);
Everything until now is correct, appart of the replacement of the link. I have try the above code, but the result I get is like the following one:
Wawef awef <em>replace</em> <strong>me</strong> falwkefi4hjtinyoh gf waf eerngl
nregsl ngsekdng selrgnlrekg slekngs ekgnselrg nselrg replace me klserng sreig klrewr
I mean the anchor is replaced with the text form of the inner HTML and not with the HTML form of the inner HTML.
So the question is, how can I do this kind of replacement.
You're creating a text node, so whatever you put in it will be interpreted as text. Instead, since you have the replacement tags predefined, you should create actual DOM elements to replace it with. Something like this could work: JSFiddle
var em_elem = document.createElement('em');
em_elem.appendChild(document.createTextNode("replace"));
var strong_elem = document.createElement('strong');
strong_elem.appendChild(document.createTextNode("me"));
var container_span = document.createElement('span');
container_span.appendChild(em_elem);
container_span.appendChild(strong_elem);
// Make the replacement
link.parentNode.replaceChild(container_span, link);
The answer was much simpler that I thought. I placed the solution below for anybody that need an equivalent solution :) :
$unlink_button.addEventListener(
'click',
function(event)
{
// Get the element with ID wpf-remove-element-now
var link = document.getElementById("wpf-remove-element-now");
// By this code you replace the link outeHTML (the link itself) with
// the link innerHTML (anything inside the link)
link.outerHTML = link.innerHTML;
}
);
Here you can find the running solution : JSFiddle
Note: The inspiration for this solution found in the web page.

Select only the root item of a html node

I have this html code.
<div class="breadcrumb">
Home
<a class="breadcrumb" href="#">About</a>
<a class="breadcrumb" href="#">History</a>
Message from our Founding Members
</div>
Using javascript I want to get the text from the div ".breadcrumb". The problem is the a tag under the div also has a class with the same name, when I run this code:
var names = document.querySelectorAll('.breadcrumb');
return [].map.call(names, function(name) {
return name.textContent;
});
My first element of the array gets the textContent of all the a elements and also the div.
How can I do to get the text of only the div. In this case I want to return only "Message from our Founding Members".
Is there a way to select only the root item of the html, when they have all the same class ?
Thanks
If you want to get the text from the <a> tags with the class="breadcrumb", you can do that by using more specific selectors that include the tag type like this:
var items = document.querySelectorAll("div.breadcrumb a.breadcrumb");
var text = [];
for (var i = 0; i < items.length; i++) {
text.push(items[i].textContent);
}
Working demo: http://jsfiddle.net/jfriend00/kVwH8/
If, what you're trying to do is to get the "Message from our Founding Members" text (I wasn't entirely clear from your original question), then you can do that like this::
var items = document.querySelectorAll("div.breadcrumb a.breadcrumb");
// get node after the last item (that should be the desired text node)
var txtNode = items[items.length - 1].nextSibling;
console.log(txtNode.nodeValue); // Message from our Founding Members
Working demo: http://jsfiddle.net/jfriend00/kynuE/
use div.breadcrumb because that will give you divs with class breadcrumb, not a tags.
You can do this:
var names = document.querySelectorAll('div.breadcrumb')[0].childNodes;
var text = Array.prototype.reduce.call(names,function(prev,node){
if(node.nodeType === 3) return (prev || '' + node.textContent.trim());
});
console.log(text);
There are a lot of ES5 stuff here like trim and reduce so better have those polyfills handy.

Categories