//script.aculo.us micro framework + additions
var ua = navigator.userAgent;
var webkit = ua.indexOf('AppleWebKit/') > -1;
var moz = ua.indexOf('Gecko') > -1 && !webkit;
var opera = ua.indexOf('Opera') > -1;
var supportsTouch = ('createTouch' in document);

function addEvent( obj, type, fn ) {
  if ( obj.attachEvent ) {
    obj['e'+type+fn] = fn;
    obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
    obj.attachEvent( 'on'+type, obj[type+fn] );
  } else
    obj.addEventListener( type, fn, false );
}
function removeEvent( obj, type, fn ) {
  if ( obj.detachEvent ) {
    obj.detachEvent( 'on'+type, obj[type+fn] );
    obj[type+fn] = null;
  } else
    obj.removeEventListener( type, fn, false );
}
      
function css3(name, isProp) {
    if (webkit) return (isProp ? "webkit" : "-webkit") + name;
    if (moz) return (isProp ? "Moz" : "-moz") + name;
    if (opera) return (isProp ? "O" : "-o") + name;
}

function $E(tag) { return document.createElement(tag); }
function $A(e, attrib, value) { e.setAttribute(attrib, value); }
function $(id){ return document.getElementById(id); }
function hide(e) { e.style["display"] = "none"; }
function show(e) { e.style["display"] = "block"; }
function toggle(e) { e.style["display"] = (e.style["display"] == "none" ? "" : "none"); }

function html(id, html){ $(id).innerHTML = html; }
function css(id, style){ $(id).style.cssText += ';'+style; }

function anim(e, trans, op, dur, tf) {
	e.style[css3("AnimationTimingFunction", true)] = (trans || "ease-in-out");
    e.style[css3("Transition", true)] = css3("-transform") + ", opacity, " + (dur||0.5) + "s";
    e.style[css3("Transform", true)] = trans;
    e.style["opacity"] = (1 || op);
}

//localstorage
function store(key, value) {
    try {
        if (localStorage) localStorage.setItem(key, value);
    } catch(e) {
        if (console && console.log) console.log(e); 
    }
}

function retrieve(key) {
    if (localStorage) return localStorage.getItem(key);
    return null;
}

function remove(key) {
    if (localStorage) localStorage.removeItem(key);
}
    
//Window Dimension Functions
function getWindowHeight() {
	var windowHeight=0;
	if ( typeof( window.innerHeight ) == 'number' ) {
		windowHeight=window.innerHeight;
	}
	else {
		if ( document.documentElement && document.documentElement.clientHeight) {
			windowHeight = document.documentElement.clientHeight;
		}
		else {
			if (document.body&&document.body.clientHeight) {
				windowHeight=document.body.clientHeight;
			}
		}
	}
	
	return windowHeight;
};

function getWindowWidth() {
	var ww = 0;
	if (self.innerWidth)
		ww = self.innerWidth;
	else if (document.documentElement && document.documentElement.clientWidth)
		ww = document.documentElement.clientWidth;
	else if (document.body)
		ww = document.body.clientWidth;
	return ww;
}

function getWindowSize()
{
	return {width:getWindowWidth(),height:getWindowHeight()};
}

if (!window.Element) { window.Element = function() { }; }

//Element Prototypes to handle dimensions and positioning.
Element.prototype.getElementWidth = function() {
    if (typeof this.clip !== "undefined") return this.clip.width;
    else if (this.style.pixelWidth) return this.style.pixelWidth;
    else return this.offsetWidth;
}

Element.prototype.setElementWidth = function(width) {
    if (typeof this.clip !== "undefined") this.clip.width = width;
    else if (this.style.pixelWidth) this.style.pixelWidth = width;
    else this.offsetWidth = width;
}

Element.prototype.getElementHeight = function() {
    if (typeof this.clip !== "undefined") return this.clip.height;
    else if (this.style.pixelHeight) return this.style.pixelHeight;
    else return this.offsetHeight;
}

Element.prototype.setElementHeight = function(height) {
    if (typeof this.clip !== "undefined") this.clip.height = height;
    else if (this.style.pixelWidth) this.style.pixelHeight = height;
    else this.offsetHeight = height;
}

Element.prototype.getElementPos = function(rel) {
	var curleft = curtop = 0;
	
	var obj = this;
	if (obj.offsetParent) {
    	do { curleft += obj.offsetLeft || 0; curtop += obj.offsetTop || 0; } while (obj = obj.offsetParent && obj != rel);
    }
    
	return { left: curleft, top: curtop, right: curleft + this.getElementWidth(), bottom: curtop + this.getElementHeight() };
}

Element.prototype.getInt = function(value) {
    return parseInt(this.getAttribute(value));
}

Element.prototype.getBool = function(value) {
    return this.getAttribute(value) == "true";
}

Element.prototype.setPosition = function(top, left) {
    if (top != null) this.style["top"] = top + "px";
    if (left != null) this.style["left"] = left + "px";
}

Element.prototype.translate = function(xPos, yPos, duration) {
    this.translation = { x: xPos, y: yPos, z: 0 };
    this.doTransform(duration);
}

Element.prototype.rotate = function(axis, rotation, duration) {
    this.rotation = { axis: axis.toUpperCase(), degrees: rotation };
    this.doTransform(duration);
}

Element.prototype.scale = function(xScale, yScale, duration) {
    this.scaling = { x: xScale, y: yScale, z: 0 };
    this.doTransform(duration);
}

Element.prototype.transform = function(xPos, yPos, axis, rotation, xScale, yScale, duration) {
    this.translation = xPos != null && yPos != null ? { x: xPos, y: yPos, z: 0 } : null;
    this.rotation = axis != null && rotation != null ? { axis: axis.toUpperCase(), degrees: rotation } : null;
    this.scaling = xScale != null && yScale != null ? { x: xScale, y: yScale, z: 1 } : null;
    this.doTransform(duration);
}

Element.prototype.moveTo = function(element) {
    this.translation = element.translation;
    this.rotation = element.rotation;
    this.scaling = element.scaling;
    this.doTransform(null);
}
Element.prototype.toggleVisibility = function(type, duration) {
    this.style[css3("TransitionDuration", true)] = duration ? (duration + "ms") : "";
    this.style.visibility = type ? type : (this.style.visibility == "hidden" ? "visible" : "hidden");
}

Element.prototype.toggleDisplay = function() {
    this.style.display = (this.style.display == "none" ? "" : "none");
}

Element.prototype.clearTransform = function() {
    this.translation = null;
    this.rotation = null;
    this.style[css3("Transform", true)] = "";
    this.style[css3("TransitionDuration", true)] = "";
}

Element.prototype.doTransform = function(duration) {
    
    var transform = "";
    this.style[css3("TransitionDuration", true)] = duration ? (duration + "ms") : "";
    
    if (this.scaling) transform = "scale3d(" + this.scaling.x + "," + this.scaling.y + "," + this.scaling.z +") ";
    if (this.translation) transform += "translate3d(" + this.translation.x + "px," + this.translation.y + "px," + this.translation.z +"px) ";
    if (this.rotation) transform += "perspective(2500) rotate" + this.rotation.axis + "(" + this.rotation.degrees + "deg)";
    
    if (transform != "") this.style[css3("Transform", true)] = transform;
}

//single finger scroll based on http://chris-barr.com/index.php/entry/scrolling_a_overflowauto_element_on_a_touch_screen_device/
function touchScroll(el, scroll, options){
	
	this.moveTo = function(childElement) {
	    var parent = childElement.parentNode;
	    
	    while (parent.parentNode != scroll && parent != childElement.ownerDocument) { parent = parent.parentNode }
	        
	    if (parent == childElement.ownerDocument) return;
	    var pos = childElement.getElementPos(scroll);
	    if (supportsTouch) {
	        
	        var elDim = { w: el.getElementWidth(), h: el.getElementHeight() };
	        var scrollDim = { w: scroll.getElementWidth(), h: scroll.getElementHeight() };
	       
	        x = (-pos.left + scrollDim.w < elDim.w) ? elDim.w - scrollDim.w : (-pos.left > 0 ? 0 : -pos.left);
            y = (pos.top + scrollDim.h > elDim.h) ? elDim.h - scrollDim.h : (pos.top < 0 ? 0 : pos.top);
            
	        scroll.translate(x, y);
	    } else {
	        scroll.parentNode.scrollLeft = pos.left;
	        scroll.parentNode.scrollTop = pos.top;
	    }
	}
	
    if (supportsTouch) { 
	
	    var lastPos = null;
	
	    scroll.translate(0,0);
	
        addEvent(el, "touchstart", function(e) { 
            lastPos = { x: e.touches[0].clientX, y: e.touches[0].clientY  }; 
        });
        
        addEvent(el, "touchend", function(e) { 
            el.moving = false;
        });
        
        addEvent(el, "touchmove", function(e) { 
            el.moving = true;
            var x = options.h ? scroll.translation.x + (e.touches[0].clientX - lastPos.x) : 0;
            var y = options.v ? scroll.translation.y + (e.touches[0].clientY - lastPos.y) : 0;
            
            var elDim = { w: el.getElementWidth(), h: el.getElementHeight() };
	        var scrollDim = { w: scroll.getElementWidth(), h: scroll.getElementHeight() };
	       
            x = (x + scrollDim.w < elDim.w) ? elDim.w - scrollDim.w : (x > 0 ? 0 : x);
            y = (y + scrollDim.h > elDim.h) ? elDim.h - scrollDim.h : (y < 0 ? 0 : y);
            
            scroll.translate(x, y); //el.translation.y + (startPos.y - e.touches[0].clientY));
            lastPos = { x: e.touches[0].clientX, y: e.touches[0].clientY  }; 
        });
	}
}

//SmartInterface
//Handles Mouse and Touch Events
//double tap timer based on http://www.chipchapin.com/WebTools/JavaScript/example3-01.html 
function SmartInterface(e, options) {

    var position      = null;
    var element       = e;
    var scrollPos     = { x: 0, y: 0 };
    
    var touchStart    = 0;
    var touchEnd      = 0;
    
    var clickStart    = 0;
    var dblclickStart = 0;
    var delay         = 100;
    var dblclickTime  = 300;

    var clickTimeout  = null;

    var fireEvent = function(name, reset) {
        
//        console.log(name); 
        var e = document.createEvent("Events"); 
        e.initEvent(name, true, true); 
        
        if (position) {
            if (element.multitouch) {
                e.pinchBox = position.pinchBox;
                e.lastBox = position.lastBox;
            } else {
                e.clientX = position.x1;
                e.clientY = position.y1;
            }
            e.target = element;
        }
        
        element.dispatchEvent(e); 
        
        if (reset) {
            element.held    = false; 
            element.moving  = false; 
            element.multitouch = false;
            scrollPos       = { x: 0, y: 0 };
            clickTimeout    = null; 
            clickStart      = 0; 
            dblclickStart   = 0; 
            position        = null;
            touchStart      = 0;
            touchEnd        = 0;
        }
    }
    
    var touchPoint = function(e) {
        return { x: (e.touches ? e.touches[0].clientX : e.pageX), y : (e.touches ? e.touches[0].clientY : e.pageY) }
    }
    
    var handleTouchStart = function(e) {
        
        e.preventDefault();
        
        if (e.touches.length > 1) {
    
            if (e.touches.length > 2) return; //ignore multiple fingers
            
            element.multitouch = true;
            
            var tp1 = { x: e.touches[0].clientX, y: e.touches[0].clientY };
            var tp2 = { x: e.touches[1].clientX, y: e.touches[1].clientY };
                
            position = { 
                pinchBox : { 
                    top: (tp1.y > tp2.y ? tp2.y : tp1.y),
                    left: (tp1.x > tp2.x ? tp2.x : tp1.x),
                    height: Math.abs(tp1.y - tp2.y),
                    width: Math.abs(tp1.x - tp2.x)
                },
                lastBox : null
            };
            fireEvent("startpinch");
        }
        else {
        
            touchStart = (new Date()).getTime();
            handlePointerDown(e);
        }
    }
    
    var handlePointerDown = function(e) {

        e.preventDefault();
        
        element.held = true;
        element.moving = false;
        var tp = touchPoint(e);
        position = { x1: tp.x, y1: tp.y };

    }
    
    var handleTouchEnd = function(e) {
        
        e.preventDefault();
        
        if (!element.multitouch && options.dblClick && (touchStart - touchEnd < dblclickTime)) { handleDoubleClick(e); return; }
        
        touchEnd = (new Date()).getTime();
        if (!element.moving && !element.multitouch) { handleClick(e); return; }
        
        if (element.multitouch && e.touches.length == 0) {
            fireEvent("endpinch", true);
            return;
        }
        
        handlePointerUp(e);
    }
    
    var handlePointerUp = function(e) {
        
        e.preventDefault();       
        
        element.held = false;
        
        if (element.moving) fireEvent("enddrag", true);
    }
    
    var handleMove = function(e) {
        
        e.preventDefault();     
        
        if (!element.held) return;
        
        if (element.multitouch) { 
            
            element.moving = false;
            var lastBox = position.pinchBox;
            var lastArea = position.pinchBox.width * position.pinchBox.height;
            
            var tp1 = { x: e.touches[0].clientX, y: e.touches[0].clientY };
            var tp2 = { x: e.touches[1].clientX, y: e.touches[1].clientY };
                
            var pinchBox = { 
                top: (tp1.y > tp2.y ? tp2.y : tp1.y),
                left: (tp1.x > tp2.x ? tp2.x : tp1.x),
                height: Math.abs(tp1.y - tp2.y),
                width: Math.abs(tp1.x - tp2.x)
            }
            
            var newArea = pinchBox.width * position.pinchBox.height;
            if (Math.abs(newArea - lastArea) < 25) return;
            
            position = { pinchBox : pinchBox, lastBox : lastBox };
            fireEvent("pinching");
            return;
        }
        
        var tp = touchPoint(e);
        if (Math.abs(position.x1 - tp.x) < 5 && Math.abs(position.y1 - tp.y) < 5) { return; }
        
        position = { x1: tp.x, y1: tp.y };
        
        if (!element.moving) { fireEvent("startdrag"); }

        element.moving = true; 
        fireEvent("dragging");
    }
    
    var handleClick = function(e) {

        e.preventDefault();    
        
        if (element.held) {
            element.held = false;
        }
            
        if (!options.dblClick) {
            fireEvent("tapped", true);
            return;
        }
        
        clickStart = (new Date()).getTime();
            
        if (clickStart - dblclickStart < delay) return; //ignore
            
        dblclickStart = 0;
            
        if (clickTimeout != null) {
            clearTimeout( clickTimeout );
        }

        clickTimeout = setTimeout(function() { fireEvent("tapped", true); }, dblclickTime);
    }
    
    var handleDoubleClick = function(e) { 
        
        e.preventDefault();        
        dblclickStart = (new Date()).getTime();
            
        if (clickTimeout != null) {
            clearTimeout( clickTimeout );
            clickTimeout = null;
        }
            
        if (options.dblClick) { fireEvent("doubletapped", true); }
    }
    
    if (!supportsTouch) {
        addEvent(element, "click", handleClick);
        addEvent(element, "dblclick", handleDoubleClick);
        
        addEvent(element, "mousedown", handlePointerDown);
        addEvent(document.body, "mouseup", handlePointerUp);
        addEvent(document.body, "mousemove", handleMove);
    } else {
        
        addEvent(element, "touchstart", handleTouchStart);
        addEvent(document.body, "touchmove", handleMove);
        addEvent(element, "touchend", handleTouchEnd);
    }
}

//Css Style Creator
//modified version of http://webdevel.blogspot.com/2006/06/create-css-class-javascript.html
//using information found at: http://www.quirksmode.org/dom/w3c_css.html
function AddCssSelector(selector, style)
{
    var GetStyleSheet = function()
    {
        for(i = 0; i<document.styleSheets.length; i++)
        {
            if(document.styleSheets[i].disabled) continue;
            var media = document.styleSheets[i].media;
            if (typeof media == "object") media = media.mediaText;
            
            if (media == "" || media.indexOf("screen") != -1)
            {
                return document.styleSheets[i];
            }
        }
        
        return null;
    }
    
    var CreateSelector = function(stylesheet, selector, style)
    {
        var mediaType = typeof stylesheet.media;
        
        // IE
        if(mediaType == "string")
        {
            for(i = 0;i<stylesheet.rules.length;i++)
            {
                // if there is an existing rule set up, replace it
                if(stylesheet.rules[i].selectorText.toLowerCase() == selector.toLowerCase())
                {
                    stylesheet.rules[i].style.cssText = style;
                    return;
                }
            }
            // or add a new rule
            stylesheet.addRule(selector,style);
        }
        else if(mediaType == "object")
        {
            for(i = 0;i<stylesheet.cssRules.length;i++)
            {
                // if there is an existing rule set up, replace it
                if(stylesheet.cssRules[i].selectorText.toLowerCase() == selector.toLowerCase())
                {
                    stylesheet.cssRules[i].style.cssText = style;
                    return true;
                }
            }
            // or insert new rule
            stylesheet.insertRule(selector + "{" + style + "}", stylesheet.cssRules.length);
        }
    }
    
    // doesn't work in older versions of Opera (< 9) due to lack of styleSheets support
    if(!document.styleSheets) return;
    if(document.getElementsByTagName("head").length == 0) return;
    
    if(document.styleSheets.length == 0)
    {
        var styleSheetElement = document.createElement("style");
        styleSheetElement.type = "text/css";
        
        // add to <head>
        document.getElementsByTagName("head")[0].appendChild(styleSheetElement);
    }
    
    var stylesheet = GetStyleSheet();
    if (!stylesheet) {
        stylesheet = document.createElement("style");
        styleshee.type = "text/css";
        
        // add to <head>
        document.getElementsByTagName("head")[0].appendChild(stylesheet);    
    }
    
    CreateSelector(stylesheet, selector, style);
}
