In CKEditor5, I tried implementing custom element to convert model to view for editing. Then, editable element(#ckeditor/ckeditor5-engine/src/view/editableelement) in container element(#ckeditor/ckeditor5-engine/src/view/containerelement) is focused on the parent container element and can not be edited.
For example, if it is implemented as follows:
buildModelConverter().for(editing.modelToView)
.fromElement('myElement')
.toElement(new ContainerElement('div', {}, [new EditableElement('h4')]));
The result of actual editing dom after inserting 'myElement' and keydown "abc". (I hope inputting text of "abc" to h4 tag but...)
<div>
abc
<h4>
<br data-cke-filler="true">
</h4>
</div>
I also tried using widget for applying contenteditable attribute.
But, text couldn't be entered in h4.
<div class="ck-widget" contenteditable="false">
<h4 class="ck-editable" contenteditable="true">
<br data-cke-filler="true">
</h4>
</div>
Is this bug, or I made mistake understanding of container element?
[Additional details]
I am assuming to make a widget plugin for ranking list.
First, the ranking list is structured by <ol> and <li> tags because of having multiple items.
I solved that by defining two schema such as "rankingList" and "rankingListItem",
so I realized dynamic elements using nested model elements.
const item1 = new ModelElement('rankingListItem');
const item2 = new ModelElement('rankingListItem');
const model = new ModelElement('rankingList', {}, [item1, item2]);
// and insert
Next, the item of ranking list has link, image, title and note.
Therefore, the ranking list item has the following DOM structure:
<ol><!-- apply toWidget -->
<li>
<a href="link[editable]">
<img src="image[editable]">
<h3>title[editable]</h3>
<p>notes[editable]</p>
</a>
</li>
...
</ol>
I expect the view element is the following:
const {ref, src, title, notes} = data; // how to get data?
const view = new ContainerElement('a', {ref}, [
new EmptyElement('img', {src}),
new EditableElement('h3', {}, new Text(title)),
new EditableElement('p', {}, new Text(title)),
]);
// maybe incorrect ...
In conclusion, I want to use editable view not to break defined DOM tree.
How can I realize it?
Thank you for describing your case. It means a lot for us at the moment to know how developers are using the editor and what are your expectations.
Unfortunately, this looks like a very complex feature. It also looks like it would need custom UI (to edit link url and image src -- unless they do not change after added to the editor). It seems that you struggle with two problems:
position mapping between the model and the view,
nested editables.
First, to answer your question about EditableElement - it seems to be correct to use them for h3 and p elements.
However, such complex feature needs custom converters. Converter builders (which you used) are dedicated to being used in simple cases, like element-to-element conversion, or attribute-to-attribute conversion.
Behind the nice API, build converter is a function factory, that creates one or multiple functions. Those are then added as callbacks to ModelConversionDispatcher (which editor.editing.modelToView is an instance of). ModelConversionDispatcher fires a series of events during the conversion, which is a process of translating a change in the model to the view.
As I've mentioned, you would have to write those converting functions by yourself.
Since this is too big of a subject for a detailed and thorough answer, I'll just briefly present you what you should be interested in. Unfortunately, there are no guides yet about creating custom converters from scratch. This is a very broad subject.
First, let me explain you from where most of your problems come from. As you already know, the editor has three layers: model (data), view (DOM-like structure) and DOM. Model is converted to view and view is rendered to DOM. Also, the other way, when you load data, DOM is converted to view and view is converted to model. This is why you need to provide model-to-view converter and view-to-model converter for your feature.
The important piece of this puzzle is engine.conversion.Mapper. Its role is to map elements and positions from model to view. As you already might have seen, the model might be quite different than the view. Correct position mapping between those is key. When you type a letter at caret position (in DOM), this position is mapped to model and the letter is inserted in the model and only then converted back to the view and DOM. If view-to-model position conversion is wrong, you will not be able to type, or really do anything, at that place.
Mapper is pretty simple on its own. All it needs is that you specify which view elements are bound to which model elements. For example, in the model you might have:
<listItem type="bulleted" indent="0">Foo</listItem>
<listItem type="bulleted" indent="1">Bar</listItem>
While in the view you have:
<ul>
<li>
Foo
<ul>
<li>Bar</li>
</ul>
</li>
</ul>
If the mapper knows that first listItem is bound with first <li> and the second listItem is bound with second <li>, then it is able to translate positions correctly.
Back to your case. Each converter has to provide data for Mapper. Since you used converter builder, the converters build by it already do this. But they are simple, so when you provide:
buildModelConverter().for(editing.modelToView)
.fromElement('myElement')
.toElement(new ContainerElement('div', {}, [new EditableElement('h4')]));
it is assumed, that myElement is bound with the <div>. So anything that is written inside that <div> will go straight to myElement and then will be rendered at the beginning of myElement:
<div>
<h4></h4>
</div>
Assuming that you just wrote x at <h4>, that position will be mapped to myElement offset 0 in the model and then rendered to view at the beginning of <div>.
Model:
<myElement>x</myElement>
View:
<div>x<h4></h4></div>
As you can see, in your case, it is <h4> which should be bound with myElement.
At the moment, we are during refactoring phase. One of the goals is providing more utility functions for converter builders. One of those utilities are converters for elements which have a wrapper element, like in that "div + h4" case above. This is also a case of image feature. The image is represented by <image> in model but it is <figure><img /></figure> in the view. You can look at ckeditor5-image to see how those converters look like now. We want to simplify them.
Unfortunately, your real case is even more complicated because you have multiple elements inside. CKE5 architecture should be able handle your case but you have to understand that this is almost impossible to write without proper guides.
If you want to tinker though, you should study ckeditor5-image repo. It won't be easy, but this is the best way to go. Image plugin together with ImageCaption are very similar to your case.
Model:
<image alt="x" src="y">
<caption>Foo</caption>
</image>
View:
<figure class="image">
<img alt="x" src="y" />
<figcaption>Foo</caption>
</figure>
While in your case, I'd see the model somewhere between those lines:
<rankItem imageSrc="x" linkUrl="y">
<rankTitle>Foo</rankTitle>
<rankNotes>Bar</rankNotes>
</rankItem>
And I'd make the view a bit heavier but it will be easier to write converters:
<li contenteditable="false">
<a href="y">
<img src="x" />
<span class="data">
<span class="title" contenteditable="true">Foo</span>
<span class="notes" contenteditable="true">Bar</span>
</span>
</a>
</li>
For rankTitle and rankNotes - base them on caption element (ckeditor5-image/src/imagecaption/imagecaptionengine.js).
For rankItem - base it on image element (ckeditor5-image/src/image/).
Once again - keep in mind that we are in the process of simplifying all of this. We want people to write their own features, even those complicated ones like yours. However, we are aware of how complex it is right now. That's why there are no docs at the moment - we are looking to change and simplify things.
And lastly - you could create that ranking list simpler, using Link plugin and elements build with converter builder:
rankList -> <ol class="rank">,
rankItem -> <li>,
rankImage -> <img />,
rankNotes -> <span class="notes">,
rankTitle -> <span class="title">.
However, it will be possible to mess it up because the whole structure will be editable.
Model:
<rankList>
<rankItem>
<rankImage linkHref="" />
<rankTitle>Foo</rankTitle>
<rankNotes>Bar</rankNotes>
</rankItem>
...
</rankList>
Where "Foo" and "Bar" also have linkHref attribute set.
View:
<ol class="rank">
<li>
<img src="" />
<span class="title">Title</span>
<span class="notes">Foo</span>
</li>
...
</ol>
Something like this, while far from perfect, should be much easier to write as long as we are before the refactor and before writing guides.
Of course you will also have to provide view-to-model converters. You might want to write them on your own (take a look at ckeditor5-list/src/converters.js viewModelConverter() -- although yours will be easier because it will be flat, not nested list). Or you can generate them through converter builder.
Maybe it will be possible to use the approach above (simpler) but use contentEditable attribute to control the structure. rankList would have to be converted to <ol> with contentEditable="false". Maybe you could somehow use toWidget for better selection handling, for example. rankNotes and rankTitle would have to be converted to element with contentEditable="true" (maybe use toWidgetEditable()).
I have a page which uses dijit/form/Form to validate all of the form widgets in it.
Validation works correctly if I put widgets directly under the Form (tag).
Once I surround the widgets with a dojox/mvc/Group (within the form), Form validation stops completely and none of the widgets seem to validate when I call Form::validate().
Debugging the Dojo code shows that nested widgets are never considered validatable in the Form so when I surround widgets with Group they get excluded from validation.
Is there a workaround for this?
AFAICT from dijit/form/_FormMixin#_getDescendantFormWidgets() and dijit/_WidgetBase#getChildren(), the issue can be solved by adding data-dojo-mixins="dijit/_Container" to the element having data-dojo-type="dojox/mvc/Group".
Also (though I'm not sure if it meets your requirement), dojox/mvc/tests/test_mvc_new_loan-stateful.html example shows form validation solution with dojox/mvc.
Hope it helps.
Best, Akira
It seems like there is no easy way to solve this with dijit/form/Form. At the very least, it should be subclassed or monkey-patched to make it consider nested widgets.
However, it seems that dojox/form/Manager handles nested widgets properly, so I have switched to it.
Switching to Manager required some refactoring since it cannot be simply converted into an object with dom-form (dijit/form/Form can be converted).
HTML code before:
<div
id="_pg_detailForm"
data-dojo-type="dijit/form/Form"
encType="multipart/form-data"
action="" method=""
>
... form widgets (surrounded with MVC Groups...etc)
</div>
After:
<form id="_pg_detailForm">
<div
id="_pg_detailFormManager"
data-dojo-type="dojox/form/Manager"
>
... form widgets (surrounded with MVC Groups...etc)
</div>
</form>
I'm working on a news publishing site that needs to load in stories from an RSS feed below the current news page. I've been using InfiniteAjaxScroll (http://infiniteajaxscroll.com/) to some success however, I've hit a brick wall. There is not way for me to dynamically change what story should load in next as you scroll down the page.
Does anyone know of any other plugins, tutorials, examples that replicate behavior like this. I've searched but come up with nothing that meets these requirements.
I'm trying to create something similar to what the Daily Beast has implemented on their site.
http://www.thedailybeast.com/articles/2014/11/05/inside-the-democrats-godawful-midterm-election-wipeout.html
How do they know what stories to load in?
Thanks!
If you're using the InfiniteAjaxScroll library, the "next story" is whatever link you define as the next URL which can be dynamic for each story you load.
Imagine your first story's HTML as something like this
<div class="stories">
<div class="story">
...
</div>
</div>
<div id="pagination">
next
</div>
Then in the storyC.html you have
...
<div id="pagination">
next
</div>
Assuming you're using some sort of dynamic backend, you would use some sort logic to grab a related story and just set that URL as the "next" URL.
I've been scratching my head like crazy over this all day, there seems to be a hundred different ways to get what I want done but I want it done a certain way - which I can't find.
Here's what I'm working on: http://schmidtbrotherscutlery.com/dev/mySchmidt/myCutlery/
My setup is one view with four different pages, each filtered by category. Default page above lists all three categories at once, and the Category sublinks in the menu take you to the three other view pages that are filtered by a single category. What I need is each of the category sublinks to load their respective view pages with AJAX instead of page by page refresh like it is now. I realize I can effectively achieve the same thing with an exposed filter on the categories but I want these specific menu sublinks to load the view pages, not filter one view on it's own with an exposed form. This really doesn't seem to be that difficult and I don't know why I haven't been able to figure it out yet but I don't have much experience with Drupal+AJAX integration. Help please!
From what I've read it sounds like you should be able to put each of the views within a jQuery tab container. So for example:
<div id="tabs">
<div class="tab">
<?php views_embed_view('viewname', 'block_1')?>
</div>
<div class="tab">
<?php views_embed_view('viewname', 'block_2')?>
</div>
<div class="tab">
<?php views_embed_view('viewname', 'block_3')?>
</div>
</div>
This would allow you to cycle through each content piece without refreshing the page.
I have a basic cms that loads content into pages that have mustache tags to indicate where in the html code those contents will appear.
The contents are specified in a widget model which indicate which type of content is to be displayed, so for example, freetext with id. or another model and id. each one of those models will be displayed differently based on the model they are based on.
I can imagine this becoming and bit unwieldy, is there a way to have a separate folder to put those widgets in so that it doesn't clutter my main code.
Something like apotomo does on rails would be good, but for codeigniter.
A widget model? That is not so nice. Have you tried looking at PyroCMS?
https://github.com/pyrocms/pyrocms/blob/master/system/pyrocms/modules/widgets/libraries/Widgets.php
From the sound of it you may be more interested in our Plugins library (sounds like the same thing with a different name). It is set up with a MY_Parser and runs on top of Dan Horrigan's Simpletags implementation.
Either way this has all be done plenty. If you want some more specific tailored advice you might have to demo some of your code.
Create a folder inside application/views called widgets. Put your widgets inside that folder and create a separate file for each widget (d0h).
Next, you have 2 options (at least that i know of):
a.) Load the widgets into variables inside the controller, then pass them to the main/general view
$data['widget_twitter_feed'] = $this->load->view('widgets/twitter', '', false);
$data['widget_something'] = $this->load->view('widgets/something', '', false);
$this->load->view('my_main_view', $data);
b.) Load the widgets inside the main/general view itself
<html>
...
<div id="sidebar">
<?php $this->load->view('widgets/twitter'); ?>
</div>
...
<div id="footer">
<?php $this->load->view('widgets/something'); ?>
</div>
...
</html>