包含修改字体,图片上传等功能的文本输入框-Bootstrap
通过jQuery Bootstrap小插件,框任何一个div转换变成一个富文本编辑框,主要特色:
- 在Mac和window平台下自动针对常用操作绑定热键
- 可以拖拽插入图片,支持图片上传(也可以获取移动设备上的照片)
- 依赖于浏览器标准,没有标准代码;工具条和键盘均可定制,并且能够执行任何浏览器支持的命令
首先看一下效果:
接下来,上代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Hello, Bootstrap</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="keywords" content="opensource rich wysiwyg text editor jquery bootstrap execCommand html5" />
<meta name="description" content="This tiny jQuery Bootstrap WYSIWYG plugin turns any DIV into a HTML5 rich text editor" />
<link rel="shortcut icon" href="http://mindmup.s3.amazonaws.com/lib/img/favicon.ico" >
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.no-icons.min.css" rel="stylesheet">
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-responsive.min.css" rel="stylesheet">
<link href="http://netdna.bootstrapcdn.com/font-awesome/3.0.2/css/font-awesome.css" rel="stylesheet">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script> <script src="external/jquery.hotkeys.js"></script>
<script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
<script src="external/google-code-prettify/prettify.js"></script>
<link href="index.css" rel="stylesheet">
<script src="bootstrap-my.js"></script>
<script src="indexexercise.js" ></script>
</head>
<body> <div class="container"style="width:651px;">
<div class="hero-unit" style="width: 600px; padding: 8px 30px 30px 30px;">
<div id="alerts"></div>
<div class="btn-toolbar" data-role="editor-toolbar" data-target="#editor">
<div class="btn-group">
<a class="btn dropdown-toggle" data-toggle="dropdown" title="Font"><i class="icon-font"></i><b class="caret"></b></a>
<ul class="dropdown-menu">
</ul>
</div>
<div class="btn-group">
<a class="btn dropdown-toggle" data-toggle="dropdown" title="Font Size"><i class="icon-text-height"></i> <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a data-edit="fontSize 5"><font size="5">Huge</font></a></li>
<li><a data-edit="fontSize 3"><font size="3">Normal</font></a></li>
<li><a data-edit="fontSize 1"><font size="1">Small</font></a></li>
</ul>
</div>
<div class="btn-group">
<a class="btn" data-edit="insertunorderedlist" title="Bullet list"><i class="icon-list-ul"></i></a>
<a class="btn" data-edit="insertorderedlist" title="Number list"><i class="icon-list-ol"></i></a>
</div>
<div class="btn-group">
<a class="btn" title="Insert picture (or just drag & drop)" id="pictureBtn"><i class="icon-picture"></i></a>
<input type="file" data-role="magic-overlay" data-target="#pictureBtn" data-edit="insertImage" />
</div>
<input type="text" data-edit="inserttext" id="voiceBtn" x-webkit-speech="">
</div> <div id="editor" style="width: 568px;height: 145px;">
welcome to edit in your space …
</div>
</div>
</div>
</html>
对应的indexexercise.js部分:
jQuery(document).ready(function(){ $(function(){
function initToolbarBootstrapBindings() {
var fonts = ['Serif', 'Sans', 'Arial', 'Arial Black', 'Courier',
'Courier New', 'Comic Sans MS', 'Helvetica', 'Impact', 'Lucida Grande', 'Lucida Sans', 'Tahoma', 'Times',
'Times New Roman', 'Verdana'],
fontTarget = $('[title=Font]').siblings('.dropdown-menu');
$.each(fonts, function (idx, fontName) {
fontTarget.append($('<li><a data-edit="fontName ' + fontName +'" style="font-family:\''+ fontName +'\'">'+fontName + '</a></li>'));
});
$('a[title]').tooltip({container:'body'});
$('.dropdown-menu input').click(function() {return false;})
.change(function () {$(this).parent('.dropdown-menu').siblings('.dropdown-toggle').dropdown('toggle');})
.keydown('esc', function () {this.value='';$(this).change();}); $('[data-role=magic-overlay]').each(function () {
var overlay = $(this), target = $(overlay.data('target'));
overlay.css('opacity', 0).css('position', 'absolute').offset(target.offset()).width(target.outerWidth()).height(target.outerHeight());
});
if ("onwebkitspeechchange" in document.createElement("input")) {
var editorOffset = $('#editor').offset();
$('#voiceBtn').css('position','absolute').offset({top: editorOffset.top, left: editorOffset.left+$('#editor').innerWidth()-35});
} else {
$('#voiceBtn').hide();
}
};
function showErrorAlert (reason, detail) {
var msg='';
if (reason==='unsupported-file-type') { msg = "Unsupported format " +detail; }
else {
console.log("error uploading file", reason, detail);
}
$('<div class="alert"> <button type="button" class="close" data-dismiss="alert">×</button>'+
'<strong>File upload error</strong> '+msg+' </div>').prependTo('#alerts');
};
initToolbarBootstrapBindings();
$('#editor').wysiwyg({ fileUploadError: showErrorAlert} );
window.prettyPrint && prettyPrint();
}); (function(i,s,o,g,r,a,m)
{i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;
a.src=g;m.parentNode.insertBefore(a,m)})
(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-37452180-6', 'github.io');
ga('send', 'pageview'); (function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id))
return;
js = d.createElement(s);
js.id = id;
js.src = "http://connect.facebook.net/en_GB/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk')); !function(d,s,id){
var js,fjs=d.getElementsByTagName(s)[0];
if(!d.getElementById(id)){
js=d.createElement(s);
js.id=id;
js.src="http://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js,fjs);}}
(document,"script","twitter-wjs");
})
对应的bootstrap-my.js部分:
(function ($) {
'use strict';
var readFileIntoDataUrl = function (fileInfo) {
var loader = $.Deferred(),
fReader = new FileReader();
fReader.onload = function (e) {
loader.resolve(e.target.result);
};
fReader.onerror = loader.reject;
fReader.onprogress = loader.notify;
fReader.readAsDataURL(fileInfo);
return loader.promise();
};
$.fn.cleanHtml = function () {
var html = $(this).html();
return html && html.replace(/(<br>|\s|<div><br><\/div>| )*$/, '');
};
$.fn.wysiwyg = function (userOptions) {
var editor = this,
selectedRange,
options,
toolbarBtnSelector,
updateToolbar = function () {
if (options.activeToolbarClass) {
$(options.toolbarSelector).find(toolbarBtnSelector).each(function () {
var command = $(this).data(options.commandRole);
if (document.queryCommandState(command)) {
$(this).addClass(options.activeToolbarClass);
} else {
$(this).removeClass(options.activeToolbarClass);
}
});
}
},
execCommand = function (commandWithArgs, valueArg) {
var commandArr = commandWithArgs.split(' '),
command = commandArr.shift(),
args = commandArr.join(' ') + (valueArg || '');
document.execCommand(command, 0, args);
updateToolbar();
},
bindHotkeys = function (hotKeys) {
$.each(hotKeys, function (hotkey, command) {
editor.keydown(hotkey, function (e) {
if (editor.attr('contenteditable') && editor.is(':visible')) {
e.preventDefault();
e.stopPropagation();
execCommand(command);
}
}).keyup(hotkey, function (e) {
if (editor.attr('contenteditable') && editor.is(':visible')) {
e.preventDefault();
e.stopPropagation();
}
});
});
},
getCurrentRange = function () {
var sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
return sel.getRangeAt(0);
}
},
saveSelection = function () {
selectedRange = getCurrentRange();
},
restoreSelection = function () {
var selection = window.getSelection();
if (selectedRange) {
try {
selection.removeAllRanges();
} catch (ex) {
document.body.createTextRange().select();
document.selection.empty();
} selection.addRange(selectedRange);
}
},
insertFiles = function (files) {
editor.focus();
$.each(files, function (idx, fileInfo) {
if (/^image\//.test(fileInfo.type)) {
$.when(readFileIntoDataUrl(fileInfo)).done(function (dataUrl) {
execCommand('insertimage', dataUrl);
}).fail(function (e) {
options.fileUploadError("file-reader", e);
});
} else {
options.fileUploadError("unsupported-file-type", fileInfo.type);
}
});
},
markSelection = function (input, color) {
restoreSelection();
if (document.queryCommandSupported('hiliteColor')) {
document.execCommand('hiliteColor', 0, color || 'transparent');
}
saveSelection();
input.data(options.selectionMarker, color);
},
bindToolbar = function (toolbar, options) {
toolbar.find(toolbarBtnSelector).click(function () {
restoreSelection();
editor.focus();
execCommand($(this).data(options.commandRole));
saveSelection();
});
toolbar.find('[data-toggle=dropdown]').click(restoreSelection); toolbar.find('input[type=text][data-' + options.commandRole + ']').on('webkitspeechchange change', function () {
var newValue = this.value; /* ugly but prevents fake double-calls due to selection restoration */
this.value = '';
restoreSelection();
if (newValue) {
editor.focus();
execCommand($(this).data(options.commandRole), newValue);
}
saveSelection();
}).on('focus', function () {
var input = $(this);
if (!input.data(options.selectionMarker)) {
markSelection(input, options.selectionColor);
input.focus();
}
}).on('blur', function () {
var input = $(this);
if (input.data(options.selectionMarker)) {
markSelection(input, false);
}
});
toolbar.find('input[type=file][data-' + options.commandRole + ']').change(function () {
restoreSelection();
if (this.type === 'file' && this.files && this.files.length > 0) {
insertFiles(this.files);
}
saveSelection();
this.value = '';
});
},
initFileDrops = function () {
editor.on('dragenter dragover', false)
.on('drop', function (e) {
var dataTransfer = e.originalEvent.dataTransfer;
e.stopPropagation();
e.preventDefault();
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
insertFiles(dataTransfer.files);
}
});
};
options = $.extend({}, $.fn.wysiwyg.defaults, userOptions);
toolbarBtnSelector = 'a[data-' + options.commandRole + '],button[data-' + options.commandRole + '],input[type=button][data-' + options.commandRole + ']';
bindHotkeys(options.hotKeys);
if (options.dragAndDropImages) {
initFileDrops();
}
bindToolbar($(options.toolbarSelector), options);
editor.attr('contenteditable', true)
.on('mouseup keyup mouseout', function () {
saveSelection();
updateToolbar();
});
$(window).bind('touchend', function (e) {
var isInside = (editor.is(e.target) || editor.has(e.target).length > 0),
currentRange = getCurrentRange(),
clear = currentRange && (currentRange.startContainer === currentRange.endContainer && currentRange.startOffset === currentRange.endOffset);
if (!clear || isInside) {
saveSelection();
updateToolbar();
}
});
return this;
};
$.fn.wysiwyg.defaults = {
hotKeys: {
'ctrl+b meta+b': 'bold',
'ctrl+i meta+i': 'italic',
'ctrl+u meta+u': 'underline',
'ctrl+z meta+z': 'undo',
'ctrl+y meta+y meta+shift+z': 'redo',
'ctrl+l meta+l': 'justifyleft',
'ctrl+r meta+r': 'justifyright',
'ctrl+e meta+e': 'justifycenter',
'ctrl+j meta+j': 'justifyfull',
'shift+tab': 'outdent',
'tab': 'indent'
},
toolbarSelector: '[data-role=editor-toolbar]',
commandRole: 'edit',
activeToolbarClass: 'btn-info',
selectionMarker: 'edit-focus-marker',
selectionColor: 'darkgrey',
dragAndDropImages: true,
fileUploadError: function (reason, detail) { console.log("File upload error", reason, detail); }
};
}(window.jQuery));
对应的样式设计:
#editor {
max-height: 250px;
height: 250px;
background-color: white;
border-collapse: separate;
border: 1px solid rgb(204, 204, 204);
padding: 4px;
box-sizing: content-box;
-webkit-box-shadow: rgba(0, 0, 0, 0.0745098) 0px 1px 1px 0px inset;
box-shadow: rgba(0, 0, 0, 0.0745098) 0px 1px 1px 0px inset;
border-top-right-radius: 3px; border-bottom-right-radius: 3px;
border-bottom-left-radius: 3px; border-top-left-radius: 3px;
overflow: scroll;
outline: none;
}
#voiceBtn {
width: 20px;
color: transparent;
background-color: transparent;
transform: scale(2.0, 2.0);
-webkit-transform: scale(2.0, 2.0);
-moz-transform: scale(2.0, 2.0);
border: transparent;
cursor: pointer;
box-shadow: none;
-webkit-box-shadow: none;
} div[data-role="editor-toolbar"] {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
} .dropdown-menu a {
cursor: pointer;
}
如有错误之处,敬请指正,谢谢
包含修改字体,图片上传等功能的文本输入框-Bootstrap的更多相关文章
- 我需要在Web上完成一个图片上传的功能
我需要在Web上完成一个图片上传的功能. 这个页面需要能从手机中选择图片上传. 首先,这个页面是从微信上面触发的,所以修改了微信的的入口地址,增加了身份识别号作为传参. 跳转到页面的时候,页面先检查身 ...
- rails使用bootstrap3-wysiwyg可视化编辑器并实现自定义图片上传插入功能
之前在rails开发中使用了ckeditor作为可视化编辑器,不过感觉ckeditor过于庞大,有很多不需要的功能,而且图片上传功能不好控制不同用户可以互相删除图片,感觉很不好.于是考虑更改可视化编辑 ...
- 使用百度UMeditor富文本编辑器,修改自定义图片上传,修改源码
富文本编辑器,不多说了,这个大家应该都用到过,至于用到的什么版本,那就分很多种 CKEditor:很早以前叫FCK,那个时候也用过,现在改名了,比较流行的一个插件,国外很多公司在用 UEDITOR:百 ...
- ASP利用xhEditor编辑器实现图片上传的功能。
本人这几天在做一个软件,无意中用到xhEditor在线编辑器,这个编辑器虽然看着比较简单,但功能非常强大,大家可以去官网上查看,废话不说了. 这篇文件主要是实现在ASP环境中利用xhEditor编辑器 ...
- KindEditor 修改多图片上传显示限制大小和张数
在使用KindEditor的时候用到多图片上传时,提示有最多上传20张图片,单张图片容量不超过1MB: 修改的文件的地方在:kindeditor\plugins\multiimage\multiima ...
- ASP.Net MVC3 图片上传详解(form.js,bootstrap)
图片上传的插件很多,但很多时候还是不能切合我们的需求,我这里给大家分享个我用一个form,file实现上传四张图片的小demo.完全是用jquery前后交互,没有用插件. 最终效果图如下: 玩过花田人 ...
- 修改DedeCMS图片上传路径命名规则的具体方法步骤
收藏到:0时间:2013-08-23 文章来源:马海祥博客 访问次数:2350 最近在整理网站根目录下文件的时候,发现马海祥博客网站已经有上千个文件夹了,其中光图片文件夹就占了近一半.这个主要 ...
- 我需要在Web上完成一个图片上传的功能(+2)
增加一个页面,用于判断传参是否正确. @{ //判断是否具备会员参数 if (UrlData.Count > 0) { Session["Arg ...
- 我需要在Web上完成一个图片上传的功能后续(+1)
微信入口施工完成.关键字识别中增加了本次活动的"关键字",在系统中增加了链接.不过,由于地址包含私密关键参数,这里隐藏,敬请原谅. 下一步,微信链接的地址页面是要对微信用户的信息进 ...
随机推荐
- 高效而稳定的企业级.NET Office 组件Spire(.NET组件介绍之二)
在项目开发中,尤其是企业的业务系统中,对文档的操作是非常多的,有时几乎给人一种错觉的是”这个系统似乎就是专门操作文档的“.毕竟现在的很多办公中大都是在PC端操作文档等软件,在这些庞大而繁重的业务中,单 ...
- 【深入Java虚拟机】之四:类加载机制
类加载过程 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载.验证.准备.解析.初始化.使用和卸载七个阶段.它们开始的顺序如下图所示: 其中类加载的过程包括了加载.验 ...
- 深入理解 Android 之 View 的绘制流程
概述 本篇文章会从源码(基于Android 6.0)角度分析Android中View的绘制流程,侧重于对整体流程的分析,对一些难以理解的点加以重点阐述,目的是把View绘制的整个流程把握好,而对于特定 ...
- ORACLE中STATUS为INACTIVE但是SERVER为SHARED状态的会话浅析
我们知道当ORACLE数据库启用共享服务器模式时,通过共享服务器模式连接到数据库的会话是有一些特征的.在v$session里面,其SERVER的状态一般为SHARED和NONE, 为SHARED时,表 ...
- 烂泥:redis3.2.3安装与配置
本文由ilanniweb提供友情赞助,首发于烂泥行天下 想要获得更多的文章,可以关注我的微信ilanniweb 前一段时间写过一篇codis集群的文章,写那篇文章主要是因为当时的项目不支持redis自 ...
- 第六代智能英特尔® 酷睿™ 处理器图形 API 开发人员指南
欢迎查看第六代智能英特尔® 酷睿™ 处理器图形 API 开发人员指南,该处理器可为开发人员和最终用户提供领先的 CPU 和图形性能增强.各种新特性和功能以及显著提高的性能. 本指南旨在帮助软件开发人员 ...
- DDD设计中的Unitwork与DomainEvent如何相容?
最近在开发过程中,遇到了一个场景,甚是棘手,在这里分享一下.希望大家脑洞大开一起来想一下解决思路.鄙人也想了一个方案拿出来和大家一起探讨一下是否合理. 一.简单介绍一下涉及的对象概念 工作单元:维护变 ...
- CYQ.Data V5 分布式自动化缓存设计介绍
前方: 其实完成这个功能之前,我就在思考:是先把想法写了来,和大伙讨论讨论后再实现,还是实现后再写文论述自己的思维. 忽然脑后传来一个声音说:你发文后会进入发呆阶段. 所以还是静下心,让我轻轻地把代码 ...
- 需要UWP Vendor一名
工作地点北京,海淀,微软大厦2号楼,小冰项目组.
- Oracle11g CentOS7安装记录
1. 操作系统环境.安装包准备 宿主机:Max OSX 10.10.5 虚拟机:Parallel Desktop 10.1.1 虚拟机操作系统:CentOS-7-x86_64-DVD-1511.iso ...