Issues (109)

1
/**
2
 * Hide Prosemirror and show the default editor
3
 *
4
 * @param {string} text the wiki syntax to be shown in the textarea
5
 */
6
function showDefaultEditor(text) {
7
    window.Prosemirror.destroyProsemirror();
8
    window.proseMirrorIsActive = false;
9
    dw_locktimer.init(dw_locktimer.timeout/1000, dw_locktimer.draft);
10
    jQuery('#wiki__text').val(text).show();
11
    jQuery('#size__ctl').show();
12
    jQuery('.editBox > .toolbar').show();
13
}
14
15
/**
16
 * Hide the default editor and start a new Prosemirror Editor
17
 *
18
 * @param {string} json the prosemirror document json
19
 */
20
function showProsemirror(json) {
21
    const $textArea = jQuery('#wiki__text');
22
    const $prosemirrorJsonInput = jQuery('#dw__editform').find('[name=prosemirror_json]').val(json);
23
    try {
24
        window.Prosemirror.enableProsemirror();
25
        stickyMenubar();
26
        disableNativeFirefoxTableControls();
27
    } catch (e) {
28
        console.error(e);
29
        let message = 'There was an error in the WYSIWYG editor. You will be redirected to the syntax editor in 5 seconds.';
30
        if (window.SentryPlugin) {
31
            SentryPlugin.logSentryException(e, {
32
                tags: {
33
                    plugin: 'prosemirror',
34
                    'id': JSINFO.id,
35
                },
36
                extra: {
37
                    'content': $textArea.val(),
38
                    'json': $prosemirrorJsonInput.val(),
39
                }
40
            });
41
            message += ' -- The error has been logged to Sentry.';
42
        }
43
        showErrorMessage(message);
44
        setTimeout(function() {
45
            jQuery('.plugin_prosemirror_useWYSIWYG').click();
46
        }, 5000);
47
    }
48
    window.proseMirrorIsActive = true;
49
    $textArea.hide();
50
    jQuery('#size__ctl').hide();
51
    jQuery('.editBox > .toolbar').hide();
52
    jQuery('div.ProseMirror').focus();
53
54
    if (dw_locktimer.addField) {
55
        // todo remove this guard after the next stable DokuWiki release after Greebo
56
        dw_locktimer.init(dw_locktimer.timeout/1000, dw_locktimer.draft, 'prosemirror__editor');
57
        dw_locktimer.addField('input[name=prosemirror_json]');
58
    } else {
59
        console.warn('Draft saving in WYSIWYG is not available. Please upgrade your wiki to the current development snapshot.')
60
    }
61
}
62
63
/**
64
 * Disables Firefox's controls for editable tables, they are incompatible with prosemirror
65
 *
66
 * See https://github.com/ProseMirror/prosemirror/issues/432 and https://github.com/ProseMirror/prosemirror-tables/issues/22
67
 */
68
function disableNativeFirefoxTableControls() {
69
    document.execCommand("enableObjectResizing", false, "false");
70
    document.execCommand("enableInlineTableEditing", false, "false");
71
}
72
73
/**
74
 * Initialize the prosemirror framework
75
 *
76
 * (This shouldn't do much until we actually use the editor, but we maybe shouldn't do this twice)
77
 */
78
function initializeProsemirror() {
79
    try {
80
        /* DOKUWIKI:include lib/bundle.js */
81
    } catch (e) {
82
        const $textArea = jQuery('#wiki__text');
83
        console.error(e);
84
        let message = 'There was an error initializing the WYSIWYG editor.';
85
        if (window.SentryPlugin) {
86
            SentryPlugin.logSentryException(e, {
87
                tags: {
88
                    plugin: 'prosemirror',
89
                    'id': JSINFO.id,
90
                },
91
                extra: {
92
                    'content': $textArea.val(),
93
                }
94
            });
95
            message += ' The error has been logged to sentry.';
96
        }
97
98
        showErrorMessage(message);
99
100
        DokuCookie.setValue('plugin_prosemirror_useWYSIWYG', '');
101
    }
102
}
103
104
/**
105
 * Add the error message above the editor
106
 *
107
 * @param {string} errorMsg
108
 */
109
function showErrorMessage(errorMsg) {
110
    jQuery('.editBox').before(
111
        jQuery('<div class="error"></div>').text(errorMsg)
112
    );
113
}
114
115
/**
116
 * Switch between WYSIWYG and Syntax editor
117
 */
118
function toggleEditor() {
119
    const $textArea = jQuery('#wiki__text');
120
    const $jsonField = jQuery('#dw__editform').find('[name=prosemirror_json]');
121
    jQuery.post(DOKU_BASE + 'lib/exe/ajax.php', {
122
        call: 'plugin_prosemirror_switch_editors',
123
        data: window.proseMirrorIsActive ? $jsonField.val() : $textArea.val(),
124
        getJSON: window.proseMirrorIsActive ? '0' : '1',
125
        id: JSINFO.id
126
    }).done(function handleSwitchEditorResponse(data) {
127
        if (window.proseMirrorIsActive) {
128
            showDefaultEditor(data.text);
129
        } else {
130
            showProsemirror(data.json);
131
        }
132
    }).fail(function (jqXHR, textStatus, errorThrown) {
133
        console.error(jqXHR, textStatus, errorThrown); // FIXME: proper error handling
134
        if (jqXHR.responseJSON && jqXHR.responseJSON.error) {
135
            showErrorMessage(jqXHR.responseJSON.error);
136
        } else {
137
            let message = 'The request failed with an unexpected error.';
138
            if (window.SentryPlugin) {
139
                SentryPlugin.logSentryException(new Error(textStatus), {
140
                    tags: {
141
                        plugin: 'prosemirror',
142
                        'id': JSINFO.id,
143
                        status: jqXHR.status
144
                    },
145
                    extra: {
146
                        'content': $textArea.val(),
147
                        'responseText': jqXHR.responseText,
148
                    }
149
                });
150
                message += ' -- The error has been logged to Sentry.';
151
            }
152
            showErrorMessage(message);
153
        }
154
    });
155
156
    const $current = DokuCookie.getValue('plugin_prosemirror_useWYSIWYG');
157
    DokuCookie.setValue('plugin_prosemirror_useWYSIWYG', $current ? '' : '1');
158
}
159
160
/**
161
 * If the cookie is set, then show the WYSIWYG editor and add the switch-editor-event to the button
162
 */
163
function handleEditSession() {
164
    const $jsonField = jQuery('#dw__editform').find('[name=prosemirror_json]');
165
    if (DokuCookie.getValue('plugin_prosemirror_useWYSIWYG')) {
166
        showProsemirror($jsonField.val());
167
    }
168
    const $toggleEditorButton = jQuery('.plugin_prosemirror_useWYSIWYG');
169
    $toggleEditorButton.on('click', toggleEditor);
170
}
171
172
/**
173
 * when the editor switch button moves out of the view-port, the menubar gets a class
174
 * @see https://codepen.io/hey-nick/pen/mLpmMV
175
 * @see https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
176
 */
177
178
function stickyMenubar() {
179
    const editorswitch = document.querySelector('button[name=prosemirror]');
180
    const menubar = document.querySelector('#prosemirror__editor div.menubar');
181
182
    const observer = new IntersectionObserver(
0 ignored issues
show
The variable IntersectionObserver seems to be never declared. If this is a global, consider adding a /** global: IntersectionObserver */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
183
        ([e]) => {
184
            return menubar.classList.toggle('prosemirror-menubar-fixed', e.intersectionRatio !== 1);
185
        },
186
        {
187
            root: null,
188
            threshold: [0, 1]
189
        }
190
    );
191
    if (editorswitch && menubar) {
192
        observer.observe(editorswitch);
193
    }
194
}
195
196
197
jQuery(function () {
198
    initializeProsemirror();
199
    window.proseMirrorIsActive = false;
200
201
    if (jQuery('#dw__editform').find('[name=prosemirror_json]').length) {
202
        handleEditSession();
203
    }
204
205
    jQuery(window).on('fastwiki:afterSwitch', function(evt, viewMode, isSectionEdit, prevViewMode) {
206
        if (viewMode === 'edit' || isSectionEdit) {
207
            handleEditSession();
208
        }
209
    });
210
});
211