/*
//this file copyright Apposite Ltd 2005
*/

//-------------start common.js-------------------//
if (!window.KJD){window.KJD = new Object;}
//object for holding all my functions/object to give them all their own namespace
//you should be able to do a find/replace with the string 'KJD' (case sensitive)
//if the script conflicts with someone elses script.

KJD.test = function(){
    window.open('','bob','resizable=yes,width=300,height=300');
}

KJD.baseUrl = 'http://localhost/contextify/';

KJD.debug_mode = 'alert'; //alert|status|window|div|none
KJD.error_mode = ''; // [alert|log|ignore] or leave empty for normal (browser based) error handling
KJD.error_log = ''; //for logging errors to another domain
//'http://www.webfoundry.co.nz/javascript_error.php';  
//this page should return an empty string or some javascript

KJD.error_handler = function(description, url, line){
    //supress all errors within the error handler
    //otherwise endless loops could occur?
    window.onerror = null;
    
    //defaults
    //mozilla doesn't give a url or line number.
    url = (url) ? url : window.location;
    line = (line) ? line : 'unknown';
    
    var msg = 'Msg = '+ description +'\nUrl  = '+ url +'\nLine = '+ line;

    switch (KJD.error_mode){
    case 'alert':
        window.alert(msg);
        break;

    case 'log':
        //log to a script src
        if (KJD.error_log == ''){
            throw Error('Error Log Src not set.');
            break;
        }
        else {
            //MZ: errors are still caught by the built in error handler
            var script = document.createElement('script');
            script.src = KJD.error_log +'?msg='+ escape(description) +'&url='+ escape(url) +'&line='+ line;
            if (document.body){
                document.body.appendChild(script);
            }
            else {
                //nothing we can do
                //FIXME: save to cookie maybe?
            }
        }
        break;
        
    case 'ignore':
        //do nothing
        break;
        
    default:
        throw Error('Invalid error_mode ('+ KJD.error_mode +')');
    }
    
    //restore the error handler
    window.onerror = KJD.error_handler;
    return true;
}

//set error handler event
if (KJD.error_mode != ''){
    window.onerror = KJD.error_handler;
}


//add activeElement to the document
//register event handlers

    

//a couple of useful string functions
String.prototype.trim = function(){
    //trims leading and trailing whitespace from a string
    var s = this.replace(/^\s+/,'');
    s = s.replace(/\s+$/,'');
    return s;
}

KJD.decToHex = function(num, min_length){
    //Converts a decimal to its hex string
    var HEX_STR = "0123456789ABCDEF";

    //validate input
    num = Math.floor(num);
    
    if (!min_length){min_length=2;}

    var mod=0;
    var hex='';

    while (num > 0){
        mod = num % 16;
        hex = HEX_STR.charAt(mod) + hex;
        num = (num - mod) / 16;
    }
    //pad to required length
    for (var i=hex.length; i<min_length; i++){
        hex = '0' + hex;
    }

    return hex;
}

KJD.escapeAll = function(obj){
    //escapes all characters in a string
    var s='';
    var str = obj.toString();
    
    for (var i=0; i<str.length; i++){
            var ch_code = str.charCodeAt(i);
            s += '%' + KJD.decToHex(ch_code, 2);
    }
	
    return s;
}

String.prototype.listToExp = function(){
    //converts a comma separated list into a regular expression
    
    //replace all commas with pipes and trim whitespace
    var s = this.trim();    
    if (s == '*'){
        s = '.*';
    }
    else {
        s = s.replace(/\s*,\s*/g,'|');
    }
    
    var exp = new RegExp('\\b('+ s + ')\\b','gi');
    return exp;
}


KJD.undef = function(v){
    var undefined_variable;
    return (v === undefined_variable);
}

KJD.isdef = function(v){
    return !(KJD.undef(v)); 
}

KJD.getId  = function(id){
    //short form of document.getElementById, allows for an element to be passed
    if (typeof(id) != 'string'){
        //object passed
        return id;
    }
    else {
        var ele = document.getElementById(id);
        if (!ele){debugger;}
        //if (!ele){throw Error('Element id not found(' + id +').');}
        return ele;
    }
}

KJD.getTags = function(tagname, parent){
    //get all elements of type tagname
    
    //default values
    tagname = (tagname) ? tagname : '*';
    parent = (parent) ? parent : document;
    
    var tags = parent.getElementsByTagName(tagname);
    
    //IE hack
    //element.getElementsByTagName('*') only works for Moz, IE6+ (not IE5 or IE5.5);
    if ((tagname == '*') && (tags.length == 0) && (parent.all)){
        //FIXME: shouldn't use document.all should use childNodes
        //Actually element.all seems to work fine
        tags = parent.all;
    }
    return tags;
}

KJD.getElementsByClass = function(classname, tagname, parent){
    //returns an array of elements that match the classname given
    //returns an empty Array() if no elements found
    
    var elements = Array();
    var exp = classname.listToExp();
    
    //get the elements
    var tags = KJD.getTags(tagname, parent);

    for (var i=0; i<tags.length; i++){
        
        if (tags[i].className.match(exp)){
            //add it to the return array
            elements[elements.length] = tags[i];
        }
    }
    
    return elements;
}


KJD.getElementsByAttribute = function (attribute, tagname, parent){
    //returns an array of elements that have the attribute
    //returns an empty Array() if no elements found
    var elements = Array();
    
    //get all the document elements
    var tags = KJD.getTags(tagname, parent);
    
    for (var i=0; i<tags.length; i++){
        var attr = tags[i].getAttribute(attribute);
        if (attr != null){
            elements[elements.length] = tags[i];
        }
    }
    return elements;
}


//style functions
KJD.toggleDisplay = function (id, src_img){
    var ele = KJD.getId(id);
    
    ele.style.display = (ele.style.display != 'none') ? 'none' : 'block' ;
    
    //change the image (if given)
    if (src_img && src_img.src){
        if (ele.style.display != 'none'){
            src_img.src = src_img.src.replace('open','close');
        }
        else {
            src_img.src = src_img.src.replace('close','open');
        }
    }
}


KJD.removeClass = function (id, classnames){
    //removes a list of classes from an element
    var ele = KJD.getId(id); 
    var exp = classnames.listToExp();
    
    ele.className = ele.className.replace(exp,'');
}

KJD.addClass = function (id, classname){
    //adds a className to an element if that name doesn't already exist
    var ele = KJD.getId(id); 
    var exp = classname.listToExp();
    
    if (!ele.className.match(exp)){
        ele.className = (ele.className +' '+ classname).trim();
    }
}
KJD.hasClass = function(id, class_name){
    //returns true if object has class
    var ele = KJD.getId(id);
    
    class_name = class_name.toLowerCase();
    
    if (KJD.undef(ele.className)){return false;}
    
    var classes = ele.className.split(/\s+/);
    
    for (var i=0; i<classes.length; i++){
        if (classes[i].toLowerCase() == class_name){
            return true;
        }
    }
    return false;
}

KJD.replaceClass = function (id, find, replace){
    //replaces a comma separaed list of classnames

    var ele = KJD.getId(id);
    
    //remove the class(es) (if they exists)
    KJD.removeClass(ele, find);
    
    //only add the new class if it doesn't already exist
    KJD.addClass(ele, replace);
}

//returns position relative to the document
KJD.objX = function (obj){
    var ele = KJD.getId(obj);
    if (!ele.offsetParent){
        return ele.offsetLeft;
    }
    else{
        return ele.offsetLeft + KJD.objX(ele.offsetParent);
    }
}

KJD.objY = function (obj){
    var ele = KJD.getId(obj); 
    if (!ele.offsetParent){
        return ele.offsetTop;
    }
    else{
        return ele.offsetTop + KJD.objY(ele.offsetParent);
    }
}


KJD.getParent = function (id, valid_tag_list, search_this_element){
    //loop through parent until it finds a parent tag of type parent_tag
    //parent tag can now be a comma separated list of tags (eg td,th,table)
    
    var NODE_TYPE_ELEMENT = 1;
    var ele = KJD.getId(id);
    if (!valid_tag_list){valid_tag_list = '*'};
    var exp = valid_tag_list.listToExp(); //new RegExp('\\b('+ valid_tag_list.toLowerCase().replace(',','|') +')\\b','i');
    
    if (!search_this_element){
        ele = ele.parentNode;
    }
    
    if ((!ele) || (ele.nodeType != NODE_TYPE_ELEMENT)){
        throw Error('Element has no parent node of type ['+valid_tag_list+']');
        return null;
    }
    else if (ele.tagName.match(exp)){
        //element found
        return ele;
    }
    else {
        //try the parent
        return KJD.getParent(ele.parentNode, valid_tag_list, true);
    }
}

KJD.getParentByAttribute = function(id, attribute, search_this_element){
    //returns the first object found with said attribute
    var NODE_TYPE_ELEMENT = 1;
    var ele = KJD.getId(id); 
        
    if (!search_this_element){
        ele = ele.parentNode;
    }

    if ((!ele) || (ele.nodeType != NODE_TYPE_ELEMENT)){
        return null;
    }
    else if (ele.getAttribute(attribute)){
        //element found
        return ele;
    }
    else {
        //try the parent
        return KJD.getParentByAttribute(ele.parentNode, attribute, true);
    } 
}
KJD.getParentByClass = function(id, classname){
    var ele = KJD.getId(id);

    if (KJD.hasClass(ele,classname)){
        return ele;
    }
    else if (ele.parentNode){
        return KJD.getParentByClass(ele.parentNode, classname);
    }
    else {
        return null;
    }
}

KJD.removeEvent = function(obj, event_name, func){
    //MZ
    if (obj.removeEventListener){
        //
        return obj.removeEventListener(event_name, func, false);
    }
    //IE
    else if (obj.detachEvent) {
        obj.detachEvent('on'+ event_name, func);
        return true; //?
    }
    else {
        throw Error("Unable to removeEvent()");
        return false;
    }
}
KJD.addEvent = function (obj, event_name, func) {
    //moz
    if (obj.addEventListener){
        obj.addEventListener(event_name, func, true);
        return true;
    }
    //ie 
    else if (obj.attachEvent){
        
        var existing_event = obj['on'+ event_name];
        
        
        //we need to create a new function that contains the event
        var event_handler = function(){
            //convert the IE event to be moz compatable
            
            //find the event object
            var e = window.event;
            
            //event occured in a frame
            //try and find the parent window and get the event from there
            /*
            if (!e && top.frames){
                //check any frames
                for (var i=0; i<top.frames.length; i++){
                    //if we try to access an event in a frame from a different domain it will throw a security error 
                    try{
                        if (top.frames[i].event != null){
                            e = top.frames[i].event;
                            break;
                        }
                    }
                    catch(e){}
                }
                
            }
            */
            if (!e && window.frames){
                //check any frames
                for (var i=0; i<window.frames.length; i++){
                    //if we try to access an event in a frame from a different domain it will throw a security error 
                    try{
                        if (window.frames[i].event != null){
                            e = window.frames[i].event;
                            break;
                        }
                    }
                    catch(e){}
                }
            }
            
            if (!e){
                throw Error('Unable to find event['+ obj +','+ event_name +','+ func +']');
                return;
            }
            
            
            //event source
            if (!e.target && e.srcElement){
                e.target = e.srcElement;
            }
            
            //event bubbling
            e.stopPropagation = function(){
                e.cancelBubble = true;
            }
            
            //prevent default action (eg form submittal when an <input type="submit"> is clicked)
            e.preventDefault = function(){
                e.returnValue = false;
            }
            
            e.which = e.button;
            //now fudge it
            if (e.button == 2){e.which = 3;}
            if (e.button == 4){e.which = 2;}
            
            if (existing_event){
                existing_event(e);
            }
            
            func(e);
        }
        //KLUDGE:      
        //events cannot be added to an iframes document with addEvent we need to add it explicitly
        //NOTE: this will remove any handler that aready exists for the iframes document.
        //FIXME: keep document events        
        
        //test to see if the event was added
        //iframe events in IE5 ...
        if (obj.parentWindow && (obj.parentWindow != top)){
            
            obj['on'+ event_name] = event_handler;
            
            return true; //?
        }
        else {
            return obj.attachEvent("on"+ event_name, event_handler);
        }
        /*
        FIXME 
        if (KJD.isdef(obj.title) && (obj != document)){
            
        }
        else {
            if (event_name == 'mouseover'){
                debug(event_name);
            }
            return obj.attachEvent("on"+ event_name, event_handler);
        }
        */
    }
    //unknown
    else {
        throw Error("Unable to addEvent()");
        return false;
    }
}

KJD.Event = Object;
KJD.Event.convert = function(e){
    //converts an ie event object into a moz compatible one

    //event source
    if (!e.target && e.srcElement){
        e.target = e.srcElement;
    }
    
    //event bubbling
    e.stopPropagation = function(){
        e.cancelBubble = true;
    }
    
    //prevent default action (eg form submittal when an <input type="submit"> is clicked)
    e.preventDefault = function(){
        e.returnValue = false;
    }
    return e;
}
KJD.Event.target = function(e, valid_tag_list){
    //returns the element the triggered the event
    var ele;
    if (!e){return null;}
    
    //have we been passed an element instead?
    if (e.nodeType){
        return e;
    }
    else if (e.target){
        return KJD.getParent(e.target, valid_tag_list, true);
    }
    else if (e.srcElement){
        return KJD.getParent(e.srcElement, valid_tag_list, true);
    }
    else {
        return null;
    }
}
KJD.writeStyle = function(style){
    //writes a <style> element to the document.
    //usually called in the <head> section when the script is first loaded
    document.write('<style type="text/css" >'+ style +'</style>');
}
KJD.uniqueId = function(prefix){
    var id = '';
    var i = 0;
    do {
        id = prefix +'_'+ i;
        i++;
    } while (document.getElementById(id));
    return id;
}


KJD.getQuery = function(key,default_value){
    //returns a value from the query string
    default_value = (default_value) ? default_value : '';

    var exp = new RegExp('\\b'+ key +'=([^&]*)','i');
    var loc = window.location.toString();
    var match = loc.match(exp);
    
    return (match) ? match[1] : default_value;
}

KJD.loadCSS = function(src){
    //loads an external style sheet by writing directly to the document
    //should only be called in the <head> of a document
    document.write('<link rel="stylesheet" type="text/css" href="'+ src +'" />');
}

KJD.importCSS = function(src, doc){
	//imports a style sheet (to be used if the document is already loaded);
	if (!doc){doc = document;}
        
	var link = doc.createElement('link');
	link.rel = 'stylesheet';
	link.href = src;
	link.type = 'text/css';
        
        var head = doc.getElementsByTagName('head')[0];
        //doc.body.appendChild(link);
        head.appendChild(link);        
}
KJD.addScript = function(src){
    //appends a script to the bottom of the page
    var script = document.createElement('script');
    script.src = src;
    document.body.appendChild(script);
}
KJD.winClose = function(delay){
    if (delay && !KJD.closing){
        //set a timer to close the window
        setTimeout(KJD.winClose, delay * 1000);
        return;
    }
    else {
        //close the window now
        window.returnValue = 1;
        window.close();
    }
}
KJD.getStyleSheet = function(doc){
    //verify the document    
    doc = (doc) ? doc : window.document;
    
    if (doc.styleSheets){
        if (doc.styleSheets.length == 0){
            //import a blank style sheet
            KJD.importCSS('');
        }
        return doc.styleSheets[doc.styleSheets.length-1];
    }
    else {
        debug('Unable to find or create a style sheet');
        return null;
    }
};
KJD.addStyle = function(style_name, rule){
    //adds a style to the last style sheet of a document
    var style_sheet = KJD.getStyleSheet();
    
    //IE
    if (!style_sheet)
    if (style_sheet.addRule){
        style_sheet.addRule(style_name, rule);
        return true;
    }
    //MZ
    else if (style_sheet.insertRule && style_sheet.cssRules) {
        rule = style_name + ' {' + rule + ';}';
        style_sheet.insertRule(rule , style_sheet.cssRules.length);
        return true;
    }
    //?
    else {
        return false;
    }
}
KJD.getStyle = function(ele, style, datatype){
    //returns the calculated style for any element
    var obj_style;
    //IE
    if (ele.currentStyle){
        obj_style = ele.currentStyle;
    }
    else if (document.defaultView && document.defaultView.getComputedStyle){
        obj_style = document.defaultView.getComputedStyle(ele,null);
    }
    else if (ele.style){
        obj_style = ele.style;
    }
    else {
        //no style available for this element
        return false;
    }
    //try to find the style
    var value = eval('obj_style.'+ style);
    if (!value){
        return false;
    }
    
    //return the 
    //number
    switch (datatype){  
        case 'int':
            value = parseInt(value,10);
            return (value==NaN) ? 0 : value;
            
        case 'string':
        default:
            return value;
    }
}

KJD.isBrowserSupported = function(){
    //
    var a_func = Array(
            'document.getElementById',
            'document.getElementsByTagName',
            'document.createElement',
            'document.createTextNode',		
            'document.body.innerHTML',
            'document.body.parentNode', 
            'document.body.parentNode.insertBefore',			
            'document.body.appendChild',
            'document.execCommand',
            'document.queryCommadValue',
            'document.className'		
            ); 
    
    for (var i; i<a_func.length; i++){
            if (!eval(a_func[i])){
                    debug('Browser does not support "'+ a_func[i] +'"');
                    return false;
            }
    }

    //now weed out the ones that say they support everything but don't or stuff up when they try
     
    if (navigator.userAgent.toLowerCase().indexOf("opera") != -1){
            //Fatal Opera browser, tries to support but fails badly
            return false;
    }
    if (navigator.product == "Gecko" && navigator.productSub < 20030624){
            return false;
    }
    return true;
} 

KJD.checkAll = function(name, check){
    var boxes = document.getElementsByName(name);
    
    for (var i=0; i<boxes.length; i++){
        boxes[i].checked = check;
    }
}
//-------------end common.js-------------------//
