MediaWiki:CatNav/code.js

// \nError info: " + data.error.info + " Please make sure that you've entered some text to the category input. Do not add empty lines.");				}			}			req.send;		}

// get members of multiple categories catnav.fn.catMembersMulti = function(catstr, ns, cb) { var cats = catstr.split("|"), completed = 0, allcats = {}; function query { if (completed == cats.length) { // all requests have been made cb(allcats); } else { catnav.fn.catMembers(cats[completed], ns, [], "", function(data) {						allcats[cats[completed]] = data;						completed++;						query;					}); }			}			query; }

// search for members that exist in all specified categories catnav.fn.joinMembers = function(data, isCommonMembers, fn) { var smallestCat, finalList = []; if (isCommonMembers === true) { // mode for the "find-in-categories" list: only list a page if it has all the listed categories smallestCat = data[catnav.fn.getSmallestCat(data)]; // start from smallest category - should take less time for (var i in smallestCat) { var itemLeSmall = smallestCat[i], // current item for check isSharedCommon = true; // if 'isCommonMembers == true', only list pages that are listed in all categories // otherwise, list all pages anyway for (var cat in data) { if (cat != smallestCat && data[cat].indexOf(itemLeSmall) == -1) { // the page 'itemLeSmall' is not categorized in one of these cats isSharedCommon = false; break; }					}					if (isSharedCommon) { finalList.push(itemLeSmall); }				}			} else { // mode for the "unwanted categories" list: list any categorized page that is categorized at least once for (var cat in data) { for (var i in data[cat]) { var currCat = data[cat][i]; if (finalList.indexOf(finalList) == -1) { // although we categorize all pages, we still don't want a category to repeat- it's time consuming and pointless finalList.push(currCat); }					}				}			}			fn(finalList); }

// find the category with the fewest members catnav.fn.getSmallestCat = function(data) { var small = { cat: null, length: Infinity }			for (var cat in data) { if (data[cat].length < small.length) { small.cat = cat; small.length = data[cat].length; }			}			return small.cat; // return name of property with the smallest number of items }

// divide to pages - take a long list of titles, and split them to groups, each with no more than 'n' titles catnav.fn.divideToPages = function(titles) { var result = []; while (titles.length > 0) { result.push(titles.splice(0, catnav.settings.itemsInNavigator * catnav.fn.getNumberOfRows)); }			return result; }

// get number of rows catnav.fn.getNumberOfRows = function { var rows = catnav.settings.rows, specified = $("#catnav-rows").val; if ($.isNumeric(specified) && specified > 0 && specified == Math.round(specified)) { // specified number of rows is a valid positive integer rows = specified; }			return rows; }

/* functions for getting info about pages */

// implement new members catnav.fn.implementNewTitles = function(titles) { // 'titles' is an array of page titles var asPages = catnav.fn.divideToPages(titles); // divide the 'titles' array to a list of smaller groups of titles if (asPages.length > 0) { catnav.data.current = asPages; catnav.fn.error(0, null); // hide error catnav.fn.updatePagesListNav; catnav.fn.gotoPage(0); } else { catnav.fn.error(1, "No pages with all specified categories were found!"); // show error }		}

// update pages' numbers catnav.fn.updatePagesListNav = function { /*var container = $(' '), a; for (var i = 0; i < catnav.data.current.length; i++) { a = $('').html("(" + (Number(i) + 1) + ")"); $(container).append(a); }			$("#catnav-pagenav").html($(container).html).find("a").click(function {				catnav.fn.gotoPage($(this).attr("data-catnav-page"));			});*/ var a,				pagenav = $("#catnav-pagenav"); $(pagenav).html(""); for (var i = 0; i < catnav.data.current.length; i++) { a = $('').html("(" + (Number(i) + 1) + ")"); $(pagenav).append(a); $(a).click(function {					catnav.fn.gotoPage(Number($(this).attr("data-catnav-page")));				}); }		}

// go to page 'n + 1' catnav.fn.gotoPage = function(n) { catnav.data.selectedPage = n;			$("#catnav-pagenav .catnav-pagenav-selected").removeClass("catnav-pagenav-selected"); $("#catnav-pagenav a").eq(n).addClass("catnav-pagenav-selected"); catnav.fn.queryPages(catnav.data.current[n]); }

// get info about pages (url, thumb, etc.) catnav.fn.queryPages = function(titles) { var req = new XMLHttpRequest, missingTitles = []; for (var i in titles) { if (!catnav.data.details.hasOwnProperty(titles[i])) { missingTitles.push(titles[i]); }			}			req.open("get", "/api/v1/Articles/Details?&abstract=0&width=140&height=140&titles=" + encodeURIComponent(missingTitles.join(","))); req.onload = function { catnav.fn.parsePagesQuery(JSON.parse(this.responseText)); catnav.fn.updateMarkup(titles); }			if (missingTitles.length > 0) { req.send; } else { // info about those pages has already loaded catnav.fn.updateMarkup(titles); }		}

// process info about pages from json catnav.fn.parsePagesQuery = function(data) { for (var pageid in data.items) { var a = data.items[pageid], title = decodeURIComponent(a.url.substr(6)).replace(/_/g, " "); // a.title doesn't provide the namespace - easiest method is to do this catnav.data.details[title] = { title: title, url: a.url, img: a.thumbnail }			}		}

// update markup catnav.fn.updateMarkup = function(titles) { var container = $(' '); for (var i in titles) { var a = catnav.data.details[titles[i]], item = $(']/g, function(m) {return "&#" + m.charCodeAt(0) + ";";}) + '">  ');				$(item).find("span").text(a.title);				$(container).append(item);			}			$("#catnav-container").html($(container).html);			window.q = container;		}

// error message catnav.fn.error = function(bool, msg) { // if 'bool' show message, otherwise hide // 'msg' is the new html content $("#catnav-noneerror").html(msg)[bool ? "show" : "hide"] }		/* ================================== *\			# css and markup \* ================================== */

/* css */ mw.util.addCSS(			'#catnav {\n' +				'\twidth: 100%;\n' +				'\tmargin: 0;\n' +				'\tpadding: 0;\n' +			'}\n' +			'#catnav-container {\n' +				'\tdisplay: flex;\n' +				'\tflex-wrap: wrap;\n' +				'\tmargin: 10px auto 20px auto;\n' +				'\tmargin: 10px 50px 20px 50px;\n' +			'}\n' +			'#catnav-container .catnav-item {\n' +				'\tdisplay: inline-block;\n' +				'\twidth: 140px;\n' +				'\theight: 140px;\n' +				'\tmargin: 3px;\n' +				'\tpadding: 2px;\n' +				'\tposition: relative;\n' +				'\toverflow: hidden;\n' +				'\tborder: 2px solid navy;\n' +				'\tborder-radius: 10px;\n' +			'}\n' +			'#catnav-container .catnav-item .catnav-item-label {\n' +				'\tmax-width: 90px;\n' +				'\theight: 18px;\n' +				'\tpadding: 0 4px;\n' +				'\tposition: absolute;\n' +				'\tbottom: 0;\n' +				'\tright: 0;\n' +				'\toverflow: hidden;\n' +				'\tbackground: #006cb0;\n' +				'\tborder-top-left-radius: 7px;\n' + '\tcolor: #fff;\n' + '\tfont-size: 14px;\n' + '\tline-height: 18px;\n' + '}\n' + '#catnav-container img {\n' + '\tborder-radius: 7px;\n' + '}\n' + '#catnav-container .catnav-item-noimage {\n' + '\tborder-color: #c00;\n' + '}\n' + '#catnav-container .catnav-item-noimage .catnav-item-label {\n' + '\tbackground: #c00;\n' + '}\n' + '#catnav-pagenav {\n' + '\tpadding: 3px 7px;\n' + '\ttext-align: center;\n' + '\tfont-size: 18px;\n' + '\tline-height: 18px;\n' + '}\n' + '#catnav-pagenav a:not(.catnav-pagenav-selected) {\n' + '\tcolor: #a6d1ec;\n' + '\ttext-shadow: 1px 1px 0 navy;\n' + '}\n' + '#catnav-pagenav a ~ a {\n' + '\tmargin-left: 10px;\n' + '}\n' + '#catnav-pagenav a.catnav-pagenav-selected {\n' + '\tcolor: black;\n' + '\tcursor: pointer;\n' + '\tfont-weight: bold;\n' + '}\n' + '#catnav textarea {\n' + '\twidth: 100%;\n' + '\twidth: calc(100% - 6px);\n' + '\theight: 60px;\n' + '\tresize: none;\n' + '}\n' + '#catnav table {\n' + '\twidth: 100%;\n' + '\tmargin: 0;\n' + '\tpadding: 0;\n' + '}\n' + '#catnav #catnav-rows {\n' + '\twidth: 30px;\n' + '}\n' + '#catnav th {\n' + '\twidth: 50%;\n' + '}\n' + '#catnav label {\n' + '\tfont-size: smaller;\n' + '}\n' + '#catnav #catnav-noneerror {\n' + '\tcolor: #c00;\n' + '\tfont-weight: bold;\n' + '}'		);

/* markup */ // interface markup $("#mw-content-text").html(			' \n' +				'\t \n' +					'\t\tThe following generator allows you to collect pages from multiple categories. Insert the names of the categories that you\'d like to get pages from to the following text area, in order to retreive pages contain all listed categories (see example):\n' +				'\t \n' +				'\t \n' +				'\t \n' +					'\t\tNumber of rows: \n' +				'\t \n' +				'\t\n' +				'\tlist mainspace only \n' +				'\t \n' +					'\t\tNo pages were found!\n' +				'\t \n' +				'\t \n' +				'\t \n' +				'\t \n' +				'\t \n' +				'\t \n' +				'\t \n' +			' '		); // update titles $("head title, #WikiaPageHeader h1").html("CatNav");

/* ================================== *\			# triggers \* ================================== */		$("#catnav-go").click(function {			var incCats = $("#catnav #catnav-textarea-include").val.replace(/\n/g, "|"), // included categories				disCats = $("#catnav #catnav-textarea-disclude").val.replace(/\n/g, "|"), // discluded categories				nsStr = $("#catnav-ns")[0].checked ? "0" : "";			// get included categories (object: key => categoryname, val => array of listed pages in that category)			catnav.fn.catMembersMulti(incCats, nsStr, function(incData) { // sort the pages into a single array catnav.fn.joinMembers(incData, true, function(incTitles) {					if (disCats.length == 0) {						// no unwated categories requested - update immediately						catnav.fn.implementNewTitles(incTitles);					} else {						// unwated categories requiested - get their categorized pages						catnav.fn.catMembersMulti(disCats, nsStr, function(disData) { // sort the pages into a single array catnav.fn.joinMembers(disData, false, function(disTitles) {								for (var i in disTitles) {									if (incTitles.indexOf(disTitles[i]) > -1) {										// unwanted page detected - remove from 'incTitles'										incTitles.splice(incTitles.indexOf(disTitles[i]), 1)									}								}								catnav.fn.implementNewTitles(incTitles);							}); });					}				});			});		});	} }); //