TUANLEADED


Domify

A quick little utility function to help turn your HTML into DOM elements:

domify = function( str ) {
  var temp = document.createElement('div');
  temp.innerHTML = str;
  return temp.firstChild;
};

JavaScript tagName with SVG

We can use the tagName property to determine what kind of element we are handling. This can be used in conjunction with event delegation: when the user hovers over a large area, we handle it by determining the target of the event.

An example can be found in High Performance JavaScript:

document.getElementById('menu').onclick = function(evt) {
  evt = evt || window.event;
  var target = evt.target || evt.srcElement;

  if( target.tagName !== 'A' ) {
    return;
  }

  handleEvent(evt);
}

We can see this script detects if our target is an anchor, and is straightforward to modify if you’d like to handle other HTML elements differently – simply swap out A with SPAN, DIV, etc. But what if you need to handle SVG elements?

According to MDN’s article on element.tagName:

  1. In HTML, the tagName is returned in all caps
  2. In XHTML or any other XML format, the tagName is returned in lowercase

So if your event handler is checking for tag name, it may return elements of the page in all caps, such as BODY, A, SVG, but within the SVG, an element’s tagName will be returned in lowercase, such as circle.

If you’d like to not have to deal with remembering between uppercase and lowercase, perhaps you can use the toLowerCase() method to process all of your tagNames and make them lowercase.

Running SASS –watch in Background

I have a basic project that uses Sass hosted on my httpd server. The command I use to have Sass watch for changes in the background is:

cd /var/www/html/_
sass --watch scss:css &
disown

The way I have my workspace set up, I keep the following two directories in /var/www/html:

  • scss directory where I keep main.scss and other Sass files
  • css direcotory, where main.scss is kept after being compiled by Sass

The & runs the process in the background, and disown allows you to close the terminal window or log out without stopping the process (e.g. it prevents the SIGHUP signal from being sent).

Killing the Process

Run the following command to search for the Sass process and kill it:

ps -aef | grep sass | grep scss | awk '{print $2;}' | xargs -i kill {}

I’m [in]

I thought I’d make a quick post to let everyone know two things, in no particular order:

  1. Any viewpoints and opinions expressed in this article are those of my own and do not, in any way, reflect those of my employer, my colleagues, or anyone else. I speak only for myself, not for them.
  2. I’m now a web dev at LinkedIn.

Digesting JavaScript Good Parts: Arguments & Currying [draft]

A variadic function is one that takes in a variable number of arguments. In this article, I’m going to take a look at some of the different ways this can be handled in JavaScript:

  1. Function Overloading
  2. The arguments object
  3. Passing arguments as an object
  4. Currying

Read more »

CSS Opacity

CSS3 has an opacity property that allows us to control the transparency level of an object. The following CSS makes our links appear at 60% opacity (40% transparent), then when hovered over (with a mouse) or focused (with keyboard navigation) they become a little more salient at 80% opacity (20% transparent):

a {
  opacity: .60;
}

a:hover, a:focus {
  opacity: .80;
}

Opacity can be a float that ranges between 0 (100% transparent; not visible) and 1.0 (100% opaque; visible, and covering all layers below it). Values between 0 and 1 will make an element somewhat transparent, allowing layers beneath the object to be somewhat visible.

Benefits of and Alternatives to Using Opacity

Combining opacity with CSS transition can enhance the user experience for visitors with modern browsers. As they interact with elements on the webpage, the elements subtly react and “come alive.”

Sometimes, it can be used interchangeably with rgba; the following two definitions are almost identical:

.foo{
  background: white;
  opacity: .80;
}

.bar {
  background: white;
  background: rgba(255,255,255,0.8);
}

However, rgba isn’t supported in all browsers; .bar elements will be 100% white (no transparency) as the rgba will be ignored in browsers that don’t support it.

Then again, opacity isn’t supported in all browsers, but with filter and -ms-filter properties we can get around it in older versions of IE.

Drawbacks of Using Opacity

Opacity impacts it’s children, which might not always be what we want. Going back to our previous examples .foo‘s children will also be 20% transparent. If we only wanted the background to be semi-transparent, then .bar might be a more appropriate definition, although it won’t work across all browsers.

Cross-Browser Opacity

IE 9 supports the opacity property, but for previous versions of IE as well as older versions of Firefox and Konqueror, we’ll need to use the following:

a {
  -moz-opacity: .25;
  -khtml-opacity: .25;
  opacity: .25;
  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=25)";  /* IE 8 */
  filter: alpha(opacity = 25);  /* IE 5-7 */
}

LESS Opacity Mixin

The following Less CSS mixin can be used to easily attain cross-browser compatibility for controlling opacity:

.opacity(@o: 50) {
  @ms-filter: ~"progid:DXImageTransform.Microsoft.Alpha(Opacity=@{o})";
  
  -moz-opacity: @o/100;
  -khtml-opacity: @o/100;
  opacity: @o/100;
  -ms-filter: "@{ms-filter}";  /* IE 8 */
  filter: ~"alpha(opacity = @{o})";  /* IE 5-7 */
}

This mixin will accept a value from 1 to 100, convert it to a decimal for the opacity properties, and use the integer value for the Microsoft filters.

The following declaration

.foo{
  .opacity(75);
}

Will compile as:

.foo {
  -moz-opacity: 0.75;
  -khtml-opacity: 0.75;
  opacity: 0.75;
  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=75)";
  filter: alpha(opacity = 75);
}

Digesting JavaScript Good Parts: Invoking Functions [draft]

There are four basic ways to invoke a function in JavaScript:

  • Method Invocation
  • Function Invocation
  • Constructor Invocation
  • Apply Invocation

You can view these examples in jsFiddle, or by cloning the /js-sandbox/invocation project on GitHub

Read more »

Digesting JavaScript Good Parts: Memoization

I first came across the concept of memoization in Douglas Crockford’s Javascript: The Good Parts, and again in Nicholas Zakas’ High Performance JavaScript.

It is a technique used in optimizing recursive functions, such as calculating factorial or Fibonacci numbers.

Read more »

Unpacking jQuery: AJAX [draft]

This is the first of a series of entries that I will devote to unpacking the popular JavaScript library: jQuery. I chose to start with AJAX because, of all the jQuery functions, I personally rely on it the most yet understand it the least.

Its a good idea to understand what goes on underneath the hood of jQuery; it gives you a greater appreciation of how much time the framework saves, reduces your dependency on the framework, gives you a better understanding of how JavaScript works (and how broken it can be across browsers), and gives insight on how you can write more optimized code.

XMLHttpRequest

It starts with the XMLHttpRequest object. Using Chrome, I created a blank HTML page and inspected a new XMLHttpRequest to take a peek at its properties and its methods.

xhr = new XMLHttpRequest();
console.log(xhr);

Cross-Browser Compatibility

If we look into the history behind XMLHttpRequest, we’ll find that Microsoft’s implementation is an ActiveXObject, which came out before XMLHttpRequest became a standard. Jonathan Snook gives an example of how a function that checks for the native AJAX transport object.

In jQuery, the check looks something like:

function createStandardXHR() {
  try {
    return new window.XMLHttpRequest();
  } catch( e ) {}
}

function createActiveXHR() {
  try {
    return new window.ActiveXObject( "Microsoft.XMLHTTP" );
  } catch( e ) {}
}

jQuery.ajaxSettings.xhr = window.ActiveXObject ?
  /* Microsoft failed to properly
   * implement the XMLHttpRequest in IE7 (can't request local files),
   * so we use the ActiveXObject when it is available
   * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
   * we need a fallback.
   */
  function() {
    return !this.isLocal && createStandardXHR() || createActiveXHR();
  } :
  // For all other browsers, use the standard XMLHttpRequest object
  createStandardXHR;

This detects if the browser supports ActiveXObjects, otherwise it creates a (standard) XMLHttpRequest object.

open and send

The first two XMLHttpRequest methods which I'll use to make an AJAX request and return the results are open and send:

xhr = new XMLHttpRequest();
console.log(xhr);
xhr.open("GET","rsp.txt",false);
xhr.send();
console.log(xhr);

The open() method fetches the file rsp.txt with a GET call, and the third parameter is an optional boolean for asychronous requests. Here we've set it to false to indicate that it is a synchronous request: the script will wait for the request to complete before continuing.

open simply makes the connection; xhr doesn't contain the contents of rsp.txt until we invoke send(). After send, we can see that xhr.response and xhr.responseText are no longer empty strings, as shown with the second xhr object in our console:

Synchronous and Asynchronous Requests

We can change the xhr.onreadystatechange property to be a function that acts as a callback. It acts as a listener to the xhr.readyState property, which can be in one of five states:

value state
0 UNSENT
1 OPENED
2 HEADERS_RECEIVED
3 LOADING
4 DONE

Observing the readyState

To get a better understanding of the readyState, we'll set xhr.onreadystatechange to a function that simply outputs the current value of readyState whenever it changes.

xhr = new XMLHttpRequest();
console.log(xhr);

xhr.onreadystatechange = function() {
    console.log(xhr.readyState);
};

xhr.open("GET","rsp.txt",false);
xhr.send();
console.log(xhr);

If we change the third open parameter to true, we make an asynchronous call and will see this instead:

Notice that only two readyStates are displayed in the synchronous call, even though xhr.onreadystatechange should output on every state change. According to MDN's documentation, we should not use onreadystatechange for synchronous calls.

In the asynchronous call, xhr is output null, and all the readyState changes are detected. The output is null because of the asynchronous nature of the request; we are attempting to output xhr even before send() is finished. Add another console.log(xhr) to onreadystatechange to see what state xhr is in at every step of the request.

xhr = new XMLHttpRequest();
console.log(xhr);

xhr.onreadystatechange = function() {
    console.log(xhr.readyState);
    console.log(xhr);
};

xhr.open("GET","rsp.txt",false);
xhr.send();
console.log(xhr);

Callbacks and Streaming

Our updates to xhr.onreadystatechange is effectively lays down the foundation for a callback to be fired. We can make the following updates so that the callback is only fired once, when the request has been successfully completed:

xhr.onreadystatechange = function() {
    if( xhr.readyState === 4 ) {
        callback();
    }
};

In some browsers, it is also possible to have a listener to perform feedback while the response is still loading. We can accomplish this by listening for when xhr.readyState:

xhr.onreadystatechange = function() {
    if( xhr.readyState === 3 ) {
        var dataSoFar = xhr.responseText;
        doWhileLoading( dataSoFar );
    } else if( xhr.readyState === 4 ) {
        var data = xhr.responseText;
        doWhenComplete( data );
    }
};

This is called streaming, and allows us to provide continuous feedback even before all the data has been transmitted.

[to be continued...]

Deploying to Tomcat with Maven

Using Maven, there are a couple of ways we can deploy to a Tomcat server, whether the server is remote or local.

Using the Tomcat plug-in

We’ll need to add the Tomcat plugin to our project by adding the following to our POM:

<plugin>
	<groupId>org.codehaus.mojo</groupId>
	<artifactId>tomcat-maven-plugin</artifactId>
	<version>1.1</version>
	<configuration>
		<server>local</server>
		<url>http://localhost:8080/manager</url>
	</configuration>
</plugin>

The <server> is just logical naming that should match a server in your Maven User Settings, and the <url> should point to Tomcat Manager.

Updating Maven User Settings

The Maven User Settings are typically found in:

  • Eclipse: Window > Preferences > Maven > User Settings
  • Windows: C:\Users\username\.m2\settings.xml

Add the following to the Maven User Settings:

<servers>
	<server>
		<id>local</id>
		<username>root</username>
		<password>root</password>
	</server>
</servers>

Deployment

From Eclipse, run the project as a Maven build…, with the tomcat:deploy goal. From the command line, run;

mvn tomcat:deploy

Using the tomcat-maven-plugin we can also run the following commands:

mvn tomcat-undeploy
mvn tomcat-redeploy