jade script loading sequence seems screwy when using includes, extends, and blocks - javascript

Okay, I'm going to try to simplify this example as much as possible. Here's my problem.
I'm using node and express with jade to generate html. I have a main layout.jade file which at the end of the body contains this:
block scripts
script(src='/javascripts/libs/jquery-1.8.1.min.js')
Then I have a jade partial (_shapes.jade) which has the following code:
block append scripts
script(src='/javascripts/wire.js')
Then I have my jade file (properties_panel.jade) which generates the html:
extends ../layout
include _shapes
block controls
include ../_controls
The wire.js file needs jQuery to run.
The html output from jade is exactly as I would expect it to be. I have a block of script tags at the end of the body tag, and in the correct order (jQuery first).
The problem is that jQuery is not being loaded by the browser first. BUT, then it seems to also load the file again after jQuery has loaded. I have deduced this because my wire.js file is wrapped in a self-executing anonymous function like this:
!function (context, $) {
console.log($);
}(this, window.jQuery);
And in my console I get 2 logs. the first one says 'undefined' and the second one logs jQuery correctly.
So here's the weird part though. If I comment out the script line from my _shapes.jade, and instead add it to the layout.jade file after the jQuery import line, it generates the exact same html file, but everything loads in the correct order then.
Using the chrome developer tools, I can see the load order in the resources tab and even though the html does not change at all, the load order changes depending on the way the jade file generates the same identical html.
Am I doing something wrong? I'm relatively new to jade, so I may very well be.
Thanks!

You should use 'extends layout' in your shape:
extends layout
block append scripts
script(src='/javascripts/wire.js')

Related

Only last javascript file linked with script tag is working

I linked all the javascript files in the header.php at atime. I included header.php in all pages
When I link the javascript files like this
<script src='js/home.js'></script>
<script src='js/disc.js'></script>
<script src='js/que.js'></script>
only last file js/que.js is working.
Make sure that the 'src' is referring to the correct file directory where the script is located. If you are using an IDE such as VS, then you may drag the file into the code and the IDE will automatically create the reference for you.
Unless you have problem with directory structure or you file name does not match with src attribute of script tag, there should not be any problem with. Please try to use type="text/javascript" and make sure your script tags are after header tag or just before </body> tag. Also keep sequence of files loading if any file depends on another file variable or any function. If it still does not work use try to see if there is any error in your code in console window.
I now I'm going to get voted down for this but oh well. I don't have enough points to comment which is what I would do but..oh well.
Okay it depends on what the scripts are doing. If you link the scripts in the head for you HTML page, and try a var element = document.getElementById("theID"); this will return null due to the fact that the browser has yet to read the HTML and hasn't had a chance to create a DOM (Document Object Model) tree. For a problem like this check out
<script>
function load() {
console.log("load event detected!");
}
window.onload = load;
</script>
This will assign window to an event/callback that will be invoked after the page has had time to load.
Look at where your JavaScript is used, and what it should be doing. Would those elements be rendered yet. Are you writing functions but not actually calling them (this happens A LOT)? It would be better if you described what the code was doing and your experience with HTML and JavaScript. Remember that the browser interprets the JavaScript as it encounters it, you can put script tags anywhere in your HTML file, not just in the head. Also are the .js files in the same directory as the HTML file or are the two non working .js files in the same directory as "js/que.js"? If not move them to the same file or use a relative or absolute path.

JavaScript file dependend on JavaScript code block in Yii2 (for dojo configuration)

I'm trying to register the dojo javascript files with Yii 2.0.
According to the dojo documentation, the code block for dojo config must be loaded before the actual dojo.js in order to be considered. However, in the HTML output my custom javascript code is always loaded after dojo.js.
This is my code:
$this->registerJs('dojoConfig="async:true,isDebug:true";', $this::POS_HEAD,'dojoconfiguration');
$this->registerJsFile('/dojo_toolkit/dojo/dojo.js', ['depends' => [\yii\web\JqueryAsset::className()], 'position' => yii\web\View::POS_HEAD]);
And in HTML it looks like this:
<script src="/dojo_toolkit/dojo/dojo.js"></script>
<script type="text/javascript">dojoConfig="async:true,isDebug:true";</script>
Any advise?
For the same position Yii2 always puts the inline scripts first and then the actual external files. So you can't fix this by adding them both to the <head>.
Its best to give the registerJsFile() call a POS_END to load it at the very end. It will still be loaded before the document.ready() call is made.
That way you can be sure that the configuration in the header is parsed before the load. Worst case scenario you can use POS_BEGIN to load it right after the body tag is opened, but since loading javascript is blocking I would try to avoid that.

Jade best practices for including JavaScript files?

I have a page-specific JavaScript code that gets loaded with that page. The problem is, it depends on jQuery. I placed script(src='/js/lib/jquery.js') at the end of body, as recommended.
Using this approach, I get Can't find variable: $ because I am trying to execute page-specific JavaScript that depends on jQuery before jQuery is loaded.
Is there any way to make this work without moving script(src='/js/lib/jquery.js') to the head section?
I have even tried doing this, but I still get Can't find variable: $:
// layout.jade
script(src='/js/lib/jquery.js')
block scripts
// login.jade
block scripts
script(type='text/javascript')
$('form').validate();
Edit: TJ Hollowaychuck has posted a link here to a similar question, but those URLs is no longer valid: Best practices for JavaScript in Jade templates
Here are the updated URLs TJ was pointing to:
https://github.com/visionmedia/express/blob/master/examples/jade/views/users/index.jade
https://github.com/visionmedia/express/blob/master/examples/jade/index.js#L34
However, I believe your real problem is on the client, not the server, where you want to wrap your jQuery inside of this:
$(document).ready(function() {
// put all your jQuery goodness in here.
});
This is (part of) my layout.jade
doctype html
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
body
block content
include scripts
block scripts
I include a scripts.jade which contains my common scripts (like jQuery and configuration bits) and then all the scripts defined inside the single pages with a simple
block scripts
script.
alert("Hello!");

How to automatically put JS files into a AJAX-called page?

Into my app I have included all needed JS files (my scripts, libraries such as Twitter Bootstrap etc.).
The problem is, that when I have a request which is called via AJAX, so in the called page are not included the JS files, which are included in my app and I have to include them into the called page.
Example: my_scripts.js contains lots of JS functions.
link to page called through AJAX
<a href="/articles/create_new" data-remote="true>Create New Article</a>
/views/articles/_create_new.html.haml
...some content of this file.. #here doesn't work the functions from the file "my_scripts.js"
when I put into the /views/articles/_create_new.html.haml this link
= javascript_include_tag "my_scripts"
...some content of this file..
so then in the /views/articles/_create_new.html.haml those JS functions working.
I would like to ask you, if exist any way, how to automatically put all JS files in my every single AJAX pages, because always include the JS files into an AJAX pages is not good way...
Thanks
use a script loader like RequireJS or $cript.
Have your pages reply 2 things also: the content and the scripts to load. This is best using JSON like:
{
"content" : "content here",
"scripts" : ["an","array","of","script","urls"]
}
then when the data is returned, parse and paint the content and after that, use the script loaders to load the scripts. Actually, you can make your own script loader. It's just a matter of dynamically creating a <script> tag, put it in the <head> and give it an src
I would achieve this in one of three ways:
jQuery
From http://api.jquery.com/load/:
Script Execution When calling .load() using a URL without a suffixed
selector expression, the content is passed to .html() prior to scripts
being removed. This executes the script blocks before they are
discarded. If .load() is called with a selector expression appended to
the URL, however, the scripts are stripped out prior to the DOM being
updated, and thus are not executed. An example of both cases can be
seen below:
Here, any JavaScript loaded into #a as a part of the document will
successfully execute.
$('#a').load('article.html');
However, in the following case, script
blocks in the document being loaded into #b are stripped out and not
executed:
$('#b').load('article.html #target');
Basically, you can add the JS references to the HTML returned by Ajax request and jQuery will execute them.
RequireJS or simular
Rather than return straight HTML, return the HTML as part of a JSON bundle that also contains an array of script references:
{
html: '<p>stuff</p>',
scriptRefs: [ 'js/one.js', 'js/two.js' ]
}
I would then iterate through the scriptRefs array with something like RequireJS.
Just add the code to base page
In all honesty, I'm more likely to just do this.

Calling a JavaScript object class that's in a separate .js file

I have created a string builder JavaScript object and I'm using it with many different .js files in my project.
Can I create this class in a separate .js file and call it from all the other scripts that instansiate it, just like a C# class file?
Is this possible, or do I continue copying and pasting it into the bottom of every .js file that uses it?
Yes, this should not be a problem. Just include the .js files in the correct order in your html pages.
If you include the file in your main HTML page with your other js, you can then use the "class" as you wish:
<script src="js1.js" type="text/javascript"></script>
<script src="js2.js" type="text/javascript"></script>
In the above example, you can now instantiate a new instance of an object from js1.js with the code in js2.js. To do this with pure javascript, you would have to add the script tag to the DOM, or use AJAX to fetch the script file and eval() it.
// Create a <script> element
var scriptEl = document.createElement("script");
scriptEl.src = "js2.js";
scriptEl.type = "text/javascript";
// Append it to the <head>
document.getElementsByTagName("head")[0].appendChild(scriptEl);
To be perfectly correct, it's not the order of inclusion that matter, but rather the order of executing code. In most cases, Andy's and Segfault's instructions are just fine, but sometimes including the class file before its consumers isn't sufficient. For example, if you use ExtJS and you happen to define your class inside an onReady handler like this:
Ext.onReady(function() {
myClass = ...
}.bind(this));
then it won't get executed by the time your second src file is included into the page and executed.
I know, the example is a bit far-fetched :) but just make sure that your code is executed in the right order, not just included in the right order.
I came across this question and I wanted to add something (which probably wasn't there a few years ago).
Even thought you can add every single script to your "index.html" it's not a very beautiful practice (imho). Especially if you consider that you may want to write a extension (~ framework). You don't want to annoy the user with a bunch of script tags he has to add to his code. What you want is a single line like this:
<script src="yourFramework" (...) />
However, with the use of RequireJS you are able to achieve this. You've the freedom to separate your code and "your user" still don't have to add a novel to his "script section".

Categories