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;
};
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;
};
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:
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.
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 filescss direcotory, where main.scss is kept after being compiled by SassThe & 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).
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 thought I’d make a quick post to let everyone know two things, in no particular order:
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:
arguments objectCSS3 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.
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.
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.
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 */
}
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);
}
There are four basic ways to invoke a function in JavaScript:
You can view these examples in jsFiddle, or by cloning the /js-sandbox/invocation project on GitHub
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.
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.
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);
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.
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:
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 |
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);
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...]
Using Maven, there are a couple of ways we can deploy to a Tomcat server, whether the server is remote or local.
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.
The Maven User Settings are typically found in:
Add the following to the Maven User Settings:
<servers> <server> <id>local</id> <username>root</username> <password>root</password> </server> </servers>
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