CSS class depending on list items text length - javascript

Is there a way to set different classes to items in a list depending on the length of the value? Preferrably plain JS or jQuery.
I have a list with fixed width, and the text amount in each list item varies. The list items has backgrounds which can't be repeated or extend, and because of that I would need to make different backgrounds (classes) for different text lengths.
1-15 chars would be taken care of by the default css class, 15-30 chars would need an extra class with the extended background and 30-45 chars would need another class etc.
Being a total n00b in JS I just can't manage to figure this out, even though I've been fiddling with it for the last two days...
Thanks a lot in advance,
Eirik.

$('#myList li').each(function() {
var length = ($(this).html().length);
if (length > 30) {
$(this).addClass('longest');
}
else if (length > 15) {
$(this).addClass('long');
}
else {
$(this).addClass('default');
}
});
Working example here.

$('.listItem').each(function(){
var content = $(this).html();
if(var.length > 30){
$(this).addClass('Over30');
}
.....etc
Set this to run after the content has loaded e.g.
$(document).ready(function () {
$('.listItem').each(function(){
var content = $(this).html();
if(var.length > 30){
$(this).addClass('Over30');
}
.....etc
}

Related

How to check last element has a css class or not?

I am adding class to these elements one by one based on user input. When I reached the last span element of this section, i need to give pop up. How to check that this last span has added a css class?
<section id="word-section"><span class="incorrect-word-c">ਪਰਕੋ</span><span class="current-word">ਚੇਤਕ</span><span>ਚਰਚ</span><span>ਪਰਕ</span><span>ਰੋਕ</span><span>ਰੇਤ</span><span>ਕਰੋ</span><span>ਚਟਪਟ</span><span>ਤਕ</span><span>ਰੁਤ</span><span>ਚਰਚ</span><span>ਰੋਕੋ</span><span>ਰਕਤ</span><span>ਰੋਕ</span><span>ਚਰਚ</span><span>ਪਰਕ</span><span>ਰੇਤ</span><span>ਪਰਕ</span><span>ਪਰਕ</span><span>ਪਰਤ</span><span>ਕਿ</span><span>ਰੋਕ</span><span>ਚੋਕਰ</span><span>ਰਕਤ</span><span>ਕਿ</span><span>ਰੋਕੋ</span><span>ਰੇਤ</span></section>
var remaining = $('#word-section > span').not('.current-word').length;
This command will find all spans that are direct children of the word-section section. It then filters to only include those that do not have the current-word class, and get the length (count) of them.
If remaining is zero, they all have the class.
To answer the specific question
Check if last element has a css class or not
you can use:
$("#word-section > span:last").hasClass("current-word")
this will:
find word-section
get all direct-descendant spans
limit the spans to the last one :last
check if that last one has class current-word
There's lots of different ways to do this, eg:
$("#word-section").find(">span").last().is(".current-word")
$("#word-section > span.current-word:last").length == 1
$("#word-section > span.current-word").nextAll().length == 0
Example snippet:
if ($("#word-section > span:last").hasClass("current-word")) {
// show popup
console.log("example: last word is current-word");
}
else {
console.log("example: more words to go");
}
if ($("#word-section-sample2 > span:last").hasClass("current-word")) {
// show popup
console.log("sample2: last word is current-word");
}
else {
console.log("sample2: more words to go");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section id="word-section"><span class="incorrect-word-c">ਪਰਕੋ</span><span class="current-word">ਚੇਤਕ</span><span>ਚਰਚ</span><span>ਪਰਕ</span><span>ਰੋਕ</span><span>ਰੇਤ</span><span>ਕਰੋ</span><span>ਚਟਪਟ</span><span>ਤਕ</span><span>ਰੁਤ</span><span>ਚਰਚ</span><span>ਰੋਕੋ</span><span>ਰਕਤ</span><span>ਰੋਕ</span><span>ਚਰਚ</span><span>ਪਰਕ</span><span>ਰੇਤ</span><span>ਪਰਕ</span><span>ਪਰਕ</span><span>ਪਰਤ</span><span>ਕਿ</span><span>ਰੋਕ</span><span>ਚੋਕਰ</span><span>ਰਕਤ</span><span>ਕਿ</span><span>ਰੋਕੋ</span><span>ਰੇਤ</span></section>
<section id="word-section-sample2"><span class="incorrect-word-c">ਪਰਕੋ</span><span>ਚੇਤਕ</span><span>ਚਰਚ</span><span>ਪਰਕ</span><span>ਰੋਕ</span><span>ਰੇਤ</span><span>ਕਰੋ</span><span>ਚਟਪਟ</span><span>ਤਕ</span><span>ਰੁਤ</span><span>ਚਰਚ</span><span>ਰੋਕੋ</span><span>ਰਕਤ</span><span>ਰੋਕ</span><span>ਚਰਚ</span><span>ਪਰਕ</span><span>ਰੇਤ</span><span>ਪਰਕ</span><span>ਪਰਕ</span><span>ਪਰਤ</span><span>ਕਿ</span><span>ਰੋਕ</span><span>ਚੋਕਰ</span><span>ਰਕਤ</span><span>ਕਿ</span><span>ਰੋਕੋ</span><span class="current-word">ਰੇਤ</span></section>

Selecting 4 images from the list

I want to create a list of hundred image boxes (50x50 px), and I wanna be able to choose four of them. To check the fifth one, I'd have to uncheck one of the previous ones.
I have found jQuery UI selectable component to do this, I could be able to use ajax to dynamically save information to the database (everything has to be stored in the database here).
The problem is that I couldn't find options to limit selection to 4, and I couldn't find the option to select elements by default after the page is loaded.
How can I do what I want to?
Right now I only have jQuery code:
$("#selectable").selectable();
An SQL choosing images and simple for loop generating those boxes.
Thanks!
This will limit to the first 4 selections using jQueryUI selectable
function clearOverlimitSelections(evt, ui) {
var selectableClasses = {
selectableselecting: 'ui-selecting',
selectableselected: 'ui-selected'
},
selectableClassName = selectableClasses[evt.type];
var $selection = $(this).find('.' + selectableClassName);
if ($selection.length >= 4) {
$selection.filter(':gt(3)').removeClass(selectableClassName)
}
}
$("#selectable").selectable({
selecting: clearOverlimitSelections,
selected: clearOverlimitSelections
});
DEMO
Suppose you have this:
<img class="select-4" ...>
<img class="select-4" ...>
...
<img class="select-4" ...>
The following jQuery code should select a maximum of 4 images:
$('img.select-4').on('click', function(){
var iAmSelected = $(this).hasClass('selected');
if (iAmSelected) {
$(this).removeClass('selected');
} else {
var canAddSelection = $('img.select-4').length < 4;
if (canAddSelection) {
$(this).addClass('selected');
}
}
});
Then, you can use the selected class to style your selected images as you like. The same technique can be used with <input type="checkbox"> elements.

If value is greater than, less than and becomes greater than again

I'm having a problem with my following logic.
Jsfiddle
The logic
var budgetCalc = function (financeBudget, totalCost, remainingBudget, changeOn) {
var reloadCalc = function () {
var formula = parseFloat($(financeBudget).val()) - parseFloat($(totalCost).val());
$(remainingBudget).val(Math.abs(formula.toFixed(0)));
if ( formula >= 0 ) {
$('.toolbar-budget').addClass('is-positive').append('<p>Remaining</p>');
} else {
$('.toolbar-budget').addClass('is-negative').append('<p>Over Budget</p>');
}
};
$(document).ready(function () {
// Price Input
$(changeOn).change(function () {
reloadCalc();
});
$(changeOn).trigger('change');
});
};
What works fine
The interface has multiple selects, inputs and a jQuery sliders that change the value of formula. The logic works fine when the page loads and the formula value is >= 0. If the value is < 0 than the formula works fine as well.
The Issue
If the value of the formula is < 0 and then becomes > 0 again because the user changes the values contributing to formula, the logic does not change the class back to .is-positive unless the page refreshes.
My goal
I want the class of .is-positive to be applied without the page refreshing if the value goes from < 0 to >= 0.
Seems like the simplest solution would be to remove both classes before adding the appropriate one but adding $('.toolbar-budget').removeClass('is-positive is-negative'); before your check:
$('.toolbar-budget').removeClass('is-positive is-negative');
if (formula >= 0) {
$('.toolbar-budget').addClass('is-positive').append('<p>Remaining</p>');
} else {
$('.toolbar-budget').addClass('is-negative').append('<p>Over Budget</p>');
}
jsFiddle example
You use addClass() and do not clear existing classes, so you end up with both classes set. You should remove previously set classes via removeClass() or toggleClass().
Also, I'd recommend to do the same with .append('<p>Remaining</p>'); part, so you don't just append paragraphs but swich them.

Can't get javascript/jquery to sort elements correctly more than one time

I have child divs that I'm trying to sort based on a jquery .data() value that I give them that is just a single number. This code works perfectly, but only once, after that I can't figure out how the heck it's sorting them. Here is a simplified version:
var myArray = $('#container div').get();
myArray.sort(function(x,y) {
return $(x).data('order') - $(y).data('order');
});
$('#container').empty().append(myArray);
I've tried so many other different methods of sorting, other plugins, etc., and I can't get anything to work right. This is as close as I can get. I just have this running on a jquery change event.
Here is the whole thing in case I'm doing something stupid elsewhere:
$('#attorneyFilter').change(function() {
//get array of links for sorting
var myArray = $('#attorneyBlocks div').get();
var selectedArea = $(this).val();
//sort alphabetically when "all" is selected
if (selectedArea == 'all') {
$('#attorneyBlocks div').show();
myArray.sort(function(a,b) {
return $(a).text() > $(b).text() ? 1 : -1;
});
//filter attorneys based on practice area and then assign its order# to the div with data, getting all values from the div's class
} else {
$('#attorneyBlocks div').hide().each(function() {
var attorneyArea = $(this).attr('class').split(', ');
for (var i=0;i<attorneyArea.length;i++) {
var practiceArea = attorneyArea[i].split('-');
if (selectedArea == practiceArea[0]) {
$(this).show().data('order',practiceArea[1]);
}
}
});
//sort based on order, the lower the number the higher it shows up
myArray.sort(function(x,y) {
return $(x).data('order') - $(y).data('order');
});
}
//append order back in
$('#attorneyBlocks').empty().append(myArray);
});
And a link to the page in question
Here's a jsFiddle with this working using .detach() instead of .empty() to keep the data.
http://jsfiddle.net/shaneblake/Tn9u8/
Thanks for the link to the site, that made it clear.
It seems to me you never clear out the data from the prior time. You hide everything but maybe something like this will solve your problem (here I set everything hidden to the bottom, you can clear it or use a different value -- as long as it is not the same as any sort key):
$('#attorneyBlocks div').hide().data('order',999999).each(function() {
var attorneyArea = $(this).attr('class').split(', ');
for (var i=0;i<attorneyArea.length;i++) {
var practiceArea = attorneyArea[i].split('-');
if (selectedArea == practiceArea[0]) {
$(this).show().data('order',practiceArea[1]);
}
}
});
Also, the code on the server is missing the 2nd line you have above:
var myArray = $('#attorneyBlocks div').get();
The problem is the change event is tied to the original items. After the sort you make all new items. They don't have any event tied to them. You will need to use .live()
Eventually figured it out, the data values from hidden divs were screwing with my sorting, so I changed my sorting code to only pay attention to :visible divs and that did the trick. Doh! Thanks for your help everyone.

Logical problem,seeking an algorithm

I am developing a javascript filtering of some results and have some difficulties..
Here is the problem...
Suppose that we have some criteria
Manufacter (Trusardi, Calvin Kein, Armani...)
Color (red, blue, black...)
OtherFeatures (goretex, blah, blah...)
Each feature is displayed as a checkbox...
The problem is that i want to disable the checkboxes if its selection would lead to no results..For example Armani's products may have color blue only so checking armani should disable the black and red,but other manufactors shouldnt be disabled... as checking them should provide a result...
Here is the code so far
results = $("#products li");
results.hide();
var filtersGroup = $("#filters li.filtersGroup");
$("#filters li.filtersGroup a").removeClass("disabled");
filtersGroup.each(function(index) {
var classes = "";
$(this).find("a.checked").each(function(index) {
classes = classes + "." + $(this).attr("id") + ",";
});
if (classes == "") return true;
results = results.filter(classes.substr(0, classes.length - 1));
//periorismos
filtersGroup.not($(this)).each(function(index) {
$(this).find("a").each(function(index) {
if (results.filter("." + $(this).attr("id")).length <= 0) {
$(this).removeClass("checked").addClass("disabled");
}
});
});
});
Although it filters them successfully ,the disabling isnt always correct. for example to reproduce the problem ,if you choose all the manufactors and then choose a color manufactors would be disabled but colors not at the first time..
One solution i figured is to create multiple results which would simulate all the next possible check.(if 16 features and 4 checked means 12 possible other checked ..
But i think that this approach sucks... Any other idea?
You could add a class for each manufacturer, colour, etc. then simply disable by class. I assume here there's a results hash keyed off manufacturer:
results['Trusardi'] = 5
results['Armani' = 0
..then:
$("#filters li.filtersGroup a").addClass("disabled");
foreach (m in manufacturers) {
if (manufacturers[m] > 0) {
$("#filters li.filtersGroup a." + m).removeClass("disabled");
}
}
etc.
You have a faceted search problem - where many combinations produce no results. Instead of disabling, I suggest calculating and showing how many results results would appear if a given criterion is selected. Then with each click, executing that algorithm again. So your search would like very similar to newegg.com:
http://www.newegg.com/Store/SubCategory.aspx?SubCategory=10&name=Desktop-PCs
Depending on how much data you're dealing with you might want to consider using solr.
I think that i found the solution.. It was simpler than i thought... I was trying to find a solution all day long and it was simpler than i thought..
Here it is....
results=$("#products li");
results.hide();
var groupClasses=[];
var groupsChecked=0;
var filtersGroup=$("#filters li.filtersGroup");
$("#filters li.filtersGroup a").removeClass("disabled");
filtersGroup.each(function(index) {
var classes="";
$(this).find("a.checked").each(function(index) {
classes=classes+ "." + $(this).attr("id") +",";
});
groupClasses[groupClasses.length]=classes;
if(classes=="") return true;
groupsChecked++;
results=results.filter(classes.substr(0,classes.length-1));
});
//disable
var gi=0;
filtersGroup.each(function(index) {
if( ! (groupsChecked<=1 && groupClasses[gi]!=""))
{
$(this).find("a").not(".checked").each(function(){
if (results.filter("." + $(this).attr("id")).length <= 0) {
$(this).removeClass("checked").addClass("disabled");
}
});
}
gi++;
});
It seems to be correct. I amnot sure though but testing it seems ok..
Can't you just compute the results for every unchecked option and compare them to the current products that suffice. (I'm not very familiar with jQuery so I wouldn't know how...)

Categories