Liferay.Loader.define("frontend-js-web@4.0.30/liferay/portlet/portlet_util.es", ['module', 'exports', 'require', 'frontend-js-metal-web$metal'], function (module, exports, require) {
  var define = undefined;
  var global = window;
  {
    Object.defineProperty(exports, "__esModule", {
      value: true
    });
    exports.validateState = exports.validatePortletId = exports.validateParameters = exports.validateForm = exports.validateArguments = exports.getUrl = exports.getUpdatedPublicRenderParameters = exports.generatePortletModeAndWindowStateString = exports.generateActionUrl = exports.encodeFormAsString = exports.decodeUpdateString = void 0;

    var _metal = require("frontend-js-metal-web$metal");

    function _typeof(obj) {
      "@babel/helpers - typeof";
      if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
        _typeof = function _typeof(obj) {
          return typeof obj;
        };
      } else {
        _typeof = function _typeof(obj) {
          return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
        };
      }return _typeof(obj);
    }

    function _toConsumableArray(arr) {
      return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
    }

    function _nonIterableSpread() {
      throw new TypeError("Invalid attempt to spread non-iterable instance");
    }

    function _iterableToArray(iter) {
      if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
    }

    function _arrayWithoutHoles(arr) {
      if (Array.isArray(arr)) {
        for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) {
          arr2[i] = arr[i];
        }return arr2;
      }
    }

    // Constants for URL generation
    var AJAX_ACTION_VALUE = '0';
    var CACHE_LEVEL_KEY = 'p_p_cacheability';
    var HUB_ACTION_KEY = 'p_p_hub';
    var PARTIAL_ACTION_VALUE = '1';
    var PORTLET_MODE_KEY = 'p_p_mode';
    var PUBLIC_RENDER_PARAM_KEY = 'p_r_p_';
    var RENDER_PARAM_KEY = 'priv_r_p_';
    var RESOURCE_ID_KEY = 'p_p_resource_id';
    var TOKEN_DELIM = '&';
    var VALUE_ARRAY_EMPTY = '';
    var VALUE_DELIM = '=';
    var VALUE_NULL = '';
    var WINDOW_STATE_KEY = 'p_p_state';
    /**
     * Decodes the update strings.
     * The update string is a JSON object containing the entire page state.
     * This decoder returns an object containing the portlet data for portlets whose
     * state has changed as compared to the current page state.
     * @param {Object} pageRenderState The page render state.
     * @param {string} updateString The update string to decode.
     * @return {Object}
     * @review
     */

    var decodeUpdateString = function decodeUpdateString(pageRenderState, updateString) {
      var portlets = pageRenderState && pageRenderState.portlets ? pageRenderState.portlets : {};

      try {
        var newRenderState = JSON.parse(updateString);

        if (newRenderState.portlets) {
          var keys = Object.keys(portlets);
          keys.forEach(function (key) {
            var newState = newRenderState.portlets[key].state;
            var oldState = portlets[key].state;

            if (!newState || !oldState) {
              throw new Error("Invalid update string.\nold state=".concat(oldState, "\nnew state=").concat(newState));
            }

            if (stateChanged(pageRenderState, newState, key)) {
              portlets[key] = newRenderState.portlets[key];
            }
          });
        }
      } catch (e) {// Do nothing
      }

      return portlets;
    };
    /**
     * Function to extract data from form and encode
     * it as an 'application/x-www-form-urlencoded' string.
     * @param {string} portletId The portlet ID.
     * @param {HTMLFormElement} form Form to be submitted.
     * @review
     */

    exports.decodeUpdateString = decodeUpdateString;

    var encodeFormAsString = function encodeFormAsString(portletId, form) {
      var parameters = [];

      var _loop = function _loop(i) {
        var element = form.elements[i];
        var name = element.name;
        var tag = element.nodeName.toUpperCase();
        var type = tag === 'INPUT' ? element.type.toUpperCase() : '';
        var value = element.value;

        if (name && !element.disabled && type !== 'FILE') {
          if (tag === 'SELECT' && element.multiple) {
            var options = _toConsumableArray(element.options);

            options.forEach(function (opt) {
              if (opt.checked) {
                var _value = opt.value;
                var parameter = encodeURIComponent(portletId + name) + '=' + encodeURIComponent(_value);
                parameters.push(parameter);
              }
            });
          } else if (type !== 'CHECKBOX' && type !== 'RADIO' || element.checked) {
            var param = encodeURIComponent(portletId + name) + '=' + encodeURIComponent(value);
            parameters.push(param);
          }
        }
      };

      for (var i = 0; i < form.elements.length; i++) {
        _loop(i);
      }

      return parameters.join('&');
    };
    /**
     * Helper for encoding a multi valued parameter.
     * @param {string} name The parameter's name.
     * @param {Array.<string>} values The parameter's value.
     * @return {string}
     * @review
     */

    exports.encodeFormAsString = encodeFormAsString;

    var encodeParameter = function encodeParameter(name, values) {
      var str = '';

      if (Array.isArray(values)) {
        if (values.length === 0) {
          str += TOKEN_DELIM + encodeURIComponent(name) + VALUE_DELIM + VALUE_ARRAY_EMPTY;
        } else {
          values.forEach(function (value) {
            str += TOKEN_DELIM + encodeURIComponent(name);

            if (value === null) {
              str += VALUE_DELIM + VALUE_NULL;
            } else {
              str += VALUE_DELIM + encodeURIComponent(value);
            }
          });
        }
      }

      return str;
    };
    /**
     * Generates the required options for an action URL request
     * according to the portletId, action URL and optional form element.
     *
     * @param {string} portletId The id of the portlet.
     * @param {string} url The action url.
     * @param {HTMLFormElement} The form element.
     * @return {Object}
     * @review
     */

    var generateActionUrl = function generateActionUrl(portletId, url, form) {
      var request = {
        credentials: 'same-origin',
        method: 'POST',
        url: url
      };

      if (form) {
        var enctype = form.enctype;

        if (enctype === 'multipart/form-data') {
          var formData = new FormData(form);
          request.body = formData;
        } else {
          var formAsString = encodeFormAsString(portletId, form);
          var method = form.method ? form.method.toUpperCase() : 'GET';

          if (method === 'GET') {
            if (url.indexOf('?') >= 0) {
              url += "&".concat(formAsString);
            } else {
              url += "?".concat(formAsString);
            }

            request.url = url;
          } else {
            request.body = formAsString;
            request.headers = {
              'Content-Type': 'application/x-www-form-urlencoded'
            };
          }
        }
      }

      return request;
    };
    /**
     * Helper for generating parameter strings for the URL
     * @param {Object} pageRenderState The page render state.
     * @param {string} portletId The portlet ID.
     * @param {string} name The parameter's name.
     * @param {string} type The parameter's type.
     * @param {string} group The parameter's group.
     * @review
     */

    exports.generateActionUrl = generateActionUrl;

    var generateParameterString = function generateParameterString(pageRenderState, portletId, name, type, group) {
      var str = '';

      if (pageRenderState.portlets && pageRenderState.portlets[portletId]) {
        var portletData = pageRenderState.portlets[portletId];

        if (portletData && portletData.state && portletData.state.parameters) {
          var values = portletData.state.parameters[name];

          if (values !== undefined) {
            // If values are present, encode the mutlivalued parameter string
            if (type === PUBLIC_RENDER_PARAM_KEY) {
              str += encodeParameter(group, values);
            } else if (type === RENDER_PARAM_KEY) {
              str += encodeParameter(portletId + RENDER_PARAM_KEY + name, values);
            } else {
              str += encodeParameter(portletId + name, values);
            }
          }
        }
      }

      return str;
    };
    /**
     * Helper for generating portlet mode & window state strings for the URL.
     * @param {Object} pageRenderState The page render state.
     * @param {string} portletId The portlet ID.
     * @return {string}
     * @review
     */

    var generatePortletModeAndWindowStateString = function generatePortletModeAndWindowStateString(pageRenderState, portletId) {
      var str = '';

      if (pageRenderState.portlets) {
        var portletData = pageRenderState.portlets[portletId];

        if (portletData.state) {
          var state = portletData.state;
          str += TOKEN_DELIM + PORTLET_MODE_KEY + VALUE_DELIM + encodeURIComponent(state.portletMode);
          str += TOKEN_DELIM + WINDOW_STATE_KEY + VALUE_DELIM + encodeURIComponent(state.windowState);
        }
      }

      return str;
    };
    /**
     * Gets the updated public parameters for the given portlet ID and new render state.
     * Returns an object whose properties are the group indexes of the
     * updated public parameters. The values are the new public parameter values.
     * @param {Object} pageRenderState The page render state.
     * @param {string} portletId The portlet ID.
     * @param {RenderState} state The new render state.
     * @return {Object} Object containing the updated public render parameters.
     * @review
     */

    exports.generatePortletModeAndWindowStateString = generatePortletModeAndWindowStateString;

    var getUpdatedPublicRenderParameters = function getUpdatedPublicRenderParameters(pageRenderState, portletId, state) {
      var publicRenderParameters = {};

      if (pageRenderState && pageRenderState.portlets) {
        var portletData = pageRenderState.portlets[portletId];

        if (portletData && portletData.pubParms) {
          var portletPublicParameters = portletData.pubParms;
          var keys = Object.keys(portletPublicParameters);
          keys.forEach(function (key) {
            if (!isParameterInStateEqual(pageRenderState, portletId, state, key)) {
              var group = portletPublicParameters[key];
              publicRenderParameters[group] = state.parameters[key];
            }
          });
        }
      }

      return publicRenderParameters;
    };
    /**
     * Returns a URL of the specified type.
     * @param {Object} pageRenderState The page render state.
     * @param {string} type The URL type.
     * @param {string} portletId The portlet ID.
     * @param {Object} parameters Additional parameters. May be <code>null</code>.
     * @param {string} cache Cacheability. Must be present if type = "RESOURCE". May be <code>null</code>.
     * @param {string} resourceId Resource ID. May be present if type = "RESOURCE". May be <code>null</code>.
     * @return {Promise} A promise that resolves the generated URL.
     * @review
     */

    exports.getUpdatedPublicRenderParameters = getUpdatedPublicRenderParameters;

    var getUrl = function getUrl(pageRenderState, type, portletId, parameters, cache, resourceId) {
      var cacheability = 'cacheLevelPage';
      var str = '';
      var url = '';

      if (pageRenderState && pageRenderState.portlets) {
        // If target portlet not defined for render URL, set it to null
        if (type === 'RENDER' && portletId === undefined) {
          portletId = null;
        }

        var portletData = pageRenderState.portlets[portletId];

        if (portletData) {
          if (type === 'RESOURCE') {
            url = decodeURIComponent(portletData.encodedResourceURL);

            if (cache) {
              cacheability = cache;
            }

            url += TOKEN_DELIM + CACHE_LEVEL_KEY + VALUE_DELIM + encodeURIComponent(cacheability);

            if (resourceId) {
              url += TOKEN_DELIM + RESOURCE_ID_KEY + VALUE_DELIM + encodeURIComponent(resourceId);
            }
          } else if (type === 'RENDER' && portletId !== null) {
            url = decodeURIComponent(portletData.encodedRenderURL);
          } else if (type === 'RENDER') {
            url = decodeURIComponent(pageRenderState.encodedCurrentURL);
          } else if (type === 'ACTION') {
            url = decodeURIComponent(portletData.encodedActionURL);
            url += TOKEN_DELIM + HUB_ACTION_KEY + VALUE_DELIM + encodeURIComponent(AJAX_ACTION_VALUE);
          } else if (type === 'PARTIAL_ACTION') {
            url = decodeURIComponent(portletData.encodedActionURL);
            url += TOKEN_DELIM + HUB_ACTION_KEY + VALUE_DELIM + encodeURIComponent(PARTIAL_ACTION_VALUE);
          } // Now add the state to the URL, taking into account cacheability if
          // we're dealing with a resource URL.
          // Put the private & public parameters on the URL if cacheability != FULL


          if (type !== 'RESOURCE' || cacheability !== 'cacheLevelFull') {
            // Add the state for the target portlet, if there is one.
            // (for the render URL, pid can be null, and the state will have
            // been added previously)
            if (portletId) {
              url += generatePortletModeAndWindowStateString(pageRenderState, portletId);
            } // Add the state for the target portlet, if there is one.
            // (for the render URL, pid can be null, and the state will have
            // been added previously)


            if (portletId) {
              str = '';

              if (portletData.state && portletData.state.parameters) {
                var stateParameters = portletData.state.parameters;
                var keys = Object.keys(stateParameters);
                keys.forEach(function (key) {
                  if (!isPublicParameter(pageRenderState, portletId, key)) {
                    str += generateParameterString(pageRenderState, portletId, key, RENDER_PARAM_KEY);
                  }
                });
                url += str;
              }
            } // Add the public render parameters for all portlets


            if (pageRenderState.prpMap) {
              str = '';
              var publicRenderParameters = {};
              var mapKeys = Object.keys(pageRenderState.prpMap);
              mapKeys.forEach(function (mapKey) {
                var groupKeys = Object.keys(pageRenderState.prpMap[mapKey]);
                groupKeys.forEach(function (groupKey) {
                  var groupName = pageRenderState.prpMap[mapKey][groupKey];
                  var parts = groupName.split('|'); // Only need to add parameter once, since it is shared

                  if (!Object.hasOwnProperty.call(publicRenderParameters, mapKey)) {
                    publicRenderParameters[mapKey] = generateParameterString(pageRenderState, parts[0], parts[1], PUBLIC_RENDER_PARAM_KEY, mapKey);
                    str += publicRenderParameters[mapKey];
                  }
                });
              });
              url += str;
            }
          }
        }
      } // Encode resource or action parameters


      if (parameters) {
        str = '';
        var parameterKeys = Object.keys(parameters);
        parameterKeys.forEach(function (parameterKey) {
          str += encodeParameter(portletId + parameterKey, parameters[parameterKey]);
        });
        url += str;
      }

      return Promise.resolve(url);
    };
    /**
     * Compares two parameters and returns a boolean indicating if they're equal
     * or not.
     * @param {?Array.<string>} parameter1 The first parameter to compare.
     * @param {?Array.<string>} parameter2 The second parameter to compare.
     * @return {boolean}
     * @review
     */

    exports.getUrl = getUrl;

    var isParameterEqual = function isParameterEqual(parameter1, parameter2) {
      var result = false; // The values are either string arrays or undefined.

      if (parameter1 === undefined && parameter2 === undefined) {
        result = true;
      }

      if (parameter1 === undefined || parameter2 === undefined) {
        result = false;
      }

      if (parameter1.length !== parameter2.length) {
        result = false;
      }

      for (var i = parameter1.length - 1; i >= 0; i--) {
        if (parameter1[i] !== parameter2[i]) {
          result = false;
        }
      }

      return result;
    };
    /**
     * Compares the values of the named parameter in the new render state
     * with the values of that parameter in the current state.
     * @param {Object} pageRenderState The page render state.
     * @param {string} portletId The portlet ID.
     * @param {RenderState} state The new render state.
     * @param {string} name The name of the parameter to check.
     * @return {boolean} True if the new parameter's value is different from the current value.
     * @review
     */

    var isParameterInStateEqual = function isParameterInStateEqual(pageRenderState, portletId, state, name) {
      var result = false;

      if (pageRenderState && pageRenderState.portlets) {
        var portletData = pageRenderState.portlets[portletId];

        if (state.parameters[name] && portletData.state.parameters[name]) {
          var newParameter = state.parameters[name];
          var oldParameter = portletData.state.parameters[name];
          result = isParameterEqual(newParameter, oldParameter);
        }
      }

      return result;
    };
    /**
     * Function for checking if a parameter is public.
     * @param {Object} pageRenderState The page render state.
     * @param {string} portletId  The portlet ID.
     * @param {string} name  The name of the parameter to check.
     * @return {boolean}
     * @review
     */

    var isPublicParameter = function isPublicParameter(pageRenderState, portletId, name) {
      var result = false;

      if (pageRenderState && pageRenderState.portlets) {
        var portletData = pageRenderState.portlets[portletId];

        if (portletData && portletData.pubParms) {
          var keys = Object.keys(portletData.pubParms);
          result = keys.includes(name);
        }
      }

      return result;
    };
    /**
     * Returns true if input state differs from the current page state.
     * Throws exception if input state is malformed.
     * @param {Object} pageRenderState The (current) page render state.
     * @param {RenderState} newState The new state to be set.
     * @param {string} portletId The portlet ID.
     * @return {boolean}  True if the two state are different.
     * @review
     */

    var stateChanged = function stateChanged(pageRenderState, newState, portletId) {
      var result = false;

      if (pageRenderState && pageRenderState.portlets) {
        var portletData = pageRenderState.portlets[portletId];

        if (portletData) {
          var oldState = pageRenderState.portlets[portletId].state;

          if (!newState.portletMode || !newState.windowState || !newState.parameters) {
            throw new Error("Error decoding state: ".concat(newState));
          }

          if (newState.porletMode !== oldState.portletMode || newState.windowState !== oldState.windowState) {
            result = true;
          } else {
            // Has a parameter changed or been added?
            var newKeys = Object.keys(newState.parameters);
            newKeys.forEach(function (key) {
              var newParameter = newState.parameters[key];
              var oldParameter = oldState.parameters[key];

              if (!isParameterEqual(newParameter, oldParameter)) {
                result = true;
              }
            }); // Make sure no parameter was deleted

            var oldKeys = Object.keys(oldState.parameters);
            oldKeys.forEach(function (key) {
              if (!newState.parameters[key]) {
                result = true;
              }
            });
          }
        }
      }

      return result;
    };
    /**
     * Used by the portlet hub methods to check the number and types of the
     * arguments.
     *
     * @param {string[]} args The argument list to be checked.
     * @param {number} min The minimum number of arguments.
     * @param {number} max The maximum number of arguments. If this value is
     * undefined, the function can take any number of arguments greater
     * than max.
     * @param {string[]} types An array containing the expected parameter types in the
     * order of occurrance in the argument array.
     * @throws {TypeError} Thrown if the parameters are in some manner incorrect.
     * @review
     */

    var validateArguments = function validateArguments() {
      var args = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
      var min = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
      var max = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
      var types = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];

      if (args.length < min) {
        throw new TypeError("Too few arguments provided: Number of arguments: ".concat(args.length));
      } else if (args.length > max) {
        throw new TypeError("Too many arguments provided: ".concat([].join.call(args, ', ')));
      } else if (Array.isArray(types)) {
        var i = Math.min(args.length, types.length) - 1;

        for (i; i >= 0; i--) {
          if (_typeof(args[i]) !== types[i]) {
            throw new TypeError("Parameter ".concat(i, " is of type ").concat(_typeof(args[i]), " rather than the expected type ").concat(types[i]));
          }

          if (args[i] === null || args[i] === undefined) {
            throw new TypeError("Argument is ".concat(_typeof(args[i])));
          }
        }
      }
    };
    /**
     * Validates an HTMLFormElement
     * @param {?HTMLFormElement} form The form element to be validated.
     * @throws {TypeError} Thrown if the form is not an HTMLFormElement.
     * @throws {TypeError} Thrown if the form's method attribute is not valid.
     * @throws {TypeError} Thrown if the form's enctype attribute is not valid.
     * @throws {TypeError} Thrown if the form's enctype attribute is not valid.
     * @review
     */

    exports.validateArguments = validateArguments;

    var validateForm = function validateForm(form) {
      if (!(form instanceof HTMLFormElement)) {
        throw new TypeError('Element must be an HTMLFormElement');
      }

      var method = form.method ? form.method.toUpperCase() : undefined;

      if (method && method !== 'GET' && method !== 'POST') {
        throw new TypeError("Invalid form method ".concat(method, ". Allowed methods are GET & POST"));
      }

      var enctype = form.enctype;

      if (enctype && enctype !== 'application/x-www-form-urlencoded' && enctype !== 'multipart/form-data') {
        throw new TypeError("Invalid form enctype ".concat(enctype, ". Allowed: 'application/x-www-form-urlencoded' & 'multipart/form-data'"));
      }

      if (enctype && enctype === 'multipart/form-data' && method !== 'POST') {
        throw new TypeError('Invalid method with multipart/form-data. Must be POST');
      }

      if (!enctype || enctype === 'application/x-www-form-urlencoded') {
        var l = form.elements.length;

        for (var i = 0; i < l; i++) {
          if (form.elements[i].nodeName.toUpperCase() === 'INPUT' && form.elements[i].type.toUpperCase() === 'FILE') {
            throw new TypeError("Must use enctype = 'multipart/form-data' with input type FILE.");
          }
        }
      }
    };
    /**
     * Verifies that the input parameters are in valid format.
     *
     * Parameters must be an object containing parameter names. It may also
     * contain no property names which represents the case of having no
     * parameters.
     *
     * If properties are present, each property must refer to an array of string
     * values. The array length must be at least 1, because each parameter must
     * have a value. However, a value of 'null' may appear in any array entry.
     *
     * To represent a <code>null</code> value, the property value must equal [null].
     *
     * @param {Object} parameters The parameters to check.
     * @throws {TypeError} Thrown if the parameters are incorrect.
     * @review
     */

    exports.validateForm = validateForm;

    var validateParameters = function validateParameters(parameters) {
      if (!(0, _metal.isDefAndNotNull)(parameters)) {
        throw new TypeError("The parameter object is: ".concat(_typeof(parameters)));
      }

      var keys = Object.keys(parameters);
      keys.forEach(function (key) {
        if (!Array.isArray(parameters[key])) {
          throw new TypeError("".concat(key, " parameter is not an array"));
        }

        if (!parameters[key].length) {
          throw new TypeError("".concat(key, " parameter is an empty array"));
        }
      });
    };
    /**
     * Validates the specificed portletId against the list
     * of current portlet in the pageRenderState.
     *
     * @param {string} portletId The ID of the portlet to be registered.
     * @param {Object} pageRenderState The current pageRenderState.
     * @return {boolean} A flag indicating if the specified portlet id is valid.
     * @review
     */

    exports.validateParameters = validateParameters;

    var validatePortletId = function validatePortletId() {
      var pageRenderState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      var portletId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
      return pageRenderState.portlets && Object.keys(pageRenderState.portlets).includes(portletId);
    };
    /**
     * Verifies that the input parameters are in valid format, that the portlet
     * mode and window state values are allowed for the portlet.
     * @param {RenderState} state The render state object to check.
     * @param {Object} portletData The porltet render state.
     * @throws {TypeError} Thrown if any component of the state is incorrect.
     * @review
     */

    exports.validatePortletId = validatePortletId;

    var validateState = function validateState() {
      var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      var portletData = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      validateParameters(state.parameters);
      var portletMode = state.portletMode;

      if (!(0, _metal.isString)(portletMode)) {
        throw new TypeError("Invalid parameters. portletMode is ".concat(_typeof(portletMode)));
      } else {
        var allowedPortletModes = portletData.allowedPM;

        if (!allowedPortletModes.includes(portletMode.toLowerCase())) {
          throw new TypeError("Invalid portletMode=".concat(portletMode, " is not in ").concat(allowedPortletModes));
        }
      }

      var windowState = state.windowState;

      if (!(0, _metal.isString)(windowState)) {
        throw new TypeError("Invalid parameters. windowState is ".concat(_typeof(windowState)));
      } else {
        var allowedWindowStates = portletData.allowedWS;

        if (!allowedWindowStates.includes(windowState.toLowerCase())) {
          throw new TypeError("Invalid windowState=".concat(windowState, " is not in ").concat(allowedWindowStates));
        }
      }
    };

    exports.validateState = validateState;
    //# sourceMappingURL=portlet_util.es.js.map
  }
});
//# sourceMappingURL=portlet_util.es.js.map