尝试写了一个js版本的wordpress后台,但是只有一个单页,后续设置项目过多的时候可能会不方便。虽然不知道到底有没有后续,作为一个学习项目也不错,于是决定为后台增加一个分页。写这个typecho主题的时候尝试过阅读joe的后台分页代码,主要思路是为不同的设置项目分类,通过点击按钮实现当前类显示,其他类目display:none。然而代码这东西实在是反人类的难记,个把月前还能看出点门道的东西,今天重新去看的时候又一头雾水了。
测试代码
勉强实现功能的代码页,写在了一个html文件里,方便本地测试:
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
<html xmlns='http://www.w3.org/1999/xhtml'>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
<title>无标题文档</title>
</head>
<body id="wpbody-content">
<input type="hidden" id="_wpnonce" name="_wpnonce" value="60ad2d3bf5">
<input type="hidden" name="_wp_http_referer" value="/wp-admin/themes.php?page=theme_options_page">
<script>
if(!options){
var options={};
};
var ThemeForm={
//主题关键词
theme:'august',
//分页信息
pages:{'global_options':'全局设置','image_options':'图片设置','static_options':'静态资源'},
pages_on:true,
//表单信息
title:'August主题设置',
form:'',
formlist:[],
formid:'august_options_form',
formvalue:'august_options',
submitname:'august_options_save',
//类名参数
titleclass:'august_options_title',
pageulclass:'august_options_pages',
pageliclass:'august_options_pageitems',
containerclass:'august_options_container',
labelclass:'august_options_label',
inputclass:'august_options_input',
textclass:'august_options_textarea',
selectclass:'august_options_select',
checkclass:'august_options_check',
itemclass:'august_options_item',
itemsclass:'august_options_items',
descriptionclass:'august_options_description',
//元素创建
newElement:function(tag,eobj){
var newelement=document.createElement(tag);
for(var i in eobj){
if(i.indexOf('data-')==-1){
newelement[i]=eobj[i];
}else{
var datavalue=i.split('-')[1];
newelement.dataset[datavalue]=eobj[i];
}
}
return newelement;
},
//初始化函数
setUp:function(tname,pswitch,pobj){
if(tname){this.setName(tname);}
if(pswitch){
if(pobj){
this.setPages(pobj);
}
}else{
this.pages_on=false;
}
this.form=this.newElement('form',{'id':this.formid,'method':'post','action':'options.php'});
var logo=this.newElement('div',{'id':'icon-themes','classList':'icon32'});
var title=this.newElement('h2',{'classList':this.titleclass,'textContent':this.title});
if(document.getElementById('wpbody-content')){
parent=document.getElementById('wpbody-content');
parent.appendChild(this.form);
}else{
alert('未能正确找到挂靠对象,请检查新增菜单页语句!');
}
this.form.appendChild(logo);
this.form.appendChild(title);
this.createPages();
},
//名称设置函数
setName:function(tname){
this.theme=tname;
this.title=this.theme + '主题设置';
this.pageulclass=this.theme + '_options_pages';
this.pageliclass=this.theme + '_options_pageitems';
this.formid=this.theme + '_options_form';
this.formvalue=this.theme + '_options';
this.submitname=this.theme + '_options_save';
this.titleclass=this.theme + '_options_title';
this.containerclass=this.theme + '_options_container';
this.labelclass=this.theme + '_options_label';
this.inputclass=this.theme + '_options_input';
this.textclass=this.theme + '_options_textarea';
this.selectclass=this.theme + '_options_select';
this.checkclass=this.theme + '_options_check';
this.itemclass=this.theme + '_options_item';
this.itemsclass=this.theme + '_options_items';
this.descriptionclass=this.theme + '_options_description';
},
//分页信息函数
setPages:function(pobj){
this.pages=pobj;
},
//创建分页
createPages:function(){
if(this.pages_on){
var pageul=this.newElement('ul',{'classList':this.pageulclass});
console.log(pageul);
for(var i in this.pages){
var pageli=this.newElement('li',{'textContent':this.pages[i],'classList':this.pageliclass,'data-current':i});
pageul.appendChild(pageli);
}
this.form.appendChild(pageul);
}
},
//页尾元素设置
createFooter:function(){
var wpnonce=document.getElementsByName('_wpnonce')[0];
var wpreferer=document.getElementsByName('_wp_http_referer')[0];
var input_data=this.newElement('input',{'id':this.formvalue,'name':this.formvalue,'type':'hidden','value':'update'});
var input_action=this.newElement('input',{'id':'page_value','name':'action','type':'hidden','value':'update'});
var input_options=this.newElement('input',{'id':'page_options','name':'page_options','type':'hidden','value':this.formvalue});
var input_submit=this.newElement('input',{'classList':'button-primary','name':this.submitname,'type':'submit','value':'保存设置','onclick':this.makeJson});
var container=this.makeContainer();
container.classList='august_options_submit_container';
container.appendChild(input_submit);
this.form.appendChild(wpnonce);
this.form.appendChild(wpreferer);
this.form.appendChild(input_data);
this.form.appendChild(input_action);
this.form.appendChild(input_options);
this.form.appendChild(container);
},
makeContainer:function(pname){
var container=document.createElement('div');
if(this.pages_on&&pname){
container.classList=this.containerclass + ' ' + pname;
}else{
container.classList=this.containerclass;
}
return container;
},
makeItem:function(parent,type){
var item=document.createElement('p');
if(type==='checkbox'||type==='radio'){
item.classList=this.itemsclass;
}else{
item.classList=this.itemclass;
}
parent.appendChild(item);
return item;
},
makeLabel:function(text,parent){
var label=document.createElement('label');
label.textContent=text+':';
label.classList=this.labelclass;
parent.appendChild(label);
},
makeDescription:function(text,parent){
var desc=document.createElement('p');
desc.classList=this.descriptionclass;
desc.innerHTML=text;
parent.appendChild(desc);
},
makeInput:function(name,value,parent){
var input=this.newElement('input',{'classList':this.inputclass,'name':name,'type':'input'});
if(options&&options[name]){
input.value=options[name];
}else if(value){
input.value=value;
}else{
input.value='';
}
var obj={};
obj.element=input;
obj.getValue=function(){
options[obj.element.name]=obj.element.value;
}
this.formlist.push(obj);
parent.appendChild(input);
},
makeTextarea:function(name,value,parent){
var input=this.newElement('textarea',{'classList':this.textclass,'name':name,'type':'textarea'});
if(options&&options[name]){
input.value=options[name];
}else if(value){
input.value=value;
}else{
input.value='';
}
var obj={};
obj.element=input;
obj.getValue=function(){
options[obj.element.name]=obj.element.value;
}
this.formlist.push(obj);
parent.appendChild(input);
},
makeRadio:function(name,value,option,parent){
var radios=[];
var choice;
if(options&&options[name]){
choice=options[name];
}else{
choice=value;
}
for(var i in option){
console.log(i);
console.log(option[i]);
var input=this.newElement('input',{'name':name,'type':'radio','value':i});
if(choice==input.value){
input.checked=true;
}
radios.push(input);
var label=this.newElement('label',{'classList':this.checkclass,'textContent':option[i]});
parent.appendChild(input);
parent.appendChild(label);
}
var obj={};
obj.element=radios;
obj.getValue=function(){
for(var i in obj.element){
if(obj.element[i].checked===true){
options[obj.element[i].name]=obj.element[i].value;
}
}
}
this.formlist.push(obj);
},
makeCheckbox:function(name,value,option,parent){
var checks=[];
var choice;
if(options&&options[name]){
choice=options[name];
}else{
choice=value;
}
for(var i in option){
var input=this.newElement('input',{'name':name,'type':'checkbox','value':i});
if(choice.includes(input.value)){
input.checked=true;
}
checks.push(input);
var label=this.newElement('label',{'classList':this.checkclass,'textContent':option[i]});
parent.appendChild(input);
parent.appendChild(label);
}
var obj={};
obj.element=checks;
obj.getValue=function(){
options[name]=[];
for(var i in obj.element){
if(obj.element[i].checked===true){
options[name].push(obj.element[i].value);
}
}
}
this.formlist.push(obj);
},
makeSelect:function(name,value,option,parent){
var selectvalue;
var selects=[];
var container=this.newElement('select',{'name':name,'classList':this.selectclass});
if(options&&options[name]){
selectvalue=options[name];
}else{
selectvalue=value;
}
for(var i in option){
var selectoption=this.newElement('option',{'value':i,'textContent':option[i]});
if(selectvalue==selectoption.value){
selectoption.selected=true;
}
selects.push(selectoption);
container.appendChild(selectoption);
}
parent.appendChild(container);
var obj={};
obj.element=selects;
obj.getValue=function(){
for(var i in obj.element){
if(obj.element[i].selected===true){
options[container.name]=obj.element[i].value;
}
}
}
this.formlist.push(obj);
},
createNew:function(label,description,name,type,pname,value,option){
var container=this.makeContainer(pname);
var item=this.makeItem(container,type);
this.makeLabel(label,item);
switch(type)
{
case 'input':
this.makeInput(name,value,item);
break;
case 'textarea':
this.makeTextarea(name,value,item);
break;
case 'radio':
this.makeRadio(name,value,option,item);
break;
case 'checkbox':
this.makeCheckbox(name,value,option,item);
break;
case 'select':
this.makeSelect(name,value,option,item);
break;
default:
break;
}
this.makeDescription(description,container);
this.form.appendChild(container);
},
//添加分页动作
pageAction:function(){
var e = document.querySelectorAll('.'+this.pageliclass);
var n = document.querySelectorAll('.'+this.containerclass);
e.forEach(function(o) {
o.addEventListener("click", function() {
e.forEach(function(e) {
e.classList.remove("active")
}), o.classList.add("active");
var c = o.getAttribute("data-current");
sessionStorage.setItem("august_config_current", c), n.forEach(function(e) {
e.style.display = "none";
var t = e.classList.contains(c);
t && (e.style.display = "block")
})
})
});
if (sessionStorage.getItem("august_config_current")) {
var o = sessionStorage.getItem("august_config_current");
console.log(o);
e.forEach(function(e) {
var t = e.getAttribute("data-current");
console.log(t);
t === o && e.classList.add("active")
}), n.forEach(function(e) {
e.style.display = "none";
e.classList.contains(o) && (e.style.display = "block")
})
} else e[0].classList.add("active");
},
//组建数据
makeJson:function(){
for(var i in ThemeForm.formlist){
ThemeForm.formlist[i].getValue();
};
options=JSON.stringify(options);
document.getElementById(ThemeForm.formvalue).value=options;
}
}
ThemeForm.setUp('august',true);
ThemeForm.createNew('测试1','看看换行管不管用','site-logo','input','global_options');
ThemeForm.createNew('测试2','本测试','test2','textarea','global_options');
ThemeForm.createNew('测试3','这就是一个单选测试','check1','select','image_options','',{'red':'红色','green':'绿色的 ','blue':'蓝色','yellow':'黄色'});
ThemeForm.createNew('测试4','这就是一个多选测试','check2','checkbox','static_options','',{'red':'红色','green':'绿色的 ','blue':'蓝色','yellow':'黄色'});
ThemeForm.createFooter();
ThemeForm.pageAction();
</script>
</body>
</html>
一些收获
“data-current”这类属性并不能直接以数组的形式来写,暂时通过判断是否包含关键字分拆为两种处理方式;createNew创建新元素的参数实在是有点太多了;是否包含某个关键字可以用indexOf函数;拆分字符串使用split;单独的setClass设置类名似乎没有必要,增加了很多代码,也不方便匹配css。