Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Html Widget #5566

Closed
turigeza opened this issue Oct 10, 2019 · 10 comments
Closed

Custom Html Widget #5566

turigeza opened this issue Oct 10, 2019 · 10 comments
Labels
resolution:duplicate This issue is a duplicate of another issue and was merged into it. type:feature This issue reports a feature request (an idea for a new functionality or a missing option). type:question This issue asks a question (how to...).

Comments

@turigeza
Copy link

turigeza commented Oct 10, 2019

📝 Provide a description of the new feature

A widget @ckeditor/ckeditor5-widget which could contain arbitrary text / html.

What is the expected behavior of the proposed feature?

Let's say the source code contains the following html.

<div class="custom-html">
    This is some text I don't want to edit just want to preserve it. Same goes
    for the html.

    The div always have the class custom-html.

    Ideally I wanted it to be converted to a non editable widget. 
    Which can then behave as a widget. 

    Can be deleted / selected /copied / pasted etc ...
    <p data-id="22221111"> 
    Unfortunately the p tab gets discarded 
    because it does not fit any model in the editor. </p>    
    <p class="someclass">
    But the content here is arbitrary and I don't want to edit it so I don't need a model for it. 
    I just would like the html not to be modified / stripped from this widget.</p>
</div>

So currently I would end up with this in the editor.

<div class="custom-html ck-widget ck-widget_selected" contenteditable="false">This is some text I don't want to edit just want to preserve it. &nbsp; &nbsp; The div always have the class customHtml. &nbsp; &nbsp; Ideally want it to be converted to a non editable widget. &nbsp; &nbsp; Which can then behave as a widget. &nbsp; &nbsp; Can be deleted / selected /copied / pasted etc ... &nbsp; &nbsp; &nbsp; &nbsp;Unfortunately the p tab gets discarded &nbsp; &nbsp; because it does not fit any model in the editor. &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;But the content here is arbitrary and I don't want to edit it so I don't need a model for it. &nbsp; &nbsp; I just would like the html stripped from this widget.</div>

I am importing old content and converting it so that I can use ckeditor5 with it.

Now for the most important things I have created (or will do so) models (plugins) which match the old content. Like for example for my layouts.

But there is some stuff which really is not worth describing as a model and I would be happy not to be able to edit it. 

Can I achieve this already somehow ? This is how far I got following the docs. I was hoping I can do it with a non editable widget.

https://github.com/turigeza/ckeditor5-build-balloon-block/tree/master/src/CustomHTML

Thank you

If you'd like to see this feature implemented, add a 👍 reaction to this post.

@turigeza turigeza added the type:feature This issue reports a feature request (an idea for a new functionality or a missing option). label Oct 10, 2019
@Mgsy
Copy link
Member

Mgsy commented Oct 14, 2019

@jodator, can you take a look at it?

@jodator
Copy link
Contributor

jodator commented Oct 15, 2019

So you can achieve this by using UIElement - the name isn't the best for this purpose and we have RawElement on roadmap (without any definitive timeline).

import { stringify } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';

editor.model.schema.register( 'customHtml', {
	// Behaves like a self-contained object (e.g. an image).
	isObject: true,
	// Allow in places where other blocks are allowed (e.g. directly in the root).
	allowWhere: '$block', // Do not allow other content inside so the children will not be converted.
	allowAttributes: [ 'htmlContent' ]
} );

conversion.for( 'upcast' ).elementToElement( {
	model: ( viewElement, writer ) => {
		const stringifiedChildren = Array.from( viewElement.getChildren() ).map( child => stringify( child ) ).join( '' );

		return writer.createElement( 'customHtml', {
			htmlContent: stringifiedChildren
		} );
	},
	view: {
		name: 'div',
		classes: 'custom-html'
	}
} );

conversion.for( 'dataDowncast' ).elementToElement( {
	model: 'customHtml',
	view: ( modelElement, viewWriter ) => {
		const div = viewWriter.createUIElement( 'div', {
			class: 'custom-html'
		}, function( domDocument ) {
			const domElement = this.toDomElement( domDocument );

			domElement.innerHTML = modelElement.getAttribute( 'htmlContent' );

			return domElement;
		} );

		return div;
	}
} );

conversion.for( 'editingDowncast' ).elementToElement( {
	model: 'customHtml',
	view: ( modelElement, viewWriter ) => {
		const div = viewWriter.createUIElement( 'div', { class: 'custom-html' }, function( domDocument ) {
			const domElement = this.toDomElement( domDocument );

			domElement.innerHTML = modelElement.getAttribute( 'htmlContent' );

			return domElement;
		} );

		return toWidget( div, viewWriter, {
			label: 'CustomHtml'
		} );
	}
} );

The trick is to use UIElement which allows rendering any DOM content of the View element - here we just save / output inner children of the div.cutom-html. The second part it to only allow the customHTML element where $block is allowed and not copy other attributes so its children will not be converted inside of it.

@jodator jodator added resolution:duplicate This issue is a duplicate of another issue and was merged into it. type:question This issue asks a question (how to...). labels Oct 15, 2019
@jodator
Copy link
Contributor

jodator commented Oct 15, 2019

I'm closing this as a duplicate of #4469.

@turigeza - If you have any questions regarding this you can ask here.

@jodator jodator closed this as completed Oct 15, 2019
@turigeza
Copy link
Author

@jodator Firstly thank you for the detailed example ! This helps me a great deal. 

You are right that the above approach will do what I want to achieve. 
Also the proposed element is the one I was after I was just not finding it. 

I have copied your code into my plugin and it works except I can not perform "cut" on the widget. I can copy paste the widget  but not cut it. If I attempt to cut the widget a greyed out widget exactly the same as the one I was attempting to cut will remain in place and will not be selectable.

Does this issue sound familiar ? If not just let me know and produce an example pen or something where you can see. 

@jodator
Copy link
Contributor

jodator commented Oct 15, 2019

Does this issue sound familiar ? If not just let me know and produce an example pen or something where you can see.

That would be helpful to check since I don't recall anything in particual that have to do with copy/paste. I suspect that the UIElement might not get copied - but with a pen it will be easier to check.

@turigeza
Copy link
Author

The repo and the source is here
https://github.com/turigeza/ckeditor5-build-balloon-block
You can clone it and run it ... or

The pen is here:
https://codepen.io/turigeza/pen/JjjKNJG
Just read the first widget which contains the instructions.

Btw this is not urgent.
Let me now if that all make sense and you see the issue. Thank you.

@jodator
Copy link
Contributor

jodator commented Oct 18, 2019

Hi @turigeza, I haven't got time to check this because we're focusing on the upcoming release. I still want to at least take a look at this since it looks like a nice example that could be added to our docs.

@turigeza
Copy link
Author

turigeza commented Jan 4, 2020

Hi @jodator ,

Time has passed and I am kind of desperate for this feature. Is there anything I could do to promote the development of this Raw Element mentioned here ?
#4469

The code example you gave above doesn't seem to work for me. I can not cut or delete the ui element. It might just be that I have messed something up ... ?

The pen is still live at.
https://codepen.io/turigeza/pen/JjjKNJG

Thank you,

@Reinmar
Copy link
Member

Reinmar commented May 29, 2020

Hi @turigeza!

I managed to workaround this by adding another container. My code is in https://github.com/ckeditor/ckeditor5/compare/i/5566-raw-html-poc and works fine (copy-paste works). But it's ugly. The issue that would need to be resolved to make this pretties is #4469. And #7336 too for that matter ;/

@turigeza
Copy link
Author

@Reinmar Thank you for that. I ended up using ProseMirror after all so I personally don't need this anymore. But maybe others find it helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
resolution:duplicate This issue is a duplicate of another issue and was merged into it. type:feature This issue reports a feature request (an idea for a new functionality or a missing option). type:question This issue asks a question (how to...).
Projects
None yet
Development

No branches or pull requests

4 participants