PHPJS' array_diff returns undefined - javascript

Example:
http://jsfiddle.net/7Cwbn/60/
I'm trying to use array_diff function from PHPJS to check if all of the elements inside selectedFeatures are found inside elem.features, but instead I receive undefined. What gives?
$(markers.houses).each(function(index, elem) {
//first filter by selected features
console.log(array_diff(elem.features, selectedFeatures).length);
if (array_diff(selectedFeatures, elem.features).length == 0) {
if (!markers.houseMarkers[index].visible) {
markers.houseMarkers[index].setVisible(true);
}
}
});

Solution:
Inside array_diff() definition change the retVal to equal [] instead of {}.

Related

Foreach function that clicks on check boxes

I need function to click on a range of check boxes. I do however not always know what i is. I tried a write a forEach loop, but it does not work:
This for loop works:
function check Boxes() {
for (let i = 0; i < 249; i++) {
document.getElementsByClassName("inventoryCbox")[i].click();
}
}
and this is the non-working for loop. I think that maybe my syntax is wrong.
checkBoxes();
var boxes = document.getElementsByClassName("inventoryCbox");
function checkBoxes(node) {
node.forEach(function(boxes) {
boxes.click()
});
}
This will check all the checkboxes with the class 'inventoryCbox':
document.querySelectorAll(".inventoryCbox").forEach(node => node.click())
node in your checkBoxes function is undefined, because you're not passing anything into the function. Also, your code has you calling checkBoxes before you assign anything to boxes. You probably meant to use boxes directly:
// This *before* `checkboxes`
var boxes = document.getElementsByClassName("inventoryCbox");
checkBoxes();
function checkBoxes() { // <== No parameter
boxes.forEach(function(box) {
//^^^^^ ^^^
box.click()
// ^^^
});
}
But that still has a problem: The HTMLCollection returned by getElementsByClassName doesn't have forEach reliably cross-browser. (The NodeList returned by querySelectorAll has it on modern browsers, but not HTMLCollection.)
You can add it if you like:
if (typeof HTMLCollection !== "undefined" &&
HTMLCollection.prototype &&
!HTMLCollection.prototype.forEach) {
// Yes, direct assignment is fine here, no need for `Object.defineProperty`
HTMLCollection.prototype.forEach = Array.prototype.forEach;
}
Then the updated code above would work.
Or stick with your existing loop, or use Array.prototype.forEach directly:
function checkBoxes() { // <== No parameter
Array.prototype.forEach.call(boxes, function(box) {
box.click()
});
}
My answer here goes into details for adding not just forEach but iterability to HTMLCollection (and NodeList in environments that haven't implemented iterability for NodeList yet).
If you want to click on all elements selected by some class, you can use this example
var els = document.querySelectorAll('.inventoryCbox');
for (i = 0; i < els.length; ++i) {
els[i].click();
};

Unexpected modify of non primitive values in loop

I'm working with an angular service of the type:
services.factory('SaveHistory', function($rootScope, $localForage){
return {
videoAccessed: function(idPillola) {
$localForage.getItem('trainings_user_'+$rootScope.user.id)
.then(function(succ, err) {
for (var item in succ) {
[].forEach.call(succ[item], function(el, index) {
el.pillole.forEach(function(el, index){
if (el.idPercorso == idPillola) {
console.log(idPillola);
el.tracking.completion_status = 1;
}
});
});
}
var newTrainings = succ;
...
});
}
When the function is fired with the correct idPillola , console.log logs the correct idPillola value one single time, so it seems that the cycle works correctly. But : if the attribute in the object (object or rather 'el' in the nested forEach cycle) that i want to change is a primitive , there are no problems, if the attribute is not primitive but an another object attribute, like tracking.completion_status in this case, all elements are updated ! (Like the if control had been ignored).
It is related to Angular or Javascript itself?

Creating custom angular filters

i have a json of items and a barcode scanner, the barcode scanner inputs directly into my app.
Now the items have a primary part number and a secondary part number, more often than not the result from the barcode scanner will be the primary part number, but i have to check with both to be sure.
I'm trying to implement a custom filter to do this, but it doesn't seem to be working, can anyone maybe let me know what i'm doing wrong ?
storeApp.filter('barcodeScanner', function() {
return function(parts, barcode) {
angular.forEach(parts, function (vals, key) {
if( !angular.isUndefined(vals.Part_Number) && vals.Part_Number !== null )
if (angular.equals(vals.Part_Number,barcode))
return parts[key];
});
angular.forEach(parts, function(vals, key) {
if ( !angular.isUndefined(vals.Other_Part_Number) && vals.Other_Part_Number !== null )
if (angular.equals(vals.Other_Part_Number,barcode))
return parts[key];
});
};
});
i then call the filter later in the controller,
$scope.addItemToCart = function() {
$scope.shoppingCart.push($filter('barcodeScanner')($scope.parts, $scope.ItemToAdd));
console.log($scope.Cart.itemToAdd);
console.log($filter('barcodeScanner')($scope.parts, $scope.Cart.itemToAdd));
$scope.Cart.itemToAdd = "";
console.log($scope.shoppingCart);
};
however the result from the filter keeps returning undefined. i know for a fact that the entry i want does exist, because when i use a normal $filter('filter') it works fine, but i cannot risk such a widespread filter for my app.
thanks for any help :)
I believe the problem lies in the forEach part of your function. A forEach function does not return a value. You are returning a value to your iterator function and since the forEach is not returning that returned value from the iterator then you will have nothing to push in your $scope.shoppingCart.push($filter('barcodeScanner')($scope.parts, $scope.ItemToAdd));
Saving to a variable ie. matchedPart declared inside the anonymous factory(wrapper) function and returning it outside of the forEach function should solve the undefined:
storeApp.filter('barcodeScanner', function() {
return function(parts, barcode) {
// declare a variable here
var matchedPart;
angular.forEach(parts, function (vals, key) {
if( !angular.isUndefined(vals.Part_Number) && vals.Part_Number !== null )
if (angular.equals(vals.Part_Number,barcode))
// save it to new variable
matchedPart = parts[key];
});
angular.forEach(parts, function(vals, key) {
if ( !angular.isUndefined(vals.Other_Part_Number) && vals.Other_Part_Number !== null )
if (angular.equals(vals.Other_Part_Number,barcode))
// save it to new variable
matchedPart = parts[key];
});
// return it outside the forEach function
return matchedPart;
};
});
last note:
I would also think you should refactor by combining your forEach functions. Not have 2 separate ones. Combining your isUndefined check with !angular.isUndefined(vals.Part_Number) && !angular.isUndefined(vals.Other_Part_Number) && vals.Part_Number...
Instead of .equals you need to check == because string will not exactly equal to number
angular.equals is nothing but strongly check in javascript === which check both values are equal with their type or not.
if(angular.equals(vals.Other_Part_Number,barcode))
Changed to
if(vals.Other_Part_Number == barcode)
If you want to strictly check then you need to convert both the value to number using parseInt and then check
if(angular.equals(parseInt(vals.Other_Part_Number),parseInt(barcode)))
Hope this could help you. Thanks.

jQuery each, find, and append

Currently I have a function that iterates through multiple divs, finds a div with the class name of ".courseArea", and return it to be appended by another
function getCourseAreaBySemester(sem_id) {
$(".semesterPanel").each(function() {
if($(this).attr('id') == sem_id) {
return $(this).find('.courseArea'));
}
});
}
Second function to process the return
var targetSemester = getCourseAreaBySemester(semesterData[i]['semester_id']);
console.log(targetSemester);
targetSemester.append(createCourse(semesterData['courses'][j]));
The console prints out "undefined", and therefore, I cannot do a .append().
But if I console.log right before the return, it returns [<ul class=​"courseArea">​</ul>​]
I know it works If I don't use the .each() function. However, I need to select by ID.
Does anyone know what is wrong here? Or of an alternative? Thanks
function getCourseAreaBySemester(sem_id) {
var result;
$(".semesterPanel").each(function() {
if($(this).attr('id') == sem_id) {
result = $(this).find('.courseArea'));
}
});
return result;
}
Returning the value of the inner function inside it obviously does not affect the return value of the getCourseAreaBySemester function!
You aren't returning anything from getCourseAreaBySemester. A return within each is closed and only returns within the each callback
You could simplify and just use the ID as selector since ID's in a page are unique:
function getCourseAreaBySemester(sem_id) {
return $('#'+sem_id).find('.courseArea');
}

in jaydata: pass variables to filter, only global works

I have this function:
function db_borrarServer(idABorrar){
serversDB.servidores
.filter(function(elementoEncontrado) {
return elementoEncontrado.id_local == this.idABorrar;
})
.forEach(function(elementoEncontrado){
console.log('Starting to remove ' + elementoEncontrado.nombre);
serversDB.servidores.remove(elementoEncontrado);
serversDB.saveChanges();
});
}
does not work, but it does if I replace the variable "this.idABorrar" with a number, it does
return elementoEncontrado.id_local == 3;
or if I declare idABorrar as a global, works to.
I need to pass idABorrar as variable. How can I do this?
The EntitySet filter() function (as any other predicate functions) are not real closure blocks, rather an expression tree written as a function. To resolve variables in this scope you can only rely on the Global and the this which represents the param context. This follows HTML5 Array.filter syntax. To access closure variables you need to pass them via the param. Some examples
inside an event handler, the longest syntax is:
$('#myelement').click(function() {
var element = this;
context.set.filter(function(it) { return it.id_local == this.id; },
{ id: element.id});
});
you can also however omit the this to reference the params as of JayData 1.2 and also use string predicates
$('#myelement').click(function() {
var element = this;
context.set.filter("it.id_local == id", { id: element.id});
});
Note that in the string syntax the use of it to denote the lambda argument is mandatory.
In JayData 1.3 we will have an even simplex calling syntax
$('#myelement').click(function() {
var element = this;
context.set.filter("it.id_local", "==", element.id);
});
In the filter you should pass an object which is the this object, like this:
.filter(function(){},{idABorrar: foo})
foo can be const or any variable which is in scope.
The .filter() function takes an optional 2nd parameter which is assigned to this inside of the first parameter function.
So you can modify your code like so :
function db_borrarServer(idABorrar){
serversDB.servidores
.filter(function(elementoEncontrado) {
return elementoEncontrado.id_local == this;
}, idABorrar)
.forEach(function(elementoEncontrado){
console.log('Starting to remove ' + elementoEncontrado.nombre);
serversDB.servidores.remove(elementoEncontrado);
serversDB.saveChanges();
});
}
Let me know how you go - I'm very new to jaydata too and I've also been going a bit crazy trying to get my head into this paradigm.
But I came across your question trying to solve the same issue, and this is how I resolved it for me.

Categories

Resources