// {{{ setup
if(typeof(SWO) != 'object')
  SWO = {}; // root of all Classes.

SWO.TOOLS = {};
SWO.SYS   = {};


var tools  = {},   // the System objects.
    sys    = {};  // the Tools objects.
    
    
SWO.TOOLS._setup = function() {
  tools.liveSearch  = new SWO.TOOLS.LiveSearch();  // 
  tools.formPicker  = new SWO.TOOLS.FormPicker();  // tol for 1-n relations (picking a form input value from another table)
  tools.tabs        = new SWO.TOOLS.Tabs();        // window tabs
  tools.editor      = new SWO.TOOLS.Editor();      // load / install/ remove WYSIWYG editor at runtime
  tools.iconDragger = new SWO.TOOLS.IconDragger(); // drag icons from Menu to Desktop
  tools.selector    = new SWO.TOOLS.Selector();    // a form widged 
  tools.sidebar     = new SWO.TOOLS.Sidebar();     // a window Sidebar
}


SWO.SYS._setup = function() {
  sys.console        = new SWO.SYS.Console(); // console for non Firefox Browsers
  sys.keys           = new SWO.SYS.Keys();   // processing keyboard input
  sys.mouse          = new SWO.SYS.Mouse();  // position of last click, what button is pressed right now
  sys.timer          = new SWO.SYS.Timer();  // timeout / interval
  sys.cssBinder      = new SWO.SYS.CssBinder();  // adding css at runtime
  sys.DOMWatchdog    = new SWO.SYS.DOMWatchdog();  // alerts global namespace Pollution at runtime
  sys.event          = new SWO.SYS.Event();         // global Event Routing (bind, unbind, trigger)
  sys.screenObserver = new SWO.SYS.ScreenObserver();  // polls and triggers active window if screen resizes
  sys.plugins        = new SWO.SYS.Plugins(); // check if Plugins are (Flash/reader/...) installed
  sys.tabKeyManager  = new SWO.SYS.TabKeyManager(); // makes the focus stay in a window when using the Tab key
  sys.cookie         = new SWO.SYS.Cookie();
  sys.serverPushPop  = new SWO.SYS.ServerPushPop();
}


var swmPlugins = {}; // for dynamically build- in;


function Void() { /* do nothing */ };

// }}}


// {{{ TOOLS


/// {{{ IconDragger


SWO.TOOLS.IconDragger = function() {
  
  var self = this,
      _pos,
      _unmoved,
      _locked,
      _title,
      _swmObject,
      _image,
      _width,
      _height,
      _obj;
  
  
  this.add = function(obj) {
    obj.onmousedown = self.savePos;
    $(obj).enableDrag(startDrag, drag, stopDrag);
  };
  
  this.savePos = function(e) {
    _pos = sys.mouse.getPos(e);
  };
  
  function startDrag(x, y, e) {
    _unmoved = true;
    _locked  = true;
  }
  
  function drag(mdx, mdy, e) {
    if(_unmoved) {
      initDrag(this);
      _unmoved = false;
    }
    _pos.x += mdx;
    _pos.y += mdy;
    _obj.xMoveBy(mdx, mdy);
  }
  
  function stopDrag(x, y, e) {
    if(_obj) {  _obj.remove(); _obj = false; }
    $(this.parentNode).unbind('mouseout', unlock);
    return _unmoved;
  }
  
  function initDrag(obj) {
    _title = $(obj).text().replace(/^ */,'').replace(/ *$/,'');
    _swmObject = $(obj).children('a').attr('object');
    _image  = $(obj).children('a').attr('image');
    _width  = $(obj).children('a').attr('width');
    _height = $(obj).children('a').attr('height');
    $(obj.parentNode).bind('mouseout', unlock);
    $('#desktop').bind('mouseup', addIcon);
    var c = $('<img src="./templates/CMS/standard/images/drop_down_icon.png" id="theDragImage" />');
    c.addClass('dragElement');
    c.xMoveTo(_pos.x + 5, _pos.y + 17);
    c.appendTo('#desktop');
    _obj = c;
  }
  
  function addIcon() {
    if(! _locked) {
      var img = (_image == 'none') ? '../data/SWM/user.png' : '../templates/images/'+_image.replace(/16/g,'48');
      _pos.x -= 50; 
      _pos.y -= 25;
      swm.d.newIcon(img,'http://www.nadja-palm.de/CMS/CMS_do.php?__id='+_swmObject, _title, _width, _height, _pos);
    }
    $('#desktop').unbind('mouseup', addIcon);
  };
  
  function unlock(e) {
    _locked = false;
  }
  
};


// }}}


// {{{ FormPicker


SWO.TOOLS.FormPicker = function () {
  
  var self     = this,
      _stack   = [],
      _mode    = 'client';
  
  
  this.openServer = function(url, backUrl, stay) {
    _stack.push({mode:'server', backUrl:backUrl, stay:stay});
    Loader.request(url);
  };
  
  
  
  this.openClient = function(callback, stay) {
    _stack.push({mode:'client', callback:callback, stay:stay});
  };
  
  
  this.open = function(field, url, callback) {
    _stack.push({mode:'input', field:field, callback:callback});
    Loader.request(url);
  };
  
  
  this.send = function(id, value, name) {
    var par, op = _stack.pop();
    
    if(!op) return;
    
    switch(op.mode) {
      case 'client':
        op.callback(id, value, name);
        break;
      case 'input':
        if(op.field) {
          op.field.value = value || id;
          $(op.field).trigger('change');
        }
        if(op.callback)
          op.callback(id, value, name);
        break;
      case 'server':
        par = {id:id};
        if((typeof name).match(/string|number/))  par.name  = encodeURI(name);
        if((typeof value).match(/string|number/)) par.value = encodeURI(value);
        Loader.call(op.backUrl, par);
        break;
    }
    if(!op.stay) swm.wm.getActive().close();
    if(op.stay)  stack.push(op);
  };
  
  this.initTable = function(table) {
    if(table.pickerInstalled) return true;
    $('TR', table).initClasses().where(function() { return typeof this.pId != 'undefined';}).bind('dblclick', function(){
      self.send(this.pId, this.pValue, this.pName);
    }).css('cursor', 'pointer');
    table.pickerInstalled = true;
  };
  
};


/// }}}


/// {{{ LiveSearch


SWO.TOOLS.LiveSearch = function () {
  
  var self = this;
  
  this.init = function(input) {
    
    $(input)
      .initClasses()
      .xBind('type', function() {
        
        var par = {fieldValue:this.value,
                   fieldName: this.name,
                   formId:    this.form.getAttribute('id')}
        
        if(this.field) {
          assert(input.form[this.field], 'LiveSearch: field "' + this.field + '" does not exist.');
          par.fieldValue = input.form[this.field].value;
        }
        
        Loader.call(this.url, par, function(data) {
          self.suggest(input, data);
        });
        
        this.onFocusOut = function() {
          if($(this).attr('onFocusOutUrl'))
            Loader.call($(this).attr('onFocusOutUrl'), {fieldValue:this.value, formId:par.formId});
        }
        
      });
  };
  
  
  this.suggest = function(obj, value) {
    var pos = obj.value.length;
    if(value && value.substring(0, pos).toUpperCase() == obj.value.toUpperCase()) {
      obj.value = value;
      if(pos > 0)
        setCursor(obj,pos);
    }
  };
  
  
  function setCursor(obj, pos) {
          obj.selectionStart = pos;
      obj.selectionEnd   = obj.value.length; //alles markieren // pos; 
      }
  
  
  function getCursor(obj) {
          return obj.selectionStart;
      }
  
  
  function sendRequest(obj, url) {
    url = url + '&fieldValue=' + obj.value + '&fieldName=' + obj.name + '&formId=' + obj.form.getAttribute('id');
    Loader.request(url);
  }
  
  
  function getCode(obj) {
    return obj.form.getAttribute('id') + '__' + obj.name;
  }
  
};


/// }}}


/// {{{ Tabs


SWO.TOOLS.Tabs = function() {
  
  var self = this;
  
  self.init = function(tabList) {
    
    var tId = $(tabList).initClasses()[0].tId;
    $('.tab_a', tabList)
      .initClasses()
      .xBind('safeClick', function() {
        self.show(tId + '_' + this.nr, this);
      })
      .each(function(){
        if(this.url)
          Loader.call(this.url);
      });
  };
  
  
  this.show = function(id, a) {
    
    assert((typeof id) == 'string', 'error in tools.tabs.show: id is not a string');
    var _a = $(a);
    if(_a.hasClass('tabDisabled')) return false;
    var tabsId = id.split('_')[0];
    
    if(a.reloadUrl)
      Loader.call(a.reloadUrl);
    
    $('#' + tabsId + ' a').removeClass('tabActive');
    _a.addClass('tabActive');
    
    $('#' + tabsId + '_layers').children().css('display', 'none');
    $('#' + id).css('display', '');
    swm.wm.getActive().onTabChange(a.name);
  };
};


/// }}}


/// {{{ Editor


SWO.TOOLS.Editor = function() {
  
  var self = this,
      mceLoading = false,
      callbacks = [],
      cssStack= {},
      rightURL = 'http://www.nadja-palm.de/CMS/CMS_do.php?__id=828&__action=getAllowedMediaObject',
      mediaId = false;
  
  // // load Editor after n seconds when CMS is loaded.
  // sys.timer.timeout(20000, function(){ requireTinyMCE('advanced'); });
  
  this.css = function(id, css) {
    // console.log('mce css: '+id+' to '+css);
    var instance = tinyMCE.get(id);
    if(!instance) {
      // console.log('mcs css: instance '+id+' not there, to stack');
      cssStack[id] = css;
      return;
    }
    cssStack[id] = null;
    var wd   = instance.getWin().document,
        head = wd.getElementsByTagName('HEAD')[0];
    var cssLink = wd.getElementById('cssLink');
    if(cssLink) {
      head.removeChild(cssLink);
    }
    if(true) {
      $('#menu_'+id+'_'+id+'_styleselect_menu_tbl')
        .find('tr').dump('tiny').each(function(){
          this.parentNode.removeChild(this);
        });
      
      cssLink = wd.createElement('link');
      cssLink.setAttribute('rel', 'stylesheet');
      cssLink.setAttribute('id', 'cssLink');
      head.appendChild(cssLink);
    }
    $(cssLink).attr('href', css)
              .attr('mce_href', css);
    //instance.render();
    instance.nodeChanged();
  };
  
  
   // install a new Editor (called from dom.layer)
  this.add = function(elem, config, css) {
    
    requireTinyMCE(config, function(){
      assert(tinyMCE.getInstanceById(elem.id) == null,'initWYSIWYG, editor already exists');
      var submitFunction = elem.form.onsubmit || function(){};
      elem.form.onsubmit = function () {
        tinyMCE.triggerSave();
        submitFunction.call(this);
        return false;
      };
      tinyMCE.execCommand('mceAddControl', false, elem.id);
      if(css) {
       self.css(elem.id, css);
      }
       // tinyMCE.get(elem.id).init({content_css:css+'.css'});
      //console.log('wysiwyg added: '+elem.id);
    });
        Loader.call(rightURL, function(d){ mediaId = d.mediaId; });
      };
  
  
  this.remove = function (elem) {
    if(!tinyMCE) return;
    tinyMCE.execCommand('mceRemoveControl', false, elem.id);
    cssStack[elem.id] = null;
  };
  
  
  function requireTinyMCE(config, callback) {
    callback = callback || function(){};
    if(typeof(__tinymce_loaded) !== 'object' && !mceLoading) {
      mceLoading = true;
      callbacks.push(callback);
      // insert script tag
      var a = document.createElement('script');
      a.setAttribute('type', 'text/javascript');
      a.setAttribute('src',  '/editors/tinymce/jscripts/tiny_mce/tiny_mce_src.js');
      document.getElementsByTagName('HEAD')[0].appendChild(a);
      
      // polling for tinyMCE object
      sys.timer.interval(250, function(){
        if(typeof(__tinymce_loaded) !== 'object') return;
        this.clear();
        mceLoading = false;
        initMCE(config);
        callbacks.each(function(){ this(); });
      });
      
    } else if(mceLoading) {
      callbacks.push(callback);
    } else {
      callback();
    }
  }
  
  function initMCE(config) {
    
    if(config == 'simple') {
      
      tinyMCE.init({
        forced_root_block : false,
        strict_loading_mode : true,
        mode : "none",
        dialog_type : "window",
        language : "de",
        theme : "simple",
        relative_urls : false,
        convert_urls : false,
        remove_script_host : false,
        verify_html : false,
        remove_script_host : true
        //file_browser_callback : 'tinyMCEFileBrowserCallback',
      });
      
    } else {
      
      tinyMCE.init({
        forced_root_block : false,
        content_css : false,
        strict_loading_mode : true,
        mode : "none",
        dialog_type : "modal",
        language : "en",
        theme : "advanced",
        relative_urls : false,
        convert_urls : false,
        remove_script_host : false,
        verify_html : false,
        file_browser_callback : 'tinyMCEFileBrowserCallback',   // plugin: inlinepopups,
        init_instance_callback : 'tinyMCEInitInstanceCallback',
        plugins : "inlinepopups, safari,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,insertdatetime,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template",
        theme_advanced_buttons1 : "save,newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect,fontselect,fontsizeselect",
        theme_advanced_buttons2 : "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,|,forecolor,backcolor",
        theme_advanced_buttons3 : "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emotions,iespell,media,advhr,|,print,|,ltr,rtl,|,fullscreen",
        theme_advanced_buttons4 : "insertlayer,moveforward,movebackward,absolute,|,styleprops,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,pagebreak",
        theme_advanced_toolbar_location : "top",
        theme_advanced_toolbar_align : "left",
        theme_advanced_statusbar_location : "bottom",
        theme_advanced_resizing : true
      });
      
      // tinyMCE.execInstanceCommand(id,'JustifyLeft',false);
      
    }
    
  }
  
  
  window.tinyMCEFileBrowserCallback = function(fieldName, url, type , win) {
    if(mediaId == 0) {
      // Msg('error','Sie haben nicht die erforderlichen Rechte.','Fehler'); // wird verdeckt
      return;
    }
    Loader.call('http://www.nadja-palm.de/CMS/CMS_do.php?__id=' + mediaId + '&__picker=1');
    tools.formPicker.openClient(function(value) {
      var element = win.document.getElementById(fieldName);
      element.value = value;
      element.onchange();
      
    });
    
  };
  
  window.tinyMCEInitInstanceCallback = function(inst) {
    var css = cssStack[inst.editorId];
    if(!css) return;
      self.css(inst.editorId, css);
  };
  
};

//
SWO.TOOLS.Selector = function() {
  
  var self = this;
  
  self.init = function(div) {
    
    $(div).initClasses();
    
    var p = $('p', div);
    var source = $('.source', div);
    var target = $('.target', div);
    
    p.click(function () {
      if($(this).parent().get(0).className == 'source') {
        target.prepend(this);
        target.prepend('<input id="' + this.id + '" class="hidden" type="hidden" value="' + this.innerHTML + '" name="' + $(div).attr('name') + '[' + this.id + ']"/>');
      } else {
        source.prepend(this);
        $('input[id=\'' + this.id + '\']', target).remove();
      }
    });
  };
  
};

SWO.TOOLS.Sidebar = function() {
  
  var self = this;
  
  self.init = function(table) {
    
    var win  = dom.layer.get(table).getWin(),
        cntl = dom.layer.get(table).getContentLayer();
    
    win.listen('resize', check);
    check();
    
    function check() {
      $(table).css('height', $(cntl).css('height'));
    }
    
  };
  
};

/// }}}


// {{{ SYS


/// {{{ Console
SWO.SYS.Console = function() {
  
  this.init = function(){
    if((typeof console).substr(0,2) == 'un' || typeof(console.log) != 'function') {
              console = new DummyConsole();
          }
  };
  
  
  function MyConsole() {
  }
  
  
  MyConsole.prototype = {
    _cnt:'<p style="border-bottom: 1px solid black;"><a onclick="console.clear();" >Clear</a></p>',
    log:function(msg) {
     this._black(msg);
    },
    info:function(msg) {
     this._black('<b>info: </b>'+msg);
    },
    warn:function(msg) {
     this._black('<b>warning: </b>'+msg);
    },
    error:function(msg) {
     this._red('<b>Error: </b>'+msg);
    },
    clear:function(){
      this._cnt = '<p style="border-bottom:1px solid black;"><a onclick="console.clear(); ">Clear</a></p>';
      this._display();
    },
    _black:function(msg) {
      msg = msg.toString().replace(/</g,'&lt;').replace(/>/g,'&gt;');
      this._cnt += '<p style="border-bottom:1px solid black;"><pre>'+msg+'</pre></p>';
      this._display();
    },
    _red:function(msg) {
      msg = msg.toString().replace(/</g,'&lt;').replace(/>/g,'&gt;');
      this._cnt += '<p style="border-bottom:1px solid red; color: red;"><pre>'+msg+'</pre></p>';
      this._display();
    },  
    _display:function() {
      if((typeof swm).substr(0,2) != 'un') {
        var wnd = swm.wm.getWindow('console');
        if(wnd) {
         // wnd.focus();
        } else {
          wnd = swm.wm.newWindow({width:800,height:600}, null, 'console', '', true, {url:'', requestWinId:'desktop'});
          wnd.setTitle('Console');
        }
        wnd.setContent(this._cnt);
      } else {
       // alert(this._cnt);
      }
    }
  };
  
  function DummyConsole() {}
  
  DummyConsole.prototype = {
    log:function(){},
    info:function(){},
    warn:function(){},
    error:function(){}
  };
  
};
/// }}}


/// {{{ Keys
SWO.SYS.Keys = function() {
  
  var self = this,
      _shiftDown = false,
      _ctrlDown  = false,
      _altDown   = false,
      _charTable = {9:'Tab', 37:'LEFT', 38:'UP', 39:'RIGHT', 40:'DOWN',
                    112:'F1', 113:'F2', 114:'F3', 115:'F4',
                    116:'F5', 117:'F6', 118:'F7', 119:'F8',
                    120:'F9', 121:'F10', 122:'F11', 123:'F12' };
  
  this.onKeyDown = function(evt) {
    if((typeof swm_cms_desktop).match(/^un/)) return; // disable for login screen
    evt = evt || event;
    var charCode = evt.charCode || evt.keyCode;
    switch (charCode) {
      case 16: // shift
        _shiftDown = true;
        break;
      case 17: // ctrl
        _ctrlDown = true;
        break;
      case 18: // alt
        _altDown = true;
        break;
    }
    processKeyEvent(charCode, 'Down', evt);
  };
  
  this.onKeyUp = function(evt) {
    if((typeof swm_cms_desktop).match(/^un/)) return; // disable for login screen
    evt = evt || event;
    var charCode = evt.charCode || evt.keyCode;
    switch (charCode) {
      case 16: // shift
        _shiftDown = false;
        break;
      case 17: // ctrl
        _ctrlDown = false;
        break;
      case 18: // alt
        _altDown = false;
        break;
    }
    processKeyEvent(charCode, 'Up', evt);
  };
  
  this.onKeyPress = function(evt) {
    if((typeof swm_cms_desktop).match(/^un/)) return; // disable for login screen
    evt = evt || event;
    var charCode = evt.charCode || evt.keyCode;
    processKeyEvent(charCode, 'Press', evt);
  };
  
  
  this.shiftDown = function() {
    return _shiftDown;
  };
  this.ctrlDown = function() {
    return _ctrlDown;
  };
  this.altDown = function() {
    return _altDown;
  };
  
  function processKeyEvent(code, mode, evt) {
    var as = '', ch = String.fromCharCode(code);
    ch = self.shiftDown() ? ch.toUpperCase() : ch.toLowerCase();
    if(self.ctrlDown()) as += 'CTRL';
    if(self.altDown())  as += 'ALT';
    if(as) as = '_'+as;
    if(code in _charTable)
      ch = _charTable[code];
    else if(!ch.match(/[0-9A-Za-zäöüÄÖÜß]/))
      return;
    var string = 'onKey'+mode+as+'_'+ch;
    var win = swm.wm.getActive();
    if(!win) return;
    win.onKeyEvent(string, code, mode, ch, evt);
  }
  
  
  $(document).bind('keydown', function(e){
    self.onKeyDown(e);
  });
  $(document).bind('keyup', function(e){
    self.onKeyUp(e);
  });
  $(document).bind('keypress', function(e){
    self.onKeyPress(e);
  });
};
/// }}}


/// {{{ Mouse
// sys.mouse holds always the mousePosition of the last Click
/**
 *  use:
 *  sys.mouse.getLastClickPosition()  // the page coordinates of the last click
 *  sys.mouse.leftButtonDown()        // wether the left Mousebutton is hold down now
 *  sys.mouse.rightButtonDown()
 */

SWO.SYS.Mouse = function() {
  var x = 0,
      y = 0,
      leftDown = false,
      rightDown = false;
      
  this.set = function(e) {
    var pos = this.getPos(e);
    x = pos.x;
    y = pos.y;
  };
  
  this.setDown = function(e) {
    this.isRightClick(e) ? (rightDown = true) :
                           (leftDown  = true);
  };
  
  this.setUp = function(e) {
    this.isRightClick(e) ? (rightDown = false) :
                           (leftDown  = false);
  };
  
  this.getLastClickPosition = function() {
     return {x:x, y:y};
  };
  
  this.getPos = function(e) {
    e = e || window.event;
    var pos = {x:0, y:0};
      pos.x = e.pageX;
    pos.y = e.pageY;
     return pos;
  };
  
  this.isRightClick = function(e) {
    e = e || window.event;
    return    (e.type && e.type == "contextmenu")
           || (e.button && e.button == 2) 
           || (e.which && e.which == 3);
  };
  
  this.isLeftClick = function(e) {
    return ! this.isRightClick(e);
  };
  
  this.leftButtonDown = function(){
    return leftDown;
  };
  
  this.rightButtonDown = function(){
    return rightDown;
  };
};



// save MousePosition on Click (see also xStopPropagation!)
$(document).bind('click',function(e){
  // console.log('document click');
   e = e || window.event;
   if(e && e.clientX) { sys.mouse.set(e); }
});

$(document).bind('mousedown',function(e){
   e = e || window.event;
   if(e) { sys.mouse.setDown(e); }
});

$(document).bind('mouseup',function(e){
   e = e || window.event;
   if(e) { sys.mouse.setUp(e); }
});

/// }}}


/// {{{ Timer
SWO.SYS.Timer = function() {
  
  var counter = 0;
  var functions = {};
  var objects   = {};
  var self = this;
  
  this.timeout = function(delay, f) {
    var ticket = this._getTicket();
    functions[ticket] = f;
    var timeout = window.setTimeout('sys.timer._call(' + ticket + ')',delay);
    timeout.clear = function() {
      window.clearTimeout(this);
    }
    return timeout;
  };
  
  this.interval = function(delay, f, now) {
    var ticket = this._getTicket();
    functions[ticket] = f;
    var obj = objects[ticket] = {}
    obj.i = 0;  // counter
    var interval = window.setInterval('sys.timer._call(' + ticket + ')',delay);
    obj.clear = function(){
      window.clearInterval(interval);
    };
    if(now) {
      f.apply(obj);
    }
    return obj;
  };
  
  this._getTicket = function() {
    return counter++;
  };
  
  this._call = function(ticket) {
    var f = functions[ticket],
        obj = objects[ticket];
    if(obj){
      obj.i++;
      f.apply(obj);
    } else {
      f();
    }
  };
  
};
/// }}}


/// {{{ ScreenObserver
SWO.SYS.ScreenObserver = function() {
  
  var self = this;
  
  var desktop;
  var screenSize = {};
  
  this.start = function() {
    // desktop = $('#desktop');
    screenSize.width  = $(document).width();   //desktop.width(); 
    screenSize.height = $(document).height();  //desktop.height();
    sys.timer.interval(300, function(){
       checkScreen();
    });
  };
  
  
  function checkScreen() {
    var width  = $(document).width();   // desktop.width();
    var height = $(document).height();  // desktop.height();
    if(width != screenSize.width || height != screenSize.height) {
      screenChange();
      screenSize.width = width;
      screenSize.height = height;
    }
  }
  
  function screenChange() {
    swm.wm.onScreenResize();
    sys.event.trigger('onScreenResize');
  }
  
};
/// }}}


/// {{{ Cookie

SWO.SYS.Cookie = function() {
  document.cookie = "resolution=" + screen.width + "x" + screen.height;
  document.cookie = "shade=" + screen.colorDepth; 
}

/// }}}


/// {{{ CssBinder
SWO.SYS.CssBinder = function() {
  
  var self      = this,
      fileAdded = {},
      cssAdded  = {};
  
  
  this.add = function(href) {
    if(fileAdded[href]) return;
    var a = document.createElement('link');
    a.setAttribute('rel', 'stylesheet')
    a.setAttribute('type', 'text/css');
    a.setAttribute('href', href);
    document.getElementsByTagName('HEAD')[0].appendChild(a);
    fileAdded[href] = true;
  };
  
  // Not for Internet Explorer
  this.addDirect = function(css) {
    var hash = css.hash();
    if(cssAdded[hash]) return;
    // console.log('addDirect: '+css);
    
    if (navigator.appName != 'Microsoft Internet Explorer') {
      
      a = document.createElement('style');
      a.setAttribute('type', 'text/css');
      a.appendChild(document.createTextNode(css));
      document.getElementsByTagName('HEAD')[0].appendChild(a);
      
    }
    
    cssAdded[hash] = true;
  };
  
};
/// }}}

/// {{{ DOMWatchdog
// alert on global namespace pollution.
SWO.SYS.DOMWatchdog = function() {
  
  var items = {};
    
  function init(){
    var n;
    for(n in window) {
      items[n] = true;
    }
  }
  
  function check() {
    var n;
    for(n in window) {
      if(!(n in items)) {
        if((typeof(console) === 'object') && typeof(console.log) === 'function')
          console.log('DOM pollution: ' + n + ' (' + (typeof window[n]) + ') ' +
                      ' added to global namespace. (uninitialized variable?)');
        items[n] = true;
      }
    }
  }
  
};
/// }}}


// Event Hub
SWO.SYS.Event = function() {
  
  var events = {}
  
  this.bind = function(e, f){
    events[e] = events[e] || [];
    events[e].push(f);
  };
  
  this.unBind = function(e, f){
    if(events[e]) 
      events[e].remove(f);
  };
  
  this.trigger = function(e, data){
    if(events[e])
      events[e].each(function(){
        this(data);
      });
  };
};



/// {{{ Plugins (check for Flash/Reader/etc.)
SWO.SYS.Plugins = function() {
  
  var plugins = {}, name;
  
  
  if((typeof swm_cms_desktop).match(/^un/)) {
    return; // disable for login screen
  }
  
  plugins.java = navigator.javaEnabled();
  
  if(window.ActiveXObject) {
    var pls = {flash:['ShockwaveFlash.ShockwaveFlash'],
               acrobat:['AcroPDF.PDF', 'PDF.PdfCtrl']}
    for(name in pls) {
      pls[name].each(function(){
        plugins[name] = plugins[name] || inIE(this);
      });
    }
  } else {
    var pls = {flash:[/^Shockwave Flash/],
               acrobat:[/^Adobe Reader/, /^Adobe Acrobat/]}
    for(name in pls) {
      pls[name].each(function(){
        plugins[name] = plugins[name] || installed(this);
      });
    }
  }
  
  // plugins = {}; // for testing purposes
  
  
  this.installed = function(name) {
    return !! plugins[name];
  }
  
  
  function inIE(name) {
    var control = null;
    try {
      control = new ActiveXObject(name);
    } catch(e) {
      return false;
    }
    return true;
  }
  
  function installed(name) {
    var p = navigator.plugins;
    for(var i=0; i< p.length; i++) {
      // console.log('plugin: '+p[i].name);
      if(p[i].name.match(name))
        return true;
    }
    return false;
  }
};
/// }}}

/// {{{ TabKeyManager

// makes the Focus stay (circle) inside a Window/Tab when using the Tab key.
SWO.SYS.TabKeyManager = function() {
  
  var node, elem;
  
  this.init = function(layer) {
    var forms = layer.getElementsByTagName('FORM'),
        i = 0, j = 0,  form, elem;
    while(form = forms[i++]) {
      extendForm(form);
    }
    this.route(layer);
  };
  
  this.route = function(layer) {
    layer = dom.layer.get(layer).getContentLayer() || layer; // the outer Window Content Layer (if it is inside a Window)
    var forms = getVisible(layer.getElementsByTagName('FORM'));
    forms.each(function(){
      this.visible = getVisible(this.elements);
    }).each(function(){
      setFormNextPrev(this, forms);
    }).each(function(){
      setElementsNextPrev(this.visible);
    });
    if(forms[0] && forms[0].visible[0])
      forms[0].visible[0].focusIfInRange();
  };
  
  
  function extendForm(form) {
    if(form.tkmExtended) return;
    form.isVisible = _isVisible;
    var j=0, elem;
    while(elem = form.elements[j++]) {
      elem.isVisible = _isVisible;
      elem.isElement = _isElement;
      if(elem.isElement())
        extendElement(elem);
    }
    form.tkmExtended = true;
  }
  
  
  function getVisible(all) {
    var j=0, elem, visible = [];
    while(elem = all[j++]) {
      if(elem.isVisible()) {
        visible.push(elem);
      }
    }
    return visible;
  }
  
  function _isElement() {
    var node = this;
    if((typeof(node.type) == 'string' &&
        node.type.toUpperCase() == 'HIDDEN') ||
        node.tagName.toUpperCase() == 'FIELDSET')
      return false;
    return true;
  }
  
  function _isVisible() {
    var node = this;
    if((typeof(node.type) == 'string' &&
        node.type.toUpperCase() == 'HIDDEN') ||
        node.tagName.toUpperCase() == 'FIELDSET')
      return false;
    while(node) {
      if(node.style && (node.style.visibility == 'hidden' ||
         node.style.display == 'none' )) {
        return false;
      }
      node = node.parentNode;
    }
    return true;
  }
  
  
  function setElementsNextPrev(elems) {
    if(!elems.length)
      return;
    for(var i = 1; i < (elems.length-1); i++) {
      elems[i].prev = elems[i-1];
      elems[i].next = elems[i+1];
    }
    var m = elems.length - 1;
    elems[0].next = elems[1] || elems[m].form.next.visible[0];
    elems[0].prev = elems[0].form.prev.visible[elems[0].form.prev.visible.length-1];
    
    elems[m].next = elems[m].form.next.visible[0];
    elems[m].prev = elems[m-1] || elems[0].form.prev.visible[elems[0].form.prev.visible.length-1];
  }
  
  
  function setFormNextPrev(myForm, forms) {
    //alert('forms='+forms+' length='+forms.length+' [0].name='+forms[0].name);
    var i = 0, form, j;
    while(form = forms[i++]) {
      if(form == myForm) {
        myForm.next = forms[i] ? forms[i] : forms[0];
        myForm.prev = (i-2 >= 0) ? forms[i-2] : forms[forms.length-1];
      }
    }
  }
  
  
  function extendElement(obj) {
    
    obj.isInRange = function() {
      var pos = $(this).position(true);
      return (pos.top < ($(document).height() - 20) && pos.left < ($(document).width() - 20)); 
    };
    
    // .tabFocussed:  select() should be triggered only by tab key, not by clicking into a field.
    
    obj.focusIfInRange = function() {
      if(!this.isInRange()) return;
      this.tabFocussed = true;
      try{  this.focus();  } catch(e) { console.log(e.message || e.description) }
      this.tabFocussed = false;
      // console.log('focus:"'+this.name+'" prev:"'+this.prev.name+'" next:"'+this.next.name+'"');
    };
    
    
    obj.onfocus = function() {
      if(typeof this.select == 'function' && this.tabFocussed)
        this.select();
    };
    
    obj.setRadio = function(value) {
      var radios = this.form[this.name];
      for(var i = 0; i < radios.length; i++) {
        if(radios[i].value === value)
          radios[i].checked = true;
      }
    };
    
    if(typeof(obj.onkeydown) != 'function') {
      obj.onkeydown = function(event) { return controlTab(event, this); };
    }
    
    if(typeof(obj.onload) == 'function')
      obj.onload();
  }
  
  
  
   //   * callback function controllTab
   //   * using the Tabbar will only affect elements in the current Window
  
  function controlTab(evt, obj) {
    /*
     console.log('controlTab  prev:'+obj.prev.form.name+'.'+obj.prev.name+
                              ' this:'+obj.form.name+'.'+obj.name+
                              ' next:'+obj.next.form.name+'.'+obj.next.name);
   */
   
    evt = evt ? evt : event;
    var charCode = (evt.charCode) ? evt.charCode : ((evt.keyCode) ? evt.keyCode : 0);
    switch (charCode) {
      case 9: // tab
       if(sys.keys.shiftDown()) {
         obj.prev.focusIfInRange();
       } else {
        // console.log('controlTab: too:'+(typeof obj)+' obj:"'+obj.name+'-'+obj.type+'-'+obj.tagName+'" next:"'+(obj.next && obj.next.name)+'"');
         obj.next.focusIfInRange();
       }
       return false;
    }
  }
  
};


SWO.SYS.ServerPushPop = function(){
    
    var self = this,
        enabled = true,
        mode    = 0;
        
        
    self.init = function(){
      if(!enabled) return false;
      
      switch(mode) {
        case 1: // pop
          Stream.request('http://www.nadja-palm.de/modules/CMS/CMS_pushpop.php');
          break;
        default: // push
          setInterval(function(){
            Loader.request('http://www.nadja-palm.de/modules/CMS/CMS_pushpop.php?', {noWinId:true});
          }, 1500);
      }
    };
    
};


/// }}}

// }}}

SWO.SYS._setup();
SWO.TOOLS._setup();

