Annotates radical, kanji and vocab pages with SRS colours. Original script by jeshuamorrissey.
目前為
// ==UserScript==
// @name WaniKani Item Annotator
// @namespace mempo
// @description Annotates radical, kanji and vocab pages with SRS colours. Original script by jeshuamorrissey.
// @author Mempo
// @version 1.2
// @include http://www.wanikani.com/radical*
// @include http://www.wanikani.com/kanji*
// @include http://www.wanikani.com/vocabulary*
// @include http://www.wanikani.com/account*
// @include https://www.wanikani.com/radical*
// @include https://www.wanikani.com/kanji*
// @include https://www.wanikani.com/vocabulary*
// @include https://www.wanikani.com/account*
// @grant none
// ==/UserScript==
console.log('@@@@ start of WaniKani Item Annotator');
var apiKey = $.jStorage.get('WIA_apiKey');
if(apiKey === null){ //not initialized yet
console.log('#### no apiKey found');
if (window.location.href.indexOf('account') != - 1) {
apiKey = "" + retrieveAPIkey();
console.log('@@@@@' + apiKey);
$.jStorage.set('WIA_apiKey', apiKey);
} else {
var okcancel = confirm('WaniKani Item Annotator has no API key entered!\nPress OK to go to your settings page and retrieve your API key!');
if (okcancel == true) {
window.location = 'https://www.wanikani.com/account';
return;
}
}
}
console.log('#### apiKey is: ' + apiKey);
// Determine which API call we are going to make.
var target = 'kanji';
if (window.location.href.indexOf('vocabulary') >= 0) {
target = 'vocabulary';
} else if (window.location.href.indexOf('radicals') >= 0) {
target = 'radicals';
}
console.log('@@@ target is: ' + target);
// Load the API data.
$.get(apiURL(target), function(xhr) {
// Parse the response.
console.log("######");
console.log(xhr);
// Build up an item mapping from Kanji --> Information
var itemMapping = {};
// Get the actual request information. If the target is vocabulary, for some reason
// we have to got an additional level into 'request_information.general'. This is
// probably to account for specialised vocab which will be added later.
var information = xhr.requested_information;
if (target === 'vocabulary') {
information = information.general;
}
for (var i in information) {
var item = information[i];
// Extract the character (Kanji) from the item.
var character = item.character;
// If we are looking at radicals, use the meaning instead (convert the meaning to
// the 'user friendly' format).
if (target === 'radicals') {
character = item.meaning.toLowerCase();
}
// Get the SRS level from the item. The 'user_specific' object will be `null` if the item
// hasn't been unlocked yet. In this case, just set the SRS level to `null`.
var srs = null;
if (item.user_specific) {
srs = item.user_specific.srs;
}
// Build the mapping for this character.
itemMapping[character] = {
'srs': srs
};
}
// Actually do stuff with this mapping.
main(itemMapping, target);
});
/**
* Mapping of SRS --> Object, where the object contains a series
* of transformation colors. These transformations will be applied
* via the element.style property, so should have priority.
*/
var newColors = {
'apprentice': {
'background': '#f100a0',
'border': '#f100a0',
'gradient_start': '#f0a',
'gradient_end': '#dd0093'
},
'guru': {
'background': '#882d9e',
'border': '#882d9e',
'gradient_start': '#aa38c6',
'gradient_end': '#882d9e'
},
'master': {
'background': '#294ddb',
'border': '#294ddb',
'gradient_start': '#5571e2',
'gradient_end': '#294ddb'
},
'enlighten': {
'background': '#0093dd',
'border': '#0093dd',
'gradient_start': '#0af',
'gradient_end': '#0093dd'
}
};
/**
* Main function: actually annotate the elements. Takes as input information from
* the WK API as a mapping from Japanese Element --> Object. In this case, the
* object need only contain the SRS level of the element.
*/
function main(itemMapping, target) {
// Find all characters on the page.
var elements = document.querySelectorAll('.character-item');
for (var i in elements) {
var element = elements[i];
/*
// If this isn't actually an element (could happen, who knows), just skip it.
if (!element.querySelector || !element.style) {
continue;
}
*/
// Get the element containing the japanese information.
var japaneseElement = element.querySelector('.character');
// The japanese value to look up in the item mapping is the text of this element.
var japanese = japaneseElement.textContent;
// If we happen to be looking at radicals, some of them use pictures instead. It is
// simpler to use the radical meaning in this case (as there is only one meaning).
// The meaning is stored in the last list element within the element (for some reason
// there is a list element first).
if (target === 'radicals') {
var radicalLink = element.querySelector('a').getAttribute('href');
japanese = radicalLink.slice(radicalLink.lastIndexOf('/') + 1);
//console.log('@@@@@ ' + japanese);
}
// Find the actual japanese SRS information.
japanese = itemMapping[japanese];
//console.log(japanese);
// If we couldn't find the SRS information for the element, or the element hasn't been unlocked
// yet, just ignore it.
if (!japanese.srs) {
continue;
}
// Find the corresponding colors.
var colors = newColors[japanese.srs];
// Actually change the properties. This was essentially taken from the elements already on the page.
element.style['background'] =
colors.background
+ ' linear-gradient(to bottom, ' + colors.gradient_start + ', ' + colors.gradient_end + ')';
element.style['borderColor'] = colors.border;
}
}
function retrieveAPIkey() {
var apiKey;
for(var i=0;i<document.getElementsByClassName('span6').length;i++){
if(document.getElementsByClassName('span6')[i].getAttribute('placeholder')=="Key has not been generated") {
apiKey = document.getElementsByClassName('span6') [i].getAttribute('value');
}
}
alert('API key was set to: ' + apiKey);
if (apiKey) {
return apiKey;
}
}
function apiURL(target){
return 'https://www.wanikani.com/api/user/' + apiKey + '/' + target;
}