首页 > 代码库 > reactjs simple text editor
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 userSelection111 if (window.getSelection) {112 // W3C Ranges113 userSelection = window.getSelection()114 // Get the range:115 if (userSelection.getRangeAt){116 var range = userSelection.getRangeAt(0)117 var container = range.commonAncestorContainer118 if (container.nodeType == 3) {119 container = container.parentNode120 return container.outerHTML121 }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.innerHTML127 }128 } else if (document.selection) {129 // Explorer selection, return the HTML130 userSelection = document.selection.createRange()131 return userSelection.htmlText132 } else {133 return ‘‘134 }135 }136 setLink(){137 this.restoreSelection()138 var wSelf = this139 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="http://www.mamicode.com/‘ + new_val.link + ‘" target="‘ + (new_val.target || ‘_blank‘) + ‘">‘ + sText + ‘</a>‘)151 }else{152 var range = window.getSelection().getRangeAt(0)153 var container = range.commonAncestorContainer154 if (container.nodeType == 3) {155 container = container.parentNode156 }157 if (container.nodeName === "A") {158 container.outerHTML = container.innerHTML159 }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] = val172 } 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.editMode181 this.props.setProps(state_clone) 182 }183 return true184 }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.state198 Styles = Styles || {}199 content = this.formatContent(content) 200 201 var fontsize_options = {202 ‘s‘ : styles.textSmall 203 ,‘n‘ : styles.textNormal204 , ‘l‘ : styles.textLarge205 }206 var fontsize_state = (Styles.fontSize in fontsize_options) ? Styles.fontSize :‘n‘207 var wrapper_cls = styles.textWrapper208 var fontsize_cls = fontsize_options[fontsize_state] 209 if (fontsize_cls) wrapper_cls += ‘ ‘ + fontsize_cls210 211 212 var StylesClone = {...Styles}213 delete StylesClone.fontSize214 215 if (‘edit‘ == GlobalVars.runMode){216 if (editMode) {217 editMode = editMode || {}218 //fontSize foreColor219 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=http://www.mamicode.com/{item.val}>{item.txt})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 Color252 <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=http://www.mamicode.com/{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 <div269 contentEditable270 suppressContentEditableWarning271 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 onm ouseUp={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
reactjs simple text editor
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。