@ckeditor/ckeditor5-editor-balloon
Advanced tools
Comparing version 35.3.2 to 35.4.0
/*! | ||
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved. | ||
* For licensing, see LICENSE.md. | ||
*/(()=>{var t={704:(t,e,o)=>{t.exports=o(79)("./src/core.js")},492:(t,e,o)=>{t.exports=o(79)("./src/engine.js")},273:(t,e,o)=>{t.exports=o(79)("./src/ui.js")},209:(t,e,o)=>{t.exports=o(79)("./src/utils.js")},79:t=>{"use strict";t.exports=CKEditor5.dll}},e={};function o(i){var r=e[i];if(void 0!==r)return r.exports;var n=e[i]={exports:{}};return t[i](n,n.exports,o),n.exports}o.d=(t,e)=>{for(var i in e)o.o(e,i)&&!o.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},o.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),o.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var i={};(()=>{"use strict";o.r(i),o.d(i,{BalloonEditor:()=>C});var t=o(704),e=o(273),r=o(209);const n=function(t){return null!=t&&"object"==typeof t};const s="object"==typeof global&&global&&global.Object===Object&&global;var c="object"==typeof self&&self&&self.Object===Object&&self;const a=(s||c||Function("return this")()).Symbol;var l=Object.prototype,d=l.hasOwnProperty,u=l.toString,h=a?a.toStringTag:void 0;const g=function(t){var e=d.call(t,h),o=t[h];try{t[h]=void 0;var i=!0}catch(t){}var r=u.call(t);return i&&(e?t[h]=o:delete t[h]),r};var p=Object.prototype.toString;const b=function(t){return p.call(t)};var f=a?a.toStringTag:void 0;const m=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":f&&f in Object(t)?g(t):b(t)};const v=function(t,e){return function(o){return t(e(o))}}(Object.getPrototypeOf,Object);var y=Function.prototype,w=Object.prototype,j=y.toString,E=w.hasOwnProperty,O=j.call(Object);const x=function(t){if(!n(t)||"[object Object]"!=m(t))return!1;var e=v(t);if(null===e)return!0;var o=E.call(e,"constructor")&&e.constructor;return"function"==typeof o&&o instanceof o&&j.call(o)==O};const S=function(t){return n(t)&&1===t.nodeType&&!x(t)};var P=o(492);class T extends t.EditorUI{constructor(t,e){super(t),this.view=e}get element(){return this.view.editable.element}init(){const t=this.editor,e=this.view,o=t.editing.view,i=e.editable,r=o.document.getRoot();i.name=r.rootName,e.render();const n=i.element;this.setEditableElement(i.name,n),i.bind("isFocused").to(this.focusTracker),o.attachDomRoot(n),this._initPlaceholder(),this.fire("ready")}destroy(){super.destroy();const t=this.view;this.editor.editing.view.detachDomRoot(t.editable.name),t.destroy()}_initPlaceholder(){const t=this.editor,e=t.editing.view,o=e.document.getRoot(),i=t.sourceElement,r=t.config.get("placeholder")||i&&"textarea"===i.tagName.toLowerCase()&&i.getAttribute("placeholder");r&&(0,P.enablePlaceholder)({view:e,element:o,text:r,isDirectHost:!1,keepOnFocus:!0})}}class D extends e.EditorUIView{constructor(t,o,i){super(t);const r=t.t;this.editable=new e.InlineEditableUIView(t,o,i,{label:t=>r("Rich Text Editor. Editing area: %0",t.name)})}render(){super.render(),this.registerChild(this.editable)}}class C extends t.Editor{constructor(o,i={}){if(!S(o)&&void 0!==i.initialData)throw new r.CKEditorError("editor-create-initial-data",null);super(i),void 0===this.config.get("initialData")&&this.config.set("initialData",function(t){return S(t)?(0,r.getDataFromElement)(t):t}(o)),S(o)&&(this.sourceElement=o,(0,t.secureSourceElement)(this));const n=this.config.get("plugins");n.push(e.BalloonToolbar),this.config.set("plugins",n),this.config.define("balloonToolbar",this.config.get("toolbar")),this.model.document.createRoot();const s=new D(this.locale,this.editing.view,this.sourceElement);this.ui=new T(this,s),(0,t.attachToForm)(this)}destroy(){const t=this.getData();return this.ui.destroy(),super.destroy().then((()=>{this.sourceElement&&this.updateSourceElement(t)}))}static create(t,e={}){return new Promise((o=>{if(S(t)&&"TEXTAREA"===t.tagName)throw new r.CKEditorError("editor-wrong-element",null);const i=new this(t,e);o(i.initPlugins().then((()=>i.ui.init())).then((()=>i.data.init(i.config.get("initialData")))).then((()=>i.fire("ready"))).then((()=>i)))}))}}(0,r.mix)(C,t.DataApiMixin),(0,r.mix)(C,t.ElementApiMixin)})(),(window.CKEditor5=window.CKEditor5||{}).editorBalloon=i})(); | ||
*/(()=>{var t={704:(t,e,o)=>{t.exports=o(79)("./src/core.js")},492:(t,e,o)=>{t.exports=o(79)("./src/engine.js")},273:(t,e,o)=>{t.exports=o(79)("./src/ui.js")},209:(t,e,o)=>{t.exports=o(79)("./src/utils.js")},79:t=>{"use strict";t.exports=CKEditor5.dll}},e={};function o(i){var r=e[i];if(void 0!==r)return r.exports;var n=e[i]={exports:{}};return t[i](n,n.exports,o),n.exports}o.d=(t,e)=>{for(var i in e)o.o(e,i)&&!o.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},o.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),o.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var i={};(()=>{"use strict";o.r(i),o.d(i,{BalloonEditor:()=>C});var t=o(704),e=o(273),r=o(209),n=o(492);class s extends t.EditorUI{constructor(t,e){super(t),this.view=e}get element(){return this.view.editable.element}init(){const t=this.editor,e=this.view,o=t.editing.view,i=e.editable,r=o.document.getRoot();i.name=r.rootName,e.render();const n=i.element;this.setEditableElement(i.name,n),i.bind("isFocused").to(this.focusTracker),o.attachDomRoot(n),this._initPlaceholder(),this.fire("ready")}destroy(){super.destroy();const t=this.view;this.editor.editing.view.detachDomRoot(t.editable.name),t.destroy()}_initPlaceholder(){const t=this.editor,e=t.editing.view,o=e.document.getRoot(),i=t.sourceElement,r=t.config.get("placeholder")||i&&"textarea"===i.tagName.toLowerCase()&&i.getAttribute("placeholder");r&&(0,n.enablePlaceholder)({view:e,element:o,text:r,isDirectHost:!1,keepOnFocus:!0})}}class c extends e.EditorUIView{constructor(t,o,i){super(t);const r=t.t;this.editable=new e.InlineEditableUIView(t,o,i,{label:t=>r("Rich Text Editor. Editing area: %0",t.name)})}render(){super.render(),this.registerChild(this.editable)}}const a=function(t){return null!=t&&"object"==typeof t};const l="object"==typeof global&&global&&global.Object===Object&&global;var d="object"==typeof self&&self&&self.Object===Object&&self;const u=(l||d||Function("return this")()).Symbol;var h=Object.prototype,g=h.hasOwnProperty,p=h.toString,b=u?u.toStringTag:void 0;const f=function(t){var e=g.call(t,b),o=t[b];try{t[b]=void 0;var i=!0}catch(t){}var r=p.call(t);return i&&(e?t[b]=o:delete t[b]),r};var m=Object.prototype.toString;const v=function(t){return m.call(t)};var y=u?u.toStringTag:void 0;const w=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":y&&y in Object(t)?f(t):v(t)};const j=function(t,e){return function(o){return t(e(o))}}(Object.getPrototypeOf,Object);var E=Function.prototype,O=Object.prototype,x=E.toString,S=O.hasOwnProperty,P=x.call(Object);const T=function(t){if(!a(t)||"[object Object]"!=w(t))return!1;var e=j(t);if(null===e)return!0;var o=S.call(e,"constructor")&&e.constructor;return"function"==typeof o&&o instanceof o&&x.call(o)==P};const D=function(t){return a(t)&&1===t.nodeType&&!T(t)};class C extends((0,t.DataApiMixin)((0,t.ElementApiMixin)(t.Editor))){constructor(o,i={}){if(!R(o)&&void 0!==i.initialData)throw new r.CKEditorError("editor-create-initial-data",null);super(i),void 0===this.config.get("initialData")&&this.config.set("initialData",function(t){return R(t)?(0,r.getDataFromElement)(t):t}(o)),R(o)&&(this.sourceElement=o,(0,t.secureSourceElement)(this));const n=this.config.get("plugins");n.push(e.BalloonToolbar),this.config.set("plugins",n),this.config.define("balloonToolbar",this.config.get("toolbar")),this.model.document.createRoot();const a=new c(this.locale,this.editing.view,this.sourceElement);this.ui=new s(this,a),(0,t.attachToForm)(this)}destroy(){const t=this.getData();return this.ui.destroy(),super.destroy().then((()=>{this.sourceElement&&this.updateSourceElement(t)}))}static create(t,e={}){return new Promise((o=>{if(R(t)&&"TEXTAREA"===t.tagName)throw new r.CKEditorError("editor-wrong-element",null);const i=new this(t,e);o(i.initPlugins().then((()=>i.ui.init())).then((()=>i.data.init(i.config.get("initialData")))).then((()=>i.fire("ready"))).then((()=>i)))}))}}function R(t){return D(t)}})(),(window.CKEditor5=window.CKEditor5||{}).editorBalloon=i})(); |
{ | ||
"name": "@ckeditor/ckeditor5-editor-balloon", | ||
"version": "35.3.2", | ||
"version": "35.4.0", | ||
"description": "Balloon editor implementation for CKEditor 5.", | ||
@@ -14,19 +14,20 @@ "keywords": [ | ||
"dependencies": { | ||
"ckeditor5": "^35.3.2", | ||
"ckeditor5": "^35.4.0", | ||
"lodash-es": "^4.17.15" | ||
}, | ||
"devDependencies": { | ||
"@ckeditor/ckeditor5-basic-styles": "^35.3.2", | ||
"@ckeditor/ckeditor5-core": "^35.3.2", | ||
"@ckeditor/ckeditor5-basic-styles": "^35.4.0", | ||
"@ckeditor/ckeditor5-core": "^35.4.0", | ||
"@ckeditor/ckeditor5-dev-utils": "^31.0.0", | ||
"@ckeditor/ckeditor5-engine": "^35.3.2", | ||
"@ckeditor/ckeditor5-enter": "^35.3.2", | ||
"@ckeditor/ckeditor5-heading": "^35.3.2", | ||
"@ckeditor/ckeditor5-image": "^35.3.2", | ||
"@ckeditor/ckeditor5-paragraph": "^35.3.2", | ||
"@ckeditor/ckeditor5-theme-lark": "^35.3.2", | ||
"@ckeditor/ckeditor5-typing": "^35.3.2", | ||
"@ckeditor/ckeditor5-ui": "^35.3.2", | ||
"@ckeditor/ckeditor5-undo": "^35.3.2", | ||
"@ckeditor/ckeditor5-utils": "^35.3.2", | ||
"@ckeditor/ckeditor5-engine": "^35.4.0", | ||
"@ckeditor/ckeditor5-enter": "^35.4.0", | ||
"@ckeditor/ckeditor5-heading": "^35.4.0", | ||
"@ckeditor/ckeditor5-image": "^35.4.0", | ||
"@ckeditor/ckeditor5-paragraph": "^35.4.0", | ||
"@ckeditor/ckeditor5-theme-lark": "^35.4.0", | ||
"@ckeditor/ckeditor5-typing": "^35.4.0", | ||
"@ckeditor/ckeditor5-ui": "^35.4.0", | ||
"@ckeditor/ckeditor5-undo": "^35.4.0", | ||
"@ckeditor/ckeditor5-utils": "^35.4.0", | ||
"typescript": "^4.8.4", | ||
"webpack": "^5.58.1", | ||
@@ -50,3 +51,4 @@ "webpack-cli": "^4.9.0" | ||
"lang", | ||
"src", | ||
"src/**/*.js", | ||
"src/**/*.d.ts", | ||
"theme", | ||
@@ -58,4 +60,6 @@ "build", | ||
"scripts": { | ||
"dll:build": "webpack" | ||
"dll:build": "webpack", | ||
"build": "tsc -p ./tsconfig.release.json", | ||
"postversion": "npm run build" | ||
} | ||
} |
@@ -5,16 +5,11 @@ /** | ||
*/ | ||
/** | ||
* @module editor-balloon/ballooneditor | ||
*/ | ||
import { Editor, DataApiMixin, ElementApiMixin, attachToForm, secureSourceElement } from 'ckeditor5/src/core'; | ||
import { BalloonToolbar } from 'ckeditor5/src/ui'; | ||
import { CKEditorError, getDataFromElement, mix } from 'ckeditor5/src/utils'; | ||
import { isElement } from 'lodash-es'; | ||
import { CKEditorError, getDataFromElement } from 'ckeditor5/src/utils'; | ||
import BalloonEditorUI from './ballooneditorui'; | ||
import BalloonEditorUIView from './ballooneditoruiview'; | ||
import { isElement as _isElement } from 'lodash-es'; | ||
/** | ||
@@ -43,195 +38,175 @@ * The {@glink installation/getting-started/predefined-builds#balloon-editor balloon editor} | ||
* {@link module:editor-balloon/ballooneditor~BalloonEditor.create `BalloonEditor.create()`}. | ||
* | ||
* @mixes module:core/editor/utils/dataapimixin~DataApiMixin | ||
* @mixes module:core/editor/utils/elementapimixin~ElementApiMixin | ||
* @implements module:core/editor/editorwithui~EditorWithUI | ||
* @extends module:core/editor/editor~Editor | ||
*/ | ||
export default class BalloonEditor extends Editor { | ||
/** | ||
* Creates an instance of the balloon editor. | ||
* | ||
* **Note:** do not use the constructor to create editor instances. Use the static | ||
* {@link module:editor-balloon/ballooneditor~BalloonEditor.create `BalloonEditor.create()`} method instead. | ||
* | ||
* @protected | ||
* @param {HTMLElement|String} sourceElementOrData The DOM element that will be the source for the created editor | ||
* (on which the editor will be initialized) or initial data for the editor. For more information see | ||
* {@link module:editor-balloon/ballooneditor~BalloonEditor.create `BalloonEditor.create()`}. | ||
* @param {module:core/editor/editorconfig~EditorConfig} [config] The editor configuration. | ||
*/ | ||
constructor( sourceElementOrData, config = {} ) { | ||
// If both `config.initialData` is set and initial data is passed as the constructor parameter, then throw. | ||
if ( !isElement( sourceElementOrData ) && config.initialData !== undefined ) { | ||
// Documented in core/editor/editorconfig.jsdoc. | ||
// eslint-disable-next-line ckeditor5-rules/ckeditor-error-message | ||
throw new CKEditorError( 'editor-create-initial-data', null ); | ||
} | ||
super( config ); | ||
if ( this.config.get( 'initialData' ) === undefined ) { | ||
this.config.set( 'initialData', getInitialData( sourceElementOrData ) ); | ||
} | ||
if ( isElement( sourceElementOrData ) ) { | ||
this.sourceElement = sourceElementOrData; | ||
secureSourceElement( this ); | ||
} | ||
const plugins = this.config.get( 'plugins' ); | ||
plugins.push( BalloonToolbar ); | ||
this.config.set( 'plugins', plugins ); | ||
this.config.define( 'balloonToolbar', this.config.get( 'toolbar' ) ); | ||
this.model.document.createRoot(); | ||
const view = new BalloonEditorUIView( this.locale, this.editing.view, this.sourceElement ); | ||
this.ui = new BalloonEditorUI( this, view ); | ||
attachToForm( this ); | ||
} | ||
/** | ||
* Destroys the editor instance, releasing all resources used by it. | ||
* | ||
* Updates the original editor element with the data if the | ||
* {@link module:core/editor/editorconfig~EditorConfig#updateSourceElementOnDestroy `updateSourceElementOnDestroy`} | ||
* configuration option is set to `true`. | ||
* | ||
* @returns {Promise} | ||
*/ | ||
destroy() { | ||
// Cache the data, then destroy. | ||
// It's safe to assume that the model->view conversion will not work after super.destroy(). | ||
const data = this.getData(); | ||
this.ui.destroy(); | ||
return super.destroy() | ||
.then( () => { | ||
if ( this.sourceElement ) { | ||
this.updateSourceElement( data ); | ||
} | ||
} ); | ||
} | ||
/** | ||
* Creates a new balloon editor instance. | ||
* | ||
* There are three general ways how the editor can be initialized. | ||
* | ||
* # Using an existing DOM element (and loading data from it) | ||
* | ||
* You can initialize the editor using an existing DOM element: | ||
* | ||
* BalloonEditor | ||
* .create( document.querySelector( '#editor' ) ) | ||
* .then( editor => { | ||
* console.log( 'Editor was initialized', editor ); | ||
* } ) | ||
* .catch( err => { | ||
* console.error( err.stack ); | ||
* } ); | ||
* | ||
* The element's content will be used as the editor data and the element will become the editable element. | ||
* | ||
* # Creating a detached editor | ||
* | ||
* Alternatively, you can initialize the editor by passing the initial data directly as a string. | ||
* In this case, the editor will render an element that must be inserted into the DOM for the editor to work properly: | ||
* | ||
* BalloonEditor | ||
* .create( '<p>Hello world!</p>' ) | ||
* .then( editor => { | ||
* console.log( 'Editor was initialized', editor ); | ||
* | ||
* // Initial data was provided so the editor UI element needs to be added manually to the DOM. | ||
* document.body.appendChild( editor.ui.element ); | ||
* } ) | ||
* .catch( err => { | ||
* console.error( err.stack ); | ||
* } ); | ||
* | ||
* This lets you dynamically append the editor to your web page whenever it is convenient for you. You may use this method if your | ||
* web page content is generated on the client side and the DOM structure is not ready at the moment when you initialize the editor. | ||
* | ||
* # Using an existing DOM element (and data provided in `config.initialData`) | ||
* | ||
* You can also mix these two ways by providing a DOM element to be used and passing the initial data through the configuration: | ||
* | ||
* BalloonEditor | ||
* .create( document.querySelector( '#editor' ), { | ||
* initialData: '<h2>Initial data</h2><p>Foo bar.</p>' | ||
* } ) | ||
* .then( editor => { | ||
* console.log( 'Editor was initialized', editor ); | ||
* } ) | ||
* .catch( err => { | ||
* console.error( err.stack ); | ||
* } ); | ||
* | ||
* This method can be used to initialize the editor on an existing element with the specified content in case if your integration | ||
* makes it difficult to set the content of the source element. | ||
* | ||
* Note that an error will be thrown if you pass the initial data both as the first parameter and also in the configuration. | ||
* | ||
* # Configuring the editor | ||
* | ||
* See the {@link module:core/editor/editorconfig~EditorConfig editor configuration documentation} to learn more about | ||
* customizing plugins, toolbar and more. | ||
* | ||
* # Using the editor from source | ||
* | ||
* The code samples listed in the previous sections of this documentation assume that you are using an | ||
* {@glink installation/getting-started/predefined-builds editor build} (for example – `@ckeditor/ckeditor5-build-balloon`). | ||
* | ||
* If you want to use the balloon editor from source (`@ckeditor/ckeditor5-editor-balloon/src/ballooneditor`), | ||
* you need to define the list of | ||
* {@link module:core/editor/editorconfig~EditorConfig#plugins plugins to be initialized} and | ||
* {@link module:core/editor/editorconfig~EditorConfig#toolbar toolbar items}. Read more about using the editor from | ||
* source in the {@glink installation/advanced/alternative-setups/integrating-from-source dedicated guide}. | ||
* | ||
* @param {HTMLElement|String} sourceElementOrData The DOM element that will be the source for the created editor | ||
* or the editor's initial data. | ||
* | ||
* If a DOM element is passed, its content will be automatically loaded to the editor upon initialization. | ||
* The editor data will be set back to the original element once the editor is destroyed only if the | ||
* {@link module:core/editor/editorconfig~EditorConfig#updateSourceElementOnDestroy updateSourceElementOnDestroy} | ||
* option is set to `true`. | ||
* | ||
* If the initial data is passed, a detached editor will be created. In this case you need to insert it into the DOM manually. | ||
* It is available under the {@link module:editor-balloon/ballooneditorui~BalloonEditorUI#element `editor.ui.element`} property. | ||
* | ||
* @param {module:core/editor/editorconfig~EditorConfig} [config] The editor configuration. | ||
* @returns {Promise} A promise resolved once the editor is ready. The promise resolves with the created editor instance. | ||
*/ | ||
static create( sourceElementOrData, config = {} ) { | ||
return new Promise( resolve => { | ||
if ( isElement( sourceElementOrData ) && sourceElementOrData.tagName === 'TEXTAREA' ) { | ||
// Documented in core/editor/editor.js | ||
// eslint-disable-next-line ckeditor5-rules/ckeditor-error-message | ||
throw new CKEditorError( 'editor-wrong-element', null ); | ||
} | ||
const editor = new this( sourceElementOrData, config ); | ||
resolve( | ||
editor.initPlugins() | ||
.then( () => editor.ui.init() ) | ||
.then( () => editor.data.init( editor.config.get( 'initialData' ) ) ) | ||
.then( () => editor.fire( 'ready' ) ) | ||
.then( () => editor ) | ||
); | ||
} ); | ||
} | ||
export default class BalloonEditor extends DataApiMixin(ElementApiMixin(Editor)) { | ||
/** | ||
* Creates an instance of the balloon editor. | ||
* | ||
* **Note:** do not use the constructor to create editor instances. Use the static | ||
* {@link module:editor-balloon/ballooneditor~BalloonEditor.create `BalloonEditor.create()`} method instead. | ||
* | ||
* @param sourceElementOrData The DOM element that will be the source for the created editor | ||
* (on which the editor will be initialized) or initial data for the editor. For more information see | ||
* {@link module:editor-balloon/ballooneditor~BalloonEditor.create `BalloonEditor.create()`}. | ||
* @param config The editor configuration. | ||
*/ | ||
constructor(sourceElementOrData, config = {}) { | ||
// If both `config.initialData` is set and initial data is passed as the constructor parameter, then throw. | ||
if (!isElement(sourceElementOrData) && config.initialData !== undefined) { | ||
// Documented in core/editor/editorconfig.jsdoc. | ||
// eslint-disable-next-line ckeditor5-rules/ckeditor-error-message | ||
throw new CKEditorError('editor-create-initial-data', null); | ||
} | ||
super(config); | ||
if (this.config.get('initialData') === undefined) { | ||
this.config.set('initialData', getInitialData(sourceElementOrData)); | ||
} | ||
if (isElement(sourceElementOrData)) { | ||
this.sourceElement = sourceElementOrData; | ||
secureSourceElement(this); | ||
} | ||
const plugins = this.config.get('plugins'); | ||
plugins.push(BalloonToolbar); | ||
this.config.set('plugins', plugins); | ||
this.config.define('balloonToolbar', this.config.get('toolbar')); | ||
this.model.document.createRoot(); | ||
const view = new BalloonEditorUIView(this.locale, this.editing.view, this.sourceElement); | ||
this.ui = new BalloonEditorUI(this, view); | ||
attachToForm(this); | ||
} | ||
/** | ||
* Destroys the editor instance, releasing all resources used by it. | ||
* | ||
* Updates the original editor element with the data if the | ||
* {@link module:core/editor/editorconfig~EditorConfig#updateSourceElementOnDestroy `updateSourceElementOnDestroy`} | ||
* configuration option is set to `true`. | ||
*/ | ||
destroy() { | ||
// Cache the data, then destroy. | ||
// It's safe to assume that the model->view conversion will not work after super.destroy(). | ||
const data = this.getData(); | ||
this.ui.destroy(); | ||
return super.destroy() | ||
.then(() => { | ||
if (this.sourceElement) { | ||
this.updateSourceElement(data); | ||
} | ||
}); | ||
} | ||
/** | ||
* Creates a new balloon editor instance. | ||
* | ||
* There are three general ways how the editor can be initialized. | ||
* | ||
* # Using an existing DOM element (and loading data from it) | ||
* | ||
* You can initialize the editor using an existing DOM element: | ||
* | ||
* ```ts | ||
* BalloonEditor | ||
* .create( document.querySelector( '#editor' ) ) | ||
* .then( editor => { | ||
* console.log( 'Editor was initialized', editor ); | ||
* } ) | ||
* .catch( err => { | ||
* console.error( err.stack ); | ||
* } ); | ||
* ``` | ||
* | ||
* The element's content will be used as the editor data and the element will become the editable element. | ||
* | ||
* # Creating a detached editor | ||
* | ||
* Alternatively, you can initialize the editor by passing the initial data directly as a string. | ||
* In this case, the editor will render an element that must be inserted into the DOM for the editor to work properly: | ||
* | ||
* ```ts | ||
* BalloonEditor | ||
* .create( '<p>Hello world!</p>' ) | ||
* .then( editor => { | ||
* console.log( 'Editor was initialized', editor ); | ||
* | ||
* // Initial data was provided so the editor UI element needs to be added manually to the DOM. | ||
* document.body.appendChild( editor.ui.element ); | ||
* } ) | ||
* .catch( err => { | ||
* console.error( err.stack ); | ||
* } ); | ||
* ``` | ||
* | ||
* This lets you dynamically append the editor to your web page whenever it is convenient for you. You may use this method if your | ||
* web page content is generated on the client side and the DOM structure is not ready at the moment when you initialize the editor. | ||
* | ||
* # Using an existing DOM element (and data provided in `config.initialData`) | ||
* | ||
* You can also mix these two ways by providing a DOM element to be used and passing the initial data through the configuration: | ||
* | ||
* ```ts | ||
* BalloonEditor | ||
* .create( document.querySelector( '#editor' ), { | ||
* initialData: '<h2>Initial data</h2><p>Foo bar.</p>' | ||
* } ) | ||
* .then( editor => { | ||
* console.log( 'Editor was initialized', editor ); | ||
* } ) | ||
* .catch( err => { | ||
* console.error( err.stack ); | ||
* } ); | ||
* ``` | ||
* | ||
* This method can be used to initialize the editor on an existing element with the specified content in case if your integration | ||
* makes it difficult to set the content of the source element. | ||
* | ||
* Note that an error will be thrown if you pass the initial data both as the first parameter and also in the configuration. | ||
* | ||
* # Configuring the editor | ||
* | ||
* See the {@link module:core/editor/editorconfig~EditorConfig editor configuration documentation} to learn more about | ||
* customizing plugins, toolbar and more. | ||
* | ||
* # Using the editor from source | ||
* | ||
* The code samples listed in the previous sections of this documentation assume that you are using an | ||
* {@glink installation/getting-started/predefined-builds editor build} (for example – `@ckeditor/ckeditor5-build-balloon`). | ||
* | ||
* If you want to use the balloon editor from source (`@ckeditor/ckeditor5-editor-balloon/src/ballooneditor`), | ||
* you need to define the list of | ||
* {@link module:core/editor/editorconfig~EditorConfig#plugins plugins to be initialized} and | ||
* {@link module:core/editor/editorconfig~EditorConfig#toolbar toolbar items}. Read more about using the editor from | ||
* source in the {@glink installation/advanced/alternative-setups/integrating-from-source dedicated guide}. | ||
* | ||
* @param sourceElementOrData The DOM element that will be the source for the created editor | ||
* or the editor's initial data. | ||
* | ||
* If a DOM element is passed, its content will be automatically loaded to the editor upon initialization. | ||
* The editor data will be set back to the original element once the editor is destroyed only if the | ||
* {@link module:core/editor/editorconfig~EditorConfig#updateSourceElementOnDestroy updateSourceElementOnDestroy} | ||
* option is set to `true`. | ||
* | ||
* If the initial data is passed, a detached editor will be created. In this case you need to insert it into the DOM manually. | ||
* It is available under the {@link module:editor-balloon/ballooneditorui~BalloonEditorUI#element `editor.ui.element`} property. | ||
* | ||
* @param config The editor configuration. | ||
* @returns A promise resolved once the editor is ready. The promise resolves with the created editor instance. | ||
*/ | ||
static create(sourceElementOrData, config = {}) { | ||
return new Promise(resolve => { | ||
if (isElement(sourceElementOrData) && sourceElementOrData.tagName === 'TEXTAREA') { | ||
// Documented in core/editor/editor.js | ||
// eslint-disable-next-line ckeditor5-rules/ckeditor-error-message | ||
throw new CKEditorError('editor-wrong-element', null); | ||
} | ||
const editor = new this(sourceElementOrData, config); | ||
resolve(editor.initPlugins() | ||
.then(() => editor.ui.init()) | ||
.then(() => editor.data.init(editor.config.get('initialData'))) | ||
.then(() => editor.fire('ready')) | ||
.then(() => editor)); | ||
}); | ||
} | ||
} | ||
mix( BalloonEditor, DataApiMixin ); | ||
mix( BalloonEditor, ElementApiMixin ); | ||
function getInitialData( sourceElementOrData ) { | ||
return isElement( sourceElementOrData ) ? getDataFromElement( sourceElementOrData ) : sourceElementOrData; | ||
function getInitialData(sourceElementOrData) { | ||
return isElement(sourceElementOrData) ? getDataFromElement(sourceElementOrData) : sourceElementOrData; | ||
} | ||
function isElement(value) { | ||
return _isElement(value); | ||
} |
@@ -5,119 +5,90 @@ /** | ||
*/ | ||
/** | ||
* @module editor-balloon/ballooneditorui | ||
*/ | ||
import { EditorUI } from 'ckeditor5/src/core'; | ||
import { enablePlaceholder } from 'ckeditor5/src/engine'; | ||
/** | ||
* The balloon editor UI class. | ||
* | ||
* @extends module:core/editor/editorui~EditorUI | ||
*/ | ||
export default class BalloonEditorUI extends EditorUI { | ||
/** | ||
* Creates an instance of the balloon editor UI class. | ||
* | ||
* @param {module:core/editor/editor~Editor} editor The editor instance. | ||
* @param {module:ui/editorui/editoruiview~EditorUIView} view The view of the UI. | ||
*/ | ||
constructor( editor, view ) { | ||
super( editor ); | ||
/** | ||
* The main (top–most) view of the editor UI. | ||
* | ||
* @readonly | ||
* @member {module:ui/editorui/editoruiview~EditorUIView} #view | ||
*/ | ||
this.view = view; | ||
} | ||
/** | ||
* @inheritDoc | ||
*/ | ||
get element() { | ||
return this.view.editable.element; | ||
} | ||
/** | ||
* Initializes the UI. | ||
*/ | ||
init() { | ||
const editor = this.editor; | ||
const view = this.view; | ||
const editingView = editor.editing.view; | ||
const editable = view.editable; | ||
const editingRoot = editingView.document.getRoot(); | ||
// The editable UI and editing root should share the same name. Then name is used | ||
// to recognize the particular editable, for instance in ARIA attributes. | ||
editable.name = editingRoot.rootName; | ||
view.render(); | ||
// The editable UI element in DOM is available for sure only after the editor UI view has been rendered. | ||
// But it can be available earlier if a DOM element has been passed to BalloonEditor.create(). | ||
const editableElement = editable.element; | ||
// Register the editable UI view in the editor. A single editor instance can aggregate multiple | ||
// editable areas (roots) but the balloon editor has only one. | ||
this.setEditableElement( editable.name, editableElement ); | ||
// Let the editable UI element respond to the changes in the global editor focus | ||
// tracker. It has been added to the same tracker a few lines above but, in reality, there are | ||
// many focusable areas in the editor, like balloons, toolbars or dropdowns and as long | ||
// as they have focus, the editable should act like it is focused too (although technically | ||
// it isn't), e.g. by setting the proper CSS class, visually announcing focus to the user. | ||
// Doing otherwise will result in editable focus styles disappearing, once e.g. the | ||
// toolbar gets focused. | ||
editable.bind( 'isFocused' ).to( this.focusTracker ); | ||
// Bind the editable UI element to the editing view, making it an end– and entry–point | ||
// of the editor's engine. This is where the engine meets the UI. | ||
editingView.attachDomRoot( editableElement ); | ||
this._initPlaceholder(); | ||
this.fire( 'ready' ); | ||
} | ||
/** | ||
* @inheritDoc | ||
*/ | ||
destroy() { | ||
super.destroy(); | ||
const view = this.view; | ||
const editingView = this.editor.editing.view; | ||
editingView.detachDomRoot( view.editable.name ); | ||
view.destroy(); | ||
} | ||
/** | ||
* Enable the placeholder text on the editing root, if any was configured. | ||
* | ||
* @private | ||
*/ | ||
_initPlaceholder() { | ||
const editor = this.editor; | ||
const editingView = editor.editing.view; | ||
const editingRoot = editingView.document.getRoot(); | ||
const sourceElement = editor.sourceElement; | ||
const placeholderText = editor.config.get( 'placeholder' ) || | ||
sourceElement && sourceElement.tagName.toLowerCase() === 'textarea' && sourceElement.getAttribute( 'placeholder' ); | ||
if ( placeholderText ) { | ||
enablePlaceholder( { | ||
view: editingView, | ||
element: editingRoot, | ||
text: placeholderText, | ||
isDirectHost: false, | ||
keepOnFocus: true | ||
} ); | ||
} | ||
} | ||
/** | ||
* Creates an instance of the balloon editor UI class. | ||
* | ||
* @param editor The editor instance. | ||
* @param view The view of the UI. | ||
*/ | ||
constructor(editor, view) { | ||
super(editor); | ||
this.view = view; | ||
} | ||
/** | ||
* @inheritDoc | ||
*/ | ||
get element() { | ||
return this.view.editable.element; | ||
} | ||
/** | ||
* Initializes the UI. | ||
*/ | ||
init() { | ||
const editor = this.editor; | ||
const view = this.view; | ||
const editingView = editor.editing.view; | ||
const editable = view.editable; | ||
const editingRoot = editingView.document.getRoot(); | ||
// The editable UI and editing root should share the same name. Then name is used | ||
// to recognize the particular editable, for instance in ARIA attributes. | ||
editable.name = editingRoot.rootName; | ||
view.render(); | ||
// The editable UI element in DOM is available for sure only after the editor UI view has been rendered. | ||
// But it can be available earlier if a DOM element has been passed to BalloonEditor.create(). | ||
const editableElement = editable.element; | ||
// Register the editable UI view in the editor. A single editor instance can aggregate multiple | ||
// editable areas (roots) but the balloon editor has only one. | ||
this.setEditableElement(editable.name, editableElement); | ||
// Let the editable UI element respond to the changes in the global editor focus | ||
// tracker. It has been added to the same tracker a few lines above but, in reality, there are | ||
// many focusable areas in the editor, like balloons, toolbars or dropdowns and as long | ||
// as they have focus, the editable should act like it is focused too (although technically | ||
// it isn't), e.g. by setting the proper CSS class, visually announcing focus to the user. | ||
// Doing otherwise will result in editable focus styles disappearing, once e.g. the | ||
// toolbar gets focused. | ||
editable.bind('isFocused').to(this.focusTracker); | ||
// Bind the editable UI element to the editing view, making it an end– and entry–point | ||
// of the editor's engine. This is where the engine meets the UI. | ||
editingView.attachDomRoot(editableElement); | ||
this._initPlaceholder(); | ||
this.fire('ready'); | ||
} | ||
/** | ||
* @inheritDoc | ||
*/ | ||
destroy() { | ||
super.destroy(); | ||
const view = this.view; | ||
const editingView = this.editor.editing.view; | ||
editingView.detachDomRoot(view.editable.name); | ||
view.destroy(); | ||
} | ||
/** | ||
* Enable the placeholder text on the editing root, if any was configured. | ||
*/ | ||
_initPlaceholder() { | ||
const editor = this.editor; | ||
const editingView = editor.editing.view; | ||
const editingRoot = editingView.document.getRoot(); | ||
const sourceElement = editor.sourceElement; | ||
const placeholderText = editor.config.get('placeholder') || | ||
sourceElement && sourceElement.tagName.toLowerCase() === 'textarea' && sourceElement.getAttribute('placeholder'); | ||
if (placeholderText) { | ||
enablePlaceholder({ | ||
view: editingView, | ||
element: editingRoot, | ||
text: placeholderText, | ||
isDirectHost: false, | ||
keepOnFocus: true | ||
}); | ||
} | ||
} | ||
} |
@@ -5,49 +5,34 @@ /** | ||
*/ | ||
/** | ||
* @module editor-balloon/ballooneditoruiview | ||
*/ | ||
import { EditorUIView, InlineEditableUIView } from 'ckeditor5/src/ui'; | ||
/** | ||
* Contextual editor UI view. Uses the {@link module:ui/editableui/inline/inlineeditableuiview~InlineEditableUIView}. | ||
* | ||
* @extends module:ui/editorui/editoruiview~EditorUIView | ||
*/ | ||
export default class BalloonEditorUIView extends EditorUIView { | ||
/** | ||
* Creates an instance of the balloon editor UI view. | ||
* | ||
* @param {module:utils/locale~Locale} locale The {@link module:core/editor/editor~Editor#locale} instance. | ||
* @param {module:engine/view/view~View} editingView The editing view instance this view is related to. | ||
* @param {HTMLElement} [editableElement] The editable element. If not specified, it will be automatically created by | ||
* {@link module:ui/editableui/editableuiview~EditableUIView}. Otherwise, the given element will be used. | ||
*/ | ||
constructor( locale, editingView, editableElement ) { | ||
super( locale ); | ||
const t = locale.t; | ||
/** | ||
* The editable UI view. | ||
* | ||
* @readonly | ||
* @member {module:ui/editableui/inline/inlineeditableuiview~InlineEditableUIView} | ||
*/ | ||
this.editable = new InlineEditableUIView( locale, editingView, editableElement, { | ||
label: editableView => { | ||
return t( 'Rich Text Editor. Editing area: %0', editableView.name ); | ||
} | ||
} ); | ||
} | ||
/** | ||
* @inheritDoc | ||
*/ | ||
render() { | ||
super.render(); | ||
this.registerChild( this.editable ); | ||
} | ||
/** | ||
* Creates an instance of the balloon editor UI view. | ||
* | ||
* @param locale The {@link module:core/editor/editor~Editor#locale} instance. | ||
* @param editingView The editing view instance this view is related to. | ||
* @param editableElement The editable element. If not specified, it will be automatically created by | ||
* {@link module:ui/editableui/editableuiview~EditableUIView}. Otherwise, the given element will be used. | ||
*/ | ||
constructor(locale, editingView, editableElement) { | ||
super(locale); | ||
const t = locale.t; | ||
this.editable = new InlineEditableUIView(locale, editingView, editableElement, { | ||
label: editableView => { | ||
return t('Rich Text Editor. Editing area: %0', editableView.name); | ||
} | ||
}); | ||
} | ||
/** | ||
* @inheritDoc | ||
*/ | ||
render() { | ||
super.render(); | ||
this.registerChild(this.editable); | ||
} | ||
} |
@@ -5,7 +5,5 @@ /** | ||
*/ | ||
/** | ||
* @module editor-balloon | ||
*/ | ||
export { default as BalloonEditor } from './ballooneditor'; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
33115
16
9
351
Updatedckeditor5@^35.4.0