├── .gitignore ├── src ├── index.js ├── uid.js └── richtext.js ├── .babelrc ├── examples ├── app.js ├── index.html └── components │ └── page1.js ├── lib ├── uid.js ├── index.js └── richtext.js ├── package.json ├── webpack.dev.config.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import RichText from './richtext'; 2 | 3 | export default RichText; -------------------------------------------------------------------------------- /src/uid.js: -------------------------------------------------------------------------------- 1 | const now = +(new Date()); 2 | let index = 0; 3 | 4 | export default function uid() { 5 | return `bee-${now}-${++index}`; 6 | } 7 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "env", 4 | "es2015", 5 | "react", 6 | "stage-2" 7 | ], 8 | "plugins": ["transform-runtime"] 9 | } -------------------------------------------------------------------------------- /examples/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Page1 from './components/page1.js' 4 | 5 | 6 | ReactDOM.render( 7 | , 8 | document.getElementById('container') 9 | ); 10 | -------------------------------------------------------------------------------- /lib/uid.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = uid; 7 | var now = +new Date(); 8 | var index = 0; 9 | 10 | function uid() { 11 | return "bee-" + now + "-" + ++index; 12 | } -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _richtext = require('./richtext'); 8 | 9 | var _richtext2 = _interopRequireDefault(_richtext); 10 | 11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 12 | 13 | exports.default = _richtext2.default; -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | richtextDemo 8 | 9 | 10 | 11 |
12 | 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-ueditor-wrap", 3 | "version": "1.0.8", 4 | "description": "react ueditor", 5 | "main": "lib/index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/uso51984/react-ueditor" 9 | }, 10 | "license": "MIT", 11 | "keywords": [ 12 | "ueditor", 13 | "react-ueditor", 14 | "rc-ueditor", 15 | "richtext" 16 | ], 17 | "config": { 18 | "name": "react-ueditor", 19 | "entry": { 20 | "react-ueditor": [ 21 | "./src/index.js" 22 | ] 23 | }, 24 | "server": { 25 | "port": 9200 26 | } 27 | }, 28 | "dependencies": {}, 29 | "devDependencies": { 30 | "bee-build-tools": "0.0.26", 31 | "react": "^16.8.6", 32 | "react-dom": "^16.8.6" 33 | }, 34 | "scripts": { 35 | "dist": "bee-tools run dist", 36 | "dev": "webpack-dev-server --config ./webpack.dev.js", 37 | "compile": "bee-tools run compile --babel-runtime", 38 | "buildExample": "bee-tools run buildExample", 39 | "gh-pages": "bee-tools run gh-pages", 40 | "release": "bee-tools run release" 41 | }, 42 | "author": "edmund_chen" 43 | } 44 | -------------------------------------------------------------------------------- /examples/components/page1.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Ueditor from '../../src' 3 | 4 | const value = '

受控设置value值

'; 5 | export default class Page1 extends React.Component { 6 | state ={ 7 | initValue: '', 8 | nowValue: '' 9 | } 10 | 11 | componentDidMount() { 12 | console.log('e23', this.ref) 13 | } 14 | 15 | onChange = (value) => { 16 | this.ueditorValue = value; 17 | this.setState({ nowValue: value }); 18 | } 19 | 20 | onBlur = (value) => { 21 | this.ueditorValue = value; 22 | console.log('----') 23 | this.setState({ nowValue: value }); 24 | } 25 | 26 | getEditorInstance(instance) { 27 | console.log('instance', instance); 28 | } 29 | 30 | render(){ 31 | return( 32 |
33 | 41 | 42 | 43 |

{this.state.nowValue}

44 |
45 | ) 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /webpack.dev.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var path = require('path'); 3 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | 5 | var BUILD_PATH = path.resolve(__dirname, './dist'); 6 | var TMP_PATH = path.resolve(__dirname,'./examples/index.html'); 7 | 8 | module.exports = { 9 | entry: { 10 | 'app': [ 11 | './examples/app.js', 12 | ], 13 | vendor: ['react', 'react-dom'] 14 | }, 15 | output: { 16 | path: BUILD_PATH, 17 | filename: '[name].js' //输出js 18 | }, 19 | plugins: [ 20 | new webpack.optimize.CommonsChunkPlugin({name:'vendor', filename: 'vendor.js'}), 21 | new HtmlWebpackPlugin({ 22 | title: 'reactdemo', 23 | template: TMP_PATH, 24 | filename: 'index.html', 25 | chunks: ['app','vendor'], 26 | inject: 'body' 27 | }), 28 | new webpack.DefinePlugin({ 29 | "process.env": { 30 | NODE_ENV: JSON.stringify("development") // development,production 31 | } 32 | }) 33 | ], 34 | 35 | module: { 36 | loaders: [{ 37 | test: /\.js$/, 38 | loaders: [ 'babel-loader?presets[]=es2015,presets[]=react,presets[]=stage-0'], 39 | exclude: /node_modules/ 40 | },{ 41 | test: /\.less$/, 42 | loaders: ['style', 'css?sourceMap', 'less?&sourceMap&includePaths[]=./user-center/style/index.less'] 43 | }, 44 | { test: /\.css$/, loader: "style-loader!css-loader" } 45 | , 46 | { 47 | test: /\.(png|jpg|gif)$/, 48 | loader: 'file-loader?name=images/[name].[ext]', 49 | }, 50 | { 51 | test: /\.(eot|ttf|svg|woff|woff2)$/, 52 | loader: 'file-loader?name=fonts/[name].[ext]', 53 | }, 54 | ] 55 | } 56 | }; -------------------------------------------------------------------------------- /src/richtext.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Uid from './uid'; 3 | 4 | const UEDITOR_LOADED_KEY = '__BEE_UEDITOR_LOADED_STATUS__'; 5 | 6 | // ueditor 默认值 7 | const initConfig = { 8 | autoClearinitialContent: false, 9 | autoFloatEnabled: true, // 是否保持 toolbar 滚动时不动 10 | focus: false, 11 | wordCount: true, 12 | elementPathEnabled: false, 13 | pasteplain: false, // 是否默认为纯文本粘贴。false为不使用纯文本粘贴,true为使用纯文本粘贴 14 | initialFrameWidth: 640, // 初始化编辑器宽度 15 | initialFrameHeight: 200, 16 | maximumWords: 10000, 17 | }; 18 | 19 | export default class RichText extends React.Component { 20 | static defaultProps = { 21 | value: '', 22 | onChange: () => { }, 23 | ueditorUrl: 'https://uso.oschina.io/react-ueditor-demo/ueditor.all.js', 24 | ueditorConfigUrl: 'https://uso.oschina.io/react-ueditor-demo/ueditor.config.js', 25 | ueditorHomeUrl: '', 26 | ueditorIframeUrl: '', 27 | editorConfig: {}, // ueditor 默认值 28 | className: '', 29 | prefix: 'bee', 30 | getEditorInstance(){} 31 | } 32 | 33 | constructor(props) { 34 | super(props); 35 | 36 | this.uuid = `bee-${Uid()}` 37 | } 38 | 39 | componentDidMount() { 40 | let timer = null; 41 | 42 | if (window.UE) { 43 | this.initRichText(); 44 | } else { 45 | timer = setInterval(() => { 46 | const status = window[UEDITOR_LOADED_KEY]; 47 | if (status === 2) { 48 | clearInterval(timer); 49 | this.initRichText(); 50 | } else if (status !== 1){ 51 | this.loadUEditorScript() 52 | } 53 | }, 50) 54 | } 55 | } 56 | 57 | componentWillUnmount() { 58 | if (!this.editor) return; 59 | this.editor.destroy(); 60 | } 61 | 62 | componentWillReceiveProps({ value }) { 63 | if (value !== this.props.value && this.editor) { 64 | this.editor.setContent(value); 65 | } 66 | } 67 | 68 | loadUEditorScript() { 69 | if (window[UEDITOR_LOADED_KEY] !== undefined) { 70 | return; 71 | } 72 | window[UEDITOR_LOADED_KEY] = 1; // 加载中 73 | let { 74 | ueditorHomeUrl, 75 | ueditorIframeUrl, 76 | ueditorUrl, 77 | ueditorConfigUrl, 78 | } = this.props; 79 | 80 | window.UEDITOR_HOME_URL = ueditorHomeUrl; 81 | window.UEDITOR_IFRAME_URL = ueditorIframeUrl; 82 | 83 | this.createScriptDom(ueditorConfigUrl, () => { 84 | this.createScriptDom(ueditorUrl, () => { 85 | window[UEDITOR_LOADED_KEY] = 2; // 加载完成 86 | }); 87 | }); 88 | } 89 | 90 | createScriptDom(url, callback) { 91 | const scriptDom = document.createElement('script'); 92 | scriptDom.type = 'text/javascript'; 93 | scriptDom.async = true; 94 | scriptDom.src = url; 95 | 96 | scriptDom.onload = function () { 97 | callback(); 98 | } 99 | document.body.appendChild(scriptDom); 100 | } 101 | 102 | initRichText = () => { 103 | const UE = window.UE; 104 | const target = document.getElementById(this.uuid); 105 | 106 | if (!UE || !target) { 107 | return false; 108 | } 109 | 110 | let { value, editorConfig } = this.props; 111 | let conf = { ...initConfig, ...editorConfig }; 112 | let editor = new UE.ui.Editor(conf); 113 | this.editor = editor; 114 | 115 | editor.addListener('contentChange', () => { 116 | this.onChange(); 117 | }); 118 | 119 | editor.addListener('blur', () => { 120 | this.onBlur(); 121 | }); 122 | 123 | editor.render(target); 124 | editor.ready(() => { 125 | editor.setContent(value); 126 | }) 127 | this.props.getEditorInstance(this.editor); 128 | } 129 | 130 | onChange = () => { 131 | const value = this.editor.getContent(); 132 | this.props.onChange && this.props.onChange(value); 133 | } 134 | 135 | onBlur = () => { 136 | const value = this.editor.getContent(); 137 | this.props.onBlur && this.props.onBlur(value); 138 | } 139 | 140 | render() { 141 | const { prefix, className } = this.props; 142 | return ( 143 |
144 |
145 |
146 | ) 147 | } 148 | } -------------------------------------------------------------------------------- /lib/richtext.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _extends2 = require('babel-runtime/helpers/extends'); 8 | 9 | var _extends3 = _interopRequireDefault(_extends2); 10 | 11 | var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); 12 | 13 | var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); 14 | 15 | var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); 16 | 17 | var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); 18 | 19 | var _createClass2 = require('babel-runtime/helpers/createClass'); 20 | 21 | var _createClass3 = _interopRequireDefault(_createClass2); 22 | 23 | var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); 24 | 25 | var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); 26 | 27 | var _inherits2 = require('babel-runtime/helpers/inherits'); 28 | 29 | var _inherits3 = _interopRequireDefault(_inherits2); 30 | 31 | var _react = require('react'); 32 | 33 | var _react2 = _interopRequireDefault(_react); 34 | 35 | var _uid = require('./uid'); 36 | 37 | var _uid2 = _interopRequireDefault(_uid); 38 | 39 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 40 | 41 | var UEDITOR_LOADED_KEY = '__BEE_UEDITOR_LOADED_STATUS__'; 42 | 43 | // ueditor 默认值 44 | var initConfig = { 45 | autoClearinitialContent: false, 46 | autoFloatEnabled: true, // 是否保持 toolbar 滚动时不动 47 | focus: false, 48 | wordCount: true, 49 | elementPathEnabled: false, 50 | pasteplain: false, // 是否默认为纯文本粘贴。false为不使用纯文本粘贴,true为使用纯文本粘贴 51 | initialFrameWidth: 640, // 初始化编辑器宽度 52 | initialFrameHeight: 200, 53 | maximumWords: 10000 54 | }; 55 | 56 | var RichText = function (_React$Component) { 57 | (0, _inherits3.default)(RichText, _React$Component); 58 | 59 | function RichText(props) { 60 | (0, _classCallCheck3.default)(this, RichText); 61 | 62 | var _this = (0, _possibleConstructorReturn3.default)(this, (RichText.__proto__ || (0, _getPrototypeOf2.default)(RichText)).call(this, props)); 63 | 64 | _this.initRichText = function () { 65 | var UE = window.UE; 66 | var target = document.getElementById(_this.uuid); 67 | 68 | if (!UE || !target) { 69 | return false; 70 | } 71 | 72 | var _this$props = _this.props, 73 | value = _this$props.value, 74 | editorConfig = _this$props.editorConfig; 75 | 76 | var conf = (0, _extends3.default)({}, initConfig, editorConfig); 77 | var editor = new UE.ui.Editor(conf); 78 | _this.editor = editor; 79 | 80 | editor.addListener('blur contentChange', function () { 81 | _this.onChange(); 82 | }); 83 | editor.render(target); 84 | editor.ready(function () { 85 | editor.setContent(value); 86 | }); 87 | }; 88 | 89 | _this.onChange = function () { 90 | var value = _this.editor.getContent(); 91 | _this.props.onChange && _this.props.onChange(value); 92 | }; 93 | 94 | _this.uuid = 'bee-' + (0, _uid2.default)(); 95 | return _this; 96 | } 97 | 98 | (0, _createClass3.default)(RichText, [{ 99 | key: 'componentDidMount', 100 | value: function componentDidMount() { 101 | var _this2 = this; 102 | 103 | var timer = null; 104 | 105 | if (window.UE) { 106 | this.initRichText(); 107 | } else { 108 | timer = setInterval(function () { 109 | var status = window[UEDITOR_LOADED_KEY]; 110 | if (status === 2) { 111 | clearInterval(timer); 112 | _this2.initRichText(); 113 | } else if (status !== 1) { 114 | _this2.loadUEditorScript(); 115 | } 116 | }, 50); 117 | } 118 | } 119 | }, { 120 | key: 'componentWillUnmount', 121 | value: function componentWillUnmount() { 122 | if (!this.editor) return; 123 | this.editor.destroy(); 124 | } 125 | }, { 126 | key: 'componentWillReceiveProps', 127 | value: function componentWillReceiveProps(_ref) { 128 | var value = _ref.value; 129 | 130 | if (value !== this.props.value && this.editor) { 131 | this.editor.setContent(value); 132 | } 133 | } 134 | }, { 135 | key: 'loadUEditorScript', 136 | value: function loadUEditorScript() { 137 | var _this3 = this; 138 | 139 | if (window[UEDITOR_LOADED_KEY] !== undefined) { 140 | return; 141 | } 142 | window[UEDITOR_LOADED_KEY] = 1; // 加载中 143 | var _props = this.props, 144 | ueditorHomeUrl = _props.ueditorHomeUrl, 145 | ueditorIframeUrl = _props.ueditorIframeUrl, 146 | ueditorUrl = _props.ueditorUrl, 147 | ueditorConfigUrl = _props.ueditorConfigUrl; 148 | 149 | 150 | window.UEDITOR_HOME_URL = ueditorHomeUrl; 151 | window.UEDITOR_IFRAME_URL = ueditorIframeUrl; 152 | 153 | this.createScriptDom(ueditorConfigUrl, function () { 154 | _this3.createScriptDom(ueditorUrl, function () { 155 | window[UEDITOR_LOADED_KEY] = 2; // 加载完成 156 | }); 157 | }); 158 | } 159 | }, { 160 | key: 'createScriptDom', 161 | value: function createScriptDom(url, callback) { 162 | var scriptDom = document.createElement('script'); 163 | scriptDom.type = 'text/javascript'; 164 | scriptDom.async = true; 165 | scriptDom.src = url; 166 | 167 | scriptDom.onload = function () { 168 | callback(); 169 | }; 170 | document.body.appendChild(scriptDom); 171 | } 172 | }, { 173 | key: 'render', 174 | value: function render() { 175 | var _props2 = this.props, 176 | prefix = _props2.prefix, 177 | className = _props2.className; 178 | 179 | return _react2.default.createElement( 180 | 'div', 181 | { className: prefix + '-richtext ' + className }, 182 | _react2.default.createElement('div', { id: this.uuid }) 183 | ); 184 | } 185 | }]); 186 | return RichText; 187 | }(_react2.default.Component); 188 | 189 | RichText.defaultProps = { 190 | value: '', 191 | onChange: function onChange() {}, 192 | ueditorUrl: 'https://uso.oschina.io/react-ueditor-demo/ueditor.all.js', 193 | ueditorConfigUrl: 'https://uso.oschina.io/react-ueditor-demo/ueditor.config.js', 194 | ueditorHomeUrl: '', 195 | ueditorIframeUrl: '', 196 | editorConfig: {}, // ueditor 默认值 197 | className: '', 198 | prefix: 'bee' 199 | }; 200 | exports.default = RichText; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 安装 2 | ``` 3 | npm i --save react-ueditor-wrap 4 | ``` 5 | [demo](http://uso.oschina.io/react-ueditor-demo/) 6 | ### 使用 7 | ``` 8 | import RcUeditor from 'react-ueditor-wrap'; 9 | 10 | class Demo extends React.Component { 11 | 12 | hanldeChage = (value) => { 13 | console.log('RcUeditor', value); 14 | } 15 | 16 | render() { 17 | 18 | return ( 19 |
20 | 21 |
22 | ); 23 | } 24 | } 25 | 26 | export default Demo; 27 | ``` 28 | ### api 29 | 30 | | 成员 | 说明 | 类型 | 默认值 | 31 | | --- | --- | --- | --- | 32 | | value | 设置编辑器的值 | string | - | 33 | | ueditorUrl | 设置ueditor(百度编辑器)js文件的地址 | string | 'https://uso.oschina.io/react-ueditor-demo/ueditor.all.js' | 34 | | ueditorConfigUrl | 设置百度编辑器默认config文件地址 | string | 'https://uso.oschina.io/react-ueditor-demo/ueditor.config.js' | 35 | | ueditorHomeUrl | 设置ueditorHomeUrl | string | '' | 36 | | ueditorIframeUrl | 设置ueditorIframeUrl | string | '' | 37 | | editorConfig | 百度编辑器的配置(如果不传则为默认配置) | Object | {} | 38 | | className | 添加自定义class | String | '' | 39 | | prefix | 修改默认class前缀 | String | 'bee' | 40 | 41 | > 注意: 实际生产环境使用请修改ueditorUrl以及ueditorConfigUrl到自己的服务器地址或者CDN。以及在对应的目录放入ueditor的依赖文件,这点可以参考ueditor官方给出的example. 自行下载观看https://ueditor.baidu.com/website/download.html 42 | 43 | ### editorConfig 例子 44 | ``` 45 | // ueditor 默认值 46 | const editorConfig = { 47 | toolbars: [ 48 | [ 49 | 'bold', 50 | 'italic', 51 | 'underline', 52 | 'strikethrough', 53 | 'forecolor', 54 | 'backcolor', 55 | 'justifyleft', 56 | 'justifycenter', 57 | 'justifyright', 58 | '|', 59 | 'insertunorderedlist', 60 | 'insertorderedlist', 61 | 'blockquote', 62 | ], 63 | ], 64 | autoClearinitialContent: false, 65 | autoFloatEnabled: true, 66 | focus: false, 67 | initialFrameWidth: 740, // 初始化编辑器宽度 68 | initialFrameHeight: 300, 69 | maximumWords: 100000, 70 | }; 71 | ``` 72 | 73 | 74 | ## ueditor完整配置项 75 | > 以下是ueditor 代码默认的配置代码。 editorConfig配置实则是调用了`new UE.ui.Editor(conf);` 76 | 具体ueditor的使用请移步到https://ueditor.baidu.com/website/index.html 77 | 78 | ``` 79 | /** 80 | * ueditor完整配置项 81 | * 可以在这里配置整个编辑器的特性 82 | */ 83 | /**************************提示******************************** 84 | * 所有被注释的配置项均为UEditor默认值。 85 | * 修改默认配置请首先确保已经完全明确该参数的真实用途。 86 | * 主要有两种修改方案,一种是取消此处注释,然后修改成对应参数;另一种是在实例化编辑器时传入对应参数。 87 | * 当升级编辑器时,可直接使用旧版配置文件替换新版配置文件,不用担心旧版配置文件中因缺少新功能所需的参数而导致脚本报错。 88 | **************************提示********************************/ 89 | 90 | (function () { 91 | 92 | /** 93 | * 编辑器资源文件根路径。它所表示的含义是:以编辑器实例化页面为当前路径,指向编辑器资源文件(即dialog等文件夹)的路径。 94 | * 鉴于很多同学在使用编辑器的时候出现的种种路径问题,此处强烈建议大家使用"相对于网站根目录的相对路径"进行配置。 95 | * "相对于网站根目录的相对路径"也就是以斜杠开头的形如"/myProject/ueditor/"这样的路径。 96 | * 如果站点中有多个不在同一层级的页面需要实例化编辑器,且引用了同一UEditor的时候,此处的URL可能不适用于每个页面的编辑器。 97 | * 因此,UEditor提供了针对不同页面的编辑器可单独配置的根路径,具体来说,在需要实例化编辑器的页面最顶部写上如下代码即可。当然,需要令此处的URL等于对应的配置。 98 | * window.UEDITOR_HOME_URL = "/xxxx/xxxx/"; 99 | */ 100 | var URL = window.UEDITOR_HOME_URL || getUEBasePath(); 101 | 102 | /** 103 | * 配置项主体。注意,此处所有涉及到路径的配置别遗漏URL变量。 104 | */ 105 | window.UEDITOR_CONFIG = { 106 | 107 | //为编辑器实例添加一个路径,这个不能被注释 108 | UEDITOR_HOME_URL: URL 109 | 110 | // 服务器统一请求接口路径 111 | , serverUrl: URL + "php/controller.php" 112 | 113 | //工具栏上的所有的功能按钮和下拉框,可以在new编辑器的实例时选择自己需要的重新定义 114 | , toolbars: [[ 115 | 'fullscreen', 'source', '|', 'undo', 'redo', '|', 116 | 'bold', 'italic', 'underline', 'fontborder', 'strikethrough', 'superscript', 'subscript', 'removeformat', 'formatmatch', 'autotypeset', 'blockquote', 'pasteplain', '|', 'forecolor', 'backcolor', 'insertorderedlist', 'insertunorderedlist', 'selectall', 'cleardoc', '|', 117 | 'rowspacingtop', 'rowspacingbottom', 'lineheight', '|', 118 | 'customstyle', 'paragraph', 'fontfamily', 'fontsize', '|', 119 | 'directionalityltr', 'directionalityrtl', 'indent', '|', 120 | 'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify', '|', 'touppercase', 'tolowercase', '|', 121 | 'link', 'unlink', 'anchor', '|', 'imagenone', 'imageleft', 'imageright', 'imagecenter', '|', 122 | 'simpleupload', 'insertimage', 'emotion', 'scrawl', 'insertvideo', 'music', 'attachment', 'map', 'gmap', 'insertframe', 'insertcode', 'webapp', 'pagebreak', 'template', 'background', '|', 123 | 'horizontal', 'date', 'time', 'spechars', 'snapscreen', 'wordimage', '|', 124 | 'inserttable', 'deletetable', 'insertparagraphbeforetable', 'insertrow', 'deleterow', 'insertcol', 'deletecol', 'mergecells', 'mergeright', 'mergedown', 'splittocells', 'splittorows', 'splittocols', 'charts', '|', 125 | 'print', 'preview', 'searchreplace', 'drafts', 'help' 126 | ]] 127 | //当鼠标放在工具栏上时显示的tooltip提示,留空支持自动多语言配置,否则以配置值为准 128 | //,labelMap:{ 129 | // 'anchor':'', 'undo':'' 130 | //} 131 | 132 | //语言配置项,默认是zh-cn。有需要的话也可以使用如下这样的方式来自动多语言切换,当然,前提条件是lang文件夹下存在对应的语言文件: 133 | //lang值也可以通过自动获取 (navigator.language||navigator.browserLanguage ||navigator.userLanguage).toLowerCase() 134 | //,lang:"zh-cn" 135 | //,langPath:URL +"lang/" 136 | 137 | //主题配置项,默认是default。有需要的话也可以使用如下这样的方式来自动多主题切换,当然,前提条件是themes文件夹下存在对应的主题文件: 138 | //现有如下皮肤:default 139 | //,theme:'default' 140 | //,themePath:URL +"themes/" 141 | 142 | //,zIndex : 900 //编辑器层级的基数,默认是900 143 | 144 | //针对getAllHtml方法,会在对应的head标签中增加该编码设置。 145 | //,charset:"utf-8" 146 | 147 | //若实例化编辑器的页面手动修改的domain,此处需要设置为true 148 | //,customDomain:false 149 | 150 | //常用配置项目 151 | //,isShow : true //默认显示编辑器 152 | 153 | //,textarea:'editorValue' // 提交表单时,服务器获取编辑器提交内容的所用的参数,多实例时可以给容器name属性,会将name给定的值最为每个实例的键值,不用每次实例化的时候都设置这个值 154 | 155 | //,initialContent:'欢迎使用ueditor!' //初始化编辑器的内容,也可以通过textarea/script给值,看官网例子 156 | 157 | //,autoClearinitialContent:true //是否自动清除编辑器初始内容,注意:如果focus属性设置为true,这个也为真,那么编辑器一上来就会触发导致初始化的内容看不到了 158 | 159 | //,focus:false //初始化时,是否让编辑器获得焦点true或false 160 | 161 | //如果自定义,最好给p标签如下的行高,要不输入中文时,会有跳动感 162 | //,initialStyle:'p{line-height:1em}'//编辑器层级的基数,可以用来改变字体等 163 | 164 | //,iframeCssUrl: URL + '/themes/iframe.css' //给编辑区域的iframe引入一个css文件 165 | 166 | //indentValue 167 | //首行缩进距离,默认是2em 168 | //,indentValue:'2em' 169 | 170 | //,initialFrameWidth:1000 //初始化编辑器宽度,默认1000 171 | //,initialFrameHeight:320 //初始化编辑器高度,默认320 172 | 173 | //,readonly : false //编辑器初始化结束后,编辑区域是否是只读的,默认是false 174 | 175 | //,autoClearEmptyNode : true //getContent时,是否删除空的inlineElement节点(包括嵌套的情况) 176 | 177 | //启用自动保存 178 | //,enableAutoSave: true 179 | //自动保存间隔时间, 单位ms 180 | //,saveInterval: 500 181 | 182 | //,fullscreen : false //是否开启初始化时即全屏,默认关闭 183 | 184 | //,imagePopup:true //图片操作的浮层开关,默认打开 185 | 186 | //,autoSyncData:true //自动同步编辑器要提交的数据 187 | //,emotionLocalization:false //是否开启表情本地化,默认关闭。若要开启请确保emotion文件夹下包含官网提供的images表情文件夹 188 | 189 | //粘贴只保留标签,去除标签所有属性 190 | //,retainOnlyLabelPasted: false 191 | 192 | //,pasteplain:false //是否默认为纯文本粘贴。false为不使用纯文本粘贴,true为使用纯文本粘贴 193 | //纯文本粘贴模式下的过滤规则 194 | //'filterTxtRules' : function(){ 195 | // function transP(node){ 196 | // node.tagName = 'p'; 197 | // node.setStyle(); 198 | // } 199 | // return { 200 | // //直接删除及其字节点内容 201 | // '-' : 'script style object iframe embed input select', 202 | // 'p': {$:{}}, 203 | // 'br':{$:{}}, 204 | // 'div':{'$':{}}, 205 | // 'li':{'$':{}}, 206 | // 'caption':transP, 207 | // 'th':transP, 208 | // 'tr':transP, 209 | // 'h1':transP,'h2':transP,'h3':transP,'h4':transP,'h5':transP,'h6':transP, 210 | // 'td':function(node){ 211 | // //没有内容的td直接删掉 212 | // var txt = !!node.innerText(); 213 | // if(txt){ 214 | // node.parentNode.insertAfter(UE.uNode.createText('    '),node); 215 | // } 216 | // node.parentNode.removeChild(node,node.innerText()) 217 | // } 218 | // } 219 | //}() 220 | 221 | //,allHtmlEnabled:false //提交到后台的数据是否包含整个html字符串 222 | 223 | //insertorderedlist 224 | //有序列表的下拉配置,值留空时支持多语言自动识别,若配置值,则以此值为准 225 | //,'insertorderedlist':{ 226 | // //自定的样式 227 | // 'num':'1,2,3...', 228 | // 'num1':'1),2),3)...', 229 | // 'num2':'(1),(2),(3)...', 230 | // 'cn':'一,二,三....', 231 | // 'cn1':'一),二),三)....', 232 | // 'cn2':'(一),(二),(三)....', 233 | // //系统自带 234 | // 'decimal' : '' , //'1,2,3...' 235 | // 'lower-alpha' : '' , // 'a,b,c...' 236 | // 'lower-roman' : '' , //'i,ii,iii...' 237 | // 'upper-alpha' : '' , lang //'A,B,C' 238 | // 'upper-roman' : '' //'I,II,III...' 239 | //} 240 | 241 | //insertunorderedlist 242 | //无序列表的下拉配置,值留空时支持多语言自动识别,若配置值,则以此值为准 243 | //,insertunorderedlist : { //自定的样式 244 | // 'dash' :'— 破折号', //-破折号 245 | // 'dot':' 。 小圆圈', //系统自带 246 | // 'circle' : '', // '○ 小圆圈' 247 | // 'disc' : '', // '● 小圆点' 248 | // 'square' : '' //'■ 小方块' 249 | //} 250 | //,listDefaultPaddingLeft : '30'//默认的左边缩进的基数倍 251 | //,listiconpath : 'http://bs.baidu.com/listicon/'//自定义标号的路径 252 | //,maxListLevel : 3 //限制可以tab的级数, 设置-1为不限制 253 | 254 | //,autoTransWordToList:false //禁止word中粘贴进来的列表自动变成列表标签 255 | 256 | //fontfamily 257 | //字体设置 label留空支持多语言自动切换,若配置,则以配置值为准 258 | //,'fontfamily':[ 259 | // { label:'',name:'songti',val:'宋体,SimSun'}, 260 | // { label:'',name:'kaiti',val:'楷体,楷体_GB2312, SimKai'}, 261 | // { label:'',name:'yahei',val:'微软雅黑,Microsoft YaHei'}, 262 | // { label:'',name:'heiti',val:'黑体, SimHei'}, 263 | // { label:'',name:'lishu',val:'隶书, SimLi'}, 264 | // { label:'',name:'andaleMono',val:'andale mono'}, 265 | // { label:'',name:'arial',val:'arial, helvetica,sans-serif'}, 266 | // { label:'',name:'arialBlack',val:'arial black,avant garde'}, 267 | // { label:'',name:'comicSansMs',val:'comic sans ms'}, 268 | // { label:'',name:'impact',val:'impact,chicago'}, 269 | // { label:'',name:'timesNewRoman',val:'times new roman'} 270 | //] 271 | 272 | //fontsize 273 | //字号 274 | //,'fontsize':[10, 11, 12, 14, 16, 18, 20, 24, 36] 275 | 276 | //paragraph 277 | //段落格式 值留空时支持多语言自动识别,若配置,则以配置值为准 278 | //,'paragraph':{'p':'', 'h1':'', 'h2':'', 'h3':'', 'h4':'', 'h5':'', 'h6':''} 279 | 280 | //rowspacingtop 281 | //段间距 值和显示的名字相同 282 | //,'rowspacingtop':['5', '10', '15', '20', '25'] 283 | 284 | //rowspacingBottom 285 | //段间距 值和显示的名字相同 286 | //,'rowspacingbottom':['5', '10', '15', '20', '25'] 287 | 288 | //lineheight 289 | //行内间距 值和显示的名字相同 290 | //,'lineheight':['1', '1.5','1.75','2', '3', '4', '5'] 291 | 292 | //customstyle 293 | //自定义样式,不支持国际化,此处配置值即可最后显示值 294 | //block的元素是依据设置段落的逻辑设置的,inline的元素依据BIU的逻辑设置 295 | //尽量使用一些常用的标签 296 | //参数说明 297 | //tag 使用的标签名字 298 | //label 显示的名字也是用来标识不同类型的标识符,注意这个值每个要不同, 299 | //style 添加的样式 300 | //每一个对象就是一个自定义的样式 301 | //,'customstyle':[ 302 | // {tag:'h1', name:'tc', label:'', style:'border-bottom:#ccc 2px solid;padding:0 4px 0 0;text-align:center;margin:0 0 20px 0;'}, 303 | // {tag:'h1', name:'tl',label:'', style:'border-bottom:#ccc 2px solid;padding:0 4px 0 0;margin:0 0 10px 0;'}, 304 | // {tag:'span',name:'im', label:'', style:'font-style:italic;font-weight:bold'}, 305 | // {tag:'span',name:'hi', label:'', style:'font-style:italic;font-weight:bold;color:rgb(51, 153, 204)'} 306 | //] 307 | 308 | //打开右键菜单功能 309 | //,enableContextMenu: true 310 | //右键菜单的内容,可以参考plugins/contextmenu.js里边的默认菜单的例子,label留空支持国际化,否则以此配置为准 311 | //,contextMenu:[ 312 | // { 313 | // label:'', //显示的名称 314 | // cmdName:'selectall',//执行的command命令,当点击这个右键菜单时 315 | // //exec可选,有了exec就会在点击时执行这个function,优先级高于cmdName 316 | // exec:function () { 317 | // //this是当前编辑器的实例 318 | // //this.ui._dialogs['inserttableDialog'].open(); 319 | // } 320 | // } 321 | //] 322 | 323 | //快捷菜单 324 | //,shortcutMenu:["fontfamily", "fontsize", "bold", "italic", "underline", "forecolor", "backcolor", "insertorderedlist", "insertunorderedlist"] 325 | 326 | //elementPathEnabled 327 | //是否启用元素路径,默认是显示 328 | //,elementPathEnabled : true 329 | 330 | //wordCount 331 | //,wordCount:true //是否开启字数统计 332 | //,maximumWords:10000 //允许的最大字符数 333 | //字数统计提示,{#count}代表当前字数,{#leave}代表还可以输入多少字符数,留空支持多语言自动切换,否则按此配置显示 334 | //,wordCountMsg:'' //当前已输入 {#count} 个字符,您还可以输入{#leave} 个字符 335 | //超出字数限制提示 留空支持多语言自动切换,否则按此配置显示 336 | //,wordOverFlowMsg:'' //你输入的字符个数已经超出最大允许值,服务器可能会拒绝保存! 337 | 338 | //tab 339 | //点击tab键时移动的距离,tabSize倍数,tabNode什么字符做为单位 340 | //,tabSize:4 341 | //,tabNode:' ' 342 | 343 | //removeFormat 344 | //清除格式时可以删除的标签和属性 345 | //removeForamtTags标签 346 | //,removeFormatTags:'b,big,code,del,dfn,em,font,i,ins,kbd,q,samp,small,span,strike,strong,sub,sup,tt,u,var' 347 | //removeFormatAttributes属性 348 | //,removeFormatAttributes:'class,style,lang,width,height,align,hspace,valign' 349 | 350 | //undo 351 | //可以最多回退的次数,默认20 352 | //,maxUndoCount:20 353 | //当输入的字符数超过该值时,保存一次现场 354 | //,maxInputCount:1 355 | 356 | //autoHeightEnabled 357 | // 是否自动长高,默认true 358 | //,autoHeightEnabled:true 359 | 360 | //scaleEnabled 361 | //是否可以拉伸长高,默认true(当开启时,自动长高失效) 362 | //,scaleEnabled:false 363 | //,minFrameWidth:800 //编辑器拖动时最小宽度,默认800 364 | //,minFrameHeight:220 //编辑器拖动时最小高度,默认220 365 | 366 | //autoFloatEnabled 367 | //是否保持toolbar的位置不动,默认true 368 | //,autoFloatEnabled:true 369 | //浮动时工具栏距离浏览器顶部的高度,用于某些具有固定头部的页面 370 | //,topOffset:30 371 | //编辑器底部距离工具栏高度(如果参数大于等于编辑器高度,则设置无效) 372 | //,toolbarTopOffset:400 373 | 374 | //设置远程图片是否抓取到本地保存 375 | //,catchRemoteImageEnable: true //设置是否抓取远程图片 376 | 377 | //pageBreakTag 378 | //分页标识符,默认是_ueditor_page_break_tag_ 379 | //,pageBreakTag:'_ueditor_page_break_tag_' 380 | 381 | //autotypeset 382 | //自动排版参数 383 | //,autotypeset: { 384 | // mergeEmptyline: true, //合并空行 385 | // removeClass: true, //去掉冗余的class 386 | // removeEmptyline: false, //去掉空行 387 | // textAlign:"left", //段落的排版方式,可以是 left,right,center,justify 去掉这个属性表示不执行排版 388 | // imageBlockLine: 'center', //图片的浮动方式,独占一行剧中,左右浮动,默认: center,left,right,none 去掉这个属性表示不执行排版 389 | // pasteFilter: false, //根据规则过滤没事粘贴进来的内容 390 | // clearFontSize: false, //去掉所有的内嵌字号,使用编辑器默认的字号 391 | // clearFontFamily: false, //去掉所有的内嵌字体,使用编辑器默认的字体 392 | // removeEmptyNode: false, // 去掉空节点 393 | // //可以去掉的标签 394 | // removeTagNames: {标签名字:1}, 395 | // indent: false, // 行首缩进 396 | // indentValue : '2em', //行首缩进的大小 397 | // bdc2sb: false, 398 | // tobdc: false 399 | //} 400 | 401 | //tableDragable 402 | //表格是否可以拖拽 403 | //,tableDragable: true 404 | 405 | 406 | 407 | //sourceEditor 408 | //源码的查看方式,codemirror 是代码高亮,textarea是文本框,默认是codemirror 409 | //注意默认codemirror只能在ie8+和非ie中使用 410 | //,sourceEditor:"codemirror" 411 | //如果sourceEditor是codemirror,还用配置一下两个参数 412 | //codeMirrorJsUrl js加载的路径,默认是 URL + "third-party/codemirror/codemirror.js" 413 | //,codeMirrorJsUrl:URL + "third-party/codemirror/codemirror.js" 414 | //codeMirrorCssUrl css加载的路径,默认是 URL + "third-party/codemirror/codemirror.css" 415 | //,codeMirrorCssUrl:URL + "third-party/codemirror/codemirror.css" 416 | //编辑器初始化完成后是否进入源码模式,默认为否。 417 | //,sourceEditorFirst:false 418 | 419 | //iframeUrlMap 420 | //dialog内容的路径 ~会被替换成URL,垓属性一旦打开,将覆盖所有的dialog的默认路径 421 | //,iframeUrlMap:{ 422 | // 'anchor':'~/dialogs/anchor/anchor.html', 423 | //} 424 | 425 | //allowLinkProtocol 允许的链接地址,有这些前缀的链接地址不会自动添加http 426 | //, allowLinkProtocols: ['http:', 'https:', '#', '/', 'ftp:', 'mailto:', 'tel:', 'git:', 'svn:'] 427 | 428 | //webAppKey 百度应用的APIkey,每个站长必须首先去百度官网注册一个key后方能正常使用app功能,注册介绍,http://app.baidu.com/static/cms/getapikey.html 429 | //, webAppKey: "" 430 | 431 | //默认过滤规则相关配置项目 432 | //,disabledTableInTable:true //禁止表格嵌套 433 | //,allowDivTransToP:true //允许进入编辑器的div标签自动变成p标签 434 | //,rgb2Hex:true //默认产出的数据中的color自动从rgb格式变成16进制格式 435 | 436 | // xss 过滤是否开启,inserthtml等操作 437 | ,xssFilterRules: true 438 | //input xss过滤 439 | ,inputXssFilter: true 440 | //output xss过滤 441 | ,outputXssFilter: true 442 | // xss过滤白名单 名单来源: https://raw.githubusercontent.com/leizongmin/js-xss/master/lib/default.js 443 | ,whitList: { 444 | a: ['target', 'href', 'title', 'class', 'style'], 445 | abbr: ['title', 'class', 'style'], 446 | address: ['class', 'style'], 447 | area: ['shape', 'coords', 'href', 'alt'], 448 | article: [], 449 | aside: [], 450 | audio: ['autoplay', 'controls', 'loop', 'preload', 'src', 'class', 'style'], 451 | b: ['class', 'style'], 452 | bdi: ['dir'], 453 | bdo: ['dir'], 454 | big: [], 455 | blockquote: ['cite', 'class', 'style'], 456 | br: [], 457 | caption: ['class', 'style'], 458 | center: [], 459 | cite: [], 460 | code: ['class', 'style'], 461 | col: ['align', 'valign', 'span', 'width', 'class', 'style'], 462 | colgroup: ['align', 'valign', 'span', 'width', 'class', 'style'], 463 | dd: ['class', 'style'], 464 | del: ['datetime'], 465 | details: ['open'], 466 | div: ['class', 'style'], 467 | dl: ['class', 'style'], 468 | dt: ['class', 'style'], 469 | em: ['class', 'style'], 470 | font: ['color', 'size', 'face'], 471 | footer: [], 472 | h1: ['class', 'style'], 473 | h2: ['class', 'style'], 474 | h3: ['class', 'style'], 475 | h4: ['class', 'style'], 476 | h5: ['class', 'style'], 477 | h6: ['class', 'style'], 478 | header: [], 479 | hr: [], 480 | i: ['class', 'style'], 481 | img: ['src', 'alt', 'title', 'width', 'height', 'id', '_src', 'loadingclass', 'class', 'data-latex'], 482 | ins: ['datetime'], 483 | li: ['class', 'style'], 484 | mark: [], 485 | nav: [], 486 | ol: ['class', 'style'], 487 | p: ['class', 'style'], 488 | pre: ['class', 'style'], 489 | s: [], 490 | section:[], 491 | small: [], 492 | span: ['class', 'style'], 493 | sub: ['class', 'style'], 494 | sup: ['class', 'style'], 495 | strong: ['class', 'style'], 496 | table: ['width', 'border', 'align', 'valign', 'class', 'style'], 497 | tbody: ['align', 'valign', 'class', 'style'], 498 | td: ['width', 'rowspan', 'colspan', 'align', 'valign', 'class', 'style'], 499 | tfoot: ['align', 'valign', 'class', 'style'], 500 | th: ['width', 'rowspan', 'colspan', 'align', 'valign', 'class', 'style'], 501 | thead: ['align', 'valign', 'class', 'style'], 502 | tr: ['rowspan', 'align', 'valign', 'class', 'style'], 503 | tt: [], 504 | u: [], 505 | ul: ['class', 'style'], 506 | video: ['autoplay', 'controls', 'loop', 'preload', 'src', 'height', 'width', 'class', 'style'] 507 | } 508 | }; 509 | 510 | function getUEBasePath(docUrl, confUrl) { 511 | 512 | return getBasePath(docUrl || self.document.URL || self.location.href, confUrl || getConfigFilePath()); 513 | 514 | } 515 | 516 | function getConfigFilePath() { 517 | 518 | var configPath = document.getElementsByTagName('script'); 519 | 520 | return configPath[ configPath.length - 1 ].src; 521 | 522 | } 523 | 524 | function getBasePath(docUrl, confUrl) { 525 | 526 | var basePath = confUrl; 527 | 528 | 529 | if (/^(\/|\\\\)/.test(confUrl)) { 530 | 531 | basePath = /^.+?\w(\/|\\\\)/.exec(docUrl)[0] + confUrl.replace(/^(\/|\\\\)/, ''); 532 | 533 | } else if (!/^[a-z]+:/i.test(confUrl)) { 534 | 535 | docUrl = docUrl.split("#")[0].split("?")[0].replace(/[^\\\/]+$/, ''); 536 | 537 | basePath = docUrl + "" + confUrl; 538 | 539 | } 540 | 541 | return optimizationPath(basePath); 542 | 543 | } 544 | 545 | function optimizationPath(path) { 546 | 547 | var protocol = /^[a-z]+:\/\//.exec(path)[ 0 ], 548 | tmp = null, 549 | res = []; 550 | 551 | path = path.replace(protocol, "").split("?")[0].split("#")[0]; 552 | 553 | path = path.replace(/\\/g, '/').split(/\//); 554 | 555 | path[ path.length - 1 ] = ""; 556 | 557 | while (path.length) { 558 | 559 | if (( tmp = path.shift() ) === "..") { 560 | res.pop(); 561 | } else if (tmp !== ".") { 562 | res.push(tmp); 563 | } 564 | 565 | } 566 | 567 | return protocol + res.join("/"); 568 | 569 | } 570 | 571 | window.UE = { 572 | getUEBasePath: getUEBasePath 573 | }; 574 | 575 | })(); 576 | 577 | ## 联系 578 | 579 | Email: usocjb@163.com 580 | weixin: chenjianbin519846538 581 | 582 | ``` 583 | --------------------------------------------------------------------------------