WaniKani Lesson Examples Audio

Allows you to play audio for example vocab during kanji lessons.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

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

(I already have a user script manager, let me install it!)

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.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name          WaniKani Lesson Examples Audio
// @namespace     https://www.wanikani.com
// @description   Allows you to play audio for example vocab during kanji lessons.
// @author        seanblue
// @version       1.0.2
// @include       *://www.wanikani.com/lesson/session*
// @grant         none
// ==/UserScript==

const eventPrefix = 'seanblue.example_audio.';

(function($) {$.each(['show'], function(i, ev) { var el = $.fn[ev]; $.fn[ev] = function() { this.trigger(eventPrefix + ev); return el.apply(this, arguments); }; }); })(jQuery);

(function() {
	'use strict';

	if (!wkof) {
		var response = confirm('WaniKani Lesson Examples Audio requires WaniKani Open Framework.\n Click "OK" to be forwarded to installation instructions.');

		if (response) {
			window.location.href = 'https://community.wanikani.com/t/instructions-installing-wanikani-open-framework/28549';
		}

		return;
	}

	wkof.include('ItemData');
	wkof.ready('ItemData').then(initialize);

	var subjectLoadingInitiated = false;
	var subjectsLoadedPromise = promise();
	var subjectToAudioMap;

	var config = {
		wk_items: {
			filters: {
				item_type: 'voc'
			}
		}
	};

	function promise(){var a,b,c=new Promise(function(d,e){a=d;b=e;});c.resolve=a;c.reject=b;return c;}

	function initialize() {
		$('#supplement-kan-related-vocabulary').on(eventPrefix + 'show', function(e) {
			loadSubjects();

			subjectsLoadedPromise.then(function() {
				let listElements = $(e.currentTarget).find('li');

				for (let i = 0; i < listElements.length; i++) {
					setUpAudio($(listElements[i]));
				}
			});
		});
	}

	function loadSubjects() {
		if (!subjectLoadingInitiated) {
			subjectLoadingInitiated = true;
			wkof.ItemData.get_items(config).then(processSubjects);
		}

		return subjectsLoadedPromise;
	}

	function processSubjects(items) {
		subjectToAudioMap = items.reduce(function(map, obj) {
			map[obj.data.characters] = getAudioUrl(obj);
			return map;
		}, {});

		subjectsLoadedPromise.resolve();
	}

	function getAudioUrl(item) {
		var mp3Audios = item.data.pronunciation_audios.filter(a => a.content_type === 'audio/mpeg');
		var preferredAudios = mp3Audios.filter(a => a.metadata.voice_actor_id === WaniKani.default_voice_actor_id);

		if (preferredAudios.length > 0) {
			return preferredAudios[0].url;
		}

		if (mp3Audios.length > 0) {
			return mp3Audios[0].url;
		}

		return '';
	}

	function setUpAudio(el) {
		let existingAudioButton = el.find('button.audio-btn');

		if (existingAudioButton.length > 0) {
			return;
		}

		let characters = el.find('span.vocabulary').text();
		let audioUrl = subjectToAudioMap[characters];

		if (audioUrl === '') {
			return;
		}

		let audioButtonElem = getAudioButtonElement().appendTo(el);
		let audioElem = getAudioElement(audioUrl);

		setUpAudioEvents(audioButtonElem, audioElem);
	}

	function getAudioButtonElement() {
		return $('<button type="button" title="Play pronunciation audio" class="audio-btn audio-idle"></button>');
	}

	function getAudioElement(audioUrl) {
		let audioElem = $('<audio></audio>');

		$('<source></source>', {
			src: audioUrl,
			type: 'audio/mpeg'
		}).appendTo(audioElem);

		return audioElem;
	}

	function setUpAudioEvents(audioButtonElem, audioElem) {
		audioElem[0].addEventListener('play', function () {
			audioButtonElem.removeClass('audio-idle').addClass('audio-play');
		});

		audioElem[0].addEventListener('ended', function () {
			audioButtonElem.removeClass('audio-play').addClass('audio-idle');
		});

		audioButtonElem.on('click', function() {
			audioElem[0].play();
		});

	}
})();