关键词:
通过jQuery Bootstrap小插件,框任何一个div转换变成一个富文本编辑框,主要特色:
- 在Mac和window平台下自动针对常用操作绑定热键
- 可以拖拽插入图片,支持图片上传(也可以获取移动设备上的照片)
- 依赖于浏览器标准,没有标准代码;工具条和键盘均可定制,并且能够执行任何浏览器支持的命令
首先看一下效果:
接下来,上代码:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="utf-8"> 5 <title>Hello, Bootstrap</title> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 7 <meta name="keywords" content="opensource rich wysiwyg text editor jquery bootstrap execCommand html5" /> 8 <meta name="description" content="This tiny jQuery Bootstrap WYSIWYG plugin turns any DIV into a HTML5 rich text editor" /> 9 <link rel="shortcut icon" href="http://mindmup.s3.amazonaws.com/lib/img/favicon.ico" > 10 <link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.no-icons.min.css" rel="stylesheet"> 11 <link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-responsive.min.css" rel="stylesheet"> 12 <link href="http://netdna.bootstrapcdn.com/font-awesome/3.0.2/css/font-awesome.css" rel="stylesheet"> 13 <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script> 14 15 <script src="external/jquery.hotkeys.js"></script> 16 <script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script> 17 <script src="external/google-code-prettify/prettify.js"></script> 18 <link href="index.css" rel="stylesheet"> 19 <script src="bootstrap-my.js"></script> 20 <script src="indexexercise.js" ></script> 21 </head> 22 <body> 23 24 <div class="container"style="width:651px;"> 25 <div class="hero-unit" style="width: 600px; padding: 8px 30px 30px 30px;"> 26 <div id="alerts"></div> 27 <div class="btn-toolbar" data-role="editor-toolbar" data-target="#editor"> 28 <div class="btn-group"> 29 <a class="btn dropdown-toggle" data-toggle="dropdown" title="Font"><i class="icon-font"></i><b class="caret"></b></a> 30 <ul class="dropdown-menu"> 31 </ul> 32 </div> 33 <div class="btn-group"> 34 <a class="btn dropdown-toggle" data-toggle="dropdown" title="Font Size"><i class="icon-text-height"></i> <b class="caret"></b></a> 35 <ul class="dropdown-menu"> 36 <li><a data-edit="fontSize 5"><font size="5">Huge</font></a></li> 37 <li><a data-edit="fontSize 3"><font size="3">Normal</font></a></li> 38 <li><a data-edit="fontSize 1"><font size="1">Small</font></a></li> 39 </ul> 40 </div> 41 <div class="btn-group"> 42 <a class="btn" data-edit="insertunorderedlist" title="Bullet list"><i class="icon-list-ul"></i></a> 43 <a class="btn" data-edit="insertorderedlist" title="Number list"><i class="icon-list-ol"></i></a> 44 </div> 45 <div class="btn-group"> 46 <a class="btn" title="Insert picture (or just drag & drop)" id="pictureBtn"><i class="icon-picture"></i></a> 47 <input type="file" data-role="magic-overlay" data-target="#pictureBtn" data-edit="insertImage" /> 48 </div> 49 <input type="text" data-edit="inserttext" id="voiceBtn" x-webkit-speech=""> 50 </div> 51 52 <div id="editor" style="width: 568px;height: 145px;"> 53 welcome to edit in your space … 54 </div> 55 </div> 56 </div> 57 </html>
对应的indexexercise.js部分:
1 jQuery(document).ready(function(){ 2 3 $(function(){ 4 function initToolbarBootstrapBindings() { 5 var fonts = ['Serif', 'Sans', 'Arial', 'Arial Black', 'Courier', 6 'Courier New', 'Comic Sans MS', 'Helvetica', 'Impact', 'Lucida Grande', 'Lucida Sans', 'Tahoma', 'Times', 7 'Times New Roman', 'Verdana'], 8 fontTarget = $('[title=Font]').siblings('.dropdown-menu'); 9 $.each(fonts, function (idx, fontName) { 10 fontTarget.append($('<li><a data-edit="fontName ' + fontName +'" style="font-family:\''+ fontName +'\'">'+fontName + '</a></li>')); 11 }); 12 $('a[title]').tooltip({container:'body'}); 13 $('.dropdown-menu input').click(function() {return false;}) 14 .change(function () {$(this).parent('.dropdown-menu').siblings('.dropdown-toggle').dropdown('toggle');}) 15 .keydown('esc', function () {this.value='';$(this).change();}); 16 17 $('[data-role=magic-overlay]').each(function () { 18 var overlay = $(this), target = $(overlay.data('target')); 19 overlay.css('opacity', 0).css('position', 'absolute').offset(target.offset()).width(target.outerWidth()).height(target.outerHeight()); 20 }); 21 if ("onwebkitspeechchange" in document.createElement("input")) { 22 var editorOffset = $('#editor').offset(); 23 $('#voiceBtn').css('position','absolute').offset({top: editorOffset.top, left: editorOffset.left+$('#editor').innerWidth()-35}); 24 } else { 25 $('#voiceBtn').hide(); 26 } 27 }; 28 function showErrorAlert (reason, detail) { 29 var msg=''; 30 if (reason==='unsupported-file-type') { msg = "Unsupported format " +detail; } 31 else { 32 console.log("error uploading file", reason, detail); 33 } 34 $('<div class="alert"> <button type="button" class="close" data-dismiss="alert">×</button>'+ 35 '<strong>File upload error</strong> '+msg+' </div>').prependTo('#alerts'); 36 }; 37 initToolbarBootstrapBindings(); 38 $('#editor').wysiwyg({ fileUploadError: showErrorAlert} ); 39 window.prettyPrint && prettyPrint(); 40 }); 41 42 (function(i,s,o,g,r,a,m) 43 {i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ 44 (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), 45 m=s.getElementsByTagName(o)[0];a.async=1; 46 a.src=g;m.parentNode.insertBefore(a,m)}) 47 (window,document,'script','//www.google-analytics.com/analytics.js','ga'); 48 ga('create', 'UA-37452180-6', 'github.io'); 49 ga('send', 'pageview'); 50 51 (function(d, s, id) { 52 var js, fjs = d.getElementsByTagName(s)[0]; 53 if (d.getElementById(id)) 54 return; 55 js = d.createElement(s); 56 js.id = id; 57 js.src = "http://connect.facebook.net/en_GB/all.js#xfbml=1"; 58 fjs.parentNode.insertBefore(js, fjs); 59 }(document, 'script', 'facebook-jssdk')); 60 61 !function(d,s,id){ 62 var js,fjs=d.getElementsByTagName(s)[0]; 63 if(!d.getElementById(id)){ 64 js=d.createElement(s); 65 js.id=id; 66 js.src="http://platform.twitter.com/widgets.js"; 67 fjs.parentNode.insertBefore(js,fjs);}} 68 (document,"script","twitter-wjs"); 69 })
对应的bootstrap-my.js部分:
1 (function ($) { 2 'use strict'; 3 var readFileIntoDataUrl = function (fileInfo) { 4 var loader = $.Deferred(), 5 fReader = new FileReader(); 6 fReader.onload = function (e) { 7 loader.resolve(e.target.result); 8 }; 9 fReader.onerror = loader.reject; 10 fReader.onprogress = loader.notify; 11 fReader.readAsDataURL(fileInfo); 12 return loader.promise(); 13 }; 14 $.fn.cleanHtml = function () { 15 var html = $(this).html(); 16 return html && html.replace(/(<br>|\s|<div><br><\/div>| )*$/, ''); 17 }; 18 $.fn.wysiwyg = function (userOptions) { 19 var editor = this, 20 selectedRange, 21 options, 22 toolbarBtnSelector, 23 updateToolbar = function () { 24 if (options.activeToolbarClass) { 25 $(options.toolbarSelector).find(toolbarBtnSelector).each(function () { 26 var command = $(this).data(options.commandRole); 27 if (document.queryCommandState(command)) { 28 $(this).addClass(options.activeToolbarClass); 29 } else { 30 $(this).removeClass(options.activeToolbarClass); 31 } 32 }); 33 } 34 }, 35 execCommand = function (commandWithArgs, valueArg) { 36 var commandArr = commandWithArgs.split(' '), 37 command = commandArr.shift(), 38 args = commandArr.join(' ') + (valueArg || ''); 39 document.execCommand(command, 0, args); 40 updateToolbar(); 41 }, 42 bindHotkeys = function (hotKeys) { 43 $.each(hotKeys, function (hotkey, command) { 44 editor.keydown(hotkey, function (e) { 45 if (editor.attr('contenteditable') && editor.is(':visible')) { 46 e.preventDefault(); 47 e.stopPropagation(); 48 execCommand(command); 49 } 50 }).keyup(hotkey, function (e) { 51 if (editor.attr('contenteditable') && editor.is(':visible')) { 52 e.preventDefault(); 53 e.stopPropagation(); 54 } 55 }); 56 }); 57 }, 58 getCurrentRange = function () { 59 var sel = window.getSelection(); 60 if (sel.getRangeAt && sel.rangeCount) { 61 return sel.getRangeAt(0); 62 } 63 }, 64 saveSelection = function () { 65 selectedRange = getCurrentRange(); 66 }, 67 restoreSelection = function () { 68 var selection = window.getSelection(); 69 if (selectedRange) { 70 try { 71 selection.removeAllRanges(); 72 } catch (ex) { 73 document.body.createTextRange().select(); 74 document.selection.empty(); 75 } 76 77 selection.addRange(selectedRange); 78 } 79 }, 80 insertFiles = function (files) { 81 editor.focus(); 82 $.each(files, function (idx, fileInfo) { 83 if (/^image\//.test(fileInfo.type)) { 84 $.when(readFileIntoDataUrl(fileInfo)).done(function (dataUrl) { 85 execCommand('insertimage', dataUrl); 86 }).fail(function (e) { 87 options.fileUploadError("file-reader", e); 88 }); 89 } else { 90 options.fileUploadError("unsupported-file-type", fileInfo.type); 91 } 92 }); 93 }, 94 markSelection = function (input, color) { 95 restoreSelection(); 96 if (document.queryCommandSupported('hiliteColor')) { 97 document.execCommand('hiliteColor', 0, color || 'transparent'); 98 } 99 saveSelection(); 100 input.data(options.selectionMarker, color); 101 }, 102 bindToolbar = function (toolbar, options) { 103 toolbar.find(toolbarBtnSelector).click(function () { 104 restoreSelection(); 105 editor.focus(); 106 execCommand($(this).data(options.commandRole)); 107 saveSelection(); 108 }); 109 toolbar.find('[data-toggle=dropdown]').click(restoreSelection); 110 111 toolbar.find('input[type=text][data-' + options.commandRole + ']').on('webkitspeechchange change', function () { 112 var newValue = this.value; /* ugly but prevents fake double-calls due to selection restoration */ 113 this.value = ''; 114 restoreSelection(); 115 if (newValue) { 116 editor.focus(); 117 execCommand($(this).data(options.commandRole), newValue); 118 } 119 saveSelection(); 120 }).on('focus', function () { 121 var input = $(this); 122 if (!input.data(options.selectionMarker)) { 123 markSelection(input, options.selectionColor); 124 input.focus(); 125 } 126 }).on('blur', function () { 127 var input = $(this); 128 if (input.data(options.selectionMarker)) { 129 markSelection(input, false); 130 } 131 }); 132 toolbar.find('input[type=file][data-' + options.commandRole + ']').change(function () { 133 restoreSelection(); 134 if (this.type === 'file' && this.files && this.files.length > 0) { 135 insertFiles(this.files); 136 } 137 saveSelection(); 138 this.value = ''; 139 }); 140 }, 141 initFileDrops = function () { 142 editor.on('dragenter dragover', false) 143 .on('drop', function (e) { 144 var dataTransfer = e.originalEvent.dataTransfer; 145 e.stopPropagation(); 146 e.preventDefault(); 147 if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) { 148 insertFiles(dataTransfer.files); 149 } 150 }); 151 }; 152 options = $.extend({}, $.fn.wysiwyg.defaults, userOptions); 153 toolbarBtnSelector = 'a[data-' + options.commandRole + '],button[data-' + options.commandRole + '],input[type=button][data-' + options.commandRole + ']'; 154 bindHotkeys(options.hotKeys); 155 if (options.dragAndDropImages) { 156 initFileDrops(); 157 } 158 bindToolbar($(options.toolbarSelector), options); 159 editor.attr('contenteditable', true) 160 .on('mouseup keyup mouseout', function () { 161 saveSelection(); 162 updateToolbar(); 163 }); 164 $(window).bind('touchend', function (e) { 165 var isInside = (editor.is(e.target) || editor.has(e.target).length > 0), 查看详情winform,自定义文本框控件实现文本框验证加水印功能
需求:1、当文本框无值时出现灰色字体提示用户输入信息; 2、当文本框有值时出现用户输入的值并且字体恢复黑色; 3、当该文本框失去焦点时验证用户输入的值是否正确(正则表达式验证),如果错误,弹出“... 查看详情
vuequilleditor自定义图片/视频上传(elementui+oss)字体字体大小段落等(代码片段)
...中并不需要那么多的功能,只需要基础的操作:字体、字体大小、标题、段落、图片上传、视频上传、居中对齐等;所以我们只需要一个轻量级的富文本编辑器就行,推荐使用Quill和TinyMCE,Quill和TinyMCE都是轻... 查看详情
h5网页怎么制作
...击页面右上角的X,可以把不需要的页面删除。功能—添加修改文字1、添加文字:点击右侧的文字选项→主编辑区会出现文字输入框→双击修改2、文字属性修改:右侧文字属性修改选项,包括字体种类,字体大小、颜色等等。功... 查看详情
测试标准1
...框,上传文件框,下拉框,日期选择等保持一致。添加,修改,详细,三个页面风格保持一致。列表页的风格应该都一致的。添加:是否做了不为空的检测。是否做了对应类型的检测。异常提示是否正确。是否对长度进行了判断... 查看详情
vuequilleditor自定义图片/视频上传(elementui+oss)字体字体大小段落等(代码片段)
近期项目中需要使用富文本编辑器,开始想到的富文本编辑器是百度的UEditor,UEditor功能齐全、插件多,但是图片只能上传到本地服务器,如果需要上传到其他服务器需要改动源码,而且是PHP、JSP、ASP、.Ne... 查看详情
如何制作带有微信支付的h5网页
...击页面右上角的X,可以把不需要的页面删除。功能—添加修改文字1、添加文字:点击右侧的文字选项→主编辑区会出现文字输入框→双击修改2、文字属性修改:右侧文字属性修改选项,包括字体种类,字体大小、颜色等等。功... 查看详情
微信中怎样嵌入自己开发的h5页面
...击页面右上角的X,可以把不需要的页面删除。功能—添加修改文字1、添加文字:点击右侧的文字选项→主编辑区会出现文字输入框→双击修改2、文字属性修改:右侧文字属性修改选项,包括字体种类,字体大小、颜色等等。功... 查看详情
word中的文本框为啥不能输入文字
...对象格式”的窗口(如第二张图片所示)。请问一下怎么修改才能输入文字?谢谢!word中的文本框不能输入文字应该是文本框使用不正确造成的。在word中的文本框的正确使用方法如下,以wps2019中的word为例做演示。1、在桌面中... 查看详情
修改ios自有的上传弹出框样式vue
您好,要修改ios自有的上传弹出框样式vue,首先您需要在vue中安装ios弹出框插件,然后在插件中配置您想要的样式,比如字体大小、颜色、背景等。接下来,您需要在vue中定义一个函数,用于调用ios弹出框插件,并传入您想要的... 查看详情
matlabgui滑动条看不见
...进入属性设置面板3.所有控件最最常用的属性就是fontsize-修改字体大小,string-修改显示文字,tag-修改按钮id其中在面板控件较多的情况下,设置合适id能够很好地让我们辨认出该按钮的功能4.右击按钮,viewcallbacks-callback,进入回调... 查看详情
matlabgui-如何修改对话框的字体大小等属性
...命令行窗口输入findobj(h),就可以看到这个图形界面里面包含哪些控件:知道了这些控件后,修改它们的属性就很容易了,之前的文章中都有讲过。举三个例子:(1)修改按钮的字体大小:set(findobj(h,'type','uicobtrol'),... 查看详情
字体不支持符号时如何在WPF文本框中插入版权、商标、服务标记等
...1-1012:32:47【问题描述】:我们有一个WPF应用程序,它显示包含各种公司符号的文本;例如商标、注册商标、版权和服务标志。数据库有一些包含标准公司 查看详情
富文本编辑器-1-选型
...内部元素。也可以通过innerHtml获取dom。2.可定制Quill可以修改、扩展现有的模块,也可以添加新的模块,甚至可以在parchment的基础上全部重写。有较强的灵活性。3.兼容性当前版本兼容Chrome、IE11、Edge,已满足业务需求。4.与其他... 查看详情
vuetinymce控制图片大小上传,以及富文本编辑框在dialog的问题
...单栏(toolbar)被置于底层了,dialog盖住了菜单栏解决:修改tinycme中的样式文件,z-index:都+00000,此文件中有多处z-index,请全部修改(另外,z-index=-1这种就不需要修改了) 查看详情
django——文本编辑器(代码片段)
...的设计,所有功能都是插件,可根据需求增减功能风格:修改编辑器风格非常容易,只需修改一个CSS文件兼容:支持大部分主流浏览器,比如IE、Firefox、Safari、Chrome、Oper2.Django中引入kindeditor2.1templates代码:<divclass="contentform-gro... 查看详情
html制作简单的搜索功能
...织或个人在万维网上的起点的页面称为主页,而主页通常包含指向其他相关页面或其他节点的指针(超链接)。从逻辑上讲作为一个整体处理的一系列页面的有机集合称为一个网站(网站或Web)。Web页面,也称为Web页面,在这里没有... 查看详情
打赏功能的实现
...码并上传为什么要修改js源代码,因为博客园的文件是不包含文件夹的,文件只有一个地址,输入文件地址即可查看文件上面这个要把img去掉同时如果我 查看详情