Draft-js: Losing cursor with non-editable entity components - reactjs

I have an editor that is supposed to have entities with the props name, color, start, end. In the editor the text in positions denoted by start and end will be subsistuted by name, and it will be rendered by a custom component with contentEditable=false.
This works great with draftjs in general but there are a couple of issues:
When moving the cursor with the keyboard arrows, the entities are skipped over, which is good. But when an entity is at the very end of the input and I try to move rightwards past it (either just with right arrow or with option or cmd + right) the cursor disappears and doesn't come back when I move left again.
If I go right to the left of an entity and push shift + option + right arrow, the entity is selected as expected. But if I then press left arrow the cursor is also lost.
I could fix this by making sure there is always a whitespace after such a last entity, but that seems hacky and probably has edge cases.
Another option is to not use contentEditable=false, but that creates other issues with my actual app, which has a more complicated entity component including a dropdown, and I will have to manually make sure the user can't change text inside the entities etc.
Here is a reproduction of the issue: https://codesandbox.io/s/competent-surf-st77i
Any ideas?

Related

Stop RichTextBox from beeping

I have a simple form containing rich text box. When trying to navigate using the cursor keys from it beeps if the caret can't be moved - for example, pressing Home key when the caret is already on start of line, or trying to move line up when the caret is already on top line. Is there a way to disable those beeps?
If you want to disable the ding (beeps) noise from being triggered each time when you press cursor keys or home key, then unfortunately it doesn't seems to be possible. But yeah, you can do it in some specific ways (i.e. using AcceptButton, CancelButton form property described in this SO thread.

Can't properly force a component on-screen with scrollComponentToVisible

On a given form, we replace one component with another.
The original component is a series of TextFields, and the new form is some informational text and a button. We hide the first one, and show the second one (the UI designer has both Containers within the form).
I tried using scrollRectToVisible with various values but it didn't seem to make any difference with the scrolling.
continueButtonContainer.setHidden(false);
f.forceRevalidate();
Button continueButton =
(Button)StateMachine.GetInstance().findByName("ButtonContinue", f);
f.scrollComponentToVisible(continueButtonContainer);
f.scrollComponentToVisible(continueButton);
I'm expecting the continue button to be near the top of the screen.
If the screen was scrolled before displaying the continue button, the button ends up right at the bottom of the screen (it was below the bottom of the screen before I put in the scrollComponentToVisible line(s).
After the user scrolls the screen, the button goes up to where it needs to be, and stays there.
If the screen is not scrolled, the button appears where it should be.
I know I can probably add some invisible containers underneath the button and force them onto the screen, but I would rather have a slightly more robust solution.
There are a few issues with this. First you are using forceRevalidate which should be used in very rare cases.
Second it seems that you are invoking this on a Form, this is a bit misleading. While it seems that:
f.add(myCmp);
Adds a component to the form it is really a synonym to:
f.getContentPane().add(myCmp);
That's important because you need to invoke the scrollComponentToVisible on the scrollable container which will actually do the work and ideally be the direct parent of said component. I'm assuming it's the content pane in your case but it depends on layout etc.
The last part is letting the layout do its job. If you are invoking this before the form is showing this might not work. Notice that doing it after a call to show is meaningless as the form might take time with transitions. You can use a show listener or override the laidOut callback method to perform things like this.

Draft.js get selection or span for already styled elements

I'm using react-rte but am willing to extend it so let's talk about Draft-js.
I need to be able to "inline-style" a selection. Then on subsequent renders re-access that selection's dom.
So let's say I highlight a selection. Then I persist the document. Then I come back, reload the document, I need to be able get access to that highlighted section, but in the dom.
Basically on the side of the document I'm applying markers, outside of draft-js, and those markers need to line up with the highlighted part. So when I do the initial highlighting I can get the dom position from window.getSelection(), and i can place my marker. But the dom may change later and I won't be able to place my marker.
--edit--
So another use case is that I highlight a selection, and even in the same session, I need to change the color of the selection programatically so again I need to access the section of the document even if the cursor is not on that section.
--end edit--
So what I really need is something like an unique classname, id or even better a react ref for the new spans that are created when you do an inline style.
Please let me know if you need a better explanation.
The SelectionState records the selection, including start block, start offset, end block and end offset. It's not problem to save the selection in you code and apply to the editor later.
So what I really need is something like an unique classname, id or even better a react ref for the new spans that are created when you do an inline style.
So the id you want is a SelectionState, tell where the span is in draft-js editor.
UPDATE
You can find the block key which your inline styled text belongs to, in data-offset-key={blockkey}-xx-xx node attribute. The block key helps you find the node from SelectionState.getStartKey()/getEndKey(). Then find the span node by SelectionState.getStartOffset()/getEndOffset().

Select control stops showing its drop down list with IE, AngularJS and some strangely-specific conditions

I have a weird problem whereby a <select> control stops showing its drop down list in IE11 using AngularJS after changing the value (twice).
Chrome (42) and FF (37) do not exhibit the issue.
Plunker: http://plnkr.co/edit/Ea0nMnPxXdqm8O59NyZS?p=preview
Fiddle: http://jsfiddle.net/xydvqo0q/
Steps:
Click the select to open its drop down list.
Select either of the two listed options. (It closes and a couple of other fields in the page update their values.)
Click to open again.
Select the other option. (It closes and the fields update again.)
Click to open the drop down list again. Will no longer open
Neither mouse click, nor Alt-downarrow will show the drop down once it gets into this state.
(Further, other selects on the same page also stop showing their drop down lists, and there appears to be a general control/windowing issue for the page - e.g. you can't select HTML text, and other controls won't show the focus or caret. Seems like IE loses the plot about which is the active "window" and it seems to be stuck inside the select. Pressing Tab a few times gets it out of this stuck state.)
Now, an IE control/windowing bug isn't unusual. But this is weird because of the specific set of requirements to reproduce. I've stripped back the example to what seems to be the minimum required to reproduce (yet you might think there's heaps of stuff in the page that should be irrelevant - afraid not).
The page needs the following for the issue to show:
The nested table (which lists "hello"s) must be there (and it must be nested - if it's not inside another table then the problem goes away). (I made it list hellos to eliminate it listing scope data to eliminate that as a cause.)
The table row which contains {{selecteditem.number}} must be there, and must be AFTER the nested table (moving it before removes the issue). I moved it to a separate table and the problem remains.
The selecteditem.number data must be different for the two items. If the "number" values are the same for the two items, it will not show the issue.
The number of "sub items" for each of the two items must be the SAME (meaning the nested table ends up with the same number of rows). If you add another sub-item to one of the items, the problem is fixed. If you add a sub-item to both (so they both have two) then the problem returns.
(Are you thinking I'm crazy yet? I thought I was. But wait there's more...)
The nested table must have the CSS property border-collapse: collapse. Without this property, or with a different value for this property, the issue doesn't occur. Note: the table can inherit this property from the parent table, or from a table CSS rule, or from a class (as the demo shows) and the issue still occurs. Removing it "live" using IE's F12 dev console and the issue gets fixed.
The TDs of the nested table - i.e. the "hellos" - must have a CSS border. They can inherit this, or obtain it from the class (as per the demo).
Basically, I have to tell the client they can have a collapsed-bordered table to show sub-items in the table of fields (there are usually many more than in the demo) or have a drop down list, but not both. (Or don't use IE, which isn't an option, or change the order of you form, which then would make no sense to the users.)
I tried not using ng-options (and instead ng-repeat-ing an option) but I get the same result (I'm limited to 2 links so here's the plnkr ID: 95XcM9j2eY70jUK10UrH).
I may dump the select entirely.

Difference between KeyboardNavigationMode Contained and Cycle?

Short question - what is the real difference put in easy and understandable words?..
Extracts from MSDN:
Contained - Depending on the direction of the navigation, focus returns to the first or the last item when the end or the beginning of the container is reached, but does not move past the beginning or end of the container.
Cycle - Depending on the direction of the navigation, the focus returns to the first or the last item when the end or the beginning of the container is reached. Focus cannot leave the container using logical navigation.
The difference is in the last part of the description of those modes. But I cannot understand it. Can anyone explain it in a more humane way?
The KeyboardNavigation class defines three attached properties that allow the modification of each of the navigation modes:
KeyboardNavigation.TabNavigation,
KeyboardNavigation.DirectionalNavigation,
KeyboardNavigation.ControlTabNavigation
Each of these properties defines six possible values.These values specifies how the navigation can be done in a list control(eg:ListBox,listview)
for instance;
KeyboardNavigation.DirectionalNavigation="Contained"
is used to indicate that when i press the down or up arrow in the keyboard to navigate between items in a list,the navigation stops at the last item or first item,then we have to use the opposite button to navigate further up or down.
KeyboardNavigation.DirectionalNavigation="Cycle"
is used to indicate that when i press the down or up arrow in the keyboard to navigate between items in a list,the navigation continues from the top or bottom item in a cyclic manner
same is the case with TabNavigation which indicate the navigation mode when we press the tab button in a list

Resources