给项目添加文件在线编辑功能

tree菜单
placeholder image
admin 发布于:2013-10-25 20:51:00
阅读:loading

给项目添加文件在线编辑的功能,这个功能可以有吧。项目上线大多都会经过这么几种环境的部署:本地—测试环境—生产环境,它们之间的最大的关系是本地和测试环境的代码可以随意更改,生产环境可能就不是这样,某些生产环境还是特别敏感的,不对非特定的人授权。但往往可能由于程序的逻辑疏漏、打包部署时的大意或者其他某个特殊的问题导致,我们需要直接修改服务器部署程序中的某个文件,多数属于js脚本不兼容啊,css样式问题等,都可以采取这里介绍的这个程序来实现(当然.class文件是不行的,由于是二进制文件,这里说到的只是字符文件)当然类似的.xml、.properties等通过本程序将其修改之后可以找缓存的理由,下回重启一下即可(这里只是举例描述这个功能在程序里面可以有,并非是我这么干过)。说到这里可能还是很模糊这是个什么云云,就是在线修改文件的功能,其实也就是将乱七八糟的几个插件揉一块,将原本各有各的用整理在一起而已。

实现目标: 
            1、%TOMCAT_HOME%/webapps/MyApps目录下的文件结构生成一个文件树

    2、使用CodeMirror插件来显示具体某个文件的内容且得让文件的内容可被编辑。

    3、添加一行工具栏,使用很流行的浮动定位插件来存放保存修改按钮。

    4、友好的页面无刷新且提示用保存修改的状态提示

 具体实现1)生成文件树
    就使用非常强大的zTree吧,使用它来默认初始加载第一级文件结果作为默认显示的节点,而后再点击再加载子级 节点,并缓存与客户端,下次点击则不再加载。另外这个tree插件支持自定义图标,那么就从eclipse的安装目录里面整理出一套图标出来。
 具体实现2)显示文件内容
    就使用CodeMirror插件吧,它拥有强大的文件代码着色的功能且支持文件代码展示可被编辑,另外此插件还包括了强大的插件机制和丰富的其他功能(如代码折叠功能),这里只使用它的换肤功能。
 具体实现3)添加浮动工具栏
    工具栏的实现可以随便找一个浮动定位的插件,发现某些实现还是比较简单的,这里就给出一个网上找的又修改了下的特别简单的版本。
 具体实现4保存修改动作 

    无刷新的form表单存储使用jquery.form插件,它可以将form表单的提交方式修改为以ajax方式的形式提交,用此插件的好处是无需考虑本次提交的代码文件中的特殊字符的转义、转码等等其他的问题。

相关代码如下: 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!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>

<link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath }/js/jquery/plugins/zTree/css/zTreeStyle/zTreeStyle.css" type="text/css">

<script type="text/javascript" src="${pageContext.request.contextPath }/app/js/jquery-1.8.3.js"></script>

<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery/plugins/zTree/js/jquery.ztree.core-3.5.min.js"></script>

<script type="text/javascript" src="${pageContext.request.contextPath }/app/js/plugins/jquery.floatLocation.js"></script>

<script type="text/javascript" src="${pageContext.request.contextPath }/app/js/plugins/jqueryform/jquery.form.js"></script>

<script type="text/javascript">

    var setting = {

        async: {

            enable: true,

            url:"${pageContext.request.contextPath}/fileFolderServlet",

            autoParam:["id"]

        },

        callback: {

            //onAsyncSuccess: expandNodes//每次点击异步请求之后均执行

        }

    };

    

    $(function(){

        var zNodes = $.ajax({

            url: "${pageContext.request.contextPath}/fileFolderServlet",

            dataType : "json",

            successfunction(data){

                //异步方式默认构造一个跟节点

                $.fn.zTree.init($("#fileFolderTree"), setting , data);

                //当存在跟节点之后,去后台加载跟节点的第一级子节点

                var zTree = $.fn.zTree.getZTreeObj("fileFolderTree");

                //打开所有的子节点

                expandNodes(zTree.getNodes());

                

            },errorfunction(msg){

                alert("加载tree错误");

            }

        });

    });

    

    function expandNodes(nodes) {

        if (!nodes) return;

        var zTree = $.fn.zTree.getZTreeObj("fileFolderTree");

        for (var i=0, l=nodes.length; i<l; i++) {

            zTree.expandNode(nodes[i], true, false, false);

            if (nodes[i].isParent && nodes[i].zAsync) {

                expandNodes(nodes[i].children);

            }

        }

    }

    

    function readFile2Editor(id){

        $("#writeId").val("");

        $.ajax({

            url : "${pageContext.request.contextPath}/fileFolderServlet?readId=" + decodeURIComponent(id),

            successfunction(data){

                

                $("#writeId").val(id);

                codeEditor.setValue(data);

            },

            errorfunction(msg){

                alert("请求错误:" + msg);

            }

        });

    }

    // prepare the form when the DOM is ready 

    $(document).ready(function() { 

        var options = { 

            target:        '#tt',   // target element(s) to be updated with server response 

            beforeSubmit:  showRequest,  // pre-submit callback 

            success:       showResponse  // post-submit callback 

        }; 

     

        // bind form using 'ajaxForm' 

        $('#contentForm').ajaxForm(options); 

    }); 

     

    function showRequest(formDatajqFormoptions) { 

        

        //alert(codeEditor.getValue());

        return true; 

    } 

     

    // post-submit callback 

    function showResponse(responseTextstatusText)  { 

        //alert('status: ' + statusText + '\n\nresponseText: \n' + responseText + 

            //'\n\nThe output div should have already been updated with the responseText.'); 

        alert(responseText);

    } 

    

    function analyseSubmit(){

        if($("#writeId").val() == ""){

            alert("请选择要修改的文件.");

            return;

        }

        if(confirm("确定是要保存更改吗?"== false){

            return;

        }

        

        $("#content").val(codeEditor.getValue());

        $("#contentForm").submit();

    }

</script>

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/lib/codemirror.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/3024-day.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/3024-night.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/ambiance.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/base16-dark.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/base16-light.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/blackboard.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/cobalt.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/eclipse.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/elegant.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/erlang-dark.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/lesser-dark.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/mbo.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/midnight.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/monokai.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/neat.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/night.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/paraiso-dark.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/paraiso-light.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/rubyblue.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/solarized.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/the-matrix.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/tomorrow-night-eighties.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/twilight.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/vibrant-ink.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/xq-dark.css" />

<link rel="stylesheet" href="${pageContext.request.contextPath }/js/CodeMirror/theme/xq-light.css" />

<script src="${pageContext.request.contextPath }/js/CodeMirror/lib/codemirror.js"></script>

<script src="${pageContext.request.contextPath }/js/CodeMirror/mode/javascript/javascript.js"></script>

<script src="${pageContext.request.contextPath }/js/CodeMirror/keymap/extra.js"></script>

<script src="${pageContext.request.contextPath }/js/CodeMirror/addon/selection/active-line.js"></script>

<script src="${pageContext.request.contextPath }/js/CodeMirror/addon/edit/matchbrackets.js"></script>

<script src="${pageContext.request.contextPath }/js/CodeMirror/mode/xml/xml.js"></script>

<script src="${pageContext.request.contextPath }/js/CodeMirror/mode/css/css.js"></script>

<script src="${pageContext.request.contextPath }/js/CodeMirror/mode/htmlmixed/htmlmixed.js"></script>

<script src="${pageContext.request.contextPath }/js/CodeMirror/doc/activebookmark.js"></script>

<style type="text/css">

  .CodeMirror { height: auto; width : auto; border: 1px solid #ddd; }

  .CodeMirror-scroll {width : auto; min-height: 200px;}

  .CodeMirror pre { padding-left: 7pxline-height: 1.25; }

  

</style>

<script type="text/javascript">

    var codeEditor = null;

    $(function(){

        

        //添加定位

        $("#toolsbar").floatLocation();

        

        codeEditor = CodeMirror.fromTextArea(document.getElementById("fileContentId"), {

            lineNumbers: true,

            mode: "text/html",

            styleActiveLine: true,

            matchBrackets: true

        });

        codeEditor.setOption("theme""eclipse");   

    });

    

    function changeCodeEditorStyle(value){

        codeEditor.setOption("theme", value);

    }

    

</script>

<style type="text/css">

    .content_wrap{

        width: 260px;

        overflow: auto;

        floatleft;

    }

    .clear{

        clear:none;

        display: none;

    }

    

    #toolsbar{

        z-index:999;

        width: 100%;

    }

    

    body{

        margin: 0px;

        padding: 0px;

    }

    

</style>

</head>

<body>

<div id="toolsbar" align="center">

    <form id="contentForm" action="${pageContext.request.contextPath}/fileFolderServlet" method="post">

        <input type="hidden" name="writeId" value="" id="writeId" />

        <textarea style="display:none;" name="content" id="content"></textarea>

        <input type="button" onclick="analyseSubmit()" value="保存更改"  />

        <input type="button" value="返回顶部" onclick="$(window).scrollTop(0);" />

        选择样式:

        <select id="codeEditorStyle" onchange="changeCodeEditorStyle(this.value)">

            <option value="default">default</option>

            <option value="3024-day">3024-day</option>

            <option value="3024-night">3024-night</option>

            <option value="ambiance">ambiance</option>

            <option value="base16-dark">base16-dark</option>

            <option value="base16-light">base16-light</option>

            <option value="blackboard">blackboard</option>

            <option value="cobalt">cobalt</option>

            <option value="eclipse" selected="selected">eclipse</option>

            <option value="elegant">elegant</option>

            <option value="erlang-dark">erlang-dark</option>

            <option value="lesser-dark">lesser-dark</option>

            <option value="mbo">mbo</option>

            <option value="midnight">midnight</option>

            <option value="monokai">monokai</option>

            <option value="neat">neat</option>

            <option value="night">night</option>

            <option value="paraiso-dark">paraiso-dark</option>

            <option value="paraiso-light">paraiso-light</option>

            <option value="rubyblue">rubyblue</option>

            <option value="solarized dark">solarized dark</option>

            <option value="solarized light">solarized light</option>

            <option value="the-matrix">the-matrix</option>

            <option value="tomorrow-night-eighties">tomorrow-night-eighties</option>

            <option value="twilight">twilight</option>

            <option value="vibrant-ink">vibrant-ink</option>

            <option value="xq-dark">xq-dark</option>

            <option value="xq-light">xq-light</option>

        </select>

    </form>

</div>

<br/><br/>

<div id="nav" class="content_wrap">

    <div id="fileFolderId" class="zTreeDemoBackground left">

        <ul id="fileFolderTree" class="ztree"></ul>

    </div>

</div>

    <div >

        <textarea id="fileContentId"></textarea>

    </div>

<div id="tt" class="clear"></div>

</body>

</html>

 使用到的组件如下:

前端文件:
    jquery-version-xx.js、jquery.form.js、jquery.floatLocation.js、editors.jsp
    zTree组件官网地址:
http://www.ztree.me/v3/main.php 
    CodeMirror组件官网地址:
http://codemirror.net/
后端文件:
    Servlet.java,Service.java,Bean.java,web.xml 

不足之处

        1、处理文件太大的情况

        2、排除一些不可被编辑的文件类型(.calss,.img图片文件等)
3、其他不明 

 运行截图:

效果图.gif

预览效果.gif


源代码下载:
    

src-code.zip

 点赞


 发表评论

当前回复:作者

 评论列表


留言区