Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(re)Init Error #430

Closed
shaan1974 opened this issue Jul 6, 2020 · 17 comments
Closed

(re)Init Error #430

shaan1974 opened this issue Jul 6, 2020 · 17 comments
Labels
Milestone

Comments

@shaan1974
Copy link

shaan1974 commented Jul 6, 2020

Hello,
Here my problem :)

I use sunEditor for one of my dynamic component related to my form builder in vuejs.

The first time when it init it's ok. But when the instance is destroy and when i try to reinitialise it i got :

TypeError: m.fileTags[t].toLowerCase is not a function
at Object._init (suneditor.min.js:9865)
at Object._editorInit (suneditor.min.js:10140)
at A (suneditor.min.js:11737)
at Object.create (suneditor.min.js:11790)
at Object. (suneditor.min.js:11747)
at VueComponent.mounted (js.js:128)
at invokeWithErrorHandling (vue.js:1863)
at callHook (vue.js:4220)
at Object.insert (vue.js:3146)
at invokeInsertHook (vue.js:6341)

But only this error in fact count => suneditor.min.js:9865

It's related to code :

this._fileManager.pluginMap[m.fileTags[t].toLowerCase()] = e

if i put this line into a try catch it's ok.

Do you have any ideas why this line break the init the second time ?

Best regards
( By the way your editor rock!)

@JiHong88
Copy link
Owner

JiHong88 commented Jul 7, 2020

Hi,
Do you use custom plugins when re-creating?

@shaan1974
Copy link
Author

Hello, yes i have a custom plugin, it add a button with functionnality of cleaning the content of the editor.

@JiHong88
Copy link
Owner

JiHong88 commented Jul 7, 2020

Please test without custom plugin.
Are you using "fileTags" property in your custom plugin?

@shaan1974
Copy link
Author

My Plugin:

Where id don't use fileTags property :)

var plugin_command = {
                name: 'customCommand',
                display: 'command',

                add: function(core, targetElement)
                {
                    var context = core.context;
                    var rangeTag = core.util.createElement('div');

                    context.customCommand = {
                        targetButton: targetElement,
                        tag: rangeTag
                    };
                },

                active: function(element)
                {
                    return false;
                },

                action: function()
                {
                    this.setContents('');
                    this.context.element.originElement.trigger("validate");
                }
            };

and the plugin in config :

"plugins": [plugin_command],
                "buttonList": [
                    [
                        {
                            name: 'customCommand',
                            dataCommand: 'customCommand',
                            buttonClass: '',
                            title: '' + this.getLabel(this.$root, "RTE_CLEAR_BTN") + '',
                            dataDisplay: 'command',
                            innerHTML: '<i class="xse-icon-add icon-empty"></i>'
                        }

@JiHong88
Copy link
Owner

JiHong88 commented Jul 8, 2020

This issue is not reproduce.
Please show the options and codes currently in use.

@shaan1974
Copy link
Author

Here the code :)

            var plugin_command = {
                name: 'customCommand',
                display: 'command',

                add: function(core, targetElement)
                {
                    var context = core.context;
                    var rangeTag = core.util.createElement('div');

                    context.customCommand = {
                        targetButton: targetElement,
                        tag: rangeTag
                    };
                },

                active: function(element)
                {
                    return false;
                },

                action: function()
                {
                    this.setContents('');
                    this.context.element.originElement.trigger("validate");
                }
            };

this.editor = SUNEDITOR.create((_Qs("[name='" + this.name + "_" + this.fieldUid + "']")),
            {
                "toolbarWidth": "100%",
                "resizingBar": false,
                "showPathLabel": false,
                "height": "auto",
                "minHeight": "150px",
                "lang": SUNEDITOR_LANG['' + (this.$root.config.lg.short).toLocaleLowerCase() + ''],
                "plugins": [plugin_command ],
                "buttonList": [
                    [
                        {
                            name: 'customCommand',
                            dataCommand: 'customCommand',
                            buttonClass: '',
                            title: '' + this.getLabel(this.$root, "RTE_CLEAR_BTN") + '',
                            dataDisplay: 'command',
                            innerHTML: '<i class="xse-icon-add icon-empty"></i>'
                        }
                    ],
                    ['undo', 'redo'],
                    ['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript'],
                    ['fontColor', 'hiliteColor'],
                    ['removeFormat'],
                    ['outdent', 'indent'],
                    ['align', 'horizontalRule', 'list'],
                    ['table', 'link'],
                    ['fullScreen', 'showBlocks']
                ]
            });

I hope it could help you.

Best regards
S.

@JiHong88
Copy link
Owner

JiHong88 commented Jul 8, 2020

Are there any other actions related to the editor?

@shaan1974
Copy link
Author

Yes, in fact as the sunEditor is created into a Vuejs component, when the component is destroy it also call the "destroy" method of sunEditor.

I have also events attach to the editor => "onload","onchange","onkeyDown","onKeyup" and "onPaste".

the entire code of the component

Rte = Vue.component(
    'Rte',
    {
        template: Rte_template,
        props: ['labels', 'name', 'value', 'fieldMode', 'parent_index', 'key2', 'fieldType', 'validations', 'resetBtn', 'behaviours', 'defaultValue', 'propStatus', 'config', 'styles'],
        mixins: [DynaForm_Mixin, Labels_Mixin, Validation_Mixin, Require_Mixin, Behaviour_Mixin, Prop_Status_Mixin, Guideline_Mixin, Value_Mixin, Event_Mixin, Helper_Mixin, Config_Mixin, Watchers_Mixin],
        data: function()
        {
            return {
                "editor": "",
                "binaryLength": "",
                "updateContent": true,
                "default_config": "rte"
            };
        },
        watch:
        {
            "status_ability": function()
            {
                if (this.status_ability === true)
                {
                    this.editor.enabled();
                    this.editor.toolbar.show();
                }
                else
                {
                    this.editor.disabled();
                    this.editor.toolbar.hide();
                }
            }
        },
        computed:
        {
            customLabels: function(x)
            {
                return [
                    this.getLabel(this.$root, "RTE_LIMIT_REACH")
                ];
            }
        },
        mounted: function()
        {
            //  CUSTOM PLUGIN TO CREATE CLEAR BUTTON
            var that = this;

            //  IF FROM IS ON DISPLAY MODE SO WE DON'T NEED TO INIT PLUGIN
            if (this.isDisplayMode())
            {
                return true;
            }

            var plugin_command = {
                name: 'customCommand',
                display: 'command',

                add: function(core, targetElement)
                {
                    var context = core.context;
                    var rangeTag = core.util.createElement('div');

                    context.customCommand = {
                        targetButton: targetElement,
                        tag: rangeTag
                    };
                },

                active: function(element)
                {
                    return false;
                },

                action: function()
                {
                    this.setContents('');
                    this.context.element.originElement.trigger("validate");
                }
            };
            /* --- */

            //  INIT EDITOR RELATED TO NAME REF OF TEXTAREA
            // this.editor = SUNEDITOR.create((document.querySelector("[name='" + this.name + "_" + this.fieldUid + "']")),
            this.editor = SUNEDITOR.create((_Qs("[name='" + this.name + "_" + this.fieldUid + "']")),
            {
                "toolbarWidth": "100%",
                "resizingBar": false,
                "showPathLabel": false,
                "height": "auto",
                "minHeight": "150px",
                "lang": SUNEDITOR_LANG['' + (this.$root.config.lg.short).toLocaleLowerCase() + ''],
                "plugins": [plugin_command ],
                "buttonList": [
                    [
                        {
                            name: 'customCommand',
                            dataCommand: 'customCommand',
                            buttonClass: '',
                            title: '' + this.getLabel(this.$root, "RTE_CLEAR_BTN") + '',
                            dataDisplay: 'command',
                            innerHTML: '<i class="xse-icon-add icon-empty"></i>'
                        }
                                          ],
                    ['undo', 'redo'],
                    ['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript'],
                    ['fontColor', 'hiliteColor'],
                    ['removeFormat'],
                    ['outdent', 'indent'],
                    ['align', 'horizontalRule', 'list'],
                    ['table', 'link'],
                    ['fullScreen', 'showBlocks']
                ]
            });

            //  CHECK STATUS
            if (this.status_ability === false)
            {
                this.editor.disabled();
                this.editor.toolbar.hide();
            }

            //  EVENTS
            //  ---- ONLOAD
            this.assignEventOnload();
            //  ---- ONCHANGE
            this.assignEventOnChange();
            //  ---- ONKEYDOWN
            this.assignEventOnKeyDown();
            //  ---- ONKEYUP
            this.assignEventOnKeyUp();
            //  ---- ONPASTE
            this.assignEventOnPaste();

            //  INIT COUNTER
            this.calculateCounter();

            //  IF INSIDE REPEATER WE RUN THIS EVENT TO BE ABLE TO REMOVE ALL COMPONENTS DECLARATION TO AVOID MEMORY LEAKS
            /*
            if (typeof this.$parent.formData === "undefined")
            {
                this.$parent.$parent.$on('event_destroyComponents', this.destroy);
            }
            */
        },
        methods:
        {
            "calculateCounter": function()
            {
                this.binaryLength = this.editor.getContents().BLENGTH();
            },
            /*
                EVENTS
            */
            "assignEventOnload": function()
            {
                var that = this;
                var fctOnLoad = function(that, r) {};
                this.editor.onload = fctOnLoad.bind(null, that);
            },
            "assignEventOnChange": function()
            {
                var that = this;

                var fctOnChange = function(that, contents)
                {
                    //  IF WE REACH THE MAXIMUM NOTICE IS DISPLAY
                    if (that.editor.getContents().BLENGTH() > parseInt(that.builded_config.max))
                    {
                        that.editor.noticeOpen('' + that.customLabels[0] + '');
                        that.updateContent = false;
                        that.updateToTextArea("");
                        that.editor.save();
                    }
                    else
                    {
                        that.editor.noticeClose();
                        that.updateContent = true;
                    }

                    if (that.updateContent === true)
                    {
                        that.editor.save();
                        that.updateToTextArea(contents);
                        that.$el.querySelector("textarea").trigger("validate");
                    }
                    that.binaryLength = that.editor.getContents().BLENGTH();
                };

                this.editor.onChange = fctOnChange.bind(null, that);
            },
            "assignEventOnKeyDown": function()
            {
                var that = this;

                var fctKeyDown = function(that, e)
                {
                };
                this.editor.onKeyDown = fctKeyDown.bind(null, that);
            },
            "assignEventOnKeyUp": function()
            {
                var that = this;
                var fctOnKeyUp = function(that)
                {
                    that.binaryLength = that.editor.getContents().BLENGTH();

                    //  IF WE REACH THE MAXIMUM NOTICE IS DISPLAY
                    if (that.editor.getContents().BLENGTH() > parseInt(that.builded_config.max))
                    {
                        that.editor.noticeOpen('' + that.customLabels[0] + '');
                        that.updateContent = false;
                        that.updateToTextArea("");
                    }
                    else
                    {
                        that.editor.noticeClose();
                        that.updateContent = true;
                    }
                };

                this.editor.onKeyUp = fctOnKeyUp.bind(null, that);
            },
            "assignEventOnPaste": function()
            {
                var that = this;
                var fctOnPaste = function(that, clipboard, pastedContent)
                {
                };

                this.editor.onPaste = fctOnPaste.bind(null, that);
            },
            /*
                UPDATE
            */
            "updateToTextArea": function(c)
            {
                if (c === "<p><br></p>")
                {
                    c = "";
                }

                this.setDataValue("" + c + "", true);
            },
            /*
                DESTROY
            */
            "destroy": function()
            {
                this.editor.destroy();
            }
        }
    }
);

@JiHong88
Copy link
Owner

JiHong88 commented Jul 8, 2020

I tested it in my view project, but it doesn't give any errors.
What version are you using?

@shaan1974
Copy link
Author

i use the lastest on jsdeliver
=> https://cdn.jsdelivr.net/npm/suneditor@latest/dist/suneditor.min.js

@JiHong88
Copy link
Owner

JiHong88 commented Jul 10, 2020

Try using the npm. example
import suneditor from 'suneditor'

When is the "destroy" method of the "Ret" component called?

Are you using like this?

<template>
  <Ret>
</template>

@shaan1974
Copy link
Author

After hard debugging i found why sunEditor return me an error but it's really weird.

If i add an array prototype called "_move" like that :

Array.prototype._move = function(from, to)
{
    this.splice(to, 0, this.splice(from, 1)[0]);
};

I got an error when i try to reinit sunEditor

But if i set my prototype like that :

Object.defineProperty(Array.prototype, '_move',
{
    value: function(from, to)
    {
        this.splice(to, 0, this.splice(from, 1)[0]);
    }
});

No errors :)

@JiHong88
Copy link
Owner

Array.prototype._move = ..:
When traversing an array, it is defined as an openable attribute.
"_Move" appears during all array loop.

Object.defineProperty : (enumerable = default value is false):
It is added to the prototype, but is not listed.

@JiHong88
Copy link
Owner

JiHong88 commented Jul 12, 2020

It's my mistake.
I'll modify the array loop for in.

@shaan1974
Copy link
Author

shaan1974 commented Jul 12, 2020

Thanks ;)
By the way, you do a great job with sunEditor.

@JiHong88
Copy link
Owner

The 2.31.1 version has been updated.
If this issue has not been resolved, please reopen this issue.
Thank you ;)

@shaan1974
Copy link
Author

As the Terminator said : "No problemo" :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants