User:Jts1882/taxonomybrowser.js
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
//---------------------------------------------------------------------------------
// 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 = $( '<div id="dialog" ></div>' )
.html( showTaxonomyBrowserForm(taxon)
// + '<div id="output" class="taxonomy-browser" style="align:left">Tree will appear here</div>'
// + showNewTaxonomyTemplateForm(taxon)
)
.dialog({
autoOpen: true,
title: mw.message('taxonomy-title').plain(),
width: '60%',
modal: true
});
}
function openCreateTaxonomyTemplateDialog( taxon ) {
taxon = getDefaultTaxonName(taxon);
var $dialog = $( '<div></div>' )
.html( showNewTaxonomyTemplateForm(taxon) )
.dialog({
autoOpen: true,
title: mw.message('taxonomy-title').plain(),
width: '50%',
modal: true
});
}
function renderTaxonomyDialog( output ) {
var $dialog = $( '<div></div>' )
.html(
'<strong>' + mw.message('taxonomy-greeting', mw.user.getName()).escaped() + '</strong> '
+ 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") $('<style>ul.nobullets{list-style: none;}</style>').appendTo('head');
var text = "";
text += '<div id="tb" class="taxonomy-browser" style="background-color:#f8f9fa;">';
text += '<div style="border:1px;padding:0.2em;margin:0.5em;" >'
+ 'Taxon name: <input id="taxonId" type="text" name="taxonname" style="width:200px;" value="'+taxon+'">'
+ ' <input id="gettree" type="submit" value="Get taxonomic tree">'
//+ ' <button id="gettree2" >Test</button>'
+ '</div>\n';
text += '<div style="width:20em;float:left;border:1px solid #dddddd;padding:0.2em;margin:0.5em;" >'
+ '<div style="width:100%;float:left;" title="number of levels in hierarchical tree" >'
+ 'Levels to display: <input id="levelsId" type="text" name="levels" value="1" style="width:20px;text-align:right;float:right;" ></div>'
+ '<div style="width:100%;float:left;" title="do not show extinct taxa" >'
+ 'Hide extinct taxa: <input id="extinctId" type="checkbox" name="extinct" value="no" style="float:right;"></div>'
+ '<div style="width:100%;float:left;" title="bold taxa that would be displayed in automatic taxobox" >'
+ 'Bold displayed taxa: <input id="bolddisplayId" type="checkbox" name="bolddisplay" value="no" style="float:right;"></div>'
+ '<div style="width:100%;float:left;" title="do not show taxa with no children" >'
+ 'Hide childless taxa: <input id="childlessId" type="checkbox" name="childless" value="no" style="float:right;" ></div>'
+ '<div style="width:100%;float:left;" title="link Wikipedia articles" >'
+ 'Link the Wikipedia article: <input id="wikiArticleId" type="checkbox" name="childless" value="no" style="float:right;" ></div>'
+ '<div style="width:100%;float:left;" title="show speciesboxes" >'
+ 'Show speciesboxes: <input id="showSpeciesboxesId" type="checkbox" name="childless" value="yes" checked style="float:right;" ></div>'
+ '<div style="width:100%;float:left;" title="show all speciesboxes at genus" >'
+ 'Show speciesboxes (all on genus): <input id="showSpeciesboxesAllId" type="checkbox" name="childless" value="no" style="float:right;" ></div>'
+ '</div>\n';
text += '<div style="width:9em;float:left;border:1px solid #dddddd;padding:0.2em;margin:0.5em;">'
+ 'Output mode: '
+ '<div style="width:100%;float:left;" title="simple listing of set number of levels in taxonomic tree" >'
+ '<input id="mode-list" type="radio" name="mode" value="list" >List</div>'
+ '<div style="width:100%;float:left;" title="interactive traversing of taxonomic tree" >'
+ '<input id="mode-interactive" type="radio" name="mode" value="interactive" checked >Interactive</div>'
+ '</div>\n';
text += '<div style="width:10em;float:left;border:1px solid #dddddd;padding:0.2em;margin:0.5em;">'
+ 'Show parameters:'
+ '<div style="width:100%;float:left;" title="show rank and show template parameters in tooltip" >'
+ '<input id="params-show" type="radio" name="parammode" value="show" checked >Yes</div>'
+ '<div style="width:100%;float:left;" title="" >'
+ '<input id="params-hide" type="radio" name="parammode" value="hide" >No</div>'
+ '</div>\n';
text += '<div style="width:8em;float:left;border:1px solid #dddddd;padding:0.2em;margin:0.5em;">' //visibility:hidden;">'
+ 'Search:'
+ '<div style="width:100%;float:left;" title="strict matching of parent taxa (excludes variant templates)" >'
+ '<input id="search-strict" type="radio" name="searchtype" value="strict" checked >Strict</div>'
+ '<div style="width:100%;float:left;" title="loose matching of parent taxa (includes variant templates as children)" >'
+ '<input id="search-loose" type="radio" name="searchtype" value="loose" >Loose</div>'
+ '<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>'
+ '<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</div>'
+ '</div>\n';
text += '<input id="export-html" type="submit" value="Export tree html">';
text += '<div style="clear:both;"> </div>';
text += '</div>\n' ;
//text += '<div style="clear:both;"> </div>';
// add container for tree
text += '<div id="output" class="taxonomy-browser" style="clear:both;"> </div>';
text += '<div class="taxonomy-browser" style="clear:both;"> \
<textarea id="html-text" rows="4" name="html-text" style="width:100%;" ></textarea> \
</div>';
return text;
}
function showNewTaxonomyTemplateForm(taxon) {
var text = "";
text += '<div id="tb" class="taxonomy-browser" >';
text += '<div style="border:1px;padding:0.2em;margin:0.5em;" >'
+ 'Taxon name:<input id="ntt-taxon" type="text" name="taxonname" value="'+taxon+'" style="width:250px;">'
+ '<button id="nnt-createtemplate" >Create new taxonomy template</button><br/>'
+ '</div>\n';
text += '<div style="width:325px;float:left;border:0px solid #dddddd;padding:0.2em;margin:0.5em;" >'
+ '<div style="width:100%;padding:0.2em;float:left;" title="parent taxon of taxon" >'
+ '<code>parent=</code> <input id="ntt-parent" type="text" name="parent" value="" style="width:250px;float:right;" ></div>'
+ '<div style="width:100%;padding:0.2em;float:left;" title="rank of taxon" >'
+ '<code>rank=</code> <input id="ntt-rank" type="text" name="rank" value="" style="width:250px;float:right;" ></div>'
+ '<div style="width:100%;padding:0.2em;float:left;" title="name of taxon with redirect to wikipedia article link if necessary" >'
+ '<code>link=</code> <input id="ntt-link" type="text" name="link" value="'+taxon+'" style="width:250px;float:right;" ></div>'
+ '<div style="width:100%;padding:0.2em;float:left;" title="get unset parents from another taxonomy template" >'
+ '<code>same as=</code> <input id="ntt-sameas" type="text" name="sameas" value="" style="width:250px;float:right;" ></div>'
+ '</div>\n';
text += '<div style="width:150px;float:left;border:1px solid #dddddd;padding:0.2em;margin:1em;" >'
+ '<div style="width:100%;padding:0.2em;float:left;" title="set Yes to indicate extinct taxon" >'
+ '<code>extinct=</code> <input id="ntt-extinct" type="checkbox" name="extinct" value="no" style="float:right;"></div>'
+ '<div style="width:100%;padding:0.2em;float:left;" title="set Yes to always display in taxobox=" >'
+ '<code>display_always=</code> <input id="ntt-alwaysdisplay" type="checkbox" name="displayalways" value="no" style="float:right;"></div>'
+ '</div>\n';
text += '<div style="width:575px;float:left;border:0px solid #dddddd;padding:0.2em;margin:0.5em;" >'
+ '<div style="width:100%;padding:0.2em;float:left;" title="reference for taxonomic information" >'
//+ '<code>refs=</code> <input id="ntt-refs" type="text" name="refs" value="" style="width:500px;text-align:right;float:right;" ></div>'
+ '<code>refs=</code> <textarea id="ntt-refs" rows="4" name="comment" style="width:505px;float:right;" ></textarea></div>'
+ '</div>\n';
text += '</div>\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>
<span class="tree-info"> [familia] [12]</span>
<span class="childbutton" id="Ranidae-2-1-load" style="font-size:120%;"> ⊞ </span>
<span class="childbutton" id="Ranidae-2-1-collapse" style="font-size:120%;display: none;"> ⊟ </span>
<span class="childbutton" id="Ranidae-2-1-expand" style="font-size:120%;display: none;"> ⊞ </span> </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 <a> opening with wikitext
text = text.replace(/#>/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 = '<br/><ul class="'+ bullets +'">'
+ '<li class="taxon_identifier" id="' + taxonId + '"><b>' + taxon + '</b>'
+ '<span class="tree-info"></span>'
+ '</li>'
+ '<br/></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 " 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</span>" (not with regex search)
//snippet = snippet.replace("</span>","");
//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("</span>","");
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 = '<i>' + name + '</i>';
}
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= '<br/><ul><li class="taxon_identifier" id="' + encodeID(taxon) + '-li"><b>' + taxon + '</b></li><br/></ul>';
//var output= '<br/><ul><li class="taxon_identifier" id="' + taxon + '-li"><b>' + taxon + '</b></li><br/></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('<span style="color:grey;"> ⊡ </span>').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 = '<b>' + name + '</b>';
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 class="tree-info">'; // 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 += '</span>'; // 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%;"> ⊞ </span>'; // +/- in square ⊞/⊟ +/-/x in circle ⊕/⊖/⊗
output2 += ' <span class="childbutton" id="' + childId + '-collapse" style="font-size:120%;display: none;"> ⊟ </span>'; // +/- in square ⊞/⊟ +/-/x in circle ⊕/⊖/⊗
output2 += ' <span class="childbutton" id="' + childId + '-expand" style="font-size:120%;display: none;"> ⊞ </span>'; // +/- in square ⊞/⊟ +/-/x in circle ⊕/⊖/⊗
}
//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('<span style="color:grey;"> ⊡ </span>').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 ('<span class="searchmatch">', ''); // remove highlighting from search snippet
snippet = snippet.replace ('</span>', '');
//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 = "<i>" + name + "</i>" ; // italicise page title if binomial
} else {
binomial = " (<i>" + binomial + "</i>)" ; // display binomial after page title if different
if ( genus == sr.title ) name = "<i>" + name + "</i>" ; // 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 class="tree-info" style="color:grey;" >'; // span for add information
output += binomial;
if (debug) {
//output += extraText(index , sr);
output += comment;
}
output += '</span>'; // 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");
});
});
}
});
});