player.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. function DGPlayer(root) {
  2. // Get elements
  3. var events = {},
  4. state = 'paused';
  5. // Preload images
  6. new Image().src = "/dgplayer/resources/playbutton_active.png";
  7. new Image().src = "/dgplayer/resources/pausebutton.png";
  8. new Image().src = "/dgplayer/resources/pausebutton_active.png";
  9. new Image().src = "/dgplayer/resources/choosefile_pressed.png";
  10. // Prevent text selection in IE
  11. root.onselectstart = function() {
  12. return false
  13. }
  14. var seekBar = (function() {
  15. var loading = root.querySelector(".seek .track .loaded"),
  16. progress = root.querySelector(".seek .track .progress"),
  17. played = root.querySelector(".seek span:first-child"),
  18. remaining = root.querySelector(".seek span:last-child"),
  19. maxWidth = loading.parentNode.offsetWidth - 2,
  20. loaded = 0, currentTime = 0, trackLength = 0, oldSeconds = 0;
  21. function pad(input) {
  22. return ("00" + input).slice(-2);
  23. }
  24. return {
  25. getTrackLength: function() {
  26. return trackLength;
  27. },
  28. setTrackLength: function(time) {
  29. trackLength = time;
  30. this.seekTime = currentTime;
  31. },
  32. getCurrentTime: function() {
  33. return currentTime;
  34. },
  35. setCurrentTime: function(time) {
  36. oldSeconds = Math.floor(currentTime / 1000 % 60);;
  37. currentTime = time;
  38. if (currentTime >= trackLength && trackLength > 0)
  39. emit("pause");
  40. var t = currentTime / 1000,
  41. seconds = Math.floor(t % 60),
  42. minutes = Math.floor((t /= 60) % 60);
  43. if (seconds === oldSeconds)
  44. return;
  45. played.innerHTML = minutes + ':' + pad(seconds);
  46. // only show the progress bar and remaining time if we know the duration
  47. if (trackLength > 0) {
  48. var r = (trackLength - currentTime) / 1000,
  49. remainingSeconds = Math.floor(r % 60),
  50. remainingMinutes = Math.floor((r /= 60) % 60);
  51. remaining.innerHTML = '-' + remainingMinutes + ':' + pad(remainingSeconds);
  52. position = Math.max(0, Math.min(1, currentTime / trackLength));
  53. progress.style.width = maxWidth * position + 'px';
  54. } else {
  55. remaining.innerHTML = '-0:00';
  56. }
  57. },
  58. getAmountLoaded: function() {
  59. return loaded;
  60. },
  61. setAmountLoaded: function(val) {
  62. loaded = Math.max(0, Math.min(100, val));
  63. loading.style.width = maxWidth * (loaded / 100) + 'px';
  64. }
  65. }
  66. })();
  67. var playpause = (function() {
  68. var button = root.querySelector(".button"),
  69. interval = null, playing = false;
  70. button.onclick = function() {
  71. emit(playing ? "pause" : "play");
  72. };
  73. root.addEventListener('keyup', function(e) {
  74. e.which === 32 && emit(playing ? "pause" : "play");
  75. });
  76. function setPlaying(play) {
  77. if (playing = play)
  78. button.classList.add("pause");
  79. else
  80. button.classList.remove("pause");
  81. }
  82. return {
  83. setPlaying: setPlaying,
  84. getPlaying: function() {
  85. return playing;
  86. }
  87. }
  88. })();
  89. var slider = (function() {
  90. var handle = root.querySelector(".volume .handle"),
  91. progress = root.querySelector(".volume .progress"),
  92. track = root.querySelector(".volume .track")
  93. volumeLeft = root.querySelector(".volume img:first-child"),
  94. volumeRight = root.querySelector(".volume img:last-child");
  95. var lastY = 0,
  96. down = false,
  97. height = 65,
  98. handleSize = 20,
  99. min = -8,
  100. max = height - handleSize / 2 - 3,
  101. curY = Math.floor(height / 2 - handleSize / 2),
  102. value = 50;
  103. function update(dontEmit) {
  104. if ('webkitTransform' in handle.style)
  105. handle.style.webkitTransform = "translate3d(0, " + (-max - min + curY) + "px" + ", 0)";
  106. else
  107. handle.style.bottom = max + min - curY + "px";
  108. progress.style.height = max - curY + "px";
  109. value = Math.round(100 - (curY - min) / (max - min) * 100);
  110. if (!dontEmit)
  111. emit("volume", value);
  112. }
  113. update();
  114. handle.onmousedown = handle.ontouchstart = function(e) {
  115. lastY = e.targetTouches ? e.targetTouches[0].pageY : e.clientY;
  116. down = true;
  117. e.stopPropagation();
  118. handle.classList.add("active");
  119. e.preventDefault();
  120. }
  121. function onMove(e) {
  122. var eventY = e.targetTouches ? e.targetTouches[0].pageY : e.clientY;
  123. var y = Math.max(min, Math.min(max, curY + eventY - lastY));
  124. if (!down || y === curY) return;
  125. curY = y;
  126. lastY = eventY;
  127. update();
  128. }
  129. function onUp(e) {
  130. if(!down) return;
  131. down = false;
  132. handle.classList.remove("active");
  133. }
  134. document.addEventListener("mousemove", onMove, false);
  135. document.addEventListener("touchmove", onMove, false);
  136. document.addEventListener("mouseup", onUp, false);
  137. document.addEventListener("touchend", onUp, false);
  138. // Handle clicking on the minimum and maximum volume icons
  139. function animate() {
  140. handle.classList.add("animatable");
  141. progress.classList.add("animatable");
  142. update();
  143. setTimeout(function() {
  144. handle.classList.remove("animatable");
  145. progress.classList.remove("animatable");
  146. }, 250);
  147. }
  148. volumeLeft.onclick = function() {
  149. curY = min;
  150. animate();
  151. }
  152. volumeRight.onclick = function() {
  153. curY = max;
  154. animate();
  155. }
  156. // Handle clicking on the track
  157. track.onmousedown = track.ontouchstart = function(e) {
  158. var y = e.targetTouches ? e.targetTouches[0].pageY : e.clientY;
  159. // Get the absolute offsetTop of the track
  160. var offset = 0, obj = track;
  161. while (obj) {
  162. offset += obj.offsetTop - obj.scrollTop;
  163. obj = obj.offsetParent;
  164. }
  165. curY = Math.max(min, Math.min(max, y - offset - (handleSize + min)));
  166. handle.onmousedown(e);
  167. update();
  168. }
  169. return {
  170. getValue: function() {
  171. return value;
  172. },
  173. setValue: function(val) {
  174. val = Math.max(0, Math.min(100, val));
  175. curY = max - (val / 100) * (max - min);
  176. update(true);
  177. }
  178. }
  179. })();
  180. var filebutton = (function() {
  181. var button = root.querySelector('.file_button'),
  182. input = document.createElement('input');
  183. input.setAttribute('type', 'file');
  184. input.style.opacity = 0;
  185. input.style.position = 'absolute';
  186. input.style.left = '-1000px';
  187. input.onchange = function(e) {
  188. emit('file', input.files[0]);
  189. }
  190. button.onclick = function() {
  191. input.click();
  192. console.log("bbbbbbbbbbbbb");
  193. }
  194. })();
  195. function emit(event) {
  196. if (!events[event]) return;
  197. var args = Array.prototype.slice.call(arguments, 1),
  198. callbacks = events[event];
  199. for (var i = 0, len = callbacks.length; i < len; i++) {
  200. callbacks[i].apply(null, args);
  201. }
  202. }
  203. var API = {
  204. on: function(event, fn) {
  205. events[event] || (events[event] = []);
  206. events[event].push(fn);
  207. },
  208. off: function(event, fn) {
  209. var eventsOf = events[event],
  210. index = eventsOf.indexOf(fn);
  211. ~index && eventsOf.splice(index, 1);
  212. }
  213. };
  214. // Object.defineProperty shim for Opera
  215. Object.defineProperty || (Object.defineProperty = function(obj, prop, config) {
  216. if (config.get && obj.__defineGetter__)
  217. obj.__defineGetter__(prop, config.get);
  218. if (config.set && obj.__defineSetter__)
  219. obj.__defineSetter__(prop, config.set);
  220. })
  221. Object.defineProperty(API, "bufferProgress", {
  222. get: seekBar.getAmountLoaded,
  223. set: seekBar.setAmountLoaded
  224. });
  225. Object.defineProperty(API, "state", {
  226. set: function(newstate) {
  227. playpause.setPlaying(newstate == 'playing' || newstate == 'buffering');
  228. state = newstate;
  229. },
  230. get: function() {
  231. return state;
  232. }
  233. });
  234. Object.defineProperty(API, "duration", {
  235. get: seekBar.getTrackLength,
  236. set: seekBar.setTrackLength
  237. });
  238. Object.defineProperty(API, "seekTime", {
  239. get: seekBar.getCurrentTime,
  240. set: seekBar.setCurrentTime
  241. });
  242. Object.defineProperty(API, "volume", {
  243. get: slider.getValue,
  244. set: slider.setValue
  245. });
  246. var img = root.querySelector(".avatar img");
  247. Object.defineProperty(API, "coverArt", {
  248. get: function() {
  249. return img.src;
  250. },
  251. set: function(src) {
  252. img.src = src;
  253. }
  254. });
  255. var title = root.querySelector("span.title"),
  256. artist = root.querySelector("span.artist");
  257. Object.defineProperty(API, "songTitle", {
  258. get: function() {
  259. return title.innerHTML;
  260. },
  261. set: function(val) {
  262. title.innerHTML = val;
  263. }
  264. });
  265. Object.defineProperty(API, "songArtist", {
  266. get: function() {
  267. return artist.innerHTML;
  268. },
  269. set: function(val) {
  270. artist.innerHTML = val;
  271. }
  272. });
  273. var description = root.querySelector('.file_description');
  274. Object.defineProperty(API, "fileDescription", {
  275. get: function() {
  276. return description.innerHTML;
  277. },
  278. set: function(val) {
  279. description.innerHTML = val;
  280. }
  281. });
  282. return API;
  283. }