Index: main/trunk/greenstone3/web/interfaces/default/transform/layouts/webswing-collage.xsl
===================================================================
--- main/trunk/greenstone3/web/interfaces/default/transform/layouts/webswing-collage.xsl	(revision 38932)
+++ main/trunk/greenstone3/web/interfaces/default/transform/layouts/webswing-collage.xsl	(revision 38932)
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+	xmlns:java="http://xml.apache.org/xslt/java"
+	xmlns:util="xalan://org.greenstone.gsdl3.util.XSLTUtil"
+	xmlns:gslib="http://www.greenstone.org/skinning"
+	xmlns:gsf="http://www.greenstone.org/greenstone3/schema/ConfigFormat"
+	extension-element-prefixes="java util"
+	exclude-result-prefixes="java util gsf">
+  
+	<xsl:template name="webswing-embed-collage">
+	  <link rel="stylesheet" href="/webswing-server/css/style.css" />
+	  <div id="webswing-collage" class="webswing-element" data-webswing-instance="webswingInstance0" style="width: 800px; height: 400px;">
+	    <div id="loading" class="ws-modal-container">
+              <div class="ws-login">
+		<div  class="ws-login-content">
+                  <div class="ws-spinner">
+		    <div class="ws-spinner-dot-1"><xsl:comment>filler</xsl:comment></div>
+		    <div class="ws-spinner-dot-2"><xsl:comment>filler</xsl:comment></div>
+		  </div>
+		</div>
+              </div>
+	    </div>
+	  </div>
+
+	  <gsf:script>
+	    // https://www.webswing.org/docs/23.2/configure/applet.html
+	    // https://www.webswing.org/docs/23.2/configure/swing.html
+	    // https://www.webswing.org/docs/23.2/integrate/javascript-api?_h=customArgs%2Cargs#usage-with-customization-and-options	    
+	    // https://www.webswing.org/docs/23.2/integrate/embed.html
+	    // https://www.webswing.org/docs/20.1/integrate/urlparams.html
+	    // https://www.webswing.org/docs/23.2/integrate/urlparams.html
+	    // https://www.webswing.org/docs/20.1/integrate/customize.html
+	    // https://www.webswing.org/docs/2.7/integrate/embed.html
+	    
+    var webswingInstance0 = {
+        options: {
+        autoStart: true,
+	//appletParams: getParam('appletParams'),
+	//appletParams: {"collection":"smallbea", "library":"library"},
+            connectionUrl:'/webswing-server/collage',
+
+	    customization: function(injector) {
+	    injector.services.base.handleActionEvent = function(actionName, data, binaryData) {
+       	        //console.log("WebSwing actionEvent callback handler: called with actionName = " + actionName);
+
+	        if (actionName === "openURL") {
+	          var url = data;
+		  // check if a target tab/window name has been specified
+		  // TODO: Any better way of passing > 1 string between Java and JavaScript?
+		  var index = url.indexOf(" - ");
+		  if (index !== -1) {
+		     var target = url.substring(index+3); // skip past " - " to get target name
+		     url = url.substring(0, index);
+		     // Note that target window name is not the same as target window title
+		     // https://stackoverflow.com/questions/8051811/how-to-show-window-title-using-window-open
+		     window.open(url, target);	             
+		  } else {
+		     window.open(url, '_blank');
+		  }
+		} else if (actionName == "javaToWebswingJSConsoleLog") {
+		    console.log("Got message from java:\n" + data);
+		}
+	    
+	      }
+            }
+
+	    
+       }
+       };
+
+       
+       // The applet jar files can just remain in web/applet where they are compiled up
+       
+       if(!webswingInstance0.options.args) {
+       webswingInstance0.options.args="";       
+       }
+       
+       //https://stackoverflow.com/questions/25203124/how-to-get-base-url-with-jquery-or-javascript
+       var baseURL = window.location.origin+window.location.pathname;       
+       // webswingInstance0.options.args += "\"" + baseURL+ "?a=a&amp;rt=d&amp;s=GsdlCollageApplet&amp;c=smallbea\"";
+       var servlet_index = baseURL.indexOf("/"+gs.xsltParams.library_name);
+       if(servlet_index > 0) {
+       baseURL = baseURL.substring(0, servlet_index+1);
+       }
+       var baseClassifier = "CL3";
+       //var gs3CollImgPath = gs.xsltParams.library_name + "/sites/" + gs.xsltParams.site_name + "/collect/" + gs.cgiParams.c;
+       var gs3CollBrowsePath = gs.xsltParams.library_name + "/collection/" + gs.cgiParams.c + "/browse/" + baseClassifier;
+       
+       webswingInstance0.options.args += "--baseurl \"" + baseURL + "\"";
+       //webswingInstance0.options.args += " --gsdlversion 3";       
+       webswingInstance0.options.args += " --collection " + gs.cgiParams.c;
+       webswingInstance0.options.args += " --library " + gs.xsltParams.library_name;
+       webswingInstance0.options.args += " --documentroot greenstone3";
+       webswingInstance0.options.args += " --hrefMustHave " + gs3CollBrowsePath;
+       webswingInstance0.options.args += " --imageMustNotHave \"interfaces/\"";
+       webswingInstance0.options.args += " --verbosity " + 3;
+       webswingInstance0.options.args += " --imageType " + "\".jpg%.png\"";
+       webswingInstance0.options.args += " --classifier \"" + baseClassifier + ".1\""; // "CL3.1"
+       webswingInstance0.options.args += " --maxDepth 500 --maxDisplay 25 --refreshDelay 1500 --bgcolor \"#96c29a\"";       
+
+       // Control the width and height of the Java application launched with webswing
+       // by passing width and height params set to the attributes of the webswing element
+       // https://stackoverflow.com/questions/21851633/get-height-from-style-attribute
+       var w = document.getElementById("webswing-collage").style.width;
+       var suffixIndex = 0;
+       if(w) {       
+       suffixIndex = w.indexOf("px");
+       if(suffixIndex>0) {
+          w = w.substring(0, suffixIndex);
+       }
+       webswingInstance0.options.args += " --width " + w;
+       }
+       var h = document.getElementById("webswing-collage").style.height;
+       if(h) {
+       suffixIndex = h.indexOf("px");
+       if(suffixIndex>0) {
+          h = h.substring(0, suffixIndex);
+       }
+       webswingInstance0.options.args += " --height " + h;
+       }
+       
+       //console.log("args: " +  webswingInstance0.options.args);
+
+       // Allow sending user events to swing application
+       // https://www.webswing.org/docs/20.2/integrate/embed.html
+       //webswingInstance0.setControl(true);
+       
+    function getParam(name) {
+        name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
+        var results = new RegExp("[\\?&amp;]" + name + "=([^&amp;#]*)").exec(location.href);
+        return results == null ? null : decodeURIComponent(results[1]);
+    }
+  </gsf:script>
+
+	  
+  <script data-webswing-global-var="webswing">
+    <xsl:text disable-output-escaping="yes">
+
+      var unloaded = false;
+      
+    (function (window, document) {
+        var loader = function () {
+
+	    unloaded = false; // reset state, because we are reloading the webswing app
+	
+	    var baseUrl = '/webswing-server/collage';
+            baseUrl = baseUrl.indexOf("/", baseUrl.length - 1) !== -1 ? baseUrl : (baseUrl + "/");
+            var xmlhttp = new XMLHttpRequest();
+            xmlhttp.onreadystatechange = function () {
+                if (xmlhttp.readyState == XMLHttpRequest.DONE) {
+                    var version = xmlhttp.status == 200 ? xmlhttp.responseText : "undefined";
+                    var script = document.createElement("script"),
+                        tag = document.getElementsByTagName("script")[0];
+                    script.src = baseUrl + "javascript/webswing-embed.js?version=" + version;
+                    tag.parentNode.insertBefore(script, tag);
+                }
+            };
+            xmlhttp.open("GET", baseUrl + "rest/version", true);
+            xmlhttp.send();
+        };
+
+	var navigatingAway = function () {
+	   console.log("*** navigatingAway called");
+
+	   // Multiple eventlisteners are registered to call navigatingAway, as not all are 
+	   // triggered in all contexts (desktop vs mobile vs older browsers)
+	   // https://developer.mozilla.org/en-US/docs/Web/API/Window/unload_event
+	   // We work with multiple eventlisteners to ensure we cleanup webswing collage app when
+	   // user navigates away from page. But we should only do the cleanup once, even if *all*
+	   // event handlers got triggered. We use the unloaded var to ensure we cleanup only once
+	   if(!unloaded) {
+	      if(typeof webswingInstance0.kill === 'function') { // it should exist
+	      
+	         console.log("@@@ Asking webswing to stop the collage application");
+		 webswingInstance0.kill();
+		 unloaded = true; // do not unload again, if multiple listeners call navigatingAway() callback function
+		 console.log("@@@@ unloaded");
+	      } // else cannot call method that does not exist
+	   } else {
+	      console.log("@@@@ already unloaded.");
+	   }
+	  
+	};
+	window.addEventListener ? window.addEventListener("load", loader, false) : window.attachEvent("onload", loader);
+
+
+	// When the user navigates away from this page or reloads it, we want to
+	// shutdown the webswing Java application.	
+	
+	// https://developer.mozilla.org/en-US/docs/Web/API/Window/unload_event
+	// unload is discouraged as it is not always supported (some mobile devices),
+	// so we listen for pagehide events too. Visibilitychange events happen on minimising win
+	// or another tab getting focus. So do not stop the app on mere visibilitychange.
+	// https://dev.to/amersikira/top-3-ways-to-easily-detect-when-a-user-leaves-a-page-using-javascript-2ce4
+	
+	// Pagehide is also fired when user presses back button: https://developer.mozilla.org/en-US/docs/Web/API/Window/pagehide_event
+	// https://stackoverflow.com/questions/15925251/trigger-an-event-when-user-navigates-away
+	
+	// Order of registering listeners may matter and be useful:
+	// https://stackoverflow.com/questions/31852179/javascript-event-listeners-firing-order
+	// https://stackoverflow.com/questions/2706109/are-javascript-dom-event-handlers-called-in-order-of-registration
+	// https://medium.com/@olofbaage/javascript-essentials-all-you-need-to-know-about-event-listeners-8ed889bffb8d
+	// Event support detection
+	// https://stackoverflow.com/questions/158673/onbeforeunload-support-detection
+	// https://stackoverflow.com/questions/2877393/detecting-support-for-a-given-javascript-event
+	// http://perfectionkills.com/detecting-event-support-without-browser-sniffing
+
+	// Does onUnload not leave enough time to get webswing to shutdown? OnBeforeUnload works
+	// https://caniuse.com/?search=beforeunload
+	window.addEventListener ? window.addEventListener("beforeunload", navigatingAway, false) : window.attachEvent("onbeforeunload", navigatingAway);
+	window.addEventListener ? window.addEventListener("pagehide", navigatingAway, false) : window.attachEvent("onpagehide", navigatingAway);
+	//window.addEventListener ? window.addEventListener("visibilitychange", navigatingAway, false) : window.attachEvent("onvisibilitychange", navigatingAway);	
+	
+	})(window, document);
+    </xsl:text>
+  </script>
+
+  </xsl:template>
+  
+</xsl:stylesheet>
Index: main/trunk/greenstone3/web/interfaces/default/transform/pages/classifier.xsl
===================================================================
--- main/trunk/greenstone3/web/interfaces/default/transform/pages/classifier.xsl	(revision 38931)
+++ main/trunk/greenstone3/web/interfaces/default/transform/pages/classifier.xsl	(revision 38932)
@@ -4,4 +4,5 @@
   <!-- use the 'main' layout -->
   <xsl:import href="layouts/main.xsl" />
+  <xsl:import href="layouts/webswing-collage.xsl" />
   <xsl:import href="map-tools.xsl" />
   <xsl:import href="panorama-viewer-tools.xsl" />
@@ -147,215 +148,4 @@
   </xsl:template>
 
-
-	<xsl:template name="webswing-embed-collage">
-	  <link rel="stylesheet" href="/webswing-server/css/style.css" />
-	  <div id="webswing-collage" class="webswing-element" data-webswing-instance="webswingInstance0" style="width: 800px; height: 400px;">
-	    <div id="loading" class="ws-modal-container">
-              <div class="ws-login">
-		<div  class="ws-login-content">
-                  <div class="ws-spinner">
-		    <div class="ws-spinner-dot-1"><xsl:comment>filler</xsl:comment></div>
-		    <div class="ws-spinner-dot-2"><xsl:comment>filler</xsl:comment></div>
-		  </div>
-		</div>
-              </div>
-	    </div>
-	  </div>
-
-	  <gsf:script>
-	    // https://www.webswing.org/docs/23.2/configure/applet.html
-	    // https://www.webswing.org/docs/23.2/configure/swing.html
-	    // https://www.webswing.org/docs/23.2/integrate/javascript-api?_h=customArgs%2Cargs#usage-with-customization-and-options	    
-	    // https://www.webswing.org/docs/23.2/integrate/embed.html
-	    // https://www.webswing.org/docs/20.1/integrate/urlparams.html
-	    // https://www.webswing.org/docs/23.2/integrate/urlparams.html
-	    // https://www.webswing.org/docs/20.1/integrate/customize.html
-	    // https://www.webswing.org/docs/2.7/integrate/embed.html
-	    
-    var webswingInstance0 = {
-        options: {
-        autoStart: true,
-	//appletParams: getParam('appletParams'),
-	//appletParams: {"collection":"smallbea", "library":"library"},
-            connectionUrl:'/webswing-server/collage',
-
-	    customization: function(injector) {
-	    injector.services.base.handleActionEvent = function(actionName, data, binaryData) {
-       	        //console.log("WebSwing actionEvent callback handler: called with actionName = " + actionName);
-
-	        if (actionName === "openURL") {
-	          var url = data;
-		  // check if a target tab/window name has been specified
-		  // TODO: Any better way of passing > 1 string between Java and JavaScript?
-		  var index = url.indexOf(" - ");
-		  if (index !== -1) {
-		     var target = url.substring(index+3); // skip past " - " to get target name
-		     url = url.substring(0, index);
-		     // Note that target window name is not the same as target window title
-		     // https://stackoverflow.com/questions/8051811/how-to-show-window-title-using-window-open
-		     window.open(url, target);	             
-		  } else {
-		     window.open(url, '_blank');
-		  }
-		} else if (actionName == "javaToWebswingJSConsoleLog") {
-		    console.log("Got message from java:\n" + data);
-		}
-	    
-	      }
-            }
-
-	    
-       }
-       };
-
-       
-       // The applet jar files can just remain in web/applet where they are compiled up
-       
-       if(!webswingInstance0.options.args) {
-       webswingInstance0.options.args="";       
-       }
-       
-       //https://stackoverflow.com/questions/25203124/how-to-get-base-url-with-jquery-or-javascript
-       var baseURL = window.location.origin+window.location.pathname;       
-       // webswingInstance0.options.args += "\"" + baseURL+ "?a=a&amp;rt=d&amp;s=GsdlCollageApplet&amp;c=smallbea\"";
-       var servlet_index = baseURL.indexOf("/"+gs.xsltParams.library_name);
-       if(servlet_index > 0) {
-       baseURL = baseURL.substring(0, servlet_index+1);
-       }
-       var baseClassifier = "CL3";
-       //var gs3CollImgPath = gs.xsltParams.library_name + "/sites/" + gs.xsltParams.site_name + "/collect/" + gs.cgiParams.c;
-       var gs3CollBrowsePath = gs.xsltParams.library_name + "/collection/" + gs.cgiParams.c + "/browse/" + baseClassifier;
-       
-       webswingInstance0.options.args += "--baseurl \"" + baseURL + "\"";
-       //webswingInstance0.options.args += " --gsdlversion 3";       
-       webswingInstance0.options.args += " --collection " + gs.cgiParams.c;
-       webswingInstance0.options.args += " --library " + gs.xsltParams.library_name;
-       webswingInstance0.options.args += " --documentroot greenstone3";
-       webswingInstance0.options.args += " --hrefMustHave " + gs3CollBrowsePath;
-       webswingInstance0.options.args += " --imageMustNotHave \"interfaces/\"";
-       webswingInstance0.options.args += " --verbosity " + 3;
-       webswingInstance0.options.args += " --imageType " + "\".jpg%.png\"";
-       webswingInstance0.options.args += " --classifier \"" + baseClassifier + ".1\""; // "CL3.1"
-       webswingInstance0.options.args += " --maxDepth 500 --maxDisplay 25 --refreshDelay 1500 --bgcolor \"#96c29a\"";       
-
-       // Control the width and height of the Java application launched with webswing
-       // by passing width and height params set to the attributes of the webswing element
-       // https://stackoverflow.com/questions/21851633/get-height-from-style-attribute
-       var w = document.getElementById("webswing-collage").style.width;
-       var suffixIndex = 0;
-       if(w) {       
-       suffixIndex = w.indexOf("px");
-       if(suffixIndex>0) {
-          w = w.substring(0, suffixIndex);
-       }
-       webswingInstance0.options.args += " --width " + w;
-       }
-       var h = document.getElementById("webswing-collage").style.height;
-       if(h) {
-       suffixIndex = h.indexOf("px");
-       if(suffixIndex>0) {
-          h = h.substring(0, suffixIndex);
-       }
-       webswingInstance0.options.args += " --height " + h;
-       }
-       
-       //console.log("args: " +  webswingInstance0.options.args);
-
-       // Allow sending user events to swing application
-       // https://www.webswing.org/docs/20.2/integrate/embed.html
-       //webswingInstance0.setControl(true);
-       
-    function getParam(name) {
-        name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
-        var results = new RegExp("[\\?&amp;]" + name + "=([^&amp;#]*)").exec(location.href);
-        return results == null ? null : decodeURIComponent(results[1]);
-    }
-  </gsf:script>
-
-	  
-  <script data-webswing-global-var="webswing">
-    <xsl:text disable-output-escaping="yes">
-
-      var unloaded = false;
-      
-    (function (window, document) {
-        var loader = function () {
-
-	    unloaded = false; // reset state, because we are reloading the webswing app
-	
-	    var baseUrl = '/webswing-server/collage';
-            baseUrl = baseUrl.indexOf("/", baseUrl.length - 1) !== -1 ? baseUrl : (baseUrl + "/");
-            var xmlhttp = new XMLHttpRequest();
-            xmlhttp.onreadystatechange = function () {
-                if (xmlhttp.readyState == XMLHttpRequest.DONE) {
-                    var version = xmlhttp.status == 200 ? xmlhttp.responseText : "undefined";
-                    var script = document.createElement("script"),
-                        tag = document.getElementsByTagName("script")[0];
-                    script.src = baseUrl + "javascript/webswing-embed.js?version=" + version;
-                    tag.parentNode.insertBefore(script, tag);
-                }
-            };
-            xmlhttp.open("GET", baseUrl + "rest/version", true);
-            xmlhttp.send();
-        };
-
-	var navigatingAway = function () {
-	   console.log("*** navigatingAway called");
-
-	   // Multiple eventlisteners are registered to call navigatingAway, as not all are 
-	   // triggered in all contexts (desktop vs mobile vs older browsers)
-	   // https://developer.mozilla.org/en-US/docs/Web/API/Window/unload_event
-	   // We work with multiple eventlisteners to ensure we cleanup webswing collage app when
-	   // user navigates away from page. But we should only do the cleanup once, even if *all*
-	   // event handlers got triggered. We use the unloaded var to ensure we cleanup only once
-	   if(!unloaded) {
-	      if(typeof webswingInstance0.kill === 'function') { // it should exist
-	      
-	         console.log("@@@ Asking webswing to stop the collage application");
-		 webswingInstance0.kill();
-		 unloaded = true; // do not unload again, if multiple listeners call navigatingAway() callback function
-		 console.log("@@@@ unloaded");
-	      } // else cannot call method that does not exist
-	   } else {
-	      console.log("@@@@ already unloaded.");
-	   }
-	  
-	};
-	window.addEventListener ? window.addEventListener("load", loader, false) : window.attachEvent("onload", loader);
-
-
-	// When the user navigates away from this page or reloads it, we want to
-	// shutdown the webswing Java application.	
-	
-	// https://developer.mozilla.org/en-US/docs/Web/API/Window/unload_event
-	// unload is discouraged as it is not always supported (some mobile devices),
-	// so we listen for pagehide events too. Visibilitychange events happen on minimising win
-	// or another tab getting focus. So do not stop the app on mere visibilitychange.
-	// https://dev.to/amersikira/top-3-ways-to-easily-detect-when-a-user-leaves-a-page-using-javascript-2ce4
-	
-	// Pagehide is also fired when user presses back button: https://developer.mozilla.org/en-US/docs/Web/API/Window/pagehide_event
-	// https://stackoverflow.com/questions/15925251/trigger-an-event-when-user-navigates-away
-	
-	// Order of registering listeners may matter and be useful:
-	// https://stackoverflow.com/questions/31852179/javascript-event-listeners-firing-order
-	// https://stackoverflow.com/questions/2706109/are-javascript-dom-event-handlers-called-in-order-of-registration
-	// https://medium.com/@olofbaage/javascript-essentials-all-you-need-to-know-about-event-listeners-8ed889bffb8d
-	// Event support detection
-	// https://stackoverflow.com/questions/158673/onbeforeunload-support-detection
-	// https://stackoverflow.com/questions/2877393/detecting-support-for-a-given-javascript-event
-	// http://perfectionkills.com/detecting-event-support-without-browser-sniffing
-
-	// Does onUnload not leave enough time to get webswing to shutdown? OnBeforeUnload works
-	// https://caniuse.com/?search=beforeunload
-	window.addEventListener ? window.addEventListener("beforeunload", navigatingAway, false) : window.attachEvent("onbeforeunload", navigatingAway);
-	window.addEventListener ? window.addEventListener("pagehide", navigatingAway, false) : window.attachEvent("onpagehide", navigatingAway);
-	//window.addEventListener ? window.addEventListener("visibilitychange", navigatingAway, false) : window.attachEvent("onvisibilitychange", navigatingAway);	
-	
-	})(window, document);
-    </xsl:text>
-  </script>
-
-	</xsl:template>
-  
   <xsl:template name="Collage">
 
