Jquery "contains" multiple values - javascript

I am finding all the divs in a document which contains inside a text: 'thetext' and i am changing this text:
$("div:contains('thetext'):not(:has(*))").each(function () {
$(this).text($(this).text() + " anotherTextAddedBefore");
})
Is it possible to put inside contains multiple values?
I would like to find the divs whic contains: 'thetext', but also another values, for example: 'thetext1', 'thetext2',etc
I`d want to make it in one procedure and not in more: dont want to use as many procedures as texts i´d like to find.
Thanks!

You can use the multiple selector as a or condition like
$("div:not(:has(*))").filter(":contains('thetext'), :contains('thetext2')").each(..)

A selector like this provides an OR condition -
$("div:contains('thetext'), div:contains('thetext1'), div:contains('thetext2')")
A selector like this provides an AND condition -
$("div:contains('thetext'):contains('thetext1'):contains('thetext2')")
Demo - http://jsfiddle.net/jayblanchard/3a72h/

You can have an array
var array = ['John', 'Martin'];
$(array).each(function () {
$("div:contains(" + this + ")").css("text-decoration", "underline");
});
WORKING EXAMPLE

Just adding one more point to above answers, if you want to select elements that dont have particular values then you can use
$("div:not(:contains('thetext'), :contains('thetext1'),:contains('thetext2'))")
works as and condition

You can create an array and loop it:
var containsVals = ["text1","text2"];
for(var i=0;i<containsVals.length;i++){
$("div:contains("+ containsVals[i] +"):not(:has(*))").each(function () {
$(this).text($(this).text() + " anotherTextAddedBefore");
});
}

Related

jquery choose every element from array

I don't know how to achieve it and I been looking for ways to do this for hours without any success.
Let's say I have this code:
var vara="bing.com";
var varb="google.com";
jQuery('a[href^="http://'+vara+'"],a[href^="https://'+vara+'"]').click(function() {alert('y'); });
jQuery('a[href^="http://'+varb+'"],a[href^="https://'+varb+'"]').click(function() {alert('y'); });
And what I need to achieve here is to use one call that sets up the .click functions for each array variable:
var varall=["bing.com","google.com"];
jQuery('a[href^="http://'+varall+'"],a[href^="https://'+varall+'"]').click(function() {alert('y'); });
But this doesn't work. How to make variable "varall" take every element from array, so the second script would work as the first one?
Evan Trimboli's answer is OK but... In this case this selector sintaxis is not very good. Because, as I know, when jQuery will add event to <a> it will split a string and loop every element (again). So we get double looping.
I think the best option is to do something like this:
var varall=["bing.com","google.com"];
varall.forEach(function(item, i, arr) {
$(document).on('click', 'a[href^="http://' + item + '"], a[href^="https://' + item + '"]', function() {
alert('y');
});
});
https://jsfiddle.net/Lfjy2Lxu/
It looks like you're looking to do this
var varall=["bing.com","google.com"];
$.each(varall, function(index, value){
jQuery('a[href^="http://'+value+'"],a[href^="https://'+value+'"]').click(function() {alert('y'); });
});

jQuery: Remove and Re-Add Classes

I've searched quite a bit before asking this question, but I may be searching / asking the wrong question:
I want to select the last two classes of an element (that has multiple classes and an unknown amount of classes) and store that in a variable. I then want to remove those two classes and add them back at a later point (like toggleClass). The first class is known, while the second class is unknown.
For instance:
<div class="c1 c2 c3 c-unknown"></div>
I would like to select c3 and c-unknown
I've tried split() and it seems like the solution, but I couldn't quite get it to work.
I appreciate any help / guidance you can offer.
You could store them on the element itself allowing to isolate multiple instances
Following solution doesn't need classes to be in any specific order or matter how many classes are on element.
$('.c1').each(function () {
/* array of classes on elemnt*/
var classes = $(this).attr('class').split(' ');
/* remove the targeted selector from array */
classes.splice(classes.indexOf('c1'), 1);
/* remove the extra classes from element and store */
$(this).removeClass(classes.join(' ')).data('classes', classes);
});
For a specific element could also use attr(function)
$('.c1.Specific').attr('class', function(_, existingClasses){
var classes = existingClasses.split(' ');
classes.splice(classes.indexOf('c1', 1));
$(this).data('classes', classes);
return 'c1';
});
Then to re-use the stored classes
var $el = $('.c1:first');
$el.addClass( $el.data('classes').join(' '))
DEMO
Probably the easiest way to get the last two classes:
var lastTwoClasses = $('.c1').attr('class').split(/\s+/).slice(-2).join(' ');
Toggle (for example with button id="btn"):
$('#btn').click(function(){
$('.c1').toggleClass(lastTwoClasses);
});
JSFiddle
EDIT.
And yet another way:
$('.c1').each(function(){
var classes = $(this).attr('class').split(/\s+/).slice(-2).join(' ');
$(this).click(function(){
$(this).toggleClass(classes);
});
});
JSFiddle
I believe this is what you're trying to do.
var ele = document.getElementsByClassName('c1'),
classes = ele[0].className,
classArr = classes.split(' '),
spliceIndex = classArr.length - 2,
last2Classes = classArr.splice(spliceIndex, 2);
Here's a working fiddle
If you're trying to remove the classes you can use jquery or you could just use the dom element's className property and set it to whichever array has the classes you want to use. You would use the array method .toString() on either array and it will give you a string representation of the classes.
The answer here could help you to get part of the functionality you need:
Get first and last class with jQuery
Starting with that, you could use split, and removeClass like this
(sample text and css added for demo purposes):
function removeTheClasses(el) {
var classes = el.attr("class").split(/\s/);
var second_to_last = classes[classes.length - 2]; //second to last class
var last = classes[classes.length -1]; //last class
el.removeClass(second_to_last, last);
}
$('button').click(function() {
removeTheClasses($('.c1'));
});
.c-unknown {font-weight:bold}
.c3 {color:pink}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="c1 c2 c3 c-unknown">
ABC
</div>
<br/>
<button>Remove the last two classes</button>
In order to add these same classes back in (toggling), you'd have to keep a record of the recently removed classes. This would require:
pushing the values of the first & last variables to a cookie or web storage (if handling multiple elements at a time), OR
a single javascript variable above the scope of the 'removeTheClasses' function (if you're just handling one element at a time).

Can I make a compound selector including this in jquery?

I have a function that uses each to go over each element in a set and renumber them after one is removed from the DOM.
Right now that function looks like this:
renumber_items = function(){
$(".item_set").each(function(index){
$(this).find('legend').html("Item " + (index+1));
});
};
I remember reading somewhere that find is a really inefficient operation, so I was wondering if there's a way to combine the 'legend' selector into a compound selector with this.
If there is only one legend per .item_set this will abbreviate things a bit:
renumber_items = function(){
$(".item_set legend").html(function(index){
return "Item " + (index+1);
});
};
.html can take a function and the result is stored.
If there is more than one legend per .item_set you will need to retain an outer each to keep the numbers sequential for each set.
Generally if you have speed issues, on a function called many times, and the jQuery selector result is on a fixed set of elements, you just archive the search to a variable once at page load and reuse that:
var $legends = $(".item_set legend");
renumber_items = function(){
$legends.html(function(index){
return "Item " + (index+1);
});
};
Maybe you can try with .filter(). As others say, it shouldn't be such a performance issue as long as you're not using it all the time. Consider labeling all the items you want to find/filter, so that you can get them all in one JQuery selector at once, and you don't have to go filtering everything after. Else you can use (as commented out by #Regent):
renumber_items = function(){
$(".item_set legend").each(function(index){
$(this).html("Item " + (index+1));
});
};
You can replace:
$(this).find('legend')
with:
$('legend', this)
The second argument sets the context in which jQuery searches for 'legend'.
If it is omitted, the context defaults to be document.

Performing the same operation on multiple selectors, elegantly?

On the project I'm working on, I've been writing a little JavaScript object. One of its behaviors involve removing any children in a series of classes, as such:
function Foo () {
var $a = $('.a'),
$b = $('.b'),
// ...etc...
$n = $('.n');
$a.remove();
$b.remove();
// ...etc again...
$n.remove();
}
While there are some ways to revise this to be more easily maintainable (putting the selectors into a single array springs instantly to mind), I'm wondering if there's any elegant way to perform the .remove() operation on a series of selectors, as such:
function FooPrime() {
var selectors = [
'.a',
'.b',
// ...
'.n'
];
// Perform remove on all given selectors?
$(selectors).remove();
}
Thus, Question: What are some ways I could perform a single jQuery operation on a number of selectors?
EDIT: here is a JSFiddle to show a cut-down version of the problem context.
You can separate the selectors with commas:
$(selectors.join(',')).remove();
The comma has that purpose in straight ordinary CSS selector syntax.
Thanks for showing your DOM, you should avoid making big lists of classes to select when you can add multiple classes to elements and create a specific class for the elements you want to target... or target via association to other elements. This would be a more clean and efficient way to do it.
By association
Basically for the selector I just have this:
$("#test-callout").find("div").not(".callout-main").remove();
Fiddle
This assumes that you do not have any other div's besides .callout-main and the target div in test-callout. If you do you can modify the selector chain a bit to compensate.
By adding another class
Your arrow creation code was like this:
function calculateArrow() {
var arrowClass;
if(pub.isLeft) {
arrowClass = 'callout-arrow-left';
} else {
arrowClass = 'callout-arrow-right';
}
pub.$callout.append('<div class="' + arrowClass + '"></div>');
}
Modify it to be like this:
function calculateArrow() {
$arrow = $("<div>")
.addClass("callout-arrow")
.addClass(pub.isLeft ? "callout-arrow-left" : "callout-arrow-right");
pub.$callout.append($arrow);
}
Then your selector can be simply:
$("#test-callout").find(".callout-arrow").remove();
Fiddle
If you are interested in a complete refactor - I reduced your CalloutObject from 53 to 17 lines and it still works the same.
Fiddle

Need to select a drop down list element with a particular attribute value from a list of drop down lists and set its selected value

.FilterList is the class name of all the drop down lists
var $lists = $('.FilterList[ctype="' + ctype + '"]').css('display', 'inline');
Something like the below works fine but I was wondering if there's a more concise and efficient method
I could use instead of the .each()
$lists.each(function () { $(this).attr('filterid') == filterid ? $(this).val(thisval) : null; });
Whilst I am after something more like:
$lists.first('.FilterList[filterid = "' + filterid + '"]').val(thisval);
Your question is a little vague without any HTML to demonstrate what you're trying to grab from the DOM, but from what I gather, it seems like something like this should work:
$lists.find("[filterid='" + filterId + "']").val(myVal);
Honestly, though, I'm just guessing at what it is you are looking for. Try creating a jsFiddle to give us a better idea of what you're after.

Categories

Resources