Moving javascript into body - javascript

I am working in an ASP.NET MVC project that uses a lot of #section scripts blocks. We also use a lot of partial views. Currently, I have our global JS (global.js) rendered in the <head> element, which blocks the rest of the page from loading until it has finished loading. I want to move this JS into the body, but because my partial views are reliant on the global.js, this becomes a problem. The rendered HTML turns out to be:
<html>
<head>
<title>Page</title>
<!-- Scripts/styles here -->
</head>
<body>
<!-- Partial A -->
<div id="PartialA">Partial A</div>
<script type="text/javascript">
$(function(){
Foo.bar();
});
</script>
<script type="text/javascript" src="global.js"></script>
</body>
</html>
And global.js:
var Foo = {};
Foo.bar = function(){
console.log("I did Foo.bar()!");
}
Is there anything I can do to place my global.js just before the </body tag while still allowing the JS that uses global.js to exist higher up in the body? Maybe some sort of custom "ready" event I can subscribe to?

why not in Partial A
window.initPartialA = function () {
Foo.bar();
}
and in Global
if (window.initPartialA) {
initPartialA();
}
This is really gross, I would figure out a way of how to organize your script tags in asp rather than doing this.

Related

Function not defined from different js file (NOT an order problem) - IE Only

Why do I get a javascript error (function not defined) on Internet Explorer when I try to call a function that lives inside a different js file?
I'm using laravel blades, this is my parent template:
<!DOCTYPE html>
<html>
<head>
<!-- METAS -->
<title>#yield('titulo')</title>
#yield('css')
</head>
<body>
#include('navbar')
#yield('content')
#include('footer')
<!-- Here I have jquery and bootstrap js files... -->
<script src="{{ asset('js/sitio/custom.js') }}" type="text/javascript"></script>
#yield('js')
</body>
</html>
So within the extending view I have:
#extends('layouts.template')
#section('content')
<button id="button" type="button">Click me</button>
#endsection
#section('js')
<!-- Here I have a js file that calls a function that lives inside custom.js -->
<script src="{{ asset('js/some-js-file.js') }}"></script>
#endsection
Basically I have a button that when clicked needs to send some data over ajax:
Code inside some-js-file.js:
$(document).ready(function(){
$('#button').on('click', function(){
sendAjax(); //the error is here, I get a 'sendAjax is not defined'
})
});
Code inside custom.js:
//this function is declared inside the global scope
function sendAjax(){
//do things
}
It's also worth mentioning that the code segment that calls the custom.js file's function gets executed inside a $(document).ready().., also, this only happens with internet explorer, in other browsers such as firefox, chrome and safari works always fine.
I've read a suggestion to change the location of my custom.js file and move it inside <head> tag but I would need to also move jquery and bootstrap js libraries because that custom file makes use of them, and according to this answer, it is NOT recommended to move jquery inside <head> tags because of performance. How can I solve this?

Razor generates jQuery too late for custom script using it despite Scripts.Render order

I've asked why the below doesn't work and got a very clear answer.
<head>
...
<script src="Stuff.js" type="text/javascript"></script>
</head>
<body>
...
#Scripts.Render("~/bundles/jquery")
</body>
So I've changed that into this.
<head></head>
<body>
#RenderBody()
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/Stuff.js")
</body>
However, I get the same misbehavior. Based on the diagnostics from the linked answer, I'm guessing that the scripts still don't render in the right order. How do I control it? Should I move both to header instead?
The generated markup ends like this.
</form>
</div>
<script src="/Scripts/jquery-1.10.2.js"></script>
<script src="Stuff.js"></script>
</body>
</html>
As asked - I'm adding a screenshot of the network tab showing scripts. There are other resources as well (images and stuff) but none of them is 4xx, no weird messages and I've turned them each off, still hitting the same problem.
Working in Default.js (formerly Stuff.js).
window.onload = function() {
console.log($(this));
};
Producing error in Default.js (any of the lines).
//$(document).ready(function () { alert("ready"); });
$(window).onload(function () { alert("onload"); });
You should use
$(window).load(function () { alert("onload"); });
onload is JavaScript native event, but in JQuery is load
Please refer to the following post for more details :
difference between $(window).load(function() { and $(document).ready(function() {
The second point and most importantly is you have the following
#RenderBody()
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/Stuff.js")
If there any JQuery call in your views, let say you needed to call something in your home page, then JQuery library is not defined yet. Because Jquery renders after RenderBody
What you need to do is put a Section and and render the section after Jquery is loaded
You should have the following in your layout
#RenderBody()
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/Stuff.js")
#RenderSection("Scripts", required: false)
And in your views put the javascripts calls in the section
#section Scripts {
<script type="text/javascript">
//<![CDATA[
$(document).ready(function() { alert ('Hi'); });
//]]>
</script>
}
I hope this helps

How to create Backbone View in a separate js file

I'm trying to understand how to modularize the Backbone ToDo tutorial
Originally everything is inside the same file, but if I try to extract to another file:
var TodoView = Backbone.View.extend({
...
});
then this throws an error:
var view = new TodoView({model: todo});
**Uncaught TypeError: undefined is not a function**
It's probably due to a scope issue, but I don't know how to create a reference inside the $(function() so I can create this new object inside the main function.
Assuming that your first code part is TodoView.js,
and your second code part is app.js.
Write your html file like this,
<html>
<head>
<script type="text/javascript" src="js/TodoView.js"></script>
<script type="text/javascript" src="js/app.js"></script>
</head>
<body>
// your dom
</body>
</html>
(Edited, at 2015-07-27)
sorry for my late reply.
how about this?
<html>
<head></head>
<body>
<!-- your dom -->
<script type="text/javascript" src="js/TodoView.js"></script>
<script type="text/javascript" src="js/app.js"></script>
</body>
</html>
In many case, most javascript codes are appended to just before </body>, so that javascript can use your dom!
You can use something like require.js to load your external files and manage dependancies.
Ok, the solution was to move the script references to the end of the body instead of inside the head tags.
I think that the reason is that TodoView.js is making use of templates that were defined in the body, and since the js file was being loaded before the body, the templates were not yet available.

Meteor - Ckeditor Integration

I'm not sure if there has been a change in the way Meteor loads items, or the way it handles jquery, but I'm having an awful lot of trouble getting ckeditor to come up.
Main Template (Iron-router):
<template name="layout">
<head>
<script type="text/javascript" src="js/ckeditor/ckeditor.js"></script>
<script type="text/javascript" src="js/ckeditor/adapters/jquery.js"></script>
</head>
.....
</template>
Independent Editor Template:
<template name="editor">
<div class="editor_container">
<textarea class="editor"></textarea>
</div>
</template>
Ckeditor located at public/js/ckeditor, any time I try to do the Template.editor.rendered() technique, or even just trying to type $('.editor').ckeditor(); into the console, I get an error of:
$('.editor').ckeditor();
VM48825:2 Uncaught TypeError: undefined is not a function
Any ideas?
Try taking the <head> section out of the layout template. Reading here I believe the <head> section is treated specially be meteor (see: http://docs.meteor.com/#/full/structuringyourapp) and that it being inside a template may be causing the JS to actually not be loaded. Just a guess though.
<head>
<script type="text/javascript" src="js/ckeditor/ckeditor.js"></script>
<script type="text/javascript" src="js/ckeditor/adapters/jquery.js"></script>
</head>
<template name="layout">
.....
</template>
You can use IRLibLoader from iron:router into the onBeforeAction like this.
Router.route('/editor', {
name: 'editor',
template: 'layout',
onBeforeAction: function () {
var ckEditor = IRLibLoader.load('/js/ckeditor/ckeditor.js');
var adapter = IRLibLoader.load('/js/ckeditor/adapters/jquery.js');
if(ckEditor.ready() && adapter.ready()){
console.log('The 2 JS just finish load');
this.next(); // Render the editor page
if(Meteor.isClient){
Template.editor.rendered = function(){
$('.editor').ckeditor();
console.log("loading coeditor when template fully rendered");
}
}
}
}
});
Alternative on the main layout you can use this.
<head>
<script type="text/javascript" src="js/ckeditor/ckeditor.js"></script>
<script type="text/javascript" src="js/ckeditor/adapters/jquery.js"></script>
</head>
<template name="layout">
{{> yield}}
</template>
<template name="editor">
<div class="editor_container">
<textarea class="editor"></textarea>
</div>
</template>
And do the same rendered function
Template.editor.rendered = function(){
$('.editor').ckeditor();
//or make a little delay (1sec)
Meteor.setTiemout(function(){
$('.editor').ckeditor();
},100)
}
There are several problems with your code :
You can't put <head> sections inside another template, it must be done outside all templates.
The path to your JS files are broken, you must prepend a slash to them to reference files in the public directory.
Loading scripts in <head> sections is not a good idea because they will be loaded when your app first loads for every user, even if they never use the editor.
Here is a solution where we load every scripts asynchronously using jQuery promises when the editor template is rendered, and only then initialize the CKEditor.
Template.editor.rendered=function(){
var template=this;
$.when(
$.getScript("/js/ckeditor/ckeditor.js"),
$.getScript("/js/ckeditor/adapters/jquery.js")
).done(function(){
template.$(".editor").ckeditor();
});
};

Calling a function from one JavaScript file which requires another

I am trying to call a function written in one JavaScript file from another JavaScript file. I have the following code, but it doesn't work:
My HTML file
<script type="text/javascript" src="js1.js"></script>
<script type="text/javascript" src="js2.js"></script>
<script language="javascript">
js1();
</script>
js1.js
function js1()
{
alert("Hello from js1");
js2();
}
js2.js
function js2()
{
alert("Hello from js2");
}
What can I do?
Try changing the order
<script type="text/javascript" src="js2.js"></script>
<script type="text/javascript" src="js1.js"></script>
<script language="javascript">
js1();
</script>
Because you call js2(); inside js1.js, so the script js2.js should be executed before.
In your case, i think it should still work without changing orders like this because you call js2(); inside a function. When this script is executed:
function js1()
{
alert("Hello from js1");
js2();
}
Even the js2.js is not executed yet, but you do not actually call js2(); at this time.
Just try it to see if it works.
I'm going to assume that's your entire HTML page.
In order to have those scripts run, you need to have those JavaScript files in the same folder as your webpage, and to actually have a proper HTML page!
In your HTML page, you need to include the references to your js1 and js2 files in either the head or body, and include the script you've written in the HTML page itself in the body so that it'll execute when it's loaded:
<!DOCTYPE html>
<!-- ^ Declaring this DOCTYPE means this is a HTML5 page. -->
<html>
<head>
<!-- This will load your scripts into the document. -->
<script src="js1.js"></script>
<script src="js2.js"></script>
<!--
In a HTML5 page, you don't need to include the
'type="text/javascript"' attribute on script tags.
They're treated as having that by default, unless you say otherwise.
-->
</head>
<body>
<!--
You could also include your scripts here, but I'll
just leave these commented out since they're already included.
<script src="js1.js"></script>
<script src="js2.js"></script>
-->
<script>
js1();
</script>
<!--
You don't need 'language="javascript"' on a script tag.
Use the type attribute, or nothing in a HTML5 page.
-->
</body>
</html>

Categories

Resources