Allows to Preview one specific Word
// ==UserScript==
// @name Memrise Preview Word
// @description Allows to Preview one specific Word
// @match http://*.memrise.com/course/*
// @match https://*.memrise.com/course/*
// @match http://*.memrise.com/community/course/*
// @match https://*.memrise.com/community/course/*
// @match http://*.memrise.com/aprender/*
// @match https://*.memrise.com/aprender/*
// @run-at document-end
// @version 2.2
// @grant none
// @namespace https://greasyfork.org/users/213706
// ==/UserScript==
if(typeof unsafeWindow == "undefined") {
unsafeWindow = window;
}
// Inside a level: add links to preview
if(typeof unsafeWindow.MEMRISE != "undefined") {
if(document.body.classList.contains('level-view')) {
window.addEventListener('load', onLoadCourse, false);
}
function onLoadCourse() {
var path = window.location.pathname;
// Retrieve course id and level index from URL
var m = path.match('/course/([0-9]+)/[^/]+/([0-9]*)');
if(!m) {
console.error('Could not extract course and level in URL');
return;
}
var idCourse = m[1],
idxLevel = m[2] || 1;
// Display link in black when not hovering
const css = document.createElement('style');
css.textContent = `
.col_a a {
color: inherit;
}
.col_a a:hover {
color:#0c618f
}`;
document.head.appendChild(css);
var url_preview = '/aprender/preview?course_id=' + idCourse + '&level_index=' + idxLevel + '&';
// var url_preview = window.location.pathname + 'garden/preview/?';
// Add links to column a
document.body.querySelectorAll('.col_a').forEach(function(node){
var a = document.createElement('a'),
id = node.parentNode.getAttribute('data-learnable-id');
node.appendChild(a);
a.setAttribute('href', url_preview + 'learnable_id=' + id);
a.appendChild(node.firstElementChild);
});
}
// Preview a specific word with learning app V1
} else if(window.location.search.startsWith('?learnable_id=')) {
if (unsafeWindow.$) {
interceptJqueryAjax();
}
window.addEventListener('load', onLoadPreviewV1, false);
// Change close preview link (toward level instead of home)
function onLoadPreviewV1() {
var url_course = window.location.pathname.replace("/garden/preview/", "/"),
exit = document.querySelector('a.session-exit');
if(exit) {
exit.setAttribute('href', url_course);
exit.addEventListener('click', function(){
window.onbeforeunload = null;
window.location.href = this.getAttribute('href');
});
}
}
// Intercept AJAX response for V1 learning session
function interceptJqueryAjax() {
function main() {
var _oldAjax = $.ajax;
$.ajax = function(options) {
if(options.url == "/ajax/session/") {
var _oldSuccess = options.success;
_oldSuccess && $.extend(options, {
success: function(data) {
var learnable_id = window.location.search.substr(14);
// Replace list of words with list of a single word
if(typeof data.screens[learnable_id] != "undefined") {
data.boxes = [{
learnable_id: learnable_id,
template: "presentation"
}];
data.session.num_items = 1;
}
_oldSuccess(data);
}
});
}
return _oldAjax(options);
};
}
// Inject JS directly in page to prevent limitations of access
var script = document.createElement('script');
script.setAttribute("type", "application/javascript");
script.appendChild(document.createTextNode('('+ main +')();'));
document.body.appendChild(script);
}
// Preview a specific word with learning app V2
} else if(window.location.pathname == '/aprender/preview' && (new URLSearchParams(window.location.search)).get('learnable_id')) {
if (window.fetch && unsafeWindow.Promise) {
interceptFetch();
}
// V2 learning session
function interceptFetch() {
function main() {
// Override native fetch
const overrideFetch = function() {
var p = _oldAjax.apply(this, arguments);
if (p.__proto__ == Promise.prototype && typeof interceptedResponse != 'undefined') {
var url = arguments[0];
if (url && url.endsWith("/preview/")) {
return p.then((response) => {
return interceptedResponse(response);
});
}
}
return p;
}
const _oldAjax = window.fetch;
if (!_oldAjax.proxiedFetch) {
overrideFetch.proxiedFetch = true;
window.fetch = overrideFetch;
}
// Override the json() function
function interceptedResponse(response) {
console.log('intercept.response', response);
var _oldFn = response.json;
if(!_oldFn) {
return response;
}
response.json = function() {
var p = _oldFn.apply(this, arguments);
if (p.__proto__ == Promise.prototype && typeof interceptedJson != 'undefined') {
return p.then((data) => {
return interceptedJson(data);
});
}
return p;
}
return response;
}
// Attempt to update the decoded data
function interceptedJson(data) {
console.log('intercept.json', data);
try {
updateData(data)
} catch(e) {
console.error(e);
}
return data;
}
function updateData(data) {
console.log('updateData', data);
var LEARNABLE_ID = (new URLSearchParams(window.location.search)).get('learnable_id');
if(!('learnables' in data) || !LEARNABLE_ID) {
return;
}
var learnable = data.learnables && data.learnables.find(x => x.id == LEARNABLE_ID);
Object.assign(data, {
learnables: learnable ? [learnable] : [],
});
}
}
// Inject JS directly in page to prevent limitations of access
var script = document.createElement('script');
script.setAttribute("type", "application/javascript");
script.appendChild(document.createTextNode('('+ main +')();'));
document.body.appendChild(script);
}
}