MediaWiki:Gadget-QDmodal.js
Jump to navigation
Jump to search
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 })