|
|

楼主 |
发表于 2023-12-9 09:44
|
显示全部楼层
三、JS(xd_editor.js)
- (function() {
- let xdForm = document.querySelector('form');
- if(!xdForm) return false;
- /* 创建界面 */
- let xdEditor = document.createElement('div');
- let picData = 'data:image/gif;base64,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';
- xdEditor.id = 'ed_outer';
- xdEditor.innerHTML = `
- <div id="ed_top">
- <button type="button" id="code" class="btn" title="代码模式"></button>
- <span id="font_color" class="btn" title="字体前景色">
- <input id="forecolor" class="colorBox" type="color" value="#ff0000" />
- </span>
- <span id="bg_color" class="btn" title="字体背景色">
- <input id="backcolor" class="colorBox" type="color" value="#0000ff" />
- </span>
- <button type="button" id="bold" class="btn" title="加粗"></button>
- <button type="button" id="italic" class="btn" title="斜体"></button>
- <button type="button" id="underline" class="btn" title="下划线"></button>
- <button type="button" id="strikethrough" class="btn" title="删除线"></button>
- <button type="button" id="removeformat" class="btn" title="清除格式"></button>
- <span id="edlist" class="btn" title="列表">
- <select id="orderlist">
- <option value="0">列表</option>
- <option value="insertorderedlist">有序列表</option>
- <option value="insertunorderedlist">无序列表</option>
- </select>
- </span>
- <button type="button" id="image" class="btn" title="图片"></button>
- <button type="button" id="audio" class="btn" title="音频"></button>
- <button type="button" id="video" class="btn" title="视频"></button>
- <span class="grow1"><a href="./" title="回退">返回日记</a></span>
- </div>
- <div id="ed_edit">
- <div id="rDiv" contenteditable="true"><p><br></p></div>
- </div>
- <div id="ed_foot">
- <span class="grow1"></span>
- <input type="submit" id="sub" name="sub" value="发布" title="提交" />
- </div>
- <div id="insertBox">
- <p id="mtitle" class="mid bold">插入</p>
- <p><label for="oSrc">地址 : </lable><input id="oSrc" type="text" value=""/ size="60" ></p>
- <p>
- <span id="s1"><label for="oWidth">宽度 : </lable><input id="oWidth" type="text" value="" size="4" /></span>
- <span id="s2"><label for="oHeight">高度 : </lable><input id="oHeight" type="text" value="" size="4" /></span>
- <span id="s3"><label for="oTitle">提示 : </lable><input id="oTitle" type="text" value="" size="8" /></span>
- <span id="s4"><input id="oCtrl" type="checkbox" value="" /><label for="oCtrl">控制</lable></span>
- <span id="s5"><input id="oAuto" type="checkbox" value="" /><label for="oAuto">自动</lable></span>
- <span id="s6"><input id="oLoop" type="checkbox" value="" /><label for="oLoop">循环</lable></span>
- </p>
- <p class="right"><input id="btnInsert" type="button" value="确定" /></p>
- </div>
- `;
- xdForm.appendChild(xdEditor); /* div追加到form */
- ed_edit.append(elm); /* textarea加入界面 */
- let codeState = false, insertIdx = 0; /* codeState : 编辑模式;insertIdx : 插入媒体索引 */
- /* btns : 所有按钮;colors : 插入颜色box;exec_btns : 一级执行按钮;media_btns :媒体按钮 */
- let btns = document.querySelectorAll('.btn'),
- colors = document.querySelectorAll('.colorBox');
- let exec_btns = ['bold','italic','underline','strikethrough','removeformat'],
- media_btns = ['image','audio','video'];
- let icon = {bold: 7,italic: 8,underline: 9,strikethrough: 10,font_color: 11,bg_color: 12,removeformat: 14,edlist: 16,image: 22,video: 23,audio: 24,code: 28};
- /* 函数 : 简单格式化代码 */
- let formatCode = (code) => {
- let regAr = [
- [/(<\/p>|<\/div>)(<)/g, '$1\n$2'],
- [/<div>(<br>)?<\/div>|<p><\/p>/g, ''],
- [/^[\t]*\n/gm, '']
- ];
- regAr.forEach((item) => {
- code = code.replaceAll(item[0],item[1]);
- });
- return code;
- };
- /* 函数 : 工具条按钮组隐藏|显示 */
- let set_btnState = () => {
- btns.forEach((btn,key) => {
- if(key > 0) btn.style.display = ['inline-block','none'][Number(codeState)];
- });
- };
- /* 函数 : 隐藏|显示元素,数组传参,用于插入媒体box */
- let hideEle = (hEles,sEles) => {
- hEles.forEach((hEle) => hEle.style.display = 'none');
- sEles.forEach((sEle) => sEle.style.display = 'inline-block');
- };
- /* 工具条按钮上图+功能处理 */
- btns.forEach((item) => {
- let num = icon[item.id];
- item.style.background = `url(${picData}) -${num * 20}px 0`;
- item.onclick = () => {
- if(exec_btns.includes(item.id)) document.execCommand(item.id,false,item.id);
- if(item.id === 'code') {
- if(codeState) {
- rDiv.innerHTML = elm.value;
- elm.style.display = 'none';
- rDiv.style.display = 'block';
- rDiv.focus();
- }else{
- elm.value = formatCode(rDiv.innerHTML);
- elm.style.display = 'block';
- elm.focus();
- rDiv.style.display = 'none';
- }
- codeState = !codeState;
- item.title = ['代码模式','常规模式'][codeState * 1];
- set_btnState();
- }
- if(item.id === 'edlist') {
- orderlist.onchange = () => document.execCommand(orderlist.value,false,orderlist.value);
- orderlist.value = "0";
- }
- if(media_btns.includes(item.id)) {
- let hides = [[s4,s5,s6],[s1,s2,s3],[s3]];
- let shows = [[s1,s2,s3],[s4,s5,s6],[s1,s2,s4,s5]];
- let idx = {image: 0, audio: 1, video: 2};
- insertBox.style.left = item.offsetLeft + 'px';
- insertBox.style.top = ed_top.clientHeight + 'px';
- insertBox.style.display = 'block';
- insertIdx = idx[item.id];
- hideEle(hides[insertIdx],shows[insertIdx]);
- mtitle.innerText = '插入' + ['图片','音频','视频'][insertIdx];
- }
- elm.value = formatCode(rDiv.innerHTML);
- };
- });
- /* 插入媒体 */
- btnInsert.onclick = () => {
- rDiv.focus();
- let sWidth = oWidth ? ' wdth="' + oWidth.value + '"': '',
- sHeight = oHeight ? ' height="' + oWidth.value + '"': '',
- sAuto = oAuto.checked ? ' autoplay="autoplay"' : '',
- sLoop = oLoop.checked ? ' loop="loop"' : '',
- sCtrl = oCtrl.checked ? ' controls="controls"' : '';
- let htmls = [
- `<img src="${oSrc.value}"${sWidth}${sHeight} alt="" title="${oTitle.value}" />`,
- `<audio src="${oSrc.value}"${sCtrl}${sAuto}${sLoop}></audio>`,
- `<video src="${oSrc.value}"${sCtrl}${sWidth}${sHeight}${sAuto}${sLoop}></video>`
- ];
- if(oSrc.value) document.execCommand('inserthtml',false,htmls[insertIdx]);
- insertBox.style.display = 'none';
- };
- /* 前景色&背景色 */
- colors.forEach((item,key) => {
- if(!codeState) item.oninput = () => document.execCommand(item.id,false,item.value);
- });
- /* 编辑时同步 */
- rDiv.oninput = () => elm.value = rDiv.innerHTML;
- /* 收起媒体box */
- rDiv.onfocus = elm.onfocus = () => insertBox.style.display = 'none';
- })();
复制代码
【说明】
一口气写成的初稿,也许有许多缺陷与错误,测试尚未发现不能运行。
|
评分
-
| 参与人数 1 | 威望 +50 |
金钱 +100 |
经验 +50 |
收起
理由
|
红影
| + 50 |
+ 100 |
+ 50 |
赞一个! |
查看全部评分
|