I cannot append a child element to a list - javascript

I used to be able to append a child to a list dynamical but now for some reason the JavaScript functions stop working. Also the error console does not throw any errors and I have place several alert('') methods in between the code to make sure that the method is actually running. this is what I used to have and it used to work perfectly fine:
var o = document.getElementById('searchResults');
var li = document.createElement('li'); //creates a list item tag
//if counter is even then highlight the cell different than an odd one
if ((counter) % 2 == 0) {
li.setAttribute('class', 'par');
} else {
li.setAttribute('class', 'non');
}
// I copied the inner html from a row that was displaying. I got rid of the dynamic variables
// just so it is a little easier to understand.
li.innerHTML = "<label class='list3p1'>testing</label><label class='list3p2'>testing2</label><label class='list3p3'>2:23</label>";
o.appendChild(li);
this function was working but as I added other tables to index.php this functions stopped working. Moreover I have used this similar method in other pages. Also other methods are working and that is the only function that does not seem to work.

It had to do with the visibility. It took me a long time to find. I had the id of the table repeated and the visibility of the other table was hidden therefore I was adding items to a hidden table. sorry for the fool question.

Related

Parse a JS array and add a style for matching values using .addClass()

I'm confused as I don't believe I've done anything out of the ordinary here, that I haven't done before.
I'm looking to implement a feature similar to Excel's "Highlight Duplicate Values" action.
I have a function that takes tab separated values and parses them into a list of claims. It's all hacky, but the "list" (or table) is a series of divs that contains various elements such as a button that holds the claim ID. Once the list is created and all claims are visible, I parse it to find what buttons hold duplicate values, and apply a class to said button to highlight it using .addClass().
The problem is that I cannot seem to get the button to highlight. Now I've used functions like this before without any issue, including making a row highlight when clicked (and dim the others), and so on, but I'm confused what seems to be wrong here.
The parsing code is as follows:
function parseForDuplicates() { // Look for duplicates to highlight
var importedListLength = $("div.column.colClaim").length; // Get length of claims in list
var claimsToReview = []; // create an array for below...
for (let a=0; a < softParsedList.length; a++) { // Add the claim IDs to the claimsToReview array
claimsToReview.push(softParsedList[a][0]);
}
for (let i=0; i < importedListLength; i++) { // Compare values...
var currentCheckedClaimBtn = $(`div.column.colClaim:nth-child(${i+1}) button`); // Get the button element for current line
if (i > 0) {
var previousCheckedClaimBtn = $(`div.column.colClaim:nth-child(${i}) button`); // Get the button element for previous line only if we're further along the list
} else {
var previousCheckedClaimBtn = "none"; // set to "none" if we're at the beginning.
}
if (i < importedListLength) {
var nextCheckedClaimBtn = $(`div.column.colClaim:nth-child(${i+2}) button`); // Get button element from next line
} else if (i == importedListLength) {
var nextCheckedClaimBtn = "none"; // set to "none" if we're at the end
}
var currentCheckedClaim = $(`div.column.colClaim:nth-child(${i+1}) button`).val(); // Get claim ID from current line
if (i > 0) {
var previousCheckedClaim = $(`div.column.colClaim:nth-child(${i}) button`).val(); // Get claim ID from previous line
} else {
var previousCheckedClaim = "none"; // set to "none" if we're at the beginning
}
if (i < importedListLength) {
var nextCheckedClaim = $(`div.column.colClaim:nth-child(${i+2}) button`).val(); // Get claim ID from next line
} else if (i == importedListLength) {
var nextCheckedClaim = "none"; // set to "none" if we're at the end
}
//console.log(`Previous Claim: ${previousCheckedClaim}`);
//console.log(`Current Claim: ${currentCheckedClaim}`);
//console.log(`Next Claim: ${nextCheckedClaim}`);
if (currentCheckedClaim == nextCheckedClaim) { // If the current claim matches next claim
currentCheckedClaimBtn.addClass('duplicateClaim'); // Highlight current button
nextCheckedClaimBtn.addClass('duplicateClaim'); // Highlight next button
nextCheckedClaimBtn.addClass('duplicateClaim'); // Highlight next button
console.log(`${currentCheckedClaim} is a duplicate!`);
}
if (currentCheckedClaim == previousCheckedClaim) { // If the current claim matches previous claim
currentCheckedClaimBtn.addClass('duplicateClaim'); // Highlight current button
previousCheckedClaimBtn.addClass('duplicateClaim'); // Highlight previous button
console.log(`${currentCheckedClaim} is a duplicate!`);
}
}
}
The CSS in question...
.duplicateClaim {
border-color: #BB9955 !important;
background-color: #773311 !important;
color: #FFFFFF !important;
}
I've tried with and without !important and that doesn't change anything
When I open up DevTools I can see that the styles get applied appropriately, however in the Styles sidebar, the style is nowhere to be found! I can add it manually to the stylesheet, and at that point, the buttons highlight as intended!
I've gone over the seemingly trivial things: I've definitely saved the CSS file. The HTML file points to the correct CSS file (it never changed to begin with), and there are no conflicting styles that I'm aware of. I use two stylesheets (one named style2.css and the other named external.css and there are no conflicts between them. I tried disabling external.css - no change. I also made sure I didn't somehow open the wrong css (from production or a backup) and just have been editing CSS that was never referenced by changing a DIFFERENT rule - the body - to have a background color that's #FFFFFF and it works. I've also tried inserting it directly into the HTML... that doesn't work. Moving .duplicateClaim to the TOP of the CSS file? Nope. Maybe I just fat fingered it all? Nope. Spelling is correct. I did a copy/paste just in case my eyes have betrayed my brain - nah, they're still cooperating with me... for now. And what about adding a class that's actually an ID?
Yeah, no, that period has not magically turned into a hash. Most definitely has remained a period, and hasn't given me an issue. Oh oh! But what about applying the style DIRECTLY too the element? Nah, I assure you I've tried and nothing wants to play nice.
And lastly, I've tried generating each line WITH the class already entered! That doesn't work either. For whatever reason, chrome just seems to eat that one rule for lunch, and it just doesn't exist. I feel like there is SOMETHING dumb that I'm just not looking at and I'm just dealing with being really, really tired, but I need some kind of sanity check here. Or, maybe I really am going crazy...
Of course, again, let me emphasize that when looking at the source in the developer tools, the class most definitely gets added to the elements that I specify in the code - the JS appears to work, regardless of whether or not it's messy and triggers you (however it's not the first time something appears to work but is still wrong. It just seems like the class ceases to exist the moment the page is loaded. And if I manually add it in the developer tools by clicking the New Style Rule button (the plus next to the :hov and .cls buttons)? It applies to the correct buttons without issue.

loop through and remove form elements in Javascript

Hi I have been writing a Javascript quiz whilst learning Javascript, but have encountered a problem.
I have one function that dynamically creates the question/answers with radio buttons to mark off the questions.
When I use this second function to attempt to remove the question/answers so I can show the new ones; it removes the text (in p tags) but doesn't remove the radio buttons, even though they also show as children to the form element.
function removeLastQuestions() {
var allQuestions = document.getElementById('questionForm');
for (var i = 0; i < allQuestions.children.length; i++) {
allQuestions.removeChild(allQuestions.children[i]);
}
}
The question/answers and buttons are contained within a form with the id of "questionForm"
I guess I could put the whole form within a div and remove the form, but I'm wondering why looping over them isn't working. I'm trying to do it without using Jquery.
Thanks for any help.
Try this way:
var node = document.getElementById('questionForm');
while (node.hasChildNodes()) {
node.removeChild(node.lastChild);
}
This will remove all form elements.
JSFiddle demo

Can someone help me apply the js 'this' keyword to an iterated jq select expression

Here's my latest version of this code. The 1st line iterates through the rows of a table skipping over the 1st row. For each row I test to see if the (class='dim') state of one of 8 tag elements (index j) on that row matches the corresponding !'dim' state of a set of 8 filters that the user can toggle. The idea is to set any rows where the 'active' filter / 'dim' tag states line up, to the 'hide' class, so they can disappear from the table that the user sees. The CSS for disappearing it is: .hide {display:none;}
It's that last 'if' statement that's killing me. I've tried dozens of versions but I always get some form of syntax error, undefined variable, etc. In that line of code here I've removed my latest set of +, ', " characters to better show clearly what I'm trying to do.
I don't just want something that works to replace this code. And I'm not interested in the shortest trickiest way to do it. I'd like to see some simple obvious code that I could easily understand a year from now so I can solve problems like this myself. Thanks in advance.
var thisRow = $('tbody tr:gt(0)').each(function() {
for (var i=0,j=4;i<8;i++,j++) {
if (!$('.butt').eq(i).hasClass('dim')) {
if (thisRow.nth-child(j)).hasClass('dim')) $(this).addClass('hide');
else $(this).removeClass('hide');
}
}
}
Above this line is the question as I first asked it. Below this is the complete function in case anyone else might find this useful. Thanks to Mr. Pavlikov for the lesson!
function filterTbl() { //Hide rows that don't satisfy all active filters
var butts=$('.butt'); //Each filter button has class 'butt'
$('tbody tr:gt(0)').each(function() { //iterate each table row except the 1st
var thisRow = $(this); //the row being examined
var chilluns = thisRow.children(); //all td's in the row being examined
for (var i=0,j=4;i<8;i++,j++) {
if (!butts.eq(i).hasClass('dim')) { //If this filter is active
//and If the corresponding tag is not active (is 'dimmed'), then hide this row
if (chilluns.eq(j).hasClass('dim')) thisRow.addClass('hide');
else thisRow.removeClass('hide'); //else unhide this row
}
}
});
}
First of all you should be getting thisRow variable like this (not like you are currently doing)
$('tbody tr:gt(0)').each(function() {
var thisRow = $(this);
}
And what does nth-child stand for? Use nth-child selector correctly or use siblings at least if you are willing to compare one row with other rows. I didn't quite understand what are you trying to do, but hope this helps.
And some usefull tips. You do not need to find $('.butt') EVERY TIME in the loop, just find it once before your each loop:
var butts = $('.butt');
So now you will be able to replace
$('.butt').eq(i)
with
butts.eq(i)
This is significant speedup.
Also if n-th child you are trying to find is something that is inside thisRow, find children and do .eq() on them.

appending a div at the end of a dynamically created row

I have rows that are dynamically created and I want to append a div at the end of each row. I tried different ways to get this to happen. one time I ended up appending the div to each row but the previous rows got additional divs every time a row was added. I want only one row to have 1 cancel div at all time. (this will be like a cancel button so the user can delete the row).
in this code i am trying to go through each row with the class of row and check to see if the row has a child with a class of "cancel" and if there is none append the div cancel. It works the first time but not the other times.
$('.row').each(function(){
if($(".row").children(".cancel").length == 0){
$("<div class = 'cancel'>test</div>").appendTo('.row')
}
})
I tried to add the div "cancel" in the else statement when I append the rows like this
if($(".table").html().length <= 0)
{
$('.table').append($("<table>").append(tableheader).append(tr));
}else{
if($(".table").html().length > 0){
$("table").append(tr).append("<div class = 'cancel'>test</div>")
}
}
but it didn't show up at all
I know I could probably add another td to the var tr to make a new column with the div, but I'm wondering why my efforts to doing it the above way was a unsuccessful. It should work. excuse my ignorance .
here is the jsfiddle for illustration. maybe there is something wrong with the code somewhere else.
I have another problem in the code that I think that you could help me out with. Its with the total amount in the total column. the format is coming out as 7.5 instead of 7.50, normal dollar pricing figures. and when im on grilled chicken cutlet and choose qnty = 3 the total is 38.849999999999994 i thought toFixed(2) and parseFloat would fix that but they didn't work. obviously I would like 38.85.
I think the problem is in the way you are accessing the table rows while appending the div.
$('.row').each(function(){
if($(".row").children(".cancel").length == 0){
$("<div class = 'cancel'>test</div>").appendTo('.row')
}
});
The above script always searches for the class .row while appending the div. So if you have a div appended to any one of the .row class, if condition fails.
Solution:
To fix the problem, use $(this) to access the each row in the loop.
$('.row').each(function(){
if($(this).children(".cancel").length == 0){
$("<div class = 'cancel'>test</div>").appendTo($(this))
}
});
Also to fix your second issue of price, change
$(".total",$row).html(parseFloat(qnty * price));
to
$(".total",$row).html(parseFloat(qnty * price).toFixed(2));
Check the updated Demo Fiddle.
try this:
$('.row').each(function(idx, val){
if($(val).children(".cancel").length == 0){
$("<div class = 'cancel'>test</div>").appendTo(val);
}
});
you can do this
a)console.log($('.row').length)// to see the length
$("test").appendTo('.row') //this.code should "$("test").appendTo($(this)) "
I think what i say above may helpful; try your self

jquery checkbox slow, not sure how to fix

I have used firebug and IE profilers and can see what function in my code is causing the slowness. Being new to jquery, the recommendations that I have read online are not clear to me. I have made an example page that shows the slow behavior when you check or uncheck a check box. No surprise that this is fast using Chrome.
The function that is slow can be found on line 139.
$('.filters input').click( function()
JSFiddle can be found here
The code is 122 KB and can be found here
UPDATE: if you know of any examples online that are similar in function and faster, please share.
i had a brief look through your code, but it was very hard to follow. it seemed as if you were looping through things many many times. i used a much simpler approach to get the list of all states.
your approach was
* make a massive string which contained every class (possibly repeated multiple times)
* chop it up into an array
* loop through the array and remove duplicates
i simply took advantage of the fact that when you select something in jQuery you get a set rather than a single item. you can therefore apply changes to groups of object
$(document).ready(function () {
//this will hold all our states
var allStates = [];
//cache filterable items for future use
var $itemsToFilter = $(".filterThis");
//loop through all items. children() is fast because it searches ONLY immediate children
$itemsToFilter.children("li").each(function() {
//use plain ol' JS, no need for jQuery to get attribute
var cssClass = this.getAttribute("class");
//if we haven't already added the class
//then add to the array
if(!allStates[cssClass]) {
allStates[cssClass] = true;
}
});
//create the container for our filter
$('<ul class="filters"><\/ul>').insertBefore('.filterThis');
//cache the filter container for use in the loop
//otherwise we have to select it every time!
var $filters = $(".filters");
// then build the filter checkboxes based on all the class names
for(var key in allStates) {
//make sure it's a key we added
if(allStates.hasOwnProperty(key)) {
//add our filter
$filters.append('<li><input class="dynamicFilterInput" type="checkbox" checked="checked" value="'+key+'" id="filterID'+key+'" /><label for="filterID'+key+'">'+key+'<\/label><\/li>');
}
}
// now lets give those filters something to do
$filters.find('input').click( function() {
//cache the current checkbox
var $this = $(this);
//select our items to filter
var $targets = $itemsToFilter.children("li." + $this.val());
//if the filter is checked, show them all items, otherwise hide
$this.is(":checked") ? $targets.show() : $targets.hide();
});
});
FIDDLE: http://jsfiddle.net/bSr2X/6/
hope that's helpful :)
i noticed it ran quite a bit slower if you tried to slideup all the targets, this is because so many items are being animated at once. you may as well just hide them, since people will only see the ones at the top of the list slide in and out of view, so it's a waste of processor time :)
EDIT: i didn't add logic for show all, but that should be quite a trivial addition for you to make if you follow how i've done it above
You could use context with your selector:
$('.filters input', '#filters_container').click(function()...
this limits the element that jQuery has to look in when selecting elements. Instead of looking at every element in the page, it only looks inside your $('#filters_container') element.

Categories

Resources