Greasy Fork 支持简体中文。

Spiegel.de without JavaScript

Enables HTML5 video and lazyloaded images with disabled JavaScript.

  1. // ==UserScript==
  2. // @name Spiegel.de without JavaScript
  3. // @namespace https://greasyfork.org/en/users/8981-buzz
  4. // @version 0.3
  5. // @description Enables HTML5 video and lazyloaded images with disabled JavaScript.
  6. // @license GPLv2
  7. // @noframes
  8. // @author buzz
  9. // @match https://www.spiegel.de/*
  10. // @grant GM.xmlHttpRequest
  11. // @require https://unpkg.com/lazysizes@5.2.2/lazysizes.js
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. function setSource(videoEl, source) {
  18. videoEl.setAttribute('src', source.file);
  19. videoEl.setAttribute('type', source.type);
  20. }
  21.  
  22. async function addVideoTag(image, sources, c) {
  23. let source = sources.find((s) => s.label === sources[0].label);
  24. if (!source) {
  25. source = sources[0];
  26. }
  27.  
  28. const videoEl = document.createElement('video');
  29. videoEl.setAttribute('autoplay', '');
  30. videoEl.setAttribute('controls', '');
  31. videoEl.setAttribute('poster', image);
  32. videoEl.setAttribute('preload', '');
  33. videoEl.setAttribute('width', sources[0].width);
  34. videoEl.setAttribute('height', sources[0].height);
  35. videoEl.style.maxWidth = '100%';
  36. videoEl.style.minWidth = '100%';
  37. videoEl.style.height = 'auto';
  38.  
  39. const sourceSelEl = document.createElement('div');
  40. if (sources.length > 1) {
  41. sourceSelEl.style.textAlign = 'right';
  42. sourceSelEl.style.paddingTop = '0.2rem';
  43. sources.forEach((s) => {
  44. const aEl = document.createElement('a');
  45. aEl.innerText = s.label;
  46. aEl.setAttribute('href', '');
  47. aEl.style.margin = '0 0.4rem';
  48. if (s === source) {
  49. aEl.style.textDecoration = 'underline';
  50. }
  51. aEl.addEventListener('click', (ev) => {
  52. ev.preventDefault();
  53. setSource(videoEl, s);
  54. for (let i = 0; i < sourceSelEl.children.length; i++) {
  55. const aChild = sourceSelEl.children[i]
  56. if (aChild.innerText === s.label) {
  57. aChild.style.textDecoration = 'underline';
  58. } else {
  59. aChild.style.textDecoration = 'none';
  60. }
  61. }
  62. });
  63. sourceSelEl.append(aEl);
  64. });
  65. }
  66.  
  67. const child = c.firstElementChild;
  68. child.style.backgroundColor = 'transparent';
  69. child.style.paddingTop = '0';
  70. child.innerHTML = '';
  71. child.append(videoEl);
  72. child.append(sourceSelEl);
  73. setSource(videoEl, source);
  74. }
  75.  
  76. function processApiResponse(r, c) {
  77. const playlist = r.playlist[0];
  78. const sources = playlist.sources
  79. .filter((s) => s.type.startsWith('video/'))
  80. .sort((a, b) => b.height - a.height)
  81. addVideoTag(playlist.image, sources, c);
  82. }
  83.  
  84. function processContainer(c) {
  85. const { apiUrl, mediaId } = JSON.parse(c.dataset.settings);
  86. GM.xmlHttpRequest({
  87. method: "GET",
  88. url: `${apiUrl}/v2/media/${mediaId}`,
  89. onload: (r) => processApiResponse(JSON.parse(r.responseText), c),
  90. });
  91. }
  92.  
  93. document.querySelectorAll('[data-settings*=apiUrl]').forEach(processContainer);
  94. })();