includes/clientside/static/ajax.js
author Dan
Tue, 22 Jul 2008 17:00:54 -0500
changeset 653 3ea1c552e734
parent 651 ce9d78d7251d
child 672 08a7875258b4
permissions -rw-r--r--
Fixed installer path check in Admin:Home; made admin-menu more compatible with componentized JS

/*
 * AJAX applets
 */
 
window.ajaxReset = function()
{
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  var ns_id = strToPageID(physical_title);
  if ( ns_id[1] == 'Special' || ns_id[1] == 'Admin' )
    return false;
  enableUnload();
  setAjaxLoading();
  var redir = ( disable_redirect ) ? '&redirect=no' : '';
  ajaxGet(scriptPath + '/ajax.php?title=' + physical_title +'&_mode=getpage&noheaders' + redir, function() {
    // Allow for 404 here, it's generated by the "page not found" error message
    // (even with noheaders specified, probably should be fixed)
    if ( ajax.readyState == 4 && ( ajax.status == 200 || ajax.status == 404 ) ) {
      unsetAjaxLoading();
      document.getElementById('ajaxEditContainer').innerHTML = ajax.responseText;
      selectButtonMajor('article');
      unselectAllButtonsMinor();
    }
  });
}

// Miscellaneous AJAX applets

window.ajaxProtect = function(l) {
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  load_component('l10n');
  
  if(shift) {
    r = 'NO_REASON';
  } else {
    r = prompt($lang.get('ajax_protect_prompt_reason'));
    if(!r || r=='') return;
  }
  setAjaxLoading();
  document.getElementById('protbtn_0').style.textDecoration = 'none';
  document.getElementById('protbtn_1').style.textDecoration = 'none';
  document.getElementById('protbtn_2').style.textDecoration = 'none';
  document.getElementById('protbtn_'+l).style.textDecoration = 'underline';
  ajaxPost(stdAjaxPrefix+'&_mode=protect', 'reason='+ajaxEscape(r)+'&level='+l, function() {
    if ( ajax.readyState == 4 && ajax.status == 200 ) {
      unsetAjaxLoading();
      if(ajax.responseText == 'good')
        return true;
      // check for JSON error response
      var response = String(ajax.responseText + '');
      if ( response.substr(0, 1) == '{' )
      {
        response = parseJSON(response);
        if ( response.mode == 'error' )
        {
          alert(response.error);
          return true;
        }
      }
      alert(ajax.responseText);
    }
  }, true);
}

window.ajaxRename = function()
{
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  
  // updated - 1.1.4 to use miniPrompt
  load_component('l10n');
  load_component('messagebox');
  miniPrompt(ajaxRenameConstructDialog);
}

var ajaxRenameConstructDialog = function(div)
{
  // title
  var heading = document.createElement('h3');
  heading.appendChild(document.createTextNode($lang.get('ajax_rename_prompt_short')));
  div.appendChild(heading);
  
  // form
  var form = document.createElement('form');
  form.action = 'javascript:void(0);';
  
  // box
  var box = document.createElement('input');
  box.size = '43';
  box.style.width = '100%';
  form.appendChild(box);
  div.appendChild(form);
  
  // notice
  var notice = document.createElement('small');
  notice.appendChild(document.createTextNode($lang.get('ajax_rename_notice')));
  div.appendChild(notice);
  
  // button area
  var btndiv = document.createElement('div');
  btndiv.className = 'mp-buttons';
  
  // buttons
  var btn_submit = document.createElement('a');
  btn_submit.href = '#';
  btn_submit.appendChild(document.createTextNode($lang.get('etc_go')));
  btn_submit.className = 'abutton abutton_green';
  
  var btn_cancel = document.createElement('a');
  btn_cancel.href = '#';
  btn_cancel.appendChild(document.createTextNode($lang.get('etc_cancel')));
  btn_cancel.className = 'abutton';
  
  btndiv.appendChild(btn_submit);
  btndiv.appendChild(document.createTextNode(' | '));
  btndiv.appendChild(btn_cancel);
  div.appendChild(btndiv);
  
  // events
  btn_submit.onclick = function()
  {
    ajaxRenameSubmit(this);
    return false;
  }
  btn_cancel.onclick = function()
  {
    miniPromptDestroy(this);
    return false;
  }
  form.onsubmit = function()
  {
    ajaxRenameSubmit(this);
    return false;
  }
  
  setTimeout(function()
    {
      box.focus();
    }, 200);
}

window.ajaxRenameSubmit = function(obj)
{
  var box = miniPromptGetParent(obj);
  if ( !box )
    return false;
  
  var input = obj.getElementsByTagName('input')[0];
  console.debug(obj, input);
  if ( !input )
    return false;
  var newname = input.value;
  newname = trim(newname);
  
  if ( newname.length < 1 )
  {
    alert($lang.get('ajax_rename_too_short'));
    return false;
  }
  
  if ( !newname )
  {
    return false;
  }
  
  var innerBox = getElementsByClassName(box, 'div', 'mp-body')[0];
  var whiteout = whiteOutElement(innerBox);
  whiteout.style.width = ( $(whiteout).Width() - 78 ) + 'px';
  whiteout.style.left = ( $(whiteout).Left() + 44 ) + 'px';
  
  ajaxPost(stdAjaxPrefix + '&_mode=rename', 'newtitle=' + ajaxEscape(newname), function()
    {
      if ( ajax.readyState == 4 && ajax.status == 200 )
      {
        whiteout.parentNode.removeChild(whiteout);
        var response = String(ajax.responseText);
        if ( !check_json_response(response) )
        {
          handle_invalid_json(response);
          return false;
        }
        response = parseJSON(response);
        if ( response.success )
        {
          miniPromptDestroy(box, true);
          ajaxRenameDoClientTransform(newname);
          new MessageBox( MB_OK|MB_ICONINFORMATION, $lang.get('ajax_rename_success_title'), $lang.get('ajax_rename_success_body', { page_name_new: newname }) );
          mb_previously_had_darkener = false;
        }
        else
        {
          var errmsg = $lang.get('page_err_' + response.error);
          alert(errmsg);
        }
      }
    }, true);
}

window.ajaxRenameDoClientTransform = function(newname)
{
  var obj = document.getElementById('h2PageName');
  if ( obj )
  {
    obj.firstChild.nodeValue = newname;
  }
  document.title = newname;
}

window.ajaxDeletePage = function()
{
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  load_component('l10n');
  var reason = prompt($lang.get('ajax_delete_prompt_reason'));
  if ( !reason || reason == '' )
  {
    return false;
  }
  c = confirm($lang.get('ajax_delete_confirm'));
  if(!c)
  {
    return;
  }
  setAjaxLoading();
  ajaxPost(stdAjaxPrefix+'&_mode=deletepage', 'reason=' + ajaxEscape(reason), function() {
    if ( ajax.readyState == 4 && ajax.status == 200 ) {
      unsetAjaxLoading();
      alert(ajax.responseText);
      window.location.reload();                                                                           
    }
  });
}

window.ajaxDelVote = function()
{
  load_component('l10n');
  load_component('messagebox');
  
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  miniPromptMessage({
      title: $lang.get('ajax_delvote_confirm_title'),
      message: $lang.get('ajax_delvote_confirm_body'),
      buttons: [
        {
          text: $lang.get('ajax_delvote_btn_submit'),
          color: 'red',
          style: {
            fontWeight: 'bold'
          },
          onclick: function(e)
          {
            miniPromptDestroy(this);
            setAjaxLoading();
            ajaxGet(stdAjaxPrefix+'&_mode=delvote', function() {
              if ( ajax.readyState == 4 && ajax.status == 200 ) {
                unsetAjaxLoading();
                alert(ajax.responseText);
              }
            }, true);
          }
        },
        {
          text: $lang.get('etc_cancel'),
          onclick: function(e)
          {
            miniPromptDestroy(this);
          }
        }
      ]
    });
}

window.ajaxResetDelVotes = function()
{
  load_component('l10n');
  load_component('messagebox');
  
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  miniPromptMessage({
      title: $lang.get('ajax_delvote_reset_confirm_title'),
      message: $lang.get('ajax_delvote_reset_confirm_body'),
      buttons: [
        {
          text: $lang.get('ajax_delvote_reset_btn_submit'),
          color: 'red',
          style: {
            fontWeight: 'bold'
          },
          onclick: function(e)
          {
            miniPromptDestroy(this);
            setAjaxLoading();
            ajaxGet(stdAjaxPrefix+'&_mode=resetdelvotes', function() {
              if ( ajax.readyState == 4 && ajax.status == 200 ) {
                unsetAjaxLoading();
                alert(ajax.responseText);
                item = document.getElementById('mdgDeleteVoteNoticeBox');
                if(item)
                {
                  opacity('mdgDeleteVoteNoticeBox', 100, 0, 1000);
                  setTimeout("document.getElementById('mdgDeleteVoteNoticeBox').style.display = 'none';", 1000);
                }
              }
            }, true);
          }
        },
        {
          text: $lang.get('etc_cancel'),
          onclick: function(e)
          {
            miniPromptDestroy(this);
          }
        }
      ]
    });
}

// Editing/saving category information
// This was not easy to write, I hope enjoy it, and dang I swear I'm gonna
// find someone to work on just the Javascript part of Enano...

window.ajaxCatEdit = function()
{
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  setAjaxLoading();
  ajaxGet(stdAjaxPrefix+'&_mode=catedit', function() {
    if ( ajax.readyState == 4 && ajax.status == 200 ) {
      unsetAjaxLoading();
      edit_open = false;
      eval(ajax.responseText);
    }
  });
}

window.ajaxCatSave = function()
{
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  if(!catlist)
  {
    alert('Var catlist has no properties');
    return;
  }
  query='';
  for(i=0;i<catlist.length;i++)
  {
    var s = ( document.forms.mdgCatForm['mdgCat_' + catlist[i]]['checked'] ) ? true : false;
    if(s) query = query + '&' + catlist[i] + '=true';
  }
  setAjaxLoading();
  query = query.substring(1, query.length);
  ajaxPost(stdAjaxPrefix+'&_mode=catsave', query, function() {
    if ( ajax.readyState == 4 && ajax.status == 200 ) {
      unsetAjaxLoading();
      edit_open = false;
      if(ajax.responseText != 'GOOD') alert(ajax.responseText);
      ajaxReset();
    }
  });
}

// History stuff

window.ajaxHistory = function()
{
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  setAjaxLoading();
  ajaxGet(stdAjaxPrefix+'&_mode=histlist', function() {
    if ( ajax.readyState == 4 && ajax.status == 200 ) {
      unsetAjaxLoading();
      edit_open = false;
      selectButtonMajor('article');
      selectButtonMinor('history');
      document.getElementById('ajaxEditContainer').innerHTML = ajax.responseText;
      buildDiffList();
    }
  });
}

window.ajaxHistView = function(oldid, ttl) {
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  if(!ttl) ttl=title;
  setAjaxLoading();
  ajaxGet(append_sid(scriptPath+'/ajax.php?title='+ttl+'&_mode=getpage&oldid='+oldid), function() {
    if ( ajax.readyState == 4 && ajax.status == 200 ) {
      unsetAjaxLoading();
      edit_open = false;
      document.getElementById('ajaxEditContainer').innerHTML = ajax.responseText;
    }
  });
}

window.ajaxRollback = function(id) {
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  setAjaxLoading();
  ajaxGet(stdAjaxPrefix+'&_mode=rollback&id='+id, function() {
    if ( ajax.readyState == 4 && ajax.status == 200 ) {
      unsetAjaxLoading();
      
      var response = String(ajax.responseText + '');
      if ( !check_json_response(response) )
      {
        handle_invalid_json(response);
        return false;
      }
      
      response = parseJSON(response);
      if ( response.success )
      {
        alert( $lang.get('page_msg_rb_success_' + response.action, { dateline: response.dateline }) )
      }
      else
      {
        if ( response.action )
        {
          alert( $lang.get('page_err_' + response.error, { action: response.action }) );
        }
        else
        {
          alert( $lang.get('page_err_' + response.error) );
        }
      }
    }
  });
}

window.ajaxClearLogs = function()
{
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  
  load_component('l10n');
  load_component('messagebox');
  
  miniPromptMessage({
      title: $lang.get('ajax_clearlogs_confirm_title'),
      message: $lang.get('ajax_clearlogs_confirm_body'),
      buttons: [
        {
          text: $lang.get('ajax_clearlogs_btn_submit'),
          color: 'red',
          style: {
            fontWeight: 'bold'
          },
          onclick: function(e)
          {
            miniPromptDestroy(this);
            setAjaxLoading();
            ajaxGet(stdAjaxPrefix+'&_mode=flushlogs', function() {
              if ( ajax.readyState == 4 && ajax.status == 200 ) {
                unsetAjaxLoading();
                alert(ajax.responseText);
                window.location.reload();
              }
            });
          }
        },
        {
          text: $lang.get('etc_cancel'),
          onclick: function(e)
          {
            miniPromptDestroy(this);
          }
        }
      ]
    });
}

window.buildDiffList = function()
{
  arrDiff1Buttons = getElementsByClassName(document, 'input', 'clsDiff1Radio');
  arrDiff2Buttons = getElementsByClassName(document, 'input', 'clsDiff2Radio');
  var len = arrDiff1Buttons.length;
  if ( len < 1 )
    return false;
  timelist = new Array();
  for ( var i = 0; i < len; i++ )
  {
    timelist.push( arrDiff2Buttons[i].id.substr(6) );
  }
  timelist.push( arrDiff1Buttons[len-1].id.substr(6) );
  delete(timelist.toJSONString);
  for ( var i = 1; i < timelist.length-1; i++ )
  {
    if ( i >= timelist.length ) break;
    arrDiff2Buttons[i].style.display = 'none';
  }
}

window.selectDiff1Button = function(obj)
{
  var this_time = obj.id.substr(6);
  var index = parseInt(in_array(this_time, timelist));
  for ( var i = 0; i < timelist.length - 1; i++ )
  {
    if ( i < timelist.length - 1 )
    {
      var state = ( i < index ) ? 'inline' : 'none';
      var id = 'diff2_' + timelist[i];
      document.getElementById(id).style.display = state;
      
      // alert("Debug:\nIndex: "+index+"\nState: "+state+"\ni: "+i);
    }
  }
}

window.selectDiff2Button = function(obj)
{
  var this_time = obj.id.substr(6);
  var index = parseInt(in_array(this_time, timelist));
  for ( var i = 1; i < timelist.length; i++ )
  {
    if ( i < timelist.length - 1 )
    {
      var state = ( i > index ) ? 'inline' : 'none';
      var id = 'diff1_' + timelist[i];
      document.getElementById(id).style.display = state;
      
      // alert("Debug:\nIndex: "+index+"\nState: "+state+"\ni: "+i);
    }
  }
}

window.ajaxHistDiff = function()
{
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  var id1=false;
  var id2=false;
  for ( i = 0; i < arrDiff1Buttons.length; i++ )
  {
    k = i + '';
    kpp = i + 1;
    kpp = kpp + '';
    if(arrDiff1Buttons[k].checked) id1 = arrDiff1Buttons[k].id.substr(6);
    if(arrDiff2Buttons[k].checked) id2 = arrDiff2Buttons[k].id.substr(6);
  }
  if(!id1 || !id2) { alert('BUG: Couldn\'t get checked radiobutton state'); return; }
  setAjaxLoading();
  ajaxGet(stdAjaxPrefix+'&_mode=pagediff&diff1='+id1+'&diff2='+id2, function()
    {
      if ( ajax.readyState == 4 && ajax.status == 200 )
      {
        unsetAjaxLoading();
        document.getElementById('ajaxEditContainer').innerHTML = ajax.responseText;
      }
    });
}

// Change the user's preferred style/theme

window.ajaxChangeStyle = function()
{
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  load_component('l10n');
  load_component('messagebox');
  
  var inner_html = '';
  inner_html += '<p><label>' + $lang.get('ajax_changestyle_lbl_theme') + ' ';
  inner_html += '  <select id="chtheme_sel_theme" onchange="ajaxGetStyles(this.value);">';
  inner_html += '    <option value="_blank" selected="selected">' + $lang.get('ajax_changestyle_select') + '</option>';
  inner_html +=      ENANO_THEME_LIST;
  inner_html += '  </select>';
  inner_html += '</label></p>';
  var chtheme_mb = new MessageBox(MB_OKCANCEL|MB_ICONQUESTION, $lang.get('ajax_changestyle_title'), inner_html);
  chtheme_mb.onbeforeclick['OK'] = ajaxChangeStyleComplete;
}

window.ajaxGetStyles = function(id)
{
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  var thediv = document.getElementById('chtheme_sel_style_parent');
  if ( thediv )
  {
    thediv.parentNode.removeChild(thediv);
  }
  if ( id == '_blank' )
  {
    return null;
  }
  ajaxGet(stdAjaxPrefix + '&_mode=getstyles&id=' + id, function() {
      if ( ajax.readyState == 4 && ajax.status == 200 )
      {
        // IE doesn't like substr() on ajax.responseText
        var response = String(ajax.responseText + ' ');
        response = response.substr(0, response.length - 1);
        if ( response.substr(0,1) != '[' )
        {
          alert('Invalid or unexpected JSON response from server:\n' + response);
          return null;
        }
        
        // Build a selector and matching label
        var data = parseJSON(response);
        var options = new Array();
        for( var i in data )
        {
          var item = data[i];
          var title = themeid_to_title(item);
          var option = document.createElement('option');
          option.value = item;
          option.appendChild(document.createTextNode(title));
          options.push(option);
        }
        var p_parent = document.createElement('p');
        var label  = document.createElement('label');
        p_parent.id = 'chtheme_sel_style_parent';
        label.appendChild(document.createTextNode($lang.get('ajax_changestyle_lbl_style') + ' '));
        var select = document.createElement('select');
        select.id = 'chtheme_sel_style';
        for ( var i in options )
        {
          select.appendChild(options[i]);
        }
        label.appendChild(select);
        p_parent.appendChild(label);
        
        // Stick it onto the messagebox
        var div = document.getElementById('messageBox');
        var kid = div.firstChild.nextSibling;
        
        kid.appendChild(p_parent);
        
      }
    }, true);
}

window.ajaxChangeStyleComplete = function()
{
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  var theme = $dynano('chtheme_sel_theme');
  var style = $dynano('chtheme_sel_style');
  if ( !theme.object || !style.object )
  {
    alert($lang.get('ajax_changestyle_pleaseselect_theme'));
    return true;
  }
  var theme_id = theme.object.value;
  var style_id = style.object.value;
  
  if ( typeof(theme_id) != 'string' || typeof(style_id) != 'string' )
  {
    alert('Couldn\'t get theme or style ID');
    return true;
  }
  
  if ( theme_id.length < 1 || style_id.length < 1 )
  {
    alert('Theme or style ID is zero length');
    return true;
  }
  
  ajaxPost(stdAjaxPrefix + '&_mode=change_theme', 'theme_id=' + ajaxEscape(theme_id) + '&style_id=' + ajaxEscape(style_id), function()
    {
      if ( ajax.readyState == 4 && ajax.status == 200 )
      {
        if ( ajax.responseText == 'GOOD' )
        {
          var c = confirm($lang.get('ajax_changestyle_success'));
          if ( c )
            window.location.reload();
        }
        else
        {
          alert('Error occurred during attempt to change theme:\n' + ajax.responseText);
        }
      }
    }, true);
  
  return false;
  
}

window.ajaxSwapCSS = function()
{
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  setAjaxLoading();
  if(_css) {
    document.getElementById('mdgCss').href = main_css;
    _css = false;
  } else {
    document.getElementById('mdgCss').href = print_css;
    _css = true;
  }
  unsetAjaxLoading();
  menuOff();
}

window.ajaxSetPassword = function()
{
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  load_component('crypto');
  pass = hex_sha1(document.getElementById('mdgPassSetField').value);
  setAjaxLoading();
  ajaxPost(stdAjaxPrefix+'&_mode=setpass', 'password='+pass, function()
    {
      unsetAjaxLoading();
      if ( ajax.readyState == 4 && ajax.status == 200 )
      {
        alert(ajax.responseText);
      }
    }, true);
}

window.ajaxDisableEmbeddedPHP = function()
{
  // IE <6 pseudo-compatibility
  if ( KILL_SWITCH )
    return true;
  if ( !confirm($lang.get('ajax_killphp_confirm')) )
    return false;
  var $killdiv = $dynano('php_killer');
  if ( !$killdiv.object )
  {
    alert('Can\'t get kill div object');
    return false;
  }
  $killdiv.object.innerHTML = '<img alt="Loading..." src="' + scriptPath + '/images/loading-big.gif" /><br />Making request...';
  var url = makeUrlNS('Admin', 'Home', 'src=ajax');
  ajaxPost(url, 'act=kill_php', function() {
      if ( ajax.readyState == 4 && ajax.status == 200 )
      {
        if ( ajax.responseText == '1' )
        {
          var $killdiv = $dynano('php_killer');
          //$killdiv.object.innerHTML = '<img alt="Success" src="' + scriptPath + '/images/error.png" /><br />Embedded PHP in pages has been disabled.';
          $killdiv.object.parentNode.removeChild($killdiv.object);
          var newdiv = document.createElement('div');
          // newdiv.style = $killdiv.object.style;
          newdiv.className = $killdiv.object.className;
          newdiv.innerHTML = '<img alt="Success" src="' + scriptPath + '/images/error.png" /><br />' + $lang.get('ajax_killphp_success');
          $killdiv.object.parentNode.appendChild(newdiv);
          $killdiv.object.parentNode.removeChild($killdiv.object);
        }
        else
        {
          var $killdiv = $dynano('php_killer');
          $killdiv.object.innerHTML = ajax.responseText;
        }
      }
    });
}

var catHTMLBuf = false;

window.ajaxCatToTag = function()
{
  if ( KILL_SWITCH )
    return false;
  setAjaxLoading();
  ajaxGet(stdAjaxPrefix + '&_mode=get_tags', function()
    {
      if ( ajax.readyState == 4 && ajax.status == 200 )
      {
        unsetAjaxLoading();
        var resptext = String(ajax.responseText + ' ');
        resptext = resptext.substr(0, resptext.length-1);
        if ( resptext.substr(0, 1) != '{' )
        {
          handle_invalid_json(resptext);
          return false;
        }
        var json = parseJSON(resptext);
        var catbox = document.getElementById('mdgCatBox');
        if ( !catbox )
          return false;
        var linkbox = catbox.parentNode.firstChild.firstChild.nextSibling;
        linkbox.firstChild.nodeValue = $lang.get('catedit_catbox_link_showcategorization');
        linkbox.onclick = function() { ajaxTagToCat(); return false; };
        catHTMLBuf = catbox.innerHTML;
        catbox.innerHTML = '';
        catbox.appendChild(document.createTextNode($lang.get('tags_lbl_page_tags')+' '));
        if ( json.tags.length < 1 )
        {
          catbox.appendChild(document.createTextNode($lang.get('tags_lbl_no_tags')));
        }
        for ( var i = 0; i < json.tags.length; i++ )
        {
          catbox.appendChild(document.createTextNode(json.tags[i].name));
          if ( json.tags[i].can_del )
          {
            catbox.appendChild(document.createTextNode(' '));
            var a = document.createElement('a');
            a.appendChild(document.createTextNode('[X]'));
            a.href = '#';
            a._js_tag_id = json.tags[i].id;
            a.onclick = function() { ajaxDeleteTag(this, this._js_tag_id); return false; }
            catbox.appendChild(a);
          }
          if ( ( i + 1 ) < json.tags.length )
            catbox.appendChild(document.createTextNode(', '));
        }
        if ( json.can_add )
        {
          catbox.appendChild(document.createTextNode(' '));
          var addlink = document.createElement('a');
          addlink.href = '#';
          addlink.onclick = function() { try { ajaxAddTagStage1(); } catch(e) { }; return false; };
          addlink.appendChild(document.createTextNode($lang.get('tags_btn_add_tag')));
          catbox.appendChild(addlink);
        }
      }
    });
}

var addtag_open = false;

window.ajaxAddTagStage1 = function()
{
  if ( addtag_open )
    return false;
  var catbox = document.getElementById('mdgCatBox');
  var adddiv = document.createElement('div');
  var text = document.createElement('input');
  var addlink = document.createElement('a');
  addlink.href = '#';
  addlink.onclick = function() { ajaxAddTagStage2(this.parentNode.firstChild.nextSibling.value, this.parentNode); return false; };
  addlink.appendChild(document.createTextNode($lang.get('tags_btn_add')));
  text.type = 'text';
  text.size = '15';
  text.onkeyup = function(e)
  {
    if ( e.keyCode == 13 )
    {
      ajaxAddTagStage2(this.value, this.parentNode);
    }
  }
  
  adddiv.style.margin = '5px 0 0 0';
  adddiv.appendChild(document.createTextNode($lang.get('tags_lbl_add_tag')+' '));
  adddiv.appendChild(text);
  adddiv.appendChild(document.createTextNode(' '));
  adddiv.appendChild(addlink);
  catbox.appendChild(adddiv);
  addtag_open = true;
}

var addtag_nukeme = false;

window.ajaxAddTagStage2 = function(tag, nukeme)
{
  if ( !addtag_open )
    return false;
  if ( addtag_nukeme )
    return false;
  addtag_nukeme = nukeme;
  tag = ajaxEscape(tag);
  setAjaxLoading();
  ajaxPost(stdAjaxPrefix + '&_mode=addtag', 'tag=' + tag, function()
    {
      if ( ajax.readyState == 4 && ajax.status == 200 )
      {
        unsetAjaxLoading();
        var nukeme = addtag_nukeme;
        addtag_nukeme = false;
        var resptext = String(ajax.responseText + ' ');
        resptext = resptext.substr(0, resptext.length-1);
        if ( resptext.substr(0, 1) != '{' )
        {
          handle_invalid_json(resptext);
          return false;
        }
        var json = parseJSON(resptext);
        var parent = nukeme.parentNode;
        parent.removeChild(nukeme);
        addtag_open = false;
        if ( json.success )
        {
          var node = parent.childNodes[1];
          var insertafter = false;
          var nukeafter = false;
          if ( node.nodeValue == $lang.get('tags_lbl_no_tags') )
          {
            nukeafter = true;
          }
          insertafter = parent.childNodes[ parent.childNodes.length - 3 ];
          // these need to be inserted in reverse order
          if ( json.can_del )
          {
            var a = document.createElement('a');
            a.appendChild(document.createTextNode('[X]'));
            a.href = '#';
            a._js_tag_id = json.tag_id;
            a.onclick = function() { ajaxDeleteTag(this, this._js_tag_id); return false; }
            insertAfter(parent, a, insertafter);
            insertAfter(parent, document.createTextNode(' '), insertafter);
          }
          insertAfter(parent, document.createTextNode(json.tag), insertafter);
          if ( !nukeafter )
          {
            insertAfter(parent, document.createTextNode(', '), insertafter);
          }
          if ( nukeafter )
          {
            parent.removeChild(insertafter);
          }
        }
        else
        {
          alert(json.error);
        }
      }
    });
}

window.ajaxDeleteTag = function(parentobj, tag_id)
{
  var arrDelete = [ parentobj, parentobj.previousSibling, parentobj.previousSibling.previousSibling ];
  var parent = parentobj.parentNode;
  var writeNoTags = false;
  if ( parentobj.previousSibling.previousSibling.previousSibling.nodeValue == ', ' )
    arrDelete.push(parentobj.previousSibling.previousSibling.previousSibling);
  else if ( parentobj.previousSibling.previousSibling.previousSibling.nodeValue == $lang.get('tags_lbl_page_tags') + ' ' )
    arrDelete.push(parentobj.nextSibling);
  
  if ( parentobj.previousSibling.previousSibling.previousSibling.nodeValue == $lang.get('tags_lbl_page_tags') + ' ' &&
       parentobj.nextSibling.nextSibling.firstChild )
    if ( parentobj.nextSibling.nextSibling.firstChild.nodeValue == $lang.get('tags_btn_add_tag'))
      writeNoTags = true;
    
  ajaxPost(stdAjaxPrefix + '&_mode=deltag', 'tag_id=' + String(tag_id), function()
    {
      if ( ajax.readyState == 4 && ajax.status == 200 )
      {
        if ( ajax.responseText == 'success' )
        {
          for ( var i = 0; i < arrDelete.length; i++ )
          {
            try
            {
              parent.removeChild(arrDelete[i]);
            } catch(e) {}
          }
          if ( writeNoTags )
          {
            var node1 = document.createTextNode($lang.get('tags_lbl_no_tags'));
            var node2 = document.createTextNode(' ');
            insertAfter(parent, node1, parent.firstChild);
            insertAfter(parent, node2, node1);
          }
        }
        else
        {
          alert(ajax.responseText);
        }
      }
    });
}

window.ajaxTagToCat = function()
{
  if ( !catHTMLBuf )
    return false;
  var catbox = document.getElementById('mdgCatBox');
  if ( !catbox )
    return false;
  addtag_open = false;
  var linkbox = catbox.parentNode.firstChild.firstChild.nextSibling;
  linkbox.firstChild.nodeValue = $lang.get('tags_catbox_link');
  linkbox.onclick = function() { ajaxCatToTag(); return false; };
  catbox.innerHTML = catHTMLBuf;
  catHTMLBuf = false;
}

var keepalive_interval = false;

window.ajaxPingServer = function()
{
  ajaxGet(stdAjaxPrefix + '&_mode=ping', function()
    {
    });
}

window.ajaxToggleKeepalive = function()
{
  if ( readCookie('admin_keepalive') == '1' )
  {
    createCookie('admin_keepalive', '0', 3650);
    if ( keepalive_interval )
      clearInterval(keepalive_interval);
    var span = document.getElementById('keepalivestat');
    span.firstChild.nodeValue = $lang.get('adm_btn_keepalive_off');
  }
  else
  {
    createCookie('admin_keepalive', '1', 3650);
    if ( !keepalive_interval )
      keepalive_interval = setInterval('ajaxPingServer();', 600000);
    var span = document.getElementById('keepalivestat');
    span.firstChild.nodeValue = $lang.get('adm_btn_keepalive_on');
    ajaxPingServer();
  }
}

var keepalive_onload = function()
{
  if ( readCookie('admin_keepalive') == '1' )
  {
    if ( !keepalive_interval )
      keepalive_interval = setInterval('ajaxPingServer();', 600000);
    var span = document.getElementById('keepalivestat');
    span.firstChild.nodeValue = $lang.get('adm_btn_keepalive_on');
  }
  else
  {
    if ( keepalive_interval )
      clearInterval(keepalive_interval);
    var span = document.getElementById('keepalivestat');
    span.firstChild.nodeValue = $lang.get('adm_btn_keepalive_off');
  }
};

window.aboutKeepAlive = function()
{
  load_component('messagebox');
  new MessageBox(MB_OK|MB_ICONINFORMATION, $lang.get('user_keepalive_info_title'), $lang.get('user_keepalive_info_body'));
}

window.ajaxUpdateCheck = function(targetelement)
{
  if ( !document.getElementById(targetelement) )
  {
    return false;
  }
  var target = document.getElementById(targetelement);
  target.innerHTML = '';
  var img = document.createElement('img');
  img.src = cdnPath + '/images/loading.gif';
  img.alt = 'Loading...';
  target.appendChild(img);
  ajaxGet(makeUrlNS('Admin', 'Home/updates.xml'), function()
    {
      if ( ajax.readyState == 4 && ajax.status == 200 )
      {
        var releases = new Array();
        var update_available = false;
        if ( ajax.responseXML == null )
        {
          alert("Error fetching updates list:\n" + ajax.responseText);
          return false;
        }
        if ( ajax.responseXML.firstChild.tagName == 'enano' )
        {
          var enanotag = ajax.responseXML.firstChild;
          for ( var i = 0; i < enanotag.childNodes.length; i++ )
          {
            if ( enanotag.childNodes[i].tagName == 'error' )
            {
              alert(enanotag.childNodes[i].firstChild.nodeValue);
            }
            else if ( enanotag.childNodes[i].tagName == 'latest' )
            {
              // got <latest>
              var latesttag = enanotag.childNodes[i];
              for ( var j = 0; j < latesttag.childNodes.length; j++ )
              {
                var node = latesttag.childNodes[j];
                if ( node.tagName == 'release' )
                {
                  var releasedata = new Object();
                  for ( var k = 0; k < node.attributes.length; k++ )
                  {
                    releasedata[node.attributes[k].nodeName] = node.attributes[k].nodeValue;
                  }
                  releases.push(releasedata);
                }
                else if ( node.tagName == 'haveupdates' )
                {
                  update_available = true;
                }
              }
              break;
            }
          }
        }
        else
        {
          return false;
        }
        var thediv = document.getElementById(targetelement);
        thediv.innerHTML = '';
        if ( !thediv )
        {
          return false;
        }
        if ( releases.length > 0 )
        {
          thediv.className = 'tblholder';
          if ( update_available )
          {
            var infobox = document.createElement('div');
            infobox.className = 'info-box-mini';
            infobox.appendChild(document.createTextNode('An update for Enano is available. The newest release is highlighted below.'));
            infobox.style.borderWidth = '0';
            infobox.style.margin = '0 0 0 0';
            thediv.appendChild(infobox);
          }
          else
          {
            var infobox = document.createElement('div');
            infobox.className = 'info-box-mini';
            infobox.appendChild(document.createTextNode('No new updates are available. The latest available releases are shown below.'));
            infobox.style.borderWidth = '0';
            infobox.style.margin = '0 0 0 0';
            thediv.appendChild(infobox);
          }
          var table = document.createElement('table');
          table.setAttribute('border', '0');
          table.setAttribute('cellspacing', '1');
          table.setAttribute('cellpadding', '4');
          
          var tr = document.createElement('tr');
          
          var td1 = document.createElement('th');
          var td2 = document.createElement('th');
          var td3 = document.createElement('th');
          var td4 = document.createElement('th');
          
          td1.appendChild( document.createTextNode('Release type') );
          td2.appendChild( document.createTextNode('Version') );
          td3.appendChild( document.createTextNode('Code name') );
          td4.appendChild( document.createTextNode('Release notes') );
          
          tr.appendChild(td1);
          tr.appendChild(td2);
          tr.appendChild(td3);
          tr.appendChild(td4);
            
          table.appendChild(tr);
          
          var cls = 'row2';
          
          var j = 0;
          for ( var i in releases )
          {
            j++;
            if ( j > 5 )
              break;
            if ( update_available && j == 1 )
              cls = 'row1_green';
            else
              cls = ( cls == 'row1' ) ? 'row2' : 'row1';
            var release = releases[i];
            var tr = document.createElement('tr');
            
            var td1 = document.createElement('td');
            var td2 = document.createElement('td');
            var td3 = document.createElement('td');
            var td4 = document.createElement('td');
            
            td1.className = cls;
            td2.className = cls;
            td3.className = cls;
            td4.className = cls;
            
            if ( release.tag )
              td1.appendChild( document.createTextNode(release.tag) );
            
            if ( release.version )
              td2.appendChild( document.createTextNode(release.version) );
            
            if ( release.codename )
              td3.appendChild( document.createTextNode(release.codename) );
            
            if ( release.relnotes )
            {
              var a = document.createElement('a');
              a.href = release.relnotes;
              a.appendChild(document.createTextNode('View'));
              td4.appendChild( a );
            }
            
            tr.appendChild(td1);
            tr.appendChild(td2);
            tr.appendChild(td3);
            tr.appendChild(td4);
            
            table.appendChild(tr);
          }
          thediv.appendChild(table);
        }
        else
        {
          thediv.appendChild(document.createTextNode('No releases available.'));
        }
      }
    });
}

window.ajaxPluginAction = function(action, plugin_filename, btnobj)
{
  // if installing, uninstalling, or re-importing, confirm
  if ( action == 'install' || action == 'uninstall' || action == 'reimport' )
  {
    var prompt = miniPrompt(function(div)
      {
        var txtholder = document.createElement('div');
        txtholder.style.textAlign = 'center';
        txtholder.appendChild(document.createTextNode($lang.get('acppl_msg_confirm_' + action)));
        txtholder.appendChild(document.createElement('br'));
        txtholder.appendChild(document.createElement('br'));
        
        // create buttons
        var btn_go = document.createElement('a');
        btn_go.className = 'abutton abutton_red';
        btn_go.href = '#';
        btn_go._action = action;
        btn_go._filename = plugin_filename;
        btn_go._button = btnobj;
        btn_go.appendChild(document.createTextNode($lang.get('acppl_btn_' + action)));
        btn_go.style.fontWeight = 'bold';
        txtholder.appendChild(btn_go);
        
        // space
        txtholder.appendChild(document.createTextNode(' '));
        
        // cancel
        var btn_cancel = document.createElement('a');
        btn_cancel.className = 'abutton abutton_blue';
        btn_cancel.href = '#';
        btn_cancel.appendChild(document.createTextNode($lang.get('etc_cancel')));
        
        txtholder.appendChild(btn_cancel);
        div.appendChild(txtholder);
        
        btn_go.onclick = function()
        {
          ajaxPluginAction(this._action + '_confirm', this._filename, this._button);
          miniPromptDestroy(this);
          return false;
        }
        btn_cancel.onclick = function()
        {
          miniPromptDestroy(this);
          return false;
        }
      });
    return true;
  }
  action = action.replace(/_confirm$/, '');
  // white-out the plugin info box
  if ( btnobj )
  {
    var td = btnobj.parentNode.parentNode.parentNode.parentNode;
    var blackbox = whiteOutElement(td);
  }
  var request = toJSONString({
      mode: action,
      plugin: plugin_filename
    });
  ajaxPost(makeUrlNS('Admin', 'PluginManager/action.json'), 'r=' + ajaxEscape(request), function()
    {
      if ( ajax.readyState == 4 && ajax.status == 200 )
      {
        var response = String(ajax.responseText + '');
        if ( !check_json_response(response) )
        {
          handle_invalid_json(response);
          return false;
        }
        response = parseJSON(response);
        if ( response.success )
        {
          if ( blackbox )
          {
            blackbox.parentNode.removeChild(blackbox);
          }
          ajaxPage( namespace_list['Admin'] + 'PluginManager' );
          return true;
        } 
        // wait for fade effect to finish its run
        setTimeout(function()
          {
            miniPrompt(function(div)
              {
                if ( blackbox )
                {
                  blackbox.parentNode.removeChild(blackbox);
                }
                var txtholder = document.createElement('div');
                txtholder.style.textAlign = 'center';
                txtholder.appendChild(document.createTextNode(response.error));
                txtholder.appendChild(document.createElement('br'));
                txtholder.appendChild(document.createElement('br'));
                
                // close button
                var btn_cancel = document.createElement('a');
                btn_cancel.className = 'abutton abutton_red';
                btn_cancel.href = '#';
                btn_cancel.appendChild(document.createTextNode($lang.get('etc_ok')));
                
                txtholder.appendChild(btn_cancel);
                div.appendChild(txtholder);
                
                btn_cancel.onclick = function()
                {
                  miniPromptDestroy(this);
                  return false;
                }
              });
          }, 750);
      }
    });
}

window.ajaxReverseDNS = function(o, text)
{
  if(text) var ipaddr = text;
  else var ipaddr = o.innerHTML;
  rDnsObj = o;
  rDnsBannerObj = bannerOn('Retrieving reverse DNS info...');
  ajaxGet(stdAjaxPrefix+'&_mode=rdns&ip='+ipaddr, function() {
      if ( ajax.readyState == 4 && ajax.status == 200 )
      {
        off = fetch_offset(rDnsObj);
        dim = fetch_dimensions(rDnsObj);
        right = off['left'] + dim['w'];
        top = off['top'] + dim['h'];
        var thediv = document.createElement('div');
        thediv.className = 'info-box';
        thediv.style.margin = '0';
        thediv.style.position = 'absolute';
        thediv.style.top  = top  + 'px';
        thediv.style.display = 'none';
        thediv.style.zIndex = getHighestZ() + 2;
        thediv.id = 'mdgDynamic_rDnsInfoDiv_'+Math.floor(Math.random() * 1000000);
        thediv.innerHTML = '<b>Reverse DNS:</b><br />'+ajax.responseText+' <a href="#" onclick="elem = document.getElementById(\''+thediv.id+'\'); elem.innerHTML = \'\'; elem.style.display = \'none\';return false;">Close</a>';
        var body = document.getElementsByTagName('body');
        body = body[0];
        bannerOff(rDnsBannerObj);
        body.appendChild(thediv);
        thediv.style.display = 'block';
        left = fetch_dimensions(thediv);
        thediv.style.display = 'none';
        left = right - left['w'];
        thediv.style.left = left + 'px';
        thediv.style.display = 'block';
        fadeInfoBoxes();
      }
    });
}

function themeid_to_title(id)
{
  if ( typeof(id) != 'string' )
    return false;
  id = id.substr(0, 1).toUpperCase() + id.substr(1);
  id = id.replace(/_/g, ' ');
  id = id.replace(/-/g, ' ');
  return id;
}