Idrinth/IDotD

View on GitHub
src/mods/core.js

Summary

Maintainability
D
2 days
Test Coverage
idrinth.core = {
  /**
     *
     * @param {string} str
     * @returns {string}
     */
  escapeRegExp: function(str) {
    return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
  },
  /**
     *
     * @param {object} parent
     * @param {string} field
     * @param {Boolean} allowObjects
     * @returns {Boolean}
     */
  fieldIsSetting: function(parent, field, allowObjects) {
    return (
      parent &&
      typeof parent === "object" &&
      field &&
      parent.hasOwnProperty(field) &&
      (parent[field] === null ||
        typeof parent[field] !== "object" ||
        allowObjects) &&
      typeof parent[field] !== "function"
    );
  },
  /**
     *
     * @type {object}
     */
  ajax: {
    /**
         *
         * @type {object}
         */
    active: {},
    /**
         *
         * @param {string} url
         * @param {function} success
         * @param {function} failure
         * @param {function} timeout
         * @param {string} additionalHeader
         * @param {Boolean} [false] isStatic
         * @returns {undefined}
         */
    runHome: function(
      url,
      success,
      failure,
      timeout,
      additionalHeader,
      isStatic
    ) {
      let server = isStatic
        ? "static"
        : (idrinth.settings.get("isWorldServer") ? "world-" : "") +
            idrinth.platform;
      let homeUrl =
        "https://dotd.idrinth.de/" + server + ("/" + url).replace(/\/\//, "/");
      idrinth.core.ajax.run(
        homeUrl,
        success,
        failure,
        timeout,
        additionalHeader
      );
    },
    /**
         *
         * @param {string} url
         * @param {function} success
         * @param {function} failure
         * @param {function} timeout
         * @param {string} additionalHeader
         * @param {Boolean} [false] isStatic
         * @returns {undefined}
         */
    run: function(url, success, failure, timeout, additionalHeader) {
      if(!idrinth.start && idrinth.settings.get("server")) {
          return;
      }
      let requestHandler = new XMLHttpRequest();
      requestHandler.onreadystatechange = function(event) {
        let request = (event || window.event).target;
        let call = function(func, value) {
          if (typeof func !== "function") {
            return;
          }
          try {
            return func(value);
          } catch (e) {
            idrinth.core.log(
              typeof e.getMessage === "function"
                ? e.getMessage()
                : e.message ? e.message : e
            );
            return null;
          }
        };
        if (request.readyState === 4) {
          let status =
            (request.status > 199 && request.status < 300) ||
            request.status === 0;
          call(
            status ? success : failure,
            status ? request.responseText : request
          );
          delete idrinth.core.ajax.active[request._url];
        }
      };
      requestHandler.timeout = 30000;
      requestHandler.ontimeout = function(event) {
        let request = (event || window.event).target;
        if (typeof timeout === "function") {
          timeout.bind(request);
        }
        delete idrinth.core.ajax.active[request._url];
        idrinth.core.log("Request to " + request._url + " failed.");
      };
      let error = function(event) {
        delete idrinth.core.ajax.active[(event || window.event).target._url];
        idrinth.core.log(
          "Request to " + (event || window.event).target._url + " failed."
        );
      };
      requestHandler.onerror = error;
      requestHandler.onabort = error;
      requestHandler._url = url;
      requestHandler.open("GET", url, true);
      if (url.match("/dotd\.idrinth\.de/")) {
        if (additionalHeader) {
          requestHandler.setRequestHeader("Idrinth-Addition", additionalHeader);
        }
        requestHandler.withCredentials = true;
      }
      idrinth.core.ajax.active[url] = requestHandler;
      idrinth.core.ajax.active[url].send();
    }
  },
  /**
     *
     * @type {object}
     */
  copyToClipboard: {
    /**
         *
         * @param {string} text
         * @returns {Boolean}
         */
    text: function(text) {
      let success;
      try {
        let textAreaElement = idrinth.ui.buildElement({
          type: "textarea",
          id: "idrinth-copy-helper"
        });
        textAreaElement.value = text;
        idrinth.ui.base.appendChild(textAreaElement);
        textAreaElement.select();
        success = document.execCommand("copy");
      } catch (exception) {
        idrinth.core.log(exception.getMessage());
        success = false;
      }
      idrinth.ui.removeElement("idrinth-copy-helper");
      return success;
    },
    /**
         *
         * @param {HTMLElement} element
         * @returns {string}
         */
    element: function(element) {
      if (element.hasAttribute("data-clipboard-text")) {
        return idrinth.core.copyToClipboard.text(
          element.getAttribute("data-clipboard-text")
        );
      }
      if (element.value) {
        return idrinth.core.copyToClipboard.text(element.value);
      }
      return idrinth.core.copyToClipboard.text(element.innerHTML);
    }
  },
  /**
     *
     * @param {string} title
     * @param {string|HTMLElement} content
     * @returns {Boolean|window.Notification}
     */
  sendNotification: function(title, content) {
    if (!("Notification" in window)) {
      return false;
    }
    if (window.Notification.permission === "default") {
      window.Notification.requestPermission();
    }
    if (window.Notification.permission === "denied") {
      return false;
    }
    let data = {};
    if (idrinth.settings.get("notification#image")) {
      data.icon = "https://dotd.idrinth.de/Resources/Images/logo.png";
    }
    if (idrinth.settings.get("notification#content")) {
      data.body = content;
    }
    return new window.Notification(title, data);
  },
  /**
     *
     * @type {object}
     */
  timeouts: {
    /**
         *
         * @type {object}
         */
    next: null,
    /**
         *
         * @type {object}
         */
    list: {},
    /**
         * makes sure the timeout is removed when called next
         * @param {string} identifier
         * @returns {undefined}
         */
    remove: function(identifier) {
      if (idrinth.core.timeouts.list[identifier] !== undefined) {
        idrinth.core.timeouts.list[identifier].repeats = 1;
        idrinth.core.timeouts.list[identifier].func = function() {};
      }
    },
    /**
         *
         * @param {string} identifier
         * @param {function} func
         * @param {int} time in milliseconds
         * @param {Number} [1] maxRepeats -1 will repeat until the end of time
         * @returns {undefined}
         */
    add: function(identifier, func, time, maxRepeats) {
      let date = new Date();
      idrinth.core.timeouts.list[identifier] = {
        func: func,
        next: date.getTime() + date.getMilliseconds() / 1000 + time / 1000,
        duration: time,
        repeats: maxRepeats ? maxRepeats : 1
      };
      if (!idrinth.core.timeouts.next) {
        idrinth.core.timeouts.next = window.setTimeout(
          idrinth.core.timeouts.process,
          1000
        );
      }
    },
    /**
         * activates all relevant timeouts and intervals
         * @returns {undefined}
         */
    process: function() {
      let date = new Date().getTime() + new Date().getMilliseconds() / 1000;
      let min = 10;
      /**
             *
             * @param {Number} min
             * @param {Number} property
             * @returns {Number}
             */
      let check = function(min, property, date) {
        /**
                 *
                 * @param {Number} durationLeft
                 * @param {string} minDuration
                 * @returns {Number}
                 */
        let getVal = function(durationLeft, minDuration) {
          if (durationLeft < 0.1) {
            return 0.1;
          }
          return durationLeft < minDuration ? durationLeft : minDuration;
        };
        /**
                 *
                 * @param {string} property
                 * @returns {undefined}
                 */
        let handle = function(property, min) {
          idrinth.core.timeouts.list[property].func();
          idrinth.core.timeouts.list[property].repeats = Math.max(
            -1,
            idrinth.core.timeouts.list[property].repeats - 1
          );
          if (idrinth.core.timeouts.list[property].repeats) {
            min = getVal(idrinth.core.timeouts.list[property].duration, min);
            idrinth.core.timeouts.list[property].next =
              date + idrinth.core.timeouts.list[property].duration / 1000;
          } else {
            delete idrinth.core.timeouts.list[property];
          }
          return min;
        };
        if (date < idrinth.core.timeouts.list[property].next) {
          return getVal(idrinth.core.timeouts.list[property].next - date, min);
        }
        try {
          return handle(property, min);
        } catch (e) {
          idrinth.core.log(e.message ? e.message : e.getMessage());
          return min;
        }
      };
      for (var property in idrinth.core.timeouts.list) {
        if (idrinth.core.timeouts.list.hasOwnProperty(property)) {
          min = check(min, property, date);
        }
      }
      if (Object.keys(idrinth.core.timeouts.list).length) {
        idrinth.core.timeouts.next = window.setTimeout(
          idrinth.core.timeouts.process,
          Math.ceil(min * 1000)
        );
      }
    }
  },
  /**
     *
     * @param {string} string
     * @returns {undefined}
     */
  log: function(string) {
    console.log("[IDotDS] " + string);
  },
  /**
     *
     * @param {string} text
     * @returns {undefined}
     */
  alert: function(text) {
    if (!idrinth.ui.base) {
      window.alert(text);
      return;
    }
    idrinth.ui.buildModal("Info", text);
  },
  /**
     *
     * @param {string} text
     * @param {function} callback
     * @returns {undefined}
     */
  confirm: function(text, callback) {
    idrinth.ui.buildModal("Do you?", text, callback);
  },
  /**
     *
     * @type {object}
     */
  multibind: {
    /**
         *
         * @type {object}
         */
    events: {},
    /**
         *
         * @param {string} event
         * @param {string} selector
         * @param {function} method
         * @returns {undefined}
         */
    add: function(event, selector, method) {
      let bind = function(event, selector, method) {
        idrinth.core.multibind.events[event] = idrinth.core.multibind.events[
          event
        ]
          ? idrinth.core.multibind.events[event]
          : {};
        idrinth.core.multibind.events[event][selector] = idrinth.core.multibind
          .events[event][selector]
          ? idrinth.core.multibind.events[event][selector]
          : [];
        idrinth.core.multibind.events[event][selector].push(method);
      };
      if (!idrinth.core.multibind.events[event]) {
        document
          .getElementsByTagName("body")[0]
          .addEventListener(event, idrinth.core.multibind.triggered);
      }
      bind(event, selector, method);
    },
    /**
         *
         * @param {Event} [window.event] event
         * @returns {undefined}
         */
    triggered: function(event) {
      /**
             *
             * @param {HTMLElement} el
             * @param {string} event
             * @param {string} selector
             * @returns {undefined}
             */
      let handleElement = function(el, event, selector) {
        if (!el) {
          return;
        }
        for (
          let pos = 0;
          pos < idrinth.core.multibind.events[event][selector].length;
          pos++
        ) {
          try {
            idrinth.core.multibind.events[event][selector][pos](el, event);
          } catch (exception) {
            idrinth.core.log(
              exception.message ? exception.message : exception.getMessage()
            );
          }
        }
      };
      event = event || window.event;
      if (idrinth.core.multibind.events[event.type]) {
        for (var selector in idrinth.core.multibind.events[event.type]) {
          if (
            idrinth.core.multibind.events[event.type].hasOwnProperty(selector)
          ) {
            handleElement(
              idrinth.ui.matchesCss(event.target, selector),
              event.type,
              selector
            );
          }
        }
      }
    }
  }
};