/**
 * A random assortment of javascript utility routines
 *
 * @url         $URL: svn+ssh://al1.percdata.com/perc/svn/www/htdocs/js/utils.js $
 * @date        $Date: 2008-12-03 00:57:49 -0500 (Wed, 03 Dec 2008) $
 * @version     $Revision: 1 $
 * @author      $Author: xris $
 * @copyright   Silicon Mechanics
 * @license     LGPL
 *
 * @package     SiMech
 * @subpackage  Javascript
 *
/**/

// Wrapper for the various "get element" functions used by different browsers.
    function get_element(id) {
        if (typeof id != 'string')
            return id;
        if (document.getElementById)
            return document.getElementById(id);
        if (document.all)
            return document.all[id];
        return null;
    }

// Add an event handler to obj
    function add_event(obj, event, func) {
    // IE
        if (obj.attachEvent)
            obj.attachEvent('on'+event, func);
    // Gecko
        else if (obj.addEventListener)
            obj.addEventListener(event, func, false);
    // Everything else (but don't override hardcoded stuff)
        else if (!obj['on'+event_name])
            obj['on'+event_name] = func_name;
    }

// Remove an event handler from obj
    function remove_event(obj, event, func) {
    // IE
        if (obj.detachEvent)
            obj.detachEvent('on'+event, func);
    // Gecko
        else if (obj.removeEventListener)
            obj.removeEventListener(event, func, false);
    // Everything else (but don't override hardcoded stuff)
        else if (obj['on'+event_name] == func_name)
            obj['on'+event_name] = null;
    }

// Stop an event from bubbling up the event DOM
    function stop_event(e) {
        if (typeof e == 'undefined')
            e = window.event;
    // IE
        if (e.stopPropagation) {
            e.stopPropagation();
            e.preventDefault();
        }
    // Gecko
        else if (typeof evt.cancelBubble != 'undefined'){
            e.cancelBubble = true;
            e.returnValue  = false;
        }
        return false;
    }

// For some reason, calling "value" from within onclick doesn't work
// Seems to be a name conflict somewhere, but I can't find it.
    function set_value(id, val) {
        value(id, val);
    }

// Pass in value to change, otherwise it returns the value of the "e" element
    function value(e, new_value) {
        if (typeof e == 'string')
            e = $(e);
        if (!e)
            return '';
    // A <select>
        if (e.options) {
            if (new_value != null) {
            // This would scan the options and choose the one that matches
            // new_value.  Not used anywhere yet, so no need to hook it up.
            }
            return value(e.options[e.selectedIndex]);
        }
    // Just an html element?  (or in IE, an option element with no value="" specified)
        else if (e.value == null || e.tagName.toLowerCase() == 'option' && e.value == '') {
            if (new_value != null)
                e.innerHTML = new_value;
            return e.innerHTML;
        }
    // Form field
        if (new_value != null) {
            e.value = new_value;
        }
        return e.value;
    }

// Some enhancements for the basic string object
    String.prototype.addslashes = function() {
        return this.replace(/(["\\\.\|\[\]\^\*\+\?\$\(\)])/g, '\\$1');
    }
    String.prototype.trim = function () {
        return this.replace(/^\s*(.*?)\s*$/, '$1');
    };

// Get the end position of the selection cursor in obj
    function get_cursor_end(obj){
        obj.focus();
    // Gecko
        if (typeof obj.selectionEnd != 'undefined') {
            return obj.selectionEnd;
        }
    // IE
        else if (document.selection && document.selection.createRange){
            var r1 = document.selection.createRange();
            try {
                var r2 = r1.duplicate();
                r2.moveToElementText(obj);
            } catch(e) {
                var r2 = obj.createTextRange();
            }
            r2.setEndPoint('EndToEnd', r1);
            if (r2.text.length > obj.value.length)
                return -1;
            return r2.text.length;
        }
    }

// Get the start position of the cursor in the object
    function get_cursor_start(obj){
        obj.focus();
    // Gecko
        if (typeof obj.selectionStart != 'undefined') {
            return obj.selectionStart;
        }
    // IE
        else if(document.selection && document.selection.createRange){
            var r1 = document.selection.createRange();
            try {
                var r2 = r1.duplicate();
                r2.moveToElementText(obj);
            } catch(e) {
                var r2 = obj.createTextRange();
            }
            r2.setEndPoint('EndToStart', r1);
            if (r2.text.length > obj.value.length)
                return -1;
            return r2.text.length;
        }
    }

// Set the selection range in the object
// (end is optional if you just want to set the cursor)
    function set_selection(obj, start, end) {
        obj.focus();
    // No selection, just a cursor
        if (typeof end == 'undefined')
            end = start;
    // Select to the end of the string?
        else if (end == 'end') {
            end = obj.value.length;
        }
    // Select backwards from the end of the string
        else if (end < 0) {
            end = obj.value.length + (end + 1);
        }
    // Swap ranges, just in case
        if (end < start) {
            var tmp = start;
            start   = end;
            end     = tmp;
        }
    // Gecko
        if (obj.setSelectionRange) {
            obj.setSelectionRange(start, end);
        }
    // IE
        else if (obj.createTextRange) {
            var r = obj.createTextRange();
            r.moveStart('character', start);
            if (start == end)
                r.collapse();
            else
                r.moveEnd('character', end);
            r.select();
        }
    }

// Overwrite the href attribute of all <a> tags with a js_href attribute
    // add_event(window, 'load', add_js_attributes);
    function add_js_attributes(w) {
    // Make sure we got the right window
        if (typeof w == 'undefined' || typeof w.document == 'undefined')
            w = window;
        if (!w)
            return;
    // Get all links in this form
        var links = w.document.getElementsByTagName('a');
        for (var i=0; i<links.length; i++) {
        // js_href
            var js_href = links[i].getAttribute('js_href');
            if (js_href && js_href.length)
                links[i].href = 'javascript:' + js_href;
        // show the link title in the status bar
            if (!links[i].onmouseover && !links[i].onmouseout) {
                var title = links[i].getAttribute('title');
                if (title && title.length) {
                    add_event(links[i], 'mouseover', function () {
                                                         window.status = this.getAttribute('title');
                                                         return true;
                                                     });
                    add_event(links[i], 'mouseout', function () {
                                                        window.status = '';
                                                        return true;
                                                    });
                }
            }
        }
    // Handle any subframes
        if (w.frames) {
            for(var i=0; i<w.frames.length; i++){
                add_js_attributes(w.frames[i]);
            }
        }
    }

// Image Preloader
    var img_on  = new Array();
    var img_off = new Array();
    function preload_image(id, on, off) {
        add_event(window,
                  'load',
                  function() {
                      img_on[id]      = new Image();
                      img_on[id].src  = on;
                      if (off) {
                          img_off[id]     = new Image();
                          img_off[id].src = off;
                      }
                  });
    }

// Confirm deleting something?
    function confirm_task(what, field, val, form, type) {
        if (!field) {
            field = 'delete';
            val   = true;
        }
        if (!type) {
            type = 'delete';
        }
        if (confirm("Are you sure you want to " + type + " this " + what + "?  This cannot be undone."))
            submit_form(field, val, form);
    }

// Submit a form
    function submit_form(newvar, val, form, confirm_str) {
    // Confirm?
        if (confirm_str && !confirm(confirm_str))
            return;
    // Find the form we want to submit
        form = $(form ? form : 'form');
        if (!form)
            form = document.form ? document.form : document.forms[0];
    // Create a new variable?
        if (newvar) {
            var hidden = document.createElement('INPUT');
            hidden.type  = 'hidden';
            hidden.name  = newvar;
            hidden.value = val ? val : 1;
            form.appendChild(hidden);
        }
    // Submit
        form.submit();
    }

// Reset a form
    function reset_form(form, confirm_str) {
    // Confirm?
        if (confirm_str && !confirm(confirm_str))
            return;
    // Find the form we want to submit
        form = $(form ? form : 'form');
        if (!form)
            form = document.form ? document.form : document.forms[0];
    // reset
        form.reset();
    }

// Check whether a particular element possess a selected class
    function has_class(id, classname) {
        var obj = $(id);
    // No obj
        if (!obj)
            return false;
    // Obj already has this class
        if (obj.className && (new RegExp('\\b'+classname+'\\b')).test(obj.className))
            return true;
        return false;
    }

// Pop open a window to a new URL
    function popup_window(url, name, width, height, center) {
        var options = 'menubar=false,status=false,toolbar=false,scrollbars,resizable';
    // Center the new window?
        if (center) {
            var left    = 0;
            var top     = 0;
        // Figure out where this window should be drawn
            if (document.documentElement.clientWidth || document.documentElement.clientHeight) {
                left = parseInt((document.documentElement.clientWidth  - width)  / 2);
                top  = parseInt((document.documentElement.clientHeight - height) / 2);
            }
            else if (document.body.clientWidth || document.body.clientHeight) {
                left = parseInt((document.body.clientWidth  - width)  / 2);
                top  = parseInt((document.body.clientHeight - height) / 2);
            }
            else {
                left = parseInt((window.innerWidth  - width)  / 2);
                top  = parseInt((window.innerHeight - height) / 2);
            }
            if (window.screenLeft || window.screenTop) {
                left += parseInt(window.screenLeft);
                top  += parseInt(window.screenTop);
            }
            else if (window.screenX || window.screenY) {
                left += parseInt(window.screenX);
                top  += parseInt(window.screenY) + parseInt(window.outerHeight) - parseInt(window.innerHeight);
            }
        // Do some error checking - Safari has issues with height/width stuff and multiple monitors
            if (top > 200 && height > 0)
                options += ',top=' + top;
            if (left > 200 && width > 0)
                options += ',left=' + left;
        }
    // Make sure the window isn't too tall/wide
        if (width > screen.availWidth)
            width = screen.availWidth;
        if (height > screen.availHeight)
            height = screen.availHeight;
    // Add the height and width
        if (width > 0)
            options += ',width=' + width;
        if (height > 0)
            options += ',height=' + height;
    // Open a new window, with the new dimensions
        var win = window.open(url, name, options);
        win.focus();
    }

// Round a number to a specified number of decimal places
    function round(num, places, strip) {
    // Default to 2 decimal places, round the number
        places = (!isNaN(places) ? parseInt(places) : 2);
        num = '' + Math.round(num * Math.pow(10, places)) / Math.pow(10, places);
    // No trailing zeroes?
        if (strip || places == 0)
            return num;
    // Need to add trailing zeroes?
        var i = num.indexOf('.');
        if (i < 0) {
            num = num + '.';
            i = num.length - 1;
        }
        i = num.length - i - 1;
        for(var j=i;j<places;j++) {
            num = num + '0';
        }
        return num;
    }

// Print out all of a variable's contents, except functions (unless show_func
// is passed in as a true value).
    function debug(what, show_func) {
        var str = typeof what + ':\n\n';
        if (typeof what == 'object') {
            for (data in what) {
                try {
                    if (typeof what[data] == 'function' && !show_func)
                        continue;
                    str += data + ':  ' + what[data] + "\n";
                }
                catch (e) {
                    continue;
                }
            }
        }
        else {
            str = what;
        }
    // Create a popup window, and print the debug content
        var win = window.open('', 'debug', 'menubar=false,status=false,toolbar=false,scrollbars,resizable,width=800,height=600');
        win.document.write('<html><body><h3>javascript debug:</h3><pre>');
        win.document.write(str);
        win.document.write('</pre></body></html>');
        win.focus();
    }

// Returns the parent of item, where parent is of type type
    function get_parent(obj, type) {
        while (obj) {
            if (obj.nodeType == 1 && obj.tagName.toLowerCase() == type.toLowerCase())
                return obj;
            obj = obj.parentNode;
        }
        return null;
    }

// Implimentation of php's urlencode
    function urlencode(string) {
        return escape(string).replace('+', '%2B');
    }

// Implimentation of php's urldecode
    function urldecode(string) {
        return unescape(string.replace('%2B', '+'));
    }

// Php's htmlentities
// quote_style and charset do nothing right now
    function htmlentities(string, quote_style, charset) {
        string = string.replace('&', '&amp;');
        string = string.replace('>', '&gt;');
        string = string.replace('<', '&lt;');
        string = string.replace('"', '&quot;');
        return string;
    }

// Php's html_entity_decode
// quote_style and charset do nothing right now
    function html_entity_decode(string, quote_style, charset) {
        string = string.replace('&quot;', '"');
        string = string.replace('&lt;', '<');
        string = string.replace('&gt;', '>');
        string = string.replace('&amp;', '&');
        return string;
    }

