• Industar-69 28mm f/2.8

    Since getting an A7, I’ve been on a vintage lens buying spree. I’m planning to spend an extended period of time with each of them in order know how each handles and draws, so you’ll see a series of posts (in time) with my thoughts on each of them.

    The Industar-69 was produced for the Soviet Chaika half-frame (18x24mm) camera, which from 1965 to 1974 sold over 2 million copies. This explains the vignetting seen when mounted on the full-frame A7. It’s not very sharp at all, but its drawing makes its black and white results exceedingly endearing. Its size is a huge plus point as well, behooving it for a full day out on the streets.

    The lens had to be modified slightly though; its flange distance is slightly off of the M39 mount, so I couldn’t achieve infinity focus right out of the box. The poor quality control of the Industar-69 worked in my favour - after disassembling the focus ring, I discovered that the focusing helicoid still had a few threads left, so I simply tightened it slightly.

    These are some pictures I took on a day out. Post-processing done entirely in Lightroom (black and white conversion and some mild curves adjustment).

    This post is a work in progress.

  • Installing Composer Globally

    Technical Context: Composer 1.0-dev, PHP 5.5.27, OS X Yosemite

    Install Composer:

    $ cd ~
    $ curl -sS https://getcomposer.org/installer | php
    

    This will create a composer.phar PHP archive as well as a .composer directory. To keep things cleaner, I move composer.phar inside .composer:

    $ mv ~/composer.phar ~/.composer
    

    Then, simply alias php ~/.composer/composer.phar to composer by adding some variation of the following to your shell config (e.g. .bash_profile or .fish_config):

    $ alias composer="php ~/.composer/composer.phar"
    
  • new-Agnostic JavaScript Constructors

    Constructors in JavaScript have gotten a bad rep because there’s nothing stopping the unwitting programmer from doing something like this:

    function Thing(x,y) {
      this.x = x;
      this.y = y;
    }
    
    var thing = Thing(1,2);
    console.log(thing); // undefined
    console.log(this); // window (or equivalent global object)
    console.log(this.x); // 1
    console.log(this.y); // 2
    

    I wrote comprehensively about object creation here, which may be useful to read as a prerequisite to this post.

    This tip from Item 33 of Effective JavaScript by David Herman makes your constructor behave as intended, regardless of whether the new keyword is present. The first method:

    function Thing(x,y) {
      if (!(this instanceof Thing)) {
        return new Thing(x,y)
      }
      this.x = x;
      this.y = y;
    }
    

    An alternative method to save that extra recursive function call:

    function Thing(x,y) {
      var self = (this instanceof Thing) ? this : Object.create(Thing.prototype);
      self.x = x;
      self.y = y;
      return self;
    }
    
  • JavaScript Timers

    Timers in JavaScript are used to schedule functions to be called at a later time. It does so by setting up a timer which, when it’s done counting down, places its associated function into the environment’s event loop. As such, setTimeout guarantees that the function won’t be fired before its specified time, but it cannot guarantee that it will be fired at that specific point in time too - if event queue has other functions waiting to be executed, then it will be delayed.

    These timer functions are methods on the window object and can be invoked as is:

    document.body.style.background = "blue"; 
    
    setTimeout(function() {
      document.body.style.background = "yellow"; 
    }, 2000);
    

    Functions scheduled with setTimeout can be cancelled with clearTimeout:

    var timedFunc = setTimeout(function() {
      console.log("I'll never be executed");
    }, 2000);
    
    clearTimeout(timedFunc);
    

    setTimeout and clearTimeout have cousins which execute their functions in regular intervals, called setInterval and clearInterval.

    Debouncing

    Timers in JavaScript can be used for debouncing to prevent event handlers from being invoked too frequently.

    There are two effects that can be achieved here:

    1. To invoke the event handler after a pause in event firing
    2. To invoke the event handler at slower periodic intervals

    An example of the first effect:

    <button>Click me constantly</button>
    
    <script>
      var textarea = document.querySelector('button');
      var timeout;
    
      textarea.addEventListener("click", function() {
        clearTimeout(timeout);
        timeout = setTimeout(function() {
          console.log("You stopped clicking");
        }, 500);
      });
    </script>
    

    We clear the timeout to reset the timer.

    An example of the second effect:

    <script>
      var scheduled = false;
      window.addEventListener("mousemove", function(event) {
        if (!scheduled) {
          scheduled = true;
          setTimeout(function() {
            scheduled = false;
            console.log("Mouse at  " + event.pageX + ", " + event.pageY);
          }, 250);
        }
      });
    </script>
    

    We check if scheduled is true fist before creating a scheduled function. When the scheduled function fires, it resets scheduled to false.

  • The Browser DOM

    The DOM, as implemented in browsers, is a model to represent a HTML or XML document as a tree of nodes, and presents an API to access and manipulate these nodes.

    There are twelve kinds of nodes, but two of them are used the most - element nodes and text nodes1. HTML tags are represented as element nodes, while the content inside these tags are represented as text nodes2.

    In a typical browser environment, every node is represented as an object (with properties). The document object contains properties to access these DOM node objects.

    The root node can be accessed with document.documentElement. Another example is the body, which can be accessed with document.body.

    In the DOM API, elements which are not found, or referenced before they are rendered are null:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <script>
        console.log(document.documentElement); // <html lang="en">...</html>
        console.log(document.body); // null
      </script>
    </head>
    <body>
      <script>
        console.log(document.body); // <body>...</body>
      </script>
    </body>
    </html>
    

    DOM Traversal

    There are several ways to move around the DOM tree.

    Direction Method
    Up parentNode
    Down childNodes, which includes all node types, and children, which includes only element nodes
    Left/Right previousSibling, nextSibling

    Aside from traversing, there are also methods to access nodes in the DOM tree directly. They are called on the document object, as in document.getElementById:

    Method Description
    getElementById Find a node by its id
    getElementsByTagName Find all nodes with the given tagName
    getElementsByName Find all nodes with the matching name HTML attribute
    getElementsByClassName Find all nodes with the given class. Understands multiple classes
    querySelector, querySelectorAll Find the first node/all nodes that matches the given CSS3 query, respectively

    querySelector and querySelectorAll offer more powerful queries, but are less performant than the other methods.

    All these methods that return multiple nodes in a HTMLCollection, except querySelectorAll, are live, meaning that they are automatically updated when the document is changed.

    XPath

    Another way to search through the DOM is using XPath.

    DOM Node Attributes and Properties

    Since DOM nodes are represented as objects, they have properties, just like JavaScript objects. These properties include implementations of the various standard DOM API interfaces, which are common across all nodes. Some properties are read-only, while others are modifiable.

    Some important ones are listed below:

    Property Description Read-only
    nodeType ID of node type Yes
    nodeName,tagName Name of element nodes Yes
    innerHTML Contents of element nodes No
    nodeValue Contents for other types of nodes except element nodes No

    Additionally, each type of HTML DOM node has its own set of standard properties. MDN maintains a comprehensive reference of all these DOM object types, for example, the <form> DOM object.

    HTML attributes of HTML DOM node objects can be accessed and modified with getAttribute and setAttribute, or with the properties of the DOM object itself:

    e.getAttribute('id')
    e.id
    

    One should use the DOM object property most of the time:

    In reality, there are only two cases where you need to use the attribute methods:

    1. A custom HTML attribute, because it is not synced to a DOM property.
    2. To access a built-in HTML attribute, which is not synced from the property, and you are sure you need the attribute (for example, the original value of an input element).

    Attribute names and property names do not always have a one-to-one correspondence. For instance, e.class is forbidden because class is a reserved class in Javascript. Instead, its corresponding property name is className, as in e.className (this is highly relevant when writing JSX in React):

    Attribute name Property name
    for htmlFor
    class className
    tabindex tabIndex

    Attribute and Property Synchronization

    Most standard DOM properties are synchronized with their corresponding attribute (one notable exception is href).

    I say most, because a select few standard properties are synchronized one-way only, for example the value property in the input DOM object. The property is synchronized from the attribute, but not the other way:

    <!DOCTYPE html>
    <html lang="en">
      <input>    
      <script>
        var input = document.getElementsByTagName("input")[0]
        console.log(input.value); // ""
        input.setAttribute("value", "I am number one!")
        console.log(input.value); // "I am number one!"
    
        input.value = "I am number two!"
        console.log(input.getAttribute("input")); // "I am number one!"
      </script>
    </body>
    </html>
    

    Custom Attributes

    HTML elements may contain custom attributes. These are not automatically represented by element properties, and so have to be accessed and modified with getAttribute and setAttribute. The HTML5 specification standardizes on prefixing data- for custom attributes.

    DOM Modification

    The most common methods of DOM node addition, removal, cloning and reinsertion are demonstrated below:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    </head>
    <body>
      <script>
    
        // Demonstration of node addition
    
        var newNode = document.createElement('p')
        document.body.appendChild(newNode)
    
        console.log(document.body.children) // [script, p]
    
        var anotherNewNode = document.createElement('div')
        document.body.insertBefore(anotherNewNode, newNode)
    
        console.log(document.body.children) // [script, div, p]
    
        document.body.innerHTML += "<em><b></b></em>" // supports nested HTML tags as well
    
        console.log(document.body.children) // [script, div, p, em]
        console.log(document.body.lastChild.children) // [b]
    
        // Demonstration of node cloning
    
        document.body.appendChild(newNode.cloneNode(true)) // set to true to clone deeply
        console.log(document.body.children) // [script, div, p, em, p]
    
        // Demonstration of node removal and reinsertion
    
        var oneMoreNode = document.createElement('input')
        document.body.appendChild(oneMoreNode)
    
        console.log(document.body.children) // [script, div, p, em, p, input]
    
        var detachedNode = document.body.removeChild(oneMoreNode)
        console.log(document.body.children) // [script, div, p, em, p]
    
        document.body.appendChild(detachedNode)
        console.log(document.body.children) // [script, div, p, em, p, input]
    
      </script>
    </body>
    </html>
    

    Footnotes

    1. Each node type is assigned an ID, which can be accessed through the nodeType property.

    2. There are also whitespace nodes, which are text nodes that contain only whitespace. Their use is purely internal. More info.