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
Related
I need a JavaScript or jQuery way of extracting the Class name of DIV element by the text it contains.
Let's illustrate. If I had let's say following code:
<div class="_className">UniqueText</div>
I need to to know how to programmatically do something like this:
getClassNameWhereText("UniqueText");
In this case output should be:
_className
Is there a way to do this?
JQuery :contains selector select element has specific text but it isn't exact. For example
$("div:contains(UniqueText)")
Select both of bottom divs
<div class="_className">UniqueText</div>
<div class="_className2">UniqueText2</div>
You can use .filter() to filter selected element by text.
var className = $("*").filter(function(){
return $(this).text() == "UniqueText";
}).attr("class");
var className = $("*").filter(function(){
return $(this).text() == "UniqueText";
}).attr("class");
console.log(className);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="_className">UniqueText</div>
<div class="_className2">UniqueText2</div>
By getting all the div with each function you can search through all the divs and place a condition in which you the value of the div is equal to the particular text that you want to find. Then get the class name by using .attr('class').
$( "div" ).each(function(){
if($(this).text() == "UniqueText"){
var output = $(this).attr('class');
$(".output").html(output);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="_classname">UniqueText</div>
<div class="output"></div>
It might be a bit long for a code but it gets the work done nicely. :)
You can use :contains(word)
var className = $( "div:contains('John')" ).attr("class");
console.log(className)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="foo">John Resig</div>
<div class="bar">George Martin</div>
<div class="foo">Malcom John Sinclair</div>
<div class="baz">J. Ohn</div>
You can keep an id for your div, as per your information your text will be unique.
<div id="UniqueText" class="_className">UniqueText</div>
and the js code will be
function getClassNameWhereText(text){
var className = $('#'+text).attr('class');
console.log(className);
}
UPDATE : if you want to using contains
then you can do this,
function getClassNameWhereText(text){
var val = document.getElementById(text).value;
if(text.indexOf(val)>=0){
var className = $('#'+text).attr('class');
console.log(className);
}
}
This should be faster than using jQuery (but a bit more to type):
var xpath = "//div[text()='UniqueText']";
var result = document.evaluate(xpath,
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE);
var node = result.singleNodeValue;
if (node) {
console.log(node.className);
} else {
console.error("Not found!");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="_className">UniqueText</div>
The reason is, browser's CSS selectors don't support :contains selector, and jQuery needs to emulate it by checking every node matching the rest of the selector. Ditto for using .filter. But XPath is done natively by the browser.
You also cannot specify exact match using the jQuery :contains, like here. If substring matching was indeed needed, you can change the XPath:
var xpath = "//div[contains(text(),'UniqueText')]";
XPath is very powerful, but a bit finicky and largely unknown, so I find it is very under-utilised, even when its use would be a perfect fit.
I want to be able to remove HTML elements if they contain no content.
Let's say we have some markup and are targeting all 'collapse' classes:
<div class='collapse'>[CONTENT?]</div>
If there is some content then don't do anything.
But if there is no content - no string characters or whitespace - then remove the div element completely.
This is easy to implement in the simple cases but with nested content it's slightly more more tricky.
Here is a demo, if you try removing the [CONTENTX?] strings and then seeing what the HTML structure is you'll notice that it doesn't work completely.
If a div only has other divs with no content then that should be treated as no characters or whitespace.
If we remove all [CONTENTX?] strings then we should see no HTML structure.
What ways are there to handle this?
jsFiddle: http://jsfiddle.net/97udq/
HTML:
<div id='container'>
<div class='collapse'>
[CONTENT1?]
</div>
<div class='collapse'>
[CONTENT2?]
<div class='collapse'>
[CONTENT3?]
<div class='collapse'>[CONTENT4?]</div>
<div class='collapse'>[CONTENT5?]</div>
</div>
</div>
</div>
Javascript:
$(function(){
// function
collapse();
// Show HTML structure
alert($('#container').html());
});
function collapse(){
// Loop thru all collapse elements
$('.collapse').each(function(){
// Check for pure whitespace
if($(this).html().replace(/\s+/g, '').length==0){
// Nothing to see, so remove.
$(this).remove();
}
});
}
CSS:
.collapse{
height:20px;
border:1px solid red;
}
I think this does the job;
It just uses text() instead of html();
Here's the documentation.
This one adds the trim(), but I thik that's not what you want.
function collapse(){
$('.collapse').each(function(){
if($(this).text().length==0){
$(this).remove();
}
});
}
Here's another way of accomplishing what you want. It recurses down the DOM pruning nodes from the bottom up. Hope this helps.
function prune(root) {
$.each($(root).children(), function(){
prune($(this));
});
if($(root).html().replace(/\s+/g, '').length==0 && $(root).hasClass("collapse")){
$(root).detach();
}
}
Code integrated into your JSFiddle
You need to recreate the .each() loop, but reversed. Just like that :
function collapse(){
var el = $('.collapse');
for(var i = el.length - 1; i >= 0; i--){
if(el[i].innerHTML.replace(/\s+/g, '').length==0){
$(el[i]).remove();
}
}
}
It will remove the childrens first, then check for parent.
Here a fiddle : http://jsfiddle.net/97udq/5/
EDIT :
I missunderstood your question, here's the right solution :
function collapse(){
$('.collapse').each(function(){
var $this = $(this)
var clone = $this.clone();
clone.children().remove();
if(clone.html().replace(/\s+/g, '').length==0){
$this.children().appendTo($this.parent());
$this.remove()
}
})
}
Basicly, you clone the current div, remove its children and then check if there is some text. If there's none, you append his children to his parent
Fiddle : http://jsfiddle.net/97udq/9/
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
I need to get the value of the content attribute of a certain meta tag.
var someContent = $("meta[name=someKindOfId]").attr("content");
is how I usually do it. For business reasons, someKindOfId may be somekindofid. It could be other combinations of cases as well. I don't know.
What is the best way to search for this meta tag? Adding an id or other identifier is out of the question.
You could use the jquery filter function like so
var meta = $('meta[name]').filter(function() {
return this.name.toLowerCase() == 'somekindofid';
});
Based upon CSS selector case insensitive for attributes
http://jsfiddle.net/nickywaites/mkBvC/
Also, for case insensitive attribute *= selector:
$("meta[name*=someKindOfId]")
You can use:
$('meta').filter(function() {
return (/somekindofid/i).test($(this).attr('name'));
}).attr("content")
How about this?
You can reuse the case-insensitive jQuery expression, as shown in the snippet below (execute it to see how the first div matches, while the second does not).
$.expr[':'].iAttrContains = function(node, stackIndex, properties){
var args = properties[3].split(',').map(function(arg) {
return arg.replace(/^\s*["']|["']\s*$/g, '');
});
if ($(node).attr(args[0])) {
//exact match:
return $(node).attr(args[0]).toLowerCase() == args[1].toLowerCase();
//if you actually prefer a "contains" behavior:
//return -1 !== $(node).attr(args[0]).toLowerCase().indexOf(args[1].toLowerCase());
}
};
$("div:iAttrContains('data-name', 'test')").addClass('matched');
div{background:red;}
div.matched{background:green;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div data-name="This is a test">First div</div>
<div data-name="This is a div">Second div</div>
I have some markup where a lot of id's have an id attribute, as well as innerText. I want to select each of these elements, performing a function on the id.
How do I do that?
Something like this?
$('[id]:not(:empty)').each(function(i, el) {
// do stuff
});
Give them a common class:
HTML
<div id="first" class="all"></div>
<div id="second" class="all"></div>
<div id="third" class="all"></div>
jQuery
$('div.all').each(function(index){
processid(this.id);
});
If you are talking about selecting elements whose id (or some permutation of it) is included in its text then
$('[id]').filter(function(){
return $(this).text().indexOf( this.id ) >= 0; // the this.id should be altered to match the permutation you seek ..
}).css('color','red'); // turn those to red
After you comment to #lonesomeday (at the question comments) here is what to do ..
$('[id]').each(function(){
processid(this.id);
});
First select by a regular ID selector and then loop over that selection by filtering .text() non-empty.
$("[id]").each(function() {
if ($(this).text() != "") {
// do stuff
}
});