Adding a Space when using addClass and variables using jQuery - javascript

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

Related

Accessing a specific li within a ul

After looking at past examples and source code I have made, I can't seem to work out accessing a specific <li><a>the value in this</a></li> based on a parameter sent in.
Mockup:
<ul class="selectBox-dropdown-menu selectBox-options size-dropdown mediumSelect footwear" style="top: 309px; left: 34px; display: none;">
<li class="" style="display: none;"><a rel=""></a></li>
<li class="size-not-in-stock"><a rel="3096786:6"> 6</a></li>
<li class="size-not-in-stock"><a rel="3096787:6.5"> 6.5</a></li>
<li class=""><a rel="3096788:7"> 7</a></li>
<li class="selectBox-selected"><a rel="3096789:7.5"> 7.5</a></li>
<li class=""><a rel="3096790:8"> 8</a></li>
<li class=""><a rel="3096791:8.5"> 8.5</a></li><li><a rel="3096792:9"> 9</a></li>
<li><a rel="3096793:9.5"> 9.5</a></li><li><a rel="3096794:10"> 10</a></li>
<li><a rel="3096795:10.5"> 10.5</a></li><li><a rel="3096796:11"> 11</a></li>
<li><a rel="3096797:11.5"> 11.5</a></li><li><a rel="3096798:12"> 12</a></li>
<li><a rel="3096799:12.5"> 12.5</a></li><li><a rel="3096800:13"> 13</a></li>
<li><a rel="3096801:14"> 14</a></li><li><a rel="3096802:15"> 15</a></li></ul>
</ul>
Here is what I am trying to get. Let us say that a user puts in a value of 7, well than it should find the corresponding <li><a></a></li> that contains the number 7 and click it.
My troubles are with finding that value inside this, I know I need to use find within the <ul> but what stumps me is based on a value.
UPDATE:
I just want to make clear that, this is something that is going to be an auto process so I am trying to make it so I don't have to do anything except load the page.
You need something like
var test = "the content to seek";
$('ul.footwear').find('a').filter(function(idx, el){
return $.trim($(this).text()) == $.trim(test);
}).closest('li').trigger('click')
Demo: Fiddle
There is no need to loop through and read the innerHTML of every element like all of the other solutions appear to be doing. You can just do it with a selector.
Since the rel attribute seems to have the data you are after at the end :size, you can use use :has() and ends with $= selectors to get the lis you are after.
var num = 7;
var elems = $(".footwear li:has(a[rel$=':" + num + "'])");
console.log(elems.length);
And if you want to click it, than you call .click() or .trigger("click")
function findAndClick (size) {
var elem = $(".footwear li:has(a[rel$=':" + size + "'])");
elem.trigger("click");
}
And to trigger it on the page load it would be something like
$(window).on("load", function() { findAndClick(7); } );
or document ready
$( function() { findAndClick(7); } );
Sad thing is, this solution appears to be great with a simple selector, but the performance can be subpar. If there is only going to be one element with the size, the best performance would be an each() loop and breaking out of it when you find the one element. No need to look at the other elements.
The best performing would be an each()
function findAndClick (size) {
var elem;
size = size.toString();
$('.footwear').find('a').each(function () {
if ($.trim($(this).text()) == size) { //compare the text
elem = $(this).parent(); //set the element that contains the link
return false; //exit each loop
}
});
if (elem) {
elem.trigger("click"); //fire click
}
}
For even better performance, eliminate the need to read the text of the element or use a ends with selector. Add a data attribute to the element.
<li data-size="7">
and than you would just use a selector
function findAndClick (size) {
$('.footwear li[data-size="' + size + '"]').trigger("click");
}
I would optimize this by making your structure better suited for these types of queries
<li id="10"><a rel="3096793:9.5"> 9.5</a></li><li><a rel="3096794:10"> 10</a></li>
Put an id on the li that corresponds to the value of the a tags.
Then you can do a simple $("#10") selector
While it's possible to make complex selectors based on filters etc, keep in mind that performance will not be great in general for non browser backed selectors (pseudo selectors)
Since you have an attribute rel that finish with the content, you can use this:
$('a[rel$="\:'+valueToMatch+'"]').parent()

JQuery - Number items in a list

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));
})
});

display first item jquery

I have a list that is kind of like this:
<li class="listElement semiUniqueCLassOne" unique-class="semiUniqueCLassOne" style="display:none;">one</li>
<li class="listElement semiUniqueCLassOne" unique-class="semiUniqueCLassOne" style="display:none;">two</li>
<li class="listElement semiUniqueCLassOne" unique-class="semiUniqueCLassOne" style="display:none;">three</li>
<li class="listElement semiUniqueCLassTwo" unique-class="semiUniqueCLassTwo" style="display:none;">four</li>
<li class="listElement semiUniqueCLassTwo" unique-class="semiUniqueCLassTwo" style="display:none;">five</li>
<li class="listElement semiUniqueCLassThree" unique-class="semiUniqueCLassThree" style="display:none;">six</li>
I'm trying to only show the first of each of the semiUniqueCLass so I'm attempting to do it like this:
$('.listElement').each(function(){
var uniqueClass = $(this).attr('unique-class');
if($('.'+uniqueClass).is(':first')){
$(this).show();
}
});
this doesn't work... what ways can I make it work? tried several, a bit stuck.
This should do the trick:
$('.listElement').hide();
$('.listElement:first-child').show();
If there's more elements with the listElement class:
$('.listElement[#class*=semiUniqueCLass]').hide();
$('.listElement[#class*=semiUniqueCLass]:first-child').show();
(Only shows / hides listElements that have a class that contains semiUniqueCLass)
To show the first of each unique semiUniqueCLass* item, take a look at Jack's Answer or xdazz's answer.
Just use the .first() method.
$('.listElement').each(function(){
var uniqueClass = $(this).attr('unique-class');
$('.'+uniqueClass).first().show();
});
And the working demo.
Another solution is shown as below:
var clazzs = $('.listElement').map(function() {
return $(this).attr('unique-class');
});
$.unique(clazzs).each(function() {
$('.'+this).first().show();
});
Also the working demo.
To show the first of each unique semiUniqueCLass* item, you'd have to iterate over all relevant .listElement nodes manually:
var shown = {}; // keep track of which class has already been shown
$('.listElement[unique-class]').each(function() {
var className = this.getAttribute('unique-class');
if (!shown[className]) {
// this class has not been seen before, show the first only
shown[className] = true;
$(this).show();
}
});
It shows elements one, four and six.
Update
I've pitted this answer against the two solutions by xdazz using this jsperf benchmark. This answer comes out on top with the runner up being ~30% slower (in Chrome).
This code shows the first item :
$('[class^=listElement]').first().show();

Access Elements After Append

I need to access DOM elements after JQuery append. Let's say I have this:
<ul id="items">
<li class="item">one</li>
<li class="item">two</li>
</ul>
Then is Javascript:
var addItems = function(html) {
$('#items').append(html);
//How do I access the new items here?
}
Let's say that html is:
<li class="item">three</li>
<li class="item">four</li>
I need to do something to the two new items. This something includes binding events to them. So I cannot simply use $('.item') because that will add double events to the existing items. Once the new items are part of the DOM, there is nothing about them that distinguishes them from the existing items.
What's the best way to do this?
Make a jQuery collection of the html before appending it:
var addItems = function(html) {
var $items = $(html);
$('#items').append($items);
$items.foo();
}
Here's a working example: http://jsfiddle.net/hunter/7UTA2/
var addItems = function(html) {
var $html = $(html);
$('#items').append($html);
$html.text("test");
}
This showcases that you still can manipulate the text (or whatever attribute) of the items since you still have a reference to the collection.

JQuery | Find all "," (comma) in an <ul> and erase them / replace with ' '

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

Categories

Resources