netflix progress and title indicator

adds div with the current title and time use 't' to add "hidden" style to the div along with some default style

  1. // ==UserScript==
  2. // @name netflix progress and title indicator
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.3
  5. // @description adds div with the current title and time use 't' to add "hidden" style to the div along with some default style
  6. // @author Me
  7. // @match https://www.netflix.com/*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. function title_getter() {
  12. var vid, title = "", on = false;
  13. function refresh_title () {
  14. try {
  15. let divs = document.querySelectorAll(".video-title div *");
  16. if(divs.length === 0){
  17. divs = document.querySelectorAll(".video-title *");
  18. }
  19. title = Array.from(divs).map((x)=>x.textContent).join(" ");
  20. } catch(e) {
  21. title = "";
  22. }
  23. }
  24. function refresh_enabled () {
  25. vid = document.querySelector(".AkiraPlayer video");
  26. if(vid === null && on) {
  27. on = false;
  28. return;
  29. }
  30. if(vid !== null && !on) {
  31. on = true;
  32. }
  33. }
  34. function time() {
  35. try {
  36. let cur = +vid.currentTime;
  37. let dur = +vid.duration;
  38. return { cur: cur, dur: dur };
  39. } catch(e) {
  40. return { cur: 0, dur: 0 };
  41. }
  42. }
  43. return { title: function () { return title; }, time, refresh_title, refresh_enabled, enabled: function () { return on; } };
  44. }
  45.  
  46. function reappend (n) {
  47. var w = document.querySelector(".sizing-wrapper");
  48. if(w !== null){
  49. if(w.contains(n)) {
  50. return;
  51. }
  52. w.appendChild(n);
  53. }
  54. }
  55. function node(cls, c) {
  56. var parent = document.createElement("div");
  57. var text = document.createTextNode("");
  58. parent.appendChild(text);
  59. if(c != null) {
  60. for(var n of c) {
  61. parent.appendChild(n);
  62. }
  63. }
  64. var current;
  65. var hidden = false;
  66. parent.className = cls;
  67. return {
  68. n: parent,
  69. set: function (value) {
  70. if(value == null) {
  71. return;
  72. }
  73. value = value.toString();
  74. if(current != value) {
  75. text.textContent = value;
  76. current = value;
  77. }
  78. },
  79. hide: function () { if(hidden) return; hidden = true; parent.className = cls + " hidden"; },
  80. show: function () { if(!hidden) return; hidden = false; parent.className = cls; }
  81. };
  82. }
  83.  
  84. function p(number) {
  85. return (number < 10 ? '0' : '') + number;
  86. }
  87.  
  88. var CreateStyle = function () {
  89. function DynamicCss () {
  90. var s = document.createElement("style");
  91. s.setAttribute("type", "text/css");
  92. s.setAttribute("rel", 'stylesheet');
  93. s.setAttribute("media", 'screen');
  94. document.head.appendChild(s);
  95. this.e_container = s;
  96. this.rules = {};
  97. }
  98.  
  99. var state = 0;
  100. DynamicCss.prototype = {
  101. addRule: function (name, selector) {
  102. if(arguments.length == 1) {
  103. selector = name;
  104. name = ++state;
  105. }
  106. if(this.rules[name]) {
  107. return this.rules[name];
  108. }
  109. var r = this.rules[name] = new DynamicRule(selector);
  110. this.e_container.appendChild(r.e_container);
  111. console.log("RULE", this);
  112. return r;
  113. },
  114. getRule: function (name) {
  115. return this.rules[name];
  116. },
  117. removeRule: function (name) {
  118. if(this.rules[name]) {
  119. var r = this.rules[name];
  120. delete this.rules[name];
  121. this.e_container.removeChild(r.e_container);
  122. }
  123. }
  124. };
  125.  
  126. function DynamicRule (selector) {
  127. var rule = this.e_container = document.createDocumentFragment();
  128. rule.appendChild(document.createTextNode(selector + "{"));
  129. var innerRule = this.e_rules = document.createTextNode("");
  130. rule.appendChild(innerRule);
  131. rule.appendChild(document.createTextNode("}\n"));
  132. this.rules = {};
  133. }
  134. DynamicRule.prototype = {
  135. setDeclarations: function (declarations) {
  136. for(var key in declarations) {
  137. this.rules[key] = declarations[key];
  138. }
  139. this.redraw();
  140. },
  141. setDeclaration: function (key, value) {
  142. this.rules[key] = value;
  143. this.redraw();
  144. },
  145. removeDeclaration: function (key) {
  146. delete this.rules[key];
  147. this.redraw();
  148. },
  149. redraw: function () {
  150. var rule = "", a = this.rules, isFirst = true;
  151. for(var key in a){
  152. rule += (!isFirst?";":(isFirst=false||"")) + key + ":" + a[key];
  153. }
  154. this.e_rules.nodeValue = rule;
  155. }
  156. };
  157.  
  158. return function () { return new DynamicCss(); }
  159. }();
  160.  
  161. (function() {
  162. var data = title_getter();
  163. function fmt_time(s) {
  164. s = s | 0;
  165. var h = (s / 3600)|0;
  166. s = s - h * 3600;
  167. var m = (s / 60)|0;
  168. s = s - m * 60;
  169. return `${p(h)}:${p(m)}:${p(s)}`;
  170. }
  171. var title = node("title");
  172. var time = node("time");
  173. var wholeTitleNode = node("myTitleNode", [title.n, time.n]);
  174. // css
  175. var style = CreateStyle();
  176. style.addRule(".myTitleNode.hidden").setDeclaration("display", "none");
  177. style.addRule(".myTitleNode").setDeclarations({
  178. top: "10px",
  179. position: "fixed",
  180. left: "10px",
  181. color: "white",
  182. right: "10px",
  183. "z-index": "100",
  184. "font-size": "2em"
  185. });
  186. style.addRule(".myTitleNode .title").setDeclaration("float", "left");
  187. style.addRule(".myTitleNode .time").setDeclaration("float", "right");
  188.  
  189. document.body.appendChild(wholeTitleNode.n);
  190. setInterval(data.refresh_title, 5000);
  191. var shown = false;
  192. document.body.addEventListener('keypress', function (e) {
  193. if(e.key == 't') {
  194. shown = shown ? false : true;
  195. refresh();
  196. }
  197. });
  198. function refresh () {
  199. data.refresh_enabled();
  200. reappend(wholeTitleNode.n);
  201. if(data.enabled() && shown) {
  202. wholeTitleNode.show();
  203. } else {
  204. wholeTitleNode.hide();
  205. return;
  206. }
  207. var my_tit = data.title();
  208. title.set(my_tit);
  209. let t = data.time();
  210. time.set(`${fmt_time(t.cur)} / ${fmt_time(t.dur)}`);
  211. }
  212. setInterval(refresh, 500);
  213. })();