UNPKG

zx-editor

Version:

ZxEditor is a HTML5 rich text editor

404 lines (371 loc) 10.3 kB
/** * Created by zx1984 7/21/2018 * https://github.com/zx1984 */ 'use strict'; // 实例化 ZxEditor var zxEditor = new ZxEditor('#editorContainer', { // 顶部偏移距离 // demo有顶部导航栏,高度44 top: 44, // 编辑框左右边距 padding: 13 }); // 底部工具栏添加一个“导语”按钮 zxEditor.addFooterButton({ name: 'summary', // 按钮外容器样式 class: 'demo-summary-button', // 按钮内i元素样式名 icon: '', // 需要注册的监听事件名 on: 'summary-button' }) var zxDebug = new ZxDebug({ position: 'top', offset: 100 }); // 监听编辑器处理通知 zxEditor.on('debug', function () { zxDebug.log.apply(zxDebug, arguments) }) zxEditor.on('message', function () { zxDebug.log.apply(zxDebug, arguments) }) zxEditor.on('error', function () { zxDebug.error.apply(zxDebug, arguments) }) var $ = zxEditor.query || function (selector, context) { return (context || document).querySelector(selector) } // 获取body元素 var $docBody = $('body'); // 封面图元素 var $coverPic = $('.cover-wrapper img'); // 标题summary是否显示 var summaryShow = false; // 标题栏子元素集(.placeholder, .input-hook) var $titleItems = null; // 摘要,导语栏子元素集(.placeholder, .input-hook) var $summaryItems = null; // 预览容器 var $previewWrapper = $('.article-preview-wrapper'); // 封面图栏 handleCoverWrapper(); // 标题栏 handlePlaceholderInputWrapper('.title-wrapper'); // 导语摘要栏 handlePlaceholderInputWrapper('.summary-wrapper'); // 初始化容器高度 initHeight(); // 初始化本地存储的数据 initLoaclData(); function initLoaclData () { var data = zxEditor.storage.get('article') if (data) { if (data.cover) { zxEditor.addClass('has-pic', $('.cover')); $coverPic.setAttribute('src', data.cover); } if (data.title) { $titleItems[0].style.display = 'none' $titleItems[1].style.display = '' $titleItems[1].innerText = data.title } if (data.summary) { summaryShow = true; $('.summary-wrapper').style.display = ''; $summaryItems[0].style.display = 'none' $summaryItems[1].style.display = '' $summaryItems[1].innerText = data.summary } zxEditor.setContent(data.content); } } /** * 预览 */ function handlePreviewClick () { // 获取文章数据 var data = getArticleData(); // 保存文章数据 zxEditor.storage.set('article', data) if (!data) { zxEditor.dialog.alert('还未添加任何内容!'); return; } // 判断内容是否完善 if (!data.cover) { zxEditor.dialog.alert('请添加文章封面'); return } if (!data.title) { zxEditor.dialog.alert('请添加文章标题'); return } if (!data.content || data.content === '<p><br></p>') { zxEditor.dialog.alert('请添加文章内容'); return } // 将数据添加到预览容器中 $('.preview-cover img', $previewWrapper).src = data.cover; $('.preview-title', $previewWrapper).innerText = data.title; var $summay = $('.preview-summary', $previewWrapper); if (data.summary) { // 显示摘要 $summay.style.display = ''; // 填充摘要(导语)内容 $summay.innerText = data.summary; } else { // 隐藏摘要 $summay.style.display = 'none'; } // 填充正文内容 $('.preveiw-content', $previewWrapper).innerHTML = data.content; $previewWrapper.style.transform = 'translateX(0)'; // 禁止body滚动 zxEditor.lock($docBody); } /** * 点击继续编辑 */ function handleBackPreviewClick () { $previewWrapper.style.transform = 'translateX(100%)'; // 接触body滚动限制 zxEditor.unlock($docBody); } function handleBackClick () { zxEditor.dialog.alert('点击了返回按钮'); } /** * 提交数据 */ function handleSubmitClick () { // 获取文章数据 var data = getArticleData() || {}; // 显示loading zxEditor.dialog.loading(); // 上传图片数据 // 上传封面图省略... // 处理正文中的base64图片 // 获取正文中的base64数据数组 var base64Images = zxEditor.getBase64Images(); // 上传base64图片数据 uploadBase64Images(base64Images, function () { // 正文中有base64数据,上传替换成功后再重新获取正文内容 if (base64Images.length) { data.content = zxEditor.getContent(); } // 填充预览正文内容 $('.preveiw-content', $previewWrapper).innerHTML = data.content; // 需要提交的数据 zxDebug.log('提交的数据', data); // 防止提交失败,再保存一次base64图片上传后的文章数据 zxEditor.storage.set('article', data) // 发送至服务器 // ... // end zxEditor.dialog.removeLoading(); zxEditor.dialog.alert('文章模拟发布成功!', function () { // 文章发布成功 // 清除本地存储的文章数据 zxEditor.storage.remove('article') // 其他操作 // ... location.reload() }) }) } /** * 获取文章数据 * @returns {{}} */ function getArticleData () { var data = { cover: $coverPic.getAttribute('src'), title: $titleItems[1].innerText, summary: $summaryItems[1].innerText, // 获取正文内容 content: zxEditor.getContent() } return (!data.cover && !data.summary && !data.title && (!data.content || data.content === '<p><br></p>')) ? null : data; } /** * 初始化容器高度 * editor, preview body */ function initHeight () { // 窗口高度 var winHeight = window.innerHeight; var headerHeight = 44; // 编辑器 var $editorContent = zxEditor.$content; var contentTop = $editorContent.getBoundingClientRect().top; $editorContent.style.minHeight = winHeight - contentTop - zxEditor.toolbarHeight + 'px'; // $previewWrapper $('.preview-wrapper').style.height = winHeight - headerHeight + 'px'; } /** * 点击链接按钮 */ zxEditor.on('add-link', function (next) { zxEditor.dialog.alert('可以调用原生接口,获取剪切板url数据', function () { // 获取原生链接 next('http://192.168.5.8:81/index.php?s=/12&page_id=1151', '这是一个测试连接地址,如果文字很长会自动省略'); }) }) // 点击导语按钮 zxEditor.on('summary-button', function (prams) { zxDebug.log('click summary-button', prams) summaryShow = !summaryShow; $('.summary-wrapper').style.display = summaryShow ? '' : 'none'; }) /** * 数据处理,并提交数据处理 */ function uploadBase64Images (base64Images, callback) { var len = base64Images.length; var count = 0; if (len === 0) { callback() return } for (var i = 0; i < len; i++) { _uploadHandler(base64Images[i]); } function _uploadHandler (data) { upload(data.blob, function (url) { // 替换正文中的base64图片 zxEditor.setImageSrc(data.id, url) // 计算图片是否上传完成 _handleCount(); }) } function _handleCount () { count++ if (count === len) { callback() } } } // 模拟文件上传 function upload (blob, callback) { setTimeout(function () { callback('https://photo.tuchong.com/1000000/f/305463584.jpg'); }, 500) } /** * ********************************* * 封面图 * ********************************* */ function handleCoverWrapper () { // 目标图片尺寸参数,强制裁剪 var imageParams = { width: 750, height: 422, clip: true } // 封面容器 var $cover = $('.cover-wrapper .cover'); var $input = $('.cover-wrapper input'); var $img = zxEditor.query('img', $cover); // 点击封面容器处理 zxEditor.addEvent($cover, 'click', function (e) { zxDebug.log('coverClickHandler', e) var oldSrc = $img.src; console.log(oldSrc); $input.click(); }); // 选中图片文件 zxEditor.addEvent($input, 'change', function (e) { // 添加loading zxEditor.dialog.loading('图片处理中...'); var files = this.files; // 处理图片数据(file数据转base64,blobData) zxEditor.filesToBase64(files, imageParams, function (err, res) { zxEditor.dialog.removeLoading(); if (err) { zxEditor.dialog.alert(err[0].message || '图片处理错误!') } if (res) { $img.src = res[0].base64; zxEditor.addClass('has-pic', $cover); } }) }); } /** * ********************************* * 标题容器 * ********************************* */ /** * 处理标题、摘要placeholder/input切换 */ function handlePlaceholderInputWrapper (selector) { var $wrapper = $(selector); var $items = zxEditor.queryAll('.item', $wrapper); // 输入最大长度 var maxLength = 30; if ($items.length === 0) return; if (selector === '.title-wrapper') { $titleItems = $items; } else if (selector === '.summary-wrapper') { $summaryItems = $items; maxLength = 140; } zxEditor.addEvent($items[0], 'click', _placeholderClikHandler, false); zxEditor.addEvent($items[1], 'blur', _inputHookHandler, false) // 输入内容限制 zxEditor.addEvent($items[1], 'keyup', function (e) { var text = this.innerText; if (text && text.length >= maxLength) { if (e.keyCode !== 8) { e.preventDefault(); } else { this.innerText = text.substr(0, maxLength); } } }) } /** * 点击标题、摘要placeholder处理程序 * @private */ function _placeholderClikHandler (e) { var $currentElm = e.currentTarget; if (zxEditor.hasClass('placeholder', $currentElm)) { this.style.display = 'none'; var $inputHook; if ($currentElm === $titleItems[0]) { $inputHook = $titleItems[1]; } else if ($currentElm === $summaryItems[0]) { $inputHook = $summaryItems[1]; } if (!$inputHook) return; $inputHook.style.display = ''; $inputHook.focus(); } } /** * 点击标题、摘要输入框处理程序 * @private */ function _inputHookHandler (e) { var $currentElm = e.currentTarget; var $placeholder; if ($currentElm === $titleItems[1]) { $placeholder = $titleItems[0]; } else if ($currentElm === $summaryItems[1]) { $placeholder = $summaryItems[0]; } if (!$placeholder) return; var text = $currentElm.innerText; if (!text) { $placeholder.style.display = ''; $currentElm.style.display = 'none'; } }