JavaScript / CodeMirror - refresh textarea - javascript

How do I use the refresh function from CodeMirror 2?
refresh()
If your code does something to change
the size of the editor element (window
resizes are already listened for), or
unhides it, you should probably follow
up by calling this method to ensure
CodeMirror is still looking as
intended.
I want to refresh all textareas after a link is clicked
I tried
$('.CodeMirror').each(function(){
getElementById($(this).attr('id')).refresh();
});
but it doesn't work....

When you instantiate the CodeMirror instance, it is placed as a property on the wrapper div.
$('.CodeMirror').each(function(i, el){
el.CodeMirror.refresh();
});
The above snippet does not recreate the editor, but instead uses the existing one.

The refresh method (just like all other CodeMirror methods) does not live on the DOM node, but on the instance object that's returned when you create the editor (by calling CodeMirror or CodeMirror.fromTextArea). So you'll have to store those somewhere for this to work.

Related

Keep selection/cursor when clicking outside of Jodit editor

Is there any way to keep the current selection inside a Jodit-editor, when clicking outside of it? E.g. I'd like to have a button completely outside the editor (e.g. in a sidebar of the application) that can insert some elements in the editor window at the current position.
You can store the selection by using editor.selection.save() and it will be temporarily written in the markup. This can be restored using editor.selection.restore(). This mechanism would actually work for my use-case, but unfortunately, the 'helper-markup' is also removed/reset in the moment of the editor losing focus.
Also, I didn't find something like a 'selection'-event, that I could use to 'remember' the selection in my own state. Plus the selection. The set method from the selection doesn't seem to work, but I haven't dug into that yet.
I had the same problems and I have solved that a small trick.
As you know you can catch selection in the "onBlur" event and in there I added a special string for the check after losing focus.
for example "{}".
and then string replace with my want.

Can't get instance of dynamically created ScEditor jQuery plugin

I'm using ScEditor and in normal situations I can get the instance like this, where sceditor is the class name of the textarea element to attach it to:
var instance = $('.sceditor').first().sceditor('instance');
However, I have a situation where I need to create an instance of the editor dynamically.
Creating it dynamically works fine, however attempting to get the instance doesn't work.
The code executes after a click event and on the first click it appears to create the instance fine but I cannot get the instance into a variable and work with it; however if I click the link again, I can now work with the instance, presumably because it now exists before I executed the code.
Is there a way I can get the instance in the same call that the instance is created?

How to remove CKeditor instances after the editor has been removed from the DOM

There have been a few related questions on SO about how to remove CKeditor instances, most using .destroy(). This is fine when the editor is still in the dom, however. I have a situation where a CMS is adding a text area, which I am converting to a CKeditor. the cms moves elements from the dom (on an unrelated event).
I can bind an event to the complete emit of that unrelated event, so that the CKeditor can be re-initialized. All that works fine but when I come to remove those left over instances I get errors, this is how I tried:
for (var name in CKEDITOR.instances) {
CKEDITOR.instances[name].destroy(true);
}
but it generates a error:
Uncaught TypeError: Cannot read property 'clearCustomData' of null
I have recreated the issue on a jsfiddle You'll see that the code:
creates a ckeditor instance from a textarea
removes the parent dom element
creates new dom elements
tried to remove all current instances
creates a new ckeditor instance
Step 4 generates the error.
n.b. related questions on removing ckeditor instances relate to still existing dom elements where in this situation the dom has been removed. I have no control over the dom element being removed.
Is there a way to bind an event to the ckeditor triggered when it parent dom elements are removed? I'd assume I'd still hit this issue even if that was the case. Any one any idea?
n.b. I am using jQuery in other places in this project, so a solution involving jQuery would be suitable even though I'm not using it in the ckeditor code.
UPDATE:
I did try setting the instances to null, which does work, but doesn't kill the object created on a CKeditor instance. i.e. CKEDITOR.htmlDataProcessor
(using 'Profiles -> Heap snapshot' in Chrome dev tools is a good demo of the issue)
UPDATE:
Thanks #oleq for the information, I looked at the discussion but couldn't so how to add to it so updated here:
Please see the image of mem profiles before and after dom changes.
You'll see the size of the CKEDITOR properties really go up.
I notice that CKEDITOR.instances.editor1.element.$ stores the element the ckeditor has been bound to/fired upon. Would a check for an existing ckeditor instance on that element, which would destroy the existing CKEDITOR.htmlDataProcessor etc objects and recreate before a new instance is added to the text area?
Does that sound like something that would be appropriate or would the fact that this is seen as an edge case mean its too low a priority? I'm happy to put in the work and pull request if deemed a reasonable solution?
The root cause of the issue appears to have been fixed in https://github.com/ckeditor/ckeditor-dev/pull/200
In short - the iFrame element is detached/removed from the DOM before you call destroy which results in the ckEditor getFrame method returning null.
My workaround until upgrading to the latest ckEditor version is to put the destroy within a try/catch.
The algorithm that controls destruction of CKEditor instances wasn't designed to handle edge cases. The error is thrown at that specific point in wysiwygarea plugin because basically editor.window.getFrame() returns null.
It's an edge case, already discussed on CKEditor bug tracker.

How can I bind a javascript dialog using Knockout?

I've got a list of data in an observableArray and I want to show it in a javascript dialog window (I'm using jQuery.blockUI if it matters). Unfortunately the dialog seems to come unbound after the page is loaded. The dialog initializes correctly (the data is displayed), but it isn't updating with changes.
There are no Javascript errors and I've moved the binding to after the dialog is generated and added to the document (no effect). I've also tried calling ko.applyBinding on the main div that makes up the dialog but that, for some reason, causes part of the main page to hide (the DOM is there, but they are hidden).
EDIT: I've created a project on jsfiddle that reproduces the problem. The main culprit seems to be wrapping the content of the dialog in a div. If I show the content directly it seems to work (of course I can't do that, the wrappers provide a common style for our dialogs).
I'm recovering from the flu and could easily be missing something obvious, but I've been trying all day and nothing is coming to me. Any ideas?
The problem is that the dialog does not exist in the DOM (despite your calling $(document).append(). You cannot append a div as a child of the document itself). Instead, append the dialog to the body and hide it.
$dlg = $('<div></div>').hide();
$('body').append($dlg);
Works here: http://jsfiddle.net/yL6ds/4/

jQuery plugin scrollTo works only from console

Im having an issue with scrollTo on newly created divs Im adding to the DOM via append(). For some reason I cant scroll to where I want from within the code, it only works from console command or if I add a button and call the scroll event that way.
Code:
$('#history').scrollTo('max');
Only works from console or attached to a button.
Edit: The history div has overflow:auto, not sure if that's causing it.
Just a guess, but are you calling "scrollTo" immediately after appending your new element to the DOM?
If that is the case, then the DOM layout likely hasn't had a chance to get recalculated. Relative offset values between elements aren't yet updated until after the current script processing finishes.
Two possible workarounds:
1. setTimeout("$('#history').scrollTo('max')", 1); // Call this after you append your element. This will allow the stack to unwind and update the DOM positions
2. $('#history').scrollTo(0, 9999); // Where "9999" is a value far larger than the actual height of the control.
This would indicate that you're trying to attach scrollTo() to elements which aren't actually existing at the time that you're calling the function on them. The fact that it works in the console would suggest this.
If that's the case, one way would be to use e.g. a library like livequery or then simply call the scrollTo() function on these elements once they have been appended.

Categories