MediaWiki:Gadget-QDmodal.js

Revision as of 18:24, 3 October 2022 by Jacmob (talk | contribs) (Created page with "→‎<nowiki> QDmodal - flexbox-based modal library CSS located at [[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 () { "use strict"; var version = 20180212; if (mw.libs.QDmodal && mw.libs.QDmodal.version >= version) { return; } var...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
  1 /* <nowiki>
  2     QDmodal - flexbox-based modal library
  3     CSS located at [[MediaWiki:Gadget-QDmodal.css]]
  4 
  5     @author OneTwoThreeFall
  6     @source <https://dev.fandom.com/wiki/QDmodal>
  7     @source <https://dev.fandom.com/wiki/MediaWiki:QDmodal.js>
  8 */
  9 
 10 /*jslint browser, long, this */
 11 /*global jQuery, mediaWiki */
 12 
 13 $(function () {
 14     "use strict";
 15 
 16     var version = 20180212;
 17 
 18     if (mw.libs.QDmodal && mw.libs.QDmodal.version >= version) {
 19         return;
 20     }
 21 
 22     var visibleModals = document.getElementsByClassName("qdmodal");
 23     var $window = $(window);
 24     var $body = $(document.body);
 25     var $closeIcon = $(
 26         "<svg class='qdmodal-close' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'>"
 27           + "<title>Close</title>"
 28           + "<path stroke='currentColor' d='M 3,3 13,13 M 13,3 3,13'/>"
 29         + "</svg>"
 30     );
 31 
 32     function addButton(button) {
 33         var $button = $("<span>");
 34 
 35         if (button.href) {
 36             $button = $("<a>").attr({
 37                 href: button.href,
 38                 target: "_blank"
 39             });
 40         }
 41 
 42         if (typeof button.handler === "function") {
 43             $button.on("click", button.handler);
 44         }
 45 
 46         if (button.attr) {
 47             $button.attr(button.attr);
 48         }
 49 
 50         $button.addClass("qdmodal-button").text(button.text);
 51 
 52         this.$footer.append($button);
 53     }
 54 
 55     //// QDmodal constructor ////
 56 
 57     mw.libs.QDmodal = function (id) {
 58         if (this === mw.libs) {
 59             throw new Error("mw.libs.QDmodal should be called as a constructor.");
 60         }
 61 
 62         var $close = $closeIcon.clone();
 63 
 64         this.$container = $("<div>").addClass("qdmodal-container");
 65         this.$element = $("<div>").addClass("qdmodal");
 66         this.$title = $("<h3>");
 67         this.$content = $("<section>");
 68         this.$footer = $("<footer>");
 69 
 70         this.$container.append(
 71             this.$element.append(
 72                 $("<header>").append(
 73                     this.$title,
 74                     $close
 75                 ),
 76                 this.$content,
 77                 this.$footer
 78             )
 79         );
 80 
 81         this.visible = false;
 82         this.data = null;
 83 
 84         if (typeof id === "string") {
 85             this.$element.attr("id", id);
 86         }
 87 
 88         $close.on("click", this.hide.bind(this));
 89 
 90         // close modal if the background outside the modal is clicked
 91         this.$container.on("click", function (event) {
 92             if (event.target === event.delegateTarget) {
 93                 this.hide();
 94             }
 95         }.bind(this));
 96 
 97         // close modal if the escape key is pressed
 98         $window.on("keydown", function (event) {
 99             if (this.visible && event.which === 27) {
100                 this.hide();
101             }
102         }.bind(this));
103     };
104 
105     mw.libs.QDmodal.prototype.hide = function () {
106         if (this.data && typeof this.data.onHide === "function") {
107             this.data.onHide(this);
108         }
109 
110         this.visible = false;
111         this.data = null;
112         this.$container.detach();
113 
114         if (!visibleModals.length) {
115             $body.removeClass("qdmodal-no-scroll");
116         }
117     };
118 
119     mw.libs.QDmodal.prototype.show = function (data) {
120         if (!data) {
121             return;
122         }
123 
124         this.data = data;
125 
126         this.$content.toggleClass("mw-ajax-loader", Boolean(data.loading));
127 
128         // only set title if one is given, else keep previous title
129         if (data.title) {
130             this.$title.text(data.title);
131         }
132 
133         this.$content.html(data.content || "");
134 
135         this.$footer.empty();
136 
137         if (Array.isArray(data.buttons)) {
138             data.buttons.forEach(addButton.bind(this));
139         }
140 
141         if (data.hook) {
142             mw.hook(data.hook).fire(this);
143         }
144 
145         if (!this.visible) {
146             $body
147                 .addClass("qdmodal-no-scroll")
148                 .append(this.$container);
149             this.visible = true;
150         }
151 
152         if (typeof this.data.onShow === "function") {
153             this.data.onShow(this);
154         }
155     };
156 
157     mw.libs.QDmodal.version = version;
158 
159     // fire hook for convenience
160     mw.hook("dev.qdmodal").fire(mw.libs.QDmodal);
161 
162     //// QDmodal theming ////
163 
164     function initStyles() {
165         var theme = {
166             scrollbarWidth: window.innerWidth - document.body.offsetWidth
167         };
168 
169         var styles = (
170             "body.qdmodal-no-scroll {"
171               // add a margin equivalent to the scrollbar width to
172               // prevent page content moving due to hidden overflow
173               + "margin-right: ${scrollbarWidth}px;"
174             + "}"
175         );
176 
177         // replace placeholders with theme data
178         mw.util.addCSS(styles.replace(/\$\{([^}]+)\}/g, function (ignore, p1) {
179             return theme[p1];
180         }));
181     }
182 
183     mw.loader.using("mediawiki.util").then(initStyles);
184 })