How do create a related search terms? - javascript

I'm working on a school project in code.org for my CS class. I'm trying to build an app that is about the bird.(We are learning about list/arrays, loops, and traversals)
In the project I'm trying to build a search box where people can type the name of the bird and in the next page will show up the information about the bird. (Those information are from the code.org data library, it has a lot of lists of datasets that you can use to build your app)
The code looks like this:
// code.org is using ES5
var birdSearch = getText('searchInput');
for(var i = 0; i < birdNameList.length; i++) {
if (birdSearch === birdNameList[i]) {
setText('birdNameOutput', birdNameList[i]);
setText('birdDietOuput', birdDietList[i]);
setText('birdImageOutput', birdImageList[i]);
}
But I'm afraid that no one will know those bird's name because you have to search the exactly same name in the list, then my app will be useless. So I am thinking to build a thing that will show the most related name depends on the user input.
It's like if you put 'Am' in the search box and it will show 'American Goldfinch', 'American Purple Gallinule' ... under the search box.
For example:
search box: Am______
do you mean: American Goldfinch
American Purple Gallinule
...

great first question and welcome! There are a lot of things here that you may wish to consider, such as the event that triggers the search - does the search happen when you click a button or when text is typed? If it is the latter then you may also want to think about debouncing the event, which is essentially adding a slight delay to calling the method to prevent it firing too many times and causing performance related issues, though I realise that this is probably a bit further on in your learning, but definitely something worth investigating as your learning progresses.
However, to get to the point of your question, I think it is probably best to look at a filter method to filter the array of results, with something like this:
const birdSearch = getText('searchInput');
const searchList = birdNameList.filter(function(bird) {
return bird.includes('birdSearch');
});
setText('suggestionBox', 'Do you mean: ' + searchList.join(', ') + '?');
Hopefully that should give you a starter for ten!

Related

How does SpeechSynthesis return a chosen list of languages?

Good Morning everybody,
I am still working on a questionnaire for illiterate people. For that I am using a Text to Speech application (thanks to #JO3-W3B-D3V)
The Problem is that the questionnaire will be developped in several languages, which means, that the text to speech application has to support several languages as well.
SpeechSynthesis.getVoices()
If I understood it correctly, the function above returns a list of all objects representing all the available voices on the current device. Now to my questions:
Is there a way to return a selection of these languages? For example, the listshould not return all 15 languages which are available on the device, but only 4 chosen ones?
Is there a way to add more languages to the device? I am using Chrome. If I understood it correctly Chromes gets the languages from Microsoft and Google. Therefore Chrome should display new language-option if I add a new language to my operation system (Windows 10). Is that assupmtion correct? I am asking because I did that already and nothing changed, so I might be missing something.
Hope my questions make sense :)
Have a great day!
Explained
Okay, so I'll answer this in two parts, considering the fact that you've kinda asked two questions, both are relatively simple & straightforward thankfully.
Question One
You've asked how to get _ chosen languages that you'd like to support, well that's simple, it's as easy as manipulating an array, within my example I've used the reduce function, fairly straightforward stuff.
P.S. For the sake of some form of consistence, I've written this snippet in a very similar fashion to the one that I wrote in the other question that you asked regarding speechSynthesis.
Assumptions
As stated within the code comments, I've written this snippet in such a way that there's no duplicated entries, i.e. within the snippet below, you will end up with a list that only contains one entity that supports the English language. In other words, you won't have both en-GB & en-US, of course you can change this, I just assumed that you'd want this type of feature, of course this is down to you & your requirements entirely.
// IIFE for the sake of it.
(function() {
"use strict";
// This is a simple list of languages that you wish to support.
var supportedLanguages = ['en', 'de', 'es', 'fr'];
var languages = [];
// This is essentially similar to jQuery's $.ready.
var ready = function(callback) {
var d = document,
s = d.readyState;
// DOMContentLoaded was fired
if (s == "complete" || s == "loaded" || s == "interactive") {
callback();
} else {
if (d.addEventListener) {
d.addEventListener("DOMContentLoaded", callback, false);
} else {
d.attachEvent("onDOMContentLoaded", callback);
}
}
};
// This is just a simple function to process whether or not you'd like to
// push a voice onto the array or not.
var shouldPush = function(array, object) {
var language = object.lang || '';
var snipped = language.substring(0, 2);
// Generate a list of all of the known languages.
var languageList = array.map(function(object) {
return object.lang;
});
// Create a list of short hand language names.
var snippedList = languageList.map(function(language) {
return language.substring(0, 2);
});
// Save having a bloated if statement, personally I find this
// more readable.
//
// Only push relevant ones, saves having any duplicated entities, i.e.
// this will not allow for both en-US & en-GB to be among the list,
// this can be altered, this is merely based on an assumption that you
// wouldn't want both en-US & en-GB, etc.
var isToPush = !snippedList.includes(snipped) &&
!languageList.includes(language) &&
supportedLanguages.includes(snipped);
// If true, push to array.
if (isToPush) {
array.push(object);
}
// Then of course return the array object.
return array;
};
// This is essentially the list of voices that you've picked to support.
var getSelectedLanguages = function() {
languages = speechSynthesis.getVoices().reduce(shouldPush, []);
};
// A starting point for this snippet.
var start = function() {
speechSynthesis.onvoiceschanged = function() {
getSelectedLanguages();
console.log(languages);
};
};
// Run the code when ready.
ready(start);
})();
Question Two
I'm not entirely sure if there's a "clean & easy" way to do this, having conducted my own research on the matter I've found that it looks like this would require some form of tinkering. One of the better sources of information that I've found is this question.
Having further looked into this question, it looks like Artyom also suggests that there's no simple way to achieve this, it looks like you can only add a language by installing the language into the operating system, so I'm lead to believe.
Conclusion
One possible idea is that you could, and I emphasise the word could possibly do this via implementing an API of your own, however I can't imagine this would be a solid or reliable implementation, as my conclusion is based on research suggests in order for an additional language to be included, the user is somewhat responsible for that, as it looks like it needs the user to have _ language installed on their OS in order for speechSynthesis to make use of _ language.
I actually find it a little odd that it appears that there's little/no formal documentation on this subject, rather I've just found mostly informal documentation, suggestions and assumptions. This could however be down to my lack of investigation, bear in mind that I've spent ~15 minutes at most looking into this issue.
Sources
A link to flaviocopes.com regarding speechSynthesis.
A link to Artyom.js, a library for speech related APIs.
A link to a previous stack overflow question similar to the second part of this question.
A link to a medium article.
MDN documentation.
A treehouse blog post.
While I may not have the answer that you desire for your second question, I hope that this entire answer has helped in some form or another! :)

Semi(Auto) Code Generating with Python/Java/etc

Before anyone down votes or call out as duplicate. I searched for code generation, auto code complete, code complete with python, and code automation with Java/Python and every results I have got were not relevant to task I want to achieve.
I am free to use any language but Java or Python are preferred due to various libraries and api support.
Task I have is: need to write a program that outputs *.js file and in that file I am going to have a same function printed many time as number of inputs.
Here Only thing that changes is name of the function and to speak.
n These two inputs are passed in as CSV file like column one is NAME and Column two is MESSAGE(to speak)
---------------------------------- output.js -------------------------------
module.exports = {
john: john,
tony: tony,
laura: laura
};
function john(assistant) {
let toSpeak = "Here something goes for John";
assistant.setContext("navigator", 1, {"mynavigator": OPTIONS});
return askAssistant(toSpeak, assistant);
function tony(assistant) {
let toSpeak = "whatever is message for tony";
assistant.setContext("navigator", 1, {"mynavigator": OPTIONS});
return askAssistant(toSpeak, assistant);
function laura(assistant) {
let toSpeak = "I think you got where I am going with";
assistant.setContext("navigator", 1, {"mynavigator": OPTIONS});
return askAssistant(toSpeak, assistant)
-----------------------------output.js------------------------------------------
I am not asking anyone to code this for me rather suggest me a tool that would help me achieve this task. I will sincerely appreciate your kind feedback
I can think of two approaches you could take.
The first approach is to use print statements in your favourite programming language to print out the required text. And, of course, wrap some of those print statements in for-loops to iterate over the list of (name, message) tuples. This approach is straightforward and does not require use of any third-party code-generation tools.
The second approach is to use a template engine, such as Apache Velocity (for Java).

Updating the view of a screen in AngularJS

Hey—I’m working on an angular 1.6 app, and I’ve come across an issue I’m not quite sure how to resolve. Here’s a brief discussion of the set up. The page is a form with thirty questions. There is a lot of conditional logic from the client that goes as follows: if user selects “Yes” on Q1 then show them Q2-4, if “No” on Q1, then skip to Q5. This repeats itself in the thirty question form.
I’ve come across the following scenario—what if the user selects “Yes” on Q1, answers Q2-4 and then realizes Q1 should really be “No”.
So my question is: 1) how do I clear the models? and 2) how do I update the view? So that if they decide, third time around, that Q1 should in fact be yes, Q2-Q4 are unchecked/clear/blank.
For 1) I just wrote a simple “clearAll method as follows:
function clearAll(arr){
arr.forEach(function(element){
if(element!==undefined){
element = null;
}
});
}
This clears the models but doesn’t update the view. How do I update the view so that Q2-4 are clear/empty/blank?
The idea I had is to update the view, so
$scope.$watch( myModel, function(val){
//set to null or delete?
}
But I cannot generalize this so it is flexible enough to accept an array. Any advice would be appreciated. Thanks.
For your particular problem I would use ui-router and resolve different states based on a question, i.e. state.questions and take different parameters like if you have url /questions as your base intro page (maybe weclome to questions or something), you would have /questions/1 and it would be 1st question /questions/2 would be second etc...
Then keep one list of objects on some simple service i.e.:
let questions = [];
which will persist throughout the app, later to be filled with some objects like:
{
q1: {
answers: [1,2,3]
},
{
q2: {
answers: [1,3]
}
You can always clear it after you are done with it or push new answer. Also you can check for particular answer before even loading the state, and this will give you great flexibility what you actually want.
well for ugly solution your watch maybe could work if you add watch group and timeout:
$scope.$watchGroup(arrayOfModels, (newVal, oldVal)=>{
if(newVal) {
// now do something you want with that models
// if they don't apply, try $timeout(()=> $scope.$apply());
}
})

Angular ngGrid Tree Control: Make a round trip on group expand

I am trying to use ngGrid to make somewhat of a "tree-control" which I can build dynamically by calling API's. ngGrid allows for grouping on rows, yet the nature of it requires that all rows be present at the beginning. This is unfortunate for the fact that an API to pull back all generation data for a File Integrity Monitoring system would be insanely slow and stupid. Instead, I wish to build the "tree" dynamically on the expansion of each generation.
I am trying to inject children (ngRows) into a group-row (ngAggregate) on a callback, yet I do not think that I am calling the correct constructor for the ngRows for the fact that the rows are ignored by the control
Through the use of the aggregateTemplate option on the gridOptions for ngGrid, I have been able to intersept the expansion of a group quite easily.
(maybe not easily, but still)
I've replaced the ng-click of the default template:
ng-click="row.toggleExpand()"
with:
ng-click="$parent.$parent.rowExpanded(row)"
I know that it's a bit of a hack, but we can get to that later. For now, it gets the job done.
The way that I discovered how to work my way up the $scope to my rowExpanded function was by setting a breakpoint in ngGrid's "row.toggleExpand" function and calling it from the template as so:
ng-click="row.toggleExpand(this)"
Once I retrieve the group I want, I call an API to get the children for said group. I then need to make the return as children of the row. I decided to do this by calling ngGrid's ngRow factory:
row.children = [];
for(var i = 0; i < childData.length; i++)
{
row.children[row.children.length] = row.rowFactory.buildEntityRow(childData[i], i);
}
row.toggleExpand();
... yet this does not appear to be working. The rows are not showing up after I do the expand! Why won't my rows show up?
Here's my current Plunker!
By the way
I've placed a debugger statement within the group-expand callback. As long as you have your debugger open, you should catch a breakpoint on the expansion of a group.
Thanks everybody!
I found my answer, I'm an idiot....
I got this control working, and then realized that it was a total hack, that I could have used the control the way it was meant to be used and it would have worked much better, had much better work-flow, and it would have saved me an entire day of development. If you are wondering how you use the control this way, the answer is that you don't.
I got the stupid thing to work by updating my data structure after the round trip and forcing the grid to refresh, pretty obvious. I had to set the grid options so that groups were always expanded and I had to control the collapser icon logic myself, outside of ngGrid. I never called row.toggleExpand. I also hid any rows with null values by a function call within an ng-if on my rowTemplate. After all that was said and done, I put my foot in my mouth.

Creating variable arrays with Javascript (dyamic, drop down)

I've been searching the board for a while (both here and Google) and can't seem to find what I'm looking. (Sorry if I've missed it and this qualifies as an annoying/redundant question.)
I'm working on form that will have copious amounts of drop downs based on previous selected variable(s). I was trying to come up with an easier way than having to create the individual fields and then hide/show based on selection. Ultimately, I'm aiming for a "tree" with between 3-5 levels of menus. (Clients doing, not mine.)
What the Logic looks like:
Variables: type, offer1, offer2, insert1, insert2, insert3,...
Where [type] determines [offer1,2] which has up to 3 variables each [insert1,2,3...]
So If user selects Type A: Offer1 = Array A (Insert1 = ArrayA1, Insert2 = ArrayA2, Insert3 = null) and Offer2 = Array B (Insert4 = ArrayB4, Insert5 = null); and so on and so forth.
So far, everything I've found only seems to handle the first tier, and JS isn't exactly my forte. Any pointing in the right direction would be greatly appreciated.
In case anyone else runs across this issue, I found this solution that uses JQuery:
http://www.appelsiini.net/projects/chained

Categories

Resources