Greasy Fork

Stig's Flickr Fixr

Show photographer's albums on photostream-pages, Increase display-size and quality of "old" photos, Display photo-notes, 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 more to come?...

目前为 2015-12-10 提交的版本。查看 最新版本

// ==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, Display photo-notes, 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 more to come?...
// @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/
// @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.12.10.1
// @grant       none
// @run-at      document-start
// ==/UserScript==

// CHANGELOG - The most important updates/versions:
var changelog = [
    {version: '2015.12.*.*', description: 'Minor fixes and new features in development...'},
    {version: '2015.12.05.2', description: 'Photo-notes support now includes displaying active links and formatting.'},
    {version: '2015.12.03.2', description: 'New feature: Basic "beta" support for the good old photo-notes (read-only, public and safe photos only, no formatting/links, not working in Lightbox mode).'},
    {version: '2015.11.30.1', description: 'Better icon for the new album-map links.'},
    {version: '2015.11.28.1', description: '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); // instead of onload?
    window.addEventListener('resize', function(){log('(onresize)');}, false);
    window.addEventListener('hashchange', function(){log('(onhashchange)');}, false);
    window.addEventListener('blur', function(){log('(onblur)');}, 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: [],
    onFocusHandlers: [],
    runningDirty: function() { // Extra experiments enabled?
        return (DEBUG && (fixr.context.userId==='10259776@N00'));
    },
    initUserId: function () {
        if (window.auth && window.auth.user && window.auth.user.nsid) {
            fixr.context.userId = window.auth.user.nsid;
            return true;
        }
        return false;
    },
    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.initUserId()) {
            log('fixr.initUserId() returned with succes: '+fixr.context.userId);
        } else {
            log('fixr.initUserId() returned FALSE!');
        }
        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);
    },
    focusActions: function () {
        if (fixr.onFocusHandlers && fixr.onFocusHandlers !== null && fixr.onFocusHandlers.length) {
            for (var f = 0; f < fixr.onFocusHandlers.length; f++) {
                fixr.onFocusHandlers[f]();
            }
        }
    },
    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, onFocusHandlerArray) {
        // 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
        window.addEventListener('focus', fixr.focusActions, false);
        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?
        }
        if (onFocusHandlerArray && onFocusHandlerArray !== null && onFocusHandlerArray.length) {
            fixr.onFocusHandlers = onFocusHandlerArray;
        }
    }
};
// 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);
}

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,
    postAction: function() {
        log('scaler.postAction');
    },
    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 () { // Do the actual scaling
            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;
            }
            scaler.postAction('notes on scaled photo');
        };
        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
                }
            }
            scaler.postAction('notes on unscaled photo'); // look for notes (not (yet?) scaled)
        }
    }
};

function insertStyle() {
    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://c2.staticflickr.com/6/5654/23426346485_334afa6e8f_o_d.png") 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} .notebrd1{position:absolute;border:1px solid #000;z-index:1000;margin:0;padding:0;display:none;} .notebrd2{border:1px solid #FFF;margin:0;padding:0;display:none;} .shownotes .notebrd1{display:block;} .shownotes .notebrd2{display:block;} .photo-well-media-scrappy-view:hover .notebrd1{display:block;} .photo-well-media-scrappy-view:hover .notebrd2{display:block;} .notebrd1:hover{z-index:1001} .notebrd1:hover .notebrd2{border:1px solid #FF0;} .ncontent{display:none;position:relative;width:150px;min-height:2.4em;z-index:1010;border:1px solid #000;background-color:#FEC;margin:0;padding:0.3em;} .notebrd1:hover .ncontent{display:block;-webkit-user-select:text;-khtml-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text;}';
        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);
    }
}

function showNotes() {
    var container = document.querySelector('div.photo-well-media-scrappy-view');
    if (container && container.classList) {
        container.classList.add('shownotes');
    }
}

function hideNotes() {
    var container = document.querySelector('div.photo-well-media-scrappy-view');
    if (container && container.classList) {
        container.classList.remove('shownotes');
    }
}

var photoInfo = { // cache albums to avoid repeating requests
    photoId: '',
    notes: [],
    json: ''
};
clearNotesZ = function() {
    var nn = document.querySelectorAll('div.notebrd1');
    for(var j=0;j<nn.length;j++){
        nn[j].style.zIndex='';
    }
};
levelNotesZ = function() {
    var nn = document.querySelectorAll('div.notebrd1');
    for(var i=0; i<nn.length; i++) {
        nn[i].style.zIndex = '1000';
    }
    setTimeout(clearNotesZ,500);
};
function makeEditableNote() {
    alert('edit!');
};
function renderNotes() {
    var scalefactor = 1;
    if (parseInt(document.querySelector('img.main-photo').getAttribute('width'),10)>=parseInt(document.querySelector('img.main-photo').getAttribute('height'),10)) {
        scalefactor = parseInt(document.querySelector('img.main-photo').getAttribute('width'),10)/500;
    } else {
        scalefactor = parseInt(document.querySelector('img.main-photo').getAttribute('height'),10)/500;
    }

    // Slet alle eksisterende noter først (kan blive genereret multiple gange ved skalering)
    var oldnode = document.querySelector('div.notebrd1');
    while (oldnode && oldnode.parentNode) {
        oldnode.parentNode.removeChild(oldnode);
        oldnode = document.querySelector('div.notebrd1');
    }

    // log(''+parseInt(document.querySelector('img.main-photo').getAttribute('width'),10)+'px wide photo has scalefactor='+scalefactor);
    if (DEBUG && photoInfo.notes.length>0) {
        log('You might also see notes at: http://dh.elsewhere.org/mbedr/?p=' + fixr.context.photoId + '&fmt=Medium&v');
    }

    photoInfo.notes.sort(function(a,b){return (a.w*a.h)-(b.w*b.h);});
    for (var i=0; i<photoInfo.notes.length; i++) // notes=obj.photo.notes.note
    {
        var n = photoInfo.notes[i];
        //log('Note med id=' + n.id + ', author=' + n.author + ', authorname=' + n.authorname + ', x=' + n.x + ', y=' + n.y + ', w=' + n.w + ', h=' + n.h + ', _content=' + n._content + '.');
        var div = document.createElement('div'); // content
        if(i===0) log(encodeURIComponent(n._content));
        div.innerHTML = n._content.replace(/\n/g, '<br />') + '<div style="text-align:right"><i>- <a href="https://www.flickr.com/photos/' + n.author + '/">' + n.authorname + '</a></i></div>';
        // div.innerHTML = '<textarea wrap="on">' + n._content + '</textarea><div style="text-align:right"><i>- <a href="https://www.flickr.com/photos/' + n.author + '/">' + n.authorname + '</a></i></div>';
        div.className = 'ncontent';
        div.style.top = Math.floor(parseInt(n.h, 10) * scalefactor) - 2 + 'px';
        div.style.left = '2px';
        div.id = 'notetext'+i;
        if (fixr.runningDirty()) {
            // For public&safe photos where notes can be read: Create notes on (almost?) any photos, delete any note on own photos(?), edit own notes...
            if (fixr.context.userId) {
                // allow create note (however not from here!)
            }
            if (fixr.context.photographerId===fixr.context.userId) {
                // allow delete any note on own photo?
            }
            if (fixr.context.userId===n.author) {
                // allow edit own note // <br> || <br /> -> &#13;&#10;, </br> -> ""   (%0A when read from flickr api)
                div.innerHTML += '<div>[Edit] <a href="https://www.flickr.com/services/api/explore/flickr.photos.notes.edit?enable_note_id=on&param_note_id='+ n.id + '&enable_note_x=on&param_note_x='+ n.x + '&enable_note_y=on&param_note_y=' + n.y + '&enable_note_w=on&param_note_w=' + n.w + '&enable_note_h=on&param_note_h=' + n.h + '&enable_note_text=on&param_note_text=' + encodeURIComponent(n._content) + '&fixr='+encodeURIComponent(window.location.href) + '">[Update...]</a> ' + '<a href="https://www.flickr.com/services/api/explore/flickr.photos.notes.delete?enable_note_id=on&param_note_id='+ n.id + '&fixr='+encodeURIComponent(window.location.href) + '">[Delete...]</a>' + '</div>';
                //div.innerHTML += '<div>[Edit] <a href="https://www.flickr.com/services/api/explore/flickr.photos.notes.edit?enable_note_id=on&param_note_id='+ n.id + '&enable_note_x=on&param_note_x='+ n.x + '&enable_note_y=on&param_note_y=' + n.y + '&enable_note_w=on&param_note_w=' + n.w + '&enable_note_h=on&param_note_h=' + n.h + '&enable_note_text=on&param_note_text=' + encodeURIComponent(n._content.replace(/<br\s*\/>/g,'&#13;&#10;')) + '&fixr='+encodeURIComponent(window.location.href) + '">[Update...]</a> ' + '<a href="https://www.flickr.com/services/api/explore/flickr.photos.notes.delete?enable_note_id=on&param_note_id='+ n.id + '&fixr='+encodeURIComponent(window.location.href) + '">[Delete...]</a>' + '</div>';
            }
        }
        // document.querySelector('div.photo-well-media-scrappy-view').insertAdjacentHTML('afterbegin', '<div class="notebrd1" onclick="levelNotesZ()" style="width:' + Math.floor(parseInt(n.w, 10) * scalefactor) + 'px;height:' + Math.floor(parseInt(n.h, 10) * scalefactor) + 'px;top:' + (50 + Math.floor(parseInt(n.y, 10) * scalefactor)) + 'px;left:' + Math.floor(parseInt(n.x, 10) * scalefactor) + 'px;"><div class="notebrd2" style="height:' + (Math.floor(parseInt(n.h, 10) * scalefactor)-2) + 'px;width:' + (Math.floor(parseInt(n.w, 10) * scalefactor)-2) + 'px;">'+ div.outerHTML +'</div></div>');
        document.querySelector('div.photo-well-media-scrappy-view').insertAdjacentHTML('afterbegin', '<div class="notebrd1" style="width:' + Math.floor(parseInt(n.w, 10) * scalefactor) + 'px;height:' + Math.floor(parseInt(n.h, 10) * scalefactor) + 'px;top:' + (50 + Math.floor(parseInt(n.y, 10) * scalefactor)) + 'px;left:' + Math.floor(parseInt(n.x, 10) * scalefactor) + 'px;"><div class="notebrd2" style="height:' + (Math.floor(parseInt(n.h, 10) * scalefactor)-2) + 'px;width:' + (Math.floor(parseInt(n.w, 10) * scalefactor)-2) + 'px;">'+ div.outerHTML +'</div></div>');
    }
    showNotes();
    // adjust size of note's textboxes:
    var im = document.querySelector('img.main-photo');
    var tn = 0;
    var te= document.getElementById('notetext'+tn);
    while(te) {
        te.style.visibility = 'hidden';
        te.style.display = 'block';
        if(te.clientHeight>100 && im.clientWidth>150) {
            te.style.width = Math.min(im.clientWidth,250)+'px';
        }
        if(te.clientHeight>im.clientHeight && im.clientWidth>250) {
            te.style.width = Math.min(im.clientWidth,400)+'px';
        }
        if((te.clientHeight+20)>im.clientHeight) {
            te.style.height = (im.clientHeight)-20+'px';
            te.style.overflow = 'auto';
        }
        var tb = (parseInt(te.parentNode.parentNode.style.top,10) + parseInt(te.style.top,10) + te.clientHeight - 50 + 7);
        if(tb>im.clientHeight) {
            te.style.top = parseInt(te.style.top,10) - (tb - im.clientHeight) + 'px';
        }
        var tr = (parseInt(te.parentNode.parentNode.style.left,10) + parseInt(te.style.left,10) + te.clientWidth + 7);
        if(tr>im.clientWidth) {
            te.style.left = parseInt(te.style.left,10) - (tr - im.clientWidth) + 'px';
        }        te.style.display = '';
        te.style.visibility = 'visible';

        te = document.getElementById('notetext'+(++tn));
    }
    setTimeout(hideNotes, 1000);
    var bb = document.querySelectorAll('.notebrd1');
    for(var b=0; b < bb.length; b++) {
        bb[b].addEventListener('click',levelNotesZ,false);
    }
}
// Call Flickr REST API to get photo info incl. eventual photo-notes:
var _wsGetPhotoInfoLock = 0; // Date.now();
function wsGetPhotoInfo() {
    var diff = 0+Date.now()-_wsGetPhotoInfoLock;
    if ((_wsGetPhotoInfoLock>0) && (diff<100)) {
        log('Skipping wsGetPhotoInfo() because already running?: '+diff);
        return;
    }

    var _reqGetPhotoInfo = null;
    if (window.XMLHttpRequest) {
        _reqGetPhotoInfo = new XMLHttpRequest();
        if (typeof _reqGetPhotoInfo.overrideMimeType !== 'undefined') {
            _reqGetPhotoInfo.overrideMimeType('application/json');
        }
        _reqGetPhotoInfo.onreadystatechange = function () {
            if (_reqGetPhotoInfo.readyState === 4 && _reqGetPhotoInfo.status === 200) {
                // do something with the results
                log('webservice photos.getInfo returned status=' + _reqGetPhotoInfo.status);
                // log('webservice photos.getInfo returned status=' + _reqGetPhotoInfo.status + ', text: ' + _reqGetPhotoInfo.responseText);

                photoInfo.photoId = fixr.context.photoId;
                photoInfo.json = _reqGetPhotoInfo.responseText;
                photoInfo.notes = [];

                var obj = JSON.parse(_reqGetPhotoInfo.responseText);
                if (obj.stat === "ok") {
                    log("ok");
                    if (obj.photo && obj.photo.notes && obj.photo.notes && obj.photo.notes.note && obj.photo.notes.note.length > 0) {
                        log("looks like there are " + obj.photo.notes.note.length + " notes on this photo");

                        photoInfo.notes = obj.photo.notes.note;
                        setTimeout(renderNotes,100); // a little delay seems to be good - sometimes

                    } else {
                        log('No notes or not accessible');
                    }
                }
                _wsGetPhotoInfoLock = 0;
            } else {
                // wait for the call to complete
            }
        };

        _wsGetPhotoInfoLock = Date.now();
        _reqGetPhotoInfo.open('GET', 'https://api.flickr.com/services/rest/?method=flickr.photos.getInfo&api_key=9b8140dc97b93a5c80751a9dad552bd4&photo_id=' + fixr.context.photoId + '&format=json&nojsoncallback=1', true);
        _reqGetPhotoInfo.send(null);

    } else {
        log('understøtter ikke XMLHttpRequest');
    }
}
function getNotes(logtext) {
    if (fixr.context.pageType === 'PHOTOPAGE') {
        log("getNotes(): " + fixr.context.photoId + ( logtext ? ': ' + logtext : '' ));
        if (fixr.context.photoId) {
            if (fixr.context.photoId === photoInfo.photoId) {
                log('render cached notes');
                setTimeout(renderNotes,100); // a little delay seems to be good - sometimes
            } else {
                log('render notes via flickr.photos.getInfo');
                wsGetPhotoInfo(); // wsGetPhotoInfo also calls renderNotes()
            }
        }
    }
}

function apiExplorePreburner() {
    log('Running apiExplorerPreburner()');
    var ss = window.location.search.substring(1);
    var pp = ss.split('&');
    var fixr = ''; // no, it's another fixr
    var fixrr = '';
    var i = 0;
    for(i=0; i<pp.length; i++) {
        if (pp[i].indexOf('fixr=')===0) {
            fixr = pp[i].substring(5);
        }
        if (pp[i].indexOf('fixrr=')===0) {
            fixrr = pp[i].substring(6);
        }
    }
    if ((fixr||fixrr) && document.getElementById('Main')) {
        var f = document.getElementById('Main').querySelectorAll('form');
        if (f.length>0) {
            if(f[0].action.indexOf('?')===-1) {
                f[0].action += ('?fixrr='+fixr);
            }
        }
        for(i=0; i<pp.length; i++) {
            var p = pp[i].split('=');
            if(p.length===2 && document.getElementById(p[0])) {
                if(document.getElementById(p[0]).type==='checkbox') {   //  && document.getElementById(p[0]).value===decodeURIComponent(p[1])
                    document.getElementById(p[0]).checked = true;
                } else {
                    document.getElementById(p[0]).value = decodeURIComponent(p[1]);
                }
            }
        }
        if (document.getElementById('signfull')) {
            document.getElementById('signfull').checked = true; // default, just to be sure
        }
        var div = document.createElement('div'); // content
        div.style.position = 'absolute';
        div.style.top = '0';
        div.style.right = '0';
        div.style.width = '260px';
        div.style.border = '1px solid #000';
        div.style.margin = '0';
        div.style.padding = '4px';
        div.style.backgroundColor = '#FEC';
        div.id = 'fixrInfo';
        if (fixr) { // ready to submit
            div.innerHTML = '<img src="http://www.rockland.dk/img/fixr64.png" style="width:64px;height:64px;display:block;float:right;border:none" /><p>Simply submit this form with the pre-filled content to update!</p>';
        } else if (fixrr) { // ready to return to photopage
            div.innerHTML = '<img src="http://www.rockland.dk/img/fixr64.png" style="width:64px;height:64px;display:block;float:right;border:none" /><p>Unless an unexpected error has occured, you can now <a href="'+decodeURIComponent(fixrr)+'">return to an updated photopage</a>.</p>';
        }
        document.getElementById('Main').insertAdjacentHTML('afterbegin',div.outerHTML);
    }
}

if (window.location.href.indexOf('flickr.com\/services\/api\/explore\/flickr.photos.notes.')>-1) {
    // We are on Flickr api explorer for note handling and outside "normal" flickr page flow. fixr wont do here...
    window.addEventListener('load', apiExplorePreburner, false);
} else {
    scaler.postAction = getNotes; // update notes after scaling
    // FIXR fixr.init(onPageHandlers, onResizeHandlers, onFocusHandlers)
    fixr.init([scaler.run, insertStyle, albumExtras, albumTeaserDelayed, updateMapLinkDelayed, updateTagsDelayed], [scaler.run], [getNotes]); // also getNotes if browser tab/window gets focus
}


/* OLD STUFF... CURRENTLY NOT USED: */


/*
 // 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');
 }
 }
 */