无论是博主自己写文章还是读者发表评论,都需要一个方便的编辑框,html自带的textarea和editable div都过于简单,本文将记录在webpack环境中添加jquery和Simditor的过程,同时加入emoji功能。

从零搭建个人博客(1)-webpack环境配置
从零搭建个人博客(2)-博客UI搭建

安装并使用Simditor

使用npm安装,由于simditor依赖jquery,所以需要安装如下几个库:

npm install jquery simditor expose-loader --save

官方文档:http://simditor.tower.im/docs/doc-usage.html。
文档中说明需要引用如下依赖:

<link rel="stylesheet" type="text/css" href="[style path]/simditor.css" />

<script type="text/javascript" src="[script path]/jquery.min.js"></script>
<script type="text/javascript" src="[script path]/module.js"></script>
<script type="text/javascript" src="[script path]/hotkeys.js"></script>
<script type="text/javascript" src="[script path]/uploader.js"></script>
<script type="text/javascript" src="[script path]/simditor.js"></script>

这里按需引入即可。首先在webpack中配置jquery,在module的loaders里加入

{
test: require.resolve('jquery'),
loader: 'expose-loader?$!expose-loader?jQuery', // jQuery and $
}

这样就可以全局引用jquery了,也方便以后使用jquery的ajax等功能,使用时直接import就行。

import $ from 'expose-loader?$!jquery';

同时我们要在入口文件中引入simditor的css文件

import '../node_modules/simditor/styles/simditor.scss';

simditor是对已有textarea的增强,所以使用时首先在react的render中插入一个textarea,这里使用react-bootstrap。

<FormGroup controlId="MainParentMessageBox">
<FormControl componentClass="textarea" placeholder="留言" ref={'editor'} />
<Button type="submit">提交</Button>
</FormGroup>

在componentDidMount中拿到这个textarea对应的dom节点并增强。

componentDidMount() {
const textbox = ReactDOM.findDOMNode(this.refs.editor);
this.editor = new Simditor({
textarea: textbox,
toolbar: ['title', 'bold', 'italic', 'underline', 'strikethrough', 'color', 'ol', 'ul', 'link', 'alignment']
});
}

Simditor的参数可以参考官方文档http://simditor.tower.im/docs/doc-usage.html。

emoji

使用npm安装

npm install simditor-emoji

在入口文件中import css文件:

import '../node_modules/simditor-emoji/styles/simditor-emoji.scss';

下面问题出现了,simditor-emoji.js无法加载进来,从node_module将simditor-emoji.js拷贝一份放到resource文件夹中,去掉文件头部的amd模块定义方式:

(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module unless amdModuleId is set
define('simditor-emoji', ["jquery","simditor"], function (a0,b1) {
return (root['EmojiButton'] = factory(a0,b1));
}
)
;
}
else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory(require("jquery"),require("Simditor"));
}
else {
root['SimditorEmoji'] = factory(jQuery,Simditor);
}

}
(this, function ($, Simditor) {

并import jquery和Simditor,取名emoji.js,变成如下代码。

import $ from 'expose-loader?$!jquery';
import Simditor from 'simditor';

const hasProp = {}.hasOwnProperty;
const slice = [].slice;
const extend = (child, parent) => { for (const key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

const EmojiButton = ((superClass) => {
function NewEmojiButton() {
const args = arguments.length >= 1 ? slice.call(arguments, 0) : [];
NewEmojiButton.__super__.constructor.apply(this, args);
$.merge(this.editor.formatter._allowedAttributes.img, ['data-emoji', 'alt']);
}

extend(NewEmojiButton, superClass);

NewEmojiButton.i18n = {
'zh-CN': {
emoji: '表情'
},
'en-US': {
emoji: 'emoji'
}
};

NewEmojiButton.images = ['smile', 'smiley', 'laughing', 'blush', 'heart_eyes', 'smirk', 'flushed', 'grin', 'wink', 'kissing_closed_eyes', 'stuck_out_tongue_winking_eye', 'stuck_out_tongue', 'sleeping', 'worried', 'expressionless', 'sweat_smile', 'cold_sweat', 'joy', 'sob', 'angry', 'mask', 'scream', 'sunglasses', 'heart', 'broken_heart', 'star', 'anger', 'exclamation', 'question', 'zzz', 'thumbsup', 'thumbsdown', 'ok_hand', 'punch', 'v', 'clap', 'muscle', 'pray', 'skull', 'trollface'];

NewEmojiButton.prototype.name = 'emoji';

NewEmojiButton.prototype.icon = 'smile-o';

NewEmojiButton.prototype.menu = true;

NewEmojiButton.prototype.renderMenu = function renderMenu() {
const tpl = '<ul class="emoji-list">\n</ul>';
const opts = $.extend({
imagePath: 'images/emoji/',
images: NewEmojiButton.images
}, this.editor.opts.emoji || {});
let html = '';
const dir = opts.imagePath.replace(/\/$/, '') + '/';
const ref = opts.images;
for (let i = 0, len = ref.length; i < len; i++) {
const name = ref[i];
html += "<li data-name='" + name + "'><img src='" + dir + name + ".png' width='20' height='20' alt='" + name + "' /></li>";
}
const $list = $(tpl);
$list.html(html).appendTo(this.menuWrapper);
return $list.on('mousedown', 'li', ((_this) => {
return (e) => {
_this.wrapper.removeClass('menu-on');
if (!_this.editor.inputManager.focused) {
return;
}
const $img = $(e.currentTarget).find('img').clone().attr({
'data-emoji': true,
'data-non-image': true
});
_this.editor.selection.insertNode($img);
_this.editor.trigger('valuechanged');
_this.editor.trigger('selectionchanged');
};
})(this));
};

NewEmojiButton.prototype.status = () => {};

return NewEmojiButton;
})(Simditor.Button);
Simditor.Toolbar.addButton(EmojiButton);

之后在入口文件将它require进来。

require('./resource/js/emoji');

使用时将emoji加入到Simditor中去。

componentDidMount() {
const textbox = ReactDOM.findDOMNode(this.refs.MainParentMessageBox);
this.editor = new Simditor({
textarea: textbox,
toolbar: ['title', 'bold', 'italic', 'underline', 'strikethrough', 'color', 'ol', 'ul', 'link', 'alignment', 'emoji'],
emoji: {
imagePath: './emoji'
}
});
}

这里还有一个大坑,imagePath的路径比较麻烦,在simditor-emoji.js中用到了这个路径并使用了img的src属性来放置该路径,为打包带来了很大麻烦,这里有个解决方案,感觉不是很完美,最后还是打算直接塞进去服务器中的图片存放地址。

更多相关文章

  1. 从JQuery文件输入中获取数据
  2. jQuery LightBox(SlimBox):如何在其中填充ASPX文件?
  3. JQuery和Struts实现Ajax文件上传
  4. 如何在metro javascript和html中读取和写入现有的xml文件
  5. XHTML 相对路径与绝对路径
  6. 使用jQuery和AJAX从JSON文件加载数据
  7. vim / vi / linux:正确缩进html文件
  8. html 引用文件编码为utf-8 的 js文件乱码问题
  9. CSS文件filemtime没有调用路径两次

随机推荐

  1. Android(安卓)权限大全
  2. Android中关于Bitmap的裁剪缩放和创建
  3. android使用SharedPreferences存储和读取
  4. android 刚进入activity 时关闭输入法
  5. Android(安卓)(DiskLruCache)硬盘缓存代码
  6. LocationManager 的requestLocationUpdat
  7. Android Wi-Fi 修改国家码(QCOM平台)
  8. h5在线动态页面调用app原生方法
  9. Android 小代码集
  10. android9.0 关闭launcher界面的搜索框