Hey guys, I have a UL like so:
<ul id="list">
<li class="something">
<div class="btns" onclick="add(this)"> + </div>
<div class="btns" onclick="sub(this)"> - </div>
</li>
<li class="something new">
<div class="btns" onclick="add(this)"> + </div>
<div class="btns" onclick="sub(this)"> - </div>
</li>
</ul>
CSS wise, the class 'something' contains a background image.
What I want to achieve here, is that when the add() or sub() function calls are made, the background-image property of the parentNode of the element that made the call changes...
So this way, I don't have to go around making ID's for each element, and can reuse the same functions...
Wha开发者_高级运维t I have is something like this, but it doesn't work (rather, the code I've written is wrong):
function add(x)
{
var y = x.parentNode.style;
if (y.backgroundImage == 'url("../assets/1.png")'
{
y.backgroundImage = 'url("../assets/2.png")';
} else if (y.backgroundImage == 'url("../assets/2.png")'
y.backgroundImage = 'url("../assets/3.png")';
...
... so on so forth...
}
The overall logic itself might be poor, so I'm open to new suggestions too...
Edit #1: Added more detail to explain current situation...
Essentially, there's a 3x3 grid which is populated with the li's, and the background image indicates the current quantity using dots. There're two buttons inside each li, to add and subtract. On click of each, the background image is supposed to change to denote the current quantity... And this has to be done independent of the different li's...
I agree with RobG that using classes is much better suited - especially if you ever decide to use a framework. In the off-case you don't want to here are some other ways:
Updated for Computed Styles - leaving the commented version at the bottom of post: The main difference in this one is that it gets the background image of the inline-style or the computed version (if its being set by a class for example).
For getting computed styles, take a look at quirksmode.org. In particlar the bottom of the getstyles page.
Here is a fiddle that is not working in jsfiddle (bit tired but I think it has to do with me using IE6 at work...), but works fine if you do it locally in a normal setting.
function add(x) {
var parent = x.parentNode;
var y = parent.currentStyle['backgroundImage'] || document.defaultView.getComputedStyle(parent,null).getPropertyValue('backgroundImage');
switch(true)
{
case (y.indexOf("1.png")!=-1):
parent.style.backgroundImage = 'url("http://www.wskidmore.com/2.png")';
break;
case (y.indexOf("2.png")!=-1):
parent.style.backgroundImage = 'url("http://www.wskidmore.com/3.png")';
break;
case (y.indexOf("3.png")!=-1):
parent.style.backgroundImage = 'url("http://www.wskidmore.com/1.png")';
break;
}
}
Outdated, but commented with logic.
function add(x) {
var y = x.parentNode.style.backgroundImage;
// using indexOf will avoid the possible quote issue and possibly other odd browser quirks
// switch true means it will do the first case it finds that evaluates to true
switch(true)
{
// indexof means it looks through your string for the given substring
// and returns the position so, "abc".indexOf("b") returns 1 (its 0 based)
// if it doesnt find it anywhere it returns -1
// so for our switch, it looks inside the backgroundImage string
// url("../assets/x.png") no-repeat 50% 50%
// or whatever it may be for the part "1.png"
// if it finds it, it will return 5, or 8, or whatever the position is
// if not it returns -1
// so when this gets evaluated we check for "not -1"
case (y.indexOf("1.png")!=-1):
// if this case is true, then everything between the : and break;
// will be performed, then it exits the switch
y = 'url("../assets/2.png")';
break;
case (y.indexOf("2.png")!=-1):
y = 'url("../assets/3.png")';
break;
case (y.indexOf("3.png")!=-1):
y = 'url("../assets/4.png")';
break;
}
}
Use the getElementsByName() function, set the same name on all the nodes you want to change.
function add(x) {
var elements = document.getElementsByName("somename");
/* Iterate over the array and set the .style.* elements as needed */
}
http://www.w3schools.com/jsref/met_doc_getelementsbyname.asp
You seem to be finding the parentNode ok. An alternative to setting properties of the style object, consider adding and removing a class instead. Some simple functions to do that are:
var yourLib = {
dom: {},
util: {}
};
/* Check if an element has a particular class name
*/
yourLib.dom.hasClassName = function(el, cName) {
if (typeof el == 'string') el = document.getElementById(el);
var re = new RegExp('(^|\\s+)' + cName + '(\\s+|$)');
return el && re.test(el.className);
}
/* Add a class name if element doesn't already have it
*/
yourLib.dom.addClassName = function(el, cName) {
if (typeof el == 'string') el = document.getElementById(el);
if (!yourLib.dom.hasClassName(el, cName)) {
el.className = yourLib.util.trim(el.className + ' ' + cName);
}
}
/* Remove a class name if element has it
*/
yourLib.dom.removeClassName = function(el, cName) {
if (typeof el == 'string') el = document.getElementById(el);
if (util.dom.hasClassName(el, cName)) {
var re = new RegExp('(^|\\s+)' + cName + '(\\s+|$)','g');
el.className = yourLib.util.trim(el.className.replace(re, ''));
}
}
/* Remove leading and trailing whitespace and reduce
** multiple intermediate whitespaces to a single space
*/
yourLib.util.trim = function(s) {
return s.replace(/(^\s+)|(\s+$)/g,'').replace(/\s+/g,' ');
}
Your code should work fine, except you're matching the existing background image wrong. It doesn't return with the same quotations as when you set it.
//When setting the url property, you need to wrap the actual URI in double quotes
//and then wrap the whole thing in single quotes to indicate to JS that it's a string
y.backgroundImage = 'url("../assets/1.png")'; //set background image
//y.backgroundImage now has a value of 'url(../assets/1.png)'
//Here you try to match the value of y.backgroundImage against the string you
//originally stored in it, but that won't work
y.backgroundImage == 'url("../assets/1.png")'; //false
//The backgroundImage property returns a string that has the quotes stripped
//out of the inside of the URL definition
y.backgroundImage == "url(../assets/1.png)"; //true
Ok, so I got it working, and here's the solution for whoever stumbles upon this later on...
function add(x)
{
var y = x.parentNode.style.backgroundImage;
if ((y == '') || (y.indexOf("3_0.png") != -1))
x.parentNode.style.backgroundImage = 'url(../_assets/3_1.png)';
else if (y.indexOf("3_1.png") != -1)
x.parentNode.style.backgroundImage = 'url(../_assets/3_2.png)';
else if (y.indexOf("3_2.png") != -1)
x.parentNode.style.backgroundImage = 'url(../_assets/3_3.png)';
else if (y.indexOf("3_-3.png") != -1)
x.parentNode.style.backgroundImage = 'url(../_assets/3_-2.png)';
else if (y.indexOf("3_-2.png") != -1)
x.parentNode.style.backgroundImage = 'url(../_assets/3_-1.png)';
else if (y.indexOf("3_-1.png") != -1)
x.parentNode.style.backgroundImage = 'url(../_assets/3_0.png)';
}
Basically, with WSkid's help (Thanks!) I used 'indexOf' to determine which was the current background, and accordingly change depending on which function was called. This is the code for the addition function.
精彩评论