django-cms / djangocms-text-ckeditor

Text Plugin for django CMS using CKEditor 4
https://www.django-cms.org/en/repositories-plugins/
BSD 3-Clause "New" or "Revised" License
164 stars 186 forks source link

caught TypeError: Cannot read properties of null (reading 'textContent') for HTMLField in Admin #644

Closed LukaRiba closed 5 months ago

LukaRiba commented 1 year ago

https://github.com/django-cms/djangocms-text-ckeditor/blob/ada4cffb2fc8c081a4440d7e016682357d34722a/djangocms_text_ckeditor/static/djangocms_text_ckeditor/js/cms.ckeditor.js#L400

fsbraun commented 1 year ago

@LukaRiba Thanks for bringing this to attention. Can you provide some details to make this reproducible?

LukaRiba commented 1 year ago

@fsbraun No problem. This happens in admin's change form, when HTMLField is used in the model. There were no issues in v5.0.1, before changes were introduced in the file. Because of the error, HTMLField is rendered like normal TextField in admin, without rich text options. This is my config regarding ckeditor:

# djangocms-ckeditor
# ------------------------------------------------------------------------------
TEXT_INLINE_EDITING = True
CKEDITOR_SETTINGS = {
    'contentsCss': [
        '/static/djangocms_text_ckeditor/ckeditor/contents.css', # default
        '/static/css/font-icons.min.css', # for icon fonts
        '/static/djangocms_text_ckeditor/ckeditor/contents_custom.css'
    ],
    'customConfig': '/static/djangocms_text_ckeditor/ckeditor/config.js'
}

I tested version 5.0.1, it works, but doesn't with v.5.1.0, so that's when error was introduced.

fsbraun commented 1 year ago

That's very helpful. Can you check what HTML is rendered in the form? I am looking for an element, the ID of which starts with id="ck-cfg-..."?

LukaRiba commented 1 year ago

id="ck-cfg-..." scripts are rendered only in frontend, when inline editing is one (.../?inline_editing=1). But in admin, no such script is rendered for the given model's HTMLField

ivarsg commented 1 year ago

We are getting the same error in the same line of the source code. The problem here (at lease in our case) is that we have very large values of primary keys (values that exceed JavaScript Number.MAX_SAFE_INTEGER value) and when plugin prints the config values, it prints value of PK as integer literal, but that in turn is later misinterpreted because of exceeding max value.

Our solution is that we override djangocms_text_ckeditor/templates/cms/plugins/widgets/ckeditor.html template and use the following modification to line No 7 - we changed it so, that value is always in single quotes:

- {{ plugin_pk|default:"''"|unlocalize }}
+ '{{ plugin_pk|default:""|unlocalize }}'

This will cause to treat PK value as string rather than integer (as it is in other places, for example here where reference value based on PK value is built).

So, at the end, our template is as follows:

{% load i18n l10n static cms_static sekizai_tags %}{{ ckeditor_settings|json_script:ckeditor_settings_id }}
<script>
    (function () {
        window._cmsCKEditors = window._cmsCKEditors || [];
        window._cmsCKEditors.push([
            '{{ ckeditor_selector }}',
            '{{ plugin_pk|default:""|unlocalize }}'
        ]);
    })();
</script>
stale[bot] commented 10 months ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 6 months ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 5 months ago

This will now be closed due to inactivity, but feel free to reopen it.

Tom-revere commented 2 weeks ago

Just bringing this up again. I have the same issue as OP using the latest version of the package (5.1.5). For me the issue is because I am also using django-modeltranslation to translate this particular field. If I don't translate the field it loads fine, with this code being generated:

<textarea name="content" cols="40" rows="10" class="CMS_CKEditor mt mt-field-content mt-default" data-ckeditor-basepath="/static/djangocms_text_ckeditor/ckeditor/" required id="id_content"></textarea>
<script id="ck-cfg-id_content" type="application/json">...</script>
<script>
    (function () {
        window._cmsCKEditors = window._cmsCKEditors || [];
        window._cmsCKEditors.push([
            'id_content',
            ''
        ]);
    })();
</script>

However with the field being translated, both EN and ES (the only two languages I have enabled) fail to load the CKEditor. This is what gets generated for this:

// EN
<textarea name="content_en" cols="40" rows="10" class="CMS_CKEditor mt mt-field-content-en mt-default" data-ckeditor-basepath="/static/djangocms_text_ckeditor/ckeditor/" required id="id_content_en"></textarea>
<script id="ck-cfg-id_content_en" type="application/json">...</script>
<script>
    (function () {
        window._cmsCKEditors = window._cmsCKEditors || [];
        window._cmsCKEditors.push([
            'id_content_en',
            ''
        ]);
    })();
</script>

// ES
<textarea name="content_es" cols="40" rows="10" class="CMS_CKEditor mt mt-field-content-es" data-ckeditor-basepath="/static/djangocms_text_ckeditor/ckeditor/" id="id_content_es"></textarea>
<script id="ck-cfg-id_content_es" type="application/json">...</script>
<script>
    (function () {
        window._cmsCKEditors = window._cmsCKEditors || [];
        window._cmsCKEditors.push([
            'id_content_es',
            ''
        ]);
    })();
</script>

Any help as to why this may be the case would be greatly appreciated. Or if you need any more info I would please let me know.

fsbraun commented 2 weeks ago

@Tom-revere For which id (in the script tag) do you get the error?

Tom-revere commented 2 weeks ago

Hi @fsbraun

Here is chrome debugger showing _en as getting the error. But I would imagine both have this issue.

image

Also, below is the exact console error I get:

image

fsbraun commented 2 weeks ago

According to your comment, the <script id="ck-cfg-id_content_en">...</script> tag is present in the DOM. What does

document.getElementById('ck-cfg-id_content_en')

in your browser console return?

Tom-revere commented 2 weeks ago

Odd, it returns null, and the script is not actually present in Chrome Inspect Element, it's only present when viewed in View Page Source

fsbraun commented 2 weeks ago

Hmm. Some js coffee must have revived it...?

Tom-revere commented 2 weeks ago

No, as you say it's only in the DOM. But once it tries to load it fails and is no longer on the page. (Sorry if I didn't explain that very well)

image

Tom-revere commented 2 weeks ago

Right, I just tried updating the ckeditor.html template with the following

{% load i18n l10n static cms_static sekizai_tags %}{{ ckeditor_settings|json_script:ckeditor_settings_id }}

<script>console.log("TestLog")</script>

This gets logged to the console, as expected, but then is removed from the page. So I presume there must be something in django-modeltranslation that's stripping out the scripts before the djangocms-text-ckeditor JS gets a chance to run ☹️