parseInt not working for window.document - javascript

Is there a reason that this would not work?
var xcurrent = parseInt(window.document.getElementById('firstdiv').style.left);
var ycurrent = parseInt(window.document.getElementById('firstdiv').style.top);
I'm being told it's not an integer NaN.

u̶ ̶n̶e̶e̶d̶ ̶t̶o̶ ̶r̶e̶m̶o̶v̶e̶ ̶̶p̶x̶̶ ̶f̶r̶o̶m̶ ̶t̶h̶e̶ ̶s̶t̶r̶i̶n̶g̶ ̶ (doesn't matter on modern browsers)
make sure window.document.getElementById('firstdiv').style.left is defined. you can't access this property if it's defined only in CSS
Examples:
CSS: http://jsfiddle.net/zuKYr/
Inline: http://jsfiddle.net/zuKYr/1/
JS: http://jsfiddle.net/zuKYr/2/
only style defined by JS and inline CSS is readable by JS.

It's not parseInt that isn't working, NaN suggests that the element you are trying to reference cannot be interpreted as an integer. Although it is difficult to say for certain, make sure that the elements you are referencing actually exist and see if you can access them at all before manipulating them. i.e check that window.document.getElementById('firstdiv') gives you anything before trying to do any more with it.
You also need to make sure that your css has actually set the attribute you are trying to retrieve otherwise you will get an undefined/Nan error.

If you're trying to get the x and y position of an element, you can use offsetLeft and offsetTop instead.
var firstDiv = document.getElementById('firstdiv');
var xcurrent = firstDiv.offsetLeft;
var ycurrent = firstDiv.offsetTop;
This will get the x and y position (with respect to the offsetParent) whether they were set through CSS positioning or not.

Is there a reason that this would not work?
var xcurrent = parseInt(window.document.getElementById('firstdiv').style.left);
Quite a few, but the likely ones are:
If element with id 'firstdiv' doesn't exist, window.document.getElementById('firstdiv') will return null. Attempting to access the style property of null will throw an error. That's not the result you specified though.
The value returned by .style.left is an empty string. In that case, parseInt returns NaN per ECMA-262.
A safer approach is:
var el = document.getElementById('firstdiv');
var xcurrent
if (el) {
xcurrent = parseInt(el.style.left);
if (isNaN(xcurrent)) {
// there was no value for xcurrent, what now?
As Nathan said, you can use offsetLeft instead.

Related

Accessing an object in JavaScript: Why do I need to use square bracket syntax instead of dot syntax in that case?

I have a JavaScript object that looks like this:
var map = {
Monday: [
'something',
'something else',
],
};
When trying to access it, I noticed something strange I don't understand:
Doing console.log(map.Monday); returns undefined. To get the array back, I need to do console.log(map["Monday"]);.
Why is this? I already tinkered with quotes and uppercase/lowercase identifiers. The only time I encountered this so far was when there were numbers involved in the identifier (but of course it was still a string).
Edit
According to the comments it's working – indeed that is correct. Then the reason is probably related to the fact that the array identifier comes from an HTML select element:
$('.select').on('change', function(event) {
var selectedDay = $(event.currentTarget).val();
if (map.hasOwnProperty(selectedDay)) {
console.log(map[selectedDay]);
}
});
Then the reason is probably related to the fact that the array identifier comes from an HTML select element.
Yes… the syntax someObj.property is equivalent to someObj['property'], i.e. the property name is passed as a string in square brackets there.
Now if you want to dynamically access some property, and only have the property name as a string, then you need to use the square bracket syntax. For example:
var day = 'Monday';
console.log(map[day]);
The map[day] is equivalent to map['Monday'] which is equivalent to map.Monday. But if you were to call map.day, you would try to access map['day'], i.e. a property day in your object which obviously doesn’t exist.
What do we learn from this question? It’s a good idea to simplify the code in order to focus on the problem instead of including lots of irrelevant things. But when you do, you should make sure that the problem actually exists in the simpler code example. Because in this case, you eliminated the problem because you thought it doesn’t matter that you are trying to access the property dynamically.
In javascript both objects and arrays can be accessed as arrays and also as objects:
var a = []; //array
a["x"] = 100; //works
a.y = 50; //works
a.z = a.x + a["y"]; //works
var b = {}; //object
b.x = 10; //works
b["y"] = 20; //works
b["z"] = b["x"] + b.y; //works
If you still have a problem it's not related to the code you posted.

jquery offset method doesn't always work / exist

Good morning and happy new year everyone!
I've run into a snag on something and need to figure out a solution or an alternative, and I don't know how to approach this. I actually hope it's something easy; meaning one of you all have dealt with this already.
The problem is that I'm doing rollovers that contain information. They're divs that get moved to the absolute location. Now I've tried this with jquery 1.6 - 1.9.1. Of course this has to work in multiple browsers.
What needs to happen is on rollover show a div, and when you rollout of that div, make it hide.
...
// .columnItem is class level and works
$(".columnItem").mouseleave(function() {
$(this).css("display", "none");
});
...
$(".column").mouseenter(function() {
var currentItem = $(this)[0]; // this is where the problem is
// hide all .columnItems
$(".columnItem").css("display", "none");
// i get this error: Object #<HTMLDivElement> has no method 'offset' (viewing in chrome console)
var offsetTop = currentItem.offset().top;
var columnInfoPanel = $("#column" + currentItem.innerText);
});
So the immediate thought of some would be don't use $(this)[0]. Instead, I should use $(this), and you are correct! Where the other problem comes into play is by removing the array index, currentItem.innerText is now undefined.
The only thing I can think of is I'll have to mix both, but it seems like there should be a way to use the selector and get both options.
What have you all done?
Thanks,
Kelly
Replace:
var currentItem = $(this)[0];
With:
var currentItem = $(this).eq(0);
This creates a new jQuery object containing only the first element, so offset will work.
Then you can use either currentItem[0].innerText or currentItem.text(), whichever you prefer.
Skip the [0] at the beginning as you are saying.
But then change the last line to:
var columnInfoPanel = $("#column" + currentItem[0].innerText);
De-referencing the jQuery selector gives you the DOM-object.
If you want to stick to pure jQuery, the .text() / .html() methods will give you the same functionality.

how to access properties of document.getElementsByClassName

I am trying to check whether the a css class is used inside the DOM or not. So, I have
var x = document.getElementsByClassName('classname');
When I print x out, I get a [object NodeList] for classes that exist on the page and classes that dont. Is there a property of x that I can access ? Like the tag name or something. Would be great if somebody can tell me the different properties of x and the ways I can access them.
Thank you :)
Notice that it's plural:
var x = document.getElementsByClassName('classname');
^
You need to iterate over x to get the individual elements:
for (var i = 0; i < x.length; i++) {
var element = x[i];
console.log(element);
}
Make sure to add fallback support for Internet Exploder: http://ejohn.org/blog/getelementsbyclassname-speed-comparison/
If you just want to check for the presence of a class in the document, you can also use querySelector.
var x = document.querySelector('.classname');
It returns null if no elements have that class, otherwise the first element with that class name. If you want all elements using classname:
var x = document.querySelectorAll('.classname');
Now x is null if the class is not used in the document, otherwise a Nodelist, containing all elements with class classname, which can be iterated the way Blender showed. In that iteration you can, for example, retrieve the elements tagName or its id. Like:
for (var i=0;i<x.lenght;(i=i+1)){
console.log(x[i].id + ': ' + x[i].tagName);
}
document.querySelector is available in all modern browsers, and for IE version 8 and up.
I almost always use document.querySelector (which: "Returns the first element within the document that matches the specified group of selectors"), which returns an element object and it's.
I don't know why but in my Chrome's console I write:
var img = document.getElementsByClassName('image__pic');
img[0]...
img[0], despite its happy existance, it doesn't generate any further attributes/methods to use in the completion window. Like there were none (even though I could use img[0].src for instance)
On the other hand:
var imgq = document.querySelector('.image__pic')
Gives me very useful autocompletion on the Console:
As far as its browser support it is phenomenal:
It is also less tricky to use, because getElementsByClassName returns an HTMLCollection, which is a little beast of its own.
Another plus for querySelector is its versatility: any kind of CSS selector goes!
On the negative side, querySelector is a bit slower, but I think it's worth it.

Js - Append a value to element CSS

This seems so simply yet its not working (undefined).
I have set a var to <ul> which is a child of <div> element "feature_tabs_indicators".
The pBoxShadowProperty function gets the BoxShadow property supported by the current browser.
And the final statement merely sets the pBoxShadowProperty to 0, i.e. its overriding the CSS set Box-Shadow property.
Can someone please explain what I am doing wrong here in the last statement?
Best,
var iActiveNo = 0;
var eTabInd = document.getElementById ("feature_tabs_indicators").children[0];
var pBoxShadowProperty = getSupportedCSSproperty(["boxShadow", "mozBoxShadow", "webkitBoxShadow"]);
function getSupportedCSSproperty (propertyArray)
{
var root = document.documentElement;
for (var i = 0; i < propertyArray.length; i++)
{
if (typeof root.style[propertyArray[i]] === "string")
{
return propertyArray[i];
}
}
}
iActiveNo = iActiveNo + 1;
eTabInd.children[iActiveNo - 1].style[pBoxShadowProperty] = "";
Here is the jsfiddle, press the light green button 'rght' on top right.
I think I figured out what your issue is. You use here:
iActiveNo = iActiveNo + 1;
something that has not been defined in your posted code. However you do have:
var iActive = 0;
which I think should have actually been:
var iActiveNo = 0;
otherwise your code has JS error in it (as it is posted, anyway).
Other than that (that is, if your intention was to take the 1st <li> element out of the <ul> element and remove its box-shadow CSS property) - your code is just fine.
Edit
Dude, what a mess.. :) Here is a JSFiddle I fixed up a bit. Below is the explanation.
There are several things going on in that JSFiddle that should be fixed before we get to the real problem.
You have errors in that fiddle - see console. The line:
var pBackgroundColorProperty = eStyle.backgroundColor //[pBoxShadowProperty];
doesn't end with a semicolon, and is then interpreted as a function due to (..) on the next line (I think) - which (for me at least) results in an error in JS console. If semicolon is added - error is gone.
Additionally... There is a line:
console.log (eTabInd.children[iActiveNo-1].style.pBoxShadowProperty);
which prints your undefined and is exactly what was discussed below and should be
console.log (eTabInd.children[iActiveNo-1].style[pBoxShadowProperty]);
which then prints the empty string.
Moreover, when printed, your pBoxShadowProperty variable contains boxShadow string. Which is, of course, not a valid CSS property I am familiar with. So this:
eTabInd.children[iActiveNo - 1].style[pBoxShadowProperty] = "";
won't do a thing.
Now to the meat of the issue here...
eTabInd.children[iActiveNo-1].style
doesn't have 'box-shadow' property to begin with, because you haven't put it in style attribute of <li> element. It is put on the <li> element through the virtues of this CSS selectors sequence: #feature_tabs_indicators ul #ind_bt.
Now, since you wanted the style attribute - you won't get the computed style the above CSS selectors sequence applies. Thus - you won't be able to remove it.
What you could have done is create another class, that doesn't have a box-shadow property and replace your original c_ind with it.
it looks like you have not set value correctly as it should be like
eTabInd.children[iActiveNo - 1].style.pBoxShadowProperty = "";
Dose that help or dose still return 0?

Javascript retrieve element by it's properties

Every HTML element has offset values. Can I return an element that has, for example, offsetLeft > 10?
Have never heard of this feature, therefore the question.
I'm aware that this can be done with loops, but those are slow. Had an idea about XPath, but cannot find anything related to properties within reference.
Thanks in advance!
P.S. No need for outdated browser compatibility- HTML5'ish can do.
As far as I'm aware, there is no way to do this that does not involve looping of some form. You could do it in standard JS with something along these lines:
var elems = document.getElementsByTagName("*"),
myElems = [];
for(var i = 0; i < elems.length; i++) {
if(elems[i].offsetLeft > 10) myElems.push(elems[i]);
}
Or, if you're using jQuery you can do it with a little less code (but it's probably even slower!):
var myElems = $("*").filter(function() {
return $(this).offset().left > 10;
});
If you think about it, you want to select all of the elements in a document with a certain property value. That's always going to involve a loop at some point, whether you write it yourself or not, as every element has to be checked.
Have you looked at this page yet? offset
jQuery can easily select attributes of elements
<div>Dont find me</div>
<div this="yes">Find me</div>
$('div[this=yes]'); // will select the second div
The problem you are going to run into is things like offset and position are calculated values, and not stored in the dom with the elements upfront. If you need to select by this, I would suggest putting them as attributes inside of the dom element itself. Then the above method with work just fine.
I would suggest the best way to do this would be to extend jQuery's selectors. Something like this works well:
$.extend($.expr[':'],{
offsetLeft: function(a,i,m) {
if(!m[3]||!(/^(<|>|=)\d+$/).test(m[3])) {return false;}
var offsetLeft = $(a).offset().left;
return m[3].substr(0,1) === '>' ?
offsetLeft > parseInt(m[3].substr(1),10) :
m[3].substr(0,1) === '<' ? offsetLeft < parseInt(m[3].substr(1),10) :
offsetLeft == parseInt(m[3].substr(1),10);
}
});
This would allow you to select elements using syntax such as
$('span:offsetLeft(>10)')
or
$('.someClass:offsetLeft(<10)')
or even
$('.someClass:offsetLeft(=10)')
Live example: http://jsfiddle.net/X4CkC/
Should add that this hooks into jQuery's selectors which are generally quite fast, but no doubt somewhere deep within there is a loop going on. There' no way of avoiding that.
You can easily do it with jQuery
$("*").each(function(index, elem){
if($(this).offset().left > 10){
// do something here with $(this)
}
});

Categories

Resources