Get Rid Of Hard-coding The Context Path Of Web Apps In External Javascript Files
Solution 1:
What happens is that the included JavaScript file named
websockets.js
where the global variablecontextPath
is attempted to be accessed, is placed before the hard-coded<script>
tag in the generated HTML<head>
tag in the master template
This is unexpected. You declared the <h:outputScript>
referring websockets.js
file inside <h:body>
with target="head"
. This is supposed to end up after all other script resources already declared in <h:head>
. See also a.o. How to reference CSS / JS / image resource in Facelets template? After all, this appears to be caused by PrimeFaces bundled HeadRenderer
which is intented to auto-include some CSS resources and take care of the <facet name="first|middle|last">
.
This is worth an issue report to PF guys (if not already done). In the meanwhile, your best bet is to turn off it by explicitly registering the JSF implementation's own HeadRenderer
back as below in faces-config.xml
(provided that you're using Mojarra).
<render-kit><renderer><component-family>javax.faces.Output</component-family><renderer-type>javax.faces.Head</renderer-type><renderer-class>com.sun.faces.renderkit.html_basic.HeadRenderer</renderer-class></renderer></render-kit>
And explicitly include the PrimeFaces theme-specific theme.css
as below in <h:head>
:
<h:outputStylesheetlibrary="primefaces-aristo"name="theme.css" />
Coming back to the real question,
Anyway, how to get rid of hard-coding the context path in external JavaScript files?
Either set it as base URI (note: relative path isn't supported in HTML4 / IE6-8).
<h:head>
<base href="#{request.contextPath}/" />
...
</h:head>
var baseURI = $("base").attr("href");
Or set it as data attribute of HTML root element.
<!DOCTYPE html><htmllang="en"data-baseuri="#{request.contextPath}/"...>
...
</html>
var baseURI = $("html").data("baseuri");
Unrelated to the concrete problem, as a word of advice, to transparently cover both http+ws and https+wss, consider using location.protocol
instead of a hardcoded wss
.
var ws = new WebSocket(location.protocol.replace("http", "ws") + "//" + location.host + baseURI + "Push");
Solution 2:
Is the following an option for you?
Define a hidden html-tag in the master template, something like :
<span id="pageContextPath" data="#{contextPath}" style="display:none;"></span>
Change your JavaScript Code to something like :
jQuery(document).ready(function ($) { if (window.WebSocket) { contextPath = $("#pageContextPath").attr("data"); var ws = newWebSocket("wss://" + document.location.host + contextPath + "/Push"); //... } else {} });
I used here jQuery. You may rewrite it in plain JavaScript. But it should be done after "document ready" to ensure that the hidden tag has been rendered. otherwise js won't find that element.
Post a Comment for "Get Rid Of Hard-coding The Context Path Of Web Apps In External Javascript Files"