Code flow through callback in java script - javascript

-----------------File1.html-------------------------
<body>
<div id="tooltip"></div>
<script src="lib/d3.js"></script>
<script src="lib/underscore.js"></script>
<script src="js/mapper.js"></script>
<script>
d3.json('data/readme.json', function (error, data) {
var mpr = chordMpr(data);
_.each(data, function (elem) {
mpr.addToMap(name(elem.name))
})
mpr.setFilter(function (row, a, b) {
/* alert(JSON.stringify(a) +"-------"+JSON.stringify(row)+"-------"+JSON.stringify(b));
alert(a.name + "--" + row.name + "--" + b.name); */
return (name(row.name) === a.name)
})
.setAccessor(function (recs, a, b) {
if (!recs[0]) return 0;
var n = 0;
_.each(recs, function (r) {
//alert(r.imports)
_.each(r.imports, function (i) {
// alert(JSON.stringify(b) + "----" + i);
if (name(i) === b.name) n++;
});
});
return n;
});
alert(/* "*****" + mpr.getMatrix() + "-----" + */ JSON.stringify(mpr.getMap()));
drawChords(mpr.getMatrix(), mpr.getMap());
});
function name(name) {
return name.substring(0, name.lastIndexOf(".")).substring(6);
}
---------------------------File1.html-----------------------------
------------------------------mapper.js---------------------------
//*******************************************************************
// CHORD MAPPER
//*******************************************************************
function chordMpr (data) {
alert(data + "kimi is faster than you");
var mpr = {}, mmap = {}, n = 0,
matrix = [], filter, accessor;
mpr.setFilter = function (fun) {
alert("inside filter");
filter = fun;
return this;
},
mpr.setAccessor = function (fun) {
accessor = fun;
return this;
},
mpr.getMatrix = function () {
matrix = [];
_.each(mmap, function (a) {
if (!matrix[a.id]) matrix[a.id] = [];
_.each(mmap, function (b) {
var recs = _.filter(data, function (row) {
return filter(row, a, b);
})
matrix[a.id][b.id] = accessor(recs, a, b);
});
});
return matrix;
},
mpr.getMap = function () {
return mmap;
},
mpr.printMatrix = function () {
_.each(matrix, function (elem) {
console.log(elem);
})
},
mpr.addToMap = function (value, info) {
if (!mmap[value]) {
mmap[value] = { name: value, id: n++, data: info }
}
},
mpr.addValuesToMap = function (varName, info) {
alert("inside addValuesToMap " + varName + info);
var values = _.uniq(_.pluck(data, varName));
alert(values);
//values is the list of countries in the importer[i] column in CSV form
_.map(values, function (v) {
//v is individual country in the importer[i] column
if (!mmap[v]) {
mmap[v] = { name: v, id: n++, data: info }
}
});
return this;
}
return mpr;
}
//*******************************************************************
// CHORD READER
//*******************************************************************
function chordRdr (matrix, mmap) {
return function (d) {
var i,j,s,t,g,m = {};
if (d.source) {
i = d.source.index; j = d.target.index;
s = _.where(mmap, {id: i });
t = _.where(mmap, {id: j });
m.sname = s[0].name;
m.sdata = d.source.value;
m.svalue = +d.source.value;
m.stotal = _.reduce(matrix[i], function (k, n) { return k + n }, 0);
m.tname = t[0].name;
m.tdata = d.target.value;
m.tvalue = +d.target.value;
m.ttotal = _.reduce(matrix[j], function (k, n) { return k + n }, 0);
} else {
g = _.where(mmap, {id: d.index });
m.gname = g[0].name;
m.gdata = g[0].data;
m.gvalue = d.value;
}
m.mtotal = _.reduce(matrix, function (m1, n1) {
return m1 + _.reduce(n1, function (m2, n2) { return m2 + n2}, 0);
}, 0);
return m;
}
}
I am having difficulty in analysing the code flow in the above code.
In the mpr.setFilter(function (row, a, b)) call, what are row, a and b? I can't find any variables by this name. Also how are the calls translating from one function to other.
Please help.

setFilter is a function which takes an argument of a function that is stored to a "member" variable filter. When the user calls setFilter and passes their function they must know the contract that it takes three arguments. These are your row, a, and b arguments, they aren't assigned here, just there to make the function match later on.
If you trace this a little further that anonymous function passed into setFilter and stored in the variable filter is then called in the getMatrix function in mapper.js. You'll see when it is called the arguments of row, a and b are passed in.
Ain't JavaScript fun?

Related

change a variable inside it without redefining the function

Friends
How, after defining a function, change a variable inside it without redefining the function.
For example, I have this function
Data = function () {
function n() {
var n = this;
this.same = function (n) {
this.search = function (n, t, i, r) { ... }
this.go = function (n, t) { ... }
this.get = function (n, t) {... }
this.run = function (n, t) { console.log("test") } //change this item
}
}
}()
And I want it to become the following function.
Data = function () {
function n() {
var n = this;
this.same= function (n) {
this.search = function (n, t, i, r) { ... }
this.go = function (n, t) { ... }
this.get = function (n, t) {... }
this.run = function (n, t) { alert("test ok") } // changed
}
}
}()
I don't think the other answer totally achieves what you want. If so, this might be a better alternative:
var Data = function () {
this.run = function (n, t) { console.log("test") } // change this later
var dataSelf = this;
this.n = function () {
var n = this;
this.same = function (n) { }
this.search = function (n, t, i, r) { }
this.go = function (n, t) { }
this.get = function (n, t) { }
this.run = dataSelf.run
};
}
const en = new Data()
new en.n().run() // Logs "test"
en.run = function(n, t) { alert("test ok"); }
new en.n().run() // Alerts "test ok"

How can I write these functions to use a forEach() statement?

How can write these (working) functions using forEach() methods:
function loadAudioMeterHistory(cell) {
var peaks = new Array(4);
for (var i = 0; i < peaks.length; i++) {
var peak,
age;
peak = cell.getAttribute("data-peak-" + i);
age = cell.getAttribute("data-age-" + i);
peaks[i] = new Peak(peak, age);
}
return peaks;
}
function setAudioMeterHistory(cell, peaks) {
for (var i = 0; i < peaks.length; i++) {
cell.setAttribute("data-peak-" + i, peaks[i].peak);
cell.setAttribute("data-age-" + i, peaks[i].age);
}
}
My attempt was the following:
function loadAudioMeterHistory(cell) {
"use strict";
var peaks = new Array(4);
peaks.forEach(function(item, index) {
var p = cell.getAttribute("data-peak-" + index);
var a = cell.getAttribute("data-age-" + index);
item = new Peak(p, a);
});
return peaks;
}
function setAudioMeterHistory(cell, peaks) {
"use strict";
peaks.forEach(function(item, index) {
cell.setAttribute("data-peak-" + index, item.peak);
cell.setAttribute("data-age-" + index, item.age);
});
}
which, behaves differently, in that peaks is never properly created. The savvy javascripter will undoubtedly recognise that I'm attempting to jslint.com my code.
The Peak() method (for brevity's sake) is simply:
function Peak(peak, age) {
this.peak = peak;
this.age = age;
}
What gives?
forEach just iterates over a list but does not return anything. So use map instead and return the newly created object.
function loadAudioMeterHistory(cell) {
"use strict";
var peaks = [0, 1, 2, 3].map(function(item, index) {
var p = cell.getAttribute("data-peak-" + index);
var a = cell.getAttribute("data-age-" + index);
return new Peak(p, a);
});
}
One more problem is peaks is not available outside the scope of loadAudioMeterHistory. So have the function return that which can be passed into the next function call.
function loadAudioMeterHistory(cell) {
"use strict";
return [0, 1, 2, 3].map(function(item, index) {
var p = cell.getAttribute("data-peak-" + index);
var a = cell.getAttribute("data-age-" + index);
return new Peak(p, a);
});
}
function setAudioMeterHistory(cell) {
"use strict";
var peaks = loadAudioMeterHistory(cell);
peaks.forEach(function(item, index) {
cell.setAttribute("data-peak-" + index, item.peak);
cell.setAttribute("data-age-" + index, item.age);
});
}
You can use Array.from() whose second argument is a function to populate the array:
function loadAudioMeterHistory(cell) {
return Array.from({ length: 4 }, (_, i) => {
const peak = cell.getAttribute('data-peak-' + i);
const age = cell.getAttribute('data-age-' + i);
return new Peak(peak, age);
});
}
For the second function, use forEach() like this:
function setAudioMeterHistory(cell, peaks) {
peaks.forEach(({ peak, age }) => {
cell.setAttribute('date-peak-' + i, peak);
cell.setAttribute('data-age-' + i, age);
});
}

Parse Cloud Code Error: Parse.Error {code: 141, message: "success/error was not called"}

I want to conditionally update several Parse.Objects using cloud code. The function is supposed to save select data to a new column should it apply to the User in question.
I'm having some serious issues with this in my first Cloud Code function. I think I have most of it right but I keep getting a success/error was not called error.
I'm using the following code:
Parse.Cloud.define("someFunction", function(request, response) {
var user = Parse.Object.extend("User");
var query = new Parse.Query(Parse.User);
var Table1 = Parse.Object.extend("Table1");
var table1Query = new Parse.Query(Table1);
var Table2 = Parse.Object.extend("Table2");
var table2Query = new Parse.Query(Table2);
var Ids = req.body //this is an array of Parse.Object Ids
var array = [];
var x = Ids.length
while (x--){
var Id = Ids[x];
table1Query.equalTo("user", {__type: "Pointer", className: "_User",
objectId: Id});
table1Query.find({
success: function (results) {
var resultIds = _.map(results, function (n) {
return n.id});
var resultObjs = _.map(results, function (n) {
return return _.extend(_.find(n), {id: n.id})});
var a = resultIds.length
while (a--) {
var resultId = resultIds[a];
table2Query.equalTo("user", {__type: "Pointer", className: "_User",
objectId: resultId});
table2Query.find({
success: function (items) {
var MA = _.map(_.flatten(items), function (n) {
return _.find(n)});
var step3 = _.map(resultObjs, function (n) {return _.extend(n, {
Matched: _.filter(MA, function (a) {return a.result.id == n.id})})});
var total = Math.round(_.reduce(_.map(step3, function (n) {return n.Bill
}), function (memo, num) {return memo + num;}, 0) * 100) / 100;
var duty = function (total, id) {
var promise = new Parse.Promise();
table2Query.get(id, {
success: function (Answer) {
Answer.set("duty", total);
Answer.save().then(function (difresult) {
response.success(difresult);
}, function (error) {
response.error(error);})
}
});
}
array.push(duty(Answer, Id))
}
})
}
}
})
}
return Parse.Promise.when(array);
})
I hope this is helpful to someone one day. The answer/difference in code is to be found at the very end as I added .then to put the response.success/error:
Parse.Cloud.define("someFunction", function(request, response) {
var user = Parse.Object.extend("User");
var query = new Parse.Query(Parse.User);
var Table1 = Parse.Object.extend("Table1");
var table1Query = new Parse.Query(Table1);
var Table2 = Parse.Object.extend("Table2");
var table2Query = new Parse.Query(Table2);
var Ids = req.body //this is an array of Parse.Object Ids
var array = [];
var x = Ids.length
while (x--){
var Id = Ids[x];
table1Query.equalTo("user", {__type: "Pointer", className: "_User",
objectId: Id});
table1Query.find({
success: function (results) {
var resultIds = _.map(results, function (n) {
return n.id});
var resultObjs = _.map(results, function (n) {
return return _.extend(_.find(n), {id: n.id})});
var a = resultIds.length
while (a--) {
var resultId = resultIds[a];
table2Query.equalTo("user", {__type: "Pointer", className: "_User",
objectId: resultId});
table2Query.find({
success: function (items) {
var MA = _.map(_.flatten(items), function (n) {
return _.find(n)});
var step3 = _.map(resultObjs, function (n) {return _.extend(n, {
Matched: _.filter(MA, function (a) {return a.result.id == n.id})})});
var total = Math.round(_.reduce(_.map(step3, function (n) {return n.Bill
}), function (memo, num) {return memo + num;}, 0) * 100) / 100;
var duty = function (total, id) {
var promise = new Parse.Promise();
table2Query.get(id, {
success: function (Answer) {
Answer.set("duty", total);
Answer.save().then(function (difresult) {
response.success(difresult);
}, function (error) {
response.error(error);})
}
});
}
array.push(duty(Answer, Id))
}
})
}
}
})
}
return
Parse.Promise.when(array).then(function() {
response.success("Successfully retrieved Total Bills.");
},
function(error) {
response.error("Something is still wrong");
console.log(error);
});;
})

Cartesian product of multidimensional array

I took js-combinatorics code and produced this:
(function(global) {
'use strict';
if (global.Combinatorics) return;
/* common methods */
var addProperties = function(dst, src) {
Object.keys(src).forEach(function(p) {
Object.defineProperty(dst, p, {
value: src[p]
});
});
};
var hideProperty = function(o, p) {
Object.defineProperty(o, p, {
writable: true
});
};
var toArray = function(f) {
var e, result = [];
this.init();
while (e = this.next()) result.push(f ? f(e) : e);
this.init();
return result;
};
var common = {
toArray: toArray,
map: toArray,
forEach: function(f) {
var e;
this.init();
while (e = this.next()) f(e);
this.init();
},
filter: function(f) {
var e, result = [];
this.init();
while (e = this.next()) if (f(e)) result.push(e);
this.init();
return result;
}
};
/* Cartesian Product */
var arraySlice = Array.prototype.slice;
var cartesianProduct = function() {
if (!arguments.length) throw new RangeError;
var args = arraySlice.call(arguments);
args = args[0];
console.log(args);
var
size = args.reduce(function(p, a) {
return p * a.length;
}, 1),
sizeOf = function() {
return size;
},
dim = args.length,
that = Object.create(args, {
length: {
get: sizeOf
}
});
if (!size) throw new RangeError;
hideProperty(that, 'index');
addProperties(that, {
valueOf: sizeOf,
dim: dim,
init: function() {
this.index = 0;
},
get: function() {
if (arguments.length !== this.length) return;
var result = [];
arguments.forEach(function(element,index,array) {
var i = arguments[index];
if(i >= this[index].length) return;
result.push(this[index][i]);
});
return result;
},
nth: function(n) {
var result = [];
arguments.forEach(function(element,index,array) {
var l = this[index].length,
i = n % l;
result.push(this[index][i]);
n -= i;
n /= l;
});
return result;
},
next: function() {
if (this.index >= size) return;
var result = this.nth(this.index);
this.index++;
return result;
}
});
addProperties(that, common);
that.init();
return that;
};
/* export */
addProperties(global.Combinatorics = Object.create(null), {
cartesianProduct: cartesianProduct
});
})(this);
var _ = [];
_[1] = [1,4];
_[7] = [2,9];
cp = Combinatorics.cartesianProduct(_);
console.log(cp.toArray());
I expect to get this result in the end:
[[1,2],[1,9],[4,2],[4,9]]
But keep getting Uncaught TypeError: undefined is not a function in Chrome and TypeError: arguments.forEach is not a function in Firefox every time I use forEach in this part of code:
nth: function(n) {
var result = [];
arguments.forEach(function(element,index,array) {
var l = this[index].length,
i = n % l;
result.push(this[index][i]);
n -= i;
n /= l;
});
return result;
}
Keeping indexes of _ array is a must.
arguments is not an Array, so it doesn't have a forEach method.
You can convert it to an array just like you did in var args = arraySlice.call(arguments);, or you use a for loop to iterate over its elements.
I needed to post the _ array with non-strict indexation:
var _ = [];
_[1] = [1,4];
_[7] = [2,9];
The default solutions are no-go, because they do not handle such arrays. So I had to tweak Bergi's idea found here:
function cartesian(arg) {
var r = [], max = arg.length-1;
function helper(arr, i) {
while(typeof arg[i] === "undefined") {
i += 1;
}
for (var j=0, l=arg[i].length; j<l; j++) {
var a = arr.slice(0); // clone arr
a.push(arg[i][j]);
if (i==max) {
r.push(a);
} else
helper(a, i+1);
}
}
helper([], 0);
return r;
}

How to put and get the value by the key using object in JavaScript?

How to use the functionality of dictionary in JavaScript?
Look at this question the specified way is working, but I am setting the function instance as a key like this:
Scale = function ()
{
this.Collections = {};
this.IndexTracker = {};
this.UpdateIndex = function ()
{
var index = 0;
for ( var i = 0; i < this.Collections.length; i++ )
{
this.SetIndex( this.Collections[i], index++ );
}
}
this.SetIndex = function ( obj, value )
{
this.IndexTracker[obj] = value;
}
this.GetIndex = function ( obj, value )
{
return this.IndexTracker[obj];
    }
}
this.Collections will hold the some function instance.
The problem here is the function instance is overwritten by the next function instance in this.Collections. The the length of the Collections always is 1. How to solve this?
This is an example:
var Scale = function () {
var _Collections = {},
_IndexTracker = {},
ret = function () {
function UpdateIndex() {
var index = 0,i,l;
for (i = 0,l=_Collections.length; i < l; i++) {
this.SetIndex(_Collections[i], index++);
}
}
function SetIndex(obj, value) {
_IndexTracker[obj] = value;
}
function GetIndex(obj, value) {
return _IndexTracker[obj];
}
return {
UpdateIndex : UpdateIndex,
SetIndex : SetIndex,
GetIndex : GetIndex
};
};
return ret;
}();

Categories