// ==UserScript==
// @name Stig's Flickr Fixr
// @namespace dk.rockland.userscript.flickr.fixr
// @description Display and update photo-notes, Show photographer's albums on photostream-pages, Increase display-size and quality of "old" photos, Photographer's other photos by tag-links, Links to album-map and album-comments, Actually show a geotagged photo on the associated map, Top-pager - 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 2016.02.14.3
// @grant none
// @run-at document-start
// ==/UserScript==
// CHANGELOG - The most important updates/versions:
var changelog = [
{version: '2016.02.14.1', description: 'Fixing a couple of issues related to scale-and-replace photos (Including never use the original if it has a different orientation).'},
{version: '2016.02.09.0', description: 'New feature: Link to Explore Calendar added to Explore page (To the right for now, but might move it to top-menu later?).'},
{version: '2016.02.06.2', description: 'New feature: Top-pager! Hover the mouse in the center just above photostreams to show a pagination-bar.'},
{version: '2016.02.05.1', description: 'Adding a little "bling" to the album-column.'},
{version: '2016.01.30.0', description: 'Killing the terrible annoying sign-up box that keeps popping up if you are *not* logged in on Flickr. Also fixes for and fine-tuning of the notes-support.'},
{version: '2016.01.24.5', description: '[2016.01.26] Alignment adjustment to "Add Note"-icon (It was not always reachable/clickable).'},
{version: '2016.01.24.3', description: 'New feature: Updating notes on photos! Besides displaying, you can now also Create, Edit and Delete notes (in a "hacky" and slightly restricted but generally usable way)'},
{version: '2015.12.05.2', description: 'Photo-notes support now includes displaying formatting and active links.'},
{version: '2015.12.03.2', description: 'New feature: Basic "beta" support for the good old photo-notes (read-only, no formatting/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.26.4', description: 'Initial release version. Photo scale, album column and tag-feature.'}
];
var DEBUG = false;
function log(s) {
if (DEBUG && window.console) {
window.console.log(s);
}
}
if (DEBUG) {
if ('loading' === document.readyState) {
log("This userscript is running at document-start time.");
} else {
log("This userscript is running with document.readyState: " + document.readyState);
}
window.addEventListener('DOMContentLoaded', function(){log('(onDOMContentLoaded)');}, false);
window.addEventListener('focus', function(){log('(onfocus)');}, false);
window.addEventListener('load', function(){log('(onload)');}, false);
window.addEventListener('pageshow', function(){log('(onpageshow)');}, false);
window.addEventListener('resize', function(){log('(onresize)');}, false);
window.addEventListener('hashchange', function(){log('(onhashchange)');}, false);
window.addEventListener('blur', function(){log('(onblur)');}, false);
}
var allowUpdateNotesViaAPIExplorer = true; // Allow support for Create, Edit and Delete photo-notes using Flickr's API Explorer
// 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() { // In-development and 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
if (fixr.context.hasOwnProperty(p)) {
fixr.context[p] = '';
}
}
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];
imgUrl = result[1].replace(/_[a-z]$/, '') + '_q' + 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 + '" class="asquare" alt="" /><div style="margin:0 0 .8em 0">' + a.title + '</div></a></div>';
} else {
log('a element not found?');
}
}
}
if (document.getElementById('albumTeaser')) {
document.getElementById('albumTeaser').innerHTML = '<div style="margin:0 0 .8em 0">Albums</div>' + albums.html + '<div><i><a href="/photos/' + (fixr.context.photographerAlias !== '' ? fixr.context.photographerAlias : fixr.context.photographerId) + '/albums/">' + (albums.count > 10 ? 'More albums...' : (albums.count == 0 ? 'No albums found...' : '')) + '</a></i></div>';
} else {
log('albumTeaser NOT FOUND!?!');
}
} else {
// wait for the call to complete
}
};
if (fixr.context.photographerId === albums.ownerId && fixr.context.photographerId !== '') {
log('Usinging CACHED albumlist!...');
document.getElementById('albumTeaser').innerHTML = '<div style="margin:0 0 .8em 0">Albums</div>' + albums.html + '<div><i><a href="/photos/' + (fixr.context.photographerAlias !== '' ? fixr.context.photographerAlias : fixr.context.photographerId) + '/albums/">' + (albums.count > 10 ? 'More albums...' : (albums.count == 0 ? 'No albums found...' : '')) + '</a></i></div>';
} else if (fixr.context.photographerId) {
var url = 'https://www.flickr.com/photos/' + (fixr.context.photographerAlias !== '' ? fixr.context.photographerAlias : fixr.context.photographerId) + '/albums';
_reqAlbumlist.open('GET', url, true);
_reqAlbumlist.send(null);
} else {
log('Attribution user (photographer) not found');
}
} else {
log('understøtter ikke XMLHttpRequest');
}
}
function albumTeaser() {
if (fixr.context.pageType !== 'PHOTOSTREAM') {
return; // exit if not photostream
}
log('albumTeaser() running');
var dpc = document.querySelector('div.photolist-container');
if (!dpc) {
return;
}
// to-do: check om personlig photostream?
// to-do: check padding-right er mindst 130px?
log('AlbumTeaser found div.photolist-container');
if (!document.getElementById('albumTeaser')) {
dpc.style.position = "relative";
dpc.insertAdjacentHTML('afterbegin', '<div id="albumTeaser" style="border:none;margin:0;padding:0;position:absolute;top:0;right:10px;width:100px"></div>');
}
if (document.getElementById('albumTeaser')) {
getAlbumlist(); // også check på fixr.context.photographerId ?
}
}
var _timerAlbumTeaserDelayed;
function albumTeaserDelayed() {
if (fixr.context.pageType !== 'PHOTOSTREAM') {
return; // exit if not photostream
}
log('albumTeaserDelayed() running...');
clearTimeout(_timerAlbumTeaserDelayed);
_timerAlbumTeaserDelayed = setTimeout(albumTeaser, 1500);
}
function exploreCalendar() {
function padZero(n) {
return (n >= 0 && n < 10) ? '0'+n : ''+n;
}
if (fixr.context.pageType !== 'EXPLORE') {
return; // exit if not explore/interestingness
}
log('exploreCalendar() running');
var plv = document.querySelector('div.photo-list-view');
if (!plv) {
return;
}
log('exploreCalendar found div.photo-list-view');
if (!document.getElementById('exploreCalendar')) {
plv.style.position = "relative";
var d = new Date();
d.setHours(d.getHours() - 8); // Use San Francisco's Pacific Time Zone UTC-08 (But when daylight-saving it is UTC-07 ?)
log('San Francisco Pacific Time Zone UTC-08 date and time: ' + d.getUTCFullYear() + '-' + padZero(1 + d.getUTCMonth()) + '-' + padZero(d.getUTCDate()) + ' ' + padZero(d.getUTCHours()) + ':' + padZero(d.getUTCMinutes()));
d.setDate(d.getDate() - 1); // and go 24h further back when looking up content from explore pages
plv.insertAdjacentHTML('afterbegin', '<div id="exploreCalendar" style="border:none;margin:0;padding:0;position:absolute;top:3px;right:-120px;width:100px"><div style="margin:0 0 .8em 0">Calendar</div><div><a href="https://www.flickr.com/explore/interesting/' + d.getUTCFullYear() + '/' + padZero(1 + d.getUTCMonth()) + '/"><img src="https://c2.staticflickr.com/2/1701/24895062996_78719dec15_o.jpg" class="asquare" style="width:75px;height:59px" alt="Calendar" /></a></div></div>');
}
}
var _timerExploreCalendarDelayed;
function exploreCalendarDelayed() {
if (fixr.context.pageType !== 'EXPLORE') {
return; // exit if not explore/interestingness
}
log('albumTeaserDelayed() running...');
clearTimeout(_timerExploreCalendarDelayed);
_timerExploreCalendarDelayed = setTimeout(exploreCalendar, 1500);
}
var scaler = {
photoId: '',
photoOrientation: '',
mf: null, // document.querySelector('img.main-photo') for (re-)re-scale
lrf: null, // document.querySelector('img.low-res-photo') for (re-)re-scale
maxSizeUrl: '',
orgUrl: '',
hasOriginal: false,
scaleToWidth: 0,
scaleToHeight: 0,
postAction: function() {
log('scaler.postAction'); // dummy-function to be replaced
},
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] scaler.run.replace() running...');
scaler.mf = document.querySelector('img.main-photo'); // for en sikkerheds skyld
if (scaler.mf && scaler.mf !== null && scaler.maxSizeUrl !== '') {
if (scaler.mf.height>=640 || scaler.mf.width>=640) { // dirty hack to work-around a bug
scaler.mf.src = scaler.maxSizeUrl; // Replace! only if original (maxSizeUrl should be orgUrl)
} else {
log('[scaler] Second thoughts. Do not replace this photo with original because unlikely needed here (bug work-around for small screens).')
}
scale();
}
};
var getSizes = function () {
log('[scaler] 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;
var sizelist = doc.body.querySelectorAll('ol.sizes-list li ol li');
var largest = null;
var largesttext = '';
while(!largest && sizelist.length>0) {
if (sizelist[sizelist.length-1].textContent.replace(/\s+/g,'')==='') {
sizelist.pop(); // remove last
} else {
log('[scaler] Found LARGEST size: '+sizelist[sizelist.length-1].textContent.replace(/\s+/g,''));
largest = sizelist[sizelist.length-1];
largesttext = largest.textContent.replace(/\s+/g,'');
}
}
if (largest.querySelector('a')) {
// list has link to _PAGE_ for showing largest image, thus it cannot be the original we already see ON the page!
log ('[scaler] Sizes-page/o has link to _PAGE_ for showing largest image, thus it cannot be the largest/original we already see ON the page!');
scaler.orgUrl = '';
scaler.maxSizeUrl = '';
scaler.hasOriginal = false;
} else if (doc.body.querySelector('div#allsizes-photo>img')) {
scaler.orgUrl = doc.body.querySelector('div#allsizes-photo>img').src;
scaler.hasOriginal = true;
scaler.maxSizeUrl = doc.body.querySelector('div#allsizes-photo>img').src;
log('[scaler] Largest/original image: ' + scaler.maxSizeUrl);
} else {
log('[scaler] UNEXPECTED situation. Assuming NO original available');
scaler.orgUrl = '';
scaler.maxSizeUrl = '';
scaler.hasOriginal = false;
}
var r = /\((\d+)x(\d+)\)$/;
var res = largesttext.match(r);
if (res != null) {
if (scaler.photoOrientation === 'h' && parseInt(res[1],10)<parseInt(res[2],10)) {
log('[scaler] Photo has been rotated from vertical to horizontal - Should NOT use the original here!');
scaler.orgUrl = '';
scaler.maxSizeUrl = '';
scaler.hasOriginal = false;
} else if (scaler.photoOrientation === 'v' && parseInt(res[1],10)>parseInt(res[2],10)) {
log('[scaler] Photo has been rotated from horizontal to vertical - Should NOT use the original here!');
scaler.orgUrl = '';
scaler.maxSizeUrl = '';
scaler.hasOriginal = false;
}
} else {
log('[scaler] No match???');
}
if (scaler.hasOriginal) {
log('[scaler] Scale and replace using Original found from XMLHttpRequest')
replace();
}
} 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.photoOrientation = '';
scaler.mf = null;
scaler.lrf = null;
scaler.maxSizeUrl = '';
scaler.orgUrl = '';
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 (scaler.mf.width>scaler.mf.height) {
scaler.photoOrientation = 'h'; // horisontal
} else {
scaler.photoOrientation = 'v'; // vertical
}
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 && scaler.photoOrientation==='h') { // if (document.querySelector('ul.sizes')) -> PHOTOPAGE in normal mode (if vertical (bigger) risk for rotated, which are better handled by getSizes())
var org = document.querySelector('ul.sizes li.Original a.download-image-size');
if (org) { // quick access 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, '.');
log('[scaler] Original photo found, now replacing');
replace();
} else {
log('[scaler] Original photo not available for download on this photographer. Re-scale just in case...');
scale(); // ???
}
observer.disconnect();
});
// configuration of the observer:
var config = {attributes: false, childList: true, subtree: false, characterData: false};
observer.observe(target, config);
}
}
} else { // PHOTOPAGE (likely) in LIGHTBOX mode
getSizes(); // resize (& replace) from/when size-list
}
} else {
log('[scaler] Scaling NOT relevant');
}
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;} .addNote:hover{cursor:pointer} '
+ 'img.asquare {width:75px;height:75px;border:none;margin:0;padding:0;transition:all 0.3s ease} a:hover>img.asquare{transform:scale(1.3)} '
+ '.signup-footer, .signup-footer-view{display:none} '
+ '#topPaginationContainer{width:250px;height:40px;margin:0 auto;position:absolute;top:0;left:0;right:0;border:none} #topPagination{width:720px;margin:0;padding:10px 0 10px 0;position:absolute;top:0;left:-235px;text-align:center;z-index:10;display:none;border:none} .album-toolbar-content #topPagination{top:-16px} .group-pool-subheader-view #topPagination{top:-7px} .title-row #topPagination{width:830px;left:-290px;top:-8px} #topPaginationContainer:hover #topPagination{display:block} ';
document.getElementsByTagName('head')[0].appendChild(style);
log('fixrStyle has been ADDED');
} else {
log('fixrStyle was already present');
}
}
function topPagination() {
log('topPagination()');
var bottomPagination = document.querySelector('.pagination-view');
if (!bottomPagination) {
bottomPagination = document.querySelector('.explore-pagination');
}
if (bottomPagination && !document.getElementById('topPagination')) {
if (bottomPagination.childElementCount>0) {
var topPagination = bottomPagination.cloneNode(true);
topPagination.id = 'topPagination';
var topPaginationContainer = document.createElement('div');
topPaginationContainer.id = 'topPaginationContainer';
topPaginationContainer.appendChild(topPagination);
var topbar = document.querySelector('.fluid-magic-tools-view');
if (!topbar) topbar = document.querySelector('.album-toolbar-content');
if (!topbar) topbar = document.querySelector('.group-pool-subheader-view');
if (!topbar) topbar = document.querySelector('.title-row');
if (topbar) {
log('topPagination: root found, inserting container');
topbar.appendChild(topPaginationContainer);
}
}
}
}
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*="/photos/tags/"],a[title][href*="?tags="],a[title][href*="?q="]');
if (atag) {
var realtag = (atag.href.match(/((\/tags\/|\?tags\=)|\?q\=)([\S]+)$/i))[3];
if (!(tags[i].querySelector('a.fixrTag'))) {
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?
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 photos only
json: ''
},
create: {
area: null,
startX: 0,
startY: 0,
stopX: 0,
stopY: 0,
hotspot: null,
init: function () {
log(' *** notes.create.init()');
if (document.querySelector('div.photo-well-media-scrappy-view') && !document.getElementById('area')) {
// document.querySelector('div.photo-well-media-scrappy-view').insertAdjacentHTML('afterbegin', '<div id="area" style="position:absolute;left:0;top:0;width:400px;height:400px;border:1px solid #F00;z-index:6000"></div>');
document.querySelector('div.photo-well-media-scrappy-view').insertAdjacentHTML('afterbegin', '<div id="area" title="Click and drag to define comment hotspot..." style="position:absolute;left:-1px;top:49px;width:'+parseInt(document.querySelector('img.main-photo').getAttribute('width'),10)+'px;height:'+parseInt(document.querySelector('img.main-photo').getAttribute('height'),10)+'px;border:1px solid #F00;z-index:6000"></div>');
notes.create.area = document.getElementById('area');
log(' *** area inserted!!');
}
notes.create.area.addEventListener("mousedown", notes.create.start, false);
},
start: function (e) {
var elem, evt = e ? e : event;
if (evt.srcElement) elem = evt.srcElement;
else if (evt.target) elem = evt.target;
log(' *** notes.create.start()');
if (elem.id && elem.id === 'area') { // same element?
notes.create.startX = evt.offsetX;
notes.create.startY = evt.offsetY;
notes.create.area.addEventListener("mouseup", notes.create.stop, false);
notes.create.area.addEventListener("mousemove", notes.create.move, false);
//evt.stopPropagation();
//evt.preventDefault();
log('Start: evt.offsetX=' + notes.create.startX + ', evt.offsetY=' + notes.create.startY);
elem.innerHTML = '<div id="noteHotspot" style="border:1px solid #F00;margin:0;padding:0;position:absolute;top:' + notes.create.startY + 'px;left:' + notes.create.startX + 'px;width:0;height:0" ></div>';
notes.create.hotspot = document.getElementById('noteHotspot');
return false;
} else {
log(' *** unexpected elem for start note creation?: '+elem.className); // for pokker, "+" er klikket, ikke drag-start...
return false;
}
},
move: function (e) {
var elem, evt = e ? e : event;
if (evt.srcElement) elem = evt.srcElement;
else if (evt.target) elem = evt.target;
log(' *** notes.create.move()');
notes.create.area.removeEventListener("mousedown", notes.create.start);
//evt.stopPropagation();
//evt.preventDefault();
if (elem.id && elem.id === 'area') {
notes.create.stopX = evt.offsetX;
notes.create.stopY = evt.offsetY;
} else if (elem.id && elem.id === 'noteHotspot') {
notes.create.stopX = notes.create.startX + evt.offsetX;
notes.create.stopY = notes.create.startY + evt.offsetY;
} else {
return false;
}
log('Move: evt.offsetX=' + notes.create.stopX + ', evt.offsetY=' + notes.create.stopY);
notes.create.hotspot.style.left = Math.min(notes.create.startX, notes.create.stopX) + 'px';
notes.create.hotspot.style.top = Math.min(notes.create.startY, notes.create.stopY) + 'px';
notes.create.hotspot.style.width = Math.abs(notes.create.stopX - notes.create.startX) + 'px';
notes.create.hotspot.style.height = Math.abs(notes.create.stopY - notes.create.startY) + 'px';
return false;
},
stop: function (e) {
var elem, evt = e ? e : event;
if (evt.srcElement) elem = evt.srcElement;
else if (evt.target) elem = evt.target;
log(' *** notes.create.stop()');
notes.create.area.removeEventListener("mousemove", notes.create.move);
notes.create.area.removeEventListener("mouseup", notes.create.stop);
//evt.stopPropagation();
//evt.preventDefault();
if (elem.id && elem.id === 'area') {
notes.create.stopX = evt.offsetX;
notes.create.stopY = evt.offsetY;
} else if (elem.id && elem.id === 'noteHotspot') {
notes.create.stopX = notes.create.startX + evt.offsetX;
notes.create.stopY = notes.create.startY + evt.offsetY;
} else {
log('where are we???');
return false;
}
// To-do: Hvis højde eller bredde er 0, så expand en smule?...
log('Stop: evt.offsetX=' + evt.offsetX + ', evt.offsetY=' + evt.offsetY);
notes.create.hotspot.style.left = Math.min(notes.create.startX, notes.create.stopX) + 'px';
notes.create.hotspot.style.top = Math.min(notes.create.startY, notes.create.stopY) + 'px';
notes.create.hotspot.style.width = Math.max(Math.abs(notes.create.stopX - notes.create.startX)) + 'px';
notes.create.hotspot.style.height = Math.max(Math.abs(notes.create.stopY - notes.create.startY)) + 'px';
notes.createNoteDlg(notes.create.startX, notes.create.startY, notes.create.stopX, notes.create.stopY); // open dialog
// To-do: clean-up
return false;
}
},
updateNotesInit: function() {
if (fixr.context.pageType !== 'PHOTOPAGE') {
return; // exit if not photopage
}
if (!notes.photo.allowNotes) {
log('Notes not supported on this photo');
return;
}
if (!document.querySelector('.show-add-tags')) {
log('Adding notes (and tagging) apparently not allowed/possible'); // photographer doesn't allow, user not logged in, or...?
return;
}
log(' *** notes.updateNotesInit()');
var panel = document.querySelector('div.photo-well-media-scrappy-view');
if (panel && !panel.querySelector('div.addNote')) {
log('notes.updateNotesInit: adding option to div.height-controller');
panel.insertAdjacentHTML('afterbegin', '<div class="addNote" style="position:absolute;right:20px;top:15px;font-size:16px;margin-right:16px;color:#FFF;z-index:3000"><img src="https://c2.staticflickr.com/2/1680/24467540082_f296118dd3_o.png" alt="Add note" title="Add note" /></div>');
log ('adding click event listner on div.addNote');
panel.querySelector('div.addNote').addEventListener('click',notes.create.init, false);
} else {
log('notes.updateNotesInit: div.height-controller not found OR addNote already defined');
}
},
updateNotesInitDelayed: function() {
setTimeout(notes.updateNotesInit, 2000); // a little delay seems to be good - sometimes
},
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);
},
_updateNoteUrl: '', // general update noteS url?
updateNote: function() {
notes._updateNoteUrl = notes._updateNoteUrl + '&enable_note_text=on¶m_note_text=' + encodeURIComponent(document.getElementById('editable').value.replace(/\n/g,' '));
window.location = notes._updateNoteUrl;
},
deleteNote: function (e) {
var elem, evt = e ? e:event;
if (evt.srcElement) elem = evt.srcElement;
else if (evt.target) elem = evt.target;
var n = parseInt(elem.id.substring(10),10);
window.location = 'https://www.flickr.com/services/api/explore/flickr.photos.notes.delete?enable_note_id=on¶m_note_id='+ notes.photo.notes[n].id + '&fixr='+encodeURIComponent(window.location.href);
},
closeEditNoteDlg: function() {
if (document.getElementById('noteEditor')) {
var oldnode = document.getElementById('noteEditor');
oldnode.parentNode.removeChild(oldnode);
if (document.getElementById('noteHotspot')) {
oldnode = document.getElementById('noteHotspot');
oldnode.parentNode.removeChild(oldnode);
}
if (document.getElementById('area')) {
oldnode = document.getElementById('area');
oldnode.parentNode.removeChild(oldnode);
}
}
},
editNoteDlg: function (e) { // create dialog
var elem, evt = e ? e:event;
if (evt.srcElement) elem = evt.srcElement;
else if (evt.target) elem = evt.target;
notes.closeEditNoteDlg();
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'; // Chrome and Opera ignore this?
ta.setAttribute('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:8000;background-color:#FEC;border:1px solid #000;margin:0;padding:3px">'+ta.outerHTML+'<div><button id="updateNoteBtn">Update...</button> <button id="cancelNoteEditorBtn">Cancel</button></div></div>');
// Cancel på note editor
notes._updateNoteUrl = 'https://www.flickr.com/services/api/explore/flickr.photos.notes.edit?enable_note_id=on¶m_note_id='+ notes.photo.notes[n].id + '&enable_note_x=on¶m_note_x='+ notes.photo.notes[n].x + '&enable_note_y=on¶m_note_y=' + notes.photo.notes[n].y + '&enable_note_w=on¶m_note_w=' + notes.photo.notes[n].w + '&enable_note_h=on¶m_note_h=' + notes.photo.notes[n].h + '&fixr='+encodeURIComponent(window.location.href);
document.getElementById('cancelNoteEditorBtn').addEventListener('click',notes.closeEditNoteDlg,false);
document.getElementById('updateNoteBtn').addEventListener('click',notes.updateNote,false);
}
},
createNoteDlg: function(x0, y0, x1, y1) { // dialog (startx,starty,stopx,stopy)
// transform x0, y0, x1, y1 by factor? (and transform/put upper left coordinates first)
// get content (textarea)
// create url (unless cancel)
// clean-up
// update by url (if not cancel)
notes.closeEditNoteDlg();
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'; // Chrome and Opera ignore this?
ta.setAttribute('style', 'width:294px;height:200px');
ta.defaultValue = '';
if (fixr.runningDirty()) {
ta.defaultValue = ' [<a href="https://www.flickr.com/groups/flickrhacks/discuss/72157655601688753/">*</a>]';
}
ta.id = 'editable';
var note_x, note_y, note_w, note_h;
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;
}
if(x0<=x1) {
note_x = Math.max(0,x0/scalefactor-1);
note_w = Math.max(1,(x1-x0)/scalefactor) + 4;
} else {
note_x = Math.max(0,x1/scalefactor-1);
note_w = Math.max(1,(x0-x1)/scalefactor) + 4;
}
if(y0<=y1) {
note_y = Math.max(0,y0/scalefactor-1);
note_h = Math.max(1,(y1-y0)/scalefactor) + 4;
} else {
note_y = Math.max(0,y1/scalefactor-1);
note_h = Math.max(1,(y0-y1)/scalefactor) + 4;
}
if ((note_x+note_w)*scalefactor>parseInt(document.querySelector('img.main-photo').getAttribute('width'),10)) {
note_x=parseInt(document.querySelector('img.main-photo').getAttribute('width'),10)/scalefactor-note_w;
}
if ((note_y+note_h)*scalefactor>parseInt(document.querySelector('img.main-photo').getAttribute('height'),10)) {
note_y=parseInt(document.querySelector('img.main-photo').getAttribute('height'),10)/scalefactor-note_h;
}
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:8000;background-color:#FEC;border:1px solid #000;margin:0;padding:3px">'+ta.outerHTML+'<div><button id="updateNoteBtn">Create...</button> <button id="cancelNoteEditorBtn">Cancel</button></div></div>');
// Cancel på note editor
notes._updateNoteUrl = 'https://www.flickr.com/services/api/explore/flickr.photos.notes.add?enable_photo_id=on¶m_photo_id='+ fixr.context.photoId + '&enable_note_x=on¶m_note_x='+ Math.floor(note_x) + '&enable_note_y=on¶m_note_y=' + Math.floor(note_y) + '&enable_note_w=on¶m_note_w=' + Math.floor(note_w) + '&enable_note_h=on¶m_note_h=' + Math.floor(note_h) + '&fixr='+encodeURIComponent(window.location.href);
document.getElementById('cancelNoteEditorBtn').addEventListener('click',notes.closeEditNoteDlg,false);
document.getElementById('updateNoteBtn').addEventListener('click',notes.updateNote,false);
},
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');
}
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];
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.className = 'ncontent';
div.style.top = Math.floor(parseInt(n.h, 10) * scalefactor) - 2 + 'px';
div.style.left = '2px';
div.id = 'notetext'+i;
if (allowUpdateNotesViaAPIExplorer) {
// 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 photos? (to-do)
}
if (fixr.context.userId===n.author) {
div.innerHTML += '<div><br /><button id="editNote'+i+'" class="editNoteBtn">Edit</button> <button id="deleteNote'+i+'" class="deleteNoteBtn">Delete...</button></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.editNoteDlg,false);
}
// click listener on note Delete buttons
var db = document.querySelectorAll('.deleteNoteBtn');
for(b=0; b < db.length; b++) {
db[b].addEventListener('click',notes.deleteNote,false);
}
},
_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');
}
// start initUpdateNotes
if (allowUpdateNotesViaAPIExplorer) {
notes.updateNotesInitDelayed();
}
} 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
// start initUpdateNotes
if (allowUpdateNotesViaAPIExplorer) {
notes.updateNotesInitDelayed();
}
} 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]).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 = '0 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" /><h2>Step 1 of 2</h2><p>Simply submit this form with the pre-filled content to update notes on the <a href="'+decodeURIComponent(fixr)+'">photopage</a>:</p><p><button onclick="document.forms[1].submit();">Submit (Call method...)</button></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" /><h2>Step 2 of 2</h2><p>Unless an error has occured, you can now return to an <a href="'+decodeURIComponent(fixrr)+'">updated photopage</a>:</p><p><form action="'+decodeURIComponent(fixrr)+'"><input type="submit" value="Return to photo"></form></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, topPagination, exploreCalendarDelayed, albumTeaserDelayed, updateMapLinkDelayed, updateTagsDelayed], [scaler.run], [notes.initNotes]);
}