sourcecode.js 7.41 KB
define('sourcecode', ['htmlEditor', 'dataModel', 'mec', 'modal', 'appdesigner/constants', 'jquery'], function (h, dataModel, mec, modal, constants) {
    var tmpl = '\
<div class="ad-sourcecode css">\
    <ul class="nav nav-tabs">\
        <li class="tab active" data-tab="css"><a href="javascript:void(0);">Css</a></li>\
        <li class="tab" data-tab="javascript"><a href="javascript:void(0);">Javascript</a></li>\
        <li class="tab" data-tab="plugin"><a href="javascript:void(0);">'+ constants.PLUGIN + '</a></li>\
    </ul>\
    <div class="sc-panels">\
        <div class="tab-panel active" data-rel="css"></div>\
        <div class="tab-panel" data-rel="javascript"><iframe src="about:blank" /></div>\
        <div class="tab-panel" data-rel="plugin"></div>\
    </div>\
    <div class="css-help">?</div>\
    <div class="js-help">?</div>\
</div>', jsHelpTmpl = '\
    <ul class="sourcecode-help">\
        <li><span>'+ constants.PRECAUTIONS_TIP_1 + '</span></li>\
        <li><span>'+ constants.PRECAUTIONS_TIP_2 + '<br>window.a = function () { ... };</span></li>\
        <li><span>'+ constants.PRECAUTIONS_TIP_4 + '<br/> $load(function(){<br/> &nbsp;&nbsp;&nbsp;&nbsp;...<br/> });<br/>\
        <span class="warn">* </span>'+ constants.PRECAUTIONS_TIP_3 + '\
        </span></li>\
    </ul>\
', cssHelpTmpl = '\
<ul class="sourcecode-help">\
<li><span>'+ constants.PRECAUTIONS_CSS_TIP_1 + ' <span style="color:red;">var(--themeColor)</span> '+ constants.LIKE + '<br/> div {<br/> &nbsp;&nbsp;&nbsp;&nbsp;background-color : var(--themeColor);<br/> }</span></li>\
<li><span>'+ constants.PRECAUTIONS_CSS_TIP_2 + ' <span style="color:red;">var(--hd)</span> '+ constants.LIKE + '<br/> div {<br/> &nbsp;&nbsp;&nbsp;&nbsp;font-size : calc(14px * var(--hd));<br/> }</span></li>\
</ul>\
';
    var defer = $.Deferred();
    var def = {
        css: "/*\n  " + constants.WRITE_CSS_TIP+" \n*/",
        javascript: "/*\n  " + constants.WRITE_JS_TIP +" \n*/"
    };

    function Editor(el, mode) {
        return h.editor(el, mode);
    }

    function SourceCode(settings) {
        var $container = $(settings.container || "body");
        var $sourcecode = $container.find(".ad-sourcecode"), editor;

        if ($sourcecode.length) return;

        this.render($container);
        this.renderEditor();
    }

    SourceCode.prototype = {
        render: function ($container) {
            var sc = this;
            var $sourcecode = $(tmpl);

            $sourcecode.on("click", ".tab", function () {
                var $tab = $(this),
                    tab = $tab.data("tab");
                var $panel = $sourcecode.find("[data-rel=" + tab + "]");
                var _toggle = function ($el) {
                    $el.addClass("active").siblings(".active").removeClass("active");
                };
                var isjavascript = tab === "javascript";
                var iscss = tab === "css";
                

                if ($tab.hasClass("active")) return;

                _toggle($tab);
                _toggle($panel);

                $sourcecode.toggleClass("javascript", isjavascript);
                $sourcecode.toggleClass("css", iscss);

                var currEditor = $panel.data("editor");

                if (!currEditor) return;

                if (isjavascript) return currEditor.focus();

                currEditor.setValue(currEditor.getValue(), true);
                currEditor.focus();
            });

            $container.append($sourcecode);

            this.$el = $sourcecode;

            $("body").on("mousedown.contextmenu", function () {
                var doc = $sourcecode.find("iframe")[0].contentWindow.document;
                var $contextmenu = $(doc).find(".context-menu");

                if (!$contextmenu.length) return;

                $contextmenu[0].contextmenu.toggle(false);
            });
            $sourcecode.find(".js-help").on("click", function () {
                modal.open({
                    title: constants.PRECAUTIONS,
                    content: jsHelpTmpl,
                    area: ["760px", "360px"],
                    btn: false
                });
            });
            $sourcecode.find(".css-help").on("click", function () {
                modal.open({
                    title: constants.PRECAUTIONS,
                    content: cssHelpTmpl,
                    area: ["760px", "360px"],
                    btn: false
                });
            });
        },
        renderEditor: function () {
            var sc = this;
            var $sourcecode = this.$el;
            var $css = $sourcecode.find("[data-rel='css']"),
                $plugin = $sourcecode.find("[data-rel='plugin']");

            this.cssEditor = new Editor($css[0], 'css');
            this.htmlEditor = new Editor($plugin[0], 'html');

            $css.data("editor", this.cssEditor);
            $plugin.data("editor", this.htmlEditor);
            this.htmlEditor.setReadOnly(true);
            this.renderJsEditor();
        },
        renderJsEditor: function () {
            var sc = this;
            var $sourcecode = this.$el,
                $javascript = $sourcecode.find("[data-rel='javascript']");

            defer = $.Deferred();
            $sourcecode.find("iframe").attr("src", this.getIframeUrl())
                .one("load", function () {
                    defer.resolve();
                        sc.getJSEditor(function (editor) {
                            $javascript.data("editor", editor);
                        });
                    });
        },
        getIframeUrl: function () {
            var appid = dataModel.get("appid"),
                appHomepageId = dataModel.get("appHomepageId");
            return "/mobilemode/admin/dialog/scriptlib/ScriptCenter.jsp?appid=" + appid +
                "&appHomepageId=" + appHomepageId + "&noTitle=false&topMenu=true";
        },
        getJSEditor: function (cb) {
            var iframe = this.$el.find("iframe")[0];

            defer.then(function () { // 确保能够获取到jsEditor
                iframe.contentWindow.getEditor(cb);
            });
        },
        setValue: function (code) {
            var d = $.Deferred();

            if (!code) return d.resolve();
            
            this.htmlEditor.setValue(code.html, true);
            this.htmlEditor.resize();
            this.cssEditor.setValue(code.css.trim() || def.css, true);
            this.cssEditor.resize();
            this.getJSEditor(function (jsEditor, contentWin) {
                jsEditor.setValue(code.js || def.javascript, true);
                jsEditor.resize();
                contentWin.renderRightMenu();
                d.resolve();
            });

            return d;
        },
        getValue: function () {
            var cssCode = this.cssEditor.getValue();
            var d = $.Deferred();

            this.getJSEditor(function (jsEditor) {
                var jsCode = jsEditor.getValue();

                if (jsCode === def.javascript) {
                    jsCode = "";
                }

                d.resolve({
                    css: cssCode,
                    js: jsCode 
                });
            });

            return d;
        },
        focus: function () {
            var $sourcecode = this.$el;
            var editor = $sourcecode.find(".tab-panel.active").data("editor");

            editor && editor.focus();
        }
    };

    return {
        init: function (settings) {
            return new SourceCode(settings);
        }
    };
});