I have a several input fields in a form each having a unique name. For example, to change the color I would do:
testForm.username.style.background = "yellow";
username being the name of the input and testform being the form name
I want to do this: replace username with a variable elem so that when I call the function to change the background color I don't need to have a separate function for every unique field. I would just send the elem name and that function would work for every field.
testForm.elem.style.background = "yellow";
My problem is it doesn't work. For example it passed the elem into the function fine, but it says that testForm.elem.style is null. For some reason javascript doesn't like variables for element names I'm guessing?
var elem = 'username';
testForm[elem].style.background = 'yellow';
try
testForm [elem].style.background = "yellow";
or
var elem = testForm.username
elem.style.background = "yellow";
in the first case elem holds the username, and in the second case, elem points to the actual DOM element.
A property of a JavaScript object (in this case, the "username" property of the object "testform") can be accessed using either object.property or object["property"] syntax. As the second form takes a string (as shown by the double quotes), it follows that a variable containing a string can also be used with that syntax. Hence:
testform[elem].style.background = "yellow";
will do what you want.
It sounds like you're creating a function to do this anyway. In that case, why not just use the following function:
function changeBackgroundOfElementToYellow(element){
element.style.background = "yellow";
}
And call it with:
changeBackgroundofElementToYellow(testForm.username);
In general I find the RaYell/kangax method posted already to be better, but this is another option.
You'd have to do an eval to do something like that, eg eval("testform." + elem + ".style.background=yellow");
Related
I wanna make a varible shortcut $$() so that i can use shortcut like $() [jquery] to save code in my project(ALL MY CODE IS PURE JAVASCRIPT).
when i put the string of id or class, it works all right, but when i put the tagName, it shows Cannot read property 'style' of undefined, it seems that the code is right,help,thanks
One more, is that way to defined a shortcut variable $$() to use in pure javascript environment right way? or is there any best practice to define a global variable like this?
window.onload = function(){
function $$(ele){
var pattern1 = /#/g;
var pattern2 = /\./g;
var pattern3 = /!/g;
var matches = ele.match(/[^#\.!]/g);//array
var elementS = matches.join("");
//alert(matches+elementS);
// console.log(document.getElementsByTagName(elementS));
var spaceExist = /\s/.test(elementS)
if(pattern1.test(ele)){
return document.getElementById(elementS);
}else if(pattern2.test(ele)){
//console.log(elementS);
return document.getElementsByClassName(elementS);
}else if(pattern3.test(ele)){
alert('hi');
console.log(elementS);
return document.getElementsByTagName(elementS);
}else if(spaceExist){
return document.querySelectorAll(elementS);
}
}
$$('#hme').style.backgroundColor = 'red';
$$('.myp')[0].style.backgroundColor = 'green';
$$('!h2')[0].style.display = 'none';//this not work,shows Cannot read property 'setAttribute' of undefined
}
<h1 id="hme">hi,friend</h1>
<p class="myp">mmdfdfd</p>
<h2>hhhhhh</h2>
Have you stepped through your code? Look at pattern #2:
var pattern2 = /./g;
That pattern will match any character at all given that's what the period represents in regular expressions - ref: http://www.regular-expressions.info/dot.html.
Therefore, this conditional is satisfied and returns its result:
else if(pattern2.test(ele)){
return document.getElementsByClassName(elementS);
}
Given there appears to be no element with a class name of h2 (which is the value of elementS), the return value is undefined.
Given that undefined has no properties, interrogating for the style property will produce the error you are seeing.
My advise is use one shortcut since you already using querySelectorAll:
window.$ = document.querySelectorAll.bind(document)
or if you rather need first element
window.$ = document.querySelector.bind(document)
this way you'll be able to do everything you are doing with normal css selectors and not obfuscated !tag for just tag
If speed actually matters, you will save some ticks by just having two aliases:
window.$ = document.querySelector.bind(document)
window.$el = document.getElementById.bind(document)
and calling $el when you need it specifically, instead of trying to make method polymorph.
Mister Epic's answer spots the main issue. Your h2 call is getting caught in that if statement, and that's why your error is happening. You need to make sure it doesn't get caught there, either by creating another pattern, or specifying in your second if statement that your 'ele' doesn't contain an '!'.
After that, in your third if statement:
else if(pattern3.test(ele)){
alert(hi); <---
console.log(elementS);
return document.getElementsByTagName(elementS);
The problem with this is you're going to alert(hi), but hi isn't defined. Make sure you wrap it in quotes.
Should be looking good after that.
Is it possible to use JavaScript to set the click event to a variable function name?
I want to dynamically set each of the selected elements to functions that the names are declared elsewhere. These functions are class methods. I don't know if this is why it's not working.
I know this is funky monkey stuff, but it's preferable to the alternative of using a switch, with all the functions I have to parse through.
function name get
// get last part of the string
var x = strName.split("_");
var y = x[x.length - 1];
This works
holder[j].onclick = function(){ini['add']();};
This does not, for some reason
holder[j].onclick = function(){ini[y]();}; // I checked: y == 'add' in the test
I found that this does not work. The onclick is not set to the function I want it to be, just the statement
ini[y]();
As y is no longer in scope after the setup is complete (and even if it was, there's no saying that it would be the correct y, as it has a different value each iteration), I've had to pull it out to make it determine function on the fly.
Using this:
holder[j].onclick = function(){clickMaster(this);};
Then this:
function clickMaster(ele){
// pull out strName based on ele
var x = strName.split("_");
var y = x[x.length - 1];
ini[y]();
}
Rather than just trying to set the onclick directly to the class method.
How to shift between variable names in jQuery and change them?
//predefined variables
var s1='';
var d2='';
//trying to change variables by .attr() parameter but no luck
$('body').on('click','span', function() {
var $(this).parent().attr('data-scan')=$(this).attr('id');
});
HTML
<div data-scan="s1"><span id="banana">Banana</span><span id="apple">Apple</span></div>
<div data-scan="d2"><span id="orange">Orange</span><span id="apple">Apple</span></div>
How can I change specific variables? I do't care about changing attr papameter, all I need is changing predefined global var parameters!
You are using wrong syntax of attr()
Syntax: attr( attributeName , value)
Change
var $(this).parent().attr('data-scan')=$(this).attr('id');
To
$(this).closest('div').attr('data-scan',$(this).attr('id'));
You code would be
Live Demo
$('body').on('click','span', function() {
debugger
$(this).closest('div').attr('data-scan',$(this).attr('id'));
s1=$(this).closest('div').attr('data-scan');
alert(s1);
});
Firstly, your html for the data-scan attributes is wrong, you have no closing quotes.
Secondly, you can the data() jquery function to access data attributes.
Thirdly, you cannot set values by using the = operator.
You want something like this:
$(this).parent().data('scan', $(this).attr('id'));
or, without the data() function:
$(this).parent().attr('data-scan', $(this).attr('id'));
Here is a working example
To get the value you can do one of the following:
var dataScan = $(this).parent().data('scan');
or
var dataScan = $(this).parent().attr('data-scan');
Your exact requirements for setting a variable based on the data-scan value
Based on your comments and code, I think it has not been clear what you were trying to do. I think I have worked it out though and you want to use the data-scan value to determine which global variable should be set...
//predefined variables
var s1='';
var d2='';
$('body').on('click','span', function() {
var variableType = $(this).parent().data('scan');
var valueToSet = $(this).attr('id');
if(variableType == "s1"){
s1 = valueToSet;
}
else if(variableType == "d2"){
d2 = valueToSet;
}
});
Here is an example of what I think you are trying to do.
However, if you have lots of variables then it is not ideal to use so many if/else statements. So you could use the javascript eval() function.
var variableType = $(this).parent().data('scan');
var valueToSet = $(this).attr('id');
eval("" + variableType + " = '" + valueToSet + "';");
See here for an example
But be careful the your eval code is subjected to user injected values (not that javascript is safe from users anyway)
You're pretty close!
// set
$('#item').attr('data-scan', 'set new value');
// get
var dataScan = $('#item').attr('data-scan');
console.log(dataScan); //=> set new value
Probably best if you use .prop() rather than .attr()
$(this).parent().prop('data-scan', $(this).attr('id') );
As the jQuery api documentation states
As of jQuery 1.6, the .attr() method returns undefined for attributes
that have not been set. In addition, .attr() should not be used on
plain objects, arrays, the window, or the document. To retrieve and
change DOM properties, use the .prop() method.
I tried to convert snippet 1 to snippet 2 but this did not work (the text fields did not clear). f3aa and f3bb are each text fields that I need to clear after a sumbit.
Snippet 1
var target=document.getElementById('f3aa');
target.value='';
var target=document.getElementById('f3bb');
target.value='';
Snippet 2
o1('f3aa')=o1('f3bb')='';
Snippet 3
function o1(a)
{
document.getElementById(a);
}
Assuming I've understood your question correctly, you were nearly there:
document.getElementById('f3aa').value = '';
document.getElementById('f3bb').value = '';
In your snippet 2, you are trying to assign an empty string to a DOM element, rather than the value property of that element.
In snippet 1, you assign a DOM element to the target variable, and then assign an empty string to the value property of the target variable. As target contains a DOM element, you assign that string to the value property of that element, which is equivalent to the code I have shown above.
You forgot to include the attribute names from your first snippet in your second:
document.getElementById('f3aa').value='';
document.getElementById('f3bb').value='';
(Note that this isn't really an "optimization" - there will be no noticeable difference in how quickly the two snippets run. Use whichever is more readable.)
X('f3aa').value = X('f3bb').value = '';
where X is your query-by-ID implementation.
Live demo: http://jsfiddle.net/zmr29/
(I wrote a X function in my demo, but I assume that you either use a library or have some other shorthand for DOM queries.)
I think it's illegal to use var to declare a variable more than once in the same scope.
This code is bad:
var test = true;
var test = false;
This code is good:
var test = true;
test = false; // <-- no "var" keyword here
Here's the problem - I know function by name (and that function has already been loaded form an external script), but I don't have an actual function object avail for me to call. Normally I would call eval(function_name + "(arg1, arg2)"), but in my case I need to pass an object to it, not a string.
Simple example:
var div = document.getElementById('myDiv')
var func = "function_name" -- this function expects a DOM element passed, not id
How do I execute this function?
Thanks!
Andrey
Never use eval, it´s evil (see only one letter difference)
You can simply do:
var div = document.getElementById('myDiv');
var result = window[function_name](div);
This is possible because functions are first class objects in javascript, so you can acces them as you could with anyother variable. Note that this will also work for functions that want strings or anything as paramter:
var result = window[another_function_name]("string1", [1, "an array"]);
You should be able to get the function object from the top-level window. E.g.
var name = "function_name";
var func = window[name];
func( blah );