Tools.js
21 May 2010 @ 02:23PM
by Satis

Updated: 1 Jun 2010 @ 04:51PM
Tools.js is less of a single script, and more of a collection of small, unrelated utility functions in JavaScript. I'll get into each function, what it's for, and how it's used later. Suffice it to say that few if any of these tools have any relation to one-another.

Originally I just used these tools as a collection of different functions. However, the problem there is function name collision. If I were using another framework, or if I was developing a particularly complex application, I didn't want to worry about inadvertently having two different functions with the same name. Since JavaScript doesn't handle overloading, this becomes a big problem.

To combat this, I ended up wrapping all the functions in their own class, called tools. The way I build the class lets you call them like static methods, without having to instantiate an object first. Eg, you can just call tools.getMouse(e) rather than having to create your object first like you would with a typical javascript class.

Requirements
JavaScript enabled browser. Most of the tools should be cross-browser compatible.

Download
tools.js v1.1
Comments (0)
tools.getMouse(e)
tools.getMouse(e) is used to get the x and y location of the mouse when an event fires. This would typically be an onclick or onmousemove event, though it could be any kind of event. You must pass the event into the function.

Usage
<script type='text/javascript'>
     function myfunction(e){
          var position = tools.getMouse(e);
          alert('x: ' + position[0] + ' y: ' + position[1]);
     }
</script>
<input type="button" onclick="myfunction(event)" value="push me">


Source
tools.getMouse = function(e){
     var posx = 0;
     var posy = 0;
     if (!e) var e = window.event;
     if (e.pageX || e.pageY)      {
          posx = e.pageX;
          posy = e.pageY;
     }
     else if (e.clientX || e.clientY)      {
          posx = e.clientX + document.body.scrollLeft
               + document.documentElement.scrollLeft;
          posy = e.clientY + document.body.scrollTop
               + document.documentElement.scrollTop;
     }
     return [posx, posy];
}
Comments (0)
tools.getSize(item)
tools.getSize(item) was built to get the height, width, x-offset and y-offset of an item. For the top and left, it also requires the tools.getLocation(el) method. The item being passed in needs to be a valid DOM element.

Usage
<script type='text/javascript'>
     function myfunction(){
          var l = tools.getSize(document.getElementById('test'));
          alert('height: ' + l['height'] + ' width: ' + l['width'] + ' left offset: ' + l['left'] + ' top offset: ' + l['top']);
     }
</script>
<input type="button" onclick="myfunction()" value="push me">
<div id='test'>This<br>is<br>test<br>data</div>

Source
tools.getSize = function(item){
     var results = new Array();
     results['height'] = item.offsetHeight;
     results['width'] = item.offsetWidth;
     results['top'] = parseInt(item.style.top.substring(0, item.style.top.length - 2));
     results['left'] = parseInt(item.style.left.substring(0, item.style.left.length - 2));
     if(results['top'] = 'NaN' || results['left'] == 'NaN'){
          var t = tools.getLocation(item);
          results['top'] = t['top'];
          results['left'] = t['left'];
     }
     return results;
}
Comments (0)
tools.getViewport()
tools.getViewport() is designed to get the size of the current viewport. The viewport is the part of the web page that the user is currently viewing. In other words, it's the dimensions of the visible browser window, not including any sections of the web page that are scrolled off the screen. This may or may not be especially reliable... I recommend testing prior to rolling this out as an important part of a website.
Usage
<script type='text/javascript'>
     function myfunction(){
          var l = tools.getViewport();
          alert('height: ' + l['height'] + ' width: ' + l['width']);
     }
</script>
<input type="button" onclick="myfunction()" value="push me">

Source
tools.getViewport = function(){
     var tArray = new Array();
     tArray['height'] = window.innerHeight || document.documentElement.clientHeight || document.getElementsByTagName('body')[0].clientHeight;
     tArray['width'] = window.innerWidth || document.documentElement.clientWidth || document.getElementsByTagName('body')[0].clientWidth;
     return tArray;
}
Comments (0)
tools.getPageSize()
tools.getPageSize() is meant to get the full size of the web page being displayed. This is to include anything that's currently scrolled off the screen. This does not work very reliably, so be forewarned. If you have a more reliable method of getting this information, please post a comment.

Usage
<script type='text/javascript'>
     function myfunction(){
          var l = tools.getPageSize();
          alert('height: ' + l['height'] + ' width: ' + l['width']);
     }
</script>
<input type="button" onclick="myfunction()" value="push me">

Source
tools.getPageSize = function(){
     var t = new Array();
     if (document.documentElement.clientHeight && document.documentElement.clientWidth) {// Firefox
          t['height'] = document.documentElement.clientHeight;
          t['width'] = document.documentElement.clientWidth;
     }
     else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
          t['height'] = document.body.scrollHeight;
          t['width'] = document.body.scrollWidth;
     }
     else { // works in Explorer 6 Strict, Mozilla (not FF) and Safari
          t['height'] = document.body.offsetHeight;
          t['width'] = document.body.offsetWidth;
     }
     return t;
}
Comments (0)
tools.getLocation(el)
tools.getLocation(el) is designed to give you the x and y offsets of an html element. You must pass it a valid DOM element for it to work. The way the function works is it takes your current element and gets its x and y offset from its parent. It then gets the parent, does the same thing, and appends it to the child. Repeat until you run out of parents. It's a bit complicated and probably doesn't scale very well, but it works, I just wouldn't recommend doing it for a lot of elements all at once.

Usage
<script type='text/javascript'>
     function myfunction(){
          var l = tools.getLocation(document.getElementById('test'));
          alert('left offset: ' + l['left'] + ' top offset: ' + l['top']);
     }
</script>
<input type="button" onclick="myfunction()" value="push me">
<div id='test'>This<br>is<br>test<br>data</div>

Source
tools.getLocation = function(el){
     var results = new Array();
     results['left'] = 0; results['top'] = 0;
     while(el != null){
          results['left'] += el.offsetLeft;
          results['top'] += el.offsetTop;
          el = el.offsetParent;
     }
     return results;
}

Comments (0)
tools.getBaseName(name)
tools.getBaseName(name) takes a path (such as a url) and gets the last part of it. Name is expected to be a string. This is not an especially robust function... it expects the directory separators to be a forward slash (/). It basically returns everything after the last /, so that would include any GET variables appended to a URL, for example. However, it's fast and simple, which is always a plus.

Usage
<script type='text/javascript'>
     function myfunction(){
          var l = tools.getBaseName(document.location.href);
          alert(l);
     }
</script>

Source
tools.getBaseName = function(name){
     return name.substr(name.lastIndexOf('/') + 1);
}
Comments (0)
tools.isInt(i)
tools.isInt(i) was written so you could pass in a number and see if it's an integer. This is, once again, a fairly quick and dirty method, but it works.

Usage
<script type='text/javascript'>
     function myfunction(){
          alert(tools.isInt('string'));
          alert(tools.isInt(0));
          alert(tools.isInt(523));
     }
</script>
<input type="button" onclick="myfunction()" value="push me">

Source
tools.isInt = function(i){
     return (i % 1) == 0;
}
Comments (0)
tools.urlEncode(str) / tools.urlDecode(str)
tools.urlEncode(str) is designed to take a string and replace any characters that are unsafe in URLs and encode them so that they're safe. The primary use for this is in taking user input and sanitizing it so it can be safely transported via AJAX. A simple example of a character that will ruin an AJAX request is the ampersand (&).

tools.urlDecode(str) is exactly the same thing, but in reverse. It can take a urlEncoded string and switch it back to normal characters again.

Usage
<script type='text/javascript'>
     function myfunction(){
          var str = tools.urlEncode('This /?\& is? an unsafe string@#!');
          alert(str);
     }
</script>
<input type="button" onclick="myfunction()" value="push me">

Source
tools.urlEncode = function(str) {
     return escape(str).replace(/\+/g,'%2B').replace(/%20/g, '+').replace(/\*/g, '%2A').replace(/\//g, '%2F').replace(/@/g, '%40');
}
tools.urlDecode = function(str) {
     return unescape(str).replace(/\+/g,' ').replace(/%2B/g, '+').replace(/%2A/g, '*').replace(/%2F/g, '/').replace(/%40/g, '@');
}
Comments (0)
tools.trim(str)
tools.trim(str) is designed to take a string input and trim off any leading or trailing white space. I was surprised that JavaScript didn't appear to have any function to do this already built into the language. I'm not sure where I discovered this gem, but it's effective.

Usage
<script type='text/javascript'>
     function myfunction(){
          var uString = ' This is a string with whitespace '
          var str = tools.trim(uString);
          alert('"' + uString + '"\n"' + str + '"');
     }
</script>
<input type="button" onclick="myfunction()" value="push me">

Source
tools.trim = function(str){
     str = str.replace(/^\s+/, '');
     for (var i = str.length - 1; i >= 0; i--) {
          if (/\S/.test(str.charAt(i))) {
               str = str.substring(0, i + 1);
               break;
          }
     }
     return str;
}

Comments (0)
tools.countLines(strtocount, cols)
tools.countLines(strtocount, cols) is designed to count the number of lines that exist in a textarea html element. I specifically wrote this script so that I could dynamically resize a textarea depending on the amount of text that is currently in it. Due to the vagaries of fonts, this is less of a science and more of an art, but what I came up with works amazingly well.

Usage
<script type='text/javascript'>
     function myfunction(el){
          el.rows = tools.countLines(el.value, el.cols+1);
     }
</script>
<textarea onkeyup='myfunction(this)' cols='40' rows='1'></textarea>

Source
tools.countLines = function(strtocount, cols) {
     var hard_lines = 1;
     var last = 0;
     while ( true ) {
          last = strtocount.indexOf("\n", last+1);
          hard_lines++;
          if ( last == -1 ) break;
     }
     var soft_lines = Math.round(strtocount.length / (cols-1));
     if(hard_lines > soft_lines)
          soft_lines = hard_lines;
     return soft_lines;
}
Comments (0)
tools.resizeTextArea(el)
tools.resizeTextArea(el) is just a wrapper function for the previous tools.countLines(strtocount, cols) method above. If you look at the example for the above, that's precisely what this does. This allows you to call the method with an onkeyup on the textarea without any additional javascript at all.

Usage
<textarea onkeyup='tools.resizeTextarea(this)' cols='40' rows='1'></textarea>

Source
tools.resizeTextarea = function(el){
     var t = tools.countLines(el.value, el.cols+1);
     el.rows = t;
}
Comments (0)
tools.resizeTextInput(el, minsize)
tools.resizeTextInput(el, minsize) is meant to do for regular input elements what tools.resizeTextarea(el) does for textarea elements. The input requires an input element. The minsize is optional, but is the minimum size you'd like the input to shrink to. If nothing else is provided, a value of 5 is assumed.

Usage
<input onkeyup='tools.resizeTextInput(this)'>

Source
tools.resizeTextInput = function(el, minsize){
     if(minsize == null)
          minsize = 5;
     el.size = (el.value.length < minsize)? minsize : el.value.length;
}
Comments (0)
tools.getSelectValue(el)
tools.getSelectValue(el) expects an html select element to be passed to it. It then returns the value of the selected item.

Usage
<script type='text/javascript'>
     function myfunction(){
          alert(tools.getSelectValue(document.getElementById('test')));
     }
</script>
<select id='test'><option value="first one">One</option><option value="second">Two</option><option value="tres">tois</option></select>
<input type="button" value="click me" onclick="myfunction()">

Source
tools.getSelectValue = function(el){
     return el.options[el.selectedIndex].value;
}
Comments (0)
tools.colorRows(el, overwrite)
tools.colorRows(el, overwrite) is designed to add even/odd classes to a table for reasons of making the body rows alternating color. I tweaked this heavily for various reasons, but in the end, you basically need to pass it an element that is a table or an element within a table. The function will automatically go up until it finds the closest table ancestor. At that point, it will drive down to any TBODY elements and grab all the table rows below it. If the row does not have a class, or if the overwrite option is set to true, the method then adds either an even or odd class to that row.

The even and odd classes must be defined in your stylesheet, otherwise it won't have any noticeable effect. Please note that this only colors TBODY rows... it purposefully avoids THEAD and TFOOT so you can apply your own formatting.

Usage
<script type='text/javascript'>
     function myfunction(){
          tools.colorRows(document.getElementById('test'));
     }
</script>
<style type='text/css'>
table{
     border-collapse: collapse;
     border: 1px solid #000000;
}
table thead tr{
     background-color: #000000;
     color: #ffffff;
}
table tbody .even{
     background-color: #ccccff;
}
table tbody .odd{
     background-color: #ccffcc;
}
</style>
<table id='test'>
<thead>
     <tr><td>Column 1</td><td>Column 2</td><td>Column 3</td></tr>
<tbody>
     <tr><td>Row 1</td><td>__jkdjfd</td><td>hi</td></tr>
     <tr><td>Row 2</td><td></td><td>welcome</td></tr>
     <tr><td>Row 3</td><td>oi</td><td>goodbye</td></tr>
</tbody>
</table>

<input type="button" value="click me" onclick="myfunction()">

Source
tools.colorRows = function(el, overwrite){
     while(el && el.tagName != 'TABLE')
          el = el.parentNode;
     if(!el)     return
     
     var rows = new Array();
     for(var i=0; i<el.childNodes.length; i++){
          if(el.childNodes[i] && el.childNodes[i].tagName == 'TBODY'){
               var t = el.childNodes[i].childNodes;
               for(var j=0; j<t.length; j++)
                    rows[rows.length] = t[j];
          }
     }
     
     for(var i=0; i<rows.length; i++){
          //don't lose specifically defined classes
          if(overwrite || rows[i].className == '' || rows[i].className == 'even' || rows[i].className == 'odd')
               rows[i].className = (i % 2 == 0)? 'even' : 'odd';
     }     
}
Comments (0)
tools.getClassSelector(stylesheet, selector)
tools.getClassSelector(stylesheet, selector) is designed to parse your stylesheet and return the values for a specific selector. For instance, you can tell the function to search your main site class for a class called 'test' and have it return all the CSS rules associated with test. From there, additional processing could be accomplished.

The stylesheet is the numerical offset of your stylesheet starting at 0. If you only have 1 stylesheet defined in your site, use 0, otherwise calculate the offset by number
Usage
<html>
<head>
     <link rel='stylesheet' type='text/css' href='style.css'>
     <script type='text/javascript' src='resources/js/tools.js'></script>
     <script type='text/javascript'>
          function myfunction(stylesheet, selector){
               var style= tools.getClassSelector(stylesheet, selector);
               alert('style: ' + style.cssText);
          }
     </script>
</head>
<body>
     <input type="button" onclick="myfunction(0, '.test')" value="push me">
</body>
</html>

Source
tools.getClassSelector = function(stylesheet, selector){
     var css = (document.styleSheets[stylesheet].cssRules)? document.styleSheets[0].cssRules : document.styleSheets[0].rules;
     for(var i=0; i<css.length; i++){
          if(css[i].selectorText == selector)
               return css[i].style;
     }
}
Comments (0)
tools.deselect()
tools.deselect() can be used to deselect anything that's currently selected in a page. IE, if someone selects text or an image, the script can be used to automatically deselect the text or image. This can be handy if you're implemented double-click mouse events, or events based off of clicking and dragging.

Usage
     <div onmouseup='tools.deselect()'>This is a bunch of text. Try double-clicking or click-dragging on it.</div>

Source
tools.deselect = function(){
     if(document.selection && document.selection.empty) {
          document.selection.empty();
     }
     else if(window.getSelection) {
          var sel = window.getSelection();
          sel.removeAllRanges();
     }
}
Comments (0)