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

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.

Related

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.

Deferring dynamically added Javascript

I need to load some Javascript dynamically after the page has loaded.
Something like this:
page loads
page adds script element with src = "file1.js"
page adds script element with src = "file2.js"
file2.js has a dependency on file1.js - it adds properties to an object defined in file1.js
The problem is that file2.js is loading first (because it is smaller), and is immediately throwing an error because its dependency doesn't exist.
Is there a way for me to defer evaluation/execution of these new scripts until they have all loaded. (There is actually more than two scripts)
If I were to just embed these scripts in a page normally in authored HTML, then it seems that the browser loads all scripts, then evaluates them. But it is behaving differently because I'm adding script elements on the fly.
Thanks
There's a library called RequireJS that handles exactly this situation, and handles every situation you never realized were problems - http://requirejs.org/docs/start.html
Can't you wrap the contents of the files in functions and call them after everything has loaded?
Two suggestions for you:
Have a look at http://requirejs.org/ It solves this problem, among
others.
Or, roll your own simple js loader function. It would be a function that
uses ajax to load a script and then calls a callback when it's done.
Call this loader function in a nested way so that you load your
scripts in the right order.

Managing page specific Javascript: 1 big file with conditionals or multiple files

In my project I have a load of functions that are used on every page, so I have put these in a single javascript file common.js and have included it in my footer template. My questions is, what is the best way to handle page-specific javscript?
For example, on one of my pages I have a google map. If my map js code is run on a page where I don't have an element with id map_canvas, I get an error.
Method 1: I could write some PHP which echos an additional script tag requesting map.js if and only if I'm on a map page.
Method 2: I could give the <body> of my map page an id of "map_page", then I could write a conditional clause in common.js along the lines of:
if (#map_page exists){
put contents of map.js here
}
The problem with method 1 is that it increases the number of requests to the server.
The problem with method 2 is that it bloats my common javascript file.
Please can somebody explain, which, if any would be the preferred method to do this, or if neither are suitable, what I should do instead?
I have approximately 10 page-specific javascript files to deal with.
Thanks
I would say that simpler is better. On every page, just add a script tag calling map.js. Or, in your common.js, you don't need to paste all of map.js's code. You can just create a new script tag with the js and call map.js like that. I would not recommend the php method. The easiest and simplest, therefore the least likely to be buggy method, is just to add another script tag to the pages that need it. Or if that is not an option, common.js could include this:
if(need map.js){
var mapjs=document.createElement("script");
mapjs.type="text/javascript";
mapjs.src="map.js";
document.body.appendChild(mapjs);
}

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 write javascript code using external files only

When using HTML5 Boilerplate, you are given a script.js file and the jquery file are all loaded after the body.
How do I know when to call certain code for a specific page? For eg. What if on /maps I want to load google maps dynamically, how do I accomplish this without putting it on the page and using script.js file while having it not load the map for all pages?
Basically, how do I structure my code when I can't have any script in my pages? How do I know what code to call for a particular page?
Script files that are included are immediately executed, so inside the script file you could have a section check the URL of the page you're on.
For example, something like this:
if (window.location.href === "http://myapp.com/maps") {
// call the map function or whatever ...
}
But, out of curiosity, why can't you add a script file to the specific page you're on? I'd only recommend the solution above if you absolutely cannot edit the HTML of your pages.
I too have the same question. I searched and just found these two
http://paulirish.com/2009/markup-based-unobtrusive-comprehensive-dom-ready-execution/
http://www.viget.com/inspire/extending-paul-irishs-comprehensive-dom-ready-execution/
I am going through of this, and not yet completely reviewed. See if it is useful to you in between.

Categories