autocomplete in plain JS from obj data - javascript

I am trying to create an 'autocomplete' search input field in vanilla javascript (no jquery or jquery-ui). I would like the 'autocomplete' to pull from my javascript object data for the 'suggestions'. I am attempting with the below; with no avail (no errors, just no response output). The functionality should be a 'match' narrowing; i.e. I begin typing 's' 's results' will be recommended first, etc.
HTML.
<div class="row">
<input type="text" id="autoSuggest" placeholder="Search..." onkeyup="changeInput(this.value)">
<div id="result"></div>
</div>
JavaScript attempt for this functionality:
function matchIt(input) {
var reg = new RegExp(input.split('').join('\\w*').replace(/\W/, ""), 'i');
return json.filter(function(file) {
if (file.match(reg)) {
return file;
}
});
}
function changeInput(val) {
var autoCompleteResult = matchIt(val);
document.getElementById("result").innerHTML = autoCompleteResult;
}
JS obj data:
var json =[{
"Name": "zips",
"Type": "Directory",
"DateModified": "6/14/2018 17:22:50",
"Size": "5 KB",
}, {
"Name": "presets",
"Type": "Directory",
"DateModified": "5/11/2018 7:32:10",
"Size": "2 KB",
}, {
"Name": "workflow",
"Type": "Directory",
"DateModified": "6/26/2018 10:29:59",
"Size": "6 KB",
},{
"Name": "software",
"Type": "Directory",
"DateModified": "3/16/2018 10:29:59",
"Size": "16 KB",
},{
"Name": "mmm_data",
"Type": "Directory",
"DateModified": "6/27/2018 1:19:29",
"Size": "3 KB",
},{
"Name": "jobs",
"Type": "Directory",
"DateModified": "4/27/2018 11:59:59",
"Size": "3 KB",
},
];

You need to match on file.Name, and not file. The filter callback function should then return a true/false value and not the object
var json = [{
"Name": "zips",
"Type": "Directory",
"DateModified": "6/14/2018 17:22:50",
"Size": "5 KB",
}, {
"Name": "presets",
"Type": "Directory",
"DateModified": "5/11/2018 7:32:10",
"Size": "2 KB",
}, {
"Name": "workflow",
"Type": "Directory",
"DateModified": "6/26/2018 10:29:59",
"Size": "6 KB",
}, {
"Name": "software",
"Type": "Directory",
"DateModified": "3/16/2018 10:29:59",
"Size": "16 KB",
}, {
"Name": "mmm_data",
"Type": "Directory",
"DateModified": "6/27/2018 1:19:29",
"Size": "3 KB",
}, {
"Name": "jobs",
"Type": "Directory",
"DateModified": "4/27/2018 11:59:59",
"Size": "3 KB",
}, ];
function matchIt(input) {
var reg = new RegExp(input.split('').join('\\w*').replace(/\W/, ""), 'i');
return json.filter(file => !!file.Name.match(reg));
}
function changeInput(val) {
if (val.length == 0) return;
var autoCompleteResult = matchIt(val);
document.getElementById("result").innerHTML = autoCompleteResult.map(i => i.Name).join('<br>')
}
<div class="row">
<input type="text" id="autoSuggest" placeholder="Search..." onkeyup="changeInput(this.value)">
<div id="result"></div>
</div>

Related

Angular pick up an item within an array

I'm using angular to manipulate a tmdb api, but I'm having trouble getting an item that is inside an array, could you help me?
the answer that the array returns to me is this:
{
"id": 423108,
"results": [{
"id": "608177732da846006e382e45",
"iso_639_1": "en",
"iso_3166_1": "US",
"key": "qc6jN1BcJi0",
"name": "Official Trailer – Warner Bros. UK & Ireland",
"site": "YouTube",
"size": 1080,
"type": "Trailer"
}, {
"id": "6081f2879e45860058f36147",
"iso_639_1": "en",
"iso_3166_1": "US",
"key": "h9Q4zZS2v1k",
"name": "Official Trailer",
"site": "YouTube",
"size": 1080,
"type": "Trailer"
}, {
"id": "60a3f3d8cb75d1003f6cad3f",
"iso_639_1": "en",
"iso_3166_1": "US",
"key": "6Eb1V9gJ5Z4",
"name": "Chasing Evil Featurette",
"site": "YouTube",
"size": 1080,
"type": "Featurette"
}, {
"id": "60a7f244e16e5a003f89fcfb",
"iso_639_1": "en",
"iso_3166_1": "US",
"key": "4GjhydkUMrQ",
"name": "The Conjuring: The Devil Made Me Do It - Demonic Possession Featurette - Warner Bros. UK",
"site": "YouTube",
"size": 1080,
"type": "Featurette"
}, {
"id": "60b65a605c563400782c09c4",
"iso_639_1": "en",
"iso_3166_1": "US",
"key": "5FEdg3FhiGc",
"name": "Final Trailer – Warner Bros. UK & Ireland",
"site": "YouTube",
"size": 1080,
"type": "Trailer"
}, {
"id": "60b6e54aefd3c20041e08f6b",
"iso_639_1": "en",
"iso_3166_1": "US",
"key": "AB9mPsH2z1U",
"name": "The Conjuring: The Devil Made Me Do It | 2021 | Clip: "
Mitigating Circumstances " HD",
"site": "YouTube",
"size": 1080,
"type": "Clip"
}, {
"id": "60b9622aabf8e2006fb33499",
"iso_639_1": "en",
"iso_3166_1": "US",
"key": "tLFnRAzcaEc",
"name": "Final Trailer",
"site": "YouTube",
"size": 1080,
"type": "Trailer"
}, {
"id": "60be2d10960cde006d905ecf",
"iso_639_1": "en",
"iso_3166_1": "US",
"key": "2V2MmKkddM0",
"name": "The Conjuring: The Devil Made Me Do It - Teaser",
"site": "YouTube",
"size": 1080,
"type": "Teaser"
}]
}
And I want to get the "key" item. The idea is to get the key and then concatenate it with the youtube link to redirect to the trailer on youtube, or put the youtube player in the application. I'm currently doing it this way:
this.clientService.getVideoID(this.id).subscribe(data => this.video = date)
But I only have access to video.results, I can't give video.results.key
it seems there is a problem in this JSON element because it contains "
You can use the filter() function like so
const myVideo = results.filter(item => item.id === "608177732da846006e382e45")[0]
note that it will only work if the id is unique, filter returns an array filled with item that return true on the condition ( item.key === "608177732da846006e382e45"), and then we take the 1st one which is supposed to be the only one.
and then you can access myVideo.key
Obviously replace "608177732da846006e382e45" with whatever your input is

How to map the values of all the leaf nodes in Javascript?

I have a nested JSON object tree like this :
{"children":[{"name":"Afghanistan","children":[{"World
Cities.Country":"Afghanistan","World Cities.Population":2997,"World
Cities.City":"Qal eh-ye Now"},{"World Cities.Country":"Afghanistan","World
Cities.Population":7407,"World Cities.City":"Mahmud-E Eraqi"},{"World
Cities.Country":"Afghanistan","World Cities.Population":10000,"World
Cities.City":"Tarin Kowt"}]
EXPECTED OUTPUT IS SOMETHING LIKE THIS
{
"name": "flare",
"children": [
{
"name": "LEGISLATIVE",
"children": [
{
"name": "Legislative Branch",
"size": 20891
}
]
},
{
"name": "JUDICIAL",
"children": [
{
"name": "Supreme Court Law Library",
"size": 1589.3
},
{
"name": "New Mexico Compilation Commission",
"size": 1853.5
},
{
"name": "Judicial Standards Commission",
"size": 860.8
},
{
"name": "Court of Appeals",
"size": 5960.2
},
{
"name": "Supreme Court",
"size": 3421.1
},
{
"name": "Supreme Court Building Commission",
"size": 977.4
},
{
"name": "Administrative Office of the Courts",
"size": 65870.4
},
{
"name": "First Judicial District Court",
"size": 8372.5
},
{
"name": "Second Judicial District Court",
"size": 28154.6
},
{
"name": "Third Judicial District Court",
"size": 7808.3
},
{
"name": "Fourth Judicial District Court",
"size": 2577.2
},
{
"name": "Fifth Judicial District Court",
"size": 7389.5
},
{
"name": "Sixth Judicial District Court",
"size": 3630.7
},
{
"name": "Seventh Judicial District Court",
"size": 2895
},
Expected output for my example :
{"children":[{"name":"Afghanistan","children":[{"name":"Qal eh-ye Now","value":2997}]]}
So I want to map the values of the leaf nodes. In this example ,World Cities.Country,World Cities.Population and World Cities .City to just a name and value for every children object.
Currently this is the function that I have :
var mappedData = nestedData.children.map(function (d) {
return { name: d[groupKey], value: d[sizeKey] };
}); //groupKey is World.Cities.City ,sizeKey is Population
But obviously this syntax does not work because I first need to access all the leaf nodes of this tree then apply the map function to it. How can I achieve that?
This is how you can achieve that:
const a = {
children: [
{
name: "Afghanistan",
children: [
{
"World Cities.Country": "Afghanistan",
"World Cities.Population": 2997,
"World Cities.City": "Qal eh-ye Now"
},
{
"World Cities.Country": "Afghanistan",
"World Cities.Population": 7407,
"World Cities.City": "Mahmud-E Eraqi"
},
{
"World Cities.Country": "Afghanistan",
"World Cities.Population": 10000,
"World Cities.City": "Tarin Kowt"
}
]
}
]
};
const deep = x => {
if (Array.isArray(x.children)) {
x.children = x.children.map(deep);
return x;
} else {
return {
name: x["World Cities.City"],
value: x["World Cities.Population"]
};
}
};
const b = deep(a);
console.log(b);

Lookup Value in JSON using Javascript

I'm very new to Javascript and have been given a task. I have a JSON feed that has been given as follows:
var data = {
"feeds": {
"regions": [{
"name": "Lichtenberg",
"id": "01408.b",
"suburbs": [{
"name": "Fennpfuhl",
"views": 76400
},
{
"name": "Lichtenberg",
"views": 87895
},
{
"name": "Rummelsberg",
"views": 10239
}
]
},
{
"name": "Mitte",
"id": "03442.f",
"suburbs": [{
"name": "Tiergarten",
"views": 82695
},
{
"name": "Mitte",
"views": 67234
},
{
"name": "Hansaviertel",
"views": 10848
},
{
"name": "Moabit",
"views": 67500
}
]
},
{
"name": "Friedrichshain-Kreuzberg",
"id": "01991.o",
"suburbs": [{
"name": "Friedrichshain",
"views": "98494"
},
{
"name": "Kreuzberg",
"views": "27800"
}
]
},
{
"name": "Templehof-Schöneberg",
"id": "01778.k",
"suburbs": [{
"name": "Friedenau",
"views": 76595
},
{
"name": "Schöneberg",
"views": 20731
},
{
"name": "Templehof",
"views": 58000
},
{
"name": "Mariendorf",
"views": 32300
}
]
},
{
"name": "Pankow",
"id": "02761.q",
"suburbs": [{
"name": "Wießensee",
"views": 81294
},
{
"name": "Prenzlauer Berg",
"views": 76470
},
{
"name": "Pankow",
"views": 90210
}
]
}
],
"branding": [{
"municipality_id": "01408.b",
"brand_color": "#f9cd90"
}, {
"municipality_id": "03442.f",
"brand_color": "#F28123"
}, {
"municipality_id": "01991.o",
"brand_color": "#D34E24"
}, {
"municipality_id": "01778.k",
"brand_color": "#563F1B"
}, {
"municipality_id": "02761.q",
"brand_color": "#38726C"
}],
"customer": {
"name": "Viktoria Tiedemann",
"date_of_birth": "1981-09-19",
"address": {
"street": "Schönfließer Str 9",
"suburb": "Prenzlauer Berg",
"postcode": "10439"
}
}
}
};
The task is simple - to find the suburb and the region of Viktoria Tiedemann. So far I've tried using the below:
var customer_suburb;
var customer_name = 'Viktoria Tiedemann';
for (var i = 0; i < data.feeds.customer.length; i++){
if (data.feeds.customer.name[i] == customer_name){
customer_suburb = data.feeds.customer.address.suburb;
}
}
but it keeps on returning undefined values - where am I going wrong? I'm thinking to use the same process to get the region.
In your data, you have just one customer — not an array of customers — which is accessible with:
data.feeds.customer
( if customer was supposed to be an array, you could find Viktoria with : let customer = data.feeds.customer.find(c => c.name === 'Viktoria Tiedemann') )
You can get the suburb with:
let suburb = data.feeds.customer.address.suburb
Once you have that, you just need to find() the region whose suburbs array has this. For that find() combined with some() does this succinctly:
var data = {"feeds": {"regions": [{"name": "Lichtenberg","id": "01408.b","suburbs": [{ "name": "Fennpfuhl", "views": 76400 },{ "name": "Lichtenberg", "views": 87895 },{ "name": "Rummelsberg", "views": 10239 }]},{"name": "Mitte","id": "03442.f","suburbs": [{ "name": "Tiergarten", "views": 82695 },{ "name": "Mitte", "views": 67234 },{ "name": "Hansaviertel", "views": 10848 },{ "name": "Moabit", "views": 67500 }]},{"name": "Friedrichshain-Kreuzberg","id": "01991.o","suburbs": [{ "name": "Friedrichshain", "views": "98494" },{ "name": "Kreuzberg", "views": "27800" }]},{"name": "Templehof-Schöneberg","id": "01778.k", "suburbs": [{ "name": "Friedenau", "views": 76595 },{ "name": "Schöneberg", "views": 20731 },{ "name": "Templehof", "views": 58000 },{ "name": "Mariendorf", "views": 32300 }]},{"name": "Pankow","id": "02761.q","suburbs": [{ "name": "Wießensee", "views": 81294 },{ "name": "Prenzlauer Berg", "views": 76470 },{ "name": "Pankow", "views": 90210 }]}],"branding": [{"municipality_id": "01408.b","brand_color": "#f9cd90"},{"municipality_id": "03442.f","brand_color": "#F28123"},{"municipality_id": "01991.o","brand_color": "#D34E24"},{"municipality_id": "01778.k","brand_color": "#563F1B"},{"municipality_id": "02761.q","brand_color": "#38726C"}],"customer": {"name": "Viktoria Tiedemann","date_of_birth": "1981-09-19","address": {"street": "Schönfließer Str 9","suburb": "Prenzlauer Berg","postcode": "10439"}}}};
let suburb = data.feeds.customer.address.suburb
let region = data.feeds.regions.find(region => region.suburbs.some(s => s.name === suburb))
console.log("suburb:", suburb, "region:", region.name)

Converting Multidimensional JSON key-value pairs into an Angular Menu (no Angular knowledge required)

I asked this question here:
Working With Dynamic Multidimensional key-value pairs in JSON
But it's become a bit more involved and I can't get where I'm going from that answer. If I have a data object that looks like this:
{
"email": "user#someco.com",
"firstname": "Bob",
"lastname": "Smith",
"company": "ACME",
"custom": {
"services": [
{
"name": "svc1",
"desc": "abcdefg",
"selected": "true",
"status": "None"
},
{
"name": "svc2",
"desc": "abcdefg",
"selected": "true",
"status": "None"
},
{
"name": "svc3",
"desc": "abcdefg",
"selected": "false",
"status": "None"
},
{
"name": "svc4",
"desc": "abcdefg",
"selected": "false",
"status": "None"
}
],
"fields": [
{
"name": "Products",
"desc": "abcdef",
"type": "multi",
"values": [
{
"name": "Product1",
"desc": "abcdef"
},
{
"name": "Product2",
"desc": "abcdef"
}
],
"services": [
"svc1",
"svc2",
"svc3"
]
},
{
"name": "Wines",
"desc": "abcdef",
"type": "multi",
"values": [
{
"name": "Wine 1",
"desc": "abcdef"
}
],
"services": [
"svc4"
]
},
{
"name": "Fruits",
"desc": "abcdef",
"type": "multi",
"values": [
{
"name": "Fruit 1",
"desc": "abcdef"
},
{
"name": "Fruit 2",
"desc": "abcdef"
}
],
"services": [
"svc4"
]
}
]
}
};
How can I convert that into an Angular menu? The menu would need to list all of the services, and then if the service has an associated item in "fields" that item should be listed underneath it. So for instance "svc1" and its description should be listed on a line (got that working) but then "Product1" and "Product2" with their descriptions should appear on the next two lines because you can see that "svc1" is listed in the "services" field for "Products." Similarly, "svc4" should appear on a line, and then "Wines" and its description on the next line because "svc4" appears in the "services" field of "Wines."
I think the best way is to unpack and re-pack this JSON object in sequential order in the Angular controller and then push this data out to the Angular view but there might be a solution using only the logic available from the view. I've tried a bunch of nested fors and ifs along these lines (very much not working):
var i, j;
var listArray = [];
for (i = 0; i < $scope.svcs.length; i++) {
var littleArray = [$scope.svcs[i].status, $scope.svcs[i].name, $scope.svcs.desc];
listArray.push[littleArray1];
for (j=0; j < $scope.jFA.length; j++) {
if ($scope.jFA[j] == $scope.svcs[i].name) {
if ($scope.jFA[j] == $scope.svcs[i].fields)
littleArray = [$scope.jFA[j].fields] //...etc
}
}
...but that logic just keeps getting more and more dense and isn't working no matter now I try to use it. I liked the simplicity in the answer to the other question but have not had success in replicating it.
So if someone can help me figure out how to get the data into the right sequence using JS I can handle the Angular part. Or if you're an Angular whiz and have an answer along those lines, even better.
So it was a little hard understanding your question, but I gave it my best shot. Does this fiddle show what you are trying to achieve? http://jsfiddle.net/arknr6qz/1/
JS:
var app = angular.module('TestApp',[]);
app.controller('TestController', function($scope)
{
$scope.checkService = function(service, fieldServices)
{
if (fieldServices.indexOf(service) != -1) return true;
return false;
};
$scope.data = {
"email": "user#someco.com",
"firstname": "Bob",
"lastname": "Smith",
"company": "ACME",
"custom": {
"services": [
{
"name": "svc1",
"desc": "abcdefg",
"selected": "true",
"status": "None"
},
{
"name": "svc2",
"desc": "abcdefg",
"selected": "true",
"status": "None"
},
{
"name": "svc3",
"desc": "abcdefg",
"selected": "false",
"status": "None"
},
{
"name": "svc4",
"desc": "abcdefg",
"selected": "false",
"status": "None"
}
],
"fields": [
{
"name": "Products",
"desc": "abcdef",
"type": "multi",
"values": [
{
"name": "Product1",
"desc": "abcdef"
},
{
"name": "Product2",
"desc": "abcdef"
}
],
"services": [
"svc1",
"svc2",
"svc3"
]
},
{
"name": "Wines",
"desc": "abcdef",
"type": "multi",
"values": [
{
"name": "Wine 1",
"desc": "abcdef"
}
],
"services": [
"svc4"
]
},
{
"name": "Fruits",
"desc": "abcdef",
"type": "multi",
"values": [
{
"name": "Fruit 1",
"desc": "abcdef"
},
{
"name": "Fruit 2",
"desc": "abcdef"
}
],
"services": [
"svc4"
]
}
]
}
};
});
HTML:
<div ng-app="TestApp">
<div ng-controller="TestController">
<div ng-repeat="service in data.custom.services">
{{ service.name }}
<div class="indent" ng-repeat="fields in data.custom.fields">
<span ng-if="checkService(service.name, fields.services)">
{{fields.services.values}}
<span ng-repeat="value in fields.values">
{{value.name}} - {{value.desc}}<br>
</span>
</span>
</div>
</div>
</div>
</div>
and finally css:
.indent {
margin-left:10px;
}

Parse JSON with multiple levels

I am trying to parse this JSON that I have assigned to a javascript variable but I am having a hard time looping through it due to it having multiple levels
<script type="text/javascript">
var varJson = {
"d": {
"results": [
{
"__metadata": {
"id": "http://www.bradinsight.com/ALFAPI/AlfWebApi/Offices(100013449)",
"uri": "http://www.bradinsight.com/ALFAPI/AlfWebApi/Offices(100013449)",
"type": "AlfWebApiInfrastructure.Poco.Office"
},
"Agency": {
"__deferred": {
"uri": "http://www.bradinsight.com/ALFAPI/AlfWebApi/Offices(100013449)/Agency"
}
},
"Advertiser": {
"__deferred": {
"uri": "http://www.bradinsight.com/ALFAPI/AlfWebApi/Offices(100013449)/Advertiser"
}
},
"Contacts": {
"results": [
{
"__metadata": {
"id": "http://www.bradinsight.com/ALFAPI/AlfWebApi/Contacts(id=59980,jobId=1000105450)",
"uri": "http://www.bradinsight.com/ALFAPI/AlfWebApi/Contacts(id=59980,jobId=1000105450)",
"type": "AlfWebApiInfrastructure.Poco.Contact"
},
"id": 59980,
"jobId": 1000105450,
"mask": 67108863,
"name": "Name",
"jobtitle": "Job Title",
"email": "email",
"companyType": "companyType",
"companyId": 1787,
"officeId": 100013449,
"address1": "address1",
"address2": "",
"address3": "",
"address4": "",
"addressTown": "addressTown",
"addressPostCode": "addressPostCode",
"tel": "tel",
"fax": "fax",
"responsibilities": "responsibilities"
},
{
"__metadata": {
"id": "http://www.bradinsight.com/ALFAPI/AlfWebApi/Contacts(id=64085,jobId=1000105448)",
"uri": "http://www.bradinsight.com/ALFAPI/AlfWebApi/Contacts(id=64085,jobId=1000105448)",
"type": "AlfWebApiInfrastructure.Poco.Contact"
},
"id": 64085,
"jobId": 1000105448,
"mask": 67108863,
"name": "name",
"jobtitle": "jobtitle",
"email": "email",
"companyType": "companyType",
"companyId": 1787,
"officeId": 100013449,
"address1": "address1",
"address2": "",
"address3": "",
"address4": "",
"addressTown": "addressTown",
"addressPostCode": "addressPostCode",
"tel": "tel",
"fax": "fax",
"responsibilities": "responsibilities"
}
]
},
"id": 100013449,
"companyId": 1787,
"addressLine1": "addressLine1",
"addressLine2": "",
"addressLine3": "",
"addressLine4": "",
"addressLine5": "addressLine5",
"postCode": "postCode",
"regionId": "regionId",
"countyId": "countyId",
"tvAreaId": "L",
"telephone": "telephone",
"fax": "fax8",
"countryId": "countryId",
"email": "email",
"isdn": null,
"mask": 66060287
}
]
}
};
$(document).ready(function () {
//var parsed = JSON.parse(varJson);
alert(varJson);
});
</script>
I tried using this:
$.each(varJson, function (index, item) {
alert(item);
});
But it just says object in my alert.
try this,
function traverse(jsonObj) {
if( typeof jsonObj == "object" ) {
$.each(jsonObj, function(k,v) {
traverse(v);
});
}
else {
alert(jsonObj);
}
}
$(document).ready(function () {
traverse(varJson);
});
http://jsfiddle.net/satpalsingh/hXEr8/
with reference of Traverse all the Nodes of a JSON Object Tree with JavaScript
You don't need to parse it in your example.
Use console.log instead of alert and you will the the object in your web inspector.
If you do want to alert do something like this
alert(varJson.d.results[0].__metadata.id)

Categories

Resources