SitePoint Sponsor

User Tag List

Results 1 to 5 of 5
  1. #1
    SitePoint Addict Smola's Avatar
    Join Date
    Mar 2005
    Posts
    260
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Unhappy Missing Attributes

    I have completed reading the Simply Javascript book from the authors of this site and have begun some exploration on my own. I am using the Core javascript file that came with the book for some basic functions. I have begin by simply creating some elements on an html page and using some javascript to reference them by class.

    the page:
    HTML Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Java Testing</title>
    
    <script type="text/javascript" src="scripts/core.js">
    </script>
    
    <style type="text/css">
    
    .tab {
    	width:100px;
    	min-height:10px;
    	border:1px solid black;
    	background-color:#00CC00;
    	}
    	
    .button {
    	height:30px;
    	text-decoration:none;
    	color:#000000;
    	width:100%;
    	text-align:center;
    	}
    	
    </style>
    
    </head>
    
    <body>
    
    <div id="poop">
    
    	<div class="tab">
    		<a class="button">Click Me</a>
    	</div>
    	<div class="tab">
    		<a class="button">Click Me</a>
    	</div>
    
    </div>
    
    </body>
    </html>
    and the script:
    Code javascript:
    var changeHeight = {
     
    	init: function() {
     
    		var elements = Core.getElementsByClass("button");
     
    		for (var i = 0; i < elements.length; i++) {
    			var color = elements[i].textNode;
    			alert(color);
    		}
     
    	}
     
    }
     
    Core.start(changeHeight);

    The Core object references are functional and included in the script but not shown here. The function shown is the one I wrote simply to do some testing. I know that the getElementsByClass functions works because I get 2 alerts when I view the page. However, no matter what attribute I try to alert, I fail to get an accurate response.

    elements[i].style.height --> gave me a blank message box
    elements[i].style.color --> message box that said 'undefined'
    elements[i].textNode --> message box that said 'undefined'

    I am unsure why these attribute references aren't working, but I am sure it's a syntax issue on my part. Any ideas?



    Smola

    EDIT: By the way, the Core.start function was written in such a way that takes an object as input and ALWAYS executes the init function of the object.
    Last edited by Smola; May 21, 2008 at 11:54. Reason: Additional Info

  2. #2
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    I can't see any HTML elements in the HTML you've posted, so I assume you've created them with some other javascript that you haven't posted.

    elements[i].textNode returns undefined because that element does not have a textNode property, sub-object or method. If you want to get the text within elements[i], I would do this:
    Code:
    elements[i].firstChild.nodeValue
    The firstChild is the text node within the anchor. Although it might not seem immediately obvious, bare text is actually a "node" in itself and you can access it like you would with many DOM methods, like firstChild, the childNodes collection, nextSibling and lastChild, but not getElementById and friends, because text nodes are simple and cannot have attributes.

    The nodeValue is the value of the node, i.e. the text itself. For an HTML element, the value is null.

    Regarding elements[i].style.height, that doesn't work because the style object refers to things that are set via the style HTML attribute, a.k.a. "inline styles":
    HTML Code:
    <a href="page.html" class="button" style="height:30em">Clicky</a>
    Code Javascript:
    alert(elements[i].style.height) // alerts 30em
    The style object has no idea what is going on in CSS, whether as external stylesheets via <link> or embedded in the <head> with <style>. If you want to access that information, it gets a bit more complex. IE makes it easy by using the currentStyle object, and Mozilla and friends doesn't make it so easy, forcing you to use the rather unfriendly CSSStyleSheet object. Mozilla and friends also provide getComputedStyle, which can come in very useful (which IE doesn't support. currentStyle is not the same thing).

    Fortunately, most of the time you know what there is in your stylesheets already so you are unlikely to need to use these. Needing to find the exact height or width of things is quite common, whether specified in the CSS or not, and the more old-school offsetWidth, offsetHeight, clientWidth and clientHeight tend to be very helpful in that area.

  3. #3
    SitePoint Addict Smola's Avatar
    Join Date
    Mar 2005
    Posts
    260
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ahh Raffles, you are so wise! Those inline styles just don't seem to fit into the feng shui of web design do they? Well I altered my code a bit and I am now running into a new error. Here is the script with the same HTML:

    Code javascript:
    var changeHeight = {
     
    	init: function() {
     
    		var elements = Core.getElementsByClass("tab");
     
    		for (var i = 0; i < elements.length; i++) {
    			changeHeight.origHeight[i] = Core.getComputedStyle(elements[i],"height");  // can I do this?
    			Core.addEventListener(elements[i],"mouseover",changeHeight.enlarge);
    			Core.addEventListener(elements[i],"mouseout",changeHeight.shrink(i));
    			//alert(height);
    		}
    	},
     
     
    	enlarge: function() 
    	{
    		this.style.height = "100px";
    	},
     
     
    	shrink: function(index) {
    		this.style.height = changeHeight.origHeight[index];
    	}
     
     
    }
     
    Core.start(changeHeight);

    The error console says changeHeight.origheight has no properties. I have a feeling that it's because I am using it as an array. What do you think?
    Last edited by Smola; May 22, 2008 at 08:09.

  4. #4
    SitePoint Addict Smola's Avatar
    Join Date
    Mar 2005
    Posts
    260
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I pray to the javascript experts to view my post...please shine down your wisdom! =D

    EDIT: As I have been waiting for responses I have been doing some messing around with the code. It would seem that there are problems passing arguments through event listeners for some reason. I guess now that I know it's a problem, I just need to know WHY.

    Also, I just want to confirm, if I add an event listener to some object and assign the function "doThis", I can use the this keyword to reference the object. However, if WITHIN the doThis function I add a doThat function, the this keyword will not point to anything if I use it within the doThat function. Is this correct?
    Last edited by Smola; May 23, 2008 at 10:08. Reason: Additional Question

  5. #5
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,684
    Mentioned
    99 Post(s)
    Tagged
    4 Thread(s)
    Passing arguments through event listeners is relatively easy.

    With the code you currently have, it will pass the returned value of changeHeight.shrink(i) to the event handler.
    I'll simplify things first to a common way of assigning event functions.

    Code javascript:
    elements[i].onmouseout = changeHeight.shrink;

    So how do we pass a value to that function? Some people attempt to pass the value in this manner

    Code javascript:
    elements[i].onmouseout = changeHeight.shrink(i);

    But that's not going to work at all. Only the return value from the function will be assigned, which is not what we want at all. What we want to occur, is for the event handler to be assigned a function and already contains the value that it needs.

    In effect, what we want is for an amount value to change each time it's assigned

    Code javascript:
    elements[i].onmouseout = function () {
        var amount = 0;
        changeHeight.shrink(amount);
    };
    elements[i].onmouseout = function () {
        var amount = 1;
        changeHeight.shrink(amount);
    };
    ...

    So how do we get the value of amount passed in while using only one function? We pass it in as an argument, where the principles of closure allow us to retain the value within the function

    Code javascript:
    elements[i].onmouseout = function (amount) {
        // amount now varies
    }(i);

    That function is going to be run instantaneously because we passed a value to it, and the return value (currently undefined) will be assigned to the event. So what we need is to return back a function that can use the ever-changing value.

    Code javascript:
    elements[i].onmouseout = function (amount) {
        return function () {
            changeHeight.shrink(amount);
        }
    }(i);

    And we can even rename that amount variable to i

    Code javascript:
    elements[i].onmouseout = function (i) {
        return function () {
            changeHeight.shrink(i);
        }
    }(i);

    That is the common usage of how it's done.

    Back to your code now, here is how you would pass the value


    Code javascript:
    Core.addEventListener(elements[i],"mouseout", function (i) {
        return function () {
            changeHeight.shrink(i);
        }
    }(i);
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •