I have a users card list, my task is:
Clicking "undo" button: will restore the last card that was deleted (use array)
Question 1: How to make array from cards list I have displayed ?
Question 2: How to restore the last card that was deleted?
(IF 2 cards are removed, "undo" button will to restore card one by one)
Link to codepen here https://codepen.io/MarinaShumeiko/pen/Nbeqew?editors=1010
var root = 'https://jsonplaceholder.typicode.com';
var notificationMessage = "Oops, there are no more user cards to display";
var userIndex = 0;
var undoBtn = $("#button")
var $clearBtn = $("#clear");
var $contentArea = $("#content");
var cardTemplate = '<div class="card" data-id="{id}"><div class="title"><div class="image"></div><div class="name">{name}</div><button onclick="removeUser({postid})" class="close"></button></div><div class="description">{body}{email}</div></div>';
// - Load all the card at once, when screen load
$(function() {
$contentArea.append(renderUser);
});
// Make array from usercards
var $cardDiv = $(".card");
var usersCardArray = $cardDiv.toArray(); // return usersCardArray.length = 0 :(
//remove all card at once
$clearBtn.click(clearUsers);
function clearUsers () {
$contentArea.empty();
userIndex = 0;
}
//remove one card
$('.card .close').on('click', removeUser);
function removeUser(postId) {
$('[data-id="' + postId + '"]').remove();
}
// get user data
function getUser () {
return $.ajax({ url: root + '/posts/1/comments', method: 'GET' });
}
function renderUser() {
getUser().then(function (user) {
for (var i = 0; i = user.length; i++) {
var card = cardTemplate
.replace('{id}', user[userIndex].id)
.replace('{postid}', user[userIndex].id)
.replace('{name}', user[userIndex].name)
.replace('{body}', user[userIndex].body)
.replace('{email}', user[userIndex].email);
$contentArea.append(card);
userIndex++;
}
})
}
Since you don't manipulate any actual data, only the view itself - you can add class .hidden on delete card, and remove this class on undo.
To keep track on deleted users I added array var deletedUsers =[]. Each time you delete a user, add its id to array and hide it from view by adding class hidden.
On undo - pop the user id from deletedUsers, and remove class hidden from this user's card
https://codepen.io/anon/pen/PbXxrB
Related
Working on a project in AppLab in Code.org, and I'm trying to traverse and display individual elements of a data table one at a time. The user hits the next button, and it should display the next cat name and image, and when they hit the back button, it goes to the previous cat's info. However, it is displaying the entire list of cat names in the text box, and the setImageURL command isn't working.
//declare variables
var catName = [getColumn("Cats", "Name")];
var catTemper = [getColumn("Cats", "Temperament")];
var catImage = [getColumn("Cats", "Image")];
var index = 0;
//Traversing/filtering the lists when the back or next button is chosen
//next button
onEvent("nextCatButton", "click", function( ) {
if(index < (catName.length - 1)) {
index = index + 1;
}
updateScreen();
});
//back button
onEvent("backCatButton", "click", function( ) {
if(index > 0){
index = index - 1;
}
updateScreen();
});
```
```
//function to display cat name and image on screen 2
function updateScreen() {
setText("nameOutput1", catName[index]);
setImageURL("imageOutput", catImage[index]);
}
I originally tried filtering with a for loop and appending to a filtered list, but switched to using indexes as I thought it would be simpler.
I have a table whose rows consist of 3 columns. 1º is a checkbox, 2º contains the colors and the 3º contains the hex.
As the user selects the colors desired by ticking the checkboxes, i imagine the colors being pushed into an arrat, that will be written to a cell as the user clicks on the save button.
I've borrowed this snippet from Mark, but it doesn't seem to run in my context:
var checkboxes = document.getElementsByTagName("input");
var selectedRows = [];
for (var i = 0; i < checkboxes.length; i++) {
var checkbox = checkboxes[i];
checkbox.onclick = function() {
var currentRow = this.parentNode.parentNode;
var secondColumn = currentRow.getElementsByTagName("td")[1];
selectedRows.push(secondColumn);
};
console.log(selectedRows)
}
This is the javascript part running to load and populate the table and I'm not sure where the above snippet woud go into:
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
/**
* Run initializations on sidebar load.
*/
$(function() {
// Assign handler functions to sidebar elements here, if needed.
// Call the server here to retrieve any information needed to build
// the dialog, if necessary.
google.script.run
.withSuccessHandler(function (record) { //<-- with this
showRecord(record);
})
.withFailureHandler(
function(msg, element) {
showStatus(msg, $('#button-bar'));
element.disabled = false;
})
.getRecord();
});
/**
* Callback function to display a "record", or row of the spreadsheet.
*
* #param {object[]} Array of field headings & cell values
*/
function showRecord(record) {
if (record.length) {
for (var i = 0; i < record.length-1; i++) {
// Adds a header to the table
if(i==0){
$('#sidebar-record-block').append($($.parseHTML('<div class="div-table-row"><div class="div-table-header">Sel</div><div class="div-table-header">Color</div><div class="div-table-header">Hex</div></div>')));
}
// build field name on the fly, formatted field-1234
var str = '' + i;
var fieldId = 'field-' + ('0000' + str).substring(str.length)
// If this field # doesn't already exist on the page, create it
if (!$('#'+fieldId).length) {
var newField = $($.parseHTML('<div id="'+fieldId+'"></div>'));
$('#sidebar-record-block').append(newField);
}
// Replace content of the field div with new record
$('#'+fieldId).replaceWith('<div id="'+fieldId+'" class="div-table-row"></div>');
$('#'+fieldId).append('<input type="checkbox" class="div-table-td" id=CB"'+fieldId+'"name="checkBox" </input>')
.append($('<div class="div-table-td">' + record[i].heading + '</div>'))
.append('<div class="div-table-td">' + record[i].cellval + '</div>')
}
}
}
</script>
Sample of how to get the checked tickboxes an button click
Assuming all your checkboxes are tied to a row, you can loop through all checkboxes with a query selector,
access their checked status
and save the indices of those checkboxes.
Those indices will be the same as when looping through the corresponding table rows.
Sample implementing a button click event:
var saveButton = document.getElementById("myButtonId");
saveButton.onclick = function(){
var checkedRowIndices = [];
$('input[type=checkbox]').each(function( index ) {
if($(this)[0].checked{
checkedRowIndices.push(index);
}
});
};
//now get the rows with those indeices and do something with them
I have a working search bar that is added through the html. However to make the code unobtrusive i am trying to append the search bar and button through JavaScript. I am able to display the search bar and button, but the functionality of bringing up results has stopped working.
Here is the section to add the search bar in JS.
var $searchSection = $('<div class="student-search"></div>');
$searchSection.append('<input id = "search-criteria" placeholder="Search for students..."></input>');
$searchSection.append('<button>Search</button>');
//Append search section
$('.page-header').append($searchSection);
I am trying to get the functionality of search working. Here is a link to the code with the search working, as the search bar is included in the html. http://codepen.io/fun/pen/RRyaNm
This is a link to the code with search bar added through the js but with no search functionality. http://codepen.io/fun/pen/VjraNd?editors=1010
How do you get the search to work through adding from the js?
Any help or pointers would be awesome.
Thank you,
Harry
You don't have to add more function, just move your codes to the top. Check this
jsfiddle https://jsfiddle.net/xt5193z1/
//Search section
var $searchSection = $('<div class="student-search"></div>');
$searchSection.append('<input id = "search-criteria" placeholder="Search for students..."></input>');
$searchSection.append('<button>Search</button>');
//Append search section
$('.page-header').append($searchSection);
var $studentItem = $('.student-item');
var $pagination = $('.pagination');
var $searchCriteria = $('#search-criteria');
var perPage = 10;
// count number of student items
var studentCount = $studentItem.length;
// number of pages = number of students / 10 rounded up
var pageNumber = Math.ceil(studentCount / perPage);
// remove all student items
var initialTen = $studentItem.hide();
// display first 10 student items
initialTen = $studentItem.slice(0, perPage).show();
// pagination ul
var paginationHTML = '<ul>';
// calc number of links
for (var i = 1; i < pageNumber + 1; i++) {
// li and link for each page
paginationHTML += '<li>' + i + '</li>';
}
// end of ul
paginationHTML += '</ul>';
// display list to page
$pagination.html(paginationHTML);
// pagination link click
$('.pagination li a').on('click', function() {
// remove active
$('.pagination li a.active').removeClass('active');
// add active class
$(this).addClass('active');
// page number of clicked
var pageNum = this.text;
// Start point for slice
// e.g 3 * 10
var startFrom = pageNum * perPage - perPage;
// end point for slice
// e.g 30 + 10
var endOn = startFrom + perPage;
// display students based on number clicked
$studentItem.hide().slice(startFrom, endOn).show();
});
// Error message for no matches found
var $noMatches = $('<h2>No matches found please try again</h2>');
// Add to page
$('.page').append($noMatches);
// hide initially
$noMatches.hide();
// search box on type
$searchCriteria.on('input', function() {
// remove all result classes
$studentItem.each(function() {
$(this).removeClass("result");
});
// value of searched
var text = $(this).val().toLowerCase();
// results of search
var results = $("ul.student-list li:contains('" + text.toLowerCase() + "')");
results.addClass("result");
// show or hide based on result matching div
$studentItem.each(function() {
if ($(this).hasClass('result')) {
$(this).show("slow");
} else {
$(this).hide();
}
});
if (results.length > 10) {
// remove all student items
var initialTen = $studentItem.hide();
// display first 10 student items
initialTen = $studentItem.slice(0, perPage).show();
// show pagination
$('.pagination').show();
// hide no matches message
$noMatches.hide();
} else if (results.length === 0) {
$pagination.hide();
$noMatches.show();
} else {
$pagination.hide();
}
});
As Siguza said, $('#search-criteria') doesn't exist at the time you're fetching it. So, the on function is a good idea, but it should be given like this :
$('.page-header').on('input', '#search-criteria', function() {
//your code
});
What it does is , it will bind the function to the element that is added dynamically in DOM
Here is the jsFiidle
It will work for you. :)
I'm making a basic list using vanilla javascript. I am able to add items, and change their class when they are clicked. Now, I want the items that have been selected (so their class has been changed) to be removed when they are clicked. At the bottom of the code, I am trying to loop through the list, then if the element in the list has the selected class, an event listener will remove the element when clicked, but this isn't working for me. Any ideas on what I'm doing wrong? (live demo: http://codepen.io/nicolaswilmot/pen/oXLgyq)
Here is the code:
var list = document.getElementById("theList"); // Get the list
// Add new item to top of list
function addItem(e) {
var userTxt = document.getElementById("userInput"); // Get user text
var newItem = document.createElement("li"); // Create new list item
var itemTxt = document.createTextNode(userTxt.value); // Get the text for item
newItem.appendChild(itemTxt); // Add text to list item
list.insertBefore(newItem, list.firstChild); // Put new item at top of list
newItem.className = 'defaultItem'; // Set default class for li
document.getElementById("userInput").value = ''; // Clear the input box
e.preventDefault(); // Prevent page from reloading when page is submitted
// Changes list item class
function changeClass () {
newItem.className = 'selectedItem';
}
// Initialize array for list items
listArray = [];
// Loop through list, add items to array, update class and counter
// when items are clicked
for (var i=0; i<list.children.length; i++) {
listArray.push(newItem);
listArray[i].addEventListener("click",changeClass);
listArray[i].addEventListener("click",countStuff);
}
}
var docForm = document.getElementById("theForm"); // Get the form element
docForm.addEventListener('submit',addItem,false); // Call addItem function when form is submitted
docForm.addEventListener('submit',countStuff,false); //Call counter when form submitted
// Function for the list item counter
function countStuff() {
// Get div container for counter
var itemCount = document.getElementById("counter");
// Get all list items that have not been selected (default class)
var unselectedItems = document.querySelectorAll('li.defaultItem');
//If more than one item, display plural "items"
if (unselectedItems.length > 1) {
itemCount.innerHTML = 'You still need '+unselectedItems.length+' items!';
} else if (unselectedItems.length == 0) {
itemCount.innerHTML = 'You have all items!';
} else {
itemCount.innerHTML = 'You still need '+unselectedItems.length+' item!';
}
}
// Loop through the list
for (var i=0; i<list.children.length; i++) {
// Remove items that are in selected state
if (list.childNodes[i].className='selectedItem') {
list.childNodes[i].addEventListener('click',function () {
list.removeChild([i])},false);
}
}
The placement of your code where you are trying to remove the element once it has the selectedItem class does not make sense, because that code will only run once on page load when the page has no items in the list. Instead, in the same function where you add the selectedItem class, you can bind an event listener to that DOM element that removes it from the list on the next click. http://codepen.io/anon/pen/vOKEzz
function changeClass () {
newItem.className = 'selectedItem';
//Remove it on click!
newItem.addEventListener('click',function () {
list.removeChild(newItem)
}, false);
}
I have a program that is configured to hide/show table rows when a +/- icon is clicked. The functionality is working, however, I need to figure out a way to reset all hide/show icons when the parent category is toggled closed.
$(function(){
//src vars
var hide_src = "http://www.synchronizeddesigns.com/filter_hide.gif",
reveal_src = "http://www.synchronizeddesigns.com/filter_reveal.gif",
s = '';
//hide all sublevel elements
$(".subsub, .subsubsub").hide();
$("a").click(function(e){
e.preventDefault();
var tID = e.target.id,
tClass = '.' + tID.replace('HS', '');
$(tClass).toggle();
if(!$(tClass).is(':visible')){
s = hide_src;
//for each subcategory
$(tClass).each(function(){
//get class names into classes array
var classes = $(this).attr('class').split(' '),
parentClass = '';
//search classes array for class that begins with 'cat'
for (var j=0; j<classes.length; j++) {
if (classes[j].match("cat")){
parentClass = classes[j];
}
}
//find subsubsub elements that have a class that begins with 'cat#sub'
var subs = $('[class*=' + parentClass + 'sub]');
//if there are sub elements, hide them too
if(subs){
subs.hide();
/*****************************************************
NEED HELP HERE !!!!!!!!!!
Need a way to reset all hide/show images icon
when 'parentClass' hide/show is clicked to close.
*****************************************************/
}
});
} else {
s = reveal_src;
}
//Change image src
$("#" + tID).attr('src', s);
});
});
To replicate: Toggle open all parents and subs, then close one of the parents, then reopen the parent. You'll notice that the +/- icon remains in it's previous state
jsFiddle link
You can find the img nodes for the subcategories under the current one and then change their src attr.
I've updated your jsfiddle: http://jsfiddle.net/nTyWv/12/
The code could be something like:
if(subs){
innerIcons = jQuery.find("a > img[id*="+tID+"sub]");
if (innerIcons) {
$(innerIcons).attr('src', s);
};
subs.hide();
}