jquery轻量级富文本编辑器Trumbowyg

html:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <meta name="renderer" content="webkit">
    <title></title>
    <link rel="stylesheet" href="assets/trumbowyg.css">
    ......
    <script type="text/javascript" src="js/jquery.js"></script>
    ......
    <script type="text/javascript" src="assets/trumbowyg.js"></script>
    ......
    <script type="text/javascript" src="assets/trumbowyg.upload.js"></script>
</head>
<body> 
      <div id="odiv" style="display:none;position:absolute;z-index:100;">
        <img src="assets/pic/sx.png" title="缩小" border="0" alt="缩小" onclick="sub(-1);"/>
        <img src="assets/pic/fd.png" title="放大" border="0" alt="放大" onclick="sub(1)"/>
        <img src="assets/pic/cz.png" title="重置" border="0" alt="重置" onclick="sub(0)"/>
        <img src="assets/pic/sc.png" title="删除" border="0" alt="删除" onclick="del();odiv.style.display='none';"/>
      </div>
      <div onmousedown="show_element(event)" style="clear:both" id="customized-buttonpane" class="editor"></div>       
</body>
</head>  

trumbowyg.css

.trumbowyg-box,.editor{clear:both;display:block;position:relative;border:1px solid #DDD;width:100%;min-height:300px;margin:17px auto}.trumbowyg-box .editor{margin:0 auto;background:#FEFEFE}.trumbowyg-box.trumbowyg-fullscreen{background:#FEFEFE}.trumbowyg-editor,.trumbowyg-textarea{position:relative;padding:1% 2%;min-height:300px;width:96%;border-style:none;resize:none;outline:none}.trumbowyg-box-blur .trumbowyg-editor *{color:transparent !important;text-shadow:0 0 7px #333}.trumbowyg-box-blur .trumbowyg-editor img{filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=20);opacity:0.2}.trumbowyg-textarea{position:relative;display:block;overflow:auto;border:none;white-space:normal}.trumbowyg-button-pane{position:relative;width:100%;background:#ecf0f1;border-bottom:1px solid #d7e0e2;margin:0;padding:0;list-style-type:none;line-height:10px}.trumbowyg-button-pane li{display:inline-block;text-align:center;overflow:hidden}.trumbowyg-button-pane li.trumbowyg-separator{width:1px;background:#d7e0e2;margin:0 5px;height:35px}.trumbowyg-button-pane.trumbowyg-disable li:not(.trumbowyg-not-disable) button{opacity:.2;cursor:default}.trumbowyg-button-pane.trumbowyg-disable li.trumbowyg-separator{background:#e3e9eb}.trumbowyg-button-pane:not(.trumbowyg-disable) li button:hover,.trumbowyg-button-pane:not(.trumbowyg-disable) li button:focus,.trumbowyg-button-pane li button.trumbowyg-active,.trumbowyg-button-pane li.trumbowyg-not-disable button:hover,.trumbowyg-button-pane li.trumbowyg-not-disable button:focus{outline:none}.trumbowyg-button-pane li .trumbowyg-open-dropdown:after{display:block;content:" ";position:absolute;top:25px;right:3px;height:0;width:0;border:3px solid transparent;border-top-color:#555}.trumbowyg-button-pane .trumbowyg-buttons-right{float:right;width:auto}.trumbowyg-button-pane .trumbowyg-buttons-right button{float:left}.trumbowyg-dropdown{width:200px;border:1px solid #ecf0f1;padding:5px 0;border-top:none;background:#FFF;margin-left:-1px;-moz-box-shadow:rgba(0,0,0,0.1) 0 2px 3px;-webkit-box-shadow:rgba(0,0,0,0.1) 0 2px 3px;box-shadow:rgba(0,0,0,0.1) 0 2px 3px}.trumbowyg-dropdown button{display:block;width:100%;height:35px;line-height:35px;text-decoration:none;background:#FFF;padding:0 14px;color:#333;border:none;cursor:pointer;text-align:left;font-size:15px;-moz-transition:all 0.15s;-o-transition:all 0.15s;-webkit-transition:all 0.15s;transition:all 0.15s}.trumbowyg-dropdown button:hover,.trumbowyg-dropdown button:focus{background:#ecf0f1}.trumbowyg-modal{position:absolute;top:0;left:50%;margin-left:-260px;width:520px;height:290px;overflow:hidden}.trumbowyg-modal-box{position:absolute;top:0;left:50%;margin-left:-250px;width:400px;padding: 10px 10px 35px 30px;z-index:1;background-color:#FFF;text-align:center;-moz-box-shadow:rgba(0,0,0,0.2) 0 2px 3px;-webkit-box-shadow:rgba(0,0,0,0.2) 0 2px 3px;box-shadow:rgba(0,0,0,0.2) 0 2px 3px}.trumbowyg-modal-box .trumbowyg-modal-title{font-size:24px;font-weight:bold;margin:0 0 20px;padding:15px 0 13px;display:block;border-bottom:1px solid #EEE;color:#333;background:#fbfcfc}.trumbowyg-modal-box .trumbowyg-progress{width:80%;background:#F00;height:3px;position:absolute;top:58px}.trumbowyg-modal-box .trumbowyg-progress .trumbowyg-progress-bar{background:#2BC06A;height:100%;-moz-transition:width 0.15s linear;-o-transition:width 0.15s linear;-webkit-transition:width 0.15s linear;transition:width 0.15s linear}.trumbowyg-modal-box input,input[type=text]{width:100%;}.trumbowyg-modal-box label{display:block;position:relative;margin:15px 12px;height:27px;line-height:27px;overflow:hidden}.trumbowyg-modal-box label .trumbowyg-input-infos{display:block;text-align:left;height:25px;line-height:25px;-moz-transition:all 0.15s;-o-transition:all 0.15s;-webkit-transition:all 0.15s;transition:all 0.15s}.trumbowyg-modal-box label .trumbowyg-input-infos span{display:block;color:#859fa5;background-color:#fbfcfc;border:1px solid #DEDEDE;padding:0 2%;width:19.5%}.trumbowyg-modal-box label .trumbowyg-input-infos span.trumbowyg-msg-error{color:#e74c3c}.trumbowyg-modal-box label.trumbowyg-input-error input,.trumbowyg-modal-box label.trumbowyg-input-error textarea{border:1px solid #e74c3c}.trumbowyg-modal-box label.trumbowyg-input-error .trumbowyg-input-infos{margin-top:-27px}.trumbowyg-modal-box label input{position:absolute;top:0;right:20px;height:25px;line-height:25px;border:1px solid #DEDEDE;background:transparent;width:72%;padding:0 2%;margin:0 0 0 23%;-moz-transition:all 0.15s;-o-transition:all 0.15s;-webkit-transition:all 0.15s;transition:all 0.15s}.trumbowyg-modal-box label input:hover,.trumbowyg-modal-box label input:focus{outline:none;border:1px solid #95a5a6}.trumbowyg-modal-box label input:focus{background:rgba(230,230,255,0.1)}.trumbowyg-modal-box .error{margin-top:25px;display:block;color:red}.trumbowyg-modal-box .trumbowyg-modal-button{position:absolute;bottom:10px;right:0;text-decoration:none;color:#FFF;display:block;width:70px; height:35px;line-height:33px;margin:0 10px;background-color:#333;border:none;border-top:none;cursor:pointer;font-family:"Trebuchet MS", Helvetica, Verdana, sans-serif;-moz-transition:all 0.15s;-o-transition:all 0.15s;-webkit-transition:all 0.15s;transition:all 0.15s;margin-right: 100px;}.trumbowyg-modal-box .trumbowyg-modal-button.trumbowyg-modal-submit{right:110px;background:#2bc06a}.trumbowyg-modal-box .trumbowyg-modal-button.trumbowyg-modal-submit:hover,.trumbowyg-modal-box .trumbowyg-modal-button.trumbowyg-modal-submit:focus{background:#40d47e;outline:none}.trumbowyg-modal-box .trumbowyg-modal-button.trumbowyg-modal-submit:active{background:#25a25a}.trumbowyg-modal-box .trumbowyg-modal-button.trumbowyg-modal-reset{background:#b33528}.trumbowyg-modal-box .trumbowyg-modal-button.trumbowyg-modal-reset:hover,.trumbowyg-modal-box .trumbowyg-modal-button.trumbowyg-modal-reset:focus{background:#d14233;outline:none}.trumbowyg-modal-box .trumbowyg-modal-button.trumbowyg-modal-reset:active{background:#962d22}.trumbowyg-overlay{position:absolute;background-color:rgba(255,255,255,0.5);width:100%;left:0;display:none}.trumbowyg-fullscreen.trumbowyg-box,.trumbowyg-fullscreen .editor{border:none}.trumbowyg-fullscreen .trumbowyg-overlay{height:100% !important}.trumbowyg-editor object,.trumbowyg-editor embed,.trumbowyg-editor video,.trumbowyg-editor img{max-width:100%}.trumbowyg-editor video,.trumbowyg-editor img{cursor:move}.trumbowyg-editor.trumbowyg-reset-css{background:#FEFEFE !important;font-family:"Trebuchet MS", Helvetica, Verdana, sans-serif !important;font-size:14px !important;line-height:1.45em !important;white-space:normal !important;color:#333}.trumbowyg-editor.trumbowyg-reset-css a{color:#15c !important;text-decoration:underline !important}.trumbowyg-editor.trumbowyg-reset-css div,.trumbowyg-editor.trumbowyg-reset-css p,.trumbowyg-editor.trumbowyg-reset-css ul,.trumbowyg-editor.trumbowyg-reset-css ol,.trumbowyg-editor.trumbowyg-reset-css blockquote{box-shadow:none !important;background:none !important;margin:0 !important;margin-bottom:15px !important;line-height:1.4em !important;font-family:"Trebuchet MS", Helvetica, Verdana, sans-serif !important;font-size:14px !important;border:none}.trumbowyg-editor.trumbowyg-reset-css iframe,.trumbowyg-editor.trumbowyg-reset-css object,.trumbowyg-editor.trumbowyg-reset-css hr{margin-bottom:15px !important}.trumbowyg-editor.trumbowyg-reset-css blockquote{margin-left:32px !important;font-style:italic !important;color:#555}.trumbowyg-editor.trumbowyg-reset-css ul,.trumbowyg-editor.trumbowyg-reset-css ol{padding-left:20px !important}.trumbowyg-editor.trumbowyg-reset-css ul ul,.trumbowyg-editor.trumbowyg-reset-css ol ol,.trumbowyg-editor.trumbowyg-reset-css ul ol,.trumbowyg-editor.trumbowyg-reset-css ol ul{border:none;margin:2px !important;padding:0 !important;padding-left:24px !important}.trumbowyg-editor.trumbowyg-reset-css hr{display:block;height:1px;border:none;border-top:1px solid #CCC}.trumbowyg-editor.trumbowyg-reset-css h1,.trumbowyg-editor.trumbowyg-reset-css h2,.trumbowyg-editor.trumbowyg-reset-css h3,.trumbowyg-editor.trumbowyg-reset-css h4{color:#111;background:none;margin:0 !important;padding:0 !important;font-weight:bold}.trumbowyg-editor.trumbowyg-reset-css h1{font-size:32px !important;line-height:38px !important;margin-bottom:20px !important}.trumbowyg-editor.trumbowyg-reset-css h2{font-size:26px !important;line-height:34px !important;margin-bottom:15px !important}.trumbowyg-editor.trumbowyg-reset-css h3{font-size:22px !important;line-height:28px !important;margin-bottom:7px !important}.trumbowyg-editor.trumbowyg-reset-css h4{font-size:16px !important;line-height:22px !important;margin-bottom:7px !important}.trumbowyg-button-pane li button{display:block;position:relative;text-indent:-9999px;width:35px;height:35px;overflow:hidden;background:transparent url('icons-sa75ce98b2b.png') no-repeat;border:none;cursor:pointer;-moz-transition:all 0.15s;-o-transition:all 0.15s;-webkit-transition:all 0.15s;transition:all 0.15s;transition:background-color .15s, background-image .15s, opacity .15s}.trumbowyg-button-pane li button.trumbowyg-viewHTML-button{background-position:5px -545px}.trumbowyg-button-pane li button.trumbowyg-formatting-button{background-position:5px -120px}.trumbowyg-button-pane li button.trumbowyg-bold-button,.trumbowyg-button-pane li button.trumbowyg-strong-button{background-position:5px -45px}.trumbowyg-button-pane li button.trumbowyg-italic-button,.trumbowyg-button-pane li button.trumbowyg-em-button{background-position:5px -270px}.trumbowyg-button-pane li button.trumbowyg-underline-button{background-position:5px -470px}.trumbowyg-button-pane li button.trumbowyg-strikethrough-button,.trumbowyg-button-pane li button.trumbowyg-del-button{background-position:5px -445px}.trumbowyg-button-pane li button.trumbowyg-link-button{background-position:5px -345px}.trumbowyg-button-pane li button.trumbowyg-insertImage-button{background-position:5px -245px}.trumbowyg-button-pane li button.trumbowyg-justifyLeft-button{background-position:5px -320px}.trumbowyg-button-pane li button.trumbowyg-justifyCenter-button{background-position:5px -70px}.trumbowyg-button-pane li button.trumbowyg-justifyRight-button{background-position:5px -395px}.trumbowyg-button-pane li button.trumbowyg-justifyFull-button{background-position:5px -295px}.trumbowyg-button-pane li button.trumbowyg-unorderedList-button{background-position:5px -495px}.trumbowyg-button-pane li button.trumbowyg-orderedList-button{background-position:5px -370px}.trumbowyg-button-pane li button.trumbowyg-horizontalRule-button{background-position:5px -220px}.trumbowyg-button-pane li button.trumbowyg-fullscreen-button{background-position:5px -170px}.trumbowyg-button-pane li button.trumbowyg-close-button{background-position:5px -95px}.trumbowyg-fullscreen .trumbowyg-button-pane li button.trumbowyg-fullscreen-button{background-position:5px -145px}.trumbowyg-button-pane li:first-child button{margin-left:6px}.trumbowyg-button-pane li:last-child button{margin-right:6px}.trumbowyg-fr .trumbowyg-button-pane li button.trumbowyg-bold-button,.trumbowyg-fr .trumbowyg-button-pane li button.trumbowyg-strong-button{background-position:5px -195px}.trumbowyg-fr .trumbowyg-button-pane li button.trumbowyg-underline-button{background-position:5px -420px}.trumbowyg-fr .trumbowyg-button-pane li button.trumbowyg-strikethrough-button,.trumbowyg-fr .trumbowyg-button-pane li button.trumbowyg-del-button{background-position:5px -20px}@media only screen and (-webkit-min-device-pixel-ratio: 1.3), only screen and (min--moz-device-pixel-ratio: 1.3), only screen and (-o-min-device-pixel-ratio: 4 / 3), only screen and (min-device-pixel-ratio: 1.3), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx){.trumbowyg-button-pane li button{background-size:72%;background-image:url('../images/icons-2x-s9034954e6d.png')}.trumbowyg-button-pane li button.trumbowyg-viewHTML-button{background-position:5px -545px}.trumbowyg-button-pane li button.trumbowyg-formatting-button{background-position:5px -120px}.trumbowyg-button-pane li button.trumbowyg-bold-button,.trumbowyg-button-pane li button.trumbowyg-strong-button{background-position:5px -45px}.trumbowyg-button-pane li button.trumbowyg-italic-button,.trumbowyg-button-pane li button.trumbowyg-em-button{background-position:5px -270px}.trumbowyg-button-pane li button.trumbowyg-underline-button{background-position:5px -470px}.trumbowyg-button-pane li button.trumbowyg-strikethrough-button,.trumbowyg-button-pane li button.trumbowyg-del-button{background-position:5px -445px}.trumbowyg-button-pane li button.trumbowyg-link-button{background-position:5px -345px}.trumbowyg-button-pane li button.trumbowyg-insertImage-button{background-position:5px -245px}.trumbowyg-button-pane li button.trumbowyg-justifyLeft-button{background-position:5px -320px}.trumbowyg-button-pane li button.trumbowyg-justifyCenter-button{background-position:5px -70px}.trumbowyg-button-pane li button.trumbowyg-justifyRight-button{background-position:5px -395px}.trumbowyg-button-pane li button.trumbowyg-justifyFull-button{background-position:5px -295px}.trumbowyg-button-pane li button.trumbowyg-unorderedList-button{background-position:5px -495px}.trumbowyg-button-pane li button.trumbowyg-orderedList-button{background-position:5px -370px}.trumbowyg-button-pane li button.trumbowyg-horizontalRule-button{background-position:5px -220px}.trumbowyg-button-pane li button.trumbowyg-fullscreen-button{background-position:5px -170px}.trumbowyg-button-pane li button.trumbowyg-close-button{background-position:5px -95px}.trumbowyg-fullscreen .trumbowyg-button-pane li a.trumbowyg-fullscreen-button{background-position:5px -145px}.trumbowyg-fr .trumbowyg-button-pane li button.trumbowyg-bold-button,.trumbowyg-fr .trumbowyg-button-pane li button.trumbowyg-strong-button{background-position:5px -195px}.trumbowyg-fr .trumbowyg-button-pane li button.trumbowyg-underline-button{background-position:5px -420px}.trumbowyg-fr .trumbowyg-button-pane li button.trumbowyg-strikethrough-button,.trumbowyg-fr .trumbowyg-button-pane li button.trumbowyg-del-button{background-position:5px -20px}}
html, body 
{
margin: 0;
padding: 0;
}
header 
{
text-align: center;
}
#main 
{
max-width: 960px;
margin: 0 auto;
}

trumbowyg.js

/* ===========================================================
 * trumbowyg.js v1.0
 * Core code of Trumbowyg plugin
 * http://alex-d.github.com/Trumbowyg
 * ===========================================================
 * Author : Alexandre Demode (Alex-D)
 *          Twitter : @AlexandreDemode
 *          Website : alex-d.fr
 */

$.trumbowyg = {
    langs: {
        en: {
            viewHTML:       "View HTML",

            formatting:     "Formatting",
            p:              "Paragraph",
            blockquote:     "Quote",
            code:           "Code",
            header:         "Header",

            bold:           "Bold",
            italic:         "Italic",
            strikethrough:  "Stroke",
            underline:      "Underline",

            strong:         "Strong",
            em:             "Emphasis",
            del:            "Deleted",

            unorderedList:  "Unordered list",
            orderedList:    "Ordered list",

            insertImage:    "Insert Image",
            insertVideo:    "Insert Video",
            link:           "Link",
            createLink:     "Insert link",
            unlink:         "Remove link",

            justifyLeft:    "Align Left",
            justifyCenter:  "Align Center",
            justifyRight:   "Align Right",
            justifyFull:    "Align Justify",

            horizontalRule: "Insert horizontal rule",

            fullscreen:     "fullscreen",

            close:          "Close",

            submit:         "Confirm",
            reset:          "Cancel",

            invalidUrl:     "Invalid URL",
            required:       "Required",
            description:    "Description",
            title:          "Title",
            text:           "Text"
        }
    },

    // User default options
    opts: {},

    btnsGrps: {
        design:     ['bold', 'italic', 'underline', 'strikethrough'],
        semantic:   ['strong', 'em', 'del'],
        justify:    ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull'],
        lists:      ['unorderedList', 'orderedList']
    }
};



(function($){
    $.fn.trumbowyg = function(opts, params){
        if($.isObject(opts) || opts == null){
            return this.each(function(){
                if(!$(this).data('trumbowyg'))
                    $(this).data('trumbowyg', new Trumbowyg(this, opts));
            });
        } else if(this.length == 1){
            try {
                var t = $(this).data('trumbowyg');
                switch(opts){
                    // Modal box
                    case 'openModal':
                        return t.openModal(params.title, params.content);
                    case 'closeModal':
                        return t.closeModal();
                    case 'openModalInsert':
                        return t.openModalInsert(params.title, params.fields, params.callback);

                    // Selection
                    case 'saveSelection':
                        return t.saveSelection();
                    case 'getSelection':
                        return t.selection;
                    case 'getSelectedText':
                        return t.selection+'';
                    case 'restoreSelection':
                        return t.restoreSelection();

                    // Destroy
                    case 'destroy':
                        return t.destroy();

                    // Empty
                    case 'empty':
                        return t.empty();

                    // Public options
                    case 'lang':
                        return t.lang;
                    case 'duration':
                        return t.o.duration;

                    // HTML
                    case 'html':
                        return t.html(params);
                }
            } catch(e){}
        }

        return false;
    };



    var Trumbowyg = function(editorElem, opts){
        // jQuery object of the editor
        this.$e       = $(editorElem);
        this.$creator = $(editorElem);

        // Extend with options
        opts = $.extend(true, {}, opts, $.trumbowyg.opts);

        // Localization management
        if(typeof opts.lang === 'undefined' || typeof $.trumbowyg.langs[opts.lang] === 'undefined')
            this.lang = $.trumbowyg.langs['en'];
        else
            this.lang = $.extend(true, {}, $.trumbowyg.langs['en'], $.trumbowyg.langs[opts.lang]);

        // Defaults Options
        this.o = $.extend(true, {
            lang: 'en',
            dir: 'ltr',
            duration: 200, // Duration of modal box animations

            mobile: false,
            tablet: true,
            closable: false,
            fullscreenable: true,
            fixedBtnPane: false,
            fixedFullWidth: false,
            semantic: false,
            resetCss: false,
            autogrow: false,

            prefix: 'trumbowyg-',

            convertLink: true,

            btns: ['viewHTML',
                        '|', 'formatting',
                        '|', $.trumbowyg.btnsGrps.design,
                        '|', 'link',
                        '|', 'insertImage',
                        '|', $.trumbowyg.btnsGrps.justify,
                        '|', $.trumbowyg.btnsGrps.lists,
                        '|', 'horizontalRule'],
            btnsAdd: [],

            /**
             * When the button is associated to a empty object
             * func and title attributs are defined from the button key value
             *
             * For example
             *      foo: {}
             * is equivalent to :
             *      foo: {
             *          func: 'foo',
             *          title: this.lang.foo
             *      }
             */
            btnsDef: {
                viewHTML: {
                    func: 'toggle'
                },

                p: {
                    func: 'formatBlock'
                },
                blockquote: {
                    func: 'formatBlock'
                },
                h1: {
                    func: 'formatBlock',
                    title: this.lang.header + ' 1'
                },
                h2: {
                    func: 'formatBlock',
                    title: this.lang.header + ' 2'
                },
                h3: {
                    func: 'formatBlock',
                    title: this.lang.header + ' 3'
                },
                h4: {
                    func: 'formatBlock',
                    title: this.lang.header + ' 4'
                },

                bold: {},
                italic: {},
                underline: {},
                strikethrough: {},

                strong: {
                    func: 'bold'
                },
                em: {
                    func: 'italic'
                },
                del: {
                    func: 'strikethrough'
                },

                createLink: {},
                unlink: {},

                insertImage: {},

                justifyLeft: {},
                justifyCenter: {},
                justifyRight: {},
                justifyFull: {},

                unorderedList: {
                    func: 'insertUnorderedList'
                },
                orderedList: {
                    func: 'insertOrderedList'
                },

                horizontalRule: {
                    func: 'insertHorizontalRule'
                },

                // Dropdowns
                formatting: {
                    dropdown: ['p', 'blockquote', 'h1', 'h2', 'h3', 'h4']
                },
                link:       {
                    dropdown: ['createLink', 'unlink']
                }
            }
        }, opts);

        if(this.o.semantic && !opts.btns)
            this.o.btns = [
                'viewHTML',
                '|', 'formatting',
                '|', $.trumbowyg.btnsGrps.semantic,
                '|', 'link',
                '|', 'insertImage',
                '|', $.trumbowyg.btnsGrps.justify,
                '|', $.trumbowyg.btnsGrps.lists,
                '|', 'horizontalRule'
            ];
        else if(opts && opts.btns)
            this.o.btns = opts.btns;

        this.init();
    }

    Trumbowyg.prototype = {
        init: function(){
            this.height = this.$e.css('height');

            if(this.isEnabled()){
                this.buildEditor(true);
                return;
            }

            this.buildEditor();
            this.buildBtnPane();

            this.fixedBtnPaneEvents();

            this.buildOverlay();
        },

        buildEditor: function(disable){
            if(disable === true){
                if(!this.$e.is('textarea')){
                    var textarea = this.buildTextarea().val(this.$e.val());
                    this.$e.hide().after(textarea);
                }
                return;
            }


            this.$box = $('<div/>', {
                'class': this.o.prefix + 'box ' + this.o.prefix + this.o.lang + ' trumbowyg'
            });

            this.isTextarea = true;
            if(this.$e.is('textarea'))
                this.$editor = $('<div/>');
            else {
                this.$editor = this.$e;
                this.$e = this.buildTextarea().val(this.$e.val());
                this.isTextarea = false;
            }

            this.$e.hide()
                   .addClass(this.o.prefix + 'textarea');

            var html = '';
            if(this.isTextarea){
                html = this.$e.val();
                this.$box.insertAfter(this.$e)
                         .append(this.$editor)
                         .append(this.$e);
            } else {
                html = this.$editor.html();
                this.$box.insertAfter(this.$editor)
                         .append(this.$e)
                         .append(this.$editor);
                this.syncCode();
            }

            this.$editor.addClass(this.o.prefix + 'editor')
                        .attr('contenteditable', true)
                        .attr('dir', this.o.dir)
                        .html(html);

            if(this.o.resetCss)
                this.$editor.addClass(this.o.prefix + 'reset-css');

            if(!this.o.autogrow){
                $.each([this.$editor, this.$e], $.proxy(function(i, $el){
                    $el.css({
                        overflow: 'auto'
                    });
                }, this));
            }

            if(this.o.semantic){
                this.$editor.html(
                    this.$editor.html()
                        .replace("<br>", "</p><p>")
                        .replace("&nsbp;", "")
                );
                this.semanticCode();
            }



            var that = this;
            this.$editor
            .on('dblclick', 'img', function(){
                var $img = $(this);
                that.openModalInsert(that.lang.insertImage, {
                    url: {
                        label: 'URL',
                        value: $img.attr('src'),
                        required: true
                    },
                    alt: {
                        label: 'description',
                        value: $img.attr('alt')
                    }
                }, function(values){
                    $img.attr('src', values['url']);
                    $img.attr('alt', values['alt']);
                });
                return false;
            })
            .on('keyup', function(e){
                that.semanticCode(false, e.which === 13);
            })
            .on('blur', function(){
                that.syncCode();
            });
        },


        // Build the Textarea which contain HTML generated code
        buildTextarea: function(){
            return $('<textarea/>', {
                'name': this.$e.attr('id'),
                'height': this.height
            });
        },


        // Build button pane, use o.btns and o.btnsAdd options
        buildBtnPane: function(){
            var t = this;
            if(t.o.btns === false) return;
            var pfx = t.o.prefix;

            t.$btnPane = $('<ul/>', {
                'class': pfx + 'button-pane'
            });

            $.each(t.o.btns.concat(t.o.btnsAdd), $.proxy(function(i, btn){
                // Managment of group of buttons
                try {
                    var b = btn.split('btnGrp-');
                    if(b[1] != undefined)
                        btn = $.trumbowyg.btnsGrps[b[1]];
                } catch(e){}

                if(!$.isArray(btn)) btn = [btn];
                $.each(btn, $.proxy(function(i, btn){
                    try { // Prevent buildBtn error
                        var $li = $('<li/>');

                        if(btn === '|') // It's a separator
                            $li.addClass(pfx + 'separator');
                        else if(t.isSupportedBtn(btn)){ // It's a supported button
                            if(btn === 'viewHTML')
                                $li.addClass(pfx + 'not-disable');
                            $li.append(t.buildBtn(btn));
                        }

                        t.$btnPane.append($li);
                    } catch(e){}
                }, t));
            }, t));


            // Build right li for fullscreen and close buttons
            var $liRight = $('<li/>', {
                'class': pfx + 'not-disable ' + pfx + 'buttons-right'
            });

            // Add the fullscreen button
            if(t.o.fullscreenable)
                $liRight
                    .append(t.buildRightBtn('fullscreen')
                    .on('click', $.proxy(function(e){
                        var cssClass = pfx + 'fullscreen';
                        t.$box.toggleClass(cssClass);
                        if(t.$box.hasClass(cssClass)){
                            $('body').css('overflow', 'hidden');
                            t.$box.css({
                                position: 'fixed',
                                top: 0,
                                left: 0,
                                 '100%',
                                margin: 0,
                                padding: 0,
                                zIndex: 99999
                            });
                            $([t.$editor, t.$e]).each(function(){
                                $(this).css({
                                    
                                    overflow: 'auto'
                                });
                            });
                            t.$btnPane.css('width', '100%');
                            $(".trumbowyg-fullscreen .editor").css("height",$(window).height()-65);
                        } else {
                            $('body').css('overflow', 'auto');
                            t.$box.removeAttr('style');
                            if(!t.o.autogrow){
                                h = t.height;
                                $([t.$editor, t.$e]).each(function(i, $el){
                                    $el.css('height', h);
                                });
                            }
                        }
                        $(window).trigger('scroll');
                    }, t)));

            // Build and add close button
            if(t.o.closable)
                $liRight
                    .append(t.buildRightBtn('close')
                    .on('click', $.proxy(function(e){
                        var cssClass = pfx + 'fullscreen';
                        if(t.$box.hasClass(cssClass))
                            $('body').css('overflow', 'auto');
                        t.destroy();
                    }, t)));


            // Add right li only if isn't empty
            if($liRight.not(':empty'))
                t.$btnPane.append($liRight);

            t.$box.prepend(t.$btnPane);
        },


        // Build a button and his action
        buildBtn: function(name){
            var pfx = this.o.prefix,
                btnDef = this.o.btnsDef[name],
                t = this,
                textDef = this.lang[name] || name.charAt(0).toUpperCase() + name.slice(1);

            var $btn = $('<button/>', {
                'type': 'button',
                'class': pfx + name +'-button' + (btnDef.ico ? ' '+ pfx + btnDef.ico +'-button' : ''),
                'text': btnDef.text || btnDef.title || textDef,
                'title': btnDef.title || btnDef.text || textDef,
                'mousedown': function(e){
                    if(!btnDef.dropdown || t.$box.find('.'+name+'-'+pfx + 'dropdown').is(':hidden'))
                        $('body').trigger('mousedown');

                    if(t.$btnPane.hasClass(pfx + 'disable')
                        && !$(this).parent().hasClass(pfx + 'not-disable'))
                        return false;

                    t.execCommand((btnDef.dropdown ? 'dropdown' : false) || btnDef.func || name,
                                     btnDef.param || name);

                    e.stopPropagation();
                    e.preventDefault();
                    return false;
                }
            });



            if(btnDef.dropdown){
                $btn.addClass(pfx + 'open-dropdown');
                var cssClass = pfx + 'dropdown';

                var dropdown = $('<div/>', {
                    'class': name + '-' + cssClass + ' ' + cssClass + ' ' + pfx + 'fixed-top'
                });
                for(var i = 0, c = btnDef.dropdown.length; i < c; i++){
                    if(t.o.btnsDef[btnDef.dropdown[i]] && t.isSupportedBtn(btnDef.dropdown[i]))
                        dropdown.append(t.buildSubBtn(btnDef.dropdown[i]));
                }
                this.$box.append(dropdown.hide());
            }

            return $btn;
        },
        // Build a button for dropdown menu
        buildSubBtn: function(name){
            var btnDef = this.o.btnsDef[name];
            return $('<button/>', {
                'type': 'button',
                'text': btnDef.text || btnDef.title || this.lang[name] || name,
                'mousedown': $.proxy(function(e){
                    $('body').trigger('mousedown');

                    this.execCommand(btnDef.func || name,
                                     btnDef.param || name);

                    e.stopPropagation();
                    e.preventDefault();
                    return false;
                }, this)
            });
        },
        // Build a button for right li
        buildRightBtn: function(name){
            return $('<button/>', {
                'type': 'button',
                'class': this.o.prefix + name+'-button',
                'title': this.lang[name],
                'text': this.lang[name]
            });
        },
        // Check if button is supported
        isSupportedBtn: function(btn){
            return typeof this.o.btnsDef[btn].isSupported !== 'function' || this.o.btnsDef[btn].isSupported()
        },

        // Build overlay for modal box
        buildOverlay: function(){
            return this.$overlay = $('<div/>', {
                'class': this.o.prefix + 'overlay'
            }).css({
                top: this.$btnPane.outerHeight(),
                height: (parseInt(this.$editor.outerHeight()) + 1) + 'px'
            }).appendTo(this.$box);
        },
        showOverlay: function(){
            $(window).trigger('scroll');
            this.$overlay.fadeIn(this.o.duration);
            this.$box.addClass(this.o.prefix + 'box-blur');
        },
        hideOverlay: function(){
            this.$overlay.fadeOut(this.o.duration/4);
            this.$box.removeClass(this.o.prefix + 'box-blur');
        },

        // Management of fixed button pane
        fixedBtnPaneEvents: function(){
            if(!this.o.fixedBtnPane)
                return;

            this.isFixed = false;

            $(window).on('scroll', $.proxy(function(e){
                if(!this.$box)
                    return;

                this.syncCode();

                var wScroll = $(window).scrollTop(),
                    offset = this.$box.offset().top + 1,
                    toFixed = (wScroll - offset > 0) && ((wScroll - offset - parseInt(this.height)) < 0);

                if(toFixed){
                    if(!this.isFixed){
                        this.isFixed = true;
                        this.$btnPane.css({
                            position: 'fixed',
                            top: 0,
                            left: (this.o.fixedFullWidth) ? '0' : 'auto',
                             (this.o.fixedFullWidth) ? '100%' : ((parseInt(this.$box.css('width'))-1) + 'px'),
                            zIndex: 7
                        });
                        this.$editor.css({ marginTop: this.$btnPane.css('height') });
                        this.$e.css({ marginTop: this.$btnPane.css('height') });
                    }

                    $('.' + this.o.prefix + 'fixed-top', this.$box).css({
                        position: this.o.fixedFullWidth ? 'fixed' : 'absolute',
                        top: this.o.fixedFullWidth ? this.$btnPane.outerHeight() : parseInt(this.$btnPane.outerHeight()) + (wScroll - offset) + 'px',
                        zIndex: 15
                    });
                } else if(this.isFixed) {
                    this.isFixed = false;
                    this.$btnPane.css({ position: 'relative' });
                    this.$editor.css({ marginTop: 0 });
                    this.$e.css({ marginTop: 0 });
                    $('.' + this.o.prefix + 'fixed-top', this.$box).css({
                        position: 'absolute',
                        top: this.$btnPane.outerHeight()
                    });
                }
            }, this));
        },



        // Destroy the editor
        destroy: function(){
            var html = this.html();

            if(this.isTextarea)
                this.$box.after(this.$e.css({height: this.height})
                                       .val(html)
                                       .removeClass(this.o.prefix + 'textarea')
                                       .show());
            else
                this.$box.after(this.$editor.css({height: this.height})
                                            .removeClass(this.o.prefix + 'editor')
                                            .attr('contenteditable', false)
                                            .html(html)
                                            .show());

            this.$box.remove();
            this.$creator.removeData('trumbowyg');
        },



        // Empty the editor
        empty: function(){
            this.$e.val('');
            this.syncCode(true);
        },



        // Function call when click on viewHTML button
        toggle: function(){
            this.semanticCode(false, true);
            this.$editor.toggle();
            this.$e.toggle();
            this.$btnPane.toggleClass(this.o.prefix + 'disable');
            this.$btnPane.find('.'+this.o.prefix + 'viewHTML-button').toggleClass(this.o.prefix + 'active');
        },

        // Open dropdown when click on a button which open that
        dropdown: function(name){
            var pfx = this.o.prefix;
            var $dropdown = this.$box.find('.'+name+'-'+pfx + 'dropdown'),
                $btn = this.$btnPane.find('.'+pfx+name+'-button');

            if($dropdown.is(':hidden')){
                $btn.addClass(this.o.prefix + 'active');

                $dropdown.css({
                    position: 'absolute',
                    top: this.$btnPane.outerHeight(),
                    left: (this.o.fixedFullWidth && this.isFixed) ? $btn.offset().left+'px' : ($btn.offset().left - this.$btnPane.offset().left)+'px'
                }).show();

                $(window).trigger('scroll');

                $('body').on('mousedown', $.proxy(function(e){
                    $('.' + pfx + 'dropdown').hide();
                    $('.' + pfx + 'active').removeClass(pfx + 'active');
                    $('body').off('mousedown');
                }, this));
            } else {
                $('body').trigger('mousedown');
            }
        },




        // HTML Code management
        html: function(html){
            if(html){
                this.$e.val(html);
                this.syncCode(true);
                return tbw;
            } else
                return this.$e.val();
        },
        syncCode: function(force){
            if(!force && this.$editor.is(':visible'))
                this.$e.val(this.$editor.html());
            else
                this.$editor.html(this.$e.val());

            if(this.o.autogrow){
                this.height = this.$editor.css('height');
                this.$e.css({ height: this.height });
            }
        },

        // Analyse and update to semantic code
        // @param force : force to sync code from textarea
        // @param full  : wrap text nodes in <p>
        semanticCode: function(force, full){
            this.syncCode(force);

            if(this.o.semantic){
                this.semanticTag('b', 'strong');
                this.semanticTag('i', 'em');
                this.semanticTag('strike', 'del');

                if(full){
                    // Wrap text nodes in p
                    this.$editor.contents()
                    .filter(function(){
                        // Only non-empty text nodes
                        return this.nodeType === 3 && $.trim(this.nodeValue).length > 0;
                    }).wrap('<p></p>').end()

                    // Remove all br
                    .filter("br").remove();

                    this.saveSelection();
                    this.semanticTag('div', 'p');
                    this.restoreSelection();
                }

                this.$e.val(this.$editor.html());
            }
        },
        semanticTag: function(oldTag, newTag){
            $(oldTag, this.$editor).each(function(){
                $(this).replaceWith(function(){ return '<'+newTag+'>' + $(this).html() + '</'+newTag+'>'; });
            });
        },


        // Function call when user click on « Insert Link »
        createLink: function(){
            var that = this;
            this.saveSelection();
            this.openModalInsert(this.lang.createLink, {
                url: {
                    label: 'URL',
                    value: 'http://',
                    required: true
                },
                title: {
                    label: this.lang.title,
                    value: this.selection
                },
                text: {
                    label: this.lang.text,
                    value: this.selection
                }
            }, function(values){
                that.execCommand('createLink', values['url']);
                var link = $(['a[href="', values['url'], '"]:not([title])'].join(''), that.$box);
                if($.trim(values['text']).length !== 0)
                    link.text(values['text']);

                if($.trim(values['title']).length !== 0)
                    link.attr('title', values['title']);

                return true;
            });
        },
        insertImage: function(){ //图片上传
            var that = this;
            this.saveSelection();
            this.openModalInsert(this.lang.insertImage, {
                url: {
                    label: 'URL',
                    value: '',
                    required: true
                },
                alt: {
                    label: 'description',
                    value: this.selection
                }
            }, function(values){
                that.execCommand('insertImage', values['url']);
                $(['img[src="', values['url'], '"]:not([alt])'].join(''), that.$box).attr('alt', values['alt']);
                return true;
            });
        },


        /*
         * Call method of trumbowyg if exist
         * else try to call anonymous function
         * and finaly native execCommand
         */
        execCommand: function(cmd, param){
            if(cmd != 'dropdown')
                this.$editor.focus();

            try {
                this[cmd](param);
            } catch(e){
                try {
                    cmd(param, this);
                } catch(e){
                    this.$editor.focus();
                    if(cmd == 'insertHorizontalRule')
                        param = null;

                    document.execCommand(cmd, false, param);
                }
            }
            this.syncCode();
        },
        formatBlock: function(param){
            if($.browser.msie)
                param = '<' + param + '>';

            document.execCommand('formatBlock', false, param);
        },


        // Open a modal box
        openModal: function(title, content){
            var pfx = this.o.prefix;

            // No open a modal box when exist other modal box
            if($('.' + pfx + 'modal-box', this.$box).size() > 0)
                return false;

            this.saveSelection();
            this.showOverlay();

            // Disable all btnPane btns
            this.$btnPane.addClass(pfx + 'disable');
            $('.' + pfx + 'not-disable', this.$btnPane)
                .not('.' + pfx + 'buttons-right')
                .removeClass(pfx + 'not-disable')
                .addClass(pfx + 'not-disable-old');


            // Build out of ModalBox, it's the mask for animations
            var $modal = $('<div/>', {
                'class': pfx + 'modal ' + pfx + 'fixed-top'
            }).css({
                top: (parseInt(this.$btnPane.css('height')) + 1) + 'px'
            }).appendTo(this.$box);

            // Click on overflay close modal by cancelling them
            this.$overlay.one('click', function(e){
                e.preventDefault();
                $modal.trigger(pfx + 'cancel');
            });


            $e = this.$editor;

            // Build the form
            $form = $('<form/>', {
                action: 'javascript:void(null);',
                html: content
            })
            .on('submit', function(e){
                e.preventDefault();
                $modal.trigger(pfx + 'confirm');
            })
            .on('reset', function(e){
                e.preventDefault();
                $modal.trigger(pfx + 'cancel');
            });


            // Build ModalBox and animate to show them
            var $modalBox = $('<div/>', {
                'class': pfx + 'modal-box',
                html: $form
            })
            .css({
                top:     '-' + parseInt(this.$btnPane.outerHeight()) + 'px',
                opacity: 0
            })
            .appendTo($modal)
            .animate({
                top:     0,
                opacity: 1
            }, this.o.duration / 2);


            // Append title
            $('<span/>', {
                text: title,
                'class': pfx + 'modal-title'
            }).prependTo($modalBox);


            // Focus in modal box
            $modalBox.find('input:first').focus();


            // Append Confirm and Cancel buttons
            this.buildModalBtn('submit', $modalBox);
            this.buildModalBtn('reset', $modalBox);


            $('body').trigger('scroll');

            return $modal;
        },
        buildModalBtn: function(name, modal){
            return $('<button/>', {
                'class': this.o.prefix + 'modal-button ' + this.o.prefix + 'modal-' + name,
                'type': name,
                'text': this.lang[name] || name
            }).appendTo(modal.find('form'));
        },
        // close current modal box
        closeModal: function(){
            var pfx = this.o.prefix;

            this.$btnPane.removeClass(pfx + 'disable');
            this.$overlay.off();

            $('.' + this.o.prefix + 'not-disable-old', this.$btnPane)
                .removeClass(pfx + 'not-disable-old')
                .addClass(pfx + 'not-disable');


            var that = this,
                $modalBox = $('.' + pfx + 'modal-box', this.$box);

            $modalBox.animate({
                top: '-' + $modalBox.css('height')
            }, this.o.duration/2, function(){
                $(this).parent().remove();
                that.hideOverlay();
            });
        },
        // Preformated build and management modal
        openModalInsert: function(title, fields, cmd){
            var html = '',
                pfx  = this.o.prefix;

            for(f in fields){
                var fd = fields[f];

                label = (fd.label == undefined)
                    ? (this.lang[f] ? this.lang[f] : f.charAt(0).toUpperCase() + f.slice(1))
                    : (this.lang[fd.label] ? this.lang[fd.label] : fd.label)
                ;

                if(fd.name == undefined)
                    fd.name = f;

                if(!fd.pattern && f == 'url'){
                    fd.pattern = /^(http|https)://([w~#!:.?+=&%@!-/]+)$/;
                    fd.patternError = this.lang.invalidUrl;
                }

                html += '<label><input type="'+(fd.type || 'text')+'" name="'+fd.name+'" value="'+(fd.value || '')+'"><span class="'+pfx+'input-infos"><span>'+label+'</span></span></label>';
            }
            var modBox = this.openModal(title, html),
                that = this;
            modBox
            .on(pfx + 'confirm', function(){
                var $form = $(this).find('form'),
                    valid  = true,
                    values = {};

                for(f in fields) {
                    var $field = $('input[name="'+f+'"]', $form);

                    values[f] = $field.val();

                    // Validate value
                    if(fields[f].required && (values[f] == null || values[f] == undefined || $.trim(values[f]) == "")) {
                        valid  = false;
                        that.addErrorOnModalField($field, that.lang.required);
                    } else if(fields[f].pattern && !fields[f].pattern.test(values[f])) {
                        valid  = false;
                        that.addErrorOnModalField($field, fields[f].patternError);
                    }
                }

                if(valid) {
                    that.restoreSelection();

                    if(cmd(values, fields)) {
                        that.syncCode();
                        that.closeModal();
                        modBox.off(pfx + 'confirm');
                    }
                }
            })
            .one(pfx + 'cancel', function(){
                modBox.off(pfx + 'confirm');
                that.closeModal();
                that.restoreSelection();
            });

            return modBox;
        },
        addErrorOnModalField: function($field, err){
            var $label = $field.parent(),
                pfx    = this.o.prefix;
            $label.addClass(pfx + 'input-error');
            $field.on('change keyup', function(){ $label.removeClass(pfx + 'input-error'); });
            $label.find('input+span').append('<span class="'+ pfx +'msg-error">'+ err +'</span>');
        },




        // Selection management
        saveSelection: function(){
            this.selection = null;
            if(window.getSelection){
                var sel = window.getSelection();
                if(sel.getRangeAt && sel.rangeCount)
                    this.selection = sel.getRangeAt(0);
            } else if(document.selection && document.selection.createRange){
                this.selection = document.selection.createRange();
            }
        },
        restoreSelection: function(){
            range = this.selection;
            if(range){
                if(window.getSelection){
                    var sel = window.getSelection();
                    sel.removeAllRanges();
                    sel.addRange(range);
                } else if(document.selection && range.select){
                    range.select();
                }
            }
        },



        // Return true if must enable Trumbowyg on this mobile device
        isEnabled: function(){
            var mobile = "iPhone|iPod|Android|BlackBerry|WindowssPhone|ZuneWP7";
            var exprTablet = new RegExp("(iPad|webOS)");
            var exprMobile = new RegExp("("+mobile+")");

            return (this.o.tablet === true && exprTablet.test(navigator.userAgent))
                    || (this.o.mobile === true && exprMobile.test(navigator.userAgent));
        }
    };

    /* isObject */
    var toString = Object.prototype.toString, hasOwnProp = Object.prototype.hasOwnProperty;
    $.isObject = function(obj) { if(toString.call(obj) !== "[object Object]") return false; var key; for(key in obj){} return !key || hasOwnProp.call(obj, key); };
    $.isString = function(str){ return typeof(str) === 'string' };
})(jQuery);


function del()
 {
    var element=document.getElementById("demoImage"); 
    if(element) 
     { 
        element.parentNode.removeChild(element); 
     } 
 }

function show_element(e)
 {  
    if(!e)
     {  
        var e = window.event;  
     }
    //获取事件点击元素  
    var targ = e.target;  
    //获取元素名称 
    var tname = targ.tagName;
    var oDiv=document.getElementById('odiv');
    if(tname=="IMG")
     {
        var scrollTop=Math.max(document.documentElement.scrollTop,document.body.scrollTop);
        oDiv.style.left=e.clientX+5+'px'; 
        oDiv.style.top=e.clientY+5+scrollTop+'px'; 
        oDiv.style.display="inline";
        targ.width=targ.width;
        var s=document.getElementById('demoImage');
        if(s!=null)
         {
            s.id="";
         }
        targ.id='demoImage'
     }else{
            var wait = setInterval(function(){
                if (oDiv != 0 && oDiv != null && oDiv != undefined) {
                    clearInterval(wait);
                    oDiv.style.display="none";
                }
            },50);
     }
 }

function tim(m)
 {
    var s=document.getElementById('demoImage');
    s.width=s.width+m;
    s.width=s.width;
 }

function sub(m)
 {
    var s=document.getElementById('demoImage');
    if(s!=null)
     {
        if(m!=0)
         {
            var t=s.width/10;
            while(t>0)
             {
                if(m==1)
                    setTimeout('tim(1)','50');
                else
                    setTimeout('tim(-1);','50');
                t=t-1;
            }
        }
        else
            s.width=-1;
        s.width=s.width;
    }
}
   
   
/* ===========================================================
 * zh_cn.js
 * Simplified Chinese translation for Trumbowyg
 * http://alex-d.github.com/Trumbowyg
 * ===========================================================
 * Author : Liu Kai (akai)
 *          Twitter : @akai404
 *          Github : https://github.com/akai
 */

$.trumbowyg.langs.zh_cn = {
    viewHTML:       "源代码",

    formatting:     "格式",
    p:              "段落",
    blockquote:     "引用",
    code:           "代码",
    header:         "标题",

    bold:           "加粗",
    italic:         "斜体",
    strikethrough:  "删除线",
    underline:      "下划线",

    strong:         "加粗",
    em:             "斜体",
    del:            "删除线",

    unorderedList:  "无序列表",
    orderedList:    "有序列表",

    image:          "图片",
    insertImage:    "网络图片",
    upload:         "本地上传", 
    uploadError:    "上传失败",
    insertVideo:    "插入视频",
    link:           "超链接",
    createLink:     "插入链接",
    unlink:         "取消链接",

    align:          "对齐方式",
    justifyLeft:    "居左对齐",
    justifyCenter:  "居中对齐",
    justifyRight:   "居右对齐",
    justifyFull:    "两端对齐",

    horizontalRule: "插入分隔线",

    fullscreen:     "全屏",

    close:          "关闭",

    submit:         "确定",
    reset:          "取消",

    invalidUrl:     "无效的 URL",
    required:       "必需的",
    description:    "描述",
    title:          "标题",
    text:           "文字"
}




$(function(){
    $.trumbowyg.btnsGrps.test = ['bold','italic','underline','link'];

    $('#customized-buttonpane').trumbowyg({
        lang: 'zh_cn',
        fixedBtnPane: true,
        btnsDef: {
            align: {
                dropdown: ['justifyLeft', 'justifyCenter', 'justifyRight', 'justifyFull'],
                ico: 'justifyLeft'
            },
            image: {
                dropdown: ['insertImage', 'upload'],
                ico: 'insertImage'
            }
        },
        btns: ['viewHTML',
            '|', 'formatting',
            '|', 'btnGrp-test',
            '|', 'align',
            '|', 'btnGrp-lists',
            '|', 'image']
    });

    $('.editor').on('dblclick', function(e){
        $(this).trumbowyg({
            lang: 'zh_cn',
            closable: false,
            fixedBtnPane: true
        });
    });
});

trumbowyg.upload.js

/* ===========================================================
 * trumbowyg.upload.js v1.0
 * Upload plugin for Trumbowyg
 * http://alex-d.github.com/Trumbowyg
 * ===========================================================
 * Author : Alexandre Demode (Alex-D)
 *          Twitter : @AlexandreDemode
 *          Website : alex-d.fr
 */

(function($){
    addXhrProgressEvent();

    $.extend(true, $.trumbowyg, {

        upload: {
            serverPath: urlcore + '/file/upload/batch'
        },

        opts: {
            btnsDef: {
                upload: {
                    func: function(params, tbw){
                        var file,
                            pfx = tbw.o.prefix;

                        var $modal = tbw.openModalInsert(
                            // Title
                            tbw.lang['upload'],

                            // Fields
                            {
                                file: {
                                    type: 'file',
                                    required: true
                                },
                                alt: {
                                    label: 'description'
                                }
                            },

                            // Callback
                            function(values, fields){
                                var data = new FormData();
                                data.append('files', file);

                                if($('.' + pfx +'progress', $modal).length == 0)
                                    $('.' + pfx + 'modal-title', $modal)
                                    .after(
                                        $('<div/>', {
                                            'class': pfx +'progress'
                                        })
                                        .append(
                                            $('<div/>', {
                                                'class': pfx +'progress-bar'
                                            })
                                        )
                                    );

                                $.ajax({
                                    url:            $.trumbowyg.upload.serverPath,
                                    type:           'POST',
                                    data:           data,
                                    cache:          false,
                                    dataType:       'json',
                                    processData:    false,
                                    contentType:    false,

                                    progressUpload: function(e){
                                        $('.' + pfx + 'progress').html(
                                            '<div class="trumbowyg-progress-bar" style="overflow: hidden;  '+e.loaded * 100 / e.total+'%;"></div>'+
                                            parseInt(e.loaded * 100 / e.total) + '%'
                                        );
                                    },

                                    success: function(data){
                                        if (data.success == true) {
                                            for(var i in data.data){
                                                tbw.execCommand('insertImage', data.data[i]);
                                            }
                                            setTimeout(function(){
                                                tbw.closeModal();
                                            }, 250);
                                        } else {
                                            tbw.addErrorOnModalField(
                                                $('input[type=file]', $modal),
                                                tbw.lang[data.message]
                                            );
                                        }
                                    },
                                    error: function(data){
                                        tbw.addErrorOnModalField(
                                            $('input[type=file]', $modal),
                                            tbw.lang['uploadError']
                                        );
                                    }
                                });
                            }
                        );

                        $('input[type=file]').on('change', function(e){
                            file = e.target.files[0];
                        });
                    }
                }
            }
        }
    });


    function addXhrProgressEvent(){
        var originalXhr = $.ajaxSettings.xhr;

        $.ajaxSetup({
            xhr: function() {
                var req  = originalXhr(),
                    that = this;

                if(req && typeof req.upload == "object" && that.progressUpload !== undefined)
                    req.upload.addEventListener("progress", function(e){
                        that.progressUpload(e);
                    }, false);

                return req;
            }
        });
    }
})(jQuery);

附件下载地址(包含图标和js): http://files.cnblogs.com/files/007sx/assets.zip

原文地址:https://www.cnblogs.com/007sx/p/6222197.html