/***********************************
*                                  *
* Javascript Library               *
* Copyright © 2008 getPraised GmbH *
*                                  *
***********************************/


(function($) {
	$.fn.extend({
		highlightErrors : function (err) {
			return this.each(function() {
				var f=this;
				$.map(['invalid','missing'],function(x) {
					var list=err[x]; 
					var cssClass=x;
					if (list.length>0) {
						var expr=$.map(list,function(x) { return ':input[name="'+x+'"]' }).join(', ');
						var ids=[];
						$(expr,f).addClass(cssClass).each(function() { if (this.id) ids.push(this.id) });
						$(expr,f).parents('fieldset.collapsed').removeClass('collapsed');
						if (ids.length>0) {
							expr=$.map(ids,function(x) { return 'label[for="'+x+'"]' }).join(', ');
							$(expr,f).addClass(cssClass);
						}
					}
				});
			});
		}
	});
})(jQuery);




$(function() {
	
	$('body').addClass('javascript-enabled');

	
	var i=$('input.set-focus-if-empty[value=""], textarea.set-focus-if-empty:empty');
	if (i.length==0) {
		i=$('input.set-focus, textarea.set-focus, button.set-focus');
	}
	if (i.length>0) {
		i[0].focus();
	}
	$('input.set-select[value!=""], textarea.set-select:not(:empty)').each(function() { this.select() });

	
	$('input.url-input').after('<input type="button" value="Test" class="url-input-test>');
	$('input.url-input-test').click(function() {
		var v=$(this).prev('input.url-input').val();
		if (v.length==0) {
			alert("Keine URL eingegeben!");
		} else if (/^(ftp|http|https):\/\//i.test(v)) {
			window.open(v,'_blank');
		} else {
			alert('Ungültige URL: "'+v+'".\n"http://" vergessen?');
		}
	});

	$.datepicker.setDefaults({
		changeFirstDay:false,
		showOtherMonths:true,
		showWeeks:true,
		duration:'',
		showOn:'focus',
		yearRange:'1900:2099',
		gotoCurrent:true
	});
	$('input.date-input').datepicker();
	
});

/**
 * iBox version 2
 * For more info & download: http://gamma.ibegin.com/ibox/
 * Created as a part of the iBegin Gamma Project - http://gamma.ibegin.com/
 * For licensing please see readme.html (MIT Open Source License)
*/

var iBox = function()
{
  var _pub = {
    // label for the close link
    close_label: '[X]',

    // padding around the box
    padding: 100,

    // how fast to fade in the overlay/ibox (this is each step in ms)
    fade_in_speed: 0,

    // our attribute identifier for our iBox elements
    attribute_name: 'rel',
    
    // tags to hide when we show our box
    tags_to_hide: ['select', 'embed', 'object'],

    // default width of the box (when displaying html only)
    // height is calculated automatically
    default_width: 450,

    // browser checks
    is_opera: navigator.userAgent.indexOf('Opera/9') != -1,
    is_ie: navigator.userAgent.indexOf("MSIE ") != -1,
    is_ie6: false /*@cc_on || @_jscript_version < 5.7 @*/,
    is_firefox: navigator.appName == "Netscape" && navigator.userAgent.indexOf("Gecko") != -1 && navigator.userAgent.indexOf("Netscape") == -1,
    is_mac: navigator.userAgent.indexOf('Macintosh') != -1,
    
    encodeUTF8: function(s)
    {
      return unescape(encodeURIComponent(s));
    },

    decodeUTF8: function(s)
    {
      return decodeURIComponent(escape(s));
    },
    
    /**
     * binds arguments to a callback function
     */
    bind: function(fn)
    {
        var args = [];
        for (var n=1; n<arguments.length; n++) args.push(arguments[n]);
        return function(e) { return fn.apply(this, [e].concat(args)); };
    },

    /**
     * Sets the content of the ibox
     * @param {String} content HTML content
     * @param {Object} params
     */
    html: function(content, params)
    {
      if (content === undefined) return els.content;
      if (cancelled) return;
      _pub.clear();
      els.wrapper.style.display = "block";
      els.wrapper.style.visibility = "hidden";
      els.content.style.height = 'auto';

      if (typeof(content) == 'string') els.content.innerHTML = content;
      else els.content.appendChild(content);

      var elemSize = _pub.getElementSize(els.content);
      var pageSize = _pub.getPageSize();

      if (params.can_resize === undefined) params.can_resize = true;
      if (params.fade_in === undefined) params.use_fade = true;

      if (params.width) var width = parseInt(params.width);
      else var width = _pub.default_width;

      if (params.height) var height = parseInt(params.height);
      else var height = elemSize.height;

      els.wrapper.style.width = width + 'px';
      els.wrapper.style.height = height + 'px';

      // if we dont do this twice we get a bug on the first display
      if (!params.height)
      {
        var elemSize = _pub.getElementSize(els.content);
        var height = elemSize.height;
      }
      if (params.can_resize) _pub.resizeObjectToScreen(els.content, width, height, params.constrain);
      else
      {
        els.content.style.width = width + 'px';
        els.content.style.height = height + 'px';
      }

      // now we set the wrapper
      var elemSize = _pub.getElementSize(els.content);
      els.wrapper.style.width = elemSize.width + 'px';
      els.wrapper.style.height = elemSize.height + 'px';

      _pub.reposition();
      
      els.wrapper.style.visibility = "visible";
      _pub.fadeIn(els.wrapper, 10, params.fade_in ? _pub.fade_in_speed : 0);
    },
    
    /**
     * Empties the content of the iBox (also hides the loading indicator)
     */
    clear: function()
    {
      els.progress.style.display = "none";
      while (els.content.firstChild) els.content.removeChild(els.content.firstChild);
    },
    
    /**
     * Loads text into the ibox
     * @param {String} url
     * @param {String} title
     * @param {Object} params
     */
    show: function(text, title, params)
    {
      _pub.hide();
      showInit(url, title, params, function(){
        _pub.html(text, params);
      });
    },
    /**
     * Loads a url into the ibox
     * @param {String} url
     * @param {String} title
     * @param {Object} params
     */
    showURL: function(url, title, params)
    {
      showInit(url, title, params, function(){
        cancelled = false;
        for (var i=0; i<_pub.plugins.list.length; i++)
        {
          var plugin = _pub.plugins.list[i];
          if (plugin.match(url))
          {
            active_plugin = plugin;
            plugin.render(url, params);
            break;
          }
        }
      });
    },

    /**
     * Hides the iBox
     */
    hide: function()
    {
      if (active_plugin)
      {
        // call the plugins unload method
        if (active_plugin.unload) active_plugin.unload();
        active_plugin = null;
      }
      window.onscroll = null;
      _pub.clear();
      // restore elements that were hidden
      for (var i=0; i<_pub.tags_to_hide.length; i++) showTags(_pub.tags_to_hide[i]);

      els.progress.style.display = 'none';
      els.overlay.style.display = 'none';
      els.wrapper.style.display = 'none';
    },

    /**
     * Resizes an object to fit on screen
     * @param {Object} obj
     * @param {Integer} width
     * @param {Integer} height
     * @param {Boolean} constrain
     */
    resizeObjectToScreen: function(obj, width, height, constrain)
    {

      var pagesize = _pub.getPageSize();

      var x = pagesize.width - _pub.padding;
      var y = pagesize.height - _pub.padding;
      
      if (!height) var height = obj.height;
      if (!width) var width = obj.width;
      if (width > x)
      {
        if (constrain) height = height * (x/width);
        width = x;
      }
      if (height > y)
      {
        if (constrain) width = width * (y/height);
        height = y;
      }
      obj.style.width = width + 'px';
      obj.style.height = height + 'px';
    },

    /**
     * Repositions the iBox wrapper (from events)
     */
    reposition: function(e)
    {
      // verify height doesnt overreach browser's viewpane
      _pub.center(els.progress);
      _pub.center(els.wrapper);
      var pageSize = _pub.getPageSize();
      var scrollPos = _pub.getScrollPos();
      
      if (_pub.is_ie6) els.overlay.style.width = document.documentElement.clientWidth + 'px';
      var height = Math.max(document.documentElement.clientHeight, document.body.clientHeight);
      els.overlay.style.height = height + 'px';
    },

    /**
     * Centers an object
     * @param {Object} obj
     */
    center: function(obj)
    {
      var pageSize = _pub.getPageSize();
      var scrollPos = _pub.getScrollPos();
      var emSize = _pub.getElementSize(obj);
      var x = Math.round((pageSize.width - emSize.width) / 2 + scrollPos.scrollX);
      var y = Math.round((pageSize.height - emSize.height) / 2 + scrollPos.scrollY);
      obj.style.left = x + 'px';
      obj.style.top = y + 'px';
    },
    
    getStyle: function(obj, styleProp)
    {
      if (obj.currentStyle)
        return obj.currentStyle[styleProp];
      else if (window.getComputedStyle)
        return document.defaultView.getComputedStyle(obj,null).getPropertyValue(styleProp);
    },

    /**
     * Gets the scroll positions
     */
    getScrollPos: function()
    {
      var docElem = document.documentElement;
      return {
        scrollX: document.body.scrollLeft || window.pageXOffset || (docElem && docElem.scrollLeft),
        scrollY: document.body.scrollTop || window.pageYOffset || (docElem && docElem.scrollTop)
      };
    },

    /**
     * Gets the page constraints
     */
    getPageSize: function()
    {
      return {
        width: window.innerWidth || (document.documentElement && document.documentElement.clientWidth) || document.body.clientWidth,
        height: window.innerHeight || (document.documentElement && document.documentElement.clientHeight) || document.body.clientHeight
      };
    },

    /**
     * Gets an objects offsets
     * @param {Object} obj
     */
    getElementSize: function(obj)
    {
      return {
        width: obj.offsetWidth || obj.style.pixelWidth,
        height: obj.offsetHeight || obj.style.pixelHeight
      };
    },

    fadeIn: function(obj, level, speed, callback)
    {
      if (level === undefined) var level = 100;
      if (speed === undefined) var speed = 70;
      if (!speed)
      {
        _pub.setOpacity(null, obj, level*10);
        if (callback) callback();
        return;
      }
    
      _pub.setOpacity(null, obj, 0);
      for (var i=0; i<=level; i++)
      {
        setTimeout(_pub.bind(_pub.setOpacity, obj, i*10), speed*i);
      }
      if (callback) setTimeout(callback, speed*(i+1));
    },

    /**
     * Sets the opacity of an element
     * @param {Object} obj
     * @param {Integer} value
     */
    setOpacity: function(e, obj, value)
    {
      obj.style.opacity = value/100;
      obj.style.filter = 'alpha(opacity=' + value + ')';
    },
    
    /**
     * Creates a new XMLHttpRequest object based on browser
     */
    createXMLHttpRequest: function()
    {
      var http;
      if (window.XMLHttpRequest)
      { // Mozilla, Safari,...
        http = new XMLHttpRequest();
        if (http.overrideMimeType)
        {
          // set type accordingly to anticipated content type
          http.overrideMimeType('text/html');
        }
      }
      else if (window.ActiveXObject)
      { // IE
        try {
          http = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
          try {
            http = new ActiveXObject("Microsoft.XMLHTTP");
          } catch (e) {}
        }
      }
      if (!http)
      {
        alert('Cannot create XMLHTTP instance');
        return false;
      }
      return http;
    },
    
    addEvent: function(obj, evType, fn)
    {
      if (obj.addEventListener)
      {
        obj.addEventListener(evType, fn, false);
        return true;
      }
      else if (obj.attachEvent)
      {
        var r = obj.attachEvent("on"+evType, fn);
        return r;
      }
      else
      {
        return false;
      }
    },
    
    plugins: {
      list: new Array(),
      register: function(func, last)
      {
        if (!last)
        {
          _pub.plugins.list = _pub.plugins.list.concat([func],_pub.plugins.list);
        }
        else
        {
          _pub.plugins.list.push(func);
        }
      }
    }
  };
  
  // private methods and variables
  var cancelled = false;
  var active_plugin = null;

  // some containers
  // we store these in memory instead of finding them each time
  var els = {
    wrapper: null,
    footer: null,
    content: null,
    overlay: null,
    progress: null
  };
  
  /**
   * Parses the arguments in the rel attribute
   * @param {String} query
   */
  var parseQuery = function(query)
  {
     var params = new Object();
     if (!query) return params; 
     var pairs = query.split(/[;&]/);
     for (var i=0; i<pairs.length; i++)
     {
        var keyval = pairs[i].split('=');
        if (!keyval || keyval.length != 2) continue;
        var key = unescape(keyval[0]);
        var val = unescape(keyval[1]);
        val = val.replace(/\+/g, ' ');
        params[key] = val;
     }
     return params;
  };


  /**
   * Creates the iBox container and appends it to an element
   * @param {Object} elem Container to attach to
   * @return {Object} iBox element
   */
  var create = function(elem)
  {
    // TODO: why isnt this using DOM tools
    // a trick on just creating an ibox wrapper then doing an innerHTML on our root ibox element
    var container = document.createElement('div');
    container.id = 'ibox';
    container.style.display = 'block';

    els.overlay = document.createElement('div');
    els.overlay.style.display = 'none';
    els.overlay.id = 'ibox_overlay';
    els.overlay.onclick = _pub.hide;
    container.appendChild(els.overlay);

    els.progress = document.createElement('div');
    els.progress.id = 'ibox_progress';
    els.progress.style.display = 'none';
    els.progress.onclick = function() {
      _pub.hide();
      cancelled = true;
    }
    container.appendChild(els.progress);

    els.wrapper = document.createElement('div')
    els.wrapper.id = 'ibox_wrapper';
    els.wrapper.style.display = 'none';

    els.content = document.createElement('div');
    els.content.id = 'ibox_content';
    els.wrapper.appendChild(els.content);
  
    var child = document.createElement('div');
    child.id = 'ibox_footer_wrapper';
  
    var child2 = document.createElement('a');
    child2.innerHTML = _pub.close_label;
    child2.href = 'javascript:void(0)';
    child2.onclick = _pub.hide;
    child.appendChild(child2);
  
    els.footer = document.createElement('div');
    els.footer.id = 'ibox_footer';
    els.footer.innerHTML = '&nbsp;';
    child.appendChild(els.footer);
    els.wrapper.appendChild(child);

    container.appendChild(els.wrapper);

    elem.appendChild(container);
    return container;
  };
  
  var hideTags = function(tag)
  {
    var list = document.getElementsByTagName(tag);
    for (var i=0; i<list.length; i++)
    {
      if (_pub.getStyle(list[i], 'visibility') != 'hidden' && list[i].style.display != 'none')
      {
        list[i].style.visibility = 'hidden';
        list[i].wasHidden = true;
      }
    }
  };
  
  var showTags = function(tag)
  {
    var list = document.getElementsByTagName(tag);
    for (var i=0; i<list.length; i++)
    {
      if (list[i].wasHidden)
      {
        list[i].style.visibility = 'visible';
        list[i].wasHidden = null;
      }
    }
  };
  
  var showInit = function(url, title, params, callback)
  {
    els.progress.style.display = "block";
    _pub.center(els.progress);
    
    _pub.reposition();
    if (!_pub.is_firefox) var amount = 8;
    else var amount = 10;
    for (var i=0; i<_pub.tags_to_hide.length; i++) hideTags(_pub.tags_to_hide[i]);

    window.onscroll = _pub.reposition;

    // set title here
    els.footer.innerHTML = title || "&nbsp;";

    els.overlay.style.display = "block";
    
    _pub.fadeIn(els.overlay, amount, _pub.fade_in_speed, callback);
  };

  var initialize = function()
  {
    // elements here start the look up from the start non <a> tags
    var els = document.getElementsByTagName("a");
    var func = function(e)
    {
      var t = this.getAttribute(_pub.attribute_name);
      var params = parseQuery(t.substr(5,999));
      var url = this.target || this.href;
      var title = this.title;
      _pub.showURL(url, title, params);
      //TODO: fix e so its defined?
      //e.preventDefault();
      return false;
    };
    for (var i=0; i<els.length; i++)
    {
      if (els[i].getAttribute(_pub.attribute_name))
      {
        var t = els[i].getAttribute(_pub.attribute_name);
        if ((t.indexOf("ibox") != -1) || t.toLowerCase() == "ibox")
        { // check if this element is an iBox element
          els[i].onclick = func;
        }
      }
    }
    create(document.body);
    _pub.http = _pub.createXMLHttpRequest();
  };

  _pub.addEvent(window, 'keypress', function(e){ if (e.keyCode == (window.event ? 27 : e.DOM_VK_ESCAPE)) { iBox.hide(); }});
  _pub.addEvent(window, 'resize', _pub.reposition);
  _pub.addEvent(window, 'load', initialize);

  // DEFAULT PLUGINS

  /**
   * Handles embedded containers in the page based on url of #container.
   * This _ONLY_ works with hidden containers.
   */
  var iBoxPlugin_Container = function()
  {
    var original_wrapper = null;
    return {
      /**
       * Matches the url and returns true if it fits this plugin.
       */
      match: function(url)
      {
        return url.indexOf('#') != -1;
      },
      /**
       * Called when this plugin is unloaded.
       */
      unload: function()
      {
        var elemSrc = _pub.html().firstChild;
        elemSrc.style.display = 'none';
        original_wrapper.appendChild(elemSrc);
      },
      /**
       * Handles the output
       * @param {iBox} ibox
       * @param {String} url
       * @return {iBoxContent} an instance or subclass of iBoxContent
       */
      render: function(url, params)
      {
        var elemSrcId = url.substr(url.indexOf("#") + 1);
        var elemSrc = document.getElementById(elemSrcId);
        // If the element doesnt exist, break the switch
        if (!elemSrc)
        {
          _pub.html('There was an error loading the document.', params);
        }
        else
        {
          original_wrapper = elemSrc.parentNode;
          elemSrc.style.display = 'block';
          _pub.html(elemSrc, params);
        }
      }
    }
  }();
  _pub.plugins.register(iBoxPlugin_Container, true);

  /**
   * Handles images
   */
  var iBoxPlugin_Image = function()
  {
    return {
      match: function(url)
      {
        return true;
      },

      render: function(url, params)
      {  
        var img = document.createElement('img');
        img.onclick = _pub.hide;
        img.className = 'ibox_image'
        img.style.cursor = 'pointer';
        img.onload = function()
        {
          _pub.html(img, {height: img.height, width: img.width, constrain: true})
        }
        img.onerror = function()
        {
          _pub.html('There was an error loading the document.', params);
        }
        img.src = url;
      }
    }
  }();
  _pub.plugins.register(iBoxPlugin_Image);

  return _pub;
}();
/* end of ibox */
/*----------------------------------------------------------------------------\
|                                 Timer Class                                 |
|-----------------------------------------------------------------------------|
|                         Created by Erik Arvidsson                           |
|                  (http://webfx.eae.net/contact.html#erik)                   |
|                      For WebFX (http://webfx.eae.net/)                      |
|-----------------------------------------------------------------------------|
| Object Oriented Encapsulation  of setTimeout  fires ontimer when the  timer |
| is triggered. Does not work in IE 5.00                                      |
|-----------------------------------------------------------------------------|
|                   Copyright (c) 2002, 2006 Erik Arvidsson                   |
|-----------------------------------------------------------------------------|
| Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| use this file except in compliance with the License.  You may obtain a copy |
| of the License at http://www.apache.org/licenses/LICENSE-2.0                |
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| Unless  required  by  applicable law or  agreed  to  in  writing,  software |
| distributed under the License is distributed on an  "AS IS" BASIS,  WITHOUT |
| WARRANTIES OR  CONDITIONS OF ANY KIND,  either express or implied.  See the |
| License  for the  specific language  governing permissions  and limitations |
| under the License.                                                          |
|-----------------------------------------------------------------------------|
| 2002-10-14 | Original version released                                      |
| 2006-05-28 | Changed license to Apache Software License 2.0.                |
|-----------------------------------------------------------------------------|
| Created 2002-10-14 | All changes are in the log above. | Updated 2006-05-28 |
\----------------------------------------------------------------------------*/

function Timer(nPauseTime) {
	this._pauseTime = typeof nPauseTime == "undefined" ? 1000 : nPauseTime;	
	this._timer = null;
	this._isStarted = false;
}

Timer.prototype.start = function () {
	if (this.isStarted())
		this.stop();
	var oThis = this;
	this._timer = window.setTimeout(function () {
		if (typeof oThis.ontimer == "function")
			oThis.ontimer();
	}, this._pauseTime);
	this._isStarted = false;
};

Timer.prototype.stop = function () {
	if (this._timer != null)
		window.clearTimeout(this._timer);
	this._isStarted = false;
};

Timer.prototype.isStarted = function () {
	return this._isStarted;
};

Timer.prototype.getPauseTime = function () {
	return this._pauseTime;
};

Timer.prototype.setPauseTime = function (nPauseTime) {
	this._pauseTime = nPauseTime;
};

/*----------------------------------------------------------------------------\
|                                Range Class                                  |
|-----------------------------------------------------------------------------|
|                         Created by Erik Arvidsson                           |
|                  (http://webfx.eae.net/contact.html#erik)                   |
|                      For WebFX (http://webfx.eae.net/)                      |
|-----------------------------------------------------------------------------|
| Used to  model the data  used  when working  with  sliders,  scrollbars and |
| progress bars.  Based  on  the  ideas of  the javax.swing.BoundedRangeModel |
| interface  defined  by  Sun  for  Java;   http://java.sun.com/products/jfc/ |
| swingdoc-api-1.0.3/com/sun/java/swing/BoundedRangeModel.html                |
|-----------------------------------------------------------------------------|
|                Copyright (c) 2002, 2005, 2006 Erik Arvidsson                |
|-----------------------------------------------------------------------------|
| Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| use this file except in compliance with the License.  You may obtain a copy |
| of the License at http://www.apache.org/licenses/LICENSE-2.0                |
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| Unless  required  by  applicable law or  agreed  to  in  writing,  software |
| distributed under the License is distributed on an  "AS IS" BASIS,  WITHOUT |
| WARRANTIES OR  CONDITIONS OF ANY KIND,  either express or implied.  See the |
| License  for the  specific language  governing permissions  and limitations |
| under the License.                                                          |
|-----------------------------------------------------------------------------|
| 2002-10-14 | Original version released                                      |
| 2005-10-27 | Use Math.round instead of Math.floor                           |
| 2006-05-28 | Changed license to Apache Software License 2.0.                |
|-----------------------------------------------------------------------------|
| Created 2002-10-14 | All changes are in the log above. | Updated 2006-05-28 |
\----------------------------------------------------------------------------*/


function Range() {
	this._value=0;
	this._minimum=0;
	this._maximum=100;
	this._extent=0;
	this._precision=0;

	this._isChanging=false;
	this._disabled=false;
}

Range.prototype.fireOnChange=function() {
	if (!this._isChanging && typeof this.onchange == "function") {
		this.onchange();
	}
}

Range.prototype.setPrecision=function(powerOf10) {
	this._precision=powerOf10;
};

Range.prototype.getPrecision=function() {
	return this._precision;
};

Range.prototype.disable = function() {
	if (!this._disabled) {
		this._disabled=true;
		this.fireOnChange();
	}
}

Range.prototype.enable = function() {
	if (this._disabled) {
		this._disabled=false;
		this.fireOnChange();
	}
}

Range.prototype.isDisabled = function() {
	return this._disabled;
}

Range.prototype.isEnabled = function() {
	return !this._disabled;
}

Range.prototype.setValue = function (value) {
	value=parseFloat(value);
	var scale=Math.pow(10,this._precision);
	if (isNaN(value)) {
		if (!this._disabled) {
			this._value=Math.round((this._minimum+this._maximum)*scale/2)/scale;
			this._disabled=true;
			this.fireOnChange();
		}
	} else {
		value=Math.round(value*scale)/scale;
		if (this._value != value || this._disabled) {
			if (value + this._extent > this._maximum) {
				this._value = this._maximum - this._extent;
			} else if (value < this._minimum) {
				this._value = this._minimum;
			} else {
				this._value = value;
			}
			this._disabled=false;
			this.fireOnChange();
		}
	}
	return this._value;
};

Range.prototype.getValue = function() {
	return this._value;
}

Range.prototype.setExtent = function (extent) {
	if (this._extent != extent) {
		if (extent < 0) {
			this._extent = 0;
		} else if (this._value + extent > this._maximum) {
			this._extent = this._maximum - this._value;
		} else {
			this._extent = extent;
		}
		this.fireOnChange();
	}
};

Range.prototype.getExtent = function () {
	return this._extent;
};

Range.prototype.setMinimum = function (minimum) {
	if (this._minimum != minimum) {
		var oldIsChanging = this._isChanging;
		this._isChanging = true;

		this._minimum = minimum;

		if (minimum > this._value) {
			this.setValue(minimum);
		}
		if (minimum > this._maximum) {
			this._extent = 0;
			this.setMaximum(minimum);
			this.setValue(minimum)
		}
		if (minimum + this._extent > this._maximum) {
			this._extent = this._maximum - this._minimum;
		}

		this._isChanging = oldIsChanging;
		this.fireOnChange();
	}
};

Range.prototype.getMinimum = function () {
	return this._minimum;
};

Range.prototype.setMaximum = function (maximum) {
	if (this._maximum != maximum) {
		var oldIsChanging = this._isChanging;
		this._isChanging = true;

		this._maximum = maximum;

		if (maximum < this._value) {
			this.setValue(maximum - this._extent);
		}
		if (maximum < this._minimum) {
			this._extent = 0;
			this.setMinimum(maximum);
			this.setValue(this._maximum);
		}
		if (maximum < this._minimum + this._extent) {
			this._extent = this._maximum - this._minimum;
		}
		if (maximum < this._value + this._extent) {
			this._extent = this._maximum - this._value;
		}
		this._isChanging = oldIsChanging;
		this.fireOnChange();
	}
};

Range.prototype.getMaximum = function () {
	return this._maximum;
};

Range.prototype.getCenter=function () {
	return (this._minimum+this._maximum)/2;
}

Range.prototype.center=function() {
	this.setValue(this.getCenter);
}

/*----------------------------------------------------------------------------\
|                                Slider 1.02                                  |
|-----------------------------------------------------------------------------|
|                         Created by Erik Arvidsson                           |
|                  (http://webfx.eae.net/contact.html#erik)                   |
|                      For WebFX (http://webfx.eae.net/)                      |
|-----------------------------------------------------------------------------|
| A  slider  control that  degrades  to an  input control  for non  supported |
| browsers.                                                                   |
|-----------------------------------------------------------------------------|
|                Copyright (c) 2002, 2003, 2006 Erik Arvidsson                |
|-----------------------------------------------------------------------------|
| Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| use this file except in compliance with the License.  You may obtain a copy |
| of the License at http://www.apache.org/licenses/LICENSE-2.0                |
| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| Unless  required  by  applicable law or  agreed  to  in  writing,  software |
| distributed under the License is distributed on an  "AS IS" BASIS,  WITHOUT |
| WARRANTIES OR  CONDITIONS OF ANY KIND,  either express or implied.  See the |
| License  for the  specific language  governing permissions  and limitations |
| under the License.                                                          |
|-----------------------------------------------------------------------------|
| Dependencies: timer.js - an OO abstraction of timers                        |
|               range.js - provides the data model for the slider             |
|               winclassic.css or any other css file describing the look      |
|-----------------------------------------------------------------------------|
| 2002-10-14 | Original version released                                      |
| 2003-03-27 | Added a test in the constructor for missing oElement arg       |
| 2003-11-27 | Only use mousewheel when focused                               |
| 2006-05-28 | Changed license to Apache Software License 2.0.                |
|-----------------------------------------------------------------------------|
| Created 2002-10-14 | All changes are in the log above. | Updated 2006-05-28 |
\----------------------------------------------------------------------------*/

Slider.isSupported = typeof document.createElement != "undefined" &&
	typeof document.documentElement != "undefined" &&
	typeof document.documentElement.offsetWidth == "number";


function Slider(oElement, oInput, isVertical) {
	if (!oElement) return;
	this._vertical = isVertical || false;
	this._range = new Range();
	this._range.setExtent(0);
	this._blockIncrement = 10;
	this._unitIncrement = 1;
	this._timer = new Timer(100);

	if (Slider.isSupported) {
		this.document = oElement.ownerDocument || oElement.document;

		this.element = oElement;
		this.element.slider = this;
		this.element.unselectable = "on";

		// add class name tag to class name
		this.element.className = (this.isVertical() ? "vertical" : "horizontal") + " " + this.classNameTag + " " + this.element.className;

		// create line
		this.line = this.document.createElement("DIV");
		this.line.className = "line";
		this.line.unselectable = "on";
		this.line.appendChild(this.document.createElement("DIV"));
		this.element.appendChild(this.line);

		// create handle
		this.handle = this.document.createElement("DIV");
		this.handle.className = "handle";
		this.handle.unselectable = "on";
		this.handle.appendChild(this.document.createElement("DIV"));
		this.handle.firstChild.appendChild(this.document.createTextNode('-'));
		this.element.appendChild(this.handle);
	}

	this.input = oInput;

	// events
	var oThis = this;
	this._range.onchange = function () {
		oThis.recalculate();
		if (typeof oThis.onchange == "function") {
			oThis.onchange();
		}
	};

	if (Slider.isSupported) {
		this.element.onfocus		= Slider.eventHandlers.onfocus;
		this.element.onblur			= Slider.eventHandlers.onblur;
		this.element.onmousedown	= Slider.eventHandlers.onmousedown;
		this.element.onmouseover	= Slider.eventHandlers.onmouseover;
		this.element.onmouseout		= Slider.eventHandlers.onmouseout;
		this.element.onkeydown		= Slider.eventHandlers.onkeydown;
		this.element.onkeypress		= Slider.eventHandlers.onkeypress;
		this.element.onmousewheel	= Slider.eventHandlers.onmousewheel;
		this.handle.onselectstart=this.element.onselectstart=function () { return false; };

		this._timer.ontimer = function () { oThis.ontimer(); };

		// extra recalculate for ie
		window.setTimeout(function() { oThis.recalculate(); }, 1);
	} else {
		this.input.onchange = function (e) {
			oThis.setValue(oThis.input.value);			
		};
	}
}

Slider.eventHandlers = {

	// helpers to make events a bit easier
	getEvent:	function (e, el) {
		if (!e) {
			if (el)
				e = el.document.parentWindow.event;
			else
				e = window.event;
		}
		if (!e.srcElement) {
			var el = e.target;
			while (el != null && el.nodeType != 1)
				el = el.parentNode;
			e.srcElement = el;
		}
		if (typeof e.offsetX == "undefined") {
			e.offsetX = e.layerX;
			e.offsetY = e.layerY;
		}

		return e;
	},

	getDocument:	function (e) {
		if (e.target)
			return e.target.ownerDocument;
		return e.srcElement.document;
	},

	getSlider:	function (e) {
		var el = e.target || e.srcElement;
		while (el != null && el.slider == null)	{
			el = el.parentNode;
		}
		if (el)
			return el.slider;
		return null;
	},

	getLine:	function (e) {
		var el = e.target || e.srcElement;
		while (el != null && el.className != "line")	{
			el = el.parentNode;
		}
		return el;
	},

	getHandle:	function (e) {
		var el = e.target || e.srcElement;
		var re = /handle/;
		while (el != null && !re.test(el.className))	{
			el = el.parentNode;
		}
		return el;
	},
	// end helpers

	onfocus:	function (e) {
		var s = this.slider;
		s._focused = true;
		//s.handle.className = "handle hover";		
	},

	onblur:	function (e) {
		var s = this.slider
		s._focused = false;
		//s.handle.className = "handle";		
	},

	onmouseover:	function (e) {
		e = Slider.eventHandlers.getEvent(e, this);
		var s = this.slider;
		if (e.srcElement == s.handle){
			/*s.handle.className = "handle hover";*/
		}
	},

	onmouseout:	function (e) {
		e = Slider.eventHandlers.getEvent(e, this);
		var s = this.slider;
		if (e.srcElement == s.handle && !s._focused){			
			//s.handle.className = "handle";
		}
	},

	onmousedown:	function (e) {
		e = Slider.eventHandlers.getEvent(e, this);
		var s = this.slider;
/*
		if (!s.activated){
			s.activated = true;
			s.handle.className = "handle active";			
			// set default value
			s.input.value=5;
			s.handle.firstChild.innerHTML=s.getValue();						
			update_group_score(active_rating_group);
			update_gp_score();
			s.setValue(5);
		}
*/
		s.enable();

		if (s.element.focus) {
			s.element.focus();
		}

		Slider._currentInstance = s;
		var doc = s.document;

		if (doc.addEventListener) {
			doc.addEventListener("mousemove", Slider.eventHandlers.onmousemove, true);
			doc.addEventListener("mouseup", Slider.eventHandlers.onmouseup, true);
		} else if (doc.attachEvent) {
			doc.attachEvent("onmousemove", Slider.eventHandlers.onmousemove);
			doc.attachEvent("onmouseup", Slider.eventHandlers.onmouseup);
			doc.attachEvent("onlosecapture", Slider.eventHandlers.onmouseup);
			s.element.setCapture();
		}

		if (Slider.eventHandlers.getHandle(e)) {	// start drag
			Slider._sliderDragData = {
				screenX:	e.screenX,
				screenY:	e.screenY,
				dx:			e.screenX - s.handle.offsetLeft,
				dy:			e.screenY - s.handle.offsetTop,
				startValue:	s.getValue(),
				slider:		s
			};
		} else {
			var lineEl = Slider.eventHandlers.getLine(e);
			s._mouseX = e.offsetX + (lineEl ? s.line.offsetLeft : 0);			
			s._mouseY = e.offsetY + (lineEl ? s.line.offsetTop : 0);
			s._increasing = null;
			
			// start timer to move to position
			/*s.ontimer();*/
			
			// new: move direct to clicked position											
			if (s.isHorizontal()) {	
				boundSize = s.getMaximum() - s.getMinimum();				
				var w = s.element.offsetWidth;				
				var hw = s.handle.offsetWidth;								
				var scale = (w-hw)/boundSize;				
				var new_val = s._mouseX/scale;				
				s.setValue(Math.round(new_val));
			} 
		}
	},

	onmousemove: function (e) {
		e = Slider.eventHandlers.getEvent(e, this);

		if (Slider._sliderDragData) {	// drag
			var s = Slider._sliderDragData.slider;

			var boundSize = s.getMaximum() - s.getMinimum();
			var size, pos, reset;

			if (s.isHorizontal()) {
				size = s.element.offsetWidth - s.handle.offsetWidth;
				pos = e.screenX - Slider._sliderDragData.dx;
				reset = Math.abs(e.screenY - Slider._sliderDragData.screenY) > 100;
			} else {
				size = s.element.offsetHeight - s.handle.offsetHeight;
				pos = s.element.offsetHeight - s.handle.offsetHeight -
					(e.screenY - Slider._sliderDragData.dy);
				reset = Math.abs(e.screenX - Slider._sliderDragData.screenX) > 100;
			}
			s.setValue(reset ? Slider._sliderDragData.startValue : s.getMinimum() + boundSize * pos / size);
			return false;
		} else {
			var s = Slider._currentInstance;
			if (s != null) {
				var lineEl = Slider.eventHandlers.getLine(e);
				s._mouseX = e.offsetX + (lineEl ? s.line.offsetLeft : 0);
				s._mouseY = e.offsetY + (lineEl ? s.line.offsetTop : 0);
			}
		}

	},

	onmouseup: function (e) {
		e = Slider.eventHandlers.getEvent(e, this);
		var s = Slider._currentInstance;
		var doc = s.document;
		if (doc.removeEventListener) {
			doc.removeEventListener("mousemove", Slider.eventHandlers.onmousemove, true);
			doc.removeEventListener("mouseup", Slider.eventHandlers.onmouseup, true);
		}
		else if (doc.detachEvent) {
			doc.detachEvent("onmousemove", Slider.eventHandlers.onmousemove);
			doc.detachEvent("onmouseup", Slider.eventHandlers.onmouseup);
			doc.detachEvent("onlosecapture", Slider.eventHandlers.onmouseup);
			s.element.releaseCapture();
		}

		if (Slider._sliderDragData) {	// end drag
			Slider._sliderDragData = null;
		}
		else {
			/* original: timer stops if mouseup,*/
			/* but we want it to go to the mouseup position*/
			s._timer.stop();
			s._increasing = null;						
			
		}
		Slider._currentInstance = null;
	},

	onkeydown:	function (e) {
		e = Slider.eventHandlers.getEvent(e, this);
		//var s = Slider.eventHandlers.getSlider(e);
		var s = this.slider;
		var kc = e.keyCode;
		switch (kc) {
			case 33:	// page up
				s.setValue(s.getValue() + s.getBlockIncrement());
				break;
			case 34:	// page down
				s.setValue(s.getValue() - s.getBlockIncrement());
				break;
			case 35:	// end
				s.setValue(s.isHorizontal() ? s.getMaximum() : s.getMinimum());
				break;
			case 36:	// home
				s.setValue(s.isHorizontal() ? s.getMinimum() : s.getMaximum());
				break;
			case 38:	// up
			case 39:	// right
				s.setValue(s.getValue() + s.getUnitIncrement());
				break;

			case 37:	// left
			case 40:	// down
				s.setValue(s.getValue() - s.getUnitIncrement());
				break;
		}

		if (kc >= 33 && kc <= 40) {
			return false;
		}
	},

	onkeypress:	function (e) {
		e = Slider.eventHandlers.getEvent(e, this);
		var kc = e.keyCode;
		if (kc >= 33 && kc <= 40) {
			return false;
		}
	},

	onmousewheel:	function (e) {
		e = Slider.eventHandlers.getEvent(e, this);
		var s = this.slider;
		if (s._focused) {
			s.setValue(s.getValue() + e.wheelDelta / 120 * s.getUnitIncrement());
			// windows inverts this on horizontal sliders. That does not
			// make sense to me
			return false;
		}
	}
};



Slider.prototype.classNameTag = "dynamic-slider-control",

Slider.prototype.enable = function()
{
	this._range.enable();
	this.input.value=this.getValue();
}

Slider.prototype.disable = function()
{
	this._range.center();
	this._range.disable();
	this.input.value='';
}

Slider.prototype.isDisabled = function()
{
	return this._range.isDisabled();
}

Slider.prototype.isEnabled = function()
{
	return this._range.isEnabled();
}

Slider.prototype.setValue = function (v) {		
	this._range.setValue(v);
	this.input.value=this.isEnabled() ? this.getValue() : '';
};

Slider.prototype.getValue = function () {
	return this._range.getValue();
};

Slider.prototype.setMinimum = function (v) {
	this._range.setMinimum(v);
	this.input.value = this.getValue();
};

Slider.prototype.getMinimum = function () {
	return this._range.getMinimum();
};

Slider.prototype.setMaximum = function (v) {
	this._range.setMaximum(v);
	this.input.value = this.getValue();
};

Slider.prototype.getMaximum = function () {
	return this._range.getMaximum();
};

Slider.prototype.setUnitIncrement = function (v) {
	this._unitIncrement = v;
};

Slider.prototype.getUnitIncrement = function () {
	return this._unitIncrement;
};

Slider.prototype.setBlockIncrement = function (v) {
	this._blockIncrement = v;
};

Slider.prototype.getBlockIncrement = function () {
	return this._blockIncrement;
};

Slider.prototype.isVertical=function () {
	return this._vertical;
};

Slider.prototype.isHorizontal=function () {
	return !this._vertical;
};

Slider.prototype.setPrecision=function (powerOf10) {
	this._range.setPrecision(powerOf10)
};

Slider.prototype.getPrecision=function (powerOf10) {
	return this._range.getPrecision();
};

Slider.prototype.recalculate = function() {
	if (!Slider.isSupported || !this.element) return;

	var w = this.element.offsetWidth;
	var h = this.element.offsetHeight;
	var hw = this.handle.offsetWidth;
	var hh = this.handle.offsetHeight;
	var lw = this.line.offsetWidth;
	var lh = this.line.offsetHeight;

	// this assumes a border-box layout

	var label;
	if (this.isEnabled()) {
		this.handle.className="handle active";
		label=this.getValue();
	} else {
		this.handle.className="handle";
		label='-';
	}

	var o=this.handle.firstChild;
	o.replaceChild(document.createTextNode(label),o.firstChild);


	if (this.isHorizontal()) {
		this.handle.style.left = (w - hw) * (this.getValue() - this.getMinimum()) / (this.getMaximum() - this.getMinimum()) + "px";
		this.handle.style.top = (h - hh) / 2 + "px";

		this.line.style.top = (h - lh) / 2 + "px";
		this.line.style.left = hw / 2 + "px";
		//this.line.style.right = hw / 2 + "px";
		this.line.style.width = Math.max(0, w - hw - 2)+ "px";
		this.line.firstChild.style.width = Math.max(0, w - hw - 4)+ "px";
	} else {
		this.handle.style.left = (w - hw) / 2 + "px";
		this.handle.style.top = h - hh - (h - hh) * (this.getValue() - this.getMinimum()) / (this.getMaximum() - this.getMinimum()) + "px";

		this.line.style.left = (w - lw) / 2 + "px";
		this.line.style.top = hh / 2 + "px";
		this.line.style.height = Math.max(0, h - hh - 2) + "px";	//hard coded border width
		//this.line.style.bottom = hh / 2 + "px";
		this.line.firstChild.style.height = Math.max(0, h - hh - 4) + "px";	//hard coded border width
	}
};

Slider.prototype.ontimer = function () {
	var hw = this.handle.offsetWidth;
	var hh = this.handle.offsetHeight;
	var hl = this.handle.offsetLeft;
	var ht = this.handle.offsetTop;
	

	if (this.isHorizontal()) {
		if (this._mouseX > hl + hw &&
			(this._increasing == null || this._increasing)) {			
			this.setValue(this.getValue() + this.getBlockIncrement());
			this._increasing = true;			
		}
		else if (this._mouseX < hl &&
			(this._increasing == null || !this._increasing)) {			
			this.setValue(this.getValue() - this.getBlockIncrement());
			this._increasing = false;
		} 
	} else {
		if (this._mouseY > ht + hh &&
			(this._increasing == null || !this._increasing)) {
			this.setValue(this.getValue() - this.getBlockIncrement());
			this._increasing = false;
		}
		else if (this._mouseY < ht &&
			(this._increasing == null || this._increasing)) {
			this.setValue(this.getValue() + this.getBlockIncrement());
			this._increasing = true;
		}
	}

	this._timer.start();
};


