- // Flickr - Widescreen
- // Copyright (c) 2010, Patrick Joseph.
- // Released under the GPL license
- // http://www.gnu.org/copyleft/gpl.html
- //
- // ==UserScript==
- // @name Flickr - Widescreen
- // @namespace http://userscripts.org/users/isamux
- // @description Adjusts the appearance of photostream pages depending on the browser's window size.
- // @version 1.2.2.1
- // @date 2011-04-24
- // @creator Patrick Joseph
- // @include http://*.flickr.com/photos/*
- // @include http://*.flickr.com/groups/*/pool*/
- // @exclude http://*.flickr.com/photos/friends*
- // ==/UserScript==
-
- // ==Changelog==
- //2011-04-24 v1.2.2:
- // * Flickr changed id of photostream's content div from "Main" to "main". Changed it in the script to make it work again.
- // * Updated integrated Flickr - TopPager to version 1.0.5.
- // 2010-11-21 v1.2.1:
- // * experimatal adjustment on photo page: comments are displayed in a column left to the photo.
- // Can be disabled by setting CONF_DISPLAY_COMMENTS_AS_LEFT_COLUMN to false.
- // 2010-10-11 v1.2:
- // * fixed medium + sets view
- // * added logging functionality
- // * added widescreen display for sets overview page (Example: http://www.flickr.com/photos/barackobamadotcom/sets/)
- // * added @include for group pool
- // 2010-04-23 v1.1:
- // * added top pager functionality (http://userscripts.org/scripts/show/73290).
- // 2010-04-22 v1.0.2:
- // * added handling for photostream layout "Medium + sets" (big5).
- // * removed @require dependency from userscript metablock.
- // 2010-04-15 v1.0.1:
- // * some minor adjustments.
- // ==/Changelog==
-
- // ---------------
- // CONFIGURATION
- // ---------------
- const CONST_ENABLE_FIREBUG_LOGGING = false;
-
- // some "constants" for the script
- const CONST_MINIMUM_COLUMN_COUNT = 3; // minimum count of columns in photostream table. Should be at least 1.
- const CONST_MAIN_CONTAINER = "Main"; // id of main photostream div
- const CONST_CELL_WIDTH = 340; // width of a single photostream table cell (Used for AUTO ADJUSTMENT)
- const CONST_SETS_COLUMNS_WIDTH = 300; // width of the photostream's sets column
- const CONST_PHOTOSTREAM_WRAPPER = '//div[@class="PhotosColumn"]'
-
- // if CONF_AUTO_ADJUST is set to false, the values configured below,
- // are used to rearrange the photostream table.
- var CONF_AUTO_ADJUST = true;
- var CONF_COLUMN_COUNT = 3; // [AUTO ADJUSTED] count of columns. Cannot be set below CONST_MINIMUM_COLUMN_COUNT;
- var CONF_MAIN_CONTAINER_WIDTH = 1800; // [AUTO ADJUSTED] width of main container. Original width 800.
-
- // config for photostream layout "Medium + sets"
- var CONF_MEDIUM_SIZE_STREAM_RESIZE_ENABLED = true; // allows to disable resize of images in "Medium + sets" layout.
- var CONF_MEDIUM_SIZE_STREAM_MINIMUM_IMAGE_WIDTH = 340; // minimum size for resized images in "Medium + sets" layout.
-
- var CONF_ADD_TOP_PAGER = true; // allows to disable top pager.
- var CONF_DISPLAY_COMMENTS_AS_LEFT_COLUMN = true; // experimental: displays comments as left column on photo page
-
- // Flickr - TopPager CONFIGURATION (should not be changed)
- const CONST_PAGINATED_CONTENT_XPATH_PHOTOSTREAM = '//div[starts-with(@class,"PhotoStream")]';
- const CONST_PAGINATED_CONTENT_XPATH_GROUP = '//div[@class="HoldPhotos"]';
- const CONST_PAGINATED_CONTENT_ID_FAVORITES = 'favoriteThumbs';
-
- // ---------------
-
- // ---------------
- // SCRIPT-MAIN
- // ---------------
-
- // 0. Prepare everything
- // init logging
- if(typeof console === "undefined" || !CONST_ENABLE_FIREBUG_LOGGING) {
-
- console = { log: function() { },
- info: function() {},
- debug: function() { } ,
- warn: function() {},
- error: function() {} };
- }
-
- // add top pager
- if(CONF_ADD_TOP_PAGER)
- tryAddTopPager();
-
- computeAdjustments(); // compute column resize parameters
-
- // I. Adjust main div width
- var mainEl = document.getElementById(CONST_MAIN_CONTAINER);
- if(mainEl == null)
- {
- // on some pages the main-container is named "Main" and on newer ones "main".
- mainEl = document.getElementById(CONST_MAIN_CONTAINER.toLowerCase());
- }
- if(mainEl !== null)
- {
- mainEl.style.width = CONF_MAIN_CONTAINER_WIDTH + "px";
- }
-
- // II.a Rearrange photostream ("Small + sets" layout)
- var elPhotoColumn = getElement(CONST_PHOTOSTREAM_WRAPPER);
- if(elPhotoColumn !== null)
- {
- elPhotoColumn.style.setProperty("width", (CONF_COLUMN_COUNT * CONST_CELL_WIDTH) + "px","important");
- }
-
- // II.b Rearrange photostream ("Big wo sets" layout)
- elPhotoColumn = getElement('//div[@class="PhotosColumn Big5Column Big5NoSets"]');
- if(elPhotoColumn !== null)
- {
- rearrangeLargeSizeLayoutPhotoStream(elPhotoColumn);
- }
-
- // // II.c Rearrange photostream in "Medium + sets" layout
- // oMediumSizeImageDivs = getElementSnapshots('//div[starts-with(@class,"StreamView Big5Photo")]');
- // if(null != oMediumSizeImageDivs)
- // {
- // console.info("PageInfo: Photostream Medium + sets column");
- // rearrangeMediumSizeLayoutPhotoStream(oMediumSizeImageDivs);
- // }
-
- // III. Remove width from favorites container, to adjust to new width of CONST_MAIN_CONTAINER.
- var oFavoritesContainer = document.getElementById('favoriteThumbs');
- if(null != oFavoritesContainer)
- {
- console.info("PageInfo: Favorites");
- oFavoritesContainer.style.width = "auto";
- }
-
- // IV. Adjust width on set page
- var oSetContainer = document.getElementById('ViewSet');
- if(null != oSetContainer)
- {
- console.info("PageInfo: Single set overview");
- oSetContainer.style.width = "auto";
- var el = getElement('//div[@class="vsThumbs"]');
- el.style.width = (CONF_MAIN_CONTAINER_WIDTH-CONST_SETS_COLUMNS_WIDTH) + "px";
- }
-
- // V. Handle Sets-Overview Page
- if(isSetsPage(document.URL))
- {
- console.info("PageInfo: Set overview");
- oBreaks = getElementSnapshots('//div[@class="Sets"]/following-sibling::br[@clear="all"]');
- if(oBreaks != null)
- {
- for(i = 0; i < oBreaks.snapshotLength-3; i++)
- {
- obreakElement = oBreaks.snapshotItem(i);
- obreakElement.parentNode.removeChild(obreakElement);
- }
- }
- }
-
-
- // VI. Insert Widescreen next to Flickr logo
- insertLogo();
-
- // VII. Experimental new photopage adjustment
- mainElNewPhotPage = document.getElementById("main");
- if(null !== mainElNewPhotPage)
- {
- //console.info("PageInfo: New Photopage");
- experimentalNewPhotoPageAdjust(mainElNewPhotPage);
- }
-
- // ===============
- // FUNCTION LIB
- // ===============
-
- function computeAdjustments()
- {
- // 0. auto config
- if(CONF_AUTO_ADJUST)
- {
- // compute count of fitting columns
- CONF_COLUMN_COUNT = Math.floor(window.innerWidth/CONST_CELL_WIDTH);
-
- console.debug("Computed count of columns fitting the window: " + CONF_COLUMN_COUNT);
-
- // by adjusting the width, the main content container on the photostream is moved to the left.
- // Otherwise the table with more columns, would be growing out of the main window to the right.
- CONF_MAIN_CONTAINER_WIDTH = (CONF_COLUMN_COUNT * CONST_CELL_WIDTH);
-
- // consider sets column. If sets column exists, the CONF_COLUMN_COUNT needs to be reduced by one.
- if(additionalRightColumnExists())
- {
- CONF_COLUMN_COUNT = CONF_COLUMN_COUNT -1;
- console.debug("Additional right column exists. Count of fitting columns was reduced to " + CONF_COLUMN_COUNT);
- }
- }
-
- // apply minimum column count
- if(CONF_COLUMN_COUNT < CONST_MINIMUM_COLUMN_COUNT)
- CONF_COLUMN_COUNT = CONST_MINIMUM_COLUMN_COUNT
- }
-
- function additionalRightColumnExists()
- {
-
- return (collectionsColumnExists() || setsColumnExists());
- }
-
- function setsColumnExists()
- {
- return elementExists('//*[@class="SetsColumn"]');
- }
-
- function collectionsColumnExists()
- {
- return elementExists('//*[@class="CollectionsColumn"]');
- }
-
- function isSetsPage(psUrl)
- {
- bResult = false;
- iUrlLength = psUrl.length;
-
- // main sets page wo pagination
- bNoPagination = psUrl.indexOf("/sets/") == iUrlLength-6;
- bResult = bNoPagination;
- console.debug("Is main set overview page: " + bNoPagination);
-
- if(!bNoPagination)
- {
- // is main sets page on a certain page
- iLastEqual = psUrl.lastIndexOf("=");
- sTestForSetsPaginated = "/sets/?&page";
-
- sToTest = psUrl.substr(iLastEqual - sTestForSetsPaginated.length, sTestForSetsPaginated.length);
- bWithPagination = (sToTest == sTestForSetsPaginated);
- console.debug("Is main set overview page on a specific page: " + bWithPagination);
- bResult = bWithPagination;
- }
-
- return bResult;
- }
-
- function getOrignialPhotostreamTableElement()
- {
- // get orignal photostream table position
- return getElement('//td[@class="PhotosColumn"]//table');
- }
-
- function rearrangeTable(poTableElement, piNewColumnCount)
- {
- var allHeaderCells = getAllPhotostreamHeaderCells(poTableElement);
- var allImgCells = getAllPhotostreamImageCells(poTableElement);
-
- // create new table element and replace orginal
- elTable = document.createElement("table");
- elTable.innerHTML = buildTable(allHeaderCells, allImgCells, piNewColumnCount);
-
- return elTable;
- }
-
- function getAllPhotostreamHeaderCells(poTable)
- {
- return getElementSnapshotsFromContext(poTable, './/tr[@valign="bottom"]//td');
- }
-
- function getAllPhotostreamImageCells(poTable)
- {
- return getElementSnapshotsFromContext(poTable,'.//tr[@valign="top"]//td');
- }
-
- function buildTable(paAllHeaderCells, paAllImgCells, piColumnCount)
- {
- var tmpTableString = '<table width="100%" cellspacing="0"><tbody>';
-
- for (var i = 0; i < paAllHeaderCells.snapshotLength; i++)
- {
- tmpTableString += buildTableRow(paAllHeaderCells, i, piColumnCount);
- tmpTableString += buildTableRow(paAllImgCells, i, piColumnCount);
- i+=piColumnCount;
- }
-
- tmpTableString += "</tbody></table>";
-
- return tmpTableString;
- }
-
- function buildTableRow(paCellContent,piOffset, piColumnCount)
- {
- var tmp = "<tr>";
-
- while(piColumnCount--)
- {
- oTd = paCellContent.snapshotItem(piOffset++);
- tmp += buildTableCell(oTd);
- }
-
- return tmp + "</tr>";
- }
-
- function buildTableCell(poTd)
- {
- if(poTd == null)
- return "<td>-</td>";
- else
- return "<td>" + poTd.innerHTML + "</td>";
- }
-
-
- function rearrangeLargeSizeLayoutPhotoStream(poPhotoColumn)
- {
- poPhotoColumn.style.setProperty("width", (CONF_COLUMN_COUNT * CONST_CELL_WIDTH) + "px","important");
- poPhotoColumn.style.setProperty("padding-left", "10px","important");
- poPhotoColumn.style.setProperty("padding-right", "10px","important");
-
- var oPhotoItemSnapsthots = getElementSnapshots('//div[@class="photo-display-item"]');
- for(i = 0; i < oPhotoItemSnapsthots.snapshotLength; i++)
- {
- oPhotoItem = oPhotoItemSnapsthots.snapshotItem(i);
- oPhotoItem.style.setProperty("float", "left","important");
- oPhotoItem.style.setProperty("margin-left", "15px","important");
- }
-
- }
-
- function rearrangeMediumSizeLayoutPhotoStream(paImageDivs)
- {
- iMargin = 15;
- bRightColumnExists = additionalRightColumnExists();
-
- if(!bRightColumnExists)
- {
- oContainerElement = getElement('//td[contains(@class,"Big5NoSets")]');
- oContainerElement.style.setProperty("padding-left", 0, "important");
- }
-
- iWidth = computeAvailableColumnsWidthForMediumSizeLayout(iMargin, bRightColumnExists);
- sPhotItemWidth = iWidth + iMargin + "px";
- sSubItemWidth = iWidth+ "px";
-
- for (var i = 0; i < paImageDivs.snapshotLength; i++)
- {
- paImageDivs.snapshotItem(i).style.cssFloat="left";
-
- // resize images
- if(CONF_MEDIUM_SIZE_STREAM_RESIZE_ENABLED)
- {
- oImage = getElementFromContext(paImageDivs.snapshotItem(i),'.//img[@class="pc_img"]');
-
- // resize image container
- paImageDivs.snapshotItem(i).style.setProperty("width", sPhotItemWidth , "important");
-
- // resize image
- oImage.style.height="auto";
- oImage.style.width=sSubItemWidth;
-
- // resize description
- oDescription = getElementFromContext(paImageDivs.snapshotItem(i),'.//p[@class="Desc"]');
- if(oDescription != null)
- oDescription.style.setProperty("width", sSubItemWidth, "important");
-
- // resize caption
- oCaption = getElementFromContext(paImageDivs.snapshotItem(i),'.//h4')
- if(oCaption != null)
- oCaption.style.setProperty("width", sSubItemWidth, "important");
-
- }
- }
- }
-
- function computeAvailableColumnsWidthForMediumSizeLayout(piMargin, pbSetsColumnExists)
- {
- iColumns = 5;
- iTotalMargin = piMargin*iColumns;
- iAvailableColumnWidth = CONF_MAIN_CONTAINER_WIDTH-iTotalMargin;
-
- if(pbSetsColumnExists)
- {
- iAvailableColumnWidth = iAvailableColumnWidth - CONST_SETS_COLUMNS_WIDTH-iTotalMargin;
- }
-
- iWidth = iAvailableColumnWidth/iColumns;
-
- if(CONF_MEDIUM_SIZE_STREAM_MINIMUM_IMAGE_WIDTH > iWidth)
- {
- iWidth = CONF_MEDIUM_SIZE_STREAM_MINIMUM_IMAGE_WIDTH;
- }
-
- return iWidth;
- }
-
- function insertLogo()
- {
- widescreenLogo = createLogo();
-
- // get flickr logo
- logo = document.getElementById('FlickrLogo');
- if(logo == null)
- {
- logo = document.getElementById('head-logo');
- }
-
- // insert widescreen logo
- logo.parentNode.insertBefore(widescreenLogo,logo);
- }
-
- function createLogo()
- {
- el = document.createElement("div");
- el.innerHTML ='<a style="font-size:10px;" href="http://userscripts.org/scripts/show/73305" target="_blank" title="Widescreen-ed by Flickr-Widescreen">Widescreen</a>';
- el.style.setProperty("font-size","10px","");
- el.style.setProperty("float","left","");
- el.style.setProperty("position","relative","");
- el.style.setProperty("top","0px","");
- el.style.setProperty("left","188px","");
- el.style.setProperty("padding","1px","");
- el.style.setProperty("border","1px solid #7B0099","");
- el.style.setProperty("background-color","#FFBFE1","");
- el.style.setProperty("-moz-border-radius","3px","");
- el.style.setProperty("text-align","center","");
- el.style.setProperty("width","65px","");
-
- return el;
- }
-
-
- function experimentalNewPhotoPageAdjust(pMainElNewPhotPage)
- {
- if(pMainElNewPhotPage == null)
- return;
-
-
- primCol = document.getElementById("primary-column");
- if(primCol === null)
- return;
-
- if(CONF_DISPLAY_COMMENTS_AS_LEFT_COLUMN && window.innerWidth > 1800)
- {
- // display comments in left column
- console.info("Widescreening: Inserting comments as left column");
-
- primCol.style.setProperty("clear","right","");
-
- comments = document.getElementById("comments");
- comments.style.setProperty("float","left","");
- comments.style.setProperty("margin-left","25px","");
- comments.style.setProperty("width","370px","");
- document.body.insertBefore(comments,pMainElNewPhotPage)
- document.getElementById("message").style.width="300px";
- }
- }
-
- // --------------------
- // TOP PAGER (v1.0.5)
- // --------------------
- function tryAddTopPager()
- {
- // get paginator
- oPaginator = getPaginator();
- if(oPaginator !== null)
- {
- // get element before which the top pager will be inserted.
- oPaginatedContent = getPaginatedContent();
-
- // insert top page paginator
- if(oPaginatedContent != null)
- {
- oPaginatorClone = oPaginator.cloneNode(true);
- oPaginatedContent.parentNode.insertBefore(oPaginatorClone, oPaginatedContent);
- }
- }
- }
-
- function getPaginatedContent()
- {
- // try get that element on photostream pages, ...
- oTmpFound = getElement(CONST_PAGINATED_CONTENT_XPATH_PHOTOSTREAM);
-
- if(oTmpFound == null)
- {
- //...then on groups pages
- oTmpFound = getElement(CONST_PAGINATED_CONTENT_XPATH_GROUP);
- }
-
- if(oTmpFound == null)
- {
- //...and finally on favorites pages.
- oTmpFound = document.getElementById(CONST_PAGINATED_CONTENT_ID_FAVORITES);
- }
-
- return oTmpFound;
- }
-
- function getPaginator()
- {
- return getElement('//div[@class="Pages"]');
- }
-
-
-
- // ===============
- // BASE LIB
- // ===============
-
- // returns result of xpath query
- function getElementSnapshots(xpathExp)
- {
- oResult = document.evaluate(
- xpathExp,
- document,
- null,
- XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
- null);
-
- return (oResult.snapshotLength > 0)? oResult : null;
- }
-
- // returns result of xpath query below a given node
- function getElementSnapshotsFromContext(contextNode, xpathExp)
- {
- return document.evaluate(
- xpathExp,
- contextNode,
- null,
- XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
- null);
- }
-
- // returns a single dom element by xpath expression
- function getElement(xpathExp)
- {
- oResult = getElementSnapshots(xpathExp);
- return (oResult == null)?null:oResult.snapshotItem(0);
- }
-
- function getElementFromContext(contextNode, xpathExp)
- {
- oResult = getElementSnapshotsFromContext(contextNode, xpathExp);
- return (oResult == null)?null:oResult.snapshotItem(0);
- }
-
- function elementExists(xpathExp)
- {
- return (getElement(xpathExp) != null);
- }
-
- function replaceElement(oldElement, newElement)
- {
- oldElement.parentNode.insertBefore(newElement, oldElement);
-
- // remove original table
- oldElement.parentNode.removeChild(oldElement);
- }