includes/clientside/static/theme-manager.js
author Dan
Sun, 25 Jan 2009 20:35:06 -0500
changeset 823 4596c40aaa94
parent 699 c7d737202d59
child 1227 bdac73ed481e
permissions -rw-r--r--
AJAX core library: possible breaking change, readystatechange functions are now called with the XHR instance as the first parameter, to allow requests to run in parallel. This means much better stability but may break some applets (compatibility hack is included)

function ajaxToggleSystemThemes()
{
  var theme_list = document.getElementById('theme_list_edit');
  var mode = ( theme_list.sys_shown ) ? 'hide' : 'show';
  for ( var i = 0; i < theme_list.childNodes.length; i++ )
  {
    var child = theme_list.childNodes[i];
    if ( child.tagName == 'DIV' )
    {
      if ( $dynano(child).hasClass('themebutton_theme_system') )
      {
        if ( $dynano(child).hasClass('themebutton_theme_disabled') )
        {
          $dynano(child).rmClass('themebutton_theme_disabled')
        }
        if ( mode == 'show' )
        {
          domObjChangeOpac(0, child);
          child.style.display = 'block';
          domOpacity(child, 0, 100, 1000);
        }
        else
        {
          domOpacity(child, 100, 0, 1000);
          setTimeout("document.getElementById('" + child.id + "').style.display = 'none';", 1050);
        }
      }
    }
  }
  theme_list.sys_shown = ( mode == 'show' );
  document.getElementById('systheme_toggler').innerHTML = ( mode == 'hide' ) ? $lang.get('acptm_btn_system_themes_show') : $lang.get('acptm_btn_system_themes_hide');
}

function ajaxInstallTheme(theme_id)
{
  var thediv = document.getElementById('themebtn_install_' + theme_id);
  if ( !thediv )
    return false;
  thediv.removeChild(thediv.getElementsByTagName('a')[0]);
  var status = document.createElement('div');
  status.className = 'status';
  thediv.appendChild(status);
  
  var req = toJSONString({
      mode: 'install',
      theme_id: theme_id
    });
  // we've finished nukeing the existing interface, request editor data
  ajaxPost(makeUrlNS('Admin', 'ThemeManager/action.json'), 'r=' + ajaxEscape(req), function(ajax)
    {
      if ( ajax.readyState == 4 && ajax.status == 200 )
      {
        var response = String(ajax.responseText + '');
        if ( response.substr(0, 1) == '{' )
        {
          response = parseJSON(response);
          if ( response.mode == 'error' )
          {
            alert(response.error);
            return false;
          }
        }
        
        var theme_list = document.getElementById('theme_list_edit');
  
        var btn = document.createElement('div');
        btn.className = 'themebutton';
        btn.style.backgroundImage = thediv.style.backgroundImage;
        btn.id = 'themebtn_edit_' + theme_id;
        
        var a = document.createElement('a');
        a.className = 'tb-inner';
        a.appendChild(document.createTextNode($lang.get('acptm_btn_theme_edit')));
        a.appendChild(document.createTextNode("\n"));
        a.theme_id = theme_id;
        a.onclick = function()
        {
          ajaxEditTheme(this.theme_id);
          return false;
        }
        a.href = '#';
        var span = document.createElement('span');
        span.className = 'themename';
        span.appendChild(document.createTextNode(thediv.getAttribute('enano:themename')));
        a.appendChild(span);
        btn.appendChild(a);
        btn.setAttribute('enano:themename', thediv.getAttribute('enano:themename'));
        theme_list.appendChild(btn);
        
        thediv.parentNode.removeChild(thediv);
      }
    });
}

function ajaxEditTheme(theme_id)
{
  // Fade out and subsequently destroy the entire list, then make an
  // ajax request to the theme manager for the theme info via JSON
  var theme_list = document.getElementById('theme_list_edit').parentNode;
  var backgroundImage = document.getElementById('themebtn_edit_' + theme_id).style.backgroundImage;
  /*
  for ( var i = 0; i < theme_list.childNodes.length; i++ )
  {
    var el = theme_list.childNodes[i];
    if ( el.tagName )
      domOpacity(el, 100, 0, 1000);
  }
  */
  var thediv = document.getElementById('themebtn_edit_' + theme_id);
  if ( !thediv )
    return false;
  thediv.removeChild(thediv.getElementsByTagName('a')[0]);
  var status = document.createElement('div');
  status.className = 'status';
  thediv.appendChild(status);
  
  setTimeout(function()
    {
      var req = toJSONString({
          mode: 'fetch_theme',
          theme_id: theme_id
        });
      // we've finished nukeing the existing interface, request editor data
      ajaxPost(makeUrlNS('Admin', 'ThemeManager/action.json'), 'r=' + ajaxEscape(req), function(ajax)
        {
          if ( ajax.readyState == 4 && ajax.status == 200 )
          {
            theme_list.innerHTML = '';
            var response = String(ajax.responseText + '');
            if ( !check_json_response(response) )
            {
              alert(response);
              return false;
            }
            response = parseJSON(response);
            if ( response.mode == 'error' )
            {
              alert(response.error);
              return false;
            }
            response.background_image = backgroundImage;
            ajaxBuildThemeEditor(response, theme_list);
          }
        });
    }, 200);
}

function ajaxBuildThemeEditor(data, target)
{
  // Build the theme editor interface
  // Init opacity
  domObjChangeOpac(0, target);
  
  // Theme preview
  var preview = document.createElement('div');
  preview.style.border = '1px solid #F0F0F0';
  preview.style.padding = '5px';
  preview.style.width = '216px';
  preview.style.height = '150px';
  preview.style.backgroundImage = data.background_image;
  preview.style.backgroundRepeat = 'no-repeat';
  preview.style.backgroundPosition = 'center center';
  preview.style.cssFloat = 'right';
  preview.style.styleFloat = 'right';
  
  target.appendChild(preview);
  
  // Heading
  var h3 = document.createElement('h3');
  h3.appendChild(document.createTextNode($lang.get('acptm_heading_theme_edit', { theme_name: data.theme_name })));
  target.appendChild(h3);
  
  // Field: Theme name
  var l_name = document.createElement('label');
  l_name.appendChild(document.createTextNode($lang.get('acptm_field_theme_name') + ' '));
  var f_name = document.createElement('input');
  f_name.type = 'text';
  f_name.id = 'themeed_field_name';
  f_name.value = data.theme_name;
  f_name.size = '40';
  l_name.appendChild(f_name);
  target.appendChild(l_name);
  
  target.appendChild(document.createElement('br'));
  target.appendChild(document.createElement('br'));
  
  // Field: default style
  var l_style = document.createElement('label');
  l_style.appendChild(document.createTextNode($lang.get('acptm_field_default_style') + ' '));
  var f_style = document.createElement('select');
  f_style.id = 'themeed_field_style';
  var opts = [];
  for ( var i = 0; i < data.css.length; i++ )
  {
    if ( data.css[i] == '_printable' )
      continue;
    
    opts[i] = document.createElement('option');
    opts[i].value = data.css[i];
    opts[i].appendChild(document.createTextNode(data.css[i]));
    if ( data.default_style == data.css[i] )
    {
      opts[i].selected = true;
    }
    f_style.appendChild(opts[i]);
  }
  l_style.appendChild(f_style);
  target.appendChild(l_style);
  
  target.appendChild(document.createElement('br'));
  target.appendChild(document.createElement('br'));
  
  // Default theme
  target.appendChild(document.createTextNode($lang.get('acptm_field_default_theme') + ' '));
  if ( data.is_default )
  {
    var l_default = document.createElement('b');
    l_default.appendChild(document.createTextNode($lang.get('acptm_field_default_msg_current')));
  }
  else
  {
    var l_default = document.createElement('label');
    var f_default = document.createElement('input');
    f_default.type = 'checkbox';
    f_default.id = 'themeed_field_default';
    l_default.appendChild(f_default);
    l_default.appendChild(document.createTextNode($lang.get('acptm_field_default_btn_make_default')));
  }
  target.appendChild(l_default);
  
  target.appendChild(document.createElement('br'));
  target.appendChild(document.createElement('br'));
  
  // Disable theme
  var disable_span = document.createElement('span');
  disable_span.appendChild(document.createTextNode($lang.get('acptm_field_disable_title') + ' '));
  target.appendChild(disable_span);
  var l_disable = document.createElement('label');
  var f_disable = document.createElement('input');
  f_disable.type = 'checkbox';
  f_disable.id = 'themeed_field_disable';
  if ( !data.enabled )
    f_disable.setAttribute('checked', 'checked');
  l_disable.style.fontWeight = 'bold';
  l_disable.appendChild(f_disable);
  l_disable.appendChild(document.createTextNode($lang.get('acptm_field_disable')));
  target.appendChild(l_disable);
  
  // Availability policy
  var h3 = document.createElement('h3');
  h3.appendChild(document.createTextNode($lang.get('acptm_heading_theme_groups')));
  target.appendChild(h3);
  
  // Label for the whole field
  var p_d_policy = document.createElement('p');
  p_d_policy.style.fontWeight = 'bold';
  p_d_policy.appendChild(document.createTextNode($lang.get('acptm_field_policy')));
  target.appendChild(p_d_policy);
  
  // Wrapper for options
  var p_f_policy = document.createElement('p');
  
  // Option: allow all
  var l_policy_allow_all = document.createElement('label');
  var f_policy_allow_all = document.createElement('input');
  f_policy_allow_all.type = 'radio';
  f_policy_allow_all.id = 'themeed_field_policy_allow_all';
  f_policy_allow_all.name = 'themeed_field_policy';
  f_policy_allow_all.value = 'allow_all';
  l_policy_allow_all.appendChild(f_policy_allow_all);
  l_policy_allow_all.appendChild(document.createTextNode(' ' + $lang.get('acptm_field_policy_allow_all')));
  if ( data.group_policy == 'allow_all' )
  {
    f_policy_allow_all.setAttribute('checked', 'checked');
  }
  
  // Option: whitelist
  var l_policy_whitelist = document.createElement('label');
  var f_policy_whitelist = document.createElement('input');
  f_policy_whitelist.type = 'radio';
  f_policy_whitelist.id = 'themeed_field_policy_whitelist';
  f_policy_whitelist.name = 'themeed_field_policy';
  f_policy_whitelist.value = 'whitelist';
  l_policy_whitelist.appendChild(f_policy_whitelist);
  l_policy_whitelist.appendChild(document.createTextNode(' ' + $lang.get('acptm_field_policy_whitelist')));
  if ( data.group_policy == 'whitelist' )
  {
    f_policy_whitelist.setAttribute('checked', 'checked');
  }
  
  // Option: blacklist
  var l_policy_blacklist = document.createElement('label');
  var f_policy_blacklist = document.createElement('input');
  f_policy_blacklist.type = 'radio';
  f_policy_blacklist.id = 'themeed_field_policy_blacklist';
  f_policy_blacklist.name = 'themeed_field_policy';
  f_policy_blacklist.value = 'blacklist';
  l_policy_blacklist.appendChild(f_policy_blacklist);
  l_policy_blacklist.appendChild(document.createTextNode(' ' + $lang.get('acptm_field_policy_blacklist')));
  if ( data.group_policy == 'blacklist' )
  {
    f_policy_blacklist.setAttribute('checked', 'checked');
  }
  f_policy_allow_all.onclick = ajaxThemeManagerHandlePolicyClick;
  f_policy_whitelist.onclick = ajaxThemeManagerHandlePolicyClick;
  f_policy_blacklist.onclick = ajaxThemeManagerHandlePolicyClick;
  
  p_f_policy.appendChild(l_policy_allow_all);
  p_f_policy.appendChild(document.createElement('br'));
  p_f_policy.appendChild(l_policy_whitelist);
  p_f_policy.appendChild(document.createElement('br'));
  p_f_policy.appendChild(l_policy_blacklist);
  
  target.appendChild(p_d_policy);
  target.appendChild(p_f_policy);
  
  var div_acl = document.createElement('div');
  div_acl.id = 'themeed_acl_box';
  div_acl.style.margin = '0 0 10px 30px';
  
  var h3_g = document.createElement('h3');
  h3_g.appendChild(document.createTextNode($lang.get('acptm_field_acl_heading_groups')));
  div_acl.appendChild(h3_g);
  
  var div_groups = document.createElement('div');
  div_groups.style.border = '1px solid #E8E8E8';
  div_groups.id = 'themeed_group_list';
  
  // Group list
  for ( var i in data.group_names )
  {
    var g_name = data.group_names[i];
    var check = document.createElement('input');
    check.type = 'checkbox';
    if ( in_array("g:" + i, data.group_list) )
    {
      check.setAttribute('checked', 'checked');
    }
    check.group_id = parseInt(i);
    var lbl_g_acl = document.createElement('label');
    lbl_g_acl.appendChild(check);
    var str = 'groupcp_grp_' + g_name.toLowerCase();
    var g_name_l10n = ( $lang.get(str) != str ) ? $lang.get(str) : g_name;
    lbl_g_acl.appendChild(document.createTextNode(g_name_l10n));
    div_groups.appendChild(lbl_g_acl);
    div_groups.appendChild(document.createElement('br'));
  }
  div_acl.appendChild(div_groups);
  
  var h3_u = document.createElement('h3');
  h3_u.appendChild(document.createTextNode($lang.get('acptm_field_acl_heading_users')));
  div_acl.appendChild(h3_u);
  
  // User addition field
  var frm = document.createElement('form');
  frm.action = 'javascript:ajaxThemeManagerHandleUserAdd();';
  frm.appendChild(document.createTextNode($lang.get('acptm_field_acl_add_user')));
  var f_useradd = document.createElement('input');
  f_useradd.type = 'text';
  f_useradd.id = 'themeed_field_adduser';
  f_useradd.onkeyup = function(e)
  {
    new AutofillUsername(this, e, false);
  }
  
  frm.appendChild(f_useradd);
  div_acl.appendChild(frm);
  
  div_acl.appendChild(document.createElement('br'));
  
  // User list
  var div_users = document.createElement('div');
  div_users.style.border = '1px solid #E8E8E8';
  div_users.style.padding = '4px';
  div_users.id = 'themeed_user_list';
  for ( var i = 0; i < data.group_list.length; i++ )
  {
    var id = data.group_list[i];
    if ( id.substr(0, 2) != 'u:' )
      continue;
    var uid = id.substr(2);
    var username = data.usernames[uid];
    
    var useritem = document.createElement('span');
    useritem.appendChild(document.createTextNode(username + ' '));
    useritem.userid = parseInt(uid);
    var deleter = document.createElement('a');
    deleter.href = '#';
    deleter.onclick = function()
    {
      ajaxThemeManagerHandleUserRemoval(this);
      return false;
    }
    deleter.appendChild(document.createTextNode('[X]'));
    useritem.appendChild(deleter);
    div_users.appendChild(useritem);
    div_users.appendChild(document.createElement('br'));
  }
  div_acl.appendChild(div_users);
  
  target.appendChild(div_acl);
  
  ajaxThemeManagerHandlePolicyClick();
  
  var clearer = document.createElement('span');
  clearer.className = 'menuclear';
  target.appendChild(clearer);
  
  // Theme ID
  var tid = document.createElement('input');
  tid.type = 'hidden';
  tid.id = 'themeed_theme_id';
  tid.value = data.theme_id;
  target.appendChild(tid);
  
  // Save button
  var raquo = unescape('%BB');
  var savebtn = document.createElement('input');
  savebtn.type = 'button';
  savebtn.style.fontWeight = 'bold';
  savebtn.value = $lang.get('etc_save_changes') + ' ' + raquo;
  savebtn.onclick = function()
  {
    ajaxThemeManagerHandleSaveRequest();
  }
  target.appendChild(savebtn);
  
  target.appendChild(document.createTextNode(' '));
  
  // Cancel button
  var savebtn = document.createElement('input');
  savebtn.type = 'button';
  savebtn.value = $lang.get('etc_cancel');
  savebtn.onclick = function()
  {
    ajaxPage(namespace_list['Admin'] + 'ThemeManager');
  }
  target.appendChild(savebtn);
  
  target.appendChild(document.createTextNode(' '));
  
  // Uninstall button
  var savebtn = document.createElement('input');
  savebtn.type = 'button';
  savebtn.value = $lang.get('acptm_btn_uninstall_theme');
  savebtn.style.color = '#D84308';
  savebtn.onclick = function()
  {
    if ( !confirm($lang.get('acptm_msg_uninstall_confirm')) )
      return false;
    ajaxThemeManagerHandleUninstallClick();
  }
  target.appendChild(savebtn);
  
  // Fade it all in
  domOpacity(target, 0, 100, 500);
  f_name.focus();
}

function ajaxThemeManagerHandlePolicyClick()
{
  if ( document.getElementById('themeed_field_policy_allow_all').checked )
  {
    document.getElementById('themeed_acl_box').style.display = 'none';
  }
  else if ( document.getElementById('themeed_field_policy_whitelist').checked || document.getElementById('themeed_field_policy_blacklist').checked )
  {
    document.getElementById('themeed_acl_box').style.display = 'block';
  }
}

function ajaxThemeManagerHandleUserAdd()
{
  var f_useradd = document.getElementById('themeed_field_adduser');
  f_useradd.setAttribute('disabled', 'disabled');
  var parent = f_useradd.parentNode;
  var img = document.createElement('img');
  img.src = ajax_load_icon;
  img.id = 'themeed_useradd_status';
  img.style.marginLeft = '10px';
  insertAfter(parent, img, f_useradd);
  
  var req = toJSONString({
      mode: 'uid_lookup',
      username: f_useradd.value
    });
  ajaxPost(makeUrlNS('Admin', 'ThemeManager/action.json'), 'r=' + ajaxEscape(req), function(ajax)
    {
      if ( ajax.readyState == 4 && ajax.status == 200 )
      {
        var img = document.getElementById('themeed_useradd_status');
        var f_useradd = document.getElementById('themeed_field_adduser');
        
        f_useradd.disabled = null;
        img.parentNode.removeChild(img);
        
        // process response
        var response = String(ajax.responseText + '');
        if ( !check_json_response(response) )
        {
          alert(response);
          return false;
        }
        response = parseJSON(response);
        if ( response.mode == 'error' )
        {
          alert(response.error);
          return false;
        }
            
        var uid = parseInt(response.uid);
        var username = response.username;
        
        // Loop through the list of users and remove any existing ones with the same uid
        var div_users = document.getElementById('themeed_user_list');
        var children = div_users.getElementsByTagName('span');
        for ( var i = 0; i < children.length; i++ )
        {
          var child = children[i];
          if ( child.userid == uid )
          {
            // the sister is the br element next to the span with the checkbox/text
            var sister = child.nextSibling;
            div_users.removeChild(child);
            div_users.removeChild(sister);
            break;
          }
        }
        
        var useritem = document.createElement('span');
        useritem.appendChild(document.createTextNode(username + ' '));
        useritem.userid = parseInt(uid);
        var deleter = document.createElement('a');
        deleter.href = '#';
        deleter.onclick = function()
        {
          ajaxThemeManagerHandleUserRemoval(this);
          return false;
        }
        deleter.appendChild(document.createTextNode('[X]'));
        useritem.appendChild(deleter);
        div_users.appendChild(useritem);
        div_users.appendChild(document.createElement('br'));
      }
    });
}

function ajaxThemeManagerHandleUserRemoval(el)
{
  var parent = el.parentNode;
  var uid = parent.userid;
  
  var grandparent = parent.parentNode;
  var sister = parent.nextSibling;
  grandparent.removeChild(parent);
  grandparent.removeChild(sister);
}

function ajaxThemeManagerHandleSaveRequest()
{
  // Build a JSON condensed request
  var md = false;
  if ( document.getElementById('themeed_field_default') )
  {
    if ( document.getElementById('themeed_field_default').checked )
    {
      md = true;
    }
  }
  var policy = 'allow_all';
  if ( document.getElementById('themeed_field_policy_whitelist').checked )
    policy = 'whitelist';
  else if ( document.getElementById('themeed_field_policy_blacklist').checked )
    policy = 'blacklist';
  var json_packet = {
    theme_id: document.getElementById('themeed_theme_id').value,
    theme_name: document.getElementById('themeed_field_name').value,
    default_style: document.getElementById('themeed_field_style').value,
    make_default: md,
    group_policy: policy,
    enabled: ( document.getElementById('themeed_field_disable').checked ? false : true )
  };
  var acl_list = [];
  var checks = document.getElementById('themeed_group_list').getElementsByTagName('input');
  for ( var i = 0; i < checks.length; i++ )
  {
    if ( checks[i].checked )
      acl_list.push('g:' + checks[i].group_id);
  }
  var spans = document.getElementById('themeed_user_list').getElementsByTagName('span');
  for ( var i = 0; i < spans.length; i++ )
  {
    if ( spans[i].userid )
      acl_list.push('u:' + spans[i].userid);
  }
  json_packet.group_list = acl_list;
  
  var json_send = {
    mode: 'save_theme',
    theme_data: json_packet
  };
  
  json_send = ajaxEscape(toJSONString(json_send));
  
  // Request the save
  var parent = document.getElementById('ajaxPageContainer');
  ajaxPost(makeUrlNS('Admin', 'ThemeManager/action.json'), 'r=' + json_send, function(ajax)
    {
      if ( ajax.readyState == 4 && ajax.status == 200 )
      {
        // process response
        var response = String(ajax.responseText + '');
        if ( !check_json_response(response) )
        {
          // For this we actually *expect* an HTML response.
          parent.innerHTML = response;
          return false;
        }
        response = parseJSON(response);
        if ( response.mode == 'error' )
        {
          alert(response.error);
          return false;
        }
      }
    });
}

function ajaxThemeManagerHandleUninstallClick()
{
  var theme_id = document.getElementById('themeed_theme_id').value;
  var json_send = {
    mode: 'uninstall',
    theme_id: theme_id
  };
  
  json_send = ajaxEscape(toJSONString(json_send));
  
  // Request the action
  var parent = document.getElementById('ajaxPageContainer');
  ajaxPost(makeUrlNS('Admin', 'ThemeManager/action.json'), 'r=' + json_send, function(ajax)
    {
      if ( ajax.readyState == 4 && ajax.status == 200 )
      {
        // process response
        var response = String(ajax.responseText + '');
        if ( !check_json_response(response) )
        {
          // For this we actually *expect* an HTML response.
          parent.innerHTML = response;
          return false;
        }
        response = parseJSON(response);
        if ( response.mode == 'error' )
        {
          alert(response.error);
          return false;
        }
      }
    });
}