Content deleted Content added
update to my commons version |
update (fixes error for high level taxa) |
||
(4 intermediate revisions by 2 users not shown) | |||
Line 1:
//---------------------------------------------------------------------------------
// Taxonomy browser script
//------------------------------------------------------------------------------------
var nLevels = 3; // this determines how many levels are show in each iteration
var nListLevels = 3;
Line 4 ⟶ 8:
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 = "";
/**
Line 48 ⟶ 53:
// Import the jQuery dialog plugin before starting the rest of this script
mw.loader.using(['jquery.ui
function openTaxonBrowserDialog( taxon ) {
Line 101 ⟶ 106:
//+ ' <button id="gettree2" >Test</button>'
+ '</div>\n';
text += '<div style="width:
+ '<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>'
Line 110 ⟶ 115:
+ '<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;">'
Line 261 ⟶ 272:
nInteractiveLevels=level; // TODO remove multiple level parameters when two methods combined
taxon=taxon.replace(/_/g, " ");
var taxonId = encodeID(taxon, depth, 1); // + '-li';
Line 272 ⟶ 283:
$('#output').html(output);
// 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;
}
Line 288 ⟶ 331:
taxon = taxon.replace(")","\\)");
taxon = taxon.replace("?","\\?");
//taxon = taxon.replace("/","\\/");
taxon = taxon.replace(/\//g,"\\/");
taxon = taxon.replace(".","\\.");
Line 305 ⟶ 349:
taxon = taxon.replace(/\?/g, "_Q_");
taxon = taxon.replace(/\./g, "_D_");
taxon = taxon.replace(/\"/g, "_E_");
return taxon+'-'+depth.toString()+'-'+count.toString();
//return encodeURIComponent(taxon);
Line 367 ⟶ 412:
}
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];
Line 380 ⟶ 425:
}
if (snippet.includes("always_display")) {
var
if (
}
if (snippet.includes("same_as") || snippet.includes("same as") ) {
Line 395 ⟶ 440:
//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) {
Line 449 ⟶ 496:
//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) {
Line 487 ⟶ 547:
}
}
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) {
Line 504 ⟶ 621:
}
function addChildrenInteractive(taxon, level, mode, depth, taxonId, rank, parent) {
if (level == 0) return;
Line 538 ⟶ 655:
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);
Line 562 ⟶ 685:
alert ("undefined data.query: id=" + taxonId);
// try again?
addChildrenInteractive(taxon, level+1, mode, depth-1 , taxonId, rank, parent);
return;
}
Line 570 ⟶ 693:
if (nResults === 0) {
// 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
Line 576 ⟶ 702:
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
}
}
}
Line 583 ⟶ 711:
$('#'+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 ) {
Line 590 ⟶ 720:
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);
Line 599 ⟶ 731:
}
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
Line 614 ⟶ 748:
if (parent && parent.includes(taxon+"/")) {
accept = true; //accept variants - "taxon/variant"
}
}
if ($("#search-all").prop("checked")) { // if all matches wanted
accept = true;
}
if ( sameAs && $("#search-sameas").prop("checked")) { // accept if sameas (any or =taxon)
accept = true;
Line 649 ⟶ 783:
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
Line 657 ⟶ 791:
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);
Line 663 ⟶ 811:
output += '</span>'; // close info span
var output2 = ""; // add the
if (level === 0 && mode=="INTERACTIVE") {
output2 += ' <span class="childbutton" id="' + childId + '-load" style="font-size:120%;"> ⊞ </span>'; // +/- in square ⊞/⊟ +/-/x in circle ⊕/⊖/⊗
Line 673 ⟶ 821:
$('#'+taxonId+' > ul').append(output); // append child li element
listCount += 1;
if (bullets == "nobullets") {
$('#'+childId).prepend(output2); // insert interactive element before (no bullets)
Line 679 ⟶ 828:
}
// 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();
Line 701 ⟶ 851:
});
}
if (level > 0){
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() {
Line 746 ⟶ 1,110:
$('.taxonomy-browser').remove(); // remove previous instances of form and output divs (prevents multiple IDs)
}
openTaxonBrowserDialog( "
$('#gettree').click( function( e ) {
e.preventDefault();
|