Jade best practices for including JavaScript files? - javascript

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!");

Related

How to load error trackers from script tag?

I'm working on small .js which is going to be embedded on multiple websites, it will be loaded in a classic way - via script tag: <script src="myscript.js"></script> in sites body tag. I cannot add any more scripts to those sites.
I would like to track errors with error tracker such as Sentry, Rollup or HoneyBadger. However, all of them require being loaded with another script tag, most preferred before everything else.
Note: Those services need to load before everything else to catch errors property.
As I cannot add another script tag in the site's code, I need to execute their code inside my script, but before my actual script code.
I tried taking the content of HoneyBadger javascript library and putting it directly inside my file - it worked, however, I feel like it's terrible practice, as their code is written with modern browsers in mind, and mine supports older ones.
Is there any good way in my situation to load their .js externally?
I don't think that would work because of the way honeybadger.js v0.5 parses the script tag to get those attributes--it looks for the script tag in the dom when it's loaded.
Also, we've moved away from using the data- attributes in honeybadger.js v1.0, which was just released. In that version, you must use Honeybadger.configure to set your API key. Take a look at the new docs here:
https://docs.honeybadger.io/lib/javascript/integration/browser.html
I'd recommend going with v1.0, and using Honeybadger.configure for the configuration.

How I can modularize static HTML file?

I'm a front-end developer. When I write a html code I repeat my self a lot by copy and paste (header section, footer section, etc).
How I can write modularize my html files? Like separate header.html and footer.html, and after that call both in index.html... same as erb in Ruby on rails? (I don't like jade lang)
In PHP we would do something like this:
index.php
<?php
include 'inc/head.inc.php'; //DOCTYPE and <head> stuff
include 'inc/header.inc.php'; //NAV or other top-of-page boilerplate
?>
<div id="uniqueDIV">
//Your unique page-specific divs can go here
</div>
<?php include 'inc/footer.inc.php'; ?>
So, in your head.inc.php file, you just have the usual DOCTYPE and <head> portion of your page file.
In Ruby, it appears the equivalent instruction is something like:
load "inc/head_inc.rb" -- OR --
require_relative "inc/head_inc.rb"
https://practicingruby.com/articles/ways-to-load-code
Another option is to use a bit of js/jQuery to populate parts of the document. If you don't have PHP, this is 2nd best option. It's less optimal than PHP because the js/jQ code will run after the page is fully rendered, which may cause a minuscule (but noticeable) lag before the code appears.
For example:
html
<div id="navbarDIV"></div>
js/jQuery:
<script type="text/javascript">
$(function(){
$('#navbarDIV').load( 'inc/navbar.inc.html' );
});
</script>
Note that you will need jQuery loaded to use the above code. Simple as this line in your <head>:
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
jsFiddle demo
Final note: the script tag can be included in your <head> as an external file, or it can be plopped anywhere in your document with the rest of the html. Whatever works. But <head> as external file, or last element in body (also as an external file) are preferred.
Final final note: the ".inc." naming convention is not required, it's just my own practice. Include file could be named head.html or head.php or etc.
You could consider using something like Swig, which doesn't require a server (you can compile your templates locally).
Swig's syntax is much like Mustache or Handlebars, it uses braces and works inside of normal HTML, so you can retain the HTML syntax you want (unlike Jade).
For separating HTML into files to be reused, you can check out Template Inheritance. You can also see File Inclusion and File Imports.
Here is a small example:
{% include "./header.html" %}
<div id="body">Hello world</div>
{% include "./footer.html" %}
i use gulp, and i want tools for compile file to standard html file. like jade. – Sajad Abedi
For this you can use gulp-swig and build your templates locally in a task.
I have used EJS, which is convenient.
You can have a try.
For HTML files there is no standard way for reusing HTML parts. You have to use into a templating system.
But erb is a templating system and can handle that. See this Stack Overflow answer about "Including one erb file into another".

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

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')

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.

Read content of external script tag with jquery

A common pattern for loading backbone templates is something like:
<script type='text/template' id='foo'>
my template
</script>
----
var whatever = $('#foo').html();
I would like to include the script in an external file like so:
<script type='text/template' id='foo' src='myTemplate.tpl'></script>
But the html() of foo is now empty.
I watched the browser pull the template file down, but I am not sure if it is in the page dom or not. Is there a simple way to reference the content of the script in javascript, or did the browser simply ignore it and throw out the result?
I think to actually execute externally loaded script you have to do an eval() of the contents. You're not adding it to the DOM really since it's script, you're adding it to the JS runtime. There might be other ways of doing it but eval() is generally considered a security hole since malicious code could be evaluated.
What I tend to do is generate template sections on the server so I know all my JS is there when the DOM is ready.
If the point is execute an action just after the script has been loaded you can put a onload attribute on the script tag. If you want to download the content in runtime, then you could use the async download strategy (like Gats pointed).
It´s important keep in mind some important points when using templates for jquery templates in external files, there is an interesting article about jquery templates with external files, you must check it.

Categories