Flickr Large Embed

Based on 'Flickr Original Link' (https://greasyfork.org/scripts/1190-flickr-original-link). Adds an 'Embed' field containing HTML code for each photo.

  1. // ==UserScript==
  2. // @name Flickr Large Embed
  3. // @namespace https://greasyfork.org/en/scripts/6699-flickr-large-embed
  4. // @description Based on 'Flickr Original Link' (https://greasyfork.org/scripts/1190-flickr-original-link). Adds an 'Embed' field containing HTML code for each photo.
  5. // @include /flickr\.com/
  6. // @version 2015-05-30
  7. // @grant GM_getValue
  8. // @grant GM_setValue
  9. // @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
  10. // ==/UserScript==
  11. //
  12.  
  13. // TODO : fix 'Loading' bug on photostream
  14.  
  15. var postfix = ".";
  16.  
  17. var imageSizeOrder = [ "o", "k", "h", "l", "c", "z" ];
  18. var globalObserver = null;
  19.  
  20. function log(s) {
  21. console.log(s);
  22. }
  23.  
  24.  
  25. function checkAlwaysShow() {
  26. $('div.interaction-view').css('opacity', '1');
  27. }
  28.  
  29. function action_single_page() {
  30. var strCss = ".commonButton{display:inline-block;cursor:pointer;border-radius:1.5em;margin:0.3em;font-size:90%} .bigButton{border-width:2px;padding:1em;font-weight:bold;border-style:solid} .smallButton{padding:0.5em;background-color:pink}";
  31. $('head').append('<style>' + strCss + '</style>');
  32. var target = $('#content')[0];
  33. var config = {
  34. childList : true,
  35. subtree : true,
  36. };
  37. var action = function(sourceCode) {
  38. var size = sourceCode.match(/modelExport: {.+?"sizes":{.+?}}/i);
  39. var mSize = size[0].match(/"width":"?\d+"?,"height":"?\d+"?,/ig);
  40. var mLink = size[0].match(/"displayUrl":"[^"]+"/ig);
  41. var length = mLink.length;
  42. var embedSize = 0;
  43. var linkSize = 0;
  44. var embedHeight = 0;
  45. var embedWidth = 0;
  46. for (var k = 0; k < length; k++) {
  47. var myArray = mSize[k].match(/:\w+,/g);
  48. var width = parseInt(myArray[0].replace(':','').replace(',',''));
  49. var height = parseInt(myArray[1].replace(':','').replace(',',''));
  50. mLink[k] = "http:" + mLink[k].replace(/"displayUrl":"([^"]+)"/i, "$1").replace(/\\/g, "").replace(/(_[a-z])\.([a-z]{3,4})/i, '$1' + postfix + '$2');
  51. if (embedSize == 0 && (width >= 800 || height >= 600) ) {
  52. embedSize = k;
  53. embedHeight = height;
  54. embedWidth = width;
  55. }
  56.  
  57. if (linkSize == 0 && (width >= 2048 || height >= 1024) ) {
  58. linkSize = k;
  59. }
  60.  
  61. if (embedSize == 0 && k == length-1) {
  62. embedSize = k;
  63. embedHeight = height;
  64. embedWidth = width;
  65. }
  66. if (linkSize == 0 && k == length-1) {
  67. linkSize = k;
  68. }
  69. }
  70. var maxWidth = '';
  71. if (embedHeight < embedWidth) {
  72. // Landscape image: full width and auto-height
  73. maxWidth= 'style="max-width: ' + embedWidth + 'px"';
  74. embedWidth = '100%';
  75. } else {
  76. embedWidth += 'px';
  77. }
  78. var embedHTML = '<p><a href="' + mLink[linkSize] + '" target="_blank" border="0"><img src="' + mLink[embedSize] + '" width="' + embedWidth + '" height="auto" border="0" ' + maxWidth + ' /></a></p>';
  79. var embedBB = '[url=' + mLink[linkSize] + '][img]' + mLink[embedSize] + '[/img][/url]';
  80. var insertLocation = $('.sub-photo-right-row1').filter(':first');
  81. if (insertLocation.length > 0) {
  82. insertLocation.append('<p>Embed</p><div style="color: black; display:block;">HTML <input type="text" name="textfield" onclick="this.select();" style="width:350px;" id="EMBED_HTML" value="Loading"/></div>');
  83. $('#EMBED_HTML').val(embedHTML);
  84. insertLocation.append('<div style="color: black; display:block;">BB <input type="text" name="textfield" onclick="this.select();" style="width:350px;" id="EMBED_BB" value="Loading"/></div>');
  85. $('#EMBED_BB').val(embedBB);
  86. }
  87. };
  88. var oldUrl = document.URL;
  89. $.get(oldUrl, action);
  90. globalObserver = new MutationObserver(function(mutations, ob) {
  91. if (document.URL == oldUrl) return false; // page is not changed
  92. oldUrl = document.URL;
  93. $.get(oldUrl, action);
  94. });
  95. globalObserver.observe(target, config);
  96. }
  97.  
  98. function getLinkFromSource(data) {
  99. if (data === null) return;// source code is not loaded, or empty, or has nothing good
  100. var sizes = data.match(/"sizes":.+?}}/ig);
  101. if (sizes === null) return false; // source code is not loaded, or empty, or has nothing good
  102. var e2 = $('div.photo-list-photo-view').get();
  103. checkAlwaysShow();
  104. for (var index = 0; index < e2.length; index++) {
  105. var e = $(e2[index]);
  106. if (e.find('.myEmbedLink').filter(':first').length > 0) continue;
  107. //e.find('.interaction-bar').append('<div class="myEmbedLink" style="color: white; display: block; opacity: 0.5">HTML <input type="text" name="textfield" onclick="this.select();" style="width:100px;" value="Loading" class="htmlCode"/> BB <input type="text" name="textfield" onclick="this.select();" style="width:100px;" value="Loading" class="bbCode"/></div>');
  108. e.find('.interaction-bar').css('padding-bottom', '15px');
  109. e.append('<div class="myEmbedLink" style="color: white; display: block; opacity: 0.5">HTML <input type="text" name="textfield" onclick="this.select();" style="width:100px;" value="Loading" class="htmlCode"/> BB <input type="text" name="textfield" onclick="this.select();" style="width:100px;" value="Loading" class="bbCode"/></div>');
  110. var embedUrl = false;
  111. var linkUrl = false;
  112. var currentEmbedWidth = 100000;
  113. var currentEmbedHeight = 100000;
  114. var currentLinkWidth = 100000;
  115. var currentLinkHeight = 100000;
  116. var maxWidth = 0;
  117. var maxHeight = 0;
  118. var maxUrl = false;
  119. for (var i = 0; i < imageSizeOrder.length; ++i) {
  120. var photo = sizes[index].match(new RegExp('"' + imageSizeOrder[i] + '":{"displayUrl":"([^"]+)","width":(\\d+),"height":(\\d+)', "i"));
  121. if (photo === null) continue;
  122. var width = parseInt(photo[2]);
  123. var height = parseInt(photo[3]);
  124. var url = "http:" + photo[1].replace(/\\/g, "").replace(/(_[a-z])\.([a-z]{3,4})/i, '$1' + postfix + '$2');
  125. if ((width >= 800 || height >= 600) && width < currentEmbedWidth && height < currentEmbedHeight) {
  126. embedUrl = url;
  127. currentEmbedHeight = height;
  128. currentEmbedWidth = width;
  129. }
  130.  
  131. if ((width >= 2048 || height >= 1024) && width < currentLinkWidth && height < currentLinkHeight ) {
  132. linkUrl = url;
  133. currentLinkHeight = height;
  134. currentLinkWidth = width;
  135. }
  136.  
  137. if (width > maxWidth && height > maxHeight) {
  138. maxWidth = width;
  139. maxHeight = height;
  140. maxUrl = url;
  141. }
  142. }
  143. if (!linkUrl) {
  144. linkUrl = maxUrl;
  145. currentLinkHeight = maxHeight;
  146. currentLinkWidth = maxWidth;
  147. }
  148. if (!embedUrl) {
  149. embedUrl = maxUrl;
  150. currentEmbedHeight = maxHeight;
  151. currentEmbedWidth = maxWidth;
  152. }
  153.  
  154. if (linkUrl && embedUrl) {
  155. var maxWidth= '';
  156. if (currentEmbedHeight < currentEmbedWidth) {
  157. // Landscape image: full width and auto-height
  158. maxWidth= 'style="max-width: ' + currentEmbedWidth + 'px"';
  159. currentEmbedWidth = '100%';
  160. } else {
  161. currentEmbedWidth += 'px';
  162. }
  163. var htmlCode = '<p><a href="' + linkUrl + '" target="_blank" border="0"><img src="' + embedUrl + '" width="' + currentEmbedWidth + '" height="auto" border="0" ' + maxWidth + ' /></a></p>';
  164. var bbCode = '[url=' + linkUrl + '][img]' + embedUrl + '[/img][/url]';
  165.  
  166. e.find('.htmlCode').val(htmlCode);
  167. e.find('.bbCode').val(bbCode);
  168. }
  169. }
  170. }
  171.  
  172. function load_links(sourceCode) {
  173. // empty
  174. }
  175.  
  176. function action_normal_page() {
  177. var target = $('#content')[0];
  178. var config = {
  179. childList : true,
  180. subtree : true,
  181. };
  182. var strCss = ".myEmbedLink{position:absolute;right:3px;bottom:0px;z-index:999;display:inline-block;color:white!important;}";
  183. $('head').append('<style>' + strCss + '</style>');
  184. var prevLink = "none";
  185. var prevUrl = "none";
  186. var prevThumbLength = 0;
  187. var sourceCode = null;
  188.  
  189. var action = function() {
  190. var e3 = $('div.photo-list-photo-view');
  191. if (document.URL == prevUrl) {
  192. if (e3.length == prevThumbLength) return false; // number of thumbnail is not change, no need to process further
  193. prevThumbLength = e3.length;
  194. log("Number of thumb: " + prevThumbLength);
  195. // source code is get, use it now
  196. getLinkFromSource(sourceCode);
  197. }
  198. else {
  199. var e1 = e3.find('a').filter(':first');
  200. if (e1.length < 1) return false; // not found any link to valid single image page
  201. // show image information for newly added nodes
  202. // get full source code for this page
  203. sourceCode = null;
  204. prevUrl = document.URL;
  205. var link1 = e1.attr('href');
  206. console.time("GetSource");
  207. $('#content').append('<div id="embedLoadingIndicator" style="position:fixed;left:5px;top:4em;display:block;background-color:pink;border:solid;padding:3px; z-index:999;">Getting embed links<br>Please wait...</div>');
  208. log("Begin find source code, start with: " + link1);
  209. $.get(link1, function(data) {// process single image page source to get entry-type link
  210. var link2 = data.match(/<a\s+class='entry-type'\s+href='([^']+)/i)[1];
  211. $.get(link2, function(data) {// process page source to get image links
  212. log("Got page source: " + link2);
  213. console.timeEnd("GetSource");
  214. $('#embedLoadingIndicator').remove();
  215. sourceCode = data;
  216. getLinkFromSource(sourceCode);
  217. });
  218. });
  219. }
  220. }
  221. action();
  222. globalObserver = new MutationObserver(function(mutations, ob) {
  223. action();
  224. });
  225. globalObserver.observe(target, config);
  226. }
  227.  
  228. function pageType() {
  229. var t = "none";
  230. var htmlClass = $('html').attr('class');
  231. console.log("HTML class: " + htmlClass);
  232. if (htmlClass.match(/html-photo-page.+scrappy-view/i) !== null) t = 'single';
  233. else if (htmlClass.match(/html-search-photos-unified-page-view/i) !== null) t = 'hover';
  234. else if ($('div.photo-list-photo-view').filter(':first').length > 0) t = 'normal';
  235. console.log("Page type: " + t);
  236. return t;
  237. }
  238.  
  239. var target = $('html')[0];
  240. var config = {
  241. childList : false,
  242. attributes : true,
  243. };
  244.  
  245. var prevType = "none";
  246. var type = "none";
  247. var observer = new MutationObserver(function(mutations, ob) {
  248. type = pageType();
  249. if (type != prevType) {
  250. if (globalObserver != null) {
  251. globalObserver.disconnect();
  252. }
  253. prevType = type;
  254. if (type == 'single') {
  255. action_single_page();
  256. } else if (type == 'normal') {
  257. action_normal_page();
  258. }
  259. }
  260. });
  261. observer.observe(target, config);