View file MMO-Hide-2.3.4/upload/js/MMO/Hide/editor.js

File size: 10.36Kb
window.MMO = window.MMO || {};
window.MMO.Hide = window.MMO.Hide || {};

((window, document) =>
{
    'use strict';

    MMO.Hide.editorConfig = {
        dialog: [],
        disabledDialog: []
    };

    MMO.Hide.EditorButtons = {
        init()
        {
            const buttonConfig = document.querySelector('.js-mhHideEditorConfig');
            if (buttonConfig)
            {
                MMO.Hide.EditorButtons.setupButtonConfig(buttonConfig);
            }
            MMO.Hide.EditorButtons.registerCommands();
        },

        setupButtonConfig(buttonConfig)
        {
            try
            {
                const buttons = JSON.parse(buttonConfig.innerHTML);

                MMO.Hide.editorConfig.dialog = buttons.buttons || [];
                MMO.Hide.editorConfig.disabledDialog = buttons.disabledDialog || [];
            }
            catch (e)
            {
                console.error('Editor buttons data not valid: ', e);
            }
        },

        registerCommands()
        {
            if (!Array.isArray(MMO.Hide.editorConfig.dialog))
            {
                return;
            }

            MMO.Hide.editorConfig.dialog.forEach(element =>
            {
                MMO.Hide[element] = MMO.Hide[element] || {};
                if (!MMO.Hide[element].editorButton)
                {
                    MMO.Hide[element].editorButton = {
                        init()
                        {
                            MMO.Hide[element].EditorDialog = XF.extend(XF.EditorDialog, {
                                cache: false,
                                container: null,

                                _beforeShow(overlay)
                                {
                                    this.ed.$el.blur();
                                },

                                _init(overlay)
                                {
                                    XF.on(overlay.overlay.querySelector('form'), 'submit', this.submit.bind(this));
                                },

                                _afterShow(overlay)
                                {
                                    var container = overlay.container,
                                        bbCodeValue = container.querySelector('#editor_hide_text');

                                    if (!bbCodeValue)
                                    {
                                        return;
                                    }

                                    bbCodeValue.value = MMO.Hide.EditorButtons.getSelectionContainer(this.ed);
                                    bbCodeValue.focus();
                                },

                                submit(e)
                                {
                                    e.preventDefault();

                                    const ed = this.ed;
                                    const type = document.querySelector('#editor_hide_count'),
                                        groupHide = document.querySelectorAll('#editor_hide_id_count input:checked'),
                                        description = document.querySelector('#editor_hide_text'),
                                        groupsIds = [];

                                    groupHide.forEach(groupCb => groupsIds.push(groupCb.value));

                                    const groupIdsString = Array.from(groupHide).map(input => input.value).join(',');

                                    ed.selection.restore();
                                    MMO.Hide.EditorButtons.insertHide(
                                        ed,
                                        element.toString().toUpperCase(),
                                        groupHide.length ? groupIdsString : type ? type.value : '',
                                        description.value
                                    );

                                    this.overlay.hide();

                                    description.value = '';
                                    if(type)
                                    {
                                        type.value = '';
                                    }
                                }
                            });
                        },

                        callback()
                        {
                            if (!MMO.Hide.editorConfig.disabledDialog.includes(element))
                            {
                                XF.EditorHelpers.loadDialog(this, element);
                            }
                            else
                            {
                                const editorButtons = MMO.Hide.EditorButtons,
                                    customEditor = JSON.parse(document.querySelector('.js-editorCustom').innerHTML),
                                    optional = !(customEditor.hasOwnProperty(element) && customEditor[element].option === 'yes');
                                editorButtons.insertHide(
                                    this,
                                    element.toString().toUpperCase(),
                                    optional ? 0 : 1,
                                    editorButtons.getSelectionContainer(this)
                                );
                            }
                        }
                    };
                }

                MMO.Hide[element].editorButton.init();
                XF.EditorHelpers.dialogs[element] = new MMO.Hide[element].EditorDialog(element);

                if (FroalaEditor.COMMANDS['xfCustom_' + element])
                {
                    FroalaEditor.COMMANDS['xfCustom_' + element].callback = MMO.Hide[element].editorButton.callback;
                }
            });
        },

        getSelectionContainer(ed)
        {
            var selectedText;

            if (ed.selection.isCollapsed())
            {
                selectedText = '';
            }
            else
            {
                const selected = ed.html.getSelected()
                    .replace(/ /gmi, ' ')
                    .replace(/\u200B/g, '')
                    .replace(/(<\/(p|div|pre|blockquote|h[1-6]|tr|th|ul|ol|li)>)\s*/gi, '$1\n')
                    .replace(/<(li|p)><br><\/\1>\s*/gi, '\n')
                    .replace(/<br>\s*/gi, '\n')

                const range = document.createRange();
                const fragment = range.createContextualFragment(selected);

                selectedText = fragment.textContent.trim();
            }

            // weird FF behavior where inserting code wouldn't replace the current selection without this
            ed.selection.save();

            return selectedText;
        },

        insertHide(ed, tag, option, text)
        {
            var output;

            text = text.replace(/&/g, '&amp;').replace(/</g, '&lt;')
                .replace(/>/g, '&gt;').replace(/"/g, '&quot;')
                .replace(/\t/g, '    ')
                .replace(/\n /g, '\n&nbsp;')
                .replace(/ {2}/g, '&nbsp; ')
                .replace(/ {2}/g, ' &nbsp;') // need to do this twice to catch a situation where there are an odd number of spaces
                .replace(/\n/g, '</p><p>');

            output = '[' + tag + (option ? '=' + option : '')  + ']' + text + '[/' + tag + ']';
            if (output.match(/<\/p>/i))
            {
                output = '<p>' + output + '</p>';
                output = output.replace(/<p><\/p>/g, '<p><br></p>');
            }

            ed.html.insert(output);
            XF.EditorHelpers.normalizeAfterInsert(ed)
        }
    };

    MMO.Hide.Reaction = XF.extend(XF.Reaction, {
        __backup: {
            'actionComplete': '__mhHide_actionComplete'
        },

        actionComplete(data)
        {
            this.__mhHide_actionComplete(data);
            if (this.options.reactionList === '< .js-post | .js-reactionsList')
            {
                if (this.target.closest('.message').querySelector('.message-body'))
                {
                    setTimeout(() => this.reloadPost(), 100);
                }
            }
        },

        reloadPost()
        {
            XF.ajax(
                'get',
                this.target.getAttribute('href').replace('react', 'show'),
                {},
                this.postUpdate.bind(this),
                {
                    skipDefaultSuccessError: true
                }
            );
        },

        postUpdate(data)
        {
            if (data.errors || data.exception)
            {
                return;
            }

            XF.setupHtmlInsert(data.html, (html, container) =>
            {
                const message = html.querySelector('.message-body'),
                    replace = this.target.closest('.message-cell--main').querySelector('.message-body');

                replace.outerHTML = message.outerHTML;
                XF.activate(message);
                XF.layoutChange();
            });
        }
    });

    if(XF.SelectToQuote)
    {
        MMO.Hide.SelectToQuote = XF.extend(XF.SelectToQuote, {
            __backup: {
                'getValidSelectionContainer': '__mhHide_getValidSelectionContainer'
            },

            getValidSelectionContainer(selection)
            {
                if (selection.isCollapsed || !selection.rangeCount)
                {
                    return null;
                }

                const range = selection.getRangeAt(0);

                const startContainer = range.startContainer.parentElement;
                const endContainer = range.endContainer.parentElement;
                if (
                    startContainer.closest('.bbCodeBlock--hide, .js-noSelectToQuote') ||
                    endContainer.closest('.bbCodeBlock--hide, .js-noSelectToQuote')
                )
                {
                    return null;
                }

                return this.__mhHide_getValidSelectionContainer(selection);
            }
        });

        XF.Element.register('select-to-quote', 'MMO.Hide.SelectToQuote');
    }

    XF.on(document, 'editor:first-start', MMO.Hide.EditorButtons.init);
    XF.Element.register('reaction', 'MMO.Hide.Reaction');
})(window, document);