Changeset 30480
- Timestamp:
- 2016-04-20T22:59:50+12:00 (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/greenstone3/web/client-side-xslt.js
r30468 r30480 7 7 8 8 @author Steven McTainsh 9 @date 14/02/2011 9 @author David Bainbridge 10 @date 2011-2016 10 11 11 12 */ 12 13 13 /* These URLs and file paths are fetched dynamically */ 14 //var gsweb = ""; // The file path to the Greenstone 3 web directory 15 //var gsurl = ""; // The root URL for this Greenstone 3 installation 16 17 /* Misc. switches and paths */ 18 var keyUrl = ''; // Used across methods to build up query string for text retrieval (client-side transformed version) 19 var on = true; // Set to false to disable operation 20 var debug = true; 21 22 var index = 0; // Used for query array (to keep track of number of elements) 23 var deferredEls = new Array(); // Elements to defer text retrieval for until later 24 var queryArr = new Array(); // Text to query for (the text for the corresponding deferred element) 14 15 function isSupported() 16 { 17 // The whole script currently assumes SaxonCE is used to provide XSLT 18 // which means it is always supported => return true 19 // 20 // Could consider testing for native XSLT (using simple 21 // hardwired XML + XSL Tranform?) and using that 22 // if successful (presumably faster) 23 // 24 // Or even try to transform the given transform natively, 25 // and store 'isNativelySupported' as true/false in cookie 26 // accordingly 27 28 return true; 29 } 30 31 function notSupportedCookie() { 32 document.cookie = 'supportsXSLT=false; expires=0; path=/'; 33 } 25 34 26 35 function notSupported() { 27 // Set not supported cookie here 28 document.cookie = 'supportsXSLT=false; expires=0; path=/'; 29 // Fall back to server version 30 var location = window.location.search.substring(1); 31 if(location == '') { 32 // Start with a question mark 33 location = window.location + "?o=server"; 34 } else { 35 // Start with an ampersand 36 location = window.location + "&o=server"; 37 } 38 window.location = location; 39 } 40 41 /* 42 $(document).ready(function() { 43 console.log("Client-side XSLT: Document is ready"); 36 notSupportedCookie(); 37 38 // knock out 'client-' part from URL 39 var location_href = window.location.href; 40 41 var new_location_href = location_href.replace(/^(.*)\/(client-)?([^\?\#]+)(.*)$/,"$1/$3$4"); 42 console.log("Client-side XSLT not supported. Redirecting to: " + new_location_href); 44 43 45 if (isSupported()) { 46 transform(false); 47 } 48 else { 49 notSupported(); 50 } 51 }); 52 */ 44 window.location = new_location_href; 45 } 46 47 function getUrlParameterHashmap() { 48 var sPageURL = decodeURIComponent(window.location.search.substring(1)); 49 var sURLVariables = sPageURL.split('&'); 50 51 var paramHashmap = {}; 52 53 for (var i = 0; i < sURLVariables.length; i++) { 54 var sParameterName = sURLVariables[i].split('='); 55 paramHashmap[sParameterName[0]] = sParameterName[1]; 56 } 57 58 return paramHashmap; 59 } 60 61 // From: 62 // http://stackoverflow.com/questions/298750/how-do-i-select-text-nodes-with-jquery 63 function getTextNodesIn(node, includeWhitespaceNodes) { 64 var textNodes = [], nonWhitespaceMatcher = /\S/; 65 66 function getTextNodes(node) { 67 if (node.nodeType == 3) { 68 if (includeWhitespaceNodes || nonWhitespaceMatcher.test(node.nodeValue)) { 69 textNodes.push(node); 70 } 71 } 72 else { 73 for (var i = 0, len = node.childNodes.length; i < len; ++i) { 74 getTextNodes(node.childNodes[i]); 75 } 76 } 77 } 78 79 getTextNodes(node); 80 return textNodes; 81 } 82 83 function applyDisableEscapingToTextNodes(elem) 84 { 85 var textNodes = getTextNodesIn(elem,false); // ignore whitespace 86 87 for (var i=textNodes.length-1; i>=0; i--) { 88 var text_node = textNodes[i]; 89 var text = text_node.nodeValue; 90 var html = $.parseHTML(text); 91 $(text_node).replaceWith(html); 92 } 93 } 94 53 95 54 96 … … 56 98 57 99 try { 100 var paramHashmap = getUrlParameterHashmap(); 101 58 102 var rooturl = window.location.pathname; 59 103 var queryStr = window.location.search.substring(1); … … 63 107 } 64 108 queryStr += "o=clientside"; 65 66 console.log("*** rooturl = " + rooturl); 67 console.log("*** queryStr = " + queryStr); 109 110 paramHashmap['o']="clientside"; 111 112 //console.log("*** rooturl = " + rooturl); 113 //console.log("*** queryStr = " + queryStr); 68 114 69 115 var skindoc = ""; 70 116 var xmldoc = ""; 71 117 72 $.get(rooturl + "?" + queryStr, function(data) { 73 74 //dataStr = dataStr.replace(/gs3:id/g, "gs3id"); 75 76 //data = parseFromString(dataStr, "text/xml"); 77 118 $.get(rooturl, paramHashmap, function(data) { 119 78 120 var toplevel_children = $(data).children().eq(0).children(); 79 121 var skindoc = toplevel_children[0]; 80 122 var xmldoc = toplevel_children[1]; 81 82 83 var site_name = $('xsltparams>param[name=site_name]', xmldoc).text(); 123 84 124 var library_name = $('xsltparams>param[name=library_name]', xmldoc).text(); 85 125 var interface_name = $('xsltparams>param[name=interface_name]', xmldoc).text(); 126 var site_name = $('xsltparams>param[name=site_name]', xmldoc).text(); 127 var use_client_side_xslt = $('xsltparams>param[name=use_client_side_xslt]', xmldoc).text(); 86 128 87 129 //// Convert temporarily to text here … … 89 131 xmldoc = convertToString(xmldoc); 90 132 91 //// This could just be done on the server (later)92 ////data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" /*+ "<?xml-stylesheet type=\"text/xsl\" href=\"" + skinurl + "\"?>\r\n"*/ + data;93 //// replace all!94 //// Be careful with regex syntax and the use of special characters!95 //skindoc = skindoc.replace(/util\:exists\(\$meta, ''\)/g, "$meta!=''"); // For now - use regex instead96 //skindoc = skindoc.replace(/%3A/g, ":"); // undo colon escaping97 98 //skindoc = skindoc.replace(/util\:.+?\(\.*?\)/g, "true");99 100 133 skindoc = skindoc.replace(/<xslt:stylesheet\s+/,"<xslt:stylesheet xmlns:ixsl=\"http://saxonica.com/ns/interactiveXSLT\" xmlns:js=\"http://saxonica.com/ns/globalJS\" "); 101 //extension-element-prefixes="ixsl" exclude-result-prefixes="xs xd d js"102 134 skindoc = skindoc.replace(/extension-element-prefixes="(.*?)"/,"extension-element-prefixes=\"$1 ixsl\""); 103 //skindoc = skindoc.replace(/exclude-result-prefixes="(.*?)"/,"exclude-result-prefixes=\"$1 js\"");104 105 135 106 136 skindoc = skindoc.replace(/util\:exists\(\$meta, ''\)/g, "$meta!=''"); // For now - use regex instead 107 skindoc = skindoc.replace(/util:replace\((.*?)\)/g, "replace($1)"); // exists in XSLT 2.0 108 skindoc = skindoc.replace(/util:storeString\((.+?),(.+)?\)/g, "$1=$2"); 109 skindoc = skindoc.replace(/util:getString\((.+?)\)/g, "$1"); 110 skindoc = skindoc.replace(/util:getDetailFromDate\((.+?),.+?,.+?\)/g, "$1"); 111 112 //skindoc = skindoc.replace(/util:getNumberedItem\(([^,]+),([^,]+)\)$/,"js:getNumberedItem($1,$2)"); // never tested 113 114 //skindoc = skindoc.replace(/\{\{/,"\\{"); 115 //skindoc = skindoc.replace(/\}\}/,"\\}"); 116 //skindoc = skindoc.replace(/"js:[^"]+"/g, "js:console.log('foo')"); 117 137 skindoc = skindoc.replace(/util:replace\((.*?)\)/g, "replace($1)"); // 'replace()' exists in XSLT 2.0 138 skindoc = skindoc.replace(/util:storeString\(\s*'(.+?)'\s*,\s*'(.*?)'\s*\)/g, "js:storeString(string($1),string($2))"); 139 skindoc = skindoc.replace(/util:getString\('(.+?)'\)/g, "js:getString(string($1))"); 140 skindoc = skindoc.replace(/util:escapeNewLinesAndQuotes\(([^)]+)\)/g, "js:escapeNewLinesAndQuotes(string($1))"); 141 //attr_val = attr_val.replaceAll("util:escapeNewLinesAndQuotes\\(\\s*(.+?)\\s*\\)","$1"); 142 143 skindoc = skindoc.replace(/util:getDetailFromDate\((.+?),.+?,.+?\)/g, "'getDetailFromDate $1'"); // **** 144 145 skindoc = skindoc.replace(/util:oidIsMatchOrParent\(([^,]+),([^)]+)\)/g,"js:oidIsMatchOrParent(string($1),string($2))"); 146 skindoc = skindoc.replace(/util:hashToDepthClass\(([^)]+)\)/g,"js:hashToDepthClass(string($1))"); 147 skindoc = skindoc.replace(/util:hashToSectionId\(([^)]+)\)/g,"js:hashToSectionId(string($1))"); 148 149 skindoc = skindoc.replace(/java:.*?getNumberedItem\(([^,]+),([^)]+)\)/g,"js:getNumberedItem(string($1),string($2))"); 150 118 151 // Convert to XML 119 152 xmldoc = parseFromString(xmldoc, "text/xml"); 120 153 skindoc = parseFromString(skindoc, "text/xml"); 121 154 155 console.log("Applying client-side XSLT"); 122 156 var output = ''; 123 /* 124 var params = { 'library_name': library_name, 'interface_name': interface_name }; 125 var proc = Saxon.run( { 126 stylesheet: skindoc, 127 source: xmldoc, 128 parameters: params 129 }); 130 */ 131 132 /* 133 var xml = Saxon.requestXML("http://localhost:8383/greenstone3/mozarts-library/collection/digital-music-stand/page/about?o=xml"); 134 var xsl = Saxon.requestXML("http://localhost:8383/greenstone3/mozarts-library/collection/digital-music-stand/page/about?o=skinandlibdocfinal"); 135 */ 136 var proc = Saxon.newXSLT20Processor(skindoc); 137 157 158 //var proc = Saxon.newXSLT20Processor(skindoc); 159 var proc = Saxon.newXSLT20Processor(); 160 138 161 proc.setParameter(null, 'library_name', library_name); 139 162 proc.setParameter(null, 'interface_name', interface_name); 140 proc.setParameter(null, 'site_name', site_name); 141 163 proc.setParameter(null, 'site_name', site_name); 164 proc.setParameter(null, 'use_client_side_xslt', use_client_side_xslt); 165 166 // Consider making above XSLT20Porcessor constructor take no arguments, 167 // and specify transform through importStylesheet(), this combination 168 // of code is more consistent with other XSLT systems 169 // 170 proc.importStylesheet(skindoc); 171 142 172 result = proc.transformToDocument(xmldoc); 173 //result = proc.transformToFragment(xmldoc); 174 175 //proc.updateHTMLDocument(xmldoc); 176 //return; 177 178 var excerptid = paramHashmap['excerptid']; 179 if (excerptid) { 180 result = result.getElementById(excerptid); 181 } 182 183 applyDisableEscapingToTextNodes(result); 143 184 xmlSer = new XMLSerializer(); 144 185 output = xmlSer.serializeToString(result); 145 146 var doc = document.open(); 147 doc.write(output); 148 doc.close(); 149 150 document.cookie = 'supportsXSLT=true; expires=0; path=/'; 151 152 153 154 }, 'xml'); 155 } 156 catch (e) { 157 if(trial) { 158 notSupportedCookie(); 159 } 160 else { 161 notSupported(); 162 } 163 } 164 } 165 166 167 168 169 function transform(trial) { 170 171 //alert("transform(): trial = " + trial); 172 173 try { 174 var rooturl = window.location.pathname; 175 var queryStr = window.location.search.substring(1); 176 queryStr = queryStr.replace(/o=.*?(&|$)/g,""); 177 if (queryStr != '') { 178 queryStr += "&"; 179 } 180 queryStr += "o=clientside"; 181 182 console.log("*** rooturl = " + rooturl); 183 console.log("*** queryStr = " + queryStr); 184 185 var skindoc = ""; 186 var xmldoc = ""; 187 188 $.get(rooturl + "?" + queryStr, function(dataStr) { 189 //dataStr = dataStr.trim(); 190 dataStr = dataStr.replace(/gs3:id/g, "gs3id"); 191 //dataStr = dataStr.replace(/&/g,"&"); 192 //dataStr = dataStr.replace(/&quot;/g,"""); 193 //dataStr = dataStr.replace(/&lt;/g,"<"); 194 //dataStr = dataStr.replace(/&gt;/g,">"); 195 //dataStr = dataStr.replace(/&amp;/g,"&"); 196 197 data = parseFromString(dataStr, "text/xml"); 198 199 var toplevel_children = $(data).children().eq(0).children(); 200 var skindoc = toplevel_children[0]; 201 var xmldoc = toplevel_children[1]; 202 203 204 //gsurl = $($(xmldoc).find("metadata[name=siteURL]")[0]).text(); 205 //gsurl = $(xmldoc).find("pageRequest").attr("baseURL"); 206 var site_name = $('xsltparams>param[name=site_name]', xmldoc).text(); 207 var library_name = $('xsltparams>param[name=library_name]', xmldoc).text(); 208 var interface_name = $('xsltparams>param[name=interface_name]', xmldoc).text(); 209 210 //gsurl = $(xmldoc).find("pageRequest").attr("baseURL") + site_name; 211 //gsweb = new RegExp($($(xmldoc).find("param[name=filepath]")[0]).text().replace(/\\/g, "\\\\"), "g"); 212 213 //// Convert temporarily to text here 214 skindoc = convertToString(skindoc); 215 xmldoc = convertToString(xmldoc); 216 217 //// This could just be done on the server (later) 218 ////data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" /*+ "<?xml-stylesheet type=\"text/xsl\" href=\"" + skinurl + "\"?>\r\n"*/ + data; 219 //// replace all! 220 //// Be careful with regex syntax and the use of special characters! 221 //skindoc = skindoc.replace(/util\:exists\(\$meta, ''\)/g, "$meta!=''"); // For now - use regex instead 222 //skindoc = skindoc.replace(/%3A/g, ":"); // undo colon escaping 223 224 //skindoc = skindoc.replace(/util\:.+?\(\.*?\)/g, "true"); 225 226 skindoc = skindoc.replace(/util\:exists\(\$meta, ''\)/g, "$meta!=''"); // For now - use regex instead 227 skindoc = skindoc.replace(/util:storeString\((.+?),(.+)?\)/g, "$1=$2"); 228 skindoc = skindoc.replace(/util:getString\((.+?)\)/g, "$1"); 229 skindoc = skindoc.replace(/util:getDetailFromDate\((.+?),.+?,.+?\)/g, "$1"); 230 231 232 // Convert to XML 233 xmldoc = parseFromString(xmldoc, "text/xml"); 234 skindoc = parseFromString(skindoc, "text/xml"); 235 236 var output = ''; 237 238 // And post-process... 239 if(window.ActiveXObject) { 240 // IE 241 var procFactory = new ActiveXObject("MSXML2.XSLTemplate"); 242 procFactory.stylesheet = skindoc; 243 var proc = procFactory.createProcessor(); 244 proc.input = xmldoc; 245 246 proc.addParameter('library_name', library_name); 247 proc.addParameter('interface_name', interface_name); 248 249 proc.transform(); 250 output = proc.output; 251 } 252 else { 253 // Firefox, Chrome ... 254 xsltProc = new XSLTProcessor(); 255 // The leading slash is oh-so important here 256 xsltProc.setParameter(null, 'library_name', library_name); 257 xsltProc.setParameter(null, 'interface_name', interface_name); 258 try { 259 xsltProc.importStylesheet(skindoc); 260 } 261 catch(e) { 262 alert("Malformed importStyle sheet:" + e.message + "\n======\nSee web browser console for more details"); 263 // Look for util: of java: 264 if (debug) { 265 console.error("Stylesheet:\n" + skindoc.documentElement.outerHTML); 266 } 267 } 268 269 // 270 try { 271 result = xsltProc.transformToDocument(xmldoc); 272 xmlSer = new XMLSerializer(); 273 output = xmlSer.serializeToString(result); 274 } 275 catch(e) { 276 alert("XSL Transform failed:" + e.message + "\n======\nSee web browser console for more details"); 277 console.error("doc:\n" + convertToString(xmldoc) + "\n========\nStylesheet:\n" + convertToString(skindoc)); 278 } 279 } 280 186 187 if (excerptid) { 188 var callback = paramHashmap['callback']; 189 parent[callback](output); 190 } 191 else { 281 192 var doc = document.open(); 282 193 doc.write(output); 283 194 doc.close(); 195 196 // **** 197 document.cookie = 'supportsXSLT=true; expires=0; path=/'; 198 } 284 199 285 document.cookie = 'supportsXSLT=true; expires=0; path=/';286 287 }, 'text'); 288 200 201 }, 'xml'); 202 203 } 289 204 catch (e) { 290 if(trial) { 291 notSupportedCookie(); 292 } 293 else { 294 notSupported(); 295 } 296 } 297 } 298 299 function notSupportedCookie() { 300 document.cookie = 'supportsXSLT=false; expires=0; path=/'; 301 } 302 303 304 // Method equivalent to PHP's in_array method 305 function contains(array, value) { 306 307 for(var val in array) 308 if(array[val] == value) 309 return true; 310 311 return false; 312 } 313 314 // Method equivalent to PHP's own 315 function print_r(arr) { 316 317 var result = ""; 318 319 for(var a in arr) { 320 result += a + " => " + arr[a] + "\r\n"; 321 } 322 323 return result; 324 } 205 alert("Error occured:" + e.message + "\n======\nSee web browser console for more details"); 206 notSupported(); 207 208 } 209 } 210 325 211 326 212 function convertToString(content) { 327 328 329 330 331 332 333 334 213 try { 214 // If this fails, it's another indication that the browser doesn't have the support we need 215 if(typeof XMLSerializer != 'undefined') { 216 return (new XMLSerializer()).serializeToString(content); 217 } else { 218 return content.xml; 219 } 220 } 335 221 catch (e) { 336 222 notSupported(); … … 361 247 } 362 248 363 function isSupported() {364 365 return true;366 // change test below to simple XML + XSL Transform367 368 /*369 // Are cookies enabled?370 if(navigator.cookieEnabled && typeof navigator.cookieEnabled != 'undefined') {371 // Is there a cookie?372 if(document.cookie.indexOf('supportsXSLT=') > -1) {373 // Cookie exists - don't try the transformation, as the server will374 // read the cookie and determine which version to serve up.375 // If it happens to be client-side, allow transformation to proceed376 return (document.cookie.indexOf('supportsXSLT=true') > -1);377 } else {378 // Cookie doesn't exist - test!379 transform(true);380 applyText(true);381 return (document.cookie.indexOf('supportsXSLT=true') > -1);382 }383 } else {384 return false;385 }386 */387 }388 249 389 250 /* Simulating web storage for browsers that don't support it */
Note:
See TracChangeset
for help on using the changeset viewer.