reactjs simple text editor
import React, { Component } from 'react'
import PubSub from 'pubsub'
import GlobalVars from 'globalVars'
import styles from './main.css' // globalVars.runMode
class Text extends Component{
static defaultProps = {
text: '文案内容' };
constructor(props, context) {
super(props)
this.state = {
'content' : props.content
,'Styles' : props.Styles
,'editMode' : false
} PubSub.subscribe('textEditorBar' , (evt) => {
var workingEditor = evt.data
if (workingEditor != this.editorID){
this.hideEditor()
}
})
}
componentWillReceiveProps(nextProps){
this.setState({'Styles' : nextProps.Styles})
} emitChange(evt ){
//https://github.com/sstur/react-rte/blob/master/src/SimpleRichTextEditor.js
var new_content = this.textInput.innerHTML
if (new_content != this.state.content){
this.setState({'content' : new_content})
}
} showEditor(evt){
evt.preventDefault()
this.setState({'editMode' : {'palette' : false}})
}
hideEditor(evt){
this.setState({'editMode' : false})
}
saveSelection() {
//https://github.com/mindmup/bootstrap-wysiwyg/blob/master/bootstrap-wysiwyg.js var sel = window.getSelection()
if (sel.getRangeAt && sel.rangeCount) {
this.selectedRange = sel.getRangeAt()
}
}
updateToolbar() {
var btns = document.querySelectorAll('.' + styles.textEditor + ' li[data-tag]') for (var i=;i< btns.length;i++){
var tag = btns[i].dataset.tag if (document.queryCommandState(tag)){
btns[i].classList.add(styles.editActive)
}else {
btns[i].classList.remove(styles.editActive)
}
}
}
emitKeyUp() {
this.saveSelection()
this.updateToolbar()
}
emitPaste(evt) {
evt.preventDefault()
var content = this.formatContent(evt.clipboardData.getData('Text') , {'nl2br':true})
this.restoreSelection()
document.execCommand('insertHTML', false, content)
this.saveSelection()
}
formatContent(content , opt){
opt = opt || {}
if (!content) return ''
if (opt.nl2br){
//content = content.replace(/<(?:.|\n)*?>/gm, '').replace(/\n/g,'</br/>')
content = content.replace(/\n/g,'</br/>')
}
return content
} restoreSelection() {
var selection = window.getSelection()
if (this.selectedRange) {
try {
selection.removeAllRanges()
} catch (ex) {
document.body.createTextRange().select()
document.selection.empty()
} selection.addRange(this.selectedRange)
}
} setStyles(tag ,new_val){
this.restoreSelection()
document.execCommand(tag ,false , new_val || null)
this.saveSelection()
this.updateToolbar()
}
getSelectionHtml(){
var userSelection
if (window.getSelection) {
// W3C Ranges
userSelection = window.getSelection()
// Get the range:
if (userSelection.getRangeAt){
var range = userSelection.getRangeAt()
var container = range.commonAncestorContainer
if (container.nodeType == ) {
container = container.parentNode
return container.outerHTML
}
//if (container.nodeName === "A") {alert ("Yes, it's an anchor!");}
var clonedSelection = range.cloneContents()
var div = document.createElement('div')
div.appendChild(clonedSelection)
return div.innerHTML
}
} else if (document.selection) {
// Explorer selection, return the HTML
userSelection = document.selection.createRange()
return userSelection.htmlText
} else {
return ''
}
}
setLink(){
this.restoreSelection()
var wSelf = this
var tmp = document.createElement('div')
tmp.innerHTML = this.getSelectionHtml()
var link = tmp.getElementsByTagName('a')
PubSub.publish(
'widgetEditLink'
, {'link' : link[]
,'cbk' : (new_val) => {
this.restoreSelection()
var sText = window.getSelection()
if (new_val.link){
document.execCommand('createlink', false, new_val.link)
//document.execCommand('insertHTML', false, '<a href="' + new_val.link + '" target="' + (new_val.target || '_blank') + '">' + sText + '</a>')
}else{
var range = window.getSelection().getRangeAt()
var container = range.commonAncestorContainer
if (container.nodeType == ) {
container = container.parentNode
}
if (container.nodeName === "A") {
container.outerHTML = container.innerHTML
} }
this.saveSelection()
}
}
,this) }
setWholeStyles(tag , val){
var Styles = {...this.state.Styles }|| {}
if (val){
Styles[tag] = val
} else {
delete Styles[tag]
}
this.setState({'Styles' : Styles})
}
shouldComponentUpdate(newProps, newState){
if (this.props.setProps) {
var state_clone = {...newState}
delete state_clone.editMode
this.props.setProps(state_clone)
}
return true
}
setFontSize(evt){
this.setWholeStyles('fontSize' , evt.target.value)
}
setForeColor(evt){
this.setWholeStyles('color' , evt.target.dataset.color)
}
palette(){
var {editMode} = this.state || {}
this.setState({'editMode' : {'palette': !editMode.palette}})
} render(){
var {content ,Styles ,editMode} = this.state
Styles = Styles || {}
content = this.formatContent(content) var fontsize_options = {
's' : styles.textSmall
,'n' : styles.textNormal
, 'l' : styles.textLarge
}
var fontsize_state = (Styles.fontSize in fontsize_options) ? Styles.fontSize :'n'
var wrapper_cls = styles.textWrapper
var fontsize_cls = fontsize_options[fontsize_state]
if (fontsize_cls) wrapper_cls += ' ' + fontsize_cls var StylesClone = {...Styles}
delete StylesClone.fontSize if ('edit' == GlobalVars.runMode){
if (editMode) {
editMode = editMode || {}
//fontSize foreColor
var size_options = []
;[{'txt' :'小' ,'val' : 's'}
,{'txt' :'普通' ,'val' : 'n'}
,{'txt' : '大' ,'val' : 'l'}].forEach((item , i) => {
size_options.push(<option key={i} value={item.val}>{item.txt}</option>)
}) var color_options = []
;['#f00','#ccc' , '#0ff','#f69'].forEach((color , i) => {
color_options.push(<li key={i} onClick={this.setForeColor.bind(this)} data-color={color} style={{'color':color}}>{color}</li>) }) var palette_style = {}
if (editMode.palette) {
palette_style.display = 'block'
}
var edit_btn = (
<ul className={styles.textEditor}>
<li data-tag='bold' onClick={this.setStyles.bind(this,'bold')}>B</li>
<li data-tag='italic' onClick={this.setStyles.bind(this,'italic')}>I</li>
<li data-tag='underline' onClick={this.setStyles.bind(this,'underline')}>U</li> <li data-tag='justifyLeft' onClick={this.setStyles.bind(this,'justifyLeft')}>L</li>
<li data-tag='justifyCenter' onClick={this.setStyles.bind(this,'justifyCenter')}>C</li>
<li data-tag='justifyRight' onClick={this.setStyles.bind(this,'justifyRight')}>R</li>
<li data-tag='justifyFull' onClick={this.setStyles.bind(this,'justifyFull')}>F</li> <li onClick={this.setLink.bind(this)}>Link</li> <li onClick={this.palette.bind(this)} className={styles.textColorEditor}>
Color
<ul style={palette_style}>
<li onClick={this.setForeColor.bind(this)} data-color='' style={{'color':'grey'}}>默认</li>
{color_options}
</ul>
</li>
<li>
<select value={fontsize_state} onChange={this.setFontSize.bind(this)}>
{size_options}
</select>
</li>
</ul>)
}
var holder_cls = `${styles.textHolder} textEditorHolder`
this.editorID = uuid()
return (
<div className={holder_cls} data-editorid={this.editorID}>
<div
contentEditable
suppressContentEditableWarning
ref={(input) => this.textInput = input}
onInput={this.emitChange.bind(this)}
onBlur={this.emitChange.bind(this )}
onClick={this.showEditor.bind(this)}
onKeyUp={this.emitKeyUp.bind(this)}
onMouseUp={this.emitKeyUp.bind(this)}
onPaste={this.emitPaste.bind(this)}
style={StylesClone}
className={wrapper_cls}
dangerouslySetInnerHTML={{__html:content}}
></div>
{edit_btn}
</div>
) }else {
return (
<div style={StylesClone} className={wrapper_cls}>{content}</div>
)
}
}
}
export default Text
reactjs simple text editor的更多相关文章
- CSU1019: Simple Line Editor
1019: Simple Line Editor Submit Page Summary Time Limit: 1 Sec Memory Limit: 128 Mb Subm ...
- Rich Text Editor for MVC
在网站开发中难免会用到富文本编辑器,本文将介绍一款富文本编辑器(在线HTML编辑器) Rich Text Editor ,简要说明一下其在MVC中的使用. 具体使用情况和下载地址请参考:http:// ...
- Android开展:ADT+Eclipse使用错误:Text editor does not have a document provider
Eclipse参加Android sdk源代码 正在使用Eclipse进行Android开发时间,我们经常需要导入sdk源代码来Eclipse中,方便api阅读和查询,详细操作为:ctrl+鼠标左键. ...
- web & Rich Text Editor
web & Rich Text Editor 富文本编辑器 http://www.wangeditor.com/ https://github.com/wangfupeng1988/wangE ...
- DevExpress ASP.NET Core v19.1版本亮点:Rich Text Editor
行业领先的.NET界面控件DevExpress 发布了v19.1版本,本文将以系列文章的方式为大家介绍DevExpress ASP.NET Core Controls v19.1中新增的一些控件及增强 ...
- Download EditPlus Text Editor
突然发现EditPlus还是很强大的,很好用,破解也很方便,有个牛人做了在线生成验证码,只能说服!! 下边把官网的最新下载地址贴出,当然还有在线生成验证码喽. EditPlus Text Editor ...
- CHtmlEditCtrl(1) : Use CHtmlEditCtrl to Create a Simple HTML Editor
I needed a lightweight HTML editor to generate "rich text" emails, so I decided to explore ...
- CHtmlEditCtrl (2): Add a Source Text Editor to Your HTML Editor
In a previous article, I described how to create an HTML editor using the MFC CHtmlEditCtrl class in ...
- 中南大学2018年ACM暑期集训前期训练题集(入门题) Q: Simple Line Editor
数据有毒,一个一个读字符是错,整个字符串读入,一次就A了. 总之,数据总是没有错的,还是对c++了解地不够深刻,还有,在比赛中,一定要有勇气重构代码 错误代码: #include<iostrea ...
随机推荐
- MongoDB如何实现读写分离
MongoDB如何实现读写分离 MongoDB复制集(Replica Set)通过存储多份数据副本来保证数据的高可靠,通过自动的主备切换机制来保证服务的高可用.但需要注意的时,连接副本集的姿势如果不对 ...
- C Linux read write function extension
前言 - 赠送 readn / writen Linux 上默认的 read 和 write 函数会被信号软中断. 且 read 和 write 函数中第三个参数 count #include < ...
- 2.Ventuz Designer常用工具介绍
Ventuz Designer常用工具介绍 1. 打开Ventuz Designer 图1.1 2. Ventuz Designer第一个界面 图2.1 Recent Projects:最近创建的 ...
- Git Learning Part II - Working locally
file status life circle basic: modified: Examples: untracked: unmodified: modified: Git branching ...
- 函数的arguments
1.arguments a.只能在函数内部被访问. b.arguments是一个伪数组(有下标索引,可以存放多个值,但是他里面没有数组的方法.) c.arguments里面存的是什么?函数的实际参数传 ...
- testdirector
TestDirector是全球最大的软件测试工具提供商Mercury Interactive公司生产的企业级测试管理工具,也是业界第一个基于Web的测试管理系统
- 2 Selenium3.0+Python3.6环境搭建
[说明] 再次搭建一次环境,是因为遇到怎么都打不开IE的问题了,环境信息为:Selenium3.0+Python3.6+win7+ie10 [搭建步骤] 1.下载Python3.6,并点击安装和配置环 ...
- 2017/01/20 学习笔记 关于修改和重打jar包
背景 客户提供了jar包,但发现db表中缺少一个字段,db追加以后需要修改jar包中的source. 操作 如何修改jar包中的source并重新打一个新的jar包,做了如下操作. ① 开包 解压j ...
- xshell登录centos7很慢解决办法
使用xshell登录到centos系统虚拟机,可以登录上去,但是认证速度特别慢. 因为在登录时,需要反向解析dns,因此,修改linux配置文件,vi /etc/ssh/sshd_config,将其注 ...
- 如何分页爬取数据--beautisoup
'''本次爬取讲历史网站'''#!usr/bin/env python#-*- coding:utf-8 _*-"""@author:Hurrican@file: 分页爬 ...