How to manage file path when accessing from different directory location? - html

I have few web pages sitting in different directories and my goal is to have some sort of organized structure so that I can access to js or css files without hardcoding the path.
For instance, the directory structure is:
root --- js --- some.js
|
|--css --- some.css
|
|---pages ---- main.jsp
|
|---other----foo---- foo.jsp
|
|--bar --- bar.jsp
Then main.jsp and foo.jsp tries to reference some.js but has to have different path.
( main.jsp )
<script type="text/javascript" src="../js/some.js"></script>
( foo.jsp)
<script type="text/javascript" src="../../js/some.js"></script>
This is not ideal if I want to change the location of main.jsp or foo.jsp, I have to come back to each files and change the path manually.
I am thinking to have factory class that has full path for each files so that it would look something like:
<script type="text/javascript" src=<% Factory.getFullPath(some.js) %> ></script>
In this case, I can still move files freely and not have to come back to each file.
Can I get some opinion to my approach? Is there other way to solve this?

Use a context-relative path. It will make the path absolute to the domain root. You can obtain the context path by HttpServletRequest#getContextPath(). In JSP, the HttpServletRequest is available by ${pageContext.request}.
<script type="text/javascript" src="${pageContext.request.contextPath}/js/some.js"></script>
(the contextPath itself already starts with a /, so you don't need to prefix it yourself)
You can also set it using the HTML <base> tag so that every relative URL in the page becomes relative to it. This way you don't need to copy ${pageContext.request.contextPath} over all the place.
<base href="${pageContext.request.contextPath}"></base>
<script type="text/javascript" src="js/some.js"></script>
This has however one caveat: anchors, like <a href="#foo"> will also become relative to it. You need to take this into account as well if you go for this.
See also:
Is is recommended to use <base> tag in HTML?

mm i'm not really sure if a factory is the most appropriate way to do this, maybe it will work.. i remember that for that i used an interface where i implemented some constants including the JS and CSS folder path
public interface Configuration {
public static final String SERVER_URL = "http://localhost:8080/";
public static final String CSS_URL = SERVER_URL + "css/";
public static final String JS_URL = SERVER_URL + "js/";
}
and then i'd have to import this interface in the servlet and call it like this:
...src="<% Configuration.JS_URL %>some.js" />..
that way if you change your folders name or path. you'll only have to change the configuration

Related

A method to get specific exports when using <script src="">

I'm making a site with Preact & Tailwind. In the code here (I know it doesn't have head, body, e.t,c but that isn't relevant to the code):
<script src="https://unpkg.com/tailwindcss-jit-cdn"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/preact/10.11.2/preact.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/htm/3.1.1/htm.js"></script>
<script>
htm.bind(h)
let component = htm`<p>Hello World</p>`
</script>
htm and h are parts of the Preact and HTM cdn. How do I get htm and h from the preact/htm cdns?
I don't want to use a node_modules, as i want it to be a copypastable template html to use anywhere, like WordPress, replit, codepen, e.t.c. I also don't want to use as the way my code is setup it would look weird and bad to read.
Adding a dependency (or dependencies) via <script> adds those to the global scope. h, in the example above, is undefined as you have not specified where it comes from.
<script src="https://unpkg.com/tailwindcss-jit-cdn"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/preact/10.11.2/preact.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/htm/3.1.1/htm.js"></script>
<script>
let html = htm.bind(preact.h)
let component = html`<p>Hello World</p>`
</script>
(Adjusted code, as htm.bind alone will not work. Need to assign & use the result).
This, however, is less than ideal in the modern age of ESM. Messing with globals is just rather unnecessary. Instead, use the following:
<script src="https://unpkg.com/tailwindcss-jit-cdn"></script>
<script type="module">
import { h } from 'https://cdn.skypack.dev/preact';
import htm from 'https://cdn.skypack.dev/htm';
let html = htm.bind(h);
let component = html`<p>Hello World</p>`;
</script>
Or, even better yet, use htm/preact export to skip manually binding altogether:
<script src="https://unpkg.com/tailwindcss-jit-cdn"></script>
<script type="module">
import { html } from 'https://cdn.skypack.dev/htm/preact';
let component = html`<p>Hello World</p>`;
</script>
Unpkg has a number of issues (very difficult to fix, if not impossible. Not a criticism, unpkg was built in a different time) regarding ESM usage, specifically for Preact, resolving package.json "exports" and sometimes duping the Preact instance. This is an issue for hooks, as they require a singleton by design. This is why I'd recommend Skypack or esm.sh. They're built for ESM and work brilliantly.

Update html file content

I worked on a little startpage for my browser. Now I would like to make some changes to it, so it updates the index.html file depending on a text file, when this got changed. What whould be an efficiant way to solve this problem?
My approach would be to create a text file and read line by line from it and update the html file. In the text file I would store the links shown on my startpage - I thought maybe something like this:
|cat_media
https://mailbox.org,mail
https://netflix.com,netflix
...
http://crunchyroll.com,crunchy
https://jott-uh-be.bandcamp.com,bc
|cat_social
https://pr0gramm.com,pr0
https://stackoverflow.com,stackoverflow
https://twitter.com,twitter
https://instagram.com,insta
When the line starts with the symbol |, it creates a new <div> with the class category and the string in that line (e.G. class= 'category cat_media'). Otherwise, if the line starts with http, it will add a href-link (e.G. <a href='https://mailbox.org'>mail</a>) to the html-code.
I got this website hosted on my raspberry pi with nginx and uploaded it to my github pages.
You don't have to update the index.html file.
You can create dynamic content.
You can use PHP:
You can learn it here:
https://www.w3schools.com/php/default.asp
And here is how to read a file
http://php.net/manual/en/function.fread.php
Or if you cant use PHP you can use Javascript:
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$(() => {
$.ajax({
url:'your-config-file.xt',
success: function (data){
console.log(data); //this is the config file. just for loop it and modify the dom
}
});
});
</script>
But your config file must contains the string how the links should be shown.
For example:
|catergory one
yt: https://www.youtube.com

Use an image from public folder

I'm trying to set as background an image located at /public/images/my-image.jpg
I've tried
<body background="public/images/my-image.jpg">
and
<body background="images/my-image.jpg">
and
<body background="my-image.jpg">
But I always get 404 (Not Found) on the Chrome console. Any idea why?
I also tried adding this:
<style>
body {
background-image: url("/public/images/my-image.jpg");
}
</style>
But nothing appears in the background of the page.
You need to have a record in the routes file
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
Then you can access the files in the public folder with the twirl helper:
<body background="#routes.Assets.versioned("images/my-image.jpg")">
It would be compiled to
<body background="/assets/images/my-image.jpg")">
You can put it as static text as well.
If you want to change "assets" to "public" or whatever, just change it in the routes file:
GET /public/*file controllers.Assets.versioned(path="/public", file: Asset)
Then your assets would be accessible by the public path, like:
<body background="/public/images/my-image.jpg")">
Still, the #routes.Assets.versioned would be the same:
<body background="#routes.Assets.versioned("images/my-image.jpg")">
This is the reason why #routes.Assets.versioned is preferable way.
As I understand it, you've got a problems obtaining assets in playframework.
Follow the documentation for play framework for assets.
To obtain assets from public directory (if you haven't change the default routes or assets controller), you need to use path with assets/ instead of public/.
Or more preferable using reverse router. In play 2.5x in your case it would be:
<body background="#routes.Assets.versioned("images/my-image.jpg")">
using reverse routing or
<body background="assets/images/my-image.jpg">
with hard coded path.
I think it is not supported anymore in HTML5, try to use css like body {
background-image: url("gradient_bg.png");
}
font: https://www.w3schools.com/tags/att_body_background.asp

How to separate html text file into multiple files?

Very basic question about html.
Because the <body> is too long, I want to divide the file into multiple files. It is not about using iframe etc, but just want to include multiple text files to create <body> of the html file.
Thank you!
You can do it using jQuery:
<head>
<script src="jquery.js"></script>
<script>
$(function(){
$("#ContentToInclude").load("b.txt or b.html");
});
</script>
</head>
And load it in HTML:
<body>
<div id="ContentToInclude"></div>
</body>
Just change the extension to .php instead of .html. Then you can just put, for example, your whole head inside the file head.php( or head.inc).
The whole thing would look something like this then:
<!DOCTYPE html>
<?php
include 'head.php';
?>
<body>
<!-- stuff in here -->
</body>
<html>
You can obviously split your body up into seperate pieces like this:
<body>
<?php
include 'firstPart.php';
?>
<!-- some other stuff -->
</body>
You can easily break your code in multiple files, Then create one file with .php extension and include them all!
With only HTML it would not be possible you need to add some JavaScript to be able to do so.
Using a data attribute with the Fetch API and some async functions you could do it as follow:
HTML file:
<div data-src="./PATH/filename.html"></div>
This element will receive as HTML content the content of the file specified in its data-src attribute.
Now the JavaScript:
async function getFileContentAsText(file) {
const response = await fetch(file);
const fileContent = await response.text();
return fileContent;
}
async function insertContentsFromFiles() {
const tbl = document.querySelectorAll('[data-src]'); // get elements with the data attribute "data-src"
for (var i=0; i < tbl.length; i++) // loop over the elements contained in tbl
tbl[i].innerHTML = await getFileContentAsText(tbl[i].dataset.src);
}
// dont forget to call the function to insert the files content into the elements
insertContentsFromFiles();
When the insertContentsFromFiles() method will be called it will first retrieve all the elements that have the data attribute data-src then we loop over these elements using their data-src value with the getFileContentAsText() method to affect their innerHTML property as the content of the file specified in the data attribute.
As we are using querySelectorAll() to get the elements with the data-src attribute the above JavaScript code will work for an unlimited amount of elements as long as they have that data attribute.
Note: In its current state the above JavaScript code is not optimized for loading a big amount of files as it process the files to be loaded one by one. If you are interested in solving this issue you may want to use promise.all() and update the insertContentsFromFiles() method to parallelize the files loading by taking advantage of the asynchronous operations.
Warning: If you plan to use elements that are in the loaded files from JavaScript you will have to retrieve them after they have been loaded into the page otherwise they will have an undefined value. To do so you can dispatch an event when a file has been loaded so you can attach specific functionnalities to the page based on the triggered events.

Read the contents of a link or script tag using src/href

How can I read the contents of a file using
<link href='path/to/file'/>
I understand that if one adds the attribute type="text/css" then they can be read using document.styleSheets but I have a hard time figuring out how to get the content of that element though.
I understand that lesscss.js lib uses the without an ajax get call.
From: http://lesscss.org/#using-less
<link rel="stylesheet/less" type="text/css" href="styles.less" />
<script src="less.js" type="text/javascript"></script>
I need to include some templates into the page, and the sooner they are loaded the better, ( vs doing it after jquery and js has loaded)
Thanks!
I understand what you mean with before jquery. But what do you mean with "before js".
When you load less.js (which does NOT depend on jQuery) the browser runs less.js before jquery has been initialized. Notice that less.js requires JavaScript.
You can read the content of such a file leveraging a XMLHttpRequest. A basis example which shows you how to do this can be found at: How to show the compiled css from a .less file in the browser?
Regarding less.js, you can find the source of that file at: https://github.com/less/less.js/blob/master/dist/less-1.7.4.js
I understand that if one adds the attribute type="text/css" then they can be read using document.styleSheets but I have a hard time figuring out how to get the content of that element though.
Globally less.js uses two steps to do that:
first it will built a list of paths as follows:
//
// Get all <link> tags with the 'rel' attribute set to "stylesheet/less"
//
var links = document.getElementsByTagName('link');
less.sheets = [];
for (var i = 0; i < links.length; i++) {
if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) &&
(links[i].type.match(typePattern)))) {
less.sheets.push(links[i]);
}
}
Then reads the content of these files by using a XMLHttpRequest too. See the doXHR function at line 7720 of less-1.7.4.js.