Memrise Preview Word

Allows to Preview one specific Word

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

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

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==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);
  }
}