I'm having a problem with my following logic.
Jsfiddle
The logic
var budgetCalc = function (financeBudget, totalCost, remainingBudget, changeOn) {
var reloadCalc = function () {
var formula = parseFloat($(financeBudget).val()) - parseFloat($(totalCost).val());
$(remainingBudget).val(Math.abs(formula.toFixed(0)));
if ( formula >= 0 ) {
$('.toolbar-budget').addClass('is-positive').append('<p>Remaining</p>');
} else {
$('.toolbar-budget').addClass('is-negative').append('<p>Over Budget</p>');
}
};
$(document).ready(function () {
// Price Input
$(changeOn).change(function () {
reloadCalc();
});
$(changeOn).trigger('change');
});
};
What works fine
The interface has multiple selects, inputs and a jQuery sliders that change the value of formula. The logic works fine when the page loads and the formula value is >= 0. If the value is < 0 than the formula works fine as well.
The Issue
If the value of the formula is < 0 and then becomes > 0 again because the user changes the values contributing to formula, the logic does not change the class back to .is-positive unless the page refreshes.
My goal
I want the class of .is-positive to be applied without the page refreshing if the value goes from < 0 to >= 0.
Seems like the simplest solution would be to remove both classes before adding the appropriate one but adding $('.toolbar-budget').removeClass('is-positive is-negative'); before your check:
$('.toolbar-budget').removeClass('is-positive is-negative');
if (formula >= 0) {
$('.toolbar-budget').addClass('is-positive').append('<p>Remaining</p>');
} else {
$('.toolbar-budget').addClass('is-negative').append('<p>Over Budget</p>');
}
jsFiddle example
You use addClass() and do not clear existing classes, so you end up with both classes set. You should remove previously set classes via removeClass() or toggleClass().
Also, I'd recommend to do the same with .append('<p>Remaining</p>'); part, so you don't just append paragraphs but swich them.
Related
I want to reset the game by appending child element back to '1'. By default in html it is labelled as 1 and on finishing game it gets to empty but when this bonus life is used i want at the end of the game to be reset to '1'.
<h2>PLAYER HEALTH<span id="bonus-life">1</span></h2>
I have used this function in JavaScript but seem to be not working:
function resetBonus() {
bonusLifeEl.parentNode.appendChild(bonusLifeEl);
}
This function is called in a file which is like this:
if (currentMonsterHealth <= 0 || currentPlayerHealth <= 0) {
reset();
resetBonus();
}
Reset function just remove bonus life
function reset() {
currentMonsterHealth = chosenMaxLife;
currentPlayerHealth = chosenMaxLife;
resetGame(chosenMaxLife);
}
Nothing will be changed when you try to add a child to the parent where it is already exists.
You can change the value instead of add/remove child by innerText or innerHTML values.
function resetBonus() {
bonusLifeEl.innerHTML = bonusLifeEl;
}
My first time writing my own javascript/jQuery for-loop and I'm running into trouble.
Basically, I have a series of divs which are empty, but when a button is clicked, the divs turn into input fields for the user. The input fields are there at the outset, but I'm using CSS to hide them and using JS/jQuery to evaluate the css property and make them visible/hide upon a button click.
I can do this fine by putting an id tag on each of the 7 input fields and writing out the jQuery by hand, like this:
$('#tryBTN').click(function(){
if ( $('#password').css('visibility') == 'hidden' )
$('#password').css('visibility','visible');
else
$('#password').css('visibility','hidden');
}
Copy/pasting that code 7 times and just swapping out the div IDs works great, however, being more efficient, I know there's a way to put this in a for-loop.
Writing this code as a test, it worked on the first one just fine:
$('#tryBTN').click(function() {
for(i = 1; i <= 7; i++) {
if($('#input1').css('visibility') == 'hidden')
$('#input1').css('visibility', 'visible');
}
});
But again, this only works for the one id. So I changed all the HTML id tags from unique ones to like id="intput1" - all the way out to seven so that I could iterate over the tags with an eval. I came up with this:
$('#tryBTN').click(function () {
for (i = 1; i <= 7; i++) {
if ($(eval('input' + i)).css('visibility') == 'hidden')
$('input' + i).css('visibility', 'visible');
}
});
When I put in the eval stuff - it doesn't work. Not sure what I'm doing wrong. A sample of the HTML looks like this:
<form>
<div class="form-group">
<label for="page">Description: Specifies page to return if paging is selected. Defaults to no paging.</label>
<input type="text" class="form-control" id="input7" aria-describedby="page">
</div>
</form>
You were forgetting the #:
$('#tryBTN').click(function () {
for (i = 1; i <= 7; i++) {
var el = $('#input' + i); // <-- The needed `#`
if (el.css('visibility') == 'hidden') {
el.css('visibility', 'visible');
}
}
});
#Intervalia's answer explains the simple error in your code (the missing #), and the comments explain why you should never use eval() unless you absolutely know it's the right tool for the job - which is very rare.
I would like to add a suggestion that will simplify your code and make it more reliable.
Instead of manually setting sequential IDs on each of your input elements, I suggest giving them all a common class. Then you can let jQuery loop through them and you won't have to worry about updating the 7 if you ever add or remove an item.
This class can be in addition to any other classes you already have on the elements. I'll call it showme:
<input type="text" class="form-control showme" aria-describedby="page">
Now you can use $('.showme') to get a jQuery object containing all the elments that have this class.
If you have to run some logic on each matching element, you would use .each(), like this:
$('#tryBTN').click( function() {
$('.showme').each( function( i, element ) {
if( $(element).css('visibility') == 'hidden' ) {
$(element).css( 'visibility', 'visible' );
}
});
});
But you don't need to check whether an element has visibility:hidden before changing it to visibility:visible. You can just go ahead and set the new value. So you can simplify the code to:
$('#tryBTN').click( function() {
$('.showme').each( function( i, element ) {
$(element).css( 'visibility', 'visible' );
});
});
And now that the only thing we're doing inside the loop is setting the new visibility, we don't even need .each(), since jQuery will do the loop for us when we call .css(). (Thanks #TemaniAfif for the reminder.)
So the code becomes very simple:
$('#tryBTN').click( function() {
$('.showme').css( 'visibility', 'visible' );
});
I have been trying to use the following I found on fiddle (modified it a bit for this example). Not even sure if i'm posting this code correctly ... would be best to just look at the fiddle I guess.
{
filters[col] = text;
$(table).find('tr').each(function(i){
$(this).data('passed', true);
});
for(index in filters)
{
if(filters[index] !== 'any')
{
$(table).find('tr td:nth-child('+index+')').each(function(i){
if($(this).text().indexOf(filters[index]) > -1 && $(this).parent().data('passed'))
{
$(this).parent().data('passed', true);
}
else
{
$(this).parent().data('passed', false);
}
});
}
}
$(table).find('tr').each(function(i){
if(!$(this).data('passed'))
{
$(this).hide();
}
else
{
$(this).show();
}
});
}
Basically I will have a table with, lets say, 100 rows, and each row will have a column with a timer value in it, e.g. 10 min or 15 min. When a user clicks the appropriate "custom filter" like 10 min, the table will be filtered to only show all entries with 10min. So far it works 100%.
But, when a user might filter anything with one digit, like 5 min or 1 min it throws out, well everything for example user filters by 5 min, now it throws out 5 min, 15 min, 45 min etc.
In the example the 10, 15, 45 and 59 min filters does their job correctly. The 5 and 9 min buttons filters wrong, you will see what i mean in the example.
Are there any way to remedy that situation, so that when 5 min filter is clicked it only loads table columns with the value 5 min? I have seen something similar in another fiddle (which i can't find right now) think it was called a regular expression and not a indexOf ... this was for a search function within a table but it worked.
Please let me know if you need more information or a better description.
Here's a much simpler approach that uses filter() and eq() and only loops the rows once
function apply_filter(table, col, text) {
var $rows = $(table).find('tr');
if (text === 'any') {
$rows.show();
} else {
// hide all rows then filter the ones to show
$rows.hide().filter(function() {
return $(this).children().eq(col - 1).text().trim() === text;
}).show();
}
}
DEMO
I have child divs that I'm trying to sort based on a jquery .data() value that I give them that is just a single number. This code works perfectly, but only once, after that I can't figure out how the heck it's sorting them. Here is a simplified version:
var myArray = $('#container div').get();
myArray.sort(function(x,y) {
return $(x).data('order') - $(y).data('order');
});
$('#container').empty().append(myArray);
I've tried so many other different methods of sorting, other plugins, etc., and I can't get anything to work right. This is as close as I can get. I just have this running on a jquery change event.
Here is the whole thing in case I'm doing something stupid elsewhere:
$('#attorneyFilter').change(function() {
//get array of links for sorting
var myArray = $('#attorneyBlocks div').get();
var selectedArea = $(this).val();
//sort alphabetically when "all" is selected
if (selectedArea == 'all') {
$('#attorneyBlocks div').show();
myArray.sort(function(a,b) {
return $(a).text() > $(b).text() ? 1 : -1;
});
//filter attorneys based on practice area and then assign its order# to the div with data, getting all values from the div's class
} else {
$('#attorneyBlocks div').hide().each(function() {
var attorneyArea = $(this).attr('class').split(', ');
for (var i=0;i<attorneyArea.length;i++) {
var practiceArea = attorneyArea[i].split('-');
if (selectedArea == practiceArea[0]) {
$(this).show().data('order',practiceArea[1]);
}
}
});
//sort based on order, the lower the number the higher it shows up
myArray.sort(function(x,y) {
return $(x).data('order') - $(y).data('order');
});
}
//append order back in
$('#attorneyBlocks').empty().append(myArray);
});
And a link to the page in question
Here's a jsFiddle with this working using .detach() instead of .empty() to keep the data.
http://jsfiddle.net/shaneblake/Tn9u8/
Thanks for the link to the site, that made it clear.
It seems to me you never clear out the data from the prior time. You hide everything but maybe something like this will solve your problem (here I set everything hidden to the bottom, you can clear it or use a different value -- as long as it is not the same as any sort key):
$('#attorneyBlocks div').hide().data('order',999999).each(function() {
var attorneyArea = $(this).attr('class').split(', ');
for (var i=0;i<attorneyArea.length;i++) {
var practiceArea = attorneyArea[i].split('-');
if (selectedArea == practiceArea[0]) {
$(this).show().data('order',practiceArea[1]);
}
}
});
Also, the code on the server is missing the 2nd line you have above:
var myArray = $('#attorneyBlocks div').get();
The problem is the change event is tied to the original items. After the sort you make all new items. They don't have any event tied to them. You will need to use .live()
Eventually figured it out, the data values from hidden divs were screwing with my sorting, so I changed my sorting code to only pay attention to :visible divs and that did the trick. Doh! Thanks for your help everyone.
Want to have a notification box displayed if amount in fieldA is higher than amount in fieldB.
Currently have some code working but the notification box toggles on and off not depending on the actual amount.
What am I missing?
jquery:
$(document).ready(function() {
$('#fieldA').change(function(){
if($(this).val()>$('#fieldb').val()){
//display it on the form
$('.labelNotification').toggle();
$('.labelNotification').append('Not recommended to have FieldA figure higher than FieldB.');
}
})
});
HTML:
< p style="display: none;" class="error labelNotification">
This is tailor-made for the toggle(boolean) method. Also, you have to be careful about appending to the notification label ... what if the user changes his answer twice? It's better to have multiple notification objects, each of which can contain stuff for a single type of notification.
$(function() {
$('#fieldA').change(function() {
var isLarger = +$(this).val() > +$('#fieldB').val(); // Note: convert to number with '+'
var $labelNotification = $('.labelNotification');
$labelNotification.toggle(isLarger);
if (isLarger) {
//display it on the form
$labelNotification.html('Not recommended to have FieldA figure higher than FieldB.');
}
})
});
If you're comparing numerical values (which it seems like you are), you should use parseInt or parseFloat to convert the (string) value returned by val() to an integer. According to the documentation for val, the function always returns a string value.
I found the problem ,
First thing is you need to have semicolon properly as below
$('#fieldA').change(function () {
if ($(this).val() > $('#fieldB').val()) {
alert("its greater");
//display it on the form
$('.labelNotification').append('Not recommended to have FieldA figure higher than FieldB.');
$('.labelNotification').show();
}
else {$('.labelNotification').hide();
$('.labelNotification').html('');}
});
Second thing , when you toggle it it won't show for the second time
if 40 > 30
and again if you entery 50 and 50 > 30 it won't show
this is second problem
final problem is empty the label all the time
$('.labelNotification').html('')'
Toggle is not the best approach for your situation.
You want to compare and then decide.
Since you are looking at numbers I would strongly suggest using a number type to do the comparison, either using parseInt() or parseFloat().
The text in the notification label only needs to be set once, since you don't have any comment for it showing something when B > A. I would suggest setting this in your HTML.
<span class="labelNotification" style="display:none">Your Warning Text</span>
<!-- if your CSS class has `display:none` remove the style attribute -->
as for the jQuery.
$(function() {
$("#fieldA").change(function() {
var a = parseInt($(this).val());
var b = parseInt($("#fieldb").val());
// handle if a or b is not a number --> isNaN(a) || isNaN(b)
if( a > b ) {
$('.labelNotification').show()
} else {
$('.labelNotification').hide()
}
});
});