tinyMCE caret positioning while moving in and out of span - javascript

Intro
I'm using tinyMCE to edit markup style syntax (TeX-like equations). To denote places where processing will be required after the content is submitted from tinyMCE, I am adding span elements to allow custom CSS to highlight the markup and attach id attributes to it. I'm having some difficulty getting sensible caret positioning behaviour when moving between the span and the enclosing paragraph - often the caret will skip a character when moving from the beginning of the span to outside the span.
A concrete example
(I'm running Firefox 12 on a MacBook)
test.html: http://pastebin.com/m8nAmetz
CSS styling for eqn and inline classes: http://pastebin.com/cQVRGVMS
Pressing the right arrow with the caret positioned before the CSS rendered '$' into the span results in the caret moving to after the first m in 'moreinterestingeqnstuff', and the same process repeated after the second f in '...stuff' results in the caret skipping the first space after the span. Clicking to select caret position briefly positions the caret correctly, before it is pushed into one of the above error states.
The questions
Have I done something wrong here? If not, does anyone know if this is a tinyMCE bug or a browser bug and if a workaround exists in either of these cases?
Update: OK, I guess I'll have to enter handling pseudo elements (see below) as a feature request with the tinyMCE folks. However, even without the pseudo-elements, I have an issue with the caret handling. In this fiddle http://fiddle.tinymce.com/EGbaab I have removed the inline class, which removes the before and after styling. If I want to insert a character directly after the span, I can't, as moving the caret to immediately after the last f in '...stuff' immediately places it inside the span. Is there a way to disable this feature in tinyMCE, or alternatively what's the best way to implement this behaviour?

Hmm, you have not done anything wrong here, but you need to know that the movement of the caret does not take care of css pseudo elements like after and before. They are used here. So this is obviuos not a bug.

Related

How to set innerHTML without losing current scroll point?

Edit: Using Coll's innerText method along with Icekid's scroll behavior solved this. Thanks!
I'm using set innerHTML to apply the <mark> tag in a series of divs. For example, user presses a key and the <mark> goes from:
<mark>This is a demonstration.</mark> To show what I mean.
to
<mark>This is a demonstration. To show what I mean.</mark>
This works great except when it comes to scrolling. The text being marked is variable and sometimes requires the div to scroll. I use the following JavaScript to scroll the view:
function prompt_scroll() {
document.getElementById("next").scrollIntoView({ behavior: 'smooth'})}
The issue is each time this happens, the newly set innerHTML begins scrolled to top, then scrolls to the end of the <mark> tag. That sort of jumping up then scrolling is enough to make someone seasick!
The solution I think I need is to set the innerHTML already scrolled to the same point as the JS code I shared above. I just don't know how to accomplish this or if there is a better solution to prevent that scrolling to the top. I'll add that I'm still learning the ropes with JS so I may need a little extra info on the how and why. All guidance is appreciated.
You can add
yourElememt.scrollIntoView({behavior:"smooth", inline:"center",block:"center"})
In place of the "center" you can use
//start, "end" ,or "nearest"
To fix it to the position you want
I think you should use nearest for your case

How to set cursor position in CodeMirror in accordance to cursor position in TinyMCE 5?

I have a form on the webpage, which uses TinyMCE 5 to edit one of the fields. In my configuration, the TinyMCE uses CodeMirror in order to inspect/edit the html-code of the field's content. When the CodeMirror starts, it positions the cursor at the beginning of the code, but I would like to find a way how to set initial cursor position in CodeMirror to the place in html-code, which corresponds to the position of cursor in TinyMCE. In other words, if the cursor is located e.g. inside a table in TinyMCE when I call the CodeMirror (by pressing "code" button on menu panel), I would like the CodeMirror to set its cursor close to or inside the <table> tag in the html-code.
The solution, which comes to my mind, is to get the tag name at the cursor position in TinyMCE, then start CodeMirror, find the line in CodeMirror, which contains that tag, and finally position the cursor to that line. But I don't really understand how to implement this. Should I edit the codemirror/plugin.js or there is another less destructive way?
Any ideas are welcome! Thanks!
After some research I've found the answer to my question. I hope it will be helpful for someone else.
First of all, the functionality described in my question has already been implemented in the CodeMirror. It's controlled by the CodeMirror option saveCursorPosition. If it's set to true, CodeMirror positions cursor to the place in the html-code, which corresponds to the position of the cursor in the TinyMCE editor and vice versa.
But the most funny thing is that all of the above doesn't work :) In order to save the cursor position, the tinymce-codemirror plugin adds the invisible span to the html-code of the TinyMCE content (<span style="display: none;" class="CmCaReT"></span>). Just before the CodeMirror instance is activated, the plugin replaces that span with invisible character (UTF code = 0), otherwise the span tag would be visible in the CodeMirror.
This replacement is performed by the following code (in the source.html file located at the same folder as plugin.js and plugin.min.js): html.replace(/<span\s+style="display: none;"\s+class="CmCaReT"([^>]*)>([^<]*)<\/span>/gm, String.fromCharCode(chr)). The regular expression should find all those span-s, but it doesn't! The reason is that style and class attributes appear to be in opposite order: the class is the first, then follows the style. (I think this is the surprise made by the browser - I use Firefox.)
Now, we have to change the regular expression to /<span\s+(style="display: none;")*\s*(class="CmCaReT")\s+(style="display: none;")*([^>]*)>([^<]*)<\/span>/gm , which catches the span tag regardless of the order of its attributes.
So, now jumping between corresponding positions in TinyMCE and CodeMirror works fine!

Limiting an editable div area by height, simulating onkeyup event in Javascript

I know there are many similar topics but none of them has the solution to my problem so please read my question carefully before sending similar topic links and marking as duplicate question.
I have a content editable DIV object, something similar to TextArea control. My goal is to cancel key press events if content starts scrolling and there must be no flickering.
When i use keyUp event, it's too late to cancel and there is also no methods available to cancel changes. What's done is done at this stage.
When i use keyDown or keyPress events, they are cancelable. But new changes are not yet applied. So, i know which character is pressed etc. but i still don't know how it's going to affect the scrolling size.
Plus, i allow style changes like making the text bold or changing the font size. Since there is;
document.execCommand("undo");
command, i'm able to test these changes and undo if scrolling starts. To test things, i use a cloned div with same content. It works fine. Changes are applied to cloned div (which is visible at the moment for debugging purposes but will be invisible if the method works) and if cloned div has an overflow, changes are canceled.
My problem is at doing the same thing for key presses. It's harder to simulate what happens to editable div content than using document.execCommand for other styling options. What i need is to get the innerHTML result at keyUp stage before keyUp occurs and event is still cancelable like keyDown or keyPress.
To simulate things, i tried getting cursor position and adding pressed characters manually using substring function but content isn't plain text and i had many problems with it. For instance when i press enter, an HTML block <div><br></div> is added for newline character which messed up cursor position. I tried many ways to handle things but it's very open to bugs. So, i decided not to follow this path.
In short my question is;
How can i possibly limit an editable div area by height, not allowing
to overflow or scroll without any flickering, just canceling key press
events? Do i have to simulate something like willKeyUp or is there any
other cross browser way?
Here is jsfiddle link for my sample which works for document.execCommand case (changing font size, weight etc.) but fails at typing letters;
http://jsfiddle.net/7zQD2/
Edit: To clarify my goal at jsfiddle example, after writing 5 lines of text, either when you press enter or type to end of the line, cursor should never reach to the sixth line. Key presses should be canceled and cursor should stay at fifth line with no content changes or flickers.
One solution is to use the cloning setup you already have, but to set the opacity of the first copy to 0 and position it on top of the clone with position: absolute in the css. The first copy won't be visible, but will catch a click directed towards the visible one underneath it. You can change your event to fire on keyup.
Since the transparent div still exists, and still has height, it can measure text height for you without being visible to the user. The visible text then updates to match what is learned with the transparent text, and never reaches the 6th line or flickers.
http://jsfiddle.net/7zQD2/2/

Zero width inline element moves justified text node contents

I have a justified text node into which I want to insert an inline placeholder ( element if you like) whose only content is a "‍" that shouldn't have any width (and chrome inspector says as much too). I have noticed that when I insert this node inline into the text node, the whole line "jiggles" as if recalculating the layout, although this should not affect it.
I have also tested that if the text node I insert it into is left-aligned, this slight movement does not happen. Is this just inherent to the way the browser calculates text placement in a justified text element or could there be any workaround for this?
As I suspected, the issue, rather no issue, is due to the way "justify" works. First to confirm that "justify" text-align is causing this, check the jsffidle : http://jsfiddle.net/e7Ne2/29/
Both divs are same -> except that First div has text-align: justify and the other does not.
You will see that first div shows that behaviour but not second div.
This is because "justify" works this way (from wiki):
In justified text, the spaces between words, and, to a lesser extent, between glyphs or letters (kerning), are stretched or sometimes compressed in order to make the text align with both the left and right margins.
So, when we introduct a &zwb;, the text gets reorganized. This behaviour not consistent because not all characters are modified with &zwb;. So, when &zwb; alters the text, few letters "may be" stretched/compressed leading to the seemingly weird behaviour
The best I can find on it is that support for the zwj is not complete in all browsers. Your code is taking the inserted span tag and removing it with that .text() call, so it's unwrapping the zwj and causing display issues wherever it lands between letters.
I'm not sure what the end application is supposed to be, but using the jQuery .html() function would probably be better (you'll just need to check and make sure you're not writing inside of a tag), because the .text() function strips tags.
Reference:
http://api.jquery.com/text/

Scroll to a text position in Javascript

I have a real-time HTML editor, with a textarea on the left for code entry, and a 'preview' DIV on the right to contain the preview of the code entered. At the moment, when editing the code in the left pane, the preview just sits where it is, so often the part of the code you're editing is not in the visible area of the preview (especially when images are involved).
My question is how do I make the preview scroll to show the part of the code that's currently being edited?
Here is the page I have so far:
http://www.caerphoto.com/rtedit.html
You'll notice in the source I have a (currently unused) matchPreview() function that tries to match the scroll position of the preview based on the scroll position of the textarea, but obviously if images or large text are involved the two panes no longer match.
Instead of a div from the clone target try using a tag.
let me decompose your task into 2 subtasks:
get informed when the dom changes
you could listen on changes of the dom like onsubtreemodified.
see
en.wikipedia.org/wiki/DOM_events
scroll the element into view
the answer to this is the scrollintoview method:
see
www.quirksmode.org/dom/tests/scrollintoview.html
however, this might not help you too much, since you are updating the whole html document on every change of the textarea. since you cannot get the position of the cursor inside the textarea, this might be not that easy.
sorry mate, at the end I have no solution, but maybe my rumination helps in some way nevertheless.
good luck!
When I tried this in Firefox. no line-breaks were seen in the preview; is this correct? I may be able to help (done something similsr recently), but not if the line breaks are removed...

Categories

Resources