angular.module("customFilters", [])
.filter("unique", function () {
return function (data, propertyName) {
if (angular.isArray(data) && angular.isString(propertyName)) {
var results = [];
var keys = {};
for (var i = 0; i < data.length; i++) {
var val = data[i][propertyName];
console.log(angular.isUndefined(keys[val]))
if (angular.isUndefined(keys[val])) {
keys[val] = true;
results.push(val);
}
}
return results;
} else {
return data;
}
}
});
i am new to angularjs and facing problem with angular.isUndefined() function.
So the issue is like i am adding properties to an object with the help of for loop and also checking that if a particular property is already defined for the object, if the property is defined then i am not adding that property to the object but when i am using angular.isUndefined() to check the property it returns false even when the property is there in the object and keeps doing so two times and for the third time it returns true when i call angular.isUndefined().
Please help in here.
I understand basic recursion, but this problem has be stumped. I have a tree structure set up in a database, where each node(row) has an id and parent id.
I need a function that can run and in the callback return an array of all the descendants of a particular node given its id.
I've been able to put together a function that can print out all of the values, but I can't figure out how to capture them and return them in the callback. I know the base case isn't set up correctly, as I'm not sure what it should even be.
I'd appreciate any help! Thank you!
// My "database"
var nodes_collection = [
{id:"id1",name:"name1",parentid:"."},
{id:"id2",name:"name2",parentid:"id1"},
{id:"id3",name:"name3",parentid:"id1"},
{id:"id4",name:"name4",parentid:"id2"},
{id:"id5",name:"name5",parentid:"id3"},
{id:"id6",name:"name6",parentid:"id3"},
{id:"id7",name:"name7",parentid:"id5"},
{id:"id8",name:"name8",parentid:"id7"},
{id:"id9",name:"name9",parentid:"id7"},
{id:"id10",name:"name10",parentid:"id9"},
];
// This is NOT a real function, it simply performs the function that the real getChildren does when connected to my database!!!
function getChildren(parentid, callback){
var children = [];
for(var i=0; i < nodes_collection.length; i++){
if(nodes_collection[i].parentid == parentid){
children.push(nodes_collection[i].id);
}
}
callback(children);
}
function allDescendants(parentid, callback) {
getChildren(parentid, function(childNodes) {
if (false) { // Only false because I don't know what my base case should be.
//console.log("done");
} else {
for (var i = 0; i < childNodes.length; i++) {
var child = childNodes[i];
allDescendants(child);
console.log(child); // Here it prints out all the values. How can I capture them? and return them with my callback?
}
}
});
}
allDescendants("id3", function(result){
console.log(result);
});
EDIT:
Due to some confusion, I've changed the code to a bare bones example of what I'm trying to do that can be run locally !!! getChildren() is NOT a real function, it simply performs the function that the real getChildren does when connected to my database!!!
Bottom line:
The code in question works to recursively touch all values. Now how can I store all the values that are currently being outputted via console.log()?
Here's one simple way. We create a result object and an intermediary recursive function, keeping allDescendants as a wrapper. When the recursion is complete, we return the result that now has all the descendants.
JsvaScript code:
// My "database"
var nodes_collection = [
{id:"id1",name:"name1",parentid:"."},
{id:"id2",name:"name2",parentid:"id1"},
{id:"id3",name:"name3",parentid:"id1"},
{id:"id4",name:"name4",parentid:"id2"},
{id:"id5",name:"name5",parentid:"id3"},
{id:"id6",name:"name6",parentid:"id3"},
{id:"id7",name:"name7",parentid:"id5"},
{id:"id8",name:"name8",parentid:"id7"},
{id:"id9",name:"name9",parentid:"id7"},
{id:"id10",name:"name10",parentid:"id9"},
];
// This is NOT a real function, it simply performs the function that the real getChildren does when connected to my database!!!
function getChildren(parentid, callback){
var children = [];
for(var i=0; i < nodes_collection.length; i++){
if(nodes_collection[i].parentid == parentid){
children.push(nodes_collection[i].id);
}
}
callback(children);
}
function allDescendants(parentid, callback) {
let result = [];
let go = function(children){
for (child of children){
result.push(child);
getChildren(child, go)
}
}
getChildren(parentid, go);
callback(result);
}
allDescendants("id3", function(result){
console.log('result: ' + JSON.stringify(result));
});
I propose this:
let obj = [
{id:"id1",name:"name1",parentid:"."},
{id:"id2",name:"name2",parentid:"id1"},
{id:"id3",name:"name3",parentid:"id1"},
{id:"id4",name:"name4",parentid:"id2"},
{id:"id5",name:"name5",parentid:"id3"},
]
function getChilds(obj, parent_id, callback) {
if(obj.length === 0) return;
else if (typeof callback !== 'function'){
throw new Error("The callback must be a function ");
return;
}
let childs = obj.filter(function (c) {return c.parentid == parent_id })
if(childs.length > 0 ){
childs = childs.map(function (c) {return c.id})
}
callback(childs)
}
// Test
getChilds(obj, "id1", function (childs) {console.log(childs)})
I've got this issue with passing a variable to an IFFE. did some reading, still didn't figure it out. would really appreciate some guidance here.
i have a click event handler function that gets a certain ID from the
DOM when clicked.
i need to pass that ID to an IIFE
that IFFE needs to either add/remove that ID from an array,
depending if it's already there or not.
This is what I got:
Event:
$(document).on('click', 'input[type="checkbox"]', check);
Click Handler:
function check() {
var id = $(this).closest('ul').attr('data-id');
return id;
}
IIFE:
var checkID = (function (val) {
var arr = [];
return function () {
var i = arr.indexOf(val);
if (i === -1) {
arr.push(val);
} else {
arr.splice(i, 1);
}
return arr;
}
})(id);
right now i'm getting the ID, but returning it to nowhere.
in my IIFE, i did pass an id variable, but it's undefined.
so, how do I pass the ID variable im getting from check() to checkID IIFE?
other solutions are also welcome.
Thanks
In your clickHandler
function check() {
var id = $(this).closest('ul').attr('data-id');
checkID(id);
}
and change checkID to
var checkID = (function () {
var arr = [];
return function (val) {
var i = arr.indexOf(val);
if (i === -1) {
arr.push(val);
} else {
arr.splice(i, 1);
}
return arr;
}
})();
I think you need to do things sort of the other way around. Your check function would return a function used by the event handler, but it would also take a callback to be called after the click handler has run, passing your array.
The check function would look like a mash-up of both your functions:
function check(callback){
var arr = [];
return function(){
var id = $(this).closest('ul').attr('data-id');
var i = arr.indexOf(id);
if (i === -1) {
arr.push(id);
} else {
arr.splice(i, 1);
}
callback(arr);
}
}
As you can see, it takes as a parameter a callback function, which will be called on each execution, passing the current array arr. For example, this is my test callback:
function handler(arr){
alert("Array has " + arr.length + " elements");
}
Finally, your event handler would look like this:
$(document).on('click', 'input[type="checkbox"]', check(handler));
Live example: https://jsfiddle.net/src282d6/
Using getter/setter-like functions in your IIFE function makes it much more organized and readable. Then, use these functions to pass, store, and read data across your IIFE function.
var checkID = (function () {
// your array
var arr = [];
// public
return {
// get
getArray: function(){
return arr;
},
// set value
setArray: function(val) {
var i = arr.indexOf(val);
if (i === -1) {
arr.push(val);
} else {
arr.splice(i, 1);
}
}
}
})();
Use it as follows:
checkID.getArray(); // returns default empty array []
checkID.setArray('car1');
checkID.setArray('car2');
checkID.setArray('car3');
checkID.setArray('car4');
checkID.setArray('car4'); // test splice()
checkID.getArray(); // returns ["car1", "car2", "car3"]
I have a javascript object with several properties and methods. I want to call the first method within the second, in order to get the default number of ingredients of a pizza and compare it with another value. However, I detect that no-value is present in the comparison of the second method.
Googling about this issue, I saw that I have to make a callback in the first method, but it didn't work for me. So, how can I be sure that the property obj.app.defaultIngredients will have a value returned by the JSON, when a 'click' event in the second method will occur? And, in that moment, I can compare the value as you also can see in the second method?
There is my (not working) code:
obj = {};
obj.app = {
defaultIngredients: '',
getDefaultIngredientsNumber: function() {
$.getJSON('/sites/all/json/pizza.json', function(data) {
var node = $('.node').attr('data-nid'),
node = 'node-' + node; // returns something like 'node-3'
$.each(data, function(key, val) {
// This returns an integer
obj.app.defaultIngredients = parseInt(data[node].general.default_ingredients);
});
}).done(function() {
return obj.app.defaultIngredients;
});
},
customAddToCart: function() {
$('#button').click(function(){
var defaultIngredients = obj.app.getDefaultIngredientsNumber();
var selectedIngredients = 0;
if defaultIngredients >= selectedIngredients) {
alert('Add some ingredients');
}
}
}
};
Some help with this will be very apreciated.
getDefaultIngredientsNumber: function(callback) {
$.getJSON('/sites/all/json/pizza.json', function(data) {
var node = $('.node').attr('data-nid'),
node = 'node-' + node; // returns something like 'node-3'
$.each(data, function(key, val) {
obj.app.defaultIngredients = parseInt(data[node].general.default_ingredients);
});
callback(obj.app.defaultIngredients)
})
},
customAddToCart: function() {
$('#button').click(function(){
obj.app.getDefaultIngredientsNumber(function(defaultIngredients) {
var selectedIngredients = 0;
if (defaultIngredients >= selectedIngredients) {
alert('Add some ingredients');
}
})
})
}
I may be missing something since seems too easy ..
});
}).done(function(data) {
return anotherfunction(data);
});
Or instead of this:
customAddToCart: function() {
$('#button').click(function(){
var defaultIngredients = obj.app.getDefaultIngredientsNumber();
var selectedIngredients = 0;
if defaultIngredients >= selectedIngredients) {
alert('Add some ingredients');
}
}
}
};
I would use this:
customAddToCart: function() {
$('#button').click(function(){
obj.app.getDefaultIngredientsNumber("alert");
}
}
};
And in the getDefaultIngredientsNumber I would check if alert is set, then perform the alert..
Is it possible for arbitrary functional objects in js to be passed to Java side, so java can call that js object? (a callback)
for example, (access is a function that already registered to call a Java function)
access(function(blabla){
...
});
Are there any great techniques that can deal with anonymous callback function in java?
You just need some sort of key to reference your individual callback anonymous function. I think this is how jsonp is used sometimes too.
Javascript:
var callbacks = [];
function registerCallback(callback)
{
callbacks.push(callback);
return callbacks.length - 1;
}
function getCallback(index)
{
var callback = callbacks[index];
callbacks[index] = null;
TryGCCallbacks();
return callbacks;
}
//The array index positions must be preserved, but when it's empty, we should restart the array so it doesn't grow forever
function TryGCCallbacks()
{
var isCallbackRemaining = false;
for (var i = 0; i < callbacks.length; i++)
{
if (callbacks[i] == null) {
continue;
}
isCallbackRemaining = true;
break;
}
if (isCallbackRemaining == false)
{
callbacks = []; //reset
}
}
Java:
#org.xwalk.core.JavascriptInterface
public String TestCallback(String someData, String onSuccess, String onError){
xwalk.evaluateJavascript("getCallback(" + onSuccess + ")('success');", null);
}
Using this from Javascript:
var onSuccess = registerCallback(function(r) {
console.log(r);
});
TestCallback('lalala', onSuccess, null);