HTML
<ul class="tabbox">
<li></li>
,
<li></li>
,
<li></li>
</ul>
JQuery (My Idea - does NOT work)
$(".tabbox").replace(',' , ''); // This was my idea, and it does not work ..
How can I remove the , from the < ul > ?
It seems to me that you're asking the wrong question.
If the intent is to remove the spurious text nodes (which happen to contain commas) from between the <li> nodes, you should do this:
$('.tabbox').contents().filter(function() {
return (this.nodeType === 3);
}).remove();
Working demo at http://jsfiddle.net/alnitak/gN7yM/
Note the use of .contents() to ensure that text nodes are included in the results.
If instead you want to purify the code to remove anything that isn't an <li> from the <ul>, use this:
$('.tabbox').contents().not(function() {
return (this instanceof HTMLLIElement);
}).remove();
FWIW, since #ShadowWizard reports that this doesn't with with IE < 8.0 I tried:
$('.tabbox').contents().not('li').remove()
and it didn't work. Reading the jQuery source it seems that pure string selectors completely ignore text nodes, but this does work:
$('.tabbox').contents().not(function() {
return $(this).is('li');
}).remove();
EDIT I've changed a couple of the examples above to use .not() instead of .filter() so as to remove the double negative.
One way to clean the list and leave only the list items is such code:
var list = $(".tabbox");
var items = $(".tabbox li");
list.html("");
items.each(function() {
list.append($(this));
});
Live test case: http://jsfiddle.net/TS8Sd/
This will not only remove comma but any other text or elements that do not belong there.
var tabbox = $(".tabbox"),
tabHtml = tabbox.html();
tabbox.html(tabHtml.replace(/,/g , ''));
This would replace all of them.
EDIT:
Although, why would you have a ',' after each li?
var tabHtml = $(".tabbox").html();
$(".tabbox").html(tabHtml.replace(/,/g , '')); //#Tomgrohl already answered it
My example makes use of the function parameter for .html().
$('.tabbox').html(function (index, oldhtml) {
return oldhtml.replace(/,/g, '');
});
jsFiddle Demo
Related
let's assume I have this code
<p>FirstLevelP
<span>SecondLevelSpan</span>
</p>
<p>FirstLevelP
<span>SecondLevelSpan
<p>ThirdLevelP</p>
</span>
</p>
Is it possible to iterate through every element that I have right now, but only get the content, that's in the direct node of it, modify the text and then have it in the original content?
Example, If I go through every $('p').each and would extract the text I would also get the text inside the span.
Basically this:
FirstelElement: FirstLevelPSecondLevelSpan
SecondElement: SecondLevelSpanSecondLevelSpanThirdLevelP
But I want to have it like this
FirstelElement: FirstLevelP
SecondElement: SecondLevelSpan
ThirdElement: FirstLevelP
FourthElement: SecondLevelSpan
FifthElement: ThirdLevelP
Is this possible?
In my research I already found this answer here
$("#foo")
.clone() //clone the element
.children() //select all the children
.remove() //remove all the children
.end() //again go back to selected element
.text();
But this would only solve half of my problems. I would still need to modify the text in the original content! Thanks in advance guys.
EDIT FOR CLARIFICATION
So basically, want I want to achieve is something like this:
For every element, I want to check if there is a dot at the end. If not I want to add one. I already managed to do this for headlines, like this:
foreach (pq($content)->filter(':header') as $headline) {
if (substr(pq($headline)->text(), 0, -1) != '.') {
$content = preg_replace('#(' . pq($headline) . ')#', pq($headline) . '.', pq($content));
}
}
The problem, as I stated, is, that when I have nested elements it would add the dot after the whole element, and not after each sub element if neccessary.
To work with my "assumed" code, it should look like this
<p>FirstLevelP.
<span>SecondLevelSpan.</span>
</p>
<p>FirstLevelP.
<span>SecondLevelSpan.
<p>ThirdLevelP.</p>
</span>
</p>
But unfortunatley, it currently looks like this
<p>FirstLevelP
<span>SecondLevelSpan</span>.
</p>
<p>FirstLevelP
<span>SecondLevelSpan
<p>ThirdLevelP</p>
</span>.
</p>
Note the dots.
finding and changing text without child elements works this ways:
// search every element
$("body *").each(function(index, el) {
// find first text node
var node = $(el).contents().filter(function() {
return this.nodeType === 3;
})[0];
// change text
node.textContent = "new text";
});
Edit, Updated
Try
$("body *").each(function (i, el) {
if ($(el).is("p, span")) {
$(el).text(function (idx, text) {
var t = text.split("\n")[0];
// if `text` string's last character is not `.`
// concat `.` to `text` string ,
// return `text` original string's with `.` added
return t.slice(-1) !== "." ? t + "." : t
})
}
})
$("body *").each(function (i, el) {
if ($(el).is("p, span")) {
$(el).text(function (idx, text) {
var t = text.split("\n")[0];
return t.slice(-1) !== "." ? t + "." : t
})
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>FirstLevelP
<span>SecondLevelSpan</span>
</p>
<p>FirstLevelP
<span>SecondLevelSpan
<p>ThirdLevelP</p>
</span>
</p>
I have jQuery read some text then add a class based on the value of this text. (The text read is rendered by my CMS).
The HTML Looks like this:
<ul class="zoneSubscriptions">
<li>
<ul>
<li class="zoneName">Professional</li>
<li>Never</li>
</ul>
</li>
<li>
<ul>
<li class="zoneName">RTTM</li>
<li>Never</li>
</ul>
</li>
</ul>
I want to read the text of class="zoneName"and add a class based on this.
JS to do this:
$(function() {
var zone = $( ".zoneName" ).text();
$( "#zones" ).addClass( zone );
});
This works without issue, however, I need it to add two classes, Professional and RTTM. What it adds is ProfessionalRTTM.
My question is how would I add the classes while keeping a space between the words?
In other words it should render like this: class="Professional RTTM" not class="ProfessionalRTTM"
Note: In my example there are two "zoneName"s. There could be anywhere from 1 to 5 or more when used live.
Try iterating the tags:
var $zones = $("#zones");
$(".zoneName").each(function () {
$zones.addClass( $(this).text() );
});
Also possible (if you want to reuse the list of class names)
var classes = [];
$(".zoneName").each(function () {
classes.push($(this).text());
});
$("#zones").addClass(classes.join(" "));
You're calling .text() on multiple results which is joining them together.
Why not do something like this instead:
var zone = $( ".zoneName" ).each(function(){
$("#zones").addClass($(this).text());
});
Find all your .zoneNames and then call addClass for each one.
jsFiddle example
You need to iterate across the .zoneNames, otherwise your .text() will be a one undivided string (unless you have whitespace in there)
$(".zoneName").each(function() {
$("#zones").addClass($(this).text());
});
You can use the callback function of addClass(), and use map() to get an array of the text, then simply join with a space:
$('#zones').addClass(function() {
return $('.zoneName').map(function() {
return $(this).text();
}).get().join(' ');
});
Here's a fiddle
I am looking for a way to wrap, with jQuery, an element into a comment, like:
<!--
<div class="my_element"></div>
-->
and also a way to remove the comments.
Is this possible?
To wrap an element with comment, or more specifically to replace an element with a comment node having that element's HTML:
my_element_jq = $('.my_element');
comment = document.createComment(my_element_jq.get(0).outerHTML);
my_element_jq.replaceWith(comment);
To switch it back:
$(comment).replaceWith(comment.nodeValue);
If you don't have the reference to the comment node then you need to traverse the DOM tree and check nodeType of each node. If its value is 8 then it is a comment.
For example:
<div id="foo">
<div>bar</div>
<!-- <div>hello world!</div> -->
<div>bar</div>
</div>
JavaScript:
// .contents() returns the children of each element in the set of matched elements,
// including text and comment nodes.
$("#foo").contents().each(function(index, node) {
if (node.nodeType == 8) {
// node is a comment
$(node).replaceWith(node.nodeValue);
}
});
You can comment the element out by doing the following:
function comment(element){
element.wrap(function() {
return '<!--' + this.outerHTML + '"-->';
});
}
DEMO:
http://jsfiddle.net/dirtyd77/THBpD/27/
I'm impresed nobody gave the following solution. The following solution require a container. This container will have inside, the commented / uncommented code.
function comment(element) {
element.html('<!--' + element.html() + '-->')
}
function uncomment(element) {
element.html(element.html().substring(4, element.html().length - 3))
}
function isCommented(element) {
return element.html().substring(0, 4) == '<!--';
}
Example: https://jsfiddle.net/ConsoleTVs/r6bm5nhz/
For wrapping?
function wrap(jQueryElement){
jQueryElement.before("<!--").after("-->");
}
Not sure how successful you'd be finding the comments once wrapped though. A text search on the body element using regular expressions is an option.
Or this - is it possible to remove an html comment from dom using jquery
I would like the number of item's in my list to be numbered from 10 --> 0
I have the following code:
<ul class="StoryBoard" id="StoryBoard">
{#storylines}
<li>{text|bl|s}</li>
{/storylines}
</ul>
An example of how this would render in the browser would be:
<ul class="StoryBoard" id="StoryBoard">
<li>Test</li>
<li>Test</li>
<li>Test</li>
<li>Test</li>
</ul>
However I would like it to render like this:
<ul class="StoryBoard" id="StoryBoard">
<li>Test (10)</li>
<li>Test (9)</li>
<li>Test (8)</li>
<li>Test (7)</li>
</ul>
There will always be a maximum of 10 items
Since you're using dustjs, you have access to an #idx helper when iterating:
{#storylines}
<li>{text|bl|s} ({#idx}{.}{/idx})</li>
{/storylines}
From the dustjs docs:
The idx tag passes the numerical index of the current element to the enclosed block.
EDIT: I didn't read your question closely enough - it looks like you're looking for a descending count. the idx helper will count up.
EDIT AGAIN: In the comments it was asked if you could just do {#idx}{10 - .}{/idx}.
The answer to that is no, because dust doesn't evaluate arbitrary expressions. But if you look at the source of dust.helpers.idx, which is where the tag comes from, it's just:
function (chunk, context, bodies) {
return bodies.block(chunk, context.push(context.stack.index))
}
It's pushing a new context with the value of the current index of the iteration. It turns out that the context.stack object has an attribute of that gives you the number of items in the stack, so you can write your own negidx helper:
dust.helpers.negidx = function(chunk, context, bodies) {
return bodies.block(chunk, context.push(context.stack.of - context.stack.index));
};
At this point, the following will accomplish what the original question asked:
{#storylines}
<li>{text|bl|s} ({#negidx}{.}{/negidx})</li>
{/storylines}
And here's a fiddle.
I'd suggest:
$('#StoryBoard li').text(function(i,t) { return t + ' (' + (10 - i )+ ')'});
JS Fiddle demo.
The anonymous function in the text() method, has two parameters i (the index of the current element (as it iterates over all the elements matched by the selector)) and t, which is the text of the current element.
This, then, returns the current text after appending an opening-bracket, the index and a closing bracket.
References:
text().
$('#StoryBoard').find('li').each(function(i){
$(this).append(' ' + (10 - i ));
});
Test? : http://jsbin.com/aduqix/1/edit
here's a demo http://jsfiddle.net/GPEth/ - in jQuery
I'm not sure if you want this fix in dust.js or jQuery
$(function () {
var $li = $('ul#StoryBoard li'),
count = $li.size();
$li.each(function (index) {
$(this).text($(this).text() + (count - index));
})
});
I need to know with jQuery if a certain value is on a <li> tag on an <ul>with a certain tag:
<ul id="timeline">
<li>MyValue</li>
<li>MySecondValue</li>
</ul>
How can I check with jQuery if for example, MySecondvalue, is already on the the <ul>with the timeline id? Thanks!
if ( $('ul li:contains("MySecondValue")').length ) {
//exists
}
$("ul li").filter(function() {
return $(this).text() == "MySecondValue";
}).length;
If that expression returns 0, it is not on the list. Otherwise, it is.
do something like this:
$('ul li').each(function(){
if($(this).text()=='MySecondvalue') alert('already exists');
}
Not quite jQuery-ish, but depending on the number of elements to filter, this could be the most performant way:
function alreadyInTimeline(text) {
return ($('#timeline').html().match(new RegExp('\>(' + text + ')\<')) !== null);
}
alert(alreadyInTimeline('MyValue'));
cf. the performance comparison of the answers given here so far on for a rather small timeline
Edit: Disregard this, I just updated the jsperf test to use the same selectors for all cases and it turns out that I was wrong.