Not a bug Cannot read property 'inEditor' of undefined

truonglv

Well-known member
Affected version
2.2.0 Beta 1
In our add-on it's use this method XF.focusEditor() then got these errors:

Code:
Uncaught TypeError: Cannot read property 'inEditor' of undefined
    at Object.restoreMaintainedSelection (editor.js?_v=a7fbff69:1883)
    at Object.focus (editor.js?_v=a7fbff69:1902)
    at fn.focus (editor.js?_v=a7fbff69:668)
    at fn.scrollToCursor (editor.js?_v=a7fbff69:1354)
    at Object.focusEditor (core.js?_v=a7fbff69:2902)
    at devjs.php?addon_id=Truonglv%2FPostReply&js=Truonglv%2FPostReply%2Fpost_reply.js:93
    at core.js?_v=a7fbff69:2324
    at Object.load (core.js?_v=a7fbff69:4553)
    at Object.setupHtmlInsert (core.js?_v=a7fbff69:2221)
    at devjs.php?addon_id=Truonglv%2FPostReply&js=Truonglv%2FPostReply%2Fpost_reply.js:76
 
First, if you really are running Beta 1, please confirm the issue with the latest version.

Beyond that, we may need a reduced test case and/or more information about the specific situation that has caused this. The only situation I can think of is where the Froala instance hasn't been initialized yet. In most scenarios, this would be a race condition or your code doing something unexpected in editor:start for example. Alternatively, this could be a situation where the editor init has been deferred, though it's not clear if that's relevant (it's only done in a small number of situations).
 
Can you include the code that demonstrates when you call focus exactly? It does appear to be when the HTML is inserted in which case, this is very likely to be the race condition I referred to: Froala's initialization hasn't finished yet. This is done asynchronously so you may need a setTimeout call before you trigger focus, for example.
 
Template HTML:

Code:
<xf:form action="{$formUrl}" ajax="true"
         class="block js-quickReply tpr-post-reply--form"
         data-xf-init="{{ $attachmentData ? 'attachment-manager ' : '' }}{{ $xf.visitor.isShownCaptcha() ? 'guest-captcha ' : '' }}quick-reply"
         data-message-container="< .message-main | .js-tprReplyMessageContainer">
    <xf:js src="xf/message.js" min="1" />

    <div class="block-container">
        <div class="block-body">
            <xf:macro template="quick_reply_macros" name="body"
                      arg-message="{$message}"
                      arg-attachmentData="{$attachmentData}"
                      arg-forceHash=""
                      arg-messageSelector=".js-post"
                      arg-simple="{{ true }}"
                      arg-lastDate="{$lastDate}"
                      arg-lastKnownDate="{$lastDate}"
                      arg-showPreviewButton="{{ false }}" />
        </div>
    </div>
    <xf:hiddenval name="tpr_post_id" value="{$parentId}" />
</xf:form>

JS:
Code:
XF.ajax('POST', this.options.formUrl, { last_post: lastShownPost }, function (data) {
                _this.formHtml = data.html;
                if (!_this.$container && data.hasOwnProperty('formHolder')) {
                    _this.$container = $(data.formHolder);
                }
                _this.$container.empty().show();

                XF.setupHtmlInsert(data.html, function ($html) {
                    var $closeBtn = _this.$close.clone();
                    $closeBtn.on('click', function () {
                        _this.$container.hide();
                    });

                    $closeBtn.appendTo($html.find('.formButtonGroup-primary'));
                    $html.appendTo(_this.$container);

                    if (data.hasOwnProperty('mentionUser') && data.mentionUser) {
                        XF.replaceEditorContent(
                            _this.$container,
                            data.mentionUser + '<span> </span>',
                            data.mentionUser + ' '
                        );
                    }

                    XF.focusEditor(_this.$container);
                });
            }).always(function () {
                _this.loading = false;
            });
 
I have actually made a tweak that would suppress this error (mostly for the deferred init case), but based on your code, I'd say this is probably more of a bug in the calling code.

First, you likely want to call the onComplete closure that's passed into your setupHtmlInsert callback manually. (It's passed as the 3rd argument, you can see a few examples of this in XF.) You'd want to do it after the appendTo call. This will trigger the element activations that you're relying on a little earlier (it does end up implicitly happening because of some lower level code), but you'd generally want to trigger it if you are triggering actions against the content you just inserted.

Second, you probably do need to consider a setTimeout call or similar approach because you take action on the editor as the initialization may be asynchronous. (Doing this sort of ends up meaning that the onComplete stuff I talked about likely ends up being moot.)

Overall, there isn't really anything to change on our end. It's possible this may be specific to 2.2, but that would be related to the Froala update and it may have made internal initialization changes (and your code may have been relying on the previous behavior).
 
Top Bottom