/*********************************************
Repository: /common/object/0.1.2.0/object.js
*********************************************/
function prw_object()
{
  //public

  //eventIdentity is optional unique key designed to manage duplicate events in cases where they cannot be avoided
  this.bindEvent = function(eventName,callfunc,eventIdentity,frameName)
  {
    if (!this.events[eventName]) {
      this.events[eventName] = [];
    }

    var index = this.getNextEventIndex(eventName,eventIdentity);

    this.events[eventName][index] = {};
    this.events[eventName][index].callfunc = callfunc;

    if (frameName) {
      this.events[eventName][index].binder = frameName;
      this.setCleanup(frameName);
    }

  }

  this.triggerEvent = function(eventName,params)
  {
    if (!this.events[eventName]) {
      return;
    }

    this.events[eventName].each(function(event) {
      if (event) {
        event.callfunc(params);
      }
    })
  }

  this.bindEventI = function(eventName,callfunc,frameName)
  {
    if (this.i_events[eventName]) {
      this.error('prw_object: Interactive event for object already set.');
    }

    this.i_events[eventName] = {};
    this.i_events[eventName].callfunc = callfunc;

    if (frameName) {
      this.i_events[eventName].binder = frameName;
      this.setCleanup(frameName);
    }
  }

  this.triggerEventI = function(eventName,params)
  {
    if (!this.i_events[eventName]) {
      return;
    }
    var event = this.i_events[eventName];
    if (event) {
      return event.callfunc(params);
    }
  }

  //private

  this.getNextEventIndex = function(eventName,eventIdentity)
  {
    var index;

    if (eventIdentity) {

      if (!this.eventWatcher[eventName]) {
        this.eventWatcher[eventName] =  {};
      }

      if (this.eventWatcher[eventName][eventIdentity] != null) {
        index = this.eventWatcher[eventName][eventIdentity]; // overrides previous event
      } else {
        index = this.events[eventName].size();
        this.eventWatcher[eventName][eventIdentity] = index;
      }

    } else {
      index = this.events[eventName].size();
    }
    return index;
  }

  this.error = function(error)
  {
    if (!document.body) {
      throw (error);
    }

    if (typeof error == 'string') {
      this.displayStringError(error);
    }

    if (typeof error == 'object') {
      this.displayCatchError(error);
    }
  }

  this.displayCatchError = function(error)
  {
    var str_error = '';
    for (var errorpart in error) {
      str_error += '<br />' + errorpart + ' => ' + error[errorpart];
    }
    this.displayStringError(str_error);
  }

  this.displayStringError = function(error)
  {
    this.checkErrorDiv();
    var errorDiv = $('prw_object_error_span');
    errorDiv.innerHTML += 'ERROR: ' + error + '<br /><br />';
  }

  this.checkErrorDiv = function()
  {
    var errorDiv = $('prw_object_error_div')

    if (!errorDiv) {
      errorDiv = document.createElement('div');
      errorDiv.style.position = 'absolute';
      errorDiv.style.left = 10;
      errorDiv.style.top = 10;
      errorDiv.style.border = '1px solid #000000';
      errorDiv.style.backgroundColor = '#ffffff';
      errorDiv.style.padding = '10px';
      errorDiv.style.zIndex = 9999;
      errorDiv.id = 'prw_object_error_div';

      var errorSpan = document.createElement('span');
      errorSpan.style.width = '100%';
      errorSpan.id = 'prw_object_error_span';
      errorSpan.style.fontWeight = 'bold';
      document.body.appendChild(errorDiv);
      errorDiv.appendChild(errorSpan);
    }
  }

  this.setCleanup = function(frameName)
  {
    if (this.cleanups[frameName]) return;

    var binder_window = this.get_binder_window(frameName);

    this.cleanups[frameName] = function()
    {
      // normal
      for (var eventName in this.events) {

        this.events[eventName].each( function(event,index) {

          if (event && event.binder && event.binder === frameName) {
            delete(this.events[eventName][index]);
          }

        }.bind(this))

      }

      // interactive
      for (var eventName in this.i_events) {

        var event = this.i_events[eventName];
        if (event && event.binder && event.binder === frameName) {
          delete(this.i_events[eventName]);
        }

      }

      // cleaning own mess
      Event.stopObserving(binder_window,'unload',this.cleanups[frameName]);
      delete(this.cleanups[frameName]);
    }.bind(this);

    Event.observe(binder_window,'unload',this.cleanups[frameName]);

    if (!this.isset_cleanown) {
      this.isset_cleanown = true;
      Event.observe(window,'unload',this.cleanown.bind(this));
    }
  }

  this.cleanown = function()
  {
    for (var frameName in this.cleanups) {
      if (this.cleanups[frameName]) {
        var binder_window = this.get_binder_window(frameName);
        Event.stopObserving(binder_window,'unload',this.cleanups[frameName]);
        delete(this.cleanups[frameName]);
      }
    }
    Event.observe(window,'unload',this.cleanown.bind(this));
  }

  this.get_binder_window = function(frameName)
  {
    if (window.frames && window.frames[frameName]) {
      return window.frames[frameName];
    }

    if (parent && parent.window && parent.window.frames && parent.window.frames[frameName]) {
      return parent.window.frames[frameName];
    }

    this.error('prw_object: Binder window not found by framename "'+frameName+'".');
  }

  this.events = {};
  this.i_events = {};
  this.eventWatcher = {};
  this.cleanups = {};

  this.isset_cleanown = false;
}

/*********************************************
Repository: /json/convert/0.1.0.0/convert.js
*********************************************/
function prw_json_decode(json)
{
  var str_php = '';
  var str_key = '';
  var str_value = '';
  var count = 0;
  for (var key in json)
  {
      count++;

      str_key = 's:' + String(key).length + ":\"" + String(key) + "\";";

      if (typeof (json[key]) == 'object') {
        str_value = prw_json_decode(json[key]);
      } else {
        str_value = 's:' + String(json[key]).length + ":\"" + String(json[key]) + "\";";
      }

      str_php = str_php + str_key + str_value;
  }
  str_php = "a:" + count + ":{" + str_php + "}";
  return str_php;
}

/*********************************************
Repository: /document/include/0.1.0.0/include.js
*********************************************/
include_handler.prototype = new prw_object();
var includer = new include_handler();

function bind_include_event(event,callfunc,ident)
{
  includer.bindEvent(event,callfunc,ident);
}

function js_include(script_filename)
{
  return includer.js_include(script_filename)
}

function js_include_once(script_filename)
{
  return includer.js_include_once(script_filename)
}

function js_code_register(code)
{
  return includer.js_code_register(code);
}

function css_include(link_filename)
{
  return includer.css_include(link_filename)
}

function css_include_once(link_filename)
{
  return includer.css_include_once(link_filename)
}

function css_code_register(code)
{
  return includer.css_code_register(code);
}

function include_handler()
{

  this.js_include = function(script_filename)
  {
    var head = document.getElementsByTagName('head').item(0);
    var js_script = document.createElement('script');
    js_script.setAttribute('language', 'javascript');
    js_script.setAttribute('type', 'text/javascript');
    js_script.setAttribute('src', script_filename);


    //FF
    js_script.onload = this.onFileIncludeComplete.bind(this);

    //IE
    var callfunc = this.onFileIncludeComplete.bind(this);
    js_script.onreadystatechange = function() {
      if (js_script.readyState == 'loaded' || js_script.readyState == 'complete') {
        callfunc(script_filename);
      }
    };

    head.appendChild(js_script);

    this.files[js_script.src] = script_filename;
    return true;
  }

  this.js_include_once = function(script_filename)
  {
    var included = false;
    var scripts = document.getElementsByTagName('script');
    for (var i = 0; i < scripts.length; i++) {
      if (scripts[i].src && scripts[i].src.match(script_filename)) {
        included = true;
        break;
      }
    }
    if (included) {
      this.files[script_filename] = script_filename;
      this.onFileIncludeComplete(script_filename);
      return false;
    } else {
      return this.js_include(script_filename);
    }
  }

  this.js_code_register = function(code)
  {

    var head = document.getElementsByTagName('head').item(0);
    var js_script = document.createElement('script');
    js_script.setAttribute('language', 'javascript');
    js_script.setAttribute('type', 'text/javascript');

    try {
      js_script.innerHTML = code;
    } catch (error) {
      try {
        js_script.text = code;
      } catch (error) {
        this.error(error);
      }
    }

    head.appendChild(js_script);
    return true;
  }

  /****************************************/

  this.css_include = function(link_filename)
  {
    var head = document.getElementsByTagName('head').item(0);
    var css_link = document.createElement('link');

    css_link.setAttribute('rel', 'stylesheet');
    css_link.setAttribute('type', 'text/css');
    css_link.setAttribute('href', link_filename);

    head.appendChild(css_link);
    return true;
  }

  this.css_include_once = function(link_filename)
  {
    var included = false;
    var links = document.getElementsByTagName('link');
    for (var i = 0; i < links.length; i++) {
      if (links[i].href && links[i].href.match(link_filename)) {
        included = true;
        break;
      }
    }
    if (included) {
      return false;
    } else {
      return this.css_include(link_filename);
    }
  }

  this.css_code_register = function(code)
  {
    var head = document.getElementsByTagName('head').item(0);
    var css_style = document.createElement('style');
    css_style.setAttribute('type', 'text/css');

    try {
      css_style.innerHTML = code;
    } catch (error) {
      try {
        css_style.styleSheet.cssText = code;
      } catch (error) {
        this.error(error);
      }
    }

    head.appendChild(css_style);
    return true;
  }

  /****************************************/

  this.onFileIncludeComplete = function(param)
  {
    if (typeof param == 'object') {
      if (param.currentTarget.src) {
        var file = param.currentTarget.src;
      } else {
        var file = param.currentTarget.href;
      }
    } else {
      var file = param;
    }
    var eventParams = {};
    eventParams.file = this.files[file];
    this.triggerEvent('onIncludeComplete',eventParams);
  }

  this.files = {};

}

/*********************************************
Repository: /ajax/prowax/0.1.3.1/prowax.js
*********************************************/
var prowax_wait = false;

function Prowax_Request(url,options,prowax_options)
{
  var quickProwax = new Prowax();
  if (prowax_options && typeof prowax_options == 'object') {
    quickProwax.setOptions(prowax_options);
  }
  quickProwax.request(url,options);
}

function Prowax()
{
  prw_object.apply(this);

  this.request = function(url, options, fileupload_form, mode)
  {
    if (!options)
      options = {};
    var proceed = this.checkRequest(options);
    if (!proceed) {
      return false;
    }

    this.requestInitialize();

    if (options.onComplete) {
      this.userOnComplete = options.onComplete;
    } else {
      this.userOnComplete = null;
    }

    options.onComplete = this.requestComplete.bind(this);

    if (!options.onFailure) {
      options.onFailure = this.requestFailed.bind(this);
    }

    url = this.parseURL(url);

    if (fileupload_form) {
      this.afu = new afu_request();
      this.afu.request(url,options,fileupload_form,mode);
    } else {
      new Ajax.Request(url,options);
    }

    return true;
  }

  this.setOptions = function(prowax_options)
  {
    if (prowax_options.LoadingImage) {
      this.setLoadingImage(prowax_options.LoadingImage);
    }
    if (prowax_options.WaitTime) {
      this.setWaitTime(prowax_options.WaitTime);
    }
    if (prowax_options.IgnoreWait) {
      this.setIgnoreWait(prowax_options.IgnoreWait);
    }

    if (prowax_options.CompleteIgnoreWait) {
      this.setCompleteIgnoreWait(prowax_options.CompleteIgnoreWait);
    }
  }

  this.setWaitTime = function(time)
  {
    this.WaitTime = time;
  }

  this.setIgnoreWait = function(bool)
  {
    this.IgnoreWait = bool;
  }

  this.getIgnoreWait = function()
  {
    return this.IgnoreWait;
  }

  this.setCompleteIgnoreWait = function(bool)
  {
    this.CompleteIgnoreWait = bool;
    this.IgnoreWait = bool;
  }

  this.setLoadingImage = function(id)
  {
    this.LoadingImage = id;
  }

  this.checkRequest = function(options)
  {
    if (this.busy) { //object can handle only one call at time
      return false;
    }

    if (!this.IgnoreWait && prowax_wait) { // if IgnoreWait is false all Prowax objects will handle only one call at time
      return false;
    }

    return true;
  }

  this.requestInitialize = function()
  {
    this.showLoadingImage();
    this.busy = true;
    if (!this.CompleteIgnoreWait) {
      prowax_wait = true;
    }
  }

  this.requestComplete = function(transport)
  {
    this.hideLoadingImage();
    setTimeout('prowax_wait = false',this.WaitTime);
    this.busy = false;

    var error = '';
    var notice = '';

    var response = transport.responseText;

    response = this.trim(response);

    if (response.match(/<\?xml/)) {

      var xml_start = response.indexOf('<?xml');

      if (xml_start != 0) {
        notice = '<b>Notice:</b><br />' + response.substring(0,xml_start);
        var xml_response = response.substring(xml_start,response.length);
      } else {
        var xml_response = response;
      }

      var bcomm_result = bcomm_response_handle(xml_response);
      if (bcomm_result == false) {
        error = '<b>Error: Invalid response XML:</b><br />' + xml_response;
      }
    } else {
      error = '<b>Error: Response is not XML:</b><br />' + response;
    }

    if (notice.length) {
      this.displayText(notice)
    }

    if (error.length) {
      this.displayText(error);
    } else if (this.userOnComplete) {
      (this.userOnComplete)(transport,bcomm_result.raw_data);
    }

    this.triggerEvent('on_request_complete'); // used by bcomm_request to handle request queu
  }

  this.requestFailed = function(transport)
  {
    this.displayText('<b>Error: Request failed</b><br />' + transport.responseText);
  }

  this.showLoadingImage = function()
  {
    if (!this.LoadingImage)
      return;

    $(this.LoadingImage).style.visibility = 'visible'
  }

  this.hideLoadingImage = function()
  {
    if (!this.LoadingImage)
      return;

    $(this.LoadingImage).style.visibility = 'hidden'
  }

  this.parseURL = function(url)
  {
    if (url.match(/\?/)) {
      if (url.charAt(url.length-1) == '?') {
        url += 'prw_call_mode=ajax&prw_call_engine=prowax';
      } else {
        url += '&prw_call_mode=ajax&prw_call_engine=prowax';
      }
    } else {
      url += '?prw_call_mode=ajax&prw_call_engine=prowax';
    }
    return url;
  }

  this.trim = function(string)
  {
    while (string.charAt(0) == ' ') {
      string = string.substring(1,string.length);
    }

    while (string.charAt(string.length-1) == ' ') {
      string = string.substring(0,string.length-1);
    }

    return string;
  }

  this.displayText = function(message)
  {
    if (!$('prowax_text_div_wrapper')) {
      this.createTextDivs();
    }

    $('prowax_text_div_wrapper').style.display = 'block';
    $('prowax_text_div').innerHTML += message + '<br /><br />';
  }

  this.createTextDivs = function()
  {
    var wrapper = this.createTextDivWrapper();
    var textDivActions = this.createTextDivActions(wrapper);
    var textDiv = this.createTextDiv();

    wrapper.appendChild(textDivActions);
    wrapper.appendChild(textDiv);
    document.body.appendChild(wrapper);
  }

  this.createTextDivWrapper = function()
  {
    var wrapper = document.createElement('div');
    wrapper.style.position = 'absolute';
    wrapper.style.left = 10;
    wrapper.style.top = 10;
    wrapper.style.width = '90%';
    wrapper.style.zIndex = 9999;
    wrapper.id = 'prowax_text_div_wrapper';
    return wrapper;
  }

  this.createTextDiv = function()
  {
    var textDiv = document.createElement('div');
    textDiv.style.border = '1px solid #000000';
    textDiv.style.backgroundColor = '#ffffff';
    textDiv.style.padding = '5px';
    textDiv.style.width = '100%';
    textDiv.id = 'prowax_text_div';
    return textDiv;
  }

  this.createTextDivActions = function()
  {
    var textDivActions = document.createElement( 'div' );
    textDivActions.style.borderTop = '1px solid #000000';
    textDivActions.style.borderLeft = '1px solid #000000';
    textDivActions.style.borderRight = '1px solid #000000';
    textDivActions.style.backgroundColor = '#ffffff';
    textDivActions.style.padding = '5px';
    textDivActions.style.width = '100%';
    textDivActions.id = 'prowax_text_div_actions';

    var closeLink = document.createElement('a');
    closeLink.innerHTML = '[Sulje]';
    Event.observe(closeLink, 'click', this.hideText.bind(this));
    textDivActions.appendChild(closeLink);

    var emptyLink = document.createElement('a');
    emptyLink.innerHTML = '&nbsp;[Tyhjennä]';
    Event.observe( emptyLink, 'click', this.emptyText.bind(this));
    textDivActions.appendChild(emptyLink);

    return textDivActions;
  }

  this.hideText = function()
  {
    $('prowax_text_div_wrapper').style.display = 'none';
  }

  this.emptyText = function()
  {
    $('prowax_text_div').innerHTML = '';
  }

  this.LoadingImage = null;
  this.WaitTime = 100;
  this.IgnoreWait = false;
  this.CompleteIgnoreWait = false;

  this.userOnComplete = null;
  this.busy = false;

  this.afu;

}

/*********************************************
Repository: /ajax/bcomm/0.1.6.2/content_updater.js
*********************************************/
function event_break(event)
{
  if (event.preventDefault) {
    event.preventDefault();
  } else {
    event.returnValue = false;
    return false;
  }
}

function bcomm_content_updater()
{
  prw_object.apply(this);

  this.replace_content = function(targetElementName, dom_content)
  {

    try {
      var ignore_missing = getattributevalue(node_Block,'ignore-missing-target');
    } catch (error) {
      var ignore_missing = false;
    }

    var targetElement = $(targetElementName);
    if (!targetElement) {
      if (!ignore_missing) {
        this.error('bcomm: Target element "' + targetElementName + '" not found.');
      }
      return;
    }

    var update_method = getattributevalue(node_Block,'update-method');

    removeChildNodes( targetElement );
    setContent(dom_content,targetElement,update_method);
  }

  this.table_row_append = function(targetElementName, dom_content,row_index)
  {
    var targetElement = $(targetElementName);
    if (!targetElement) {
      this.error('bcomm: Target element "' + targetElementName + '" not found.');
      return;
    }

    var node_Html = dom_content.firstChild;
    var row_Html = node_Html.nodeValue;

    row_index = parseInt(row_index);

    if (row_index == 0) {
      new Insertion.Top(targetElement,row_Html);
    } else {
      var previous_row = targetElement.rows[row_index-1];
      new Insertion.After(previous_row,row_Html);
    }
  }

  this.table_row_delete = function(targetElementName,row_index)
  {
    var targetElement = $(targetElementName);
    if (!targetElement) {
      this.error('bcomm: Target element "' + targetElementName + '" not found.');
      return;
    }

    targetElement.deleteRow(row_index);
  }

  function removeChildNodes( element )
  {
    if( element.hasChildNodes ) {
      for( var i = element.childNodes.length - 1; i >= 0; i-- ) {
        var cn = element.childNodes[i];
        element.removeChild( cn );
      }
    }
    // element.innerHTML = ''; //! Turha?
  }

  function createHtmlElement(xmlObj)
  {
    // create element
    var element = document.createElement(xmlObj.tagName);
    // set element attributes
    setAttributes(xmlObj,element);
    //
    /*
    if(xmlObj.tagName == 'table') {
      var tBody = document.createElement('tbody');
      element.appendChild(tBody);
      element = tBody;
    }
    */
    // set element childs
    if (xmlObj.hasChildNodes()) {
      setChildNodes(xmlObj,element);
    }
    return element;
  }

  function setAttributes(xmlObj,element)
  {
    var attributes = xmlObj.attributes;
    var len = attributes.length;
    for (var loopIndex = 0; loopIndex < len; loopIndex++) {
      var attribute = attributes[loopIndex];

      switch (attribute.nodeName.toLowerCase()) {
        case 'class':
          element.className = attribute.nodeValue;
          break;
        case 'cellpadding':
          element.cellPadding = attribute.nodeValue;
          break;
        case 'cellspacing':
          element.cellSpacing = attribute.nodeValue;
          break;
        case 'colspan':
          element.colSpan = attribute.nodeValue;
          break;
        default:
          if(attr_is_event(attribute)) {
            event_set(attribute,element);
          } else {
            element.setAttribute(attribute.nodeName, attribute.nodeValue);
          }
      }
    }
  }

  function attr_is_event(obj_attribute)
  {
    return (obj_attribute.nodeName.toLowerCase( ).substr( 0, 2 ) == 'on');
  }

  function attr_get_eventname(obj_attribute)
  {
    var name = obj_attribute.nodeName;
    return name.toLowerCase( ).substring( 2, name.length );
  }

  function event_set(obj_attribute,element)
  {
    var eventName = attr_get_eventname(obj_attribute);
    var event_function = new Function('event',obj_attribute.nodeValue);
    addEventX( element, eventName, event_function );
    // element.observe( eventName, event_function.bindAsEventListener(element) );
  }

  function addEventX( 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 setContent(dom_content,targetElement,update_method)
  {
    switch (update_method) {
      case 'dom':
        // alert('update_dom');
        setChildNodes(dom_content,targetElement);
        break;
      case 'simple':
        var node_Html = dom_content.firstChild;
        targetElement.innerHTML = node_Html.nodeValue;
        break;
      default:
        this.error('bcomm / content-update: Invalid update method.');
    }
  }

  function setChildNodes(xmlObj,element)
  {
    var xmlChild = xmlObj.firstChild;
    var hasChild = true;

    while (hasChild) {
      switch (xmlChild.nodeType) {
        case 1: // normal element

          var childElement = createHtmlElement(xmlChild);
          element.appendChild(childElement);
          break;
        case 3: // text
        case 4: //CDATA
          var textValue = xmlChild.nodeValue;
          var textNode = document.createTextNode(textValue);
          element.appendChild(textNode);
          break;
        case 8: //COMMENT
          break;
        default:
          alert(xmlChild.nodeType);
          break;
      }
      if (xmlChild.nextSibling) {
        xmlChild = xmlChild.nextSibling;
      } else {
        hasChild = false;
      }
    }
  }

  var getattributevalue = function (node,attributename)
  {
    var list_attribute = node.attributes;
    return list_attribute.getNamedItem(attributename).value;
  }

}

/*********************************************
Repository: /ajax/bcomm/0.1.6.2/fieldinfo.js
*********************************************/
function FieldInfo( FieldID )
{
  this.FieldID = FieldID;
  this.infoFieldID = 'fieldinfo_' + FieldID;

  this.show = function( info )
  {
    this.checkField( );

    var field = $( this.infoFieldID );
    field.style.display = 'block';
    $( this.infoFieldID ).innerHTML = info;
  }

  this.hide = function( )
  {
    if( $( this.infoFieldID ) ) {
      $( this.infoFieldID ).style.display = 'none';
    }
  }

  this.setStyle = function( style )
  {
    this.checkField( );

    var field = $( this.infoFieldID );

    switch( style ) {
      case 'info':
        field.style.border = '1px solid green';
        field.style.backgroundColor = '#BFFFBF';
        break;
      case 'error':
      default:
        field.style.border = '1px solid red';
        field.style.backgroundColor = '#FFBFBF';
        break;
    }
  }

  this.checkField = function( )
  {
    if( !$( this.infoFieldID ) ) {

      var isIE = (navigator.appName.indexOf("Microsoft") !=-1);

      var infoField = document.createElement( 'div' );
      infoField.setAttribute( 'id', this.infoFieldID );
      infoField.style.display = 'none';
      infoField.style.padding = '5px';
      infoField.style.position = 'absolute';
      infoField.style.fontWeight = 'bold';
      if( isIE ) {
        infoField.style.marginLeft = '5px';
        infoField.style.marginTop = '0px';
      }
      else {
        infoField.style.marginLeft = 5 + $( this.FieldID ).getWidth( ) + 'px';
        infoField.style.marginTop = 0 - $( this.FieldID ).getHeight( ) + 'px';
      }

      infoField.style.border = '1px solid black';
      infoField.style.backgroundColor = 'gray';

      $( this.FieldID ).parentNode.appendChild( infoField );

    }
  }


}

/*********************************************
Repository: /ajax/bcomm/0.1.6.2/request.js
*********************************************/
function bcomm_request()
{
  prw_object.apply(this);
  // Interface functions

  this.add_fu = function(action_name,action_target,action_values,fu_form)
  {
    this.request.has_fu = true;
    this.request.fu_form = fu_form;
    this.add(action_name,action_target,action_values,fu_form);
  }

  this.add = function(action_name,action_target,action_values,form_name)
  {
    if (this.request.actions[action_name]) {
      this.error('bcomm_request: duplicate action "' + action_name + '".');
      this.lock = true;
    }
    this.request.actions[action_name] = {};
    this.request.actions[action_name].values = {};
    if (action_values) {
      var success = this.set_action_values(action_name,action_values);
      if (!success) {
        this.lock = true;
        return;
      }
    }
    if (form_name) {
      var form_values = Form.serialize(form_name,true);
      var success = this.set_action_values(action_name,form_values);
      if (!success) {
        this.lock = true;
        return;
      }
    }
    if (this.target_base) {
      this.request.actions[action_name].target = this.target_base + ';' + action_target;
    } else {
      this.request.actions[action_name].target = action_target;
    }
    this.request.action_count++;
  }

  this.send = function(url,mode)
  {
    if (this.lock) {
      this.reset(false);
      return;
    }

    this.request.url = url;
    this.request.mode = mode;

    if (!url) {
      if (!this.default_url) {
        this.error('bcomm_request: no url or default url given.');
        return;
      }
      url = this.default_url;
    }

    if (this.request.action_count == 0) {
      this.error('bcomm_request: no actions set when trying to send.');
      return;
    }

    try {
      var app_ident = js_codehandler_app_ident;
      url = this.parseURL(url,app_ident);
    } catch (error) {};

    var values = this.build_send_values();

    if (this.request.has_fu) {
      var success = this.ajax.request(url,{parameters:values},this.request.fu_form,mode);
    } else {
      var success = this.ajax.request(url,{parameters:values});
    }

    if (!success && this.use_queu) {
      this.reset(true);
    } else {
      this.reset(false);
    }
  }

  this.setURL = function(url)
  {
    this.default_url = url;
  }

  this.setTargetBase = function(target_base)
  {
    this.target_base = target_base;
  }

  this.setQueu = function(bool)
  {
    this.use_queu = bool;
  }

  // Prowax option functions

  this.setOptions = function(options)
  {
    this.ajax.setOptions(options)
  }

  this.setWaitTime = function(time)
  {
    this.ajax.setWaitTime(time);
  }

  this.setIgnoreWait = function(bool)
  {
    this.ajax.setIgnoreWait(bool);
  }

  this.setCompleteIgnoreWait = function(bool)
  {
    this.ajax.setCompleteIgnoreWait(bool);
  }

  this.setLoadingImage = function(id)
  {
    this.ajax.setLoadingImage(id);
  }

  // private functions

  //triggered by prowax 'on_request_complete'
  this.on_request_complete = function()
  {
    if (this.stored_request) {
      this.retrieve_request();

      var current_ignorewait = this.ajax.getIgnoreWait();
      this.ajax.setIgnoreWait(true);
      this.send(this.request.url,this.request.mode);
      this.ajax.setIgnoreWait(current_ignorewait);
    }
  }

  this.set_action_values = function(action_name,action_values)
  {
    var parameter_counter = 0;

    for (var i in this.request.actions[action_name].values) {
      parameter_counter++;
    }

    for (var parameter_name in action_values) {
      if (this.request.values[parameter_name]) {
        this.error('bcomm_request: duplicate parameter "' + parameter_name + '".');
        return false;
      }

      var parameter_value = action_values[parameter_name];
      this.request.values[parameter_name] = parameter_value;

      var array_index = parameter_name.indexOf('[');
      if (array_index != -1 && array_index) {
        parameter_name = parameter_name.substr(0,array_index);
      }

      this.request.actions[action_name].values[parameter_counter] = parameter_name;
      parameter_counter++;
    }
    return true;
  }

  this.build_send_values = function()
  {
    var values = this.request.values;
    var action_counter = 0;

    for (var action_value in this.request.actions) {

      var action_key = 'bcomm_actions['+action_counter+'][name]';
      values[action_key] = action_value;

      var target_key = 'bcomm_actions['+action_counter+'][target]';
      var target_value = this.request.actions[action_value].target;
      values[target_key] = target_value;

      var action_values = this.request.actions[action_value].values;
      for (var param_index in action_values) {
        var param_value = action_values[param_index];
        var param_key = 'bcomm_actions['+action_counter+'][values]['+param_index+']';
        values[param_key] = param_value;
      }

      action_counter = action_counter + 1;
    }
    return values;
  }

  this.parseURL = function(url,js_app_ident)
  {
    if (url.match(/\?/)) {
      if (url.charAt(url.length-1) == '?') {
        url += 'js_codehandler_app_ident=' + js_app_ident;
      } else {
        url += '&js_codehandler_app_ident=' + js_app_ident;
      }
    } else {
      url += '?js_codehandler_app_ident=' + js_app_ident;
    }
    return url;
  }

  this.reset = function(store)
  {
    if (store) {
      this.store_request();
    }

    this.request = {};

    this.request.actions = {};
    this.request.values = {};
    this.request.action_count = 0;
    this.request.url = '';
    this.request.mode = '';

    this.request.has_fu = false;
    this.request.fu_form = '';

    this.lock = false;

    if (!this.ajax) {
      this.ajax = new Prowax();
      this.ajax.bindEvent('on_request_complete',this.on_request_complete.bind(this));
    }
  }

  this.store_request = function()
  {
    this.stored_request = this.request;
  }

  this.retrieve_request = function()
  {
    this.request = this.stored_request;
    this.stored_request = false;
  }

  this.request;
  this.stored_request = null;

  this.ajax;

  this.default_url = false;
  this.target_base = false;
  this.use_queu = false;

  this.lock;

  this.reset(false);
}

/*********************************************
Repository: /ajax/bcomm/0.1.6.2/response_handler.js
*********************************************/
function bcomm_response_handle(str_Response)
{
  var Handler = new bcomm_response_handler();
  try {
    var result = Handler.response_handle(str_Response);
  } catch (error) {
    Handler.error(error);
  }
  return result;
}

function bcomm_response_handler()
{
  prw_object.apply(this);

  this.response_handle = function (xml_Response)
  {
    var result = {};
    result.raw_data = '';

    var dom_Response = this.xml_to_dom(xml_Response);

    if (!dom_Response) {
      return false;
    }

    var success = this.success_fetch(dom_Response);

    if (!success) {
      return false;
    }

    var list_action = dom_Response.getElementsByTagName('action');

    // Loop actions

    for (var i_action = 0; i_action < list_action.length; i_action++) {
      var node_action = list_action[i_action];
      result = this.process_action(node_action,result);
    }

    this.onloadHandler.checkOnLoad();

    return result;
  }

  this.process_action = function (node_action,result)
  {
    var action_type = this.getattributevalue(node_action,'type');

    switch (action_type) {
      case 'content-update':
        this.content_update(node_action);
        break;
      case 'content-table_row_append':
        this.content_table_row_append(node_action);
        break;
      case 'content-table_row_delete':
        this.content_table_row_delete(node_action);
        break;
      case 'fieldvalue-update':
        this.fieldvalue_update(node_action);
        break;
      case 'fieldinfo-show':
        this.fieldinfo_show( node_action );
        break;
      case 'fieldinfo-hide':
        this.fieldinfo_hide( node_action );
        break;
      case 'pass-raw-data':
        result.raw_data += this.raw_data_fetch(node_action);
        break;
      case 'js-script-append':
        this.js_script_append(node_action);
        break;
      case 'css-link-append':
        this.css_link_append(node_action);
        break;
      case 'css-style-append':
        this.css_style_append(node_action);
        break;
      case 'js-set-event':
        this.js_set_event(node_action);
        break;
      default:
        this.error('bcomm_response_handler: Unknown action: ' + action_type);
    }
    return result;
  }

  this.xml_to_dom = function (xml)
  {
    if(document.implementation && document.implementation.createDocument) {
      var objDOMParser = new DOMParser();
      var xmlObj = objDOMParser.parseFromString(xml, "text/xml");

      if (xmlObj.getElementsByTagName('parsererror').length) {
        return false;
      }

      xmlObj.normalize();
    } else if (window.ActiveXObject) {
      var xmlObj = new ActiveXObject("MSXML2.DOMDocument.3.0");
      xmlObj.async = false;

      if (!xmlObj.loadXML(xml)) {
        return false;
      }

    }
    return xmlObj;
  }

  this.content_update = function (node_action)
  {
    // debug('CONTENT_UPDATE');
    // debug(node_action);
    node_Block = node_action.getElementsByTagName('block').item(0);
    // debug(node_Block);
    var target_container = this.getattributevalue(node_Block,'target-container');

    // debug(target_container);
    var Updater = new bcomm_content_updater();
    Updater.replace_content(target_container, node_Block);
  }

  this.content_table_row_append = function(node_action)
  {
    node_Block = node_action.getElementsByTagName('block').item(0);
    var target_container = this.getattributevalue(node_Block,'target-container');
    var row_index = this.getattributevalue(node_Block,'target-row_index');

    var Updater = new bcomm_content_updater();
    Updater.table_row_append(target_container, node_Block,row_index);
  }

  this.content_table_row_delete = function(node_action)
  {
    var target_container = this.getattributevalue(node_action,'target-container');
    var row_index = this.getattributevalue(node_action,'target-row_index');

    var Updater = new bcomm_content_updater();
    Updater.table_row_delete(target_container, row_index);
  }

  this.fieldvalue_update = function (node_action)
  {
    var node_Field = node_action.getElementsByTagName('field').item(0);
    var node_Value = node_Field.getElementsByTagName('value').item(0);
    var data = '';
    if( node_Value.firstChild && node_Value.firstChild.data) {
      var data = node_Value.firstChild.data;
    }

    var target_field = $( node_Field.getAttribute( 'id' ) );
    if( !target_field ) {
      this.error('bcomm_response_handler: Field not found: ' + node_Field.getAttribute( 'id' ) );
    }

    if( target_field.tagName == 'INPUT' ) {
      target_field.value = data;
    }
    else {
      target_field.innerHTML = data;
    }
  }

  this.raw_data_fetch = function(node_action)
  {
    var node_Data = node_action.getElementsByTagName('data').item(0);
    return node_Data.firstChild.data;
  }

  this.js_script_append = function(node_action)
  {
    var node_Data = node_action.getElementsByTagName('data').item(0);

    var file_src = node_Data.getAttribute('src');
    if (file_src) {
      this.onloadHandler.setFileLoading(file_src);
      js_include_once(file_src);
    }

    if (node_Data.firstChild) {
      var code = node_Data.firstChild.data;
      js_code_register(code);
    }
  }

  this.css_link_append = function(node_action)
  {
    var node_Data = node_action.getElementsByTagName('data').item(0);

    var file_src = node_Data.getAttribute('href');
    css_include_once(file_src);
  }

  this.css_style_append = function(node_action)
  {
    var node_Data = node_action.getElementsByTagName('data').item(0);

    var code = node_Data.firstChild.data;
    css_code_register(code);
  }

  this.js_set_event = function(node_action)
  {
    var node_Data = node_action.getElementsByTagName('data').item(0);

    var event = node_Data.getAttribute('event');
    switch (event) {
      case 'onload':
        var code = node_Data.firstChild.data;
        this.onloadHandler.setCode(code);
        break;
      default:
        this.error('bcomm_response_handler: Unknown event "' + event + '" for action js-set-event');
        return;
        break;
    }
  }

  this.fieldinfo_show = function( node_action )
  {
    var node_field = node_action.getElementsByTagName( 'field' ).item(0);
    var node_info = node_action.getElementsByTagName( 'info' ).item(0);

    var FieldID = node_field.getAttribute( 'id' );
    var style = node_info.getAttribute( 'style' );
    var info = '';

    if( node_info.firstChild && node_info.firstChild.data ) {
      info = node_info.firstChild.data;
    }

    var fieldinfo = new FieldInfo( FieldID );
    fieldinfo.setStyle( style );
    fieldinfo.show( info );
  }

  this.fieldinfo_hide = function( node_action )
  {
    var node_field = node_action.getElementsByTagName( 'field' ).item(0);
    var FieldID = node_field.getAttribute( 'id' );

    var fieldinfo = new FieldInfo( FieldID );
    fieldinfo.hide( );
  }

  this.success_fetch = function(dom_Response)
  {
    var node_Result = dom_Response.getElementsByTagName('result').item(0);
    return this.getattributevalue(node_Result,'success');
  }

  this.getattributevalue = function (node,attributename)
  {
    var list_attribute = node.attributes;
    return list_attribute.getNamedItem(attributename).value;
  }

  this.onloadHandler = new bcomm_onload_handler();
}

function bcomm_onload_handler()
{
  this.setCode = function(code)
  {
    this.code += code;
  }

  this.checkOnLoad = function()
  {
    if (!this.code.length) {
      return;
    }

    this.files_waiting = false;

    for (var file in this.files) {
      this.files_waiting = true;
      break;
    }

    if (!this.files_waiting) {
      js_code_register(this.code);
    }
  }

  this.setFileLoading = function(file)
  {
    this.files[file] = true;
  }

  this.setFileLoaded = function(eventParams)
  {
    delete(this.files[eventParams.file]);
    if (this.files_waiting) {
      this.checkOnLoad();
    }
  }

  bind_include_event('onIncludeComplete',this.setFileLoaded.bind(this),'bcomm_onload_handler_event');

  this.files_waiting;
  this.files = {};
  this.code = '';
}

/*********************************************
Repository: /ajax/afu/0.1.0.0/afu.js
*********************************************/
afu_request.prototype = new prw_object();

function afu_request()
{
  this.request = function(url,options,form_name,mode)
  {
    afu_response_object.current_call_options = options;

    url += '&prw_afu=1';

    if (!$('afu_iframe')) {
      var wrapper_div = document.createElement('div');
      wrapper_div.id = 'afu_iframe_wrapper';
      document.body.appendChild(wrapper_div);

      if (mode && mode == 'debug') {
        wrapper_div.innerHTML = '<iframe id="afu_iframe" name="afu_iframe"></iframe>';
      } else {
        wrapper_div.innerHTML = '<iframe id="afu_iframe" name="afu_iframe" style="margin: 0px; padding: 0px; border: 0px; height: 0px; width: 0px; display:none;"></iframe>';
      }
    }

    var added_inputs = {};
    var form_object = $(form_name);

    for (var input_name in options.parameters) {
      var temp_input = document.createElement('input');
      temp_input.type = 'hidden';
      temp_input.name = input_name;
      temp_input.value = options.parameters[input_name];

      form_object.appendChild(temp_input);

      added_inputs[input_name] = temp_input;
    }

    var prev_target = form_object.target;
    var prev_action = form_object.action;
    form_object.target = 'afu_iframe';
    form_object.action = url;
    form_object.submit();
    form_object.target = prev_target;
    form_object.action = prev_action;


    for (var input_name in added_inputs) {
      form_object.removeChild(added_inputs[input_name]);
    }
  }

}

afu_response.prototype = new prw_object();
var afu_response_object = new afu_response();

function afu_response()
{

  this.handle_response = function(bcomm_response)
  {
    var fake_transport = {};
    fake_transport.responseText = bcomm_response;
    this.current_call_options.onComplete(fake_transport);
  }

  this.current_call_options;

}

/*********************************************
Repository: /document/grid_walker/0.1.0.0/grid_walker.js
*********************************************/
function grid_walker()
{
  prw_object.apply(this);

  // public

  // required
  this.set_grid = function(grid_name,parent_element)
  {
    if (this.grids[grid_name]) {
      this.error('grid_walker: grid already set with name "'+grid_name+'".');
      return;
    }

    if (parent_element) {
      parent_element = $(parent_element);
    } else {
      parent_element = document.body;
    }

    this.grids[grid_name] = {};
    this.grids[grid_name].order = this.grid_count;
    this.grids[grid_name].object = new grid_walker_grid(grid_name,parent_element);
    this.grid_count++;

    this.grids[grid_name].object.bindEvent('on_grid_begin',this.on_grid_begin.bind(this));
    this.grids[grid_name].object.bindEvent('on_grid_end',this.on_grid_end.bind(this));
  }

  // use this function to unset grid when elements have been reloaded with ajax
  this.unset_grid = function(grid_name)
  {
    if (!this.grids[grid_name]) {
      return;
    }

    var deleted_order = this.grids[grid_name].order;
    delete(this.grids[grid_name]);

    for (var existing_grid_name in this.grids) {
      if (this.grids[existing_grid_name].order > deleted_order) {
        this.grids[existing_grid_name].order--;
      }
    }
    this.grid_count--;
  }

  // utility
  this.set_focus = function(grid_name,element_index)
  {
    if (!grid_name) {
      grid_name = this.current_grid;
    }
    if (!grid_name) {
      grid_name = this.get_grid_name(0);
    }
    if (!grid_name) return false;

    if (!this.grids[grid_name]) {
      this.error('grid_walker: grid not set with name "'+grid_name+'".');
      return;
    }

    this.current_grid = grid_name;
    return this.grids[grid_name].object.set_focus(element_index);
  }

  // private

  this.on_grid_begin = function(event_params)
  {
    var current_order = this.grids[event_params.grid_name].order;
    var new_grid = this.get_grid_name(current_order - 1);
    if (new_grid) {
      this.set_focus(new_grid,'LAST');
    }
  }

  this.on_grid_end = function(event_params)
  {
    var current_order = parseInt(this.grids[event_params.grid_name].order);
    var new_grid = this.get_grid_name(current_order + 1);
    if (new_grid) {
      this.set_focus(new_grid,'FIRST');
    }
  }

  this.get_grid_name = function(order)
  {
    for (var grid_name in this.grids) {
      if (this.grids[grid_name].order == order) {
        return grid_name;
      }
    }

    return false;
  }

  this.grids = {};
  this.grid_count = 0;
  this.current_grid = false;
}

///////////////////////////////////////////////

function grid_walker_grid(grid_name,parent_element)
{
  prw_object.apply(this);

  //public

  this.set_focus = function(element_index,next_is_forward)
  {
    if (next_is_forward !== true) {
      next_is_forward = false;
    }

    if (element_index === 'FIRST') {
      element_index = 0;
    }
    if (element_index === 'LAST') {
      element_index = this.element_count - 1;
    }
    if (!element_index && element_index !== 0) {
      element_index = this.current_element_index;
    }
    if (!element_index) {
      element_index = 0;
    }
    element_index = parseInt(element_index);

    if (!this.elements[element_index]) return false;

    try {
      this.elements[element_index].focus();
    } catch (e) { // we will move to next element
      if (next_is_forward === true) {
        return this.set_focus(element_index + 1,true);
      } else {
        return this.set_focus(element_index - 1,false);
      }
    };

    try {
      this.elements[element_index].select();
    } catch (e) {}; // failing of select is not interesting

    this.current_element_index = element_index;
    return true;
  }

  //private

  this.initialize = function(parent_element)
  {
    var a_elements = parent_element.getElementsByClassName(this.grid_name);
    a_elements.each( function(element){
      this.elements[this.element_count] = element;
      this.element_count++;
    }.bind(this));

    this.set_element_binds();
  }

  this.set_element_binds = function()
  {
    for (var index in this.elements) {
      Event.observe(this.elements[index],'keydown',this.onkeydown.bind(this));
    }
  }

  this.onkeydown = function(uevent)
  {
    if (this.keys.is_forward(uevent)) {
      this.move_forward(uevent);
    } else if (this.keys.is_backward(uevent)) {
      this.move_backward(uevent);
    }
  }

  this.move_forward = function(uevent)
  {
    var element = Event.element(uevent);
    Event.stop(uevent);
    var index = parseInt(this.get_element_index(element));
    var success = this.set_focus(index + 1,true);

    if (!success) {
      var event_params = {};
      event_params.grid_name = this.grid_name;
      this.triggerEvent('on_grid_end',event_params);
    }
  }

  this.move_backward = function(uevent)
  {
    var element = Event.element(uevent);
    Event.stop(uevent);
    var index = this.get_element_index(element);
    var success = this.set_focus(index - 1,false);

    if (!success) {
      var event_params = {};
      event_params.grid_name = this.grid_name;
      this.triggerEvent('on_grid_begin',event_params);
    }
  }

  this.get_element_index = function(element)
  {
    for (var index in this.elements) {
      if (this.elements[index] === element) {
        return index;
      }
    }
    return false;
  }

  this.keys = new grid_walker_keys();
  this.elements = {};
  this.element_count = 0;
  this.current_element_index = false;
  this.grid_name = grid_name;
  this.initialize(parent_element);
}

///////////////////////////////////////////////

function grid_walker_keys()
{
  //public

  this.is_forward = function(uevent)
  {
    return this.is_direction('forward',uevent);
  }

  this.is_backward = function(uevent)
  {
    return this.is_direction('backward',uevent);
  }

  //private

  this.is_direction = function(direction,uevent)
  {
    var key_name = this.get_key_name(uevent);
    if (key_name === false) {
      return false;
    }

    var config = this.get_config(direction,uevent);

    if (config[key_name] === true) {
      return true;
    } else {
      return false;
    }
  }

  this.get_config = function(direction,uevent)
  {
    var element = Event.element(uevent);
    var tag_name = element.tagName.toLowerCase();

    if (tag_name === 'input') {
      var input_type = element.type.toLowerCase();
      if (this.keys[direction][tag_name+';'+input_type]) {
        return this.keys[direction][tag_name+';'+input_type];
      }
    }

    if (this.keys[direction][tag_name]) {
      return this.keys[direction][tag_name];
    }

    return this.keys[direction]['default'];
  }

  this.get_key_name = function(uevent)
  {
    var key_code = (uevent.which) ? uevent.which : uevent.keyCode;
    if (this.map[key_code]) {
      if (uevent.shiftKey) {
        return 'shift+'+this.map[key_code];
      } else {
        return this.map[key_code];
      }
    } else {
      return false;
    }
  }

  this.initialize = function()
  {
    this.map = {};
    this.map[13] = 'enter';
    this.map[9] = 'tab';

    this.keys = {};
    this.keys['forward'] = {};
    this.keys['backward'] = {};

    this.keys['forward']['default'] = {};
    this.keys['forward']['default']['enter'] = true;
    this.keys['forward']['default']['tab'] = true;

    this.keys['backward']['default'] = {};
    this.keys['backward']['default']['shift+enter'] = true;
    this.keys['backward']['default']['shift+tab'] = true;

    this.keys['forward']['textarea'] = {};
    this.keys['forward']['textarea']['tab'] = true;

    this.keys['backward']['textarea'] = {};
    this.keys['backward']['textarea']['shift+tab'] = true;
  }

  this.keys;
  this.map;
  this.initialize();

}

/*********************************************
Repository: /document/object/position/0.1.0.3/position.js
*********************************************/
function objectPosition()
{
  //returns x and y coordinates where element will fit to screen
  this.process = function(elem,coordX,coordY,exact)
  {
    if (exact) {
      var modifier = 0;
    } else {
      var modifier = 3;
    }
    var coords = Array();

    var scrolls = this.get_scrolls();

    var bottom = (elem.offsetHeight) + coordY;
    if (bottom > document.body.clientHeight + scrolls.top) {
      coords['Y'] = document.body.clientHeight + scrolls.top - (elem.offsetHeight);
    } else {
      coords['Y'] = coordY;
    }

    var right = (elem.offsetWidth) + coordX;

    if (right > document.body.clientWidth + scrolls.left) {
      coords['X'] = document.body.clientWidth + scrolls.left - (elem.offsetWidth) - modifier;
    } else {
      coords['X'] = coordX - modifier;
    }

    if (coords['X'] < 0)
      coords['X'] = 0;
    if (coords['Y'] < 0)
      coords['Y'] = 0;

    return coords;
  }

  this.get_scrolls = function() {
    var scroll_x = 0;
    var scroll_y = 0;
    if (typeof (window.pageYOffset) == 'number' ) {
      scroll_y = window.pageYOffset;
      scroll_x = window.pageXOffset;
    } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
      scroll_y = document.body.scrollTop;
      scroll_x = document.body.scrollLeft;
    } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
      scroll_y = document.documentElement.scrollTop;
      scroll_x = document.documentElement.scrollLeft;
    }

    var scrolls = {};
    scrolls['left'] = scroll_x;
    scrolls['top'] = scroll_y;
    return scrolls;
  }

}

/*********************************************
Repository: /document/object/drag/0.1.0.0/drag.js
*********************************************/
// script.aculo.us dragdrop.js v1.7.0, Fri Jan 19 19:16:36 CET 2007

// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//           (c) 2005, 2006 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/

// Draggable(s) modified to prw_draggable(s)

var prw_draggables = {
  drags: [],
  observers: [],

  register: function(draggable) {
    if(this.drags.length == 0) {
      this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
      this.eventMouseMove = this.updateDrag.bindAsEventListener(this);

      Event.observe(document, "mouseup", this.eventMouseUp);
      Event.observe(document, "mousemove", this.eventMouseMove);
    }
    this.drags.push(draggable);
  },

  unregister: function(draggable) {
    this.drags = this.drags.reject(function(d) { return d==draggable });
    if(this.drags.length == 0) {
      Event.stopObserving(document, "mouseup", this.eventMouseUp);
      Event.stopObserving(document, "mousemove", this.eventMouseMove);
    }
  },

  activate: function(draggable) {
    this.activeDraggable = draggable;
  },

  deactivate: function() {
    this.activeDraggable = null;
  },

  updateDrag: function(event) {
    if(!this.activeDraggable) return;
    var pointer = [Event.pointerX(event), Event.pointerY(event)];
    // Mozilla-based browsers fire successive mousemove events with
    // the same coordinates, prevent needless redrawing (moz bug?)
    if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
    this._lastPointer = pointer;

    this.activeDraggable.updateDrag(event, pointer);
  },

  endDrag: function(event) {
    if(this._timeout) {
      clearTimeout(this._timeout);
      this._timeout = null;
    }
    if(!this.activeDraggable) return;
    this._lastPointer = null;
    this.activeDraggable.endDrag(event);
    this.activeDraggable = null;
  },

  addObserver: function(observer) {
    this.observers.push(observer);
    this._cacheObserverCallbacks();
  },

  removeObserver: function(element) {  // element instead of observer fixes mem leaks
    this.observers = this.observers.reject( function(o) { return o.element==element });
    this._cacheObserverCallbacks();
  },

  notify: function(eventName, draggable, event) {  // 'onStart', 'onEnd', 'onDrag'
    if(this[eventName+'Count'] > 0)
      this.observers.each( function(o) {
        if(o[eventName]) o[eventName](eventName, draggable, event);
      });
    if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
  },

  _cacheObserverCallbacks: function() {
    ['onStart','onEnd','onDrag'].each( function(eventName) {
      prw_draggables[eventName+'Count'] = prw_draggables.observers.select(
        function(o) { return o[eventName]; }
      ).length;
    });
  }
}

/*--------------------------------------------------------------------------*/

var prw_draggable = Class.create();
prw_draggable._dragging    = {};

prw_draggable.prototype = {
  initialize: function(element) {
    var defaults = {
      handle: false
    };

    var options = Object.extend(defaults, arguments[1] || {});

    this.element = $(element);

    if(options.handle && (typeof options.handle == 'string'))
      this.handle = this.element.down('.'+options.handle, 0);

    if(!this.handle) this.handle = $(options.handle);
    if(!this.handle) this.handle = this.element;

    Element.makePositioned(this.element); // fix IE

    this.delta    = this.currentDelta();
    this.options  = options;
    this.dragging = false;

    this.eventMouseDown = this.initDrag.bindAsEventListener(this);
    Event.observe(this.handle, "mousedown", this.eventMouseDown);

    prw_draggables.register(this);
  },

  destroy: function() {
    Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
    prw_draggables.unregister(this);
  },

  currentDelta: function() {
    return([
      parseInt(Element.getStyle(this.element,'left') || '0'),
      parseInt(Element.getStyle(this.element,'top') || '0')]);
  },

  initDrag: function(event) {
    if(typeof prw_draggable._dragging[this.element] != 'undefined' &&
      prw_draggable._dragging[this.element]) return;
    if(Event.isLeftClick(event)) {
      // abort on form elements, fixes a Firefox issue
      var src = Event.element(event);
      if((tag_name = src.tagName.toUpperCase()) && (
        tag_name=='INPUT' ||
        tag_name=='SELECT' ||
        tag_name=='OPTION' ||
        tag_name=='BUTTON' ||
        tag_name=='TEXTAREA')) return;

      var pointer = [Event.pointerX(event), Event.pointerY(event)];
      var pos     = Position.cumulativeOffset(this.element);
      this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });

      prw_draggables.activate(this);
      Event.stop(event);
    }
  },

  startDrag: function(event) {
    this.dragging = true;

    if(this.options.ghosting) {
      this._clone = this.element.cloneNode(true);
      Position.absolutize(this.element);
      this.element.parentNode.insertBefore(this._clone, this.element);
    }

    prw_draggables.notify('onStart', this, event);
  },

  updateDrag: function(event, pointer) {
    if(!this.dragging) this.startDrag(event);
    Position.prepare();
    prw_draggables.notify('onDrag', this, event);

    this.draw(pointer);
    if(this.options.change) this.options.change(this);

    // fix AppleWebKit rendering
    if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);

    Event.stop(event);
  },

  finishDrag: function(event, success) {
    this.dragging = false;

    if(this.options.ghosting) {
      Position.relativize(this.element);
      Element.remove(this._clone);
      this._clone = null;
    }

    prw_draggables.notify('onEnd', this, event);

    var d = this.currentDelta();

    this.delta = d;

    prw_draggables.deactivate(this);
  },

  endDrag: function(event) {
    if(!this.dragging) return;
    this.finishDrag(event, true);
    Event.stop(event);
  },

  draw: function(point) {
    var pos = Position.cumulativeOffset(this.element);
    if(this.options.ghosting) {
      var r   = Position.realOffset(this.element);
      pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
    }

    var d = this.currentDelta();
    pos[0] -= d[0]; pos[1] -= d[1];

    var p = [0,1].map(function(i){
      return (point[i]-pos[i]-this.offset[i])
    }.bind(this));

    var style = this.element.style;
    if((!this.options.constraint) || (this.options.constraint=='horizontal'))
      style.left = p[0] + "px";
    if((!this.options.constraint) || (this.options.constraint=='vertical'))
      style.top  = p[1] + "px";

    if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
  }
}

/*--------------------------------------------------------------------------*/

// Returns true if child is contained within element
Element.isParent = function(child, element) {
  if (!child.parentNode || child == element) return false;
  if (child.parentNode == element) return true;
  return Element.isParent(child.parentNode, element);
}

/*********************************************
Repository: /document/object/common/0.1.0.0/common.js
*********************************************/
function obj_getbyid()
{
  switch (arguments.length)
  {
    case 1:
      return _obj_getbyid(document,arguments[0])
      break;
    case 2:
      return _obj_getbyid(arguments[0],arguments[1])
      break;
    default:
      return error_raise('obj_getbyid: Invalid number of arguments.');
  }
}

function _obj_getbyid(vDocument, vObjectID)
{
  if(vDocument.getElementById && vDocument.getElementById(vObjectID)) {
    return vDocument.getElementById(vObjectID); // W3C DOM
  } else if (vDocument.all && vDocument.all(vObjectID)) {
    return vDocument.all(vObjectID); // MSIE 4 DOM
  } else {
    return false;
  }
}

function obj_stylebyid(objectId)
{
  switch (arguments.length)
  {
    case 1:
      return _obj_stylebyid(document,arguments[0])
      break;
    case 2:
      return _obj_stylebyid(arguments[0],arguments[1])
      break;
    default:
      return error_raise('obj_stylebyid: Invalid number of arguments.');
  }
}

function _obj_stylebyid(vDocument, vObjectID)
{
  if(vDocument.getElementById && vDocument.getElementById(vObjectID)) {
    return vDocument.getElementById(vObjectID).style; // W3C DOM
  } else if (vDocument.all && vDocument.all(vObjectID)) {
    return vDocument.all(vObjectID).style; // MSIE 4 DOM
  } else if (vDocument.layers && vDocument.layers[vObjectID]) {
    return vDocument.layers[vObjectID]; // NN 4 DOM //! doesn't find nested layers
  } else {
    return false;
  }
}