Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.

  • Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
  • Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
  • Internet Explorer/Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
  • Opera: Strg+F5
// <nowiki>

// TODO: Ladevorgänge verringern:
//       - Anzahl der Unterkategorien abfragen (wie auf den Kategorieseiten selbst)
//            Eventuell: http://localhost/borpex/api.php?action=query&prop=categoryinfo&titles=Kategorie:Kochzubeh%C3%B6r|Kategorie:L%C3%A4nderk%C3%BCche|Kategorie:Rezepte|Kategorie:Rezeptkategorien%20nach%20Art|Kategorie:Zutaten

mw.loader.load('https://de.wikibooks.org/w/index.php?title=Benutzer:Prog/Tools.js&action=raw&ctype=text/javascript');
mw.loader.load('https://de.wikibooks.org/w/index.php?title=Benutzer:Prog/EditExtensionFunctions.js&action=raw&ctype=text/javascript');

function CreateCategoryWidget(link, category, uniqueID){
	if(document.getElementById(uniqueID)) return $(uniqueID);
	var list = $('<div class="JSCategoryWidgetList">...</div>');
	var box = $('<div class="JSCategoryWidget" id="'+uniqueID+'" />').append(list);

	var categoryList = {};

	var reset = $('<button type="button" id='+uniqueID+'_reset" class="JSCategoryButton JSCategoryButtonReset" />');
	var save  = $('<button type="button" id='+uniqueID+'_save" class="JSCategoryButton JSCategoryButtonSave" />');

	var makeCategoryTree = function(name, callback){
		var CategoryURL = mw.config.get('wgServer')+mw.config.get('wgScriptPath')+
			'/api.php?action=query&format=json&list=categorymembers&cmtype=subcat&cmlimit=500&cmtitle=';

		var ongoing = 0;

		var tree = new MyMap();
		tree.set(name, []);

		var load = function(name, insert, parents, next){
			++ongoing;

			var request = function(json){
				var subcats = json.query.categorymembers;
				for(var i = 0; i < subcats.length; ++i){
					var title = subcats[i].title;
					if(parents.indexOf(title) != -1) continue;

					var sub = new MyMap();
					sub.set(title, []);
					var subparents = parents.slice(0, parents.length);
					subparents.push(title);
					load(title, sub, subparents, null);
					insert.get(name).push(sub);
				}
				if(json['query-continue']){
					load(name, insert, json['query-continue'].categorymembers.cmcontinue);
				}

				--ongoing;
				if(ongoing == 0){
					callback(tree);
				}
			}

			insert.set(name, []);
			var add = next?'&cmcontinue='+next:'';
			jsonRequest(CategoryURL+name+add, request);
		};

		load(name, tree, [name], null);
	};

	var doEnable = function(element, enable){
		if(enable){
			element.prop('disabled', false);
		}else{
			element.attr('disabled', 'disabled');
		}
	}

	var disableSubelements = function(id){
		var new_id = id.slice(0, id.length);
		new_id.push(0);
		while(document.getElementById(uniqueID+'_'+new_id.join('_'))){
			doEnable($('#'+uniqueID+'_'+new_id.join('_')), false);
			disableSubelements(new_id);
			++new_id[new_id.length-1];
		}
	}

	var enableElements = function(id){
		var new_id = id.slice(0, id.length);
		new_id.push(0);
		var childs_unchecked = true;
		while(document.getElementById(uniqueID+'_'+new_id.join('_'))){
			if($('#'+uniqueID+'_'+new_id.join('_')).attr('checked')){
				doEnable($('#'+uniqueID+'_'+new_id.join('_')), true);
				childs_unchecked=false;
			}else if(enableElements(new_id)){
				childs_unchecked=false;
			}
			++new_id[new_id.length-1];
		}
		if(childs_unchecked)doEnable($('#'+uniqueID+'_'+id.join('_')), true);
		return !childs_unchecked;
	}

	var createEntries = function(map){
		var makeElement = function(name, id){
			var click_exec = function(){
				var element = $('#'+uniqueID+'_'+id.join('_'));
				var checked = element.attr('checked');
				if(checked){
					for(var i = 1; i < id.length; ++i){
						var parentNode = $('#'+uniqueID+'_'+id.slice(0, i).join('_'));
						parentNode.prop('checked', false);
						parentNode.trigger('click_exec');
						doEnable(parentNode, false);
					}
					disableSubelements(id);
				}else{
					enableElements([0]);
				}
			};
			var click = function(){
				var element = $('#'+uniqueID+'_'+id.join('_'));
				var checked = element.attr('checked');
				for(var i = 0; i < categoryList[name].length; ++i){
					if(checked){
						categoryList[name][i].attr('checked', 'checked');
					}else{
						categoryList[name][i].prop('checked', false);
					}
					categoryList[name][i].trigger('click_exec');
				}
			};

			var check = $('<input type="checkbox" id="'+uniqueID+'_'+id.join('_')+'" />');
			var label = $('<label for="'+uniqueID+'_'+id.join('_')+'">'+name+'</label>');
			var div = $('<div class="JSCategoryWidgetListEntry" />').append(check, label);
			check.bind('click_exec', click_exec);
			check.bind('click', click);
			if(!$.isArray(categoryList[name])) categoryList[name] = [];
			categoryList[name].push(check);
			return div;
		};

		var makeList = function(elements){
			var makeSubList = function(insert, array, id_postfix){
				if(array.length == 0) return;
				var sublist = $('<div class="JSCategoryWidgetSubList" />');
				for(var i = 0; i < array.length; ++i){
					for(var element in array[i].values){
						var new_id_postfix = id_postfix.slice(0, id_postfix.length);
						new_id_postfix.push(i);
						var div = makeElement(element, new_id_postfix);
						makeSubList(div, array[i].get(element), new_id_postfix);
						sublist.append(div);
					}
				}
				insert.append(sublist);
			};

			var name;
			for(var n in map.values) name = n;
			var top = makeElement(name, [0]);

			makeSubList(top, map.get(name), [0]);
			return top;
		};

		list.html(makeList(map));

		var loadCategories = function(){
			var wpTextbox = $('#wpTextbox1');
			var text = wpTextbox.val();
			for(var entry in categoryList){
				for(var i = 0; i < categoryList[entry].length; ++i){
					categoryList[entry][i].prop('checked', false);
				}
			}
			$('#'+uniqueID+'_0').trigger('click_exec');
			for(var entry in categoryList){
				if(text.search(new RegExp('\\[\\['+maskRegex(entry)+'(\\|[^\\]]*){0,1}\\]\\]'))==-1) continue;
				for(var i = 0; i < categoryList[entry].length; ++i){
					categoryList[entry][i].attr('checked', 'checked');
					categoryList[entry][i].trigger('click_exec');
				}
			}
		};

		var saveCategories = function(){
			var wpTextbox = $('#wpTextbox1');
			var text = wpTextbox.val();
			for(var entry in categoryList){
				text = text.replace(new RegExp('\\[\\['+maskRegex(entry)+'(\\|[^\\]]*){0,1}\\]\\]', 'g'), '');
			}
			for(var entry in categoryList){
				var checked = false;
				for(var i = 0; i < categoryList[entry].length; ++i){
					if(categoryList[entry][i].attr('checked')) checked = true;
				}
				if(checked) text += '[['+entry+'|{{subst:#if:1|{{subst:#titleparts:{{subst:PAGENAME}}|1|-1}}}}]]\n';
			}
			wpTextbox.val(text);
			resortMetadata();
		};

		loadCategories();
		reset.click(loadCategories);
		save.click(saveCategories);
	};

	makeCategoryTree(category, createEntries);

	var headline = $('<div>'+link.text()+'</div>')
		.attr('id', link.attr('id'))
		.attr('class', link.attr('class'))
		.addClass('JSCategoryHeadline');
	if(link.attr('title')) headline.attr('title', link.attr('title'));
	var footer = $('<div class="JSCategoryFooter" />').append(reset, save);
	var content = box.addClass('JSCategoryContent').append(footer);
	var categoryBox = $('<div class="JSCategoryBox" />').append(headline, content);

	link.replaceWith(categoryBox);

	headline.click(function(){content.toggleClass('JSUnvisible');});
}

function MakeCategoryTreeBox(link, name){
	var id = 'category_'+name.replace(/[^a-zA-Z0-9_]/g, '');
	while(document.getElementById(id)) id = id+'_';

	CreateCategoryWidget($('#'+link), name, id);
}

mw.loader.load('https://de.wikibooks.org/w/index.php?title=Benutzer:Prog/Categories.css&action=raw&ctype=text/css', 'text/css');

// </nowiki>