Discuz编辑器简单分析

本文详细分析了Discuz论坛编辑器的工作原理,包括工具栏按钮的实现方式、使用CSS和JavaScript进行格式设置的方法,以及如何通过JavaScript处理按钮点击事件。
Discuz编辑器简单分析2009-09-27 23:26 Post.php 加载post.htm打开 http://127.0.0.1/bbs/post.php?action=newthread&fid=2 进入发贴页面,查看该页源代码。可以看到
这个div里面就是编辑器的内容了。继续在里面找到
….
这里面大概就是格式、工具栏了,通过这些按扭可以设置相关格式,及插入图片,代码等。在
里面可以看到如下代码:
fly
这里就是那条工具栏了,可是 中间并没有文字和图片啊,为什么在页面上能显示出 这样的形式呢,那个代码文字就是 title="代码"起的作用,图片其实是通过css样式弄出来的。在html源代码里可以看到 @import url(forumdata/cache/style_5_common.css?RzZ);打开style_5_common.css,里面是压缩过的样式,可以用css压缩解压工具把代码整理一下,让其变成正常人能看懂的。 .editor a{float:left;text-align:left;text-decoration:none;display:block;height:21px;width:20px;background:url(../../images/common/editor.gif) no-repeat 0 30px;text-indent:-9999px;overflow:hidden;border:1px solid #F7F7F7;margin:1px 0;} 这是设置应用了.editor类里面的a标签的背景,就是那张editor.gif。 #e_cmd_insertimage{background-position:0 -161px;} /*插入图片背景*/ #e_cmd_code{background-position:0 -461px;} /*代码工具按扭的背景,这个按扭其实就是a 标签*/那为什么点击 这个标签会出现一个插入代码框呢?这其实是通过js来完成的。 Post.php 页面的html代码里有这样的几句 function openEditor(){……} //定义打开编辑器函数 Post.php 页面并没有直接调用openEditor(),而且在post.js里调用了openEditor(), function openEditor() { try { newEditor(wysiwyg); //新建一个编辑器,此函数定义在post.js里 if(editbox) { editbox.className = 'autosave max'; } …… }Post.js function newEditor(mode, initialtext) { …… setEditorEvents(); initEditor(); //初始化编辑器 } 看看 initEditor()函数的定义 function initEditor() { var buttons = $(editorid + '_controls').getElementsByTagName('a'); //得到e_controls里的a //遍历a,给它加上onclick事件 for(var i = 0; i < buttons.length; i++) { if(buttons[i].id.indexOf(editorid + '_cmd_') != -1) { buttons[i].href = 'javascript:;'; buttons[i].onclick = function(e) {discuzcode(this.id.substr(this.id.lastIndexOf('_cmd_') + 5))}; } else if(buttons[i].id == editorid + '_popup_media') { buttons[i].href = 'javascript:;'; buttons[i].onclick = function(e) {discuzcode('media')}; } else if(buttons[i].id.indexOf(editorid + '_popup_') != -1) { buttons[i].href = 'javascript:;'; buttons[i].onclick = function(e) {InFloat = InFloat_Editor;showMenu(this.id, true, 0, 2)}; } } setUnselectable($(editorid + '_controls')); textobj.onkeydown = function(e) {ctlent(e ? e : event)}; } //关键是在点击时调用的discuzcode()函数 function discuzcode(cmd, arg) { if(cmd != 'redo') { addSnapshot(getEditorContents()); } …… if(in_array(cmd, ['quote', 'code', 'free', 'hide','php'])) { …… lang['e_code'] = '请输入要插入的代码'; lang['e_free'] = '请输入要插入的免费信息'; lang['e_hide'] = '请输入要插入的隐藏内容'; if(cmd != 'hide' || !selection) { str += lang['e_' + cmd] + ':
'; } str += cmd == 'hide' ? '
只有当浏览者回复本帖时才显示
只有当浏览者积分高于 时才显示' : ''; var div = editorMenu(ctrlid, str); //此div就是代码输入显示框 $(ctrlid + '_param_' + (cmd == 'hide' && selection ? 2 : 1)).focus(); $(ctrlid + '_param_' + (cmd == 'hide' && selection ? 2 : 1)).onkeydown = editorMenuEvent_onkeydown; $(ctrlid + '_submit').onclick = function() { //处理提交按扭点击事件 checkFocus(); if(is_ie) { setCaret(pos); } if(cmd == 'hide' && $(ctrlid + '_radio_2').checked) { var mincredits = parseInt($(ctrlid + '_param_2').value); opentag = mincredits > 0 ? '[hide=' + mincredits + ']' : '[hide]'; } var text = selection ? selection : $(ctrlid + '_param_1').value; if(wysiwyg) { if(cmd == 'code') { text = preg_replace(['<', '>'], ['<', '>'], text); } text = text.replace(//r?/n/g, '
'); } text = opentag + text + closetag; //对应 [code] + text +[/code],产生相应ubb代码 insertText(text, strlen(opentag), strlen(closetag), false, sel); hideMenu(); div.parentNode.removeChild(div); } return; } else if(cmd.substr(0, 6) == 'custom') { …… …… if(cmd != 'undo') { addSnapshot(getEditorContents()); } if(in_array(cmd, ['bold', 'italic', 'underline', 'fontname', 'fontsize', 'forecolor', 'justifyleft', 'justifycenter', 'justifyright', 'insertorderedlist', 'insertunorderedlist', 'indent', 'outdent', 'floatleft', 'floatright', 'removeformat', 'unlink', 'undo', 'redo'])) { hideMenu(); } return ret; }function editorMenu(ctrlid, str) { var div = document.createElement('div'); div.id = ctrlid + '_menu'; …… div.innerHTML = '
' + str + '
 
'; InFloat = InFloat_Editor; showMenu(ctrlid, true, 0, 3); //定义在common.js中 return div; }function insertText(text, movestart, moveend, select, sel) { if(wysiwyg) { if(is_moz || is_opera) { …… //非ie浏览器 } else { //IE浏览器 checkFocus(); if(!isUndefined(editdoc.selection) && editdoc.selection.type != 'Text' && editdoc.selection.type != 'None') { movestart = false; editdoc.selection.clear(); } if(isUndefined(sel)) { sel = editdoc.selection.createRange(); } sel.pasteHTML(text); if(text.indexOf('/n') == -1) { if(!isUndefined(movestart)) { sel.moveStart('character', -strlen(text) + movestart); sel.moveEnd('character', -moveend); } else if(movestart != false) { sel.moveStart('character', -strlen(text)); } if(!isUndefined(select) && select) { sel.select(); } } } } else { …… } } 原文地址: http://blog.nmgline.com/space-115-do-blog-id-101.html
(1)普通用户端(全平台) 音乐播放核心体验: 个性化首页:基于 “听歌历史 + 收藏偏好” 展示 “推荐歌单(每日 30 首)、新歌速递、相似曲风推荐”,支持按 “场景(通勤 / 学习 / 运动)” 切换推荐维度。 播放页功能:支持 “无损音质切换、倍速播放(0.5x-2.0x)、定时关闭、歌词逐句滚动”,提供 “沉浸式全屏模式”(隐藏冗余控件,突出歌词与专辑封面)。 多端同步:自动同步 “播放进度、收藏列表、歌单” 至所有登录设备(如手机暂停后,电脑端打开可继续播放)。 音乐发现与管理: 智能搜索:支持 “歌曲名 / 歌手 / 歌词片段” 搜索,提供 “模糊匹配(如输入‘晴天’联想‘周杰伦 - 晴天’)、热门搜索词推荐”,结果按 “热度 / 匹配度” 排序。 歌单管理:创建 “公开 / 私有 / 加密” 歌单,支持 “批量添加歌曲、拖拽排序、一键分享到社交平台”,系统自动生成 “歌单封面(基于歌曲风格配色)”。 音乐分类浏览:按 “曲风(流行 / 摇滚 / 古典)、语言(国语 / 英语 / 日语)、年代(80 后经典 / 2023 新歌)” 分层浏览,每个分类页展示 “TOP50 榜单”。 社交互动功能: 动态广场:查看 “关注的用户 / 音乐人发布的动态(如‘分享新歌感受’)、好友正在听的歌曲”,支持 “点赞 / 评论 / 转发”,可直接点击动态中的歌曲播放。 听歌排行:个人页展示 “本周听歌 TOP10、累计听歌时长”,平台定期生成 “全球 / 好友榜”(如 “好友中你本周听歌时长排名第 3”)。 音乐圈:加入 “特定曲风圈子(如‘古典音乐爱好者’)”,参与 “话题讨论(如‘你心中最经典的钢琴曲’)、线上歌单共创”。 (2)音乐人端(创作者中心) 作品管理: 音乐上传:支持 “无损音频(FLAC/WAV)+ 歌词文件(LRC)+ 专辑封面” 上传,填写 “歌曲信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值