Passing a variable into a JavaScript Function - javascript

I have written a Javascript Function
jQuery(document).ready( function newbie($) {
//var email = 'emailaddress'
var data = {
action: 'test_response',
post_var: email
};
// the_ajax_script.ajaxurl is a variable that will contain the url to the ajax processing file
$.post(the_ajax_script.ajaxurl, data, function(response) {
alert(response);
});
return false;
});
Which I will call using
newbie();
But I want to pass in a variable (the email address) when I call the function but I am not sure how to do this. That $ sign seems to get in my way! Any thoughts much appreciated.

jQuery(document).ready(function(){
var email = 'emailaddress';
newbie(email);
});
function newbie(email) {
var data = {
action: 'test_response',
post_var: email
};
// the_ajax_script.ajaxurl is a variable that will contain the url to the ajax processing file
$.post(the_ajax_script.ajaxurl, data, function(response) {
alert(response);
});
return false;
}
OR
jQuery(document).ready(function(){
var newbie = function(email) {
var data = {
action: 'test_response',
post_var: email
};
// the_ajax_script.ajaxurl is a variable that will contain the url to the ajax processing file
$.post(the_ajax_script.ajaxurl, data, function(response) {
alert(response);
});
return false;
}
var email = 'emailaddress';
newbie(email);
});

Functions in javascript take 'arguments'. You can pass in as many arguments you want and define their name space in the function declaration. ie
function foo(bar,baz,etc){
console.log(bar,baz,etc);
}
foo(1,2,3)
//logs out 1 2 3
Sometimes you don't always know what's going to be passed in or how many arguments there are going to be, in this case inside of the function declaration we can use the 'arguments' object to pick out certain arguments passed into the function.
function foo(){
console.log(arguments);
}
foo(1,2,3)
//logs out an array object that looks like this [1,2,3]

jQuery(document).ready( function newbie($, email) {
//var email = 'emailaddress'
var data = {
action: 'test_response',
post_var: email
};
// the_ajax_script.ajaxurl is a variable that will contain the url to the ajax processing file
$.post(the_ajax_script.ajaxurl, data, function(response) {
alert(response);
});
return false;
});
you simply call the function by passing the values

Related

How to pass variables when using multiple module exports which are dependent on the result of another?

I have three files: user.js, influencer.js, & validate.js
In user.js, I import ./influencer (as var = influencer) & ./validate (as var = validate).
My function in user.js:
addAccount: function(){
return functions.database.ref('/acct/{accountID}/name/').onCreate(event => {
var accountID = event.params.accountID;
var name = JSON.stringify(event.data.val()).replace(/['"]+/g, '');
console.log("New Account Added ("+accountID+")");
console.log("Nickname: " +name);
influencer.getIG(name);
var data = influencer.data;
validate.validateThis(data);
});
}
With influencer.getIG(name), I am passing the name we defined above to the function getIG (inside of influencer.js). This works like a charm. The result is JSON body.
What I want to do now is take this JSON body result and pass it to the validate function (in validate.js). In influencer.js, I also added "exports.data = data;".
With that being said, I can't seem to figure out how to pass "data" to validate.js. I log it, and it returns undefined. I added a timeout before running validateThis(data) and still undefined. The validate function on its own works great; I've tested it. But clearly, I am not doing this the correct way.
This is my influencer.getIG function:
module.exports = {
getIG: function (name) {
var url = "https://www.instagram.com/"+name+"/?__a=1"
console.log(url);
request({
url: url
}, function (error, response, body) {
var data = JSON.parse(body);
console.log(data);
exports.data = data;
})
}
}
How can I pass the result of the second module to the third module in my function? What am I doing wrong?
You can try passing callback function as another parameter to getIG
Your influencer file will look like this.
module.exports = {
getIG: function (name, callback) {
var url = "https://www.instagram.com/"+name+"/?__a=1"
request({
url: url
}, callback)
}
}
And your user file will look like this
addAccount: function(){
return functions.database.ref('/acct/{accountID}/name/').onCreate(event => {
var accountID = event.params.accountID;
var name = JSON.stringify(event.data.val()).replace(/['"]+/g, '');
influencer.getIG(name, function (error, response, body) {
var data = JSON.parse(body);
validate.validateThis(data);
});
});
}
Using callback will ensure that data is retrieved before you call it.
As the two other commentors noted - you have an asynchronous function with a callback. One way around this is to define the callback inside the user.js file, and pass it to the getIG function. So you would have
user.js
<pre><code>
addAccount: function(){
return functions.database.ref('/acct/{accountID}/name/').onCreate(event => {
var accountID = event.params.accountID;
var name = JSON.stringify(event.data.val()).replace(/['"]+/g, '');
console.log("New Account Added ("+accountID+")");
console.log("Nickname: " +name);
function callback(err, res, data) {
var data = JSON.parse(body);
console.log(data);
validate.validateThis(data)
}
influencer.getIG(name, callback);
});
}
</pre></code>
then in the other file
influencer.js
module.exports = {
getIG: function (name, callback) {
var url = "https://www.instagram.com/"+name+"/?__a=1"
request({
url: url
}, callback)
}
}
This way the asynchronous function runs inside of influencer, and then calls back to the user when the result is done. Data is now in scope for the user file to utilize.
The alternative (and better) way is to use promises. In that case the user code would be along the lines of
influencer.getIg(name).then(data => //use data here in user.js//)

callback json value by name/key

With this function I'm trying to get the licence name from a json url by name/key
my json looks like this:
[{"Gallery":true,"Responsive":true,"Main":true,"Seasonal":true}]
js:
function getLicenseName(name, callback){
var license = 'default'
$.getJSON(adl+'DesignTemplateBuilder.aspx?GetLicense=1', function(data){
/*
licence = data[0].Gallery;
respValue = data[0].Responsive;
seasonalValue = data[0].Seasonal;
*/
licence = data[0].name;
callback(licence)
});
}
getLicenseName(name, function(Responsive) {
console.log(name);
//this returns empty right now
});
What I need is to get the true or false value using something like this
getLicenceName(Gallery);
I need to use it in my functions eg: if(getLicenceName(Gallery)=false)...
function getLicenseName(callback){
$.getJSON(adl+'DesignTemplateBuilder.aspx?GetLicense=1', function(data){
callback(data)
});
}
getLicenseName(function(data) {
console.log(data[0].Gallery);
//this returns empty right now
});
Will do the trick.
You can't really do if(getLicenceName(Gallery) == false) because the AJAX request is asynchronous, but you can do it this way:
function getLicenseName(name, callback) {
$.getJSON(adl+'DesignTemplateBuilder.aspx?GetLicense=1', function(data){
// pass back the name parameter
callback(data[0][name])
});
}
// use quotes around the name
getLicenseName('Gallery', function (name) {
if (name) {
...
}
});

How to pull JSON data from two different sources?

I was wondering if there is a way to pull and use JSON data from two different sources. Currently, the code looks like this:
//JSON1
$.getJSON('url1',function(data){
$.each(data,function(key,val){
//code
});
});
//JSON2
$.getJSON('url2',function(data){
$.each(data,function(key,val){
//code
});
});
When I do this, i seems that variables created from one JSON function aren't available in the other one, which makes it hard for them to be useful together.
Is there a better way to have these two work together?
This function takes an array of urls and a callback as parameters:
function getMultiJSON(urlList,callback) {
var respList = {};
var doneCount = 0;
for(var x = 0; x < urlList.length; x++) {
(function(url){
$.getJSON(url,function(data){
respList[url] = data;
doneCount++;
if(doneCount === urlList.length) {
callback(respList);
}
});
})(urlList[x]);
}
}
You would use it like this:
getMultiJSON(['url1','url2'],function(response) {
// in this case response would have 2 properties,
//
// response.url1 data for url1
// response.url2 data for url2
// continue logic here
});
You might want to add a timeout as the function will never call your handler should any of the URLs fail to load
Variable declared within the functions using var (or blocks, using let) are not available outside of the functions (or blocks).
$.getJSON('url1',function(data){
$.each(data,function(key,val){
var only_accessible_here = key;
});
});
So if you want variables that are accessible outside the scope of the function they are declared in, you need to declare them outside of the function they are used in.
var combined_stuff = ''
$.getJSON('url1',function(data){
$.each(data,function(key,val){
combined_stuff += val;
});
});
//JSON2
$.getJSON('url2',function(data){
$.each(data,function(key,val){
combined_stuff += val;
});
});
As Marc B says, there is no way to know which order the combined_stuff variable will be updated, either by JSON1 first, or by JSON2 first, or by only one, if one of the getJSON calls fail, or by neither if both fail.
If the order of updating is important, call the one you want to use second in the function of the one you want to call first.
var combined_stuff = ''
$.getJSON('url1',function(data){
$.each(data,function(key,val){
combined_stuff += val;
//JSON2
$.getJSON('url2',function(data){
$.each(data,function(key,val){
combined_stuff += val;
});
});
});
});
Easily using the open source project jinqJs (http://www.jinqJs.com)
var data1 = jinqJs().from('http://....').select();
var data2 = jinqJs().from('http://....').select();
var result = jinqJs().from(data1, data2).select();
The example does a sync call, you can do an async call by doing something like this:
var data1 = null;
jinqJs().from('http://....', function(self){ data1 = self.select(); });
Result will contain both results combined.
If you control the endpoint, you could make it return all of the data you want in one shot. Then your data would look like:
{
"url1_data": url1_json_data,
"url2_data": url2_json_data
}
If you still have 2 endpoints you need to hit, you can pass the result of your first ajax call to the second function (but this makes your 2 ajax calls synchronous):
function getJson1(){
$.getJSON('url1',function(data){
getJson2(data);
});
}
function getJson2(json1Data){
$.getJSON('url2',function(data){
//Do stuff with json1 and json2 data
});
}
getJson1();
I would recommend you to use $.when function available in jquery to execute both the methods in parallel and then take the action. See the code snipped below,
var json1 = [], json2 = [];
$.when(GetJson1(), GetJson2()).always(function () {
//this code will execute only after getjson1 and getjson2 methods are run executed
if (json1.length > 0)
{
$.each(json1,function(key,val){
//code
});
}
if (json2.length > 0)
{
$.each(json2,function(key,val){
//code
});
}
});
function GetJson1()
{
return $.ajax({
url: 'url1',
type: 'GET',
dataType: 'json',
success: function (data, textStatus, xhr) {
if (data != null) {
json1 = data;
}
},
error: function (xhr, textStatus, errorThrown) {
json1 = [];//just initialize to avoid js error
}
}
function GetJson2()
{
return $.ajax({
url: 'url2',
type: 'GET',
dataType: 'json',
success: function (data, textStatus, xhr) {
if (data != null) {
json2 = data;
}
},
error: function (xhr, textStatus, errorThrown) {
json2 = [];//just initialize to avoid js error
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
The returned data from each AJAX call are not available outside its own callback function. I'm sure there are more elegant (complex?) solutions, but a couple of simple, Occamic, solutions include global variables, or storing the received data in hidden input elements.
Within each callback function, just loop until the data from the other call is present:
function getJson1(){
$.getJSON('url1',function(data){
var d2 = '';
$('#hidden1').val(data);
while ( d2 == '' ){
//you should use a time delay here
d2 = $('#hidden2').val();
}
getJson2();
});
}
function getJson2(){
$.getJSON('url2',function(d2){
var d1 = '';
$('#hidden2').val(d2);
while ( d1 == '' ){
//you should use a time delay here
d1 = $('#hidden1').val();
}
//Do stuff with json1 and json2 data
});
}
getJson1();

Accessing outer scope

I'm working on creating a Users collection with the ability to then grab single users inside. This will be used to match from another system, so my desire is to load the users once, and then be able to fine/match later. However, I'm having a problem accessing the outer users collection from an inner method.
function Users(){
var allUsers;
this.getUsers = function () {
// ajax to that Jasmine behaves
$.ajax({
url: '../app/data/jira_users.json',
async: false,
dataType: 'json',
success: function(data) {
allUsers = data;
}
});
return allUsers;
};
this.SingleUser = function (name) {
var rate = 0.0;
var position;
this.getRate = function () {
if(position === undefined){
console.log('>>info: getting user position to then find rate');
this.getPosition();
}
$.ajax({
url: '../app/data/rates.json',
async: false,
dataType: 'json',
success: function(data) {
rate = data[position];
}
});
return rate;
};
this.getPosition = function () {
console.log(allUsers);
//position = allUsers[name];
return position;
};
//set name prop for use later I guess.
this.name = name;
};
}
and the test that's starting all of this:
it("get single user's position", function(){
var users = new Users();
var someone = new users.SingleUser('bgrimes');
var position = someone.getPosition();
expect(position).not.toBeUndefined();
expect(position).toEqual('mgr');
});
The getPosition method is the issue (which might be obvious) as allUsers is always undefined. What I have here is yet another attempt, I've tried a few ways. I think the problem is how the Users.getUsers is being called to start with, but I'm also unsure if I'm using the outer and inner vars is correct.
Though the others are correct in that this won't work as you have it typed out, I see the use case is a jasmine test case. So, there is a way to make your test succeed. And by doing something like the following you remove the need to actually be running any kind of server to do your test.
var dataThatYouWouldExpectFromServer = {
bgrimes: {
username: 'bgrimes',
show: 'chuck',
position: 'mgr'
}
};
it("get single user's position", function(){
var users = new Users();
spyOn($, 'ajax').andCallFake(function (ajaxOptions) {
ajaxOptions.success(dataThatYouWouldExpectFromServer);
});
users.getUsers();
var someone = new users.SingleUser('bgrimes');
var position = someone.getPosition();
expect(position).not.toBeUndefined();
expect(position).toEqual('mgr');
});
This will make the ajax call return whatever it is that you want it to return, which also allows you to mock out tests for failures, unexpected data, etc. You can set 'dataThatYouWouldExpectFromServer' to anything you want at any time.. which can help with cases where you want to test out a few different results but don't want a JSON file for each result.
Sorta-edit - this would fix the test case, but probably not the code. My recommendation is that any time you rely on an ajax call return, make sure the method you are calling has a 'callback' argument. For example:
var users = new Users();
users.getUsers(function () {
//continue doing stuff
});
You can nest them, or you can (preferably) create the callbacks and then use them as arguments for eachother.
var users = new Users(), currentUser;
var showUserRate = function () {
//show his rate
//this won't require a callback because we know it's loaded.
var rate = currentUser.getRate();
}
var usersLoaded = function () {
//going to load up the user 'bgrimes'
currentUser = new users.SingleUser('bgrimes');
currentUser.getRate(showUserRate);
}
users.getUsers(usersLoaded);
your approach to fill the data in allUsers is flawed
the ajax call in jquery is async so every call to users.getAllUsers would be returned with nothing and when later the success function of the jquery ajax is called then allUsers would get filled
this.getUsers() won't work. Its returning of allUsers is independent from the ajax request that fetches the data, because, well, the ajax is asynchronous. Same with getRate().
You'll have to use a callback approach, where you call getUsers() with a callback reference, and when the ajax request completes, it passes the data to the callback function.
Something like:
this.getUsers = function (callback) {
// ajax to that Jasmine behaves
$.ajax({
url: '../app/data/jira_users.json',
async: false,
dataType: 'json',
success: function(data) {
callback(data);
}
});
};
And the call would be along the lines of:
var user_data = null;
Users.getUsers(function(data) {
user_data = data;
});

How to solve this double ajax calls issue

I am trying to do 2 ajax function calls when a user clicks a button.
I have
$('.test').on('click', function(){
code.getCode();
code.getText();
})
code.prototype.getCode=function(){
var call=//call ajax
call.callback= function(data){
//parse return data
}
}
code.prototype.getText=function(){
var call=//call ajax
call.callback= function(data){
//parse return data
}
}
I can only do 1 ajax call and only 1 ajax call will return data.
I am not sure how to solve this. Any ideas? Thanks a lot!
I am not sure if I understood correctly, but I think you are looking for a single callback from both the ajax calls..
You should use $.when.done. See below,
$.when($.ajax("/page1.php"), $.ajax("/page2.php")).done(function(a1, a2){
/* a1 and a2 are arguments resolved for the
page1 and page2 ajax requests, respectively */
var jqXHR = a1[2]; /* arguments are [ "success", statusText, jqXHR ] */
if ( /Whip It/.test(jqXHR.responseText) ) {
alert("First page has 'Whip It' somewhere.");
}
});
Not sure if you looking for sequencing it or trying to have 1 callback.
You could also have the first ajax call, call the second on success:
$('.test').on('click', function(){
var datastr = "your data";
$.ajax({
type: "POST",
url: "url",
data: datastr,
success: function(successMsg) {
//ajax done
if (/* not yet complete */) {
setTimeout(secondAjaxCall(),500);
} else {
secondAjaxCall();
}
}
});
});
You could just save each return in the code object (since you are in a different context you have to work around "this"). Then you can use a third function that checks if the data objects are loaded... and start parsing once both are there.
$('.test').on('click', function(){
code.getCode();
code.getText();
})
code.prototype.getCode=function(){
var call=//call ajax
var that = this;
call.callback= function(data){
//parse return data
that.codeData = data;
parseData();
}
}
code.prototype.getText=function(){
var call=//call ajax
var that = this;
call.callback= function(data){
//parse return data
that.textData = data;
parseData();
}
}
function parseData() {
if(!code.textData || !code.codeData) return;
... work with both
}

Categories