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学习笔记 操作jQuery对象 CSS处理
Sep 19 Javascript
js读写cookie实现一个底部广告浮层效果的两种方法
Dec 29 Javascript
将form表单通过ajax实现无刷新提交的简单实例
Oct 12 Javascript
js实现导航吸顶效果
Feb 24 Javascript
原生JavaScript实现的简单省市县三级联动功能示例
May 27 Javascript
AngularJS 控制器 controller的详解
Oct 17 Javascript
ExtJs整合Echarts的示例代码
Feb 27 Javascript
JS实现的哈夫曼编码示例【原始版与修改版】
Apr 22 Javascript
jQuery控制input只能输入数字和两位小数的方法
May 16 jQuery
JS实现可控制的进度条
Mar 25 Javascript
JS异步宏队列微队列原理详解
Sep 09 Javascript
JavaScript仿京东轮播图效果
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
MySQL中create table语句的基本语法是
2007/01/15 PHP
getimagesize获取图片尺寸实例
2014/11/15 PHP
PHP快速排序quicksort实例详解
2016/09/28 PHP
thinkPHP5框架分页样式类完整示例
2018/09/01 PHP
浅谈laravel数据库查询返回的数据形式
2019/10/21 PHP
基于PHP实现堆排序原理及实例详解
2020/06/19 PHP
取得父标签
2006/11/14 Javascript
Javascript Jquery 遍历Json的实现代码
2010/03/31 Javascript
js中字符替换函数String.replace()使用技巧
2011/08/14 Javascript
自定义百度分享的分享按钮
2015/03/18 Javascript
javascript实现随机读取数组的方法
2015/08/03 Javascript
解析预加载显示图片艺术
2016/12/05 Javascript
JavaScript设计模式之代理模式详解
2017/06/09 Javascript
jquery实现用户登陆界面(示例讲解)
2017/09/06 jQuery
深入理解Promise.all
2018/08/08 Javascript
微信小程序+云开发实现欢迎登录注册
2019/05/24 Javascript
通过js给网页加上水印背景实例
2019/06/17 Javascript
解决layui追加或者动态修改的表单元素“没效果”的问题
2019/09/18 Javascript
vue 解决路由只变化参数页面组件不更新问题
2019/11/05 Javascript
element-ui树形控件后台返回的数据+生成组织树的工具类
2020/03/05 Javascript
小程序实现录音功能
2020/09/22 Javascript
[01:01:14]完美世界DOTA2联赛PWL S2 SZ vs Rebirth 第一场 11.21
2020/11/23 DOTA
用python做一个搜索引擎(Pylucene)的实例代码
2017/07/05 Python
python3基于OpenCV实现证件照背景替换
2018/07/18 Python
anaconda中更改python版本的方法步骤
2019/07/14 Python
森海塞尔美国官网:Sennheiser耳机与耳麦
2017/07/19 全球购物
博朗(Braun)俄罗斯官方商店:德国小家电品牌
2019/09/24 全球购物
EM Cosmetics官网:由彩妆大神Michelle Phan创办的独立品牌
2020/04/27 全球购物
化学实验员岗位职责
2013/12/28 职场文书
个人能力自我鉴赏
2014/01/25 职场文书
私人房屋买卖协议书
2014/10/04 职场文书
面试通知短信
2015/04/20 职场文书
高中班长竞选稿
2015/11/20 职场文书
【TED出品】天梯非主流开心游1700 划水骑士
2022/03/31 魔兽争霸
Python&Matlab实现樱花的绘制
2022/04/07 Python
MySQL库表太大怎么办? 数据库分库分表项目实践
2022/04/11 MySQL