Sleazy Fork is available in English.

Safari Embedded WebM Support

Lets Safari play embedded WebM videos on supported imageboards: 4chan, 8chan, Gelbooru and Danbooru.

  1. // ==UserScript==
  2. // @name Safari Embedded WebM Support
  3. // @namespace safari-embedded-webm-support
  4. // @version 1.2
  5. // @description Lets Safari play embedded WebM videos on supported imageboards: 4chan, 8chan, Gelbooru and Danbooru.
  6. // @author Calumks
  7. // @grant none
  8. // @run-at document-end
  9. // @match *://boards.4chan.org/*
  10. // @match *://8ch.net/*
  11. // @match *://gelbooru.com/index.php?page=post&*
  12. // @match *://danbooru.donmai.us/posts/*
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. // Create the VLC video player
  19. function createVLC(video) {
  20. let vlc = document.createElement('embed');
  21. vlc.setAttribute('autoplay', true);
  22. vlc.setAttribute('loop', true);
  23. vlc.setAttribute('class', video.getAttribute('class'));
  24. vlc.setAttribute('type', 'application/x-vlc-plugin');
  25. vlc.setAttribute('pluginspage', 'http://www.videolan.org');
  26. vlc.setAttribute('width', 855);
  27. vlc.setAttribute('height', 481);
  28. vlc.setAttribute(
  29. 'target', video.src || video.querySelector('source').src
  30. );
  31. video.after(vlc);
  32. video.setAttribute(
  33. 'style', 'opacity: 0; height: 0; width: 0; display: none'
  34. );
  35. if (document.querySelector('a[title^="4chan X"]')) {
  36. let thumbnail = video.parentNode.querySelector('img');
  37. thumbnail.setAttribute('style', 'display: none');
  38. video.removeAttribute('src');
  39. }
  40. return vlc;
  41. }
  42.  
  43. // Destroy the VLC player
  44. function destroyVLC(video, embed) {
  45. if (document.querySelector('a[title^="4chan X"]')) {
  46. let thumbnail = embed.parentNode.querySelector('img');
  47. thumbnail.removeAttribute('style');
  48. video.src = embed.target;
  49. }
  50. embed.remove();
  51. }
  52.  
  53. // Filter observer nodes to video elements.
  54. function filterNodes(nodes) {
  55. nodes = Array.from(nodes);
  56. let n1 = nodes.filter(n => n instanceof HTMLVideoElement);
  57. let n2 = nodes
  58. .filter(n => n instanceof HTMLElement)
  59. .map(n => n.querySelector('video'))
  60. .filter(n => n);
  61. return n1.concat(n2);
  62. }
  63.  
  64. // Dynamic videos
  65. new MutationObserver(mutations => {
  66. for(let mutation of mutations) {
  67. filterNodes(mutation.addedNodes).map(n => createVLC(n));
  68. filterNodes(mutation.removedNodes).map(n =>
  69. destroyVLC(n, mutation.target.querySelector('embed')));
  70. }
  71. }).observe(document, {attributes: false, childList: true, subtree: true});
  72.  
  73. // On page load
  74. let video = document.querySelector('video');
  75. ! video || createVLC(video);
  76. })();