Return to Misc. topics index

Random collection of misc. code and snippets

  1. Private variable using closures

    function x() {
        var id = 0;
        return function() { return id++; }
        }
        
    var makeid = x();
    
    var i = makeid();
    var j = makeid();
    

    id has effectively private access, via (and only) via the closure makeid() function.
  2. Remembering variables via closures

    foo() {
        var req = xmlhttp();
        req.onreadystatechange = function() { /*closure created here*/
            if (req.readyState == 4) {
                ...
                }
            }
        }
    
    Even though the onreadystatechange is a property/method of req, it is not invoked *via* req by the request handling (browser) thread. Since t needs access to itself and can either use a global variable (essentially window.req) or a closure to hold/access a reference to it.

    See also: http://ncyoung.com/entry/493#

  3. Closures have access to variables that can be changed

    x = elements('a')
    for (var i = 0; i < 10; i++)
        x[i].onclick = function{ ...use x[i]..}
        }
    
    All onclick function will refer to x[10], the final/latest value of the the closed variable i
  4. Various ways for Object creation

    
    A) new and function definition combined 
    var obj =   new function() {
        /* stuff */
        }
        
    B) object literal
    var obj = {
        /* stuff */
        }
    
    
  5. Defining object methods

    function MyObj() {}
    MyObj.prototype = {
        foo: function () {
            alert(this);
            }    
        ...etc..
        }
    
    var my1 = new MyObj();
    my1.foo();
    
  6. Toggling display visibility

    var elem = getElement('elem');
    elem.style.display = '';
    
    use display: '' as opposed to display: block (this uses the default "none" type which can differ from block or table-row or whatever, but in all cases, makes the element visible properly.

    However, setting elem.style.display = '' to just removing the inline style. If a document level css style declaration also exists and applies to the element, then the element will be still be rendered instead with that declaration (since elem.style.display only affects the inline declaration). So either:

    1. Don't use non-inline styles in addition to inline styles when using the display property (only use inline styles)
    2. or, change the stylesheet/classname as well as the display property

    See: http://tobielangel.com/2006/12/31/why-the-css-display-property-sucks

  7. Changing CSS for an element

    //inline style
    elem.style.xxx = ...
    //classname
    elem.className  = ...
    
    Either inline styles or className can be used.
  8. Use className

    elem.className = 'foo;;
    
    Use className and not class (since class can be a reserved word)
  9. DOM 0 Event handlers are methods

    <form>
    <button onclick="myfunc()"></button>
    </form>
    <script>
    alert(button.onclick);
    </script>
    
    classic event handlers (like button.onclick = ... ) are methods of the corresponding DOM button object
  10. Using the id attribute

    When the id attribute is used, all elements should have unique id's. The same id for multiple elements results in all sorts of problems in IE, even when using something like prototype's down/up, where we want a unique id (and there is a unique id) when starting downwards from a given element.
  11. Programmatic assignment of classes

    var table = document.getElementById('mytable');
    var rows  = table.getElementsByTagName('tr');
    for (var i = 0; i < rows.length; i++) {
        if(i%2) {
            rows[i].className += " even";
            }
        }
    
    Programmatically adding a class to a table to achieve a zebra stripes effect. JS functions for onmouseover/onmouseout can also be added this way.
  12. Ease of DOM

    $('foo').related = $('bar');
    
    Add properties to dom objects itself to refer to other related dom objects (this causes no memory leaks in IE since we are staying within the DOM).
  13. Force CSS layout

    window.resizeBy(0,1)
    window.resizeBy(0, -1)
    
    This forces css relayout and rendering updates.
  14. Accessing css styles from JS

    $('x').style.foo
    
    foo is only available if:
    1. it is set in an INLINE style definition on 'x'
    2. if it was previously assigned in JS, like:
      $('x').style.foo = 4

    Otherwise, foo is not available.

    This is a common issue when accessing left and top style properties on a div (where the default left/top are not available since they were not set in a inline style). The solution is to set these initially, either inline or via JS.

    Working example (in the right column):

    <style>
    #x, #y, #z {
        border: 1px solid #ccc;
        margin: 5px;
        }   
    
    #y {
        font-size: 2em;
        left: 30px;
        position: relative;
        }
    
    #z {
        font-size: 2em;
        position: relative;
        }
    </style>
    <script>
    function show(name) {
        var div = document.getElementById(name);
        alert("left="+div.style.left +
          "\nfontSize="+div.style.fontSize);
        }
    </script>
    <div onclick="show('x')" id=x 
      style="font-size: 2em;">x-div</div>
    
    <div style="position: relative">
    <div onclick="show('y')" id=y>y-div</div>
    </div>
    
    <div style="position: relative">
    <div onclick="show('z')" id=z 
      style="left: 60px;">z-div</div>
    </div>
    
    x-div
    y-div
    z-div
  15. DOM/HTML: attributes are useful

    <a href="javascript:showImg()">
    <img title="my image" name='sunset'>
    </a>
    
    A simple slide show whereby moving over a href shows a corresponding image in a image area. The title and name attributes of the img tag can be easily used to achieve this (and other custom attributes can be used as well, although the page will not "validate" if that's the case, but no big deal).

    Another example:

    <input type=text pattern="^\w+$" required=true>
    
    At page load time, JS code walks through all form fields, and if the pattern/required attributes are present, adds a validate function that validates the contents of the text field conform to the regex pattern before the form is submitted.
  16. Event bubbling

    An event bubble is not invoked on parent if the parent does not support that event handler (even if we add a event handler to the parent, the parent will never see it)
  17. Simple animation

        ---| 
        -----| 
        --------| 
        -----------|
    
    simple animation of a progress bar: keep increasing the width of a div or img.
    function progress() 
        { 
        var img = ..the img..
        if (img.width < 200) {
            img.width += 5;
            //to not autosize height along with width
            img.height = 5; 
            }
        else
            img.width = origwidth;
        }
    
    setInterval("progress()", 500);
    
  18. Prevent Caching of a resource

    document.write("< img src='foo.jpg?" + Math.random() + "' />"); 
    
    We change the URL harmlesslessly (as long as the stuff after "?" is ignored by the server) and prevent browser caching of the image
  19. DOM/HTML: common methods

    document.createElement('div')
    Creates a element node (div in this example)
    document.createTextNode()
    Creates a text node
    document.createDocumentFragment()
    Creates an empty DOM tree (useful for appending/creating elements too, and then transferring the entire tree to the actual document in one go)

     

    document.getElementById()
    document.getElementsByTagName("h1")
    Gets all tags of the specified type (h1 in this example). getElementsByTagName("*") gets all child elements of the specified elements/document (but this may not work in IE)
    element.getElementsByTagName("h1")
    Gets all tags of the specified type (h1 in this example) that are descendents of that element
    document.getElementsByClassName("myclass")
    Gets all elements that have the specified class name. This is not standard across browsers as far as I know.

    JS libraries like prototype, jquery etc., implement a full CSS2/CSS3 selector mechanism, so not only can we get elements by classname but many more CSS3 ways as well.

    Properties of nodes

    node.nodeType
    1. Node.ELEMENT_NODE == 1
    2. Node.ATTRIBUTE_NODE == 2
    3. Node.TEXT_NODE == 3
    4. Node.ENTITY_NODE == 6
    5. Node.DOCUMENT_NODE == 9
    6. Node.DOCUMENT_FRAGMENT_NODE == 11
    devedge link
    node.nodeValue
    value of text for a Text node (useful for #text). Null for most other nodes (including element nodes) devedge link
    node.nodeName
    mainly useful for the element tag name or "#text" for text nodes.
    1. Element ==> Element.tagName ("DIV", "H1", etc, UPPERCASE)
    2. Text => "#text"
    devedge link
    node.getAttribute()
    Gets an attribute for a node, such as getAttribute("href")
    node.setAttribute()
    Sets an attribute for a node, such as node.setAttribute("href", "http://bar.com");

    Operations on Nodes

    Finding nodes
    1. Children: firstChild, lastChild, childNodes
    2. Siblings: nextSibling, previousSibling
    3. Parents: parentNode
    Adding/Removing nodes
    1. removeChild(), appendChild()
    2. insertBefore(newnode, someOtherChild)
  20. Removing the current node from the DOM tree

    var node = ..some_element..
    node.parentNode.removeChild(node);
    
  21. Inserting a node before another node

    var list; 
    var newnode;
    list.insertBefore(newnode, list.firstChild);
    
  22. Cloning a node (shallow or deep copy)

    var node = ...
    var newnode = node.cloneNode(true|false); true=deep copy, else shallow
    
  23. Replacing a child node with another node

    var list;
    var newnode;
    list.replaceChild(newnode, list.oldchild)