User:Jts1882/taxonomybrowser.js

//- //      Taxonomy browser script // var nLevels = 3;               // this determines how many levels are show in each iteration var nListLevels = 3; var nInteractiveLevels = 1; var debug = false; var nRun = 1; var ntt = false; //true;                // enable create new taxonomy template tool (development only) var bullets = "nobullets";     // suppress the bullets and place expand/collapse symbols to left: nobullets|bullets var genus = "";

/** * This script adds a tool and dialog using code modified from the following tutorial script * * Tutorial script: QuickRC ("Quick Recent Changes") * * A tutorial user script which adds a "Quick changelog" link to the page skin's * toolbox, and when clicked it pops up a dialog with up to 25 recent edits. * * Demonstrates: * - Use of the API * - Use of jQuery * - Use of ResourceLoader and some of the default modules that come with it * - Use of localization * * (Be bold and improve it!) * * Authors: * Erik Moeller, 2011, public domain * Brion Vibber, 2012, public domain */

messages = { 'en': { 'taxonomy-title': 'Taxonomy template browser', 'taxonomy-greeting': 'Welcome, $1!', 'taxonomy-intro': 'The following templates are children of this taxon taxonomy template:', 'taxonomy-link': 'Taxonomy browser', 'taxonomy-link2': 'Taxonomy (test)', 'taxonomy-tooltip': 'Get children for particular taxonomy template', 'ntt-link': 'Create new template', 'ntt-tooltip': 'Create new taxonomy template' } };

mw.messages.set(messages.en); var lang = mw.config.get('wgUserLanguage'); if (lang && lang != 'en' && lang in messages) { mw.messages.set(messages[lang]); }

// Import the jQuery dialog plugin before starting the rest of this script mw.loader.using(['jquery.ui'], function {

function openTaxonBrowserDialog( taxon ) { taxon = getDefaultTaxonName(taxon); var $dialog = $( ' ' ) .html( showTaxonomyBrowserForm(taxon)		//	+ ' Tree will appear here '		//	+ showNewTaxonomyTemplateForm(taxon)			) .dialog({				autoOpen: true,				title: mw.message('taxonomy-title').plain,				width: '60%',				modal: true			}); }   function openCreateTaxonomyTemplateDialog( taxon ) { taxon = getDefaultTaxonName(taxon); var $dialog = $( ' ' ) .html( showNewTaxonomyTemplateForm(taxon) 	) .dialog({				autoOpen: true,				title: mw.message('taxonomy-title').plain,				width: '50%',				modal: true			}); }   function renderTaxonomyDialog( output ) { var $dialog = $( ' ' ) .html(				' ' + mw.message('taxonomy-greeting', mw.user.getName).escaped + ' ' 				+ mw.message('taxonomy-intro').escaped 				+ output			) .dialog({				autoOpen: true,				title: mw.message('taxonomy-title').plain,				width: '60%',				modal: true			}); }	// the dialog functions --- function showTaxonomyBrowserForm(taxon) { if (bullets == "nobullets") $(' ul.nobullets{list-style: none;} ').appendTo('head'); var text = ""; text +=	' '; text +=		' ' + 'Taxon name: ' + ' ' //+ '   Test ' + ' \n'; text +=		' ' + ' ' 						+	'Levels to display:  ' + ' ' 	                   +	'Hide extinct taxa:  ' + ' ' 	                   +	'Bold displayed taxa:  ' + ' ' 	                   +	'Hide childless taxa:  ' + ' ' 	                   +	'Link the Wikipedia article:  ' + ' ' 	                   +	'Show speciesboxes:  ' + ' ' 	                   +	'Show speciesboxes (all on genus):  ' + ' \n'; text +=		' ' + 'Output mode: ' + ' ' 						+	'List ' + ' ' 						+	'Interactive ' + ' \n'; text +=		' ' + 'Show parameters:' + ' ' 						+	'Yes ' + ' ' 						+	'No ' + ' \n'; text +=		' ' //visibility:hidden;">'						+ 'Search:'	                   + '' 						+	'Strict '	                    + '' 						+	'<input id="search-loose"   type="radio" name="searchtype" value="loose"          >Loose '	                    + '<div style="width:100%;float:left;" title="loose matching of parent taxa (includes variant templates as children)" >' 						+	'<input id="search-all"   type="radio" name="searchtype" value="all"          >All '	                    + '<div style="width:100%;float:left;" title="uses same_as= to assign parent templates when parent not set (slow)" >' 						+	'<input id="search-sameas"  type="radio" name="searchtype" value="sameas"   >Same as ' + ' \n'; text +=			'<input id="export-html" type="submit" value="Export tree html">'; text +=    '   '; text +=	' \n' ; //text += '  '; // add container for tree text += '  '; text += ' \ <textarea id="html-text" rows="4" name="html-text" style="width:100%;" > \ '; 		return text; }   function showNewTaxonomyTemplateForm(taxon) { var text = ""; text +=	' '; text +=		' ' + 'Taxon name:<input id="ntt-taxon" type="text" name="taxonname" value="'+taxon+'" style="width:250px;">' + '<button id="nnt-createtemplate" >Create new taxonomy template ' + ' \n'; text +=		' ' + ' ' 						+	' <input id="ntt-parent" type="text" name="parent" value="" style="width:250px;float:right;" > ' + ' ' 						+	' <input id="ntt-rank" type="text" name="rank" value="" style="width:250px;float:right;" > ' + '<div style="width:100%;padding:0.2em;float:left;" title="name of taxon with redirect to wikipedia article link if necessary" >' +	' <input id="ntt-link" type="text" name="link" value="'+taxon+'" style="width:250px;float:right;" > ' + '<div style="width:100%;padding:0.2em;float:left;" title="get unset parents from another taxonomy template" >' +	' <input id="ntt-sameas" type="text" name="sameas" value="" style="width:250px;float:right;" > ' + ' \n'; text +=		' ' + ' ' 	                   +	'  <input id="ntt-extinct" type="checkbox" name="extinct" value="no" style="float:right;"> ' + ' ' 	                   +	'  <input id="ntt-alwaysdisplay" type="checkbox" name="displayalways"  value="no" style="float:right;"> ' + ' \n'; text +=		' ' + ' ' 						//+	' <input id="ntt-refs" type="text" name="refs" value="" style="width:500px;text-align:right;float:right;" > ' +	' <textarea id="ntt-refs" rows="4"  name="comment" style="width:505px;float:right;" > ' + ' \n'; text +=	' \n' ; return text; }   function createNewTemplate (taxon) { //taxon = prompt("Enter taxon name for new taxonomy template:", getDefaultTaxonName(taxon));

var link         = $('#ntt-link').val;       // use taxon //alert(link); //if (link.includes("|")) link.replace("|","%7c"); //alert(link); var parent       = $('#ntt-parent').val; var rank         = $('#ntt-rank').val; var sameas       = $('#ntt-sameas').val; var refs         = $('#ntt-refs').val ; var extinct      = ""; if ($("#ntt-extinct").prop("checked")) extinct = "yes";             // set to yes or leave empty var alwaysdisplay = ""; if ($("#ntt-alwaysdisplay").prop("checked") ) alwaysdisplay = "yes"; // set to yes or leave empty

var url = 'https://en.wikipedia.org/w/index.php?action=edit&title=Template:taxonomy/' + $('#ntt-taxon').val + '&preload=User:Jts1882/Taxonomy/preload' + '&preloadparams%5b%5d=' + link           // link=$1           use taxon + '&preloadparams%5b%5d=' + parent         // parent=$2 + '&preloadparams%5b%5d=' + rank           // rank=$3 + '&preloadparams%5b%5d=' + extinct        // extinct=$4 + '&preloadparams%5b%5d=' + alwaysdisplay  // display_always=$5 + '&preloadparams%5b%5d=' + refs           // refs=$6 + '&preloadparams%5b%5d=' + sameas;        // same_as=$7 //window.location = url; //"www.example.com/index.php?id=" + this.id; window.open(url, 'window name', 'window settings'); // target="_blank"> }   function exportTree {                 // Note this needs a title in the <a> tag to work properly //alert("HTML code of taxonomic tree copied to clipboard"); var text = $('#output').html;                  // get content of div containing tree /*<li id="Ranidae-2-1" class="taxon_identifier"> <a href="/wiki/Template:Taxonomy/Ranidae" title="parameters: rank=familia parent=Ranoidea link=True frog|Ranidae">Ranidae</a> [familia] [12] ⊞    	   ⊟     	   ⊞ 	</li>   	*/ //var title = text.match(/" title[\s]*=[\s]*[\w\s\|\.=\[\]\/"':]*>/g);          // match /" title= ... >/    	//console.log(title);    	text = text.replace(/" title[\s]*=[\s]*[\w\s\|\.=\[\]\(\)\/"':]*"/g, "#"); // replace title with # text = text.replace(/<a href="\/wiki\//g, "');                                     // replace the #> with a pipe    	text = text.replace(/<\/a>/g, '');                                 /// replace <a> closing with wikitext

text = text.replace(/<span class=\"childbutton\"[\w\d\s\|\/\.=_\[\]"':;<>\%\-]*[⊞⊟ ]*<\/span>/g, ""); //remove interactive symbols   	$('#html-text').val(text);                        // place in textarea    	$('#html-text').select;                          // Select the text field    	document.execCommand("copy");                      // Copy the text in the textarea to the clipboard    }    function getTree(taxon) {        cleanUpAfterPreviousRuns;		var level = nListLevels;		var depth = 1;        //taxon = prompt("Enter the parent taxon:", getDefaultTaxonName(taxon));		taxon =  $('#taxonId').val;		level =$('#levelsId').val;          // can be changed in getTaxonName        var mode = "LIST";        if ($("#mode-interactive").prop("checked")) {        	mode = "INTERACTIVE";        }        nInteractiveLevels=level;  // TODO remove multiple level parameters when two methods combined taxon=taxon.replace(/_/g, " "); var taxonId = encodeID(taxon, depth, 1); // + '-li'; // note class="bullets" or "nobullets"; var output = ' <ul class="'+ bullets +'">' + '<li class="taxon_identifier" id="' + taxonId + '">' + taxon + '' + ' '                       + '</li>' + ' </ul>'; $('#output').html(output);

//addChildrenInteractive(taxon, level, mode, depth, taxonId); // we don't ahve the rank, so first get the rank (needed to get speciesboxes for genus) var search = 'intitle:Taxonomy\\/' + escapeSeq(taxon) + ' insource:/\| *rank *= *[a-zA-Z]+/'; console.log(search); jQuery.getJSON(			mw.util.wikiScript( 'api' ),			{ 'format': 'json', 'action': 'query', 	'list': 'search', 'srnamespace' :10, 'srlimit' : 5000, 'srsearch' : search },			function( data ) {                if (data.query == undefined) return;            	// intermittant and seemingly random - not clear why                var nResults = data.query.searchinfo.totalhits;                console.log(data.query);                 if (nResults === 0) {                	console.log ('no results for rank of taxon ' + taxon );                	addChildrenInteractive(taxon, level, mode, depth, taxonId); // pass without a rank                }                else { // so we have some results                	$.each ( data.query.search , function( index , sr ) { if (sr.title == "Template:Taxonomy/" + taxon ) { console.log(sr.snippet); var match = sr.snippet.match(/rank[\s]*=[\s]*([a-zA-Z ]*)/); if (match && match[1] ) { var rank = match[1]; console.log ("rank="+rank); addChildrenInteractive(taxon, level, mode, depth, taxonId, rank); }               		}                	});                }			}		);

nRun += 1; }

// - utlity functions --- function escapeSeq(taxon) { // Special Regex Characters: ., +*?^$[]{}| // Only these four characters require escape sequence inside the bracket list: ^-]\ taxon = taxon.replace(" ("," \\("); taxon = taxon.replace(")","\\)"); taxon = taxon.replace("?","\\?"); //taxon = taxon.replace("/","\\/"); taxon = taxon.replace(/\//g,"\\/"); taxon = taxon.replace(".","\\."); return taxon; }   function encodeID(taxon, depth, count) { //taxon = taxon.replace("/","_X_"); //taxon = taxon.replace("(","_Y_");   	//taxon = taxon.replace(")","_Z_"); //taxon = taxon.replace(" ","_S_"); //taxon = taxon.replace("?","_Q_"); taxon = taxon.replace(/\//g, "_X_"); taxon = taxon.replace(/\(/g, "_Y_");   	taxon = taxon.replace(/\)/g, "_Z_"); taxon = taxon.replace(/ /g, "_S_"); taxon = taxon.replace(/\?/g, "_Q_"); taxon = taxon.replace(/\./g, "_D_"); taxon = taxon.replace(/\"/g, "_E_");   	return taxon+'-'+depth.toString+'-'+count.toString;	    //return encodeURIComponent(taxon);    }    function decodeID(taxon) {    	//taxon = taxon.replace("_X_","/");     	//taxon = taxon.replace("_Y_","(");   	    //taxon = taxon.replace("_Z_",")");   	    //taxon = taxon.replace("_S_"," ");   	    //taxon = taxon.replace("_Q_","?");    	taxon = taxon.replace(/_X_/g, "/");     	taxon = taxon.replace(/_Y_/g, "(");   	    taxon = taxon.replace(/_Z_/g, ")");   	    taxon = taxon.replace(/_S_/g, " ");   	    taxon = taxon.replace(/_Q_/g, "?");   	    taxon = taxon.replace(/_D_/g, ".");   	    return taxon;	    //return encodeURIComponent(taxon);    }        function getTaxonName(taxon) {    	taxon = prompt("Enter the parent taxon:", getDefaultTaxonName(taxon));    	var split = taxon.split(" ");        if (split[1]) {          var number = parseInt(split[1]); //if (number != NaN) nLevels = number; if (!isNaN(number)) { nLevels = number; nInteractiveLevels= number; // TODO make decision on level parameters nListLevels= number; }         taxon = split[0]; }       return taxon; }   function getDefaultTaxonName(taxon) {         // get default from page name var page = mw.config.get( 'wgPageName' ) ;

if (page.includes("Template:Taxonomy/") ) { var res = page.split("Template:Taxonomy/"); taxon = res[1]; }   	else  { var title = new mw.Title ( page ); var ns = title.getNamespaceId; if ( ns === 0 && !page.includes(" ") ) 	taxon = page; }   	return taxon; }   function  getParameterString(index, sr) { var paramString = "parameters: "; //" [extra info] ";

var snippet =sr.snippet; // this contains the template code if (snippet.includes("rank")) { //var rank = templateData.match(/rank[\s]*=[\s]*[a-zA-Z]*/); //gets "rank%s=%sclassis" var rank = snippet.match(/rank[\s]*=[\s]*([a-zA-Z ]*)/); //if (rank && rank[0] ) 	extraInfo = ' ['+rank[0]+']'; if (rank && rank[0] ) 	paramString += rank[0]; }		if (snippet.includes("parent")) { var parent = snippet.match(/parent[\s]*=[\s]*([a-zA-Z\-\(\)\._ \/\?]*)/); if (parent && parent[0] ) 	paramString += ' ' + parent[0]; }		if (snippet.includes("link")) { var link = snippet.match(/link[\s]*=[\s]*([a-zA-Z\-\|#\.\(\)"'&; ]*)/);			//if (snippet.includes("Ichthyostegalia")) alert(link[0] + '_' + link[1] + '_');			if (link && link[0] ) 	paramString += ' ' + link[0];		}		if (snippet.includes("extinct")) {			var extinct = snippet.match(/extinct[\s]*=[\s]*([a-zA-Z ]*)/);			if (extinct && extinct[0] ) 	paramString  += ' ' + extinct[0];		}		if (snippet.includes("always_display")) {			var always = snippet.match(/always_display[\s]*=[\s]*([a-zA-Z ]*)/);			if (always && always[0] ) 	paramString  += ' ' + always[0];		}		if (snippet.includes("same_as") || snippet.includes("same as") ) {			var sameas = snippet.match(/same[ _]as[\s]*=[\s]*([a-zA-Z]*)/);			if (sameas && sameas[0] ) 	paramString  += ' ' + sameas[0];		}		if (snippet.includes("refs")) {			var refs = snippet.match(/refs[\s]*=[\s]*([a-zA-Z0-9{}| ]*)/);			var refText = 'refs=[empty]';			if (refs && refs[1] ) refText =	'refs=[...]'; paramString += ' ' + refText; }		//paramString = paramString.replace(/\"/g, '\\\"'); // " already replaced by &quot; in snippet		return 'title="' + paramString + '" '; 		//return 'title="' + encodeURI(paramString) + '" '; // what if " in title string }      function  getSameAs(index, sr) { var snippet =sr.snippet; // this contains the template code if (snippet.includes("same_as") || snippet.includes("same as") ) { var sameas = snippet.match(/same[ _]as[\s]*=[\s]*([a-zA-Z]*)/); if (sameas && sameas[0] ) return ' [same_as=<a href="/wiki/Template:Taxonomy/' + sameas[1] + '" title="">' + sameas[1] + '</a>]'; }		return false; }   function  getExtinct(index, sr) { var snippet =sr.snippet; // this contains the template code if (snippet.includes("extinct")) { var extinct = snippet.match(/extinct[\s]*=[\s]*([a-zA-Z ]*)/); if (extinct && extinct[1] ) { var value = extinct[1].toLowerCase; if (value=="yes" || value=="true") return true; }		}		return false; }   function  getAlwaysDisplay(index, sr) { if (!$("#bolddisplayId").prop("checked")) return false; var snippet =sr.snippet; // this contains the template code if (snippet.includes("always_display")) { var alwaysDisplay = snippet.match(/always_display[\s]*=[\s]*([a-zA-Z ]*)/); if (alwaysDisplay && alwaysDisplay[1] ) { var value = alwaysDisplay[1].toLowerCase; if (value=="yes" || value=="true") return true; }		}		if (snippet.includes("rank")) { var rank = snippet.match(/rank[\s]*=[\s]*([a-zA-Z ]*)/); if (rank && rank[1] ) { var value = rank[1].toLowerCase; if (value == 'ordo' || value == 'order' || value == 'classis' || value == 'class'				   || value == 'kingdom' || value == 'phylum' || value == 'divisio' || value == 'division'				    || value == 'familia' || value == 'family' || value == 'classis' || value == 'class'				    ) return true; }		}		return false; }   function getParent(index, sr) { var snippet = sr.snippet; // this contains the template code if (snippet.includes("parent")) { //if (snippet.includes("Vaccinium")) alert(snippet); // snippet contains "<span class=\"searchmatch\">parent=Reptiliomorpha " (not with regex search) //snippet = snippet.replace(" ",""); //var parent = snippet.match(/parent[\s]*=[\s]*([a-zA-Z\._ \/\?]*)/); var parent = snippet.match(/parent[\s]*=[\s]*([a-zA-Z\-\(\)\._ \/\?]*)/); if (parent && parent[1] ) { return parent[1].trim; }		}		return false; }   function getLink(index, sr) { var snippet = sr.snippet; // this contains the template code if (snippet.includes("link")) { var link = snippet.match(/link[\s]*=[\s]*([a-zA-Z\-\|#\.\(\)"'&; ]*)/);			//if (link && link[0] ) 	return link[0];			if (link && link[1] ) {				var redirect = link[1].match(/([a-zA-Z\-#\.\(\)"'&; ]*)|(.*)/); if (redirect && redirect[1]) return redirect[1]; return link[1]; //return link[1]; }		}    }    function  getSnippet(index, sr) { var snippet =sr.snippet; // this contains the template code snippet = snippet.replace('<span class=\"searchmatch\">', ""); snippet = snippet.replace(" ",""); return snippet; }   function  getRank(index, sr) { var snippet =sr.snippet; // this contains the template code if (snippet.includes("rank")) { var rank = snippet.match(/rank[\s]*=[\s]*([a-zA-Z ]*)/); if (rank && rank[1] ) 	return rank[1]; }	/*	if (snippet.includes("same_as") || snippet.includes("same as") ) { var sameas = snippet.match(/same[ _]as[\s]*=[\s]*([a-zA-Z]*)/); if (sameas && sameas[0] ) 	return sameas[0]; }*/		return false; //"unknown rank"; }   function formatByRank(name, rank) { // check for genus and species; inlcude should pick up subgenus, species group, etc if ( rank && (rank.includes("genus") || rank.includes("species")) ) { name = ' + name + '; }       return name; }   function cleanUpAfterPreviousRuns { if (nRun > 1) { //if (debug) alert ("run number = "+ nRun); $('.taxon_identifier').remove; }	}	function InfraGenericRank(rank) { switch(rank) { case "genus": case "subgenus": case "sectio": case "series": return true; default: return false; }   } 	function getTaxonRank(taxon, callback) {

var search = 'hastemplate:Taxonomy/' + taxon + ' insource:/\| *rank *=[a-zA-Z]+/';

jQuery.getJSON(			mw.util.wikiScript( 'api' ),			{ 				'format': 'json',				'action': 'query',				'list': 'search',				'srnamespace' :10,                       // search in template namespace				'srlimit' : 500,				'srsearch' : search

},			function( data ) {

if (data.query == undefined) { // intermittant and seemingly random - not clear why alert ("undefined data.query: id=" + taxonId); return; }               var nResults = data.query.searchinfo.totalhits; console.log(data.query); if (nResults === 0) { console.log ('no results for rank of taxon ' + taxon ); }               else { // so we have some results $.each ( data.query.search, function( index , sr ) {               		if (sr.title == "Template:Taxonomy/" + taxon ) {                			//console.log(sr.snippet);                			var match = sr.snippet.match(/rank[\s]*=[\s]*([a-zA-Z ]*)/);							if (match && match[1] ) {								var rank = match[1];                				console.log ("rank="+rank);                 				callback;                				return(rank);							}                		}                	}); }			}		);	}   ///---  interactive function (when is this used?)    function getTreeInteractive(taxon) {

cleanUpAfterPreviousRuns;

//taxon = prompt("Enter the parent taxon:", getDefaultTaxonName(taxon)); taxon = getTaxonName(taxon); var output= ' <ul><li class="taxon_identifier" id="' + encodeID(taxon) + '-li">' + taxon + '</li> </ul>'; //var output= ' <ul><li class="taxon_identifier" id="' + taxon + '-li">' + taxon + '</li> </ul>'; var level = nInteractiveLevels; // nLevels is globally set at top addChildrenInteractive(taxon, level, "INTERACTIVE"); renderTaxonomyDialog( output ); nRun += 1; }   function addChildrenInteractive(taxon, level, mode, depth, taxonId, rank, parent) { if (level == 0) return; level -= 1; depth +=1; // perform search using API with one of jQuery's AJAX functions //var search = 'insource:/parent[ ]*=[ ]*' + escapeSeq(taxon) + '[\\s]*/ prefix:Template:Taxonomy/';

// strict search using RegEx /search terms/ var search = 'insource:/parent[ ]*=[ ]*';                         // search for parent if ($("#search-sameas").prop("checked")) {                        // else search for parent or same as			// insource: /[ps]a[rm]e[n ][ta][s]*[ ]*=[ ]*Archaeplastida/  prefix:Template:Taxonomy/ search = 'insource: /[ps]a[rm]e[n _][ta][s]*[ ]*=[ ]*'; }	   search += escapeSeq(taxon) + '[a-zA-Z0-9 \\.\\/\\?\\\s]*/'            // regex expression for search - we want the name and variants + ' prefix:Template:Taxonomy/';            // restrict search to taxonomy templates // looser search with "search terms" //           -- this gives 9 children for Reptilomorpha and Reptilomorpha/? instead of 9 and 2 //           -- but the issue is handling the variant templates (see parent match code below) //	   if ($("#search-loose").prop("checked")) { //	   	search = 'insource:"parent[ ]+=[ ]+' + escapeSeq(taxon) + '" prefix:Template:Taxonomy/'; //	   	alert("loose search"); //	   }		// not what is wanted: the search wants to retrieve the full name, then decide how to handle it	    var showParameters = true; if ($("#params-hide").prop("checked")) showParameters = false; var hideExtinct = false; if ($("#extinctId").prop("checked")) hideExtinct = true; var hideChildless = false; if ($("#childlessId").prop("checked")) hideChildless = true; var linkWikiArticle = false; if ($("#wikiArticleId").prop("checked")) linkWikiArticle = true; var showSpeciesboxes = false; var showSpeciesboxesAll = false; if ($("#showSpeciesboxesId").prop("checked")) showSpeciesboxes = true; if ($("#showSpeciesboxesAllId").prop("checked")) showSpeciesboxesAll = true;

//TODO Ass [a-zA-Z\/\?\s]* //alert(search); //search ="insource:/parent[ ]*=[ ]*Reptiliomorpha\\/\\?[\\s]*/ prefix:Template:Taxonomy/"; jQuery.getJSON(			mw.util.wikiScript( 'api' ),			{				'format': 'json',				'action': 'query',				'list': 'search',				'srnamespace' :10,                       // search in template namespace				'srlimit' : 500,			//	'srqiprofile' : 'classic',     				'srsearch' : search  // uses /regex/

},			function( data ) { var output = ""; if (data.query == undefined) { // intermittant and seemly random - not clear why alert ("undefined data.query: id=" + taxonId); // try again? addChildrenInteractive(taxon, level+1, mode, depth-1, taxonId, rank, parent); return; }               var nResults = data.query.searchinfo.totalhits; //alert ("nResults="+nResults); var count = 0; if (nResults === 0) { // if (debug) alert ('no results for taxon (rank) = ' + taxon + ' (' + rank + ')'); // speciesboxes search now launched after the end of the if else results loop

output = ' [no child templates]'; // "zero hits: " + taxon; if (hideChildless) { $('#'+taxonId).hide; // hide taxon }        	                	else { if (showParameters) $('#'+taxonId+' span.tree-info').append(output); if (rank != "genus" && rank != "subgenus" && rank != "sectio" && rank != "series") { $('#'+taxonId+'-collapse').html(' &#8865; ').off("click"); // change symbols and disable }               	}                }                else { // so we have some results if (debug && showParameters) $('#'+taxonId+' span.tree-info').append(" [" + nResults + "]"); // number of results; includes variants $('#'+taxonId).append('<ul class="' + bullets + '"></ul>');  // add ul element to contain children var listCount = 0; data.query.search.sort(function(a, b){return a.title>b.title}); // sort on title

$.each ( data.query.search, function( index , sr ) {	                   var child = sr.title.replace("Template:Taxonomy/", "");		                                     var rank = getRank(index , sr);                        var extinct = getExtinct(index , sr);                        var link = getLink(index , sr);                        var parent = getParent(index , sr);                        var variant = "";                        var alwaysDisplay = getAlwaysDisplay(index , sr);                        var sameAs = getSameAs(index , sr);                        var titleString = ' title=""'; // alt text to display on mouse over [default empty to help export code]                        if (showParameters) {                              //titleString = 'title="rank='+rank+'; parent='+parent+'; always_display='+alwaysDisplay+'" ';                             titleString = getParameterString(index , sr); }                       if (hideExtinct && extinct) return true; // don't show extinct taxa if (rank == 'genus' ) genus = child; // a global required for speciesbox searching // select taxa to display //    the search results for Template:Taxonomy/TAXON will also contain variant templates; //    we normally (strict search) don't want to include those under base template name if (1==1 && (!parent || parent!=taxon )) { if (debug && parent && parent.includes("Vaccinium")) { alert("parent not matching for child "+child+"\nparent="+parent+"\ntaxon="+taxon); }                       	var accept = false; // we have a parent mismatch if ($("#search-loose").prop("checked")) { // if loose match allowed //if (debug) alert("in loose: taxon="+taxon+";parent="+parent); if (parent && parent.includes(taxon+"/")) { accept = true;                    //accept variants - "taxon/variant" variant = ' [parent='+parent+']'; }                       	}                        	if ($("#search-all").prop("checked")) {  // if all matches wanted accept = true; variant = ' [parent='+parent+']'; }

if ( sameAs && $("#search-sameas").prop("checked")) { // accept if sameas (any or =taxon) accept = true; //if (debug) alert('child='+child+': no parent, same_as='+sameAs); }                       	if (accept == false)  return true; // skip to next in each loop (equivalent of continue;                        } // check parents loop //                        if ($("#search-loose").prop("checked")) {       // if loose match (testing) //                           // can we exlude reptilomorpha/? if sister reptilomorpha //                           // skip variant if element at base name exists (unreliable as requires base name before variants) //                        	if (child.includes("/")) { //                        		var value = child.split("/"); //                        		if (value[1] && $('#'+encodeID(value[0],depth)+'-li').length ) { //                        		//alert('child='+child+'; value1='+value[0]); //                        		return true; //                        		} //                            } //                        } // display the selected child taxa (either matched parents or allowed loose match) count += 1; var name = formatByRank(child, rank); // italicise if genus or species rank if (alwaysDisplay) name =  + name + ; var childId = encodeID(child, depth, count); // + '-li'; output = '<li id="' + childId + '" class="taxon_identifier" >'; if (extinct) output += '†'; output += '<a href="/wiki/' + sr.title + '" ' + titleString + ' target="_blank" >' + name + '</a>'; output += ' '; // span for add information if (showParameters) { if (rank)  output += ' ['+rank+']'; if (sameAs) output += sameAs; if (variant) output += variant; }

if (linkWikiArticle) { if (link == child) { output += ' (article: <a href="/wiki/' + child + '" ' + ' target="_blank" >' + name + '</a>)'; // name is formated }							else {								output += ' (links to: <a href="/wiki/' + link + '" ' + ' target="_blank" >' + formatByRank(link, rank); + '</a>';								output += ' ; redirects from <a href="/wiki/' + child + '" ' + ' target="_blank" >' + name + '</a>'; //keep for debugging								output += ')'; }						}

if (debug) { //output += extraText(index, sr); //output += " [child="+child+"; parent="+parent+"; taxon="+taxon+ "]"; }	                   output += ' '; // close info span var output2 = "";                              // add the spans with interactive elements if (level === 0 && mode=="INTERACTIVE") { output2 += ' <span class="childbutton" id="' + childId + '-load" style="font-size:120%;"> &#8862; '; // +/- in square &#8862;/&#8863; +/-/x in circle &#8853;/&#8854;/&#8855; output2 += ' <span class="childbutton" id="' + childId + '-collapse" style="font-size:120%;display: none;"> &#8863; '; // +/- in square &#8862;/&#8863; +/-/x in circle &#8853;/&#8854;/&#8855; output2 += ' <span class="childbutton" id="' + childId + '-expand" style="font-size:120%;display: none;"> &#8862; '; // +/- in square &#8862;/&#8863; +/-/x in circle &#8853;/&#8854;/&#8855; }	                   //output += output2; // if interactive elements on right output += '</li>' ; $('#'+taxonId+' > ul').append(output);  // append child li element listCount += 1; if (bullets == "nobullets") { $('#'+childId).prepend(output2);        // insert interactive element before (no bullets) } else { $('#'+childId).append(output2);       // insert interactive element after (with default bullets) }                       // code for interactive loading, collapsing and expanding tree if (level === 0 && mode=="INTERACTIVE") { //console.log("adding interactive stuff"); // load children, hide load icon, show collapse icon $('#'+childId+'-load').click(function (e) {								e.preventDefault;	                           addChildrenInteractive(child, nInteractiveLevels, mode, depth, childId, rank, taxon);  // trigger new run							    $(this).hide;							    $('#'+childId+'-collapse').show;							}); // hide children of node; show expand icon $('#'+childId+'-collapse').click(function (e) {								$('#'+childId+' > ul').hide;								$(this).hide;								$('#'+childId+'-expand').show;							}); // show children of node, show collapse icon $('#'+childId+'-expand').click(function (e) {								$('#'+childId+' > ul').show;								$(this).hide;								$('#'+childId+'-collapse').show;							}); }

if (level > 0){                         // if expanding multiple levelss console.log("level > 0 for taxon "+taxon); addChildrenInteractive(child, level, mode, depth, childId, rank, taxon); }					}); // end @each loop                   if (listCount == 0 ) { // we are here when there are no strict results                    	                   // e.g.  with Panthera, which has results with "parent=Pantherapsida"                        console.log("no results with strict matching of " + taxon + ' (' + rank + ')');                    }					if (showParameters) {						$('#'+taxonId+' > span.tree-info').append(" [" + count + " child templates]"); // number of results; excludes variants					}			    } // end if results        		    if (showSpeciesboxesAll ) {  // check speciesboxes at genus level (including infrageneric ranks)            		if (rank == 'genus' || rank == 'subgenus'  ) { //alway check speciesboxes at genus level                		//if (debug) alert ('Checking for all speciesboxes associated with this genus');                		if ($('#'+taxonId + ' ul.speciesboxes').length  ) { //if (debug) alert ('Speciesbox block already exists'); } else { //if (debug) alert ("Speciesbox block doesn't exist; will add one"); addSpeciesboxes(taxon, level, mode, depth, taxonId, rank, parent); // look for species boxes }           		}                 }			    else if (showSpeciesboxes) { // check speciesboxes even when there are child templates if (rank == 'genus' || rank == 'subgenus' || rank == 'sectio' || rank == 'series' ) { //if (debug) alert ('rank = ' + rank + '; taxon = ' + taxon + '; parent = ' + parent ); addSpeciesboxes(taxon, level, mode, depth, taxonId, rank, parent); }      		    }

} // end processing function (data) );           } // end function addChildrenInteractive //function to check species boxes under generic taxa-   	function addSpeciesboxes(taxon, level, mode, depth, taxonId, rank, parentTaxon) {

//if (debug) alert ('Call to addSpeciesboxs for taxon (rank) = ' + taxon + ' (' + rank + '); parent = ' + parent );

var showParameters = true; if ($("#params-hide").prop("checked")) showParameters = false; //var hideExtinct = false; //if ($("#extinctId").prop("checked")) hideExtinct = true; var hideChildless = false; if ($("#childlessId").prop("checked")) hideChildless = true; //var showSpeciesboxes = false; //if ($("#showSpeciesboxesId").prop("checked")) showSpeciesboxes = true; var showSpeciesboxesAll = false; if ($("#showSpeciesboxesAllId").prop("checked")) showSpeciesboxesAll = true; // hastemplate:speciesbox insource:Panthera insource:/\| *[gt][ea][nx][uo][sn] *= *Panthera/ var search = 'hastemplate:speciesbox'                   // pages with speciesbox template + ' insource:' + escapeSeq(taxon)          // reduce to pages with taxon before regex inquiry //	                + ' insource:' + '/\| *genus *= *Neofelis/'; //search += escapeSeq(taxon) //	                + ' insource:' + '/\| *[gt][ea][nx][uo][sn] *= *' + escapeSeq(taxon) + '/' + ' insource:' + '/\| *[gt][ea][nx][uo][sn] *= *' + escapeSeq(taxon) + '[^a-z]/'; // match word, e.g. exclude Mustela from Mus //+ '[a-zA-Z0-9 \\.\\/\\?\\\s]*/'            // regex expression for search - we want the name and variants if ( rank == "genus" && !showSpeciesboxesAll ) { //search += ' -insource:' + '/\| *parent *= *' + escapeSeq(taxon) +'/'; search += ' -insource:' + '/\| *parent *= *[a-zA-Z]+/'; console.log(search); }       if ( rank == "subgenus" || rank == "sectio" || rank == 'series' ) { search = 'hastemplate:speciesbox'                   // pages with speciesbox template + ' insource:' + escapeSeq(taxon)          // reduce to pages with taxon before regex inquiry + ' insource:' + '/\| *parent *= *' + escapeSeq(taxon) + '[^a-z]/'; // match word, e.g. exclude Mustela from Mus }       console.log(search);

jQuery.getJSON(			mw.util.wikiScript( 'api' ),			{				'format': 'json',				'action': 'query',				'list': 'search',				'srnamespace' :0,                       // search in main namespace				'srlimit' : 500,			//	'srqiprofile' : 'classic',     				'srsearch' : search  // uses /regex/

},			function( data ) { var output = ""; if (data.query == undefined) { // intermittant and seemingly random - not clear why alert ("undefined data.query: id=" + taxonId); return; }               var nResults = data.query.searchinfo.totalhits; //alert ("nResults="+nResults); var count = 0; console.log(data.query); //.searchinfo);               if (nResults === 0) {                	console.log ('no speciesbox results for taxon (rank) = ' + taxon + ' (' + rank + ')');                	if (rank == 'genus' || rank == 'subgenus' || rank == 'sectio') {                	   console.log ('No speciesboxes associated with genus ' + taxon)                	}                	output = ' [no speciesboxes]'; // "zero hits: " + taxon;                	if (hideChildless) {                		$('#'+taxonId).hide; // hide taxon                	}         	                	else {                		if (showParameters) $('#'+taxonId+' > span.tree-info').append(output); //                		$('#'+taxonId+'-collapse').hide; // hide collapse button  TODO not with genus                    	$('#'+taxonId+'-collapse').html(' &#8865; ').off("click"); // change symbols and disable

}               }                else { // so we have some results if (showParameters) $('#'+taxonId+' > span.tree-info').append(" [" + nResults + " speciesboxes]"); // number of results; includes variants if ( showSpeciesboxesAll && rank == "genus" ) { //$('#'+taxonId).parent.prepend('<li>speciesboxes for whole genus<ul id="' + rank + '" class="' + bullets + ' speciesboxes"></ul></li>'); $('#'+taxonId).append('<ul class="' + bullets + '"><li>speciesboxes for whole genus<ul id="' + rank + '" class="' + bullets + ' speciesboxes"></ul></li></ul>'); } else { //$('#'+taxonId).append('<ul class="' + bullets + ' speciesboxes">ul block for speciesboxes</ul>');  // add ul element to contain children $('#'+taxonId).append('<ul class="' + bullets + ' speciesboxes"></ul>');  // add ul element to contain children }					data.query.search.sort(function(a, b){return a.title>b.title}); $.each ( data.query.search, function( index , sr ) {                       //var rank = getRank(index , sr);                        //var extinct = getExtinct(index , sr);                        //if (hideExtinct && extinct) return true; // don't show extinct taxa   (info not available for speciesboxes)                        // display the selected child taxa                         count += 1;

var child = sr.title.replace(" ", "_"); var genus = ""; var species = ""; var parent = ""; var binomial = ""; var comment = ""; if ( sr.snippet.search(/taxon *=/) > 0 ) { var snippet = sr.snippet.replace (' ', ''); // remove highlighting from search snippet snippet = snippet.replace (' ', ''); //var snippetTaxon = snippet.replace(/[\s\S]+taxon *= *(\w+) (\w+)[\s\S]+/, "$1 $2"); var snippetTaxon = snippet.replace(/[\s\S]+taxon *= *(\w+) ([ ×\w]+)[\s\S]+/, "$1 $2"); //	snippetTaxon = snippet.replace(/[\s\S]+taxon *= *(\w+ \w+)[\s\S]+/, "$1"); if (snippetTaxon == snippet) { if (debug) comment = " [taxon not available in search snippet]"; // } else { binomial = snippetTaxon;  // should snippetTaxon be checke? }                       	console.log("taxon=" + snippetTaxon + comment); }                       else if (sr.snippet.search(/genus *=/) > 0 && sr.snippet.search(/species *=/) > 0 ) { // if speciesbox with genus= and species= genus =  sr.snippet.replace(/[\s\S]+genus *= *(\w+)[\s\S]+/, "$1"); species = sr.snippet.replace(/[\s\S]+species *= *([\w ×]+)[\s\S]*/, "$1"); binomial = genus + " " + species; if (species == sr.snippet) {     // if species epithet not available in search snippet species = "</i>sp."; comment = " [species epithet not available in search snippet]"; // when species not available in snippet }                        	console.log("taxon(genus+species)=" + genus + " " + species + " " + comment); } else { comment = " [snippet doesn't contain taxon or genus and species]"; binomial = "not available"; }                   	parent =   sr.snippet.replace(/[\s\S]+parent *= *(\w+[\w \.]*\w+)[\s\S]+/, "$1"); //parent =  sr.snippet.replace(/[\s\S]+parent *= *(\w+)[\s\S]+/, "$1"); if (parent == sr.snippet) {     // if parent not captured if (debug) comment += " [no parent or not in snippet]"; } else { if (debug) comment += " [parent = " + parent + "]"; }

var name = sr.title; if ( binomial == sr.title ) { binomial = "";                           // don't show if binomial if same as page title name = "" + name + "" ;           // italicise page title if binomial } else { binomial = " (" + binomial + ")" ;               // display binomial after page title if different if ( genus == sr.title ) name = "" + name + "" ; // italicise page title is monotypic genus }

var titleString = ' title=""'; if (showParameters) { //titleString = ' title="' + encodeURIComponent(sr.snippet) +'"'; }

var childId = sr.title.replace(" ", "_") + "_SPECIES"; // + '-li'; output = '<li id="' + childId + '" class="taxon_identifier" >'; //if (extinct) output += '†';                                            // cannot know extinct status for speciesbox output += '<a href="/wiki/' + sr.title + '" ' + titleString + ' target="_blank" >' + name + '</a>';

output += ' '; // span for add information output += binomial; if (debug) { //output += extraText(index, sr); output += comment; }	                   output += ' '; // close info span output += '</li>' ; if (rank == "subgenus" || rank == "sectio" || rank == 'series' ) { $('#'+taxonId+' > ul.speciesboxes').append(output);  // append child li element } else { $('#'+taxonId+' ul.speciesboxes').append(output);   // append child li element }					});					if (showParameters) {						//$('#'+rank).parent.prepend(" [" + count + " ???]"); // number of results; excludes variants					}			   }			} // end processing function (data)		); } // end function addChildrenInteractive

// - document ready - add functions to tool menu -- $(document).ready( function {      // alert("hello")   // my test that the page is loading		//  mw.util.addPortletLink( portletId, href, text, id, tooltip, accesskey, nextnode );		// Add a link to the toolbox		var link = mw.util.addPortletLink( 'p-tb', '#',			mw.message('taxonomy-link').plain, 't-prettylinkwidget', mw.message('taxonomy-tooltip').plain, '/'			//'#t-whatlinkshere'   // this places it at the top of the tools );		if (debug) {			var link2 = mw.util.addPortletLink('p-tb', '#', mw.message('taxonomy-link2').plain, 't-prettylinkwidget', mw.message('taxonomy-tooltip').plain);		}		if (ntt) {			var link3 = mw.util.addPortletLink('p-tb', '#', mw.message('ntt-link').plain, 't-prettylinkwidget', mw.message('ntt-tooltip').plain	);		}		// Create a jQuery object for this link so that we get to use jQuery awesomeness 		//       like .click for binding functions to events and methods like e.preventDefault;		$(link).click( function( e ) { e.preventDefault; // Avoid the browser going to '#' //getChildren("Felidae"); // get children for prompted taxon //getTreeList("Plantae"); // get more than one level of tree if (nRun >1 ) { $('.taxonomy-browser').remove; // remove previous instances of form and output divs (prevents multiple IDs) }			openTaxonBrowserDialog( "Fagaceae" ); $('#gettree').click( function( e ) {				e.preventDefault;				getTree("Plantae");			}); $('#export-html').click( function( e ) {				e.preventDefault;				exportTree;			}); });		if (debug) {			$(link2).click( function( e ) { e.preventDefault;// Avoid the browser going to '#' //getTreeInteractive("Carnivora"); // get more than one level of tree getTreeInteractive("Tetrapoda"); // get more than one level of tree });		}		if (ntt) {			$(link3).click( function( e ) { e.preventDefault;// Avoid the browser going to '#' openCreateTaxonomyTemplateDialog( "Miodocus" ); $('#nnt-createtemplate').click( function( e ) {					e.preventDefault;					createNewTemplate("Miodocus");				}); });		}	});

});