How to include a javascript from /js/ in jekyll - javascript

I've added the cookie consent code from here
It has
<script>
...
if(readCookie('cookie-notice-dismissed')=='true') {
{% include ga.js %}
{% include chatbutton.js %}
}
...
</script>
in the html. This is placed within _includes but I can't figure out how to include javascript like /js/foo.js, located in another directory. I believe this is bundled with bundler within the jekyll assets.
Up to now, I've added javascript on my layouts in the following way, but haven't used {% include %} for this yet and I don't know how to let the _includes/cookie_consent.html know แบhere to find it.
<script src="/js/foo.js"></script>
<script>
$(function(){
new Foo(".js-foo");
});
</script>

I can see two options to solve this
you create a file in _includes that contains the links to the extra JS you want.
For example:
# /_includes/bar.html
<script src="/js/foo.js"><\/script>
Inside _cookie_consent.html you can then add{% include bar.html %}
You add the link directly to your body.
if(readCookie('cookie-notice-dismissed')=='true') {
const js = '<script src="/js/foo.js"></script>'
document.body.appendChild(js)
}

Related

JavaScript only runs when both the code is inside the HTML and is called externally with <script src=...>

My JavaScript code only runs when the code is both inside the HTML file and called externally via
<script type="text/javascript" src="{{ url_for('static', filename='index.js') }}"></script>
<script>
var scroller = document.querySelector("#scroller");
...
</script>
I am using Flask and Jinja, with a file structure of:
/app
/static
index.js
/templates
base.html
myfile.html
routes.py
__init__.py
...
The code inside index.js is the exact same code between the <script> tags inside the HTML.
In terms of jinja and using block tags, base.html:
<body>
{% block content %}
<!-- typical HTML stuff here -->
{% endblock %}
<!-- some Bootstrap tags -->
<script ... ></script>
{% block script %}{% endblock %}
</body>
myfile.html:
<body>
...
{% block script %}
<script type="text/javascript" src="{{ url_for('static', filename='index.js') }}"></script>
{% endblock %}
<script>
...
</script>
The code itself works, and it worked not too long ago without this issue; I don't know what I changed to cause this, nor can I even imagine what could cause this. If there is more code that is required, I can easily share it.
Is there something I not understanding?
To note: I have had a similar issue trying to including external JavaScript code inside my HTML; at one point it wouldn't work, then it did, now it behaves the way I have described.
To further note: I have another .html file with its own external .js file that works fine.
Mr.#JakeJackson, Script in externl file never requires the same content to be available inside your inline code.
May be you are trying to process some elements and your script got executed before those elements are mounted to the document object.
A lazy solution to that problem is moving the external file linking tag to the bottom your HTML.Body.
OR
You can use defer attribute to your script element https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script
OR
If you have some libraries like jQuery included in your page, You can use the document.ready implementations in that
OR
you can implement your own document.ready like below
function myReady() {
return new Promise(function(resolve) {
function checkState() {
if (document.readyState !== 'loading') {
resolve();
}
}
document.addEventListener('readystatechange', checkState);
checkState();
});
};
myReady().then(function() {
// Put your app custom code here
});

Django3: dynamically generating js which I can use in HTML page

As we know in Django framework we can generate the HTML page based on some predefined template files.
Inside those templates we can use and some specific django keywords/operators/functions.
Like:
{% block stylesheets %}
<link href="{% static 'js/jquery/jquery-ui.css' %}" rel="stylesheet">
<link href="{% static 'vendor/chosen/chosen.css' %}" rel="stylesheet">
{% endblock stylesheets %}
But most important things which I want to touch in this question are related to tag 'translate'
"{% trans 'List of all available masters' %}"
So I can be sure that the final content of my page will use some predefined language.
And the places where I am using such tags are different: "simple" html content with / and etc tags AND inline javascripts blocks. Like:
<script type="text/javascript">
$('#datepicker_value').on('change', function(){
....
var dialog = BootstrapModalWrapperFactory.createModal({
title: '{% trans 'Extended information about the event' %}',
message: '<pre>'+JSON.stringify(info.event.extendedProps.description, null, 4)+'</pre>',
buttons: [
{
label: '{% trans 'Close' %}',
cssClass: "btn btn-secondary",
action: function (button, buttonData, originalEvent) {
return this.hide();
}
}
]
});
....
</script>
So my main question here is such:
HOW correctly I can move ALL <script>...</script> blocks from html template into the external JS file?
To keep all the functionality of the django framework working! And my 1 variant was - I should use the same technique which I use for generating HTMLs with Django framework abilities. But maybe in a little shorten variant: Right inside the views.py file - CAN I somehow correctly generate on the fly full content of GLOBAL.js file which will contains ALL ... blocks from html template - where they all were previously stored.
And in a such manner - that standard django template engine can convert all {% ..... %} placeholders in a correct real content BEFORE the full content of GLOBAL.js will be generated and given out. And especially the content of translatable placeholders!!! Well, then in the HTML page template I can insert a call to a special command that can display the contents of this script at the moment the page is rendered by the browser on the client side. Something like:
<script type="text/javascript" src="{% url 'GLOBAL.js' %}"></script>
Am i right? If yes - how I can do that step-by-step? Or maybe there is something new and more logical way?
Django version is the latest one!!! 3.*
P.S. Also I've faced with a problem of transferring script block with content like document.addEventListener('DOMContentLoaded', function(){...}); Looks like such event handlers can't be moved out to the separate JS file from HTML page((
There is no reason you couldn't use Django template tags inside Javascript files (or any other filetype for that matter). As an example, here's is a view that returns rendered Javascript:
from django.shortcuts import render
def render_javascript(request):
return render(request, 'myapp/global.js', {})
If you hook this view into your urlpatterns like this:
urlpatterns = [
path("js/global.js", render_javascript, name="globaljs"),
]
You can then use the {% url %} template tag to refer to it from your HTML templates like this:
<script type="text/javascript" src="{% url 'globaljs' %}"></script>
Now when your browser requests js/global.js, the Django view will take the template myapp/global.js, process it with the templating system, and return the rendered template.

How to defer JavaScript when using Django template variables?

I have a problem. I am doing all of this new fancy defer stuff when I load my JavaScript, as recommended by lighthouse while working on PWA.
{% block head_content %}
<script defer src={% static 'js/jquery.min.js' %}></script>
{% endblock %}
If I was just doing this in a Django tempalte, it would not be a problem, I could just move the <script> content to a .js file and defer that also:
{% block content %}
<script>
$( jquery thing
let x = 0; // Do jQuery stuff with NO json_data
);
</script>
{% endblock %}
However, I have a Django application that is doing something like:
{% block content %}
<script>
$( jquery thing
{{ json_data|safe }} // Do jQuery stuff with json_data
);
</script>
{% endblock %}
So if I try and move the script to a separate .js file I get: SyntaxError: expected property name, got {.
This very popular Q&A seems not to work if you get $ is not defined due to using defer, as noted by the top comment. Is my only option to put the script above the portion of the code that uses jquery in the body with no defer? If so, this limits the usefulness of Django's template inheritance.
{% block content %}
<script>
<script src={% static 'js/jquery.min.js' %}></script> // Add above each first-use of jQuery (along with every other relevant library)
$( jquery thing
{{ json_data|safe }} // Do jQuery stuff with json_data
);
</script>
{% endblock %}
I haven't been using Django in a while now, but I don't think you can "defer" that script tag inside your template. That said, you could try one of the following:
01: Load your json_data into a variable that you can access from an external .js file.
Something like:
var myJsonData = "{{ json_data|safe }}";.
Check this thread here for more info.
02: Another option is to create an endpoint that will return that json_data and call it from an external .js using ajax. Then you can use the data to do whatever you need.
Something like
$.ajax({
url: "my_django_endpoint",
success: function(result){
// Do jQuery stuff;
}
});
Check this thread here for more info.
We used a framework called T3JS that has a neat way of implementing Option 01 using context. (if you wanna take a look under the topic getConfig).
Hope it helps :)

Scrollify function not being found even when script is imported

So I'm trying to use Scrollify, which is a jQuery plugin for scroll snapping. I have jQuery imported no problem, but no matter how I import the plugin itself, I get the error:
Uncaught TypeError: $.scrollify is not a function
I have the plugin script loading after jQuery itself loads, and the configuration code after both of those load, even to the point where I put the plugin's script tag and configuration code at the very end of the page before </body>.
I've tried hosting the plugin script locally, and I tried using a CDN. Both gave the same issue.
I've had these sort of issues with other scripts and they always were due to the loading order, but I'm stumped here. Any help?
So I am building a custom Theme in OctoberCMS, and I was hopping to use scrollify before running into the same error. After a lot of struggling, switching JQuery versions and moving functions around, I noticed my issue was related to using Laravel Mix/Webpack to import the scrollify code. I had it required at the top of my main.js file, but the code itself was loaded after.
My solution was using some October twig functions to load the code after JQuery manually.
// These get loaded first
<script src="{{ [
'assets/js/app.js', // My JQuery gets loaded here
'assets/js/vue.js' // Other JS for the website
]|theme }}"></script>
// Scripts in here injected into page by the {% scripts %} tag after, having the
// scrollify.js in the array above or outside the {% put scripts %} tag would always throw
// $.scrollify is not a function error
{% put scripts %}
<script src="{{ 'assets/js/scrollify.js'|theme }}"></script>
<script>
$(document).ready(function () {
$.scrollify({
section: ".example-section",
});
});
</script>
{% endput %}
{% scripts %}
The {% scripts %} tag inserts JavaScript file references to scripts
injected by the application.
https://octobercms.com/docs/markup/tag-scripts
As the above answers mentioned, Scrollify needs to be loaded after the page and Jquery loads, but if you are using Webpack or equivalent I would suggest checking the compiled scripts in your browser and making sure they are ordered correctly.
Try putting your script at the bottom of your code.
...
<script>
$(function(){
$.scrollify({
...
});
});
</script>
</body>
Try to use it this way
jQuery(document).ready(function($) {
$.scrollify({
...
});
});
The reason behind the error is, that the Scrollify Script should initialize after the document has finished loading. Thus, the solution is to move it to the end
Move these two lines at the end of the body tag, as shown below:
<body>
..
..
..
<script src="..\js\Scrollify\jquery.scrollify.js"></script>
<script>
$(document).ready(function() {
$.scrollify({
section : ".sectionalScrolling",
});
});
</script>
</body>
Make sure that the script is right before the closing body tag.

How to include simple JavaScript within Hugo

Given the following code:
$('img').mouseenter(function(){
//...
}).mouseleave(function(){
//...
});
I'd like it to be included in my articles. I'd like to avoid editing the theme if possible so to avoid forking etc.
This depends a little on which theme you use. This may be an area where we could do a better job, but do this:
In the theme, look in the
layouts/partials folder.
If you find a header.html or similar, copy this to your local layouts/partials. You can then override the content of this file only. Alternatively you can customize by copying the template used for single pages, often: layouts/_default/single.html.
bep's answer is excellent, but here are some additional details for hugo/frontend newcomers like me
1. Find a place in your HTML where to include the JS
First, one should copy the header.html or footer.html (or similar) of the Hugo theme to your layouts/partials folder. It does not necessarily have to be the header or the footer, but a file that is included in every page on your html (and that's why you would typically use the header.html or footer.html).
I got a theme that had the footer at <theme_folder>\layouts\partials\_shared\footer.html, which I then copied from the theme folder into the project layout folder <project_root>\layouts\partials\_shared\footer.html.
2. Include the script.js in the HTML
Then, I added to the bottom of footer.html
<script defer language="javascript" type="text/javascript" src="{{ "/js/myscripts.js" | urlize | relURL }}"></script>
The defer attribute can improve the page loading time a bit, and "/js/myscripts.js" is the location of my javascripts. The location is path relative to <project_root>\static\. Here are the documentation about relURL and urlize.
The example script file contains just
// myscripts.js
function myFunction(x) {
let d = new Date();
alert("Current datetime: " + d + "\nYou passed in: " + x);
}
3. Use the JS function
This is an example of using the JS function from within Hugo template (any .html belonging to the template):
{{ $somevar := "spam"}}
<button onclick="myFunction( {{ $somevar}} )">Click me</button>
Inline JS
It looks like also inline JS runs just fine; for example, adding
<script>
alert("Script loaded!");
</script>
to a template html file ran just fine. I would use this only for quick testing though, since some scripts might be needed in multiple html files, and adding the same script to multiple files would just increase your overall website filesize.
I copy themes/whatever/layouts/_default/baseof.html to layout/_default/baseof.html and add the following block at the end of the html tag:
{{ block "page-script" . }}{{ end }}
Then I can add
{{- define "page-script" -}}
<script>console.log("Hello!")</script>
{{- end -}}
in my layouts files to put in a script.

Categories

Resources