Running a jquery function from JS - javascript

Sorry for the noobish question, but nothing works for me today.
I'm creating a Phonegap application and have intergrated PushWoosh API into my app. And on receive push notification I want to run my previous functions again, so the data will be updated.
Pushwoosh has JS function like this:
document.addEventListener('push-notification',
function(event) {
var title = event.notification.title;
var userData = event.notification.userdata;
var notification = event.notification;
if (typeof(userData) != "undefined") {
console.warn('user data: ' + JSON.stringify(userData));
}
var object = JSON.parse(notification.u);
window.runPushFunctions(object.active, object.open); //Runs a jQuery function I have created..
}
);
Now window.runPushFunctions looks like this:
$(document).ready(function() {
window.runPushFunctions = function(active, open) {
if (active != null || active != undefined) {
$('.hubs-page').removeClass('hubs-active').hide().eq(active).show().addClass('hubs-active');
}
if (open == 2) {
$('html').addClass('hubs-opening');
}
//Trying to run functions from jQuery file that will get data from database and so on..
received();
sent();
checkFriends();
};
});
But I can't for some reason not run received(), sent(), checkFriends().
These functions is set like this in their own files like this:
(function($) {
'use strict';
function checkFriends () {
$.getJSON('url',function(data){
$.each(data,function(index,value){
//Do something with value
});
});
}
Im including files in this order:
file.js -> received(); sent();
file.js -> checkFriends();
file.js -> pushnotifications
Any help will be gladly appreciated

As the other answer here says, you are scoping your method definitions so they are not accessible anywhere outside the containing method.
(function($) {
This is a method definition. Any variables or functions non-globally declared within it cannot be accessed outside it. Therefore, you need to define the functions somewhere else or make them global for them to be accessible.
If you go for defining them somewhere else, you can simply move the function definitions to the top of the same file, outside of the (function($) {})() scope.
If you go for global definitions instead, you need to change the methods' defining lines slightly: instead of
function foo() { }
you need
window.foo = function() { }
This assigns an anonymously declared function to an object in the window scope, which is globally accessible. You can then call it using
window.foo();
or simply
foo();
since it is in the window scope.

I'm not exactly sure I'm understanding your question, but it looks to me like you are defining the function checkFriends inside of a function scope. If you need access to that function definition, you would need to declare it on an object that can be referenced from the global scope. Obviously the easiest way to do that would be to attach it to the window, though there are plenty of reasons not to do that.
window.checkFriends = function(){//code that does stuff};

Related

can't access variables in another javascript file

So i have link every file needed into the index.html file :
<script src="jquery.js"></script>
<script src="notify.js"></script>
<script src="script.js"></script>
i create an object in 'notify.js' :
var notify = {
newNotification : function(text) {
}
}
script.js :
alert(notify.newNotification);
When i try to access the 'notify' object in 'script.js', it works just fine.But i want to use jquery so i add $(document).ready() to both of the file like this:
notify.js
$(document).ready (
function() {
var notify = {
newNotification : function(text) {
}
}
}
)
Script.js:
$(document).ready (
function() {
alert(notify.newNotification);
}
)
And after i add that, it comes up with notify is not defined.What's wrong? Can anyone explain why it doesn't work?
As you have defined var notify in notify.js inside $(document).ready( which is an anonymous function and var notify scope is limited to this function only .
So it is not accessible outside the $(document).ready( function
To make accessible outside don't wrap it in $(document).ready( function
like this:-
var notify;
$(document).ready(function () {
notify = {
newNotification: function (text) { }
}
});
Like everyone else here already pointed out: Only use $().ready when you're handling DOM-Elements and your Variable is not accessible because you used the var keyword (like you're supposed to). The var keyword limits the defined variables to the current scope, which is the scope of the anonymous function you use as your DOM-Ready-Handler.
So, removing the unnecessary $().read will temporary solve your problem.
BUT(!) you should wrap your code into a closures to avoid messing up the global scope and to avoid possible naming conflicts with 3rd-party code.
Like that:
notify.js
;(function ($, window, undefined) {
var notify = {
newNotification : function(text) {
return text;
}
};
})(jQuery, this);
script.js
;(function ($, window, undefined) {
alert(notify.newNotification());
})(jQuery, this);
So, now you'll have the same problem as before, you don't have access to your Object.
Sure you could just add your notify Object to the global scope as Arun P Johny suggested in his answer, but i'm pretty sure over the time there will be more Object you'll need to make global accessible.
If you put each of them in the global scope, you start messing up the global scope again, so my recommendation would be ONE global Object that will hold all other objects/variables you need globally accessible. (Or even better use something like requirejs
Somethink like this:
main.js
;var MyApp = {}; # Only variable in global scope
# Maybe some more initalization code here, dunno
notify.js
;(function ($, window, undefined) {
MyApp.notify = {
newNotification : function(text) {
return text;
}
};
})(jQuery, this);
script.js
;(function ($, window, undefined) {
alert(MyApp.notify.newNotification());
})(jQuery, this);
Some interesting Q/A's about scope and closures here on stackoverflow:
What is the scope of variables in JavaScript?
How do JavaScript closures work?
JavaScript closures vs. anonymous functions
A good Answer about messing around with the global scope:
What is meant by “leaking” into global scope?
In this case there is no need to wrap the notification object in dom ready... because from the looks of it you are not creating any dom element reference while creating the object... the only thing that matters is any method invokation that deals with dom element has to be done on dom ready.
var notify = {
newNotification: function (text) {}
}
$(document).ready(function () {
notify.newNotification()
})
if you declare the variable inside a dom ready handler then it becomes a local variable to the dom ready handler... so it will not be accessible outside the dom ready handler...
Another solution is to add the variable to the global scope within the dom ready handle like
var notify;
$(document).ready(function () {
notify = {
newNotification: function (text) {}
}
})
or
$(document).ready(function () {
window.notify = {
newNotification: function (text) {}
}
})
You only need one document.ready
And this only declare the variables that will move freely in their scripts.
See the example:
script.js:
$(document).ready(function(){
// declare the variables as global
$.varA, $.varB, $.varC;
});
notify.js:
function doNotify(){
// your code here
$.varA = /*your code here */
}
function otherFunc(txt){
// your code here
$.varB = txt;
}
All of your JavaScripts will load before the document is ready.
Create a separate function in script.js that references the notify object, then call that function from $(document).ready
Try this.
var notify = {
newNotification : function(text) {
}

How do I make a nonexistent (non-member, non-global) method invocable without using eval?

Let's start from the code:
function say(name) {
var ghost=function () {
function ghost() {
alert('!');
};
return body;
};
eval("var body=''+"+name+';');
eval(name+('=('+ghost).replace('body', body)+')();');
eval(name+'();');
}
function Baal() {
if ('undefined'===typeof ghost) {
say('Baal');
return;
}
ghost();
}
say('Baal'); // or just Baal();
Looks like that saying the devil's name invoke his presence (well, maybe he needs somebody for spiritual possession) ..
As you can see the ghost doesn't exist along with Baal, but we can invoke it since there're evals in say(name).
say(name) reassigns Baal to its code body as a closure and makes it captured a ghost method, that's how things work. But I'm trying to avoid eval ..
So .. let me reword the question:
How do I make a nonexistent(and not a member or global) method invocable without using eval?
Let me rephrase your question, just to make sure I’ve got it. Given a function, you want to put a new variable in its scope, without that scope being the global scope or a scope shared between the caller and the subject, without using eval (or the equivalent new Function and other hacks depending on the environment).
You can’t.
In the case you just mentioned, you could define one function, base(), that uses arguments.callee.caller.
Don’t do that.
The short answer: You don't.
That scope is not available. If you were to attach the scope then it would be available inside of the scope used. You could then access the method handles. I assume this is not what you were looking for, but here is what that would look like. demo
function say(name){
var methods = {};
methods.Baal = function(){
alert("!");
};
return methods[name];//this could invoke as well: methods[name]()
}
var handle = say('Baal');
handle();
What your evals break down to is something along these lines (although with dynamic content from string building - this is the end result)
function say(name) {
var Baal = (function () {
function ghost() {
alert('!');
};
return function(){
if ('undefined'===typeof ghost) {
say('Baal');
return;
}
ghost();
}
})();
Baal();
}
say('Baal'); // or just Baal();
Note that the meat of what happens here is from the function Baal, namely that it calls a hardcoded ghost() which in turn calls a hardcoded alert. Why go through all of this trouble to access a hardcoded function?
A better way would be to inject this function as a callback which expects some parameters to be injected.
jsFiddle Demo
function say(callback){
var params = "!";
if( typeof callback == "function" ){
callback(params);
}
}
say(function(params){
alert(params);
});
It's very difficult for me to read through your code and figure out what you are trying to accomplish with it, but it appears that you are trying to introduce a variable into the current scope so that you can call it. You cannot do this in javascript with the method that you demonstrated. Scoping only ever "flows down". By that I mean that a variable or function defined within a function will only be available to that function and any other functions defined therein. Your function named ghost will only ever be available within the function where it is defined, regardless of when that function is evaluated.
What you can do, however, is write a function that returns a function. You can then call that function and assign the result to a variable in the scope where you want to expose functionality. Doing that would look something like this.
function defineSpecialAlert() {
return function(name) {
alert(name + "!");
};
}
var newlyDefinedMethod = defineSpecialAlert();
newlyDefinedMethod("Baal");
So if I understand, it seems like you want to create an alias of eval: Something like
#Note this code is not intended as a solution, but demonstrates
#an attempt that is guaranteed to fail.
#
function myAlias(ctx) {
eval.call(ctx, 'var ghost = 42');
}
myAlias(this);
alert(ghost);
Javascript allows many funky sleight-of-hand tricks especially with closures, but this is maybe the one impossible thing that javascript cannot do. I've tried at length to do this exact same thing, and I can tell you that you'll run into nothing but complaints from the browser, saying that eval cannot be re-contexted or aliased in any way.

Access a javascript variable from a function inside a variable

Hello i have the following issue i am not quite sure how to search for it:
function(){
var sites;
var controller = {
list: function(){
sites = "some value";
}
}
}
So the question is how to access the sites variable from the top defined as
var sites
EDIT:
Here is a more complete part. i am Using marionette.js. i don't want to define the variable attached to the Module (code below) variable but keep it private to the Module, hope that makes sense. Here is the code that works:
Admin.module("Site", function(Module, App, Backbone, Marionette, $, _ ) {
Module.sites = null;
Module.Controller = {
list: function (id) {
Module.sites = App.request("site:entities");
}
};
});
and i would like instead of
Module.sites=null;
to do
var sites;
That sort of thing does make a difference right? Because in the first case i would be defining an accessible variable from outside where as the second case it would be a private one. i am a bit new to javascript so please try to make it simple.
if you are looking for global access, just declare the variable outside the function first, make your changes to the variable inside the function, then you can get the value whenever you need it.
I have found some info on this: sadly what i am trying to do doesn't seem possible.
Can I access a private variable of a Marionette module in a second definition of that module?
So i guess i have to do _variable to make developers know its private.
Disclaimer: I have no experience using Marionette, however, what you're describing sounds very doable.
One of the most powerful (in my opinion) features of JavaScript is closures. What this means is that any function declared from within another function has access to the variables declared in the outer function.
For example:
var func;
function foo() {
var answer = 42;
func = function () {
// I have access to variable answer from in here.
return answer++;
};
}
// By calling foo(), I will assign the function func that has access "answer"
foo();
// Now I can call the func() function and it has access to the "answer"
// variable even though it was in a scope that doesn't exist anymore.
// Outputs:
// 42
// 43
console.log(func());
console.log(func());
What this means is that if you declare var sites from within your module definition function as you described, you should have access to it from within any of your inner anonymous functions. The only exception is if Marionette is re-writing your functions (by using the Function function and toString()), which seems unlikely but possible.
Your original example should would as described, my suspicion is that there is something else going wrong with the code that is unrelated to your scope.

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".

Calling function inside a variable

I am using a plugin JS and need to call a function in it.
It is having functions inside a variable like,
var win = window;
var Page = function(pageOptions, callback) {
function abc(){
--------
}
function xyz(){
------
}
};
win.Sales = {
Page: Page
};
Now, I need to call a function abc(). How can I call it.
Already tried with win.Sales.page.abc();.
Please help me out on this. Thanks in advance.
You cannot do that with your configuration because the functions are local or private.
You should make them accessible globally like:
var Page = function(...) {
...
};
Page.abc = function() {
...
};
That way, abc is a property of Page, and you can then access it like Page.abc and execute it like Page.abc(). Functions are basically also objects so they can have properties too.
You cant call function abc since it is declared as a private member of the function referenced by variable Page.
If you want to call the function You have to make it as a property of the variable Page.
var Page = function(){
.........
.........
.........
}
Page.abc = function(){
}
But there is another problem of variable scoping like if there is another variable x defined in function Page and used inside function abc, it will not work.
Anyway since you've said it is a js plugin I do not think it will be possible for you to change the function Page. So the answer will be No you cannot do that.

Categories

Resources