Search from 7 inputs criteria to look into a json file - javascript

I'll try to explain.
I have a form with 7 inputs (Age, country, city,...) and in a JSON file i have many people. I need to search into that json file with all the criteria in the form. For example Spain&25years old.
I have the inputs data in an array, but i'm not able or don't know how to compare that criteria and retrieve info from JSON file.
Code below:
<!-- Google Maps -->
<script src="assets/js/jquery.ui.map.full.min.js"></script>
<script src="assets/js/jquery.ui.map.extensions.js"></script>
<script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>
<script type="text/javascript">
$(function(){
$('#mapa').gmap({'callback': function() {
var self = this;
parsejson = function(arrayvalues){
$.getJSON( 'mapa.json', function(data) {
$.each(arrayvalues, function(x, val) {
if (val.value !== "") {
console.log(val.value);
$.each( data.markers, function(i, marker) {
console.log('marker ' + marker);
// PROBLEM IS HERE, DON'T KNOW HOW TO SOLVE
});
};
});
// Draw markers in map
// $.each( data.markers, function(i, marker) {
// self.addMarker({
// 'position': new google.maps.LatLng(marker.latitude, marker.longitude),
// 'bounds': false
// }).click(function() {
// self.openInfoWindow({'content': marker.content }, this);
// });
// });
});
};
self.getCurrentPosition(function(position, status) {
if ( status === 'OK' ) {
var clientPosition = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
self.addMarker({'position': clientPosition, 'bounds': false});
self.option('center', clientPosition);
self.option('zoom', 12);
self.addShape('Circle', {
'strokeColor': "#008595",
'strokeOpacity': 0.8,
'strokeWeight': 2,
'fillColor': "#008595",
'fillOpacity': 0.35,
'center': clientPosition,
'radius': 500,
'clickable': false
});
}
else {
console.log("else");
var clientPosition = new google.maps.LatLng(40.463667, -3.74922);
self.option('center', clientPosition);
self.option('zoom', 4);
}
});
}});
});
// Search form actions
$('#searcher-form').submit(function(e) {
e.preventDefault();
var $inputs = $(this).serializeArray();
parsejson($inputs);
});
</script>
<!-- End of Google Maps -->
The JSON file look like this:
{"markers":[
{
"fromcountry":"Spain",
"fromcity":"San Cristóbal de la Laguna",
"livecountry":"Spain",
"livecity":"San Cristóbal de la Laguna",
"age":25,
"profession":"Diseñador"
"title":"La Laguna",
"latitude":28.469294910391532,
"longitude":-16.329975128173828,
"content":"Mooola"
},
{
"fromcountry":"Spain",
"fromcity":"Madrid",
"livecountry":"Spain",
"livecity":"Santa Crus de Tenerife",
"age":30,
"profession":"Programador"
"title":"Los Majuelos",
"latitude":28.44038127509586,
"longitude":-16.311674416065216,
"content":"Mooola"
}
]}
The array from the form gives me back this:
Object {name: "regsearchcountry", value: "whatever"}
Object {name: "regsearchcity", value: "whatever"}
Object {name: "regsearchlivecountry", value: ""}
Object {name: "regsearchlivecity", value: "whatever"}
Object {name: "regsearchagefrom", value: ""}
Object {name: "regsearchageto", value: "whatever"}
Object {name: "regsearchprofession", value: ""}
And I need to comare the form fields with some fields in the JSON, not all data. So i need to compare all those form fields with the JSON, and in case one is empty, compare the rest.

You simply need to loop through the records in the json file, and check each record against your input record.
Within each iteration of the loop you need to do another loop over the input record fields, comparing them to the current record one property at a time.
If you are looking for an exact match, you can speed things up by continuing on to the next record as soon as one field does not match.
var records = [
{ name : 'bob', age : 22 },
{ name : 'john', age : 32 }
/* lots of other records */
];
var input = {
name : 'john',
age : 32
};
var compare, match, result;
// loop through all the records
for(var i = 0, len = records.length; i < len; i++) {
compare = records[i];
match = true;
// loop through each property (name, age etc)
for(prop in input) {
// as soon as something is wrong, break out and try the next one
if(input[prop] !== compare[prop]) {
match = false;
break;
}
}
// if we got through without anything being wrong, we found the result!
if(match) {
result = compare;
break;
}
}
// result should be set to a matching result

Use linq.js
Here is the sample copypasted from http://linqjs.codeplex.com/
var jsonArray = [
{ "user": { "id": 100, "screen_name": "d_linq" }, "text": "to objects" },
{ "user": { "id": 130, "screen_name": "c_bill" }, "text": "g" },
{ "user": { "id": 155, "screen_name": "b_mskk" }, "text": "kabushiki kaisha" },
{ "user": { "id": 301, "screen_name": "a_xbox" }, "text": "halo reach" }
]
// ["b_mskk:kabushiki kaisha", "c_bill:g", "d_linq:to objects"]
var queryResult = Enumerable.From(jsonArray)
.Where(function (x) { return x.user.id < 200 })
.OrderBy(function (x) { return x.user.screen_name })
.Select(function (x) { return x.user.screen_name + ':' + x.text })
.ToArray();
// shortcut! string lambda selector
var queryResult2 = Enumerable.From(jsonArray)
.Where("$.user.id < 200")
.OrderBy("$.user.screen_name")
.Select("$.user.screen_name + ':' + $.text")
.ToArray();

Related

Filter rows of a CSV using an Array to show arrayItem : 1 in CSV

I have built the following function that, when a user presses a button, the string is appended to an array (and also, the button changes red). I have d3, and JQ(not yet used) in my scripts:
// Create button click array
var clickedBusinesses = [];
function toggle(business) {
clickedBusinesses[business] = !clickedBusinesses[business];
};
function getClickedBusinesses() {
return Object.keys(clickedBusinesses).filter(key => clickedBusinesses[key]);
};
// Update array and change button colour to reflect selection
function toggleClickedBuz( bizStr , id ) {
if(clickedBusinesses.includes(bizStr)){
// removing duplicate element from that array, dependant on button pressed
clickedBusinesses = clickedBusinesses.filter( cb => cb !== bizStr );
document.getElementById( id ).style.backgroundColor='white';
}else{
// else push it to the array
clickedBusinesses.push(bizStr)
document.getElementById( id ).style.backgroundColor='red';
}
console.log(clickedBusinesses)
var arrayLength = clickedBusinesses.length;
for (var i = 0; i < arrayLength; i++) {
console.log(clickedBusinesses[i]);
// Do something
}
}
I am trying to use this array to filter on columns in a CSV to only display the value '1.0'
const data = d3.csv("./binary.csv").then(function(data){
console.log(data);
});
This is how each row looks (6k) in the console window:
{is_active: "1", "Bx": "1", "By": "1", "Bz": "0", count: "5,133,151"}
I'm struggling on creating the logic that iterates through the data and only returns values where a specific key (Bx, By, Bz - depending on the selection) has the specified value(1).
Thanks
const clickedBusinesses = [
];
const business = [
{ is_active: "1", Bx: "1", By: "1", Bz: "0", count: "5,133,151" },
{ is_active: "0", Bx: "1", By: "1", Bz: "0", count: "5,1121,151" },
{ is_active: "0", Bx: "1", By: "1", Bz: "0", count: "5,1212,151" },
]
// Update array and change button colour to reflect selection
function toggleClickedBuz(index, id) {
var data = business[index];
if (data) {
document.getElementById(id).style.backgroundColor = "white";
} else {
clickedBusinesses.push(index);
document.getElementById(id).style.backgroundColor = "red";
}
for (let item of clickedBusinesses ) {
console.log(item);
// Do something
}
}

How to search across more than one attribute in Jquery UI Autocomplete?

I have an array of objects with structure similar to this:
$scope.usersList = [{
"name": "John",
"email": "john#xyz.com",
"id": "abcd"
},{
"name": "Jane",
"email": "jane#xyz.com",
"id": "efgh"
}];
I get the array after making an ajax call to the server. I am currently using jQuery UI Autocomplete in an angular app like this
$(input).autocomplete({
source: $scope.usersList,
appendTo: container,
position: {
at: 'left bottom',
of: container
},
select: function(e, v) {
e.preventDefault();
//Do something
}
});
If the array simply consists of names, the above code works, but I want to search across "email" and "id" fields as well. e.g. if I type "abcd" in the search box I want to see John's name in the result list. I am unable to figure out how to proceed with this.
Can you please try modifying your source as below:
$("#suggest").autocomplete({
delay: 100,
minLength:2,
**source: function (request, response) {
var temp = [];
usersList.filter(buildResponse);
function buildResponse(p){
for (var key in p) {
if (p.hasOwnProperty(key)) {
if(p[key].indexOf(request.term) > -1){
temp.push({
"label" : p[key],
"value" : p
});
}
}
}
}
console.log(temp);
response(temp);
}**,
select: function (event, ui) {
// Prevent value from being put in the input:
this.value = ui.item.label;
// Set the next input's value to the "value" of the item.
console.log(ui.item);
event.preventDefault();
}
});
//usersList = $scope.usersList (as mentioned in your question)
jsfiddle: http://jsfiddle.net/32Bck/501/
After a while of stumbling, I managed to get the search term to be any property. This should work in your case (just substitute var usersList with your collection):
<input id="in" type="input" class="ui-autocomplete-input" />
var usersList = [{
"name": "John",
"email": "john#xyz.com",
"id": "abcd"
}, {
"name": "Jane",
"email": "jane#xyz.com",
"id": "efgh"
}];
$("#in").autocomplete({
source: function(request, response) {
function hasMatch(s) {
return s.toLowerCase().indexOf(request.term.toLowerCase()) !== -1;
}
var i, l, obj, matches = [];
if (request.term === "") {
response([]);
return;
}
for (i = 0, l = usersList.length; i < l; i++) {
obj = usersList[i];
if (hasMatch(obj.name) || hasMatch(obj.email) || hasMatch(obj.id)) {
if ($.inArray(obj, matches) < 1) { // remove duplicates
matches.push({
"label": obj.name
//add here other properties you might need
})
}
}
response(matches);
}
}
});
Working fiddle here: https://jsfiddle.net/qg50zwv3/

How to Group By Json Array

I have an array and i want to apply group By column (key).
I have this.
app.groupDtData = function(data, column) {
var generatedData=[];
$.each(data,function(i,dt){
// generatedData
// if(jQuery.inArray( "John", generatedData ))
});
}
i have to push it into generatedData and check by jQuery.inArray ?
You wouldn't use inArray for that as you need an object to hold the result, not an array. Use the in operator to look for the property in the object.
You would get the column value from the item and then check if it exist in the result. If it doesn't exist, add a new array by that name. Add the item to the array and lastly return the result:
app.groupDtData = function(data, column) {
var generatedData = {};
$.each(data, function(i, dt) {
var key = dt[column];
if (!(key in generatedData)) {
generatedData[key] = [];
}
generatedData[key].push(dt);
});
return generatedData;
};
Demo:
function group(data, column) {
var generatedData = {};
$.each(data, function(i, dt) {
var key = dt[column];
if (!(key in generatedData)) {
generatedData[key] = [];
}
generatedData[key].push(dt);
});
return generatedData;
}
var g = group([
{ name: 'John', grp: '1' },
{ name: 'Elsa', grp: '2' },
{ name: 'Mandy', grp: '2' },
{ name: 'Bo', grp: '1' }
], 'grp');
document.write(JSON.stringify(g));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Filter Array based on another array

I have a list with that contains a list of objects. Each object has 4 properties on it. There is a checkbox list with the unique values of two of the properties, this helps build my filter array.
the Filter might end up looking like this:
[
{
prop: 'username',
val: ['max', 'sam']
},
{
prop: 'color',
val: ['blue', 'green']
}
]
The list of objects would look something like this:
[
{
username: 'sam',
color: 'blue'
},
{
username: 'jimmy',
color: 'blue'
},
{
username: 'sam',
color: 'black'
},
{
username: 'max',
color: 'green'
},
{
username: 'max',
color: 'blue'
}
]
The Desired Result
[
{
username: 'sam',
color: 'blue'
},
{
username: 'max',
color: 'green'
},
{
username: 'max',
color: 'blue'
}
]
I feel like I'm going down a never ending forEach rabbit hole. I'm guessing I need some sort of recursion. Currently here is what I have:
var temporary = scope.transactions;
function getFilteredTransactions() {
var filter = deviceFilterService.get();
if (filter.length > 0) {
var temp2 = [];
angular.forEach(filter, function (fil) {
//object
angular.forEach(fil.val, function (filterValue) {
//list on each object
angular.forEach(temporary, function (transaction) {
if (transaction[fil.prop] === filterValue) {
if (temp2.indexOf(transaction) === -1) {
temp2.push(transaction);
}
}
});
temporary = temp2;
});
});
$log.debug(temporary);
scope.transactions = temporary;
} else {
initialize();
}
}
This is starting to work, the second time it goes through the property for color it ends up just wanting to add the exact same transaction to the temp2 array. There has to be a better way to set this up, possibly through recursion.
If you convert the format of the first list to a dictionary, i think if should get easier.
var dict = {};
angular.forEach(source1, function(ob){
dict[ob.prop] = ob.val;
});
function getFiltered(ob){
for(var prop in ob){
if(dict[prop] && dict[prop].indexOf(ob[prop]) === -1){
return false;
}
}
return true;
};
and just call it as:
var temporary = scope.transactions.filter(getFiltered);
Demo
Basically the first part converts:
[
{
prop: 'username',
val: ['max', 'sam']
},
{
prop: 'color',
val: ['blue', 'green']
}
];
to:
{
username:['max', 'sam'],
color:['blue', 'green']
}
so that it makes the look up much easier.
You might want to change the variable names here for clarity, but this will do what you're asking for:
var values = {};
angular.forEach(startingData, function(rawData) {
angular.forEach(rawData, function(value, key) {
if (angular.isUndefined(values[key])) {
values[key] = [];
}
if (values[key].indexOf(value) === -1) {
values[key].push(value);
}
})
});
var result = [];
angular.forEach(values, function(value, key) {
result.push({prop: key, val: value})
});
You can simply iterate each key of the data the needs filtering, find the appropriate filter per that key, and check the value against the filter values:
$scope.transactions = $scope.transactions.filter(isItemValidFilter);
function isItemValidFilter(item) {
var filters = deviceFilterService.get();
//For each property in the data, get the correct filter from the list of filters
var totalConditions = Object.keys(item).length;
var correctConditions = 0;
for (var filterKey in item) {
var correctFilters = filters.filter(function(dataFilter) {
return dataFilter.prop == filterKey
});
if (correctFilters.length) {
//Ill assume only 1 filter, so just use the 0 index
var correctFilter = correctFilters[0];
var conditions = correctFilter.val;
if (conditions && conditions.length) {
//check the values!
if (conditions.indexOf(item[filterKey]) > -1) {
correctConditions++;
}
}
}
}
return correctConditions === totalConditions;
}
Demo: http://jsfiddle.net/Lz32hka5/1/
Try:
var temp2 = [], matched;
angular.forEach(temporary, function(item){
matched = true;
angular.forEach(Object.keys(item), function(key){
angular.forEach(filter, function(filter){
filter.prop == key && filter.val.indexOf(item[key]) == -1 && (matched = false);
});
});
matched && temp2.push(item);
});
console.log(temp2)
temporary is the list of objects, filter: your filters
Demo: http://jsfiddle.net/wZVanG/7wnae850/

Jquery object search

I have the following object and what I would like achieve is to get the index of theme if the name has match with a variable.
for example: I'm making a loop in the views and if my task (something1) variable has matches with the name element than to return the index of object.
By the given example I should have as result 0,
var views = [
{
name: "something1",
type: something1,
columns: something1
},
{
name: "something2",
type: something2,
columns: something2
},
{
name: "something3",
type: something3,
columns: something3
}
];
var task = 'something1';
$.each(views, function(index, value) {
if (value.name = task) {
alert(index);
}
});
You dont really need jQuery for this:
See: http://jsfiddle.net/enNya/2/
var views = [
{
name: "something1",
type: "something1",
columns: "something1"
},
{
name: "something2",
type: "something2",
columns: "something2"
}
];
var task = 'something2';
// Set a var and maintain scope
var i;
// Loop each element of the array
for (i = 0; i < views.length; i++) {
// If the X = Y the stop looping
if (views[i].name == task) {
break;
}
}
// Check if it was not found
i = i == views.length ? false : i;
// Log the result
console.log(i);
It's just a matter of syntax, as lgt said don't forget toseparate elements within your object with commas. Aslo the correct 'equal' operator is '=='.
'value.name=task' would be always true. It means can I affect the content of 'task' into 'value.name'.
Here is your valid js.
Note that in this example you'll get 2 alertbox.. ;)
var views=[
{
name:"something1",
type:'something1',
columns:'something1'
},
{
name:"something1",
type:'something1',
columns:'something1'
},
{
name:"something2",
type:'something2',
columns:'something2',
},
];
var task='something1';
$.each(views, function(index, value) {
if (value.name==task){
alert(index);
}
});
replace something1 variable for 0 and value.name == task (double =)
var views=[{
name:"something1",
type:0,
columns:0
}, {
name:"something1",
type:0,
columns:0
}, {
name:"something2",
type:0,
columns:0
}];
var task='something1';
$.each(views, function(index, value) {
if (value.name==task){
return index;
}
});

Categories