diff -r de56132c008d -r bdac73ed481e includes/clientside/static/rank-manager.js --- 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); }