var RichTextControls = Class.create({/*{{{*/
  initialize:function(area,div,downloads,tables) {/*{{{*/
    this.textarea = $(area);
    this.controlarea = $(div);
    this.tables = tables;

    this.s1 = 0;
    this.s2 = 0;
    this.dlg = null;

    this.dlArr = urlDecodeArray(downloads);

    // Textarea event handlers/*{{{*/
    this.textarea.observe('select',this.changeSelection.bind(this));
    this.textarea.observe('focus',this.changeSelection.bind(this));
    this.textarea.observe('keyup',this.changeSelection.bind(this));
    this.textarea.observe('click',this.changeSelection.bind(this));
    /*}}}*/
    // Create buttons/*{{{*/
    this.bnbold = new Element('input');
    this.bnbold.type = 'button';
    this.bnbold.className = 'richtextbn';
    this.bnbold.value = 'Vetgedrukt';
    this.bnbold.style.fontWeight = 'bold';
    this.controlarea.appendChild(this.bnbold);

    this.bnitalic = new Element('input');
    this.bnitalic.type = 'button';
    this.bnitalic.className = 'richtextbn';
    this.bnitalic.value = 'Cursief';
    this.bnitalic.style.fontStyle = 'italic';
    this.controlarea.appendChild(this.bnitalic);

    this.bnspecial = new Element('input');
    this.bnspecial.type = 'button';
    this.bnspecial.className = 'richtextbn';
    this.bnspecial.value = 'Speciale tekens';
    this.controlarea.appendChild(this.bnspecial);

    this.bncolor = new Element('input');
    this.bncolor.type = 'button';
    this.bncolor.className = 'richtextbn';
    this.bncolor.value = 'Tekstkleur';
    this.controlarea.appendChild(this.bncolor);

    this.bnlink = new Element('input');
    this.bnlink.type = 'button';
    this.bnlink.className = 'richtextbn';
    this.bnlink.value = 'Link naar website';
    this.controlarea.appendChild(this.bnlink);

    this.bnmailto = new Element('input');
    this.bnmailto.type = 'button';
    this.bnmailto.className = 'richtextbn';
    this.bnmailto.value = 'Link naar email';
    this.controlarea.appendChild(this.bnmailto);

    if(this.dlArr.length > 0) {
      this.bndl = new Element('input');
      this.bndl.type = 'button';
      this.bndl.className = 'richtextbn';
      this.bndl.value = 'Downloads';
      this.controlarea.appendChild(this.bndl);
    }
    else {
      this.bndl = null;
    }

    this.bnclear = new Element('input');
    this.bnclear.type = 'button';
    this.bnclear.className = 'richtextbn';
    this.bnclear.value = 'Opmaak wissen';
    this.controlarea.appendChild(this.bnclear);
    /*}}}*/
    // Button event handlers/*{{{*/
    this.bnbold.observe('click',function(){this.insMarkup('[bold]','[/bold]');}.bind(this));
    this.bnitalic.observe('click',function(){this.insMarkup('[italic]','[/italic]');}.bind(this));
    this.bnspecial.observe('click',this.onBnSpecial.bind(this));
    this.bncolor.observe('click',this.onBnColor.bind(this));
    this.bnlink.observe('click',this.onBnLink.bind(this));
    this.bnmailto.observe('click',this.onBnMailto.bind(this));
    if(this.bndl !== null) this.bndl.observe('click',this.onBnDl.bind(this));
    this.bnclear.observe('click',this.onBnClear.bind(this));
    /*}}}*/
  },/*}}}*/
  changeSelection:function(evt) {/*{{{*/
    if(window.getSelection)
    {
      // Opera, Firefox
      this.s1 = this.textarea.selectionStart;
      this.s2 = this.textarea.selectionEnd;
    }
    else if(document.selection) {
      // IE
      var selRange = document.selection.createRange();
      var fullRange = selRange.duplicate();
      fullRange.moveToElementText(this.textarea);
      fullRange.setEndPoint('EndToEnd',selRange);
      this.s1 = fullRange.text.length - selRange.text.length;
      this.s2 = this.s1 + selRange.text.length;
    }
  },/*}}}*/
  onBnSpecial:function(){/*{{{*/
    var dlg = new Dialog('Speciale tekens invoegen');
    dlg.addCmp('static',
	'<p>Kies hier de speciale tekens die u in wilt voeren. Deze worden automatisch op de plek van de cursor ingevoerd.</p>');

    var table = dlg.addCmp('table', null);
    table.setRows(6);
    table.setCols(8);
    var str = "áàäâÁÀÄÂéèëêÉÈËÊíìïîÍÌÏÎóòöôÓÒÖÔúùüûÚÙÜÛÆÇçñβ©®€";
    for(var i=0; i<str.length; i++)
      table.addCell(new DialogButtonCancel('callback',str.charAt(i),function(e){this.onSpecial(e)}.bind(this)));

    dlg.addButton('cancel','OK',null);
    dlg.show();
  },/*}}}*/
  onBnColor:function(){/*{{{*/
    var len = this.s2-this.s1;
    if(len <= 0) {
      var dlg = new Dialog('Fout');
      dlg.addCmp('static',
	  '<p>Er is nog geen tekst geselecteerd. Selecteer eerst de tekst waarvan u de kleur wilt wijzigen.</p>');
      dlg.addButton('cancel','OK',null);
      dlg.show();
    }
    else {
      this.dlg = new Dialog('Speciale tekens invoegen');
      this.dlg.addCmp('static',
	  '<p>Kies de kleur van de geselecteerde tekst.');
      this.dlg.addCmp('color','#ffffff');
      this.dlg.addButton('cancel','Annuleren',null);
      this.dlg.addButton('callback','OK',this.onColor.bind(this));
      this.dlg.show();
    }
  },/*}}}*/
  onBnLink:function(){/*{{{*/
    if(this.s2-this.s1 <= 0) {
      var dlg = new Dialog('Fout');
      dlg.addCmp('static',
	"<p>U heeft nog geen tekst geselecteerd.</p>"
	+"<p>Selecteer eerst de tekst waar u een"
	+" hyperlink van wilt maken</p>");
      dlg.addButton('cancel','OK',null);
      dlg.show();
    }
    else {
      this.dlg = new Dialog('Link toevoegen');
      this.dlg.addCmp('static',
	"<p>Voer de link in waar naar verwezen moet worden.</p>");
      this.dlg.addCmp('textline','http://');
      this.dlg.addButton('callback','OK',this.onLink.bind(this));
      this.dlg.addButton('cancel','Annuleren',null);
      this.dlg.show();
    }
  },/*}}}*/
  onBnMailto:function(){/*{{{*/
    if(this.s2-this.s1 <= 0) {
      var dlg = new Dialog('Fout');
      dlg.addCmp('static',
	"<p>U heeft nog geen tekst geselecteerd.</p>"
	+"<p>Selecteer eerst de tekst waar u een"
	+" email-link van wilt maken</p>");
      dlg.addButton('cancel','OK',null);
      dlg.show();
    }
    else {
      this.dlg = new Dialog('E-mail link toevoegen');
      this.dlg.addCmp('static',
	"<p>Voer hieronder het e-mailadres in</p>");
      this.dlg.addCmp('textline','iemand@voorbeeld.nl');
      this.dlg.addButton('callback','OK',this.onMail.bind(this));
      this.dlg.addButton('cancel','Annuleren',null);
      this.dlg.show();
    }
  },/*}}}*/
  onBnClear:function(){/*{{{*/
    if(this.s2-this.s1 <= 0) {
      var dlg = new Dialog('Opmaak wissen');
      dlg.addCmp('static',
	"<p>Hiermee verwijdert u alle opmaak, links en e-mail addressen. Wilt u doorgaan?</p>");
      dlg.addButton('cancel','Annuleren',null);
      dlg.addButton('callback','OK',this.onClearAll.bind(this));
      dlg.show();
    }
    else {
      this.dlg = new Dialog('Opmaak wissen');
      this.dlg.addCmp('static',
	"<p>Hiermee verwijdert u alle opmaak, links en e-mail addressen uit de selectie. Wilt u doorgaan?</p>");
      this.dlg.addButton('cancel','Annuleren',null);
      this.dlg.addButton('callback','OK',this.onClear.bind(this));
      this.dlg.show();
    }
  },/*}}}*/
  onBnDl:function(){/*{{{*/
    this.dlg = new Dialog('Download invoegen');
    this.dlg.addCmp('static',
	'<p>Selecteer hier welk bestand u als download wilt invoegen. U kunt downloads aan deze lijst toevoegen bij de module "Pagina\'s" - "Downloads"</p>');

    var pd = this.dlg.addCmp('pulldown', this.dlArr);

    this.dlg.addButton('callback','OK',this.onDl.bind(this));
    this.dlg.addButton('cancel','Annuleren',null);
    this.dlg.show();
  },/*}}}*/
  onSpecial:function(e) {/*{{{*/
    this.s2=this.s1;
    this.insMarkup(e.findElement('input').value,'');
    this.s1++;this.s2++;
  },/*}}}*/
  onColor:function(data) {//{{{
    for(var i=0; i<this.dlg.comps.length; i++)
      if(this.dlg.comps[i].type == 'color')
       	this.insMarkup('[color '+this.dlg.comps[i].result.value+']','[/color]');
    this.dlg.close();
  },//}}}
  onLink:function(data) {//{{{
    for(var i=0; i<this.dlg.comps.length; i++)
      if(this.dlg.comps[i].type == 'textline')
       	this.insMarkup('[link '+this.dlg.comps[i].inputelem.getValue()+']','[/link]');
    this.dlg.close();
  },//}}}
  onDl:function(data) {//{{{
    for(var i=0; i<this.dlg.comps.length; i++)
      if(this.dlg.comps[i].type == 'pulldown') {
       	this.insMarkup('[download '+this.dlg.comps[i].getId()+']'+this.dlg.comps[i].getName()+'[/download]','');
      }
    this.dlg.close();
  },//}}}
  onMail:function(data) {//{{{
    for(var i=0; i<this.dlg.comps.length; i++) {
      if(this.dlg.comps[i].type == 'textline') {
       	this.insMarkup('[mail '+this.dlg.comps[i].inputelem.getValue()+']','[/mail]');
      }
    }
    this.dlg.close();
  },//}}}
  insMarkup:function(a,b){/*{{{*/
    var s = this.textarea.scrollTop;
    var v=this.textarea.value;
    this.textarea.value=v.substr(0,this.s1)+a+v.substr(this.s1,this.s2-this.s1)+b+v.slice(this.s2);
    this.textarea.scrollTop = s;
    clearSelection();
  },/*}}}*/
  onClear:function(data) {//{{{
    var s=this.textarea.scrollTop;
    var v=this.textarea.value.substr(this.s1,this.s2-this.s1);
    var i=0;

    this.textarea.value = this.textarea.value.slice(0,this.s1,this.s2-this.s1)
      + txtClearMarkup(v)
      + this.textarea.value.slice(this.s2);

    this.dlg.close();
    this.textarea.scrollTop=s;
    clearSelection();
  },//}}}
  onClearAll:function(data) {//{{{
    var s=this.textarea.scrollTop;

    this.textarea.value = txtClearMarkup(this.textarea.value);

    this.dlg.close();
    this.textarea.scrollTop = s;
    clearSelection();
  }//}}}
});/*}}}*/
var Dialog = Class.create({//{{{
  initialize:function(title){//{{{
    this.title = title;
    this.buttons = [];
    this.comps = [];
    this.bgObj = null;
    this.dlgObj = null;
  },//}}}
  addCmp:function(type,data) {//{{{
    var nextIndex = this.comps.length;
    switch(type) {
      case 'static':
	this.comps[nextIndex] = new DialogObjStatic(data);
	break;
      case 'table':
	this.comps[nextIndex] = new DialogObjTable();
	return this.comps[nextIndex];
	break;
      case 'textline':
	this.comps[nextIndex] = new DialogObjTextline(data);
	break;
      case 'color':
	this.comps[nextIndex] = new DialogObjColor(data);
	break;
      case 'pulldown':
	this.comps[nextIndex] = new DialogObjPulldown(data);
	break;
      default:
	alert('Dialog::addCmp: no object type "' + type + '" defined.');
	break;
    }
  },//}}}
  addButton:function(command,title,handler) {//{{{
    var nextIndex = this.buttons.length;
    switch(command) {
      case 'cancel':
	this.buttons[nextIndex] =
	  new DialogButtonCancel(command,title);
	break;
      case 'callback':
	this.buttons[nextIndex] =
	  new DialogButtonCancel(command,title,handler);
	break;
      default:
	alert('Dialog::addButton: no object type "' + command + '" defined.');
	break;
    }
  },//}}}
  show:function() {//{{{
    this.bgObj = new Element('div');
    this.bgObj.className = "dlgBackground";
    this.bgObj.style.width = Element.getDimensions(document.body).width + "px";
    this.bgObj.style.height = Element.getDimensions(document.body).height + "px";
    this.bgObj.setOpacity(0.6);
    document.body.appendChild(this.bgObj);

    this.dlgObj = new Element('div');
    this.dlgObj.className = "dlgWindow";
    document.body.appendChild(this.dlgObj);
    
    // Add title
    var div = new Element('div');
    div.className = 'dlgWindowTitle';
    div.appendChild(document.createTextNode(this.title));
    this.dlgObj.appendChild(div);

    // Add components
    var i=0;
    for(i=0; i<this.comps.length; i++) {
      this.dlgObj.appendChild(this.comps[i].getDomNode());
      this.comps[i].addHandlers();
    }

    // Add buttons
    div = new Element('div');
    div.className = 'dlgWindowButtons';
    this.dlgObj.appendChild(div);
    var i=0;
    for(i=0; i<this.buttons.length; i++) {
      var button = this.buttons[i].getDomNode();
      div.appendChild(button);
      if(this.buttons[i].command == 'cancel') {
	button.observe('click',this.close.bind(this));
      }
      if(this.buttons[i].command == 'callback') {
	button.observe('click',this.buttons[i].handler);
      }
    }

    // Finally, position window in center
    var vscroll = document.viewport.getScrollOffsets();
    var vdim = document.viewport.getDimensions();
    var edim = this.dlgObj.getDimensions();
    this.dlgObj.style.position = 'absolute';
    this.dlgObj.style.left = (vscroll.left + (vdim.width-edim.width)/2)+'px';
    this.dlgObj.style.top = (vscroll.top + (vdim.height-edim.height)/2)+'px';
  },//}}}
  close:function() {//{{{
    document.body.removeChild(this.dlgObj);
    document.body.removeChild(this.bgObj);
  }//}}}
});//}}}
var DialogObjColor = Class.create({//{{{
  initialize: function(color) {//{{{
    this.color = color;
    this.type = 'color';
    this.result = null;

    this.objHue = null;
    this.objSV = null;
    this.obj = null;
    this.objSelHue = null;
    this.objSelSV = null;
    this.currObj = null;
    this.objColor = null;
  },//}}}
  getDomNode: function() {//{{{
    var tbody = null;
    var tr = null;
    var td = null;
    var i = 0;
    var x = 0;
    var y = 0;
    var hsv = null;
    var img = null;

    // Create Hue bar/*{{{*/
    this.objHue = new Element('table');
    this.objHue.style.position = 'absolute';
    this.objHue.style.top = '10px';
    this.objHue.style.left = '10px';
    tbody = new Element('tbody');
    this.objHue.appendChild(tbody);
    for(i=0; i<=50; i++) {
      tr = new Element('tr');
      tbody.appendChild(tr);
      td = new Element('td');
      tr.appendChild(td);
      td.style.width='20px';
      td.style.height='4px';
      hsv = hsvToRgb(i/50,1,1);
      td.style.background = rgbToHex(hsv.r,hsv.g,hsv.b,true);
    }
    /*}}}*/
    // Create SV plane/*{{{*/
    this.objSV = new Element('table');
    this.objSV.style.position = 'absolute';
    this.objSV.style.top = '10px';
    this.objSV.style.left = '40px';
    tbody = new Element('tbody');
    this.objSV.appendChild(tbody);
    for(y=0; y<=50; y++) {
      tr = new Element('tr');
      tbody.appendChild(tr);
      for(x=0; x<=50; x++) {
	td = new Element('td');
	tr.appendChild(td);
	td.style.width = '4px';
	td.style.height = '4px';
	hsv = hsvToRgb(0,x/50,y/50);
	td.style.background = rgbToHex(hsv.r,hsv.g,hsv.b,true);
      }
    }
    /*}}}*/
    // Create selectors/*{{{*/
    this.objSelHue = new Element('div');
    this.objSelHue.style.width = '24px';
    this.objSelHue.style.height = '11px';
    this.objSelHue.style.background = 'url(art2/colorselect_h.png)';
    this.objSelHue.style.position = 'absolute';
    this.objSelHue.style.top = '5px';
    this.objSelHue.style.left = '8px';

    this.objSelSV = new Element('div');
    this.objSelSV.style.width = '12px';
    this.objSelSV.style.height = '12px';
    this.objSelSV.style.background = 'url(art2/colorselect_sv.png)';
    this.objSelSV.style.position = 'absolute';
    this.objSelSV.style.top = '4px';
    this.objSelSV.style.left = '34px';
    /*}}}*/
    // Create selected color div/*{{{*/
    this.objColor = new Element('div');
    this.objColor.style.position = 'absolute';
    this.objColor.style.top = '10px';
    this.objColor.style.left = '254px';
    this.objColor.style.width = '30px';
    this.objColor.style.height = '14px';
    this.objColor.style.border = '1px solid black';
    this.objColor.style.backgroundColor = '#000000';
    /*}}}*/
    // Create result field/*{{{*/
    this.result = new Element('input');
    this.result.type = 'hidden';
    this.result.value = '#ff0000';/*}}}*/
    // Create container/*{{{*/
    this.obj = new Element('div');
    this.obj.style.position = 'relative';
    this.obj.style.background = 'orange';
    this.obj.style.width = '300px';
    this.obj.style.height = '220px';
    this.obj.appendChild(this.objHue);
    this.obj.appendChild(this.objSV);
    this.obj.appendChild(this.objSelHue);
    this.obj.appendChild(this.objSelSV);
    this.obj.appendChild(this.objColor);
    this.obj.appendChild(this.result);
    return this.obj;
    /*}}}*/
  },//}}}
  addHandlers: function() {/*{{{*/
    this.objSelHue.observe('mousedown',this.down.bind(this));
    this.objSelSV.observe('mousedown',this.down.bind(this));
  },/*}}}*/
  down: function(e) {/*{{{*/
    this.currObj = e.findElement('div');
    Event.observe(document.body,'mousemove',this.move.bind(this));
    Event.observe(document.body,'mouseup',function(){this.up();this.currObj = null;Event.stopObserving(document.body)}.bind(this));
  },/*}}}*/
  move: function(e) {/*{{{*/
    var px = e.pointerX() - this.obj.cumulativeOffset().left;
    var py = e.pointerY() - this.obj.cumulativeOffset().top;
    switch(this.currObj) {
      case this.objSelHue:
	py = Math.min(py,this.objHue.cumulativeOffset().top - this.obj.cumulativeOffset().top + this.objHue.getDimensions().height);
	py = Math.max(py,this.objHue.cumulativeOffset().top - this.obj.cumulativeOffset().top);
	this.objSelHue.style.top = (py-5)+'px';
	break;
      case this.objSelSV:
	px = Math.min(px,this.objSV.cumulativeOffset().left - this.obj.cumulativeOffset().left + this.objSV.getDimensions().width);
	px = Math.max(px,this.objSV.cumulativeOffset().left - this.obj.cumulativeOffset().left);
	this.objSelSV.style.left = (px-6)+'px';
	py = Math.min(py,this.objSV.cumulativeOffset().top - this.obj.cumulativeOffset().top + this.objSV.getDimensions().height);
	py = Math.max(py,this.objSV.cumulativeOffset().top - this.obj.cumulativeOffset().top);
	this.objSelSV.style.top = (py-6)+'px';
	break;
      default:
	break;
    }
  },/*}}}*/
  up: function(e) {/*{{{*/
    this.updateSV();
    this.updateResult();
    var h;
    var s;
    var v;
    h = this.objSelHue.cumulativeOffset().top - this.objHue.cumulativeOffset().top + 5;
    s = this.objSelSV.cumulativeOffset().left - this.objSV.cumulativeOffset().left + 6;
    v = this.objSelSV.cumulativeOffset().top - this.objSV.cumulativeOffset().top + 6;
    h = h/204;
    s = s/204;
    v = v/204;
    //this.objTest.innerHTML = h+","+s+","+v;
    var rgb = hsvToRgb(h,s,v);
    this.objColor.style.background = rgbToHex(rgb.r,rgb.g,rgb.b,true);
    this.result.value = rgbToHex(rgb.r,rgb.g,rgb.b,true);
  },/*}}}*/
  updateSV: function() {/*{{{*/
    var tbody = null;
    var tr = null;
    var td = null;
    var i = 0;
    var x = 0;
    var y = 0;
    var h = 0;

    h = this.objSelHue.cumulativeOffset().top - this.objHue.cumulativeOffset().top + 5;
    h = h/204;
    while(this.objSV.firstChild) this.objSV.removeChild(this.objSV.firstChild);

    tbody = new Element('tbody');
    for(y=0; y<=50; y++) {
      tr = new Element('tr');
      tbody.appendChild(tr);
      for(x=0; x<=50; x++) {
	td = new Element('td');
	tr.appendChild(td);
	td.style.width = '4px';
	td.style.height = '4px';
	hsv = hsvToRgb(h,x/50,y/50);
	td.style.background = rgbToHex(hsv.r,hsv.g,hsv.b,true);
      }
    }
    this.objSV.appendChild(tbody);
  },/*}}}*/
  updateResult: function() {/*{{{*/
  }/*}}}*/
});//}}}
var DialogObjStatic = Class.create({//{{{
  initialize: function(text) {//{{{
    this.type = 'static';
    this.text = text;
  },//}}}
getDomNode: function() {//{{{
  var div = new Element('div');
  div.className = 'dlgCompStatic';
  div.innerHTML = this.text;
  return div;
},//}}}
addHandlers: function() {/*{{{*/
}/*}}}*/
});//}}}
var DialogObjTextline = Class.create({//{{{
  initialize: function(text) {//{{{
    this.type = 'textline';
    this.text = text;
    this.inputelem = null;
  },//}}}
getDomNode: function() {//{{{
  var div = new Element('div');
  div.className = 'dlgCompStatic';

  this.inputelem = new Element('input');
  this.inputelem.className = 'dlgCompTextline';
  this.inputelem.type = 'text';
  this.inputelem.value = this.text;
  div.appendChild(this.inputelem);
  return div;
},//}}}
addHandlers: function() {/*{{{*/
}/*}}}*/
});//}}}
var DialogObjPulldown = Class.create({//{{{
  initialize: function(d) {//{{{
    this.type = 'pulldown';
    this.opts = d;
    this.result = null;
    this.obj = null;
    this.select = null;
  },//}}}
getDomNode: function() {//{{{
  var o = null;
  this.select = new Element('select');
  for(var i=0; i<this.opts.length; i++) {
    o = new Element('option');
    o.value = this.opts[i][0];
    o.innerHTML = this.opts[i][1];
    this.select.appendChild(o);
  }
  this.result = new Element('input');
  this.result.type = 'hidden';
  this.result.value = this.opts[0][0];

  this.obj = new Element('div');
  this.obj.appendChild(this.select);
  this.obj.appendChild(this.result);
  return this.obj;
},//}}}
  addHandlers: function() {/*{{{*/
    this.select.observe('change',this.onChange.bind(this));
    this.onChange();
  },/*}}}*/
  onChange:function() {/*{{{*/
    var v = this.select.value;
    var a = this.select.select('option');
    for(var i=0; i<a.length; i++) {
      if(a[i].value == this.select.value)
	v += ":"+a[i].innerHTML;
    }
    this.result.value=v;
  },/*}}}*/
  getId:function() {/*{{{*/
    return this.result.value.substr(0,this.result.value.indexOf(':'));
  },/*}}}*/
  getName:function() {/*{{{*/
    return this.result.value.substr(this.result.value.indexOf(':')+1);
  }/*}}}*/
});//}}}
var DialogButtonCancel = Class.create({//{{{
  initialize:function(command,title,handler) {//{{{
    this.command = command;
    this.title = title;
    this.handler = handler;
    this.obj = null;
  },//}}}
  getDomNode: function() {//{{{
    var input = new Element('input');
    input.className = 'dlgButton';
    input.type='button';
    input.value=this.title;
    this.obj = input;
    return input;
  },//}}}
  addHandlers: function() {/*{{{*/
    if(this.obj != null)
      this.obj.observe('click',this.handler);
  }/*}}}*/
});//}}}
var DialogObjTable = Class.create({//{{{
  initialize: function(text) {//{{{
    this.type = 'static';
    this.text = text;
    this.rows = 2;
    this.cols = 2;
    this.cells = [];
  },//}}}
  setRows: function(num) {/*{{{*/
    this.rows = num;
  },/*}}}*/
  setCols: function(num) {/*{{{*/
    this.cols = num;
  },/*}}}*/
  addCell: function(bn) {/*{{{*/
    var len = this.cells.length;
    this.cells[len] = bn;
  },/*}}}*/
  getDomNode: function() {//{{{
    var table = new Element('table');
    var tbody = new Element('tbody');
    table.appendChild(tbody);

    var i = 0;
    var j = 0;
    var tr = null;
    var td = null;

    for(i=0; i<this.rows; i++) {
      tr = new Element('tr');
      for(j=0; j<this.cols; j++) {
	td = new Element('td');
	tr.appendChild(td);

	var x = i*this.cols + j;
	if(x < this.cells.length) {
	  td.appendChild(this.cells[x].getDomNode());
	}
	else {
	  td.appendChild(document.createTextNode(j));
	}
      }
      tbody.appendChild(tr);
    }

    var div = new Element('div');
    div.className = 'dlgCompStatic';
    div.innerHTML = this.text;
    return table;
  },//}}}
  addHandlers: function() {/*{{{*/
    var i=0;
    for(i=0; i<this.cells.length; i++) {
      if(this.cells[i].constructor.name == 'klass') {
	this.cells[i].addHandlers();
      }
    }
  }/*}}}*/
});//}}}
var DialogObjStatic = Class.create({//{{{
  initialize: function(text) {//{{{
    this.type = 'static';
    this.text = text;
  },//}}}
getDomNode: function() {//{{{
  var div = new Element('div');
  div.className = 'dlgCompStatic';
  div.innerHTML = this.text;
  return div;
},//}}}
addHandlers: function() {/*{{{*/
}/*}}}*/
});//}}}
var Selection = Class.create({ //{{{
  initialize:function(wnd){//{{{
    this.wnd = wnd;
    if(this.wnd.getSelection)
      this.type = 'w3c';
    else if(document.selection)
      this.type = 'ie';

    this.text = '';
    this.range = null;
    if(this.type == 'ie') {
      var sel = this.wnd.document.selection.crateRange();
      this.text = sel.text;
      this.range = sel;
    }
    else if(this.type = 'w3c') {
      var sel = this.wnd.getSelection();
      this.text = sel;
      this.range = this.w3cGetRangeObject(sel);
    }
  },//}}}
  w3cGetRangeObject:function(sel) {//{{{
    if(sel.getRangeAt) {
      return sel.getRangeAt(0);
    }
    else { // Safari
      var range = document.createRange();
      range.setStart(selectionObject.anchorNode,selectionObject.anchorOffset);
      range.setEnd(selectionObject.focusNode,selectionObject.focusOffset);
      return range;
    }
  }//}}}
});//}}}
var SelImgPos = Class.create({//{{{
  initialize:function(target,root,imgarr){//{{{
    this.targetObj = $(target);
    this.rootObj = $(root);
    this.imgarr = urlDecodeArray(imgarr);

    var elem = null;
    var i=0;

    //Build position select object//{{{
    this.posObj = new Element('select');
    elem = new Element('option');
    elem.value = 'none';
    elem.appendChild(document.createTextNode('Geen afbeelding'));
    this.posObj.appendChild(elem);
    elem = new Element('option');
    elem.value = 'left';
    elem.appendChild(document.createTextNode('Afbeelding links'));
    this.posObj.appendChild(elem);
    elem = new Element('option');
    elem.value = 'right';
    elem.appendChild(document.createTextNode('Afbeelding rechts'));
    this.posObj.appendChild(elem);
    //}}}
    //Build image select object//{{{
    this.imgObj = new Element('select');
    elem = new Element('option');
    elem.value = -1;
    elem.appendChild(document.createTextNode('-'));
    this.imgObj.appendChild(elem);
    for(i=0; i<this.imgarr.length; i++) {
      elem = new Element('option');
      elem.value = imgarr[i][0];
      elem.appendChild(document.createTextNode(decodeURIComponent(imgarr[i][1])));
      this.imgObj.appendChild(elem);
    }//}}}
  },//}}}
  init:function(){//{{{
    this.rootObj.appendChild(this.posObj);
    this.rootObj.appendChild(this.imgObj);
    this.getValue();

    this.posObj.observe('change',this.posChange.bind(this));
    this.imgObj.observe('change',this.setValue.bind(this));
  },//}}}
  getValue:function(){//{{{
    var i=0;
    var elements=null;

    this.imgObj.style.visibility = 'hidden';
    var val = this.targetObj.getValue();

    if(val.length == 0)
      return;

    var pos = val.substr(0,val.indexOf(':'));
    elements = this.posObj.childElements();
    for(i=0; i<elements.length; i++) {
      if(elements[i].value == pos)
	elements[i].selected = true;
    }

    var img = val.substr(val.indexOf(':')+1);
    elements = this.imgObj.childElements();
    for(i=0; i<elements.length; i++) {
      if(elements[i].value == img)
	elements[i].selected = true;
    }
    this.posChange();
  },//}}}
  setValue:function(){//{{{
    var val = "";
    val += this.posObj.childElements()[this.posObj.selectedIndex].value;
    val += ":";
    val += this.imgObj.childElements()[this.imgObj.selectedIndex].value;
    this.targetObj.value = val;
  },//}}}
  posChange:function(){//{{{
    var selobj = this.posObj.childElements()[this.posObj.selectedIndex];
    if(selobj.value == 'none') {
      this.imgObj.style.visibility = 'hidden';
    }
    else {
      this.imgObj.style.visibility = 'visible';
    }
    this.setValue();
  }//}}}
});//}}}
var SelImg = Class.create({//{{{
  initialize:function(target,root,imgarr){//{{{
    this.targetObj = $(target);
    this.rootObj = $(root);
    this.imgarr = urlDecodeArray(imgarr);

    var elem = null;
    var i=0;

    //Build image select object//{{{
    this.imgObj = new Element('select');
    elem = new Element('option');
    elem.value = -1;
    elem.appendChild(document.createTextNode('-'));
    this.imgObj.appendChild(elem);
    for(i=0; i<this.imgarr.length; i++) {
      elem = new Element('option');
      elem.value = imgarr[i][0];
      elem.appendChild(document.createTextNode(decodeURIComponent(imgarr[i][1])));
      this.imgObj.appendChild(elem);
    }//}}}
  },//}}}
  init:function(){//{{{
    this.rootObj.appendChild(this.imgObj);
    this.getValue();

    this.imgObj.observe('change',this.setValue.bind(this));
  },//}}}
  getValue:function(){//{{{
    var i=0;
    var elements=null;

    var val = this.targetObj.getValue();

    if(val.length == 0)
      return;

    elements = this.imgObj.childElements();
    for(i=0; i<elements.length; i++) {
      if(elements[i].value == val)
	elements[i].selected = true;
    }
    this.setValue();
  },//}}}
  setValue:function(){//{{{
    var val = this.imgObj.childElements()[this.imgObj.selectedIndex].value;
    this.targetObj.value = val;
  }//}}}
});//}}}
var Sel = Class.create({/*{{{*/
  initialize:function(target,root,imgarr){//{{{
    this.targetObj = $(target);
    this.rootObj = $(root);
    this.options = urlDecodeArray(imgarr);

    var elem = null;
    var i=0;

    //Build image select object//{{{
    this.selObj = new Element('select');
    elem = new Element('option');
    elem.value = -1;
    elem.appendChild(document.createTextNode('-'));
    this.selObj.appendChild(elem);
    for(i=0; i<this.options.length; i++) {
      elem = new Element('option');
      elem.value = this.options[i][0];
      elem.appendChild(document.createTextNode(this.options[i][1]));
      this.selObj.appendChild(elem);
    }//}}}
  },//}}}
  init:function(){//{{{
    this.rootObj.appendChild(this.selObj);
    this.getValue();

    this.selObj.observe('change',this.setValue.bind(this));
  },//}}}
  getValue:function(){//{{{
    var i=0;
    var elements=null;

    var val = this.targetObj.getValue();

    if(val.length == 0)
      return;

    elements = this.selObj.childElements();
    for(i=0; i<elements.length; i++) {
      if(elements[i].value == val)
	elements[i].selected = true;
    }
    this.setValue();
  },//}}}
  setValue:function(){//{{{
    var val = this.selObj.childElements()[this.selObj.selectedIndex].value;
    this.targetObj.value = val;
  }//}}}
    });/*}}}*/

function clearSelection() {/*{{{*/
  if (document.selection) {
    document.selection.empty();
  }
  else if (window.getSelection) {
    window.getSelection().removeAllRanges();
  }
}/*}}}*/
function hsvToRgb(hue, saturation, value) {/*{{{*/
  var red;
  var green;
  var blue;
  if (value == 0.0) {
    red = 0;
    green = 0;
    blue = 0;
  }
  else {
    var i = Math.floor(hue * 6);
    var f = (hue * 6) - i;
    var p = value * (1 - saturation);
    var q = value * (1 - (saturation * f));
    var t = value * (1 - (saturation * (1 - f)));
    switch (i) {
      case 1: red = q; green = value; blue = p; break;
      case 2: red = p; green = value; blue = t; break;
      case 3: red = p; green = q; blue = value; break;
      case 4: red = t; green = p; blue = value; break;
      case 5: red = value; green = p; blue = q; break;
      case 6: // fall through
      case 0: red = value; green = t; blue = p; break;
    }
  }
  return {r: red, g: green, b: blue};
}/*}}}*/
function rgbToHsv(red, green, blue) {/*{{{*/
  var max = Math.max(Math.max(red, green), blue);
  var min = Math.min(Math.min(red, green), blue);
  var hue;
  var saturation;
  var value = max;
  if (min == max) {
    hue = 0;
    saturation = 0;
  }
  else {
    var delta = (max - min);
    saturation = delta / max;
    if (red == max)
      hue = (green - blue) / delta;
    else if (green == max)
      hue = 2 + ((blue - red) / delta);
    else
      hue = 4 + ((red - green) / delta);
    hue /= 6;
    if (hue < 0)
      hue += 1;
    if (hue > 1)
      hue -= 1;
  }
  return { h: hue, s: saturation, v: value };
}/*}}}*/
function hexToRgb(hex_string, default_) {/*{{{*/
  if (default_ == undefined)
    default_ = null;

  if (hex_string.substr(0, 1) == '#')
    hex_string = hex_string.substr(1);

  var r;
  var g;
  var b;
  if (hex_string.length == 3) {
    r = hex_string.substr(0, 1);
    r += r;
    g = hex_string.substr(1, 1);
    g += g;
    b = hex_string.substr(2, 1);
    b += b;
  }
  else if (hex_string.length == 6) {
    r = hex_string.substr(0, 2);
    g = hex_string.substr(2, 2);
    b = hex_string.substr(4, 2);
  }
  else
    return default_;
    
  r = parseInt(r, 16);
  g = parseInt(g, 16);
  b = parseInt(b, 16);
  if (isNaN(r) || isNaN(g) || isNaN(b))
    return default_;
  else
    return {r: r / 255, g: g / 255, b: b / 255};
}/*}}}*/
function rgbToHex(r, g, b, includeHash) {/*{{{*/
  r = Math.round(r * 255);
  g = Math.round(g * 255);
  b = Math.round(b * 255);
  if (includeHash == undefined)
    includeHash = true;

  r = r.toString(16);
  if (r.length == 1)
    r = '0' + r;

  g = g.toString(16);
  if (g.length == 1)
    g = '0' + g;

  b = b.toString(16);
  if (b.length == 1)
    b = '0' + b;

  return ((includeHash ? '#' : '') + r + g + b).toUpperCase();
}/*}}}*/



