Moving inline Javascript to external .js file - javascript

I have some inline Javascript in my <body> that I'm trying to export to a .js file. I know that normally you would just copy/paste it over, sometimes including it in a document ready function, but something about this one is different. I'm not super fluent in JS and the code wasn't written by me (but was provided free online).
This is how the code is in my file. If you need any more info just ask!
<body>
<script>
(function (window, document) {
var menu = document.getElementById('menu')
, WINDOW_CHANGE_EVENT = ('onorientationchange' in window) ? 'orientationchange' : 'resize';
function toggleHorizontal() {
[].forEach.call(document.getElementById('menu').querySelectorAll('.custom-can-transform'), function (el) {
el.classList.toggle('pure-menu-horizontal');
});
};
function toggleMenu() {
// set timeout so that the panel has a chance to roll up
// before the menu switches states
if (menu.classList.contains('open')) {
setTimeout(toggleHorizontal, 500);
}
else {
toggleHorizontal();
}
menu.classList.toggle('open');
document.getElementById('toggle').classList.toggle('x');
};
function closeMenu() {
if (menu.classList.contains('open')) {
toggleMenu();
}
}
document.getElementById('toggle').addEventListener('click', function (e) {
toggleMenu();
e.preventDefault();
});
window.addEventListener(WINDOW_CHANGE_EVENT, closeMenu);
})(this, this.document);
</script>
</body>
UPDATE:
I was able to wrap the script in a scope (foo = function() {}) and get it to work externally by adding window.onload = function to the HTML page. This was suggested by #marmeladze and worked.

As suggested by #marmeladze, I was able to wrap the script in a scope (foo = function() {}) and get it to work externally by adding window.onload = function to the HTML page.

So what is the real problem to export it in an external js file?
As always i would copy and past code in a new js. Link it to HTML page and write functions that i need as attribute of HTML's tag (ex. "onload=functioname();" in body's tag).
As marmeladze said you can wrap all in an unique scope so you can call it in body.
Maybe you are doing it so if you maybe can explain better your problem would be great.

Related

How to load an es6 module in an html page on the load event

I am new to ES6 modules, please could you let me know how I can import a function from an ES6 module on a web-page and then use that function on a click event on a button.
So far I have defined this module in a file called (ES6Part3Module.js):
export function sayHello() {
return "hi there folks";
}
Then in my html page I have loaded the module in this way:
`<script src="ES6Part3Module.js" type="module"`>`</script`>
I now want some way of creating a click handler for a button on the page:
`<button id="sayHelloButton"`>Say Hello`</click`>
which calls the sayHello() function from my ES6 module.
I have tried creating a local (module) script on my page:
`<script type="module"`>
import sayHello from "ES6Part3Module.js";
window.hello = sayHello;
`</script`>
and then having some jquery on the page which runs on load:
$( function() {
$("#sayHelloButton").click(function() {
alert(hello());
});
});
But when the button on the html page is clicked, I get an error, saying that hello is not defined.
Please could you let me know what I am doing wrong?
Here is an answer using an old version of system.js. I would be interested in an answer using the new version of system.js.
<!--
ref (https://livebook.manning.com/#!/book/angular-2-development-with-typescript/chapter-2/159, p 159, listing2.7)
-->
<!--unpkg is a fast, global content delivery network for everything on npm-->
<script src="//unpkg.com/es6-promise#3.0.2/dist/es6-promise.js"></script>
<script src="//unpkg.com/traceur#0.0.111/bin/traceur.js"></script>
<!--system js, version that was released in 21/08/2016-->
<script src="//unpkg.com/systemjs#0.19.37/dist/system.src.js"></script>
<script>
System.import('./ES6Part3Module.js').then(ES6Part3Module => {
window.hello = ES6Part3Module.sayHello;
});
</script>
<script>
$( function() {
$("#sayHelloButton").click(function() {
alert(hello());
});
});
</script>
you were actually very close to the solution.
after you setwindow.hello=sayHello; (which you can do inside your module, you don't need an inline module to do so), you just set the button's click event to window.hello (instead of just hello), you don't even need to use JQuery for that, you can just do:
<button onclick="window.hello()">Say Hello</button>

Passing reference to object javascript function

I have a function that gets called during a control update where 'This' is passed so the function knows what control is updating. I am also calling the function at page load to get initial values but sending document.getElementById() doesn't seem to work. What should I be passing here?
For example:
<script type="text/javascript">
window.onload = function () {
alert("Got to window.onload");
materialSelectionChange(document.getElementById('SquaresDropDownList'));
};
</script>
in the js file...
function materialSelectionChange(obj) {
alert("Got into function");
}
Also, it does fire the js function on change properly
EDIT
The problem seems to be the load time of the JS document. The function wasn't successfully being called at that point because apparently the JS file hadn't finished loading. Likely because of window.onload. It works if I move the function into the page rather than in the JS file. Is there a way I can add delay so I know the page and it's components are fully loaded?
You are not delegating for window load event, you are invoking it, also your missing quotes around the id:
window.onload = myFunction(document.getElementById(typeSelect));
Try wrapping it around:
window.onload = function() {
myFunction(document.getElementById('typeSelect')); //id in quotes
};
EDIT
You must take care of js file import, import must be first before invoking the function within:
<script src='your-script-file.js'></script>
<script type="text/javascript">
window.onload = function () {
materialSelectionChange(document.getElementById('SquaresDropDownList'));
};
</script>
<select id="typeSelect" onchange="myFunction(this)">
window.onload = function(){
myFunction.bind(document.getElementById('typeSelect'));
}
The problem seems to be the load time of the JS document. The function wasn't successfully being called at that point because apparently the JS file hadn't finished loading. It works if I move the function into the page rather than in the JS file. Is there a way I can add delay so I know the page and it's components are fully loaded?

Calling external JS function from internal JS code block

I have 2 JS blocks that I am working with. One is internal to my HTML. It handles touch functionality. The other is an external file which is a content slider. Basically I want to use the touchevents to control the slider and move to the previous/next slide depending on which direction the user swipes on mobile devices but have more traditional controls on desktops. Is it possible to call a function in the external file from my internal code block.
HTML File
<html>
<head>
<script type="text/javascript" src="js/externalfile.js"></script>
<script>
... lots of code for touchevents ....
function processingRoutine() {
if ( swipeDirection == 'left' ) {
// Function below is in external file
previous();
} else if ( swipeDirection == 'right' ) {
// Function below is in external file
next();
}
</script>
</head>
<body>
Some HTML code
</body>
External JS File
(function($) {
... Functionality to work slider ...
// load the next slide
// These are the functions I am trying to call from above.
function next() {
goToAndPause(counter+1);
};
// load the previous slide
function previous() {
goToAndPause(counter-1);
};
})(jQuery);
Is there an easy way to do this or is there a rotator that has this functionality built in already?
The slider must have been instantiated somehow and you may have a reference to it, i.e. to make the slider work in the first place you might have called something like $('.mySlider').slider();
if you changed that to
window.mySlider = $('.mySlider').slider();
you could then potentially then call mySlider.next() or similar in your "internal" code.
why not just extract your code into an external js file? I don't see any reason you would actually need to have it embedded in the script tag , and in general i think that may be a poor architectural decision.
2nd idea, you could also get to it by declaring a global variable and accessing it, though thats not great practice.
If you don't mind editing the plugin, you could use jQuery's event API.
// external file
(function($) {
....
$(window).on('slider:next', next);
$(window).on('slider:previous', previous);
})(jQuery);
// inline js (this should really live in its own file, too)
function processingRoutine () {
if ( swipeDirection === 'left' ) {
$(window).trigger('slider:next');
} else if ( swipeDirection === 'right' ) {
$(window).trigger('slider:previous');
}
}

Intercept hyperlink clicks

I'm trying to intercept clicks on this link:
<a id="test-button" href="#">Test</a>
with this js:
(function() {
$('#test-button').click(function (event) {
console.log("This code never gets called.")
event.preventDefault();
$('#alert-placeholder').html(['<div class="alert"><a class="close"',
'data-dismiss="alert">×</a>',
'<span>"+message+"</span></div>'].join())
return false;
})
console.log("yes, this code loads");
debugger;
})();
but the URL '#' loads and the code in the click() function doesn't run. What am I missing?
I'm using this code in a flask app using bootstrap.
Seems like you're trying to attach an event handler to the element that doesn't exist yet
(function() {
})();
only creates a local scope but doesn't guarantee DOM to load. To confirm it - add console.log($('#test-button').length); to your code.
What you need is to wrap your code with
$(function() {
// your code is here
});
instead

window.onload in external script gets ignored in Javascript

index.html
<html>
<head>
<script type="text/javascript" src="foo.js"></script>
<script type="text/javascript">
window.onload = function() {
console.log("hello from html");
};
</script>
</head>
<body>
<div class="bar">bar</div>
</body>
</html>
foo.js
// this js file will be completely ignored with window.onload
//window.onload = function() {
console.log("hello from external js");
var bar = document.getElementsByClassName("bar");
// this returns 0 instead of 1
console.log(bar.length);
//};
When window.onload is used in html, window.onload from external js will be ignored.
When window.onload from external js is commented out, bar.length returns 0.
When window.onload from html is removed, window.onload from external js works fine.
Can anyone explain why I can't use both window.onload?
If I had to use window.onload in html, how do tell if window is loaded from external js?
1)The way you're binding, you can have just one method attached to an event. You need to add an event listener for what you want.
window.addEventListener("load", function() { alert("hello!");});
Setting directly a method to the onload event will replace any previously attached method. But if you use listeners instead, you can have many of them bound to an event.
2)If you comment out the onload in your external file, when the document.getElementsByClassName("bar") is called, your document isn't ready yet, then, it will return 0 items.
3)Use the addEventListener as I explained in the first point. If you apply this in both places, it will work like a charm.
onload is a property of window. It acts like any other variable property. When you try to use it twice you're overwriting the original value with your second write.
So your entire external script is ignored when you wrap it in window.onload, because window.onload is then overwritten to be
function() {
console.log("hello from html");
};
If you want to do execute 2 functions, define 2 functions, a and b,
and set window.onload like this:
window.onload = function(){
a();
b();
}
Alternatively, you can bind 2 separate events in the way Alcides' answer suggests. My personal view is that its cleaner to do a single bind with multiple functions since its easier to know whats bound, know what order your functions will execute in, and see everything thats happening in one place, but its mostly a matter of style/preference if the order doesn't matter.
Thats Correct, you are overwriting your own onload, but you can always attach a new event listener to the window like this
function onLoadHandler(){
console.log("hello from external js");
var bar = document.getElementsByClassName("bar");
// page not loaded, so this returns 0 instead of 1
console.log(bar.length);
}
if (window.addEventListener) {
window.addEventListener('load', onLoadHandler); }
else if (window.attachEvent) { window.attachEvent('onload', onLoadHandler ); }

Categories