Angular user input calculator - javascript

I would like to do a small aplication. I did it but my if statement doesn't work. I will appreciate if somebody can tell me what is wrong.
The application presents the user with a textbox where they can list comma-separated items. If the number of items in the textbox is less than or equal to 3 (e.g., 1, 2, or 3), a message should show up under to the textbox saying "Enjoy!". If the number of items is greater than 3 (4, 5, and above), the message "Too much!". To implement this behavior, I used the split method. If the textbox is empty and the user clicks the "Check If Too Much" button, the message "Please enter data first" should show up.
Here is my code:
(function () {
'use strict';
var app = angular.module('LunchCheck', []);
app.controller('LunchCheckController', LunchCheckController);
LunchCheckController.$inject = ['$scope'];
function LunchCheckController($scope) {
$scope.name;
$scope.message;
$scope.displayNumeric = function () {
console.log($scope.name);
console.log($scope.name.length);
var lungimea = $scope.name.length;
console.log(lungimea);
if (lungimea == null) {
$scope.message = "Please enter data first";
}
else {
$scope.name = $scope.name.split(" ");
console.log($scope.name);
if ($scope.name.length = 3) {
$scope.message = "Enjoy!";
}
else {
$scope.message = "Too much!";
};
};
};
};
})();
<!doctype html>
<html ng-app="LunchCheck">
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body>
<div ng-controller="LunchCheckController">
<form>
<input type="text" ng-model="name" placeholder="Check it!" />
<button ng-click="displayNumeric()">Check If Too Much</button>
</form>
{{message}}
</div>
</body>
</html>

From the example you gave above, I am assuming you want space-separated words, you can achieve this behavior with the below example where I have introduced a local variable to avoid updating the scope variable which is bound to the input.
(function () {
'use strict';
var app = angular.module('LunchCheck', []);
app.controller('LunchCheckController', LunchCheckController);
LunchCheckController.$inject = ['$scope'];
function LunchCheckController($scope) {
$scope.name;
$scope.message;
$scope.displayNumeric = function () {
if (!$scope.name) {
$scope.message = "Please enter data first";
}
else {
let nameSplit = $scope.name.split(" ");
if (nameSplit.length <= 3) {
$scope.message = "Enjoy!";
}
else {
$scope.message = "Too much!";
};
};
};
};
})();
<!doctype html>
<html ng-app="LunchCheck">
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body>
<div ng-controller="LunchCheckController">
<form>
<input type="text" ng-model="name" placeholder="Check it!" />
<button ng-click="displayNumeric()">Check If Too Much</button>
</form>
{{message}}
</div>
</body>
</html>
I hope this helps.

You are missing the part where you split the comma separated items from the string. Using $scope.name.length will return only the count of characters of the input.
var lungimea = $scope.name.length;
console.log(lungimea);
if (lungimea == null)
{
$scope.message = "Please enter data first";
}
else
{
$items = $scope.name.split(",");
$scope.message = $items.length <= 3? 'Enjoy!' : 'Too much!';
};
Will give you the amount of items separated by comma.
Also try to stored the items in a different variable instead of replacing the $scope.name one (remember that you have a ng-model listening to that variable)

Related

Enter key as well as submit button on Google Script Code in Sheet

I would like to be able to use enter as well as the submit button to execute / accept data entry and commit to cell.
I cannot seem to get the code to work.
Any advice how to modify?
<script>
var itemBox = document.getElementById("itemname");
document.getElementById("btn").addEventListener("click",addRecord);
function addRecord(){
var name = itemBox.value;
if(name.trim().length == 0){
M.toast({html: "Please enter a valid barcode!"})
} else{
var data = {
name:itemBox.value
};
google.script.run.appendData(data);
itemBox.value = "";
}
}
</script>
Please read comments:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<script>
var itemBox = document.getElementById("itemname");
document.getElementById("btn").addEventListener("click",addRecord);
function addRecord(){
var name = itemBox.value;//item box is undefined
if(name.trim().length == 0){
M.toast({html: "Please enter a valid barcode!"})//M is undefined and toast does not exist clientside
} else{
var data = {name:itemBox.value};
google.script.run.appendData(data);
itemBox.value = "";
}
}
</script>
</body>
</html>
Spreadsheet.toast() is a server side method of Class Spreadsheet and is not intended to function clientside on the browser.
Spreadsheet.toast()
So far your description of your question is incomplete

Display key name with spaces in ng-repeat

repeat where i am repeating key value pairs, I am having key without spaces where i need to display with space.
my ng-repeat:
ng-repeat="(key, value) in scenariosViewAll.collectionBookObject"
i am displaying in span:
<span class="accordion-title">
{{key}}
</span>
in controller i am pushing the array as :
vm.shared.collectionFlyoutObject.BusinessDrivers.push(data);
Its working fine and displaying key as BusinessDrivers.
But i need to display as Business Drivers .
You might be able to somehow work with the current key and add spaces to it the way you want. One alternative would be to just maintain state in the collection book object for the human readable form of the key. Assuming such a field keyView existed, then you would access it on the value, not the key, using this:
<span class="accordion-title">
{{value.keyView}}
</span>
Another approach would be to just maintain a map in your controller which can map the keys to the human readable forms you want, e.g.
$scope.keyViews = { };
$scope.keyViews['BusinessDrivers'] = 'Business Drivers';
And then display using this:
<span class="accordion-title">
{{keyViews[key]}}
</span>
But this approach is less nice than keeping all the relevant state in a single map, for maintenance and other reasons.
var app = angular.module('myApp', []);
app.filter('myFormat', function() {
return function(x) {
var txt = x.replace(/([A-Z]+)/g, "$1").replace(/([A-Z][a-z])/g, " $1")
return txt;
};
});
we can make a filter to create the effect.
in template
<span class="accordion-title">
{{key | myFormat}}
</span>
You can use a custom function to split camelCase. You just have to define the function in your main controller and it can be referenced anywhere in your code.
var app = angular.module('plunker', []);
app.controller('ApplicationController', function($scope) {
$scope.splitCamelCase = function(input) {
if (!input)
return;
var j = 0;
var splitString = "";
var i = 0;
for (i = 1; i < input.length; i++) {
if (input.charAt(i) == input.charAt(i).toUpperCase()) {
splitString = splitString + " " + input.slice(j, i);
j = i;
}
}
splitString = splitString + " " + input.slice(j, i);
return splitString.replace("And", "and").replace("and", " and").substr(1, splitString.length);
};
});
<!doctype html>
<html ng-app="plunker">
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.js"></script>
</head>
<body>
<div class="container" ng-controller="ApplicationController">
<div class="row">
{{splitCamelCase("BusinessDrivers")}}
</div>
</div>
</body>
</html>
I am copied the snippet from #Vivz to make my change
try this.
var app = angular.module('plunker', []);
app.controller('ApplicationController', function($scope) {
$scope.splitCamelCase = function(input) {
return input.replace(/([A-Z]+)/g, " $1").replace(/([A-Z][a-z])/g, " $1");
};
});
<!doctype html>
<html ng-app="plunker">
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.js"></script>
</head>
<body>
<div class="container" ng-controller="ApplicationController">
<div class="row">
{{splitCamelCase("BusinessDrivers")}}
</div>
</div>
</body>
</html>
If you only want to convert the key from camelCase to a space separated proper string, then I suggest you to use a filter as that would be the easiest way.
You can simply create a new filter and use that.
controller:
var myApp = angular.module('myApp',[]);
myApp.filter('splitCamelCase', function() {
return function(input) {
return input.charAt(0).toUpperCase() + input.substr(1).replace(/[A-Z]/g, ' $&');
}
});
View:
<div ng-controller="MyCtrl">
{{str | splitCamelCase }}
</div>
This is just an example. Hope this helps :) Fiddle
I think the answers above is a little bit overwhelming. It can all be narrowed down to :
.filter('splitByUppercase', function() {
return function(input) {
return input.split(/(?=[A-Z])/).join(' ')
}
})
Example
<span ng-repeat="t in test">
{{ t | splitByUppercase }}<br>
</span>
http://plnkr.co/edit/OUfmusiswNeEpSURFVRx?p=preview
If you want to lowercase the extracted words so it becomes "Business drivers" etc you can use
.filter('splitByUppercase', function() {
return function(input) {
input = input.split(/(?=[A-Z])/);
input = input.map(function(s,i) {
if (i>0) s = s[0].toLowerCase() + s.substring(1)
return s
});
return input.join(' ')
}
})

Javascript - basic programing, can´t change picture

I have five jpg pictures and on a homepage i want to choose between these five pics by typing 1,2,3,4 or 5 and click OK and then i want that picture to show.
My code looks like this:
var inputElem, msgElem;
function init() {
msgElem = document.getElementById("message");
inputElem = [];
inputElem[1] = document.getElementById("input1");
inputElem[2] = document.getElementById("input2");
inputElem[3] = document.getElementById("input3");
document.getElementById("btn1").onclick = showFruit;
}
window.onload = init;
function showFruit() {
var nr, fruitUrl;
fruitUrl = (fruitImg.src = "pics/fruit" + nr + ".jpg");
nr = Number(input1.value);
fruitImg.src = "pics/fruit" + nr + ".jpg";
fruitUrl = document.getElementById("fruitImg").src = "pics/fruit1.jpg";
The problem is that I can't change the picture.I don't know whats missing, or how to make it choose between pic 1-5.
I have no privilege to write comments, so can't estimate what you actually want. But the resulting effect may be the thing you want.
But have look up below examples (live here). Enter a number then click button.
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="image">
<img src="salon1.jpg" id="fruit">
</div>
<input type="number" id="inp">
<input type="submit" id="btn1" onclick="showFruit('inp')">
<script type="text/javascript">
makeImageFromNum = function (n) {
var nr = document.getElementById(n).value;
if (parseInt(nr)>5) {
nr = 5;
}
else if (parseInt(nr)<1) {
nr = 1;
}
return "salon"+nr+".jpg";
}
showFruit = function (n) {
document.getElementById("fruit").src = makeImageFromNum(n);
}
</script>
</body>
</html>
In below example (live here) just change the number - no need to click a button, there is no any actually :)
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="image">
<img src="salon1.jpg" id="fruit">
</div>
<input type="number" id="inp" onchange="showFruit(this.value)">
<script type="text/javascript">
makeImageFromNum = function (nr) {
if (parseInt(nr)>5) {
nr = 5;
}
else if (parseInt(nr)<1) {
nr = 1;
}
return "salon"+nr+".jpg";
}
showFruit = function (n) {
document.getElementById("fruit").src = makeImageFromNum(n);
}
</script>
</body>
</html>
Note that you're always assinging the first image in this line of code (the last Iine if your code)
fruitUrl = document.getElementById("fruitImg").src = "pics/fruit1.jpg";
So, you'll always see image one

Splitting input one by one and translating input one by one using functions in JS and HTML

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<link rel="stylesheet" href="css/main.css" />
<script type="application/javascript" src="js/client.js"></script>
<title>A simple translation app</title>
</head>
<body>
<h1>A simple tranlation app</h1>
<div>
<textarea id="sourceText">
</textarea>
</div>
<div>
<label for="translation">Choose:</label>
<select id="translation" name="translation">
<option value="englishToFrench">English to French</option>
<option value="frenchToEnglish">French to English</option>
</select>
</div>
<div>
<textarea id="targetText" disabled="disabled"></textarea>
</div>
<div>
<button id="translateBtn" type="button">Translate</button>
</div>
<div id="alert">
</div>
The task here is for the user to input a certain english words in the object and translate them into french as follows and vice versa as follows:
<script type="text/javascript">
var englishToFrench = {
'He': 'il',
'throws': 'jete',
'the': 'la',
'ball': 'balle',
}
var frenchToEnglish = {
'il': 'He',
'jete': 'throws',
'la': 'the',
'balle': 'ball',
}
var sourceText;
What I was planning to do was use two functions. One that splits the object inputs one by one and the other function is to translate them one by one. My work so far is as follows:
var translateText = function() {
var translationType = document.getElementById('translation').value;
if (translationType === 'englishToFrench') {
console.log('translation used: English to French');
return 'code1';
}else if(translationType === 'frenchToEnglish'){
console.log('translation used: French to English');
return 'code2';
}else{
return "No valid translation selected.";
}
};
My second function is:
var translateBtnClickHandler = function() {
var sourceText = document.getElementById('sourceText').value;
document.getElementById('targetText').value = translateText();
};
window.onload = function() {
document.getElementById('translateBtn').onclick = translateBtnClickHandler;
};
</script>
</body>
</html>
My problem here is linking the split function with the translating function. Assuming the everything else is fine, with HTML, how can I close this gap? Any advice is much appreciated.
You can wrap your functions into one function by checking your translation type and getting value to display like following
var englishToFrench = {
'He': 'il',
'throws': 'jete',
'the': 'la',
'ball': 'balle'
};
var frenchToEnglish = {
'il': 'He',
'jete': 'throws',
'la': 'the',
'balle': 'ball'
};
var translateBtnClickHandler = function () {
var dictionary;
var translationType = document.getElementById('translation').value;
//get dictionary type
if (translationType === 'englishToFrench') {
dictionary = englishToFrench;
}else if(translationType === 'frenchToEnglish'){
dictionary = frenchToEnglish;
}else{
dictionary = false;
}
//if dictionary type is valid, get value from dictionary and display
if(dictionary) {
var sourceText = document.getElementById('sourceText').value;
var translateText = dictionary[sourceText];
document.getElementById('targetText').value = undefined ? "" : translateText;
}
}
window.onload = function() {
document.getElementById('translateBtn').onclick = translateBtnClickHandler;
};
Try passing sourceText to translateText , using String.prototype.match() , String.prototype.replace() to match , replace words in first textarea element
var englishToFrench = {
'He': 'il',
'throws': 'jete',
'the': 'la',
'ball': 'balle',
}
var frenchToEnglish = {
'il': 'He',
'jete': 'throws',
'la': 'the',
'balle': 'ball',
}
var translateText = function(src) {
var translationType = document.getElementById('translation').value;
// do translation
var re = new RegExp(src.value.match(/\w+/g).join("|"), "g"),
translate = function(type) {
return src.value.replace(re, function(match) {
return window[type][match] || match
});
};
if (translationType === 'englishToFrench') {
console.log('translation used: English to French');
return translate(translationType)
} else if (translationType === 'frenchToEnglish') {
console.log('translation used: French to English');
return translate(translationType)
} else {
return "No valid translation selected.";
}
};
var translateBtnClickHandler = function() {
var sourceText = document.getElementById('sourceText');
document.getElementById('targetText').value = translateText(sourceText);
};
window.onload = function() {
document.getElementById('translateBtn').onclick = translateBtnClickHandler;
};
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>A simple translation app</title>
</head>
<body>
<h1>A simple tranlation app</h1>
<div>
<textarea id="sourceText">
</textarea>
</div>
<div>
<label for="translation">Choose:</label>
<select id="translation" name="translation">
<option>select a translation type</option>
<option value="englishToFrench">English to French</option>
<option value="frenchToEnglish">French to English</option>
</select>
</div>
<div>
<textarea id="targetText" disabled="disabled"></textarea>
</div>
<button id="translateBtn" type="button">Translate</button>
</body>
</html>

infdig Infinite $digest Loop

I'm learning AngularJs but I cant make it works.
I read about the digest cycle but it is not clear for me.
It's obvious that this code fails because enter in a infinite loop, but I dont know how to fix it.
Could someone help me?
<!DOCTYPE html>
<html lang="eng" ng-app="test">
<head>
<title>Learning Angular</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular-route.js"></script>
<script type="text/javascript">
var app = angular.module('test', ['ngRoute']);
app.factory('visitCounterService', function () {
var counterService = function() {
var _count = 1;
var counter = function() { return _count++; };
return { counter: counter }
}();
return counterService;
});
app.service('homeModel', ['visitCounterService', function(visitCounterService){
this.getTitle = function() {
var n = visitCounterService.counter();
return "Welcome to this awesome demo. You are the visitor n° " + n;
};
}]);
app.controller('homeController', ['$scope', 'homeModel', function($scope, homeModel) {
$scope.home = homeModel;
}]);
</script>
</head>
<body ng-controller="homeController">
<h3>{{home.getTitle()}}</h3>
</body>
</html>
Thanks in advice!!!
Angular registers an implicit $watch on the home.getTitle() expression. This expression will get called at least twice because angular wants to check if the model has stabilized.
Your code returns a different string everytime home.getTitle() is called so angular continues digesting until it reaches the max digest cycles limit.
Try:
$scope.homeTitle = homeModel.getTitle();
and
<h3>{{homeTitle}}</h3>

Categories