PolyAnno: Homepages, Queues, and Others

This is part of my series of posts about the PolyAnno project – more here

Having at least partially separated out the core functionality of the complete generic annotation package into different back and front end libraries, I then finally needed to complete all the remaining features of a website specifically for the University of Edinburgh’s Collections. Sadly by this point in time, an additional layer of gamification was not to be but I feel that the modularity (and hopefully simplicity of use for further development) of the code doesn’t prevent that future possibility! But there were still other loose ends to be tied up…

The Queue and the Home Page

In earlier stages I had been going through various designs for keeping the annotations pages within a scrolling, swiping, or carousel-type format as the main homepage itself in a sort of more app-friendly design. However, the escalating complexity of the functions involved in the editing pages did not eventually lend itself to an easy introduction and quick searching for a home page.

Fortunately the IIIF format lends itself nicely to loading small thumbnails, and so I chose to maintain what I could of the scrolling app style by using an infinity scroll of the thumbnails as the main page for those logged in, vaguely imitating the Twitter social network page.

However, to enable queuing and the ability to simply click “next” on the main editing page to go to the next image in the queue without having to exit back to the main page each time (a frustrating and deterring feature of many existing crowd sourcing websites I’d found in my research), I decided to separate out the Javascript filtering and building the queues (polyedsearchpage.js) from the homepage Javascript presenting that queue visually as infinity scrolling thumbnails (scrolling.js), and the Javascript for the editing pages that would also be using the queue (app.js).

polyedsearchpage.js

The queue of images, i.e. the order in which they appear as thumbnails on the Homepage and which images load next when clicking the up and down buttons on the Editing pages is determined by using the polyedsearchpage.js file.

This requires the JSON variable theFilters to be defined in the following format:

var theFilters = {
    metadata: {
        startYear: Number,
        endYear: Number,

    },
    transcription: {
        languages: String,
        difficulty: String
    },
    translation: {
        languages: String,
        difficulty: String
    },
    searchTerms: String

}

And then the queue generated using the function generateQueue which takes the following options:

  • children_no (Number) – The number of items to be selected from the collectionDocArray to be added to the queue.
  • scrolling (Boolean) – [Optional] If true, look for the object defined by variable InfinityListView and fill with thumbnail icons of the queue.
  • reuse (Boolean) – [Optional] If true then will reuse images from the collectionDocArray to keep lengthening the queue dynamically, if scrolling is also true then the queue will infinitely lengthen when the thumbnail list is scrolled through.
  • repeat_no (Number) – [Optional] The maximum number of times that objects can be reused to lengthen the queue – if undefined with reuse true then reuse will continue infinitely – this could cause harm to user experience if unlimited icons are loaded into the page.
generateQueue(children_no, scrolling, reuse, repeat_no)

theCollectionArray.js

Then the array variable collectionDocArray needs to be defined – this must be an array of IIIF info.json URLs from which the queue can be generated.

In this case it is defined in a separate file (but could be defined by any other means within app.js as long as the variable name and resulting format remain the same) and lists University of Edinburgh Collections LUNA test URLs.

For example:

collectionDocArray = [

"http://lac-luna-test2.is.ed.ac.uk:8181/luna/servlet/iiif/UoEcha~4~4~343880~104980/info.json",

"http://lac-luna-test2.is.ed.ac.uk:8181/luna/servlet/iiif/UoEgal~5~5~76533~105854/info.json",

"http://lac-luna-test2.is.ed.ac.uk:8181/luna/servlet/iiif/UoEsha~3~3~54530~102219/info.json",

"http://lac-luna-test2.is.ed.ac.uk:8181/luna/servlet/iiif/UoEsha~3~3~64904~103090/info.json"
]

Building the Queue

The queue itself is simply defined in three main arrays:

var polyEdPrevDocs = [];
var polyEdCurrentDocs = [];
var polyEdNextDocs = [];

TheFilters are used in the code in multiple approximate stages to extract from collectionDocArray the relevant information to build up the three queue arrays.

Firstly checking if any valid input has been made at all, done with the “checks” functions:

  • languageCheck
  • bySearchTerms
  • dateCheck

Secondly by then filtering out the results based on the criteria selected using the following functions:

  • annoLanguageFilters
  • annoSearchFilters
  • theURL
  • annoFilters
  • metaFilters
  • startFilters

Then using these to build a queue with the function options.

var generateQueue = function(childrenNo, scrolling, reuse, repeatNo) {

	var theRowHTML = iconRowHTML;

	for ( i=1; i<=childrenNo; i++ ) {

		var theNewDoc = loopImageFilter(polyEdFilters);

		addToNextQueue(theNewDoc);

		if (scrolling) {
                  /////generating thumbnail infinity page code here
		};
	};

	if (reuse) {	
		shouldScrollLoop = true;
		if (collectionDocArray.length < (childrenNo * repeatNo)) {
			collectionDocArray.forEach(function(doc){
				addToQueue(doc);
			});
			collectionDocArray = polyEdNextDocs;
			generateQueue(childrenNo * repeatNo, true, true);
		}
		else {
			generateQueue(childrenNo * repeatNo, true, true);
		};	
	};
};

Building the Thumbnail Scroll

screen-shot-2016-08-22-at-11-47-03

Finally the queue can be used to fill the infinity scroll with the relevant thumbnails, firstly by building the thumbnail HTML strings to be added:

var endOfPageHTML = `End of Page`; 
var iconRowHTML = ``; 
var openAnchorHTML = ``; 
var openImgHTML = ` `; 
var endAnchorHTML = `</a>`; 
var theThumbnailIIIF = "http://lac-luna-test2.is.ed.ac.uk:8181/luna/servlet/iiif/"; 
var thumbnailFileExt = "/full/100,100/0/default.jpg"; /////??????? 
var generateIconHTML = function(theURL) { 
   var theDocID = theURL.substring( 57, theURL.lastIndexOf("/info.json")       ); 
   ///the 57 comes from length of LUNA Test URL length 
   var theDOMID = " id='"+theDocID+"' "; 
   var theHREF = " href='/editors/"+encodeURI(theDocID)+"' "; 
   var theTitle = "<p >" + "</p>"; 
   ///////find title 
   return openAnchorHTML+theDOMID+theHREF+" >"+docIconHTML+theTitle+openImgHTML+theThumbnailIIIF+theDocID+thumbnailFileExt+" >"+endDivHTML+endAnchorHTML; 
};

Then within the generateQueue function, if the “scrolling” option is enabled, these icons are built and added:

var createRow = function(theNewDoc, theIndexNo) {
	if (theIndexNo % 3 == 0) {
		theRowHTML += generateIconHTML(theNewDoc) + endDivHTML;
		infinityListView.append(theRowHTML);
		theRowHTML = iconRowHTML; ///reset?
	}
	else {
		theRowHTML += generateIconHTML(theNewDoc);
	};
};
createRow(theNewDoc, i);
if (i==childrenNo) {	infinityListView.append(endOfPageHTML);	};

Additionally, if the page is scrolled, further thumbnails need to be loaded if there are any:

$('#poly-ed-scroll').on("scroll", function(){
	var viewportBottom = $('#poly-ed-scroll').scrollTop() + $('#poly-ed-scroll').height(); 
	var nearEnd = $(".poly-ed-end-scroll").offset().top; ///distance from top of scroll to the div at the end of the list
	var reloadDistance = $('#poly-ed-scroll').height() / 10; ///distance of bottom of scroll from bottom of screen when the next lot should be generated

	if ((shouldScrollLoop) && (nearEnd <= viewportBottom + reloadDistance)) {
		infinityListView.find(".poly-ed-end-scroll")[0].remove();
		if (collectionDocArray.length < 12) {
			collectionDocArray.forEach(function(doc){
				addToQueue(doc);
			});
			collectionDocArray = polyEdNextDocs;
			generateQueue(12, true, true);
		}
		else {
			generateQueue(12, true, true);
		};
	};
});

The Queue In The Editing Pages

screen-shot-2016-08-22-at-11-58-50

Alternatively the queue can be used to provide information about the next, current, and previous images to display when moving along from the editing pages. This is done both through global variables and through setting cookies to remember queue positions.

var settingPolyEdCookies = function(prevDocs, upDocs) {
  document.cookie = "upcomingdocs="+upDocs+";";
  document.cookie = "previousdocs="+upDocs+";";
};

var searchPolyEdCookie = function(field) {
  var fieldIndex = document.cookie.lastIndexOf(field);
  if (fieldIndex == -1) {  return false;  }
  else {
    var postField = document.cookie.substring(fieldIndex+field.length);
    var theValueEncoded = postField.split(";", 1);
    var theValue = theValueEncoded[0];
    return theValue;
  };
};

var cookieNextDocs = searchPolyEdCookie("upcomingdocs=");
var cookiePrevDocs = searchPolyEdCookie("previousdocs=");

var setUpPolyEdChangeBtns = function() {

	if (isUseless(cookieNextDocs) && isUseless(polyEdNextDocs[0])) {
	  	generateQueue(3, false, false, 0);
	  	$(".poly-ed-editors-next").attr("href", extractLunaIds(polyEdNextDocs[0]));
	}
	else if (!isUseless(cookieNextDocs) && isUseless(polyEdNextDocs[0])) {
		//alert("using cookies to set next");
	  	polyEdNextDocs = cookieNextDocs.split(",");
	  	$(".poly-ed-editors-next").attr("href", extractLunaIds(polyEdNextDocs[0]));
	}
	else if (!isUseless(polyEdNextDocs[0])) {
		$(".poly-ed-editors-next").attr("href", extractLunaIds(polyEdNextDocs[0]));
	};

	if (isUseless(cookiePrevDocs) && isUseless(polyEdPrevDocs)) {
	  	polyEdPrevDocs = [];
	  ////set CSS of prev button to disabled or faded
	}
	else if (!isUseless(cookiePrevDocs) && isUseless(polyEdPrevDocs[0])) {
	  	polyEdPrevDocs = cookiePrevDocs.split(",");
	  	$(".poly-ed-editors-prev").attr("href", extractLunaIds(polyEdPrevDocs[0]));
	}
	else if (!isUseless(polyEdPrevDocs[0])) {
	  	$(".poly-ed-editors-prev").attr("href", extractLunaIds(polyEdPrevDocs[0]));
	};

	$(".poly-ed-editors-prev").on("click", function(event){
		polyEdCurrentDocs.forEach(function (doc) {
			addToNextQueue(doc);
		});
		var theURL = createLUNAurl( this );
		removeFromPrevQueue( theURL );
		document.cookie = "imageviewing="+theURL;
		settingPolyEdCookies(polyEdPrevDocs, polyEdNextDocs);
	});
	$(".poly-ed-editors-next").on("click", function(event){
		var theURL = createLUNAurl( this );
	  	removeFromNextQueue( theURL );
	  	polyEdCurrentDocs.forEach(function (doc) {
			addToPrevQueue(doc);
		});
	  	document.cookie = "imageviewing="+theURL;
	  	settingPolyEdCookies(polyEdPrevDocs, polyEdNextDocs);
	});
};

 

Other Pages

This left me with a handful of other static pages left to simply design and build within the framework laid down elsewhere in the website. These were:

  • Basic Login Page
  • FAQs
  • Contact Us

I never started the basic login page, and started but never completed the others. Due to not quite finishing the users system on the back end, I was never able to link up with the University’s login system EASE, and unable to experiment with the user functionality I simply used a Placekitten API image and the “Jane Blogg” to act as placeholders in the page corners.

However, the FAQs and 404 page did give me the opportunity to display my tacky-but-glorious animated handwriting logo in full, triggered by hover motion over the image.

screen-shot-2017-01-27-at-17-58-14
So ironically the University of Edinburgh part of the logo refused to load for the 404 page….

 

Next: Overview

This is part of my series of posts about the PolyAnno project – more here

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s