single and multiple card selection data in angularjs - javascript

Please look at the fiddle
jsfiddle
I have multiple cards in a container. And I have a unique value "objectid".
I have "selactAll" button, If I click that button, every card should get selected and save button is enable. That time I need to pass all cards in a parameter.
After "selectAll", if i click on any of the card, that particular card should get unselect. That time if I click save button, the remaining selecteds cards should go in a array format.
Third one is I can select single card on click inside on button. That time I need to pass the single card in a save parameter. How can I pass these datas in a Array format. Only selected Datas.
var myApp = angular.module('myApp', []);
myApp.controller('MainCtrl', function($scope) {
$scope.unselectBtn = true;
$scope.selectBtn = false;
$scope.saveBtn = true;
$scope.divs = [1, 2, 3]; // for eample
$scope.containerSelected = $scope.divs.map(val => false);
$scope.buttonVisible = $scope.divs.map(val => true);
$scope.toggleButton = function(e, i) {
console.log('toggleButton')
$scope.containerSelected[i] = true;
if($scope.containerSelected[i] = true){
$scope.saveBtn = false;
}
$scope.buttonVisible[i] = false;
e.stopPropagation();
};
$scope.toggleContainer = function(i) {
if ($scope.containerSelected[i]) {
$scope.containerSelected[i] = false;
$scope.buttonVisible[i] = true;
}
};
$scope.toggleAllButton = function() {
$scope.unselectBtn = false;
$scope.selectBtn = true;
$scope.saveBtn = false;
$scope.containerSelected = $scope.containerSelected.map(val => true);
$scope.buttonVisible = $scope.buttonVisible.map(val => false);
console.log($scope.containerSelected)
}
$scope.toggleUnselectAllBtn = function(){
$scope.unselectBtn = true;
$scope.selectBtn = false;
$scope.saveBtn = true;
$scope.containerSelected = $scope.containerSelected.map(val => true);
$scope.buttonVisible = $scope.buttonVisible.map(val => false);
console.log($scope.containerSelected)
}
$scope.saveData = function(data){
console.log(data);
}
});
#myApp {
width: 100%;
display: -webkit-inline-box;
border: 1px solid black;
margin-top: 55px;
}
.container {
width: 10%;
height: 100px;
border: 1px solid black;
margin: 10%;
}
button.btn.btn-primary {
margin-top: 25%;
margin-left: 40%;
}
.selectedBorder {
border: 3px solid blue;
}
#selectALL {
margin-top: 20px;
}
<div title="Angular Scope" ng-app ng-controller="MainCtrl">
<button id="selectALL" ng-hide="selectBtn" ng-click="toggleAllButton()">Select All</button>
<button id="unselectALL" ng-hide="unselectBtn" ng-click="toggleUnselectAllBtn()">UnSelect All</button>
<button id="save" ng-hide="saveBtn" ng-click="saveData(div)">Save</button>
<div id="myApp">
<div class="container" ng-repeat="div in divs track by $index" ng-class="{ 'selectedBorder': containerSelected[$index] }" ng-click="toggleContainer($index)">
<button id="okBtn" class="btn btn-primary" ng-click="toggleButton($event, $index)" ng-show="buttonVisible[$index]">ok</button>
</div>
</div>
</div>

It looks like the position of the value in the $scope.containerSelected array corresponds to the ID of the div.
For example, if $scope.containerSelected is [true, false, false], then the first div is selected, but the remaining two are not.
With this assumption, you could use the reduce method to create an array that gives the position of all true elements, which would correspond to the div. If the div IDs start at 1, just add 1 to the values in the array.
For example:
let dataToSend = $scope.containerSelected.reduce(function(a, e, i) {
if (e === true)
a.push(i);
// or, if they start at 1, use a.push(i+1)
return a;
}, []);
Updated fiddle: https://jsfiddle.net/jmg157/pfzg4t1n/

Related

Trying to Clone one Element but multiplies items cloned

I am trying to clone elements onclick one time only but multiple items are being cloned when I click continuously multiple times then multiple items created.
I don't understand why multiple items are created continuously. I only want items from the data-id should be appended one time even if I click it should be removed the cloned item. Also when we click appended items they should be removed.
$('.item-save').click(function() {
$(this).toggleClass('productad')
window.localStorage.setItem('test' + this.dataset.id, $(this).hasClass('productad'));
});
$('.item-save').each(function() {
var id = 'test' + this.dataset.id;
if (localStorage.getItem(id) && localStorage.getItem(id) == "true") {
$(this).addClass('productad');
}
});
$('.item-save').click(function() {
var id = this.dataset.id;
$(".item-save").attr("data-id", function() {
var $button = $(this).clone();
$button.appendTo('.item-append');
});
});
.item-save {
position: relative;
display: block;
font-size: 14px;
margin: 5px;
padding: 5px;
background: #a5a5a5;
text-align: center;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div class='item-all'>
<div class='item-save' data-id='123'>Save</div>
<div class='item-save' data-id='124'>Save</div>
<div class='item-save' data-id='125'>Save</div>
<div class='item-save' data-id='126'></div>
</div>
<div class='item-append'></div>
Here is my code JsFiddle Demo
I work with localStorage function to store some value so that is important without removing localStorage is it possible to fix this issue Any help or advice is highly appropriated
Get rid of the attr() function in your second click function.
Change this
$('.item-save').click(function() {
var id = this.dataset.id;
$(".item-save").attr("data-id", function() {
var $button = $(this).clone();
$button.appendTo('.item-append');
});
});
To this
$('.item-save').click(function() {
var $button = $(this).clone();
$button.appendTo('.item-append');
});

Displaying images through series of button clicks

I'm trying to build a website with a very basic functionality. Essentially the website is supposed to contain various buttons and display images based on which series of buttons are clicked. Unfortunately my experience in web development is limited (to non-existent), but I've found some code that works to some extent here on stackoverflow. Building on that, I wanted to alter the code in a way that allows me to achieve the functionality I desire.
Here's how the website is supposed to look like:
As you can notice, the website contains various buttons from A-D and 0-9. The button clicks are logged in the field beneath and once a combination has been put in that matches the name of a file, the image will be displayed.
Here's the code:
$(document).ready(function() {
/**
* Select the buttons.
* The $display and $clickedButtons are just to output
* the values that are stored.
*/
const $buttons = $('.button');
const $display = $('#display');
const $clickedButtons = $('#clicked-buttons');
const $reset = $('#reset');
$reset.on('click', function() {
values = [];
$clickedButtons.text(values);
});
/**
* Array which tracks your clicked buttons.
* If a button is clicked, the value of that button
* should be added to this array. The combination
* of the values will then later represent the key.
*/
var values = [];
/**
* Listen for the click event on all the buttons.
* When clicked, get the value of that clicked button
* and add that to the values array.
* After that the clicked button values will be combined
* to form a single key and check if that key matches
* a combination. If there is a match the content should
* be anything other than undefined.
*/
$buttons.on('click', function() {
// This is the currently clicked button.
const $button = $(this);
// Get the value of the button.
const value = $button.val();
// If there already are 15 previously clicked buttons,
// then empty the array, so we can start a new combination.
if (values.length === 15) {
values = [];
}
// Now add the newly clicked value.
values.push(value);
// This will output the current values in the array.
$clickedButtons.text(values);
// Transform the array into a single string.
// This will be the key to select content.
// ["1", "2", "3"] becomes "123".
const key = values.join('');
// Check if key has a match in the combinations object.
$display.attr('src', 'output/' + key + '.png');
});
});
Now to my problem: The code requires that they combination of buttons is clicked exactly in the order of the name of the image. So for example, inputting A-B-C-1-2-3 will display ABC123.png. For my purpose however, I would need the code to display ABC123.png even if the inputs are 31B2AC or any other combination of these 6 inputs. I've looked into the option of 'sorting' but this creates a problem on the other hand, namely that some of the pictures are named like this e.g. D9B6C4.png so there is no applicable logic like alphabetic or numerical that would be required for a sorting algorithm to function. Every image in the folder has an unique however so when ABC123.png exists, BCA321 cannot.
What I would need the script to do is to parse through the pictures and find the unique picture that contains all letters & numbers that are entered regardless of their order. Is that even possible? How would I go about achieving this?
///////// EDIT ////////
My attempt to add a display, a tracker of clicked buttons and as well as a remove button:
So not really sure why literally nothing is working. Neither the inputs are displayed in the appropriate field nor is a picture being displayed ...
const $buttons = $('.button');
const $display = $('#display');
const $clickedButtons = $('#clicked-buttons');
const $removeButton = $('#remove-button');
const values = [];
var imgs = ["ABC123.png", "1A2B4C.png", "ABC132.png", "123ABC.png"];
function case_insensitive_comp(strA, strB) {
return strA.toLowerCase().localeCompare(strB.toLowerCase());
}
function reSortFiles() {
var all = {};
imgs.forEach(function(a) {
d = a.split(".");
img = d[0].split("");
img = sortStr(img);
img = img.join("");
all[img] ? all[img].push(a) : all[img] = [a];
});
return all;
}
function sortStr(str) {
return str.sort(case_insensitive_comp)
}
function tryCombination() {
// This will output the current values from the array.
$clickedButtons.text(values);
const key = values.join('');
allImages = reSortFiles()
console.log(allImages)
buttons = document.querySelectorAll("button")
clicked = "";
buttons.forEach(function(btn) {
btn.addEventListener("click", function(e) {
clicked += e.target.dataset.value;
clicked_s = sortStr(clicked.split("")).join("")
console.log(clicked, clicked_s)
img = allImages[clicked_s]
if (img) {
console.log("Found: ", img.join(","))
clicked="";
}
});
});
.container {
display: grid;
grid-template-rows: auto auto;
grid-template-columns: 200px 1fr;
grid-gap: 1em;
border: 1px solid #d0d0d0;
background-color: #f7f7f7;
padding: 1em;
border-radius: 5px;
}
.buttons {
grid-area: 1 / 1 / 2 / 3;
}
#display {
grid-area: 2 / 1 / 3 / 2;
width: 200px;
height: 200px;
background-color: #d0d0d0;
border-radius: 5px;
}
#clicked-buttons {
grid-area: 2 / 2 / 3 / 3;
display: block;
background-color: #d0d0d0;
border-radius: 5px;
padding: 1em;
margin: 0;
}
#remove-button {
grid-area: 1 / 2 / 2 / 3;
}
.hidden {
opacity: 0;
visibility: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="buttons">
<button class="button" id="1" value="1" >1</button>
<button class="button" id="2" value="2" >2</button>
<button class="button" id="3" value="3" >3</button>
<button class="button" id="4" value="4" >4</button>
<button class="button" id="5" value="5" >5</button>
<button class="button" id="6" value="6" >6</button>
</div>
<img id="display" class="hidden">
<button id="remove-button">Remove last input</button>
<code id="clicked-buttons"></code>
</div>
Here is my working solution, albeit its kind of hacky.
Have all of your images loaded in an array, just the file names.
Then loop through ALL of those files and create an object with the sorted name as the key and the file name as the value. That way no matter how the images are named, they will have a key like 999XXX.
Then it's just a matter of getting the buttons clicked and sorting its string until that string exists as a key.
var imgs = ["ABC123.png", "1A2B4C.png"];
function case_insensitive_comp(strA, strB) {
return strA.toLowerCase().localeCompare(strB.toLowerCase());
}
function reSortFiles() {
var all = {};
imgs.forEach(function(a) {
d = a.split(".");
img = d[0].split("");
img = sortStr(img);
img = img.join("");
all[img] = a;
});
return all;
}
function sortStr(str) {
return str.sort(case_insensitive_comp)
}
allImages = reSortFiles()
buttons = document.querySelectorAll("button")
clicked = "";
buttons.forEach(function(btn) {
btn.addEventListener("click", function(e) {
clicked += e.target.dataset.value;
clicked = sortStr(clicked.split("")).join("")
img = allImages[clicked]
if (img) {
console.log(img)
}
});
});
<button type="button" data-value="A">A</button>
<button type="button" data-value="B">B</button>
<button type="button" data-value="C">C</button>
<button type="button" data-value="1">1</button>
<button type="button" data-value="2">2</button>
<button type="button" data-value="3">3</button>
Version that allows multiple
var imgs = ["ABC123.png", "1A2B4C.png", "ABC132.png", "123ABC.png"];
function case_insensitive_comp(strA, strB) {
return strA.toLowerCase().localeCompare(strB.toLowerCase());
}
function reSortFiles() {
var all = {};
imgs.forEach(function(a) {
d = a.split(".");
img = d[0].split("");
img = sortStr(img);
img = img.join("");
all[img] ? all[img].push(a) : all[img] = [a];
});
return all;
}
function sortStr(str) {
return str.sort(case_insensitive_comp)
}
allImages = reSortFiles()
console.log(allImages)
buttons = document.querySelectorAll("button")
clicked = "";
buttons.forEach(function(btn) {
btn.addEventListener("click", function(e) {
clicked += e.target.dataset.value;
clicked_s = sortStr(clicked.split("")).join("")
console.log(clicked, clicked_s)
img = allImages[clicked_s]
if (img) {
console.log("Found: ", img.join(","))
clicked="";
}
});
});
<button type="button" data-value="A">A</button>
<button type="button" data-value="B">B</button>
<button type="button" data-value="C">C</button>
<button type="button" data-value="1">1</button>
<button type="button" data-value="2">2</button>
<button type="button" data-value="3">3</button>
<button type="button" data-value="4">4</button>

Can you save multiple separate lists to localStorage?

I'm working on a project that will take user input and store it into a list in localStorage. I want to be able to have three of these to do lists on the page.
I have put the code into three separate columns, however when I try to submit information in them, it seems to be adding the values in all of the columns to one list. I don't every use JS or Jquery, so I have been trying to learn as I go, and I'm stumped. This is the code that I am looking to run in three separate columns.
How do I make sure that the lists are stored in three separate places and also stored separately in localStorage?
var list = JSON.parse(localStorage.getItem("todolist"));
// Checks for to dos in LS, if none starts with empty array
if (!Array.isArray(list)) {
list = [];
}
function putOnPage() {
$("#todo-list").empty(); // empties out the html
var insideList = JSON.parse(localStorage.getItem("todolist"));
if (!Array.isArray(insideList)) {
insideList = [];
}
// todos to page
for (var i = 0; i < insideList.length; i++) {
var p = $("<p>").text(insideList[i]);
var b = $("<button class='delete'>").text("x").attr("data-index", i);
p.prepend(b);
$("#todo-list").prepend(p);
}
}
// rtodos on page load
putOnPage();
$(document).on("click", "button.delete", function() {
var todolist = JSON.parse(localStorage.getItem("todolist"));
var currentIndex = $(this).attr("data-index");
// deletes items
todolist.splice(currentIndex, 1);
list = todolist;
localStorage.setItem("todolist", JSON.stringify(todolist));
putOnPage();
});
$("input[type='submit']").on("click", function(event) {
event.preventDefault();
// changes input to variable and clears input field
var val = $("input[type='text']").val();
$("input[type='text']").val("");
// adds to do to list and local storage
list.push(val);
localStorage.setItem("todolist", JSON.stringify(list));
putOnPage();
});
You can probably go with making the list an array with three object each one containing a separate column from the page, than update or set using something list[0] for list one, list[1] for list 2 and so on.
Or
You can approach it with using three stores in the localstorage one for each column.
JS Fiddle Example -> https://jsfiddle.net/jassMarok/3gcnyamp/18/
// find elements
var banner = $("#banner-message")
var button = $("button")
var testObject = [{
name: "todo-list1",
items: ["Sell", "Buy", "Donate"]
},
{
name: "todo-list2",
items: ["Go", "Run", "Sleep"]
},
{
name: "todo-list3",
items: ["Work", "Program", "Code"]
}
];
// Put the object into storage
localStorage.setItem('testObject', JSON.stringify(testObject));
// handle click and add class
button.on("click", function() {
var lists = $('[id|="list"]');
console.log(lists);
var retrievedObject = JSON.parse(localStorage.getItem('testObject'));
console.log(retrievedObject)
for (i = 0; i < lists.length; i++) {
var $list = lists[i];
var items = retrievedObject[i].items;
for (j = 0; j < items.length; j++) {
console.log(items);
$($list).append('<li>' + items[j] + '</li>');
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#banner-message {
background: #fff;
border-radius: 4px;
padding: 20px;
font-size: 25px;
text-align: center;
transition: all 0.2s;
margin: 0 auto;
width: 300px;
}
button {
background: #0084ff;
border: none;
border-radius: 5px;
padding: 8px 14px;
font-size: 15px;
color: #fff;
}
#banner-message.alt {
background: #0084ff;
color: #fff;
margin-top: 40px;
width: 200px;
}
#banner-message.alt button {
background: #fff;
color: #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="banner-message">
<p>Hello World</p>
<button>Load Data</button>
<hr/>
<h3>
List 1
</h3>
<ul id="list-1"></ul>
<hr/>
<h3>
List 2
</h3>
<ul id="list-2"></ul>
<hr/>
<h3>
List 3
</h3>
<ul id="list-3"></ul>
</div>

How to map JSON Data from an API to a div

I've been working on an app that fetches data from an API and then neatly puts them into card div's. I've written the code for performing the request and getting all the data in JSON (image below), however I can't find a way to keep my code clean and manage the results.
What i want to do is create a div called card for each JSON object (there are 50 in the picture below) and then inside those divs i append span tags with the information.
Here's my current code
xhr.onreadystatechange = () => {
if (xhr.readyState == 4) {
results.style.opacity = 1
let result = xhr.responseText
result = JSON.parse(result)
console.log(result)
Create the function and pass the JSON data to that function and then you need to iterate the loop for the key name results. Then access the each element by using the key name of the array's object. Below is the example code (css not included). More about object
<body>
<div id="container">
</div>
</body>
<script>
xhr.onreadystatechange = () => {
if (xhr.readyState == 4) {
results.style.opacity = 1
let result = xhr.responseText
result = JSON.parse(result)
loadDiv(result);
}
}
function loadDiv(data){
for(var x of data.results){
var div = `<div class="cols">
${x.mal_id}
<img src="${x.url}"/>
</div>
`;
document.getElementById("container").insertAdjacentHTML("beforeend",div);
}
}
You can iterate the object and create divs and spans.
// I expect your results in this variable.
var result = {
results: [{
One: 'div',
Two: 'span'
}]
};
result.results.forEach(data => {
var div = document.createElement('div');
div.id = 'block';
div.className = 'block';
var span = document.createElement('span');
span.className = 'block-2';
div.appendChild(span);
document.getElementsByTagName('body')[0].appendChild(div);
});
.block {
height: 50px;
width: 50px;
border: 1px solid red;
}
.block-2 {
height: 20px;
width: 20px;
border: 1px solid blue;
position: absolute;
}

Adding a div with CSS to DOM

For a project, I am building an app that gets user input, stores it in an array, and displays the input in the DOM. I did the first two parts but I am having trouble displaying it. More specifically, I can't get the CSS to show up.
I have tried .createElement() which creates a new list-item but it does not include CSS. I am starting to think I am completely going about this incorrectly. If you need more information or code let me know.
\\HTML
<div id="boxhold">
<ul>
<li>
<div class="twogrid">
<h1>Fruit Juice</h1>
<p>50</p>
</div>
</li>
</ul>
</div>
\\CSS
#boxhold {
margin: 0 auto;
ul {
list-style-type: none;
padding: 0;
li {
margin: 0 auto;
width: 408px;
height: 75px;
border: 3px solid $prime-color;
h1 {
font-family: $header-font;
font-weight: $header-weight;
font-size: 1em;
}
p {
font-family: $header-font;
font-weight: $header-weight;
}
}
}
}
\\JS
//Get Data
//Empty array for storing
var added = [];
//Get Data
var userInput = function() {
return {
name: document.getElementById('name').value,
amount: document.getElementById('amount').value
}
};
// Store Data
var newSugar = function(){
return added.push(userInput());
}
// New HTML
function newBox() {
var newLi = document.createElement('li');
var newName = document.getElementById('name').value;
var n = document.createTextNode(newName);
newLi.appendChild(n);
var newAmount = document.getElementById('amount').value;
var a = document.createTextNode(newAmount);
newLi.appendChild(a);
var boxhold = document.getElementById('boxhold').getElementsByTagName('ul')[0];
document.body.appendChild(newLi);
};
//Adding stuff
var displayData = (function() {
var addInput = function() {
var data = userInput();
var item = newSugar();
var box = newBox();
//var box = newItem();
};
var addFood = document.getElementById('addFood');
addFood.addEventListener('click', addInput);
document.addEventListener('keypress', function(event) {
if (event.keyCode === 13 || event.which === 13) {
addInput();
}
});
})(userInput, newSugar, newBox);
Welcome to Stack Overflow #nzart 👋
It looks like you're appending the newly created list item to the document's body, which means it will be added as the last element of the page. Your CSS indicates that the styles only apply to list items inside of an unordered list, so this would explain the lack of styles.
The simple fix should be to replace document.body.appendChild(newLi); with boxhold.appendChild(newLi);. I hope this helps!

Categories

Resources