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 相关文章推荐
js宝典学习笔记(上)
Jan 10 Javascript
js自动生成对象的属性示例代码
Oct 28 Javascript
IE8的JavaScript点击事件(onclick)不兼容的解决方法
Nov 22 Javascript
如何在MVC应用程序中使用Jquery
Nov 17 Javascript
jQuery实现监控页面所有ajax请求的方法
Dec 10 Javascript
JS实现部分HTML固定页面顶部随屏滚动效果
Dec 24 Javascript
JS实现点击事件统计的简单实例
Jul 10 Javascript
js获取html的span标签的值方法(超简单)
Jul 26 Javascript
tangram.js库实现js类的方式实例分析
Jan 06 Javascript
基于打包工具Webpack进行项目开发实例
May 29 Javascript
vue调试工具vue-devtools安装及使用方法
Nov 07 Javascript
Vue+Express实现登录状态权限验证的示例代码
May 05 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
星际原理概述
2020/03/04 星际争霸
最令PHP初学者头痛的十四个问题
2006/07/12 PHP
PHP 设计模式之观察者模式介绍
2012/02/22 PHP
apache配置虚拟主机的方法详解
2013/06/17 PHP
统计出现最多的字符次数的js代码
2010/12/03 Javascript
JS格式化数字保留两位小数点示例代码
2013/10/15 Javascript
wap手机图片滑动切换特效无css3元素js脚本编写
2014/07/28 Javascript
jquery 无限极下拉菜单的简单实例(精简浓缩版)
2016/05/31 Javascript
JS图片定时翻滚效果实现方法
2016/06/21 Javascript
JS+HTML5实现上传图片预览效果完整实例【测试可用】
2017/04/20 Javascript
html5+canvas实现支持触屏的签名插件教程
2017/05/08 Javascript
gulp解决跨域的配置文件问题
2017/06/08 Javascript
基于Vue 2.0的模块化前端 UI 组件库小结
2017/12/21 Javascript
Vue表单类的父子组件数据传递示例
2018/05/03 Javascript
详解element-ui中form验证杂记
2019/03/04 Javascript
Vue基本使用之对象提供的属性功能
2019/04/30 Javascript
关于JS模块化的知识点分享
2019/10/16 Javascript
mpvue微信小程序开发之实现一个弹幕评论
2019/11/24 Javascript
JS数组Reduce方法功能与用法实例详解
2020/04/29 Javascript
nodejs使用Sequelize框架操作数据库的实现
2020/10/21 NodeJs
Python实现求解一元二次方程的方法示例
2018/06/20 Python
Python求两个圆的交点坐标或三个圆的交点坐标方法
2018/11/07 Python
python 实现交换两个列表元素的位置示例
2019/06/26 Python
Python使用numpy模块实现矩阵和列表的连接操作方法
2019/06/26 Python
Python3 元组tuple入门基础
2020/02/09 Python
python中文分词库jieba使用方法详解
2020/02/11 Python
css3新单位vw、vh的使用教程
2018/03/23 HTML / CSS
深入理解HTML5定时器requestAnimationFrame的使用
2018/12/12 HTML / CSS
英国第一的市场和亚马逊替代品:OnBuy
2019/03/16 全球购物
SportsDirect.com新加坡:英国第一体育零售商
2019/03/30 全球购物
人事助理岗位职责
2013/11/18 职场文书
公司业务主管岗位职责
2013/12/07 职场文书
机械设计毕业生自荐信
2014/02/02 职场文书
《在家里》教后反思
2014/03/01 职场文书
婚礼证婚人演讲稿
2014/09/13 职场文书
SpringBoot深入分析讲解监听器模式下
2022/07/15 Java/Android