Greasy Fork

Greasy Fork is available in English.

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-13 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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.13.2
// @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: '',
        pageSubType: '',
        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';
            if (fixr.content.querySelector('div.vr-overlay-view') && fixr.content.querySelector('div.vr-overlay-view').hasChildNodes()) {
                fixr.context.pageSubType = 'VR'; // maybe I can find a better way to detect, not sure how reliable this is?
            } else if (fixr.content.querySelector('div.videoplayer')) {
                fixr.context.pageSubType='VIDEO';
            } else {
                fixr.context.pageSubType='PHOTO';
            }
        } else if (fixr.content.querySelector('div.photo-page-lightbox-scrappy-view')) {
            fixr.context.pageType = 'PHOTOPAGE LIGHTBOX';
            if (fixr.content.querySelector('div.vr-overlay-view') && fixr.content.querySelector('div.vr-overlay-view').hasChildNodes()) {
                fixr.context.pageSubType='VR'; // VR-mode currently not supported in lightbox?
            } else if (fixr.content.querySelector('div.videoplayer')) {
                fixr.context.pageSubType='VIDEO';
            } else {
                fixr.context.pageSubType='PHOTO';
            }
        } 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);
        log('fixr.context.pageSubType = '+fixr.context.pageSubType);
        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
        }
        if (fixr.context.pageSubType !== 'PHOTO') {
            log('Exiting scaler because fixr.context.pageSubType='+fixr.context.pageSubType);
            return; // exit if subtype VR or VIDEO
        }
        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);
    }
}

var notes = {
    photo: { // cache photo data to avoid repeating requests
        photoId: '',
        notes: [],
        allowNotes: false, // public&safe
        json: ''
    },
    showNotes: function () {
        var container = document.querySelector('div.photo-well-media-scrappy-view');
        if (container && container.classList) {
            container.classList.add('shownotes');
        }
    },
    hideNotes: function() {
        var container = document.querySelector('div.photo-well-media-scrappy-view');
        if (container && container.classList) {
            container.classList.remove('shownotes');
        }
    },
    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(notes.clearNotesZ, 500);
    },
    editNote: function (e) {
        var elem, evt = e ? e:event;
        if (evt.srcElement)  elem = evt.srcElement;
        else if (evt.target) elem = evt.target;
        notes.closeEditNote();
        if (elem.className==='editNoteBtn') {
            var n = parseInt(elem.id.substring(8),10);
            var pwmsv = document.querySelector('div.photo-well-media-scrappy-view');
            var ta = document.createElement('textarea'); // content
            ta.wrap = 'on';
            ta.style = 'width:294px;height:200px';
            ta.defaultValue = notes.photo.notes[n]._content;
            ta.id = 'editable';
            pwmsv.insertAdjacentHTML('afterbegin', '<div id="noteEditor" style="position:absolute;top:'+((scaler.mf.height-200)/2+30)+'px;left:'+(scaler.mf.width-300)/2+'px;min-width:300px;z-index:2000;background-color:#FFF;border:1px solid #000;margin:0;padding:3px">'+ta.outerHTML+'<div>[Update...] <span id="cancelNoteEditor">[Cancel]</span></div></div>');
            // Cancel på note editor
            document.getElementById('cancelNoteEditor').addEventListener('click',notes.closeEditNote,false);
        }
    },
    closeEditNote: function() {
        if (document.getElementById('noteEditor')) {
            var oldnode = document.getElementById('noteEditor');
            oldnode.parentNode.removeChild(oldnode);
        }
    },
    renderNotes: function() {
        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 && notes.photo.notes.length>0) {
            log('You might also see notes at: http://dh.elsewhere.org/mbedr/?p=' + fixr.context.photoId + '&fmt=Medium&v');
        }

        notes.photo.notes.sort(function(a,b){return (a.w*a.h)-(b.w*b.h);});
        for (var i=0; i<notes.photo.notes.length; i++) // notes=obj.photo.notes.note
        {
            var n = notes.photo.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>[<a href="#" id="editNote'+i+'" class="editNoteBtn">Edit</a>] <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>');
        }
        notes.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(notes.hideNotes, 1000);
        // click listener on hot rectangles
        var bb = document.querySelectorAll('.notebrd1');
        for(var b=0; b < bb.length; b++) {
            bb[b].addEventListener('click',notes.levelNotesZ,false);
        }
        // click listener on note Edit buttons
        var eb = document.querySelectorAll('.editNoteBtn');
        for(b=0; b < eb.length; b++) {
            eb[b].addEventListener('click',notes.editNote,false);
        }
        if(notes.photo.allowNotes) {
            // Show Create Note button
        } else {
            // (Hide Create Note button)
        }
    },
    _wsGetPhotoInfoLock: 0,  // Date.now();
    wsGetPhotoInfo: function () { // Call Flickr REST API to get photo info incl. eventual photo-notes
        var diff = 0 + Date.now() - notes._wsGetPhotoInfoLock;
        if ((notes._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);

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

                    var obj = JSON.parse(_reqGetPhotoInfo.responseText);
                    if (obj.stat === "ok") {
                        log("flickr.photos.getInfo returned ok");
                        notes.photo.allowNotes = true;
                        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");

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

                        } else {
                            log('No notes or not accessible');
                        }
                    } else {
                        log('flickr.photos.getInfo returned an ERROR: obj.stat='+obj.stat+', obj.code='+obj.code+', obj.message='+obj.message);
                        // failed, and notes should probably not be createable either!!!
                        notes.photo.allowNotes = false;
                    }
                    notes._wsGetPhotoInfoLock = 0;
                } else {
                    // wait for the call to complete
                }
            };

            notes._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');
        }
    },
    initNotes: function (logtext) {
        if (fixr.context.pageType === 'PHOTOPAGE' && fixr.context.pageSubType === 'PHOTO') { // Photopage with photos only (not video or vr)
            log("initNotes(): " + fixr.context.photoId + ( logtext ? ': ' + logtext : '' ));
            if (fixr.context.photoId) {
                if (fixr.context.photoId === notes.photo.photoId) {
                    log('render cached notes');
                    setTimeout(notes.renderNotes, 100); // a little delay seems to be good - sometimes
                } else {
                    log('render notes via flickr.photos.getInfo');
                    notes.wsGetPhotoInfo(); // wsGetPhotoInfo also calls renderNotes()
                }
            }
        } else {
            log('Exiting initNotes() because: fixr.context.pageType='+fixr.context.pageType+' and fixr.context.pageSubType='+fixr.context.pageSubType);
        }
    }
};



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 = notes.initNotes; // update notes after scaling
    // FIXR fixr.init(onPageHandlers, onResizeHandlers, onFocusHandlers)
    fixr.init([scaler.run, insertStyle, albumExtras, albumTeaserDelayed, updateMapLinkDelayed, updateTagsDelayed], [scaler.run], [notes.initNotes]); // 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');
 }
 }
 */