To working my static file (CSS, JS) I have to write absolute path like /AppName/templates/style/main.css. Is there any solution, that I could write relative path like style/main.css?
If your actual concern is the dynamicness of the webapp context (the "AppName" part), then just retrieve it dynamically by HttpServletRequest#getContextPath().
<head>
<link rel="stylesheet" href="${pageContext.request.contextPath}/templates/style/main.css" />
<script src="${pageContext.request.contextPath}/templates/js/main.js"></script>
<script>var base = "${pageContext.request.contextPath}";</script>
</head>
<body>
link
</body>
If you want to set a base path for all relative links so that you don't need to repeat ${pageContext.request.contextPath} in every relative link, use the <base> tag. Here's an example with help of JSTL functions.
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
...
<head>
<c:set var="url">${pageContext.request.requestURL}</c:set>
<base href="${fn:substring(url, 0, fn:length(url) - fn:length(pageContext.request.requestURI))}${pageContext.request.contextPath}/" />
<link rel="stylesheet" href="templates/style/main.css" />
<script src="templates/js/main.js"></script>
<script>var base = document.getElementsByTagName("base")[0].href;</script>
</head>
<body>
link
</body>
This way every relative link (i.e. not starting with / or a scheme) will become relative to the <base>.
This is by the way not specifically related to Tomcat in any way. It's just related to HTTP/HTML basics. You would have the same problem in every other webserver.
See also:
Browser can't access/find relative resources like CSS, images and links when calling a Servlet which forwards to a JSP
Is it recommended to use the <base> html tag?
Just use <c:url>-tag with an application context relative path.
When the value parameter starts with an /, then the tag will treat it as an application relative url, and will add the application-name to the url.
Example:
jsp:
<c:url value="/templates/style/main.css" var="mainCssUrl" />`
<link rel="stylesheet" href="${mainCssUrl}" />
...
<c:url value="/home" var="homeUrl" />`
home link
will become this html, with an domain relative url:
<link rel="stylesheet" href="/AppName/templates/style/main.css" />
...
home link
You start tomcat from some directory - which is the $cwd for tomcat. You can specify any path relative to this $cwd.
suppose you have
home
- tomcat
|_bin
- cssStore
|_file.css
And suppose you start tomcat from ~/tomcat, using the command "bin/startup.sh".
~/tomcat becomes the home directory ($cwd) for tomcat
You can access "../cssStore/file.css" from class files in your servlet now
Hope that helps, - M.S.
Instead using entire link we can make as below (solution concerns jsp files)
With JSTL we can make it like:
To link resource like css, js:
<link rel="stylesheet" href="${pageContext.request.contextPath}/style/sample.css" />
<script src="${pageContext.request.contextPath}/js/sample.js"></script>
To simply make a link:
<a id=".." class=".." href="${pageContext.request.contextPath}/jsp/sample.jsp">....</a>
It's worth to get familiar with tags
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
There is also jsp method to do it like below, but better way like above:
<link rel="stylesheet" href="<%=request.getContextPath()%>/style/sample.css" />
<script type="text/javascript" src="<%=request.getContextPath()%>/js/sample.js"></script>
To simply make a link:
<a id=".." class=".." href="<%=request.getContextPath()%>/jsp/sample.jsp">....</a>
This could be done simpler:
<base href="${pageContext.request.contextPath}/"/>
All URL will be formed without unnecessary domain:port but with application context.
This is a derivative of #Ralph suggestion that I've been using. Add the c:url to the top of your JSP.
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:url value="/" var="root" />
Then just reference the root variable in your page:
<link rel="stylesheet" href="${root}templates/style/main.css">
Related
I have an Electron (1.7.10) application that is reporting it can't find 5 of 7 PNG files in my ASAR. All 7 PNGs are in the same folder, and 2 of them are displayed on screen fine. The other 5 report net::ERR_FILE_NOT_FOUND.
All src attributes for the img tags are dynamically generated and use relative paths (assets/images/MyImage.png). If I extract the ASAR, I can see the files in there, in the correct folder (as referenced by the src attribute).
If I use the console to set the location of my browser to one of the images (document.location.href = "file:///path/to/app.asar/dist/assets/images/MyImage.png") I get the same results - 2 of 7 show OK.
Before packaging my application (with electron-builder), all images show correctly.
Let me guess, you are building a react SPA using react-router, and BrowserRouter?
If so, use HashRouter instead. Electron does not work with SPA's route by default, because a SPA route changes, but the resource path is always relative to index.html.
I haven't evaluated the other answers, but for my particular case, an extremely solution worked. I don't believe this is well documented, so it might be fairly common for people to still encounter this issue. For my particulars, the relevant problem and solution were identified here.
To address, add <base href='./' /> to the index.html (or whatever your starting html file is that hosts your SPA). This is a complete example of mine:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<base href="./" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<meta
http-equiv="Content-Security-Policy"
content="script-src 'Self' 'unsafe-inline';"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
const path = require('path');
path.join(__dirname, 'assets/images/MyImage.png');
I'm using asp mvc, and I'm using the following code to generate the CSS html reference:
#Styles.Render("~/Content/css")
which generates the following html:
<link href="/Content/site.css" rel="stylesheet"/>
and that works fine. However, I need to add media type as an additional attribute. How can I go about using this style.render to add attributes to the generated html? Should I be thinking about making the change in the bundle config instead?
edit: I would like the end product to look like this:
<link href="/Content/site.css" rel="stylesheet" media="handheld"/>
You should be using #Styles.RenderFormat() for that:
#Styles.RenderFormat(#"<link href=""{0}""
rel=""stylesheet""
media=""handheld"" />",
"~/Content/css")
Try this
< link href="#Styles.Url("~/Content/css")" rel="stylesheet" type="text/css" media="handheld" />
may I know what's the difference between <body> and <g:layoutBody>, and how do I use these tags?
body tag is a HTML tag. (nothing to do with grails)
g:layoutBody should be used in templates to allow the concrete views to inject their data into the template.
Official documentation on g:layoutBody is quite helpful.
In particular, this is their example of a decorator layout a.k.a. main.gsp. In this example <g:layoutBody /> will be replaced with the body of the document to be decorated (e.g. index.gsp) and, of course, <g:layoutHead /> will be replaced with the head of the document to be decorated.
<html>
<head>
<script src="global.js" />
<g:layoutHead />
</head>
<body><g:layoutBody /></body>
</html>
By default Master pages in .NET MVC2 placed like this /folderlevel1/folderlevel2/Site.master accessed from the url domain.com/urllevel1/urllevel2/ will resolve the URL in this tag:
<link href="/Content/Site.css" rel="stylesheet" type="text/css" />
to
<link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
This becomes problematic in my multi-tennant MVC app. And I want to stop this behaviour. I want the master page to leave the url alone.
You are probably having this issue because ASP.NET performs magic tricks when you specify the head tag as a server side control like so:
<head runat="server">
These tricks include:
resolving relative CSS paths
populating title and meta tags from your view's #Page directive
If you don't want these tricks, simply remove the runat attribute from the head tag:
<%# Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
<!DOCTYPE html>
<html>
<head>
<link href="Content/Site.css" rel="stylesheet" type="text/css" />
</head>
<body>
...
</body>
</html>
you can use
<link href="<%=Url.Content("~/Content/Site.css")%>" rel="stylesheet" type="text/css" />
but that basically always translates to this:
<link href="/Content/Site.css" rel="stylesheet" type="text/css" />
so you might as well just use the latter.
Like mentioned on Kazi's best practices entry (http://weblogs.asp.net/rashid/archive/2009/04/03/asp-net-mvc-best-practices-part-2.aspx), ignore routing when accessing resources. To do this it's very simple and works well. Add the below to your AddRoutes function in Global.asax
_routes.IgnoreRoute("assets/{*pathInfo}");
...where "assets/" is your content folder (by default it's "Content")
oscar,
i'm sure there will be many similar answers to follow, but the standard way would be:
<link href="<%=Url.Content("~/Content/Site.css")%>" rel="stylesheet" type="text/css" />
I may have missed something subtle here of course :)
I suggest using an extension method for the HtmlHelper to take care of this task for you.
using System.Web;
using System.Web.Mvc;
namespace MyApplicationNamepsace.Views
{
public static class HtmlExtensions
{
public static IHtmlString RelativeCssLink(this HtmlHelper helper, string fileNameAndRelativePath)
{
TagBuilder builder = new TagBuilder("link");
builder.Attributes.Add("rel", "stylesheet");
builder.Attributes.Add("type", "text/css");
builder.Attributes.Add("href", fileNameAndRelativePath);
IHtmlString output = new HtmlString(builder.ToString());
return output;
}
}
}
Then make sure you add the namespace to the web.config file in the views folder.
<system.web>
<pages>
<namespaces>
<add namespace="MyApplicationNamespace.Views"/>
</namespaces>
</pages>
</system.web>
Then use it in your masterpage.
<head runat="server">
<title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
<%: Html.RelativeCssLink("Content/Site.css") %>
</head>
I've started to work a bit with master pages for an ASP.net mvc site and I've come across a question. When I link in a stylesheet on the master page it seems to update the path to the sheet correctly. That is in the code I have
<link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
but looking at the source once the page is fed to a browser I get
<link href="Content/Site.css" rel="stylesheet" type="text/css" />
which is perfect. However the same path translation doesn't seem to work for script files.
<script src="../../Content/menu.js" type="text/javascript"></script>
just comes out as the same thing. It still seems to work on a top level page but I suspect that is just the browser/web server correcting my error. Is there a way to get the src path to be globbed too?
<script src="<%= ResolveClientUrl("~/Content/menu.js") %>" type="text/javascript"></script>
Make an extension method. Here's a method:
public static string ResolveUrl(this HtmlHelper helper, string virtualUrl)
{
HttpContextBase ctx = helper.ViewContext.HttpContext;
string result = virtualUrl;
if (virtualUrl.StartsWith("~/"))
{
virtualUrl = virtualUrl.Remove(0, 2);
//get the site root
string siteRoot = ctx.Request.ApplicationPath;
if (!siteRoot.EndsWith("/"))
siteRoot += "/";
result = siteRoot + virtualUrl;
}
return result;
}
You can then write your script ref like:
<script type="text/javascript" src="<%= Html.ResolveUrl("~/Content/menu.js")%>"></script>
Use this instead:
<link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
or you can use BASE tag in you HEAD section of page. All you links then are relative to location entered in "base" tag, and you don't have to use "../../" and "~" stuff. Except links in CSS files (background url,etc), where links are relative to location of css file.