/* * Copyright (C) 2016 - present Instructure, Inc. * * This file is part of Canvas. * * Canvas is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License as published by the Free * Software Foundation, version 3 of the License. * * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License along * with this program. If not, see . */ import I18n from 'i18n!shared.flash_notices' import $ from 'jquery' import _ from 'underscore' import preventDefault from 'compiled/fn/preventDefault' import htmlEscape from 'str/htmlEscape' import 'jqueryui/effects/drop' import 'jquery.cookie' class RailsFlashNotificationsHelper { constructor() { this.holder = null; this.screenreader_holder = null; } initHolder() { const $current_holders = $('#flash_message_holder'); if ($current_holders.length === 0) { this.holder = null; } else { this.holder = $current_holders[0]; $(this.holder).on('click', '.close_link', (event) => { event.preventDefault(); }); $(this.holder).on('click', 'li', (event) => { if ($(event.currentTarget).hasClass('no_close')) { return; } if ($(event.currentTarget).hasClass('unsupported_browser')) { $.cookie('unsupported_browser_dismissed'); } $(event.currentTarget).stop(true, true).remove(); }); } } holderReady() { return this.holder != null; } createNode(type, content, timeout, cssOptions = {}) { if(this.holderReady()) { const node = this.generateNodeHTML(type, content); $(node).appendTo($(this.holder)). css(_.extend({zIndex: 2}, cssOptions)). show('fast'). delay(timeout || 7000). fadeOut('slow', function() { $(this).remove(); }); } } generateNodeHTML(type, content) { const icon = this.getIconType(type); // See generateScreenreaderNodeHtml for SR features return ` `; } getIconType(type) { if (type === 'success') { return 'check'; } else if (type === 'warning' || type === 'error') { return 'warning'; } else { return 'info'; } } initScreenreaderHolder() { const $current_screenreader_holders = $('#flash_screenreader_holder'); if ($current_screenreader_holders.length === 0) { this.screenreader_holder = null; } else { this.screenreader_holder = $current_screenreader_holders[0]; this.setScreenreaderAttributes(); } } screenreaderHolderReady() { return this.screenreader_holder != null; } createScreenreaderNode(content, closable = true) { if (this.screenreaderHolderReady()) { const node = $(this.generateScreenreaderNodeHTML(content, closable)); node.appendTo($(this.screenreader_holder)); window.setTimeout( () => { // Accessibility attributes must be removed for the deletion of the node // and then reapplied because JAWS/IE will not respect the // "aria-relevant" attribute and read when the node is deleted if // the attributes are in place this.resetScreenreaderAttributes(); node.remove(); this.setScreenreaderAttributes(); }, 10000); } } setScreenreaderAttributes() { if(this.screenreaderHolderReady()) { // These attributes are added for accessibility. However, adding them // to the DOM at load causes some screenreaders to read "alert" when // the page is loaded. That is why these attributes are added here. $(this.screenreader_holder).attr('role', 'alert'); $(this.screenreader_holder).attr('aria-live', 'assertive'); $(this.screenreader_holder).attr('aria-relevant', 'additions'); $(this.screenreader_holder).attr('class', 'screenreader-only'); $(this.screenreader_holder).attr('aria-atomic', 'false'); } } resetScreenreaderAttributes() { if(this.screenreaderHolderReady()) { $(this.screenreader_holder).removeAttr('role'); $(this.screenreader_holder).removeAttr('aria-live'); $(this.screenreader_holder).removeAttr('aria-relevant'); $(this.screenreader_holder).removeAttr('class'); $(this.screenreader_holder).removeAttr('aria-atomic'); } } createScreenreaderNodeExclusive(content) { if (this.screenreaderHolderReady()) { this.screenreader_holder.innerHTML = ''; let node = $(this.generateScreenreaderNodeHTML(content, false)); node.appendTo($(this.screenreader_holder)); } } generateScreenreaderNodeHTML(content, closable) { let closeContent; if(closable) { closeContent = I18n.t('Close'); } else { closeContent = ''; } return ` ${this.escapeContent(content)} ${htmlEscape(closeContent)} `; } /* xsslint safeString.method escapeContent */ escapeContent(content) { if(content.hasOwnProperty('html')) { return content.html; } else { return htmlEscape(content); } } } export default RailsFlashNotificationsHelper