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 相关文章推荐
jQuery EasyUI 中文API Layout(Tabs)
Apr 27 Javascript
JSChart轻量级图形报表工具(内置函数中文参考)
Oct 11 Javascript
jQuery AjaxQueue改进步骤
Oct 06 Javascript
原生javaScript做得动态表格(注释写的很清楚)
Dec 29 Javascript
JS实现可关闭的对联广告效果代码
Sep 14 Javascript
举例讲解JavaScript中关于对象操作的相关知识
Nov 16 Javascript
基于jQuery实现的仿百度首页滑动选项卡效果代码
Nov 16 Javascript
jQuery niceScroll滚动条错位问题的解决方法
Feb 03 jQuery
VUE在for循环里面根据内容值动态的加入class值的方法
Aug 12 Javascript
微信小程序使用wxParse解析html的实现示例
Aug 30 Javascript
通过jQuery学习js类型判断的技巧
May 27 jQuery
深入分析JavaScript 事件循环(Event Loop)
Jun 19 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
基于Snoopy的PHP近似完美获取网站编码的代码
2011/10/23 PHP
IIS+fastcgi下PHP运行超时问题的解决办法详解
2013/06/20 PHP
joomla数据库操作示例代码
2016/01/06 PHP
PHP使用glob方法遍历文件夹下所有文件的实例
2018/10/17 PHP
Laravel框架学习笔记之批量更新数据功能
2019/05/30 PHP
从零开始学习jQuery (八) 插播:jQuery实施方案
2011/02/23 Javascript
jquery插件validate验证的小例子
2013/05/08 Javascript
javascript原生和jquery库实现iframe自适应高度和宽度
2014/07/18 Javascript
js实现点击图片将图片地址复制到粘贴板的方法
2015/02/16 Javascript
JS简单实现DIV相对于浏览器固定位置不变的方法
2016/06/17 Javascript
使用vue.js2.0 + ElementUI开发后台管理系统详细教程(一)
2017/01/21 Javascript
electron demo项目npm install安装失败的解决方法
2018/02/06 Javascript
ElementUI Tag组件实现多标签生成的方法示例
2019/07/08 Javascript
[01:00:53]OG vs IG 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
Python实时获取cmd的输出
2015/12/13 Python
python常见的格式化输出小结
2016/12/15 Python
python爬虫_微信公众号推送信息爬取的实例
2017/10/23 Python
浅析python继承与多重继承
2018/09/13 Python
解决Django中调用keras的模型出现的问题
2019/08/07 Python
使用Python和OpenCV检测图像中的物体并将物体裁剪下来
2019/10/30 Python
python 循环数据赋值实例
2019/12/02 Python
Python Tkinter Entry和Text的添加与使用详解
2020/03/04 Python
PyInstaller的安装和使用的详细步骤
2020/06/02 Python
详解pycharm连接远程linux服务器的虚拟环境的方法
2020/11/13 Python
CSS3 mask 遮罩的具体使用方法
2017/11/03 HTML / CSS
BrandAlley英国:法国折扣奢侈品网上零售商
2017/07/03 全球购物
Wallis官网:英国女装零售商
2020/01/21 全球购物
自荐信怎么写好
2013/11/11 职场文书
诉讼授权委托书
2014/10/15 职场文书
2014年检察院个人工作总结
2014/12/09 职场文书
2015年采购员工作总结
2015/04/27 职场文书
婚礼必备主持词范本!
2019/07/23 职场文书
适合青年人白手起家的创业项目分享
2019/08/16 职场文书
PyQt5 QThread倒计时功能的实现代码
2021/04/02 Python
Ajax请求超时与网络异常处理图文详解
2021/05/23 Javascript
springboot读取resources下文件的方式详解
2022/06/21 Java/Android