<script>
//<body>
//<div class="prod"></div>
//<div class="details"></div>
//</body>
const product=document.querySelector(".prod");
var ourRequest=new XMLHttpRequest();
ourRequest.open('GET','http://inec.sg/assignment/retrieve_records.php');
ourRequest.onload=function(){
var data=JSON.parse(ourRequest.responseText);
renderHTML(data);
};
ourRequest.send();
function renderHTML(data){
for(var i=0;i<data.songs.length;i++){
product.innerHTML+=`
<div><img src="${data.songs[i].image}" height="200px"></div>
<div><h2>${data.songs[i].name}</h2></div>
<div><h2>$${data.songs[i].price}</h2></div>
<button id="">Details</button>
`;
}
}
//how do i display prod details when click on button? Able to hide the prod listing div, show the details in details div?
// details eg. data.songs.image, data.songs.brand, data.songs.style, data.songs.discount, data.songs.price
</script>
How do I display prod details when click on button? Able to hide the product listing div, show the details in details div?
Show these in details:
data.songs.image, data.songs.brand, data.songs.style, data.songs.discount, data.songs.price
This is what I came up with:
<button class="load">Load List</button>
<button class="hide">Hide List</button>
<div class="prod"></div>
<div class="details"></div>
<script>
const product = document.querySelector(".prod");
const details = document.querySelector(".details");
const loadBtn = document.querySelector(".load");
const hideBtn = document.querySelector(".hide");
loadBtn.addEventListener("click", () => { // on click of load button
// send request to get data
var ourRequest = new XMLHttpRequest();
ourRequest.open(
'GET',
'http://inec.sg/assignment/retrieve_records.php'
);
ourRequest.onload = function () {
var data = JSON.parse(ourRequest.responseText);
renderHTML(data);
};
ourRequest.send();
function renderHTML(data) {
product.innerHTML = ""; // empty product element
for (var i = 0; i < data.songs.length; i++) {
product.innerHTML += `
<div><img src="${data.songs[i].image}" height="200px"></div>
<div><h2>${data.songs[i].name}</h2></div>
<div><h2>$${data.songs[i].price}</h2></div>
<button data-index="${i}" class="detailsBtn">Details</button>
`; // data-index represents the index of the item in the songs array
}
let detailsBtns = document.querySelectorAll(".detailsBtn"); // get button element(s) previously created
for (var i = 0; i < detailsBtns.length; i++) {
let detailsBtn = detailsBtns[i];
detailsBtn.addEventListener("click", () => { // add on click event for individual details btn
// load details
let index = detailsBtn.dataset.index; // get index of song item
let song = data.songs[index];
details.innerHTML = `<h2>${song.image}</h2><h2>${song.brand}</h2><h2>${song.style}</h2><h2>${song.discount}</h2><h2>${song.price}</h2>`;
});
}
}
});
hideBtn.addEventListener("click", () => { // hide details when hide details button is clicked
product.innerHTML = ""; // empty product element
details.innerHTML = ""; // empty details element
});
</script>
First I declared and assigned common elements like product, details, hideBtn, and loadBtn.
I used the EventTarget.addEventListener() function to bind click events to loadBtn, hideBtn, and detailsBtn .
I used arrow functions for the callback functions of the events, but ES5 functions could certainly be used.
I used the HTMLElement.dataset attribute to link a song index to each product, so I can link the HTML of the product item(s) to their corresponding JS event functionality.
There are many other ways this could be done, but this is how I solved the problem.
Related
How do I create a dynamic dependent dropdown list in Google AppsScript? What I want to achieve is, when I choose PH in order type, the product selection dropdown should have ['PH-Test Product 1', 'PH-Test Product 2', 'PH-Test Product 3'] options. And when I choose EC it should have ['EC-Test Product 1', 'EC-Test Product 2', 'EC-Test Product 3'].
Here's my code-
form.html
<head>
<base target="_top">
<?!= include('css_script'); ?>
</head>
<body>
<div class="container">
<div class = "row">
<h1>A Sample Form</h1>
</div>
<div id="productsection"></div>
<div class = "row">
<button id="addproduct">Add Product</button>
</div> <!-- end of row -->
</div>
<?!= include('js_script'); ?>
</body>
js_script.html
<script>
let counter = 0;
const orderTypeList = ["PH", "EC"];
const optionListPH = ["PH-Test Product 1", "PH-Test Product 2", "PH-Test Product 3"];
const optionListEC = ["EC-Test Product 1", "EC-Test Product 2", "EC-Test Product 3"];
document.getElementById("addproduct").addEventListener("click", addInputField);
function addInputField(){
counter++;
// creates a new div of class row
const newDivElem = createElementTemplate('div', `row${counter}`, 'row');
// creates a new select tag for order type dropdown
const newOrderTypeSelectElem = createElementTemplate('select', `ordertype${counter}`);
// function that populates the dropdown for products and is inserted to the above "ordertypeX" select tag
createOptionsElem(newOrderTypeSelectElem, orderTypeList);
// creates a new select tag for product dropdown
const newProductSelectElem = createElementTemplate('select', `product${counter}`);
// Code to switch options depending on ordertype
//------------------------- Does Not Work --------------------------
if(document.getElementById(`ordertype${counter}`).value === 'PH'){
const optionList = optionListPH;
}else{
const optionList = optionListEC;
}
//------------------------------------------------------------------
// generates the content of the dropdown for products and is inserted to the above "productX" select tag
createOptionsElem(newProductSelectElem, optionList);
newDivElem.appendChild(newOrderTypeSelectElem);
newDivElem.appendChild(newProductSelectElem);
// Finally, appends the newly created div tag to the productSection tag.
document.getElementById('productsection').appendChild(newDivElem);
}
function createOptionsElem(selectTag, optionsArr){
const newDefaultOptionTag = document.createElement('option');
newDefaultOptionTag.value = "";
// newDefaultOptionTag.select = false;
newDefaultOptionTag.textContent="Choose your option";
for(let i in optionsArr){
const newOptionTag = document.createElement('option');
newOptionTag.textContent = optionsArr[i];
newOptionTag.value = optionsArr[i];
// Inserts the option tag in select tag
selectTag.appendChild(newOptionTag);
}
}
// function to create a new element
function createElementTemplate(tagType, idVal, className){
const newElement = document.createElement(tagType);
if(idVal !== undefined)
newElement.id = idVal;
if(className !== undefined)
newElement.classList.add(className);
return newElement;
}
</script>
css_script.html
<style>
.row{
margin-top: 5px;
margin-bottom: 5px;
}
</style>
Code.gs
function doGet(e) {
Logger.log(e);
return HtmlService.createTemplateFromFile('form_basic').evaluate();
}
function include(fileName){
return HtmlService.createHtmlOutputFromFile(fileName).getContent();
}
Modification points:
In your script, when a button is clicked, 2 dropdown lists are created. By this, at the following script,
if(document.getElementById(`ordertype${counter}`).value === 'PH'){
const optionList = optionListPH;
}else{
const optionList = optionListEC;
}
in the case of your script, optionListPH is always used to the 1st dropdown list.
And, when you want to change the 2nd dropdown list by changing the 1st dropdown list, it is required to add more script for checking it.
When these points are reflected in your script, how about the following modification?
From:
// Code to switch options depending on ordertype
//------------------------- Does Not Work --------------------------
if(document.getElementById(`ordertype${counter}`).value === 'PH'){
const optionList = optionListPH;
}else{
const optionList = optionListEC;
}
//------------------------------------------------------------------
// generates the content of the dropdown for products and is inserted to the above "productX" select tag
createOptionsElem(newProductSelectElem, optionList);
newDivElem.appendChild(newOrderTypeSelectElem);
newDivElem.appendChild(newProductSelectElem);
// Finally, appends the newly created div tag to the productSection tag.
document.getElementById('productsection').appendChild(newDivElem);
To:
// Code to switch options depending on ordertype
//------------------------- Does Not Work --------------------------
const optionList = optionListPH; // Modified
//------------------------------------------------------------------
// generates the content of the dropdown for products and is inserted to the above "productX" select tag
createOptionsElem(newProductSelectElem, optionList);
newDivElem.appendChild(newOrderTypeSelectElem);
newDivElem.appendChild(newProductSelectElem);
// Finally, appends the newly created div tag to the productSection tag.
document.getElementById('productsection').appendChild(newDivElem);
// I added the below script.
newOrderTypeSelectElem.addEventListener("change", function() {
newProductSelectElem.innerHTML = "";
createOptionsElem(newProductSelectElem, this.value === 'PH' ? optionListPH : optionListEC);
});
When this modification is reflected in your script, when a button is clicked, 2 dropdown lists are created. And, when 1st dropdown list is changed, the 2nd dropdown list is refreshed with new values.
Note:
This modification is for your showing script. When you change your script, this script might not be able to be used. Please be careful about this.
Why when you are searching for something else is deleting the previous contents ?For example first you search for egg and show the contents but then when you search for beef the program deletes the egg and shows only beef.Code :
const searchBtn = document.getElementById('search-btn');
const mealList = document.getElementById('meal');
const mealDetailsContent = document.querySelector('.meal-details-content');
const recipeCloseBtn = document.getElementById('recipe-close-btn');
// event listeners
searchBtn.addEventListener('click', getMealList);
mealList.addEventListener('click', getMealRecipe);
recipeCloseBtn.addEventListener('click', () => {
mealDetailsContent.parentElement.classList.remove('showRecipe');
});
// get meal list that matches with the ingredients
function getMealList(){
let searchInputTxt = document.getElementById('search-input').value.trim();
fetch(`https://www.themealdb.com/api/json/v1/1/filter.php?i=${searchInputTxt}`)
.then(response => response.json())
.then(data => {
let html = "";
if(data.meals){
data.meals.forEach(meal => {
html += `
<div class = "meal-item" data-id = "${meal.idMeal}">
<div class = "meal-img">
<img src = "${meal.strMealThumb}" alt = "food">
</div>
<div class = "meal-name">
<h3>${meal.strMeal}</h3>
Get Recipe
</div>
</div>
`;
});
mealList.classList.remove('notFound');
} else{
html = "Sorry, we didn't find any meal!";
mealList.classList.add('notFound');
}
mealList.innerHTML = html;
});
}
It's because you are replacing the contents in the mealList element every time.
A simple workaround would be to retrieve the the innerHTML values before you update it.
Something like
let html = mealList.innerHTML;
rather than starting off empty every time you call the function should do the trick.
I have a list of user cards. That card contains add and remove button.
I want to remove that card from list of card when I click at remove button.
Code is similar to following:
// function to generate card
function generateUserCard(id) {
return `
<div class="user-card" id="${id}">
<button data-id="${id}" class="add" >Add</button>
<button data-id="${id}" class="remove" >Remove</button>
</div>
`;
}
// function to generate list of user
function generateUsers(users) {
const userGrid = $("#user-grid");
for(let user of users) {
const userCard = generateUserCard(user.id);
userGrid.append(userCard);
// adding event listeners
$(`[data-id=${user.id}]`).on("click", function() {
// I did something like this
(`#${user.id}`).remove(); // But this didn't work
})
}
}
Please help!
There are several issues in the logic used in your click event callback:
The variable id is not accessible in the callback. A quick fix will be to fix the reference so that you are using user.id in the selector instead. Also, you can simply remove it by ID without needing to search for it inside its parent element, since it is unique.
Your selector [data-id]=${user.id} is syntacically incorrect. I suppose you meant [data-id=${user.id}]
You should be using .remove() to remove a node
A quick fix will look like this:
$(`button[data-id=${user.id}].remove`).on("click", function() {
$(`#${user.id}`).remove();
});
See proof-of-concept below:
function generateUserCard(id) {
return `
<div class="user-card" id="${id}">
User ID: ${id}
<button data-id="${id}" class="add" >Add</button>
<button data-id="${id}" class="remove" >Remove</button>
</div>
`;
}
function generateUsers(users) {
const userGrid = $("#user-grid");
for (let user of users) {
const userCard = generateUserCard(user.id);
userGrid.append(userCard);
$(`button[data-id=${user.id}].remove`).on("click", function() {
$(`#${user.id}`).remove();
})
}
}
// For demo only
let i = 0;
$('#btn').on('click', function() {
const userArray = [];
for (let j = 0; j < 3; j++) {
i++;
userArray.push({ id: i });
}
generateUsers(userArray);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn">Generate users</button>
<div id="user-grid"></div>
However, an improvement to your code will be to avoid adding new click event listeners to all your newly appended elements. You can simply listen to the click event bubbling up to a parent that is already present at runtime (e.g. #user-grid), and you can bind it outside of your generateUsers function:
$('#user-grid').on('click', 'button.add, button.remove', function() {
const id = $(this).attr('data-id');
$(`#${id}`).remove();
});
See proof-of-concept below:
function generateUserCard(id) {
return `
<div class="user-card" id="${id}">
User ID: ${id}
<button data-id="${id}" class="add" >Add</button>
<button data-id="${id}" class="remove" >Remove</button>
</div>
`;
}
function generateUsers(users) {
const userGrid = $("#user-grid");
for (let user of users) {
const userCard = generateUserCard(user.id);
userGrid.append(userCard);
}
}
// Listen to event bubbling instead!
$('#user-grid').on('click', 'button.remove', function() {
const id = $(this).attr('data-id');
$(`#${id}`).remove();
});
// For demo only
let i = 0;
$('#btn').on('click', function() {
const userArray = [];
for (let j = 0; j < 3; j++) {
i++;
userArray.push({
id: i
});
}
generateUsers(userArray);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn">Generate users</button>
<div id="user-grid"></div>
So I am trying to make a flashcards website, where users can add, edit, and delete flashcards. There are two cards - front and back. The user can already add words, but cannot edit or delete them. For the purposes of this question I will use an example array:
var flashcards = [["Uomo", "Man"],["Donna", "Woman"],["Ragazzo", "Boy"]]
But I would like a more user-friendly way to edit the flashcards, preferably using a table like this:
<table>
<tr>
<th>Front</th>
<th>Back</th>
</tr>
<tr>
<td><input type="text" name="flashcard" value="Uomo"> </td>
<td><input type="text" name="flashcard" value="Man"></td>
</tr>
<tr>
<td><input type="text" name="flashcard" value="Donna"></td>
<td><input type="text" name="flashcard" value="Woman"></td>
</tr>
<tr>
<td><input type="text" name="flashcard" value="Ragazzo"></td>
<td><input type="text" name="flashcard" value="Boy"></td>
</tr>
</table>
<button type="button">Add more</button>
<br>
<button type="button">Save changes</button>
So they can update their flashcards editing the input fields, or clicking "add more" and it creating a new row. Clicking "save changes" updates the array to the content of the table.
I don't mind it not being a HTML table per se, but something that is easy to edit for the user.
I just cannot figure out the best way to approach this. Any advice?
I already recommended VueJS - it really is a pretty good tool for this problem. Regardless, I have typed up a basic solution using vanilla JavaScript. For the editing part it uses the contenteditable HTML attribute which allows the end-user to double click an element and change it's textContent.
The html display is basic so you can change it however to fit your needs
<div id=style="width: 100%;">
<ul id="table" style="list-style-type: none; display: inline-block;">
</ul>
</div>
<script>
var flashcards = [["Uomo", "Man"],["Donna", "Woman"],["Ragazzo", "Boy"]];
var displayedCard = []; //Using a parallel array to keep track of which side is shown
for(var i = 0; i < flashcards.length; i++){
displayedCard.push(0);
}
function renderFlashcardTable(){ //This will do the initial rendering of the table
let ulTable = document.getElementById("table");
for(var i = 0; i < flashcards.length; i++){
let card = flashcards[i];
let indexOfSideShown = displayedCard[i];
let li = document.createElement("li");
let cardValueSpan = document.createElement("span");
cardValueSpan.innerHTML = card[indexOfSideShown]; //Get the value of the side of the card that is shown
cardValueSpan.setAttribute("contenteditable", "true");
cardValueSpan.oninput = function(e){ //This method gets called when the user de-selects the element they have been editing
let li = this.parentElement;
let sideIndex = parseInt(li.getAttribute("side-index"));
card[sideIndex] = this.textContent;
}
li.appendChild(cardValueSpan);
li.appendChild(getFlipSidesButton(li));
li.setAttribute("side-index", indexOfSideShown);
li.setAttribute("card-index", i);
ulTable.appendChild(li);
}
}
function getFlipSidesButton(listItem){//This is generated for each card and when clicked it "flips the switch"
let btn = document.createElement("button");
btn.innerHTML = "Flip card";
btn.onclick = function(e){
let card = flashcards[listItem.getAttribute("card-index")];
let index = parseInt(listItem.getAttribute("side-index"));
let nextSide = (index == 1) ? 0 : 1;
listItem.setAttribute("side-index", nextSide);
listItem.children[0].innerHTML = card[nextSide];
}
return btn;
}
renderFlashcardTable();
</script>
I've put together a working sample using pure native javascript with a data-driven approach. You can have a look and understand the way how data should be manipulated and worked with in large Js application.
The point here is to isolate the data and logic as much as possible.
Hope this help.
Codepen: https://codepen.io/DieByMacro/pen/rgQBPZ
(function() {
/**
* Default value for Front and Back
*/
const DEFAULT = {
front: '',
back: '',
}
/**
* Class Card: using for holding value of front and back.
* As well as having `update` method to handle new value
* from input itself.
*/
class Card {
constructor({front, back, id} = {}) {
this.front = front || DEFAULT.front;
this.back = back || DEFAULT.back;
this.id = id;
}
update = (side, value) => this[side] = value;
}
/**
* Table Class: handle rendering data and update new value
* according to the instance of Card.
*/
class Table {
constructor() {
this.init();
}
/** Render basic table and heading of table */
init = () => {
const table = document.querySelector('#table');
const thead = document.createElement('tr');
const theadContent = this.renderRow('th', thead, { front: 'Front', back: 'Back' })
const tbody = document.createElement('tbody');
table.appendChild(theadContent);
table.appendChild(tbody);
}
/** Handling add event from Clicking on Add button
* Note the `update: updateFnc` line, this means we will refer
* `.update()` method of Card instance with `updateFnc()`, this is
* used for update value Card instance itself.
*/
add = ({front, back, id, update: updateFnc }) => {
const tbody = document.querySelector('#table tbody');
const row = document.createElement('tr');
const rowWithInput = this.renderRow('td', row, {front, back, id, updateFnc});
tbody.appendChild(rowWithInput);
}
renderInput = (side, id, fnc) => {
const input = document.createElement('input');
input.setAttribute('type','text');
input.setAttribute('name',`${side}-value-${id}`)
input.addEventListener('change', e => this.onInputChangeHandler(e, side, fnc));
return input;
}
renderRow = ( tag, parent, { front, back, id, updateFnc }) => {
const frontColumn = document.createElement( tag );
const backColumn = document.createElement( tag );
/** Conditionally rendering based on `tag` type */
if ( tag === 'th') {
frontColumn.innerText = front;
backColumn.innerText = back;
}else {
/** Create two new inputs for each Card instance. Each handle
* each side (front, back)
*/
const inputFront = this.renderInput('front', id, updateFnc);
const inputBack = this.renderInput('back', id, updateFnc);
frontColumn.appendChild(inputFront);
backColumn.appendChild(inputBack);
}
parent.appendChild(frontColumn)
parent.appendChild(backColumn)
return parent;
}
/** Getting new value and run `.update()` method of Card, now referred as `fnc` */
onInputChangeHandler = (event, side, fnc) => {
fnc(side, event.target.value);
}
}
class App {
/**
* Holding cards data
* Notice this is an object, not an array
* Working with react for a while, I see most of the times data as an object works best when it comes to cRUD, this means we don't have to iterate through the array to find the specific element/item to do the work. This saves a lot of time
*/
cards = {};
constructor(){
this.domTable = new Table();
this.domAdd = document.querySelector('#btn-add');
this.domResult = document.querySelector('#btn-result');
this.domAdd.addEventListener('click', this.onClickAddHandler );
this.domResult.addEventListener('click', this.onClickResultHandler );
}
onClickAddHandler = () => {
const id = uuid();
const newCard = new Card({id});
this.cards[id] = newCard;
this.domTable.add(newCard)
}
onClickResultHandler = () => {
/**
* Using `for ... in ` with object. Or you can use 3rd party like lodash for iteration
*/
for (const id in this.cards) {
console.log({
front: this.cards[id].front,
back: this.cards[id].back,
id: this.cards[id].id
});
}
};
}
// Start the application
const app = new App();
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/node-uuid/1.4.8/uuid.min.js"></script>
<div id="table"></div>
<button id="btn-add">Add</button>
<button id="btn-result">Result</button>
i think you can use In-Place Editing System and there's a good tutorial i found
Create an In-Place Editing System
I use WordPress. I have an audio player on my site. When a user clicks the play button on an individual song, it will play the song. The post ID is how the player determines which song to play.
So in the DIV that wraps the button tag, I assign an attribute: data-id which is the post id of the song. My app then grabs the MP3 file that is associated with that post ID. Simple.
My play button tag is essentially this:
<div class="item item-action" data-id="1161">
<button class="btn-playpause"></button>
</div>
The important parts of my player.js file that handles the click event and plays the song is below:
Simulate the play button
// simulate the play btn
$(document).on('click.btn', '.btn-playpause, .btn-queque', function(e){
e.stopPropagation();
var self = $(this),
item = $(this).closest('.item'),
id = item.attr('data-id'),
type = item.data('user-id') ? 'user' : 'post',
play = true;
if(!player){
getItem(id, type).done(function(obj){
if(obj.status == 'success'){
mep.mepPlaylistTracks = obj.tracks;
initPlayer();
player && player.mepSelect(0, true);
}
});
return;
}
if(self.is('.btn-queque')){
play = false;
self.parent().dropdown('toggle');
}
if( self.hasClass('is-playing') ){
self.removeClass('is-playing');
player.pause();
}else{
var index = player.find(id);
if( index !== -1){
var track = player.mepGetCurrentTrack();
if(track && track.id == id && !play) return;
player.mepSelect(index, true);
}else{
getItem(id, type).done(function(obj){
if(obj.status == 'success'){
addToPlay(obj.tracks, play);
}
});
}
}
});
getItem() function
function getItem(id, type){
return $.ajax({
type : "post",
dataType : "json",
url : ajax.ajax_url,
data : {action: "ajax_music", id : id, type: type, nonce: ajax.nonce}
});
}
addToPlay() function
function addToPlay(obj, play){
if(obj.length == 1){
player.mepAdd( obj[0], play );
}else if(obj.length > 1){
if(play){
player.options.mepPlaylistTracks = obj;
player.updatemepList();
player.mepSelect(0, true);
}else{
for(var i=0; i<obj.length; i++){
player.mepAdd( obj[i] );
}
}
}
}
You can see that once I click the play button, depending on a condition, it fires the getItem() function. getItem() takes the data-id attribute defined earlier as the id variable and begins to play the song.
The addToPlay() function will add another song to the playlist if there is already an instance of the player open. And when a user clicks another play button, it will add that new song to the list and begin to play that song.
Is it possible to modify this code so that I can add multiple data-id values to my button code so that my script will recognize there is more than one song id and add those to my playlist, using the addToPlay() function?
I'd like to do something like this
<div class="item item-action" data-id="1161, 1288, 1456">
<button class="btn-playpause"></button>
</div>
The reason I want to do this, is I would like to add a feature that will allow my users to Play All Songs on the current page they're viewing. Some of our pages, like the catalog page, displays dozens of songs that fit a certain criteria and I'd like the option to play all songs on the page.
Can anyone help push me in the right direction?
Thanks.
You could store a JSON encoded array in the data-id tag. Like:
<div class="item item-action" data-id='[1161, 1288, 1456]'>
<button class="btn-playpause"></button>
</div>
Then you can parse the array, and loop over its contents, adding each id to the queue.
See an example of parsing here: https://gist.github.com/charliepark/4266921
Here I present a alternative method.
In your markup, you can set the data-id='[1234] attribute as an encoded array. You can then collect those properties and set them as the data id property on a given element using jQuery as I illustrate here:
let someElement = $('.item');
let setItems = someElement.data('id');
let thisItem = someElement.attr('data-id');
IMPORTANT: the someElement.data('id') returns the same as the someElement.attr('data-id') (except as a string) IF nothing for that element has been set with someElement.data('id',[567,890]); which sets the property id for someElement. So, once set that way
let x = someElement.data('id'); // returns the array 567,890
let org = someElement.attr('data-id'); // still returns the [1234]
This code illustrates:
let someElement = $('.item').first();
let setItems = someElement.data('id');
let thisItemS = someElement.attr('data-id');
// make an array of the string
let thisItem = JSON.parse(thisItemS);
console.log(typeof setItems, setItems, typeof thisItemS, thisItemS, typeof thisItem, thisItem);
someElement.data('id', [567, 890]);
let x = someElement.data('id'); // returns and gets the array 567,890
let org = JSON.parse(someElement.attr('data-id')); // still returns the string [1234] made into an array
// merge with no duplicates, in the other code I used .map()
let z = Array.from(new Set(x.concat(org)));
console.log(x, org, z);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class='item' data-id='[1234]'>me the item</div>
This code show a set of elements using the concepts introduced above plus:
Set some check boxes for selection
Get the values (all)
Get the values (checkbox checked)
You can combine any of this for your original purpose, but you will need to manage that addition of new items values (and subsequently how to remove perhaps) on a given element. You might even add to a <select> element so the user then can pick some to remove perhaps...
function showPicks(choicedata) {
let ul = $('#choices').append('<ul />');
//ul.remove('li');
ul.html('empty');
ul.text('choices:');
$.each(choicedata, function(index, choice) {
let c = $('<li/>').html(choice);
ul.append(c);
});
}
$(function() {
let mydata = $('.item').map(function() {
return $(this).data('id');
}).get();
$('.all-items').data("id", mydata);
showPicks(mydata); //now do what is desired
});
$('item.item-action').filter(':not(".some-items")')
.on('click', '.btn-playpause', function() {
let setItems = $(this).closest('.item').data('id');
let thisItem = $(this).closest('.item').attr('data-id');
// do what you wish here, I show them
showPicks(setItems);
});
$('.some-items').on('click', '.btn-playpause', function(event) {
let mydata = $('.item-select').filter(':checked')
.add(this) // set an additional one from the button
.closest('.item')
.map(function() {
return $(this).data('id');
}).get();
$(event.delegatedTarget).data("id", mydata);
let setItems = $(event.delegatedTarget).data('id');
// the original pick
let thisItem = $(event.delegatedTarget).attr('data-id');
// do what you wish here
showPicks(mydata);
});
.btn-playpause {
height: 2em;
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="item item-action" data-id="[1161]">
<button class="btn-playpause" type="button"></button>
<input type="checkbox" class="item-select" />
</div>
<div class="item item-action" data-id="[1163]">
<button class="btn-playpause"></button>
<input type="checkbox" class="item-select" />
</div>
<div class="item item-action" data-id="[9961,7744]">
<button class="btn-playpause" type="button"></button>
<input type="checkbox" class="item-select" />
</div>
<div class="item item-action all-items" data-id="[42]">
<button class="btn-playpause" type="button">Play All</button>
</div>
<div class="item item-action some-items" data-id="[95]">
<button class="btn-playpause" type="button">Play selected</button>
</div>
<div id="choices">none</div>