Add Hover CSS to table cells processed in javascript - javascript

I'm currently using the below code to colour the cells based on their value:
cell.each(function() {
var cell_value = $(this).html();
if (cell_value == 0){
$(this).css({'background' : '#DF0101'});
} else if ((cell_value >= 1) && (cell_value <=10)) {
$(this).css({'background' : '#FF7C00'});
} else if (cell_value >= 8) {
$(this).css({'background' : '#04B404'});
}
});
I've also added the CSS to the stylesheet:
td:hover{
background-color:#CA2161;}
So how can I make it so that on hover the cells processed in the javascript will change colour? At the minute they won't change at all, they just stay as the colour processed above^^^

Just try to bind an hover function to the "tds" of your table like this
$('td').hover(function(){
$(this).css('background-color', '#CA2161');
});
and if you want to remove the colour on mouse out you can try this
$( "td" ).hover(
function() {
$(this).css('background-color', '#CA2161');
}, function() {
$(this).css('background-color', '');
}
);

EDIT: Turns out you want the colors to leave instead of show when you hover. Simple change.
Okay first of all, you should separate these out into CSS classes:
.ZeroValue {
background:'#DF0101';
}
.ValueBetween1And10 {
background:'#FF7C00';
}
.ValueOver8 {
background:'#04B404';
}
.ValueTransparent {
background:transparent !important;
}
Add the above classes on $(document).ready() based on their values:
if(cell_value === 0){
cell.addCLass('ZeroValue');
} else if((cell_value >= 1) && (cell_value <= 10)){
cell.addClass('ValueBetween1And10');
} else if(cell_value >= 8){
cell.addClass('ValueOver8');
}
Then just dynamically add the transparent class when you hover, removing it when you leave:
cell.on({
mouseenter:function(){
$(this).addClass('ValueTransparent');
},
mouseleave:function(){
$(this).removeClass('ValueTransparent');
}
});
Or if there was a unique color to each item and you wanted to temporarily remove that, you would just create a function:
function classByValue(cell,cell_value){
if(cell_value === 0){
cell.addCLass('ZeroValue');
} else if((cell_value >= 1) && (cell_value <= 10)){
cell.addClass('ValueBetween1And10');
} else if(cell_value >= 8){
cell.addClass('ValueOver8');
}
}
This will clear any of the classes when the mouse enters, and then re-add the class based on cell_value when mouse enters. Then dynamically apply on load and when mouseleave. The $(document).ready():
cell.each(function(){
classByValue(this,this.val());
});
And the hover:
cell.on({
mouseenter:function(){
$(this).removeClass('ZeroValue ValueBetween1And10 ValueOver8');
},
mouseleave:function(){
classByValue($(this),$(this).val());
}
});
There you have it, multiple ways to accomplish your goal. You might need to modify $(this).val() to appropriately reflect the value of that specific cell, but without your HTML I can't really determine that.
As a side, that last option with >= 8 should probably be reconsidered, because a value of 8 or 9 will never fire it.

Related

Jquery - If each() .filter working on console but not in code in realtime

Context:
I have a gallery of images. The user can select each image, when they click it, the "selected" attribute is added to the individual element and a new class is added to their chosen image.
The thing is, I want to limit this to only 2 selections being available.
I want to edit my script to only run up until the length is 2 or less. If the length reaches 2, no more Selected attributes to be added and no more class changes to be toggled.
I feel like I'm close. Right now my users can select/deselect but they can just do it too many times. Where am I going wrong?
function NFTSelector() {
$("#NFTGallery2 > img").each(function() {
$(this).on("click", function() {
if($(this).filter("[selected]").length>=2) {
alert('true');
} else
console.log("less than 2 or undefined so letting them choose more");
{
$(this).toggleClass('chosenNFT');
if ($(this).attr('selected')) {
$(this).removeAttr('selected');
} else {
$(this).attr('selected', 'selected');
}
}
})
});
}
I changed my approach, I instead set it up as checkboxes and limited the checkboxes this way
function NFTSelector() {
var limit = 3;
$('#NFTGallery2 > li > input').on('change', function(evt) {
if($('#NFTGallery2 > li > input:checked').length >= limit) {
this.checked = false;
}
});
}

Input is not detecting that it is empty if removing text with "ctrl + a + backspace"

I am doing some easy div filtering with jQuery and input field. It is working, however it is not detecting that it is empty if I remove input using " Ctrl + a + backspace ", in other words if I select all text and remove it. What causes this?
It is not reordering divs back to default if using the keyboard commands but is going back to normal if you backspace every character.
This is how I do it:
$('#brandSearch').keyup(function() {
var valThis = $(this).val().toLowerCase();
if (valThis.length == 0) {
$('.card').show();
} else {
$('.card').each(function() {
var text = $(this).text().toLowerCase();
(text.indexOf(valThis) >= 0) ? $(this).parent().show(): $(this).parent().hide();
});
};
});
Your if block that handles the empty string is not showing the same elements that the else block hides. The else block calls .parent() but the if block does not.
So the else case shows or hides the parent of each .card element, but the if case shows the .card elements themselves—without unhiding their parents. See my comments added to the code (I also reformatted the conditional expression in the else for clarity):
$('#brandSearch').keyup(function() {
var valThis = $(this).val().toLowerCase();
if (valThis.length == 0) {
// Show all of the .card elements
$('.card').show();
} else {
$('.card').each(function() {
var text = $(this).text().toLowerCase();
// Show or hide the *parent* of this .card element
text.indexOf(valThis) >= 0 ?
$(this).parent().show() :
$(this).parent().hide();
});
};
});
Since it sounds like the non-empty-string case is working correctly, it should just be a matter of adding .parent() in the if block so it matches the others:
$('#brandSearch').keyup(function() {
var valThis = $(this).val().toLowerCase();
if (valThis.length == 0) {
// Show the parent of each .card element
$('.card').parent().show();
} else {
// Show or hide the parent of each .card element
$('.card').each(function() {
var text = $(this).text().toLowerCase();
text.indexOf(valThis) >= 0 ?
$(this).parent().show() :
$(this).parent().hide();
});
};
});
This is the kind of situation where familiarity with your browser's debugging tools would pay off big time. The .show() or .hide() methods manipulate the DOM, and by using the DOM inspector you could easily see which elements are being hidden and shown.
In fact, as a learning exercise I recommend un-fixing the bug temporarily by going back to your original code, and then open the DOM inspector and see how it reveals the problem. While you're there, also try out the JavaScript debugger and other tools.
If you use Chrome, here's an introduction to the Chrome Developer Tools. Other browsers have similar tools and documentation for them.
It seems to be working just fine:
$('#brandSearch').keyup(function() {
var valThis = $(this).val().toLowerCase();
if (valThis.length == 0) {
$('.card').show();
console.log("input is empty");
} else {
console.log("input is not empty");
$('.card').each(function() {
var text = $(this).text().toLowerCase();
(text.indexOf(valThis) >= 0) ? $(this).parent().show(): $(this).parent().hide();
});
};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="brandSearch">

If element changed class from one particular to another in jQuery

Normally my slideshow goes automatically to the next picture, but I want to detect if it goes backwards by an user-initiated action (keyboard arrows or controls). My solution to this would be to do this (my imaginary code):
if(jQuery("#slideshow article").hasChangedClassFrom("previous").hasChangedClassTo("current")) {
backwards = true;
}
if(backwards) { // code for backwards
jQuery("#slideshow article.previous").css("z-index", "1");
jQuery("#slideshow article.next").css("z-index", "2");
}
else { // code for forwards (normal state)
jQuery("#slideshow article.previous").css("z-index", "2");
jQuery("#slideshow article.next").css("z-index", "1");
}
The classes are already implemented, so that the current slide always has the class "current" and so on. I know this isn't valid code at all, but by reading this, I think it would be quite clear what I want to achieve. I'm not very good at JavaScript/jQuery, but I've tried searching for solutions like this without luck.
Live site // Live JS code
Based on the code from the mentioned link http://dans.no/cycle.js
Declare a variable clickindex=0;
Place the following inside the click function of jQuery("#slideshow nav a").click
clickindex = jQuery("#slideshow nav a").index(this);
if(clickindex<index){
console.log("execute some logic");
}
The jsfiddle link for my solution javascript code http://jsfiddle.net/y601tkfL/
Instead of guessing that the previous class, use the current and the previous index.
http://jsfiddle.net/whyba4L9/5/
UPDATE 2:
var stopp, antall = jQuery("#slideshow article").length;
var index = 0
function slideTo(idx) {
jQuery("#slideshow article, #slideshow nav a").removeAttr("class").filter(':nth-of-type(' + (idx+1) + ')').addClass("current");
if(jQuery("#slideshow article:nth-of-type(2)").hasClass("current")) {
jQuery("#slideshow article:first-of-type").addClass("forrige");
jQuery("#slideshow article:last-of-type").addClass("neste");
}
else if(jQuery("#slideshow article:first-of-type").hasClass("current")) {
jQuery("#slideshow article:last-of-type").addClass("forrige");
jQuery("#slideshow article:nth-of-type(2)").addClass("neste");
}
else if(jQuery("#slideshow article:last-of-type").hasClass("current")) {
jQuery("#slideshow article:nth-of-type(2)").addClass("forrige");
jQuery("#slideshow article:first-of-type").addClass("neste");
}
if(index ==antall-1 && idx ==0 )
{
//lasto to first
}
else if(index>idx || (index == 0 && idx == antall-1))
{
alert('BACKWARDS')
}
index = idx;
};
function startCycle() {
stopp = setInterval(function() {
jQuery("#slideshow article").stop(true, true);
var idx = index + 1 > antall - 1 ? 0 : index + 1;
slideTo(idx,false);
}, 5500);
};
if (antall > 1) {
jQuery("#slideshow").append("<nav>").css("height", jQuery("#slideshow img").height());
jQuery("#slideshow article").each(function() {
jQuery("#slideshow nav").append("<a>•</a>");
}).filter(":first-of-type").addClass("current first");
jQuery("#slideshow article:nth-of-type(2)").addClass("neste");
jQuery("#slideshow article:last-of-type").addClass("forrige");
startCycle();
jQuery("#slideshow nav a").click(function() {
clearInterval(stopp);
startCycle();
var idx = jQuery("#slideshow nav a").index(this);
if (index === idx) return;
slideTo(idx);
}).filter(":first-of-type").addClass("current");
jQuery(document).keyup(function(e) {
if (e.keyCode == 37) {
var idx = index - 1 < 0 ? antall - 1 : index - 1;
slideTo(idx);
clearInterval(stopp);
startCycle();
}
else if (e.keyCode == 39) {
var idx = index + 1 > antall - 1 ? 0 : index + 1;
slideTo(idx);
clearInterval(stopp);
startCycle();
}
});
}
Try calling this function when the user changes the image with parameter of this. I hope I correctly understood what you are asking. If not let me know and I will recode it. Also if the slide show is finished please post your html and javascript.
function whatever(this)
{
if(this.className == 'previous')
{
alert('the user has changed the image');
this.className = 'current';
}
else
{
alert('the user hasn\'t changed the image');
}
}
The dead simplest way to do this, from what I understand your question to aim at, is to put a handler on the index buttons and a method for tracking the current image.
Listen for slide change
var currentSlide = '';
$('.slideIndexButtons').on('click', function(e){
// Conditional logic that compares $(this).data('whichimage') to currentSlide
var whichImage = $(this).data('whichimage');
// ->this means attaching data-whichimage="" to each of the elements, or
// ->you can just stick with detecting the class and going from there
// Either process results in isBackwards boolean
if (currentSlide == 'prev' && whichImage == 'current') {
isBackwards = true;
}
if (isBackwards) {
// Backwards logic here
} else {
// Other logic here
}
// Unless the event we're listening for in keeping currentSlide updated is also fired when
// the slide changes due to user input, we'll need to update currentSlide manually.
currentSlide = whichImage;
});
Track the current slide
$('#slider').on('event', function(){
// This is assuming that we're strictly listening to the slider's automatic sliding
// The event you attach this to is either fired before or after the slide changes.
// Knowing which is key in getting the data you want. You are either getting
// The data from this slide $(this).data('whichimage') or
// $(this).next().data('whichimage')
// Again, you can go with classes, but it is a lot of logic which you have to
// update manually if you ever have to add or alter an image in the slide set.
// Either way, you end up with the variable targetImage
currentSlide = targetImage;
});
With any luck, your slideshow code has an API that will allow you to listen for when slide-related events are fired. Otherwise, you'll have to find a way of setting up, firing and listening for these events manually, either through callbacks passed in or by (eek!) altering the code and possibly unintentionally changing its functionality.
This should give you what you asked for. Let me know how it goes.
You can add this line at the very start of slideTo function in your cycle.js
if((idx < index && !(idx == 0 && index == antall - 1)) ||
(idx == antall - 1 && index == 0)){
jQuery.trigger('BACKWARDS')
}
and then add an event handler for "BACKWARDS" somewhere else convenient (Maybe at the end of cycle.js?).
jQuery.on('BACKWARDS', function(e){
//DO THINGS HERE
}
I wrote a plugin attrchange which I think will effectively solve your problem. attrchange is a simple jQuery plugin to detect an attribute change. The plugin internally uses one of the following compatible methods based on the browser to detect an attribute change,
Mutation Observer
DOMAttrModified
onpropertychange
Try out below demo to understand more about how you can use the plugin for your need.
Click to read more about attrchange.
Note: The plugin doesn't use polling so you can use it without any worries, however polling is supported as an extension to the plugin. You can read more if you are interested.
$('#test').one('click', function() {
$('#test').attrchange({
trackValues: true,
callback: function(event) {
$('#result').html('<div><label>Attribute Name: </label>' + event.attributeName + '</div>' + '<div><label>Old Value</label>' + event.oldValue + '</div>' + '<div><label>New Value</label>' + event.newValue + '</div>');
}
});
//this will toggleClass 'blue-background' every 2 secs
setInterval(function() {
$('#test').toggleClass('lightblue-background');
}, 2000);
});
html {
font-family: Segoe UI, Arial, sans-serif;
font-size: 13px;
}
div#test {
border: 1px solid #d2d2d2;
padding: 10px;
display: inline-block;
}
.lightblue-background {
background-color: #DBEAF9;
}
div label {
font-weight: bold;
margin-right: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://raw.githubusercontent.com/meetselva/attrchange/master/js/attrchange.js"></script>
<div id="test">
<p style="font-weight: bold;">Click anywhere in this box to Start the DEMO</p>
<p>The demo is to simply toggle a class 'lightblue-background' to this div every 2 secs.</p>
<div id="result" style="font-size: 0.9em;"></div>
See the pseudo code for your case using the plugin,
jQuery("#slideshow article").attrchange({
trackValues: true,
callback: function(event) {
if ($(this).hasClass('current') &&
(event.oldValue && event.oldValue.indexOf('previous') >= 0)) {
//code for backward
} else {
//code for forward
}
}
});

Float list-items left when others are hidden

I'm having an issue with my list items not floating left automatically upon toggling the visibility of other list items through a filter.
See the website and code here:
http://javinladish.com/dev/
When you toggle 'Gloves' for example, the gloves should not appear in the same place, but instead move to the first slot in the list.
Is the plugin I'm using called AwesomeGrid causing this issue? It might be absolutely positioning the li elements, but I'm not exactly sure.
The jQuery code I'm using to toggle the filter and list-items is:
$(document).ready(function() {
$('ul#filter a').click(function() {
$(this).css('outline','none');
$('ul#filter .current').removeClass('current');
$(this).parent().addClass('current');
var filterVal = $(this).text().toLowerCase().replace(' ','-');
if(filterVal == 'all') {
$('ul.grid li.hidden').fadeIn('slow').removeClass('hidden');
} else {
$('ul.grid li').each(function() {
if(!$(this).hasClass(filterVal)) {
$(this).fadeOut('normal').addClass('hidden');
} else {
$(this).fadeIn('slow').removeClass('hidden');
}
});
}
return false;
});
});
How can I make sure that when I filter my list-items, that they always float left?
Thanks in advance to anyone who helps out!
AwesomeGrid has a built in property called hiddenClass, you can define hidden as your hidden class selector, then recall AwesomeGrid after the click event. Basically the code will be like this :
$(window).load(function(){
function grid_relayout() {
$('ul.grid').AwesomeGrid({
responsive : true,
initSpacing : 0,
rowSpacing : 28,
colSpacing : 28,
hiddenClass : 'hidden',
columns : {
'defaults' : 3,
'990' : 2,
'650' : 1
}
})
}
grid_relayout();
$('ul#filter a').click(function() {
$(this).css('outline','none');
$('ul#filter .current').removeClass('current');
$(this).parent().addClass('current');
var filterVal = $(this).text().toLowerCase().replace(' ','-');
if(filterVal == 'all') {
$('ul.grid li.hidden').fadeIn('slow').removeClass('hidden');
} else {
$('ul.grid li').each(function() {
if(!$(this).hasClass(filterVal)) {
$(this).fadeOut('normal').addClass('hidden');
} else {
$(this).fadeIn('slow').removeClass('hidden');
}
});
}
grid_relayout()
return false;
});
})
If you look at the CSS properties of the "li" elements, you see that they are positioned "absolute" with pixel values for "left". What you want is "float: left". But I don't know AwesomeGrid so I can't give you a solution without studying it further.

jQuery $(this) duplicate

This code really messes me up.. Could you help? There is 5 elements, with the #newlinks. In all #newlinks, there is childs of a. This code runs perfect on the first #newlinks, but after that one, it won't give the even a-elements a gray background.
#newlinks.
$(function(){
var bg = 0;
$("#newlinks").children("a").each(function(){
if(bg % 2 == 0){
$(this).css("backgroundColor", "#F2F2F2");
bg++;
}else{
bg++;
}
});
});
I have also tried this, but i guess it won't work, because $(this) could be both the newlinks-element selected and the a-element selected.
$(function(){
var bg = 0;
$("#newlinks").each(function(){
$(this).children("a").each(function(){
if(bg % 2 == 0){
$(this).css("backgroundColor", "#F2F2F2");
bg++;
}else{
bg++;
}
});
});
});
You can not give the same ID for more than one elements. They must be unique.
You must use classes. So that $(".newlinks") selector should work.
ID should be only one per page. Please change to class like <div class="newlinks"> and then use the code below :
$(function(){
$(".newlinks").children("a").each(function(index){
if(index % 2 == 0){
$(this).css("background", "#000000");
}
});
});
Try this jssfiddle :
$(function () {
$("#newlinks a").each(function (index) {
if (index % 2 == 0) {
$(this).css("backgroundColor", "#F2F2F2");
}
});
});

Categories

Resources