#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 11 years ago by
Keywords: | editor destroyed element undefined hasAttribute removed |
---|---|
Status: | new → pending |
Version: | 4.3.2 |
comment:2 Changed 11 years ago by
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 11 years ago by
Resolution: | → duplicate |
---|---|
Status: | pending → closed |
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 11 years ago by
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 11 years ago by
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 11 years ago by
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 ?
comment:7 Changed 11 years ago by
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 11 years ago by
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 11 years ago by
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 11 years ago by
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;
?
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.