How do I call function with changing name properly in Javascript? - javascript

So, this is my current problem:
I have locations.js file that has several functions inside with different town/area names and they all include few switches. This is example:
let Locations = {
town1: function (eventType) {
switch (eventType) {
case "load":
// Stuff related to main starting point of this location
break;
}}
They have been all nice for everything else, but now I'm trying to create a "main access" when starting the program. Let's call main file as manager.js
let Manager = {
setStart: function () {
currentLocation = user.currentLoc;
// Call load function based on current location to start program from right spot
Locations.currentLocation("load");
}
Result:
TypeError: Locations is not a function
As you see, I want to call function with user.currentLoc information (town names), which are saved to database. But it seems like I cant add it to variable and just use it. What am I missing here? Do I type it wrong when calling a function? I'm quite sure that there's some easy solution to this, but even after several hours I still fail to do this right.

You are trying to access to a property field of the Locations object. This field is a function, however, if you are trying to call this function by the name of a variable, the Javascript interpreter will take it as a direct call of the function.
let manager = {
setStart: () => {
const currentLocation = user.currentLoc;
// Access the Locations property
const fn = Locations[currentLocation];
// Invoke the function
fn(`load`);
}
};
Hope it helps.

Perhaps Locations[currentLocation]('load') is what you mean to call, but all the same - it looks like Locations isn't in scope in your Manager file, you need to import it somehow. That could be a missing require or import depending on your project

let manager = {
setStart: () => {
const currentLocation = user.currentLoc;
// Access the Locations property
const fn = Locations[currentLocation];
// Invoke the function
fn(`load`);
}
};
This did it! Thanks VRoxa. I had no idea that Javascript works like this.

Related

Firebase Functions error: .once is not a function

I am trying to deploy a simple function to Firebase, but I am having some difficulties. Every time I try to use .once on a reference Firebase tells me that it is not a function. Here is my code
exports.testFunction = functions.database.ref('/Rooms/{firstID}/{pushId}/On').onWrite(event => {
const value = event.data.val();
var ref = functions.database.ref(roomNum);
return ref.once('value').then(snapshot => {
console.log(snapshot.numChildren);
return true;
}); });
I have also tried the following:
firebaseRef.once('value', function(dataSnapshot) {
console.log(snapshot.numChildren);
});
Nothing seems to work. Does anyone know of a fix or a different way of getting the number of children from a ref/snapshot?
Thank you.
functions.database.ref is a different object than the one you're used to using on the client. It's sole purpose is to listen for writes using it's only function, onWrite.
You can obtain your intended ref thru the event parameter.
var ref = event.data.ref
This is a reference to the path you specified in onWrite.
If you want the root reference:
var rootRef = event.data.ref.root
Further reading: https://firebase.google.com/docs/reference/functions/functions.database

Protractor: Unable to call exported function within the same module

I have written a export module using protractor. it has multiple function defined inside it.
Now, I want to call one of the exported function inside another function within the same module.
My module looks like below.
module.exports = {
read_page_number_data: function {
// code here
},
read_page_data: function {
this.read_page_number_data().then(function () {
// Code here.
});
},
check_link_present: function {
// code here
},
click_link: function {
this.check_link_present().then(function () {
// Code here.
});
},
}
Now, when I call read_page_data function in my test script, I get below error.
Failed: this.read_page_number_data is not a function.
I have tried all the options given in below question. still there is no success.
protractor calling an exported function within the same module
NOTE: Before calling read_page_data function, I am calling click_link function, which internally calls check_link_present function. But this call works fine and check_link_present function gets call properly from click_link function. After this, control navigates to the page given in link.
One solution would be to assign the object to a variable specific to your module.
e.g.
module.exports = myModule = {
//...
}
Then you can call your functions within the module with myModule.read_page_number_data() etc.
You can find an example JSFiddle here.
Note on this context
One thing to keep in mind is that this can change it's context depending on how the parent function is called, which could be why it is working for click_link but not for read_page_data.
You can find more information on the this keyword here.
Why don't try like below. This is one of the best practices for Page Object Model test framework.
var PageName = function(){
this.firstMethod = function(){
//logic
};
this.secodnMethod = function(){
//logic
};
}
module.exports = new PageName();

Accessing var function within function in another file

I have 2 JS files - one with the functions I would like to access and the other that I'd like to call the function with.
(function($) {
var Place = function() {
var Location = function(id, duration, check) {
//Should access this function
}
}
})(jQuery);
I'm trying to access it with:
Place.Location(markerId, 600);
But all I'm getting is that it's not defined. Simple issue but can't quite figure this one out.
As it's a jQuery plugin, maybe there's a way I can access it via another method?
$.fn.place = function(params) {
var len = this.length;
return this.each(function(index) {
var me = $(this),
key = 'place' + (len > 1 ? '-' + ++index : ''),
instance = (new Place).init(me, params);
});
};
The way you are defining Location, it is a private variable inside the function Place. If you want to access it as an attribute of Place, you should replace var Location = ... with this.Location = ...
It's going out of scope. Because you wrapped your Place object in function($) {}, now anything outside that wrapper will no longer have access to variables inside the wrapper. If $ stands for jQuery, it should be a global anyways and you can take the wrapper out.
The solution is a combination of the other two answers.
You define Place as a variable in the (anonymous) function. It can't be used outside the scope of that function. (This function doesn't use jQuery, either, so the wrapper is unnecessary).
Place is a function. It executes code that sets local variable Location to a function, but doesn't export that function, so Location() is inaccessible outside the Place function.
You probably mean to make Place an object (instead of a function), and give it a Location method. Here's one way to write it:
var Place = {
Location: function(id, duration, check) {
// do something with id, duration, & check
}
};
// execute
Place.Location(someId, someDuration, someCheck);
(It doesn't look like you've posted all your code, like the Place.init() method, but there are plenty of ways to write this so that it works correctly; this should solve your immediate problem.)

encapsulating javascript inside a namespace

I'm looking to encapsulate my javascript inside a namespace like this:
MySpace = {
SomeGlobal : 1,
A: function () { ... },
B: function () { ....; MySpace.A(); .... },
C: function () { MySpace.SomeGlobal = 2;.... }
}
Now imagine that instead of a few lines of code, I have about 12K lines of javascript with hundreds of functions and about 60 globals. I already know how to convert my code into a namespace but I'm wondering if there's a quicker way of doing it than going down 12K lines of code and adding MySpace. all over the place.
Please let me know if there's a faster way of doing this.
Thanks for your suggestions.
I like to wrap up the namespace like so. The flexibility is huge, and we can even separate different modules of the MySpace namespace in separate wrappers if we wanted too. You will still have to add some sort of _self. reference infront of everything, but at least this way you can change the entire name of the namespace very quickly if need be.
You can see how with this method you can even call _self.anotherFunc() from the 1st module, and you'll get to the second one.
(function (MySpace, $, undefined) {
var _self = MySpace; // create a self-reference
_self.test = function () {
alert('we got here!');
_self.anotherFunc(); // testing to see if we can get the 2nd module
};
_self = MySpace; // reassign everything just incase
}(window.MySpace = window.MySpace || {}, jQuery));
$(function () {
MySpace.test(); // call module 1
MySpace.callOtherModule(); // call module 2
});
// Here we will create a seperate Module to the MySpace namespace
(function (MySpace, $, undefined) {
var _self = MySpace; // create a self-reference
_self.callOtherModule = function () {
alert('we called the 2nd module!');
};
_self.anotherFunc = function () {
alert('We got to anotherFunc from the first module, even by using _self.anotherFunc()!');
};
_self = MySpace; // reassign everything just incase
}(window.MySpace = window.MySpace || {}, jQuery));​
jsFiddle DEMO
Wrap a function body around your existing code to use as scope, hiding everything from global - this will allow you to do internal calls without pasting Namespace. prefix everywhere, neatly hide things you don't want everyone else to see, and will require minimal changes as well.
After that, decide what functions you want to "export" for everyone and assign them to properties of object you want to use as "namespace".

How do I use closures to access twitters #Anywhere javascript api?

I want to do something that in a classical object oriented language like Java, C# etc. is very easy to do. I simply want to access a property of an instantiated object. The object is globally scoped in the browser's window object, and provided by the twitter #anywhere API.
For my code examples, assume you have already logged the user in.
If I were using java for instance, I would say (assuming all fields were public:
twttr = new twtter();
String screenName = twtter.currentUser.data('screen_name');
For some reason, this is way hard in Javascript. I've gotten a workaround working where inside the anonymous method that the twitter anywhere API is using, I set the value I want to a DOM element, and fish it out later. This is ugly though. I just want to access it directly.
Here's what I have so far, which doesn't even pass syntax checks in eclipse:
function AnywhereFacade()
{
var twitterReference;
window.twttr.anywhere
(
return function(T)
{
twitterReference = T;
};
)
getValue(propertyToGet)
{
return twitterReference.currentUser.data(propertyToGet);
}
};
var anywhereFacade = AnywhereFacade();
var screen_name = anywhereFacade.getValue("screen_name");
alert("screen name is: " + propertyGetter);
Please help! Why is Javascript so hard to use anyway? What I'm trying to do is use a closure I think.
Thanks!
I have done something similar in my app since I am using the Facebook JavaScript SDK and Twitter SDK and want to provide a consistent interface to access both. So I namespace the variables under App. For twitter anywhere, this is how the variable is captured.
window.App = {};
twttr.anywhere(function(T) {
App.Twitter = {
getValue: function(property) {
return T.currentUser.data(property);
},
getPublicTimeline: function() {
return T.Status.publicTimelime();
}
};
});
We are calling the anywhere function and passing it a callback function. The callback function is needed because the anywhere library might not be loaded at this point. By passing the entire function, we are saying that this function should be executed whenever the anywhere library is loaded.
Now when the library does load, this function will execute, define the App.Twitter property which contains a getValue function. The anywhere or T object is captured in the closure.
If you now call,
App.Twitter.getValue("screen_name");
the actually anywhere object (T), will be used to get the screen_name property.
this is all I needed to do.
document.getElementById('messagePanel').innerHTML = "loading...";
window.twttr.anywhere(function(T)
{
document.getElementById('messagePanel').innerHTML = "screen_name: " + T.currentUser.data('screen_name');
});
this made me realize my issue was just that I had to use a callback for when twitter returned from the async call. that helped me solve my initial problem of how to wrap it for gwt.

Categories

Resources