Hi recently I was writing a code which basically askes users to input a cost for any item.
The item name or price are not important so far.
How the system works is that a prompt pops up and asks what is the cost of the item, and when you enter a cost, it asks you again (while loop). When total cost reaches $36, while loop ends and an alert screen pops up saying your shipping is free since it is over $35.
My problem is when I enter string value as a user input it takes the value into cost array and since it goes as Nan value, my cost calculation never end even though it passes $36.
How can I eliminate any string input and do not push it into the array?
Here is my code:
while (complete === false) {
var costValue = prompt('Enter the cost of the item?');
//If user click cancel
if (costValue === null) {
alert('Process canceled');
complete = true;}
//AT THIS LINE HOW CAN I ELIMINATE STRING VALUES
//convert input to a number
userInput = parseInt(costValue);
/push the value into the array
myCost.push(userInput);
Leading special character will give you NAN and if you use a special character after the Int value then the parseInt will give you the correct result. You can also use regex to remove all the special characters.
userInput.replace(/[^\w\s]/gi, '')
You can read about parseInt from here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
After you parse your user input into an integer (i.e. using parseInt method), then have an if statement that checks whether the parsed values is not NaN. If so, then only push the parsed value into your array.
// TRY parse user input into an integer
userInput = parseInt(costValue);
// only push into your array when it is not `NaN`
if (userInput !== 'NaN') {
// push the value into the array
myCost.push(userInput);
}
Try this code, it should work
var userInput;
var totalInput=0;
var complete = false;
var costValue;
var numPattern = /^\d+$/;
while (!complete) {
costValue = prompt('Enter the cost of the item?');
//If user click cancel
if (costValue === null)
{
alert('Process canceled');
complete = true;
}
//convert input to a number if it matches regular expression
if (costValue.match(numPattern)){
userInput = parseInt(costValue);
totalInput+=userInput;
if (totalInput>35) {
complete=true;
alert("Cost is $" + totalInput + ". Shipping is free over $35");
}
}
}
On the other hand, if you want to go another route, you can check for NaN using this function isNaN(userInput) and exclude it from your calculations
Related
I am attempting to add a search feature to Quill and want to highlight the text that it finds. I am having trouble getting the range index for the text it finds, and it is likely that I am not using the correct approach.
So far, I get the text using getContents() and can find matches by iterating through the lines. However, I have not been able to find the correct index position for setSelection(). A second issue is that I want the window to scroll to where the selection is found, and it is not scrolling into view.
...
myKeyPhrases = ['obvious', 'orange', 'apple'];
var myDelta = editor.getContents();
myDelta.eachLine((line, attributes, i) => {
mytext = line.filter((op) => typeof op.insert === 'string').map((op) => op.insert).join('');
mytext = mytext.toLowerCase();
ndx = isKeyPhraseFound(mytext, myKeyPhrases);
if (ndx >= 0){
// The code finds the matches OK to here.
// The next 4 lines don't get the correct range and scroll.
index = i;
editor.focus();
editor.setSelection(index, 1, Quill.sources.USER);
editor.scrollIntoView();
return index;
}
});
My desired results would be that a found text match would be selected and that the window would be scrolled so that the selection is displayed. The actual results are that the wrong text is selected and the window is not scrolled to view the selection.
You're basically there. I suspect your issue is that you're filtering out block elements, which acts similarly to Quill's getText method. According to the docs:
Non-string content are omitted, so the returned string’s length may be shorter than the editor’s as returned by getLength.
This is because non-text elements usually have a length of 1, so for every one of those you omit, your index will drift by 1.
A simple workaround for this is to replace any non-text elements with a newline character, which has length 1, and the added benefit of causing a search across it to fail (unless you let users search with newlines - maybe then you can pick another special character like a control character).
The following method should return a plain-text representation of your Quill contents whose length matches quill.getLength, and therefore should be able to be searched using whatever JavaScript text search method you want (eg indexOf for simple searches).
function textContents() {
return quill.getContents().ops
.reduce((text, op) => {
if (typeof op.insert === 'string') {
// If the op is a string insertion, just concat
return text + op.insert;
} else {
// Otherwise it's a block. Represent this as a newline,
// which will preserve the length of 1, and also prevent
// searches matching across the block
return text + '\n';
}
}, '');
}
Here's a rough example: https://codepen.io/alecgibson/pen/GLVzPb
I am making a program which has the user enter a golf score which then stores it in an array. However, the user can only enter up to 18 scores and I have attempted to code a prompt which indicates the number of scores that are in the array/they have entered. The label is called lblPrompt1 and it does not function. I also want to disable the addscore button when the user has entered all 18 scores. The prompt does not function. Please advise. Thanks!
// Purpose: To add golf scores to an array
// This line makes the button, btnAddScore wait for a mouse click
// When the button is clicked, the addName function is called
btnAddScore.addEventListener(MouseEvent.CLICK, addScore);
// This line makes the button, btnDisplayScores wait for a mouse click
// When the button is clicked, the displayScores function is called
btnDisplayScores.addEventListener(MouseEvent.CLICK, displayScores);
// declare the global variables
var scores: Array = new Array(); // array of golf scores
// This is the addName function
// e:MouseEvent is the click event experienced by the button
// void indicates that the function does not return a value
function addScore(e: MouseEvent): void {
// declare the variables
var golfScore: String; // friend's name entered by user
// get the name from the user
golfScore = txtinScore.text;
// append the name to the end of the array
scores.push(golfScore);
// display the length of the array in the label
lblArraySize.text = "Number of Golf Scores Entered: " + scores.length;
}
// This is the displayNames function
// e:MouseEvent is the click event experienced by the button
// void indicates that the function does not return a value
function displayScores(e: MouseEvent): void {
var holeNumber: Number;
lblScores.text = "";
for (var x = 0; x < scores.length; x++) {
lblScores.text += scores[x] + "\r";
}
holeNumber++;
if (holeNumber <= 18) {
lblPrompt1.text = "Enter the score for hole #" + holeNumber.toString() + ":";
} else {
lblPrompt1.text = "All scores are entered.";
txtinScore.text = "";
btnAddScore.enabled = false;
}
}
While it's not very clear what you are asking, one issue you have is that your holeNumber variable will never have a numeric value - it will always be NaN (Not A Number).
Whenever the display scores button is clicked, inside the click handler function (displayScores), you create this variable (holeNumber) and you don't give it a value. Numbers default to NaN, so later when you increment it with holeNumber++, you'll just end up with NaN still (because NaN plus 1 is still NaN).
The other part of that issue, is you create the variable in the scope of the click handler, and only increment it once, so even if you changed the var definition to var holeNumber:Number = 0;, it would still have a value of 1 every time you clicked because every click the variable get's recreated and then incremented by 1.
What you probably want to do, is forgo the holeNumber var altogether and just reference scores.length as that is essentially the current hole.
function displayScores(e: MouseEvent): void {
lblScores.text = "";
for (var x = 0; x < scores.length; x++) {
lblScores.text += scores[x] + "\r";
}
//use scores.length instead of holeNumber
if (scores.length < 18) {
lblPrompt1.text = "Enter the score for hole #" + String(scores.length + 1) + ":";
//adding 1 to the length because that would be the next hole number
} else {
lblPrompt1.text = "All scores are entered.";
txtinScore.text = "";
btnAddScore.enabled = false;
}
}
I am creating an application that needs to take user input from a text input. If, at any point, the character that was inputted was incorrect (ie: a number when it should only be a-z), the input box will become invalid. I then take that character and place it in an array of "bad characters" that are in the input. The input box should become valid again if the character is deleted.
I am aware that I can take the input with every new key press and check that, but then that is going through each character to make sure it is allowed.
I am curious if there is anyway to see what character was deleted with a backspace press.
I cannot post my code, I'm sorry.
I am using ng-keydown and mg-model in html. When the confirm button is pressed, the input should be valid from the ng-model.
Thanks -- I am teaching myself Angularjs, so I am not the best with it yet.
To get the deleted characters you can use plain old javascript:
var caret_get_position = function(element){
var pos = 0;
var posEnd = 0;
if('selectionStart' in element){
pos = element.selectionStart;
posEnd = element.selectionEnd;
}else if('selection' in document){
element.focus();
var Sel = document.selection.createRange();
var SelLength = document.selection.createRange().text.length;
Sel.moveStart('character', -element.value.length);
pos = Sel.text.length-SelLength;
posEnd = Sel.text.length;
}
// return both selection start and end;
return [pos, posEnd];
};
//get deletet character
element.addEventListener('keydown', function(event){
var keycode = ('which' in event)?event.which:event.keyCode;
caret_positions = caret_get_position(element);
var val = this.value;
if(keycode == 8){
if(caret_positions[0] == caret_positions[1]){
if(caret_positions[0] == 0){
deleted = '';
}else{
deleted = val.substr(caret_positions[0]-1, 1);
}
}else{
deleted = val.substring(caret_positions[0], caret_positions[1]);
}
}else if(keycode == 46){
if(caret_positions[0] == caret_positions[1]){
if(caret_positions[0] === val.length){
deleted = '';
}else{
deleted = val.substr(caret_positions[0], 1);
}
}else{
deleted = val.substring(caret_positions[0], caret_positions[1]);
}
}
});
So the hell am i doing here:
caret_get_position is pretty much self-explanatory. It will get the current position of the caret (the blinking line in your inputfield). Even with a selected range (this blue stuff) if you select more than one character.
In the keydown event it will check the pressed key and some more checks where the caret is.
In the end the deleted characters are in the variable deleted. This is from my code so you need to adjust it for your needs.
I'm writing a flexible search algorithm for a portion of my XML file. I have this exact same method working flawlessly elsewhere, thus why this is driving me batty.
Here is the section of my function that I'm having trouble with.
var searchResults:Array = [];
var r:Array = [];
//Other code...
var classSplit:Array = inClass.split("-");
var profs:Array = getCourseProfs(classSplit[0], classSplit[1]);
trace(searchResults + "-vs-" + profs);
for each(var si:String in searchResults)
{
trace(si + " is at index " + profs.indexOf(si));
trace(profs);
if(r.indexOf(si) == -1 && profs.indexOf(si) != -1)
{
r.push(si);
trace(r);
}
}
And here is the output for a particular run's trace statements (from the above code).
GABIOMA1,GABIOMA1-vs-GABIOMA1,MITCHKA1,GIBSOCA1
GABIOMA1 is at index -1
GABIOMA1,MITCHKA1,GIBSOCA1
GABIOMA1 is at index -1
GABIOMA1,MITCHKA1,GIBSOCA1
Final:
As you can see, the function has two results in the searchResults array (of strings). They're both identical since I haven't yet sorted out duplicate search results. "GABIOMA1,GABIOMA1"
Then, I'm comparing that to an array "profs" with these three values: "GABIOMA1,MITCHKA1,GIBSOCA1"
You can see the matching result in index 0 of profs. However, as you see from the next line, profs.indexOf(si)' whensi` is "GABIOMA1" incorrectly returns "-1".
I can write a workaround in a heartbeat, but I need to know why indexOf has decided to bork.
EDIT: Even more infurating, the code in the other branch of the IF statement from this works like a charm...
for each(var s:String in searchResults)
{
if(r.indexOf(s) == -1)
{
r.push(s);
}
}
EDIT 2: This is my WORKING workaround. As you can see, all of the arrays are working properly.
for each(var si:String in searchResults)
{
var match:Boolean = false;
for each(var pi:String in profs)
{
if(si == pi)
{
pr.push(si);
break;
}
}
}
Given your trace(profs) returns a single string, your array contains a string GABIOMA1,MITCHKA1,GIBSOCA1 as a single entity, that's why your index of GABIOMA1 returns -1. You need to do split by comma within getCourseProfs() to get your GABIOMA1 as a separate string.
UPDATE: I have tested with the following:
var t:Array = ['GABIOMA1', 'MISCHKA1', 'GIBSOCA1'];
trace(t);
trace(t.indexOf('GABIOMA1'));
var a:Array = ['MITCHKA1', 'GABIOMA1\x00'];
for each(var si:String in a) trace(si, 'is at index', t.indexOf(si));
This gave me an expected result of -1 for either element of a, and expected trace results as in your example, however, equality test fails. Please try trimming the searchResults strings prior to checking for indexOf().
A side note: placing a \x00 as the first char of a string produces different results for tracing! trace(si, 'is at index', t.indexOf(si)); results in an empty string displayed in place of si like this: is at index -1, while trace(si + ' is at index ' + t.indexOf(si)); results in full string displayed: GABIOMA1 is at index -1. So carefully check either string for non-printable symbols, it's likely there is some hidden zero char that screws indexOf().
Hey I am using GetUserMedia() to capture audio input from user's microphone. Meanwhile I want to put captured values into an array so I can manipulate with them. I am using the following code but the problem is that my array gets filled with value 128 all the time (I print the results in console for now), and I can't find my mistake. Can someone help me find my mistake?
//create a new context for audio input
context = new webkitAudioContext();
var analyser = null;
var dataarray = [];
getLiveInput = function() {
navigator.webkitGetUserMedia({audio: true},onStream,onStreamError);
};
function onStream(stream)
{
var input = context.createMediaStreamSource(stream);
analyser = context.createAnalyser();
var str = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteTimeDomainData(str);
for (var i = 0; i < str.length; i++) {
var value = str[i];
dataarray.push(value);
console.log(dataarray)
}//end for loop
}//end function
function onStreamError(e) {
console.error('Streaming failed: ', e);
};
The values returned from getByteTimeDomainData are 8 bit integers, from 0 to 255. 128, which is half way, basically means "no signal". It is the equivalent of 0 in PCM audio data from -1 to 1.
But ANYWAY - there are a couple problems:
First, you're never connecting the input to the analyser. You need input.connect(analyser) before you call analyser.getByteTimeDomainData().
The second problem isn't with your code so much as it's just an implementation issue.
Basically, the gotStream function only gets called once - and getByteTimeDomainData only returns data for 1024 samples worth of audio (a tiny fraction of a second). The problem is, this all happens so quickly and for such a short period of time after the stream gets created, that there's no real input yet. Try wrapping the analyser.getByteTimeDomainData() call and the loop that follows it in a 1000ms setTimeout and then whistle into your microphone as soon as you give the browser permission to record. You should see some values other than 128.
Here's an example: http://jsbin.com/avasav/5/edit