MediaWiki:Gadget-pct.js

Z Wikipedii, wolnej encyklopedii

Uwaga: aby zobaczyć zmiany po opublikowaniu, może zajść potrzeba wyczyszczenia pamięci podręcznej przeglądarki.

  • Firefox / Safari: Przytrzymaj Shift podczas klikania Odśwież bieżącą stronę, lub naciśnij klawisze Ctrl+F5, lub Ctrl+R (⌘-R na komputerze Mac)
  • Google Chrome: Naciśnij Ctrl-Shift-R (⌘-Shift-R na komputerze Mac)
  • Internet Explorer / Edge: Przytrzymaj Ctrl, jednocześnie klikając Odśwież, lub naciśnij klawisze Ctrl+F5
  • Opera: Naciśnij klawisze Ctrl+F5.
$(document).ready(function()
{
	var wgWikibaseItemId = mw.config.get("wgWikibaseItemId");
	if (!wgWikibaseItemId) {
		console.log("no wikidata");
		return;
	}
	
	var wgWikibaseItem = wgWikibaseItemId.slice(1);
 
	console.log("wgWikibaseItem: " + wgWikibaseItem);
 	console.log("wgWikibaseItemId: " + wgWikibaseItemId);
	
	C = {
		cache : {},
		putClaims : function(me, p, q, c) {
			var cache = me.cache[p];
			if (!cache) {
				cache = {};
				me.cache[p] = cache;
			}
			cache[q] = c;
		},
		getClaims : function(me, p, q) {
			return me[p] ? me[p][q] : undefined;
		},
	},

	newNode = function(name)	{
		var me = {};
		me.name = name;
		me.nodes = [];
		me.parent = undefined;
		me.getLevel = function(me) {
			var result = 0;
			var parent = me.parent;
			while (parent) {
				result++;
				parent = parent.parent;
			}
			
			return result;
		};
		me.normalize = function(me) {
			var nodes = me.nodes;
			var i = 0;
			if (!nodes.length) {
				// there are no children
				return 0;
			}
			
			var node = nodes[i++];
			var deep = node.normalize(node);
			while (i < nodes.length) {
				var node2 = nodes[i++];
				var deep2 = node2.normalize(node2);
				if (deep < deep2) {
					// take longer path
					node = node2;
					deep = deep2;
				}
			}
			
			// use single parent
			this.nodes = [node];
			return 1 + deep;
		};
		me.getPath = function(me, accept, useroot) {
			var result = [];
			if (me.nodes[0]) {
				var node = useroot ? me : me.nodes[0];
				while (node) {
					var name = node.name;
					if (!accept(name)) {
						// terminate sequence
						break;
					}
					
					result.push(name);
					node = node.nodes[0];
				}
				
				result.reverse();
			}
			return result;
		};
		me.add = function(me, node) {
			node.parent = me;
			me.nodes.push(node);
		};
		me.remove = function(me, node) {
			var nodes = [];
			for (var i = 0; i < me.nodes.length; i++) {
				var item = me.nodes[i];
				if (item.name !== node.name) {
					nodes.push(item);
				} else {
					node.parent = undefined;
				}
			}
			
			me.nodes = nodes;
		};
		return me;
	},

	generator = function(C, T, wgWikibaseItemId, newNode, item, data) {
		var me = {};
		me.C = C;
		me.T = T;
		me.wgWikibaseItemId = wgWikibaseItemId;
		me.newNode = newNode;
		me.itemToShow = item;
		me.dataField = data;
		me.before = document.getElementById( 'pt-userpage' );
		me.inside = me.before.parentNode;
		me.start = function(me) {
				console.log("start: "+me.wgWikibaseItemId);
				me.state = 0;
				me.pendingRequests = 0;
				me.retrievedRequests = 0;
				me.types = {};
				me.subclasses = {};
				me.loadData(me, wgWikibaseItemId);
			};
		me.completed = function(me) {
				switch(me.state++){
					case 0:
						me.buildTree(me);
						break;
				}
			};
		me.loadData = function(me, q) {
				console.log("loadData: "+q);
				if (me.T.terminators.indexOf(q) >= 0) {
					console.log("loadData: cut searching "+q);
					// cut searching
					return;
				}
				
				me.getclaims(me, q, 'P31', me.P31);
			};
		me.buildTree = function(me) {
				console.log("START BUIDING TREE");
				var dictionary = {};
				var root = me.newNode(me.wgWikibaseItemId);
				dictionary[me.wgWikibaseItemId] = root;
				me.buildingTree(me, dictionary, root);
				console.log("STOP BUIDING TREE");
				var deep = root.normalize(root);
				var accept = function(item) {
					return me.T.terminators.indexOf(item) == -1;
				};
				var path = root.getPath(root, accept, me.T.showLeaf);
				console.log(me.wgWikibaseItemId + ": "+path.join());
				if (path.length) {
					me.loadLinksAndLabels(me, path);
				}
			};
		me.loadLinksAndLabels = function(me, path) {
				var entities = {};
				var requestNames = function(items) {
					console.log("request links and labels for "+items.join());
					var result = $.ajax({
						url: '//www.wikidata.org/w/api.php',
						data: {
							action: 'wbgetentities',
							format: 'json',
							ids: items.join("|"),
							sitefilter: 'plwiki',
							languages: 'pl',
							props: 'sitelinks/urls|labels',
						},
						dataType: 'jsonp',
					});
					result.done(function(data) {
					console.log("retrieved links and labels for "+items.join());
						for(var i = 0; i < items.length; i++) {
							var id = items[i];
							entities[id] = data.entities[id];
						}
					});
					return result;
				};
				var maxChunkSize = 50;
				var chunks = Math.floor((path.length + maxChunkSize - 1) / maxChunkSize);
				var requests = [];
				for (var i = 0; i < chunks; i++) {
					var startIndex = i * maxChunkSize;
					var stopIndex = (startIndex + maxChunkSize) < path.length ? startIndex + maxChunkSize : path.length;
					console.log("chunk "+i+" of "+chunks+", starting at "+startIndex+", next at "+stopIndex);
					var chunkData = path.slice(startIndex, stopIndex);
					requests.push(requestNames(chunkData));
				}
				$.when.apply(me, requests).done(function(){
					console.log("retrieved ALL links and labels");
					var data = {};
					data.entities = entities;
					me.showTree(me, path, data);
				});
			};
		me.showTree = function(me, path, data) {
				var builder = [];
				builder.push("<ul>");
				for(var i = 0; i < path.length; i++) {
					var q = data.entities[path[i]];
					var site = q.sitelinks ? q.sitelinks.plwiki : undefined;
					var label = q.labels && q.labels.pl ? q.labels.pl.value : site ? site.title : q.id;
					//console.log(site ? '* [['+site+'|'+label+']]' : '* '+label);
					var text = site ? '<li><a href="'+site.url+'" title="'+site.title+'">'+label+'</a></li>' : '<li>'+label+'</li>';
					console.log(text);
					builder.push(text);
				}
				builder.push("</ul>");
				if (me.dataField) {
					var result = builder.join("");
					me.dataField.html(result);
					if (me.itemToShow) {
						me.itemToShow.show("slow");
					}
				}
			};
		me.buildingTree = function(me, nodes, node) {
				var subclasses = me.subclasses[node.name];
				if (subclasses) {
					for(var i = 0; i < subclasses.length; i++) {
						var subclass = subclasses[i];
						if (me.findParent(me, node, subclass)) {
							// there is cycle in the graph
							continue;
						}
						
						var available = nodes[subclass];
						if (available) {
							var alevel = available.getLevel(available);
							var nlevel = node.getLevel(node);
							if (alevel <= nlevel) {
								// the available node level path is shorter
								// move it to this location
								available.parent.remove(available.parent, available);
								node.add(node, available);
							} else {
								// the available node level path is same size or longer
								// as this is further class, it is ignored
							}
						} else {
							var newnode = me.newNode(subclass);
							nodes[subclass] = newnode;
							node.add(node, newnode);
							me.buildingTree(me, nodes, newnode);
						}
					}
				}
			};
		me.findParent = function(me, node, name) {
				while (node) {
					if (node.name === name) {
						return node;
					}
					
					node = node.parent;
				}
				
				return undefined;
			};
		me.getclaims = function(me, q, p, f) {
				console.log("getclaims: "+q+"."+p);
				var C = me.C;
				var c = C.getClaims(C, p, q);
				if (c) {
					console.log("get "+q+"."+p+" from cache");
					f(me, q,c);
				} else {
					me.pendingRequests++;
					console.log("ajax #"+me.pendingRequests+" "+q+"."+p);
					$.ajax({
						url: '//www.wikidata.org/w/api.php',
						data: {
							action: 'wbgetclaims',
							format: 'json',
							entity: q,
							property: p,
						},
						dataType: 'jsonp',
					}).done(function(data){
						console.log("retrieved "+q+"."+p);
						C.putClaims(C, p, q, data);
						f(me, q, data);
						me.pendingRequests--;
						if (me.pendingRequests === 0)
						{
							console.log("retrieved last completed???"+q+"."+p);
							me.completed(me);
						}
					});
				}
			};
		me.P31 = function(me, q, data) {
				console.log("P31: "+q);
				if (!me.types[q]) {
					var ids = me.parseItemClaims(me, data.claims.P31, function(me, id) {return me.T.acceptableTypes.indexOf(id) >= 0; });
					if (ids) {
						me.types[q] = ids;
						for(var i=0; i < me.T.parentSources.length; i++) {
							var p = me.T.parentSources[i];
							me.getclaims(me, q, p, me.LoadParentItems);
						}
					}
				}
			};
		me.LoadParentItems = function(me, q, data) {
				console.log("LoadParentItems: "+q);
				var accept = function(){return true;};
				for(var i=0; i < me.T.parentSources.length; i++) {
					var p = me.T.parentSources[i];
					var ids = me.parseItemClaims(me, data.claims[p], accept);
					if (ids) {
						me.subclasses[q] = ids;
						for(var j=0; j < ids.length; j++) {
							me.loadData(me, ids[j]);
						}
					}
				}
			};
		me.parseItemClaims = function(me, items, check) {
				console.log("parseItemClaims");
				if (!items || !items.length) {
					console.log("parseItemClaims: no items");
					return [];
				}
				
				var ids = [];
				var j = 0;
				for(var i=0; i < items.length; i++) {
					var id = 'Q' + items[i].mainsnak.datavalue.value['numeric-id'];
					console.log("parseItemClaims: id = "+id);
					if (check(me, id)) {
						ids[j++] = id;
					}
				}
				
				return ids.length ? ids : undefined;
			};
		return me;
	};
	
	itemsGenerator = function(query, item, data) {
		var me = {};
		me.query = query;
		me.itemToShow = item;
		me.dataField = data;
		me.start = function(me) {
				console.log("start: "+me.query);
				$.ajax({
					url: '//wdq.wmflabs.org/api',
					data: {
						q: me.query,
					},
					dataType: 'jsonp',
				}).done(function(data){
					console.log("retrieved "+query);
					if ((data.status.error == "OK") && (data.status.items > 0) && data.items.length) {
						var path = [];
						for(var i=0; i < data.items.length; i++) {
							path[i] = 'Q' + data.items[i];
						}
						me.loadLinksAndLabels(me, path);
					}
				});
			};
		me.loadLinksAndLabels = function(me, path) {
				var entities = {};
				var requestNames = function(items) {
					console.log("request links and labels for "+items.join());
					var result = $.ajax({
						url: '//www.wikidata.org/w/api.php',
						data: {
							action: 'wbgetentities',
							format: 'json',
							ids: items.join("|"),
							sitefilter: 'plwiki',
							languages: 'pl',
							props: 'sitelinks/urls|labels',
						},
						dataType: 'jsonp',
					});
					result.done(function(data) {
					console.log("retrieved links and labels for "+items.join());
						for(var i = 0; i < items.length; i++) {
							var id = items[i];
							entities[id] = data.entities[id];
						}
					});
					return result;
				};
				var maxChunkSize = 50;
				var chunks = Math.floor((path.length + maxChunkSize - 1) / maxChunkSize);
				var requests = [];
				for (var i = 0; i < chunks; i++) {
					var startIndex = i * maxChunkSize;
					var stopIndex = (startIndex + maxChunkSize) < path.length ? startIndex + maxChunkSize : path.length;
					console.log("chunk "+i+" of "+chunks+", starting at "+startIndex+", next at "+stopIndex);
					var chunkData = path.slice(startIndex, stopIndex);
					requests.push(requestNames(chunkData));
				}
				$.when.apply(me, requests).done(function(){
					console.log("retrieved ALL links and labels");
					var data = {};
					data.entities = entities;
					me.showList(me, path, data);
				});
			};
		me.showList = function(me, path, data) {
				var builder = [];
				builder.push("<ul>");
				for(var i = 0; i < path.length; i++) {
					var q = data.entities[path[i]];
					var site = q.sitelinks ? q.sitelinks.plwiki : undefined;
					var label = q.labels && q.labels.pl ? q.labels.pl.value : site ? site.title : q.id;
					//console.log(site ? '* [['+site+'|'+label+']]' : '* '+label);
					var text = site ? '<li><a href="'+site.url+'" title="'+site.title+'">'+label+'</a></li>' : '<li>'+label+'</li>';
					console.log(text);
					builder.push(text);
				}
				builder.push("</ul>");
				if (me.dataField) {
					var result = builder.join("");
					me.dataField.html(result);
					if (me.itemToShow) {
						me.itemToShow.show("slow");
					}
				}
			};
		return me;
	};

	$("tr.wikidata-parent-tree-item").each(function(index, item){
		console.log("drabinka "+index+" start");
		var data = $("td.wikidata-parent-tree-data", item);
		if (data.length === 1) {
			try {
				console.log("drabinka "+index+" parse");
				var params = JSON.parse(data.html());
				if (params) {
					console.log("drabinka "+index+" process");
					var me = generator(C, params, wgWikibaseItemId, newNode, $(item), data);
					me.start(me);
				}
			} catch (e) {
				console.log("drabinka "+index+" ERROR");
				$(item).css("display", "none");
				console.log(e);
			}
		}
	});

	$("tr.wdq-items").each(function(index, item){
		console.log("wdq "+index+" start");
		var data = $("td.wdq-query", item);
		if (data.length === 1) {
			try {
				console.log("wdq "+index+" parse");
				var params = JSON.parse(data.html());
				var query = params.query.replace(/%wgWikibaseItem%/g, wgWikibaseItem);
				if (query) {
					console.log("wdq "+index+" process");
					var me = itemsGenerator(query, $(item), data);
					me.start(me);
				}
			} catch (e) {
				console.log("wdq "+index+" ERROR");
				$(item).css("display", "none");
				console.log(e);
			}
		}
	});
	
});