// <nowiki>
(function (mw, $) {
function coyoneda(f, t) {
return function() {
return f(t);
};
}
//recursive implementation, needs to be trampolined for actual use. Also, value should be deferred.
function startLazyIterator(initiator, producer, hasNext) {
return initiator().then(function(t) {
return {
value: t,
hasNext: hasNext(t),
next: function() {
if (hasNext(t)) {
return startLazyIterator(coyoneda(producer, t), producer,
hasNext);
} else {
var reject = $.Deferred();
reject.reject();
return reject.promise();
}
}
};
});
}
//recursive implementation, needs to be trampolined for actual use. Also, value should be deferred.
function startEagerIterator(initiator, producer, hasNext) {
return initiator().then(function(t) {
var res;
if (hasNext(t)) {
res = startEagerIterator(coyoneda(producer, t), producer, hasNext);
} else {
var reject = $.Deferred();
reject.reject();
res = reject.promise();
}
return {
value: t,
hasNext: hasNext(t),
next: function() {
return res;
}
};
});
}
function map_iter(it, f) {
var newdef = $.Deferred();
var result = {
value: f(it.value),
hasNext: it.hasNext,
next: function() {
if (it.hasNext) {
it.next().done(function(t) {
return newdef.resolve(t);
});
} else {
newdef.reject();
}
return newdef.promise();
}
};
return result;
}
function flatmap_array(arr, f) {
return [].concat.apply(arr.map(f));
}
function flatmap_deferred(prom, f) {
var def = $.Deferred();
prom.then(f).done(function(pp) {
return pp.done;
});
return def.promise();
}
function tokensource(names) {
var url = "/w/api.php?action=query&meta=tokens&format=json&continue=&type=" +
names.join("|");
var req = $.getJSON(url);
return startLazyIterator(function() {
return req;
}, function(x) {
return tokensource(names);
}, function(x) {
return true;
});
}
function mergeprops(left, right) {
var result = {};
var leftname;
var rightname;
for (leftname in left) {
result[leftname] = left[leftname];
}
for (rightname in right) {
result[rightname] = right[rightname];
}
return result;
}
function post_query_continue(baseurl, data, init_iter) {
var baseprops = {
type: "POST",
headers: {
'Api-User-Agent': 'Martijn/1.0'
}
};
function getreq(params) {
var postdata = mergeprops(data, {
"continue": "",
format: "json"
});
postdata = mergeprops(postdata, params);
var querysettings = mergeprops(baseprops, {
data: postdata
});
var req = $.ajax(baseurl, querysettings);
console.debug("requesting", req);
return req;
}
return init_iter(coyoneda(getreq, baseprops), function(res) {
var continue_part = res["continue"];
var req = getreq(continue_part);
return req;
}, function(res) {
return ("continue" in res);
});
}
function get_tokens(names) {
var url = "/w/api.php?action=query&meta=tokens&format=json&type=" + names.join("|");
var req = $.getJSON(url);
return req.then(function(res) {
return res.query.tokens;
});
}
function watchWithTemplates(title) {
var baseurl = "/w/api.php";
var baseparams = {
action: "watch",
generator: "templates",
titles: title
};
var tokens_p = get_tokens(["watch"]);
var params_p = tokens_p.then(function(tok) {
return mergeprops(baseparams, {token: tok.watchtoken});
});
return flatmap_deferred(params_p, function(params) {
return post_query_continue(baseurl, params, startEagerIterator);
});
}
function foreach_iterator(it, f){
f(it.value);
if(it.hasNext){
it.next().done(function(n) {foreach_iterator(n, f);});
}
}
function foldl_iterator(it, init, accumulator){
if (it.hasNext){
var next = accumulator(init, it.value);
return flatmap_deferred(it.next(), function (nit) {
foldl_iterator(nit, next, accumulator);
});
} else {
var def = $.Deferred();
def.resolve(init);
return def.promise();
}
}
function id(x){ return x; }
function left(a, b){ return a;}
function right(a, b){ return b;}
function watch_transclusions_of_current() {
var title = "";
if (mw.config.values.wgNamespaceNumber === 0){
title = mw.config.values.wgTitle;
} else {
title = mw.config.values.wgCanonicalNamespace + ":" + mw.config.values.wgTitle;
}
return watchWithTemplates(title);
}
var portletname = "p-views";
var portlettextdone ="{{★}}";
var portlettextnotdone = "{{☆}}";
//var portlettextdone = "{{}}";
//var portlettextnotdone = "{{W}}";
var portletid = "p-watchtemplates";
var portlettooltip = "watch all pages transcluded on this page";
//seems this should be a mw.hooks event, but the documentation is unclear
//on which events are available, and which one is "right"
$( function(){
if ((mw.config.values.wgNamespaceNumber % 2) === 0) {
var portletlink = mw.util.addPortletLink(portletname, "#", portlettextnotdone, portletid, portlettooltip);
$( portletlink ).click( function ( e ) {
e.preventDefault();
var it_p = watch_transclusions_of_current();
it_p.done(function(it){
foldl_iterator(it, null, left).done(function(n){
$( portletLink ).text(portlettextdone);
});
});
});
}
});
}(window.mw, window.$));
// </nowiki>