SPON Video tag

Enables HTML5 video playback on SPON with disabled JavsScript.

当前为 2020-09-03 提交的版本,查看 最新版本

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