Преглед на файлове

Extracted DOM renderes and cleaned up naming to make the downcast callback comprehensible.

Piotrek Koszuliński преди 5 години
родител
ревизия
8a6d724395
променени са 1 файла, в които са добавени 115 реда и са изтрити 93 реда
  1. 115 93
      packages/ckeditor5-html-embed/src/htmlembedediting.js

+ 115 - 93
packages/ckeditor5-html-embed/src/htmlembedediting.js

@@ -98,10 +98,6 @@ export default class HtmlEmbedEditing extends Plugin {
 		const upcastWriter = new UpcastWriter( view.document );
 		const htmlProcessor = new HtmlDataProcessor( view.document );
 
-		const editButtonDOMElement = getButtonDOMElement( editor.locale, 'edit' );
-		const saveButtonDOMElement = getButtonDOMElement( editor.locale, 'save' );
-		const cancelButtonDOMElement = getButtonDOMElement( editor.locale, 'cancel' );
-
 		editor.conversion.for( 'upcast' ).elementToElement( {
 			view: {
 				name: 'div',
@@ -134,113 +130,68 @@ export default class HtmlEmbedEditing extends Plugin {
 				const widgetLabel = t( 'HTML snippet' );
 				const placeholder = t( 'Paste raw HTML here...' );
 
-				const widgetView = writer.createContainerElement( 'div', {
+				const viewContainer = writer.createContainerElement( 'div', {
 					class: 'raw-html-embed'
 				} );
 
-				const rawHtmlContainer = writer.createContainerElement( 'div', {
+				const viewRawHtmlContainer = writer.createContainerElement( 'div', {
 					class: 'raw-html-embed__content-wrapper'
 				} );
 
-				const textareaAttributes = {
-					placeholder,
-					disabled: true,
-					class: 'ck ck-reset ck-input ck-input-text raw-html-embed__source'
-				};
-
-				// The editing raw HTML field.
-				const sourceElement = writer.createUIElement( 'textarea', textareaAttributes, function( domDocument ) {
-					const root = this.toDomElement( domDocument );
-
-					writer.setCustomProperty( 'domElement', root, sourceElement );
-					root.value = modelElement.getAttribute( 'value' ) || '';
-					root.readOnly = editor.isReadOnly;
-
-					// When focusing the "edit source" element, the model selection must be updated.
-					// If we do not do it, the `updateHtmlEmbed` command will fail because it
-					// searches the `rawHtml` element based on selection.
-					root.addEventListener( 'focus', () => {
-						editor.model.change( writer => {
-							writer.setSelection( modelElement, 'on' );
-						} );
-					} );
-
-					root.addEventListener( 'input', () => {
-						editor.execute( 'updateHtmlEmbed', root.value );
-					} );
-
-					return root;
-				} );
-
-				const buttonsWrapperAttributes = {
-					class: 'raw-html-embed__buttons-wrapper'
-				};
+				const viewTextarea = writer.createUIElement(
+					'textarea',
+					{
+						placeholder,
+						disabled: true,
+						class: 'ck ck-reset ck-input ck-input-text raw-html-embed__source'
+					},
+					domDocument => {
+						return createDomTextarea( { editor, writer, viewTextarea, modelElement, domDocument } );
+					}
+				);
 
 				// The switch button between preview and editing HTML.
-				const buttonsWrapper = writer.createUIElement( 'div', buttonsWrapperAttributes, function( domDocument ) {
-					const buttonsWrapperDOMElement = this.toDomElement( domDocument );
-
-					buttonsWrapperDOMElement.appendChild( editButtonDOMElement.cloneNode( true ) );
-
-					writer.setCustomProperty( 'domElement', buttonsWrapperDOMElement, buttonsWrapper );
-
-					buttonsWrapperDOMElement.addEventListener( 'click', evt => {
-						view.change( writer => {
-							if ( htmlEmbedConfig.showPreviews ) {
-								if ( widgetView.hasClass( DISPLAY_PREVIEW_CLASS ) ) {
-									writer.setAttribute( IGNORE_EVENTS_ATTRIBUTE, 'true', rawHtmlContainer );
-									writer.removeClass( DISPLAY_PREVIEW_CLASS, widgetView );
-								} else {
-									writer.addClass( DISPLAY_PREVIEW_CLASS, widgetView );
-									writer.removeAttribute( IGNORE_EVENTS_ATTRIBUTE, rawHtmlContainer );
-								}
-							}
-
-							const textarea = sourceElement.getCustomProperty( 'domElement' );
-							textarea.disabled = !textarea.disabled;
-
-							while ( buttonsWrapperDOMElement.firstChild ) {
-								buttonsWrapperDOMElement.firstChild.remove();
-							}
-
-							if ( textarea.disabled ) {
-								buttonsWrapperDOMElement.appendChild( editButtonDOMElement.cloneNode( true ) );
-							} else {
-								buttonsWrapperDOMElement.appendChild( saveButtonDOMElement.cloneNode( true ) );
-								buttonsWrapperDOMElement.appendChild( cancelButtonDOMElement.cloneNode( true ) );
-							}
+				const viewButtonsWrapper = writer.createUIElement(
+					'div',
+					{
+						class: 'raw-html-embed__buttons-wrapper'
+					},
+					function( domDocument ) {
+						return createDomButtonsWrapper( {
+							editor, domDocument, viewButtonsWrapper, htmlEmbedConfig,
+							writer, viewContainer, viewRawHtmlContainer, viewTextarea
 						} );
+					}
+				);
 
-						evt.preventDefault();
-					} );
-
-					return buttonsWrapperDOMElement;
-				} );
-
-				writer.insert( writer.createPositionAt( widgetView, 0 ), rawHtmlContainer );
-				writer.insert( writer.createPositionAt( rawHtmlContainer, 0 ), buttonsWrapper );
-				writer.insert( writer.createPositionAt( rawHtmlContainer, 1 ), sourceElement );
+				writer.insert( writer.createPositionAt( viewContainer, 0 ), viewRawHtmlContainer );
+				writer.insert( writer.createPositionAt( viewRawHtmlContainer, 0 ), viewButtonsWrapper );
+				writer.insert( writer.createPositionAt( viewRawHtmlContainer, 1 ), viewTextarea );
 
 				// The container that renders the HTML should be created only when `htmlEmbed.showPreviews=true` in the config.
 				if ( htmlEmbedConfig.showPreviews ) {
-					writer.addClass( [ 'raw-html-embed_preview_enabled', DISPLAY_PREVIEW_CLASS ], widgetView );
+					writer.addClass( [ 'raw-html-embed_preview_enabled', DISPLAY_PREVIEW_CLASS ], viewContainer );
 
-					const previewContainer = writer.createRawElement( 'div', { class: 'raw-html-embed__preview' }, function( domElement ) {
-						writer.setCustomProperty( 'domElement', domElement, previewContainer );
+					const viewPreviewContainer = writer.createRawElement(
+						'div',
+						{ class: 'raw-html-embed__preview' },
+						function( domElement ) {
+							writer.setCustomProperty( 'domElement', domElement, viewPreviewContainer );
 
-						const sanitizeOutput = htmlEmbedConfig.sanitizeHtml( modelElement.getAttribute( 'value' ) || '' );
-						domElement.innerHTML = sanitizeOutput.html;
-					} );
+							const sanitizedOutput = htmlEmbedConfig.sanitizeHtml( modelElement.getAttribute( 'value' ) || '' );
+							domElement.innerHTML = sanitizedOutput.html;
+						}
+					);
 
-					writer.insert( writer.createPositionAt( rawHtmlContainer, 2 ), previewContainer );
+					writer.insert( writer.createPositionAt( viewRawHtmlContainer, 2 ), viewPreviewContainer );
 				}
 
 				// Listen to read-only changes.
 				this.listenTo( editor, 'change:isReadOnly', ( evt, name, value ) => {
-					sourceElement.getCustomProperty( 'domElement' ).readOnly = value;
+					viewTextarea.getCustomProperty( 'domElement' ).readOnly = value;
 				} );
 
-				return toRawHtmlWidget( widgetView, writer, widgetLabel );
+				return toRawHtmlWidget( viewContainer, writer, widgetLabel );
 			}
 		} );
 
@@ -248,6 +199,77 @@ export default class HtmlEmbedEditing extends Plugin {
 	}
 }
 
+function createDomTextarea( { editor, writer, viewTextarea, modelElement, domDocument } ) {
+	const domTextarea = viewTextarea.toDomElement( domDocument );
+
+	writer.setCustomProperty( 'domElement', domTextarea, viewTextarea );
+
+	domTextarea.value = modelElement.getAttribute( 'value' ) || '';
+	domTextarea.readOnly = editor.isReadOnly;
+
+	// When focusing the "edit source" element, the model selection must be updated.
+	// If we do not do it, the `updateHtmlEmbed` command will fail because it
+	// searches the `rawHtml` element based on selection.
+	domTextarea.addEventListener( 'focus', () => {
+		editor.model.change( writer => {
+			writer.setSelection( modelElement, 'on' );
+		} );
+	} );
+
+	domTextarea.addEventListener( 'input', () => {
+		editor.execute( 'updateHtmlEmbed', domTextarea.value );
+	} );
+
+	return domTextarea;
+}
+
+function createDomButtonsWrapper( {
+	editor, domDocument, viewButtonsWrapper, htmlEmbedConfig,
+	writer, viewContainer, viewRawHtmlContainer, viewTextarea
+} ) {
+	const domButtonsWrapper = viewButtonsWrapper.toDomElement( domDocument );
+
+	const domEditButton = createDomButton( editor.locale, 'edit' );
+	const domSaveButton = createDomButton( editor.locale, 'save' );
+	const domCancelButton = createDomButton( editor.locale, 'cancel' );
+
+	domButtonsWrapper.appendChild( domEditButton.cloneNode( true ) );
+
+	writer.setCustomProperty( 'domElement', domButtonsWrapper, viewButtonsWrapper );
+
+	domButtonsWrapper.addEventListener( 'click', evt => {
+		editor.editing.view.change( writer => {
+			if ( htmlEmbedConfig.showPreviews ) {
+				if ( viewContainer.hasClass( DISPLAY_PREVIEW_CLASS ) ) {
+					writer.setAttribute( IGNORE_EVENTS_ATTRIBUTE, 'true', viewRawHtmlContainer );
+					writer.removeClass( DISPLAY_PREVIEW_CLASS, viewContainer );
+				} else {
+					writer.addClass( DISPLAY_PREVIEW_CLASS, viewContainer );
+					writer.removeAttribute( IGNORE_EVENTS_ATTRIBUTE, viewRawHtmlContainer );
+				}
+			}
+
+			const textarea = viewTextarea.getCustomProperty( 'domElement' );
+			textarea.disabled = !textarea.disabled;
+
+			while ( domButtonsWrapper.firstChild ) {
+				domButtonsWrapper.firstChild.remove();
+			}
+
+			if ( textarea.disabled ) {
+				domButtonsWrapper.appendChild( domEditButton.cloneNode( true ) );
+			} else {
+				domButtonsWrapper.appendChild( domSaveButton.cloneNode( true ) );
+				domButtonsWrapper.appendChild( domCancelButton.cloneNode( true ) );
+			}
+		} );
+
+		evt.preventDefault();
+	} );
+
+	return domButtonsWrapper;
+}
+
 // Returns a converter that handles the `value` attribute of the `rawHtml` element.
 //
 // It updates the source (`textarea`) value and passes an HTML to the preview element if `htmlEmbed.showPreviews=true`.
@@ -258,15 +280,15 @@ function downcastRawHtmlValueAttribute( htmlEmbedConfig ) {
 	return dispatcher => {
 		dispatcher.on( 'attribute:value:rawHtml', ( evt, data, conversionApi ) => {
 			const widgetView = conversionApi.mapper.toViewElement( data.item );
-			const rawHtmlContainer = widgetView.getChild( 1 );
-			const textareaDomElement = rawHtmlContainer.getChild( 1 ).getCustomProperty( 'domElement' );
+			const viewRawHtmlContainer = widgetView.getChild( 1 );
+			const textareaDomElement = viewRawHtmlContainer.getChild( 1 ).getCustomProperty( 'domElement' );
 
 			if ( textareaDomElement ) {
 				textareaDomElement.value = data.item.getAttribute( 'value' );
 			}
 
 			if ( htmlEmbedConfig.showPreviews ) {
-				const previewDomElement = rawHtmlContainer.getChild( 2 ).getCustomProperty( 'domElement' );
+				const previewDomElement = viewRawHtmlContainer.getChild( 2 ).getCustomProperty( 'domElement' );
 
 				if ( previewDomElement ) {
 					const sanitizeOutput = htmlEmbedConfig.sanitizeHtml( data.item.getAttribute( 'value' ) || '' );
@@ -299,7 +321,7 @@ function toRawHtmlWidget( viewElement, writer, label ) {
 //  @param {module:utils/locale~Locale} locale Editor locale.
 //  @param {'edit'|'save'|'cancel'} type Type of button to create.
 //  @returns {HTMLElement}
-function getButtonDOMElement( locale, type ) {
+function createDomButton( locale, type ) {
 	const t = locale.t;
 	const buttonView = new ButtonView( locale );