Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#11924 closed Bug (duplicate)

Uncaught TypeError: Cannot read property 'hasAttribute' of undefined

Reported by: Catalin Owned by:
Priority: Normal Milestone:
Component: General Version:
Keywords: Cc:

Description

Hi,

I'm working on a project and we are using CKEditor 4.3.2. I have a test where each question is displayed in a new html page. But when i switch from one page to another i get the error "Uncaught TypeError: Cannot read property 'hasAttribute' of undefined".

I did some debug and i saw that this happens because the previous editor instance from the previous page (it has the same editor id) is still listening (although destroyed) to the "customConfigLoaded" event. So i guess it's catching the custom loaded config event in the new page.

And at the line:

a.readOnly = !(!c.readOnly && !(a.elementMode == CKEDITOR.ELEMENT_MODE_INLINE ? a.element.is("textarea") ? a.element.hasAttribute("disabled") : a.element.isReadOnly() : a.elementMode == 
                CKEDITOR.ELEMENT_MODE_REPLACE && a.element.hasAttribute("disabled")));

a.element is null because the editor was destroyed and a.status is "destroyed".

From what i could tell also, this listener is not removed in the removeAllListeners method, i see it's not part of the list of events to be removed.

Is there any way i can solve this without modifying the ckeditor code ? I have tried a lot of things but nothing seems to work.

Thanks, Catallin

Change History (11)

comment:1 Changed 3 years ago by Piotrek Koszuliński

Keywords: editor destroyed element undefined hasAttribute removed
Status: newpending
Version: 4.3.2

The editor#customConfigLoaded event should not be fired twice because, because it's used only twice and both times with editor.fireOnce which removes the listener automatically.

The only possibility for it to fail which I see is that it's fired after editor is destroyed. And here we get to the missing part. You did a great job debugging the issue and describing that, but you didn't mention how you reproduce it :). Please explain this part, because we cannot work on it without being able to reproduce it.

PS. Check it on latest CKEditor. Maybe it has been already fixed.

comment:2 Changed 3 years ago by Catalin

Thanks for your answer. I will try the latest version, in the meantime i will try to better explain myself.

We have a backbone application where we setup views in which we display the editor. A view itself is setup as a RequireJs module, and the ckeditor is loaded inside the view as a RequireJs module each time a view is created (after the model is fetched). Then on view closed event, the editor is destroyed. We do this because we need two types of editor toolbar so each view type sets its own type.

I am able to reproduce the error by switching very fast between two questions. While of course this is not the normal use case, the effect is the same. If you need more details please let me know.

comment:3 Changed 3 years ago by Piotrek Koszuliński

Resolution: duplicate
Status: pendingclosed

So, as I thought, this is a DUP of more general #11502. Basically, when you call destroy() CKEditor does not control whether editor is ready (and it cannot be destroyed when it's not). We are analyzing whether this can be handled on CKEditor side, but even if it can be, then it requires significant changes, because suddenly destroy() becomes an asynchronous method.

The easy workaround is to check editor.status flag and if it's not ready defer destroy() to editor#instanceReady.

comment:4 Changed 3 years ago by Catalin

Ok, but when i get that error, the editor in cause has the status destroyed. So it is actually destroyed, right ? So it's still the same thing ?

comment:5 Changed 3 years ago by Piotrek Koszuliński

As I understand, you get the error while destroying it. But that error does not mean that process of destroying editor is totally stopped. So at the end the status == 'destroyed'. Does it make sense?

comment:6 Changed 3 years ago by Catalin

I think i get it now, so the old editor is still in the destroy process so that is why it's catching the custom config loaded event. If the destroy method would be completely finished, then the editor reference would not be there so it wouldn't catch the mention event. So i need to make sure the editor is finished destroying before proceeding. Is there any way to tell when this happened ? A specific event or someway to pass a handler ?

LE: oh wait, i can listen to the instanceDestroyed event. I think i know how to continue. Thanks for the help. Greatly appreciated :)

Last edited 3 years ago by Catalin (previous) (diff)

comment:7 Changed 3 years ago by Piotrek Koszuliński

I rather think that you destroy editor to quickly. Not that you initialize next one before previous is not destroyed. Note that customConfigLoaded is fired on editor instance, so if you create new editor (even on the same element) the old event won't be fired on the new one.

What's happening IMO, is that you destroy editor, before customConfigLoaded is fired (it requires few ms, because it loads file). So this event is fired after your editor is destroyed on the editor which was just destroyed. That causes an error.

What you need to do in this case is wait with destroying editor until it's ready.

Note, that this is only my assumption based on cases I saw and your description. You need to debug this yourself.

comment:8 Changed 3 years ago by Catalin

You are right, i did some debug and in those cases the status is unloaded. So i added a check for status to be loaded or ready. So i don't need to call destroy on it as it's not event loaded, right ? Is it safe to just leave it continue and it will create a new instance when i call CKEDITOR.replace('editor') in the new view ?

comment:9 Changed 3 years ago by Piotrek Koszuliński

I'm afraid that it depends on a case and I cannot give you a straight answer. It's always good to destroy old editor, because you free memory, but in some cases you may not do that and if you're not reusing the elements used by old editor everything should work.

comment:10 Changed 3 years ago by Catalin

Well, the old editor has just the empty div element that we use to hold the editor. So,is it safe to do:

CKEDITOR.instances.editor.removeAllListeners(); // just in case
delete CKEDITOR.instances.editor;

?

comment:11 Changed 3 years ago by Catalin

It seems to do the job. Thanks for your help Reinmar.

Note: See TracTickets for help on using tickets.
© 2003 – 2017 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy