Dailymotion: BETA Included By Feature

...

当前为 2014-07-19 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @id www.dailymotion.com-42e0c072-f078-4276-8f84-952524d36896@http://foobar.com/baz
  3. // @name Dailymotion: BETA Included By Feature
  4. // @version 0.9.5
  5. // @namespace http://foobar.com/baz
  6. // @author David Toso
  7. // @description ...
  8. // @include http://www.dailymotion.com/video/*
  9. // @require http://code.jquery.com/jquery-1.9.1.min.js
  10. // @run-at document-end
  11. // ==/UserScript==
  12.  
  13. // TODO:
  14. // 1. reverse order of lookup+render of playlist review. Instead do render (placeholder), lookup, re-place (preview & details)
  15.  
  16. (function($){
  17. var doc = unsafeWindow.document;
  18.  
  19. // Wait for element given by selector to become available
  20. var waitFor = function(selector, cb) {
  21. if ($(selector, doc).get(0)) return cb();
  22. else setTimeout(function(){ waitFor(selector, cb); }, 200);
  23. };
  24.  
  25. // interate pair-wise through the given list
  26. var iter_pairwise = function(list, pair_cb) {
  27. var pair = [], i=0;
  28. while (i<list.length) {
  29. pair.push(list[i++]);
  30. if (i < list.length) pair.push(list[i++]);
  31. pair_cb(pair[0], pair[1]); pair = [];
  32. }
  33. };
  34.  
  35. // Get useful details about the playlist
  36. var getPlaylistDetails = function(playlist_id, playlist_title, playlist_owner, cb) {
  37. GM_xmlhttpRequest({
  38. method: 'GET',
  39. url: 'http://www.dailymotion.com/playlist/'+playlist_id,
  40. onload: function (res) {
  41.  
  42. // build DOM object for playlist page
  43. var listPage = $(res.responseText);
  44.  
  45. // extract relevant info from DOM
  46. var listOwner = $('div.mrg-btm-md.foreground2 a.link-on-hvr', listPage).html();
  47. var listVideos; res.responseText.replace(/(\d+) videos?/, function(_m, _nv) { listVideos = _nv; });
  48. var listItem = $('div.sd_video_listitem',listPage).eq(0);
  49. var gridItem = $('div.sd_video_griditem',listPage).eq(0);
  50. var video_image = listItem.find('div.media-img a.preview_link img.preview').eq(0).attr('data-src') ||
  51. gridItem.find('div.media-img a.preview_link img.preview').eq(0).attr('data-src');
  52. var video_title = listItem.find('div.media-block a.link').eq(0).attr('title') ||
  53. gridItem.find('div.media-block a.link').eq(0).attr('title');
  54.  
  55. // emit playlist information
  56. cb({ playlist_id: playlist_id, title: playlist_title, owner: listOwner, size: listVideos }, /* returns: playlist: { playlist_id, title, owner, size } */
  57. { preview: video_image, title: video_title }); /* previewVideo: { title, previewImageURL } */
  58. }
  59. });
  60. };
  61.  
  62. // Get N'th page of playlists (10 per page).
  63. var getPlaylists = function(video_id, page_no, cb) {
  64. GM_xmlhttpRequest({
  65. method: "GET",
  66. url: "https://api.dailymotion.com/video/"+video_id+"/playlists?page="+page_no+"&limit=10",
  67. onload: function(res) {
  68. var obj = JSON.parse(res.responseText);
  69. cb(obj.list, (page_no > 1), obj.has_more); // returns: list, priorPages?, subsequentPages?
  70. }
  71. });
  72. };
  73.  
  74. // determine your username if logged in
  75. var myUser; $('div.dm_login_info a.media-block',doc).each(function(){ $(this).attr('href').replace(/^\/(.*)/, function(_m, _usr) { myUser = _usr; }); });
  76.  
  77. // fix tab styles (Dailymotion just plain broke this for all users)
  78. $('head',doc).append('<style type="text/css"> ul.mo_tabs > li > a { position: relative; z-index: 9999; } </style>');
  79.  
  80. // Render a single playlist preview inside the given elem
  81. var display_playlist_preview = function(elem, playlist, preview) {
  82. var ownerStyle = (myUser === playlist.owner) ? 'color: white; background-color: #0079B8; ' : 'color: #42AEDC';
  83. elem.append(
  84. '<table style="width: 293px; height: 85px; border-collapse: collapse; border: 0px; margin: 0px; margin-left: 6px; display:none"><tr>'+
  85. '<td style="width:136px;"><a href="http://www.dailymotion.com/playlist/'+playlist.playlist_id+'" style="width: 136px;">'+
  86. '<img style="width: 136px; height: 80px;" src="'+preview.preview+'" alt="'+preview.title+'"></a></td>'+
  87. '<td align="left" valign="top" style="padding-left: 5px; width: 157px;">'+
  88. '<a style="font-size: 12px; font-weight: bold; color: #0079B8" href="http://www.dailymotion.com/playlist/'+playlist.playlist_id+'">'+playlist.title+'</a><br>'+
  89. '<span style="font-size: 11px; color: black;">by <a href="http://www.dailymotion.com/'+playlist.owner+'" style="'+ownerStyle+'">'+playlist.owner+'</a></span><br>'+
  90. (playlist.size ? playlist.size+' video'+(playlist.size > 1 ? 's' : '') : '')+'</td>'+
  91. '</tr></table>').children('table').fadeIn(1000);
  92. };
  93.  
  94. // Add playlist preview to container
  95. var add_playlist_preview = function(container, pl_entry) {
  96. if (pl_entry == undefined) return;
  97. container.append('<div id="myPlaylists_pl_'+pl_entry.id+'" style="display: inline-block; width: 293px; margin: 0px; padding: 0px; "></div>');
  98. getPlaylistDetails(pl_entry.id, pl_entry.name, pl_entry.owner, function(playlist, preview){
  99. display_playlist_preview($('#myPlaylists_pl_'+playlist.playlist_id, doc), playlist, preview);
  100. });
  101. };
  102.  
  103. // Add prev/next page navigation link
  104. var add_navigation = function(container, elem, video_id, label, pageNo, loadingElem, prevElem, nextElem) {
  105. elem.html('<a style="font-family: arial; font-size: 13px;" href="javascript:void(0)">'+label+'</a>').children('a').click(function(){
  106. render_playlists_page(container, video_id, parseInt(pageNo) + 1, loadingElem, prevElem, nextElem);
  107. });
  108. };
  109.  
  110. // Render a page of playlists previews
  111. var render_playlists_page = function(container, video_id, pageNo, loadingElem) {
  112. // display loading indicator
  113. loadingElem.html('<p>Loading<span style="text-decoration: blink">...</span></p>');
  114.  
  115. // get pageNo of full lists of playlists which include this video
  116. getPlaylists(video_id, pageNo, function(list, canGoPrev, canGoNext){
  117.  
  118. // panel layout
  119. container.find('.myPlaylists_loading').remove();
  120. container.find('.myPlaylists_listing').remove();
  121. container.append('<ul class="myPlaylists_listing" style="margin-top: 10px"></ul>');
  122. var listing = $('.myPlaylists_listing', doc);
  123. // navigation interface
  124. $('.myPlaylists_navigation').remove();
  125. var navStyle = 'width: 595px; height: 15px; position: relative; top: 5px;';
  126. listing.before('<table class="myPlaylists_navigation" style="'+navStyle+'"><tr><td align="left" style="padding-left: 5px;" class="myPlaylists_goBack"></td><td align="right" class="myPlaylists_goForward"></td></tr></table>');
  127. listing.after('<table class="myPlaylists_navigation" style="'+navStyle+'"><tr><td align="left" style="padding-left: 5px;" class="myPlaylists_goBack"></td><td align="right" class="myPlaylists_goForward"></td></tr></table>');
  128. var prevElem = container.find('.myPlaylists_goBack'), nextElem = container.find('.myPlaylists_goForward');
  129. if (canGoPrev) add_navigation(container, prevElem, video_id, '<span class="pagination_arrow">◄</span> previous', parseInt(pageNo) - 1, loadingElem, prevElem, nextElem);
  130. if (canGoNext) add_navigation(container, nextElem, video_id, 'next <span class="pagination_arrow">►</span>', parseInt(pageNo) + 1, loadingElem, prevElem, nextElem);
  131.  
  132. // add playlist previews in two columns of 5 videos each
  133. iter_pairwise(list, function(left, right) {
  134. var li = $('<li style="margin-left: 10px; padding: 5px;"></li>', doc);
  135. listing.append(li); add_playlist_preview(li, left); add_playlist_preview(li, right);
  136. });
  137. });
  138. };
  139.  
  140. // when the video tabs are availale...
  141. waitFor('.pl_video_tabs ul.mo_tabs', function(){
  142.  
  143. // find tabs & corresponding panels
  144. var tabs = $('.pl_video_tabs ul.mo_tabs', doc);
  145. var panels = $('.pl_video_tabs', doc);
  146.  
  147. // add new 'Included By' tab, and corresponding panel (myPanel)
  148. tabs.append('<li id="tab_myplaylists" class="pull-start mrg-end-lg"><a class="alt-link link-border-color-on-hvr" href="">Included By</li>');
  149. panels.append('<div id="tab_myplaylists_content" class="pl_video_tabmyplaylists tab_content clearfix" style="display: none"></div>');
  150. var myPanel = $('#tab_myplaylists_content', doc);
  151.  
  152. // add title to new panel & loading message
  153. myPanel.append('<h3 class="tab_title clearfix" style="clear:both; margin-left: 18px; font-weight: normal; font-size: 13px; color: #0079B8; font-family: arial;">All playlists which include this video</h3>');
  154. myPanel.append('<p class="myPlaylists_loading"></p>');
  155.  
  156. // get the video id for the current page!
  157. var video_id; $('link[rel="canonical"]', doc).eq(0).attr('href').replace(/\/video\/([^_]+)/, function (_m, _vid) { video_id = _vid; });
  158.  
  159. // render the first page of playlist previews
  160. render_playlists_page(myPanel, video_id, 1, $('.myPlaylists_loading'));
  161.  
  162.  
  163. }); // waitfor
  164. })(jQuery);
  165.  
  166.  
  167.