Stig's Flickr Fixr

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

目前為 2015-11-29 提交的版本,檢視 最新版本

// ==UserScript==
// @name        Stig's Flickr Fixr
// @namespace   dk.rockland.userscript.flickr.fixr
// @description Show photographer's albums on photostream-pages, Increase display-size and quality of "old" photos, Photographer's other photos by tag-links, Links to album-map and album-comments on album headers, A fix to actually show a geotagged photo on the from photo linked map - - - And maybe more to come later...
// @author      Stig Nygaard, http://www.rockland.dk, https://www.flickr.com/photos/stignygaard/
// @homepageURL http://www.rockland.dk/userscript/flickr/fixr/
// @supportURL  http://www.rockland.dk/userscript/flickr/fixr/#support
// @icon        http://www.rockland.dk/img/fixr32.png
// @icon64      http://www.rockland.dk/img/fixr64.png
// @include     https://www.flickr.com/*
// @include     https://flickr.com/*
// @match       https://*.flickr.com/*
// @version     2015.11.29.1
// @grant       none
// @run-at      document-start
// ==/UserScript==

// CHANGELOG - The most important updates/versions:
var changelog = [
  {version:'2015.11.28.1', description:'Added a new feature: Album-headers are now updated with links to album-map and album-comments'},
  {version:'2015.08.27.3', description:'Fixing an error when using the Chrome browser'},
  {version:'2015.08.26.4', description:'Initial release version'}
];

var DEBUG = false;
function log(s) {
  if (DEBUG && window.console) { window.console.log(s); }
}
if (DEBUG) {
  if ('loading' === document.readyState) {
    log("This userscript is running at document-start time.");
  } else {
    log("This userscript is running with document.readyState: " + document.readyState);
  }
  window.addEventListener('DOMContentLoaded', function () {log('(onDOMContentLoaded)'); }, false);
  window.addEventListener('focus', function () {log('(onfocus)'); }, false);
  window.addEventListener('load', function () {log('(onload)'); }, false);
  window.addEventListener('pageshow', function () {log('(onpageshow)'); }, false);
  window.addEventListener('resize', function () {log('(onresize)'); }, false);
  window.addEventListener('hashchange', function () {log('(onhashchange)'); }, false);
}

// FIXR page-tracker
var fixr = {
  context: {
    pageType: '',
    userId: '',
    photographerId: '', // value might be delayed (If uninitialized, try call initPhotographerId())
    photographerIcon: '',
    photographerAlias: '', // (pathalias) bonus-info sometimes initialized (from url) when initializing photoId or albumId
    photographerName: '',
    photoId: '',
    albumId: '',
    groupId: '',
    galleryId: ''
  },
  content: null,
  pageactionsCount: 0,
  timerResizeActionDelayed: 0,
  onPageHandlers: [],
  onResizeHandlers: [],
  initPhotographerId: function () { // photographer/attribution id
    var elem;
    if (document.querySelector('div.photostream-page-view')) {
      // photostream
      elem = document.querySelector('div.photostream-page-view div.fluid-photostream-coverphoto-view div.avatar.person');
    } else if (document.querySelector('div.photo-page-scrappy-view')) {
      // photopage
      elem = document.querySelector('div.photo-page-scrappy-view div.sub-photo-view div.avatar.person');
    } else if (document.querySelector('div.photo-page-lightbox-scrappy-view')) {
      // photopage lightbox
      elem = document.querySelector('div.photo-page-lightbox-scrappy-view div.photo-well-view div.photo-attribution div.avatar.person');
    } else if (document.querySelector('div.album-page-view')) {
      // album page
      elem = document.querySelector('div.album-page-view div.album-container div.album-header-view div.album-attribution div.avatar.person');
    } else {
      log('we do not look for photographerId on this page');
      return true;
    }
    // album oversigt
    // etc...
    // men minus f.eks. favorites oversigt!
    if (!elem) {
      log('fixr.initPhotographerId() - Attribution elem NOT found - returning false');
      return false;
    } // re-run a little later???
    log('fixr.initPhotographerId() - Attribution elem found');
    // (div.avatar.person).style.backgroundImage=url(https://s.yimg.com/pw/images/buddyicon07_r.png#44504567@N00)
    //                    .style.backgroundImage=url(//c4.staticflickr.com/8/7355/buddyicons/10259776@N00_r.jpg?1372021232#10259776@N00)
    if (elem.style.backgroundImage) {
      log('fixr.initPhotographerId() - elem has style.backgroundImage "' + elem.style.backgroundImage + '", now looking for the attribution id...');
      var pattern = /url[^#\?]+(\/\/[^#\?]+\.com\/[^#\?]+\/buddyicon[^\?\#]+)[^#]*#(\d+\@N\d{2})/i;
      // var pattern = /\/buddyicons\/(\d+\@N\d{2})\D+/i;
      var result = elem.style.backgroundImage.match(pattern);
      if (result) {
        log('fixr.initPhotographerId() - Attribution pattern match found: ' + result[0]);
        log('fixr.initPhotographerId() - the attribution icon is ' + result[1]);
        log('fixr.initPhotographerId() - the attribution id is ' + result[2]);
        fixr.context.photographerIcon = result[1];
        fixr.context.photographerId = result[2];
      } else {
        log('fixr.initPhotographerId() - attribution pattern match not found');
        return false;
      }
    } else {
      log('fixr.initPhotographerId() - elem.style.backgroundImage not found');
      return false;
    }
    log('fixr.initPhotographerId() - returning true...');
    return true;
  },
  initPhotoId: function () { // Photo Id
    //  *flickr.com/photos/user/PId/*
    var pattern = /^\/photos\/([^\/]+)\/([\d]{2,})/i;
    var result = window.location.pathname.match(pattern);
    if (result) {
      log('url match med photoId=' + result[2]);
      log('url match med photographerAlias=' + result[1]);
      fixr.context.photoId = result[2];
      fixr.context.photographerAlias = result[1];
      return true;
    }
    return false;
  },
  initAlbumId: function () {
    //  *flickr.com/photos/user/albums/AId/*
    //  *flickr.com/photos/user/sets/AId/*
    var pattern = /^\/photos\/([^\/]+)\/albums\/([\d]{2,})/i;
    var result = window.location.pathname.match(pattern);
    if(!result) {
      pattern = /^\/photos\/([^\/]+)\/sets\/([\d]{2,})/i;
      result = window.location.pathname.match(pattern);
    }
    if (result) {
      log('url match med albumId=' + result[2]);
      log('url match med photographerAlias=' + result[1]);
      fixr.context.albumId = result[2];
      fixr.context.photographerAlias = result[1];
      return true;
    }
    return false;
  },
  pageActions: function () {
    if (fixr.content) {
      log('fixr.pageActions() has started with fixr.content defined');
    } else {
      log('fixr.pageActions() was called, but fixr.content NOT defined');
      return;
    }
    fixr.pageactionsCount++;
    for (var p in fixr.context) {  // reset context on new page
      fixr.context[p] = ''; // filter ?
    }
    if (fixr.content.querySelector('div.photostream-page-view')) {
      if (fixr.content.querySelector('div.slideshow-view')) {
        fixr.context.pageType = 'PHOTOSTREAM SLIDESHOW';
      } else {
        fixr.context.pageType = 'PHOTOSTREAM';
      }
    } else if (fixr.content.querySelector('div.photo-page-scrappy-view')) {
      fixr.context.pageType = 'PHOTOPAGE';
    } else if (fixr.content.querySelector('div.photo-page-lightbox-scrappy-view')) {
      fixr.context.pageType = 'PHOTOPAGE LIGHTBOX';
    } else if (fixr.content.querySelector('div.albums-list-page-view')) {
      fixr.context.pageType = 'ALBUMSLIST';
    } else if (fixr.content.querySelector('div.album-page-view')) {
      if (fixr.content.querySelector('div.slideshow-view')) {
        fixr.context.pageType = 'ALBUM SLIDESHOW';
      } else {
        fixr.context.pageType = 'ALBUM';
      }
    } else if (fixr.content.querySelector('div.cameraroll-page-view')) {
      fixr.context.pageType = 'CAMERAROLL';
    } else if (fixr.content.querySelector('div.explore-page-view')) {
      fixr.context.pageType = 'EXPLORE';
    } else if (fixr.content.querySelector('div.favorites-page-view')) {
      if (fixr.content.querySelector('div.slideshow-view')) {
        fixr.context.pageType = 'FAVORITES SLIDESHOW';
      } else {
        fixr.context.pageType = 'FAVORITES';
      }
    } else if (fixr.content.querySelector('div.groups-list-view')) {
      fixr.context.pageType = 'GROUPSLIST'; // personal grouplist
    } else if (fixr.content.querySelector('div#activityFeed')) { // id=main i stedet for id=fixr.content
      fixr.context.pageType = 'ACTIVITYFEED'; // aka. front page
    } else {
      // fixr.context.pageType = ''; // unknown
    }

    log('fixr.context.pageType = ' + fixr.context.pageType);
    if (fixr.initPhotographerId()) {
      log('fixr.initPhotographerId() returned true');
    } else {
      log('fixr.initPhotographerId() returned false - re-running delayed...');
      setTimeout(fixr.initPhotographerId, 2000);
    }
    if (fixr.initPhotoId()) {
      log('fixr.initPhotoId() returned true');
    } else {
      log('fixr.initPhotoId() returned false');
    }
    if (fixr.initAlbumId()) {
      log('fixr.initAlbumId() returned true');
    }
    if (fixr.content.querySelector('a.owner-name')) {
      fixr.context.photographerName = fixr.content.querySelector('a.owner-name').textContent;
    }

    // Now run the page handlers....
    if (fixr.onPageHandlers && fixr.onPageHandlers !== null && fixr.onPageHandlers.length) {
      log('We have ' + fixr.onPageHandlers.length + ' onPage handlers starting now...');
      for (var f = 0; f < fixr.onPageHandlers.length; f++) {
        fixr.onPageHandlers[f]();
      }
    }
  },
  setupContent: function () {
    if (document.getElementById('content')) {
      fixr.content = document.getElementById('content');
    } else if (document.getElementById('main')) {
      fixr.content = document.getElementById('main');    // frontpage
    }
    if (fixr.content && fixr.content.id) {
      log('fixr.content.id = ' + fixr.content.id);
    } else {
      log('content or main element NOT found!');
    }
  },
  runPageActionsIfMissed: function () {
    if (fixr.pageactionsCount === 0) {
      log('Vi kører fixr.pageActions() på bagkant via onload...');
      fixr.setupContent();
      if (fixr.content === null) {
        log('Vi kan IKKE køre fixr.pageActions() på bagkant, da fixr.content ikke er defineret');
        return;
      }
      fixr.pageActions();
    } else {
      log('ej nødvendigt at køre fixr.pageActions() på bagkant i dette tilfælde...');
    }
  },
  runDelayedPageActionsIfMissed: function () {
    setTimeout(fixr.runPageActionsIfMissed, 2000);
  },
  resizeActions: function () {
    if (fixr.onResizeHandlers && fixr.onResizeHandlers !== null && fixr.onResizeHandlers.length) {
      for (var f = 0; f < fixr.onResizeHandlers.length; f++) {
        fixr.onResizeHandlers[f]();
      }
    }
  },
  resizeActionsDelayed: function () { // or "preburner"
    clearTimeout(fixr.timerResizeActionDelayed);
    fixr.timerResizeActionDelayed = setTimeout(fixr.resizeActions, 250);
  },
  setupObserver: function () {
    log('fixr.setupObserve INITIALIZATION START');
    fixr.setupContent();
    if (fixr.content === null) {
      log('Init fails because content not defined');
      return;
    }
    // create an observer instance
    var observer = new MutationObserver(function (mutations) {
      log('NEW PAGE MUTATION!');
      //mutations.forEach(function(mutation) {
      //  log('MO: '+mutation.type); // might check for specific type of "mutations" (MutationRecord)
      //});
      fixr.pageActions();
    }); // MutationObserver end
    // configuration of the observer:
    var config = {attributes: false, childList: true, subtree: false, characterData: false};
    observer.observe(fixr.content, config);
    log('fixr.setupObserve INITIALIZATION DONE');
  },
  init: function (onPageHandlerArray, onResizeHandlerArray) {
    // General page-change observer setup:
    window.addEventListener('DOMContentLoaded', fixr.setupObserver, false); // Page on DOMContentLoaded
    window.addEventListener('load', fixr.runDelayedPageActionsIfMissed, false); // Page on load
    window.addEventListener('resize', fixr.resizeActionsDelayed, false); // også på resize
    if (onPageHandlerArray && onPageHandlerArray !== null && onPageHandlerArray.length) {
      fixr.onPageHandlers = onPageHandlerArray; // Replace by adding with a one-by-one by "helper" for flexibility?
    }
    if (onResizeHandlerArray && onResizeHandlerArray !== null && onResizeHandlerArray.length) {
      fixr.onResizeHandlers = onResizeHandlerArray; // Replace by adding with a one-by-one by "helper" for flexibility?
    }
  }
};
// FIXR page-tracker end


var _timerMaplink = 0;
function updateMapLink() {
  if (fixr.context.pageType !== 'PHOTOPAGE') {
    return; // exit if not photopage
  }
  log('updateMapLink() running at readystate=' + document.readyState + ' and with photoId=' + fixr.context.photoId);
  if (fixr.context.photoId) {
    var maplink = fixr.content.querySelector('a.static-maps');
    if (maplink) {
      if (maplink.getAttribute('href') && (maplink.getAttribute('href').indexOf('map/?') > 0) && (maplink.getAttribute('href').indexOf('&photo=') === -1)) {
        maplink.setAttribute('href', maplink.getAttribute('href') + '&photo=' + fixr.context.photoId);
        log('link is updated by updateMapLink() at readystate=' + document.readyState);
      } else {
        log('link NOT updated by updateMapLink(). Invalid element or already updated. readystate=' + document.readyState);
      }
    } else {
      log('NO maplink found at readystate=' + document.readyState + '. Re-try later?');
    }
  } else {
    log('NO photoId found at readystate=' + document.readyState);
  }
}
function updateMapLinkDelayed() {
  if (fixr.context.pageType !== 'PHOTOPAGE') {
    return;
  } // exit if not photopage
  log('updateMapLinkDelayed() running... with pageType=' + fixr.context.pageType);
  //clearTimeout(_timerMaplink);
  _timerMaplink = setTimeout(updateMapLink, 2000); // make maplink work better on photopage
}

var album = { // cache to avoid repeating requests
  albumId: '',
  commentCount: 0
};
function updateAlbumCommentCount() {
  var _reqAlbumComments = null;
  if (window.XMLHttpRequest) {
    _reqAlbumComments = new XMLHttpRequest();
    if (typeof _reqAlbumComments.overrideMimeType !== 'undefined') {
      _reqAlbumComments.overrideMimeType('text/html');
    }

    _reqAlbumComments.onreadystatechange = function () {
      if (_reqAlbumComments.readyState === 4 && _reqAlbumComments.status === 200) {
        log('_reqAlbumComments returned status=' + _reqAlbumComments.status);
        var doc = document.implementation.createHTMLDocument("sizeDoc");
        doc.documentElement.innerHTML = _reqAlbumComments.responseText;
        album.albumId = fixr.context.albumId;
        album.commentCount = -1;
        var e = doc.body.querySelectorAll('span.LinksNew b.Here');
        if (e && e.length===1) {
          var n = parseInt(e[0].textContent, 10);
          if (isNaN(n)) {
            album.commentCount = 0;
          } else {
            album.commentCount = n;
          }
        } else {
          album.commentCount = -1;
          log('b.Here??? ');
        }
        if (document.getElementById('albumCommentCount')) {
          if (album.commentCount===-1) {
            document.getElementById('albumCommentCount').innerHTML = '?';
          } else {
            document.getElementById('albumCommentCount').innerHTML = '' + album.commentCount;
          }
        } else {
          log('albumCommentCount element not found');
        }
      } else {
        // wait for the call to complete
      }
    };

    if (fixr.context.albumId === album.albumId && fixr.context.albumId !== '' && album.commentCount!==-1) {
      log('Usinging CACHED album count!...');
      document.getElementById('albumCommentCount').innerHTML = ''+album.commentCount;
    } else if (fixr.context.albumId!=='') {
      var url = 'https://www.flickr.com/photos/' + (fixr.context.photographerAlias !== '' ? fixr.context.photographerAlias : fixr.context.photographerId) + '/albums/' + fixr.context.albumId + '/comments/';
      _reqAlbumComments.open('GET', url, true);
      _reqAlbumComments.send(null);
    } else {
      log('albumId not initialized');
    }
  } else {
    log('understøtter ikke XMLHttpRequest');
  }
}

var albums = { // cache albums to avoid repeating requests
  ownerId: '',
  html: '',
  count: 0
};
function getAlbumlist() {
  var _reqAlbumlist = null;
  if (window.XMLHttpRequest) {
    _reqAlbumlist = new XMLHttpRequest();
    if (typeof _reqAlbumlist.overrideMimeType !== 'undefined') {
      _reqAlbumlist.overrideMimeType('text/html');
    }

    _reqAlbumlist.onreadystatechange = function () {
      if (_reqAlbumlist.readyState === 4 && _reqAlbumlist.status === 200) {
        log('_reqAlbumlist returned status=' + _reqAlbumlist.status); // + ', \ntext:\n' + _reqAlbumlist.responseText);
        var doc = document.implementation.createHTMLDocument("sizeDoc");
        doc.documentElement.innerHTML = _reqAlbumlist.responseText;

        albums.ownerId = fixr.context.photographerId;
        albums.html = '';
        albums.count = 0;
        var e = doc.body.querySelectorAll('div.photo-list-album-view');
        var imgPattern = /url\([\'\"]*([^\)\'\"]+)(\.[jpgtifn]{3,4})[\'\"]*\)/i;
        if (e && e.length > 0) {
          albums.count = e.length;
          for (var i = 0; i < Math.min(10, e.length); i++) {
            var imgUrl = '';
            log(e[i].outerHTML);
            log('A7 (' + i + ') : '+e[i].style.backgroundImage);
            // var result = e[i].style.backgroundImage.match(imgPattern); // strangely not working in Chrome
            var result = (e[i].outerHTML).match(imgPattern); // quick work-around for above (works for now)
            if (result) {
              imgUrl = result[1].replace(/_[a-z]$/, '') + '_s' + result[2];
              log('imgUrl=' + imgUrl);
            } else {
              log('No match on imgPattern');
            }
            var a = e[i].querySelector('a[href][title]'); // sub-element
            if (a && a!==null) {
              log('Album title: ' + a.title);
              log('Album url: ' + a.getAttribute('href'));
              albums.html += '<div><a href="//www.flickr.com' + a.getAttribute('href') + '"><img src="' + imgUrl + '" alt="" /><div style="margin:0 0 .8em 0">' + a.title + '</div></a></div>';
            } else {
              log('a element not found?');
            }
          }
        }
        if (document.getElementById('albumTeaser')) {
          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>';
        } else {
          log('albumTeaser NOT FOUND!?!');
        }
      } else {
        // wait for the call to complete
      }
    };

    if (fixr.context.photographerId === albums.ownerId && fixr.context.photographerId !== '') {
      log('Usinging CACHED albumlist!...');
      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>';
    } else if (fixr.context.photographerId) {
      var url = 'https://www.flickr.com/photos/' + (fixr.context.photographerAlias !== '' ? fixr.context.photographerAlias : fixr.context.photographerId) + '/albums';
      _reqAlbumlist.open('GET', url, true);
      _reqAlbumlist.send(null);
    } else {
      log('Attribution user (photographer) not found');
    }
  } else {
    log('understøtter ikke XMLHttpRequest');
  }
}
function albumTeaser() {
  if (fixr.context.pageType !== 'PHOTOSTREAM') {
    return; // exit if not photostream
  }
  log('albumTeaser() running');
  var dpc = document.querySelector('div.photolist-container');
  if (!dpc) {
    return;
  }
  // to-do: check om personlig photostream?
  // to-do: check padding-right er mindst 130px?
  log('AlbumTeaser found div.photolist-container');
  if (!document.getElementById('albumTeaser')) {
    dpc.style.position = "relative";
    dpc.insertAdjacentHTML('afterbegin', '<div id="albumTeaser" style="border:none;margin:0;padding:0;position:absolute;top:0;right:10px;width:100px"></div>');
  }
  if (document.getElementById('albumTeaser')) {
    getAlbumlist();  // også check på fixr.context.photographerId ?
  }
}
var _timerAlbumTeaserDelayed;
function albumTeaserDelayed() {
  if (fixr.context.pageType !== 'PHOTOSTREAM') {
    return; // exit if not photostream
  }
  log('albumTeaserDelayed() running...');
  clearTimeout(_timerAlbumTeaserDelayed);
  _timerAlbumTeaserDelayed = setTimeout(albumTeaser, 1500);
}

function getUserId() { // Id of logged-in user
  return null; // to-do
}

var scaler = {
  photoId: '',
  mf: null,   // document.querySelector('img.main-photo') for (re-)re-scale
  lrf: null,  // document.querySelector('img.low-res-photo') for (re-)re-scale
  maxSizeUrl: '',
  hasOriginal: false,
  scaleToWidth: 0,
  scaleToHeight: 0,
  run: function () {
    if (fixr.context.pageType !== 'PHOTOPAGE' && fixr.context.pageType !== 'PHOTOPAGE LIGHTBOX') {
      return; // exit if not photopage or lightbox
    }
    log('scaler.run() running...');
    // var that = this;
    var scale = function () {
      if (fixr.context.pageType !== 'PHOTOPAGE' && fixr.context.pageType !== 'PHOTOPAGE LIGHTBOX') {
        return;
      } // exit if not photopage or lightbox
      log('scaler.scale() running... (scale to:' + scaler.scaleToWidth + 'x' + scaler.scaleToHeight + ')');
      scaler.mf = document.querySelector('img.main-photo');  // for en sikkerheds skyld
      scaler.lrf = document.querySelector('img.low-res-photo');  // for en sikkerheds skyld
      if (scaler.mf && scaler.mf !== null && scaler.lrf && scaler.lrf !== null && scaler.scaleToWidth > 0 && scaler.scaleToHeight > 0) {
        log('[scaler] do scaling WORK. Height from ' + scaler.mf.height + ' to ' + scaler.scaleToHeight);
        scaler.mf.height = scaler.scaleToHeight;
        log('[scaler] do scaling WORK. Width from ' + scaler.mf.width + ' to ' + scaler.scaleToWidth);
        scaler.mf.width = scaler.scaleToWidth;
        scaler.lrf.height = scaler.mf.height;
        scaler.lrf.width = scaler.mf.width;
      }
    };
    var replace = function () { // and (re-)scale?
      if (fixr.context.pageType !== 'PHOTOPAGE' && fixr.context.pageType !== 'PHOTOPAGE LIGHTBOX') {
        return; // exit if not photopage or lightbox
      }
      log('scaler.run.replace() running...');
      scaler.mf = document.querySelector('img.main-photo');  // for en sikkerheds skyld
      if (scaler.mf && scaler.mf !== null) {
        scaler.mf.src = scaler.maxSizeUrl; // only if original
        scale();
      }
    };
    var getSizes = function () {
      log('scaler.run.getSizes() running...');
      var _reqAllSizes = null;
      if (window.XMLHttpRequest) {
        _reqAllSizes = new XMLHttpRequest();
        if (typeof _reqAllSizes.overrideMimeType !== 'undefined') {
          _reqAllSizes.overrideMimeType('text/html');
        }
        _reqAllSizes.onreadystatechange = function () {
          if (_reqAllSizes.readyState === 4 && _reqAllSizes.status === 200) {
            log('[scaler] _reqAllSizes returned status=' + _reqAllSizes.status); // + ', \ntext:\n' + _reqAllSizes.responseText);
            var doc = document.implementation.createHTMLDocument("sizeDoc");
            doc.documentElement.innerHTML = _reqAllSizes.responseText;
            if (doc.body.querySelector('div#allsizes-photo>img')) {
              scaler.maxSizeUrl = doc.body.querySelector('div#allsizes-photo>img').src;
              log('[scaler] Largest image size: ' + scaler.maxSizeUrl);
            }
            var e = doc.body.querySelectorAll('ol.sizes-list li ol li');
            if (e && e.length > 0) {
              var s = e[e.length - 1].textContent.replace(/\s{2,}/g, ' ');
              if (s.indexOf('Original') > -1) {
                scaler.hasOriginal = true;
                log('[scaler] ' + s);
                replace();
              } else {
                log('[scaler] Bruger tillader ikke adgang til original');
              }
              // udtræk evt sizes fra s?
            }
          } else {
            // wait for the call to complete
          }
        };
        var url = 'https://www.flickr.com/photos/' + (fixr.context.photographerAlias !== '' ? fixr.context.photographerAlias : fixr.context.photographerId) + '/' + fixr.context.photoId + '/sizes/o';
        _reqAllSizes.open('GET', url, true);
        _reqAllSizes.send(null);
      } else {
        log('[scaler] understøtter ikke XMLHttpRequest');
      }
    };
    if (scaler.photoId === '') {
      scaler.photoId = fixr.context.photoId;
    } else if (scaler.photoId !== fixr.context.photoId) {
      scaler.photoId = fixr.context.photoId;
      scaler.mf = null;
      scaler.lrf = null;
      scaler.maxSizeUrl = '';
      scaler.hasOriginal = false;
      scaler.scaleToWidth = 0;
      scaler.scaleToHeight = 0;
    }
    var roomHeight = 0;
    var roomWidth = 0;
    var roomPaddingHeight = 0;
    var roomPaddingWidth = 0;

    // Fortsæt kun hvis PhotoId!!!?

    var dpev = document.querySelector('div.photo-engagement-view');
    var pwv = document.querySelector('div.photo-well-view');
    if (pwv) {
      log('[scaler] height-controller: height=' + pwv.clientHeight + ' (padding=70?), width=' + pwv.clientWidth + ' (padding=80?).'); // hc.style.padding: 20px 40px 50px
      if (roomHeight === 0) {
        roomHeight = pwv.clientHeight;
      }
      if (roomWidth === 0) {
        roomWidth = pwv.clientWidth;
      }
      roomPaddingHeight += (parseInt(window.getComputedStyle(pwv, null).getPropertyValue('padding-top'), 10) + parseInt(window.getComputedStyle(pwv, null).getPropertyValue('padding-bottom'), 10));
      roomPaddingWidth += (parseInt(window.getComputedStyle(pwv, null).getPropertyValue('padding-left'), 10) + parseInt(window.getComputedStyle(pwv, null).getPropertyValue('padding-right'), 10));
    }
    var hc = document.querySelector('div.height-controller');
    if (hc) {
      log('[scaler] height-controller: height=' + hc.clientHeight + ' (padding=70?), width=' + hc.clientWidth + ' (padding=80?).'); // hc.style.padding: 20px 40px 50px
      if (roomHeight === 0) {
        roomHeight = hc.clientHeight;
      }
      if (roomWidth === 0) {
        roomWidth = hc.clientWidth;
      }
      roomPaddingHeight += (parseInt(window.getComputedStyle(hc, null).getPropertyValue('padding-top'), 10) + parseInt(window.getComputedStyle(hc, null).getPropertyValue('padding-bottom'), 10));
      roomPaddingWidth += (parseInt(window.getComputedStyle(hc, null).getPropertyValue('padding-left'), 10) + parseInt(window.getComputedStyle(hc, null).getPropertyValue('padding-right'), 10));
    }
    var pwmsv = document.querySelector('div.photo-well-media-scrappy-view');
    if (pwmsv) {
      log('[scaler] div.photo-well-media-scrappy-view: height=' + pwmsv.clientHeight + ' (padding=70?), width=' + pwmsv.clientWidth + ' (padding=80?).'); // pwmsv.style.padding: 20px 40px 50px
      if (roomHeight === 0) {
        roomHeight = pwmsv.clientHeight;
      }
      if (roomWidth === 0) {
        roomWidth = pwmsv.clientWidth;
      }
      roomPaddingHeight += (parseInt(window.getComputedStyle(pwmsv, null).getPropertyValue('padding-top'), 10) + parseInt(window.getComputedStyle(pwmsv, null).getPropertyValue('padding-bottom'), 10));
      roomPaddingWidth += (parseInt(window.getComputedStyle(pwmsv, null).getPropertyValue('padding-left'), 10) + parseInt(window.getComputedStyle(pwmsv, null).getPropertyValue('padding-right'), 10));
    }
    scaler.mf = document.querySelector('img.main-photo');
    scaler.lrf = document.querySelector('img.low-res-photo');
    // var zl = document.querySelector('img.zoom-large'); // currently not used
    // var zs = document.querySelector('img.zoom-small'); // currently not used
    if (scaler.mf) {
      log('[scaler] main-photo: h=' + scaler.mf.height + ', w=' + scaler.mf.width + '.  -  Room: (h=' + (roomHeight - roomPaddingHeight) + ',w=' + (roomWidth - roomPaddingWidth) + ')');
      if (roomPaddingWidth === 0) { // hack
        roomPaddingWidth = 120;
        log('[scaler] roomPaddingWidth=120 hack used');
      }
      if (((roomHeight - roomPaddingHeight) > scaler.mf.height + 5) && ((roomWidth - roomPaddingWidth) > scaler.mf.width + 5)) {
        log('[scaler] ALLRIGHT - WE ARE READY FOR SCALING!...');
        if (((roomHeight - roomPaddingHeight) / scaler.mf.height) < ((roomWidth - roomPaddingWidth) / scaler.mf.width)) {
          scaler.scaleToWidth = Math.floor(scaler.mf.width * ((roomHeight - roomPaddingHeight) / scaler.mf.height));
          scaler.scaleToHeight = roomHeight - roomPaddingHeight;
        } else {
          scaler.scaleToHeight = Math.floor(scaler.mf.height * ((roomWidth - roomPaddingWidth) / scaler.mf.width));
          scaler.scaleToWidth = roomWidth - roomPaddingWidth;
        }
        log('[scaler] now calling scale()... [' + scaler.scaleToWidth + ', ' + scaler.scaleToWidth + ']');
        scale();
        log('[scaler] ...AND CONTINUE LOOKING FOR ORIGINAL...');
        if (dpev) { // if (document.querySelector('ul.sizes'))
          var org = document.querySelector('ul.sizes li.Original a.download-image-size');
          if (org) { // når vi bladrer?
            scaler.hasOriginal = true; // ??? kun hvis original
            scaler.maxSizeUrl = (org.href).replace(/^https\:/i, '').replace(/_d\./i, '.');
            replace();
          } else {
            // vi kan finde original "inline"
            var target = document.querySelector('div.photo-engagement-view');
            // if(!target) return; ???
            if (target) {
              var observer = new MutationObserver(function (mutations) {
                mutations.forEach(function (mutation) {
                  log('[scaler] MO size: ' + mutation.type); // might check for specific "mutations"?
                });
                var org = document.querySelector('ul.sizes li.Original a.download-image-size');
                if (org) {
                  scaler.hasOriginal = true; // ??? kun hvis original
                  scaler.maxSizeUrl = (org.href).replace(/^https\:/i, '').replace(/_d\./i, '.');
                  replace();
                } else {
                  scale(); // ???
                  log('Original photo not available for download on this photographer');
                }
                observer.disconnect();
              });
              // configuration of the observer:
              var config = {attributes: false, childList: true, subtree: false, characterData: false};
              observer.observe(target, config);
            }
          }
        } else {
          getSizes(); // resize (& replace) from/when size-list
        }
      }
    }
  }
};

function insertStyle() {
  log('tagStyle()');
  if (!document.getElementById('fixrStyle')) {
    var style = document.createElement('style');
    style.type = 'text/css';
    style.id = 'fixrStyle';
    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;} .album-map-icon{background:url("https://s.yimg.com/uy/build/images/scrappy/scrappy-1x-s41c2371182.png") -21px -197px no-repeat;height:21px;width:24px;top:6px;left:3px} .album-comments-icon{background:url("https://s.yimg.com/uy/build/images/icons-1x-s2fb29ad15b.png") -32px -460px no-repeat;height:21px;width:24px;top:6px;left:3px}';
    document.getElementsByTagName('head')[0].appendChild(style);
    log('fixrStyle has been ADDED');
  } else {
    log('fixrStyle was already present');
  }
}
function albumExtras() { // links to album's map and comments
  if (fixr.context.pageType !== 'ALBUM') {
    return; // exit if not albumpage
  }
  if (fixr.context.albumId) {
    log('albumsExtra() med album='+fixr.context.albumId);
  } else {
    log('Exit albumsExtra(). Mangler albumId');
    return;
  }
  var elist = document.querySelector('div.album-engagement-view');
  if (elist) {
    // map-link:
    var mapdiv = document.createElement('div');
    mapdiv.className = 'create-book-container';
    mapdiv.title = 'Album on map';
    mapdiv.style.textAlign = 'center';
    mapdiv.innerHTML = '<a href="/photos/' + fixr.context.photographerAlias + '/albums/' + fixr.context.albumId + '/map/" style="font-size:14px;color:#FFF;"><span title="Album on map" class="album-map-icon"></span></a>';
    elist.appendChild(mapdiv);
    // comments-link:
    var comurl = '/photos/' + fixr.context.photographerAlias + '/albums/' + fixr.context.albumId + '/comments/';
    var cmdiv = document.createElement('div');
    cmdiv.className = 'create-book-container';
    cmdiv.title = 'Comments';
    cmdiv.style.textAlign = 'center';
    cmdiv.innerHTML = '<a href="' + comurl + '" style="font-size:14px;color:#FFF;"><span title="Album comments" class="album-comments-icon" id="albumCommentCount"></span></a>';
    elist.appendChild(cmdiv);
    updateAlbumCommentCount();
  }
}
function updateTags() {
  if (fixr.context.pageType !== 'PHOTOPAGE') {
    return; // exit if not photopage
  }
  log('updateTags()');
  if (document.querySelector('ul.tags-list')) {
    var tags = document.querySelectorAll('ul.tags-list>li');
    if (tags && tags !== null && tags.length > 0) {
      for (var i = 0; i < tags.length; i++) {
        var atag = tags[i].querySelector('a[title][href*="?tags="],a[title][href*="?q="]');
        if (atag) {
          var realtag = (atag.href.match(/\?(tags|q)\=([\S]+)$/i))[2];
          if (!(tags[i].querySelector('a.fixrTag'))) {
            //log('updateTags() '+i+' fixr.context.photographerIcon: '+fixr.context.photographerIcon);
            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?
            //log('updateTags() '+i+' icon: '+icon); //
            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>');
          }
        }
      }
    } else {
      log('no tags defined (yet?)');
    }
  } else {
    log('taglist container not found');
  }
}
function updateTagsDelayed() {
  if (fixr.context.pageType !== 'PHOTOPAGE') {
    return; // exit if not photopage
  }
  log('updateTagsDelayed() running... with pageType=' + fixr.context.pageType);
  //clearTimeout(_timerMaplink);
  if (fixr.context.pageType === 'PHOTOPAGE') {
    setTimeout(updateTags, 2500);
  }
}

// FIXR fixr.init(onPageHandlers, onResizeHandlers)
fixr.init([scaler.run, insertStyle, albumExtras, albumTeaserDelayed, updateMapLinkDelayed, updateTagsDelayed], [scaler.run]);



/* OLD STUFF...


 // Call Flickr REST API to get available photo sizes - Method currently NOT used:
 function wsGetSizes(photoId) {
 var _reqGetSizes = null;
 if (window.XMLHttpRequest) {
 _reqGetSizes = new XMLHttpRequest();
 if ( typeof _reqGetSizes.overrideMimeType !== 'undefined') {
 _reqGetSizes.overrideMimeType('application/json');
 }
 _reqGetSizes.onreadystatechange = function() {
 if (_reqGetSizes.readyState === 4 && _reqGetSizes.status === 200) {
 // do something with the results
 // var myObj = eval ( _reqGetSizes.responseText );
 log('webservice photos.getSizes returned status=' + _reqGetSizes.status + ', text: ' + _reqGetSizes.responseText);
 var obj = JSON.parse(_reqGetSizes.responseText);
 if (obj.stat === "ok") {
 log("ok");
 if (obj.sizes.candownload==1) {
 log("can download");
 var array = obj.sizes.size;
 if (array && array.length>0) {
 log("array length="+array.length);
 var elem = array[array.length-1];
 if (elem) {
 log("last elem is: "+elem.label+" with source="+elem.source);
 if (elem.label==="Original" && elem.source && elem.source.length>0) {
 // make sure photoId matches source
 photoOrg(elem.source);
 log("Original from webservice was used");
 }
 }
 }
 } else {
 log('Originals not available on user');
 }
 }
 // Hvis sizeList && original tilgængelig
 //   photoOrg(url); // Update image now!!!
 // ellers hvis sizelist
 //   log('Originals not available on user');
 // ellers hvis sizelist
 //   log('Error fetching original');
 } else {
 // wait for the call to complete
 }
 };

 _reqGetSizes.open('GET', 'https://api.flickr.com/services/rest/?method=flickr.photos.getSizes&api_key=9b8140dc97b93a5c80751a9dad552bd4&photo_id=' + photoId + '&format=json&nojsoncallback=1', true);
 _reqGetSizes.send(null);

 } else {
 log('understøtter ikke XMLHttpRequest');
 }
 }


 // Call Flickr REST API to get albums - Method currently NOT used:
 function wsGetAlbums() {
 var _reqGetAlbums = null;
 if (window.XMLHttpRequest) {
 _reqGetAlbums = new XMLHttpRequest();
 if ( typeof _reqGetAlbums.overrideMimeType != 'undefined') {
 _reqGetAlbums.overrideMimeType('application/json');
 }
 _reqGetAlbums.onreadystatechange = function() {
 if (_reqGetAlbums.readyState == 4 && _reqGetAlbums.status == 200) {
 log('Webservice photosets.getList returned status=' + _reqGetAlbums.status + _reqGetAlbums.responseText);
 var obj = JSON.parse(_reqGetAlbums.responseText);
 if (obj && obj.stat == "ok") {
 log("ok");
 albums.ownerId = fixr.context.photographerId;
 albums.set = [];
 albums.html = '';
 albums.pathalias = '';
 if (obj.photosets) {
 if(parseInt(obj.photosets.total,10)===0) {
 // keep empty
 } else if (obj.photosets.photoset) {
 albums.set = obj.photosets.photoset;
 var elem;
 for(var i=0; i<obj.photosets.photoset.length; i++) {
 elem = obj.photosets.photoset[i];  // should loop through multiple
 log("elem is: "+elem.id+" with title="+elem.title._content);
 if (elem.primary_photo_extras && elem.primary_photo_extras.url_sq && elem.primary_photo_extras.url_sq.length>0) {
 log('photoset ikon url = ' + elem.primary_photo_extras.url_sq);
 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>';
 }
 }
 albums.pathalias = elem.primary_photo_extras.pathalias;
 } else {
 log('why are we here?');
 }
 }
 } else {
 // error parse
 }
 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>';
 } else {
 // wait for the call to complete
 }
 };
 if (fixr.context.photographerId === albums.ownerId && fixr.context.photographerId!='') {
 // use cached
 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>';
 log('Using CACHED albumlist!');
 } else if (fixr.context.photographerId) {
 _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);
 _reqGetAlbums.send(null);
 } else {
 log('Attribution user (photographer) not found');
 }
 } else {
 log('Understøtter ikke XMLHttpRequest');
 }
 }
 */