UNPKG

c-mdui-a

Version:

A fast way to build an application based on Material Design UI(MDUI).

515 lines (431 loc) 12.1 kB
/*! * LiveEditor (https://www.mdui.org) * Copyright 2016-2016 zdhxiong */ var LiveEditor = (function () { 'use strict'; var $ = {}; /** * 是否是数组 * @param arr * @returns {boolean} */ $.isArray = function (arr) { return Object.prototype.toString.apply(arr) === '[object Array]'; }; /** * nodeList 转换为数组 * @param nodeList * @returns {Array} */ $.toArray = function (nodeList) { var i; var arr = []; for (i = 0; i < nodeList.length; i++) { if (nodeList[i]) { arr.push(nodeList[i]); } } return arr; }; /** * 循环数组或对象 * @param obj * @param callback */ $.each = function (obj, callback) { var i; var prop; if (!obj) { return; } if ($.isArray(obj)) { // Array for (i = 0; i < obj.length; i++) { if (callback(i, obj[i]) === false) { break; } } } else { // Object for (prop in obj) { if (obj.hasOwnProperty(prop)) { if (callback(prop, obj[prop]) === false) { break; } } } } }; /** * 函数节流 * @param fn * @param delay * @returns {Function} */ $.throttle = function (fn, delay) { var timer = null; return function () { var _this = this; var args = arguments; if (timer === null) { timer = setTimeout(function () { fn.apply(_this, args); timer = null; }, delay); } }; }; /** * 发送 ajax 请求 * @param data */ $.ajax = function(data) { if (typeof data === "object") { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState === 4 && xmlhttp.status === 200) { data.success(xmlhttp); } }; xmlhttp.open(data.type, data.url, false); xmlhttp.send(); } }; // DOM 元素缓存 var dom = { controlsDrag: document.querySelector('.editor-controls-drag'), preview: document.querySelector('.preview-container'), panel: document.querySelector('.editor-panel'), controls: document.querySelector('.editor-controls'), editorContainers: document.querySelectorAll('.editor-container'), editorContainerHTML: document.querySelector('.editor-container-html'), editorContainerCSS: document.querySelector('.editor-container-css'), editorContainerJS: document.querySelector('.editor-container-js'), controlHTML: document.querySelector('.editor-control-html'), controlCSS: document.querySelector('.editor-control-css'), controlJS: document.querySelector('.editor-control-js'), controlLiveMode: document.querySelector('.editor-controls-live-mode input[type="checkbox"]'), }; // 编辑器 var editor = { html: ace.edit('editor-ace-html'), css: ace.edit('editor-ace-css'), js: ace.edit('editor-ace-js'), }; var editors = [ { inst: editor.html, mode: 'html' }, { inst: editor.css, mode: 'css' }, { inst: editor.js, mode: 'javascript' } ]; /** * 编辑器 * @constructor */ function LiveEditor () { var _this = this; ace.require("ace/ext/language_tools"); _this.init(); } /** * 初始化 */ LiveEditor.prototype.init = function () { var _this = this; _this.resizePanel(); // 初始化编辑器 $.each(editors, function (i, editor) { editor.inst.setTheme('ace/theme/chrome'); editor.inst.getSession().setMode('ace/mode/' + editor.mode); editor.inst.getSession().setTabSize(2); // 缩进两个字符 editor.inst.getSession().setUseSoftTabs(true); // 使用空格缩进 editor.inst.setOptions({ enableBasicAutocompletion: true, enableSnippets: true, enableLiveAutocompletion: true, }); editor.inst.setShowPrintMargin(false); // 不显示打印线 editor.inst.setFontSize(14); // 字体 14px editor.inst.renderer.setShowGutter(false); // 不显示行号 editor.inst.resize(true); }); _this.hotkey(); _this.isShowHTML = true; _this.isShowCSS = true; _this.isShowJS = true; // 编辑器显示状态 if (dom.controlHTML.classList.contains('editor-control-active')) { _this.showHTML(); } else { _this.hideHTML(); } if (dom.controlCSS.classList.contains('editor-control-active')) { _this.showCSS(); } else { _this.hideCSS(); } if (dom.controlJS.classList.contains('editor-control-active')) { _this.showJS(); } else { _this.hideJS(); } // Live Mode _this.isLiveMode = dom.controlLiveMode.checked; _this.liveMode(); // 绑定面板拖动事件 _this.resizePanelEvent(); window.addEventListener('resize', function () { _this.resizePanel(); }); _this.run(); }; /** * 绑定快捷键 */ LiveEditor.prototype.hotkey = function () { var _this = this; // Ctrl + enter 运行 document.addEventListener('keydown', function (e) { e = e || window.event; var keyCode = e.keyCode || e.charCode; if (keyCode === 13 && e.ctrlKey) { _this.run(); } }); }; /** * 设置或取消 LiveMode */ LiveEditor.prototype.liveMode = function () { var _this = this; $.each(editors, function (i, editor) { editor.inst.on('change', $.throttle(function () { if (_this.isLiveMode) { _this.run(); } }, 500)); }); }; /** * 修改面板高度 * @param Top 面板距离页面顶部的距离 */ LiveEditor.prototype.resizePanel = function (Top) { var _this = this; if (typeof Top === 'undefined') { // 在小屏幕设备上隐藏面板 if (window.innerWidth < 600) { dom.preview.style.height = document.body.offsetHeight + 'px'; dom.panel.style.display = 'none'; return; } Top = document.body.offsetHeight / 2; } var previewHeight = Top; var panelHeight = document.body.offsetHeight - Top; var controlsHeight = dom.controls.offsetHeight; dom.preview.style.height = previewHeight + 'px'; dom.panel.style.display = 'block'; dom.panel.style.height = panelHeight + 'px'; $.each(dom.editorContainers, function (i, editorContainer) { editorContainer.style.height = panelHeight - controlsHeight + 'px'; }); $.each(editors, function (e, editor) { editor.inst.resize(); }); }; /** * 绑定拖拽面板高度事件 */ LiveEditor.prototype.resizePanelEvent = function () { var _this = this; dom.controlsDrag.onmousedown = function (e) { var panelTopOrigin = dom.panel.offsetTop; var tempHeight = e.clientY - panelTopOrigin; document.onmousemove = function (e) { e.preventDefault(); var mouseTop = e.clientY; var Top = mouseTop - tempHeight; // 避免面板超出页面可见区域 if (Top + dom.controls.offsetHeight + 40 < document.body.offsetHeight && Top >= 0) { _this.resizePanel(Top); } }; document.onmouseup = function (e) { document.onmousemove = null; }; }; }; /** * 设置编辑器的宽度 * @param width * @private */ LiveEditor.prototype._setEditorWidth = function (width) { dom.editorContainerHTML.style.width = dom.editorContainerCSS.style.width = dom.editorContainerJS.style.width = width; }; /** * 调整编辑器的宽度 */ LiveEditor.prototype.resizeEditor = function () { var _this = this; var showCount = 0; _this.isShowHTML && showCount++; _this.isShowCSS && showCount++; _this.isShowJS && showCount++; if (showCount === 3) { _this._setEditorWidth('33.333333%'); } else if (showCount === 2) { _this._setEditorWidth('50%'); } else if (showCount === 1) { _this._setEditorWidth('100%'); } _this.isShowHTML && editor.html.resize(); _this.isShowCSS && editor.css.resize(); _this.isShowJS && editor.js.resize(); }; /** * 显示 HTML 编辑器 */ LiveEditor.prototype.showHTML = function () { var _this = this; dom.controlHTML.classList.add('editor-control-active'); dom.editorContainerHTML.style.display = 'block'; editor.html.resize(); _this.isShowHTML = true; _this.resizeEditor(); }; /** * 隐藏 HTML 编辑器 */ LiveEditor.prototype.hideHTML = function () { var _this = this; dom.controlHTML.classList.remove('editor-control-active'); dom.editorContainerHTML.style.display = 'none'; _this.isShowHTML = false; _this.resizeEditor(); }; /** * 切换 HTML 编辑器 */ LiveEditor.prototype.toogleHTML = function () { var _this = this; if (dom.controlHTML.classList.contains('editor-control-active')) { _this.hideHTML(); } else { _this.showHTML(); } }; /** * 显示 CSS 编辑器 */ LiveEditor.prototype.showCSS = function () { var _this = this; dom.controlCSS.classList.add('editor-control-active'); dom.editorContainerCSS.style.display = 'block'; editor.css.resize(); _this.isShowCSS = true; _this.resizeEditor(); }; /** * 隐藏 CSS 编辑器 */ LiveEditor.prototype.hideCSS = function () { var _this = this; dom.controlCSS.classList.remove('editor-control-active'); dom.editorContainerCSS.style.display = 'none'; _this.isShowCSS = false; _this.resizeEditor(); }; /** * 切换 CSS 编辑器 */ LiveEditor.prototype.toogleCSS = function () { var _this = this; if (dom.controlCSS.classList.contains('editor-control-active')) { _this.hideCSS(); } else { _this.showCSS(); } }; /** * 显示 JS 编辑器 */ LiveEditor.prototype.showJS = function () { var _this = this; dom.controlJS.classList.add('editor-control-active'); dom.editorContainerJS.style.display = 'block'; editor.js.resize(); _this.isShowJS = true; _this.resizeEditor(); }; /** * 隐藏 JS 编辑器 */ LiveEditor.prototype.hideJS = function () { var _this = this; dom.controlJS.classList.remove('editor-control-active'); dom.editorContainerJS.style.display = 'none'; _this.isShowJS = false; _this.resizeEditor(); }; /** * 切换 JS 编辑器 */ LiveEditor.prototype.toogleJS = function () { var _this = this; if (dom.controlJS.classList.contains('editor-control-active')) { _this.hideJS(); } else { _this.showJS(); } }; /** * Live Mode 切换 */ LiveEditor.prototype.toogleLiveMode = function () { var _this = this; dom.controlLiveMode.checked = _this.isLiveMode = !_this.isLiveMode; _this.liveMode(); }; /** * 运行代码 */ LiveEditor.prototype.run = function () { var _this = this; var html = editor.html.getValue(); var css = editor.css.getValue(); var js = editor.js.getValue(); // 移除旧的 iframe var iframeEle = document.getElementById('preview-iframe'); if (iframeEle) { iframeEle.parentNode.removeChild(iframeEle); } // 添加新的 iframe var tempParent = document.createElement('div'); tempParent.innerHTML = '<iframe id="preview-iframe" sandbox="allow-modals allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts" name="iframe" frameborder="0"></iframe>'; iframeEle = $.toArray(tempParent.childNodes)[0]; dom.preview.appendChild(iframeEle); var iframe = iframeEle.contentDocument || iframeEle.contentWindow.document; iframe.open(); iframe.write(html + '<style>' + css + '</style>' + '<script>' + js + '</script>'); iframe.close(); }; /** * 下载代码 */ LiveEditor.prototype.download = function () { }; return LiveEditor; })();