Content disappears after user finishes entering groceries - javascript

Happy new year, everyone! I'm celebrating by working on learning jquery. I added some jQuery to my code below and managed to add some content and change some css with it. The getGroceries function is working fine and is doing what it's supposed to do. When the user finishes entering the groceries, the program (printGroceries) is supposed to print the list that the user entered. That portion is also working.... HOWEVER, when that happens, the program removes the header (My grocery list) and removes all styling.
What am I doing wrong?
EDITED CODE: Deleted full code and added the portion that I changed (commented the old).
function printGroceries(groceryItems) {
if (groceryItems.length > 1) {
$('grocery-list').html('<ol class="items" id="list-items">');
//document.write("<ol>");
for(x=0; x < groceryItems.length;x++){
groceryItems;
$('#list-items').prepend('<li>' + groceryItems[x] + '</li>');
//document.write("<li>" + groceryItems[x] + '</li>');
}
$('#grocery-list').append('</ol>');
//document.write("</ol>");
} else {
$('#grocery-list').prepend('<p>Sorry, your list is empty.</p>');
//document.write('<p>Sorry, your list is empty.</p>');
}
}
Problem: fiddle

Try this
function printGroceries(groceryItems) {
if (groceryItems.length > 0) {
$('#grocery-list').html('<ol class="items" id="list-items">');
//document.write("<ol>");
for(x=0; x < groceryItems.length;x++){
groceryItems;
$('#list-items').prepend('<li>' + groceryItems[x] + '</li>');
//document.write("<li>" + groceryItems[x] + '</li>');
}
$('#grocery-list').append('</ol>');
//document.write("</ol>");
} else {
$('#grocery-list').prepend('<p>Sorry, your list is empty.</p>');
//document.write('<p>Sorry, your list is empty.</p>');
}
}
You have missed few things as I suggested in the comments
1. The if condition should check groceryItems.length > 0
2. $('grocery-list') should be $('#grocery-list'), you are missing the id selector here
Solution: fiddle

Since you're using jQuery; here's a version that takes advantage of $.each(). Also, it's best to build out your string and append only once rather that append each item over and over.
function printGroceries(groceryItems) {
var listItems = '';
if (groceryItems.length > 0) {
$.each(groceryItems, function (i, item) {
listItems += '<li>' + item + '</li>';
});
$('#grocery-list').append('<ol class="items" id="list-items">'+listItems+'</ol>');
} else {
$('#grocery-list').prepend('<p>Sorry, your list is empty.</p>');
}
}

Related

removeClass & addClass jquery

I am relatively new to jquery and try to solve the following issue
I want to build a tree diagram, cf.
When an item in the first category is clicked, the second category (in div #category_2) pops-up. The same for the 3rd category. Every subsequent click on category 1 or 2 should remove the appended 2nd and 3rd item and append the chosen item from the 2nd and 3rd category.
Here is what I tried at the example of opening an item in category 3 (=subMenu2):
function makeType(subMenu2, root) {
if (typeof root === 'undefined') {
root = $('#category_3');
}
var ul = $("<ul></ul>");
if (root.children().length > 0) {
root.removeClass(ul)
}
root.append(ul);
for (var k = 0; k < subMenu2.length; k++) {
var li = $("<li class='category-selection-list-item is-subleaf'></li>");
ul.append(li);
var a = $("<a href='#' data-param='" + array[array_i].subMenu[submenu_i].subMenu2[k].param + "'>" + array[array_i].subMenu[submenu_i].subMenu2[k].type + "</a>");
li.append(a);
console.log(k);
}
}
Though the removeClass element stops adding further items, it does not delete previously added items. I tried to find a suitable answer in the forum, but this did not help. So, how can I fix this issue?
To remove the previously added items, you need to empty root.
if (root.children().length > 0) {
root.removeClass('ul');
root.empty();
}
addClass("className")
removeClass("className")
if you want to hide some node, just use this:
$("#someNode").hide()

jQuery- counting articles in a row- it counts items from both boxes

I'm trying to count the articles in the top row of the two boxes on the page.
The boxes are separate and I want the count to be like that too -
function calculateArticlesInRow() {
var articleInRow = 0;
$('.promotionWrapper').each(function() {
console.log($(this).prev().length);
if($(this).prev().length > 0) {
console.log($(this).offset().top + '='+ $(this).prev().offset().top);
if($(this).offset().top != $(this).prev().offset().top){
return false;
}
articleInRow++;
}
else {
articleInRow++;
}
});
$('.result1').html('No: of articles in a row = ' + articleInRow);
}
setTimeout(function(){
calculateArticlesInRow();
}, 3000);
The problem I'm having however, is that the script is counting the articles in both boxes when only the articles with a certain top offset should be counted.
I have found other questions like this, but the all seem to use only one box.
Any help would be appreciated.
Here is a fiddle so you can see what I'm trying to do: https://jsfiddle.net/JackofD/de31nojn/
Thanks in advance
I think you should count the .promotionWrapper articles for each .productWrapper section.
i've updated your fiddle.
var articleInRow = 0,
maxArtNo = 0;
// cycle for every .productWrapper
$('.productWrapper').each(function (index, el) {
articleInRow = 0
// cycle for every .promotionWrapper in this .productWrapper
$('.promotionWrapper', el).each(function (innerIndex, innerEl) {
//your code
});
//set the count to the max
if (articleInRow > maxArtNo) maxArtNo = articleInRow;
});
// rest of your code
Try something like this:
$('.contentWrapper').each(function(){
//finds how many articles in the current container
console.log($(this).find('.promotionWrapper').length);
});
But to get each container individually, maybe you should put a separate class on each section tag instead.
You are counting all the sections with "promotionWrapper" class. To count the 1st row only, you need to select its parent section first and then count children of that. Here is the code:
$('.productWrapper:first').children('.promotionWrapper').each(function () {
console.log($(this).prev().length);
if ($(this).prev().length > 0) {
console.log($(this).offset().top + '=' + $(this).prev().offset().top);
if ($(this).offset().top != $(this).prev().offset().top) {
return false;
}
articleInRow++;
} else {
articleInRow++;
}
});
Sorry, my bad. Didnt see the jsfiddle.
Here is a working solution independent of your code:
var articlesInRow = [];
$('.productWrapper').each(function (index) {
articlesInRow[index] = $(this).find('.promotionWrapper').length;
$('.result' + (index+1)).html('No: of articles in row' + (index + 1) + ' = ' + articlesInRow[index]);
});
which i added to your calculateArticlesInRow function.
Please see updated jsfiddle:
https://jsfiddle.net/de31nojn/15/

Edit HTML list entry with javascript

Note: i searched a half hour. I need a special solution for this:
I have the folowing code already (node some Variables have german Names i hope that's ok)
function generateList () {
document.getElementById("liste").innerHTML =""
var listEasy = vorNameListe[i] + " " + nachNameListe[i] + " " + alterListe[i]
for (var i=0; i < vorNameListe.length; i++) {
document.getElementById("liste").innerHTML += "<li>" + listEasy + "</li>"
};
Now i need a javascript (pls no jquery) solution so the user can change every List entry by himself. How do i do that?
further explanation: The code i have is one to bring a "li" in a existing "ul" with every loop.
But then i want to give every "li entry" the ability to be changed by the user.
Are you trying to change text of every li of #liste ul?
function generateList() {
var liItems = document.querySelectorAll('#liste > li');
for (i = 0; i === liItems, i++) {
liItems[i].innerHTML = 'content';
}
}
i refined my edit function with jquery fdurther and further i will edit this entry for every step:
I have a Special Idea about an Edit function
https://stackoverflow.com/questions/28695711/edit-and-delete-selected-list-entrys

Filtering divs based on classes, using jQuery

Looking for some help on how to write a function to filter out certain divs with certain classes.
Essentially I have thrown together a quick e-commerce example. There are lists of different filters, with values. There are then products. Each product div has a number of classes applied to it, e.g "green" or "adult" or "wool" - these are the filterable parameters.
Not being savvy at all with JS I'm trying to write something, but looking for some advice. Here is basically what I'm after:
Starts with displaying all
If user selects GREEN, all items that do not have GREEN attributed are display:none'd (with a fade transition
Rep #2 for any attribute checked
Notes: multiple attributes can be checked, when items are unchecked, everything needs to reappear.
Any help? I guess it's basically linking up the value of each checkbox to the class.
Not sure if there is a better way codewise to do this... data attributes maybe?
Working example of the code here (obviously no JS)
Updated your fiddle and added some jQuery to hide the divs where the classes don't match the selected checkboxes.
Demo: fiddle
JS is a bit verbose, you can refactor it further if you like:
$(document).ready(function() {
var allSelectedClasses;
allSelectedClasses = '';
$('input[type="checkbox"]').click(function(){
//ensure the correct classes are added to the running list
if(this.checked){
allSelectedClasses += '.' + $(this).val();
}else{
allSelectedClasses = allSelectedClasses.replace($(this).val(), '');
}
//format the list of classes
allSelectedClasses = allSelectedClasses.replace(' ', '');
allSelectedClasses = allSelectedClasses.replace('..', '.');
var selectedClasses;
var allSelected;
allSelected = '';
//format these for the jquery selector
selectedClasses = allSelectedClasses.split(".");
for(var i=0;i < selectedClasses.length;i++){
var item = selectedClasses[i];
if(item.length > 0){
if(allSelected.length == 0){
allSelected += '.' + item;
}else{
allSelected += ', .' + item;
}
}
}
//show all divs by default
$("div.prodGrid > div").show();
//hide the necessary ones, include the 2 top level divs to prevent them hiding as well
if(allSelected.length > 0){
$("div.prodGrid > div:not(" + allSelected + ")").hide();
}
});
});
I added a new class to your Colors ul. Hope that's okay.
Here's a crude version of a filtering function, it only takes colors into account so you have to modify it yourself to take everything into account but the basic outline is there.
It can be refactored massively! :)
Since you're using jQuery:
$('ul.colorFilter li input[type="checkbox"]').click(function(){
var checkedBoxes = $('ul.colorFilter li input[type="checkbox"]:checked');
var listOfClasses = [];
checkedBoxes.each(function(index, el){
listOfClasses.push(el.value);
});
if(listOfClasses.length >= 1){
$('div.prodGrid').children('div').hide();
for(var i = 0; i < listOfClasses.length; i++){
$('div.prodGrid > div.'+listOfClasses[i]).show();
}
} else {
$('div.prodGrid > div').show();
}
});
I made a fiddle as well:
http://jsfiddle.net/Z9ZVk/4/

Filtering the list of friends extracted by Facebook graph api ( more of a JavaScript/Jquery question than Facebook API question)

Hello there JavaScript and Jquery gurus, I am getting and then displaying list of a facebook user's friend list by using the following code:
<script>
function getFriends(){
var theword = '/me/friends';
FB.api(theword, function(response) {
var divInfo = document.getElementById("divInfo");
var friends = response.data;
divInfo.innerHTML += '<h1 id="header">Friends/h1><ul id="list">';
for (var i = 0; i < friends.length; i++) {
divInfo.innerHTML += '<li>'+friends[i].name +'</li>';
}
divInfo.innerHTML += '</ul></div>';
});
}
</script>
graph friends
<div id = divInfo></div>
Now, in my Facebook integrated website, I would eventually like my users to choose their friends and send them gifts/facebook-punch them..or whatever. Therefore, I am trying to implement a simple Jquery filter using this piece of code that manipulates with the DOM
<script>
(function ($) {
// custom css expression for a case-insensitive contains()
jQuery.expr[':'].Contains = function(a,i,m){
return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase())>=0;
};
function listFilter(header, list) { // header is any element, list is an unordered list
// create and add the filter form to the header
var form = $("<form>").attr({"class":"filterform","action":"#"}),
input = $("<input>").attr({"class":"filterinput","type":"text"});
$(form).append(input).appendTo(header);
$(input)
.change( function () {
var filter = $(this).val();
if(filter) {
// this finds all links in a list that contain the input,
// and hide the ones not containing the input while showing the ones that do
$(list).find("a:not(:Contains(" + filter + "))").parent().slideUp();
$(list).find("a:Contains(" + filter + ")").parent().slideDown();
} else {
$(list).find("li").slideDown();
}
return false;
})
.keyup( function () {
// fire the above change event after every letter
$(this).change();
});
}
//ondomready
$(function () {
listFilter($("#header"), $("#list"));
});
}(jQuery));
</script>
Now, This piece of code works on normal unordered list, but when the list is rendered by JavaScript, it does not. I have a hunch that it has to do something with the innerHTML method. Also, I have tried putting the JQuery filter code within and also right before tag. Neither seemed to work.
If anyone knows how to resolve this issue, please help me out. Also, is there a better way to display the friends list from which users can choose from?
The problem is here:
$(list).find("a:not(:Contains(" + filter + "))").parent().slideUp();
$(list).find("a:Contains(" + filter + ")").parent().slideDown();
Since you're rendering this:
divInfo.innerHTML += '<li>'+friends[i].name +'</li>';
There is no anchor wrapper, the text is directly in the <li> so change the first two lines to look in those elements accordingly, like this:
$(list).find("li:not(:Contains(" + filter + "))").slideUp();
$(list).find("li:Contains(" + filter + ")").slideDown();
You could also make that whole section a bit faster by running your Contains() code only once, making a big pact for long lists, like this:
$(input).bind("change keyup", function () {
var filter = $(this).val();
if(filter) {
var matches = $(list).find("li:Contains(" + filter + ")").slideDown();
$(list).find("li").not(matches).slideUp();
} else {
$(list).find("li").slideDown();
}
});
And to resolve those potential (likely really) innerHTML issues, build your structure by using the DOM, like this:
function getFriends(){
var theword = '/me/friends';
FB.api(theword, function(response) {
var divInfo = $("#divInfo"), friends = response.data;
divInfo.append('<h1 id="header">Friends/h1>');
var list = $('<ul id="list" />');
for (var i = 0; i < friends.length; i++) {
$('<li />', { text: friends[i].name }).appendTo(list);
}
divInfo.append(list);
});
}
By doing it this way you're building your content all at once, the <ul> being a document fragment, then one insertion....this is also better for performance for 2 reasons. 1) You're currently adding invalid HTML with the .innerHTML calls...you should never have an unclosed element at any point, and 2) you're doing 2 DOM manipulations (1 for the header, 1 for the list) after the much faster document fragment creation, not repeated .innerHTML changes.

Categories

Resources