MediaWiki:Gadget-QDmodal.js: Difference between revisions

From RuneRealm Wiki
Jump to navigation Jump to search
Content added Content deleted
 
No edit summary
 
Line 1: Line 1:
"use strict";

/* <nowiki>
/* <nowiki>
QDmodal - flexbox-based modal library
QDmodal - flexbox-based modal library
Line 12: Line 14:


(function ($, mw) {
(function ($, mw) {
"use strict";
"use strict";


var version = 20230117;
var version = 20230117;
if (mw.libs.QDmodal && mw.libs.QDmodal.version >= version) {

return;
if (mw.libs.QDmodal && mw.libs.QDmodal.version >= version) {
}
return;
var visibleModals = document.getElementsByClassName("qdmodal");
var $window = $(window);
var $body = $(document.body);
var $closeIcon = $("<svg class='qdmodal-close' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'>" + "<title>Close</title>" + "<path d='M 3,3 13,13 M 13,3 3,13'/>" + "</svg>");
var $spinner = $("<svg class='qdmodal-spinner' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 50 50'>" + "<path d='M 25,5 v 10'/>".repeat(12) + "</svg>");
function isElementOrChildFrontmost(element) {
var pos = element.getBoundingClientRect();
var frontmostElement = document.elementFromPoint(pos.left, pos.top);
return element.contains(frontmostElement);
}
function addButton(button) {
var $button = $("<span>");
if (!button) {
// invalid
return;
}
}
if (typeof button.condition === "function" && !button.condition(this)) {

// condition function present and didn't return truthy
var visibleModals = document.getElementsByClassName("qdmodal");
var $window = $(window);
return;
}
var $body = $(document.body);
var $closeIcon = $(
if (button.href) {
$button = $("<a>").attr({
"<svg class='qdmodal-close' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'>"
+ "<title>Close</title>"
href: button.href,
+ "<path d='M 3,3 13,13 M 13,3 3,13'/>"
target: "_blank"
+ "</svg>"
});
);
}
if (typeof button.handler === "function") {
var $spinner = $(
$button.on("click", button.handler);
"<svg class='qdmodal-spinner' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 50 50'>"
+ ("<path d='M 25,5 v 10'/>".repeat(12))
+ "</svg>"
);

function isElementOrChildFrontmost(element) {
var pos = element.getBoundingClientRect();
var frontmostElement = document.elementFromPoint(pos.left, pos.top);
return element.contains(frontmostElement);
}
}
if (button.attr) {
$button.attr(button.attr);
}
$button.addClass("qdmodal-button").text(button.text);
this.$footer.append($button);
}
function closeOnBackgroundClick(event) {
if (event.target === event.delegateTarget) {
this.hide();
}
}
function closeOnEscapeKeydown(event) {
if (event.key === "Escape" && isElementOrChildFrontmost(this.$container[0])) {
this.hide();
}
}


//// QDmodal constructor ////
function addButton(button) {
var $button = $("<span>");


if (!button) {
mw.libs.QDmodal = function (id) {
if (this === mw.libs) {
// invalid
throw new Error("mw.libs.QDmodal should be called as a constructor.");
return;
}

if (typeof button.condition === "function" && !button.condition(this)) {
// condition function present and didn't return truthy
return;
}

if (button.href) {
$button = $("<a>").attr({
href: button.href,
target: "_blank"
});
}

if (typeof button.handler === "function") {
$button.on("click", button.handler);
}

if (button.attr) {
$button.attr(button.attr);
}

$button.addClass("qdmodal-button").text(button.text);

this.$footer.append($button);
}
}
var $close = $closeIcon.clone();

this.$container = $("<div>").addClass("qdmodal-container");
function closeOnBackgroundClick(event) {
this.$element = $("<div>").addClass("qdmodal");
if (event.target === event.delegateTarget) {
this.hide();
this.$title = $("<h3>");
this.$content = $("<section>");
}
this.$footer = $("<footer>");
this.$container.append(this.$element.append($("<header>").append(this.$title, $close), this.$content, this.$footer));
this.visible = false;
this.data = null;
if (typeof id === "string") {
this.$element.attr("id", id);
}
$close.on("click", this.hide.bind(this));
this.$container.on("click", closeOnBackgroundClick.bind(this));
$window.on("keydown", closeOnEscapeKeydown.bind(this));
};
mw.libs.QDmodal.prototype.hide = function () {
if (this.data && typeof this.data.onHide === "function") {
if (this.data.onHide(this) === false) {
return;
}
}
this.visible = false;
this.data = null;
this.$container.detach();
if (!visibleModals.length) {
$body.removeClass("qdmodal-is-visible");
}
}
};
mw.libs.QDmodal.prototype.show = function (data) {
if (!data) {
return;
}
this.data = data;


// only set title if one is given, else keep previous title
function closeOnEscapeKeydown(event) {
if (
if (data.title) {
this.$title.text(data.title);
event.key === "Escape"
}
&& isElementOrChildFrontmost(this.$container[0])
) {
if (data.loading) {
this.hide();
this.$content.empty().append($spinner.clone());
}
} else {
this.$content.html(data.content || "");
}
this.$footer.empty();
if (Array.isArray(data.buttons)) {
data.buttons.forEach(addButton.bind(this));
}
}
if (typeof this.data.onBeforeShow === "function") {
this.data.onBeforeShow(this);
}
if (data.hook) {
mw.hook(data.hook).fire(this);
}
if (!this.visible) {
$body.addClass("qdmodal-is-visible").append(this.$container);
this.visible = true;
}
if (typeof this.data.onShow === "function") {
this.data.onShow(this);
}
};


//// QDmodal constructor ////
//// Initialisation ////

mw.libs.QDmodal = function (id) {
if (this === mw.libs) {
throw new Error("mw.libs.QDmodal should be called as a constructor.");
}

var $close = $closeIcon.clone();

this.$container = $("<div>").addClass("qdmodal-container");
this.$element = $("<div>").addClass("qdmodal");
this.$title = $("<h3>");
this.$content = $("<section>");
this.$footer = $("<footer>");

this.$container.append(
this.$element.append(
$("<header>").append(
this.$title,
$close
),
this.$content,
this.$footer
)
);

this.visible = false;
this.data = null;

if (typeof id === "string") {
this.$element.attr("id", id);
}

$close.on("click", this.hide.bind(this));
this.$container.on("click", closeOnBackgroundClick.bind(this));
$window.on("keydown", closeOnEscapeKeydown.bind(this));
};

mw.libs.QDmodal.prototype.hide = function () {
if (this.data && typeof this.data.onHide === "function") {
if (this.data.onHide(this) === false) {
return;
}
}

this.visible = false;
this.data = null;
this.$container.detach();

if (!visibleModals.length) {
$body.removeClass("qdmodal-is-visible");
}
};

mw.libs.QDmodal.prototype.show = function (data) {
if (!data) {
return;
}

this.data = data;

// only set title if one is given, else keep previous title
if (data.title) {
this.$title.text(data.title);
}

if (data.loading) {
this.$content.empty().append($spinner.clone());
} else {
this.$content.html(data.content || "");
}

this.$footer.empty();

if (Array.isArray(data.buttons)) {
data.buttons.forEach(addButton.bind(this));
}

if (typeof this.data.onBeforeShow === "function") {
this.data.onBeforeShow(this);
}

if (data.hook) {
mw.hook(data.hook).fire(this);
}

if (!this.visible) {
$body.addClass("qdmodal-is-visible").append(this.$container);
this.visible = true;
}

if (typeof this.data.onShow === "function") {
this.data.onShow(this);
}
};


//// Initialisation ////

mw.libs.QDmodal.version = version;


mw.libs.QDmodal.version = version;
// provide other scripts a copy of the loading spinner
mw.libs.QDmodal.getSpinner = function () {
return $("<span>").addClass("qdmodal-spinner-container").append($spinner.clone());
};


// provide other scripts a copy of the loading spinner
// no-op function, kept to prevent breakage in other scripts
mw.libs.QDmodal.loadTheme = function () {};
mw.libs.QDmodal.getSpinner = function () {
return $("<span>").addClass("qdmodal-spinner-container").append($spinner.clone());
};


$(function () {
// no-op function, kept to prevent breakage in other scripts
mw.libs.QDmodal.loadTheme = function () {};
document.documentElement.style.setProperty(
$(function () {
"--qdmodal-scrollbar-width",
(window.innerWidth - document.body.offsetWidth) + "px"
document.documentElement.style.setProperty("--qdmodal-scrollbar-width", window.innerWidth - document.body.offsetWidth + "px");
);
});
});


// fire hook for convenience
// fire hook for convenience
mw.hook("dev.qdmodal").fire(mw.libs.QDmodal);
mw.hook("dev.qdmodal").fire(mw.libs.QDmodal);
}(jQuery, mediaWiki));
})(jQuery, mediaWiki);
// </nowiki>
// </nowiki>

Latest revision as of 12:06, 20 October 2024

"use strict";

/* <nowiki>
    QDmodal - flexbox-based modal library
    Modified to remove Wikia-specific i18n code; relies on [[MediaWiki:Gadget-QDmodal.css]]

    @author OneTwoThreeFall
    @source <https://dev.fandom.com/wiki/QDmodal>
    @source <https://dev.fandom.com/wiki/MediaWiki:QDmodal.js>
*/

/*jslint browser, long, this */
/*global jQuery, mediaWiki */

(function ($, mw) {
  "use strict";

  var version = 20230117;
  if (mw.libs.QDmodal && mw.libs.QDmodal.version >= version) {
    return;
  }
  var visibleModals = document.getElementsByClassName("qdmodal");
  var $window = $(window);
  var $body = $(document.body);
  var $closeIcon = $("<svg class='qdmodal-close' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'>" + "<title>Close</title>" + "<path d='M 3,3 13,13 M 13,3 3,13'/>" + "</svg>");
  var $spinner = $("<svg class='qdmodal-spinner' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 50 50'>" + "<path d='M 25,5 v 10'/>".repeat(12) + "</svg>");
  function isElementOrChildFrontmost(element) {
    var pos = element.getBoundingClientRect();
    var frontmostElement = document.elementFromPoint(pos.left, pos.top);
    return element.contains(frontmostElement);
  }
  function addButton(button) {
    var $button = $("<span>");
    if (!button) {
      // invalid
      return;
    }
    if (typeof button.condition === "function" && !button.condition(this)) {
      // condition function present and didn't return truthy
      return;
    }
    if (button.href) {
      $button = $("<a>").attr({
        href: button.href,
        target: "_blank"
      });
    }
    if (typeof button.handler === "function") {
      $button.on("click", button.handler);
    }
    if (button.attr) {
      $button.attr(button.attr);
    }
    $button.addClass("qdmodal-button").text(button.text);
    this.$footer.append($button);
  }
  function closeOnBackgroundClick(event) {
    if (event.target === event.delegateTarget) {
      this.hide();
    }
  }
  function closeOnEscapeKeydown(event) {
    if (event.key === "Escape" && isElementOrChildFrontmost(this.$container[0])) {
      this.hide();
    }
  }

  //// QDmodal constructor ////

  mw.libs.QDmodal = function (id) {
    if (this === mw.libs) {
      throw new Error("mw.libs.QDmodal should be called as a constructor.");
    }
    var $close = $closeIcon.clone();
    this.$container = $("<div>").addClass("qdmodal-container");
    this.$element = $("<div>").addClass("qdmodal");
    this.$title = $("<h3>");
    this.$content = $("<section>");
    this.$footer = $("<footer>");
    this.$container.append(this.$element.append($("<header>").append(this.$title, $close), this.$content, this.$footer));
    this.visible = false;
    this.data = null;
    if (typeof id === "string") {
      this.$element.attr("id", id);
    }
    $close.on("click", this.hide.bind(this));
    this.$container.on("click", closeOnBackgroundClick.bind(this));
    $window.on("keydown", closeOnEscapeKeydown.bind(this));
  };
  mw.libs.QDmodal.prototype.hide = function () {
    if (this.data && typeof this.data.onHide === "function") {
      if (this.data.onHide(this) === false) {
        return;
      }
    }
    this.visible = false;
    this.data = null;
    this.$container.detach();
    if (!visibleModals.length) {
      $body.removeClass("qdmodal-is-visible");
    }
  };
  mw.libs.QDmodal.prototype.show = function (data) {
    if (!data) {
      return;
    }
    this.data = data;

    // only set title if one is given, else keep previous title
    if (data.title) {
      this.$title.text(data.title);
    }
    if (data.loading) {
      this.$content.empty().append($spinner.clone());
    } else {
      this.$content.html(data.content || "");
    }
    this.$footer.empty();
    if (Array.isArray(data.buttons)) {
      data.buttons.forEach(addButton.bind(this));
    }
    if (typeof this.data.onBeforeShow === "function") {
      this.data.onBeforeShow(this);
    }
    if (data.hook) {
      mw.hook(data.hook).fire(this);
    }
    if (!this.visible) {
      $body.addClass("qdmodal-is-visible").append(this.$container);
      this.visible = true;
    }
    if (typeof this.data.onShow === "function") {
      this.data.onShow(this);
    }
  };

  //// Initialisation ////

  mw.libs.QDmodal.version = version;

  // provide other scripts a copy of the loading spinner
  mw.libs.QDmodal.getSpinner = function () {
    return $("<span>").addClass("qdmodal-spinner-container").append($spinner.clone());
  };

  // no-op function, kept to prevent breakage in other scripts
  mw.libs.QDmodal.loadTheme = function () {};
  $(function () {
    document.documentElement.style.setProperty("--qdmodal-scrollbar-width", window.innerWidth - document.body.offsetWidth + "px");
  });

  // fire hook for convenience
  mw.hook("dev.qdmodal").fire(mw.libs.QDmodal);
})(jQuery, mediaWiki);
// </nowiki>