Utente:Nastoshka/Wikidata Lookup.js
Nota: dopo aver pubblicato, potrebbe essere necessario pulire la cache del proprio browser per vedere i cambiamenti.
- Firefox / Safari: tieni premuto il tasto delle maiuscole Shift e fai clic su Ricarica, oppure premi Ctrl-F5 o Ctrl-R (⌘-R su Mac)
- Google Chrome: premi Ctrl-Shift-R (⌘-Shift-R su un Mac)
- Internet Explorer / Edge: tieni premuto il tasto Ctrl e fai clic su Aggiorna, oppure premi Ctrl-F5
- Opera: premi Ctrl-F5.
/**
* @author User:Nastoshka
* @date 31-01-2024
*
* Feel free to use and modify this code and most importantly, have fun! (no guarantee, expcept for the fun part :D )
*
* Very simple script to search on Wikidata for an item with a label in the selected language.
*
* It lets a button appear on the page, which when clicked, will search for the currently selected text on Wikidata.
* If the search returns results, a modal window will appear with the results displaying:
* - the Wikidata ID
* - the label
* - the description
*
*/
// Settings
const RESULT_LIMIT = 10; // Massimo numero di risultati da caricare da Wikidata
const BOTTOM_LEFT_POSITION = true; // Posiziona la finestra di ricerca in basso a sinistra, se "false" in alto accanto al titolo della pagina
const SEARCH_LANGUAGE = 'it'; // Lingua di ricerca (it, en, fr, ecc.) su Wikidata
if (mw.config.get('wgNamespaceNumber') == 0 || mw.config.get('wgNamespaceNumber') == 102 | mw.config.get('wgNamespaceNumber') == 108 || mw.config.get('wgNamespaceNumber') == 110 ) {
// ------------------------------------------------------------
// Button
// ------------------------------------------------------------
// Stile del bottone
const btnStyle = {
marginLeft: '10px',
padding: '5px',
backgroundImage: 'linear-gradient(#3670c8,#2282dc)',
fontSize: '12px',
fontWeight: 'bold',
color: '#fff',
borderRadius: '5px',
border: 'none',
cursor: 'pointer'
};
const searchButton = document.createElement('button');
searchButton.textContent = 'Wikidata Lookup'
searchButton.style.marginLeft = btnStyle.marginLeft;
searchButton.style.width = '150px';
searchButton.style.height = '30px';
searchButton.style.padding = btnStyle.padding;
searchButton.style.backgroundImage = btnStyle.backgroundImage;
searchButton.style.fontSize = btnStyle.fontSize;
searchButton.style.fontWeight = btnStyle.fontWeight;
searchButton.style.color = btnStyle.color;
searchButton.style.borderRadius = btnStyle.borderRadius;
searchButton.style.border = btnStyle.border;
searchButton.style.cursor = btnStyle.cursor;
// Aggancio il bottone al DOM
if (BOTTOM_LEFT_POSITION) {
searchButton.style.position = 'fixed';
searchButton.style.bottom = '20px';
searchButton.style.left = '20px';
document.body.appendChild(searchButton);
} else {
const titleElement = document.getElementById('firstHeading');
if (titleElement) {
titleElement.appendChild(searchButton);
} else {
console.error('Impossibile agganciare il bottone. Controlla il codice.');
}
}
/*
// ------------------------------------------------------------
// Modal window - Display the results
// ------------------------------------------------------------
*/
function showModal(items) {
const modal = document.createElement('div');
// Modal base styles
modal.style.position = 'fixed';
modal.style.left = '30vw';
modal.style.top = '150px';
modal.style.backgroundColor = 'rgba(0,0,0,0.5)';
modal.style.display = 'flex';
modal.style.justifyContent = 'center';
modal.style.alignItems = 'center';
modal.style.zIndex = '10000';
modal.style.width = 'auto';
modal.style.height = 'auto';
modal.style.maxWidth = '60%';
modal.style.maxHeight = '80%';
modal.style.boxShadow = '2px 4px 4px 2px #c8ccd1';
const content = document.createElement('div');
// Content styles for flex grid
content.style.display = 'flex';
content.style.flexWrap = 'wrap';
content.style.justifyContent = 'start'; // Align items to the start of the content box
content.style.gap = '10px'; // Space between grid items
content.style.backgroundColor = '#fff';
content.style.padding = '20px';
content.style.borderRadius = '5px';
content.style.overflowY = 'auto';
content.style.display = 'flex';
content.style.flexDirection = 'column';
content.style.alignItems = 'center';
content.style.maxWidth = '600px';
const closeButton = document.createElement('button');
closeButton.textContent = 'Close';
closeButton.style.marginTop = btnStyle.marginLeft;
closeButton.style.padding = btnStyle.padding;
closeButton.style.backgroundColor = 'rgba(248,56,56,0.8)';
closeButton.style.color = ('#fff');
closeButton.style.borderRadius = btnStyle.borderRadius;
closeButton.style.border = btnStyle.border;
closeButton.style.fontSize = btnStyle.fontSize;
closeButton.style.fontWeight = btnStyle.fontWeight;
closeButton.style.padding = '7px 15px';
closeButton.onclick = function () {
document.body.removeChild(modal);
};
content.appendChild(document.createElement('h2')).textContent = 'Risultati';
content.appendChild(document.createElement('p')).innerHTML = "<strong><em>Clicca su un risultato per copiare l'ID Wikidata.</em></strong>";
content.appendChild(document.createElement('hr'));
const resultList = document.createElement('ul');
resultList.style.listStyleType = 'none'; // Remove default list styling
resultList.style.padding = '0';
items.forEach(item => {
const itemPoint = document.createElement('li');
itemPoint.style.margin = '10px 0'; // Add margin for separation between items
itemPoint.style.cursor = 'pointer';
const label = item.itemLabel ? item.itemLabel.value : "-- label assente --";
const desc = item.itemDescription ? item.itemDescription.value : "-- descrizione assente --";
const wikidataId = item.item.value.split('/').pop();
itemPoint.textContent = `${wikidataId} : ${label} (${desc})`;
itemPoint.onclick = () => {
navigator.clipboard.writeText(wikidataId).then(() => {
document.body.removeChild(modal);
});
};
resultList.appendChild(itemPoint);
});
content.appendChild(resultList);
content.appendChild(closeButton);
modal.appendChild(content);
document.body.appendChild(modal);
}
// ------------------------------------------------------------
// Event listener - responsabile per la ricerca su Wikidata
// ------------------------------------------------------------
searchButton.addEventListener('click', function () {
let selectedText = window.getSelection().toString().trim();
if (!selectedText) {
alert("Seleziona del testo prima di cliccare sul bottone ;)");
return;
}
// Query SPARQL
// https://www.wikidata.org/wiki/Wikidata:SPARQL_tutorial/it
// La Query seguente cerca un item in Wikidata che abbia una label in italiano
// e che abbia almeno una proprietà "wikisource" o "wikipedia".
let query = `
SELECT ?item ?itemLabel ?itemDescription WHERE {
SERVICE wikibase:mwapi {
bd:serviceParam wikibase:endpoint "www.wikidata.org";
wikibase:api "EntitySearch";
mwapi:search "${selectedText}";
mwapi:language "${SEARCH_LANGUAGE}".
?item wikibase:apiOutputItem mwapi:item.
}
OPTIONAL { ?item wdt:P31/wdt:P279* wd:Q5. BIND(1 AS ?priority) } # Higher priority to Human beings
OPTIONAL { ?item wdt:P31/wdt:P279* wd:Q7725634. BIND(2 AS ?priority) } # Higher priority to Literary works
OPTIONAL { ?item rdfs:label ?itemLabel. FILTER(LANG(?itemLabel) = "${SEARCH_LANGUAGE}") } # Label in the search language
OPTIONAL { ?item schema:description ?itemDescription. FILTER(LANG(?itemDescription) = "${SEARCH_LANGUAGE}") } # Description in the search language
OPTIONAL { ?item schema:name ?sitelink. FILTER(CONTAINS(LCASE(?sitelink), LCASE("${selectedText}")) && LANG(?sitelink) = "${SEARCH_LANGUAGE}") }
} ORDER BY ?priority LIMIT ${RESULT_LIMIT}
`;
let url = 'https://query.wikidata.org/sparql?query=' + encodeURIComponent(query) + '&format=json';
fetch(url)
.then(response => response.json())
.then(data => {
const results = data.results.bindings;
console.log(data)
if (results.length > 0) {
showModal(results);
} else {
alert("Nessun risultato trovato.");
}
})
.catch(error => {
console.error('Error nel fetch dei dati: ', error);
alert("Errore nel fetch dei dati. Controlla la console per maggiori informazioni.");
});
});
}