diff --git a/tfdclerk.js b/tfdclerk.js
index 2d066aa..cbfeeb5 100644
--- a/tfdclerk.js
+++ b/tfdclerk.js
@@ -28,289 +28,353 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
-mw.loader.using(["mediawiki.api", "mediawiki.ui", "jquery.ui.core"], function() {
- if (mw.config.get("wgAction") != "view" ||
- mw.config.get("wgIsProbablyEditable") != true ||
- mw.config.get("wgRevisionId") != mw.config.get("wgCurRevisionId") ||
- mw.config.get("wgNamespaceNumber") != 4 || (
- mw.config.get("wgTitle") != "Templates for discussion" &&
- mw.config.get("wgTitle").indexOf("Templates for discussion/Log/2") != 0))
+var dependencies = [
+ "mediawiki.api",
+ "mediawiki.ui",
+ "mediawiki.util",
+ "jquery.ui.core"
+];
+
+var is_tfd_page = function() {
+ return mw.config.get("wgAction") == "view" &&
+ mw.config.get("wgIsProbablyEditable") == true &&
+ mw.config.get("wgRevisionId") == mw.config.get("wgCurRevisionId") &&
+ mw.config.get("wgNamespaceNumber") == 4 && (
+ mw.config.get("wgTitle") == "Templates for discussion" ||
+ mw.config.get("wgTitle").indexOf("Templates for discussion/Log/2") == 0);
+}
+
+if (is_tfd_page()) {
+ mw.loader.using(dependencies, function() {
+
+/* Main script starts here */
+
+TFDClerk = {
+ api: new mw.Api(),
+ sysop: $.inArray("sysop", mw.config.get("wgUserGroups")) >= 0,
+ // TODO: access time?
+ _counter: 1,
+ _wikitext_cache: {},
+ _wikitext_cache_extra: {}
+};
+
+TFDClerk._get_today = function() {
+ return new Date().toISOString().slice(0, 10);
+};
+
+TFDClerk._guard = function(head) {
+ if (head.data("guard"))
+ return false;
+ head.data("guard", true);
+ return true;
+};
+
+TFDClerk._unguard = function(head) {
+ head.removeData("guard");
+};
+
+TFDClerk._get_section_number = function(head) {
+ var url = head.find(".mw-editsection a").first().prop("href");
+ var match = url.match(/section=(.*?)(\&|$)/);
+ return match ? match[1] : null;
+};
+
+TFDClerk._error = function(box, msg, extra) {
+ var elem = $("", {
+ text: "Error: " + (extra ? msg + ": " : msg),
+ style: "color: #A00;"
+ });
+ if (extra)
+ elem.append($("", {
+ text: extra,
+ style: "font-family: monospace;"
+ }));
+ elem.insertAfter(box.find("h5"));
+ box.find(".tfdclerk-submit").prop("disabled", true);
+};
+
+TFDClerk._with_section_content = function(head, box, callback) {
+ var section = TFDClerk._get_section_number(head);
+ if (section === null)
+ return TFDClerk._error(box, "couldn't get section number");
+
+ var cache = TFDClerk._wikitext_cache,
+ extra_cache = TFDClerk._wikitext_cache_extra;
+ if (section in cache) {
+ if (cache[section] === null) {
+ if (section in extra_cache)
+ extra_cache[section].push(callback);
+ else
+ extra_cache[section] = [callback];
+ } else
+ callback(cache[section]);
return;
+ }
+ cache[section] = null;
- TFDClerk = {
- api: new mw.Api(),
- sysop: $.inArray("sysop", mw.config.get("wgUserGroups")) >= 0,
- counter: 1
- };
-
- TFDClerk._get_today = function() {
- return new Date().toISOString().slice(0, 10);
- };
-
- TFDClerk._guard = function(head) {
- if (head.data("guard"))
- return false;
- head.data("guard", true);
- return true;
- };
-
- TFDClerk._unguard = function(head) {
- head.removeData("guard");
- };
-
- TFDClerk._get_section = function(head) {
- var url = head.find(".mw-editsection a").first().prop("href");
- var match = url.match(/section=(.*?)(\&|$)/);
- return match ? match[1] : null;
- };
-
- TFDClerk._error = function(box, msg, extra) {
- var elem = $("", {
- text: "Error: " + (extra ? msg + ": " : msg),
- style: "color: #A00;"
- });
- if (extra)
- elem.append($("", {
- text: extra,
- style: "font-family: monospace;"
- }));
- elem.insertAfter(box.find("h5"));
- $("#" + box.prop("id") + "-submit").prop("disabled", true);
- };
-
- TFDClerk._remove_option_box = function(box) {
- var head = box.prev("h4");
- box.remove();
- TFDClerk._unguard(head);
- };
-
- TFDClerk._add_option_box = function(head, verb, title, callback, options) {
- var box_id = "tfdclerk-" + verb + "-box-" + TFDClerk.counter++;
- var box = $("
", {
- id: box_id,
- addClass: "tfdclerk-" + verb + "-box"
- })
- .css("border", "1px solid #AAA")
- .css("color", "#000")
- .css("background-color", "#F9F9F9")
- .css("margin", "0.5em 0")
- .css("padding", "1em")
- .append($("", {
- text: title,
- style: "margin: 0; padding: 0 0 0.25em 0;"
- }));
- options(box, head, box_id + "-");
- box.append($("", {
- id: box_id + "-submit",
- text: verb.charAt(0).toUpperCase() + verb.slice(1),
- addClass: "mw-ui-button mw-ui-progressive",
- style: "margin-right: 0.5em;",
- click: function() {
- callback(head, box);
- }
- }))
- .append($("", {
- id: box_id + "-cancel",
- text: "Cancel",
- addClass: "mw-ui-button",
- click: function() {
- TFDClerk._remove_option_box(box);
- }
- }))
- .insertAfter(head);
- };
-
- TFDClerk._add_option_table = function(box, options) {
- var table = $("", {style: "border-spacing: 0;"});
- $.each(options, function(i, opt) {
- table.append($("
")
- .append(
- $(" | ", {
- style: "padding-bottom: 0.75em; padding-right: 0.5em;"
- }).append(opt[0]))
- .append(
- $(" | ", {
- style: "padding-bottom: 0.75em;"
- }).append(opt[1]))
- );
- });
- box.append(table);
- };
-
- TFDClerk._do_close = function(head, box) {
- // TODO
- TFDClerk._remove_option_box(box);
- };
-
- TFDClerk._do_relist = function(head, box) {
- // TODO
- TFDClerk._remove_option_box(box);
- };
-
- TFDClerk._is_merge = function(head) {
- return head.nextUntil("h4").filter("p").first().find("b")
- .text() == "Propose merging";
- };
-
- TFDClerk._build_close_results = function(head) {
- if (TFDClerk._is_merge(head))
- var choices = ["Merge", "Do not merge", "No consensus"];
- else
- var choices = ["Delete", "Keep", "Redirect", "No consensus"];
-
- var elems = $("");
- $("").append($("", {
- name: "result-speedy",
- type: "checkbox",
- value: "true"
- })).append($("", {
- text: "Speedy",
- style: "margin: 0 1.25em 0 0.25em;"
- })).appendTo(elems);
- $.each(choices, function(i, choice) {
- $("").append($("", {
- name: "result",
- type: "radio",
- value: choice
- })).append($("", {
- text: choice,
- style: "margin: 0 1.25em 0 0.25em;"
- })).appendTo(elems);
- });
+ TFDClerk.api.get({
+ action: "query",
+ prop: "revisions",
+ rvprop: "content",
+ rvsection: section,
+ revids: mw.config.get("wgRevisionId")
+ }).done(function(data) {
+ var pageid = mw.config.get("wgArticleId");
+ var content = data.query.pages[pageid].revisions[0]["*"];
+ cache[section] = content;
+ callback(content);
+ if (section in extra_cache) {
+ for (var i in extra_cache[section])
+ extra_cache[section][i](content);
+ }
+ }).fail(function(err) {
+ TFDClerk._error(box, "API query failure", err);
+ }).always(function() {
+ if (section in extra_cache)
+ delete extra_cache[section];
+ });
+};
+
+TFDClerk._remove_option_box = function(box) {
+ var head = box.prev("h4");
+ box.remove();
+ TFDClerk._unguard(head);
+};
+
+TFDClerk._add_option_box = function(head, verb, title, callback, options) {
+ var box_id = "tfdclerk-" + verb + "-box-" + TFDClerk._counter++;
+ var box = $("", {
+ id: box_id,
+ addClass: "tfdclerk-" + verb + "-box"
+ })
+ .css("border", "1px solid #AAA")
+ .css("color", "#000")
+ .css("background-color", "#F9F9F9")
+ .css("margin", "0.5em 0")
+ .css("padding", "1em")
+ .append($("", {
+ text: title,
+ style: "margin: 0; padding: 0 0 0.25em 0;"
+ }));
+ options(box, head, box_id + "-");
+ box.append($("", {
+ id: box_id + "-submit",
+ text: verb.charAt(0).toUpperCase() + verb.slice(1),
+ addClass: "tfdclerk-submit mw-ui-button mw-ui-progressive",
+ style: "margin-right: 0.5em;",
+ click: function() {
+ callback(head, box);
+ }
+ }))
+ .append($("", {
+ id: box_id + "-cancel",
+ text: "Cancel",
+ addClass: "mw-ui-button",
+ click: function() {
+ TFDClerk._remove_option_box(box);
+ }
+ }))
+ .insertAfter(head);
+};
+
+TFDClerk._add_option_table = function(box, options) {
+ var table = $("", {style: "border-spacing: 0;"});
+ $.each(options, function(i, opt) {
+ table.append($("
")
+ .append(
+ $(" | ", {
+ style: "padding-bottom: 0.75em; padding-right: 0.5em;"
+ }).append(opt[0]))
+ .append(
+ $(" | ", {
+ style: "padding-bottom: 0.75em;"
+ }).append(opt[1]))
+ );
+ });
+ box.append(table);
+};
+
+TFDClerk._do_close = function(head, box) {
+ // TODO
+ TFDClerk._remove_option_box(box);
+};
+
+TFDClerk._do_relist = function(head, box) {
+ // TODO
+ TFDClerk._remove_option_box(box);
+};
+
+TFDClerk._is_merge = function(head) {
+ return head.nextUntil("h4").filter("p").first().find("b")
+ .text() == "Propose merging";
+};
+
+TFDClerk._build_close_results = function(head) {
+ if (TFDClerk._is_merge(head))
+ var choices = ["Merge", "Do not merge", "No consensus"];
+ else
+ var choices = ["Delete", "Keep", "Redirect", "No consensus"];
+
+ var elems = $("");
+ $("").append($("", {
+ name: "result-speedy",
+ type: "checkbox",
+ value: "true"
+ })).append($("", {
+ text: "Speedy",
+ style: "margin: 0 1.25em 0 0.25em;"
+ })).appendTo(elems);
+ $.each(choices, function(i, choice) {
$("").append($("", {
name: "result",
type: "radio",
- value: "Other"
+ value: choice
})).append($("", {
- text: "Other: ",
- style: "margin: 0 0.25em;"
- })).append($("", {
- name: "result-other",
- type: "text"
+ text: choice,
+ style: "margin: 0 1.25em 0 0.25em;"
})).appendTo(elems);
- return elems;
- };
-
- TFDClerk._add_close_actions = function(box, head, prefix) { // prefix?
- var section = TFDClerk._get_section(head);
- if (section === null)
- return TFDClerk._error(box, "couldn't get section number");
-
- TFDClerk.api.get({
- action: "query",
- prop: "revisions",
- rvprop: "content",
- rvsection: section,
- revids: mw.config.get("wgRevisionId")
- }).done(function(data) {
- // TODO
- console.log(data);
- }).fail(function(err) {
- TFDClerk._error(box, "API query failure", err);
+ });
+ $("").append($("", {
+ name: "result",
+ type: "radio",
+ value: "Other"
+ })).append($("", {
+ text: "Other: ",
+ style: "margin: 0 0.25em;"
+ })).append($("", {
+ name: "result-other",
+ type: "text"
+ })).appendTo(elems);
+ return elems;
+};
+
+TFDClerk._add_close_actions = function(box, head) {
+ TFDClerk._with_section_content(head, box, function(content) {
+ var regex = /\{\{tfd links\|(.*?)(\||\}\})/gi,
+ match = regex.exec(content);
+ if (match === null)
+ return TFDClerk._error(box, "no templates found in section");
+
+ var actions = box.find(".tfdclerk-actions"),
+ list = $("", {style: "margin: 0 0 0 1em;"});
+ do {
+ var page = "Template:" + match[1];
+ $("").append($("", {
+ href: mw.util.getUrl(page),
+ title: page,
+ text: page
+ })).appendTo(list);
+ } while ((match = regex.exec(content)) !== null);
+ actions.empty();
+ actions.append(list);
+ });
+};
+
+TFDClerk.close = function(head) {
+ if (!TFDClerk._guard(head))
+ return;
+
+ TFDClerk._add_option_box(
+ head, "close", "Closing discussion", TFDClerk._do_close,
+ function(box, head, prefix) {
+ TFDClerk._add_option_table(box, [
+ [
+ $("", {text: "Result:"}),
+ TFDClerk._build_close_results(head)
+ ],
+ [
+ $("", {
+ for: prefix + "comments",
+ text: "Comments:"
+ }),
+ $("", {
+ id: prefix + "comments",
+ name: "comments",
+ rows: 2,
+ cols: 60,
+ placeholder: "Optional. Do not sign."
+ })
+ ],
+ [
+ $("", {text: "Actions:"}),
+ $("", {addClass: "tfdclerk-actions"}).append(
+ $("", {
+ text: "Fetching...",
+ style: "font-style: italic; color: #777;"
+ })),
+ ]
+ ]);
+ TFDClerk._add_close_actions(box, head);
});
- };
+};
- TFDClerk.close = function(head) {
- if (!TFDClerk._guard(head))
- return;
+TFDClerk.relist = function(head) {
+ if (!TFDClerk._guard(head))
+ return;
+
+ TFDClerk._add_option_box(
+ head, "relist", "Relisting discussion", TFDClerk._do_relist,
+ function(box, head, prefix) {
+ TFDClerk._add_option_table(box, [
+ [
+ $("", {
+ for: prefix + "date",
+ text: "New date:"
+ }),
+ $("", {
+ id: prefix + "date",
+ name: "date",
+ type: "date",
+ value: TFDClerk._get_today()
+ })
+ ],
+ [
+ $("", {
+ for: prefix + "comments",
+ text: "Comments:"
+ }),
+ $("", {
+ id: prefix + "comments",
+ name: "comments",
+ rows: 2,
+ cols: 60,
+ placeholder: "Optional. Do not sign."
+ })
+ ]
+ ]);
+ });
+};
+
+TFDClerk._build_hook = function(head, verb, callback) {
+ return $("", {style: "margin-left: 1em;"})
+ .append($("", {addClass: "mw-editsection-bracket", text: "["}))
+ .append($("", {
+ href: "#",
+ text: verb,
+ title: "tfdclerk: " + verb + " discussion",
+ click: function() {
+ callback($(head));
+ return false;
+ }
+ }))
+ .append($("", {addClass: "mw-editsection-bracket", text: "]"}));
+};
- TFDClerk._add_option_box(
- head, "close", "Closing discussion", TFDClerk._do_close,
- function(box, head, prefix) {
- TFDClerk._add_option_table(box, [
- [
- $("", {text: "Result:"}),
- TFDClerk._build_close_results(head)
- ],
- [
- $("", {
- for: prefix + "comments",
- text: "Comments:"
- }),
- $("", {
- id: prefix + "comments",
- name: "comments",
- rows: 2,
- cols: 60,
- placeholder: "Optional. Do not sign."
- })
- ],
- [
- $("", {text: "Actions:"}),
- $("", {id: prefix + "actions"}).append(
- $("", {
- text: "Fetching...",
- style: "font-style: italic; color: #777;"
- })),
- ]
- ]);
- TFDClerk._add_close_actions(box, head, prefix);
- });
- };
-
- TFDClerk.relist = function(head) {
- if (!TFDClerk._guard(head))
+TFDClerk.install = function() {
+ $("h4").each(function(i, head) {
+ if ($(head).next().hasClass("tfd-closed"))
return;
- TFDClerk._add_option_box(
- head, "relist", "Relisting discussion", TFDClerk._do_relist,
- function(box, head, prefix) {
- TFDClerk._add_option_table(box, [
- [
- $("", {
- for: prefix + "date",
- text: "New date:"
- }),
- $("", {
- id: prefix + "date",
- name: "date",
- type: "date",
- value: TFDClerk._get_today()
- })
- ],
- [
- $("", {
- for: prefix + "comments",
- text: "Comments:"
- }),
- $("", {
- id: prefix + "comments",
- name: "comments",
- rows: 2,
- cols: 60,
- placeholder: "Optional. Do not sign."
- })
- ]
- ]);
- });
- };
-
- TFDClerk._build_hook = function(head, verb, callback) {
- return $("", {style: "margin-left: 1em;"})
- .append($("", {addClass: "mw-editsection-bracket", text: "["}))
- .append($("", {
- href: "#",
- text: verb,
- title: "tfdclerk: " + verb + " discussion",
- click: function() {
- callback($(head));
- return false;
- }
- }))
- .append($("", {addClass: "mw-editsection-bracket", text: "]"}));
- };
-
- TFDClerk.install = function() {
- $("h4").each(function(i, head) {
- if ($(head).next().hasClass("tfd-closed"))
- return;
-
- $("", {addClass: "tfdclerk-hooks"})
- .append(TFDClerk._build_hook(head, "close", TFDClerk.close))
- .append(TFDClerk._build_hook(head, "relist", TFDClerk.relist))
- .appendTo($(head).find(".mw-editsection"));
- });
- };
+ $("", {addClass: "tfdclerk-hooks"})
+ .append(TFDClerk._build_hook(head, "close", TFDClerk.close))
+ .append(TFDClerk._build_hook(head, "relist", TFDClerk.relist))
+ .appendTo($(head).find(".mw-editsection"));
+ });
+};
+
+$(TFDClerk.install);
+
+/* Main script ends here */
- $(TFDClerk.install);
-});
+ });
+}