view class doc
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300/// FOURJS_START_COPYRIGHT(D,2015)
/// Property of Four Js*
/// (c) Copyright Four Js 2015, 2022. All Rights Reserved.
/// * Trademark of Four Js Development Tools Europe Ltd
///   in the United States and elsewhere
///
/// This file can be modified by licensees according to the
/// product manual.
/// FOURJS_END_COPYRIGHT

'use strict';

modulum('MessageWidget', ['TextWidgetBase', 'WidgetFactory'],
  function(context, cls) {

    /**
     * Message Widget to display information as toated popups
     * @class MessageWidget
     * @memberOf classes
     * @extends classes.TextWidgetBase
     * @publicdoc Widgets
     */
    cls.MessageWidget = context.oo.Class(cls.TextWidgetBase, function($super) {
      return /** @lends classes.MessageWidget.prototype */ {
        __name: 'MessageWidget',
        $static: /** @lends classes.MessageWidget */ {
          defaultDisplayTime: 10
        },

        /**
         * Content of the message
         * @type {string}
         */
        _text: '',

        /**
         * Is the message is displayed with html formatting
         * @type {boolean}
         */
        _htmlFormat: false,

        /**
         * true if we must sanitize the html
         * @type {boolean}
         * */
        _sanitize: null,

        /** @type {string} */
        _kind: 'message',

        /**
         * Timer to handle display time
         * @type {?number}
         */
        _currentTimeout: null,

        /**
         * Time (in seconds) before hiding message
         * 0  : always show
         * -1 : always hide
         */
        _messageDisplayTime: 0,

        /**
         * Close button element
         * @type {HTMLElement}
         */
        _closeButton: null,

        /**
         * Text Element
         * @type {HTMLElement}
         */
        _textElement: null,

        /**
         * @inheritDoc
         */
        _initElement: function() {
          $super._initElement.call(this);

          this._closeButton = this._element.querySelector('.close-button');
          this._textElement = this._element.querySelector('.message-text');

          var themeDisplayTime = context.ThemeService.getValue('theme-message-display-time');
          this._messageDisplayTime = Object.isNumber(themeDisplayTime) || Object.isString(themeDisplayTime) ?
            parseInt(themeDisplayTime, 10) : cls.MessageWidget.defaultDisplayTime;

          var swipeDirections = this.getPosition().split('-');
          // Interesting on touch device. On desktop click catches all
          this._element.onSwipe('MessageWidget', this._onSwipe.bind(this), {
            direction: swipeDirections
          });

          this.setHidden(true);
        },

        /**
         * @inheritDoc
         */
        destroy: function() {
          this._closeButton = null;
          this._textElement = null;
          if (this._htmlFilter) {
            this._htmlFilter.destroy();
            this._htmlFilter = null;
          }
          $super.destroy.call(this);
        },

        /**
         * @inheritDoc
         */
        manageMouseClick: function(domEvent) {
          this.setHidden(true);
          return true;
        },

        /**
         * Set the message text
         * @param {string} text - the text to display
         * @publicdoc
         */
        setText: function(text) {
          if (text !== this._text) {
            this._text = text;
            this._refreshText();
            this.getLayoutEngine().invalidateMeasure();
          }
        },

        /**
         * Handle text reformatting
         * @private
         */
        _refreshText: function() {
          this.domAttributesMutator(function() {
            if (this._htmlFormat) {
              if (this._sanitize) {
                if (!this._htmlFilter) {
                  this._htmlFilter = cls.WidgetFactory.createWidget('HtmlFilterWidget', this.getBuildParameters());
                }
                this._textElement.innerHTML = this._htmlFilter.sanitize(this._text);
              } else {
                this._textElement.innerHTML = this._text;
              }
            } else {
              this._textElement.textContent = this._text;
            }
          }.bind(this));

          if (this._text.trim().length <= 0) {
            this.setHidden(true);
          } else {
            this.setHidden(false);
          }
          if (this.isReversed()) {
            var ui = this.getUserInterfaceWidget();
            if (ui) {
              var left = ui.getElement().getBoundingClientRect().left;
              this.setStyle({
                'left': (left + 12) + 'px'
              });
            }
          }
        },

        /**
         * Get the current text
         * @returns {string} the displayed text
         * @publicdoc
         */
        getText: function() {
          return this._textElement.textContent;
        },

        /**
         * Hide / show the message
         * @param {boolean} hidden - visibility state
         * @publicdoc
         */
        setHidden: function(hidden) {
          // Message text is empty or display time is 0, hide it
          if (this._text.trim().length <= 0 || this._messageDisplayTime < 0) {
            hidden = true;
          }
          if (!hidden) {
            this.removeClass("out-of-view");
          }
          var disp = this._messageDisplayTime * 1000;
          // Handle hide timeout only if display time is positive
          if (this._messageDisplayTime > 0) {
            if (this._hidden !== hidden) {
              $super.setHidden.call(this, hidden);
              if (this._currentTimeout !== null) {
                this._clearTimeout(this._currentTimeout);
                this._currentTimeout = null;
              }
              if (!hidden) {
                this._currentTimeout = this._registerTimeout(this._hide.bind(this), disp);
              }
              this.emit("hide.MessageWidget", hidden);
            }
          } else {
            $super.setHidden.call(this, hidden);
          }
        },

        /**
         * Hide message with a sliding animation
         * @private
         */
        _onSwipe: function() {
          this.getElement().addClass("slideOut");
          this._registerTimeout(function() {
            this.setHidden(true);
            this.getElement().removeClass("slideOut");
          }.bind(this), 350);
        },

        /**
         * do hide
         * @private
         */
        _hide: function() {
          this.setHidden(true);
          this._currentTimeout = null;
        },

        /**
         * Set message formatting as html
         * @param {boolean} html - true if html formatted, false otherwise
         * @publicdoc
         */
        setHtmlFormat: function(html) {
          if (this._htmlFormat !== html) {
            this._htmlFormat = html;
            this._refreshText();
          }
        },

        /**
         * sanitize = false : Authorize to send html text without control
         * @param {boolean} sanitize
         */
        setSanitize: function(sanitize) {
          this._sanitize = sanitize;
        },

        /**
         * Defines the type of message, thus the right customization variables will be used
         * @param {string} kind - could be 'message' or 'error'
         * @publicdoc
         */
        setMessageKind: function(kind) {
          this._kind = kind;
          if (kind) {
            // Handle display time
            var themeDisplayTime = context.ThemeService.getValue('theme-' + kind + '-display-time');
            this._messageDisplayTime = Object.isNumber(themeDisplayTime) || Object.isString(themeDisplayTime) ?
              parseInt(themeDisplayTime, 10) : cls.MessageWidget.defaultDisplayTime;
            // Handle position
            if (context.ThemeService.getValue("theme-" + kind + "-display-position")) {
              this.addClass(context.ThemeService.getValue("theme-" + kind + "-display-position"));
            }
          }
        },

        /**
         * Get the message kind
         * @return {string} could be 'error' or 'message'
         */
        getMessageKind: function() {
          return this._kind;
        },

        /**
         * Get the 4ST position value for the message
         * @return {string} - something like "bottom-left"
         */
        getPosition: function() {
          var pos = "bottom-right"; // default value
          var kind = this.getMessageKind();
          var themePos = context.ThemeService.getValue("theme-" + kind + "-display-position");
          return themePos ? themePos : pos;
        },

        /**
         * Use this to create a widget in the dom without displaying it
         */
        setDummyMessage: function() {
          this.setText("...");
          this.addClass("out-of-view"); // see: GBC-2187
        },

      };
    });
    cls.WidgetFactory.registerBuilder('Message', cls.MessageWidget);
  });