Checking for equivelance - javascript

OK, I'm missing something here and I just can't seem to find it because the logic seems correct to me, but I'm certain I'm not seeing the error.
var VisibleMarkers = function() {
var filtered = _.reject(Gmaps.map.markers, function(marker) {
return marker.grade != $('.mapDataGrade').val() && !_.contains(marker.subjects,$('.mapDataSubjects').val())
});
return filtered
}
I'm using underscore.js and jQuery to simplify my javascript work.
So right now, I'm checking by means of selects which data gets to be rejected and then I display the filtered markers on the (google) map (if it helps at all, this is using gmaps4rails which is working perfectly fine, its this bit of javascript that's making me lose the last of the hairs on my head).
Currently, the code functions 100% correctly for the ".mapDataGrade" select, but the ".mapDataSubjects" isn't. Now the markers object has a json array of the subjects (this is for students) and each item in the array has its ID. Its this ID that I am supposed to be checking.
Can someone see what I'm doing wrong?
If there's more info that needs to be included, please let me know.
This is on plain javascript on a RoR application using gmaps4rails

Now the markers object has a json array of the subjects (this is for students) and each item in the array has its ID. Its this ID that I am supposed to be checking.
_.contains compares a values, but it sounds like you want your iterator to compare a value to an object's "id" property. For that, _.some would work; it's like contains, except that, instead of comparing values, you can write the comparison as a function:
Returns true if any of the values in the list pass the iterator truth test.
Here's how you'd use it:
!_.some(marker.subjects, function(subject) {
return subject.id == $('.mapDataSubjects').val();
})
If I'm right, the whole line should be like this:
return marker.grade != $('.mapDataGrade').val() &&
// check that none of the subjects is a match
!_.some(marker.subjects, function(subject) {
// the current subject is a match if its ID matches the selected value
return subject.id == $('.mapDataSubjects').val();
});

Related

Use multiple key-value filters on an object of objects?

Bit of a lengthy one so those of you who like a challenge (or I'm simply not knowledgeable enough - hopefully it's an easy solution!) read on!
(skip to the actual question part to skip the explanation and what I've tried)
Problem
I have a site that has a dataset that contains an object with multiple objects inside. Each of those objects contains an array, and within that array there are multiple objects. (yes this is painful but its from an API and I need to use this dataset without changing or modifying it.) I am trying to filter the dataset based of the key-value pairs in the final object. However, I have multiple filters being executed at once.
Example of Path before looping which retrieves the key-value pair needed for one hall.
["Hamilton Hall"]["Hire Options"][2].Commercial
After Looping Path of required key-value pair for all halls, not just one (the hall identifier is stored):
[0]["Hire Options"][2].Commercial
Looping allows me to check each hall for a specific key-value pair (kind of like map or forEach, but for an object).
After getting that out of the way back to the question.
How would I go about filtering which of the looped objects are displayed?
What I have Tried
(userInput is defined elsewhere - this happens on a btn click btw)
let results = Object.keys(halls);
for (key of results) {
let weekend = [halls[ `${key}` ][ 'Hire Options' ][4][ 'Weekend function' ]];
if(userInput == weekend) {
outputAll([halls[ `${key}` ]]);
}
}
That filters it fine. However, I run into an issue here. I want to filter by multiple queries, and naturally adding an AND into the if statement doesn't work. I also dont want to have 10 if statements (I have 10+ filters of various data types I need to sort by).
I have recently heard of ternary operators, but do not know enough about them to know if that is the correct thing to do? If so, how? Also had a brief loook at switches, but doesnt seem to look like what I want (correct me if I am wrong.)
Actual Question minus the babble/explanation
Is there a way for me to dynamically modify an if statements conditions? Such as adding or removing conditions of an if statement? Such as if the filter for 'a' is set to off, remove the AND condition for 'a' in the if statement? This would mean that the results would only filter with the active filters.
Any help, comments or 'why haven't you tried this' remark are greatly appreciated!
Thanks!
Just for extra reference, here is the code for retrieving each of the objects from the first object as it loops through them:
(Looping Code)
halls = data[ 'Halls' ];
let results = Object.keys(halls);
for (key of results) {
let arr = [halls[ `${key}` ]];
outputAll(arr);
}
You can use Array.filter on the keys array - you can structure the logic for a match how you like - just make it return true if a match is found and the element needs to be displayed.
let results = Object.keys(halls);
results.filter(key => {
if (userInput == halls[key]['Hire Options'][4]['Weekend function']) {
return true;
}
if (some other condition you want to match) {
return true;
}
return false;
}).forEach(key => outputAll([halls[key]]));

Filter through Angular Collection fast

I know it's trivial but I have a doubt to be clarified.
I have a collection vm.groups that has almost 1000 objects. Now, each object has name, id, links etc. property fields.
Grid only displays name and id.
Now, there is a text box where we enter some text and we have to filter data, according to whatever we entered but filtering must happen only within name and id fields of the objects not the other fields that are present within the objects.
So, both things can be done,
1) I create a temp collection from the original collection objects with only name and id fields and then bind the collection to view.
// vm.groups.forEach(function(element) {
// vm.displayedFieldGroups.
// push({name: element.name,id: element.id,transformedId: element.transformedId});
// });
2) Or, I create a custom filter vm.customSearch :
vm.customSearch = function(searchVal) {
if(vm.filter.length) {
if(vm.filter.toLowerCase().indexOf(searchVal.name.toLowerCase) !== -1 ||
vm.filter.toLowerCase().indexOf(searchVal.name.toLowerCase) !== -1) {
console.log(searchVal);
return true;
}else {
return false;
}
} else {
console.log(searchVal);
return true;
}
};
And in the view vm.groups | filter: vm.customSearch.
But I think second method is slower because each value in the collection would be passed to the filter which is obviously tedious for huge collection.
Am I right?
Which is the right way to do?
UPDATE
This was for a legacy application. There was a filter already implemented but that just goes through all the fields in the object. I need to only filter for name and id fields of objects.
Hence, I need to either create a custom filter or choose the first approach that I depicted.
You're right in your assumption that the filter would go over every item in the source array and run your filter function each time there's a digest cycle.
You should proceed with the first approach.

Check whether any of multiple values exists in an array

(This question has been changed a bit since some of the answers were posted. That is why they might seem a bit off-topic and/or out of context)
Hello! So basically, I have this string that is entered by a user (a caption for an image, for example), and an array of links/words that I want to "block" the user from entering. (This would be to prevent from swearing, advertising etc.)
So I need some code that checks whether a certain value exists in an array.
This is my array:
var blockedUrls = ["https://google.com", "https://facebook.com"]
and this is the values I want to check
var userInput = "Hello! Check out my cool facebook profile at https://facebook.com";
(This would normally be set to a value fetched from an input of some sort, the static text is just to simplify)
So this is what I have tried:
let values = userInput.split(" ");
values.forEach((i, value) => {
// inArray is a made-up-function in order to better explain my intention
// The function I need here is a function that can check whether the value of the "value" variable exists in the "blockedUrls" array.
if(value.inArray(blockedUrls)) {
return alert(`You can't say that word! [${value}]`);
}
});
So a summary: How do I check if any of multiple values exists in an array?
You can check if a value is in an array by using indexOf
var value = document.getElementById('myFile').value;
if (unAllowedLinks.indexOf(value) != -1) {
// value is in array
}
-1 is returned when the value is not found in the array, else it returns the index of the value.
If you want to be able to change the number of values in unAllowedLinks you’d be better off using indexOf(), like so:
function updateImage() {
if (unAllowedLinks.indexOf(document.getElementById('myFile').value) > -1) {
alert("This link is reserved");
} else {
// Use the value
}
};

Count occurrences of object

I'm working on something to give users a preview of changes they have made in a form where I compare serialised arrays of objects from the forms fields before and after changes. This all works fine, but I needed to exclude the 'product[territory_ids][]' elements for which there are many as I don't need such a deep level of comparison. The code below works fine.
// Get product form values before any changes are made
// and serialise them into an array of objects
$(".product_form_edit").ready(function() {
form_before = $(".product_form_edit").serializeArray()
// Using Underscore JS take out all off the product[territory_ids][] elements
// as they cause comparison to fail.
// We'll do a count comparision of the number of territories set separately
$.each(form_before, function(i){
form_before = _.without(form_before, _.findWhere(form_before, {name: 'product[territory_ids][]'}));
});
console.log(form_before);
});
What I do need to do and am struggling with is detecting a change in the number of 'product[territory_ids][]' elements that are checked.
I thought some kind of variation of:
$.each(form_before, function(i){
form_before = _.without(form_before, _.findWhere(form_before, {name: 'product[territory_ids][]'}));
});
Like:
$.each(form_before, function(i){
_.countBy(form_before, _.findWhere(form_before, {name: 'product[territory_ids][]'}));
}).length;
Might work, but this and lots of other attempts just return undefined.
Can anyone help? I'm sure it's way simpler than i'm making it.
Okay, so, after a little messing around with an example I came up with, I came to the conclusion that you probably want to be using _.filter to get your array of checkboxes. filter will always return an array, so you should get a count of 0 when there are no checkboxes checked.
$('#serialize').click(function() {
var data = $('#testForm').serializeArray(),
checkboxes = _.filter(data, function(i) {
return i.name === 'xyz';
});
console.log(data, checkboxes);
console.log(data.length, checkboxes.length);
});

How do I use #DbLookup results to populate a Readers field in xpages?

db = new Array("myserver", "myfolder\\mydb.nsf")
dir = getComponent("Dir").value;
div = getComponent("Div").value;
lu = #DbLookup(db, "ManagerAccess", dir + "PP" + div, "DTManagers");
var a = [];
a.push(lu);
var item:NotesItem = docBackEnd.replaceItemValue('FormReaders', #Unique(a));
item.setReaders(true);
That code is on the querySaveDocument ssjs. The result I get from the #DbLookup (when I put in a computed field) look like this:
Pedro Martinez,Manny Ramirez,David Ortiz,Terry Francona
I tried doing an #Explode(#Implode) thing on it, but it doesn't seem to work.
The error I get in the browser just tells me that the replaceItemValue line is broken.
To test it, I pushed several strings one at a time, and it worked correctly populating my FormReaders field with the multiple entries.
What am I doing wrong?
I see several problems here:
A. In cases as described by you #Dblookup in fact would return an array. If you push an array into a plain computedField control it will exactly look as that you wrote:
value1, value2, ..., valueN
A computedField doesn't know anything about multiple values etc, it just can display strings, or data that can be converted to strings.
If you want to test the return value you could try to return something like lu[0]; you then should receive the array's 1st element, or a runtime error, if lu is NOT an array. Or you could ask for the array's size using lu.length. That returns the number of array elements, or the number of characters if it's just a plain string.
B. your code contains these two lines:
var a = [];
a.push(lu);
By that you create an empty array, then push lu[] to the first element of a[]. The result is something like this:
a[0] = [value1, value2, ..., valueN],
i.e. a is an array where the first element contains another array. Since you don't want that, just use #Unique(lu) in your replaceItemValue-method.
C. I don't see why replaceItemValue would throw an error here, apart from what I wrote in topic B. Give it a try by writing lu directly to the item (first without #Unique). That should work.
D. for completeness: in the first line you used "new Array". A much better way to define your db parameters is
var db = ["myserver", "myfolder/mydb.nsf"];
(see Tim Tripcony's comment in your recent question, or see his blog entry at http://www.timtripcony.com/blog.nsf/d6plinks/TTRY-9AN5ZK)

Categories