Call function in parent's parent from inside jquery's .each - javascript

I've created a 'class' in javascript called QuoteProductService(), see below.
I've added two functions to the prototype and now, I'm trying to call one of the functions (getQuoteProductFromArray) from within a jquery $.each inside the other function (getFakeQuoteProducts). This doesn't work. I've tried adding 'this.', but this also does not work, because 'this' inside the .each refers to the current element in the loop.
How should I do this ?
function QuoteProductService() {
}
QuoteProductService.prototype.getQuoteProductFromArray = function(quoteproductarray, quoteproductid){
var founditem=null;
// do stuff
return founditem;
}
QuoteProductService.prototype.getFakeQuoteProducts = function(){
// do something to fill the mappedQuoteProducts array
$.each(mappedQuoteProducts, function (index, quoteproduct) {
if (quoteproduct!=-null) {
if (quoteproduct.parentid != "") {
// this is where it goes wrong :
var parent = getQuoteProductFromArray(mappedQuoteProducts, quoteproduct.parentid);
if (parent != null) {
parent.attachChild(quoteproduct);
}
}
}
});
}

Save a reference to your QuoteProductService instance before calling each
QuoteProductService.prototype.getFakeQuoteProducts = function(){
var _this = this;
// do something to fill the mappedQuoteProducts array
$.each(mappedQuoteProducts, function (index, quoteproduct) {
if (quoteproduct!=-null) {
if (quoteproduct.parentid != "") {
// this is where it goes wrong :
var parent = _this.getQuoteProductFromFlatArray(mappedQuoteProducts, quoteproduct.parentid);
if (parent != null) {
parent.attachChild(quoteproduct);
}
}
}
});
}

Add var self = this; to the beginning of the getFakeQuoteProducts function. Then call getQuoteProductFromFlatArray like this: self.getQuoteProductFromFlatArray.

First of all you provided wrong method name - getQuoteProductFromFlatArray instead of getQuoteProductFromArray. Secondly in JS you must provide scope for instance methods.
Easiest way to achieve this is to store this reference into some other, private variable. See the example below.
function QuoteProductService() {
}
QuoteProductService.prototype.getQuoteProductFromArray = function(quoteproductarray, quoteproductid){
var founditem=null;
// do stuff
return founditem;
}
QuoteProductService.prototype.getFakeQuoteProducts = function(){
var me = this; // store this into me
// do something to fill the mappedQuoteProducts array
$.each(mappedQuoteProducts, function (index, quoteproduct) {
// this === me will return false
if (quoteproduct!=-null) {
if (quoteproduct.parentid != "") {
// this is where it goes wrong :
var parent = me.getQuoteProductFromArray(mappedQuoteProducts, quoteproduct.parentid);
if (parent != null) {
parent.attachChild(quoteproduct);
}
}
}
});
}

Related

Convert Javascript array back into JQuery-type object

For the code below, I wanted to make the _formsOk function work for both Javascript arrays and "JQuery objects". In function1(), I tried to create a Javascript array with all DOM elements except those that have a parent element with id="objectTypesContainer". Basically, function1() filters out the DOM elements I don't want before calling _formsOk() function, which does the actual form validation.
function1() {
var allForms = $('form:not(.vv_hidden)', this.selectMarketsContainer);
var nonObjectTypeForms = [];
allForms.each(function () {
if ($(this).parent().attr("id") !== "objectTypesContainer"){
nonObjectTypeForms.push($(this)[0]);
}
});
return this._formsOk(nonObjectTypeForms);
},
_formsOk: function($forms) {
var formOk = true;
console.log(typeof $forms)
$forms.each(function () { // This line fails
var validator = $(this).validate(DEFAULT_VALIDATION_OPTIONS);
if (!(validator && validator.form())) {
formOk = false;
}
});
return formOk;
},
However, I realized that because nonObjectTypeForms is now a JS Array rather than a "JQuery Object", the line marked (// This line fails) now fails.
The original code looked like this:
function1() {
var allForms = $('form:not(.vv_hidden)', this.selectMarketsContainer); // This is a "JQuery object", so no error occurs
return this._formsOk(allForms);
},
_formsOk: function($forms) {
var formOk = true;
console.log(typeof $forms)
$forms.each(function () { // This line fails
var validator = $(this).validate(DEFAULT_VALIDATION_OPTIONS);
if (!(validator && validator.form())) {
formOk = false;
}
});
return formOk;
},
Is there a way I can convert a JS array into a JQuery object ? I don't want to change _formsOk function definition just yet.
Instead of putting all elements in a new array, just use .filter() from the jQuery object.
allForms.filter(function () {
return $(this).parent().attr("id") !== "objectTypesContainer")
});
This will remove all the items you don't need in your selection and now allForms will only have the wanted elements.

call user function in foreach loop

i have understand that i need to change the global scope of this, because in the loop this refers to the window object. But if i try to define a variable in my foreach loop via a function its not working and i dont know why although my functio returns the correct value :(
// simple class for xml import
function io() {
this.vertexes = [];
this.getVertexByID = function(id) {
this.vertexes.forEach(function(entry) {
if (id == entry.id) {
// correct element found, displayed and returned
console.log(entry);
return entry;
}
});
}
this.importXML = function(xmlString) {
cells = this.xmlToJson(xmlString);
var parent = graph.getDefaultParent();
var _this = this;
graph.getModel().beginUpdate();
try {
// addEdges
cells.XMLInstance.Edges.Relation.forEach(function(entry) {
// both will be empty but i dont understand why :(
fromVertex = _this.getVertexByID(entry.fromNode);
toVertex = _this.getVertexByID(entry.toNode);
var e1 = graph.insertEdge(parent, null, '', fromVertex, toVertex);
});
} finally {
graph.getModel().endUpdate();
}
}
Returning a value in a forEach callback has no effect. It certainly is not the return value of the function that the forEach is part of.
So change this:
this.vertexes.forEach(function (entry) {
if(id==entry.id){
//correct element found,displayed and returned
console.log(entry);
return entry;
}
});
to this:
return this.vertexes.find(function (entry) {
return id==entry.id;
});

Javascript: Calling an object-function from a click-function inside an object-function

I have a problem. It is my first try to work with objects in Javascript and I run in a problem.
I have an object that contains a DOM-Element and I want to add to the children of that element a click-function. Inside the click-function I want to call another object-function but that doesn't work. To call another object function I have to use this.functionname() but because I am inside the click-function this isn't anymore my object but the child-Element that I add the click-function to. So my question is: How do call my object-function from inside of a click-function.
Here is my Code (the if-condition in the middle of the code isn't important):
function ManagementCard(card) {
this.card = card;
this.row = null;
this.rowAlt = null;
this.managementCard = this;
}
ManagementCard.prototype.initializeCard = function () {
this.card.find(".card ul li div:first-child").click(function () {
row = $(this).parent();
if(this.rowAlt != null && this.rowAlt[0] != $(this).parent()[0])
{
this.rowAlt.children("div:last-child").collapse('hide');
$(this.rowAlt).css('background-color', '');
$(this.rowAlt).css('color', '');
this.rowAlt = null;
}
this.toggleManagementRow(); <=== Important! Call object-function from inside of a click-function which is inside the object-function
});
}
ManagementCard.prototype.getCard = function () {
return this.card;
}
Keep the reference to the object in another variable e.g. self. It is a common thing to do that in JavaScript
ManagementCard.prototype.initializeCard = function () {
var self = this;
this.card.find(".card ul li div:first-child").click(function () {
row = $(this).parent();
if(this.rowAlt != null && this.rowAlt[0] != $(this).parent()[0])
{
this.rowAlt.children("div:last-child").collapse('hide');
$(this.rowAlt).css('background-color', '');
$(this.rowAlt).css('color', '');
this.rowAlt = null;
}
self.toggleManagementRow();
});
}

Init class properties

i have some javascript class someClass and have initialization function init which check constructor params. Object with this params are rather huge and this function became too large.
function SomeClass (paramObj) {
this.inputHourId;
this.inputHourName;
this.inputHourValue;
......
......
this.Init = function (paramObj) {
if (typeof paramObj.hourOptions.inputName == "undefined") {
this.inputHourName = "default_name";
} else {
this.inputHourName = paramObj.hourOptions.inputName;
}
if (typeof paramObj.hourOptions.inputValue == "undefined") {
this.inputHourValue = "default_value";
} else {
this.inputHourValue = paramObj.hourOptions.inputValue;
}
......
......
......
}
this.Init(paramObj);
}
To avoid code duplication and make it more readable i decide to create function which will do var initialization with check
this.initVar = function (veriable, value) {
if (typeof value == "undefined") {
veriable = "some_default_value";
} else {
veriable = val;
}
}
after adding initVar function, my Init function should look like that:
this.Init = function (paramObj) {
// Input hour initialization
this.initVar(this.inputHourId, paramObj.hourOptions.inputId);
this.initVar(this.inputHourName,
paramObj.hourOptions.inputName);
this.initVar(this.inputHourValue, paramObj.hourOptions.inputValue);
....
....
....
}
but after that class vars this.inputHourName are still undefined
Now the question. How can I init my class property with the help of function? Or how can i transmit class property like function parametr?
That's because when you pass this.inputHourId to initVar() it will make a copy of the variable when it's being updated; that's not what you want.
You can rewrite initVar() to this; it uses the name of the variable as a string rather than the variable itself. Then it uses this[variable] to update the actual instance variable.
this.initVar = function (variable, value) {
if (typeof value == "undefined") {
this[variable] = "some_default_value";
} else {
this[variable] = val;
}
}
Then, you call it like:
this.initVar('inputHourId', paramObj.hourOptions.inputId);
also you can use this syntax instead of your bunch of ifs :
this.param1 = params.param1 || "default_value";
How can I init my class property with the help of function?
Since you can't pass a reference of the property which you want to assign to to the function, just return the value from the function and assign the result to the property:
this.inputHourId = initVar(paramObj.hourOptions.inputId);

Resolve function pointer in $(document).ready(function(){}); by json string name

I have a json object retrieved from server in my $(document).ready(...); that has an string that I would like to resolve to a function also defined within $(document).ready(...); so, for example:
$(document).ready(function{
$.getJSON(/*blah*/,function(data){/*more blah*/});
function doAdd(left,right) {
return left+right;
}
function doSub(left,right) {
return left-right;
}
});
with json string:
{"doAdd":{"left":10,"right":20}}
One way I thought about was creating an associative array of the function before loading the json:
var assocArray=...;
assocArray['doAdd'] = doAdd;
assocArray['doSub'] = doSub;
Using eval or window[](); are no good as the function may not be called for some time, basically I want to link/resolve but not execute yet.
Change your JSON to
{method: "doAdd", parameters : {"left":10,"right":20}}
Then do
var method = eval(json.method);
// This doesn't call it. Just gets the pointer
Or (haven't tried this)
var method = this[json.method]
How about something like this?
$(function(){
// Function to be called at later date
var ressolvedFunc = null;
// Ajax call
$.getJSON(/*blah*/,function(data){
// Generate one function from another
ressolvedFunc = (function(data) {
var innerFunc;
var left = data.left;
var right = data.right;
// Detect action
for (action in data) {
if (action == "doAdd")
innerFunc = function() {
return left + right;
};
else
innerFunc = function() {
return left - right;
};
}
return innerFunc;
})(data);
});
});
The anonymous function returns fresh function, with the new values stored within the enclosure. This should allow you to call the function at later date with the data previously retrieved from the GET request.
Rich
try this:
var doX = (function() {
var
data = [],
getDo = function(action) {
for(var d in data) {
if (data[d][action]) {
return data[d];
}
}
return null;
};
return {
set: function(sdata) {
data.push(sdata);
},
doAdd: function() {
var add = getDo("doAdd");
if (!add)
return 0;
return add.doAdd.left + add.doAdd.right;
},
doSub: function() {
var sub = getDo("doSub");
if (!sub)
return 0;
return sub.doAdd.left + sub.doAdd.right;
}
};
})();
$(document).ready(function{
$.getJSON(/*blah*/,function(data){ doX.set(data); });
});

Categories