I am working on a simple website. It has to search quite a few text files in different sub-folders. The rest of the page uses jquery, so I would like to use it for this also. The function I am looking at is .get() for downloading the files. So my main question is, can I test this on my local computer (Ubuntu Linux) or do I have to have it uploaded to a server?
Also, if there's a better way to go about this, that would be nice to know. However, I'm more worried about getting it working.
Thanks,
Frankie
PS: Heres the JS/jQuery code for downloading the files to an array.
g_lists = new Array();
$(":checkbox").each(function(i){
if ($(this).attr("name") != "0")
{
var path = "../" + $(this).attr("name") + ".txt";
$("#bot").append("<br />" + path); // debug
$.get(path, function(data){
g_lists[i] = data;
$("#bot").html(data);
});
}
else
{
g_lists[i] = "";
}
});
Edit: Just a note about the path variable. I think it's correct, but I'm not 100% sure. I'm new to web development. Here's some examples it produces and the directory tree of the site. Maybe it will help, can't hurt.
.
├── include
│ ├── jquery.js
│ └── load.js
├── index.xhtml
├── style.css
└── txt
└── Scripting_Tools
├── Editors.txt
└── Other.txt
Examples of path:
../txt/Scripting_Tools/Editors.txt
../txt/Scripting_Tools/Other.txt
Well I'm a new user, so I can't "answer" my own question, so I'll just post it here:
After asking for help on a IRC chat channel specific to jQuery, I was told I could use this on a local host. To do this I installed Apache web server, and copied my site into it's directory. More information on setting it up can be found here: http://www.howtoforge.com/ubuntu_debian_lamp_server
Then to run the site I navigated my browser to "localhost" and everything works.
You could create a Titanium desktop app and wrap up your JS in there. Titanium seems to eliminate the cross-domain scripting issues when running JS from inside a packaged app.
Related
A brief introduction
First of all, I know, the question is often asked and I have read many discussion before asking.
Tipical approches to handle the cache problem that are suggested in other question are:
Versioning js files in this way: <script src="/myJavascript.js?version=4"></script>. See Keparo's answer here.
Create a rewrite rule on the web server in this way: RewriteRule ^(.*)\.[\d]{10}\.(css|js)$ $1.$2 [L]. See Kip's answer here.
Context description
Currently I'm refactoring my old php code running on apache2, introducing an heavy layer of js/jquery to handle the frontend and decoupling FE and BE building some api.
The js project is organized in this way:
my-project/
├── main.js
├── main.css
├── main.php
├── js/
│ ├── JsClass1.js
│ └── JsClass2.js
└── src/
└── php_code/
├── class1.php
└── class2.php
My problem
I don't know how to avoid that js classes are cached from web browser because the previous solution describer in the description are not feasible.
Just to make a brief example of my problem this is a portion of code that gives me problems:
main.js
//Import my js classes
import JsClass1 from './js/JsClass1.js';
import JsClass2 from './js/JsClass2.js';
//Instantiate js objects
const j1 = new JsClass1();
const j2 = new JsClass2();
//Use js object
j2.do_stuff();
j2.do_stuff();
JsClass1.js
import JsClassN from "./JsClassN.js";
export default class JsClass1 {
constructor(var1) {
//Create stuff
}
do_stuff() {
//Doing real stuff
}
}
main.php
<!DOCTYPE html>
<html lang='it-IT'>
<head>
<script type='module' src='/main.js?ver=<? echo getVersion(); ?>' type='text/javascript'></script>
</head>
<body>
...
</body>
Wrap up
How can I handle those js imports and avoid that browser caches old classes when I release in production new versions?
Do I need to reorganize my code structure to achieve this? And if so, what's the best approach?
I'm trying to embed a local asciinema session in html. here is my directory layout:
$ tree
.
├── asciinema
│ └── demo.cast
├── css
│ └── asciinema-player.css
├── index.html
├── js
│ └── asciinema-player.js
└── makefile
And here is my html file, just like it says in here:
$ cat index.html
<html>
<head>
<link rel="stylesheet" type="text/css" href="/css/asciinema-player.css" />
</head>
<body>
ABCDE
<asciinema-player src="/asciinema/demo.cast"></asciinema-player>
<script src="/js/asciinema-player.js"></script>
</body>
</html>
When I drag-and-drop this file to Mozilla, it only shows ABCDE
The main problem is that you're trying to run a script that uses XMLHttpRequest as a local HTML file in your browser. If you open your browser console, you'll see that it gives an error trying to find the files in all your src/href tags. You could fix that by removing the starting / from every src/href and the player would load, but then you'd run into problems with CORS when the script tries to load your cast file.
The solution would be to use an HTTP server to host your cast files, so you could reference them directly by their full server path, like http://localhost:3000/asciinema/demo.cast. Or you could just use an external URL for a cast file, providing the external website has no CORS enabled. Example:
<asciinema-player src="https://asciinema.org/a/28307.cast"></asciinema-player>
Now which HTTP server you choose is on you, there are many many really simple servers made in every programming language possible. If you're familiar with Node/JavaScript, then http-server would do. If you're familiar with Python then simplehttpserver would also do. Try whichever one you're comfortable with.
Another "solution" is to disable CORS in your browser. But then you're just risking yourself and that's also just a cheap hack.
TL;DR: you can't load local cast files within local HTML files because of CORS. You need to host your casts on a local or external HTTP server.
There is a workaround, though, if you really want to have it all local on your PC. And that is by embedding the asciicast file into the HTML page by inlining it into the src attribute. You can do that by converting the demo.cast file, which is a JSON file, into a single Base64 encoded line.
Convert the demo.cast file with base64 -w 0 demo.cast. You will need to capture that output somehow so you can then paste it into the HTML file. For example pipe it into a text file, or directly append it at the end of the HTML file and then work the rest of the HTML around it.
Then write your asciinema-player line like so:
<asciinema-player src="data:application/json;base64,BASE_64_ENCODED_STRING_HERE" />
For example:
<asciinema-player src="data:application/json;base64,eyJ2ZXJzaW9uIjogMiwgIndpZHRoIjogMTQwL" />
I really like the folder structure as can be seen here when dealing with a React frontend and a some backend with express:
root
├── backend
| ├── node_modules
| ├── public
| ├── src
│ │ └── Server.ts
| ├── package.json
| └── tsconfig.json
├── frontend (created using create-react-app)
| ├── node_modules
| ├── public
| ├── src
│ │ └── Index.js
| ├── package.json
| └── tsconfig.json
I think that having separate packages with individual node_modules is reasonable since the frontend and backend are basically completely different things, e. g. they need different node modules. Also, this modular approach is visually appealing to me and the repository looks tidy.
However, I encounter a problem with this structure when I need to share content between the frontend and the backend. I added a shared folder under the root-of-project which contains its own project with its own tsconfig.json, package.json and so on. This approach is a mix of the approaches here and here. For the backend, this works totally fine: having set up the tsconfig.json appropriately (using TypeScript Project References and aliased imports), I can reference the file root/shared/src/myFile.ts like this:
import { myFunction } from #shared/myFile;
I created the React frontend using create-react-app. It's ok for me that alias imports don't work, so I would have to use (inside the src folder in frontend):
import { myFunction } from '../../shared/src/myFile';
Sadly, these imports from outside the src directory are not supported by create-react-app and I don't want to use eject since I have no experience with webpack and don't want to maintain all the configuration files on my own (that's why I used create-react-app in the first place).
I know I can move the shared content to the frontend's src directory. But this would mean, I had to add the tags needed for using Project References in TypeScript, e. g. setting composite to true, in the frontend's tsconfig.json which seems odd to me and feels more like a hack. I'd like to have a separate npm project with my shared content.
Since create-react-app does not inherently support imports from outside the src directory, I thought that maybe I'm getting the big picture wrong. Isn't the folder structure I use right now a valid way of how to setup a React project with a backend? What mechanism does create-react-app provide to link files between the frontend and the backend? I could also think of having a root project with a src folder and inside of that the two folders backend and frontend. But this means, that we'd have one shared node_modules folder in root.
It's my first project with React and I'd love to get to know some best practicese for this kind of architectural problem. Some links to trustful resources where project structures for full-stack React development are explained would be really helpful. Thank you 😊
It's perfectly reasonable to want to share code between your front and back end. It's one of the reasons to code in javascript instead of Ruby or PHP.
You can accomplish exactly what you want by using yarn instead of npm and yarn workspaces: https://yarnpkg.com/lang/en/docs/workspaces/. At the top level you set up three modules/packages in your package.json (make sure you name the workspaces correctly in their respective package.json files):
"workspaces": {
"packages": [
"backend",
"frontend",
"shared"
]
},
Once you do, you can import shared code in your CRA app or your back end simply like this:
import { myFunction } from 'shared/src/myFile';
The drawback is that you can't import react components from the shared directory into frontend as long as you are using CRA. This won't affect you now since you only have one react app. Should you need to share react components among multiple projects, look into some on the suggestions above like bit.dev.
ADDENDUM!!! It's now possible to use CRA and yarn workspaces to share React code, if you replace CRA with CRACO. All you do is create another workspace with the shared react code. Then create a symbolic link in each module where you want to access it:
root
├── fontend-one
| ├── symbolic link to frontend-shared
├── frontend-two
| ├── symbolic link to frontend-shared
├── frontend-shared
Each of the CRA front end modules modules also requires a craco.config.js file where you tell web-pack not to follow symbolic links:
module.exports = {
// ...
webpack: {
configure: {
resolve: {
symlinks: false
}
}
}
};
You import from shared-frontend normally:
import { myFunction } from 'shared-frontend/src/myFile';
It's a pretty lo-fi solution but has proven robust for the year we've been using it.
Architecture is a tricky one, everyone has a different opinion and every option has pro and cons.
Personally I believe its best to separate the backend and frontend into sperate projects and keep them that way. Now as JavaScript/React/Node encourage component-based approaches a really nice way of sharing code between them is Bit.dev.
https://bit.dev
I am currently using it to share components and functions between three web apps and a few Node microservices.
A good structure for React app can be found here, this one works well and scales nicely:
https://hackernoon.com/fractal-a-react-app-structure-for-infinite-scale-4dab943092af
As for Express, there are so many ways to structure the project but personally recommend a folder for your Routes, a folder for your Controllers, this is where the logic for Routes live. Then go from there. Check this link out:
https://www.freecodecamp.org/news/how-to-write-a-production-ready-node-and-express-app-f214f0b17d8c/
Depending on what your building you may not even need a full backend you can check out the JAMStack here for more info:
https://jamstack.org
I would consider separating them though as the project scales it makes it much easier to manage. You can release your front end on something like Netlify and then use something like AWS or Azure to host your Node/Express server.
Having separate sub-projects for frontend and backend makes perfect sense due to vastly different dependencies. Mixing it up increases disk space consumption in production deployments and goes against security guidelines. Your folder structure is reasonable (except for public/ subfolders I'm unsure about, maybe I'm missing something).
The approach import { myFunction } from #shared/myFile; is fine. Just don't use CRA.
For a project with a single frontend and a single backend there is no need for a shared\ top-level folder because the frontend is the only source of 'UI truth' (e.g. the source of types and components related to UI) that is consumed by the frontend and the backend is the only source of 'API truth' consumed by both frontend and backend. With this arrangement only #backend/api_shared_stuff needs to be shared.
Some links to trustful resources where project structures for full-stack React development are explained would be really helpful. On the one hand, usually project authors have to explain plenty of other things and on the other hand keep the documentation (typically a README) reasonably concise. You may find that providing a justification/explanation why the subdirectory structure is this and not that was not the top priority.
I'm currently working on developing some set of codes to display all blobs inside specified Azure Container using web front-end. I'm expecting the final output to be something like this:
I started by creating a dummy storage account and populates it with some dummy files for me to play around with.
https://alicebob.blob.core.windows.net/documents
├── docx
│ ├── 201801_Discussion.docx
│ ├── 201802_Discussion.docx
├── xlsx
│ ├── 201801_Summary.xlsx
│ ├── 201802_Summary.xlsx
│ ├── 201803_Summary.xlsx
├── 201801_Review.pdf
├── 201802_Review.pdf
├── 201803_Review.pdf
To develop file listing function, I'm using Azure Storage JavaScript client library from here and put all the necessary codes (.html and .js files) in Azure Static website $web container and set index.html as Index document name and Error document path in the Static website configuration.
https://alicebob.z23.web.core.windows.net/
├── azure-storage.blob.min.js
├── azure-storage.common.min.js
├── index.html
The problem is that the function to do the listing is only either listBlobsSegmentedWithPrefix or listBlobDirectoriesSegmentedWithPrefix. So, in my case, I assume it wouldn't work straightforwardly to list all the blobs and directories in a well-structured / tree format.
My current approach is that I trick the code to keep using listBlobDirectoriesSegmentedWithPrefix until there is no more directory to list inside, then continue to list using listBlobsSegmentedWithPrefix
So far I'm quite satisfied that my code can list all the Blobs at the leaf-level and also list all the directories if it isn't on the leaf-level. You can take a look at the blob listing here and feel free to go for 'View Source' to see the codes I built so far.
The only problem that I face is that this set of code fails to list the Blobs if it wasn't on the leaf-level. For example, it fails to list these blobs on alicebob storage account:
├── 201801_Review.pdf
├── 201802_Review.pdf
├── 201803_Review.pdf
This is an expected issue as I'm not running listBlobsSegmentedWithPrefix if it isn't on the leaf-level. The reason is that it will produces the output with something like this which isn't what I want:
├── docx/201801_Discussion.docx
├── docx/201802_Discussion.docx
├── xlsx/201801_Summary.xlsx
├── xlsx/201802_Summary.xlsx
├── xlsx/201803_Summary.xlsx
├── 201801_Review.pdf
├── 201802_Review.pdf
├── 201803_Review.pdf
Any suggestion on how to overcome this issue? The real implementation would involves a huge amount of data so I think a simple if-then-else wouldn't be efficient on this case.
sorry for the long description but I just want to describe my problem as clear as possible :)
There's an option called delimiter when listing blobs. Let's get down to code.
blobService.listBlobsSegmentedWithPrefix('documents',null,null,{delimiter:'/'},(error,result,response)=>{
console.log(result);
console.log(response.body.EnumerationResults.Blobs.BlobPrefix);
})
With delimiter /, listing operation returns results of two parts.
result, contains info of blobs under the root directory of container, e.g. 201801_Review.pdf, etc. in your case.
BlobPrefix in response body, contains directory names of single level with delimiter.
[ { Name: 'docx/' }, { Name: 'xlsx/' } ]
Use BlobPrefix as prefix, we can continue listing content of current subdirectory.
blobService.listBlobsSegmentedWithPrefix('documents','docx/',null,{delimiter:'/'},(error,result,response)=>{
console.log(result);
console.log(response.body.EnumerationResults.Blobs.BlobPrefix);
})
Basically point 1 result is enough, you don't necessarily have to use BlobPrefix to refactor your code. See more info in section Using a Delimiter to Traverse the Blob Namespace of list blobs.
You can also do this with out the overhead of the whole storage api using a fetch request as follows.
fetch("https://cvworkshop.blob.core.windows.net/telaviv-bw/?restype=container&comp=list")
.then(response => response.text())
.then(str => new window.DOMParser().parseFromString(str, "text/xml"))
.then(data => console.log(data));
I've installed Jetty using homebrew on osx. Jetty is in the usual folder:
/usr/local/Cellar/jetty/9.4.5.v20170502
However, we are not going to use this for anything related to Java. It's just our requirement that the web server we will have in production is Websphere. Our code is pure html and some JS. Only static files. All the tutorials on the web require modifying XML files and setting up complex folder structures for java apps. We do not need any of this. All we want is to put html/js files in some specific place.
Is there an easy way to do this? Do we have to create a start.jar for this simple task? How do we create a WAR package via Maven or something else? Would appreciate any simple pointer to getting this dev environment set up. Thank you!
It seems you might be overthinking this a bit. start.jar is merely the JAR file that starts up the sever. You can easily host static content out of Jetty. I am unsure of your specific requirements, but for the sake of an example, I will just assume you have a simple webapp with a page and some resources. Your implementation might look like this.
Inside the Jetty 9.4.5.v20170502 directory - Also called Jetty_Home (you can learn about Jetty_Home vs Jetty_Base here), you'll find the following directories:
bin demo-base etc lib logs modules resources webapps
These are the standard of truth and should not be modified (though demo-base can be removed entirely if desired). You will want to create your own Jetty_Base directory to host your content out of, let's call it stackoverflow for this example. It is worth noting that a Jetty_Base can exist anywhere, I am just keeping it here for ease of this example.
Inside the stackoverflow directory you'll find nothing to start with, so we will need to enable some modules to populate our Jetty_Base. Now, I have no idea what all you plan to do with this webserver, so I will keep it minimal - enough to host the content. From inside this directory run:
> java -jar ../start.jar --create-startd
MKDIR : ${jetty.base}/start.d
INFO : Base directory was modified
This will create a start.d directory for all of our module files to live in, which makes modifying and configuring things a breeze (though for the sake of this example everything will be left default). Now we need to add the modules which will enable the functionality on the server. You can view a whole list of available modules by running:
> java -jar ../start.jar --list-modules
I am not going to paste the whole list here but instead enable the following:
> java -jar ../start.jar --add-to-start=server,client,deploy,http,webapp,jsp
INFO : webapp initialized in ${jetty.base}/start.d/webapp.ini
INFO : server initialized in ${jetty.base}/start.d/server.ini
INFO : security transitively enabled
INFO : apache-jsp transitively enabled
INFO : servlet transitively enabled
INFO : jsp initialized in ${jetty.base}/start.d/jsp.ini
INFO : jndi transitively enabled
INFO : client initialized in ${jetty.base}/start.d/client.ini
INFO : http initialized in ${jetty.base}/start.d/http.ini
INFO : annotations transitively enabled
INFO : plus transitively enabled
INFO : deploy initialized in ${jetty.base}/start.d/deploy.ini
MKDIR : ${jetty.base}/webapps
INFO : Base directory was modified
This will enable all the modules I defined (server,client,deploy,http,webapp,jsp) as well as any dependencies required for them to operate and any required folders (such as webapps).
Now, I created a very small webapp named example. I've gone ahead and moved it into the webapps directory inside our stackoverflow Jetty_Base:
> tree
.
├── start.d
│ ├── client.ini
│ ├── deploy.ini
│ ├── http.ini
│ ├── jsp.ini
│ ├── server.ini
│ └── webapp.ini
└── webapps
├── example
│ ├── images
│ │ ├── jetty-header.jpg
│ │ └── webtide_logo.jpg
│ ├── index.html
│ └── jetty.css
└── example.xml
I have a context xml file I created for this webapp named example.xml, which is only serving static content, and it is very simple:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure id="exampleApp" class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/example</Set>
<Set name="war"><Property name="jetty.webapps" default="."/>/example</Set>
</Configure>
This configures the webapp so that when I run the server I can navigate to, in this case, localhost:8080/example and see my content. Now all I have to do is run my server. From inside the stackoverflow directory:
java -jar ../start.jar
2017-06-08 10:36:32.300:INFO::main: Logging initialized #427ms to org.eclipse.jetty.util.log.StdErrLog
2017-06-08 10:36:32.477:INFO:oejs.Server:main: jetty-9.4.5.v20170502
2017-06-08 10:36:32.494:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:///Users/example/installs/repository/jetty-distribution-9.4.5.v20170502/stackoverflow/webapps/] at interval 1
2017-06-08 10:36:32.633:INFO:oeja.AnnotationConfiguration:main: Scanning elapsed time=26ms
2017-06-08 10:36:32.668:INFO:oejs.session:main: DefaultSessionIdManager workerName=node0
2017-06-08 10:36:32.668:INFO:oejs.session:main: No SessionScavenger set, using defaults
2017-06-08 10:36:32.669:INFO:oejs.session:main: Scavenging every 600000ms
2017-06-08 10:36:32.692:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext#6e06451e{/example,file:///Users/example/installs/repository/jetty-distribution-9.4.5.v20170502/stackoverflow/webapps/example/,AVAILABLE}{/example}
2017-06-08 10:36:32.713:INFO:oejs.AbstractConnector:main: Started ServerConnector#21a947fe{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
2017-06-08 10:36:32.714:INFO:oejs.Server:main: Started #840ms
And now you have a server up and running and content being served. I hope this helps. It can seem overwhelming at first, but it isn't so bad once your get your hands dirty. I recommend reading up more at the official documentation.