jQuery how to acess a function within a plugin? - javascript

So I am trying to access a function within a plugin but am not sure how to.
Here is a snippet of code. I am trying to access the find_matches function OUTSIDE of this plugin and get a return from it.
$.fn.variation = function () {
$.fn.variation.find_matches = function( variations, settings ) {
var matching = [];
for (var i = 0; i < variations.length; i++) {
var variation = variations[i];
matching.push(variation);
}
return matching;
}
};
Thanks for looking.

If you do not want to expose the function to external scope as a utility function then you can write it as a closure function
$.fn.variation = function () {
var find_matches = function( variations, settings ) {
var matching = [];
for (var i = 0; i < variations.length; i++) {
var variation = variations[i];
matching.push(variation);
}
return matching;
}
var matches = find_matches(variations, settngs);//you can call it directly
};
If you want to expose the function to external context then you can use the format used by you and you can access it using
var matches = $.fn.variation.find_matches(variations, settngs);

Related

Use closure inside array with pure javascript

I need to copy a string inside an array to a value inside another array that is created in a loop. In the end when I print all names are the last in the array of names. I want to copy/clone the value so that I don't have a reference and I would like it to be only in native javascript without external libraries.
This is my code
var exp_names =["name1","name2","name3"];
var i;
for (i = 0; i < exp_names.length; i++) {
d3.tsv("data/"+exp_names[i], function(data) {
data.forEach(function(d){
//Do stuff with my tsv
d.expId = exp_names[i];
});
});
});
And then all expId are "name3"
Data is loading correctly per file.
I have tried with jquery's extend function and also lodash's clone function, I have tried my own clone function and nothing works it will still throw "name3" for all the expId.
These didn't work:
var newname = new String(exp_names[i]);
var newname = $.extend(true, {}, exp_names[i]);
var newname = $.extend( {}, exp_names[i]);
var newname = _.clone(exp_names[i]);
var newname = exp_names[i].slice(0);
I am desperate by now.
You need to use bind function.
var exp_names =["name1","name2","name3"];
var i;
var func = [];
for (i = 0; i < exp_names.length; i++) {
func[i]=(function(index){
d3.tsv("data/"+exp_names[index], function(data) {
data.forEach(function(d){
//Do stuff with my tsv
d.expId = exp_names[index];
});
});
}).bind(this,i);
}
for(i = 0; i < 3; i++){
func[i](i);
}
Another solution is to use let keyword.
ES6 provides the let keyword for this exact circumstance. Instead of using closures, we can just use let to set a loop scope variable.
Please try this:
for (let i = 0; i < exp_names.length; i++) {
d3.tsv("data/"+exp_names[i], function(data) {
data.forEach(function(d){
//Do stuff with my tsv
d.expId = exp_names[i];
});
});
}
I guess usage of IIFE and bind together, in the first answer is a little weird. It's best to choose either one of them. Since in the newest versions of the browsers bind is way faster than an IIFE closure and the let keyword I might suggest you the bind way.
A similar example to your case might be as folows;
var exp_names = ["name1","name2","name3"],
lib = {doStg: function(d,cb){
cb(d);
}
},
data = [{a:1},{a:2},{a:3}];
for (i = 0; i < exp_names.length; i++) {
lib.doStg(data, function(i,d) {
d.forEach(function(e){
//Do stuff with doStg
e.expId = exp_names[i];
console.log(e);
});
}.bind(null,i));
}

Passing through array that is in an object into a function

I want to pass an object into a function as a parameter, and assign things to properties of that object, then those would be accessible outside of the function. But I am not to clear on how it is done.
At first I thought it could be done using callbacks, but it was made clear to me that JavaScript does not work that way. I eventually managed to get it working, and the undefined error messages went way. But I wanted to now pass an array through the function. How can this be done? This is what I've done so far, but it doesn't seem to be working.
var journey = {};
journey['waypointsArrayItem'] = new Array();
setupAddress(journey)
function setupAddress(journey) {
var waypointsItem = $('.timeline-item.active-item > .timeline-status > .waypoints').text().substring(4);
journey.waypointsArrayItem = [];
journey.waypointsArrayItem = listToArray(waypointsItem, ', ');
for (var i = 0; i < waypointsArray.length; i++) {
journey.waypointsArrayItem[i] = journey.waypointsArrayItem[i];
}
}
You are copying array items to themselves. Copy from the waypointsArray array to the journey.waypointsArrayItem array:
function setupAddress(journey) {
var waypointsItem = $('.timeline-item.active-item > .timeline-status > .waypoints').text().substring(4);
var waypointsArray = listToArray(waypointsItem, ', ');
for (var i = 0; i < waypointsArray.length; i++) {
journey.waypointsArrayItem[i] = waypointsArray[i];
}
}
Depending on what you need, you could also just replace the entire array:
function setupAddress(journey) {
var waypointsItem = $('.timeline-item.active-item > .timeline-status > .waypoints').text().substring(4);
journey.waypointsArrayItem = listToArray(waypointsItem, ', ')
}
Assigning properties to an object in a function is the same as assigning properties outside of a function.
function addName(obj, name) {
obj.name = name;
}
var bob = {};
console.log(bob.name); // undefined
addName(bob, 'Bob');
console.log(bob.name); // 'Bob'

Outer Variable scope is not available inside the javascript function

How to access the outer variable inside the inner javascript function , please check my code below i need to access "index" variable inside app() function .
function validate()
{
for (index = 0; index < results.length; index++) {
var parsedData_1;
var provider = results[index].get("provider");
var user = results[index].get("user");
var addresses = user.get("addresses");
var address = addresses[1];
var GameScore = Parse.Object.extend("Address");
var query = new Parse.Query(GameScore);
var data = JSON.stringify(address);
var parsedData = jQuery.parseJSON(data);
query.get(parsedData.objectId, {
success: function(resultadr) {
var res = JSON.stringify(resultadr);
var parsedData_1 = jQuery.parseJSON(res);
var apartment = parsedData_1.apartment;
apa(apartment);
},
error: function(object, error) {
alert('error');
}
});
function apa(apartment)
{
alert(index); [I'm not getting the index value inside this function]
alert(apartment);
}
}
}
Inside the function apa() i need the index count , but im unable to get it , please help how to access the outer value inside the function.
As far as I can see apa() does not have access to the index variable, so I would put it inside the parameter of the function call, and call apa() like this
apa(apartment, index);
The problem is that you are using closures to access the index, thus the lastest value assinged to that variable is accessible in the app function. For example, if results.length equlas 11, index in app function will always be 11.
The soltion is to declare a variable inside the for loop, assign the index value to that variable, and pass the variable to app function.
//Create a factory function for the app function
//Outside the for loop.
var createAppFunc = function (i) {
return function () {
console.log(i);
};
};
for (var index = 0, l = results.length; index < l; index++)
{
var newVar = index;
var app = createAppFunc(index); //Now, app is a function.
}
Good Luck :).
You can use Function.bind() to pass the actual index as first argument to the sucess-callback. There you can get it and pass it along as parameter to function apa(). And: use keyword var for the index in for().
function validate() {
for (var index = 0; index < results.length; index++) {
/* all the vars here */
query.get(parsedData.objectId, {
success: function(idx, resultadr) {
var res = JSON.stringify(resultadr);
var parsedData_1 = jQuery.parseJSON(res);
var apartment = parsedData_1.apartment;
apa(idx, apartment);
}.bind(null, index),
error: function(object, error) {
alert('error');
}
});
function apa(index, apartment) {
console.log(index); console.log(apartment);
}
}
}
The first parameter (here: null) of bind() sets the context of the bound function. Whatever you pass in will be accessible in the success-callback by the keyword this.
I think every time you call the function the call will be compromised by next loop call.. so at last the method will be called only once.
You can declare index variable globally then all the functions have access to it

Why is my variable undefined inside the Underscore.js each function?

Here is my code:
TextClass = function () {
this._textArr = {};
};
TextClass.prototype = {
SetTexts: function (texts) {
for (var i = 0; i < texts.length; i++) {
this._textArr[texts[i].Key] = texts[i].Value;
}
},
GetText: function (key) {
var value = this._textArr[key];
return String.IsNullOrEmpty(value) ? 'N/A' : value;
}
};
I'm using the Underscore.js library and would like to define my SetTexts function like this:
_.each(texts, function (text) {
this._textArr[text.Key] = text.Value;
});
but _textArr is undefined when I get into the loop.
In JavaScript, the function context, known as this, works rather differently.
You can solve this in two ways:
Use a temporary variable to store the context:
SetTexts: function (texts) {
var that = this;
_.each(texts, function (text) {
that._textArr[text.Key] = text.Value;
});
}
Use the third parameter to _.each() to pass the context:
SetTexts: function (texts) {
_.each(texts, function (text) {
this._textArr[text.Key] = text.Value;
}, this);
}
You have to pass this as context for _.each call like this:
_.each(texts, function (text) {
this._textArr[text.Key] = text.Value;
}, this);
See the docs for http://underscorejs.org/#each
this in javascript does not work the same way as you would expect. read this article:
http://www.digital-web.com/articles/scope_in_javascript/
short version:
the value of this changes every time you call a function. to fix, set another variable equal to this and reference that instead
TextClass = function () {
this._textArr = {};
};
TextClass.prototype = {
SetTexts: function (texts) {
var that = this;
for (var i = 0; i < texts.length; i++) {
that._textArr[texts[i].Key] = texts[i].Value;
}
},
GetText: function (key) {
var value = this._textArr[key];
return String.IsNullOrEmpty(value) ? 'N/A' : value;
}
};
Note that you can also pass things other that "this". For example, I do something like:
var layerGroupMasterData = [[0],[1,2,3],[4,5],[6,7,8,9],[10]];
_.each(layerGroupMasterData,function(layerGroup,groupNum){
_.each(layerGroup, function (layer, i) {
doSomethingThatComparesOneThingWithTheOverallGroup(layerGroupMasterData,layer);
},layerGroups);
},layerGroupMasterData);

OO JS - loop through object array

Quite new to OO Js, used to program with function after function so trying to fix that now!
I'm making a tab layout -
I create a tab by calling: tab.NewTab();
I can access the tabs at tab[0], tab[1] etc
var tabCount = 0;
var tabs = [];
tabs.NewTab = function (){
var tabName = "tab" + tabCount;
tabs[tabCount] = new Tab(tabName);
tabCount++;
};
function Tab(tabName){
return{
name: tabName
}
}
I wanted to make a function that counts how many tabs are open:
tabs.HowMany = function () {
for (var i in tabs) {
alert("new");
}
};
This is returning the methods too (0,1, NewTab, HowMany).
Any advice?
You're looking for tabs.push(new Tab(tabName));
Then ditch tabCount, and instead use the length property native to all javascript arrays: tabs.length
Also, your Tab constructor is wrong. As it is currently written it should not be called with new. Just call Tab('someName') and it will return to you the object you're looking for. If you do that however, change it to tab since non-constructor functions should be lowercase.
If you're really eager to use the new keyword, this is what Tab should look like:
function Tab(tabName){
this.name = tabName;
}
EDIT
If you want to iterate over all members of your array, this is the simplest way:
for (var i = 0; i < tabs.length; i++)
var currentTab = tabs[i];
You need to change var tabs = []; to var tabs = new Array();.
And add items to it using tabs.push(new Tab(tabName));
Simple count:
var count = tabs.lenght
Enumeration of items:
for (var i = 0; i < tabs.length; i++) {
alert(tabs[i]);
}
You could do:
tabs.HowMany = function () {
for (var i in tabs) {
if(tabs.hasOwnProperty(i)){
if(typeof tabs[i] !== 'function'){
alert('new')
}
}
}
};
but you'd better switch using it as array
tabs.push(new Tab(tabName))
tabs.HowMany = function () {
return tabs.length
};

Categories

Resources