if statement inside jQuery selector - javascript

I'm getting those 2 vars from the DOM:
var get_category = $('#category').find('.current').attr('rel');
var get_subcategory = $('#subcategory').find('.current').attr('rel');
and I want here to find the classes in my DOM and show it
$('.filter-result').find('.'+get_category, '.'+get_subcategory ).show();
But I need to write it inside the .find() only if the variables are exist

I hope it answers your question:
var get_category = $('#category').find('.current').attr('rel');
var get_subcategory = $('#subcategory').find('.current').attr('rel');
var classes = [];
if (get_category) {
classes.push('.' + get_category);
}
if (get_subcategory) {
classes.push('.' + get_subcategory);
}
//if get_category or get_subcategory were found
if (classes.length) {
$('.filter-result').find(classes.join('')).show();
}

I do like Gabriels answer because it is very simple another option that works well and is extensible all you would have to do add another selector is add it to the selectors array. It is a little bit more advanced using javascripts filter and map array methods though.
var get_category = $('#category').find('.current').attr('rel');
var get_subcategory = $('#subcategory').find('.current').attr('rel');
var selectors = [get_category, get_subcategory];
var query = selectors.filter(function(elem) {
if (elem) { return elem };
}).map(function(elem){
return '.' + elem;
}).join(', ')
$('.filter-result').find(query).show();

Related

Clone elements found with different selectors, avoiding code repetition

Could you please help me, how to simplify this code? I think, it is too long and confused.
var launchPad = $(".launchPad").clone();
var launchPad_plankovy = $(".launchPad-plankovy").clone();
var launchPad_plankovy_tvarovany = $(".launchPad-plankovy-tvarovany").clone();
var launchPad_tyckovy = $(".launchPad-tyckovy").clone();
var launchPad_kombinovany = $(".launchPad-kombinovany").clone();
var launchPad_barvy_plankovy = $(".launchPad-barvy-plankovy").clone();
var launchPad_barvy_tyckovy = $(".launchPad-barvy-tyckovy").clone();
var launchPad_zakonceni_plotovek = $(".launchPad-zakonceni-plotovek").clone();
var launchPad_zakonceni_tycek = $(".launchPad-zakonceni-tycek").clone();
$("[name='reset']").click(function(){
$(".launchPad").html(launchPad.html());
$(".launchPad-plankovy").html(launchPad_plankovy.html());
$(".launchPad-plankovy-tvarovany").html(launchPad_plankovy_tvarovany.html());
$(".launchPad-tyckovy").html(launchPad_tyckovy.html());
$(".launchPad-kombinovany").html(launchPad_kombinovany.html());
$(".launchPad-barvy-plankovy").html(launchPad_barvy_plankovy.html());
$(".launchPad-barvy-tyckovy").html(launchPad_barvy_tyckovy.html());
$(".launchPad-zakonceni-plotovek").html(launchPad_zakonceni_plotovek.html());
$(".launchPad-zakonceni-tycek").html(launchPad_zakonceni_tycek.html());
});
You could make one big selector and collect all elements at once. You can apply clone on all of them in one call. For restoring, you would reuse that same selector, loop over the results and replace the HTML from the collected clones.
var $restorable = $(".launchPad, .launchPad-plankovy, " +
" .launchPad-plankovy-tvarovany, .launchPad-tyckovy, .launchPad-kombinovany, " +
" .launchPad-barvy-plankovy, .launchPad-barvy-tyckovy, " +
" .launchPad-zakonceni-plotovek, .launchPad-zakonceni-tycek");
var $launchPad = $restorable.clone();
$("[name='reset']").click(function (){
$restorable.each(function (i) {
$(this).html($launchPad.eq(i).html());
});
});
I do seem to notice you give unique classes to each of your elements. It is better to use id properties for that purpose, and use classes for marking the same kind of elements with the same class. If you would use one class for all these elements, like 'restorable', the list would not have to be that long.
Also, as you only use the HTML of the clones, you will get better performance and memory usage, if you don't actually clone, but just save the HTML. Together with the idea to give the class restorable to all these elements, the code becomes:
var $restorable = $(".restorable");
var launchPadHtml = $restorable.map(function() { return $(this).html(); }).get();
$("[name='reset']").click(function (){
$restorable.each(function (i) {
$(this).html(launchPadHtml[i]);
});
});
var keys = ['launchPad-plankovy-tvarovany', 'launchPad-plankovy' ...];
var clones = {};
keys.forEach(function(key){
clones[key] = $('.' + key).clone();
}
$("[name='reset']").click(function(){
keys.forEach(function(key){
$('.' + key).html(clones[key];
}
});
In lodash, it's move elegant:
var keys = ['launchPad-plankovy-tvarovany', 'launchPad-plankovy' ...];
var clones = _.zipObject(keys, _.map(keys, function(key){
return $('.' + key).clone();
});

jQuery append element if it doesn't exist, otherwise replace

Here's a short piece of code:
var $el = $("#something").find(".test");
if (!$el.length) {
$("#something").append('<div class="test">somecontent</div>');
} else {
$el.replaceWith('<div class="test">somenewcontent</div>');
}
I couldn't find a method appendOrReplaceWith or anything similar.
Any ideas how can I make it shorter?
I believe that:
$("#something").appendOrReplace('<div class="test">sometext</div>');
would be much easier to read, but no such method is available yet.
Just remove it first then append.
$(".test").remove();
$("#something").append('<div class="test">somecontent</div>');
Mandatory vanilla answer. It may not be shorter, but it's faster.
Get the element, grab all subelements with the class "test", create your div, check the subelements length, and if length is truthy, set the innerHTML to the div. Else, append it.
var el = document.getElementById("something");
var subel = el.getElementsByClassName("test");
var div = document.createElement("div");
div.className = "test"
if (subel.length) {
div.textContent = "somenewcontent";
while(el.hasChildNodes()) el.removeChild(el.lastChild); //remove child nodes
el.appendChild(div);
} else {
div.textContent = "somecontent";
el.appendChild(div);
}
Adding a method like findOrAppend to jQuery could be useful:
$.fn.findOrAppend = function(selector, content) {
var elements = this.find(selector);
return elements.length ? elements : $(content).appendTo(this);
}
Then you can chain text, replaceWith, empty etc. as needed:
$("#something")
.findOrAppend(".test", "<div class='test'>")
.text("newcontent");
First of all you should cache your selectors:
var $som = $('#something');
var $ele = $(".test",$som);
var newHtml = '<div class="test">somecontent</div>';
if (!$el[0]) $som.append( newHtml );
else $ele.replaceWith( newHtml );
but you already did it really fine, (beside not caching repeated selectors), and me, trying to make it smaller could be a**-kicked for not using {} for my if and else :)
I would do this
var $s = $("#something"), $t = $s.find(".test"), c = 'New content';
( $t[0] ? $t:$s)[( $t[0] ? 'html':'append')](( $t[0] ? c :$('<div>',{class:'test'}).append(c)));

jQuery - extract class name that 'starts with' prefix [duplicate]

This question already has answers here:
Get class list for element with jQuery
(16 answers)
Closed 9 years ago.
My items have the following classes:
<div class="class-x some-class-1 other-class"></div>
<div class="some-class-45 class-y"></div>
<div class="some-class-123 something-else"></div>
I'm wondering if there is an easy way to:
Grab only all classes with some-class- prefix.
Remove them from each element.
Have their names (not corresponding DOM elements) in a variable?
I can easily select such elements with jQuery( "div[class^='some-class-'], div[class*=' some-class-']" ) but how its class name could be extracted with the shortest and the most readable code to a variable (can be some global object)?
Like this?
var arrClasses = [];
$("div[class*='some-class-']").removeClass(function () { // Select the element divs which has class that starts with some-class-
var className = this.className.match(/some-class-\d+/); //get a match to match the pattern some-class-somenumber and extract that classname
if (className) {
arrClasses.push(className[0]); //if it is the one then push it to array
return className[0]; //return it for removal
}
});
console.log(arrClasses);
Fiddle
.removeClass() accepts a callback function to do some operation and return the className to be removed, if nothing to be removed return nothing.
You could loop through all the elements, pull the class name using a regular expression, and store them in an array:
var classNames = [];
$('div[class*="some-class-"]').each(function(i, el){
var name = (el.className.match(/(^|\s)(some\-class\-[^\s]*)/) || [,,''])[2];
if(name){
classNames.push(name);
$(el).removeClass(name);
}
});
console.log(classNames);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="class-x some-class-1 other-class"></div>
<div class="some-class-45 class-y"></div>
<div class="some-class-123 something-else"></div>
You can iterate over each found node and iterate over the classes to find a match; if found, remove the class and log it:
var found = [];
$('div[class*="some-class-"]').each(function() {
var classes = this.className.split(/\s+/),
$this = $(this);
$.each(classes, function(i, name) {
if (name.indexOf('some-class-') === 0) {
$this.removeClass(name);
found.push(name);
}
});
});
Note that a selector like div[class*="some-class-"] is pretty expensive and since you need to perform extra processing anyway, it would be easier to just iterate over all div tags and process them:
var elements = document.getElementsByTagName('div'),
found = [];
$.each(elements, function(i, element) {
var classes = element.className.split(/\s+/);
$.each(classes, function(i, name) {
if (name.indexOf('some-class-') === 0) {
$(element).removeClass(name);
found.push(name);
}
});
});
Modern browsers expose Element.classList which you can use to manipulate class names and Array.forEach for iteration:
var found = [];
[].forEach.call(document.getElementsByTagName('div'), function(element) {
(function(names, i) {
while (i < names.length) {
var name = names[i];
if (name.indexOf('some-class-') === 0) {
names.remove(name);
found.push(name);
} else {
++i;
}
}
}(element.classList, 0));
});
The easy way
You clould create your own filter :
$.fn.hasClassStartsWith = function(className) {
return this.filter('[class^=\''+className+'\'], [class*=\''+className+'\']');
}
var divs = $('div').hasClassStartsWith("some-class-");
console.log(divs.get());
See fiddle

How to make jQuery objects from an array?

anArray = ['thing1','thing2','thing3'];
$.each(anArray, function (i,el) {
var object = 'name.space.' + el;
var selector = 'node-' + el;
var object = $('#' + selector);//need object here to be interpreted as it's value
//as if: var name.space.thing1 = $('#' + selector);
});
such that these are usable jQuery objects:
console.log(name.space.thing1);
console.log(name.space.thing2);
console.log(name.space.thing3);
I feel like eval() is involved. I'm hydrating navigation selectors so as pages are added/removed, we just update the array. We could build the array from the nav nodes, but either way, we still need to be able to make these namespaced selectors...
You will have to use bracket notation:
var array = ['thing1', 'thing2'];
var object = {};
object.space = {};
$.each(array, function () {
object.space[this] = $('#node-' + this);
});
console.log(object.space.thing1); // [<div id="node-1">];
I am not sure what are you trying to accomplish, but
name.space[el] = $('#' + selector);
might work.
Object properties are always accessible with the bracket notation as well. This means that obj.xy is just the same as obj['xy'], but the latter is more flexible and can be used in situations like yours.
var anArray = ['thing1','thing2','thing3'];
var name = {space:new Array()};
$.each(anArray, function (i,el) {
var selector = 'node-' + el;
name.space[el] = $('#' + selector);
});

Jquery: Matching indexes of two arrays, string and object to replace text in object?

I have two arrays, one is full of strings, the other is an array of objects. The indexes on each correspond, and I want to replace the text of each of the objects in my object array with the corresponding text in my string array.
For example, I have an array like this:
var textarr = ["value1", "value2", "value3"]
and a Jquery object array that contains a bunch of span elements:
var spans = $("span.myClass");
var spanarr = $.makeArray(spans);
I'm trying to use $.each() to iterate over each of the spans and use the corresponding index of my text array to assign a text value to the current span.
I've tried a couple different ways, and nothing seems to work. I'm missing some logic here, but why wouldn't this work?:
i = 0;
jQuery.each(spanarr, function() {
$(this).text(textarr[i]);
i++;
});
EDIT:
I think maybe the rest of my function might be causing this not to work. Here's the entire script:
$("span input:radio").click(function() {
if (($(this).is(":checked")) == true) {
var parent = $(this).parent();
var aunts = parent.parent().children();
var parentIndex = aunts.index(parent);
var indexToNthChild = parentIndex + 1;
var otherSpans = $(".DropDownMenu span:nth-child(" + indexToNthChild + ")");
var position = parent.position();
var topValue = position.top;
var smallPrice = otherSpans.children("span.dropDownPrice");
var pricearr = jQuery.makeArray(smallPrice);
var textarr = [];
jQuery.each(pricearr, function() {
textarr[i] = $(this).text();
});
alert(textarr); // Returns all the text values expected in array
var changers = $(".bigPriceChanger");
var changerarr = $.makeArray(changers);
$(".DropDownMenu").css({ "top": "-" + topValue + "px" });
$(".DropDownMenu span").css("background-image", "none");
parent.css({ "background": "#f3f1e7 url(assets/images/branding/DropDownArrow.gif) no-repeat right" });
otherSpans.css({ "background": "#f3f1e7 url(assets/images/branding/DropDownArrow.gif) no-repeat right" });
alert(changearr); // Returns all span objects in array
i = 0;
jQuery.each(changearr, function() {
$(this).text(textarr[i]);
i++;
});
}
});
Try
$("span.myClass").each(function (i) {
$(this).text(textarr[i]);
});
I think you don't need the call to makeArray. Just write:
i = 0;
jQuery.each($("span.myClass"), function() {
$(this).text(textarr[i++]);
});
I hate to end the question with a 'it was all a dream afterall' copout, but it turns out my browser was funked.
I've since checked my script (and the million variations of it that everyone suggested) in IE8 and someone else's firefox, and low and behold, it works.
You might want to try something like this:
var spans = $("span.myClass");
for(i=0;i<spans.length;i++){
spans[i].innerHTML = textarr[i];
}
You can think of a jQuery object like an extended version of an array. You can use length and [i] in reference to the number of DOM elements selected and the DOM element at a certain index respectively.
Your code is fine, although the makeArray call is redundant
There must be an error somewhere else,
here is your code running fine in firefox
http://jsbin.com/oxiwu
to edit go to http://jsbin.com/oxiwu/edit
I think your code is not working because the variable i was defined outside its scope.
Probably there is a better solution, but you could try the following:
function createF() {
var i = 0;
function f() {
$(this).text(textarr[i]);
i++;
}
return f;
}
f = createF();
jQuery.each(spanarr, f);
What's the reason for calling $.makeArray? You can iterate through your spans like this...
$("span.myClass").each(function(i) {
alert(textarr[i]);
$(this).text(textarr[i]);
});

Categories

Resources