reactjs simple text editor

  1 import React, { Component } from ‘react‘
  2 import PubSub from ‘pubsub‘
  3 import GlobalVars from ‘globalVars‘
  4 import styles from ‘./main.css‘
  5
  6 // globalVars.runMode
  7 class Text extends Component{
  8     static defaultProps = {
  9         text: ‘文案内容‘
 10
 11     };
 12     constructor(props, context) {
 13         super(props)
 14         this.state = {
 15                 ‘content‘ : props.content
 16                ,‘Styles‘ : props.Styles
 17                ,‘editMode‘ : false
 18             }
 19
 20         PubSub.subscribe(‘textEditorBar‘ , (evt) => {
 21             var workingEditor = evt.data
 22             if (workingEditor != this.editorID){
 23                 this.hideEditor()
 24             }
 25         })
 26     }
 27     componentWillReceiveProps(nextProps){
 28         this.setState({‘Styles‘ : nextProps.Styles})
 29     }
 30
 31     emitChange(evt ){
 32         //https://github.com/sstur/react-rte/blob/master/src/SimpleRichTextEditor.js
 33         var new_content = this.textInput.innerHTML
 34         if (new_content != this.state.content){
 35             this.setState({‘content‘ : new_content})
 36         }
 37     }
 38
 39     showEditor(evt){
 40         evt.preventDefault()
 41         this.setState({‘editMode‘ : {‘palette‘ : false}})
 42     }
 43     hideEditor(evt){
 44        this.setState({‘editMode‘ : false})
 45     }
 46     saveSelection() {
 47         //https://github.com/mindmup/bootstrap-wysiwyg/blob/master/bootstrap-wysiwyg.js
 48
 49         var sel = window.getSelection()
 50         if (sel.getRangeAt && sel.rangeCount) {
 51             this.selectedRange = sel.getRangeAt(0)
 52         }
 53     }
 54     updateToolbar() {
 55         var btns = document.querySelectorAll(‘.‘ + styles.textEditor + ‘ li[data-tag]‘)
 56
 57         for (var i=0;i< btns.length;i++){
 58             var tag = btns[i].dataset.tag
 59
 60             if (document.queryCommandState(tag)){
 61                 btns[i].classList.add(styles.editActive)
 62             }else {
 63                 btns[i].classList.remove(styles.editActive)
 64             }
 65         }
 66     }
 67     emitKeyUp() {
 68         this.saveSelection()
 69         this.updateToolbar()
 70     }
 71     emitPaste(evt) {
 72         evt.preventDefault()
 73         var content = this.formatContent(evt.clipboardData.getData(‘Text‘) , {‘nl2br‘:true})
 74         this.restoreSelection()
 75         document.execCommand(‘insertHTML‘, false, content)
 76         this.saveSelection()
 77     }
 78     formatContent(content , opt){
 79         opt = opt || {}
 80         if (!content) return ‘‘
 81         if (opt.nl2br){
 82             //content = content.replace(/<(?:.|\n)*?>/gm, ‘‘).replace(/\n/g,‘</br/>‘)
 83             content = content.replace(/\n/g,‘</br/>‘)
 84         }
 85         return content
 86     }
 87
 88     restoreSelection() {
 89         var selection = window.getSelection()
 90         if (this.selectedRange) {
 91             try {
 92                 selection.removeAllRanges()
 93             } catch (ex) {
 94                 document.body.createTextRange().select()
 95                 document.selection.empty()
 96             }
 97
 98             selection.addRange(this.selectedRange)
 99         }
100     }
101
102
103     setStyles(tag ,new_val){
104         this.restoreSelection()
105         document.execCommand(tag ,false , new_val || null)
106         this.saveSelection()
107         this.updateToolbar()
108     }
109     getSelectionHtml(){
110         var userSelection
111         if (window.getSelection) {
112             // W3C Ranges
113             userSelection = window.getSelection()
114             // Get the range:
115             if (userSelection.getRangeAt){
116                 var range = userSelection.getRangeAt(0)
117                 var container = range.commonAncestorContainer
118                 if (container.nodeType == 3) {
119                     container = container.parentNode
120                     return container.outerHTML
121                 }
122                 //if (container.nodeName === "A") {alert ("Yes, it‘s an anchor!");}
123                 var clonedSelection = range.cloneContents()
124                 var div = document.createElement(‘div‘)
125                 div.appendChild(clonedSelection)
126                 return div.innerHTML
127             }
128         } else if (document.selection) {
129             // Explorer selection, return the HTML
130             userSelection = document.selection.createRange()
131             return userSelection.htmlText
132         } else {
133             return ‘‘
134         }
135     }
136     setLink(){
137         this.restoreSelection()
138         var wSelf = this
139         var tmp = document.createElement(‘div‘)
140         tmp.innerHTML = this.getSelectionHtml()
141         var link = tmp.getElementsByTagName(‘a‘)
142         PubSub.publish(
143                 ‘widgetEditLink‘
144                 , {‘link‘ : link[0]
145                     ,‘cbk‘ : (new_val) => {
146                         this.restoreSelection()
147                         var sText = window.getSelection()
148                         if (new_val.link){
149                             document.execCommand(‘createlink‘, false, new_val.link)
150                             //document.execCommand(‘insertHTML‘, false, ‘<a href="‘ + new_val.link + ‘" target="‘ + (new_val.target || ‘_blank‘) + ‘">‘ + sText + ‘</a>‘)
151                         }else{
152                             var range = window.getSelection().getRangeAt(0)
153                             var container = range.commonAncestorContainer
154                             if (container.nodeType == 3) {
155                                 container = container.parentNode
156                             }
157                             if (container.nodeName === "A") {
158                                 container.outerHTML = container.innerHTML
159                             }
160
161                         }
162                         this.saveSelection()
163                     }
164                 }
165         ,this)
166
167     }
168     setWholeStyles(tag , val){
169         var Styles = {...this.state.Styles }|| {}
170         if (val){
171             Styles[tag] = val
172         } else {
173             delete Styles[tag]
174         }
175         this.setState({‘Styles‘ : Styles})
176     }
177     shouldComponentUpdate(newProps, newState){
178         if (this.props.setProps) {
179             var state_clone = {...newState}
180             delete state_clone.editMode
181             this.props.setProps(state_clone)
182         }
183         return true
184     }
185     setFontSize(evt){
186         this.setWholeStyles(‘fontSize‘ , evt.target.value)
187     }
188     setForeColor(evt){
189         this.setWholeStyles(‘color‘ , evt.target.dataset.color)
190     }
191     palette(){
192         var {editMode} = this.state || {}
193         this.setState({‘editMode‘ : {‘palette‘: !editMode.palette}})
194     }
195
196     render(){
197         var {content ,Styles ,editMode}  = this.state
198         Styles = Styles || {}
199         content = this.formatContent(content)
200
201         var fontsize_options = {
202             ‘s‘ : styles.textSmall
203             ,‘n‘ : styles.textNormal
204             , ‘l‘ : styles.textLarge
205         }
206         var fontsize_state = (Styles.fontSize in fontsize_options) ? Styles.fontSize :‘n‘
207         var wrapper_cls = styles.textWrapper
208         var fontsize_cls = fontsize_options[fontsize_state]
209         if (fontsize_cls) wrapper_cls += ‘ ‘ + fontsize_cls
210
211
212         var StylesClone = {...Styles}
213         delete StylesClone.fontSize
214
215         if (‘edit‘ == GlobalVars.runMode){
216             if (editMode) {
217                 editMode = editMode || {}
218                 //fontSize foreColor
219                 var size_options = []
220                 ;[{‘txt‘ :‘小‘ ,‘val‘ : ‘s‘}
221                 ,{‘txt‘ :‘普通‘ ,‘val‘ : ‘n‘}
222                 ,{‘txt‘ : ‘大‘ ,‘val‘ : ‘l‘}].forEach((item , i) => {
223                     size_options.push(<option key={i} value={item.val}>{item.txt}</option>)
224                 })
225
226                 var color_options = []
227                 ;[‘#f00‘,‘#ccc‘ , ‘#0ff‘,‘#f69‘].forEach((color , i) => {
228                     color_options.push(<li key={i} onClick={this.setForeColor.bind(this)} data-color={color} style={{‘color‘:color}}>{color}</li>)
229
230                 })
231
232                 var palette_style = {}
233                 if (editMode.palette) {
234                     palette_style.display = ‘block‘
235                 }
236                 var edit_btn = (
237                     <ul className={styles.textEditor}>
238                         <li data-tag=‘bold‘  onClick={this.setStyles.bind(this,‘bold‘)}>B</li>
239                         <li data-tag=‘italic‘  onClick={this.setStyles.bind(this,‘italic‘)}>I</li>
240                         <li data-tag=‘underline‘  onClick={this.setStyles.bind(this,‘underline‘)}>U</li>
241
242                         <li data-tag=‘justifyLeft‘ onClick={this.setStyles.bind(this,‘justifyLeft‘)}>L</li>
243                         <li data-tag=‘justifyCenter‘ onClick={this.setStyles.bind(this,‘justifyCenter‘)}>C</li>
244                         <li data-tag=‘justifyRight‘  onClick={this.setStyles.bind(this,‘justifyRight‘)}>R</li>
245                         <li data-tag=‘justifyFull‘ onClick={this.setStyles.bind(this,‘justifyFull‘)}>F</li>
246
247
248                         <li onClick={this.setLink.bind(this)}>Link</li>
249
250                         <li onClick={this.palette.bind(this)} className={styles.textColorEditor}>
251                             Color
252                             <ul style={palette_style}>
253                                 <li  onClick={this.setForeColor.bind(this)} data-color=‘‘ style={{‘color‘:‘grey‘}}>默认</li>
254                                 {color_options}
255                             </ul>
256                         </li>
257                         <li>
258                         <select value={fontsize_state}  onChange={this.setFontSize.bind(this)}>
259                             {size_options}
260                        </select>
261                         </li>
262                     </ul>)
263             }
264             var holder_cls = `${styles.textHolder} textEditorHolder`
265             this.editorID = uuid()
266             return (
267                 <div className={holder_cls} data-editorid={this.editorID}>
268                     <div
269                         contentEditable
270                         suppressContentEditableWarning
271                         ref={(input) => this.textInput = input}
272                         onInput={this.emitChange.bind(this)}
273                         onBlur={this.emitChange.bind(this )}
274                         onClick={this.showEditor.bind(this)}
275                         onKeyUp={this.emitKeyUp.bind(this)}
276                         onMouseUp={this.emitKeyUp.bind(this)}
277                         onPaste={this.emitPaste.bind(this)}
278                         style={StylesClone}
279                         className={wrapper_cls}
280                         dangerouslySetInnerHTML={{__html:content}}
281                     ></div>
282                     {edit_btn}
283                 </div>
284             )
285
286         }else {
287             return (
288                 <div style={StylesClone} className={wrapper_cls}>{content}</div>
289             )
290         }
291     }
292 }
293 export default Text
时间: 2024-12-16 02:09:43

reactjs simple text editor的相关文章

哈理工 oj——Simple Line Editor

Simple Line Editor Time Limit: 1000 MS Memory Limit: 65536 K Total Submit: 573(151 users) Total Accepted: 183(139 users) Rating: Special Judge: No Description Early computer used line editor, which allowed text to be created and changed only within o

10款优秀的Rich Text Editor

Introduction Javascript rich text editor has ease our life when we need to edit articles, post or even documents online. Most of the editors allow user to edit the content straight away (What You See Is What You Get - WYSIWYG), it just like editting

Download EditPlus Text Editor

突然发现EditPlus还是很强大的,很好用,破解也很方便,有个牛人做了在线生成验证码,只能说服!! 下边把官网的最新下载地址贴出,当然还有在线生成验证码喽. EditPlus Text Editor下载 Download EditPlus Text Editor Supported Operating Systems Windows 8.1/8/7/Vista/XP EditPlus Text Editor 3.70 Evaluation Version (1.96 MB)Download (

HDU 1981 A Special Text Editor

Problem Description After AC all the hardest problems in the world , the ACboy 8006 now has nothing to do . So he develops a special text editor.The text editor is so special that it only supports 3 special operation: "Reverse","Shift"

控件之应用-创建Text Editor教程

原文地址 http://www.baidusap.com/abap/dialog/1627 1, Text Editor介绍 不同于一般的屏幕字段,Text Editor可以保存多行文本,它是SAP各种凭证中常用的控件之一,比如采购订单中,凭证头和行项目中都应用到text editor控件,如下: 2, 创建text editor控件 下面介绍如何在dailog程序中创建一个text editor控件, 2.1, SE80创建dialog程序 Tcode:se80,创建一个dialog程序,并且

Change shortcut key of forward navigation in VS2012 text editor

Keywords: Visual Studio, shortcut key, Alt, Right Arrow, navigation, NavigateForward, CompleteWord If you want to assign shortcut key to Alt+Right Arrow (from Ctrl+Shift+-), please following these steps: 1. Open Tools\Options\Environment\Keyboard, lo

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

行业领先的.NET界面控件DevExpress 发布了v19.1版本,本文将以系列文章的方式为大家介绍DevExpress ASP.NET Core Controls v19.1中新增的一些控件及增强的控件功能,欢迎下载v19.1试用,点击立即下载>> Pivot Grid 新的富文本编辑器 全新的ASP.NET Core Rich Text Editor附带了您在ASP.NET Core应用程序中快速合并高级文本编辑功能所需的一切. 其功能包括: 文件导入/导出(docx,rtf,txt)

Libgdx学习笔记:Simple text input

官方Wiki:https://github.com/libgdx/libgdx/wiki/Simple-text-input 实现接口TextInputListener public class MyTextInputListener implements TextInputListener {       @Override    public void input (String text) {    }       @Override    public void canceled () 

Lecture 9: vim : An Advanced Text Editor vim编辑器

q:quit w:write q!:强制退出 实用的功能 o:当前行的下面插入一行 O:当前光标的上一行插入一行 home:行首 end:行尾 i:进入插入模式 esc :回到命令模式 命令行模式:G表示文件最末尾,g按两下 跳到文件第一行 100G:跳到第100行 :150回车 直接跳到150行 /xxx :查找xxx n:向下查找 N:向上查找 满屏的颜色字,随意敲打几个单词就可以了. 搜索替换 :%s/ssl/sss/g dd:以行为单位 dd什么都不做,就是删除,p代表粘贴 5dd.10