Proper way to call javascript handler - javascript

I have a huge JS file and want to divide it, for example, I have this one:
page.html
<!-- some tags and jquery include... -->
<script src="example.js"></script>
<!-- externalHandlers only needs for second example, in original working example It's empty -->
<script src="externalHandlers.js"></script>
<script>
$(document).ready(function(){
var something = new Something('someValue');
);
</script>
<!-- some tags... -->
example.js
var Something = (function (document) {
"use strict";
var Something = function(x){
//initialize some stuff
};
Something.prototype.func1 = function(){
//do things
}
Something.prototype.func2 = function(){
//do things
}
//more funcs
$(document).on('click', 'a.some-class', function (e) {
//do things when click
});
$(document).on('click', 'a.some-class-2', function (e) {
//do things when click
});
return Something;
})(document);
Above code works fine, but I want to externalize click handlers in another js file. I tried this:
example.js (new)
var Something = (function (document) {
"use strict";
var Something = function(x){
//initialize some stuff
};
Something.prototype.func1 = function(){
//do things
}
Something.prototype.func2 = function(){
//do things
}
//more funcs
$(document).on('click', 'a.some-class', handlerFunction);
$(document).on('click', 'a.some-class-2', function (e) {
//do things when click
});
return Something;
})(document);
externalHandlers.js
function handlerFunction(){
//do some stuff
}
But browser console show me errors
ReferenceError: handlerFunction is not defined
TypeError: Something is not a constructor
How can I do something like that I want? It's possible?

Make sure externalHandlers runs first, so that handlerFunction is defined when example.js runs, so that example.js can properly reference handlerFunction without an error, and so that Something gets defined properly:
<script src="externalHandlers.js"></script>
<script src="example.js"></script>

try this code..
<script type="text/javascript" src="externalHandlers.js"></script>
<script type="text/javascript" src="example.js"></script>
<script>
$(document).ready(function(){
var something = new Something('someValue');
});
</script>

Related

How can I split the same function in two parts?

Let's say I have the following structure, just an example:
(function number1( $ ) {
$.fn.abcd = function( options ) {
heyyou.find(".123").css({});
heyyou.find(".456").css({});
var delay = 1000;
var site = "http://url";
setTimeout(function(){ window.location.href = site; },delay);}
$("#button").on('click', function(){ window.location.href = site;});
return this;
}( jQuery ));
And what I believe I need to do is something like this:
//part1
(function number1( $ ) {
$.fn.abcd = function( options ) {
heyyou.find(".123").css({});
heyyou.find(".456").css({});
return this;
}( jQuery ));
//part2
(function number1( $ ) {
$.fn.abcd = function( options ) {
var delay = 1000;
var site = "http://url";
setTimeout(function(){ window.location.href = site; },delay);}
$("#button").on('click', function(){ window.location.href = site;});
return this;
}( jQuery ));
What I'm trying to achieve here is:
"part1" is going to be inside a js file that's going to be placed inside the header. "part2" is a function that I need to call from a <script></script> later on the DOM.
The thing is that both parts are using the same main function, one is continuing the other.
For example:
<script src="part1.js"></script>
<body>
<script>//part2</script>
<button id="button">Do something</button>
</body>
So basically I want the function to start in the js file, then I'll finish it from another part. I'm not sure how to explain this, it's just that I need the var site to be called separately, as I'm going to use the same script for different pages, I need each page to call for the var site with a different value.
Basically it's a redirect script, so I can't use the same redirection url for every page.
EDITED:
The structure needs to be like this:
mainjs.js:
<header>
<script>
//part1
(function number1( $ ) {
$.fn.abcd = function( options ) {
heyyou.find(".123").css({});
heyyou.find(".456").css({});
return this;
}( jQuery ));
</script>
</header>
Page 1:
//part2
var site google
Page 2:
//part2
var site bing
Page 3:
//part2
var site yahoo
"//Part1" is executed first and is executed in every page.
"//part2" is executed later and each page will have a different url to redirect to, inside "//part2" function.
In reply to Ehsan:
It would have to be like this:
<script type="text/javascript" >
function function1(site) {
//redirect to site
alert(site);
}
</script>
<script type="text/javascript" >
function function2() {
// Do your css thing here.
site = "http://somethingelse";
function2(site);
}
</script>
<button onclick="function2()">Click me</button>
Edit - 3
You are looking for something like this.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
alert(site);
});
</script>
<script type="text/javascript">
var site = "google.com";
</script>
You can create two separate functions, chain them and use global variables to pass the data between them.
<script type="text/javascript" >
var site = "http://url";
function function1() {
// Do your css thing here.
site = "http://somethingelse";
function2();
}
</script>
<button onclick="function1()">Click me</button>
<script type="text/javascript" >
function function2() {
//redirect to site
alert(site);
}
</script>
Edit: You can also pass data by using parameter in function, then you don't need to use the global parameter. It depends on the use case, but I assume passing as a parameter is a much cleaner option.
<script type="text/javascript" >
function function1() {
// Do your css thing here.
site = "http://somethingelse";
function2(site);
}
</script>
<button onclick="function1()">Click me</button>
<script type="text/javascript" >
function function2(site) {
//redirect to site
alert(site);
}
</script>

how to create a js function and use it on another files [duplicate]

I wanted to call a function defined in a first.js file in second.js file. Both files are defined in an HTML file like:
<script type="text/javascript" src="first.js"></script>
<script type="text/javascript" src="second.js"></script>
I want to call fn1() defined in first.js in second.js. From my searches answers were if first.js is defined first it is possible, but from my tests I haven't found any way to do that.
Here is my code:
second.js
document.getElementById("btn").onclick = function() {
fn1();
}
first.js
function fn1() {
alert("external fn clicked");
}
A function cannot be called unless it was defined in the same file or one loaded before the attempt to call it.
A function cannot be called unless it is in the same or greater scope then the one trying to call it.
You declare function fn1 in first.js, and then in second you can just have fn1();
1.js:
function fn1 () {
alert();
}
2.js:
fn1();
index.html :
<script type="text/javascript" src="1.js"></script>
<script type="text/javascript" src="2.js"></script>
You could consider using the es6 import export syntax. In file 1;
export function f1() {...}
And then in file 2;
import { f1 } from "./file1.js";
f1();
Please note that this only works if you're using <script src="./file2.js" type="module">
You will not need two script tags if you do it this way. You simply need the main script, and you can import all your other stuff there.
1st JS:
function fn(){
alert("Hello! Uncle Namaste...Chalo Kaaam ki Baat p Aate h...");
}
2nd JS:
$.getscript("url or name of 1st Js File",function(){
fn();
});
You can make the function a global variable in first.js
and have a look at closure and do not put it in document.ready put it outside
you can use ajax too
$.ajax({
url: "url to script",
dataType: "script",
success: success
});
same way you can use jquery getScript
$.getScript( "ajax/test.js" )
.done(function( script, textStatus ) {
console.log( textStatus );
})
.fail(function( jqxhr, settings, exception ) {
$( "div.log" ).text( "Triggered ajaxError handler." );
});
declare function in global scope with window
first.js
window.fn1 = function fn1() {
alert("external fn clicked");
}
second.js
document.getElementById("btn").onclick = function() {
fn1();
}
include like this
<script type="text/javascript" src="first.js"></script>
<script type="text/javascript" src="second.js"></script>
use "var" while creating a function, then you can access that from another file. make sure both files are well connected to your project and can access each other.
file_1.js
var firstLetterUppercase = function(str) {
str = str.toLowerCase().replace(/\b[a-z]/g, function(letter) {
return letter.toUpperCase();
});
return str;
}
accessing this function/variable from file_2.js file
firstLetterUppercase("gobinda");
output => Gobinda
It should work like this:
1.js
function fn1() {
document.getElementById("result").innerHTML += "fn1 gets called";
}
2.js
function clickedTheButton() {
fn1();
}
index.html
<html>
<head>
</head>
<body>
<button onclick="clickedTheButton()">Click me</button>
<script type="text/javascript" src="1.js"></script>
<script type="text/javascript" src="2.js"></script>
</body>
</html>
output
Try this CodePen snippet: link .
Please note this only works if the
<script>
tags are in the body and NOT in the head.
So
<head>
...
<script type="text/javascript" src="first.js"></script>
<script type="text/javascript" src="second.js"></script>
</head>
=> unknown function fn1()
Fails and
<body>
...
<script type="text/javascript" src="first.js"></script>
<script type="text/javascript" src="second.js"></script>
</body>
works.
This is actually coming very late, but I thought I should share,
in index.html
<script type="text/javascript" src="1.js"></script>
<script type="text/javascript" src="2.js"></script>
in 1.js
fn1 = function() {
alert("external fn clicked");
}
in 2.js
fn1()
Use cache if your server allows it to improve speed.
var extern =(url)=> { // load extern javascript
let scr = $.extend({}, {
dataType: 'script',
cache: true,
url: url
});
return $.ajax(scr);
}
function ext(file, func) {
extern(file).done(func); // calls a function from an extern javascript file
}
And then use it like this:
ext('somefile.js',()=>
myFunc(args)
);
Optionally, make a prototype of it to have it more flexible. So that you don't have to define the file every time, if you call a function or if you want to fetch code from multiple files.
first.js
function first() { alert("first"); }
Second.js
var imported = document.createElement("script");
imported.src = "other js/first.js"; //saved in "other js" folder
document.getElementsByTagName("head")[0].appendChild(imported);
function second() { alert("Second");}
index.html
<HTML>
<HEAD>
<SCRIPT SRC="second.js"></SCRIPT>
</HEAD>
<BODY>
method in second js<br/>
method in firstjs ("included" by the first)
</BODY>
</HTML>
window.onload = function(){
document.getElementById("btn").onclick = function(){
fn1();
}
// this should work, It calls when all js files loaded, No matter what position you have written
});
// module.js
export function hello() {
return "Hello";
}
// main.js
import {hello} from 'module'; // or './module'
let val = hello(); // val is "Hello";
reference from https://hype.codes/how-include-js-file-another-js-file
My idea is let two JavaScript call function through DOM.
The way to do it is simple ...
We just need to define hidden js_ipc html tag.
After the callee register click from the hidden js_ipc tag, then
The caller can dispatch the click event to trigger callee.
And the argument is save in the event that you want to pass.
When we need to use above way ?
Sometime, the two javascript code is very complicated to integrate and so many async code there. And different code use different framework but you still need to have a simple way to integrate them together.
So, in that case, it is not easy to do it.
In my project's implementation, I meet this case and it is very complicated to integrate. And finally I found out that we can let two javascript call each other through DOM.
I demonstrate this way in this git code. you can get it through this way. (Or read it from https://github.com/milochen0418/javascript-ipc-demo)
git clone https://github.com/milochen0418/javascript-ipc-demo
cd javascript-ipc-demo
git checkout 5f75d44530b4145ca2b06105c6aac28b764f066e
Anywhere, Here, I try to explain by the following simple case. I hope that this way can help you to integrate two different javascript code easier than before there is no any JavaScript library to support communication between two javascript file that made by different team.
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/style.css" />
</head>
<body>
<div id="js_ipc" style="display:none;"></div>
<div id="test_btn" class="btn">
<a><p>click to test</p></a>
</div>
</body>
<script src="js/callee.js"></script>
<script src="js/caller.js"></script>
</html>
And the code
css/style.css
.btn {
background-color:grey;
cursor:pointer;
display:inline-block;
}
js/caller.js
function caller_add_of_ipc(num1, num2) {
var e = new Event("click");
e.arguments = arguments;
document.getElementById("js_ipc").dispatchEvent(e);
}
document.getElementById("test_btn").addEventListener('click', function(e) {
console.log("click to invoke caller of IPC");
caller_add_of_ipc(33, 22);
});
js/callee.js
document.getElementById("js_ipc").addEventListener('click', (e)=>{
callee_add_of_ipc(e.arguments);
});
function callee_add_of_ipc(arguments) {
let num1 = arguments[0];
let num2 = arguments[1];
console.log("This is callee of IPC -- inner-communication process");
console.log( "num1 + num2 = " + (num1 + num2));
}
better late than never
(function (window) {const helper = { fetchApi: function () { return "oke"}
if (typeof define === 'function' && define.amd) {
define(function () { return helper; });
}
else if (typeof module === 'object' && module.exports) {
module.exports = helper;
}
else {
window.helper = helper;
}
}(window))
index html
<script src="helper.js"></script>
<script src="test.js"></script>
in test.js file
helper.fetchApi()
I have had same problem. I have had defined functions inside jquery document ready function.
$(document).ready(function() {
function xyz()
{
//some code
}
});
And this function xyz() I have called in another file. This doesn't working :) You have to defined function above document ready.
TLDR: Load Global Function Files first, Then Load Event Handlers
Whenever you are accessing an element within a JS file or <script> block, it is essential to check to make sure that element exists, i.e., jQuery's $(document).ready() or plain JS's document.addEventListener('DOMContentLoaded', function(event)....
However, the accepted solution does NOT work in the event that you add an event listener for the DOMContentLoaded, which you can easily observe from the comments.
Procedure for Loading Global Function Files First
The solution is as follows:
Separate the logic of your JS script files so that each file only contains event listeners or global, independent functions.
Load the JS script files with the global, independent functions first.
Load the JS script files with event listeners second. Unlike the other previous files, make sure to wrap your code in document.addEventListener('DOMContentLoaded', function(event) {...}). or document.Ready().

Difference between init events in js file or html template

Is there a difference between lauch js functions from same JS file where they declared after page load, or in html template? When both signed into $(document).ready(function () {...}).
I assume that no, but I ran into a problem when replace my ExampleService.init() function from template to separate JS file.
For example i have that construction:
common.js
var ExampleService= {
catalogSpinner: '',
init: function() {
this.initEvents();
},
initEvents: function() {
var self = this;
$('.example-button').on('click', function() {
//do some logic, append spinner...
self.removeSpinner();
});
},
removeSpinner: function() {
$(this.catalogSpinner).fadeOut('slow', function() {
$(this).remove().css({display: 'block'});
});
}
}
index.html
<script src="js/common.js"></script>
<script>
$(document).ready(function () {
ExampleService.catalogSpinner = '<div class="spinner"></div>'; // css3 animation
ExampleService.init();
});
</script>
That way all works perfect, my catalogSpinner overriden from template, and i can use them like DOM element.
But! if i move ExampleService.init(); to common.js file, like that:
common.js
var ExampleService= {
...
// all the same...
...
};
$(document).ready(function () {
'use strict';
ExampleService.init();
});
index.html
<script src="js/common.js"></script>
<script>
$(document).ready(function () {
ExampleService.catalogSpinner = '<div class="spinner"></div>';
});
</script>
That way it wouldn't work. And throw console error Uncaught TypeError: this.catalogSpinner.fadeOut is not a function
Why it's happens? After all in both cases init functions starts only after full page load, and no matters that i override my variable after starting base functions. What im doing wrong?
About orders in which inits will executed. How i understand its no matter. Cause in any case, second document.ready from template file, always ovverride empty catalogSpinner variable from JS file, before click event happens
It's almost certainly a timing issue. What guarantee do you have that $(document).ready in common.js will fire after the same event handler in your html file (which is what needs to happen according to your implementation)?
Or, you need to make sure that when it occurs in common.js, that code can somehow retrieve the catalogSpinner value.
Also, catalogSpinner needs to be a valid jQuery object, not a string.
It will and it does work in both the cases. To use jQuery methods over DOM elements, you must have valid jQuery selectors which will return objects binded with jQuery methods.
Try this:
case 1:
common.js
var ExampleService= {
catalogSpinner: '',
init: function() {
this.initEvents();
},
initEvents: function() {
var self = this;
$('.example-button').on('click', function() {
//do some logic, append spinner...
self.removeSpinner();
});
},
removeSpinner: function() {
this.catalogSpinner.fadeOut('slow', function() {
$(this).remove().css({display: 'block'});
});
}
};
index.html
<!doctype html>
<html>
<head>
<script src="jquery.min.js"></script>
<script src="common.js"></script>
<style>
</style>
</head>
<body>
<div class="spinner">Spinner</div>
<button type="button" class="example-button">Remove</button>
<script type="text/javascript">
$(document).ready(function () {
ExampleService.catalogSpinner = $('.spinner');
ExampleService.init();
});
</script>
</body>
</html>
case 2:
common.js
var ExampleService = {
catalogSpinner: '',
init: function () {
this.initEvents();
},
initEvents: function () {
var self = this;
$('.example-button').on('click', function () {
//do some logic, append spinner...
self.removeSpinner();
});
},
removeSpinner: function () {
this.catalogSpinner.fadeOut('slow', function () {
$(this).remove().css({display: 'block'});
});
}
};
$(document).ready(function () {
'use strict';
ExampleService.init();
});
index.html
<!doctype html>
<html>
<head>
<script src="jquery.min.js"></script>
<script src="common.js"></script>
<style>
</style>
</head>
<body>
<div class="spinner">Spinner</div>
<button type="button" class="example-button">Remove</button>
<script type="text/javascript">
$(document).ready(function () {
ExampleService.catalogSpinner = $('.spinner');
});
</script>
</body>
</html>

How to call javascript function from ScriptManager.RegisterStartupScript?

I have the following javascript code:
<script type="text/javascript" language="javascript">
$(document).ready(
function () {
// THIS IS FOR HIDE ALL DETAILS ROW
$(".SUBDIV table tr:not(:first-child)").not("tr tr").hide();
$(".SUBDIV .btncolexp").click(function () {
$(this).closest('tr').next('tr').toggle();
//this is for change img of btncolexp button
if ($(this).attr('class').toString() == "btncolexp collapse") {
$(this).addClass('expand');
$(this).removeClass('collapse');
}
else {
$(this).removeClass('expand');
$(this).addClass('collapse');
}
});
function expand_all() {
$(this).closest('tr').next('tr').toggle();
};
});
</script>
I want to call expand_all function via code-behind .
I know I can use something like this, but it does not work and I don't understand used parameters:
ScriptManager.RegisterStartupScript(Me, GetType(String), "Error", "expand_all();", True)
Can you help me?
Because you have your expand_all function defined within anonymous $.ready event context. Put your code outside and it should work.
function expand_all(){
alert('test B');
}
$(document).ready(
function () {
// this won't work
function expand_all() {
alert('test A');
};
});
// will show test B
expand_all();
check this:
http://jsfiddle.net/jrrymg0g/
Your method expand_all only exists within the scope of the function inside $(document).ready(...), in order for you to call it from ScriptManager.RegisterStartupScript it needs to be at the window level, simply move that function outside the $(document).ready(...)
<script type="text/javascript" language="javascript">
$(document).ready(
function () {
....
});
function expand_all() {
$(this).closest('tr').next('tr').toggle();
};
</script>

jQuery trigger click not working in IE

The following works in Chrome and HTML--it clicks five separate elements on page load. IE8 doesn't throw any error, but the click event does not happen. Any suggestions would be appreciated.
<script>
window.onload = function(){
$(document).ready(function(){
var1=document.getElementById("agencyautoclick")
$(var1).trigger('click');
var2=document.getElementById("scaleautoclick")
$(var2).trigger('click');
var3=document.getElementById("modeautoclick")
$(var3).trigger('click');
var4=document.getElementById("infrastructureautoclick")
$(var4).trigger('click');
var5=document.getElementById("topicsautoclick")
$(var5).trigger('click');
});
}
</script>
I originally wasn't using jQuery (just used .click()), but that again did not work in IE8.
All you have written is the same as:
<script>
$(document).ready(function(){
$('#agencyautoclick').trigger('click');
$('#scaleautoclick').trigger('click');
$('#modeautoclick').trigger('click');
$('#infrastructureautoclick').trigger('click');
$('#topicsautoclick').trigger('click');
});
</script>
You are not taking advantage of jQuery =)
don't do
var1=document.getElementById("agencyautoclick")
$(var1).trigger('click');
do
var $var1 = $('#agencyautoclick');
// OR
var $var1 = document.getElementById('agencyautoclick');
and don't forget the semicolon ";" end the end of EACH complete command (line).
further
window.onload = function(){
$(document).ready(function() { /* ... */ });
};
is not good.
You have to decide if you want to load the function on window-load or if you want to load it on document-ready.
just write
<script type="text/javascript">
$(document).ready(function() { /* ... */ });
// OR
$(window).load(function() { /* ... */ });
</script>

Categories