jQuery Calculate Issue - javascript

I am creating an Invoicing System, using jquery.calculate.
var newIDSuffix = 2;
$(".invoice_items").delegate('#add-row', 'click', function () {
var lastRow = $("tr.lastrow");
var cloned = $("tr.default").clone().removeAttr('class');
cloned.find('td#total_item_1').each(function() {
$(this).attr('id', 'total_item_'+2);
});
cloned.find('input, select').each(function() {
var id = $(this).attr('id'),
name = $(this).attr('name');
id = id.substring(0, id.length-1) + newIDSuffix;
$(this).attr('id', id);
});
cloned.insertBefore(lastRow).find('input:text').val('');
newIDSuffix++;
});
// update the plug-in version
$("#idPluginVersion").text($.Calculation.version);
// bind the recalc function to the quantity fields
$("input").bind("keyup", recalc);
// run the calculation function now
recalc();
$("input").bind("keyup", recalc);
// run the calculation function now
recalc();
Here's what I have done so far. http://jsfiddle.net/aliharis/VXZe8/
The problem is once I add a row dynamically, and when I enter the values to it, It doesn't update the amount column and total. But If I enter values for the dynamically added row and go back to first row and enter values, It makes the calculation including the dynamically added fields.
I couldn't figure out whats going wrong.

add the line:
cloned.bind("keyup", recalc);
right after this line:
cloned.insertBefore(lastRow).find('input:text').val('');
to bind a click event to the new element.
.. or alternatively use .on() instead of bind here:
$("input").on("keyup", recalc);

Related

Angular JS calculation based on input boxes

I read this thread:
Simple Percentage Calculation of an Input Field with JQuery
But can't seem to get it to work for my situation. I have two input boxes, Wholesale and Sell Price, and I want to calculate the markup (difference) on the fly as the user is changing their Sell Price. I've built a simplified version of what I'm trying to do here:
http://jsfiddle.net/schuss/rp0brqj1/2/
And below is the JS - can anyone see what I'm doing wrong? Thanks!!
$(function() {
// cache elements that are used at least twice
var $sellprice = $("#SellPrice"),
$markup = $("#markup"),
$wholesale = $("#wholesale");
// attach handler to input keydown event
$sellprice.keyup(function(e){
if (e.which == 13) {
return;
}
var sellprice = parseFloat($sellprice.val()),
markup = sellprice-wholesale;
if (isNaN(sellprice)) {
$markup.hide();
return;
}
else {
$markup.fadeIn().text(markup.toFixed(2));
}
});
});
You want to set the value of input field, so in this case you need to use $.fn.val method:
$markup.fadeIn().val(markup.toFixed(2));
Demo: http://jsfiddle.net/rp0brqj1/6/
Try this (I haven't included the else - and don't forget to include JQuery in your fiddles!):
$(function() {
var $sellprice = $("#SellPrice"),
$markup = $("#markup"),
$wholesale = $("#Wholesale");
$sellprice.on('keyup', function(){
$markup.val(parseFloat($sellprice.val()-$wholesale.val()))
});
});
Fiddle

jQuery .click() Not Executing for Cloned Element

I'm running into a bug with my code. I am cloning a div so that the user can add multiple customers.
var num = $('.clonedInput').length; // how many "duplicatable" input fields we currently have
var newNum = new Number(num + 1); // the numeric ID of the new input field being added
var newElem = $('#divInput' + num).clone().attr('id', 'divInput' + newNum); // create the new element via clone(), and manipulate it's ID using newNum value
// clear input value for cloned items and do not remove text for del button.
newElem.find('input:not(.DeleteBtn),textarea').val('');
//newElem.find('input[type="submit"]
// Replace clone num with incremental num.
newElem.find(':input').each(function () {
$(this).attr('id', $(this).attr('id').replace(/\d+/, newNum));
$(this).attr('name', $(this).attr('name').replace(/\d+/, newNum));
});
// insert the new element after the last "duplicatable" input field
$('#divInput' + num).after(newElem);
I have provided a delete button to delete rows and I am using the class name for the button to execute a function on click .
$(".DeleteBtn").click(function () {
alert(".DeleteBtn Click Function - " + $(this).attr('id'));
var DelBtnNum = $(this).attr('id');
DelBtnNum = DelBtnNum[DelBtnNum.length - 1];
$('#divInput' + DelBtnNum).remove();
});
I am able to delete the first (original) input row, but any additional customer rows are not deleted.
I have a running demo of the code located here: http://jsfiddle.net/crjunk/FB4BZ/2/
Why will the cloned items not fire the .DeleteBtn.click function?
You need to use event delegation for supporting dynamic elements.
Since you have used jQuery 1.6 in the fiddle
$(document).delegate(".DeleteBtn", 'click', function () {
alert(".DeleteBtn Click Function - " + $(this).attr('id'));
var DelBtnNum = $(this).attr('id');
DelBtnNum = DelBtnNum[DelBtnNum.length - 1];
$('#divInput' + DelBtnNum).remove();
});
if jQuery >= 1.7
$(document).on('click', ".DeleteBtn", function () {
alert(".DeleteBtn Click Function - " + $(this).attr('id'));
var DelBtnNum = $(this).attr('id');
DelBtnNum = DelBtnNum[DelBtnNum.length - 1];
$('#divInput' + DelBtnNum).remove();
});
Another option is to clone the element along with the event using clone(true)
Because the default when using clone is to not clone events. Try passing true to clone():
var newElem = $('#divInput' + num).clone(true).attr('id', 'divInput' + newNum); // create the new element via clone(), and manipulate it's ID using newNum value
jsFiddle example
As the .clone() docs state:
.clone( [withDataAndEvents ] ) withDataAndEvents (default: false)
When you bound the click event, only one div existed, so it is the only one that has a click handler. You should change your code to use on instead of click.
$(document).on('click', ".DeleteBtn", function () {
try going on with .on('click',function(e){ ... }); or use live() selector (but i think live goes deprecated...)
so in your case
$(".DeleteBtn").on('click',function () { ..

function called repeatedly in javascript

I define a tag picker which will generate checkbox inputs based on "group". If I select the tags I want and press done button, it should return a string to set the value of a text input.
Here are the related codes. The problem is it only works well at the first time. For example, for the first time, if I checked 'jquery','javascript' in the tags,
console.log('output is:' + tags);
print out 'output is: jquery,javascript'. Works!
Then I use it again and select 'jquery','javascript','bootstrap',
it will return
output is: jquery,javascript,bootstrap
output is:
One more time for 'jquery','javascript','bootstrap', it returns
output is: jquery,javascript,bootstrap
output is:
output is:
Seems the done button pressed, the function is called repeatedly. Being stuck with it for several hours but can't figure out. Really appreciate for your answer! Thanks
(function(){
$.fn.tagPicker = function(source,options){
var settings = $.extend({
perRow : 3
},options);
$.fn.attachRow = function(row,col){
//codes here
...
}
$.fn.attachPicker = function(){
//codes here
// generate html for checkbox inputs
...
};
var $input = this;
if($('.tag-picker').length == 0){
$input.attachPicker();
$('body').on('click','.tag-picker .close-picker',function(){
$('.tag-picker').remove();
})
$('.tag-picker .close-picker').off();
$('body').on('click','.tag-picker #btn-done', function(){
var tags = getTags();
$('.tag-picker').remove();
console.log('output is:' + tags);
$input.val(tags);
});
}
function getTags(){
var t = [];
$('.tag-picker input').each(function(){
if($(this).is(':checked')) t.push($(this).attr('id'));
})
return t.join(',');
}
}
})(jQuery);
$('body').on('click','input.participant',function(){
$(this).val('');
$(this).tagPicker(group);
})
You are initialising the plugin every time the elements are clicked. You should initialise it once, on DOM ready.
OR if you want to do this anyway; you could use .one() for the event to run only once and remove itself. Use .off() to detach an event, attached with .on().

Jquery creating checkboxs dynamically, and finding checked boxes

I have information that comes out of a database and gets put into a list with a checkbox by each element. This is how it is currently done:
function subjects(){
$.ajax({
url: "lib/search/search.subject.php",
async: "false",
success: function(response){
alert(response);
var responseArray = response.split(',');
for(var x=0;x<responseArray.length;x++){
$("#subjects").append("<br />");
$("#subjects").append(responseArray[x]);
$("#subjects").append("<input type='checkbox' />");
}
}
});
}
it works fine, but I need a way to pick up on if a checkbox is clicked, and if it is clicked then display which one was clicked, or if multiple ones are clicked.
I can't seem to find a way to pick up on the checkboxs at all.
the response variable is "math,science,technology,engineering"
Because you are populating the Checkboxes Dynamically you need to Delegate the event
$("#subjects").on("click", "input[type='checkbox']", function() {
if( $(this).is(":checked") ) {
alert('Checkbox checked')
}
});
To better capture the data it is better if you encase the corresponding data into a span , so that it can be easier to search..
$("#subjects").append('<span>'+responseArray[x] + '</span>');
$("#subjects").on("click", "input[type='checkbox']", function() {
var $this = $(this);
if( $this.is(":checked") ) {
var data = $this.prev('span').html();
alert('Current checkbox is : '+ data )
}
});
It would be best to give your dynamically injected checkboxes a class to target them better, but based on your code try:
$("#subjects").on("click", "input", function() {
if( $(this).is(":checked") ) {
// do something
}
});
Since your input elements are added dynamically, you need to use jQuery's .on() function to bind the click event to them. In your case you need to use .on() to bind to an element that exist in the DOM when the script is loaded. In your case, the element with the ID #subjects.
This note from the docs is mainly for machineghost who downvoted my answer for no apparent reason:
Event handlers are bound only to the currently selected elements; they
must exist on the page at the time your code makes the call to .on().
To ensure the elements are present and can be selected, perform event
binding inside a document ready handler for elements that are in the
HTML markup on the page. If new HTML is being injected into the page,
select the elements and attach event handlers after the new HTML is
placed into the page.
$('#subjects input[type=checkbox]').on('click',function(){
alert($(this).prop('checked'));
});
or the change event: in case someone uses a keyboard
$('#subjects input[type=checkbox]').on('change',function(){
alert($(this).prop('checked'));
});
simple fiddle example:http://jsfiddle.net/Dr8k8/
to get the array example use the index of the inputs
alert($(this).prop('checked') +'is'+ $(this).parent().find('input[type=checkbox]').index(this)+ responseArray[$(this).parent().find('input[type=checkbox]').index(this) ]);
simplified example: http://jsfiddle.net/Dr8k8/1/
EDIT: Just for an example, you could put the results in an array of all checked boxes and do somthing with that:
$('#subjects>input[type=checkbox]').on('change', function() {
var checklist = [];
$(this).parent().find('input[type=checkbox]').each(function() {
$(this).css('background-color', "lime");
var myindex = $(this).parent().find('input[type=checkbox]').index(this);
if ($(this).prop('checked') == true) {
checklist[myindex] = responseArray[myindex];
}
});
$('#currentlyChecked').text(checklist);
});
EDIT2:
I thought about this a bit and you can improve it by using .data() and query that or store it based on an event (my button called out by its id of "whatschecked")
var responseArray = ['math', 'science', 'technology', 'engineering'];// just for an example
var myList = '#subjects>input[type=checkbox]';//to reuse
for (var x = 0; x < responseArray.length; x++) {
// here we insert it all so we do not hit the DOM so many times
var iam = "<br />" + responseArray[x] + "<input type='checkbox' />";
$("#subjects").append(iam);
$(myList).last().data('subject', responseArray[x]);// add the data
}
var checklist = [];// holds most recent list set by change event
$(myList).on('change', function() {
checklist = [];
$(myList).each(function() {
var myindex = $(this).parent().find('input[type=checkbox]').index(this);
if ($(this).prop('checked') == true) {
checklist.push($(this).data('subject'));
alert('This one is checked:' + $(this).data('subject'));
}
});
});
// query the list we stored, but could query the checked list data() as well, see the .each() in the event handler for that example
$("#whatschecked").click(function() {
var numberChecked = checklist.length;
var x = 0;
for (x = 0; x < numberChecked; x++) {
alert("Number " + x + " is " + checklist[x] + " of " + numberChecked);
}
});
live example of last one: http://jsfiddle.net/Dr8k8/5/
The general pattern to do something when a checkbox input is clicked is:
$('input[type=checkbox]').click(function() {
// Do something
})
The general pattern to check whether a checkbox input is checked or not is:
var isItChecked = $('input[type=checkbox]').is(':checked');
In your particular case you'd probably want to do something like:
$('#subjects input[type=checkbox]').click(function() {
to limit the checkboxes involved to the ones inside your #subjects element.

Create hidden field element for each drop

I know this is a similar question to my previous one however its slightly different.
I have this script adding each 'dropped' element to a list. Now i need it adding into a variable / hidden field so i can pass it to the next page via a form.
When i run it at the moment. It alerts for each one however, it does it not just for every item dropped but if there are 10 items dropped it will run 10 times per item droped rather than once per item dropped.
Any help would be great.
//Record and add dropped items to list
var txt = $("#listbox");
var dtstart = copiedEventObject.start + '\n'
var caltitle = copiedEventObject.title
var txt = $('#listbox');
txt.append("<li class ='listItem'> "+dtstart +"</li>")
var listItems = $('.listItem');
$('#calendarform').submit(function() {
listItems.each(function(){ //For each event do this:
alert( listItems.text() );
});
return false;
});
// remove the element from the "Draggable Events" list
$(this).remove();
the problem lies in this code
listItems.each(function(){ //For each event do this:
alert( listItems.text() );
});
you are alerting the text of all the list items for each list item.
use jQuery(this) to access the current item within an each block
listItems.each(function(){ //For each event do this:
alert( $(this).text() );
});
Assuming your code is within a drop event handler, you are also adding a submit handler each time you drop. This means that each time you drop, you queue up another submit event. This is probably not desired. Move this submit(function(){}) block outside your drop handler to prevent it from firing that function more than once.
$('#calendarform').submit(function(e) {
var listItems = $('.listItem');
listItems.each(function(){ //For each event do this:
alert( listItems.text() );
});
e.preventDefault();//stop normal behavior
return false;
});
and to create elements on the fly you just pass jQuery the html, and append it to your form.
$('<input type="hidden" name="listItem[]"/>').appendTo("#calendarForm").val(listItem.text())
you may have to fiddle with the name element to get it to submit as an array in your server side language, but you're also within an each loop, which provides you with an index, so you can do the following.
$('#calendarform').submit(function(e) {
var form = $(this);
var listItems = $('.listItem');
listItems.each(function(index){ //For each event do this:
var listItem = $(this);
$("<input type='hidden'/>").val(listItem.text()).appendTo(form).attr('name', 'listItem[' + index + ']');
});
e.preventDefault();//stop normal behavior
return false;
});

Categories

Resources