Javascript rendering in tornado webserver - javascript

In following code snippet I'm trying to add JavaScript Files from Tornado server in HTML file in <HEAD> tag.
DEBUG_SCRIPTS = ''' <script src="src/main.js" type="text/javascript"></script> '''
class Entries(tornado.web.UIModule):
def javascript_files(self):
return 'src/main.js'
class MainHandler(tornado.web.RequestHandler):
def get(self):
params = {}
params['CORE_SCRIPTS'] = DEBUG_SCRIPTS
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.render(path, params=params)
by params['CORE_SCRIPTS'] = DEBUG_SCRIPTS I was trying to add the <script> tag in HTML but it gets parsed in text which generates
<script type="text/javascript" src="src/main.js"></script>
So I came across javascript_files() method in tornado specs but I'm not getting any examples about its implementations. Can anyone help?

javascript files only works with UIModules. Javascript files included that way are appended to the page just before the end of the body tag, though, not in the head tag.
If you really want the file included in the head tag, you can simply output the value of params['CORE_SCRIPTS'] in the head tag of your template:
{% raw params['CORE_SCRIPTS'] %}

Related

Using innerHTML to get a whole page content

I am still a beginner in Javascript and I wondering if I can use innerHTML to post the whole HTML content from another page.
I have used innerHTML to just post an HTML code within the same .js page. For example:
I have main.js that contains this
class MyComponent extends HTMLElement {
connectedCallback() {
this.innerHTML = `<h1>Hello world</h1>`;
}
}
customElements.define('my-component', MyComponent);
and in the index.html I use this code to implement the main.js
<!doctype html>
<html lang="en">
<head>
<script type="application/javascript" src="js/main.js"></script>
</head>
<body>
<my-component></my-component>
</body>
</html>
The question is can I include an HTML page instead <h1>Hello world</h1> like header.html to get the whole HTML code from it? if not, Is there any way to do that?
Thanks.
Edit: I mean for example if I have a page named footer.html and in that page, I have an h1 ex. "Hello world" And I need to use the same h1 in another page index.html without rewrite it again. Can I make that h1 as a template to use in any other page using javascript?
My idea that I was looking for is:
Making main.js
get h1 from footer.html in main.js
import that script in index.html
using h1 in index.html
I know that I can do that using "include" in PHP but I am just trying to do it by javascript.
You can try:
document.body.innerHTML
to access page content.
You can do that with AJAX. Set an URL for that file and make a get request with AJAX.
Using JQUERY
$.get("file_path.html", function(fileText){});

Use js file as cdn in HTML

I made a library in jquery an hosted in to my shared hosting. That js file is accessible when I hit from browser . But if I set it in my html like cdn it's not working. That's mean if I use code directly without use separate file it works but when I keep that js code in a file and include file then not works.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
body code ...........
<script src="https://mydomain/acdn/jsfile.js"></script>
</body>
</html>
My cdn file
<script>
$(document).ready(function() {
$.ajax({
url: '{{ url('get-list') }}',
.........................
})
</script>
here shows error Unexpected identifier in {{ url('get-list') }}
You JavaScript contains:
'{{ url('get-list') }}'
This appears to be some kind of template code that the server-side code which generates your HTML document will replace with some data.
When you take it out of the HTML document, it is no longer being generated by that server-side code so won't be replaced. The JS parser therefore attempts to parse it, fails, and throws an error.
Move the template code back inside your HTML, then read the data from the HTML document using the JS.
e.g.
<script src="..." data-url="{{ url('get-list') }}">
And then in your script:
const url = document.currentScript.dataset.url;
(Make sure you change any logic which escapes the data to make it safe to be injected into JS to logic which makes it safe to be injected in HTML).

Write hyperlink so that an html file loads but internal link to js file changes

This is a general question for which I have searched high and low to no avail, and would greatly appreciate any input.
I have a html/javascript educational quiz that loads a separate js file to retrieve an array to determine the content of the quiz. For example this retrieves the js file with an array of hard level math problems
<script type="text/javascript" src="../js/arrays/math-hard.js"></script>
I have a number of js files with arrays of different content. Another one might load English questions, etc. I need to have a variety of these quizzes, all launched from separate links in different sections of an overall interface.
Currently to create a new quiz I am duplicating the html file and changing the reference to point to the requisite js file for the array.
I would much prefer to have a single html file, and simply write different links that all load that same single html file, but dynamically substitute one of the other js array files to change the content. I cannot figure out how to do this, nor have I been able to find a published solution anywhere.
At the moment the html file is written such that it only references one of the js files that have the arrays, but it's fine to include links to all of them in that single file if that's necessary as part of achieving this functionality.
Currently I have a single html file (stripped down)
<!doctype html>
<html>
<head>
<script type="text/javascript" src="../js/quiz.js"></script>
<script type="text/javascript" src="../js/gridquiz/s-english-easy.js"></script>
</head>
<body>
<div id="gridQuizContent" class="quiz-content">
<div id="divClick" class="quiz-click"></div>
</div>
</div>
</body>
</html>
and it load that english-easy.js, that looks basically like this (simplified)
Quiz.easy = [
['hi-IN', 'dog', 'cat', 'pig', 'cow'],
['hi-IN', 'me', 'you', 'he', 'she'],
['hi-IN', 'up', 'down', 'in', 'out'],
['hi-IN', 'hot', 'cold', 'big', 'small'],
];
And I want to write many links that simply load the same html file but change this line
<script type="text/javascript" src="../js/gridquiz/s-english-easy.js"></script>
as it loads to reference a different array.
If each quiz URL looks similar to the following:
https://quiz.com/quiz.html?quiz=math-hard
https://quiz.com/quiz.html?quiz=math-easy
https://quiz.com/quiz.html?quiz=history-hard
Then you could possibly dynamically load the desired JavaScript file in a 'base' JavaScript file for quizzes by checking the URL path:
// base.js
function dynamicallyLoadScript(url) {
// create a script DOM node
var script = document.createElement("script");
// set its src to the provided URL
script.src = url;
/* add it to the end of the head section of the page (could change 'head'
to 'body' to add it to the end of the body section instead) */
document.head.appendChild(script);
}
let params = new URLSearchParams(location.search);
if (params.has('quiz')) {
dynamicallyLoadScript(params.get('quiz') + ".js");
}
So the HTML of https://quiz.com/quiz?quiz=math-hard would be similar to:
<!doctype html>
<html>
<head>
<script src="../js/base.js"></script>
<!-- Added by 'base.js' -->
<script src="../js/arrays/math-hard.js"></script>
</head>
<body>
</body>
</html>
Personally I would use JSON files to realize this. I found a tutorial on this website, which follows the same problem "how to store quiz questions".

Adding Javascript to Custom widgets

This question is related to
Django: Best Way to Add Javascript to Custom Widgets
But is not the same.
The original question asks how to add supporting javascript to a custom django widget, and the answer is to use forms.Media, but that solution does not work for me. My example is this:
The widget, when rendered in a form, creates a line which looks like (toy example) this:
<div id="some-generated-id">Text here</div>
Now, what I also want to add to the output is another line looking like this:
<script>
$('#some-generated-id').datetimepicker(some-generated-options)
</script>
The initial idea is that when the widget is rendered, both the div and script get rendered, but that does not work. The problem is that the structure of the html document looks like:
-body
- my widget
- my widget's javascript
-script
-calls to static files (jQuery, datetimepicker,...)
At the time the widget's javascript code is loaded in the browser, jQuery and datetimepicker js files have not yet been loaded (they load at the end of the document).
I cannot do this using Media, since the options and id I generate are vital to the function. What is the best way to solve this?
From the docs:
The order in which assets are inserted into the DOM is often important. For example, you may have a script that depends on jQuery. Therefore, combining Media objects attempts to preserve the relative order in which assets are defined in each Media class.
Consider this example:
class FooWidget(forms.TextInput):
class Media:
js = ('foo.js',)
class BarWidget(forms.TextInput):
class Media:
js = ('bar.js',)
class SomeForm(forms.Form):
field1 = forms.CharField(widget=BarWidget)
field2 = forms.CharField(widget=FooWidget)
def __init__(self, *args, **kwargs):
super(SearchForm, self).__init__(*args, **kwargs)
Now when you call form.media, the scripts will render like this:
<script type="text/javascript" src="/static/bar.js"></script>
<script type="text/javascript" src="/static/foo.js"></script>
Why does bar.js render before foo.js? Because django renders them based on the order they were called on in the form, not the order that the classes were defined in. If you want to change the order in this example, simply swap the position field1 and field2 in SomeForm.
How does this help you with jQuery? You can render your jQuery CDN script via your custom widget:
class FooWidget(forms.TextInput):
class Media:
js = ('https://code.jquery.com/jquery-3.4.1.js', 'foo.js',)
class BarWidget(forms.TextInput):
class Media:
js = ('https://code.jquery.com/jquery-3.4.1.js', 'bar.js',)
Now your form.media will look like this:
<script src="https://code.jquery.com/jquery-3.4.1.js"></script>
<script type="text/javascript" src="/static/bar.js"></script>
<script type="text/javascript" src="/static/foo.js"></script>
Notice how /static/ wasn't appended to the jQuery CDN? This is because the .media attribute checks whether the given filepaths contain http or https, and only appends your STATIC_URL setting to filepaths that are relative.
Also note that duplicate file names are automatically removed, so I would say it's good practice to include a https://code.jquery.com/jquery-3.4.1.js at the beginning of every widget that requires it. That way, no matter what order you render them in, the jQuery script will always appear before files that need it.
On a side note, I would be careful when including numbers in your filenames. As Django 2.2 there appears to be a bug when trying to order the scripts.
For example:
class FooWidget(forms.TextInput):
class Media:
js = ('foo1.js', 'foo2.js',)
class BarWidget(forms.TextInput):
class Media:
js = ('bar1.js', 'bar13.js',)
class SomeForm(forms.Form):
field1 = forms.CharField(widget=BarWidget)
field2 = forms.CharField(widget=FooWidget)
def __init__(self, *args, **kwargs):
super(SearchForm, self).__init__(*args, **kwargs)
Will look like:
<script type="text/javascript" src="/static/bar1.js"></script>
<script type="text/javascript" src="/static/foo1.js"></script>
<script type="text/javascript" src="/static/bar13.js"></script>
<script type="text/javascript" src="/static/foo2.js"></script>
I've tried various combinations of names containing numbers, and I can't follow the logic, so I assume this is a bug.
Since the JavaScript is an inline script, you will need to use a the native DOMContentLoaded event to wait for the jQuery to load.
<script>
window.addEventListener('DOMContentLoaded', function() {
(function($) {
$('#some-generated-id').datetimepicker(some-generated-options);
})(jQuery);
});
</script>
Alternately, if you can put your code into an external script file, you can use the defer attribute of the script tag.
<script src="myfile.js" defer="defer"></script>
See the MDN.
You want to execute some plugin script on added div. You need to add class to your element and associate a custom event to class. Which will execute your desire function or script.
To associate custom event to dynamically added node, please refer below code.
<!DOCTYPE html>
<html>
<head>
<title>adding javascript to custom widgets</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
</head>
<body>
<section class="team">
<div class="container">
<div class="row">
<div class="container maxwidth">
<button data-tab="tab1" class="active">AA<span></span></button>
</div>
<div class="maincontent"></div>
</div>
</div>
</section>
<script>
$(function(){
$(".active").click(function(){
$(".maincontent").append("<div class='scroll'><h2>Hello</h2><div style='background:red; height:500px;'></div></div>")
$(".maincontent").find(".scroll").trigger('dynload');
});
$('.container').on('dynload', '.scroll', function(){
console.log("Append event fired");
// Additinal Script resource you want to load for plugin
$.getScript("Custom_Scrollbar.min.js") //script URL with abosolute path
.done(function() {
// Script loaded successfully calling of function
$(".scroll").mCustomScrollbar({
});
})
.fail(function() {
// Give you error when script not loaded in browser
console.log('Script file not loaded');
})
})
})
</script>
</body>
</html>
Hope this will help!
You should init JS as:
<script type="text/javascript">
$( document ).ready(function() {
var some-generated-options = {};
$('#some-generated-id').datetimepicker(some-generated-options);
});
</script>
Like you I did own custom widget that look as:
class DaysInput(TextInput):
def render(self, name, value, attrs=None):
result = super(DaysInput, self).render(name, value, attrs)
return u"""
%s
<script type="text/javascript">
$( document ).ready(function() {
$('a.id_days').click(function(e){
e.preventDefault();
$('input#id_days').val($(e.currentTarget).attr('attr-value'));
});
});
</script>
<a href="#" class="id_days" attr-value='1'>1d</a>
<a href="#" class="id_days" attr-value='2'>2d</a>
<a href="#" class="id_days" attr-value='3'>3d</a>
""" % result
class TestForm(forms.ModelForm):
days = forms.IntegerField(widget=DaysInput())

Embed javascript in markdown

I'm using the Maruku markdown processor. I'd like this
*blah* blah "blah" in [markdown](blah)
<script src="http://code.jquery.com/jquery-1.4.2.min.js"></script>
<script>
...do stuff...
</script>
but it complains when I render it with a multitude of errors. The first one being
___________________________________________________________________________
| Maruku tells you:
+---------------------------------------------------------------------------
| Could you please format this better?
| I see that "<script type='text/javascript'>" is left after the raw HTML.
| At line 31
| raw_html |<script src='http://code.jquery.com/jquery-1.4.2.min.js' /><script type='text/javascript'>|
| text --> |//<![CDATA[|
and then the rest seems like the parser is going nuts. Then it renders the javascript into a div on the page. I've tried making it a CDATA block and extra spacing between the jquery and my script.
Help?
I had this same problem, but I managed to get JavaScript to appear in my code by putting a newline after the opening tag.
Different solution that might work in some cases: (the selected answer didn't work for me when I was trying to embed a CodePen example)
add this to your default layout:
<!-- Custom JavaScript files set in YAML front matter -->
{% for js in page.customjs %}
<script async type="text/javascript" src="{{ js }}"></script>
{% endfor %}
In posts where you need some JavaScript files, you can add them in the YAML front matter like so:
---
layout: post
title: Adding custom JavaScript for a specific post
category: posts
customjs:
- http://code.jquery.com/jquery-1.4.2.min.js
- http://yourdomain.com/yourscript.js
---
The async might not be necessary or wanted but you could probably add that as a parameter in customjs. (see YAML front matter for Jekyll and nested lists for details)
I use this code to write JavaScript code in markdown.
just add js after "```" , and you'll have your JavaScript code highlighted.
```js
const myvar = "hello"
module.exports.response = response = ()=>{mycode here}
```
Markdown supports inline XHTML but not Javascript.
The example they give on their site shows an empty <script> tag containing a newline. Maybe that's it?
I found that escaping the closing '>' symbol in both, the opening and closing 'script' tags, will display it correctly, for example:
If you type the follwing:
<script\>... javascript code...</script\>
It will be rendered like this:
<script>... javascript code...</script>
That's just my two cents.
I built an express server with a library called Showdown that converts markdown to HTML, and also will let you use HTML in your markdown file, and this is how I am able to use javascript and also link to my css file.
TOC.md
<script src="/js/toc"></script>
server.js
app.get('/js/toc', (req, res) => {
fs.readFile(path.join(__dirname, 'public', 'js', 'toc.js'), 'utf-8', (err, data) => {
if(err) throw err;
res.set({
'Content-Type': 'text/javascript'
})
res.send(data)
})
})
Or you could do it using express static middleware. You would just need to put your javascript file inside a folder called public.
TOC.md
<script src="/static/js/toc.js"></script>
server.js
app.use('/static', express.static('public'))
You could use pandoc, which handles this input (and javascript generally) just fine.
To my experience, markdown will outpus javascript text as plain text as long as you remove the code formatting that may confuse markdown.
remove comments from javascript, as /* ... */ is translated to < em>
remove the space indent in the front of each line. < p> may be inserted according to your indentation.
Basically what I do is to review the generated html and find out what extra tags are inserted in between my javascript code by markdown. And remove the formatting that generates the extra tag.
A good idea is to have local and cloud js sources separated:
In the post file:
cloudjs:
- //cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.min.js
- //cdnjs.cloudflare.com/ajax/libs/topojson/1.6.9/topojson.min.js
localjs:
- datamaps.world.min.js
- custom.js
In the default file after footer inclusion:
{% for js in page.cloudjs %}
<script type="text/javascript" src="{{ js }}"></script>
{% endfor %}
{% for js in page.localjs %}
<script type="text/javascript" src="{{ "/assets/scripts/" | prepend: site.baseurl | append: js }}"></script>
{% endfor %}
Just indent the first line contains < script > tag.

Categories