includes/clientside/static/rank-manager.js
changeset 1227 bdac73ed481e
parent 823 4596c40aaa94
--- a/includes/clientside/static/rank-manager.js	Sun Mar 28 21:49:26 2010 -0400
+++ b/includes/clientside/static/rank-manager.js	Sun Mar 28 23:10:46 2010 -0400
@@ -4,477 +4,477 @@
 
 var RankEditorControl = function(rankdata)
 {
-  this.rankdata = ( typeof(rankdata) == 'object' ) ? rankdata : {};
-  if ( !this.rankdata.rank_style )
-  {
-    this.rankdata.rank_style = '';
-  }
-  
-  // have the browser parse CSS for us and use an anchor to be as close
-  // as possible in calculating CSS
-  
-  // this is kind of a hack as it relies on setAttribute/getAttribute in
-  // order to obtain stringified versions of CSS data
-  var cssobj = document.createElement('a');
-  cssobj.setAttribute('style', this.rankdata.rank_style);
-  
-  this.style_sim_obj = cssobj;
-  
-  // figure out if we're editing or creating
-  this.editing = ( typeof(this.rankdata.rank_id) == 'number' );
-  
-  this.render = function()
-  {
-    var editor = document.createElement('div');
-    editor.className = 'tblholder';
-    // stash this editor instance in the parent div for later function calls
-    editor.editor = this;
-    this.wrapperdiv = editor;
-    editor.style.width = '100%';
-    
-    // tables suck.
-    var table = document.createElement('table');
-    table.setAttribute('cellspacing', '1');
-    table.setAttribute('cellpadding', '4');
-    table.setAttribute('width', '100%');
-    
-    // heading: "Edit rank: foo" or "Create a new rank"
-    var tr_head = document.createElement('tr');
-    var th_head = document.createElement('th');
-    th_head.setAttribute('colspan', '2');
-    if ( this.editing )
-    {
-      var th_head_string = 'acpur_th_edit_rank';
-      var th_head_data = { rank_title: $lang.get(this.rankdata.rank_title) };
-    }
-    else
-    {
-      var th_head_string = 'acpur_th_create_rank';
-      var th_head_data = { };
-    }
-    th_head.appendChild(document.createTextNode($lang.get(th_head_string, th_head_data)));
-    tr_head.appendChild(th_head);
-    this.th_head = th_head;
-    table.appendChild(tr_head);
-    
-    // row: rank title
-    var tr_title = document.createElement('tr');
-    var td_title_l = document.createElement('td');
-    var td_title_f = document.createElement('td');
-    
-    td_title_l.className = td_title_f.className = 'row1';
-    
-    td_title_l.appendChild(document.createTextNode($lang.get('acpur_field_rank_title')));
-    
-    // field: rank title
-    var f_rank_title = document.createElement('input');
-    f_rank_title.type = 'text';
-    f_rank_title.size = '30';
-    f_rank_title.value = ( this.editing ) ? this.rankdata.rank_title : '';
-    f_rank_title.editor = this;
-    f_rank_title.onkeyup = function()
-    {
-      this.editor.renderPreview();
-    }
-    this.f_rank_title = f_rank_title;
-    td_title_f.appendChild(f_rank_title);
-    
-    tr_title.appendChild(td_title_l);
-    tr_title.appendChild(td_title_f);
-    table.appendChild(tr_title);
-    
-    // row: basic style options
-    var tr_basic = document.createElement('tr');
-    var td_basic_l = document.createElement('td');
-    var td_basic_f = document.createElement('td');
-    
-    td_basic_l.className = td_basic_f.className = 'row2';
-    
-    td_basic_l.appendChild(document.createTextNode($lang.get('acpur_field_style_basic')));
-    
-    // fieldset: basic style options
-    // field: bold
-    var l_basic_bold = document.createElement('label');
-    var f_basic_bold = document.createElement('input');
-    f_basic_bold.type = 'checkbox';
-    f_basic_bold.checked = ( this.style_sim_obj.style.fontWeight == 'bold' ) ? true : false;
-    f_basic_bold.editor = this;
-    f_basic_bold.onclick = function()
-    {
-      this.editor.style_sim_obj.style.fontWeight = ( this.checked ) ? 'bold' : null;
-      this.editor.renderPreview();
-    }
-    l_basic_bold.style.fontWeight = 'bold';
-    l_basic_bold.appendChild(f_basic_bold);
-    l_basic_bold.appendChild(document.createTextNode(' '));
-    l_basic_bold.appendChild(document.createTextNode($lang.get('acpur_field_style_basic_bold')));
-    
-    // field: italic
-    var l_basic_italic = document.createElement('label');
-    var f_basic_italic = document.createElement('input');
-    f_basic_italic.type = 'checkbox';
-    f_basic_italic.checked = ( this.style_sim_obj.style.fontStyle == 'italic' ) ? true : false;
-    f_basic_italic.editor = this;
-    f_basic_italic.onclick = function()
-    {
-      this.editor.style_sim_obj.style.fontStyle = ( this.checked ) ? 'italic' : null;
-      this.editor.renderPreview();
-    }
-    l_basic_italic.style.fontStyle = 'italic';
-    l_basic_italic.appendChild(f_basic_italic);
-    l_basic_italic.appendChild(document.createTextNode(' '));
-    l_basic_italic.appendChild(document.createTextNode($lang.get('acpur_field_style_basic_italic')));
-    
-    // field: underline
-    var l_basic_underline = document.createElement('label');
-    var f_basic_underline = document.createElement('input');
-    f_basic_underline.type = 'checkbox';
-    f_basic_underline.checked = ( this.style_sim_obj.style.textDecoration == 'underline' ) ? true : false;
-    f_basic_underline.editor = this;
-    f_basic_underline.onclick = function()
-    {
-      this.editor.style_sim_obj.style.textDecoration = ( this.checked ) ? 'underline' : null;
-      this.editor.renderPreview();
-    }
-    l_basic_underline.style.textDecoration = 'underline';
-    l_basic_underline.appendChild(f_basic_underline);
-    l_basic_underline.appendChild(document.createTextNode(' '));
-    l_basic_underline.appendChild(document.createTextNode($lang.get('acpur_field_style_basic_underline')));
-    
-    // finish up formatting row#1
-    td_basic_f.appendChild(l_basic_bold);
-    td_basic_f.appendChild(document.createTextNode(' '));
-    td_basic_f.appendChild(l_basic_italic);
-    td_basic_f.appendChild(document.createTextNode(' '));
-    td_basic_f.appendChild(l_basic_underline);
-    
-    tr_basic.appendChild(td_basic_l);
-    tr_basic.appendChild(td_basic_f);
-    table.appendChild(tr_basic);
-    
-    // row: rank color
-    var tr_color = document.createElement('tr');
-    var td_color_l = document.createElement('td');
-    var td_color_f = document.createElement('td');
-    
-    td_color_l.className = td_color_f.className = 'row1';
-    
-    td_color_l.appendChild(document.createTextNode($lang.get('acpur_field_style_color')));
-    
-    // field: rank color
-    var f_rank_color = document.createElement('input');
-    f_rank_color.type = 'text';
-    f_rank_color.size = '7';
-    f_rank_color.value = ( this.editing ) ? this.rgb2hex(this.style_sim_obj.style.color) : '';
-    f_rank_color.style.backgroundColor = this.style_sim_obj.style.color;
-    f_rank_color.editor = this;
-    this.f_rank_color = f_rank_color;
-    f_rank_color.onkeyup = function(e)
-    {
-      if ( !e.keyCode )
-        e = window.event;
-      if ( !e )
-        return false;
-      var chr = (String.fromCharCode(e.keyCode)).toLowerCase();
-      this.value = this.value.replace(/[^a-fA-F0-9]/g, '');
-      if ( this.value.length > 6 )
-      {
-        this.value = this.value.substr(0, 6);
-      }
-      if ( this.value.length == 6 || this.value.length == 3 )
-      {
-        this.style.backgroundColor = '#' + this.value;
-        this.editor.style_sim_obj.style.color = '#' + this.value;
-        this.style.color = '#' + this.editor.determineLightness(this.value);
-        this.editor.renderPreview();
-      }
-      else if ( this.value.length == 0 )
-      {
-        this.style.backgroundColor = null;
-        this.editor.style_sim_obj.style.color = null;
-        this.editor.renderPreview();
-      }
-    }
-    td_color_f.appendChild(f_rank_color);
-    
-    tr_color.appendChild(td_color_l);
-    tr_color.appendChild(td_color_f);
-    table.appendChild(tr_color);
-    
-    // field: additional CSS
-    var tr_css = document.createElement('tr');
-    
-    var td_css_l = document.createElement('td');
-    td_css_l.className = 'row2';
-    td_css_l.appendChild(document.createTextNode($lang.get('acpur_field_style_css')));
-    tr_css.appendChild(td_css_l);
-    
-    var td_css_f = document.createElement('td');
-    td_css_f.className = 'row2';
-    var f_css = document.createElement('input');
-    f_css.type = 'text';
-    f_css.value = this.stripBasicCSSAttributes(this.rankdata.rank_style);
-    f_css.style.width = '98%';
-    f_css.editor = this;
-    f_css.onkeyup = function()
-    {
-      if ( !(trim(this.value)).match(/^((([a-z-]+):(.+?);)+)?$/) )
-        return;
-      var newcss = this.editor.stripExtendedCSSAttributes(String(this.editor.style_sim_obj.getAttribute('style'))) + ' ' + this.value;
-      this.editor.preview_div.setAttribute('style', 'font-size: x-large; ' + newcss);
-      this.editor.style_sim_obj.setAttribute('style', newcss);
-    }
-    this.f_css = f_css;
-    td_css_f.appendChild(f_css);
-    tr_css.appendChild(td_css_f);
-    table.appendChild(tr_css);
-    
-    // "field": preview
-    var tr_preview = document.createElement('tr');
-    var td_preview_l = document.createElement('td');
-    td_preview_l.className = 'row1';
-    td_preview_l.appendChild(document.createTextNode($lang.get('acpur_field_preview')));
-    tr_preview.appendChild(td_preview_l);
-    
-    var td_preview_f = document.createElement('td');
-    td_preview_f.className = 'row1';
-    var div_preview = document.createElement('a');
-    this.preview_div = div_preview;
-    div_preview.style.fontSize = 'x-large';
-    div_preview.appendChild(document.createTextNode(''));
-    div_preview.firstChild.nodeValue = ( this.editing ) ? this.rankdata.rank_title : '';
-    td_preview_f.appendChild(div_preview);
-    tr_preview.appendChild(td_preview_f);
-    
-    table.appendChild(tr_preview);
-    
-    // submit button
-    var tr_submit = document.createElement('tr');
-    var th_submit = document.createElement('th');
-    th_submit.className = 'subhead';
-    th_submit.setAttribute('colspan', '2');
-    var btn_submit = document.createElement('input');
-    btn_submit.type = 'submit';
-    btn_submit.value = ( this.editing ) ? $lang.get('acpur_btn_save') : $lang.get('acpur_btn_create_submit');
-    btn_submit.editor = this;
-    btn_submit.style.fontWeight = 'bold';
-    btn_submit.onclick = function(e)
-    {
-      this.editor.submitEvent(e);
-    }
-    this.btn_submit = btn_submit;
-    th_submit.appendChild(btn_submit);
-    
-    // delete button
-    if ( this.editing )
-    {
-      var btn_delete = document.createElement('input');
-      btn_delete.type = 'button';
-      btn_delete.value = $lang.get('acpur_btn_delete');
-      btn_delete.editor = this;
-      btn_delete.onclick = function(e)
-      {
-        this.editor.deleteEvent(e);
-      }
-      th_submit.appendChild(document.createTextNode(' '));
-      th_submit.appendChild(btn_delete);
-    }
-    
-    tr_submit.appendChild(th_submit);
-    
-    table.appendChild(tr_submit);
-    
-    // render preview
-    this.renderPreview();
-    
-    // finalize the editor table
-    editor.appendChild(table);
-    
-    // stash rendered editor
-    this.editordiv = editor;
-    
-    // send output
-    return editor;
-  }
-  
-  /**
-   * Takes the existing editor div and transforms the necessary elements so that it goes from "create" mode to "edit" mode
-   * @param object Edit data - same format as the rankdata parameter to the constructor, but we should only need rank_id
-   */
-  
-  this.transformToEditor = function(rankdata)
-  {
-    // we need a rank ID
-    if ( typeof(rankdata.rank_id) != 'number' )
-      return false;
-    
-    if ( this.editing )
-      return false;
-    
-    this.editing = true;
-    
-    this.rankdata = rankdata;
-    this.rankdata.rank_title = this.f_rank_title.value;
-    this.rankdata.rank_style = this.getCSS();
-    
-    // transform various controls
-    this.th_head.firstChild.nodeValue = $lang.get('acpur_th_edit_rank', {
-        rank_title: $lang.get(this.rankdata.rank_title)
-      });
-    this.btn_submit.value = $lang.get('acpur_btn_save');
-    
-    // add the delete button
-    var th_submit = this.btn_submit.parentNode;
-    
-    var btn_delete = document.createElement('input');
-    btn_delete.type = 'button';
-    btn_delete.value = $lang.get('acpur_btn_delete');
-    btn_delete.editor = this;
-    btn_delete.onclick = function(e)
-    {
-      this.editor.deleteEvent(e);
-    }
-    th_submit.appendChild(document.createTextNode(' '));
-    th_submit.appendChild(btn_delete);
-    
-    return true;
-  }
-  
-  /**
-   * Takes a hex color, averages the three channels, and returns either 'ffffff' or '000000' depending on the luminosity of the color.
-   * @param string
-   * @return string
-   */
-  
-  this.determineLightness = function(hexval)
-  {
-    var rgb = this.hex2rgb(hexval);
-    var lumin = ( rgb[0] + rgb[1] + rgb[2] ) / 3;
-    return ( lumin > 60 ) ? '000000' : 'ffffff';
-  }
-  
-  /**
-   * Strips out basic CSS attributes (color, font-weight, font-style, text-decoration) from a snippet of CSS.
-   * @param string
-   * @return string
-   */
-  
-  this.stripBasicCSSAttributes = function(css)
-  {
-    return trim(css.replace(/(color|font-weight|font-style|text-decoration): ?([A-z0-9# ,\(\)]+);/g, ''));
-  }
-  
-  /**
-   * Strips out all but basic CSS attributes.
-   * @param string
-   * @return string
-   */
-  
-  this.stripExtendedCSSAttributes = function(css)
-  {
-    var match;
-    var final_css = '';
-    var basics = ['color', 'font-weight', 'font-style', 'text-decoration'];
-    while ( match = css.match(/([a-z-]+):(.+?);/) )
-    {
-      if ( in_array(match[1], basics) )
-      {
-        final_css += ' ' + match[0] + ' ';
-      }
-      css = css.replace(match[0], '');
-    }
-    final_css = trim(final_css);
-    return final_css;
-  }
-  
-  this.getCSS = function()
-  {
-    return this.style_sim_obj.getAttribute('style');
-  }
-  
-  this.renderPreview = function()
-  {
-    if ( !this.preview_div )
-      return false;
-    var color = ( this.style_sim_obj.style.color ) ? '#' + this.rgb2hex(this.style_sim_obj.style.color) : null;
-    this.preview_div.style.color = color;
-    this.preview_div.style.fontWeight = this.style_sim_obj.style.fontWeight;
-    this.preview_div.style.fontStyle = this.style_sim_obj.style.fontStyle;
-    this.preview_div.style.textDecoration = this.style_sim_obj.style.textDecoration;
-    this.preview_div.firstChild.nodeValue = $lang.get(this.f_rank_title.value);
-  }
-  
-  this.submitEvent = function(e)
-  {
-    if ( this.onsubmit )
-    {
-      this.onsubmit(e);
-    }
-    else
-    {
-      window.console.error('RankEditorControl: no onsubmit event specified');
-    }
-  }
-  
-  this.deleteEvent = function(e)
-  {
-    if ( this.ondelete )
-    {
-      this.ondelete(e);
-    }
-    else
-    {
-      window.console.error('RankEditorControl: no ondelete event specified');
-    }
-  }
-  
-  /**
-   * Converts a parenthetical color specification (rgb(x, y, z)) to hex form (xxyyzz)
-   * @param string
-   * @return string
-   */
-  
-  this.rgb2hex = function(rgb)
-  {
-    var p = rgb.match(/^rgb\(([0-9]+), ([0-9]+), ([0-9]+)\)$/);
-    if ( !p )
-      return rgb.replace(/^#/, '');
-    
-    var r = parseInt(p[1]).toString(16), g = parseInt(p[2]).toString(16), b = parseInt(p[3]).toString(16);
-    if ( r.length < 2 )
-      r = '0' + r;
-    if ( g.length < 2 )
-      g = '0' + g;
-    if ( b.length < 2 )
-      b = '0' + b;
-    
-    return r + g + b;
-  }
-  
-  /**
-   * Get red, green, and blue values for the given hex color
-   * @param string
-   * @return array (numbered, e.g. not an object
-   */
-  
-  this.hex2rgb = function(hex)
-  {
-    hex = hex.replace(/^#/, '');
-    if ( hex.length != 3 && hex.length != 6 )
-    {
-      return hex;
-    }
-    if ( hex.length == 3 )
-    {
-      // is there a better way to do this?
-      hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2);
-    }
-    hex = [ hex.substr(0, 2), hex.substr(2, 2), hex.substr(4, 2) ];
-    var red = parseInt(hex[0], 16);
-    var green = parseInt(hex[1], 16);
-    var blue = parseInt(hex[2], 16);
-    return [red, green, blue];
-  }
+	this.rankdata = ( typeof(rankdata) == 'object' ) ? rankdata : {};
+	if ( !this.rankdata.rank_style )
+	{
+		this.rankdata.rank_style = '';
+	}
+	
+	// have the browser parse CSS for us and use an anchor to be as close
+	// as possible in calculating CSS
+	
+	// this is kind of a hack as it relies on setAttribute/getAttribute in
+	// order to obtain stringified versions of CSS data
+	var cssobj = document.createElement('a');
+	cssobj.setAttribute('style', this.rankdata.rank_style);
+	
+	this.style_sim_obj = cssobj;
+	
+	// figure out if we're editing or creating
+	this.editing = ( typeof(this.rankdata.rank_id) == 'number' );
+	
+	this.render = function()
+	{
+		var editor = document.createElement('div');
+		editor.className = 'tblholder';
+		// stash this editor instance in the parent div for later function calls
+		editor.editor = this;
+		this.wrapperdiv = editor;
+		editor.style.width = '100%';
+		
+		// tables suck.
+		var table = document.createElement('table');
+		table.setAttribute('cellspacing', '1');
+		table.setAttribute('cellpadding', '4');
+		table.setAttribute('width', '100%');
+		
+		// heading: "Edit rank: foo" or "Create a new rank"
+		var tr_head = document.createElement('tr');
+		var th_head = document.createElement('th');
+		th_head.setAttribute('colspan', '2');
+		if ( this.editing )
+		{
+			var th_head_string = 'acpur_th_edit_rank';
+			var th_head_data = { rank_title: $lang.get(this.rankdata.rank_title) };
+		}
+		else
+		{
+			var th_head_string = 'acpur_th_create_rank';
+			var th_head_data = { };
+		}
+		th_head.appendChild(document.createTextNode($lang.get(th_head_string, th_head_data)));
+		tr_head.appendChild(th_head);
+		this.th_head = th_head;
+		table.appendChild(tr_head);
+		
+		// row: rank title
+		var tr_title = document.createElement('tr');
+		var td_title_l = document.createElement('td');
+		var td_title_f = document.createElement('td');
+		
+		td_title_l.className = td_title_f.className = 'row1';
+		
+		td_title_l.appendChild(document.createTextNode($lang.get('acpur_field_rank_title')));
+		
+		// field: rank title
+		var f_rank_title = document.createElement('input');
+		f_rank_title.type = 'text';
+		f_rank_title.size = '30';
+		f_rank_title.value = ( this.editing ) ? this.rankdata.rank_title : '';
+		f_rank_title.editor = this;
+		f_rank_title.onkeyup = function()
+		{
+			this.editor.renderPreview();
+		}
+		this.f_rank_title = f_rank_title;
+		td_title_f.appendChild(f_rank_title);
+		
+		tr_title.appendChild(td_title_l);
+		tr_title.appendChild(td_title_f);
+		table.appendChild(tr_title);
+		
+		// row: basic style options
+		var tr_basic = document.createElement('tr');
+		var td_basic_l = document.createElement('td');
+		var td_basic_f = document.createElement('td');
+		
+		td_basic_l.className = td_basic_f.className = 'row2';
+		
+		td_basic_l.appendChild(document.createTextNode($lang.get('acpur_field_style_basic')));
+		
+		// fieldset: basic style options
+		// field: bold
+		var l_basic_bold = document.createElement('label');
+		var f_basic_bold = document.createElement('input');
+		f_basic_bold.type = 'checkbox';
+		f_basic_bold.checked = ( this.style_sim_obj.style.fontWeight == 'bold' ) ? true : false;
+		f_basic_bold.editor = this;
+		f_basic_bold.onclick = function()
+		{
+			this.editor.style_sim_obj.style.fontWeight = ( this.checked ) ? 'bold' : null;
+			this.editor.renderPreview();
+		}
+		l_basic_bold.style.fontWeight = 'bold';
+		l_basic_bold.appendChild(f_basic_bold);
+		l_basic_bold.appendChild(document.createTextNode(' '));
+		l_basic_bold.appendChild(document.createTextNode($lang.get('acpur_field_style_basic_bold')));
+		
+		// field: italic
+		var l_basic_italic = document.createElement('label');
+		var f_basic_italic = document.createElement('input');
+		f_basic_italic.type = 'checkbox';
+		f_basic_italic.checked = ( this.style_sim_obj.style.fontStyle == 'italic' ) ? true : false;
+		f_basic_italic.editor = this;
+		f_basic_italic.onclick = function()
+		{
+			this.editor.style_sim_obj.style.fontStyle = ( this.checked ) ? 'italic' : null;
+			this.editor.renderPreview();
+		}
+		l_basic_italic.style.fontStyle = 'italic';
+		l_basic_italic.appendChild(f_basic_italic);
+		l_basic_italic.appendChild(document.createTextNode(' '));
+		l_basic_italic.appendChild(document.createTextNode($lang.get('acpur_field_style_basic_italic')));
+		
+		// field: underline
+		var l_basic_underline = document.createElement('label');
+		var f_basic_underline = document.createElement('input');
+		f_basic_underline.type = 'checkbox';
+		f_basic_underline.checked = ( this.style_sim_obj.style.textDecoration == 'underline' ) ? true : false;
+		f_basic_underline.editor = this;
+		f_basic_underline.onclick = function()
+		{
+			this.editor.style_sim_obj.style.textDecoration = ( this.checked ) ? 'underline' : null;
+			this.editor.renderPreview();
+		}
+		l_basic_underline.style.textDecoration = 'underline';
+		l_basic_underline.appendChild(f_basic_underline);
+		l_basic_underline.appendChild(document.createTextNode(' '));
+		l_basic_underline.appendChild(document.createTextNode($lang.get('acpur_field_style_basic_underline')));
+		
+		// finish up formatting row#1
+		td_basic_f.appendChild(l_basic_bold);
+		td_basic_f.appendChild(document.createTextNode(' '));
+		td_basic_f.appendChild(l_basic_italic);
+		td_basic_f.appendChild(document.createTextNode(' '));
+		td_basic_f.appendChild(l_basic_underline);
+		
+		tr_basic.appendChild(td_basic_l);
+		tr_basic.appendChild(td_basic_f);
+		table.appendChild(tr_basic);
+		
+		// row: rank color
+		var tr_color = document.createElement('tr');
+		var td_color_l = document.createElement('td');
+		var td_color_f = document.createElement('td');
+		
+		td_color_l.className = td_color_f.className = 'row1';
+		
+		td_color_l.appendChild(document.createTextNode($lang.get('acpur_field_style_color')));
+		
+		// field: rank color
+		var f_rank_color = document.createElement('input');
+		f_rank_color.type = 'text';
+		f_rank_color.size = '7';
+		f_rank_color.value = ( this.editing ) ? this.rgb2hex(this.style_sim_obj.style.color) : '';
+		f_rank_color.style.backgroundColor = this.style_sim_obj.style.color;
+		f_rank_color.editor = this;
+		this.f_rank_color = f_rank_color;
+		f_rank_color.onkeyup = function(e)
+		{
+			if ( !e.keyCode )
+				e = window.event;
+			if ( !e )
+				return false;
+			var chr = (String.fromCharCode(e.keyCode)).toLowerCase();
+			this.value = this.value.replace(/[^a-fA-F0-9]/g, '');
+			if ( this.value.length > 6 )
+			{
+				this.value = this.value.substr(0, 6);
+			}
+			if ( this.value.length == 6 || this.value.length == 3 )
+			{
+				this.style.backgroundColor = '#' + this.value;
+				this.editor.style_sim_obj.style.color = '#' + this.value;
+				this.style.color = '#' + this.editor.determineLightness(this.value);
+				this.editor.renderPreview();
+			}
+			else if ( this.value.length == 0 )
+			{
+				this.style.backgroundColor = null;
+				this.editor.style_sim_obj.style.color = null;
+				this.editor.renderPreview();
+			}
+		}
+		td_color_f.appendChild(f_rank_color);
+		
+		tr_color.appendChild(td_color_l);
+		tr_color.appendChild(td_color_f);
+		table.appendChild(tr_color);
+		
+		// field: additional CSS
+		var tr_css = document.createElement('tr');
+		
+		var td_css_l = document.createElement('td');
+		td_css_l.className = 'row2';
+		td_css_l.appendChild(document.createTextNode($lang.get('acpur_field_style_css')));
+		tr_css.appendChild(td_css_l);
+		
+		var td_css_f = document.createElement('td');
+		td_css_f.className = 'row2';
+		var f_css = document.createElement('input');
+		f_css.type = 'text';
+		f_css.value = this.stripBasicCSSAttributes(this.rankdata.rank_style);
+		f_css.style.width = '98%';
+		f_css.editor = this;
+		f_css.onkeyup = function()
+		{
+			if ( !(trim(this.value)).match(/^((([a-z-]+):(.+?);)+)?$/) )
+				return;
+			var newcss = this.editor.stripExtendedCSSAttributes(String(this.editor.style_sim_obj.getAttribute('style'))) + ' ' + this.value;
+			this.editor.preview_div.setAttribute('style', 'font-size: x-large; ' + newcss);
+			this.editor.style_sim_obj.setAttribute('style', newcss);
+		}
+		this.f_css = f_css;
+		td_css_f.appendChild(f_css);
+		tr_css.appendChild(td_css_f);
+		table.appendChild(tr_css);
+		
+		// "field": preview
+		var tr_preview = document.createElement('tr');
+		var td_preview_l = document.createElement('td');
+		td_preview_l.className = 'row1';
+		td_preview_l.appendChild(document.createTextNode($lang.get('acpur_field_preview')));
+		tr_preview.appendChild(td_preview_l);
+		
+		var td_preview_f = document.createElement('td');
+		td_preview_f.className = 'row1';
+		var div_preview = document.createElement('a');
+		this.preview_div = div_preview;
+		div_preview.style.fontSize = 'x-large';
+		div_preview.appendChild(document.createTextNode(''));
+		div_preview.firstChild.nodeValue = ( this.editing ) ? this.rankdata.rank_title : '';
+		td_preview_f.appendChild(div_preview);
+		tr_preview.appendChild(td_preview_f);
+		
+		table.appendChild(tr_preview);
+		
+		// submit button
+		var tr_submit = document.createElement('tr');
+		var th_submit = document.createElement('th');
+		th_submit.className = 'subhead';
+		th_submit.setAttribute('colspan', '2');
+		var btn_submit = document.createElement('input');
+		btn_submit.type = 'submit';
+		btn_submit.value = ( this.editing ) ? $lang.get('acpur_btn_save') : $lang.get('acpur_btn_create_submit');
+		btn_submit.editor = this;
+		btn_submit.style.fontWeight = 'bold';
+		btn_submit.onclick = function(e)
+		{
+			this.editor.submitEvent(e);
+		}
+		this.btn_submit = btn_submit;
+		th_submit.appendChild(btn_submit);
+		
+		// delete button
+		if ( this.editing )
+		{
+			var btn_delete = document.createElement('input');
+			btn_delete.type = 'button';
+			btn_delete.value = $lang.get('acpur_btn_delete');
+			btn_delete.editor = this;
+			btn_delete.onclick = function(e)
+			{
+				this.editor.deleteEvent(e);
+			}
+			th_submit.appendChild(document.createTextNode(' '));
+			th_submit.appendChild(btn_delete);
+		}
+		
+		tr_submit.appendChild(th_submit);
+		
+		table.appendChild(tr_submit);
+		
+		// render preview
+		this.renderPreview();
+		
+		// finalize the editor table
+		editor.appendChild(table);
+		
+		// stash rendered editor
+		this.editordiv = editor;
+		
+		// send output
+		return editor;
+	}
+	
+	/**
+ 	* Takes the existing editor div and transforms the necessary elements so that it goes from "create" mode to "edit" mode
+ 	* @param object Edit data - same format as the rankdata parameter to the constructor, but we should only need rank_id
+ 	*/
+	
+	this.transformToEditor = function(rankdata)
+	{
+		// we need a rank ID
+		if ( typeof(rankdata.rank_id) != 'number' )
+			return false;
+		
+		if ( this.editing )
+			return false;
+		
+		this.editing = true;
+		
+		this.rankdata = rankdata;
+		this.rankdata.rank_title = this.f_rank_title.value;
+		this.rankdata.rank_style = this.getCSS();
+		
+		// transform various controls
+		this.th_head.firstChild.nodeValue = $lang.get('acpur_th_edit_rank', {
+				rank_title: $lang.get(this.rankdata.rank_title)
+			});
+		this.btn_submit.value = $lang.get('acpur_btn_save');
+		
+		// add the delete button
+		var th_submit = this.btn_submit.parentNode;
+		
+		var btn_delete = document.createElement('input');
+		btn_delete.type = 'button';
+		btn_delete.value = $lang.get('acpur_btn_delete');
+		btn_delete.editor = this;
+		btn_delete.onclick = function(e)
+		{
+			this.editor.deleteEvent(e);
+		}
+		th_submit.appendChild(document.createTextNode(' '));
+		th_submit.appendChild(btn_delete);
+		
+		return true;
+	}
+	
+	/**
+ 	* Takes a hex color, averages the three channels, and returns either 'ffffff' or '000000' depending on the luminosity of the color.
+ 	* @param string
+ 	* @return string
+ 	*/
+	
+	this.determineLightness = function(hexval)
+	{
+		var rgb = this.hex2rgb(hexval);
+		var lumin = ( rgb[0] + rgb[1] + rgb[2] ) / 3;
+		return ( lumin > 60 ) ? '000000' : 'ffffff';
+	}
+	
+	/**
+ 	* Strips out basic CSS attributes (color, font-weight, font-style, text-decoration) from a snippet of CSS.
+ 	* @param string
+ 	* @return string
+ 	*/
+	
+	this.stripBasicCSSAttributes = function(css)
+	{
+		return trim(css.replace(/(color|font-weight|font-style|text-decoration): ?([A-z0-9# ,\(\)]+);/g, ''));
+	}
+	
+	/**
+ 	* Strips out all but basic CSS attributes.
+ 	* @param string
+ 	* @return string
+ 	*/
+	
+	this.stripExtendedCSSAttributes = function(css)
+	{
+		var match;
+		var final_css = '';
+		var basics = ['color', 'font-weight', 'font-style', 'text-decoration'];
+		while ( match = css.match(/([a-z-]+):(.+?);/) )
+		{
+			if ( in_array(match[1], basics) )
+			{
+				final_css += ' ' + match[0] + ' ';
+			}
+			css = css.replace(match[0], '');
+		}
+		final_css = trim(final_css);
+		return final_css;
+	}
+	
+	this.getCSS = function()
+	{
+		return this.style_sim_obj.getAttribute('style');
+	}
+	
+	this.renderPreview = function()
+	{
+		if ( !this.preview_div )
+			return false;
+		var color = ( this.style_sim_obj.style.color ) ? '#' + this.rgb2hex(this.style_sim_obj.style.color) : null;
+		this.preview_div.style.color = color;
+		this.preview_div.style.fontWeight = this.style_sim_obj.style.fontWeight;
+		this.preview_div.style.fontStyle = this.style_sim_obj.style.fontStyle;
+		this.preview_div.style.textDecoration = this.style_sim_obj.style.textDecoration;
+		this.preview_div.firstChild.nodeValue = $lang.get(this.f_rank_title.value);
+	}
+	
+	this.submitEvent = function(e)
+	{
+		if ( this.onsubmit )
+		{
+			this.onsubmit(e);
+		}
+		else
+		{
+			window.console.error('RankEditorControl: no onsubmit event specified');
+		}
+	}
+	
+	this.deleteEvent = function(e)
+	{
+		if ( this.ondelete )
+		{
+			this.ondelete(e);
+		}
+		else
+		{
+			window.console.error('RankEditorControl: no ondelete event specified');
+		}
+	}
+	
+	/**
+ 	* Converts a parenthetical color specification (rgb(x, y, z)) to hex form (xxyyzz)
+ 	* @param string
+ 	* @return string
+ 	*/
+	
+	this.rgb2hex = function(rgb)
+	{
+		var p = rgb.match(/^rgb\(([0-9]+), ([0-9]+), ([0-9]+)\)$/);
+		if ( !p )
+			return rgb.replace(/^#/, '');
+		
+		var r = parseInt(p[1]).toString(16), g = parseInt(p[2]).toString(16), b = parseInt(p[3]).toString(16);
+		if ( r.length < 2 )
+			r = '0' + r;
+		if ( g.length < 2 )
+			g = '0' + g;
+		if ( b.length < 2 )
+			b = '0' + b;
+		
+		return r + g + b;
+	}
+	
+	/**
+ 	* Get red, green, and blue values for the given hex color
+ 	* @param string
+ 	* @return array (numbered, e.g. not an object
+ 	*/
+	
+	this.hex2rgb = function(hex)
+	{
+		hex = hex.replace(/^#/, '');
+		if ( hex.length != 3 && hex.length != 6 )
+		{
+			return hex;
+		}
+		if ( hex.length == 3 )
+		{
+			// is there a better way to do this?
+			hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2);
+		}
+		hex = [ hex.substr(0, 2), hex.substr(2, 2), hex.substr(4, 2) ];
+		var red = parseInt(hex[0], 16);
+		var green = parseInt(hex[1], 16);
+		var blue = parseInt(hex[2], 16);
+		return [red, green, blue];
+	}
 }
 
 /**
@@ -483,313 +483,313 @@
 
 function ajaxInitRankEdit(rank_id)
 {
-  load_component('messagebox');
-  var json_packet = {
-    mode: 'get_rank',
-    rank_id: rank_id
-  };
-  json_packet = ajaxEscape(toJSONString(json_packet));
-  ajaxPost(makeUrlNS('Admin', 'UserRanks/action.json'), 'r=' + json_packet, function(ajax)
-    {
-      if ( ajax.readyState == 4 && ajax.status == 200 )
-      {
-        var response = String(ajax.responseText + '');
-        if ( !check_json_response(response) )
-        {
-          handle_invalid_json(ajax.responseText);
-          return false;
-        }
-        try
-        {
-          var response = parseJSON(ajax.responseText);
-        }
-        catch(e)
-        {
-          handle_invalid_json(ajax.responseText);
-        }
-        if ( response.error )
-        {
-          if ( response.error == 'need_auth_to_admin' )
-          {
-            load_component('login');
-            var rid = rank_id;
-            ajaxDynamicReauth(function()
-              {
-                ajaxInitRankEdit(rid);
-              });
-          }
-          else
-          {
-            alert(response.error);
-          }
-          return false;
-        }
-        var editor = new RankEditorControl(response);
-        editor.onsubmit = ajaxRankEditHandleSaveExisting;
-        editor.ondelete = ajaxRankEditHandleDelete;
-        var container = document.getElementById('admin_ranks_container_right');
-        container.innerHTML = '';
-        container.appendChild(editor.render());
-      }
-    }, true);
+	load_component('messagebox');
+	var json_packet = {
+		mode: 'get_rank',
+		rank_id: rank_id
+	};
+	json_packet = ajaxEscape(toJSONString(json_packet));
+	ajaxPost(makeUrlNS('Admin', 'UserRanks/action.json'), 'r=' + json_packet, function(ajax)
+		{
+			if ( ajax.readyState == 4 && ajax.status == 200 )
+			{
+				var response = String(ajax.responseText + '');
+				if ( !check_json_response(response) )
+				{
+					handle_invalid_json(ajax.responseText);
+					return false;
+				}
+				try
+				{
+					var response = parseJSON(ajax.responseText);
+				}
+				catch(e)
+				{
+					handle_invalid_json(ajax.responseText);
+				}
+				if ( response.error )
+				{
+					if ( response.error == 'need_auth_to_admin' )
+					{
+						load_component('login');
+						var rid = rank_id;
+						ajaxDynamicReauth(function()
+							{
+								ajaxInitRankEdit(rid);
+							});
+					}
+					else
+					{
+						alert(response.error);
+					}
+					return false;
+				}
+				var editor = new RankEditorControl(response);
+				editor.onsubmit = ajaxRankEditHandleSaveExisting;
+				editor.ondelete = ajaxRankEditHandleDelete;
+				var container = document.getElementById('admin_ranks_container_right');
+				container.innerHTML = '';
+				container.appendChild(editor.render());
+			}
+		}, true);
 }
 
 function ajaxInitRankCreate()
 {
-  load_component('messagebox');
-  var editor = new RankEditorControl();
-  editor.onsubmit = ajaxRankEditHandleSaveNew;
-  var container = document.getElementById('admin_ranks_container_right');
-  container.innerHTML = '';
-  container.appendChild(editor.render());
+	load_component('messagebox');
+	var editor = new RankEditorControl();
+	editor.onsubmit = ajaxRankEditHandleSaveNew;
+	var container = document.getElementById('admin_ranks_container_right');
+	container.innerHTML = '';
+	container.appendChild(editor.render());
 }
 
 function ajaxRankEditHandleSave(editor, switch_new)
 {
-  var whitey = whiteOutElement(editor.wrapperdiv);
-  
-  // pack it up, ...
-  var json_packet = {
-    mode: ( switch_new ) ? 'create_rank' : 'save_rank',
-    rank_title: editor.f_rank_title.value,
-    rank_style: editor.getCSS()
-  }
-  if ( !switch_new )
-  {
-    json_packet.rank_id = editor.rankdata.rank_id;
-  }
-  /// ... pack it in
-  var json_packet = ajaxEscape(toJSONString(json_packet));
-  
-  ajaxPost(makeUrlNS('Admin', 'UserRanks/action.json'), 'r=' + json_packet, function(ajax)
-    {
-      if ( ajax.readyState == 4 && ajax.status == 200 )
-      {
-        var response = String(ajax.responseText + '');
-        if ( !check_json_response(response) )
-        {
-          handle_invalid_json(ajax.responseText);
-          return false;
-        }
-        try
-        {
-          var response = parseJSON(ajax.responseText);
-        }
-        catch(e)
-        {
-          handle_invalid_json(ajax.responseText);
-        }
-        if ( response.mode == 'success' )
-        {
-          whiteOutReportSuccess(whitey);
-          if ( switch_new )
-          {
-            //
-            // we have a few more things to do with a newly created rank.
-            //
-            
-            // 1. transform editor
-            editor.transformToEditor(response);
-            editor.onsubmit = ajaxRankEditHandleSaveExisting;
-            editor.ondelete = ajaxRankEditHandleDelete;
-            
-            // 2. append the new rank to the list
-            var create_link = document.getElementById('rankadmin_createlink');
-            if ( create_link )
-            {
-              var parent = create_link.parentNode;
-              var edit_link = document.createElement('a');
-              edit_link.href = '#rank_edit:' + response.rank_id;
-              edit_link.className = 'rankadmin-editlink';
-              edit_link.setAttribute('style', editor.getCSS());
-              edit_link.id = 'rankadmin_editlink_' + response.rank_id;
-              edit_link.rank_id = response.rank_id;
-              edit_link.appendChild(document.createTextNode($lang.get(editor.f_rank_title.value)));
-              parent.insertBefore(edit_link, create_link);
-              edit_link.onclick = function()
-              {
-                ajaxInitRankEdit(this.rank_id);
-              }
-            }
-          }
-          else
-          {
-            // update the rank title on the left
-            var edit_link = document.getElementById('rankadmin_editlink_' + editor.rankdata.rank_id);
-            if ( edit_link )
-            {
-              edit_link.firstChild.nodeValue = $lang.get(editor.f_rank_title.value);
-              edit_link.setAttribute('style', editor.getCSS());
-            }
-          }
-        }
-        else
-        {
-          whitey.parentNode.removeChild(whitey);
-          if ( response.error == 'need_auth_to_admin' )
-          {
-            load_component('login');
-            ajaxDynamicReauth(function()
-              {
-                ajaxRankEditHandleSave(editor, switch_new);
-              });
-          }
-          else
-          {
-            miniPromptMessage({
-                title: $lang.get('acpur_err_save_failed_title'),
-                message: response.error,
-                buttons: [
-                  {
-                    text: $lang.get('etc_ok'),
-                    color: 'red',
-                    style: {
-                      fontWeight: 'bold'
-                    },
-                    onclick: function()
-                    {
-                      miniPromptDestroy(this);
-                    }
-                  }
-                ]
-            });
-          }
-        }
-      }
-    }, true);
+	var whitey = whiteOutElement(editor.wrapperdiv);
+	
+	// pack it up, ...
+	var json_packet = {
+		mode: ( switch_new ) ? 'create_rank' : 'save_rank',
+		rank_title: editor.f_rank_title.value,
+		rank_style: editor.getCSS()
+	}
+	if ( !switch_new )
+	{
+		json_packet.rank_id = editor.rankdata.rank_id;
+	}
+	/// ... pack it in
+	var json_packet = ajaxEscape(toJSONString(json_packet));
+	
+	ajaxPost(makeUrlNS('Admin', 'UserRanks/action.json'), 'r=' + json_packet, function(ajax)
+		{
+			if ( ajax.readyState == 4 && ajax.status == 200 )
+			{
+				var response = String(ajax.responseText + '');
+				if ( !check_json_response(response) )
+				{
+					handle_invalid_json(ajax.responseText);
+					return false;
+				}
+				try
+				{
+					var response = parseJSON(ajax.responseText);
+				}
+				catch(e)
+				{
+					handle_invalid_json(ajax.responseText);
+				}
+				if ( response.mode == 'success' )
+				{
+					whiteOutReportSuccess(whitey);
+					if ( switch_new )
+					{
+						//
+						// we have a few more things to do with a newly created rank.
+						//
+						
+						// 1. transform editor
+						editor.transformToEditor(response);
+						editor.onsubmit = ajaxRankEditHandleSaveExisting;
+						editor.ondelete = ajaxRankEditHandleDelete;
+						
+						// 2. append the new rank to the list
+						var create_link = document.getElementById('rankadmin_createlink');
+						if ( create_link )
+						{
+							var parent = create_link.parentNode;
+							var edit_link = document.createElement('a');
+							edit_link.href = '#rank_edit:' + response.rank_id;
+							edit_link.className = 'rankadmin-editlink';
+							edit_link.setAttribute('style', editor.getCSS());
+							edit_link.id = 'rankadmin_editlink_' + response.rank_id;
+							edit_link.rank_id = response.rank_id;
+							edit_link.appendChild(document.createTextNode($lang.get(editor.f_rank_title.value)));
+							parent.insertBefore(edit_link, create_link);
+							edit_link.onclick = function()
+							{
+								ajaxInitRankEdit(this.rank_id);
+							}
+						}
+					}
+					else
+					{
+						// update the rank title on the left
+						var edit_link = document.getElementById('rankadmin_editlink_' + editor.rankdata.rank_id);
+						if ( edit_link )
+						{
+							edit_link.firstChild.nodeValue = $lang.get(editor.f_rank_title.value);
+							edit_link.setAttribute('style', editor.getCSS());
+						}
+					}
+				}
+				else
+				{
+					whitey.parentNode.removeChild(whitey);
+					if ( response.error == 'need_auth_to_admin' )
+					{
+						load_component('login');
+						ajaxDynamicReauth(function()
+							{
+								ajaxRankEditHandleSave(editor, switch_new);
+							});
+					}
+					else
+					{
+						miniPromptMessage({
+								title: $lang.get('acpur_err_save_failed_title'),
+								message: response.error,
+								buttons: [
+									{
+										text: $lang.get('etc_ok'),
+										color: 'red',
+										style: {
+											fontWeight: 'bold'
+										},
+										onclick: function()
+										{
+											miniPromptDestroy(this);
+										}
+									}
+								]
+						});
+					}
+				}
+			}
+		}, true);
 }
 
 var ajaxRankEditHandleSaveExisting = function()
 {
-  ajaxRankEditHandleSave(this, false);
+	ajaxRankEditHandleSave(this, false);
 }
 
 var ajaxRankEditHandleSaveNew = function()
 {
-  ajaxRankEditHandleSave(this, true);
+	ajaxRankEditHandleSave(this, true);
 }
 
 var ajaxRankEditHandleDelete = function()
 {
-  var mp = miniPromptMessage({
-      title: $lang.get('acpur_msg_rank_delete_confirm_title'),
-      message: $lang.get('acpur_msg_rank_delete_confirm_body'),
-      buttons: [
-        {
-          text: $lang.get('acpur_btn_delete'),
-          color: 'red',
-          style: {
-            fontWeight: 'bold'
-          },
-          onclick: function()
-          {
-            var parent = miniPromptGetParent(this);
-            var editor = parent.editor;
-            setTimeout(function()
-              {
-                ajaxRankEditDeleteConfirmed(editor);
-              }, 1000);
-            miniPromptDestroy(parent);
-          }
-        },
-        {
-          text: $lang.get('etc_cancel'),
-          onclick: function()
-          {
-            miniPromptDestroy(this);
-          }
-        }
-      ]
-    });
-  console.debug(mp);
-  mp.editor = this;
+	var mp = miniPromptMessage({
+			title: $lang.get('acpur_msg_rank_delete_confirm_title'),
+			message: $lang.get('acpur_msg_rank_delete_confirm_body'),
+			buttons: [
+				{
+					text: $lang.get('acpur_btn_delete'),
+					color: 'red',
+					style: {
+						fontWeight: 'bold'
+					},
+					onclick: function()
+					{
+						var parent = miniPromptGetParent(this);
+						var editor = parent.editor;
+						setTimeout(function()
+							{
+								ajaxRankEditDeleteConfirmed(editor);
+							}, 1000);
+						miniPromptDestroy(parent);
+					}
+				},
+				{
+					text: $lang.get('etc_cancel'),
+					onclick: function()
+					{
+						miniPromptDestroy(this);
+					}
+				}
+			]
+		});
+	console.debug(mp);
+	mp.editor = this;
 }
 
 function ajaxRankEditDeleteConfirmed(editor)
 {
-  var whitey = whiteOutElement(editor.wrapperdiv);
-  
-  load_component(['jquery', 'jquery-ui']);
-  
-  var json_packet = {
-    mode: 'delete_rank',
-    rank_id: editor.rankdata.rank_id
-  };
-  var rank_id = editor.rankdata.rank_id;
-  
-  json_packet = ajaxEscape(toJSONString(json_packet));
-  ajaxPost(makeUrlNS('Admin', 'UserRanks/action.json'), 'r=' + json_packet, function(ajax)
-    {
-      if ( ajax.readyState == 4 && ajax.status == 200 )
-      {
-        var response = String(ajax.responseText + '');
-        if ( !check_json_response(response) )
-        {
-          handle_invalid_json(ajax.responseText);
-          return false;
-        }
-        try
-        {
-          var response = parseJSON(ajax.responseText);
-        }
-        catch(e)
-        {
-          handle_invalid_json(ajax.responseText);
-        }
-        if ( response.mode == 'success' )
-        {
-          // the deletion was successful, report success and kill off the editor
-          whiteOutReportSuccess(whitey);
-          setTimeout(function()
-            {
-              // nuke the rank title on the left
-              var edit_link = document.getElementById('rankadmin_editlink_' + editor.rankdata.rank_id);
-              if ( edit_link )
-              {
-                edit_link.parentNode.removeChild(edit_link);
-              }
-              // collapse and destroy the editor
-              $(editor.wrapperdiv).hide("blind", {}, 500, function()
-                  {
-                    // when the animation finishes, nuke the whole thing
-                    var container = document.getElementById('admin_ranks_container_right');
-                    container.innerHTML = $lang.get('acpur_msg_select_rank');
-                  }
-                );
-            }, 1500);
-        }
-        else
-        {
-          whitey.parentNode.removeChild(whitey);
-          if ( response.error == 'need_auth_to_admin' )
-          {
-            load_component('login');
-            ajaxDynamicReauth(function()
-              {
-                ajaxRankEditDeleteConfirmed(editor);
-              });
-          }
-          else
-          {
-            miniPromptMessage({
-                title: $lang.get('acpur_err_delete_failed_title'),
-                message: response.error,
-                buttons: [
-                  {
-                    text: $lang.get('etc_ok'),
-                    color: 'red',
-                    style: {
-                      fontWeight: 'bold'
-                    },
-                    onclick: function()
-                    {
-                      miniPromptDestroy(this);
-                    }
-                  }
-                ]
-            });
-          }
-        }
-      }
-    }, true);
+	var whitey = whiteOutElement(editor.wrapperdiv);
+	
+	load_component(['jquery', 'jquery-ui']);
+	
+	var json_packet = {
+		mode: 'delete_rank',
+		rank_id: editor.rankdata.rank_id
+	};
+	var rank_id = editor.rankdata.rank_id;
+	
+	json_packet = ajaxEscape(toJSONString(json_packet));
+	ajaxPost(makeUrlNS('Admin', 'UserRanks/action.json'), 'r=' + json_packet, function(ajax)
+		{
+			if ( ajax.readyState == 4 && ajax.status == 200 )
+			{
+				var response = String(ajax.responseText + '');
+				if ( !check_json_response(response) )
+				{
+					handle_invalid_json(ajax.responseText);
+					return false;
+				}
+				try
+				{
+					var response = parseJSON(ajax.responseText);
+				}
+				catch(e)
+				{
+					handle_invalid_json(ajax.responseText);
+				}
+				if ( response.mode == 'success' )
+				{
+					// the deletion was successful, report success and kill off the editor
+					whiteOutReportSuccess(whitey);
+					setTimeout(function()
+						{
+							// nuke the rank title on the left
+							var edit_link = document.getElementById('rankadmin_editlink_' + editor.rankdata.rank_id);
+							if ( edit_link )
+							{
+								edit_link.parentNode.removeChild(edit_link);
+							}
+							// collapse and destroy the editor
+							$(editor.wrapperdiv).hide("blind", {}, 500, function()
+									{
+										// when the animation finishes, nuke the whole thing
+										var container = document.getElementById('admin_ranks_container_right');
+										container.innerHTML = $lang.get('acpur_msg_select_rank');
+									}
+								);
+						}, 1500);
+				}
+				else
+				{
+					whitey.parentNode.removeChild(whitey);
+					if ( response.error == 'need_auth_to_admin' )
+					{
+						load_component('login');
+						ajaxDynamicReauth(function()
+							{
+								ajaxRankEditDeleteConfirmed(editor);
+							});
+					}
+					else
+					{
+						miniPromptMessage({
+								title: $lang.get('acpur_err_delete_failed_title'),
+								message: response.error,
+								buttons: [
+									{
+										text: $lang.get('etc_ok'),
+										color: 'red',
+										style: {
+											fontWeight: 'bold'
+										},
+										onclick: function()
+										{
+											miniPromptDestroy(this);
+										}
+									}
+								]
+						});
+					}
+				}
+			}
+		}, true);
 }