I am trying to play around with learning jQuery and have made the following jsFiddle:
http://jsfiddle.net/jkNK3/
The idea is to have a div's color change on click. Fine, I got that but I am wondering if there is a way to have the div's color change through multiple classes changes, perhaps with some sort of array or loop. Let me explain.
I have created several CSS classes like so:
.color1 {..}
.color2 {..}
.color3 {..}
.color4 {..}
.color5 {..}
.color6 {..}
and am wondering if we can do something like
addClass("color" + i)
where i can be looped through 1 - 6.
Is there any way to accomplish this? Thanks for the help.
This is a good place to consider the danger of global javascript namespaces. Here's a simple example that takes advantage of closures to avoid that with jquery:
$(function() {
var numb = 1;
// this bit of managing the color state swap is another topic for discussion, so keeping it simple
var colors_len = 6;
$("div").click(function() {
// this closure has access to the numb variable
if (numb < colors_len) {
numb++;
$(this).addClass("color" + numb);
$(this).removeClass("color" + (numb-1));
} else {
numb = 1;
$(this).removeClass("color" + colors_len);
$(this).addClass("color" + numb);
}
});
});
http://jsfiddle.net/2taH5/
ps. Jquery ui also has a swap class method but that is more for animations
In my opinion the easiest would be to just store the color number in jQuery's handy data(), and then increment it from that:
function fnClick() {
var numb = $(this).data('color') || 2;
$(this).addClass("color" + numb).data('color', ++numb)
}
FIDDLE
To make it go back to the first color after the last color etc
function fnClick() {
var numb = $(this).data('color') || 2;
numb = numb == 7 ? 1 : numb;
$(this).removeClass().addClass("color" + numb).data('color', ++numb)
}
FIDDLE
How about using a random number to give a random color to the div.
var classCount = 6;
$(document).ready(function () {
$("div").on("click", fnClick);
});
function fnClick(e) {
// Get the currently clicked element
var $this = $(e.target),
className = 'color' + Math.floor((Math.random() * classCount )+1);
// Remove the exixting class/s
$this.removeClass();
// Add the class
$this.addClass(className);
}
Check Fiddle
Related
I made a kind of game in javascript and in this game there are some divs which are horizontally moving with different transition times. In this game there is a function which is called each 1/100 seconds. Then it first checks it position with:
$("class1").css("margin-left")
And now the weird thing: when I set the class in html like:
<div class = "class1"></div>
The .css("margin-left") works perfectly, but when I don't set a class in html and I add the class in js like:
$("div:nth-child(6)").addClass("class1");
Then the $(theclass).css("margin-left") give wrong outputs.
I tried with the .position and .offset but those both didn't work for me.
My code:
function newBlock(block, marginTop, bgc, height, hoogte1, hoogte2, v, tijd){
block.css("background-color", bgc).css("height", height).css("margin-top", marginTop);
var movement1 = "movement1";
var movement2 = "movement2";
// if (positionPixelsBlockF > 0){
// positionPixelsBlockF = positionBlockF.slice(0, 3);
// }
setInterval(positie, 10);
function positie(){
tijd = tijd + 1;
if (v != 0){
block.addClass("i" + v);
$(".i" + v).css({"width": "50px", "display": "inline-block", "position": "absolute", "z-index": "20"});
var positionBlockF = $(".i" + v).css("margin-left");
var positionPixelsBlockF = positionBlockF.slice(0, 4);
$("#uitleg4").html(positionPixelsBlockF);
else if (v === 0){
var positionBlockF = $(".b1").css("margin-left");
var positionPixelsBlockF = positionBlockF.slice(0, 4);
Don't mind the incomplete use of the {}, but in my code that's fixed.
PS: using brackets
I believe you are missing a dot before class1 selection, in jquery there are two types of elements selection either by class like $(".ElemnetClass") OR by ID like $("#ElementID")
More info about .css()
This Is An Example Of Your Requirement
$(".class").css('margin-left','10px');// Some Px (or) percentage Your Based On Requirement
You Can Use This Type Also Firstly You Create One Class Of Your Requirements
And Use Below Code
$("#ElementId").addClass('created classname Here');
I need to change each item's color in a list after a reorder or removing one item, now I am using jquery's css method like below
$('li').css('background-color', color);
It works, but terribly slow, and sometimes the page will render the color incorrectly, even on Chrome, which is supposed to be fast. The list doesn't have many items, below 10, usually 5 - 7. So this performance is not acceptable. So I want to know if there is a better, faster way in CSS3, or HTML5. If not, if there is an walkaround or some kind of jquery solution?
The code for refreshing list items' color is as below. The index can be decided by a function and the color can decide color by it. The major issue I think is that changing background color trigger reflow or maybe rerendering.
function refreshListItemColor(liElements, colorGetter, indexGetter) {
colorGetter = colorGetter || (function (color) {
return color;
});
indexGetter = indexGetter || (function (liElement, index) {
return index;
});
liElements.each(function (index, liElement) {
index = indexGetter(liElement, index);
var data = ko.dataFor(liElement);
var indexColor = colorForIndex(index);
indexColor = colorGetter(indexColor, data);
if (indexColor !== $(liElement).css('background-color')) {
$(liElement).css('background-color', indexColor);
}
});
}
Update: using element.style['background-color'] won't do. The issue still remains. Another possible explanation for the lagging is that every list item itself has about 10 child elements, making change list item's color particularly expensive.
Update2: I'll try to ask a related question: is there a way to change the color of the background of the parent node without triggering a rerender of children elements?
Update3: I tried to add delay for each color change operation, like below
var delay = 100, step = 100;
liElements.each(function (index, liElement) {
index = indexGetter(liElement, index);
var data = ko.dataFor(liElement);
var indexColor = colorForIndex(index);
indexColor = colorGetter(indexColor, data);
if (indexColor !== $(liElement).css('background-color')) {
setTimeout(function () {
liElement.style['background-color'] = indexColor;
}, delay);
delay += step;
}
});
It seems can alleviate this issue a lot. I guess this will not solve the problem, but will reduce the impact to an acceptable level.
Could you use attribute selectors in your stylesheet?
[data-row="1"][data-col="3"]{
background-color: blue;
}
I noticed that If you want to select a whole row or column you have to use !important
[data-col="3"]{
background-color: blue !important;
}
(edit)Adding styles dynamically
Create a empty style tag with a div
<style type="text/css" id="dynamicstyle"></style>
and just append to it like any other tag
$("#dynamicstyle").append('[data-row="0"]{background-color:red !important;}');
for your case you can check whenever an element is added and add a row style since in theory the user could pile up all of the elements.
$(function () {
var maxRows = 0;
$("ul").bind("DOMSubtreeModified", updateStyleSheet);
function updateStyleSheet() {
var childCount = $("ul").children().length;
if (maxRows < childCount) {
maxRows = childCount;
var newRule = [
'[data-row="',
maxRows,
'"]{background-color:', ((maxRows % 2) ? "red" : "blue"),
' !important;}'].join('')
$("#dynamicstyle").append(newRule);
}
}
});
http://jsfiddle.net/PgAJT/126/
FizzBuzz rows http://jsfiddle.net/PgAJT/127/
Remove your "if", which may force browser to redraw/recompile/reflow latest CSS value.
if (indexColor !== $(liElement).css('background-color')) {
Yes, read are slow and as they will block write-combine.
Presumably, the colour is determined by the position of the element in the list.
Use nth-child or nth-of-type selectors in your stylesheet.
Hi i have just tried wat u need just check it..
http://jsbin.com/awUWAMeN/7/edit
function change()
{
var colors = ['green', 'red', 'purple'];
alert(colors)
$('.sd-list li').each(function(i) {
var index = $(this).index();
$(this).css('background-color', colors[index]);
});
}
I've created a simple test with 10 list items, each with 12 children and setting the background colour for every item each time Gridster's draggable.stop event fires. The change is pretty much instantaneous in IE11 and Chrome.
To me, this suggests it isn't the CSS rendering that's slow, but maybe the calculations determining which colours are for which elements.
This is the JavaScript I was using:
var colors = ['#000', '#001', '#002', '#003', '#004', '#005', '#006', '#007', '#008', '#009', '#00a', '#00b'];
$('.gridster ul').gridster({
widget_margins: [10, 10],
widget_base_dimensions: [120, 120],
draggable: {
stop: function (e, ui, $widget) {
refreshListItemColor();
}
}
});
function refreshListItemColor() {
var sortedElements = [];
$('ul > li:not(.preview-holder').each(function () {
sortedElements.push([this, this.getAttribute('data-col'), this.getAttribute('data-row')]);
});
sortedElements.sort(function (a, b) {
return a[1] - b[1] || a[2] - b[2];
});
for (var i = sortedElements.length - 1; i >= 0; i--) {
sortedElements[i][0].style.backgroundColor = colors[i];
}
}
How are you determining which colours to set on each list item?
I've find it fast to create a class with the css attributes you want and then add that class to the dom element you want the css attribute applied to. CSS rules appear without refresh.
css:
.bg-green{
background:green;
}
js:
$("#someDomId").toggleClass('bg-green','add');
A cool way of dealing with lists is to index the id of each list element as you create/alter it:
Create list:
for (i=0;i=m;i++){
var listElement = "<li id='"+i+">Some Content</div>";
$('ul').append(listElement);
}
Then instead of iterating through a dom element (which is expensive) you can run another for loop and alter each list element by selecting it's id.
for (i=0;i=m;i++){
$("#"+i).toggleClass('bg-green','add');
}
I have got something like this in html
<div class="change"><div>
<div class="change"><div>
<div class="change"><div>
<div class="change"><div>
Now here we go for the java script
var base = document.getElementsByClassName("change");
base[0].setAttribute();
console.log(base[0]);
From the console I can see that I"m getting an object but I can't edit it this way, is there any other possibility to edit/add attributes( i need to add a onclick function to like 100 elements).
It's pretty difficult to get the higer object by document.getElementById,
so... anyone got a solution for this?^^
You can add attributes like this
var element = document.getElementByClassName('change')[0];
element.setAttribute(attributeName,attributeValue);
Just use jQuery. Then it's just a matter of doing something like the following:
$(document).ready(function () {
$('.change').click(function () {
$(this).attr('class', 'new-value');
});
});
JSFiddle demo here.
You can accomplish this using the code below:
var nodes = document.querySelectorAll('.change'),
length = nodes.length,
counter = 0;
for (; counter < length; counter += 1) {
// set an attribute.
nodes[counter].setAttribute('data-test', 'test' + counter);
// add a click event.
nodes[counter].addEventListener('click', function () {
alert('Yep, you clicked me');
}, false);
}
Demo here
Using jQuery:
$('.change').on('click', function() {
// Action
});
Syntax of setAttributte:
Object.setAttributte(attribute, value);
I'm trying to build a menu. OVer a canvas I load different images and position them using CSS. Currently I operate with SHOW / HIDE with a lots of code duplication. My questions are:
- instead of just hidding an image, how can I change it on click with another one? and then again hide it, if I should click another button?
- is it possible to write all this code somehow simpler?
Thanks a lot...
$("#ten").click(sizeTen);
function sizeTen(){
cb_ctx.lineWidth = 10;
clickSound();
$(this).hide();
$("#twenty").show();
$("#forty").show();
$("#sixty").show();
}
$("#twenty").click(sizeTwenty);
function sizeTwenty(){
cb_ctx.lineWidth = 20;
clickSound();
$(this).hide();
$("#tenClick").show();
$("#ten").show();
$("#forty").show();
$("#sixty").show();
}
$("#forty").click(sizeForty);
function sizeForty(){
cb_ctx.lineWidth = 40;
clickSound();
$(this).hide();
$("#ten").show();
$("#twenty").show();
$("#sixty").show();
}
$("#sixty").click(sizeSixty);
function sizeSixty(){
cb_ctx.lineWidth = 60;
clickSound();
$(this).hide();
$("#ten").show();
$("#twenty").show();
$("#forty").show();
}
May be You Could shrink your coding by the following piece of code,
$("#ten,#twenty,#sixty").show();
I'd put all numeric values along with the corresponding IDs in a map and create a single handler for all buttons:
var boo = function () {
var values = { 'ten': 10, 'twenty': 20, 'forty': 40, 'sixty': 60 };
var id = $(this).attr('id');
$(this).hide();
// cb_ctx.lineWidth = values[id];
// clickSound();
$.each(values, function(key, value) {
if (id != key) {
$('#' + key).show();
}
});
};
$('#ten, #twenty, #forty, #sixty').click(boo);
Check out a jsfiddle at: http://jsfiddle.net/LNFza/4/
Cheers.
First, please take a look at my fiddle.
I'm trying to figure out a clean way of making the price next to each item change when any item is selected (in that group, you can image that there will be graphics cards etc in a different section which also will need the same functionality).
If its positive I need the class to be .positive and vice versa, and if the item is selected (+0) then the price difference wont be displayed.
This will also be used on checkbox's.
Non-working example.
You'll want to compare each selected item with items having the same name. In the .each() loop in CalculatePrice(), pass the checked item to this function:
function CalculateDiffs(item) {
var selectedPrice = +item.data("price");
item.siblings(".item_price").text("");
$(".calculation-item[name='"+item.attr("name")+"']").not(item).each(function(){
var price = +$(this).data("price");
var diff = (price-selectedPrice).toFixed(2);
if (diff >= 0) {
diff = "+"+diff;
}
$(this).siblings(".item_price").toggleClass("negative", diff < 0).text(diff);
});
}
As for checkboxes, the above function will take care of hiding the price when it is checked. To display the prices for unchecked checkboxes:
$(".calculation-item:checkbox:not(:checked)").each(function(){
$(this).siblings(".item_price").text("+"+$(this).data("price"));
});
Or, if you want to display the price of a checked checkbox as negative, use this instead:
$(".calculation-item:checkbox").each(function(){
var diff = (this.checked ? "-" : "+") + $(this).data("price");
$(this).siblings(".item_price").toggleClass("negative",this.checked).text(diff);
});
http://jsfiddle.net/gilly3/HpEJf/8/
Actually it's pretty straight forward, all you'll need to do is calculate the difference between the selected price and the price of all the options in the list. Eg, something like this:
$(".calculation-item").each(function(index) {
var my_cost = base_price + $(this).data("price");
var difference = Math.round(my_cost - base_cost);
});
I've created a working jsFiddle for you here: http://jsfiddle.net/HpEJf/6/. You'll need to implement decimal rounding etc but this should put you on the right track :)
If my understanding is correct, you want to display the cost difference from the previously selected radio button and the currently selected radio button.
To do that you need to keep track of the previously selected button. The only way I know of to do that is to set a variable outside the clickhandler scope to keep track of it and update the element in the clickhandler.
The rest is fairly straightforward. I updated your jsFiddle with an example of how to do it. The relevant code is below:
Adding at top of script:
//global for last checked/selected radio
var lastSelection = $(".calculation-item:checked");
//clear existing price diffs set by markup
$('span.processor_price').text('');
Added another function:
function priceDifference(oldPrice, newPrice) {
var difference = {
'cssClass': '',
'inCost': '0'
};
var fixedDiff = '';
var diff = newPrice - oldPrice;
diff = Math.ceil(Math.abs(diff * 100)) / 100;
fixedDiff = diff.toString();
if (newPrice < oldPrice) {
difference.cssClass = 'negative';
difference.inCost = '-' + fixedDiff;
} else if (newPrice > oldPrice) {
difference.cssClass = 'positive';
difference.inCost = '+' + fixedDiff;
}
/* else {
* must be the same, no reason for this block
* as the default empty string will suffice
* as will the cost difference of 0
}*/
return difference;
}
And changed your click handler to:
$(".calculation-item").click(function() {
var difference = {};
if (lastSelection) {
//get difference
difference = priceDifference($(lastSelection).data("price"), $(this).data("price"));
//change class
$(this).siblings('span.processor_price').addClass(difference.cssClass).text(difference.inCost);
$(lastSelection).siblings('span.processor_price').removeClass('positive').removeClass('negative').text('');
if (lastSelection !== this) {
lastSelection = this;
}
} else {
lastSelection = this;
}
CalculatePrice();
});