Inside handler.js and I have exported 2 functions. One for initialize() and other handle(). Initialize function use to load handler dynamic based on the application settings. And I have shared variable var handler outside the module.exports function.
handler = new Handler(app); new instance created assign to shared variable var handler. And then inside handle() function shared variable var handler. used
Dynamically require() a file in web request time is not good idea. So initialize() method created and called in application start time.
Let me know suggestion to remove the shared variable 'handler'
var handler;
module.exports = {
initialize : function (app){
var Handler = require(path.resolve(app.basedir, app.settings.handler));
handler = new Handler(app);
},
handle : function handle(ctx) {
var urlToHandle = ctx.url;
return handler.resolveURL(ctx)
.then(function (json) {
ctx.layoutJSON = json;
return ctx;
})
.catch(function (e) {
throw e;
});
}
};
Not sure if I got your right, but if you call the initialize just once you can do something like that:
var app = require('path-to-a-file-which-return-app');
var Handler = require(path.resolve(app.basedir, app.settings.handler));
var handler = new Handler(app);
module.exports = {
handle : function handle(ctx) {
var urlToHandle = ctx.url;
return handler.resolveURL(ctx)
.then(function (json) {
ctx.layoutJSON = json;
return ctx;
})
.catch(function (e) {
throw e;
});
}
};
Now the require will just be called once, since Node will cache it for you.
Related
I have integrated some HTML/JS Code into my Vaadin WebApplication by creating an AbstractJavaScriptComponent. The Component almost works as intended.
How do I call the passInfo() method defined in the "connector.js" without having to manually click the Button defined in the innerHTML of the "chessControll.JsLabel" Component in "chessControll.js". My Goal is to pass Information, when the onChange Event of the init() function is called, which is located in the same file "chessControll.js", but not part of the Component.
I have already tried to create a Custom Event and then dispatch it whenever onChange() in the init() function is called, it worked as long as I didn't listen for the Event inside of my Component (chessControll.js, chessControll.JsLabel). It seems it can only be accessed in a static way.
How can I access the chessControll.JsLabel in "chessControll.js" from the init() function and then dispatch the button click or listen for events inside the component to achieve the same?
connector.js:
com_*myname*_*applicationName*_JsLabel = function() {
var mycomponent = new chessControll.JsLabel(this.getElement());
connector = this;
this.onStateChange = function() {
mycomponent = this.getState().boolState;
};
mycomponent.click = function() {
connector.passInfo(true);
};
};
chessControll.js:
var chessControll = chessControll || {};
chessControll.JsLabel = function (element) {
element.innerHTML =
"<input type='button' value='Click'/>";
// Getter and setter for the value property
this.getValue = function () {
return element.
getElementsByTagName("input")[0].value;
};
var button = element.getElementsByTagName("input")[0];
var self = this;
button.onclick = function () {
self.click();
};
};
var init = function() {
var onChange = function() {
/*Click Button defined in JsLabel Component */
};
};$(document).ready(init);
I figured out what the problem was.
The architecture of Java Web Applications doesn't allow a simple communication like i did in my example. The JavaScript made a call from the Client Side to the Server Side Vaadin Component.
I integrated the whole JavaScript, including the init function, as a Component. This way i can call the method from the init function because everything is known on the Server Side.
edited chessControll.js :
var chessControll = chessControll || {};
chessControll.JsLabel = function (element) {
element.innerHTML =
"<input type='button' value='Click'/>";
// Getter and setter for the value property
this.getValue = function () {
return element.
getElementsByTagName("input")[0].value;
};
var button = element.getElementsByTagName("input")[0];
var self = this;
//deleted bracket here
var init = function() {
var onChange = function() {
self.click();
};
};$(document).ready(init);
} //<-- that Simple
I am trying to call one of the function in from .js file in angular whenever a route change happen.
This is my code in the javascript file and I need to call need to call the appData function in angular.
The console.logs for console.log(parsedJsonResponse); and console.log(appData) works fine and I am getting the JSON response.
window.dataLayer = (function () {
var dataCall = function () {
return new Promise((resolve, reject) => {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4) {
if (this.status == 200) {
resolve(this.responseText);
} else {
console.log(this.status + '.....' + this.statusText)
}
}
};
xhttp.open("GET", "http://localhost:4200/assets/sample.json", true);
xhttp.send();
})
}
dataCall().then((CallResponse) => {
getData(CallResponse)
});
window.addEventListener("load", function (event) {
appData();
})
var getData = function (cData) {
jsonResponse = cData.replace(/'/g, '"');
parsedJsonResponse = JSON.parse(this.jsonResponse);
var appData = parsedJsonResponse['content']['copy$$' + applicationContent];
console.log(parsedJsonResponse);
}
I am calling appData function in
var appData = function (applicationContent) {
var appData = parsedJsonResponse['content']['copy$$' + applicationContent];
console.log(appData)
}
return {
appData: appData,
dataCall: dataCall
}
}())
This is my code in angular calling the function.
When calling this function in angular I'm getting ReferenceError: parsedJsonResponse is not defined.
constructor(private router:Router) {}
ngOnInit(){
this.router.events
.filter(event => event instanceof NavigationStart)
.subscribe((event: NavigationStart) => {
dataLayer.appData();
})
};
What is going wrong? Thanks.
parsedJsonResponse variable should be declared outside all functions if you're going to use it in different functions. Otherwise parsedJsonResponse is private to getData function.
window.dataLayer = (function () {
var parsedJsonResponse;
// ...rest
Next you need to remove the function call inside window load event. appData() is getting called in window load but the data is still fetching and parsedJsonResponse has no content.
window.addEventListener("load", function (event) {
// appData();
})
In getData function remove this since jsonResponse is a private variable.
parsedJsonResponse = JSON.parse(jsonResponse);
I hope this will help.
EDIT:
Anyway I don't encourage using external js files. Try to use a service inside your Angular app.
UPDATE:
You are not passing the parameter in dataLayer.appData().
You are not handling the exceptions properly in the API request.
Try to declare parsedJsonResponse variable inside of a dataLayer function:
window.dataLayer = (function () {
var parsedJsonResponse;
/* rest of your code */
EDIT
The problem why this is happening, because your variable parsedJsonResponse gets its value, when ajax response comes from the server. It means, that it depends on async action. What you can do, is wait for response in promise. My suggestion is to keep that promise in new variable getAsyncData:
var getAsyncData = dataCall().then((CallResponse) => {
getData(CallResponse)
});
also don't forget to add that variable into return object:
return {
appData: appData,
dataCall: dataCall,
getAsyncData: getAsyncData
}
and you can use it in your angular app like so:
dataLayer.getAsyncData.then(() => {
dataLayer.appData();
});
One more thing I've noticed, that you are using applicationContent in getData function, but it haven't been initialized in your function dataLayer. The only usage on that variable in appData:
var appData = function (applicationContent) {
You should consider also initializing that variable on top of your function.
window.dataLayer = (function() {
var parsedJsonResponse;
var applicationContent;
/* rest of your code */
Here is the code, which I've made on top of your's with slight changes(here I sending response to jsonplaceholder server, so parsing that response is different, and also I've removed load event listener:
https://jsbin.com/birofufade/edit?html,js,console,output
I have a weird situation, I'm working with a 3rd party API and I can use JavaScript but all my code has to be a return function in order for it to work, here is how my app looks like, it gets plugged into their system:
app.js
(function() {
var myVar1 = null;
var globalFunction = function(){
alert('TEST');
}
return {
test: null,
requests: {
},
events: {
'app.activated': 'initApp'
},
insideFunction: function(item){
//some code
},
initApp:function(){
//some code
//I can set the gobal variables using varName = Value
//I can set the return variables using this.varName = Value
//I can call the return functions using this.insideFunction()
//the entire app is basically run from inside 'return'
}
};
}());
I can access the global vars / function from inside the return, but how can I do it vice-versa? I need to call insideFunction from the globalFunction.
Assign the object you're returning to a variable before returning it.
var api = {
test: null,
...
};
var globalFunction = function() {
api.insideFunction();
};
return api;
I'm only learning how to work with the modules in JavaScript, so I have three separate .js files: main, listener and fileHandler
Simply this is a program that for every selected or dropped file(image) from computer gets appended to the page. Functions are working when I drag and drop files to the page, but when I select them through inputBox button files even files are stored in inputBox.files, they are not getting appended to the page.
var uploader = {};
uploader.init = function () {
this.inputBox = document.getElementById('uploadButton');
this.dropbox = document.getElementById('dropbox');
this.listener();
}
and listener method as:
probably I'm calling 'change' event wrongly here, that files are not appended.
uploader.listener = function () {
uploader.inputBox.addEventListener('change', uploader.fileHandler.addFiles(uploader.inputBox.files));
this.dropbox.addEventListener('drop', this.fileHandler.drop.bind(this));
}
one another constructor is:
uploader.fileHandler = new function () {
var uploadHandler = function () {...}
this.addFiles = function (files) {
Object.keys(files).forEach(function (key) {
var file = files[key];
uploadHandler(files[key]);
});
};
this.drop = function (event) {
event.stopPropagation();
event.preventDefault();
var files = event.dataTransfer.files;
this.fileHandler.addFiles(files);
};
}
EDIT
I see another issue. When you do this:
uploader.inputBox.addEventListener('change', uploader.fileHandler.addFiles(uploader.inputBox.files));
You are calling uploader.fileHandler.addFiles(uploader.inputBox.files) immediately and passing it's return value to .addEventListener(). Probably what you want instead is this:
uploader.inputBox.addEventListener('change', function() {
uploader.fileHandler.addFiles(uploader.inputBox.files)
});
Here you are passing an anonymous function reference which can be called later by the event handler.
This construct:
uploader.fileHandler = new function () {
this.addFiles = function (files) {
Object.keys(files).forEach(function (key) {
var file = files[key];
uploadHandler(files[key]);
});
};
}
only assigns a function to uploader.fileHandler. It does not define uploader.fileHandler.addFiles until you actually call that function (which you do not show).
I don't know why you're trying to nest your function definitions (that usually just causes more complexity than benefit in Javascript), but if you really wanted to define them that way, you could do this:
uploader.fileHandler = {
addFiles: function (files) {
Object.keys(files).forEach(function (key) {
var file = files[key];
uploadHandler(files[key]);
});
},
drop: function(...) {...}
};
This would then define both of these functions:
uploader.fileHandler.addFiles()
uploader.fileHandler.drop()
I'm using require.js and have a library of functions I use in multiple places. I define the functions thusly:
define(function (require) {
"use strict";
var $ = require('jquery');
var UsefulFuncs = {};
UsefulFuncs.hideAlert = function() {
$('.alert').hide();
};
UsefulFuncs.loadURL = function (url){
navigator.app.loadUrl(url, { openExternal:true });
return false;
};
UsefulFuncs.linkClicked = function (e) {
e.preventDefault();
var url = $(e.currentTarget).attr("rel");
this.loadURL(url);
};
return UsefulFuncs;
});
Then, in my backbone view, I call a function from the library with:
UsefulFuncs = require('app/utils/useful_func'),
....
UsefulFuncs.linkClicked
This works fine for any standalone function in the library e.g. hideAlert(). However when one function in the library refers to another, such as linkClicked() calling loadURL(), I get an error:
Uncaught TypeError: Object [object Object] has no method 'loadURL'.
Any ideas how I can reference loadUrl()?
I would assume you set UsefulFuncs.linkClicked as a handler for an event.
If you were to use it like this:
UsefulFuncs.linkClicked()
, this inside the function would refer to UsefulFuncs, so this.loadURL() would be valid.
However, since you set it as a handler for an event, it can be called in other ways, and this is set to some other object (probably the element which triggered the event). To avoid the event handling mechanism changing your this, you can bind the function when you assign it:
element.onclick = UsefulFuncs.linkClicked.bind(UsefulFuncs);
Another way to go around it is to avoid using this in the handler, like so:
UsefulFuncs.linkClicked = function (e) {
e.preventDefault();
var url = $(e.currentTarget).attr("rel");
UsefulFuncs.loadURL(url);
};
This creates a closure over UsefulFuncs (the first method does as well, but it's more standardized).
Try something like this:
define(function (require) {
"use strict";
var $ = require('jquery');
var hideAlert = function() {
$('.alert').hide();
};
var loadURL = function (url){
navigator.app.loadUrl(url, { openExternal:true });
return false;
};
var linkClicked = function (e) {
e.preventDefault();
var url = $(e.currentTarget).attr("rel");
loadURL(url);
};
return {
hideAlert : hideAlert,
loadURL : loadURL,
linkClicked : linkClicked
};
});