Major underlying changes to namespace handling. Each namespace is handled by its own class which extends Namespace_Default. Much greater customization/pluggability potential, at the possible expense of some code reusing (though code reusing has been avoided thus far). Also a bit better handling of page passwords [SECURITY].
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()
{
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()
{
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()
{
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()
{
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()
{
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;
}
}
});
}