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的更多相关文章

  1. CSU1019: Simple Line Editor

    1019: Simple Line Editor Submit Page   Summary   Time Limit: 1 Sec     Memory Limit: 128 Mb     Subm ...

  2. Rich Text Editor for MVC

    在网站开发中难免会用到富文本编辑器,本文将介绍一款富文本编辑器(在线HTML编辑器) Rich Text Editor ,简要说明一下其在MVC中的使用. 具体使用情况和下载地址请参考:http:// ...

  3. Android开展:ADT+Eclipse使用错误:Text editor does not have a document provider

    Eclipse参加Android sdk源代码 正在使用Eclipse进行Android开发时间,我们经常需要导入sdk源代码来Eclipse中,方便api阅读和查询,详细操作为:ctrl+鼠标左键. ...

  4. web & Rich Text Editor

    web & Rich Text Editor 富文本编辑器 http://www.wangeditor.com/ https://github.com/wangfupeng1988/wangE ...

  5. DevExpress ASP.NET Core v19.1版本亮点:Rich Text Editor

    行业领先的.NET界面控件DevExpress 发布了v19.1版本,本文将以系列文章的方式为大家介绍DevExpress ASP.NET Core Controls v19.1中新增的一些控件及增强 ...

  6. Download EditPlus Text Editor

    突然发现EditPlus还是很强大的,很好用,破解也很方便,有个牛人做了在线生成验证码,只能说服!! 下边把官网的最新下载地址贴出,当然还有在线生成验证码喽. EditPlus Text Editor ...

  7. 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 ...

  8. 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 ...

  9. 中南大学2018年ACM暑期集训前期训练题集(入门题) Q: Simple Line Editor

    数据有毒,一个一个读字符是错,整个字符串读入,一次就A了. 总之,数据总是没有错的,还是对c++了解地不够深刻,还有,在比赛中,一定要有勇气重构代码 错误代码: #include<iostrea ...

随机推荐

  1. Hashmap 详解和迭代器问题

    重点介绍HashMap.首先介绍一下什么是Map.在数组中我们是通过数组下标来对其内容索引的,而在Map中我们通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value.在下文中会 ...

  2. 浅析CLR的事件

    文章目录:     1.C#(.net framework框架)中的事件以及特点 2.事件的组成部分 3.编辑器如何实现事件的         4.显式实现事件 1.C#(.net framework ...

  3. &nbsp; 等等空格用法

    平时经常用到 空格转移字符,记住一个   表示一个字符就可以了. Non-Breaking SPace 记住它是什么的缩写,更有助于我们记忆和使用.下面的字符转义自己视图翻译一下. 记录一下,空格的转 ...

  4. Django学习案例一(blog):一. 创建project、app

    1.创建project 方法1:使用命令行创建项目.在E盘cmd执行如下命令: django-admin.py startproject myblog 方法2:使用pycharm创建项目.放置位置为D ...

  5. 给<hr/>添加样式

    点线式 破折线式 直线式 双线式 脊线式 槽线式 内嵌效果的 突起效果的 border-top:10px 设置水平线的大小 <hr style=" border-top:5px dot ...

  6. Android 解决toolbar标题不显示问题

    问题原因:toolbar的兼容性有问题 解决办法: setSupportActionBar(toolbar); toolbar使用步骤: 1.编写menu.xml 为了保持兼容需要这样写: andro ...

  7. python第三方模块大杂烩

    Python单元测试框架之pytest---如何执行测试用例 unittest单元测试框架实现参数化 (用例有相似参数断言时使用,可以精简代码) python中标示符作用详解 一篇文章让你彻底搞清楚P ...

  8. 使用PyQT编写界面程序

    使用PyQT比QT好在,可以随时监测函数正确性,省去编译时间 ! 这是个不小的节省. 1. PyQt: 打开对话框 msgbox = QtGui.QMessageBox(self)# 我的语句是 ms ...

  9. 如何选择优动漫PAINT版本?是个人版还是EX版

    优动漫PAINT也就是我们常说的clip studio paint(CSP)的中文版本,它是一款功能强大的动漫绘图软件,适用于个人和专业团队创作,分为个人版和EX版.搭载了绘制漫画和插画所需的所有功能 ...

  10. Dynamics CRM 使用 Profiler 来做debug

    首先,我们需要install Profiler 我们选中一个plugin, 并且选择start Profilling 然后我们选择Persist to Entity 然后我们执行trigger这个pl ...