I am using Twig as my template, utilizing a layout, in which I have a javascript block
...
{% block javascripts %}
{% javascripts
'#jquery'
'#bootstrap_js' %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
{% endblock %}
</body>
In a content template, I have
{% block javascripts %}
{{ parent() }}
{% javascripts '#AppBundle/Resources/public/index/*' %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
{% endblock %}
This is my assetic section of the config.yml
assetic:
debug: true
use_controller: false
filters:
cssrewrite: ~
assets:
bootstrap_js:
inputs:
- %kernel.root_dir%/../vendor/twbs/bootstrap/dist/js/bootstrap.min.js
bootstrap_css:
inputs:
- %kernel.root_dir%/../vendor/twbs/bootstrap/dist/css/bootstrap.css
- %kernel.root_dir%/../vendor/twbs/bootstrap/dist/css/bootstrap-theme.css
filters:
[cssrewrite]
bootstrap_glyphicons_ttf:
inputs:
- %kernel.root_dir%/../vendor/twbs/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf
output:
"../fonts/glyphicons-halflings-regular.ttf"
bootstrap_glyphicons_eot:
inputs:
- %kernel.root_dir%/../vendor/twbs/bootstrap/dist/fonts/glyphicons-halflings-regular.eot
output:
"../fonts/glyphicons-halflings-regular.eot"
bootstrap_glyphicons_svg:
inputs:
- %kernel.root_dir%/../vendor/twbs/bootstrap/dist/fonts/glyphicons-halflings-regular.svg
output:
"../fonts/glyphicons-halflings-regular.svg"
bootstrap_glyphicons_woff:
inputs:
- %kernel.root_dir%/../vendor/twbs/bootstrap/dist/fonts/glyphicons-halflings-regular.woff
output:
"../fonts/glyphicons-halflings-regular.woff"
jquery:
inputs:
- %kernel.root_dir%/../vendor/components/jquery/jquery.min.js
Everything else works fine, except for the files under #AppBundle/Resources/public/index/*. I run assetic:dump for my environment, everything goes smoothly, but I keep getting a 404 HTML dump underneath the script element for #AppBundle/Resources/public/index/*
<script src="/logbook/web/js/431d650.js">
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>An Error Occurred: Not Found</title>
</head>
<body>
<h1>Oops! An Error Occurred</h1>
<h2>The server returned a "404 Not Found".</h2>
<div>
Something is broken. Please let us know what you were doing when this error occurred.
We will fix it as soon as possible. Sorry for any inconvenience caused.
</div>
</body>
</html>
</script>
Something is broken, apparently, but I cannot figure out what???
I did also have some issues using assetic in the past and I wrote down a way how I got it work. Maybe it would help you if you'd try to execute the following command first before dumping the assetic stuff:
php app/console assets:install --symlink web
Related
I'm extending the layout of my sphinx-book-theme by adding the following to the layout.htmlunder my source\_templatesfolder:
{% extends "!layout.html" %}
{%- block extrahead %}
<script
type="text/javascript"
src="https://utteranc.es/client.js"
async="async"
repo="executablebooks/jupyter-book"
issue-term="pathname"
theme="github-light"
label="š¬ comment"
crossorigin="anonymous">
</script>
{% endblock %}
When I build from source with the command:
sphinx-build -b html ....
The html output doesn't render the comment section at the bottom of the pages.
However, if I add the javascript bloc directly to the bottom of a Markdown file, the comment section appears at the bottom of the relevant page.
What am I missing here? When I inspect the page source, I can see that the javascript block is in the head section.
I'm using Sphinx v4.5.0 with the Sphinx-book-theme on a Windows OS
I managed to find an answer to my own question. :-)
Looking at the main 'layout.html', I figured out the template had a different structure and the blocks were using different naming conventions than the ones used in the default Sphinx templates.
So I changed my initial configuration by adding an extra block extraScript inside the block docs_main, then I added a block there under {super}:
{% block extraScript } {% endblock extraScript %}
Then I adapted the code indicated in my former question as shown below:
{% extends "!layout.html" %}
{%- block extraScript %}
<script
type="text/javascript"
src="https://utteranc.es/client.js"
async="async"
repo="executablebooks/jupyter-book"
issue-term="pathname"
theme="github-light"
label="š¬ comment"
crossorigin="anonymous">
</script>
{% endblock extraScript %}
If you have a more elegant method to solve this issue, please share your ideas with us.
I'm working on an application built with flask and using templates. I have a layout.html file with head tags and js/css links which I'm importing on each page using:
{% extends "layout.html" %}
{% block content %}
{# My content #}
{% endblock content %}
This works but I now need to link to other JS files only for specific html files and wondering what is the correct way of doing it using flask.
You can simply include your <script> tags in the HTML file where you need them. This way, the javascript will be imported only when that specific page is loaded.
An example is:
{% extends "layout.html" %}
{% block content %}
{# My content #}
{% endblock content %}
{% block scripts %}
<script scr="..."></script>
{% endblock scripts %}
If I am not wrong, you want some of your HTML pages to have a link to JavaScript code.
To achieve this just add the <script> tag in that particular HTML page as follows:
<script src="{{ url_for('static', filename='JS/some_file.js') }}"></script>
where-
JavaScript file is kept at: static->JS->some_file.js
{% block javascript %}
<script type="text/javascript">
{% include "some-js-file.js" %}
</script>
{% endblock %}
Create a code block like the block above.
For completeness, you can also reference this SO question: Loading external script with jinja2 template directive
You can have all the unique Javascript tags in the layout.html file then for each endpoint use if else statements to render the tag you want for each page. The endpoint is simply the name of the view function.
{% if request.endpoint == 'index' %}
<script src="{{ url_for('static', filename='JS/file.js') }}"></script>
{% elif request.endpoint == 'another-endpoint' %}
<script src="{{ url_for('static', filename='JS/some_other_file.js') }}"></script>
In Django, how can you handle the fact that you need to wait for that a JS file is loaded before actually using it?
let's see the problem with this example:
base.html
<!DOCTYPE html>
<html>
<head>...</head>
<body>
{% include "content.html" %}
<script src="jquery.js"></script>
<script src="awesome-script.js"></script>
</body>
</html>
content.html
<script>
$(document).ready(function(){
...
});
</script>
This logically fail ($ is undefined). I could load jQuery before calling the script, but I'm trying to avoid loading JS file before my main content to keep the website loading as fast as possible.
So, what can I do? Thanks.
Extending Wtower's suggestion - keep his accepted.
I would really insist on using the template inheritance based approach in his examples. I would like to introduce a few more elements to that approach, to cover some other common needs :
<!DOCTYPE html>
<html>
<head>{% block scripts-head %}{% endblock %}</head>
<body>
{% block content %}{% endblock %}
{% block scripts %}
<script src="jquery.js"></script>
{% endblock %}
<script>{% block script-inline %}{% endblock %}</script>
</body>
</html>
There are 3 ideas here:
Adding a placeholder in the header, in case you could need scripts there at some point. Self explanatory.
Including common scripts in the base file. If they are common, the belong in the base file, you should not have to repeat yourself in every template. Yet you put it inside the block, so it can be overriden along the hierarchy.
{% extends "base.html" %}
{% block scripts %}
{{ block.super }}
<script src="a-local-lib.js"></script>
{% endblock %}
The key is in using {{Ā block.superĀ }} to bring any script that was defined in the parent template. It works especially well when you have several levels of inheritance in your templates. You get to control whether script go before or after inherited scripts. And of course, you can completely override the block, not including {{Ā block.superĀ }} if you so wish.
Basically the same idea, but with raw javascript. You use it the same way: every template that needs to include some inline javascript will have its {{ block script-inline }}, and will start with {{ block.super }} so whatever the parent put in there is still included.
For instance, I use Ember in my project, and have a couple of initializers to setup project settings and load bootstrap data. My base app-loading templates has a global project settings initializer, and child templates define local settings and data.
Since your script uses jQuery, you can simply use the $(document).ready() and $(window).load() functions of jQuery to bind a function on the event that DOM is ready and all window contents have been loaded, respectively.
If you do not use jQuery, take a look at these relative questions to understand how to imitate the above behaviour with pure JS:
pure JavaScript equivalent to jQuery's $.ready() how to call a function when the page/dom is ready for it
Javascript - How to detect if document has loaded
EDIT 1: The inclusion order matters. You have to include the jQuery scripts before any scripts that require jQuery are executed.
EDIT 2: You can organize your templates better by keeping the scripts separately from the main content, either with a second template:
base.html
<!DOCTYPE html>
<html>
<head>...</head>
<body>
{% include "content.html" %}
{% include "js.html" %}
</body>
</html>
js.html
<script src="jquery.js"></script>
<script src="awesome-script.js"></script>
<script>
$(document).ready(function(){
...
});
</script>
(in this case you render base.html)
Or with blocks (recommended):
base.html
<!DOCTYPE html>
<html>
<head>...</head>
<body>
{% block content %}{% endblock %}
{% block scripts %}{% endblock %}
</body>
</html>
content.html
{% extends 'base.html' %}
{% block content %}
...
{% endblock %}
{% block scripts %}
<script src="jquery.js"></script>
<script src="awesome-script.js"></script>
<script>
$(document).ready(function(){
...
});
</script>
{% endblock %}
(in this case you render content.html)
When i compile my code using assetic my js files are being named part_1.js, part_2.js. i dont see this referent to part_ anywhere in my code. where is this coming from?
config.yml
assetic:
assets:
our_custom_js:
inputs:
- '#MyBundle/Resources/public/js/base.js'
filters: []
output: 'custom.js'
fos_js_routes:
inputs:
- 'bundles/fosjsrouting/js/router.js'
output: 'fos_js_router.js'`
base.html.twig
{% javascripts combine=false output="sandbox.js"
'#our_custom_js'
'#fos_js_routes'
%}
<script src="{{ asset_url }}"></script>
<script src="{{ path('fos_js_routing_js', {"callback": "fos.Router.setData"}) }}"></script>
{% endjavascripts %}
my source ends up looking like this
<script src="/sandbox_part_1.js"></script>
<script src="/js/routing?callback=fos.Router.setData"></script>
<script src="/sandbox_part_2.js"></script>
<script src="/js/routing?callback=fos.Router.setData"></script>
This question was also asked here How to make Symfony 2 asset compilation to product different filenames?
Just answered the same question here. The 'part_#' string is added when accessing your application in the development environment (app_dev.php).
By default, {% javascripts %} will print all your assets/scripts, using a <script> line for each script. In the production environment, they are combined.
The {% javascripts %} function acts like a foreach loop in dev environment, while it will combine all assets in to a single <script> line in production. If you take a look at the PHP-script in the documentation, you can see that it's using foreach:
<?php foreach ($view['assetic']->javascripts(
array(
'#AppBundle/Resources/public/js/*',
'#AcmeBarBundle/Resources/public/js/form.js',
'#AcmeBarBundle/Resources/public/js/calendar.js',
)
) as $url): ?>
<script src="<?php echo $view->escape($url) ?>"></script>
<?php endforeach ?>
Your base.html.twig should look like this:
{% javascripts combine=false output="sandbox.js"
'#our_custom_js'
'#fos_js_routes'
%}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
<script src="{{ path('fos_js_routing_js', {"callback": "fos.Router.setData"}) }}"></script>
When the other <script> is not inside the javascripts part, it will not be in the loop, so it will be printed only once.
I am using jQuery in my Symfony2 application and I have a "ReferenceError: jQuery is not defined" error. I think changing Javascript file load order could fix this.
How could I force to load jQuery Javascript file first in order to avoid such errors? I would like to keep the "js/*" in order to load auto-magically the future new JS files I will put.
Here is stylesheets part of my *.html.twig template:
{% javascripts
'#xxxBundle/Resources/public/js/*'
'js/*'
%}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
And here is current output generated by Symfony2:
<script type="text/javascript" src="/Symfony/web/app_dev.php/js/8d3a8ee_part_2_acidTabs_1.js"></script>
<script type="text/javascript" src="/Symfony/web/app_dev.php/js/8d3a8ee_part_2_jquery-1.6.min_2.js"></script>
You can list your core dependencies first, then load all others:
{% javascripts
'#xxxBundle/Resources/public/js/*'
'js/example_1.js'
'js/example_2.js'
...
'js/*' %}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}