JSON 编辑器实现代码


Posted in Javascript onDecember 06, 2009

大家可以输入或者粘贴一些JSON数据来校验是否正确。
按Tab键自动全文缩进格式化。

JSON 编辑器实现代码 
JSON 编辑器
核心代码

<script type="text/javascript"><!-- 
/* 
main Object 
*/ 
JE={ 
data:{},/* 关联数据 */ 
code:false,/* 格式化后的代码 */ 
oldCode:[],/* 历史代码 */ 
editUI:null,/* 关联编辑框 */ 
msgUI:null,/* 信息显示窗口 */ 
treeUI:null,/* 树窗口 */ 
name:'JE',/* 实例名 */ 
root:'<b>JSON无忧</b>',/* 根节点标题 */ 
checkbox:0,/* 是否添加复框 */ 
hot:null,/* 选中节点 */ 
indent:' ',/*缩进符'\t'或者4个' '*/ 
firstUp:true,/*第一次自动刷新*/ 
onclick:Array,/*树点击通知*/ 
countInfo:'',/*统计信息*/ 
formating:false,/* 格式化中(禁止重构树) */ 
ico:{/* 树图标 */ 
//文件夹结构线 
r0:'img?uuid=20166b3094daba4bc6e18817b8301b093a', 
r0c:'img?uuid=208018827ed877e31810e838d33e4ac2b0', 
r1:'img?uuid=2094c793496278bde84be80bb6cb2117f5', 
r1c:'img?uuid=205f2329c537dcfd32b5f33bf642f76fa6', 
r2:'img?uuid=20af62be7c197cae64d3e533f7aaf28c25', 
r2c:'img?uuid=20a005983863e5bc8544cecd8b7f82fcdb', 
//前缀图片 
nl:'img?uuid=20f508bdc9bb8d98f4529e0fa2475b91bb', 
vl:'img?uuid=20d5de63f4e6927bbb23c377bd1073d26f', 
//文件结构线 
f1:'img?uuid=202ccc639afd44130a3946e9837672479c', 
f2:'img?uuid=20900ceb0053a2f7bd07a22337c4e4c72c', 
root:'img?uuid=2069cf3fd1e53a2bb365f771eac65b50a2', 
//文件夹 
arr:'img?uuid=20b7d6e86f4f288ea097c10b1c0d7f4b6b', 
arrc:'img?uuid=20b7d6e86f4f288ea097c10b1c0d7f4b6b', 
obj:'img?uuid=20c34d1d5d5a4639061e08165c61a97e63', 
objc:'img?uuid=20c34d1d5d5a4639061e08165c61a97e63', 
//文件 
arr2:'img?uuid=20327500502b71ed0278a0cc1bf8f8bb41', 
obj2:'img?uuid=203346cafeedac1fb7628bc886b9b7fb47' 
}, 
toTree:function(){/* JSON转换为树HTML,同时格式化代码 */ 
var draw=[],This=this,ico=this.ico; 
JE.firstUp=false;/*完成首次自动构造*/ 
var notify=function(prefix/*前缀HTML*/,lastParent/*父是否是尾节点(确定图标是空白|结构线)*/,name /*节点名*/,value/*节点值*/,formObj/* 父是否是对象(确定子图标) */){/* 构造子节点 */ 
var rl=prefix==''?ico.r0:lastParent?ico.r1:ico.r2;/* 配置根节点图标 */ 
if(value&&value.constructor==Array){/* 处理数组节点 */ 
draw.push('<dl><dt>',This.draw(prefix,rl,ico.arr,name,''),'</dt><dd>');/* 绘制文件夹 */ 
for (var i=0;i<value.length;i++) 
notify(prefix+This.img(lastParent?ico.nl:ico.vl),i==value.length-1,i,value[i]); 
draw.push('</dd></dl>'); 
}else if(value&&typeof value=='object'){/* 处理对象节点 */ 
draw.push('<dl><dt>',This.draw(prefix,rl,ico.obj,name,''),'</dt><dd>');/* 绘制文件夹 */ 
var len=0,i=0; 
for(var key in value)len++;/* 获取对象成员总数 */ 
for(var key in value)notify(prefix+This.img(lastParent?ico.nl:ico.vl),++i==len,key,value[key],true); 
draw.push('</dd></dl>'); 
}else{/* 处理叶节点(绘制文件) */ 
draw.push('<dl><dt>',This.draw(prefix,lastParent?ico.f1:ico.f2,formObj?ico.obj2:ico.arr2,name,value),'</dt></dl>'); 
}; 
};/* 不是[]或者{}不绘制 */ 
if(typeof this.data=='object'){notify('',true,this.root,this.data);}; 
if(this.treeUI)this.treeUI.innerHTML=draw.join('');/* 显示在树窗口 */ 
this.msg('成功构造树视图!'); 
}, 
draw:function(prevfix,line,ico,name,value){/* 子项HTML构造器 */ 
var cmd=false,J=this.ico,imgName=false; 
switch (line) {//传递切换图标 
case J.r0:imgName='r0';break; 
case J.r1:imgName='r1';break; 
case J.r2:imgName='r2'; 
} 
if(imgName)cmd=' onclick="'+this.name+'.show(this,\''+imgName+'\')" ';/* 加入折叠命令 */ 
var type=typeof name=='string'?'(对象成员)':'(数组索引)'; 
return prevfix+this.img(line,cmd) 
+(this.checkbox?'<input type="checkbox" onclick="'+this.name+'.select(this)" />':'') 
+this.img(ico)+' <a href="javascript:void(0)" href="javascript:void(0)" onclick="'+this.name+'.click(this);" ' 
+'key="'+name+'" val="'+value+'" >' 
+name+type+(value==''?'':' = ')+value+'</a>' 
}, 
img:function(src,attr){/* img HTML构造 */ 
return '<img src="'+src+'" src="'+src+'" '+(attr||'')+' />'; 
}, 
click:function(item){/* 子项点击统一回调 */ 
if(this.hot)this.hot.className=''; 
this.hot=item; 
this.hot.className='hot';/* 切换选中项 */ 
this.onclick(item); 
}, 
format:function(txt,compress/*是否为压缩模式*/){/* 格式化JSON源码(对象转换为JSON文本) */ 
if(/^\s*$/.test(txt))return this.msg('数据为空,无法格式化! '); 
try{var data=eval('('+txt+')');} 
catch(e){ 
JE.editUI.style.color='red'; 
return this.msg('数据源语法错误,格式化失败! 错误信息: '+e.description,'err'); 
}; 
JE.editUI.style.color='#000'; 
var draw=[],last=false,This=this,line=compress?'':'\n',nodeCount=0,maxDepth=0; 
var notify=function(name,value,isLast,indent/*缩进*/,formObj){ 
nodeCount++;/*节点计数*/ 
for (var i=0,tab='';i<indent;i++ )tab+=This.indent;/* 缩进HTML */ 
tab=compress?'':tab;/*压缩模式忽略缩进*/ 
maxDepth=++indent;/*缩进递增并记录*/ 
if(value&&value.constructor==Array){/*处理数组*/ 
draw.push(tab+(formObj?('"'+name+'":'):'')+'['+line);/*缩进'[' 然后换行*/ 
for (var i=0;i<value.length;i++) 
notify(i,value[i],i==value.length-1,indent,false); 
draw.push(tab+']'+(isLast?line:(','+line)));/*缩进']'换行,若非尾元素则添加逗号*/ 
}else if(value&&typeof value=='object'){/*处理对象*/ 
draw.push(tab+(formObj?('"'+name+'":'):'')+'{'+line);/*缩进'{' 然后换行*/ 
var len=0,i=0; 
for(var key in value)len++; 
for(var key in value)notify(key,value[key],++i==len,indent,true); 
draw.push(tab+'}'+(isLast?line:(','+line)));/*缩进'}'换行,若非尾元素则添加逗号*/ 
}else{ 
if(typeof value=='string')value='"'+value+'"'; 
draw.push(tab+(formObj?('"'+name+'":'):'')+value+(isLast?'':',')+line); 
}; 
}; 
var isLast=true,indent=0; 
notify('',data,isLast,indent,false); 
this.countInfo='共处理节点<b>'+nodeCount+'</b>个,最大树深为<b>'+maxDepth+'</b>'; 
return draw.join(''); 
}, 
msg:function(text,type){/* 编辑状态或者错误通知 */ 
if(!this.msgUI)return alert(text); 
with(new Date)var now=([getHours(),getMinutes(),getSeconds()].join(':')).replace(/\b\d\b/g,'0$&'); 
this.msgUI.innerHTML='<div>['+now+']   '+text.replace(/\n/g,'<br/>')+'</div>'; 
this.msgUI.className=type; 
}, 
show:function (ico,id){/* 显隐树节点 */ 
var subView=ico.parentNode.parentNode.childNodes[1].style,J=this.ico; 
if(subView.display=='none'){ 
subView.display=''; 
ico.src=J[id]; 
}else{ 
subView.display='none'; 
ico.src=J[id+'c']; 
}; 
}, 
select:function (sender){ 
var sub=sender.parentNode.parentNode.getElementsByTagName("INPUT"); 
for (var i=0;i<sub.length;i++ ) {sub[i].checked=sender.checked;} 
} 
}; 
JE.add=function(){ 
this.msg('功能添加中...*_^'); 
} 
JE.editItem=function(){ 
this.msg('功能添加中...*_^'); 
} 
JE.begin=function(){/* 设置UI控件关联响应 */ 
var $=function (id){return document.getElementById(id)}; 
/* 关联UI */ 
JE.editUI=$("json_eidit"); 
JE.msgUI=$("json_editInfo"); 
JE.treeUI=$("tree"); 
var updateUI=$("update"); 
var auto=$("autoUpdate"); 
var fontSize=$("fontSize"); 
/* 单击树子项 */ 
JE.onclick=function(item){ 
var key='键名: <input value="'+item.getAttribute('key')+'" />', 
val=' 键值: '+(item.getAttribute('val')==''?'成员列表':'<input value="'+item.getAttribute('val')+'" />'), 
add='<button onclick="'+this.name+'.add(this)">新增</button>', 
edit='<button onclick="'+this.name+'.editItem(this)">修改</button>'; 
JE.msg(key+val+add+edit,'info'); 
} 
/* 监听代码变化事件 */ 
JE.editUI.oninput=JE.editUI.onpropertychange=function (){ 
if(JE.formating)return;/* 格式化不刷新树 */ 
if(/^\s*$/.test(this.value))return JE.msg('请输入JSON格式的代码!');; 
clearTimeout(JE.update); 
try{JE.data=eval('('+this.value+')'); 
}catch(e){ 
JE.editUI.style.color='red'; 
return JE.msg("源代码有错误: "+e.description+' , 如果正在编辑中, 请忽略此消息!','err'); 
}; 
JE.editUI.style.color='#000'; 
if(auto.checked||JE.firstUp){/*若同步*/ 
JE.msg('语法正确,正在重新构造树,请稍候...','busy'); 
JE.update=setTimeout(function(){ 
JE.toTree(); 
},450); 
}else{ 
JE.msg('语法正确,请点击刷新,或者打开视图同步开关,或者继续编辑!') 
} 
return true; 
}; 
if(window.ActiveXObject) 
document.execCommand("BackgroundImageCache", false, true); 
/* 拦截Tab,自动格式化 */ 
JE.editUI.onkeydown=function (){ 
if(event.keyCode==9){$('format_indent').onclick();event.returnValue=false;}; 
JE.code=this.value; 
} 
/* 格式化 */ 
var format=function(compress){ 
var code=JE.format(JE.editUI.value,compress); 
JE.formating=true; 
if(code)JE.editUI.value=code; 
JE.editUI.focus(); 
setTimeout(function(){JE.formating=false;},1000); 
return code; 
} 
/* 工具栏按钮 */ 
$('format_indent').onclick=function (){if(format())JE.msg('完成缩进风格转换,'+JE.countInfo)} 
$('format_compress').onclick=function (){if(format(true)!=undefined)JE.msg('完成紧凑风格转换,'+JE.countInfo);} 
updateUI.onclick=function (){ 
JE.firstUp=true; 
JE.editUI.onpropertychange()?JE.msg('成功刷新视图!'):JE.msg('数据有误,刷新失败!','err') 
JE.firstUp=false; 
}; 
$('clear_txt').onclick=function (){JE.editUI.value=JE.treeUI.innerHTML='';JE.editUI.focus();} 
auto.onclick=function (){JE.msg('自动同步视图功能'+(this.checked?'开启':'关闭!'));}; 
/* 另存为 */ 
if(/*@cc_on !@*/true){$('save_as').style.display='none'}; 
$('save_as').onclick=function (){ 
var d=document,w=d.createElement('IFRAME'); 
w.style.display="none"; 
d.body.appendChild(w); 
setTimeout(function(){ 
var g=w.contentWindow.document; 
g.charset = 'utf-8'; 
g.body.innerHTML=JE.editUI.value; 
g.execCommand("saveas",'', "json.txt") ; 
},1); 
} 
}; 
/* 从这里开始 */ 
window.onload=function (){ 
JE.begin(); 
} 
// --></script>
Javascript 相关文章推荐
新浪微博字数统计 textarea字数统计实现代码
Aug 28 Javascript
面向对象继承实例(a如何继承b问题)(自写)
Jul 01 Javascript
详解javascript传统方法实现异步校验
Jan 22 Javascript
Bootstrap每天必学之折叠(Collapse)插件
Apr 25 Javascript
JS判断图片是否加载完成方法汇总(最新版)
May 13 Javascript
KnockoutJS 3.X API 第四章之click绑定
Oct 10 Javascript
js控制文本框禁止输入特殊字符详解
Apr 07 Javascript
JSON创建键值对(key是中文或者数字)方式详解
Aug 24 Javascript
JavaScript字符串转数字的5种方法及遇到的坑
Jul 16 Javascript
微信小程序实现之手势锁功能实例代码
Jul 19 Javascript
js实现转动骰子模型
Oct 24 Javascript
Vue实现简单计算器案例
Feb 25 Javascript
JS 控制非法字符的输入代码
Dec 04 #Javascript
对采用动态原型方式无法展示继承机制得思考
Dec 04 #Javascript
JavaScript 申明函数的三种方法 每个函数就是一个对象(一)
Dec 04 #Javascript
javascript 跳转代码集合
Dec 03 #Javascript
javascript KeyDown、KeyPress和KeyUp事件的区别与联系
Dec 03 #Javascript
javascript json 新手入门文档
Dec 03 #Javascript
js 屏蔽鼠标右键脚本附破解方法
Dec 03 #Javascript
You might like
php遍历文件夹和文件列表示例分享
2014/03/11 PHP
PHP使用pear自带的mail类库发邮件的方法
2015/07/08 PHP
PHP基于mssql扩展远程连接MSSQL的简单实现方法
2016/10/08 PHP
ThinkPHP框架获取最后一次执行SQL语句及变量调试简单操作示例
2018/06/13 PHP
js脚本获取webform服务器控件的方法
2014/05/16 Javascript
用js传递value默认值的示例代码
2014/09/11 Javascript
Javascript中封装window.open解决不兼容问题
2014/09/28 Javascript
jQuery实现平滑滚动页面到指定锚点链接的方法
2015/07/15 Javascript
jquery实现鼠标经过显示下划线的渐变下拉菜单效果代码
2015/08/24 Javascript
jQuery实现删除li节点的方法
2016/12/06 Javascript
bootstrap table表格插件使用详解
2017/05/08 Javascript
修改 bootstrap table 默认detailRow样式的实例代码
2017/07/21 Javascript
基于javaScript的this指向总结
2017/07/22 Javascript
JavaScript对象的浅拷贝与深拷贝实例分析
2018/07/25 Javascript
从零开始学习搭建React脚手架项目
2018/08/23 Javascript
解决百度Echarts图表坐标轴越界的方法
2018/10/17 Javascript
CountUp.js数字滚动插件使用方法详解
2019/10/17 Javascript
JavaScript组合模式---引入案例分析
2020/05/23 Javascript
[04:21]狐狸妈带你到现场 DOTA2 TI中国区预选赛线下赛路线指引
2014/05/22 DOTA
python基础教程之基本数据类型和变量声明介绍
2014/08/29 Python
Python字符串逆序的实现方法【一题多解】
2019/02/18 Python
pyqt 实现在Widgets中显示图片和文字的方法
2019/06/13 Python
pyinstaller参数介绍以及总结详解
2019/07/12 Python
python分布式计算dispy的使用详解
2019/12/22 Python
利用css3如何设置没有上下边的列表间隔线
2017/07/03 HTML / CSS
HTML5本地存储和本地数据库实例详解
2017/09/05 HTML / CSS
澳大利亚正品化妆品之家:Cosmetic Capital
2017/07/03 全球购物
约瑟夫·特纳男装:Joseph Turner
2017/10/10 全球购物
委托书范文
2014/04/02 职场文书
2014年国庆节演讲稿
2014/09/02 职场文书
2014年妇委会工作总结
2014/12/10 职场文书
《雷雨》教学反思
2016/02/20 职场文书
幼儿园教师教学反思
2016/03/02 职场文书
创业计划书之奶茶店开店方案范本!
2019/08/06 职场文书
nginx配置ssl实现https的方法示例
2021/03/31 Servers
Vue中foreach数组与js中遍历数组的写法说明
2021/06/05 Vue.js