Comparing array results and then unhiding audio elements - javascript

I am trying to compare the the results of 2 arrays, and then make the corresponding elements visible.
I am passing in a list from the controller, and setting the element Id's and Names using the values from the model. I can get the values from the ticked check boxes and these alert correctly, but when I try and get the values from the appropriate audio tags, I get undefined.
<div style="display:none;" name="audioDiv" id="audioDiv">
#foreach (var item in Model)
{
<div class="divclass" value="#item.Name" id="audioDiv" hidden>
<h1> #item.Track - #item.Singer</h1>
<audio controls id="audioPlayer" value="#item.Name">
<source src="~/MP3s/#item.Name" type="audio/mp3" />
</audio>
</div>
}
</div>
function myFunction() {
document.querySelector(".table").style.display = "none";
var audionodes = document.getElementsByTagName('audio').value;
alert(audionodes)
var checkboxes = document.getElementsByName('playlist');
var vals = "";
for (var i = 0, n = checkboxes.length; i < n; i++) {
if (checkboxes[i].checked) {
vals += "," + checkboxes[i].value;
}
}
if (vals) vals = vals.substring(1);
alert(vals);
alert(audionodes)
}
I want to be able to compare the values of 'vals' and 'audionodes' and then un hide the corresponding audio elements. so for example - if the checkbox for luis fonzi - despacito is ticked, on the click of submit, I want that audio element to be visible, and the table I had displaying the 'playlist' information to be hidden.
One array will have the values of the checked boxes - so a list of track names. The second will contain all of the values for every hidden audio element - which is a value for every song. Once they've been compared, it then makes the appropriate audio elements visible.

Well if I understand you right, you are trying to display the audios based on the checkbox selection, in order to do that you need to check 2 arrays and display them, I converted html collection to array and iterated over them, you can check my comments and implement it in your own.
document.querySelector(".table").style.display = "none";
//getting all audio controls with element and its value
var audionodes = Array.from(document.getElementsByTagName('audio')).map(a => {
return {
element: a,
value: a.getAttribute("value")
}
});
//getting all the checkboxes checked
var checkboxes = Array.from(document.getElementsByTagName('input')).reduce((prev, next) => {
if (next.checked) {
prev.push(next.getAttribute("value"))
}
return prev;
}, []);
//filtering the audio control values with checkboxes and displaying them.
audionodes.filter(a => checkboxes.indexOf(a.value) >= 0).forEach(a => {
a.element.style.display = "block";
});
audio {
display: none
}
<table class="table">
<audio value="luis fonzi - despacito">test</audio>
</table>
<input value="luis fonzi - despacito" name="playlist" checked type="checkbox">
<input value="luis fonzi - despacit1o" name="playlist1" type="checkbox">

Related

Clicking images to pass the names in a URL string

I have a low level knowledge of javascript and am trying to create a basic image based quiz that passes data back to a search page for local businesses.
Each image would have it's own "tag" as the image ID that relates to one of the options in the search. Ie. Outdoor, Ballroom, Barn, Garden, etc.
Upon submission, it would send the selected image ID's data to www.sitename/search/?_characteristics=TAG1,TAG2,TAG3
That search page will filter the business listings by the tags. Currently it's search function filters the businesses with the following format: website.com/search/?_characteristics=TAG1%2CTAG2
The HTML would look like this:
<img src="http://website.com/image1" id="TAG1"/>
<br/>
<img src="http://website.com/image2" id="TAG2"/>
<form action="https://website.com/business/?&_characteristics=TAG1, TAG2, TAG3" method="get">
<input type="submit" value="View Selected"/>
What you want is the following
Register a click handler on your images to
Capture ids into a collection (array or Set)
Toggle the "selected" class
Register a submit handler on the form to inject an hidden input element, transforming the tag collection into a CSV and setting it to the input value
const form = document.querySelector("form")
const tags = new Set()
document.querySelectorAll("img[id]").forEach(img => {
img.addEventListener("click", () => {
const selected = img.classList.toggle("selected")
tags[selected ? "add" : "delete"](img.id)
})
})
form.addEventListener("submit", (e) => {
const input = Object.assign(document.createElement("input"), {
name: "_characteristics",
type: "hidden",
value: ([...tags]).join(",")
})
form.append(input)
// this is just for the example, omit the following
e.preventDefault()
console.log(`Submitting to ${form.action}?${new URLSearchParams(new FormData(form))}`)
input.remove()
})
img { border: 2px solid grey; }
img.selected { border-color: red; }
<img src="https://picsum.photos/100" id="TAG1"/>
<br/>
<img src="https://picsum.photos/100" id="TAG2"/>
<form action="https://website.com/business/" method="get">
<input type="submit" value="View Selected"/>
</form>
I'm not sure how you want to get the selected img, but here's a way to do it:
Add the class active to the selected img
When clicking on the button, get the id and push it to the output array
Create the link of the tags (id's)
Read the comments below for the detailed explanation.
// Get the images and the submit button
let images = document.querySelectorAll('img');
let btn = document.getElementById('btn');
// Array to hold the tags
let output = [];
// variable to hold the link
let link = '';
// Add the class active to the selected images
for(let i = 0; i < images.length; i++) {
// For each image onclick:
images[i].addEventListener('click', () => {
// Toggle the `active` class on click
images[i].classList.toggle('active');
});
}
// Button onclick:
btn.addEventListener('click', () => {
for(let i = 0; i < images.length; i++) {
// Get the images with the `active` class and push the id to the output array
images[i].classList.contains('active') ? output.push(images[i].getAttribute('id')) : '';
}
// Remove duplicates if found
let uniq = [...new Set(output)];
// Create the link by adding the tags to the string (output values)
link = `www.sitename/search/?_characteristics=${uniq.join(',')}`;
// Print the link to the console
console.log(link);
});
img.active {
box-shadow: 0 0 1px 1px #121212;
}
5. <img src="http://www.gravatar.com/avatar/e1122386990776c6c39a08e9f5fe5648?s=128&d=identicon&r=PG" id="air-conditioned"/>
<br/>
6. <img src="http://www.gravatar.com/avatar/e1122386990776c6c39a08e9f5fe5648?s=128&d=identicon&r=PG" id="outdoor"/>
<br/>
7. <img src="http://www.gravatar.com/avatar/e1122386990776c6c39a08e9f5fe5648?s=128&d=identicon&r=PG" id="indoor"/>
<br/>
8. <img src="http://www.gravatar.com/avatar/e1122386990776c6c39a08e9f5fe5648?s=128&d=identicon&r=PG" id="house"/>
<br/>
<button id="btn">Submit</button>

dynamic link based on checkbox values => Issue when deselecting the checkbox the url value multiplies

I am trying to generate link on the button when multiple Checkbox is clicked based on the value. I have used the below link and it's working fine and I am able to generate link.
Create a dynamic link based on checkbox values
The issue is that when I select the checkbox for the first time it generates a link to /collections/all/blue+green but when I again select/deselect the different value its duplicates and ADDs the values with old Link → to collections/all/blue+green+blue+green
For Live Issue check on mobile View Click on filter on bottom => https://faaya-gifting.myshopify.com/collections/all
$("input[type=checkbox]").on("change", function() {
var arr = []
$(":checkbox").each(function() {
if ($(this).is(":checked")) {
arr.push($(this).val())
}
})
var vals = arr.join(",")
var str = "http://example.com/?subject=Products&checked=" + vals
console.log(str);
if (vals.length > 0) {
$('.link').html($('<a>', {
href: str,
text: str
}));
} else {
$('.link').html('');
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<input type="checkbox" name="selected" value="Blue" class="products"> Blue<br>
<input type="checkbox" name="selected" value="Green" class="products"> Green<br>
<input type="checkbox" name="selected" value="Purple" class="products"> Purple
<br>
<span class="link"></span>
For Live Issue check on mobile View Click on filter on bottom => https://faaya-gifting.myshopify.com/collections/all
I see what's going on now. What's causing the duplicate is actually multiple checkboxes having the checked value.
If you run this code in your console, you should see that you have twice of the item checked as its length:
// Run this in your browser console
$('input[type=checkbox]:checked').length
For example, if I have Wood and Metal checked and clicked Apply, running the code above gives length of 4 instead of just 2. Meaning, you have a duplicate checkbox input for each filter hidden somewhere in your code. I have verified this.
As options, you can:
Try to remove the duplicate checkbox input – Best Option; or
Add class to narrow down your selector to just one of the checkbox input containers.
Here's a screenshare of what's going on: https://www.loom.com/share/2f7880ec3435427a8378050c7bf6a6ea
UPDATED 2020/06/09:
If there's actually no way to modify how your filters are displayed, or add classes to narrow things down, we can opt for an ad hoc solution which is to actually, just remove the duplicates:
// get all your values
var arr = []
$(":checkbox").each(function() {
if ($(this).is(":checked")) {
arr.push($(this).val().toLowerCase())
}
})
// removes duplicates
var set = new Set(arr)
// convert to array and join
var vals = [...set].join(",")
I am bit bad in jquery. Am I doing right?
Should I just add the script which I have written below
$("input[type=checkbox]").on("change", function() {
var arr = []
$(":checkbox").each(function() {
if ($(this).is(":checked")) {
arr.push($(this).val().toLowerCase())
}
})
// removes duplicates
var set = new Set(arr)
// convert to array and join
var vals = [...set].join(",")
var str = "http://example.com/?subject=Products&checked=" + vals
console.log(str);
if (vals.length > 0) {
$('.link').html($('<a>', {
href: str,
text: str
}));
} else {
$('.link').html('');
}
})
Am I right?
Or should I add any values on var set = new Set(arr) or var vals = [...set]
Thank you for you help Algef

Store values from dynamically generated text boxes into array

I'm creating a Time table generating website as a part of my project and I am stuck at one point.
Using for loop, I am generating user selected text boxes for subjects and faculties. Now the problem is that I cannot get the values of those dynamically generated text boxes. I want to get the values and store it into array so that I can then later on store it to database
If I am using localstorage, then it sometimes shows NaN or undefined. Please help me out.
Following is my Jquery code
$.fn.CreateDynamicTextBoxes = function()
{
$('#DynamicTextBoxContainer, #DynamicTextBoxContainer2').css('display','block');
InputtedValue = $('#SemesterSubjectsSelection').val();
SubjectsNames = [];
for (i = 0; i < InputtedValue; i++)
{
TextBoxContainer1 = $('#DynamicTextBoxContainer');
TextBoxContainer2 = $('#DynamicTextBoxContainer2');
$('<input type="text" class="InputBoxes" id="SubjectTextBoxes'+i+'" placeholder="Subject '+i+' Name" style="margin:5px;" value=""><br>').appendTo(TextBoxContainer1);
$('<input type="text" class="InputBoxes" id="FacultyTextBoxes'+i+'" placeholder="Subject '+i+' Faculty Name" style="margin:5px;" value=""><br>').appendTo(TextBoxContainer2);
SubjectsNames['SubjectTextBoxes'+i];
}
$('#DynamicTextBoxContainer, #UnusedContainer, #DynamicTextBoxContainer2').css('border-top','1px solid #DDD');
}
$.fn.CreateTimeTable = function()
{
for (x = 0; x < i; x++)
{
localStorage.setItem("Main"+x, +SubjectsNames[i]);
}
}
I am also posting screenshot for better understanding
I understand you create 2 text boxes for each subject, one for subject, and second one for faculty. And you want it as a jQuery plugin.
First of all, I think you should create single plugin instead of two, and expose what you need from the plugin.
You should avoid global variables, right now you have InputtedValue, i, SubjectsNames, etc. declared as a global variables, and I believe you should not do that, but keep these variables inside you plugin and expose only what you really need.
You declare your SubjectNames, but later in first for loop you try to access its properties, and actually do nothing with this. In second for loop you try to access it as an array, but it's empty, as you did not assign any values in it.
Take a look at the snippet I created. I do not play much with jQuery, and especially with custom plugins, so the code is not perfect and can be optimized, but I believe it shows the idea. I pass some selectors as in configuration object to make it more reusable. I added 2 buttons to make it more "playable", but you can change it as you prefer. Prepare button creates your dynamic text boxes, and button Generate takes their values and "print" them in result div. generate method is exposed from the plugin to take the values outside the plugin, so you can do it whatever you want with them (e.g. store them in local storage).
$(function() {
$.fn.timeTables = function(config) {
// prepare variables with jQuery objects, based on selectors provided in config object
var numberOfSubjectsTextBox = $(config.numberOfSubjects);
var subjectsDiv = $(config.subjects);
var facultiesDiv = $(config.faculties);
var prepareButton = $(config.prepareButton);
var numberOfSubjects = 0;
prepareButton.click(function() {
// read number of subjects from the textbox - some validation should be added here
numberOfSubjects = +numberOfSubjectsTextBox.val();
// clear subjects and faculties div from any text boxes there
subjectsDiv.empty();
facultiesDiv.empty();
// create new text boxes for each subject and append them to proper div
// TODO: these inputs could be stored in arrays and used later
for (var i = 0; i < numberOfSubjects; i++) {
$('<input type="text" placeholder="Subject ' + i + '" />').appendTo(subjectsDiv);
$('<input type="text" placeholder="Faculty ' + i + '" />').appendTo(facultiesDiv);
}
});
function generate() {
// prepare result array
var result = [];
// get all text boxes from subjects and faculties divs
var subjectTextBoxes = subjectsDiv.find('input');
var facultiesTextBoxes = facultiesDiv.find('input');
// read subject and faculty for each subject - numberOfSubjects variable stores proper value
for (var i = 0; i < numberOfSubjects; i++) {
result.push({
subject: $(subjectTextBoxes[i]).val(),
faculty: $(facultiesTextBoxes[i]).val()
});
}
return result;
}
// expose generate function outside the plugin
return {
generate: generate
};
};
var tt = $('#container').timeTables({
numberOfSubjects: '#numberOfSubjects',
subjects: '#subjects',
faculties: '#faculties',
prepareButton: '#prepare'
});
$('#generate').click(function() {
// generate result and 'print' it to result div
var times = tt.generate();
var result = $('#result');
result.empty();
for (var i = 0; i < times.length; i++) {
$('<div>' + times[i].subject + ': ' + times[i].faculty + '</div>').appendTo(result);
}
});
});
#content div {
float: left;
}
#content div input {
display: block;
}
#footer {
clear: both;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
<div id="header">
<input type="text" id="numberOfSubjects" placeholder="Number of subjects" />
<button id="prepare">
Prepare
</button>
</div>
<div id="content">
<div id="subjects">
</div>
<div id="faculties">
</div>
</div>
</div>
<div id="footer">
<button id="generate">Generate</button>
<div id="result">
</div>
</div>

In Jquery take a different values from single text box id

I am using Data Table in jquery. So i passed one input type text box and passed the single id. This data table will take a multiple text box. i will enter values manually and pass it into the controller. I want to take one or more text box values as an array..
The following image is the exact view of my data table.
I have marked red color in one place. the three text boxes are in same id but different values. how to bind that?
function UpdateAmount() {debugger;
var id = "";
var count = 0;
$("input:checkbox[name=che]:checked").each(function () {
if (count == 0) {
id = $(this).val();
var amount= $('#Amount').val();
}
else {
id += "," + $(this).val();
amount+="," + $(this).val(); // if i give this i am getting the first text box value only.
}
count = count + 1;
});
if (count == 0) {
alert("Please select atleast one record to update");
return false;
}
Really stuck to find out the solution... I want to get the all text box values ?
An Id can only be used once; use a class, then when you reference the class(es), you can loop through them.
<input class="getValues" />
<input class="getValues" />
<input class="getValues" />
Then, reference as ...
$(".getValues")
Loop through as ...
var allValues = [];
var obs = $(".getValues");
for (var i=0,len=obs.length; i<len; i++) {
allValues.push($(obs[i]).val());
}
... and you now have an array of the values.
You could also use the jQuery .each functionality.
var allValues = [];
var obs = $(".getValues");
obs.each(function(index, value) {
allValues.push(value);
}
So, the fundamental rule is that you must not have duplicate IDs. Hence, use classes. So, in your example, replace the IDs of those text boxes with classes, something like:
<input class="amount" type="text" />
Then, try the below code.
function UpdateAmount() {
debugger;
var amount = [];
$("input:checkbox[name=che]:checked").each(function () {
var $row = $(this).closest("tr");
var inputVal = $row.find(".amount").val();
amount.push(inputVal);
});
console.log (amount); // an array of values
console.log (amount.join(", ")); // a comma separated string of values
if (!amount.length) {
alert("Please select atleast one record to update");
return false;
}
}
See if that works and I will then add some details as to what the code does.
First if you have all the textbox in a div then you get all the textbox value using children function like this
function GetTextBoxValueOne() {
$("#divAllTextBox").children("input:text").each(function () {
alert($(this).val());
});
}
Now another way is you can give a class name to those textboxes which value you need and get that control with class name like this,
function GetTextBoxValueTwo() {
$(".text-box").each(function () {
alert($(this).val());
});
}

Moving objects between two arrays

I have two lists formed from an array containing objects.
I'm trying to move objects from one list to the other and vice versa.
Controller:
spApp.controller('userCtrl',
function userCtrl($scope,userService,groupService){
//Generate list of all users on the SiteCollection
$scope.users = userService.getUsers();
//array of objects selected through the dom
$scope.selectedAvailableGroups;
$scope.selectedAssignedGroups;
//array of objects the user actually belongs to
$scope.availableGroups;
$scope.assignedGroups;
//Generate all groups on the site
$scope.groups = groupService.getGroups();
//Boolean used to disable add/remove buttons
$scope.selectedUser = false;
//Take the selectedAvailableGroups, add user to those groups
//so push objects to "assignedGroups" array and remove from "avaiableGroups" array
$scope.addUserToGroup = function (){
userService.addUserToGroup($scope.selectedUser, $scope.selectedAvailableGroups, $scope.assignedGroups, $scope.availableGroups)
};
}
);
Service:
spApp.factory('userService', function(){
var addUserToGroup = function (selectedUser, selectedAvailableGroups, assignedGroups, availableGroups) {
var addPromise = [];
var selectLength = selectedAvailableGroups.length;
//Add user to selected groups on server
for (var i = 0; i < selectLength; i++) {
addPromise[i] = $().SPServices({
operation: "AddUserToGroup",
groupName: selectedAvailableGroups[i].name,
userLoginName: selectedUser.domain
});
};
//when all users added, update dom
$.when.apply($,addPromise).done(function (){
for (var i = 0; i < selectLength; i++) {
assignedGroups.push(selectedAvailableGroups[i]);
availableGroups.pop(selectedAvailableGroups[i]);
};
//alert(selectedUser.name + " added to: " + JSON.stringify(selectedAvailableGroups));
});
}
}
Object:
[{
id: 85,
name: Dev,
Description:,
owner: 70,
OwnerIsUser: True
}]
HTML:
<div>
<label for="entityAvailable">Available Groups</label>
<select id="entityAvailable" multiple
ng-model="selectedAvailableGroups"
ng-options="g.name for g in availableGroups | orderBy:'name'">
</select>
</div>
<div id="moveButtons" >
<button type="button" ng-disabled="!selectedUser" ng-click="addUserToGroup()">Add User</button>
<button type="button" ng-disabled="!selectedUser" ng-click="removeUserFromGroup()">Remove</button>
</div>
<div>
<label for="entityAssigned">Assigned Groups</label>
<select id="entityAssigned" multiple
ng-model="selectedAssignedGroups"
ng-options="g.name for g in assignedGroups | orderBy:'name'">
</select>
</div>
Right now, the push into assigned groups works but only updates when I click on something else or in the list, not really dynamically. But the biggest issue is the .pop() which I don't think works as intended.
$.when.apply($,addPromise).done() seems not to be angular api or synchronous. So angular is not aware of your changes. You must wrap your code inside a $scope.$apply call:
$scope.$apply(function(){
for (var i = 0; i < selectLength; i++) {
assignedGroups.push(selectedAvailableGroups[i]);
availableGroups.pop(selectedAvailableGroups[i]);
};
});
If you click on something, a $digest loop will happen and you will see your changes.
Your pop did not work because Array.pop only removes the last element. I guess that is not what you want. If you want to remove a specific element you should use Array.splice(),

Categories

Resources