Google+ Photos Download

Download Google+ Album using Picasa, showing all full size images in new tab

  1. // ==UserScript==
  2. // @name Google+ Photos Download
  3. // @description Download Google+ Album using Picasa, showing all full size images in new tab
  4. // @author vinsai
  5. // @version 1.6.0
  6. // @include *.google.com/*
  7. // @require https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js
  8. // @namespace https://greasyfork.org/users/7446
  9. // ==/UserScript==
  10. var MAX_IMAGES = 100;
  11.  
  12. GM_registerMenuCommand("G+->Maximum Images", SetMax);
  13.  
  14. function SetMax() {
  15. var maximum = prompt("Maximum Number of Images to show:",GM_getValue(MAX_IMAGES, 30));
  16.  
  17. maximum = parseInt(maximum, 10);
  18. GM_setValue(MAX_IMAGES, maximum);
  19. }
  20.  
  21. function getDocHeight() {
  22. //utility function to find dimensions of page
  23. var D = document;
  24. return Math.max(
  25. Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),
  26. Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
  27. Math.max(D.body.clientHeight, D.documentElement.clientHeight)
  28. );
  29. }
  30.  
  31. (function()
  32. {
  33.  
  34. var css =
  35. '<style type="text/css">\n\
  36. img {margin: 5px auto;}\n\
  37. #imagesCollection {display:table-cell;vertical-align:middle;text-align:center;}\n\
  38. a {color:white;text-align:center;}\n\
  39. body {background-color:black;width:99%;height:98%;display:table;font-family:"メイリオ",Meiryo;}\n\
  40. </style>\n';
  41. var plainTextCSS =
  42. '<style type="text/css">\n\
  43. #imagesCollection {vertical-align:middle;text-align:left;}\n\
  44. a {color:white;text-align:left;}\n\
  45. body {background-color:black;font-family:"メイリオ",Meiryo;}\n\
  46. </style>\n';
  47. var js =
  48. '<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>\n\
  49. <script type="text/javascript">\n\
  50. function setMaxWidth(){\n\
  51. var mwidth = $(document).width()-15;\n\
  52. $("img").css("max-width", mwidth);\n\
  53. }\n\
  54. $(document).ready(function(){\n\
  55. setMaxWidth();\n\
  56. });\n\
  57. $(window).resize(function(){\n\
  58. setMaxWidth();\n\
  59. });\n\
  60. </script>\n';
  61.  
  62. var append = '<div id="gplus"><div class="d-k-l b-c b-c-R b-c-da-ja mFd i1d" id="PicasaDownload">Picasa</div>';
  63.  
  64. append += '<div class="d-k-l b-c b-c-R b-c-da-ja mFd i1d" id="NewPage">Full Size Images</div>';
  65. append += '<div class="d-k-l b-c b-c-R b-c-da-ja mFd i1d" id="ScrollToBottom">︾</div></div>';
  66.  
  67.  
  68. // var d = document.querySelector('#gbvg>.gbtc>.gbt');
  69. var d = document.querySelector('body');
  70. d.insertAdjacentHTML('beforeEnd', append);
  71. // console.log($('.Koa').offset());
  72. // console.log($('.Koa').offset().top);
  73. $('#gplus').css('top', 12);
  74. $('#gplus').css('left', $(document).width()-600);
  75. $('#gplus').css('position', 'fixed');
  76. $('#gplus').css('z-index', 1000);
  77. //===============================================================================
  78. // - Scroll to bottom -
  79. //===============================================================================
  80.  
  81. var scrolling = false;
  82. var terminate = false;
  83.  
  84. $('#ScrollToBottom').click(function(e) {
  85. if (scrolling == false) {
  86. scrolling = true;
  87. terminate = false;
  88. }
  89. else {
  90. scrolling = false;
  91. terminate = true;
  92. }
  93. var delay = 100;
  94. var retry = 30;
  95. var fail = 0;
  96. var top = 0;
  97. function scrollB() {
  98. if (terminate == false) {
  99. var mTop = getDocHeight() + $(window).height();
  100.  
  101. if ( top < mTop) {
  102. top = mTop;
  103. fail = 0;
  104. // $(document).scrollTop(mTop);
  105. $('html, body').animate({scrollTop:mTop}, 200);
  106. setTimeout(scrollB,delay);
  107. }
  108. else if (fail < retry) {
  109. fail++;
  110. setTimeout(scrollB,delay);
  111. }
  112. else {
  113. scrolling = false;
  114. }
  115. }
  116. }
  117. scrollB();
  118. });
  119. //===============================================================================
  120. // - End of Scroll to bottom -
  121. //===============================================================================
  122. //===============================================================================
  123. // - Picasa Download -
  124. //===============================================================================
  125. $('#PicasaDownload').click(function() {
  126. var currentPage = location.href;
  127.  
  128. if (currentPage.search('plus.google.com/') != -1 && currentPage.search('/photos/') != -1 && currentPage.search('/albums/') != -1) {
  129. var findex = currentPage.indexOf("photos");
  130. if (findex > 0) {
  131. findex += 7;
  132. var lindex = currentPage.indexOf("/albums/");
  133. if(lindex >0) {
  134. var userID
  135. var albumID;
  136. userID = currentPage.substr(findex, lindex-findex);
  137. findex = lindex + 8;
  138. lindex = currentPage.lastIndexOf("/");
  139. if (findex == lindex) {
  140. albumID = currentPage.substr(findex);
  141. }
  142. else {
  143. albumID = currentPage.substr(findex, lindex);
  144. }
  145. var picasa_dl_url = 'picasa://downloadfeed/'
  146. + '?url=https://picasaweb.google.com/data/feed/back_compat'
  147. + '/user/' + userID + '/albumid/' + albumID
  148. + '?kind=photo&alt=rss&imgdl=1';
  149. window.location = picasa_dl_url;
  150. }
  151. }
  152. }
  153. });
  154. $('#PicasaDownload').mouseover(function() {
  155. var currentPage = location.href;
  156. if (currentPage.search('plus.google.com/') != -1 && currentPage.search('/photos/') != -1 && currentPage.search('/albums/') != -1) {
  157. $(this).find('span').css('color', '#C53727');//"rgb(197,55,39)";
  158. }
  159. else {
  160. $(this).find('span').css('color', '#666666');//"rgb(107,107,107)";
  161. }
  162. });
  163. //===============================================================================
  164. // - End of Picasa Download -
  165. //===============================================================================
  166. //===============================================================================
  167. // - Full Size images -
  168. //===============================================================================
  169. $('#NewPage').click(function() {
  170. var images = $('.sp img');
  171. var album = $('.yh .kq');
  172. console.log(album);
  173. var page = "<html>\n<head>\n<meta charset='utf-8'>\n<title>";
  174. page += "Google+ Images";
  175. if (images.length <= GM_getValue(MAX_IMAGES, 30)) {
  176. page += '</title>\n' + css + js + '</head>\n<body>\n';
  177. }
  178. else {
  179. page += '</title>\n' + plainTextCSS + '</head>\n<body>\n';
  180. }
  181. page += '<div id=imagesCollection>\n';
  182.  
  183. var url = "";
  184. var findex = -1;
  185. var lindex = -1;
  186.  
  187. images.each(function(i, image) {
  188. var src = image.src;
  189. lindex = src.lastIndexOf("/");
  190. if (lindex > -1 && src.search("focus-opensocial") < 0) {
  191. if (src.match('=.*-p-no')) {
  192. url = src.replace(/=.*p-no/, '=s0');
  193. }
  194. else {
  195. findex = src.substr(0,lindex).lastIndexOf("/");
  196. if (findex > -1) {
  197. url = src.substr(0, findex) + "/s0" + src.substr(lindex);
  198. }
  199. }
  200. }
  201. if (url) {
  202. if (images.length <= GM_getValue(MAX_IMAGES, 30)) {
  203. page += '<a href="' + url + '" target="_blank"><img id="img' + i + '" src=' + url + '></a><br />\n';
  204. }
  205. else {
  206. // page += '<a href="' + url + '" target="_blank"><img style="width:auto;height:300px;" src=' + images.item(i).src+ '><br />' + url + '</a><br />';
  207. page += '<a href="' + url + '" target="_blank">' + url + '</a><br />\n';
  208. }
  209. }
  210. });
  211.  
  212. page += "</div>\n</body>\n</html>";
  213. var uriContent = "data:text/html;charset=utf-8," + encodeURIComponent(page);
  214. window.open(uriContent);
  215. });
  216. //===============================================================================
  217. // - End of Full Size images -
  218. //===============================================================================
  219.  
  220. //===============================================================================
  221. // - View images -
  222. //===============================================================================
  223. var app = '<div class="a-f-e dk view" title="View images in new tap" tabindex="0" role="button">'
  224. + '<img alt="Im" class="sr" src="http://cdn1.iconfinder.com/data/icons/fatcow/32x32_0500/image_add.png" style="width:16px;height:auto;" /></div>';
  225.  
  226. $(document).off('mouseover', '.qf');
  227. $(document).on('mouseover', '.qf', function() {
  228. if ($(this).find('.Ry>.Mm').length && !$(this).find('.LI>.view').length) {
  229. var add = $(this).find('.LI>.rE');
  230. add.before(app);
  231. $(this).find('.LI>.view').click( function() {
  232. var page = "<html>\n<head>\n<meta charset='utf-8'>\n<title>";
  233. page += "Google+ Images";
  234. page += '</title>\n' + css + js + '</head>\n<body>\n';
  235. page += '<div id=imagesCollection>\n';
  236. var url = "";
  237. var findex = -1;
  238. var lindex = -1;
  239. var images = $(this).closest('.qf').find('.Mm').find('img').each(function(i, image) {
  240. src = image.src;
  241. lindex = src.lastIndexOf("/");
  242. if (lindex > -1 && src.search("focus-opensocial") < 0) {
  243. url = src.substr(0,lindex);
  244. findex = url.lastIndexOf("/");
  245. if (findex > -1) {
  246. url = src.substr(0, findex) + "/s0" + src.substr(lindex);
  247. page += '<a href="' + url + '" target="_blank"><img id="img' + i + '" src=' + url + '></a><br />\n';
  248. }
  249. }
  250. });
  251. page += "</div>\n</body>\n</html>";
  252. var uriContent = "data:text/html;charset=utf-8," + encodeURIComponent(page);
  253. window.open(uriContent);
  254. });
  255. }
  256. });
  257.  
  258. //===============================================================================
  259. // - End of View images -
  260. //===============================================================================
  261.  
  262. //===============================================================================
  263. // - View album image -
  264. //===============================================================================
  265. // var ap = '<div class="downloadIt a-f-e m-la-qONoCf-Id-jNm5if fu Bchcbd" title="View in new tab" ><a href="';
  266. // var ap2 = '" target="_blank"><img alt="Im" src="http://cdn1.iconfinder.com/data/icons/fatcow/32x32_0500/image_add.png" style="z-index:1000;width:26px;height:auto;" /></a></div>';
  267.  
  268. var ap = '<div class="downloadIt"><div class="yKm1Pc ufIVef"></div><span class="wILgub ufIVef" data-tooltip="Open in new tab" data-tooltip-align="b" style="left:50px !important;"><a href="';
  269. var ap2 = '" target="_blank"><img alt="Im" src="http://cdn1.iconfinder.com/data/icons/fatcow/32x32_0500/image_add.png" style="z-index:1000;width:26px;height:auto;" /></a></span></div>';
  270. $(document).off('mouseover', '.PkkLkd');
  271. $(document).on('mouseover', '.PkkLkd', function() {
  272. if (!$(this).find('.downloadIt').length) {
  273. // var t = $(this).find('.m-la-qONoCf-Id-soaiwe-b');
  274. var src = $(this).find('img').attr('src');
  275. var url ="";
  276. var findex = -1;
  277. var lindex = -1;
  278. if (src.match('=.*-p-no')) {
  279. url = src.replace(/=.*p-no/, '=s0');
  280. }
  281. else {
  282. lindex = src.lastIndexOf("/");
  283. findex = src.substr(0,lindex).lastIndexOf("/");
  284. if (findex > -1) {
  285. url = src.substr(0, findex) + "/s0" + src.substr(lindex);
  286. }
  287. }
  288. $(this).append(ap + url +ap2);
  289. }
  290. });
  291. $(document).off('mouseover', '.downloadIt');
  292. $(document).on('mouseover', '.downloadIt', function(e) {
  293. $(this).removeClass('ufIVef');
  294. });
  295. //===============================================================================
  296. // - End of View album image -
  297. //===============================================================================
  298.  
  299. })();
  300.  
  301.  
  302. //===============================================================================
  303. // - Weekly Auto-Update Check -
  304. //===============================================================================
  305. // CheckForUpdate() will verify if the time has come to look if an update is available.
  306. // CheckVersion() will verify if this script version is the latest available.
  307. //===============================================================================
  308. var script_title = "Google+ Photos Download";
  309. var source_location = "http://userscripts.org/scripts/source/135225.user.js";
  310. var current_version = "1.6.0";
  311. var latest_version = " ";
  312. var gm_updateparam = "GoogleDownload_lastupdatecheck";
  313. var lastupdatecheck = GM_getValue(gm_updateparam, "never");
  314.  
  315. // a google document is used to store the latest version number (If the version in that file does not match the current_version variable, an update will be triggered)
  316. var version_holder = "http://dl.dropbox.com/u/4978696/userscripts/GooglePhotosDownloadversion.txt";
  317.  
  318. //Add a command to the menu in case someone wants to manually check for an update.
  319. GM_registerMenuCommand("Google+ Download->Manually Update", CheckVersion);
  320.  
  321. //Initiate the download of the new script version.
  322. function GetNewVersion() {
  323. var today = new Date();
  324. GM_setValue(gm_updateparam, String(today));
  325. window.location = source_location;
  326. }
  327.  
  328. //Verify if it's time to update
  329. function CheckForUpdate()
  330. {
  331. var today = new Date();
  332. var one_day = 24 * 60 * 60 * 1000; //One day in milliseconds
  333.  
  334. if(lastupdatecheck != "never")
  335. {
  336. today = today.getTime(); //Get today's date
  337. var lastupdatecheck = new Date(lastupdatecheck).getTime();
  338. var interval = (today - lastupdatecheck) / one_day; //Find out how much days have passed
  339.  
  340. //If a week has passed since the last update check, check if a new version is available
  341. if(interval >= 7)
  342. CheckVersion();
  343. }
  344. else
  345. CheckVersion();
  346. }
  347.  
  348. //Make sure we don't have the latest version
  349. function CheckVersion()
  350. {
  351. GM_xmlhttpRequest({
  352. method: 'GET',
  353. url: version_holder,
  354. headers: {'Content-type':'application/x-www-form-urlencoded'},
  355. onload: function(responseDetails)
  356. {
  357. var line = String(responseDetails.responseText.match(/version=[0-9].[0-9]?[0-9].[0-9]?[0-9]/));
  358. if(line != null)
  359. {
  360. var strSplit = new Array();
  361. strSplit = line.split('=');
  362. latest_version = strSplit[1];
  363.  
  364. if(current_version != latest_version && latest_version != "undefined")
  365. {
  366. if(confirm("A more recent version of " + script_title + " (" + latest_version + ") has been found.\r\nWould you like to get it now?"))
  367. GetNewVersion();
  368. else
  369. AskForReminder();
  370. }
  371. else if(current_version == latest_version)
  372. alert("You have the latest version of " + script_title + ".");
  373. }
  374. else
  375. {
  376. alert("Could not locate the version holder file.\r\nThis should be reported to the script author.\r\nThank you!");
  377. SkipWeeklyUpdateCheck();
  378. }
  379. }
  380. });
  381. }
  382.  
  383. //Ask the user to be reminded in 24 hours or only next week.
  384. function AskForReminder()
  385. {
  386. if(confirm("Would you like to be reminded in 24 hours ?\r\n(Cancel to be reminded next week only)"))
  387. {
  388. var today = new Date();
  389. today = today.getTime();
  390. var sixdays_ms = 6 * 24 * 60 * 60 * 1000;
  391. var sda_ms = today - sixdays_ms;
  392. var sixdaysago = new Date(sda_ms)
  393.  
  394. //Since we check for updates after 7 days, just make it seem like the last check was 6 days ago.
  395. GM_setValue(gm_updateparam, String(sixdaysago));
  396. }
  397. else
  398. SkipWeeklyUpdateCheck();
  399. }
  400.  
  401. //Set the next update check in seven days
  402. function SkipWeeklyUpdateCheck()
  403. {
  404. var today = new Date();
  405. //As if we've just updated the script, the next check will only be next week.
  406. GM_setValue(gm_updateparam, String(today));
  407. }
  408. //===============================================================================
  409. // - Weekly Auto-Update Check -
  410. //===============================================================================