热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

包含修改字体,图片上传等功能的文本输入框Bootstrap

通过jQueryBootstrap小插件,框任何一个div转换变成一个富文本编辑框,主要特色:在Mac和window平台下自动针对常用操作绑定热键可以拖拽插入图片,支持图片上传(也

通过jQuery Bootstrap小插件,框任何一个div转换变成一个富文本编辑框,主要特色:

  • 在Mac和window平台下自动针对常用操作绑定热键
  • 可以拖拽插入图片,支持图片上传(也可以获取移动设备上的照片)
  • 依赖于浏览器标准,没有标准代码;工具条和键盘均可定制,并且能够执行任何浏览器支持的命令

首先看一下效果:

包含修改字体,图片上传等功能的文本输入框-Bootstrap

接下来,上代码:

 

 1 DOCTYPE html>
 2 <html lang="en">
 3  <head>
 4     <meta charset="utf-8">
 5     <title>Hello, Bootstraptitle>
 6     <meta name="viewport" content=" />
 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">Hugefont>a>li>
37           <li><a data-edit="fontSize 3"><font size="3">Normalfont>a>li>
38           <li><a data-edit="fontSize 1"><font size="1">Smallfont>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 errorstrong> '+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(/(
|\s|

<\/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), 166 currentRange = getCurrentRange(), 167 clear = currentRange && (currentRange.startCOntainer=== currentRange.endContainer && currentRange.startOffset === currentRange.endOffset); 168 if (!clear || isInside) { 169 saveSelection(); 170 updateToolbar(); 171 } 172 }); 173 return this; 174 }; 175 $.fn.wysiwyg.defaults = { 176 hotKeys: { 177 'ctrl+b meta+b': 'bold', 178 'ctrl+i meta+i': 'italic', 179 'ctrl+u meta+u': 'underline', 180 'ctrl+z meta+z': 'undo', 181 'ctrl+y meta+y meta+shift+z': 'redo', 182 'ctrl+l meta+l': 'justifyleft', 183 'ctrl+r meta+r': 'justifyright', 184 'ctrl+e meta+e': 'justifycenter', 185 'ctrl+j meta+j': 'justifyfull', 186 'shift+tab': 'outdent', 187 'tab': 'indent' 188 }, 189 toolbarSelector: '[data-role=editor-toolbar]', 190 commandRole: 'edit', 191 activeToolbarClass: 'btn-info', 192 selectionMarker: 'edit-focus-marker', 193 selectionColor: 'darkgrey', 194 dragAndDropImages: true, 195 fileUploadError: function (reason, detail) { console.log("File upload error", reason, detail); } 196 }; 197 }(window.jQuery));

对应的样式设计:

 1 #editor {
 2     max-height: 250px;
 3     height: 250px;
 4     background-color: white;
 5     border-collapse: separate; 
 6     border: 1px solid rgb(204, 204, 204); 
 7     padding: 4px; 
 8     box-sizing: content-box; 
 9     -webkit-box-shadow: rgba(0, 0, 0, 0.0745098) 0px 1px 1px 0px inset; 
10     box-shadow: rgba(0, 0, 0, 0.0745098) 0px 1px 1px 0px inset;
11     border-top-right-radius: 3px; border-bottom-right-radius: 3px;
12     border-bottom-left-radius: 3px; border-top-left-radius: 3px;
13     overflow: scroll;
14     outline: none;
15 }
16 #voiceBtn {
17   width: 20px;
18   color: transparent;
19   background-color: transparent;
20   transform: scale(2.0, 2.0);
21   -webkit-transform: scale(2.0, 2.0);
22   -moz-transform: scale(2.0, 2.0);
23   border: transparent;
24   cursor: pointer;
25   box-shadow: none;
26   -webkit-box-shadow: none;
27 }
28 
29 div[data-role="editor-toolbar"] {
30   -webkit-user-select: none;
31   -moz-user-select: none;
32   -ms-user-select: none;
33   user-select: none;
34 }
35 
36 .dropdown-menu a {
37   cursor: pointer;
38 }

如有错误之处,敬请指正,谢谢


推荐阅读
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 解决.net项目中未注册“microsoft.ACE.oledb.12.0”提供程序的方法
    在开发.net项目中,通过microsoft.ACE.oledb读取excel文件信息时,报错“未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序”。本文提供了解决这个问题的方法,包括错误描述和代码示例。通过注册提供程序和修改连接字符串,可以成功读取excel文件信息。 ... [详细]
  • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
  • Android实战——jsoup实现网络爬虫,糗事百科项目的起步
    本文介绍了Android实战中使用jsoup实现网络爬虫的方法,以糗事百科项目为例。对于初学者来说,数据源的缺乏是做项目的最大烦恼之一。本文讲述了如何使用网络爬虫获取数据,并以糗事百科作为练手项目。同时,提到了使用jsoup需要结合前端基础知识,以及如果学过JS的话可以更轻松地使用该框架。 ... [详细]
  • 单页面应用 VS 多页面应用的区别和适用场景
    本文主要介绍了单页面应用(SPA)和多页面应用(MPA)的区别和适用场景。单页面应用只有一个主页面,所有内容都包含在主页面中,页面切换快但需要做相关的调优;多页面应用有多个独立的页面,每个页面都要加载相关资源,页面切换慢但适用于对SEO要求较高的应用。文章还提到了两者在资源加载、过渡动画、路由模式和数据传递方面的差异。 ... [详细]
  • 本文介绍了pack布局管理器在Perl/Tk中的使用方法及注意事项。通过调用pack()方法,可以控制部件在显示窗口中的位置和大小。同时,本文还提到了在使用pack布局管理器时,应注意将部件分组以便在水平和垂直方向上进行堆放。此外,还介绍了使用Frame部件或Toplevel部件来组织部件在窗口内的方法。最后,本文强调了在使用pack布局管理器时,应避免在中间切换到grid布局管理器,以免造成混乱。 ... [详细]
  • 本文介绍了在满足特定条件时如何在输入字段中使用默认值的方法和相应的代码。当输入字段填充100或更多的金额时,使用50作为默认值;当输入字段填充有-20或更多(负数)时,使用-10作为默认值。文章还提供了相关的JavaScript和Jquery代码,用于动态地根据条件使用默认值。 ... [详细]
  • 使用C++编写程序实现增加或删除桌面的右键列表项
    本文介绍了使用C++编写程序实现增加或删除桌面的右键列表项的方法。首先通过操作注册表来实现增加或删除右键列表项的目的,然后使用管理注册表的函数来编写程序。文章详细介绍了使用的五种函数:RegCreateKey、RegSetValueEx、RegOpenKeyEx、RegDeleteKey和RegCloseKey,并给出了增加一项的函数写法。通过本文的方法,可以方便地自定义桌面的右键列表项。 ... [详细]
  • 本文介绍了解决mysql 5.1启动问题的方法,通过修改my.ini文件中的相关配置,包括innodb_data_home_dir和skip-innodb等,可以解决启动问题。同时还介绍了如何调整内存池来存储metadata信息。 ... [详细]
  • 本文介绍了使用FormData对象上传文件同时附带其他参数的方法。通过创建一个表单,将文件和参数添加到FormData对象中,然后使用ajax发送POST请求进行文件上传。在发送请求时,需要设置processData为false,告诉jquery不要处理发送的数据;同时设置contentType为false,告诉jquery不要设置content-Type请求头。 ... [详细]
  • 本文介绍了使用jQuery实现图片预加载和等比例缩放的方法,同时提供了演示和相关代码。该方法可以重置图片的宽度和高度,并使图片在水平和垂直方向上居中显示。 ... [详细]
  • 通过Anaconda安装tensorflow,并安装运行spyder编译器的完整教程
    本文提供了一个完整的教程,介绍了如何通过Anaconda安装tensorflow,并安装运行spyder编译器。文章详细介绍了安装Anaconda、创建tensorflow环境、安装GPU版本tensorflow、安装和运行Spyder编译器以及安装OpenCV等步骤。该教程适用于Windows 8操作系统,并提供了相关的网址供参考。通过本教程,读者可以轻松地安装和配置tensorflow环境,以及运行spyder编译器进行开发。 ... [详细]
  • 本文介绍了利用ARMA模型对平稳非白噪声序列进行建模的步骤及代码实现。首先对观察值序列进行样本自相关系数和样本偏自相关系数的计算,然后根据这些系数的性质选择适当的ARMA模型进行拟合,并估计模型中的位置参数。接着进行模型的有效性检验,如果不通过则重新选择模型再拟合,如果通过则进行模型优化。最后利用拟合模型预测序列的未来走势。文章还介绍了绘制时序图、平稳性检验、白噪声检验、确定ARMA阶数和预测未来走势的代码实现。 ... [详细]
author-avatar
dushearer304
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有