/**
 * Ein Logger mit Log-Level und verschiedenen Einstellungsm��������glichkeiten
 */


/* SVN FILE:   $Id: AbstractComponent.js 111 2011-11-28 12:33:45Z g.meyer $
 * SVN HEADER: 1.1
 ***
 * $title           Logger & LoggerInstance
 *
 * $description
 *   Eine Logger Klasse, die LoggerInstance Instanzen mit gewissen Konfigurationen zur����ckgibt.
 *   Diese LogInstance Objekte greifen dann mit Ihren Konfigurationen auf die Log-Funktion in Logger zu.
 *
 * $author          g.meyer
 * $copyright       Babiel GmbH
 * $version         $Revision: ${revision}111 ${revision}108 $
 * $modifiedby      $LastChangedBy: g.meyer $
 * $lastmodified    $LastChangedDate: ${date}2011-11-28 13:33:45 +0100 (Mo, 28 Nov 2011) ${date}2011-11-24 10:59:06 +0100 (Do, 24 Nov 2011) $
 * $filesource      $HeadURL: http://svn.babiel.com/JavaScript_Base/trunk/Projekte/ComponentExamples/AbstractComponent/AbstractComponent.js $
 * $keywords        Logger, LoggerInstance,log, logging
 * $require         -
 *
 */
function Logger() {
  
  var days = {
    "long" : ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],
    "short" : ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"],
    "no" : ["","","","","","",""]
  };
  this.showWeekDay = "long";
  
  // Einstellungen, ob bestimmte Sachen beim loggen angezeigt werden sollen
  this.showDate2 = false;
  this.showDate = true;
  this.showSinceStart = true;
  this.showLogName = true;
  this.logName = false; // Kann einen Lognamen enthalten
  this.customConsole = false;
  this.setStartTime = function() { var now = new Date(); return now.getTime(); };
  this.startTime = this.setStartTime();
  this.level = 0;
  this.globalLogLevel = false;
  
  // F��������r Debug-Zwecke k��������nnen Fehlermeldungen als alert ausgegeben werden
  this.alertErrors = false;
  
  
  //Liste mit Logger-Instanzen 
  this.loggers = {};
  
  /**
   * F��������gt eine Logging-Konfiguration hinzu
   * @param logname Name der Logging Instanz
   */
  this.addLogConfig = function(logname, configs) {
    var config = {};
    if(typeof logname == "string" && logname.length > 0) {
      if(configs && typeof configs == "object") {
       config.level = (configs.level && typeof configs.level == "string") ? this.getLevelNumber(configs.level) : null;
       // Wurde ein anderer Appender angegeben und hat dieser die Log-Methode?
       if(configs.appender && typeof configs.appender == "object" && configs.appender.log) { var appen = configs.appender; }
       else { try { var appen = console;}catch(e){var appen = false;} }
       config.appender = appen;
       config.name = (configs.name && configs.name.length > 0) ? configs.name : logname;
      } else { if(this.alertErrors) alert("addLogConfig[Warn]: Second parameter must is not given or is not type of object");  }
        
      
      this.loggers[logname] = new LoggerInstance(config, this);      
     } else {if(this.alertErrors){alert("addLogConfig[Error]: First parameter has to be a valid string");} return false;}
  };
    
  this.getLogger = function(loggerName) {
    if(this.loggers[loggerName]) return this.loggers[loggerName]; else return false;
  };
  
  // Alle Log-Methoden
  this.info = function(msg, conf) { this.write(msg, 1, false, conf); };
  this.debug = function(msg, conf) {this.write(msg, 2, false, conf); };
  this.trace = function(msg, conf) { this.write(msg, 2, "trace", conf); };
  this.warn = function(msg, conf) {this.write(msg, 3, false, conf); };
  this.error = function(msg, conf) { this.write(msg, 4, false, conf); };
  this.log = function(msg, conf) {this.write(msg, 4, "log", conf); };
  this.list = function(msg, conf){this.write(msg, 2, "list", conf); };
  this.xml = function(msg, conf){this.write(msg, 2, "xml", conf); };
  /**
   * Alle Log-Funktionen benutzen write zum eigentlichen Schreiben
   * @param message Nachricht
   * @param logLevel Nummer des Loglevels
   * @param type Ausnahmen wie trace befinden sich auch auf dem Loglevel von Debug brauchen aber sp��������ter einen anderen Aufruf
   * @param conf Konfiguration der Logger-Instanz
   */
  this.write = function(message, logLevel, type, conf) {
    if(conf == undefined) conf = {};
    // Wenn keine Konsole zum debuggen vorhanden ist braucht man garnicht erst probieren zu loggen
    try {if(conf.appender == undefined && console == undefined) {return false; } } catch(e) { return false; }
    // Wenn kein Log-Level angegeben wurde, dann beenden
    if(!logLevel) return false;
    // Wenn kein Log-Level gesetzt nehme das globale Loglevel (standard: kein logging)
    if(conf.level == null || conf.level == undefined || this.globalLogLevel == true) conf.level = this.level;
    // Stimmt f����������������������r die Nachricht das Log-Level?
     if (logLevel >= conf.level && conf.level > 0) {
       
       // Custom-Console setzen wenn n��������tig
       try {
         if(console == undefined) console = false;
         } catch(e) {
           console = false;
         }
       var logConsole = (conf.appender) ? conf.appender : console;
       if(logConsole === false) return false;
       
       // Zeit erfassen f��������r Logausgabe wenn gewollt
       var now = new Date();
       if(this.showSinceStart == true) {
         var sinceStart =  now.getTime() - this.startTime;
         if( sinceStart > 0) sinceStart /= 1000;
         sinceStart = "["+sinceStart+"s]";
       } else { sinceStart = "";}
       if(this.showDate == true) {
         var hours = (now.getHours() >= 10) ? now.getHours() : "0"+now.getHours();
         var mins = (now.getMinutes() >= 10) ? now.getMinutes() : "0"+now.getMinutes();
         var secs = (now.getSeconds() >= 10) ? now.getSeconds() : "0"+now.getSeconds();
         if(this.showDate2 == true) {
           var day =  days[this.showWeekDay][now.getDay()]+", ";
           var d = (now.getDate() >= 10) ? now.getDate() : "0"+now.getDate();
           var m = ((now.getMonth()+1) >= 10) ? (now.getMonth()+1) : "0"+(now.getMonth()+1);
           var y = now.getFullYear();
         
           var now = "["+day+d+"."+m+"."+y+" | "+hours+":"+mins+":"+secs+"."+now.getMilliseconds()+"]";
         } else {
           var now = "["+hours+":"+mins+":"+secs+"."+now.getMilliseconds()+"]";
         }
         
       } else {
         now = "";
       }
       if(this.showLogName && (conf.name != undefined || this.logName != false)) { 
         if(this.logName != false) logname = "["+this.logName+"]";
         else logname = "["+conf.name+"]";
       } else {logname = "";}
        // Ausnahme f��������r trace, list, xml und log
        if(logLevel == 2 && type && type == "trace") logLevel = 5;
        if(logLevel == 2 && type && type == "list") logLevel = 7;
        if(logLevel == 2 && type && type == "xml") logLevel = 8;
        if(logLevel == 4 && type && type == "log") logLevel = 6;
       
        // Da IE7 und 8 nicht alle nachrichten loggen k��������nnen wird abgefragt, ob die Konsole die Funktion kann
        switch (logLevel) {
          case 1: try{if(!logConsole.info){logConsole.log(now+sinceStart+logname+": ",message);}else{logConsole.info(now+sinceStart+logname+": ",message);}}catch(e){} break;
          case 2: try{if(!logConsole.debug){logConsole.log(now+sinceStart+logname+": ",message);}else{logConsole.debug(now+sinceStart+logname+": ", message);}}catch(e){} break;
          case 3: try{if(!logConsole.warn){logConsole.log(now+sinceStart+logname+": ",message);}else{logConsole.warn(now+sinceStart+logname+": ",message);}}catch(e){} break;
          case 4: try{if(!logConsole.error){logConsole.log(now+sinceStart+logname+": ",message);}else{logConsole.error(now+sinceStart+logname+": ",message);}}catch(e){} break;
          case 5: try{if(!logConsole.trace){logConsole.log(now+sinceStart+logname+": ",message);}else{logConsole.trace(message);}}catch(e){} break;
          case 6: try{if(!logConsole.log){}else{logConsole.log(now+sinceStart+logname+": ",message);}}catch(e){} break;
          case 7: try{if(!logConsole.dir){logConsole.log(now+sinceStart+logname+": ",message);}else{logConsole.dir(message);}}catch(e){} break;
          case 8: try{if(!logConsole.dirxml){logConsole.log(now+sinceStart+logname+": ",message);}else{logConsole.dirxml(message);}}catch(e){} break;
        }
      }
  };
  
  /**
   * Setzt das Log-Level des Loggers, das zur��������ckgegeben wird, wenn die Konfiguration kein Loglevel hat (globales Loglevel)
   * @param level Log-Level des Loggers (m��������glich sind info,debug,warn und error und none/no/false)
   */
  this.setLogLevel = function(level) {
  
    switch(level) {
      case "info" : this.level = 1; return true; break;
      case "debug" : this.level = 2;return true; break;
      case "warn" : this.level = 3; return true; break;
      case "warning" : this.level = 3;return true; break;
      case "error" : this.level = 4; return true;break;
      case "none" : this.level = 0; return true;break;
      case "no" : this.level = 0; return true;break;
      case "false" : this.level = 0;break;
      default: this.level = 0; return false; break;
    }
  };
  /**
   * Gibt die Loglevel-Nummer f��������r ein Log-Level zur��������ck
   * @param level Log-Level des Loggers (m��������glich sind info,debug,warn und error, none/no/false und inherit)
   */
  this.getLevelNumber = function(level) { 
    switch(level) {
    case "info" : return 1; break;
    case "debug" : return 2; break;
    case "warn" : return 3; break;
    case "warning" : return 3; break;
    case "error" : return 4;break;
    case "none" : return 0; break;
    case "no" : return 0;break;
    case "false" : return 0;break;
    case "inherit" : return this.level;break;
    default: return 0; break;
  }};
 
 /**
  * Erm��������glicht die globalen Log-M��������glichkeiten umzustellen
  * @param options Ein JSON-Object mit Optionen
  */
 this.setLogOptions = function(options) {
   if(options['logName'] != undefined && typeof options['logName'] == "string" ) this.logName = options['logName'];
   if(options['level'] != undefined && typeof options['level'] == "string" ) this.setLogLevel(options['level']);
   if(options['showDate'] != undefined && typeof options['showDate'] == "boolean" ) this.showDate = options['showDate'];
   if(options['showDate2'] != undefined && typeof options['showDate2'] == "boolean" ) this.showDate2 = options['showDate2'];
   if(options['showSinceStart'] != undefined && typeof options['showSinceStart'] == "boolean" ) this.showSinceStart = options['showSinceStart'];
   if(options['showLogName'] != undefined && typeof options['showLogName'] == "boolean" ) this.showLogName = options['showLogName'];
   if(options['customConsole'] != undefined && typeof options['customConsole'] == "object" ) this.customConsole = options['customConsole'];
   if(options['showWeekDay'] != undefined && typeof options['showWeekDay'] == "boolean" ) this.showWeekDay = options['showWeekDay'];
   if(options['globalLogLevel'] != undefined && typeof options['globalLogLevel'] == "boolean" ) this.globalLogLevel = options['globalLogLevel'];   
 };

   
};

/**
 * Wird vom Logger mit den Methode getLogger() zur��������ckgegeben
 * @param configs Konfigurationen f��������r die Logger Instanz
 * @param logObj Bezugsobjekt zu dem Logger
 * @return {LoggerInstance}
 */
function LoggerInstance(configs, logObj) {
  
  var conf;
  var logObj;
  
  var __construct = function(argConfigs, argLogObj) {
     conf = argConfigs;
     logObj = argLogObj;
  };
  
  
  /**
   * Erm��������glicht die globalen Log-M��������glichkeiten umzustellen
   * @param options Ein JSON-Object mit Optionen
   */
  this.setLogOptions = function(options) {
    if(options['logName'] != undefined && typeof options['logName'] == "string" ) conf.name = options['logName'];
    if(options['level'] != undefined && typeof options['level'] == "string" ) this.setLogLevel(options['level']);
    if(options['appender'] != undefined && typeof options['appender'] == "object" ) conf.appender = options['appender'];
    if(options['name'] != undefined && typeof options['name'] == "name" ) conf.name = options['name'];
  };
  
  /**
   * Setzt das Log-Level des Loggers, das zur��������ckgegeben wird, wenn die Konfiguration kein Loglevel hat
   * @param level Log-Level des Loggers (m��������glich sind info,debug,warn und error und none/no/false)
   */
  this.setLogLevel = function(level) {
  
    switch(level) {
      case "info" : conf.level = 1; return true; break;
      case "debug" : conf.level = 2;return true; break;
      case "warn" : conf.level = 3; return true; break;
      case "warning" : conf.level = 3;return true; break;
      case "error" : conf.level = 4; return true;break;
      case "none" : conf.level = 0; return true;break;
      case "no" : conf.level = 0; return true;break;
      case "false" : conf.level = 0;break;
      case "inherit" : conf.level = logObj.level;break;
      default: conf.level = 0; return false; break;
    }
  };
  
//Alle Log-Methoden
  this.info = function(msg) {var mess; if(arguments.length > 1)mess = arguments; else mess = msg; logObj.info(mess, conf); };
  this.debug = function(msg) {var mess; if(arguments.length > 1)mess = arguments; else mess = msg; logObj.debug(mess, conf); };
  this.trace = function(msg) {var mess; if(arguments.length > 1)mess = arguments; else mess = msg; logObj.trace(mess, conf); };
  this.warn = function(msg) {var mess; if(arguments.length > 1)mess = arguments; else mess = msg; logObj.warn(mess, conf); };
  this.error = function(msg) {var mess; if(arguments.length > 1)mess = arguments; else mess = msg; logObj.error(mess, conf); };
  this.log = function(msg) {var mess; if(arguments.length > 1)mess = arguments; else mess = msg; logObj.log(mess,conf); };
  this.list = function(msg){var mess; if(arguments.length > 1)mess = arguments; else mess = msg; logObj.list(mess, conf); };
  this.xml = function(msg){var mess; if(arguments.length > 1)mess = arguments; else mess = msg; logObj.xml(mess, conf); };
  
  __construct(configs, logObj);
}/* SVN FILE:   $Id: AbstractComponent.js 111 2011-11-28 12:33:45Z g.meyer $
 * SVN HEADER: 1.1
 ***
 * $title           HTMLAppender
 *
 * $description
 * Eine Log-Konsole, die auf HTML-Ebene Log-Nachrichten ausgeben kann
 * Kann mit der Logger-Klasse gekoppelt werden.
 * Alle Log-Nachrichten, die vor dem Laden des Dokumentes angestossen werden, werden nachtr����glich ins Log-Interface geschrieben,
 * sobald dieses geladen wurde.
 *
 * $author          g.meyer
 * $copyright       Babiel GmbH
 * $version         $Revision: 111 $
 * $modifiedby      $LastChangedBy: g.meyer $
 * $lastmodified    $LastChangedDate: 2011-11-28 13:33:45 +0100 (Mo, 28 Nov 2011) $
 * $filesource      $HeadURL: http://svn.babiel.com/JavaScript_Base/trunk/Projekte/ComponentExamples/AbstractComponent/AbstractComponent.js $
 * $keywords        Logger, HTML
 * $require         Logger
 *
 */



function HTMLAppender(args) {
  
  var containerCreated = false;
  
  this.inter = false;
  this.containerWidth;
  this.logContainer;
  this.css;
  // HTML Appender kann nur gesehen werden wenn Dokument vollstaendig geladen wurde. Somit muessen Messages evtl. nachgepusht werden
  this.messages = [];
  
  var tempArgs;
  
  
  var __construct = function(argOptions) {
      argOptions = (argOptions) ? argOptions : {};  
      I.containerWidth = (argOptions.logWidth) ? argOptions.logWidth : 400;    
      if(argOptions.cssClass) 
      I.css = argOptions.cssClass; 
      tempArgs = argOptions;
      // HTML Appender kann nur gesehen werden wenn Dokument vollstaendig geladen wurde
      $(document).ready(I.onLoaded);  
  };
  
  /**
   * HTML Appender kann erst erscheinen, wenn das Dokument geladen wurde
   */
  this.onLoaded = function() {
    if(!tempArgs.outputElement || !tempArgs.outputElement.tagName) createContainer();
    else I.inter = tempArgs.outputElement;
    createDrag();
    // Nachrichten nachschieben, die vor dem Laden des Dokumentes geschrieben werden sollten
    for(var i=0; i < I.messages.length; i++) {
      var msg = I.messages[i];
      I.write(msg.pre, msg.message, msg.level, msg.color);
    }
    I.messages = null;
  };
  
  
  
  
  /**
   * Falls kein Element zum anh����ngen der Log-Nachrichten existiert wird einer erstellt  
   */
  var createContainer = function() {
     I.inter = document.createElement("div");
     $(I.inter).css({
       "position" : "absolute",
       "top" : "0px",
       "left" : "200px",
       "width" : I.containerWidth
     });
     $("body").append(I.inter);
     
  };
  
  /**
   * Den Debug-Container Draggable machen
   */
  var createDrag = function() {
    try {
    $(I.inter).easydrag();
    } catch(e){
      alert("HTML Appender: Easy Drag wasn't found. HTML Appender needs jQuery easydrag Plugin for drag & drop function.");
    }
  };
  
  this.debug = function(pre, message) { this.write(pre, message, "DEBUG", "#33BB55");};
  this.error = function(pre, message) { this.write(pre, message, "ERROR", "#BB5555");};
  this.warn = function(pre, message) { this.write(pre, message, "WARN" , "#AAAA33");};
  this.info = function(pre, message) { this.write(pre, message, "INFO", "#5599DD");};
  this.log = function(pre, message) { this.write(pre, message, "LOG", "#557788");};
  this.write = function(pre, message, level, color) {
    if(!containerCreated) {
      // Wenn Container nicht existiert Nachrichten Zwischenspeichern und sp����ter ausgeben lassen
      this.messages.push({
        "pre" : pre,
        "message" : message,
        "color" : color,
        "level" : level        
      });
      return false;
    }
    if(this.inter != false) { 
      if(typeof message == "function") message = "<pre>"+message+"</pre>";
      var cssClass = (level == "LOG") ? "" : level.toLowerCase()+"Message";
      var spanStyle = (this.css) ? "" : "style='padding: 0.1em; display: block; background-color: "+color+"; color: white; border-bottom: 1px solid black; text-align: center; font-weight: bold;'";
      pre = "<span "+spanStyle+" class='"+(level.toLowerCase())+"Message'>"+level+": "+pre+"</span>";
      if(typeof message == "object") message = this.objToString(message);
      var style = (this.css) ? "class='"+this.css+"'" : "style='width: "+this.containerWidth+"px; background-color: #DDEEFF; border: 1px solid black; margin-bottom: 0.3em; max-height: "+(Math.round(this.containerWidth/1.5))+"; overflow-y: auto;'";
      this.inter.innerHTML += "<div "+style+">"+pre+"<p>"+message+"</p></div>";
    }
  }; 
  
  /**
   * Wandelt Nachrichten vom Typ object in etwas lesbares um
   */
  this.objToString = function(obj, space, type) {
    var maxDeep = 7 * (2);
    var message = "";
    var startSpace = (type == "array") ? space : "";
    space = (space == null || space == undefined) ? "" : space;
    //Ist array?
    if(obj.push != undefined && obj.push != null) {
      // Ist Array
      message += startSpace+"[<br/>";
      for (var i=0; i < obj.length; i++) {
        // ist das Kindobject auch vom Typ Objekt?
        if(typeof obj[i] == "object"){ if(space.length < maxDeep) { message  += this.objToString(obj[i], "&nbsp;&nbsp;"+space, "array"); } else { message += "&nbsp;&nbsp;"+space+"Object...<br/>";  } }
        else message += "&nbsp;&nbsp;"+space+obj[i]+"<br/>";
      }
      message += space+"]<br/>";
    } else {
      // Ist Hash-Map
      
      // Wenn das Objekt ein HTML-Element dann nur ausgeben, wenn es auf der ersten Ebene ist.
      if(obj.tagName != null){ 
        if(space.length > 0) { 
          message += startSpace+"Element...<br/>"; 
        } else {
          message += startSpace+obj.tagName+"-Element : {<br/>";
          message += "&nbsp;&nbsp;"+space+"id"+" : "+obj["id"]+"<br/>";
          message += "&nbsp;&nbsp;"+space+"className"+" : "+obj["className"]+"<br/>";
          message += "&nbsp;&nbsp;"+space+"innerHTML"+" : "+obj["innerHTML"]+"<br/>";
          message += startSpace+"}";
        }
      } else{
        if(obj instanceof Event) {
          message += startSpace+"Event Object...<br/>";  
        } else {
          message += startSpace+"{<br/>";
          for (var part in obj) {
            if(typeof obj[part] == "object") {
              if(space.length < maxDeep) { 
                message += "&nbsp;&nbsp;"+space+part+" : "+this.objToString(obj[part], "&nbsp;&nbsp;"+space, "object");
              } else {
                message += "&nbsp;&nbsp;"+space+"Object...<br/>"; 
              } 
            } else { 
              // Funktionen nicht im Objektbereich ausgeben lassen
              if(typeof obj[part] == "function"){
                message += "&nbsp;&nbsp;"+space+part+" : Function...<br/>"; 
              } else {
                
                if(part != "textContent") 
                  message += "&nbsp;&nbsp;"+space+part+" : "+obj[part]+"<br/>";
              }
            }
          }
          message += space+"}<br/>";
        }
      }
    }
    
    return message;
  };
  
  
  var I = this;
  if(this == window) {
    throw new Error("HTML Appender was called as function");
  } else {
    __construct(args);    
  }
  
}
/* SVN FILE:   $Id: AbstractComponent.js 111 2011-11-28 12:33:45Z g.meyer $
 * SVN HEADER: 1.1
 ***
 * $title           Utils
 *
 * $description
 *   Diese Datei beinhaltet nuetzliche Javascript Funktionen
 *
 * $author          g.meyer
 * $copyright       Babiel GmbH
 * $version         $Revision: 111 $
 * $modifiedby      $LastChangedBy: g.meyer $
 * $lastmodified    $LastChangedDate: 2011-11-28 13:33:45 +0100 (Mo, 28 Nov 2011) $
 * $filesource      $HeadURL: http://svn.babiel.com/JavaScript_Base/trunk/Projekte/ComponentExamples/AbstractComponent/AbstractComponent.js $
 * $keywords        Utils
 * $require         
 *
 */



/**
 * Dummylogger, falls das Logging Framework nicht benutzt werden soll
 * Diese Funktion verhindert, dass Fehler auftreten, wenn keine richtige Log-Instanz zum Loggen vorhanden ist.
 * @return
 */
function DummyLogger() {
  this.info = function() {};
  this.debug = function() {};
  this.trace = function() {};
  this.warn = function() {};
  this.error = function() {};
  this.log = function() {};
  this.list = function(){};
  this.xml = function(){};
}


//Um den Objektnamen auch in IE auslesen zu k����nnen
Function.prototype.isnamed= function(){
  var M= this.toString().match(/function\s+([\w\$]+)\s*\(/) || '';
  return M? M[1]: '';
}; 

// JQuery Drag & Drop
/**
* EasyDrag 1.5 - Drag & Drop jQuery Plug-in
*
* Thanks for the community that is helping the improvement
* of this little piece of code.
*
* For usage instructions please visit http://fromvega.com/scripts
*/
try {
(function($){

  // to track if the mouse button is pressed
  var isMouseDown    = false;

  // to track the current element being dragged
  var currentElement = null;

  // callback holders
  var dropCallbacks = {};
  var dragCallbacks = {};
  
  // bubbling status
  var bubblings = {};

  // global position records
  var lastMouseX;
  var lastMouseY;
  var lastElemTop;
  var lastElemLeft;
  
  // track element dragStatus
  var dragStatus = {};  

  // if user is holding any handle or not
  var holdingHandler = false;

  // returns the mouse (cursor) current position
  $.getMousePosition = function(e){
    var posx = 0;
    var posy = 0;

    if (!e) var e = window.event;

    if (e.pageX || e.pageY) {
      posx = e.pageX;
      posy = e.pageY;
    }
    else if (e.clientX || e.clientY) {
      posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
      posy = e.clientY + document.body.scrollTop  + document.documentElement.scrollTop;
    }

    return { 'x': posx, 'y': posy };
  };

  // updates the position of the current element being dragged
  $.updatePosition = function(e) {
    var pos = $.getMousePosition(e);

    var spanX = (pos.x - lastMouseX);
    var spanY = (pos.y - lastMouseY);

    $(currentElement).css("top",  (lastElemTop + spanY));
    $(currentElement).css("left", (lastElemLeft + spanX));
  };

  // when the mouse is moved while the mouse button is pressed
  $(document).mousemove(function(e){
    if(isMouseDown && dragStatus[currentElement.id] != 'false'){
      // update the position and call the registered function
      $.updatePosition(e);
      if(dragCallbacks[currentElement.id] != undefined){
        dragCallbacks[currentElement.id](e, currentElement);
      }

      return false;
    }
  });

  // when the mouse button is released
  $(document).mouseup(function(e){
    if(isMouseDown && dragStatus[currentElement.id] != 'false'){
      isMouseDown = false;
      if(dropCallbacks[currentElement.id] != undefined){
        dropCallbacks[currentElement.id](e, currentElement);
      }

      return false;
    }
  });

  // register the function to be called while an element is being dragged
  $.fn.ondrag = function(callback){
    return this.each(function(){
      dragCallbacks[this.id] = callback;
    });
  };

  // register the function to be called when an element is dropped
  $.fn.ondrop = function(callback){
    return this.each(function(){
      dropCallbacks[this.id] = callback;
    });
  };
  
  // disable the dragging feature for the element
  $.fn.dragOff = function(){
    return this.each(function(){
      dragStatus[this.id] = 'off';
    });
  };
  
  // enable the dragging feature for the element
  $.fn.dragOn = function(){
    return this.each(function(){
      dragStatus[this.id] = 'on';
    });
  };
  
  // set a child element as a handler
  $.fn.setHandler = function(handlerId){
    return this.each(function(){
      var draggable = this;
      
      // enable event bubbling so the user can reach the handle
      bubblings[this.id] = true;
      
      // reset cursor style
      $(draggable).css("cursor", "");
      
      // set current drag status
      dragStatus[draggable.id] = "handler";

      // change handle cursor type
      $("#"+handlerId).css("cursor", "move"); 
      
      // bind event handler
      $("#"+handlerId).mousedown(function(e){
        holdingHandler = true;
        $(draggable).trigger('mousedown', e);
      });
      
      // bind event handler
      $("#"+handlerId).mouseup(function(e){
        holdingHandler = false;
      });
    });
  };

  // set an element as draggable - allowBubbling enables/disables event bubbling
  $.fn.easydrag = function(allowBubbling){

    return this.each(function(){

      // if no id is defined assign a unique one
      if(undefined == this.id || !this.id.length) this.id = "easydrag"+(new Date().getTime());
      
      // save event bubbling status
      bubblings[this.id] = allowBubbling ? true : false;

      // set dragStatus 
      dragStatus[this.id] = "on";
      
      // change the mouse pointer
      $(this).css("cursor", "move");

      // when an element receives a mouse press
      $(this).mousedown(function(e){
        
        // just when "on" or "handler"
        if((dragStatus[this.id] == "off") || (dragStatus[this.id] == "handler" && !holdingHandler))
          return bubblings[this.id];

        // set it as absolute positioned
        $(this).css("position", "absolute");

        // set z-index
        $(this).css("z-index", parseInt( new Date().getTime()/1000 ));

        // update track variables
        isMouseDown    = true;
        currentElement = this;

        // retrieve positioning properties
        var pos    = $.getMousePosition(e);
        lastMouseX = pos.x;
        lastMouseY = pos.y;

        lastElemTop  = this.offsetTop;
        lastElemLeft = this.offsetLeft;

        $.updatePosition(e);

        return bubblings[this.id];
      });
    });
  };

})(jQuery);
} catch(e) {}

/**
 * Wandelt einen relativen in einen absoluten Pfad um
 * @param url
 * @return
 */
function getAbsolutePath(url){
  if(url.match(/^(http:|https:|ftp:|mailto:)/)) return url;
  var loc = window.location;
  var path = loc.pathname.replace("\\","/");
  
  var splittedUrl = url.replace("\\","/").split("/");
  if(splittedUrl.length > 0) {
    if(splittedUrl[0] == "") {
      url = splittedUrl.join("/");
      return loc.protocol+"//"+loc.host+url;
    }
    
    if(splittedUrl[0] == ".") {
      splittedUrl.shift();
      url = splittedUrl.join("/");
      return loc.protocol+"//"+loc.host+path+url;
    }
    
    var pathArray = path.split("/");
    var extractParts = 0;
    for(var i=0; i < splittedUrl.length; i++) {
      if (splittedUrl[i] == "..") {
        url = url.substr(3);
        extractParts++;             
      } 
    }
    if (pathArray.length - (1 + extractParts) >= 0) {
      path = pathArray.slice(0, (pathArray.length - 1 - extractParts));
      path = path.join("/");
      path +="/";
    }
    else {
      path = "/";
    }
    return loc.protocol+"//"+loc.host+path+url;    
  } 
}
/* SVN FILE:   $Id: AbstractComponent.js 111 2011-11-28 12:33:45Z g.meyer $
 * SVN HEADER: 1.1
 ***
 * $title           EventHandler
 *
 * $description
 *   Der Event-Handler kann in Klassen zum Einsatz kommen und wird f����r automatisches Registrieren von Events verwendet.
 *   Dieser Handler verh����lt sich vergleichsweise ����hnlich wie der des alten Komponenten-Frameworks.
 *
 * $author          g.meyer
 * $copyright       Babiel GmbH
 * $version         $Revision: 111 $
 * $modifiedby      $LastChangedBy: g.meyer $
 * $lastmodified    $LastChangedDate: 2011-11-28 13:33:45 +0100 (Mo, 28 Nov 2011) $
 * $filesource      $HeadURL: http://svn.babiel.com/JavaScript_Base/trunk/Projekte/ComponentExamples/AbstractComponent/AbstractComponent.js $
 * $keywords        Framework, Event, Handler
 * $require         -
 *
 */


function EventHandler() {
  
  this.events = {};
  
    
  this.setup = function(events) {
     for(var ev in events ) {
       ev = events[ev];
        if(ev['elements'] && ev['function'] && (typeof ev['function'] == "function" || typeof ev['function'] == "object") && typeof ev['event'] == "string") {
          this.events[ev] = {
            "data" : (ev['data']) ? ev['data'] : false,
            "elements" : ev['elements'],
            "function" : ev['function']
          };
          
          // Bind events to Elements
          // Ausnahme: Wenn document.ready aufgerufen werden soll
          if(jQuery) {
            if(ev['elements'] === document && ev['event'] == "ready") {
              if(jQuery.isReady) {
                ev['function']();
              } else {
                $(document).ready(ev['function']);
              }
            } else {
              var params = (ev['data'] !== undefined) ? ev['data'] : { "self" : this };
              $(ev['elements']).unbind(ev['event'], ev['function']).bind(ev['event'], params, ev['function']);
            }
          } else {
            // No jQuery Variante
            var elements = [];
            
            // Element(e) wurden angegeben
            if(typeof ev['elements'] == "object") {
              if(ev['elements'].length == undefined) elements.push(ev['elements']);
              else elements = ev['elements'];   
            }
            
            // Selector wurde angegeben
            if(typeof ev['elements'] == "string") {
              if(ev['event'] != "ready" && ev['event'] != "load") {
                // Id 
                if(ev['elements'][0] == "#") {
                  elements.push(document.getElementById(ev['elements'].substr(1)));
                }
                else if(ev['elements'][0] == ".") {
                  elements = document.getElementsByClassName(ev['elements'].substr(1));
                } else {
                  elements = document.getElementsByTagName(ev['elements']);
                }
              } else {
                elements.push(window); 
                ev['type'] = "load";
              }
              
            }
            
            // Elemente binden
            for(var el in elements) {
              if(elements[el].addEventListener) {
               //Firefox, Chrome etc.
               elements[el].addEventListener(ev['event'], ev['function'], false); 
              } else {
               //IE
                elements[el].attachEvent("on"+ev['event'], ev['function']); 
              }
              
            }
            
            
          }
          
          
          
        }
        
     }
  };
  
  
  
}function AbstractComponent() {
  // Die Abstract-Klasse wird nur durch Hauptkomponenten erweitert
}
//Abstract.prototype.validator = new Validator();
AbstractComponent.prototype.eventHandler = new EventHandler();

window._logging = new Logger();/**
 * @author g.meyer
 */
function PrintPreviewComponent(config) {
  
  var options;
  var data;
  var switchIndex = 0;
  var log;
  
  var __construct = function(argOptions) {
    options = {  
      "event" : {
        "init" : {
          "function" : setEventHandler,
          "elements" : document,
          "event" : "ready",
          "data" : {"self" : I}
        }

      },
      "content" : {
        "cssIncludeElement" : "",
        "triggerOnElement" : "",
        "triggerOffElement" : "",
        "mediaSwitch" : ["all","print"],
        "callFunctions" : [
          "showImagesSources",
          "showLinkUrls"
        ]                          
      },
      "functions" : {
        "showImagesSources" : {
          "selector" : "img",
          "excludeClass" : "noImgSource",
          "cssClass" : "imgSources",
          "function" :  [
            I.showImagesSources,
            I.deleteImagesSources
          ]
        },
        "showLinkUrls" : {
          "selector" : "a",
          "excludeClass" : "noLinkSource",
          "cssClass" : "aSources",
          "function" :  [
            I.showLinkUrls,
            I.deleteLinkUrls
          ]
        }
      }
    };
    $.extend(true, options, argOptions);
    try {log = (options.debug != undefined)? window._logging.getLogger(options.debug) : window._logging; } catch(e) { log = new DummyLogger(); }
    // Event-Handler
    if(options.event != undefined) I.eventHandler.setup(options.event);     
        
  };
  
  
  /**
   * Legt einen Event-Handler auf einen Link
   */
  var setEventHandler = function() {
    log.debug("setEventHandler");
    $(options.content.triggerOnElement).click(I.activatePreview);
    $(options.content.triggerOffElement).click(I.deactivatePreview);
  };
  
  /**
   * Wechselt das Media Attribute f��r eine CSS-Datei
   */
  this.activatePreview = function() {
    $(options.content.cssIncludeElement).attr("media", options.content.mediaSwitch[switchIndex]);
    // Alle Funktionen aufrufen, die aufgerufen werden sollen
    for(var i=0; i < options.content.callFunctions.length; i++) {
      try {
        options.functions[options.content.callFunctions[i]]['function'][switchIndex]();
      } catch(e) {}
    }
    switchIndex = 1;
    return false;
  };
  
  this.deactivatePreview = function() {
    $(options.content.cssIncludeElement).attr("media", options.content.mediaSwitch[switchIndex]);
    // Alle Funktionen aufrufen, die aufgerufen werden sollen
    for(var i=0; i < options.content.callFunctions.length; i++) {
      try {
        options.functions[options.content.callFunctions[i]]['function'][switchIndex]();
      } catch(e) {}
    }
    switchIndex = 0;
    return false;
  };
  
  /**
   * Erstellt Spans mit den Bild-Urls direkt neben Bild
   */
  this.showImagesSources = function() {
     data = options.functions.showImagesSources;
     $(data.selector).each(function(index, element) {
       var loc = window.location; 
       if(!$(element).hasClass(data.excludeClass) && $(element).css("display") != "none" && $(element).css("visibility") != "hidden")
       $("<span class='"+data.cssClass+"'>"+getAbsolutePath($(element).attr("src"))+"</span>").insertAfter(element);  
     });
  };
  
  /**
   * Entfernt die f��r die Druckvorschau erzeugten Bild-Sourcen
   */
  this.deleteImagesSources = function() {
    var data = options.functions.showImagesSources;
     $("."+data.cssClass).remove();
  };
  
  /**
   * Erstellt Spans mit den Link-Urls direkt neben dem Link
   */
  this.showLinkUrls = function() {
     data = options.functions.showLinkUrls;
     $(data.selector).each(function(index, element) {
       if(!$(element).hasClass(data.excludeClass) && $(element).css("display") != "none" && $(element).css("visibility") != "hidden")
       $("<span class='"+data.cssClass+"'>"+getAbsolutePath($(element).attr("href"))+"</span>").insertAfter(element);  
     });
  };
  
  /**
   * Entfernt die f��r die Druckvorschau erzeugten Link-Urls
   */
  this.deleteLinkUrls = function() {
    var data = options.functions.showLinkUrls;
     $("."+data.cssClass).remove();
  };
  
  
  var I = this;
  __construct(config);
}
PrintPreviewComponent.prototype = new AbstractComponent();/* SVN FILE:   $Id: BookmarkComponent.js 584 2011-11-28 12:33:47Z g.meyer $
 * SVN HEADER: 1.0
 ***
 * $title           BookmarkComponent
 *
 * $description
 *    Funktionalit��t "Bookmark"...
 *
 *
 * $package         com.babiel.brd.js
 * $classname       BookmarkComponent
 * $author          a.rouel
 * $copyright       $Copyright$
 * $version         $Revision: 584 $
 * $lastrevision    $Date: 2011-11-28 13:33:47 +0100 (Mo, 28 Nov 2011) $
 * $modifiedby      $LastChangedBy: g.meyer $
 * $lastmodified    $LastChangedDate: 2011-11-28 13:33:47 +0100 (Mo, 28 Nov 2011) $
 * $filesource      $URL: http://svn.babiel.com/BAFA/trunk/Projekte/JavascriptComponents/src/BookmarkComponent.js $
 * $keywords        Such-Komponente, Suche, Schnellsuche
 * $require         com.babiel.application.jsctrl
 *
 */

/**
 * Funktionalit��t "Bookmark"...
 * 
 * @author s.schweminski edited by g.meyer
 * @class
 * @param {String} bookmarkButton <i>Selector</i>
 * 
 */
function BookmarkComponent(config ) {
  
  /**
   * Attribut f��r Funktionen die w��rend der Laufzeit von dieser 
   * Instanz kreiert werden und Zugriff auf andere Methoden 
   * ben��tigen (z.B. EventHandler-Funktionen).
   */
  var I;   
  
  /**
   * Selector des Parameters bookmarkMenuBoxId
   */
  var bookmarkMenuSelector;
  
  /**
   * JSON-Konfiguration
   */
  var options;
  
  var log;
  
  /**
   * Konstruktor-Funktion
   */
  var __construct = function(argOptions) {
    
    
    options = { // JSON
        event : { // Konfiguration automatisch zu verarbeiteten Ereignissen
          "init" : { // Bezeichnung des Ereignisses
            "data" : { "self" : I }, // Beinhaltet optional zu ��bergebende Werte der Ereignisbehandlungsroutine
            "function" : I.onEventInit, // Auszuf��hrende Funktion bei Eintritt des Ereignisses
            "event" : "ready", // Ereignistyp
            "elements" : document // <i>Selector</i> zum Ereignis gekoppelten Element
          },
          "openMenu" : { // Bezeichnung des Ereignisses
            "data" : { "self" : I }, // Beinhaltet optional zu ��bergebende Werte der Ereignisbehandlungsroutine
            "function" : I.onEventOpenMenu, // Auszuf��hrende Funktion bei Eintritt des Ereignisses
            "event" : "click", // Ereignistyp
            "elements" : "" // <i>Selector</i> zum Ereignis gekoppelten Element
          }          
        },
        content : { // Konfiguration zu verwendeten Inhaltsbereichen
          bookmarkButtonSelector : "",
          bookmarkMenuBoxId : "bookmarkMenuBox",
          closeButtonId  : "at16ptx",
          classToRemove : "displayNone"
        }
      };

    $.extend(true, options, argOptions);
    try {log = (options.debug != undefined)? window._logging.getLogger(options.debug) : window._logging; } catch(e) { log = new DummyLogger(); }
    // Event-Handler
    if(options.event != undefined) I.eventHandler.setup(options.event);   
    try { setup(); } catch(e) {}
  };
  
  
  /**
   * <strong>Ereignisbehandlungsroutine</strong>
   * ��ffnet den zugeh��rigen Navigationspunkt des ausl��senden Elements.
   *
   * @param {Event} event <i>jQuery.Event</i>
   * @return {Boolean} <code>false</code>
   */
  this.onEventOpenMenu = function(event) {
    log.debug("opening bookmark menu. " + event.type );
    try {
      I.openMenu(this);      
    } catch(e) {
      log.warn("Catched exception: " + e);
    }
  };
  
  this.onEventClickOpenMenu = function (event){
    var isTargetOutSideOfButtonSelector = true;
    $(options.content.bookmarkButtonSelector).each(function() {
      if($(options.content.bookmarkButtonSelector).index(event.target) !== -1 || $(options.content.bookmarkButtonSelector).index($(event.target).parent()) !== -1) {
        isTargetOutSideOfButtonSelector = false;
      }
    });

    if ( isTargetOutSideOfButtonSelector && $(I.bookmarkMenuBoxSelector).has(event.target).length == 0) {
      log.debug("close bookmark menu. " + event.type );
      I.closeMenu();
      $("html").unbind("click",I.onEventClickOpenMenu);
    }    
  };

  this.openMenu = function(element) {
    log.debug("openMenu");
    if(typeof element !== "object") {
      throw TypeError("Argument \"element\" is not an object.");
    }
    var pos = $(element).position();
    var posLeft = pos.left;
    var posTop = pos.top + $(element).height();
    
    $(I.bookmarkMenuBoxSelector).css({"position":"absolute", "top": posTop, "left": posLeft});
    $("html").bind("click",I.onEventClickOpenMenu);
    
    if($(I.bookmarkMenuBoxSelector).hasClass(options.content.classToRemove)) {
      $(I.bookmarkMenuBoxSelector).removeClass(options.content.classToRemove);
    }
    
    $(I.bookmarkMenuBoxSelector).show();
  };
  
  this.closeMenu = function() {
    $(I.bookmarkMenuBoxSelector).hide();
  };

  this.includeBookmarkLinkBox = function() {
    bookmarkMenu = I.generateBookmarkBox();
    $("body").append(bookmarkMenu);
    I.includeBookmarkServiceScript();
    
  };

  this.includeBookmarkServiceScript = function() {
    if (window.addthis){
      window.addthis = null;
    }
    var addthisUrl = options.menu.bookmarkServiceScriptUrl + "&domready=1";
    $.getScript(options.menu.bookmarkServiceScriptUrl,function() {
      if(!options.menu.loadMenuOnInit) {
        $(I.bookmarkMenuBoxSelector).show();
      }
    });
  };

  this.onEventInit = function(event) {
    $("#" + options.content.closeButtonId).bind("click",function (){I.closeMenu();});
  };

  /**
   * Integriert die Funktionalit��t der Komponente in das HTML-Dokument.
   */
  var setup = function() {
    $(options.content.bookmarkButtonSelector).attr("href","javascript:void(0)");
    I.bookmarkMenuBoxSelector = "#" + options.content.bookmarkMenuBoxId;
    var bookmarkMenuBoxHtml = $("body").find(I.bookmarkMenuBoxSelector).parent().html();
    $("body").remove(I.bookmarkMenuBoxSelector);
    //$(options.content.bookmarkButtonSelector).parent().append(bookmarkMenuBoxHtml);
    
  };
  
  
  var I = this;
  __construct(config);

  
};
BookmarkComponent.prototype = new AbstractComponent();
function InitialValue(config) {
 
  var options;
  var log;
 
  var __construct = function(argOptions) {
     options = {
       "event" : {
        "init" : {
          "function" : I.onEventInit,
          "elements" : document,
          "event" : "ready",
          "data" : {"self" : I}
 
        }
      },
      "inputElement" : "",
      "initText" : "",
      "debug" : "InitialValue" // Es muss vorher eine Logger-Konfiguration mit diesem Namen hinzugef����gt werden
     };
 
    // Options um Config erg����nzen
    $.extend(true,options, (argOptions) ? argOptions : {});
    //Log setzen
    try {log = (options.debug != undefined && window._logging.getLogger(options.debug) != false)? window._logging.getLogger(options.debug) : window._logging;} catch(e) { log = new DummyLogger(); }
    try {log.logName = "[InitialValue]"; } catch(e){}
    // Event-Handler
    if(options.event != undefined) I.eventHandler.setup(options.event);
  };
 
 
  this.onEventInit = function() {
  	log.debug("::onEventInit");
    $(options.inputElement).focus(I.checkFocus).blur(I.checkBlur);
    fillField();
  };
 
 this.checkBlur = function() {
   if($(this).attr("value") == "") fillField();
 };
 
 this.checkFocus = function() {
   if($(this).attr("value") == options.initText) emptyField();
 };
 
 var fillField = function() {
 	$(options.inputElement).attr("value", options.initText);
 };
 
  var emptyField = function() {
  	$(options.inputElement).attr("value", "");
  };
 
 
  // Call Construct
  var I = this;
  if(this == window) {
    throw new Error("InitialValue was called as function");
  } else {
    __construct(config);
  }
 
}
InitialValue.prototype = new AbstractComponent();
