Javascript Array String Generator Problem - javascript

My web page allows users to generate strings/phrases by selecting a combination of two radio buttons from two different groups: mode and category. After selecting their choice of buttons, they click the 'Push' button and a string pops up. See the snippet below:
class modes {
constructor(items) {
this.items = items;
this.randomUnused = [...items];
this.forwardIndex = 0;
this.reverseIndex = items.length - 1;
}
forwardItem() {
return this.items[this.forwardIndex++ % (this.items.length)];
}
randomItem() {
if (!this.randomUnused.length) {
this.randomUnused.push(...this.items);
}
const index = Math.floor(Math.random() * this.randomUnused.length);
return this.randomUnused.splice(index, 1);
}
reverseItem() {
if (this.reverseIndex < 0) {
this.reverseIndex = this.items.length - 1;
}
return this.items[this.reverseIndex--];
}
}
const categ = {
A: new modes([
"A example 1",
"A example 2",
"A example 3",
"A example 4",
]),
B: new modes([
"B example 1",
"B example 2",
"B example 3",
"B example 4",
]),
C: new modes([
"C example 1",
"C example 2",
"C example 3",
"C example 4",
]),
D: new modes([
"D example 1",
"D example 2",
"D example 3",
"D example 4",
])
};
function main() {
const output = document.querySelector("output");
if(!(document.forms.thingSelection2.type.value in categ)) {
return false;
}
const list = categ[document.forms.thingSelection2.type.value];
const method = document.forms.thingSelection1.mode.value + "Item";
const item = list[method]();
output.innerHTML = item;
}
const abutton = document.getElementById("abutton");
if(abutton) {
abutton.addEventListener("click", main);
}
<output></output>
<button id="abutton">Push</button>
<form name="thingSelection1">
Forwards<input type="radio" name="mode" value="forward">
Random<input type="radio" name="mode" value="random">
Backwards<input type="radio" name="mode" value="reverse">
</form>
<form name="thingSelection2">
<li><input type="radio" name="type" value="A">Choice A</li>
<li><input type="radio" name="type" value="B">Choice B</li>
<li><input type="radio" name="type" value="C">Choice C</li>
<li><input type="radio" name="type" value="D">Choice D</li>
</form>
Each category is currently represented by a radio button and has its own separate array, so only one may be selected at a time. My goal is to allow the user to select multiple categories and combine them into a new array, then cycle through them.
Problem 1: Changing the category radio buttons into checkboxes causes the function to break. The snippet below illustrates this. I figure this is due to the fact that checkboxes have 3 possible states (checked, unchecked, indeterminate) while radio buttons can only be true or false. I am unsure what changes to make to the function to allow the checkboxes to work. I could use some assistance. I'm fairly new to javascript, so please be patient.
class modes {
constructor(items) {
this.items = items;
this.randomUnused = [...items];
this.forwardIndex = 0;
this.reverseIndex = items.length - 1;
}
forwardItem() {
return this.items[this.forwardIndex++ % (this.items.length)];
}
randomItem() {
if (!this.randomUnused.length) {
this.randomUnused.push(...this.items);
}
const index = Math.floor(Math.random() * this.randomUnused.length);
return this.randomUnused.splice(index, 1);
}
reverseItem() {
if (this.reverseIndex < 0) {
this.reverseIndex = this.items.length - 1;
}
return this.items[this.reverseIndex--];
}
}
const categ = {
A: new modes([
"A example 1",
"A example 2",
"A example 3",
"A example 4",
]),
B: new modes([
"B example 1",
"B example 2",
"B example 3",
"B example 4",
]),
C: new modes([
"C example 1",
"C example 2",
"C example 3",
"C example 4",
]),
D: new modes([
"D example 1",
"D example 2",
"D example 3",
"D example 4",
])
};
function main() {
const output = document.querySelector("output");
if(!(document.forms.thingSelection2.type.value in categ)) {
return false;
}
const list = categ[document.forms.thingSelection2.type.value];
const method = document.forms.thingSelection1.mode.value + "Item";
const item = list[method]();
output.innerHTML = item;
}
const abutton = document.getElementById("abutton");
if(abutton) {
abutton.addEventListener("click", main);
}
<output></output>
<button id="abutton">Push</button>
<form name="thingSelection1">
Forwards<input type="radio" name="mode" value="forward">
Random<input type="radio" name="mode" value="random">
Backwards<input type="radio" name="mode" value="reverse">
</form>
<form name="thingSelection2">
<li><input type="checkbox" name="type" value="A">Choice A</li>
<li><input type="checkbox" name="type" value="B">Choice B</li>
<li><input type="checkbox" name="type" value="C">Choice C</li>
<li><input type="checkbox" name="type" value="D">Choice D</li>
</form>
Problem 2: Constructing the custom array in a specific order. While internet searches provide many ways to combine multiple arrays into one, like concat, none of them explain how to organize the strings in a custom order.
Example of what im looking for: ["A example 1", "B example 1", "C example 1", "D example 1", "A example 2", "B example 2"...]
Rather than simply stacking the array contents on top of each other, like concat and every other method of combining arrays: ["A example 1", "A example 2", "A example 3", "A example 4", "B example 1", "B example 2"...]
I'm unaware of any method to achieve this. No external libraries please.

Related

Select const by select drop down

I am looking for a solution to select different const via select dropdown menu to be shown in a table.
Anyone able to point me in the right direction?
Thanks.
<select id="select" name="select"\>
<option value="1"\>Device 1\</option\>
<option value="2"\>Device 2\</option\>
<option value="3"\>Device 3\</option\>
</select\>
const 1 = [Name: "Name 1", Code: "Code 1", Speed: "10"]
const 2 = [Name: "Name 2", Code: "Code 2", Speed: "20"]
const 3 = [Name: "Name 3", Code: "Code 3", Speed: "30"]
Function to select const by option value?
var text = selected option value
document.getElementById("Name").innerHTML = text.Name;
document.getElementById("Code").innerHTML = text.Code;
document.getElementById("Speed").innerHTML = text.Speed;
+--------------------------------+
| Name: | Selected const Name |
|---------|----------------------|
| Code: | Selected const Code |
|---------|----------------------|
| Speed: | Selected const Speed |
+--------------------------------+
I've tried to above method by cant get it to work.
Put your data in a structure that correlates to your selection process. Here I'm using an array of objects. You could also use an object containing objects as properties if you prefer to retrieve the device data by key instead of numerical index.
Add an event listener for the select element.
Update the DOM with the data by index.
const deviceData = [{
Name: "Name 1",
Code: "Code 1",
Speed: "10"
}, {
Name: "Name 2",
Code: "Code 2",
Speed: "20"
}, {
Name: "Name 3",
Code: "Code 3",
Speed: "30"
}];
document.querySelector('#select').addEventListener('change', event => {
// zero-based index requires deducting 1 from the option value
const user = deviceData[event.currentTarget.value - 1];
document.getElementById("Name").innerHTML = user.Name;
document.getElementById("Code").innerHTML = user.Code;
document.getElementById("Speed").innerHTML = user.Speed;
});
<select id="select" name="select">
<option>Select a device</option>
<option value="1">Device 1</option>
<option value="2">Device 2</option>
<option value="3">Device 3</option>
</select>
<div id="Name"></div>
<div id="Code"></div>
<div id="Speed"></div>
You will want to use objects not arrays and attach an event listener to the select.
Objects allow you to use non numerical and more dynamic keys.
let device = document.querySelector("#select");
let devices = {
"1": {
Name: "Name 1",
Code: "Code 1",
Speed: "10"
},
"2": {
Name: "Name 2",
Code: "Code 2",
Speed: "20"
},
"3": {
Name: "Name 3",
Code: "Code 3",
Speed: "30"
}
};
device.addEventListener("change", function() {
let deviceID = this.value;
let selDevice = devices[deviceID];
if (selDevice) {
document.getElementById("Name").innerHTML = selDevice.Name;
document.getElementById("Code").innerHTML = selDevice.Code;
document.getElementById("Speed").innerHTML = selDevice.Speed;
}
});
<select id="select" name="select">
<option value="">Select a device</option>
<option value="1">Device 1</option>
<option value="2">Device 2</option>
<option value="3">Device 3</option>
</select>
<div id="Name"></div>
<div id="Code"></div>
<div id="Speed"></div>
Why don'T you try an assoc array?
const array = {
"1" : {Name: "Name 1", Code: "Code 1", Speed: "10"},
"2" : {Name: "Name 2", Code: "Code 2", Speed: "20"},
"3" : {Name: "Name 3", Code: "Code 3", Speed: "30"}
}
Console.log(array[1].Name);

Filter "custom values" in AngularJS ng-repeat

I need to filter a list by their category, but each of these categories are custom, every user can write any category they want in the list.
I tried to make a list with ng-repeat in which I filtered all the duplicated values (In the code below is the unique:'Category' part), and I gave them the Category name as the value to filter, also I added an "All" category to show all the elements:
<ul class="categoriesList">
<li>
<label>
<input type="radio" ng-model="searchCategory.Category" value=""> All
</label>
</li>
<li ng-repeat="x in myList | unique:'Category'">
</label>
<input type="radio" ng-model="searchCategory.Category" value="{{x.Category}}"> {{x.Category}}
</label>
</li>
</ul>
But this approach isn't working. I've made a Plunker as example: Here is my plunker
I need to be able to add any category I want in the json example, and to be able of filter them. Thanks in advance.
OK the issue with your code was just that your property searchCategory was not defined on the $scope. Adding $scope.searchCategory = {}; to your controller will solve the issue. And the reason behind this is that ng-repeat creates its own child scope. Below is a snippet with the working solution.
Also one more thing was missing i.e you need to have the same group for all the radio buttons so that only one is selected at a time and that you do by adding name='filter' attribute all radio button.
var app = angular.module('app', []);
//duplicates filter
app.filter('unique', function() {
return function(items, filterOn) {
if (filterOn === false) {
return items;
}
if ((filterOn || angular.isUndefined(filterOn)) && angular.isArray(items)) {
var hashCheck = {},
newItems = [];
var extractValueToCompare = function(item) {
if (angular.isObject(item) && angular.isString(filterOn)) {
return item[filterOn];
} else {
return item;
}
};
angular.forEach(items, function(item) {
var valueToCheck, isDuplicate = false;
for (var i = 0; i < newItems.length; i++) {
if (angular.equals(extractValueToCompare(newItems[i]), extractValueToCompare(item))) {
isDuplicate = true;
break;
}
}
if (!isDuplicate) {
newItems.push(item);
}
});
// items = newItems;
}
return newItems;
};
});
app.controller('MainCtrl', function($scope) {
$scope.searchCategory = {};
$scope.myList = [{
"Category": "My custom category",
"Title": "Title example",
"Comments": "Example comments"
},
{
"Category": "My custom category",
"Title": "My cat is named George",
"Comments": "Example comments"
},
{
"Category": "My custom category",
"Title": "Hocus pokus",
"Comments": "Example comments"
},
{
"Category": "My custom category",
"Title": "Tyrion Lannister must have been king",
"Comments": "Example comments"
},
{
"Category": "My custom category",
"Title": "some text",
"Comments": "Example comments"
},
{
"Category": "Some new category",
"Title": "7 projects going LIVE now",
"Comments": "Example comments"
},
{
"Category": "Some new category",
"Title": "Batman vs Superman was a good movie",
"Comments": "Example comments"
},
{
"Category": "Some new category",
"Title": "Youtube channel projects",
"Comments": "Example comments"
},
{
"Category": "Some new category",
"Title": "Some project name",
"Comments": "Example comments"
},
{
"Category": "Some new category",
"Title": "projects (more)",
"Comments": "Example comments"
},
{
"Category": "A different category",
"Title": "Remember, remember the fifth of november",
"Comments": "Hello there!"
},
{
"Category": "A different category",
"Title": "It's night, electric night",
"Comments": "General Kenobi"
},
{
"Category": "Custom category",
"Title": "project name again",
"Comments": "Example comments"
}
];
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>AngularJS Filter with custom values</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.12/angular.js" data-semver="1.4.9"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<ul class="categoriesList">
<li>
<label>
<input name="filter" type="radio" ng-model="searchCategory.Category" ng-value=""> All
</label>
</li>
<li ng-repeat="x in myList | unique:'Category'">
<label>
<input name="filter" type="radio" ng-model="searchCategory.Category" ng-value="x.Category"> {{x.Category}}
</label>
</li>
</ul>
<div class="wrapper" ng-repeat="y in myList | filter:searchCategory:true">
<ul class="click-text">
<li>{{y.Title}} - {{y.Comments}}</li>
</ul>
</div>
</body>
</html>
Hope this helps :)
You have to write Ex- name="rdoCategory" attribute for radio button
`<ul class="categoriesList">
<li>
<label>
<input type="radio" name="rdoCategory" ng-model="searchCategory.Category" value=""> All
</label>
</li>
<li ng-repeat="x in myList | unique:'Category'">
</label>
<input type="radio" name="rdoCategory" ng-model="searchCategory.Category" value="{{x.Category}}"> {{x.Category}}
</label>
</li>
</ul>`
After that it will work.

Apply CSS style within .js var

I'm currently building a game which relies on a random number to show a particular string from an array within a .js file. What I want to do is effectively apply a span element to certain text within the array - eg. make positive outcomes green & negative red, however I can't figure out how to do this outside of html. Eg:
var data = [
{"label": "Question 1", "value": 1, "question": "Awareness: High, Consistency: Low."},
{"label": "Question 2", "value": 1, "question": "Consistency: High, Awareness: Low."},
]
A separate set of code, after selecting a random number, returns data[i].label. How would I set a span within js so that the "High" strings return in green, and "Low" return in red?
Cheers.
You have not specified much, but I went and did what I could.
First, your span
<span id="result">here we go</span>
The CSS file, minimalist, I did not include Bootstrap for this.
span {color:green}
.red{color:red}
The JS, the is no event, or event handler.
var data = [
{"label": "Question 1", "value": 1, "question": "Awareness: High, Consistency: Low."},
{"label": "Question 2", "value": 1, "question": "Consistency: High, Awareness: Low."}
]
The array, I have removed the trailing comma after the second object.
let outputs = data[0].question; This will hold the result from the array, data[0] targets the first object, you can also get map over the properties, but you have not entirely specified the scope and desired functionality.
var output = document.getElementById('result'); // the span element
output.innerText = outputs; // i prefer innerText to innerHTML
if (outputs.includes("Consistency: Low")) { // new string method includes, you can pass the whole ("Consistency: Low")in with no worries.
output.classList.toggle("red"); // if condidtion is true, toggle the red class
}
Codepen
https://codepen.io/damPop/pen/ZwvvGV?editors=0010
Uses classes
var data = [
{label: "Question 1", value: 1, awareness: 'High', consistency: 'Low' },
{label: "Question 2", value: 1, awareness: 'Low', consistency: 'High' },
{label: "Question 3", value: 1, awareness: 'Low', consistency: 'Low' },
{label: "Question 4", value: 1, awareness: 'High', consistency: 'High' }
];
const questionElement = document.getElementById('question');
const awarenessElement = document.getElementById('awareness');
const consistencyElement = document.getElementById('consistency');
document.getElementById('select').addEventListener('click', select);
select();
function select() {
const question = data[Math.floor(Math.random() * 4)];
questionElement.innerText = question.label;
awarenessElement.innerText = `Awareness: ${question.awareness}`;
awarenessElement.className = question.awareness;
consistencyElement.innerText = `Consistency: ${question.consistency}`;
consistencyElement.className = question.consistency;
}
.High {
background-color: green;
}
.Low {
background-color: red;
}
<span id="question"></span>
<div id="awareness"></div>
<div id="consistency"></div>
<button id="select">Select</button>

remove first element from array and return the array minus the first element

var myarray = ["item 1", "item 2", "item 3", "item 4"];
//removes the first element of the array, and returns that element.
alert(myarray.shift());
//alerts "item 1"
//removes the last element of the array, and returns that element.
alert(myarray.pop());
//alerts "item 4"
How to remove the first array but return the array minus the first element
In my example i should get "item 2", "item 3", "item 4" when i remove the first element
This should remove the first element, and then you can return the remaining:
var myarray = ["item 1", "item 2", "item 3", "item 4"];
myarray.shift();
alert(myarray);
As others have suggested, you could also use slice(1);
var myarray = ["item 1", "item 2", "item 3", "item 4"];
alert(myarray.slice(1));
Why not use ES6?
var myarray = ["item 1", "item 2", "item 3", "item 4"];
const [, ...rest] = myarray;
console.log(rest)
Try this
var myarray = ["item 1", "item 2", "item 3", "item 4"];
//removes the first element of the array, and returns that element apart from item 1.
myarray.shift();
console.log(myarray);
This can be done in one line with lodash _.tail:
var arr = ["item 1", "item 2", "item 3", "item 4"];
console.log(_.tail(arr));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
myarray.splice(1) will remove the first item from the array … and return the updated array (['item 2', 'item 3', 'item 4'] in your example).
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
array = [1,2,3,4,5,6,7,8,9];
array2 = array.slice(1,array.length); //arrayExceptfirstValue
console.log(array2);
I over through all the notable answers. I am pointing out a different answer. It works for me. I hope it will help you
array.slice(1,array.length)
You can use array.slice(0,1) // First index is removed and array is returned.

Bind JSON to Angularjs input

I got some JSON like this:
[{
"Id": 0,
"Text": "Item 1",
"Selected": 1
}, {
"Id": 1,
"Text": "Item 2",
"Selected": 1
}]
And an Input like this:
<input type="text"
value="{{question.postObjs}}"
What I want is the only the property "Text" as a list in the input.
Item 1, Item 2, ...
Is this even possible? I trying around like a while, got nothing to work :-(
in your controller :
scope.text = '';
for (var value in scope.question.postObjs){
scope.text = scope.text + value.Text;
}
in your input :
<input type="text" value="{{text}}" />
or
<input type="text" ng-model="text" />
Write a method in AngularController like this
$scope.getText(){
// which will return ["Item1", "Item2"]
}
And in view you can use the method to populate the value.

Categories

Resources