I have a problem with Javascript that keeps bugging me for quite a while now. I have an external file called search.js which is in the same folder as the .html file it's loaded into.
The piece of code I use in th HTML to load the javascript file is:
<script type="text/javascript" src="search.js"></script>
From all the websites I've read I can't find an issue here with the code.
Also, I know that the syntax in the javascript file has to be correct in order for it to work, so here is my Javascript code from search.js:
$(document).ready(function(){
$('#searchForm').submit(function(){
var lookfor = $("#billSearched").val();
alert(lookfor);
var a = $(this).attr('action');
alert(a);
a = a.replace("__search_term__",lookfor);
alert(a);
window.location.href = a;
return false;
});
});
I've runned this code in another project and it has worked just fine, all that I've changed was the names of the fields, i.e. billSearched.
If there are any other reasons for why Javascript doesn't load in my page please leave a message or a comment.
Thanks in advance!
EDIT
Full html code:
<html>
<head>
<title>Bills</title>
<script type="text/javascript" src="/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="/search.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body bgcolor="#0066CC" color="FFFFFF">
<table>
<tr>
<td style="color:white"><b>Products</b></td>
<td style="color:white">Price</td>
<form method="POST" id="searchForm" action="{% url ps.views.search searchTerm='__search_term__' %}">
{% csrf_token %}
<td><input type="text" id="billSearched"></td>
<td><input type="submit" value="Search"></td>
</form>
</tr>
{% for x in products %}
<tr>
<td style="color:white">{{ x.name }}</td>
<td style="color:white">{{ x.price }}</td>
</tr>
{% endfor %}
</tr>
</table>
</body>
From the tags and your template code, I gather that you are using Django. To understand your issue, you'll have to understand how Django views work relative to your browser, and what happens when your browser issues a request for a given url.
What happens on the Django side:
What happens when you request an url is that your base urls.py file will be searched for pattern matching your url. If a pattern is encountered, then the corresponding view will be called.
The viewwill carry out its logic, and will use a template to render its response into html.
What happens from your browser's point of view
The browser requested an url, and received a response, it is not aware of the fact that a view was called, and that it fetched a template somewhere.
What this means to you
The fact that your search.js file is located next to your template is totally irrelevant, as your browser never requested any file from this directory, it's the view that did, when it fetched its template.
Actually, your browser's request for search.js will be forwarded to Django by your webserver and will (most likely) result in a 404 error, unless search.js resolves to a view in your urls.py.
How you can use this to solve your issue
You'll need to serve your search.js file from a directory that can be accessed by the browser. Usually, this is done in three steps:
Configure your webserver so that it serves any path starting with /static/ on its own (somehow, this means not forwarding the request to Django).
In Apache, you'd use the following rule: Alias /static/ /YOUR/STATIC/DIRECTORY/
Configure Django's settings.py to use /YOUR/STATIC/DIR as STATIC_ROOT, and /static/ as STATIC_URL.
Put your search.js file in your /YOUR/STATIC/DIR/
Use src="/static/search.js to reference your file in your html template.
One last thing: if you're using the development server, you might need to ensure your STATIC_URL starts with the full path to your server, including the port. (Or you might have issues with browser security policies).
A few additions:
Your should be using template tags so that you don't have to write /static/ in your template.
You should be using manage.py collectstatic to autimatically put static files in your static directory.
Most importantly, you should investigate what Django's MVC (or MTV) model is about.
Paths prefixed with / points to the root - not the current folder. In this case you want to drop the / prefix.
Your HTML files at project/ps/templates/bill.html which links a JS script /search.js means it's looking for the files in the completely wrong location.
For instance, you can see how it resolves the path if you add a link to /search.js in your HTML.
For illustrative purposes, create an HTML file on your desktop:
<html>
<body>
Hello
World
</body>
</html>
When you hover over the link you will see that Hello it resolves to file:///foobar.txt and World resolves to the path to your desktop - in my case file:///C:/Users/thm.ARC/Desktop/foobar.txt.
I had to make a mix of your answers in order to fix the problem but eventually it was fixed. I had to make the following modifications:
Add the '/static/' folder to STATIC_URL and STATICFILES_DIRS in the settings.py file
Import the .js files (search.js and the jQuery source) with the following commands, in this order:
<script type="text/javascript" src="/static/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="/static/search.js"></script>
And make the according file structure, placing the "static" file in the project's root directory.
i.e.
Psroot:
psApp
static
templates
and the rest of the files (settings.py, urls.py, manage.py, etc.)
Related
I'm trying to get a html page to run a js script from the static files of the host using Flask (as it's a test project it's a localhost) and for some reason every script comes back as a 404 - I'm using this file structure
¬static
¬html
¬user.html
¬js
¬script.js
https://i.stack.imgur.com/vIXzr.png
I've followed as many guides and other queries on fixing this but I don't get what else I'm missing. I've used <script src="js/script.js"></script> to call it, I've used src="{{url_for('static', filename='js/script.js') }}" in place of src="js/script.js, I've tried using just script.js instead of js/script.js, I've tried putting it in different places in the file tree and using as many ways as I can think of to call it from these places, I've downloaded plugins, I looked at official sites explaining how to create html and js and etcetera... Can't get anything to work
EDIT - solved, for some reason clearing my cache for the 2000th time fixed it. Copied the project to another device, same problem, fixed it by replacing js/script.js with static/js/script.js. That doesn't seem like that's how it should be but it works I guess
Static content in Flask loaded as follows:
<script src="{{ url_for('static', filename='js/script.js') }}"></script>
But in this case your html-template should be located in separate folder:
static
--js
scripts.js
templates
user.html
Folder templates is the default place where all html-templates are located in Flask.
In media/json I have JSON files and I want to read them with a JavaScript file which is in static/js without hardcoding. How can I do it?
Assuming you mean how to get the JSON through an AJAX or similar mechanism which the JavaScript in question will deal with, then you probably want JsonResponse and a simple view that starts at an URL on your server and returns the JSON in question. The script will be loaded in some other view using a <script src="http://wherever" /> tag. In a template you'll probably use <script src="{% static "js/scriptname" %} /> See managing static files
It's not clear what you mean "without hardcoding". The view can receive arguments through its URL and serve up the JSON that these arguments dictate.
I have a more complicate question but I'm trying to isolate the problem to avoid confusion.
I'm testing a page using selenium. In this page there are two javascript external scripts. If you go there manually the page is working correctly but using selenium one of the javascript isn't loaded:
The script from “http://localhost:55234/static/js/common.js” was loaded even though its MIME type (“text/html”) is not a valid JavaScript MIME type.
2 add-name
Loading failed for the <script> with source “http://localhost:55234/static/js/common.js”.
Checking the source (right click => view page source) gives me correctly the template with this two lines (and the others, off course):
[...]
<!-- load global javascript -->
<script type='text/javascript' src="/static/js/common.js"></script>
<!-- load app javascript -->
<script type='text/javascript' src="/static/lists/js/lists.js"></script>
[...]
the src are clickable. Cliking the first one reload the source page without the line three and four, so without this lines:
<!-- load app javascript -->
<script type='text/javascript' src="/static/lists/js/lists.js"></script>
Clicking the second one (lists.js) gives the javascript code. But! But this code looks an (very) old version of my code. Many days old (isn't too long to be cached?). At that time all the code was in one javascript file (lists.js) and the other one (common.js) didn't existed so this can explain why isn't loaded.
Why is that? How can I update this code? If I go manually in the page I can find the real updated code.
Also can be useful to know that in my browser I recently selected 'Disable cache' in the Network tab (press F12 with firefox) and 'Disable HTTP cache (...)' in the setting just to avoid these problems. In the page opened by selenium these options are both unchecked. I tried to check both (using a breakpoint()) and reload the page but nothing changed.
I repeat, maybe the cause of this is somewhere else and there many other thing to say but I think is better to keeps things as simple as possible and open other questions when I need. Now, any of this make any sense? why my script isn't updated in days (I prefer to do not empty the cache, if possible)?
I found this code to delete the cache, should I try? It look right?
def setUp(self):
profile = webdriver.FirefoxProfile()
profile.set_preference("browser.cache.disk.enable", False)
profile.set_preference("browser.cache.memory.enable", False)
profile.set_preference("browser.cache.offline.enable", False)
profile.set_preference("network.http.use-cache", False)
self.browser = webdriver.Firefox(profile)
Here some code:
My template base.html:
[...]
<head>
[...]
<!-- load global javascript -->
<script type='text/javascript' src="{% static '/js/common.js' %}"></script>
<!-- load app javascript -->
{% block script %}{% endblock %}
[...]
my template list.html
{% block script %}
<script type='text/javascript' src="{% static 'lists/js/lists.js' %}"></script>
{% endblock %}
where common.js is in myproject/static/js/common.js, while lists.js is in myproject/lists/static/lists/js/lists.js. I call both with {% static but it should be correct.
My test.py:
class NameFormSeleniumTest(LiveServerTestCase):
def setUp(self):
self.browser = webdriver.Firefox()
self.browser.implicitly_wait(2)
def tearDown(self):
self.browser.quit()
def test_form_can_save_a_name(self):
# some code
# english = ...
self.browser.get(self.live_server_url + '/lists/add-name/')
Select(self.browser.find_element_by_id('id_namelanguage')).\
select_by_value(str(english.id))
# ...
breakpoint()
form = NameForm({'nametype': nome.id, 'gender': maschio.id,
'name': 'Remo', 'namelanguage': english.id,
'usato': 0})
print(form.errors)
form.save()
The error the test gives is (in the line form = ...):
ValueError: The Name could not be created because the data didn't validate.
and form.error is:
<ul class="errorlist"><li>nametype<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
but with breakpoint() I see the javascript function to add options to the field isn't found, the field stay empty so Select() don't select nothing, and the form gives the error.
Thank you for your help
I found the problem.
From the documentation:
When running tests that use actual HTTP requests instead of the built-in testing client (i.e. when using the built-in LiveServerTestCase) the static assets need to be served along the rest of the content so the test environment reproduces the real one as faithfully as possible, but LiveServerTestCase has only very basic static file-serving functionality: It doesn’t know about the finders feature of the staticfiles application and assumes the static content has already been collected under STATIC_ROOT.
Because of this, staticfiles ships its own
django.contrib.staticfiles.testing.StaticLiveServerTestCase, a
subclass of the built-in one that has the ability to transparently
serve all the assets during execution of these tests in a way very
similar to what we get at development time with DEBUG = True, i.e.
without having to collect them using collectstatic first.
So it was loading an old version of my javascript script. Like you can read the solution is to use StaticLiveServerTestCase instead of LiveServerTestCase.
I'm trying to use JavaScript functions from the a JavaScript library in my JSP file to display the result on a web-browser page, but it seems like the inclusion didn't work.
I actually put the .js file corresponding to the library in the WEB-INF folder and added the following line in the JSP file to include it in it :
<script type="text/javascript" src="./jsgl.min.js"></script>
I successfully managed to use the library in a simple HTML file, that's why I don't understand why this doesn't work.
EDIT :
TLDR
Put the JS file in a folder under web content (but not WEB-INF) like [WebContent]/js/jsgl.min.js, and use the following in the JSP:
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jsgl.min.js"></script>
Explanation
JSP files are compiled by the server, then processed to send data (typically HTML) back to the web browser. A <script> tag is a HTML tag that gets interpreted by the browser, not by the servlet container. So the browser sees that in the HTML then makes a new request to the server for the JavaScript file in the src attribute.
The src attribute is relative to the URL that the browser asked for, not to the path of the JSP on the server.
So as an example, let's say:
The browser asks for a page at http://example.com/SomeWebApp/some-resource
The servlet container internally forwards the request to a JSP at /WEB-INF/jsp/somepage.jsp
The response sent to the browser contains the script tag <script type="text/javascript" src="./jsgl.min.js"></script> (as in your question)
The browser sees the URL ./jsgl.min.js and resolves it relative to the URL it has asked the server for (which in this case was http://example.com/SomeWebApp/some-resource - note there is no trailing '/') so the browser will request the JS file from http://example.com/SomeWebApp/jsgl.min.js*. This is because the relative URL in the script tag's src attribute starts with a '.'.
Another answer suggested putting the JS file in a 'js' folder and changing the script tag to <script type="text/javascript" src="/js/jsgl.min.js"></script>. Using the same original page URL as in the example above, the browser would translate this src URL to http://example.com/js/jsgl.min.js. Note that this is missing the "/SomeWebApp" context path.
The best solution therefore is indeed to put the JS file in a static folder like /js/jsgl.min.js, but to use the following in the JSP script tag:
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jsgl.min.js"></script>
The JSP will translate the ${pageContext.request.contextPath} bit into the current context path, making the code portable (if you redeploy the webapp with a different context path, it will still work). So the HTML response received by the browser will be (again, sticking with our example above):
<script type="text/javascript" src="/SomeWebApp/js/jsgl.min.js"></script>
The browser will now resolve that relative URL to the correct target.
__
*If the original URL had a trailing slash = i.e., was http://example.com/SomeWebApp/some-resource/, the JS URL would be http://example.com/SomeWebApp/some-resource/jsgl.min.js
Static resources should be put outside the WEB-INF folder (as you would typically not allow web access to its content).
You could put the file under webapp/js/, then change your script import to:
<script type="text/javascript" src="/js/jsgl.min.js"></script>
In addition to being good practice, this is good as it is not relative to the location of the JSP file.
Files in WEB-INF are inaccessible.
You may put them under webapp and try accessing as mentioned above.
It all works in my local server, but when others try to deploy what I have done to the server, it fails.
the file system is the server something like:
SERVER_FOLDER
--homepage
----static
----templates
------404.html
----app.py
----config.py
for example: The server is: MY_SERVER
and then in my app.py, I use
#app.route('/homepage/')
#app.route('/homepage/index')
def index():
# TODO
to define the homepage, and #app.errorhandler(404) to redirect all the not found page to 404.html
So I can get access to my homepage with http://MY_SERVER/homepage/, a little different than my local server. That's one thing that I am confused.
What I think is that the app.py runs under the MY_SERVER rather than MY_SERVER/homepage right?
But, in this way, when I run a template in my template file, and the html template file will use the js file under the static folder. the response always shows the js file is not found.
when I use <script src="{{ url_for('static', filename='file.js') }}"></script>, it shows not found in MY_SERVER/static and return to 404
when I try <script src="../homepage/static/file.js"></script>, same result.
How to handle this?
Build toward your solution:
Get flask serving image files from static
Put an image in the static directory and call it from your browser: http://yoursite/static/some_image_there.jpg
Plug away until that works.
Get flask serving the js file directly to your browser
Now put your js file into static and do as you did for the image.
Plug away until you can call it from the browser:
http://yoursite/static/yourfile.js
get your html to call the js file from static
Now you know that there is no problem actually serving the file, and you know the exact url to it. So it's not a big step to getting the HTML to reference it and your browser to load it.