YouTube Remaining Time

Show the remaining time of a YouTube video inside the player.

目前为 2016-04-25 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name YouTube Remaining Time
  3. // @namespace http://the6p4c.com/
  4. // @version 1.0
  5. // @description Show the remaining time of a YouTube video inside the player.
  6. // @author The6P4C
  7. // @match *://www.youtube.com/*
  8. // @require https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. var TIME_KEYS_ORDER = ["days", "hours", "minutes", "seconds"];
  13. var TIME_KEYS_ORDER_REV = [].concat(TIME_KEYS_ORDER).reverse();
  14.  
  15. function parseTime(timeString) {
  16. // reversed so seconds first
  17. var parts = timeString.split(":").reverse();
  18. var time = {};
  19.  
  20. for (var i = 0; i < TIME_KEYS_ORDER_REV.length; ++i) {
  21. var key = TIME_KEYS_ORDER_REV[i];
  22.  
  23. if (i < parts.length) {
  24. time[key] = parseInt(parts[i]);
  25. } else {
  26. time[key] = 0;
  27. }
  28. }
  29.  
  30. return time;
  31. }
  32.  
  33. function pad2(n) {
  34. if (n >= 10) {
  35. return n;
  36. } else {
  37. return "0" + n;
  38. }
  39. }
  40.  
  41. function stringifyTime(time) {
  42. var timeString = "";
  43. var nonZeroEncountered = false;
  44.  
  45. for (var i = 0; i < TIME_KEYS_ORDER.length; ++i) {
  46. var key = TIME_KEYS_ORDER[i];
  47. var currentValue = time[key];
  48.  
  49. // Only start adding values from the first non zero
  50. // But... always show minutes, even if they're zero.
  51. if (currentValue !== 0 || nonZeroEncountered || key == "minutes") {
  52. // We don't want to pad the first value:
  53. // If there's hours, don't pad days
  54. // If there's minutes, don't pad hours
  55. // If there's seconds, don't pad minutes
  56. if (nonZeroEncountered) {
  57. currentValue = pad2(currentValue);
  58. }
  59.  
  60. timeString += currentValue;
  61.  
  62. if (key != "seconds") {
  63. timeString += ":";
  64. }
  65.  
  66. nonZeroEncountered = true;
  67. }
  68. }
  69.  
  70. return timeString;
  71. }
  72.  
  73. function subtractTime(a, b) {
  74. var secondsDiff = a.seconds - b.seconds;
  75. var minutesDiff = a.minutes - b.minutes;
  76. var hoursDiff = a.hours - b.hours;
  77. var daysDiff = a.days - b.days;
  78.  
  79. if (secondsDiff < 0) {
  80. minutesDiff -= 1;
  81. secondsDiff += 60;
  82. }
  83.  
  84. if (minutesDiff < 0) {
  85. hoursDiff -= 1;
  86. minutesDiff += 60;
  87. }
  88.  
  89. if (hoursDiff < 0) {
  90. daysDiff -= 1;
  91. hoursDiff += 24;
  92. }
  93.  
  94. return {
  95. days: daysDiff,
  96. hours: hoursDiff,
  97. minutes: minutesDiff,
  98. seconds: secondsDiff
  99. };
  100. }
  101.  
  102. function onTimeChange() {
  103. var $this = $(this);
  104.  
  105. // If this event was called in the context of the .ytp-time-duration event,
  106. // we need to set $timeCurrent not to $this but to the actual
  107. // .ytp-time-current element.
  108. var $timeCurrent = $this;
  109. if (!$this.hasClass("ytp-time-current")) {
  110. $timeCurrent = $this.parent().find(".ytp-time-current");
  111. }
  112.  
  113. var $timeDisplay = $timeCurrent.parent();
  114. var $timeDuration = $timeDisplay.parent().find(".ytp-time-duration");
  115.  
  116. if ($timeDisplay.attr("____remaining-added") != "____remaining-added") {
  117. var $timeRemainingWrapper = $("<div style='display: inline-block; width: 5px;'></div><span style='color: #ddd; text-shadow: 0 0 2px rgba(0,0,0,.5)'>(-<span class='____time-remaining'></span>)</span>");
  118. $timeDuration.after($timeRemainingWrapper);
  119.  
  120. $timeDisplay.attr("____remaining-added", "____remaining-added");
  121. }
  122.  
  123. var $timeRemaining = $timeDisplay.find(".____time-remaining");
  124.  
  125. var currentTime = parseTime($timeCurrent.text());
  126. var durationTime = parseTime($timeDuration.text());
  127. var remainingTime = subtractTime(durationTime, currentTime);
  128.  
  129. $timeRemaining.text(stringifyTime(remainingTime));
  130. }
  131.  
  132. $(document).ready(function() {
  133. $("body").on("DOMSubtreeModified", ".ytp-time-current", onTimeChange);
  134. $("body").on("DOMSubtreeModified", ".ytp-time-duration", onTimeChange);
  135. });