Stig's Flickr Fixr

Updates your Flickr-experience. Increase display-size and quality of "old" photos, Show photographer's albums on photostream-pages, Photographer's other photos by tag-links, A fix to actually show a geotagged photo on the linked map - - - And maybe more to come later...

目前为 2015-08-27 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Stig's Flickr Fixr
  3. // @namespace dk.rockland.userscript.flickr.fixr
  4. // @description Updates your Flickr-experience. Increase display-size and quality of "old" photos, Show photographer's albums on photostream-pages, Photographer's other photos by tag-links, A fix to actually show a geotagged photo on the linked map - - - And maybe more to come later...
  5. // @author Stig Nygaard, http://www.rockland.dk, https://www.flickr.com/photos/stignygaard/
  6. // @homepageURL http://www.rockland.dk/userscript/flickr/fixr/
  7. // @supportURL http://www.rockland.dk/userscript/flickr/fixr/
  8. // @icon http://www.rockland.dk/img/fixr32.png
  9. // @icon64 http://www.rockland.dk/img/fixr64.png
  10. // @include https://www.flickr.com/*
  11. // @include https://flickr.com/*
  12. // @match https://*.flickr.com/*
  13. // @version 2015.08.27.1
  14. // @grant none
  15. // @run-at document-start
  16. // ==/UserScript==
  17.  
  18. var DEBUG = false;
  19. function log(s) {
  20. if (DEBUG && window.console) { window.console.log(s); }
  21. }
  22. if (DEBUG) {
  23. if ('loading' === document.readyState) {
  24. log("This userscript is running at document-start time.");
  25. } else {
  26. log("This userscript is running with document.readyState: " + document.readyState);
  27. }
  28. window.addEventListener('DOMContentLoaded', function () {log('(onDOMContentLoaded)'); }, false);
  29. window.addEventListener('focus', function () {log('(onfocus)'); }, false);
  30. window.addEventListener('load', function () {log('(onload)'); }, false);
  31. window.addEventListener('pageshow', function () {log('(onpageshow)'); }, false);
  32. window.addEventListener('resize', function () {log('(onresize)'); }, false);
  33. window.addEventListener('hashchange', function () {log('(onhashchange)'); }, false);
  34. }
  35.  
  36. // FIXR page-tracker start
  37. var fixr = {
  38. context: {
  39. pageType: '',
  40. userId: '',
  41. photographerId: '', // value might be delayed (If uninitialized, try call initPhotographerId())
  42. photographerIcon: '',
  43. photographerAlias: '', // (pathalias) bonus-info sometimes initialized (from url) when initializing photoId
  44. photographerName: '',
  45. photoId: '',
  46. albumId: '',
  47. groupId: '',
  48. galleryId: ''
  49. },
  50. content: null,
  51. pageactionsCount: 0,
  52. timerResizeActionDelayed: 0,
  53. onPageHandlers: [],
  54. onResizeHandlers: [],
  55. initPhotographerId: function () { // photographer/attribution id
  56. var elem;
  57. if (document.querySelector('div.photostream-page-view')) {
  58. // photostream
  59. elem = document.querySelector('div.photostream-page-view div.fluid-photostream-coverphoto-view div.avatar.person');
  60. } else if (document.querySelector('div.photo-page-scrappy-view')) {
  61. // photopage
  62. elem = document.querySelector('div.photo-page-scrappy-view div.sub-photo-view div.avatar.person');
  63. } else if (document.querySelector('div.photo-page-lightbox-scrappy-view')) {
  64. // photopage lightbox
  65. elem = document.querySelector('div.photo-page-lightbox-scrappy-view div.photo-well-view div.photo-attribution div.avatar.person');
  66. } else if (document.querySelector('div.album-page-view')) {
  67. // album page
  68. elem = document.querySelector('div.album-page-view div.album-container div.album-header-view div.album-attribution div.avatar.person');
  69. } else {
  70. log('we do not look for photographerId on this page');
  71. return true;
  72. }
  73. // album oversigt
  74. // etc...
  75. // men minus f.eks. favorites oversigt!
  76. if (!elem) {
  77. log('fixr.initPhotographerId() - Attribution elem NOT found - returning false');
  78. return false;
  79. } // re-run a little later???
  80. log('fixr.initPhotographerId() - Attribution elem found');
  81. // (div.avatar.person).style.backgroundImage=url(https://s.yimg.com/pw/images/buddyicon07_r.png#44504567@N00)
  82. // .style.backgroundImage=url(//c4.staticflickr.com/8/7355/buddyicons/10259776@N00_r.jpg?1372021232#10259776@N00)
  83. if (elem.style.backgroundImage) {
  84. log('fixr.initPhotographerId() - elem has style.backgroundImage "' + elem.style.backgroundImage + '", now looking for the attribution id...');
  85. var pattern = /url[^#\?]+(\/\/[^#\?]+\.com\/[^#\?]+\/buddyicon[^\?\#]+)[^#]*#(\d+\@N\d{2})/i;
  86. // var pattern = /\/buddyicons\/(\d+\@N\d{2})\D+/i;
  87. var result = elem.style.backgroundImage.match(pattern);
  88. if (result) {
  89. log('fixr.initPhotographerId() - Attribution pattern match found: ' + result[0]);
  90. log('fixr.initPhotographerId() - the attribution icon is ' + result[1]);
  91. log('fixr.initPhotographerId() - the attribution id is ' + result[2]);
  92. fixr.context.photographerIcon = result[1];
  93. fixr.context.photographerId = result[2];
  94. } else {
  95. log('fixr.initPhotographerId() - attribution pattern match not found');
  96. return false;
  97. }
  98. } else {
  99. log('fixr.initPhotographerId() - elem.style.backgroundImage not found');
  100. return false;
  101. }
  102. log('fixr.initPhotographerId() - returning true...');
  103. return true;
  104. },
  105. initPhotoId: function () { // Photo Id
  106. // *flickr.com/photos/user/PId/*
  107. //log('window.location.pathname: '+window.location.pathname);
  108. var pattern = /^\/photos\/([^\/]+)\/([\d]{2,})/i;
  109. var result = window.location.pathname.match(pattern);
  110. if (result) {
  111. //log('url match med path='+result[0]);
  112. log('url match med photoId=' + result[2]);
  113. log('url match med photographerAlias=' + result[1]);
  114. fixr.context.photoId = result[2];
  115. fixr.context.photographerAlias = result[1];
  116. return true;
  117. }
  118. return false;
  119. },
  120. pageActions: function () {
  121. if (fixr.content) {
  122. log('fixr.pageActions() has started with fixr.content defined');
  123. } else {
  124. log('fixr.pageActions() was called, but fixr.content NOT defined');
  125. return;
  126. }
  127. fixr.pageactionsCount++;
  128. for (var p in fixr.context) { // reset context on new page
  129. fixr.context[p] = ''; // filter ?
  130. }
  131. if (fixr.content.querySelector('div.photostream-page-view')) {
  132. if (fixr.content.querySelector('div.slideshow-view')) {
  133. fixr.context.pageType = 'PHOTOSTREAM SLIDESHOW';
  134. } else {
  135. fixr.context.pageType = 'PHOTOSTREAM';
  136. }
  137. } else if (fixr.content.querySelector('div.photo-page-scrappy-view')) {
  138. // photopage
  139. fixr.context.pageType = 'PHOTOPAGE';
  140. } else if (fixr.content.querySelector('div.photo-page-lightbox-scrappy-view')) {
  141. // photopage lightbox
  142. fixr.context.pageType = 'PHOTOPAGE LIGHTBOX';
  143. } else if (fixr.content.querySelector('div.albums-list-page-view')) {
  144. // album lists page
  145. fixr.context.pageType = 'ALBUMSLIST';
  146. } else if (fixr.content.querySelector('div.album-page-view')) {
  147. // album page
  148. if (fixr.content.querySelector('div.slideshow-view')) {
  149. fixr.context.pageType = 'ALBUM SLIDESHOW';
  150. } else {
  151. fixr.context.pageType = 'ALBUM';
  152. }
  153. } else if (fixr.content.querySelector('div.cameraroll-page-view')) {
  154. // camera roll
  155. fixr.context.pageType = 'CAMERAROLL';
  156. } else if (fixr.content.querySelector('div.explore-page-view')) {
  157. // explore page
  158. fixr.context.pageType = 'EXPLORE';
  159. } else if (fixr.content.querySelector('div.favorites-page-view')) {
  160. // favorites page
  161. if (fixr.content.querySelector('div.slideshow-view')) {
  162. fixr.context.pageType = 'FOVORITES SLIDESHOW';
  163. } else {
  164. fixr.context.pageType = 'FAVORITES';
  165. }
  166. } else if (fixr.content.querySelector('div.groups-list-view')) {
  167. // groups page
  168. fixr.context.pageType = 'GROUPSLIST'; // personal grouplist
  169. } else if (fixr.content.querySelector('div#activityFeed')) { // id=main i stedet for id=fixr.content
  170. // front/activityfeed page
  171. fixr.context.pageType = 'ACTIVITYFEED'; // aka. front page
  172. } else {
  173. // fixr.context.pageType = ''; // unknown
  174. }
  175. // actions end
  176.  
  177. log('fixr.context.pageType = ' + fixr.context.pageType);
  178. if (fixr.initPhotographerId()) {
  179. log('fixr.initPhotographerId() returned true');
  180. } else {
  181. log('fixr.initPhotographerId() returned false - re-running delayed...');
  182. setTimeout(fixr.initPhotographerId, 2000);
  183. }
  184. if (fixr.initPhotoId()) {
  185. log('fixr.initPhotoId() returned true');
  186. } else {
  187. log('fixr.initPhotoId() returned false');
  188. }
  189.  
  190. if (fixr.content.querySelector('a.owner-name')) {
  191. fixr.context.photographerName = fixr.content.querySelector('a.owner-name').textContent;
  192. }
  193. // Now run the page handlers....
  194. if (fixr.onPageHandlers && fixr.onPageHandlers !== null && fixr.onPageHandlers.length) {
  195. log('We have ' + fixr.onPageHandlers.length + ' onPage handlers starting now...');
  196. for (var f = 0; f < fixr.onPageHandlers.length; f++) {
  197. fixr.onPageHandlers[f]();
  198. }
  199. }
  200. },
  201. setupContent: function () {
  202. log('fixr.setupContent START');
  203. if (document.getElementById('content')) {
  204. fixr.content = document.getElementById('content');
  205. } else if (document.getElementById('main')) {
  206. fixr.content = document.getElementById('main'); // frontpage
  207. }
  208. if (fixr.content && fixr.content.id) {
  209. log('fixr.content.id = ' + fixr.content.id);
  210. } else {
  211. log('content or main element NOT found!');
  212. }
  213. },
  214. runPageActionsIfMissed: function () {
  215. if (fixr.pageactionsCount === 0) {
  216. log('Vi kører fixr.pageActions() på bagkant via onload...');
  217. fixr.setupContent();
  218. if (fixr.content === null) {
  219. log('Vi kan IKKE køre fixr.pageActions() på bagkant, da fixr.content ikke er defineret');
  220. return;
  221. }
  222. fixr.pageActions();
  223. } else {
  224. log('ej nødvendigt at køre fixr.pageActions() på bagkant i dette tilfælde...');
  225. }
  226. },
  227. runDelayedPageActionsIfMissed: function () {
  228. setTimeout(fixr.runPageActionsIfMissed, 2000);
  229. },
  230. resizeActions: function () {
  231. log('fixr.resizeActions() running...');
  232. if (fixr.onResizeHandlers && fixr.onResizeHandlers !== null && fixr.onResizeHandlers.length) {
  233. log('We have an array of onResize handlers...');
  234. for (var f = 0; f < fixr.onResizeHandlers.length; f++) {
  235. fixr.onResizeHandlers[f]();
  236. }
  237. }
  238. },
  239. resizeActionsDelayed: function () { // or "preburner"
  240. clearTimeout(fixr.timerResizeActionDelayed);
  241. fixr.timerResizeActionDelayed = setTimeout(fixr.resizeActions, 250);
  242. },
  243. setupObserver: function () {
  244. log('fixr.setupObserve INITIALIZATION START');
  245. fixr.setupContent();
  246. if (fixr.content === null) {
  247. log('Init fails because content not defined');
  248. return;
  249. }
  250. // create an observer instance
  251. var observer = new MutationObserver(function (mutations) {
  252. log('NEW PAGE MUTATION!');
  253. //mutations.forEach(function(mutation) {
  254. // log('MO: '+mutation.type); // might check for specific type of "mutations" (MutationRecord)
  255. //});
  256. fixr.pageActions();
  257. }); // MutationObserver end
  258. // configuration of the observer:
  259. var config = {attributes: false, childList: true, subtree: false, characterData: false};
  260. // pass in the target node, as well as the observer options
  261. observer.observe(fixr.content, config);
  262. // later, you can stop observing
  263. // observer.disconnect();
  264. log('fixr.setupObserve INITIALIZATION DONE');
  265. },
  266. init: function (onPageHandlerArray, onResizeHandlerArray) {
  267. // General page-change observer setup:
  268. window.addEventListener('DOMContentLoaded', fixr.setupObserver, false); // Page on DOMContentLoaded
  269. window.addEventListener('load', fixr.runDelayedPageActionsIfMissed, false); // Page on load
  270. window.addEventListener('resize', fixr.resizeActionsDelayed, false); // også på resize
  271. if (onPageHandlerArray && onPageHandlerArray !== null && onPageHandlerArray.length) {
  272. fixr.onPageHandlers = onPageHandlerArray; // No, ad one-by-one by "helper"?
  273. }
  274. if (onResizeHandlerArray && onResizeHandlerArray !== null && onResizeHandlerArray.length) {
  275. fixr.onResizeHandlers = onResizeHandlerArray; // No, ad one-by-one by "helper"?
  276. }
  277. }
  278. };
  279. // FIXR page-tracker end
  280.  
  281.  
  282. var _timerMaplink = 0;
  283. function updateMapLink() {
  284. if (fixr.context.pageType !== 'PHOTOPAGE') {
  285. return;
  286. } // exit if not photopage
  287. log('updateMapLink() running at readystate=' + document.readyState + ' and with photoId=' + fixr.context.photoId);
  288. if (fixr.context.photoId) {
  289. var maplink = fixr.content.querySelector('a.static-maps');
  290. if (maplink) {
  291. if (maplink.getAttribute('href') && (maplink.getAttribute('href').indexOf('map/?') > 0) && (maplink.getAttribute('href').indexOf('&photo=') === -1)) {
  292. maplink.setAttribute('href', maplink.getAttribute('href') + '&photo=' + fixr.context.photoId);
  293. log('link is updated by updateMapLink() at readystate=' + document.readyState);
  294. } else {
  295. log('link NOT updated by updateMapLink(). Invalid element or already updated. readystate=' + document.readyState);
  296. }
  297. } else {
  298. log('NO maplink found at readystate=' + document.readyState);
  299. }
  300. } else {
  301. log('NO photoId found at readystate=' + document.readyState);
  302. }
  303. }
  304. function updateMapLinkDelayed() {
  305. if (fixr.context.pageType !== 'PHOTOPAGE') {
  306. return;
  307. } // exit if not photopage
  308. log('updateMapLinkDelayed() running... with pageType=' + fixr.context.pageType);
  309. //clearTimeout(_timerMaplink);
  310. _timerMaplink = setTimeout(updateMapLink, 2000); // make maplink work better on photopage
  311. }
  312.  
  313. var albums = { // cache albums to avoid repeating requests
  314. ownerId: '',
  315. html: '',
  316. count: 0
  317. };
  318. function getAlbumlist() {
  319. var _reqAlbumlist = null;
  320. if (window.XMLHttpRequest) {
  321. _reqAlbumlist = new XMLHttpRequest();
  322. if (typeof _reqAlbumlist.overrideMimeType !== 'undefined') {
  323. _reqAlbumlist.overrideMimeType('text/html');
  324. }
  325.  
  326. _reqAlbumlist.onreadystatechange = function () {
  327. if (_reqAlbumlist.readyState === 4 && _reqAlbumlist.status === 200) {
  328. log('_reqAlbumlist returned status=' + _reqAlbumlist.status); // + ', \ntext:\n' + _reqAlbumlist.responseText);
  329. var doc = document.implementation.createHTMLDocument("sizeDoc");
  330. doc.documentElement.innerHTML = _reqAlbumlist.responseText;
  331.  
  332. albums.ownerId = fixr.context.photographerId;
  333. albums.html = '';
  334. albums.count = 0;
  335. var e = doc.body.querySelectorAll('div.photo-list-album-view');
  336. var imgPattern = /url\([\'\"]*([^\)\'\"]+)(\.[jpgtifn]{3,4})[\'\"]*\)/i;
  337. if (e && e.length > 0) {
  338. albums.count = e.length;
  339. for (var i = 0; i < Math.min(10, e.length); i++) {
  340. var imgUrl = '';
  341. log('A7 (' + i + ')');
  342. var result = e[i].style.backgroundImage.match(imgPattern);
  343. if (result) {
  344. log('Album img url: ' + result[1] + ' - ' + result[2]);
  345. imgUrl = result[1].replace(/_[a-z]$/, '') + '_s' + result[2];
  346. log('imgUrl=' + imgUrl);
  347. } else {
  348. log('No match on imgPattern');
  349. }
  350. var a = e[i].querySelector('a'); // sub-element
  351. if (a && a.href) {
  352. log('Album title: ' + a.title);
  353. log('Album url: ' + a.href);
  354. albums.html += '<div><a href="//www.flickr.com' + a.href + '"><img src="' + imgUrl + '" alt="" /><div style="margin:0 0 .8em 0">' + a.title + '</div></a></div>';
  355. }
  356. }
  357. }
  358. if (document.getElementById('albumTeaser')) {
  359. document.getElementById('albumTeaser').innerHTML = '<div style="margin:0 0 .8em 0">Albums</div>' + albums.html + '<div><i><a href="/photos/' + (fixr.context.photographerAlias !== '' ? fixr.context.photographerAlias : fixr.context.photographerId) + '/albums/">' + (albums.count > 10 ? 'More albums...' : (albums.count == 0 ? 'No albums found...' : '')) + '</a></i></div>';
  360. } else {
  361. log('albumTeaser NOT FOUND!?!');
  362. }
  363. } else {
  364. // wait for the call to complete
  365. }
  366. };
  367.  
  368. if (fixr.context.photographerId === albums.ownerId && fixr.context.photographerId !== '') {
  369. // use cached
  370. log('Usinging CACHED albumlist!...');
  371. document.getElementById('albumTeaser').innerHTML = '<div style="margin:0 0 .8em 0">Albums</div>' + albums.html + '<div><i><a href="/photos/' + (fixr.context.photographerAlias !== '' ? fixr.context.photographerAlias : fixr.context.photographerId) + '/albums/">' + (albums.count > 10 ? 'More albums...' : (albums.count == 0 ? 'No albums found...' : '')) + '</a></i></div>';
  372. } else if (fixr.context.photographerId) {
  373. var url = 'https://www.flickr.com/photos/' + (fixr.context.photographerAlias !== '' ? fixr.context.photographerAlias : fixr.context.photographerId) + '/albums';
  374. _reqAlbumlist.open('GET', url, true);
  375. _reqAlbumlist.send(null);
  376. } else {
  377. log('Attribution user (photographer) not found');
  378. }
  379. } else {
  380. log('understøtter ikke XMLHttpRequest');
  381. }
  382. }
  383. function albumTeaser() {
  384. if (fixr.context.pageType !== 'PHOTOSTREAM') {
  385. return;
  386. } // exit if not photostream
  387. log('albumTeaser() running');
  388. var dpc = document.querySelector('div.photolist-container');
  389. if (!dpc) {
  390. return;
  391. }
  392. // to-do: check om personlig photostream?
  393. // to-do: check padding-right er mindst 130px?
  394. log('AlbumTeaser found div.photolist-container');
  395. if (!document.getElementById('albumTeaser')) {
  396. dpc.style.position = "relative";
  397. dpc.insertAdjacentHTML('afterbegin', '<div id="albumTeaser" style="border:none;margin:0;padding:0;position:absolute;top:0;right:10px;width:100px"></div>');
  398. }
  399. if (document.getElementById('albumTeaser')) {
  400. getAlbumlist(); // også check på fixr.context.photographerId ?
  401. }
  402. }
  403. var _timerAlbumTeaserDelayed;
  404. function albumTeaserDelayed() {
  405. if (fixr.context.pageType !== 'PHOTOSTREAM') {
  406. return;
  407. } // exit if not photostream
  408. log('albumTeaserDelayed() running... with pageType=' + fixr.context.pageType);
  409. clearTimeout(_timerAlbumTeaserDelayed);
  410. _timerAlbumTeaserDelayed = setTimeout(albumTeaser, 1500);
  411. }
  412.  
  413. function getUserId() { // Id of logged-in user
  414. return null; // to-do
  415. }
  416.  
  417. var scaler = {
  418. photoId: '',
  419. mf: null, // document.querySelector('img.main-photo') for (re-)re-scale
  420. lrf: null, // document.querySelector('img.low-res-photo') for (re-)re-scale
  421. maxSizeUrl: '',
  422. hasOriginal: false,
  423. scaleToWidth: 0,
  424. scaleToHeight: 0,
  425. run: function () {
  426. if (fixr.context.pageType !== 'PHOTOPAGE' && fixr.context.pageType !== 'PHOTOPAGE LIGHTBOX') {
  427. return;
  428. } // exit if not photopage or lightbox
  429. log('scaler.run() running...');
  430. // var that = this;
  431. var scale = function () {
  432. if (fixr.context.pageType !== 'PHOTOPAGE' && fixr.context.pageType !== 'PHOTOPAGE LIGHTBOX') {
  433. return;
  434. } // exit if not photopage or lightbox
  435. log('scale() running... (scale to:' + scaler.scaleToWidth + 'x' + scaler.scaleToHeight + ')');
  436. scaler.mf = document.querySelector('img.main-photo'); // for en sikkerheds skyld
  437. scaler.lrf = document.querySelector('img.low-res-photo'); // for en sikkerheds skyld
  438. if (scaler.mf && scaler.mf !== null && scaler.lrf && scaler.lrf !== null && scaler.scaleToWidth > 0 && scaler.scaleToHeight > 0) {
  439. log('[scaler] do scaling WORK. Height from ' + scaler.mf.height + ' to ' + scaler.scaleToHeight);
  440. scaler.mf.height = scaler.scaleToHeight;
  441. log('[scaler] do scaling WORK. Width from ' + scaler.mf.width + ' to ' + scaler.scaleToWidth);
  442. scaler.mf.width = scaler.scaleToWidth;
  443. scaler.lrf.height = scaler.mf.height;
  444. scaler.lrf.width = scaler.mf.width;
  445. log('[scaler] Photo scaled to: ' + scaler.mf.width + 'x' + scaler.mf.height + '.');
  446. }
  447. };
  448. var replace = function () { // and (re-)scale?
  449. if (fixr.context.pageType !== 'PHOTOPAGE' && fixr.context.pageType !== 'PHOTOPAGE LIGHTBOX') {
  450. return;
  451. } // exit if not photopage or lightbox
  452. log('scaler.run.replace() running...');
  453. scaler.mf = document.querySelector('img.main-photo'); // for en sikkerheds skyld
  454. if (scaler.mf && scaler.mf !== null) {
  455. scaler.mf.src = scaler.maxSizeUrl; // only if original
  456. scale();
  457. }
  458. };
  459. var getSizes = function () {
  460. log('scaler.run.getSizes() running...');
  461. var _reqAllSizes = null;
  462. if (window.XMLHttpRequest) {
  463. _reqAllSizes = new XMLHttpRequest();
  464. if (typeof _reqAllSizes.overrideMimeType !== 'undefined') {
  465. _reqAllSizes.overrideMimeType('text/html');
  466. }
  467. _reqAllSizes.onreadystatechange = function () {
  468. if (_reqAllSizes.readyState === 4 && _reqAllSizes.status === 200) {
  469. log('[scaler] _reqAllSizes returned status=' + _reqAllSizes.status); // + ', \ntext:\n' + _reqAllSizes.responseText);
  470. var doc = document.implementation.createHTMLDocument("sizeDoc");
  471. doc.documentElement.innerHTML = _reqAllSizes.responseText;
  472. if (doc.body.querySelector('div#allsizes-photo>img')) {
  473. scaler.maxSizeUrl = doc.body.querySelector('div#allsizes-photo>img').src;
  474. log('[scaler] Largest image size: ' + scaler.maxSizeUrl);
  475. }
  476. var e = doc.body.querySelectorAll('ol.sizes-list li ol li');
  477. if (e && e.length > 0) {
  478. var s = e[e.length - 1].textContent.replace(/\s{2,}/g, ' ');
  479. if (s.indexOf('Original') > -1) {
  480. scaler.hasOriginal = true;
  481. log('[scaler] ' + s);
  482. replace();
  483. } else {
  484. log('[scaler] Bruger tillader ikke adgang til original');
  485. }
  486. // udtræk evt sizes fra s?
  487. }
  488. } else {
  489. // wait for the call to complete
  490. }
  491. };
  492. var url = 'https://www.flickr.com/photos/' + (fixr.context.photographerAlias !== '' ? fixr.context.photographerAlias : fixr.context.photographerId) + '/' + fixr.context.photoId + '/sizes/o';
  493. _reqAllSizes.open('GET', url, true);
  494. _reqAllSizes.send(null);
  495. } else {
  496. log('[scaler] understøtter ikke XMLHttpRequest');
  497. }
  498. };
  499. if (scaler.photoId === '') {
  500. scaler.photoId = fixr.context.photoId;
  501. } else if (scaler.photoId !== fixr.context.photoId) {
  502. scaler.photoId = fixr.context.photoId;
  503. scaler.mf = null;
  504. scaler.lrf = null;
  505. scaler.maxSizeUrl = '';
  506. scaler.hasOriginal = false;
  507. scaler.scaleToWidth = 0;
  508. scaler.scaleToHeight = 0;
  509. }
  510. var roomHeight = 0;
  511. var roomWidth = 0;
  512. var roomPaddingHeight = 0;
  513. var roomPaddingWidth = 0;
  514.  
  515. // Fortsæt kun hvis PhotoId!!!?
  516.  
  517. var dpev = document.querySelector('div.photo-engagement-view');
  518. var pwv = document.querySelector('div.photo-well-view');
  519. if (pwv) {
  520. log('[scaler] height-controller: height=' + pwv.clientHeight + ' (padding=70?), width=' + pwv.clientWidth + ' (padding=80?).'); // hc.style.padding: 20px 40px 50px
  521. if (roomHeight === 0) {
  522. roomHeight = pwv.clientHeight;
  523. }
  524. if (roomWidth === 0) {
  525. roomWidth = pwv.clientWidth;
  526. }
  527. roomPaddingHeight += (parseInt(window.getComputedStyle(pwv, null).getPropertyValue('padding-top'), 10) + parseInt(window.getComputedStyle(pwv, null).getPropertyValue('padding-bottom'), 10));
  528. roomPaddingWidth += (parseInt(window.getComputedStyle(pwv, null).getPropertyValue('padding-left'), 10) + parseInt(window.getComputedStyle(pwv, null).getPropertyValue('padding-right'), 10));
  529. }
  530. var hc = document.querySelector('div.height-controller');
  531. if (hc) {
  532. log('[scaler] height-controller: height=' + hc.clientHeight + ' (padding=70?), width=' + hc.clientWidth + ' (padding=80?).'); // hc.style.padding: 20px 40px 50px
  533. if (roomHeight === 0) {
  534. roomHeight = hc.clientHeight;
  535. }
  536. if (roomWidth === 0) {
  537. roomWidth = hc.clientWidth;
  538. }
  539. roomPaddingHeight += (parseInt(window.getComputedStyle(hc, null).getPropertyValue('padding-top'), 10) + parseInt(window.getComputedStyle(hc, null).getPropertyValue('padding-bottom'), 10));
  540. roomPaddingWidth += (parseInt(window.getComputedStyle(hc, null).getPropertyValue('padding-left'), 10) + parseInt(window.getComputedStyle(hc, null).getPropertyValue('padding-right'), 10));
  541. }
  542. var pwmsv = document.querySelector('div.photo-well-media-scrappy-view');
  543. if (pwmsv) {
  544. log('[scaler] div.photo-well-media-scrappy-view: height=' + pwmsv.clientHeight + ' (padding=70?), width=' + pwmsv.clientWidth + ' (padding=80?).'); // pwmsv.style.padding: 20px 40px 50px
  545. if (roomHeight === 0) {
  546. roomHeight = pwmsv.clientHeight;
  547. }
  548. if (roomWidth === 0) {
  549. roomWidth = pwmsv.clientWidth;
  550. }
  551. roomPaddingHeight += (parseInt(window.getComputedStyle(pwmsv, null).getPropertyValue('padding-top'), 10) + parseInt(window.getComputedStyle(pwmsv, null).getPropertyValue('padding-bottom'), 10));
  552. roomPaddingWidth += (parseInt(window.getComputedStyle(pwmsv, null).getPropertyValue('padding-left'), 10) + parseInt(window.getComputedStyle(pwmsv, null).getPropertyValue('padding-right'), 10));
  553. }
  554. scaler.mf = document.querySelector('img.main-photo');
  555. scaler.lrf = document.querySelector('img.low-res-photo');
  556. // var zl = document.querySelector('img.zoom-large'); // currently not used
  557. // var zs = document.querySelector('img.zoom-small'); // currently not used
  558. if (scaler.mf) {
  559. log('[scaler] main-photo: h=' + scaler.mf.height + ', w=' + scaler.mf.width + '. - Room: (h=' + (roomHeight - roomPaddingHeight) + ',w=' + (roomWidth - roomPaddingWidth) + ')');
  560. if (roomPaddingWidth === 0) { // hack
  561. roomPaddingWidth = 120;
  562. log('[scaler] roomPaddingWidth=120 hack used');
  563. }
  564. if (((roomHeight - roomPaddingHeight) > scaler.mf.height + 5) && ((roomWidth - roomPaddingWidth) > scaler.mf.width + 5)) {
  565. log('[scaler] ALLRIGHT - WE ARE READY FOR SCALING!...');
  566. if (((roomHeight - roomPaddingHeight) / scaler.mf.height) < ((roomWidth - roomPaddingWidth) / scaler.mf.width)) {
  567. scaler.scaleToWidth = Math.floor(scaler.mf.width * ((roomHeight - roomPaddingHeight) / scaler.mf.height));
  568. scaler.scaleToHeight = roomHeight - roomPaddingHeight;
  569. } else {
  570. scaler.scaleToHeight = Math.floor(scaler.mf.height * ((roomWidth - roomPaddingWidth) / scaler.mf.width));
  571. scaler.scaleToWidth = roomWidth - roomPaddingWidth;
  572. }
  573. log('[scaler] now calling scale()... [' + scaler.scaleToWidth + ', ' + scaler.scaleToWidth + ']');
  574. scale();
  575. log('[scaler] ...AND CONTINUE LOOKING FOR ORIGINAL...');
  576. if (dpev) { // if (document.querySelector('ul.sizes'))
  577. var org = document.querySelector('ul.sizes li.Original a.download-image-size');
  578. if (org) { // når vi bladrer?
  579. scaler.hasOriginal = true; // ??? kun hvis original
  580. scaler.maxSizeUrl = (org.href).replace(/^https\:/i, '').replace(/_d\./i, '.');
  581. replace();
  582. } else {
  583. // vi kan finde original "inline"
  584. var target = document.querySelector('div.photo-engagement-view');
  585. // if(!target) return; ???
  586. if (target) {
  587. var observer = new MutationObserver(function (mutations) {
  588. mutations.forEach(function (mutation) {
  589. log('[scaler] MO size: ' + mutation.type); // might check for specific "mutations"
  590. });
  591. var org = document.querySelector('ul.sizes li.Original a.download-image-size');
  592. if (org) {
  593. scaler.hasOriginal = true; // ??? kun hvis original
  594. scaler.maxSizeUrl = (org.href).replace(/^https\:/i, '').replace(/_d\./i, '.');
  595. replace();
  596. } else {
  597. log('Original photo not available for download on this photographer');
  598. }
  599. observer.disconnect();
  600. });
  601. // configuration of the observer:
  602. var config = {attributes: false, childList: true, subtree: false, characterData: false};
  603. observer.observe(target, config);
  604. }
  605. }
  606. } else {
  607. getSizes(); // resize (& replace) from/when size-list
  608. }
  609. }
  610. }
  611. }
  612. };
  613.  
  614. function insertStyle() {
  615. log('tagStyle()');
  616. if (!document.getElementById('fixrStyle')) {
  617. var style = document.createElement('style');
  618. style.type = 'text/css';
  619. style.id = 'fixrStyle';
  620. style.innerHTML = 'ul.tags-list>li.tag>a.fixrTag,ul.tags-list>li.autotag>a.fixrTag{display:none;} ul.tags-list>li.tag:hover>a.fixrTag,ul.tags-list>li.autotag:hover>a.fixrTag{display:inline;}';
  621. document.getElementsByTagName('head')[0].appendChild(style);
  622. /*
  623. if(!(style.sheet||{}).insertRule) {
  624. (style.styleSheet || style.sheet).addRule(selector, declarations);
  625. } else {
  626. style.sheet.insertRule(selector+"{"+declarations+"}",0);
  627. }
  628. */
  629. log('fixrStyle has been ADDED');
  630. } else {
  631. log('fixrStyle was already present');
  632. }
  633. }
  634. function updateTags() {
  635. if (fixr.context.pageType !== 'PHOTOPAGE') {
  636. return;
  637. } // exit if not photopage
  638. log('updateTags()');
  639. if (document.querySelector('ul.tags-list')) {
  640. var tags = document.querySelectorAll('ul.tags-list>li');
  641. if (tags && tags !== null && tags.length > 0) {
  642. for (var i = 0; i < tags.length; i++) {
  643. var atag = tags[i].querySelector('a[title][href*="?tags="],a[title][href*="?q="]');
  644. if (atag) {
  645. var realtag = (atag.href.match(/\?(tags|q)\=([\S]+)$/i))[2];
  646. if (!(tags[i].querySelector('a.fixrTag'))) {
  647. //log('updateTags() '+i+' fixr.context.photographerIcon: '+fixr.context.photographerIcon);
  648. var icon = fixr.context.photographerIcon.match(/^([^_]+)(_\w)?\.[jpgntif]{3,4}$/)[1] + '' + fixr.context.photographerIcon.match(/^[^_]+(_\w)?(\.[jpgntif]{3,4})$/)[2]; // do we know for sure it is square?
  649. //log('updateTags() '+i+' icon: '+icon); //
  650. tags[i].insertAdjacentHTML('afterbegin', '<a class="fixrTag" href="/photos/' + (fixr.context.photographerAlias !== '' ? fixr.context.photographerAlias : fixr.context.photographerId) + '/tags/' + realtag + '/" title="' + atag.title + ' by ' + fixr.context.photographerName + '"><img src="' + icon + '" style="width:1em;height:1em;margin:0;padding:0;position:relative;top:3px" alt="*" /></a>');
  651. }
  652. }
  653. }
  654. } else {
  655. log('no tags defined (yet?)');
  656. }
  657. } else {
  658. log('taglist container not found');
  659. }
  660. }
  661. function updateTagsDelayed() {
  662. if (fixr.context.pageType !== 'PHOTOPAGE') {
  663. return;
  664. } // exit if not photopage
  665. log('updateTagsDelayed() running... with pageType=' + fixr.context.pageType);
  666. //clearTimeout(_timerMaplink);
  667. if (fixr.context.pageType === 'PHOTOPAGE') {
  668. setTimeout(updateTags, 2500);
  669. }
  670. }
  671.  
  672. // FIXR fixr.init(onPageHandlers, onResizeHandlers)
  673. fixr.init([scaler.run, insertStyle, albumTeaserDelayed, updateMapLinkDelayed, updateTagsDelayed], [scaler.run]);
  674.  
  675.  
  676.  
  677. /* OLD STUFF...
  678.  
  679.  
  680. // Call Flickr REST API to get available photo sizes - Method currently NOT used:
  681. function wsGetSizes(photoId) {
  682. var _reqGetSizes = null;
  683. if (window.XMLHttpRequest) {
  684. _reqGetSizes = new XMLHttpRequest();
  685. if ( typeof _reqGetSizes.overrideMimeType !== 'undefined') {
  686. _reqGetSizes.overrideMimeType('application/json');
  687. }
  688. _reqGetSizes.onreadystatechange = function() {
  689. if (_reqGetSizes.readyState === 4 && _reqGetSizes.status === 200) {
  690. // do something with the results
  691. // var myObj = eval ( _reqGetSizes.responseText );
  692. log('webservice photos.getSizes returned status=' + _reqGetSizes.status + ', text: ' + _reqGetSizes.responseText);
  693. var obj = JSON.parse(_reqGetSizes.responseText);
  694. if (obj.stat === "ok") {
  695. log("ok");
  696. if (obj.sizes.candownload==1) {
  697. log("can download");
  698. var array = obj.sizes.size;
  699. if (array && array.length>0) {
  700. log("array length="+array.length);
  701. var elem = array[array.length-1];
  702. if (elem) {
  703. log("last elem is: "+elem.label+" with source="+elem.source);
  704. if (elem.label==="Original" && elem.source && elem.source.length>0) {
  705. // make sure photoId matches source
  706. photoOrg(elem.source);
  707. log("Original from webservice was used");
  708. }
  709. }
  710. }
  711. } else {
  712. log('Originals not available on user');
  713. }
  714. }
  715. // Hvis sizeList && original tilgængelig
  716. // photoOrg(url); // Update image now!!!
  717. // ellers hvis sizelist
  718. // log('Originals not available on user');
  719. // ellers hvis sizelist
  720. // log('Error fetching original');
  721. } else {
  722. // wait for the call to complete
  723. }
  724. };
  725.  
  726. _reqGetSizes.open('GET', 'https://api.flickr.com/services/rest/?method=flickr.photos.getSizes&api_key=9b8140dc97b93a5c80751a9dad552bd4&photo_id=' + photoId + '&format=json&nojsoncallback=1', true);
  727. _reqGetSizes.send(null);
  728.  
  729. } else {
  730. log('understøtter ikke XMLHttpRequest');
  731. }
  732. }
  733.  
  734.  
  735. // Call Flickr REST API to get albums - Method currently NOT used:
  736. function wsGetAlbums() {
  737. var _reqGetAlbums = null;
  738. if (window.XMLHttpRequest) {
  739. _reqGetAlbums = new XMLHttpRequest();
  740. if ( typeof _reqGetAlbums.overrideMimeType != 'undefined') {
  741. _reqGetAlbums.overrideMimeType('application/json');
  742. }
  743. _reqGetAlbums.onreadystatechange = function() {
  744. if (_reqGetAlbums.readyState == 4 && _reqGetAlbums.status == 200) {
  745. log('Webservice photosets.getList returned status=' + _reqGetAlbums.status + _reqGetAlbums.responseText);
  746. var obj = JSON.parse(_reqGetAlbums.responseText);
  747. if (obj && obj.stat == "ok") {
  748. log("ok");
  749. albums.ownerId = fixr.context.photographerId;
  750. albums.set = [];
  751. albums.html = '';
  752. albums.pathalias = '';
  753. if (obj.photosets) {
  754. if(parseInt(obj.photosets.total,10)===0) {
  755. // keep empty
  756. } else if (obj.photosets.photoset) {
  757. albums.set = obj.photosets.photoset;
  758. var elem;
  759. for(var i=0; i<obj.photosets.photoset.length; i++) {
  760. elem = obj.photosets.photoset[i]; // should loop through multiple
  761. log("elem is: "+elem.id+" with title="+elem.title._content);
  762. if (elem.primary_photo_extras && elem.primary_photo_extras.url_sq && elem.primary_photo_extras.url_sq.length>0) {
  763. log('photoset ikon url = ' + elem.primary_photo_extras.url_sq);
  764. albums.html += '<div><a href="//www.flickr.com/photos/' + elem.primary_photo_extras.pathalias + '/sets/' + elem.id + '"><img src="' + elem.primary_photo_extras.url_sq +'" alt="" /><div style="margin:0 0 .8em 0">' + elem.title._content + '</div></a></div>';
  765. }
  766. }
  767. albums.pathalias = elem.primary_photo_extras.pathalias;
  768. } else {
  769. log('why are we here?');
  770. }
  771. }
  772. } else {
  773. // error parse
  774. }
  775. document.getElementById('albumTeaser').innerHTML = '<div style="margin:0 0 .8em 0">Albums</div>'+albums.html+'<div><i><a href="/photos/'+albums.pathalias+'/albums/">More albums...</a></i></div>';
  776. } else {
  777. // wait for the call to complete
  778. }
  779. };
  780. if (fixr.context.photographerId === albums.ownerId && fixr.context.photographerId!='') {
  781. // use cached
  782. document.getElementById('albumTeaser').innerHTML = '<div style="margin:0 0 .8em 0">Albums</div>'+albums.html+'<div><i><a href="/photos/'+albums.pathalias+'/albums/">More albums...</a></i></div>';
  783. log('Using CACHED albumlist!');
  784. } else if (fixr.context.photographerId) {
  785. _reqGetAlbums.open('GET', 'https://api.flickr.com/services/rest/?method=flickr.photosets.getList&api_key=9b8140dc97b93a5c80751a9dad552bd4&user_id=' + fixr.context.photographerId + '&page=1&per_page=10&primary_photo_extras=geo%2C+path_alias%2C+url_sq&format=json&nojsoncallback=1', true);
  786. _reqGetAlbums.send(null);
  787. } else {
  788. log('Attribution user (photographer) not found');
  789. }
  790. } else {
  791. log('Understøtter ikke XMLHttpRequest');
  792. }
  793. }
  794. */