I'm having a bit of an issue with IE8 and jQuery 1.9.1.
The target browser is IE8. I get an undefined variable when I try to alert the rolevalue var.
Here's the code:
function get_role(){
var test = document.getElementsByName("admin_role");
for(var elem in test){
if(test[elem].checked){
var rolevalue = test[elem].value;
$.post('<?php echo base_url(); ?>ajaxsc/getrole/',{role:rolevalue},function(result){
$('#roletest').html(result);
});
}
}
**alert('role = ' + rolevalue);**
return rolevalue;
}
The problem is that the for..in loop is iterating over some unwanted items.
If you using a for..in loop, you need to be aware of this; you may get the loop iterating over object properties that are part of the object prototype rather than actual elements that you want to iterator over.
What is happening is that it's hitting an property in the loop that is not a DOM element, and of course, that means it doesn't have a .value, so when you try to set the variable from .value, you get undefined.
To avoid this, you need to use the .hasOwnProperty() method to determine whether the loop is iterating a prototype method, and avoid them. You need to do something like this:
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
.....
}
}
Hope that helps.
Related
I've been looking all over the web for how to do this. I am trying to make Jquerys .html() function in vanilla JavaScript. I want to recreate so I can understand it better. I've tried the following but nothing seems to work, I just don't understand what I am doing wrong.
let $ = function(ele) {
if (ele.charAt(0) == '.' || ele.charAt(0) == '#') {
let newEle = cut(ele,0);
if (ele.charAt(0) == '#')
get(newEle);
else
return document.getElementsByClassName(newEle);
} else
return document.getElementById(ele);
}
$.prototype.html = function(html) {
this.innerHTML = html;
}
$('test').html('hey');
$('.hey')[0].html('hey');
function cut(string,num) {
let a = string.slice(0,num);
let b = string.slice(num + 1,string.length);
return a + b;
}
It doesn't work, the console log reports this error:
Uncaught TypeError: $(...).html is not a function
Please help and thanks in advance.
The problem here is what you are returning from the $ function.
Think about this: document.getElementsByClassName and document.getElementById return dom elements and dom elements don't have a .html function. That is why you are getting the error.
What you need is to return is an object, a wrapper, with a .html function, and a closure over the dom elements that you want to modify.
Because you're returning an object from $, you're overriding the default behavior of new $; instead of resulting in the newly-created object, it results in the object you returned out of $.
Instead, you'd want to remember the results of those getElementsByClassName/getElementById calls in an array or Set you store on this (the newly-created object), and then use that array or Set within html (since you want to loop over all matching elements in the case where you're setting the new HTML).
Side note: Since you're using ES2015+ features anyway (let), you might want to use the simpler class syntax instead of a separate function declaration and assigning to $.prototype:
class $ {
constructor(ele) {
// ...
}
html(html) {
// ..
}
}
I am writing a bit of JS code to switch classes for certain DOM elements.
Everything is working as it should, but I am also getting this error and this
prevents the code that follows to be executed.
I added a check to make sure that the array of elements is not empty as I thought
this was the problem. But still the error occurs. Debugging always showed a value for old_name when replace is called on it. Am I missing something JS-esque?
This is the part of the code that causes the error, specifically line 31:
if (w > MOBILE_THRESHOLD) {
responsive_elements = document.getElementsByClassName("desktop");
if (responsive_elements.length > 0) {
for (i in responsive_elements) {
var old_name = responsive_elements[i].className;
var new_name = old_name.replace("desktop", "mobile");
responsive_elements[i].className = new_name;
}
}
When necessary I will be happy to provide more code, or whatever information is needed. Thanks!
Never use for...in loops to iterate array-like objects!!!!!
In this case, the HTMLCollection has enumerable properties like item or namedItem. Accessing these won't return an HTML element, so className will be undefined.
To iterate properly, you can use one of these
for(var i=0; i<responsive_elements.length; ++i) {
// ...
}
[].forEach.call(responsive_elements, function(element, index, collection) {
// ...
});
I know in javascript I can iterate over an object to get all of it's properties. If one or more of the properties is a method, is it possible to see what code is in the method instead of just the method name? E.g.
var a = someobject;
for (property in a) {
console.log(property);
}
Is it possible to get method code in a way similar to this? Thank you in advance.
You need to use toString, per the standard. i.e:
//EX:
var a = {method:function(x) { return x; }};
//gets the properties
for (x in a) {
console.log(a[x].toString());
}
You can also use toSource but it is NOT part of the standard.
PS: attempting to reliably iterate through an object with a for : loop is nontrivial and dangerous (for..in only iterates over [[Enumerable]] properties, for one), try to avoid such constructs. I would ask why, exactly, are you doing this?
Yes. It actually works. Try:
var a = {};
a.id = 'aaa';
a.fun = function(){alert('aaa');}
for (x in a) {
var current = a[x].toString();
if(current.indexOf('function') == 0){
current = current.substring(current.indexOf('{')+ 1, current.lastIndexOf('}'));
}
console.log(current);
}
But it will not work for browser native code.
You can use the toString method on the function
i.e.
function hello() {
var hi = "hello world";
alert(hi);
}
alert(hello.toString());
Update: The reason it wasn't working in JSFiddle was because I forgot to add the output inside of either console.log or alert - http://jsfiddle.net/pbojinov/mYqrY/
As long as a is an object, you should be able to use the square bracket notation and query a value from by argument with the same name as the objects property. For example:
a[ property ];
If you log typeof( property ), it will return "string" which is what we want.
var brands = document.getElementsByName("brand");
for(var brand in brands){
$("input[name='brand']").eq(brand).click(function(){
alert("hello22");
loadDataFN(1);
});
}
This code is not executing in ie6,
Any help would be appreciated.
The problem is likely that you are trying to use a for-in construct to iterate over a numeric array. This often won't give expected results. Use an incremental for loop instead:
var brands = document.getElementsByName("brand");
// Use an incremental for loop to iterate an array
for(var i=0; i<brands.length; i++){
$("input[name='brand']").eq(brands[i]).click(function(){
alert("hello22");
loadDataFN(1);
});
}
However,
after seeing the first part of your code, the loop appears unnecessary. You should only need the following, since you are assigning the same function to all brand inputs.
// These will return the same list of elements (as long as you don't have non-input elements named brand)
// though the jQuery version will return them as jQuery objects
// rather than plain DOM nodes
var brands = document.getElementsByName("brand");
$("input[name='brand']");
Therefore, the getElementsByName() and loop are not necessary.
$("input[name='brand']").click(function() {
alert("hello22");
loadDataFN(1);
});
for-in loops are used for iterating over the properties of an object, not over the elements of an array.
Why don't you write the code without jQuery if this doesn't work?
Something like this:
function getInputByName(name) {
var i, j = document.getElementsByTagName('input').length;
for(i=0;i<j;++i) { // You can also use getAttribute, but maybe it won't work in IE6
if(document.getElementsByTagName('input')[i].name === name) {
return document.getElementsByTagName('input')[i];
}
}
return null;
}
I don't know jQuery, but maybe you can do something like this:
$(getInputByName('brand')).eq(brand).click(function(){
alert("hello22");
loadDataFN(1);
});
I can't seem to find the answer to this anywhere...
I have a function that needs to set the bg color of two tables. Only the first table in the function is being affected. Is only one for loop allowed in a function? ...or is the 1st for loop maybe never exiting?
I can pretty much work around this by creating multiple functions but I really want to understand why this behaves the way it does!
Thanks!
Here is my simplified code:
function setColor()
{
//This works
var t1rows=document.getElementById("table1").getElementsByTagName("tr");
var x;
for (x in t1rows)
{
t1rows[x].style.backgroundColor='yellow';
}
//this one does not work
var t2rows=document.getElementById("table2").getElementsByTagName("tr");
var y;
for (y in t2rows)
{
t2rows[y].style.backgroundColor='yellow';
}
}
getElementsByTagName() returns a NodeList object, and for-in will iterate its properties which you don't want. You want to use a straight for loop:
for(var i=0; i < t2rows.length; i++) {
t2rows[i].style.backgroundColor='yellow';
}
You're not getting to the second loop because the first is failing when it tries to access a non-existent style property on one of the NodeList's members.