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. Node.js:常用工具

    ylbtech-Node.js:常用工具 1.返回顶部 1. Node.js 常用工具 util 是一个Node.js 核心模块,提供常用函数的集合,用于弥补核心JavaScript 的功能 过于精简 ...

  2. (Go)01.Windows 安装 Go语言开发环境以及使用

    一.Go语言下载 go语言官方下载地址:https://golang.org/dl/ 找到适合你系统的版本下载,本人下载的是windows msi版本.也可以下载Source自己更深层次研究go语言 ...

  3. js设计模式-组合模式

    组合模式是一种专为创建web上的动态用户界面而量身定制的模式.使用这种模式,可以用一条命令在多个对象上激发复杂的或递归的行为.这可以简化粘合性代码,使其更容易维护,而那些复杂行为则被委托给各个对象. ...

  4. if,elif,else的关系 input print int的用法

    qian=input("找劳保网是什么网站?:")if qian=="zhaolaobaowang.com": print("正确")els ...

  5. BZOJ 3910 并查集+线段树合并

    思路: 1. 并查集+线段树合并 记得f[LCA]==LCA的时候 f[LCA]=fa[LCA] 2.LCT(并不会写啊...) //By SiriusRen #include <cstdio& ...

  6. B - Mike and Cellphone(map)

    Problem description While swimming at the beach, Mike has accidentally dropped his cellphone into th ...

  7. springmvc-servlet.xml 第二种选择

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  8. 使用C#正则表达式获取必应每日图片地址

    微软的Bing搜索引擎首页每天都会提供了一些有趣的图片,下面使用正则表达式获取图片的地址,不管是在手机app还是在网站上都是很好的图片素材,而且每天更新,非常不错. 首先访问微软的API,该地址返回的 ...

  9. 一款APP的开发设计是如何从0到1一步一步设计的

    目前在行业里,关于APP界面设计规范也是层次不齐,很多都还停留在6的设备和ios 9的系统之上,而现在最新的是iphone 7和iOS 10了(更新换代真的很快),我这里说的是最新的iOS 界面设计规 ...

  10. MySQL 5.6 Reference Manual-14.1 Introduction to InnoDB

    14.1 Introduction to InnoDB 14.1.1 InnoDB as the Default MySQL Storage Engine 14.1.2 Checking InnoDB ...