Proyectos de Subversion Moodle

Rev

Rev 1 | Mostrar el archivo completo | | | Autoría | Ultima modificación | Ver Log |

Rev 1 Rev 1441
Línea 36... Línea 36...
36
    'core_message/message_drawer_routes',
36
    'core_message/message_drawer_routes',
37
    'core_message/message_drawer_events',
37
    'core_message/message_drawer_events',
38
    'core_message/message_drawer_helper',
38
    'core_message/message_drawer_helper',
39
    'core/pending',
39
    'core/pending',
40
    'core/drawer',
40
    'core/drawer',
-
 
41
    'core/toast',
-
 
42
    'core/str',
-
 
43
    'core/config',
-
 
44
    'core/ajax',
-
 
45
    'core/local/aria/focuslock',
-
 
46
    'core/modal_backdrop',
-
 
47
    'core/templates',
-
 
48
    'core/local/aria/selectors',
41
],
49
],
42
function(
50
function(
43
    $,
51
    $,
44
    CustomEvents,
52
    CustomEvents,
45
    PubSub,
53
    PubSub,
Línea 53... Línea 61...
53
    Router,
61
    Router,
54
    Routes,
62
    Routes,
55
    Events,
63
    Events,
56
    Helper,
64
    Helper,
57
    Pending,
65
    Pending,
58
    Drawer
66
    Drawer,
-
 
67
    Toast,
-
 
68
    Str,
-
 
69
    Config,
-
 
70
    Ajax,
-
 
71
    FocusLock,
-
 
72
    ModalBackdrop,
-
 
73
    Templates,
-
 
74
    AriaSelectors,
59
) {
75
) {
Línea 60... Línea 76...
60
 
76
 
61
    var SELECTORS = {
77
    var SELECTORS = {
62
        DRAWER: '[data-region="right-hand-drawer"]',
-
 
63
        JUMPTO: '.popover-region [data-region="jumpto"]',
78
        DRAWER: '[data-region="right-hand-drawer"]',
64
        PANEL_BODY_CONTAINER: '[data-region="panel-body-container"]',
79
        PANEL_BODY_CONTAINER: '[data-region="panel-body-container"]',
65
        PANEL_HEADER_CONTAINER: '[data-region="panel-header-container"]',
80
        PANEL_HEADER_CONTAINER: '[data-region="panel-header-container"]',
66
        VIEW_CONTACT: '[data-region="view-contact"]',
81
        VIEW_CONTACT: '[data-region="view-contact"]',
67
        VIEW_CONTACTS: '[data-region="view-contacts"]',
82
        VIEW_CONTACTS: '[data-region="view-contacts"]',
-
 
83
        VIEW_CONVERSATION: '[data-region="view-conversation"]',
-
 
84
        VIEW_CONVERSATION_WITH_ID: '[data-region="view-conversation"][data-conversation-id]',
68
        VIEW_CONVERSATION: '[data-region="view-conversation"]',
85
        VIEW_CONVERSATION_WITH_USER: '[data-region="view-conversation"][data-other-user-id]',
69
        VIEW_GROUP_INFO: '[data-region="view-group-info"]',
86
        VIEW_GROUP_INFO: '[data-region="view-group-info"]',
70
        VIEW_OVERVIEW: '[data-region="view-overview"]',
87
        VIEW_OVERVIEW: '[data-region="view-overview"]',
71
        VIEW_SEARCH: '[data-region="view-search"]',
88
        VIEW_SEARCH: '[data-region="view-search"]',
72
        VIEW_SETTINGS: '[data-region="view-settings"]',
89
        VIEW_SETTINGS: '[data-region="view-settings"]',
73
        ROUTES: '[data-route]',
90
        ROUTES: '[data-route]',
74
        ROUTES_BACK: '[data-route-back]',
91
        ROUTES_BACK: '[data-route-back]',
75
        HEADER_CONTAINER: '[data-region="header-container"]',
92
        HEADER_CONTAINER: '[data-region="header-container"]',
76
        BODY_CONTAINER: '[data-region="body-container"]',
93
        BODY_CONTAINER: '[data-region="body-container"]',
77
        FOOTER_CONTAINER: '[data-region="footer-container"]',
94
        FOOTER_CONTAINER: '[data-region="footer-container"]',
-
 
95
        CLOSE_BUTTON: '[data-action="closedrawer"]',
-
 
96
        MESSAGE_INDEX: '[data-region="message-index"]',
78
        CLOSE_BUTTON: '[data-action="closedrawer"]'
97
        MESSAGE_TEXT_AREA: '[data-region="send-message-txt"]',
Línea 79... Línea 98...
79
    };
98
    };
80
 
99
 
81
    /**
100
    /**
Línea 127... Línea 146...
127
        routes.forEach(function(route) {
146
        routes.forEach(function(route) {
128
            Router.add(namespace, route[0], getParametersForRoute(namespace, root, route[1]), route[2], route[3]);
147
            Router.add(namespace, route[0], getParametersForRoute(namespace, root, route[1]), route[2], route[3]);
129
        });
148
        });
130
    };
149
    };
Línea -... Línea 150...
-
 
150
 
-
 
151
    let backdropPromise = null;
-
 
152
 
-
 
153
    /**
-
 
154
     * Set the focus on the drawer.
-
 
155
     *
-
 
156
     * This method also creates or destroy any necessary backdrop zone and focus trap.
-
 
157
     *
-
 
158
     * @param {Object} root The message drawer container.
-
 
159
     * @param {Boolean} hasFocus Whether the drawer has focus or not.
-
 
160
     */
-
 
161
    var setFocus = function(root, hasFocus) {
-
 
162
        var drawerRoot = Drawer.getDrawerRoot(root);
-
 
163
        if (!drawerRoot.length) {
-
 
164
            return;
-
 
165
        }
-
 
166
        if (!backdropPromise) {
-
 
167
            backdropPromise = Templates.render('core/modal_backdrop', {})
-
 
168
                .then(html => new ModalBackdrop(html));
-
 
169
        }
-
 
170
        const backdropWithAdjustments = backdropPromise.then(modalBackdrop => {
-
 
171
            const messageDrawerZIndex = window.getComputedStyle(drawerRoot[0]).zIndex;
-
 
172
            if (messageDrawerZIndex) {
-
 
173
                modalBackdrop.setZIndex(messageDrawerZIndex - 1);
-
 
174
            }
-
 
175
            modalBackdrop.getAttachmentPoint().get(0).addEventListener('click', e => {
-
 
176
                PubSub.publish(Events.HIDE, {});
-
 
177
                e.preventDefault();
-
 
178
            });
-
 
179
            return modalBackdrop;
-
 
180
        });
-
 
181
        if (hasFocus) {
-
 
182
            FocusLock.trapFocus(root[0]);
-
 
183
            // eslint-disable-next-line promise/catch-or-return
-
 
184
            backdropWithAdjustments.then(modalBackdrop => {
-
 
185
                if (modalBackdrop) {
-
 
186
                    modalBackdrop.show();
-
 
187
                    const pageWrapper = document.getElementById('page');
-
 
188
                    pageWrapper.style.overflow = 'hidden';
-
 
189
                    // Set the focus on the close button so when we press enter, it closes the drawer as it did before
-
 
190
                    var closeButton = root.find(SELECTORS.CLOSE_BUTTON);
-
 
191
                    if (closeButton.length) {
-
 
192
                        closeButton.focus();
-
 
193
                    }
-
 
194
                }
-
 
195
                return modalBackdrop;
-
 
196
            });
-
 
197
        } else {
-
 
198
            // eslint-disable-next-line promise/catch-or-return
-
 
199
            backdropWithAdjustments.then(modalBackdrop => {
-
 
200
                if (modalBackdrop) {
-
 
201
                    FocusLock.untrapFocus();
-
 
202
                    var button = $(SELECTORS.DRAWER).attr('data-origin');
-
 
203
                    if (button) {
-
 
204
                        $('#' + button).focus();
-
 
205
                    }
-
 
206
                    modalBackdrop.hide();
-
 
207
                    const pageWrapper = document.getElementById('page');
-
 
208
                    pageWrapper.style.overflow = 'visible';
-
 
209
                }
-
 
210
                return modalBackdrop;
-
 
211
            });
-
 
212
        }
131
 
213
    };
132
    /**
214
    /**
133
     * Show the message drawer.
215
     * Show the message drawer.
134
     *
216
     *
135
     * @param {string} namespace The route namespace.
217
     * @param {string} namespace The route namespace.
Línea 141... Línea 223...
141
            root.attr('data-shown', true);
223
            root.attr('data-shown', true);
142
        }
224
        }
Línea 143... Línea 225...
143
 
225
 
144
        var drawerRoot = Drawer.getDrawerRoot(root);
226
        var drawerRoot = Drawer.getDrawerRoot(root);
-
 
227
        if (drawerRoot.length) {
145
        if (drawerRoot.length) {
228
            setFocus(root, true);
146
            Drawer.show(drawerRoot);
229
            Drawer.show(drawerRoot);
147
        }
230
        }
Línea 148... Línea 231...
148
    };
231
    };
Línea 153... Línea 236...
153
     * @param {Object} root The message drawer container.
236
     * @param {Object} root The message drawer container.
154
     */
237
     */
155
    var hide = function(root) {
238
    var hide = function(root) {
156
        var drawerRoot = Drawer.getDrawerRoot(root);
239
        var drawerRoot = Drawer.getDrawerRoot(root);
157
        if (drawerRoot.length) {
240
        if (drawerRoot.length) {
-
 
241
            setFocus(root, false);
158
            Drawer.hide(drawerRoot);
242
            Drawer.hide(drawerRoot);
159
        }
243
        }
160
    };
244
    };
Línea 161... Línea 245...
161
 
245
 
Línea 181... Línea 265...
181
    var setJumpFrom = function(buttonid) {
265
    var setJumpFrom = function(buttonid) {
182
        $(SELECTORS.DRAWER).attr('data-origin', buttonid);
266
        $(SELECTORS.DRAWER).attr('data-origin', buttonid);
183
    };
267
    };
Línea 184... Línea 268...
184
 
268
 
-
 
269
    /**
-
 
270
     * Store an unsent message.
-
 
271
     *
-
 
272
     * Don't store this if the user has already seen the unsent message.
-
 
273
     * This avoids spamming and ensures the user is only reminded once per unsent message.
-
 
274
     * If the unsent message is sent, this attribute is removed and notification is possible again (see sendMessage).
-
 
275
     */
-
 
276
    const storeUnsentMessage = async() => {
-
 
277
        const messageTextArea = document.querySelector(SELECTORS.MESSAGE_TEXT_AREA);
-
 
278
 
-
 
279
        if (messageTextArea.value.trim().length > 0 && !messageTextArea.hasAttribute('data-unsent-message-viewed')) {
-
 
280
 
-
 
281
            let message = messageTextArea.value;
-
 
282
            let conversationid = 0;
-
 
283
            let otheruserid = 0;
-
 
284
 
-
 
285
            // We don't always have a conversation to link the unsent message to, so let's check for that.
-
 
286
            const conversationId = document.querySelector(SELECTORS.VIEW_CONVERSATION_WITH_ID);
-
 
287
            if (conversationId) {
-
 
288
                const conversationWithId = messageTextArea.closest(SELECTORS.VIEW_CONVERSATION_WITH_ID);
-
 
289
                conversationid = conversationWithId.getAttribute('data-conversation-id');
-
 
290
            }
-
 
291
            // Store the 'other' user id if it is there. This can be used to create conversations.
-
 
292
            const conversationUser = document.querySelector(SELECTORS.VIEW_CONVERSATION_WITH_USER);
-
 
293
            if (conversationUser) {
-
 
294
                const conversationWithUser = messageTextArea.closest(SELECTORS.VIEW_CONVERSATION_WITH_USER);
-
 
295
                otheruserid = conversationWithUser.getAttribute('data-other-user-id');
-
 
296
            }
-
 
297
 
-
 
298
            setStoredUnsentMessage(message, conversationid, otheruserid);
-
 
299
        }
-
 
300
    };
-
 
301
 
-
 
302
    /**
-
 
303
     * Get the stored unsent message from the session via web service.
-
 
304
     *
-
 
305
     * @returns {Promise}
-
 
306
     */
-
 
307
    const getStoredUnsentMessage = () => Ajax.call([{
-
 
308
        methodname: 'core_message_get_unsent_message',
-
 
309
        args: {}
-
 
310
    }])[0];
-
 
311
 
-
 
312
    /**
-
 
313
     * Set the unsent message value in the session via web service.
-
 
314
     *
-
 
315
     * SendBeacon is used here because this is called on 'beforeunload'.
-
 
316
     *
-
 
317
     * @param {string} message The message string.
-
 
318
     * @param {number} conversationid The conversation id.
-
 
319
     * @param {number} otheruserid The other user id.
-
 
320
     * @returns {Promise}
-
 
321
     */
-
 
322
    const setStoredUnsentMessage = (message, conversationid, otheruserid) => {
-
 
323
        const method = 'core_message_set_unsent_message';
-
 
324
        const requestUrl = new URL(`${Config.wwwroot}/lib/ajax/service.php`);
-
 
325
        requestUrl.searchParams.set('sesskey', Config.sesskey);
-
 
326
        requestUrl.searchParams.set('info', method);
-
 
327
 
-
 
328
        navigator.sendBeacon(requestUrl, JSON.stringify([{
-
 
329
            index: 0,
-
 
330
            methodname: method,
-
 
331
            args: {
-
 
332
                message: message,
-
 
333
                conversationid: conversationid,
-
 
334
                otheruserid: otheruserid,
-
 
335
            }
-
 
336
        }]));
-
 
337
    };
-
 
338
 
-
 
339
    /**
-
 
340
     * Check for an unsent message.
-
 
341
     *
-
 
342
     * @param {String} uniqueId Unique identifier for the Routes.
-
 
343
     * @param {Object} root The message drawer container.
-
 
344
     */
-
 
345
    const getUnsentMessage = async(uniqueId, root) => {
-
 
346
        let type;
-
 
347
        let messageRoot;
-
 
348
 
-
 
349
        // We need to check if we are on the message/index page.
-
 
350
        // This logic is needed to handle the two message widgets here and ensure we are targetting the right one.
-
 
351
        const messageIndex = document.querySelector(SELECTORS.MESSAGE_INDEX);
-
 
352
        if (messageIndex !== null) {
-
 
353
            type = 'index';
-
 
354
            messageRoot = document.getElementById(`message-index-${uniqueId}`);
-
 
355
            if (!messageRoot) {
-
 
356
                // This is not the correct widget.
-
 
357
                return;
-
 
358
            }
-
 
359
 
-
 
360
        } else {
-
 
361
            type = 'drawer';
-
 
362
            messageRoot = document.getElementById(`message-drawer-${uniqueId}`);
-
 
363
        }
-
 
364
 
-
 
365
        const storedMessage = await getStoredUnsentMessage();
-
 
366
        const messageTextArea = messageRoot.querySelector(SELECTORS.MESSAGE_TEXT_AREA);
-
 
367
        if (storedMessage.message && messageTextArea !== null) {
-
 
368
            showUnsentMessage(messageTextArea, storedMessage, type, uniqueId, root);
-
 
369
        }
-
 
370
    };
-
 
371
 
-
 
372
    /**
-
 
373
     * Show an unsent message.
-
 
374
     *
-
 
375
     * There are two message widgets on the message/index page.
-
 
376
     * Because of that, we need to try and target the correct widget.
-
 
377
     *
-
 
378
     * @param {String} textArea The textarea element.
-
 
379
     * @param {Object} stored The stored message content.
-
 
380
     * @param {String} type Is this from the drawer or index page?
-
 
381
     * @param {String} uniqueId Unique identifier for the Routes.
-
 
382
     * @param {Object} root The message drawer container.
-
 
383
     */
-
 
384
    const showUnsentMessage = (textArea, stored, type, uniqueId, root) => {
-
 
385
        // The user has already been notified.
-
 
386
        if (textArea.hasAttribute('data-unsent-message-viewed')) {
-
 
387
            return;
-
 
388
        }
-
 
389
 
-
 
390
        // Depending on the type, show the conversation with the data we have available.
-
 
391
        // A conversation can be continued if there is a conversationid.
-
 
392
        // If the user was messaging a new non-contact, we won't have a conversationid yet.
-
 
393
        // In that case, we use the otheruserid value to start a conversation with them.
-
 
394
        switch (type) {
-
 
395
            case 'index':
-
 
396
                // Show the conversation in the main panel on the message/index page.
-
 
397
                if (stored.conversationid) {
-
 
398
                    Router.go(uniqueId, Routes.VIEW_CONVERSATION, stored.conversationid, 'frompanel');
-
 
399
                // There was no conversation id, let's get a conversation going using the user id.
-
 
400
                } else if (stored.otheruserid) {
-
 
401
                    Router.go(uniqueId, Routes.VIEW_CONVERSATION, null, 'create', stored.otheruserid);
-
 
402
                }
-
 
403
                break;
-
 
404
 
-
 
405
            case 'drawer':
-
 
406
                // Open the drawer and show the conversation.
-
 
407
                if (stored.conversationid) {
-
 
408
                    let args = {
-
 
409
                        conversationid: stored.conversationid
-
 
410
                    };
-
 
411
                    Helper.showConversation(args);
-
 
412
                // There was no conversation id, let's get a conversation going using the user id.
-
 
413
                } else if (stored.otheruserid) {
-
 
414
                    show(uniqueId, root);
-
 
415
                    Router.go(uniqueId, Routes.VIEW_CONVERSATION, null, 'create', stored.otheruserid);
-
 
416
                }
-
 
417
                break;
-
 
418
        }
-
 
419
 
-
 
420
        // Populate the text area.
-
 
421
        textArea.value = stored.message;
-
 
422
        textArea.setAttribute('data-unsent-message-viewed', 1);
-
 
423
 
-
 
424
        // Notify the user.
-
 
425
        Toast.add(Str.get_string('unsentmessagenotification', 'core_message'));
-
 
426
    };
-
 
427
 
185
    /**
428
    /**
186
     * Listen to and handle events for routing, showing and hiding the message drawer.
429
     * Listen to and handle events for routing, showing and hiding the message drawer.
187
     *
430
     *
188
     * @param {string} namespace The route namespace.
431
     * @param {string} namespace The route namespace.
189
     * @param {Object} root The message drawer container.
432
     * @param {Object} root The message drawer container.
190
     * @param {bool} alwaysVisible Is this messaging app always shown?
433
     * @param {bool} alwaysVisible Is this messaging app always shown?
191
     */
434
     */
192
    var registerEventListeners = function(namespace, root, alwaysVisible) {
435
    var registerEventListeners = function(namespace, root, alwaysVisible) {
193
        CustomEvents.define(root, [CustomEvents.events.activate]);
436
        CustomEvents.define(root, [CustomEvents.events.activate, CustomEvents.events.escape]);
Línea 194... Línea 437...
194
        var paramRegex = /^data-route-param-?(\d*)$/;
437
        var paramRegex = /^data-route-param-?(\d*)$/;
195
 
438
 
196
        root.on(CustomEvents.events.activate, SELECTORS.ROUTES, function(e, data) {
439
        root.on(CustomEvents.events.activate, SELECTORS.ROUTES, function(e, data) {
Línea 237... Línea 480...
237
            Router.back(namespace);
480
            Router.back(namespace);
Línea 238... Línea 481...
238
 
481
 
239
            data.originalEvent.preventDefault();
482
            data.originalEvent.preventDefault();
Línea -... Línea 483...
-
 
483
        });
-
 
484
 
-
 
485
        // Close the message drawer if the drawer is visible and the click happened outside the drawer and the toggle button.
-
 
486
        $(document).on(CustomEvents.events.activate, e => {
-
 
487
            var drawer = $(e.target).closest(SELECTORS.DRAWER);
-
 
488
            var toggleButtonId = $(SELECTORS.DRAWER)?.attr('data-origin');
-
 
489
            var toggleButton = '';
-
 
490
            if (toggleButtonId !== undefined && toggleButtonId) {
-
 
491
                toggleButton = $(e.target).closest("#" + toggleButtonId);
-
 
492
            }
-
 
493
 
-
 
494
            if (!drawer.length && !toggleButton.length && isVisible(root)) {
-
 
495
                // Determine if the element that was clicked is focusable.
-
 
496
                var focusableElement = $(e.target).closest(AriaSelectors.elements.focusable);
-
 
497
                if (focusableElement.length) {
-
 
498
                    // We need to move the focus to the clicked element after the drawer is hidden,
-
 
499
                    // so we need to clear the `data-origin` attribute first.
-
 
500
                    $(SELECTORS.DRAWER).attr('data-origin', '');
-
 
501
                }
-
 
502
                // Hide the drawer.
-
 
503
                hide(root);
-
 
504
                // Move the focus to the clicked element if it is focusable.
-
 
505
                if (focusableElement.length) {
-
 
506
                    focusableElement.focus();
-
 
507
                }
-
 
508
            }
240
        });
509
        });
241
 
510
 
242
        // These are theme-specific to help us fix random behat fails.
511
        // These are theme-specific to help us fix random behat fails.
-
 
512
        // These events target those events defined in BS3 and BS4 onwards.
243
        // These events target those events defined in BS3 and BS4 onwards.
513
        root[0].querySelectorAll('.collapse').forEach((collapse) => {
244
        root.on('hide.bs.collapse', '.collapse', function(e) {
514
            collapse.addEventListener('hide.bs.collapse', (e) => {
245
            var pendingPromise = new Pending();
515
                var pendingPromise = new Pending();
-
 
516
                e.target.addEventListener('hidden.bs.collapse', function() {
246
            $(e.target).one('hidden.bs.collapse', function() {
517
                    pendingPromise.resolve();
247
                pendingPromise.resolve();
518
                }, {once: true});
Línea 248... Línea 519...
248
            });
519
            });
-
 
520
        });
249
        });
521
 
250
 
522
        root[0].querySelectorAll('.collapse').forEach((collapse) => {
251
        root.on('show.bs.collapse', '.collapse', function(e) {
523
            collapse.addEventListener('show.bs.collapse', (e) => {
-
 
524
                var pendingPromise = new Pending();
252
            var pendingPromise = new Pending();
525
                e.target.addEventListener('shown.bs.collapse', function() {
253
            $(e.target).one('shown.bs.collapse', function() {
526
                    pendingPromise.resolve();
Línea 254... Línea 527...
254
                pendingPromise.resolve();
527
                }, {once: true});
255
            });
528
            });
Línea 279... Línea 552...
279
            PubSub.subscribe(Events.HIDE, function() {
552
            PubSub.subscribe(Events.HIDE, function() {
280
                hide(root);
553
                hide(root);
281
            });
554
            });
Línea 282... Línea 555...
282
 
555
 
-
 
556
            PubSub.subscribe(Events.TOGGLE_VISIBILITY, function(buttonid) {
283
            PubSub.subscribe(Events.TOGGLE_VISIBILITY, function(buttonid) {
557
                const buttonElement = document.getElementById(buttonid);
284
                if (isVisible(root)) {
558
                if (isVisible(root)) {
-
 
559
                    hide(root);
285
                    hide(root);
560
                    buttonElement?.setAttribute('aria-expanded', false);
286
                    $(SELECTORS.JUMPTO).attr('tabindex', -1);
561
                    $(SELECTORS.JUMPTO).attr('tabindex', -1);
287
                } else {
562
                } else {
-
 
563
                    show(namespace, root);
288
                    show(namespace, root);
564
                    buttonElement?.setAttribute('aria-expanded', true);
289
                    setJumpFrom(buttonid);
565
                    setJumpFrom(buttonid);
290
                    $(SELECTORS.JUMPTO).attr('tabindex', 0);
566
                    $(SELECTORS.JUMPTO).attr('tabindex', 0);
291
                }
567
                }
-
 
568
            });
-
 
569
            root.on(CustomEvents.events.escape, function() {
-
 
570
                PubSub.publish(Events.HIDE, {});
292
            });
571
            });
Línea 293... Línea 572...
293
        }
572
        }
294
 
573
 
295
        PubSub.subscribe(Events.SHOW_CONVERSATION, function(args) {
574
        PubSub.subscribe(Events.SHOW_CONVERSATION, function(args) {
Línea 299... Línea 578...
299
        });
578
        });
Línea 300... Línea 579...
300
 
579
 
301
        var closebutton = root.find(SELECTORS.CLOSE_BUTTON);
580
        var closebutton = root.find(SELECTORS.CLOSE_BUTTON);
302
        closebutton.on(CustomEvents.events.activate, function(e, data) {
581
        closebutton.on(CustomEvents.events.activate, function(e, data) {
303
            data.originalEvent.preventDefault();
-
 
-
 
582
            data.originalEvent.preventDefault();
304
 
583
            setFocus(root, false);
305
            var button = $(SELECTORS.DRAWER).attr('data-origin');
584
            var button = $(SELECTORS.DRAWER).attr('data-origin');
306
            if (button) {
585
            if (button) {
307
                $('#' + button).focus();
586
                $('#' + button).focus();
308
            }
587
            }
309
            PubSub.publish(Events.TOGGLE_VISIBILITY);
588
            PubSub.publish(Events.TOGGLE_VISIBILITY, button);
Línea 310... Línea 589...
310
        });
589
        });
311
 
590
 
312
        PubSub.subscribe(Events.CREATE_CONVERSATION_WITH_USER, function(args) {
591
        PubSub.subscribe(Events.CREATE_CONVERSATION_WITH_USER, function(args) {
Línea 329... Línea 608...
329
            if (enterToSendPreference) {
608
            if (enterToSendPreference) {
330
                var viewConversationFooter = root.find(SELECTORS.FOOTER_CONTAINER).find(SELECTORS.VIEW_CONVERSATION);
609
                var viewConversationFooter = root.find(SELECTORS.FOOTER_CONTAINER).find(SELECTORS.VIEW_CONVERSATION);
331
                viewConversationFooter.attr('data-enter-to-send', enterToSendPreference.value);
610
                viewConversationFooter.attr('data-enter-to-send', enterToSendPreference.value);
332
            }
611
            }
333
        });
612
        });
-
 
613
 
-
 
614
        // If our textarea is modified, remove the attribute which indicates the user has seen the unsent message notification.
-
 
615
        // This will allow the user to be notified again.
-
 
616
        const textArea = document.querySelector(SELECTORS.MESSAGE_TEXT_AREA);
-
 
617
        if (textArea) {
-
 
618
            textArea.addEventListener('keyup', function() {
-
 
619
                textArea.removeAttribute('data-unsent-message-viewed');
-
 
620
            });
-
 
621
        }
-
 
622
 
-
 
623
        // Catch any unsent messages and store them.
-
 
624
        window.addEventListener('beforeunload', storeUnsentMessage);
334
    };
625
    };
Línea 335... Línea 626...
335
 
626
 
336
    /**
627
    /**
337
     * Initialise the message drawer.
628
     * Initialise the message drawer.
Línea 356... Línea 647...
356
            }
647
            }
357
        }
648
        }
Línea 358... Línea 649...
358
 
649
 
359
        // Mark the drawer as ready.
650
        // Mark the drawer as ready.
-
 
651
        Helper.markDrawerReady();
-
 
652
 
-
 
653
        // Get and show any unsent message.
360
        Helper.markDrawerReady();
654
        getUnsentMessage(uniqueId, root);
Línea 361... Línea 655...
361
    };
655
    };
362
 
656
 
363
    return {
657
    return {