WaniKani Item Annotator

Annotates radical, kanji and vocab pages with SRS colours. Original script by jeshuamorrissey.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey, το Greasemonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Userscripts για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

Θα χρειαστεί να εγκαταστήσετε μια επέκταση διαχείρισης κώδικα χρήστη για να εγκαταστήσετε αυτόν τον κώδικα.

(Έχω ήδη έναν διαχειριστή κώδικα χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Έχω ήδη έναν διαχειριστή στυλ χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

// ==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.3.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*
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js
// @grant       none  
// ==/UserScript==

var $ = jQuery;

console.log('@@@@ start of WaniKani Item Annotator');

  var apiKey = 'b998b40a4587405b3ca65fa03705dce4';

  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/settings/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);
  
  var css = 
    '.WIA_apprentice {' +
    '    background: #f100a0 linear-gradient(to bottom,#f0a,#dd0093) !important;' +
    '    border-color: #f100a0 !important;' +
    '}                          ' +  
    '.WIA_guru {' +
    '    background: #882d9e linear-gradient(to bottom,#aa38c6,#882d9e) !important;' +
    '    border-color: #882d9e !important;' +
    '}                          ' + 
    '.WIA_master {' +
    '    background: #294ddb linear-gradient(to bottom,#5571e2,#294ddb) !important;' +
    '    border-color: #294ddb !important;' +
    '}                          ' + 
    '.WIA_enlighten {' +
    '    background: #0093dd linear-gradient(to bottom,#0af,#0093dd) !important;' +
    '    border-color: #0093dd !important;' +
    '}                          ' ;


  // ADD CSS
  addStyle(css);

  // Load the API data.


console.log('before API call');

  $.get(apiURL(target), function(xhr) {
    // Parse the response.
    /*
    console.log("###### JSON RESPONSE");
    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();
      }

        //console.log("ITEMMAPPING CHARACTER:" + character);

      // 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
      };
    }
    /*
   console.log('&&&&& ITEM MAPPING');
   console.log(itemMapping);
*/
    // 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.
   */



/**
   * 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) {
    //console.log('inside main function');

    // Find all characters on the page.
    var elements = $('.character-item');
    
    //console.log('size of elements is ' + elements.size());
    var i= 0;
    for (i=0;i<elements.length;i++) {
      var element = elements[i];
      //console.log("elements:" + element);
      
      
     
      
      /*
      // If this isn't actually an element (could happen, who knows), just skip it.
      if (!element.querySelector || !element.style) {
        console.log('///////////////////////////// What the shit why are we here.');
        continue;
      }
      */


      // The japanese value to look up in the item mapping is the text of this element.
      var japanese = element.querySelector('.character').innerText;

      // 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 &nbsp; list element first).
      if (target === 'radicals') {
        var radicalLink = element.querySelector('a').getAttribute('href');
        japanese = radicalLink.slice(radicalLink.lastIndexOf('/') + 1);
        //console.log('@@@@@ ' + japanese);
      }

/*
      console.log('@@@@@ japanese var:');
      console.log(japanese);
      console.log(itemMapping[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) {
        console.log('///////////// What are you doing here????');
        continue;
      }
      */
      
   

      // Find the corresponding colors. 
      //var colors = colorDict[japanese.srs];
      
      $(element).addClass("WIA_" + itemMapping[japanese].srs);
      
    }
  }
    
    
function retrieveAPIkey() { 
  var apiKey = document.getElementById('user_api_key').value;
  alert('API key was set to: ' + apiKey);
  if (apiKey) {
    return apiKey;
  }
  
}

function apiURL(target){
  return 'https://www.wanikani.com/api/user/' + apiKey + '/' + target;
}

function addStyle(aCss) {
  var head, style;
  head = document.getElementsByTagName('head')[0];
  if (head) {
    style = document.createElement('style');
    style.setAttribute('type', 'text/css');
    style.textContent = aCss;
    head.appendChild(style);
    return style;
  }
  return null;
}