Jquery :contains selector without children - javascript

I need to do a function to change color (in this example) of dom element in javascript(jquery) but i have some trouble with :contains selector but i need to use because i don't have specific ID or class.
HTML :
<p id="title">John</p><!-- contain John must be red -->
<div id="description">John</div><!-- contain John must be red -->
<div id="element">
<p id="element1">John</p><!-- contain John must be red -->
<p id="element2">Anonymous</p><!-- dont contain John dont change color -->
</div>
ID in this code just to show you my problem.
Js :
$("div:contains('John'), p:contains('John')").css("color", "red");
Problem :
This script make unwanted changes (#element2)
I already check : Jquery doc but to simple dom in this example .
Testable example here : JSFIDDLE

Try to use exclude the div with other elements,
$("div:contains('John'):not(:has(*)), p:contains('John')").css("color", "red");
If your html have chances of containing elements like this,
<div id="description">John<p>test</p></div>
Then ultimately you have to go along with #TrueBlueAussie's answer.
DEMO

You could create your own filter that removes children elements and checks the textNodes of the current element only.
As the string you're trying to match is present in the comments as well, any use of innerHTML is out, so textContent is used.
$("#bug").on('click', function () {
$("div, p").filter(function() {
var clone = this.cloneNode(true);
while (clone.firstElementChild) {
clone.removeChild(clone.firstElementChild);
}
return clone.textContent.indexOf('John') != -1;
}).css("color", "red");
});
FIDDLE

Related

Counting div's with class and returning position

I have a page with many dynamically creted div's as seen below:
<div class="open"></div>
<div class="open"></div>
<div class="open"></div>
<div class="open"></div>
I'm looking for a way to get get a position of an element (eg. If the element is the first instance of, assign id="1" if element is the second instance of, assign id="2".
I'm currently using the following jquery, but am stuck, as Im not sure where to go from here.
$(document).ready(function () {
var numDialogs = $('.open').length;
});
Any suggestions?
Just use:
$('div.open').prop('id', function(i){
return 'openElement' + (i + 1);
});
JS Fiddle demo.
I've deliberately added a prefix string because while numerical ids are valid under HTML5, they remain invalid under HTML4, and are difficult to select using CSS selectors.
References:
prop().
Mark, you can target the element and then add an attribute like so:
$('.open').attr('id', numDialogs);
This will give it all 4's in this case, but I'll leave you to wrestle with the actual logic to implement the right numbers. Good luck.

How to get element by both id and class

Is there any alternative solution (in JavaScript) for document.getElementById(); to select a specific element, specifying both the class and id ?
for example I have such a content:
<a class="q_href" onclick="showQuestion(1)">Question 1:</a>
<div class="q_content" id="1"></div>
<a class="q_href" onclick="showQuestion(2)">Question 2:</a>
<div class="q_content" id="2"></div>
And I want to select the corresponding div under the "Question X" link in the function
function showQuestion(id)
{
var thediv = GetByClassAndId("q_content",id); // how to implement this function ?
WriteQuestionIn(thediv); //Ajax
}
Thanks in advance.
you can try document.querySelector()
like document.querySelector(".q_content#2") use the para like css selector..
Since ID is always unique (unless u make a mistake) u have no need to use both class and id to select the element.
Such an approach is not correct, and should be avoided at all cost.
What I suspect is your problem, is that the ID is only a number. Try adding a prefix which is a letter. Do view source to this page to see examples.
<a class="q_href" onclick="showQuestion(1)">Question 1:</a>
<div class="q_content" id="q1"></div>
<a class="q_href" onclick="showQuestion(2)">Question 2:</a>
<div class="q_content" id="q2"></div>
function showQuestion(id)
{
var thediv = document.getElementById("q"+id);
WriteQuestionIn(thediv); //Ajax
}
Actually there is a function $ in jQuery for doing this operation. If you are using any framework, then you should remember there is always a jQuery library available. Else if you are using custom PHP, then add one of them like jQuery or other because they provide lots of types of selectors.
Now here is the code after adding jQuery:
$("#yourid") //basic selector
$("#yourid.yourclass").show()
Use .show() to show the selected element
Use .hide() To hide element

How to use document.getElementById with jquery next siblings selector

I want to remove some silblings. I tried as given below.
But not working. why? And how to solve it?
<div>
<div id="idx1">child1 </div>
<div id="idx2">child2</div>
<div id="idx3">child3</div>
...
<div id="/a/b/c">This should be last child</div>
<div id="idx4">Remove it.</div>
<div id="idx5">Remove it.</div>
<div id="idx6">Remove it.</div>
...
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script>
// Since the id contains special chars,
// javascript method has been used to get the element.
lastChildObj = jQuery(document.getElementById('a/b/c'));
// I don't know how to remove the childs after lastChildObj.
// I tried as given below.
lastChildObj.filter('~').remove();
There are two key steps to this.
Select the elements to remove
Remove them
Step 1 can be broken down into two parts, obtaining a reference to the last element to keep, then getting a list of all of its siblings that come after it. Step 2 just uses the .remove() function.
$(document.getElementById('/a/b/c')).nextAll().remove();
You can still use jquery for your selector but you need to escape the id like so :
$("#\\/a\\/b\\/c")
Then you just need to select any following divs like this :
$("#\\/a\\/b\\/c").nextAll().remove();
http://jsfiddle.net/8mMJq/
Further informations about special characters in selectors : http://api.jquery.com/category/selectors/
This should work for you:
var base = document.getElementById('/a/b/c');
while(base.nextSibling){ // While the element has siblings
base.parentElement.removeChild(base.nextSibling); // remove the siblings from the parent element.
}
Working example
You can also make it slightly more efficient:
var base = document.getElementById('/a/b/c');
while(base.parentElement.removeChild(base.nextSibling))​ // Remove the nextSiblings while they exist.
Example
Try this :
$("#\\/a\\/b\\/c").nextAll().remove();
JsFiddle : http://jsfiddle.net/QcvWQ/
First of all change id from "/a/b/c" to ie "abc" and then run following
$("#abc").nextAll().each(function () { $(this).remove());});

How to select HTML elements which don't have any attributes defined on them?

I need to use jQuery to locate all DIV tags that have no attributes on them and apply a class to each. Here's a sample HTML:
<div id="sidebar">
<div>Some text goes here</div>
<div class="something">something goes here</div>
<div>Another div with no attributes.</div>
</div>
So, I need to take that and turn it into this:
<div id="sidebar">
<div class="myClass">Some text goes here</div>
<div class="something">something goes here</div>
<div class="myClass">Another div with no attributes.</div>
</div>
How do you locate elements of type div that have no attributes via jQuery? Thanks.
Here you go:
$('div', '#sidebar').filter(function () {
return this.attributes.length === 0;
})
Live demo: http://jsfiddle.net/phbU9/
The attributes property returns a list of all attributes set on the element. "Naked" elements have an empty attributes list.
Update: Be sure to read Tim's answer below which provides a solution for older versions of IE, since my own solution doesn't work in IE8 and below.
#Šime's answer is close but doesn't work in IE 6, 7 or 8, where an element's attributes collection has an entry for every possible attribute, not just those specified in the HTML. You can get round this by checking each attribute object's specified property.
Live demo: http://jsfiddle.net/timdown/6MqmK/1/
Code:
$("div").filter(function() {
var attrs = this.attributes, attrCount = attrs.length;
if (attrCount == 0) {
return true;
} else {
for (var i = 0; i < attrCount; ++i) {
if (attrs[i].specified) {
return false;
}
}
return true;
}
});
check this out:
http://jsfiddle.net/thilakar/CHux9/
You need to give some sort of selector, in this case Ive used your side bar but it can be anything. Then get the children that have no class attribute and add a new class. See JSFiddle for the example:
http://jsfiddle.net/HenryGarle/q3x5W/
$("#sidebar").children('div:not([class])').addClass('newClass');
So this would return the 2 elements with no class tag and leave the sidebar and div with the class completely unaffected.
You could use a combination of jQuery's has attribute selector and the not selector. For example:
$('div:not([class], [id])').addClass('myClass');
jsFiddle demonstrating this
With this approach, you need to explicitly specify the attributes to check the presence of. Sime's solution would apply the class to divs that do not have any attributes at all.
To expound upon Tim Down's answer, I recommend checking that the attrs var not null special cases where the html has comment tags, etc.
try $('div:not([class])').addClass('myClass');
it is a general approach because the class will apply to all the div that have no class
$('#sidebar div')` or more general `$('div'); //returns collections of divs
to answer the question:
$('#sidebar div').addClass('myClass');

How do I remove descendant elements from a jQuery wrapped set?

I'm a little confused about which jQuery method and/or selectors to use when trying to select an element, and then remove certain descendant elements from the wrapped set.
For example, given the following HTML:
<div id="article">
<div id="inset">
<ul>
<li>This is bullet point #1.</li>
<li>This is bullet point #2.</li>
<li>This is bullet point #3.</li>
</ul>
</div>
<p>This is the first paragraph of the article</p>
<p>This is the second paragraph of the article</p>
<p>This is the third paragraph of the article</p>
</div>
I want to select the article:
var $article = $('#article');
but then remove <div id="inset"></div> and its descendants from the wrapped set. I tried the following:
var $article = $('#article').not('#inset');
but that didn't work, and in retrospect, I think I can see why. I also tried using remove() unsuccessfully.
What would be the correct way to do this?
Ultimately, I need to set this up in such a way that I can define a configuration array, such as:
var selectors = [
{
select: '#article',
exclude: ['#inset']
}
];
where select defines a single element that contains text content, and exclude is an optional array that defines one or more selectors to disregard text content from.
Given the final wrapped set with the excluded elements removed, I would like to be able to call jQuery's text() method to end up with the following text:
This is the first paragraph of the article.This is the second paragraph of the article.This is the third paragraph of the article.
The configuration array doesn't need to work exactly like that, but it should provide roughly equivalent configuration potential.
Thanks for any help you can provide!
I suppose you do not want to modify the original HTML by removing elements from it, but you want to just get the content of article without the inset.
Thats why I would use clone() to get a copy of the article and then remove the inset from it.
Like this:
$("#article").clone().find("#inset").remove().end().text()
$("#article") selects the article div, clone creates a
copy,
find gets the children to
remove (you could also use children),
remove(), removes the selected inset,
end() goes back to the original selection.
At the end I just added text() as you mentioned you wanted to do that.
if you want to remove anything in #article but #inset use:
$('#article > *:not(#inset)').remove() // selects all direct children of #article but not #inset and removes them
see an example here: http://jsfiddle.net/zwPsD/
if want to apply this rule to more then one DOM element you can chain them:
$('#article, #article2, #article3, #etc').find('> *').not('#inset, #that, #and. #there').remove()
you can find an example of this here:
http://jsfiddle.net/ZNjdE/
and with a simple each you can extract the text:
http://jsfiddle.net/ZNjdE/2/
Unless I am missing something, why can't you select all of the <p> elements within the article div?
$("#article p")
If that is unacceptable, I think you are looking for the filter function...
$("#article").filter(":not(#inset)")
Note: you can have multiple selectors within the :not() selector. They just have to be comma delimited, so this approach should accomodate your configurational needs.
Try something like this.
$('#article').children(':not(#inset)').each(function(){
alert($(this).text());
});
If you want to do it with an object:
var selectors = {
select: '#article',
exclude: ['#inset', 'p']
};
$(selectors.select).children(':not('+selectors.exclude.join(',')+')').each(function(){
alert($(this).text());
});
EDIT
To get any level of ancestor, you could add extra selectors and use find(). Eg.
$('#article').find('li:first, :not(#inset, #inset *)').each(function(){
alert($(this).text());
});
With this you'd be excluding #inset and all #inset's ancestors except the first li. It won't quite work with the selectors object from before though because you're excluding a group of elements and then including some of the excluded ones. You could do it with three elements in the object:
var selectors = {select: ... , exclude: ... , includeFromExcluded: ...};

Categories