Quick and simultaneous ajax call - javascript

I am currently working on add sale for POS using laravel. Here we can use barcode to scan the product code, when barcode is entered it then calls check function, if same product code is found in the cart table then it simply adds the quantity value by 1 else it make an ajax call which will return the detail of that particular product. My jQuery function looks like this:
function check() {
if ($(".product_code").length) {
var product_code = $("#product_code").val();
var total = $('#cart_contents tr').length;
$('#cart_contents tr').each(function(index) {
var p_code = $(this).find(".product_code").val();
if (product_code == p_code) {
var num = +$(this).find('.product_quantity').val() + 1;
$(this).find('.product_discount').val(0);
$(this).find('.product_quantity').val(num).keyup();
return false;
} else if (index === total - 1) {
populatecart();
}
});
} else {
populatecart();
$(".cart_content_area").hide();
}
}
function populatecart() {
var product_code = $("#product_code").val();
$.ajax({
url: "{{ url('getproductdata')}}",
data: {
p_id: product_code
},
datatype: "JSON",
type: "get",
success: function(data) {
if (data == 'null') {
alert('No product code found!');
} else {
$.each(data, function(k, v) {
$("#cart_contents").append('<tr>' +
'<td class="quantity"> {!! Form::text('sales_quantity[]', 1, ['class'=>'product_quantity form-control']) !!} </td>' +
'<td class="product_codes"><input type="text" name="product_code[]" value="' + v["product_code"] + '" class="form-control product_code" readonly/></td>' +
'<td><input type="text" name="product_name[]" value="' + v["product_name"] + '" class="form-control product_name" readonly/> </td>' +
'<td><input type="text" name="unit_value[]" value="' + v["sell_price"] + '" class="form-control unit_value" readonly/></td>' +
'<td>{!! Form::text('product_discount[]', 0, ['class'=>'product_discount form-control']) !!}</td>' +
'<td><input type="text" name="line_total[]" value="' + v["sell_price"] + '" class="form-control line_total" readonly/></td>' +
'<td class="remove_row"><input name="product_id[]" type="hidden" value="' + v["id"] + '" /><button type="button" class="removebutton" title="Remove this row">X</button></td>' +
'</tr>');
calculateTotalSum();
});
}
}
});
}
However, the problem here is that when I try to scan same product(ie; product having same product code) simultaneously it adds up the quantity but if i try the same thing really quick, the same product is populated into two different rows of the cart table but what I actually want is to have the quantity value of the product be 2 instead of creating 2 rows for same product code.
How can I deal with this problem?

rather than use callback based api.
I suggest you use promise based .
the flow goes like this.
var cart = {};
if(cart[product_code] == undefined)
{
cart[product_code] = $.ajax(url: "{{ url('getproductdata')}}" ,
data:{
p_id:product_code
},
datatype:"JSON",
type: "get");
cart[product_code].done(function(data){
//do the initialization
});
}
else
{
cart[product_code].done(function(){
//do the update.
});
}

The ajax calls may overlap.
You should probably do the check for existance in the ajax callback only, not already in check();

Related

Insert multiple data from input Laravel

I'm making a quiz system. I have 3 tables:
tests table
id,
title,
total_question,
time,
status,
id_subject
questions table:
id,
content,
optA,
optB,
optC,
optD,
answer,
unit,
id_subject
questions_of_test table:
id,
id_test,
id_question
When I create a test, after I select subject, base on the number of unit of that subject will show a number of textbox to fill a number of question for each unit.
Example, the subject I selected have 3 unit. It will show 3 textboxes and I fill:
Textbox1: 1
Textbox2: 2
Textbox3: 1
Total is 10 question.
How can I insert this 10 question to questions_of_test table.
This is my some code to show texbox from dropdownlist:
$('select').select();
function get_units() {
var id = $('#id_subject').val();
var list = $('#list_unit');
list.empty();
var url = "{{ route('test.getunit', ':id') }}";
url = url.replace(':id', id);
var success = function (result) {
if (result.length <= 0) {
var item = '<div class="form-group"><div class="col-sm-12"><input type="text" disabled value="This subject have no question" class="form-control" style="color: #26c6da;"></div></div>';
list.append(item);
} else {
for (i = 0; i < result.length; i++) {
var item = '<div class="form-group"><label for="unit-' + result[i].unit+ '" class="col-sm-12 control-label" style="font-size: medium;">Enter number of question of unit ' + result[i].unit+ ' (have' + result[i].Total + ' questions) <span class="failed">(*)</span></label><div class="col-sm-12"><br><input type="number" min="0" max="' + result[i].Total + '" class="unit_input form-control" onchange="set_sum(' + result[i].Total + ')" name="unit-' + result[i].unit+ '" id="unit[' + result[i].unit+ '][]" required></div></div>';
list.append(item);
}
}
};
$.get(url, success);
}
I got an array like this:
I want to Insert random(1) where id_subject = select_id and unit = 1, random(2) where id_subject = select_id and unit = 2... How can I get it?
<input type="number" name="unit['+result[i].chuong+'][]"></input>

Cannot Read Property of Dynamically Created Checkbox after DOM is Loaded

I have an application that allows users to select one or more courses. The user may choose to save the selected courses and come back later to finish the process. When/if the user returns, I recreate the list of checkboxes. Then, I try to find all the input checkboxes within that div. I log it to the console, and it returns an empty collection. How do I obtain the checkboxes properties?
The empty div that is populated with the checkboxes.
<div class="courseList applyBackgroundColor" id="UserCheckList">
</div>
Where I am doing the post and creating the dynamic textboxes using the result.
var createCourse = function(studentID)
{
var StudentCourseList = '<table><tbody>';
do post here
$.each(result, function (index, item) {
StudentCourseList += '<td valign="top" style="width:1%" id=td.ck.' +
item.ID + '><div class=""><input type="checkbox" class="checkbox"
id="'+ item.ID + '" value="' + item.ID + '" /></div></td>
<td valign="top" style="width:30%;padding:.25em;" id="' + item.ID +
'"><span id="span.' + item.ID + '" title="' + item.Description + '">'
+ item.Description +'</span></td>';
}
$('#UserCheckList').html(StudentCourseList );
}
Checking if there is a student id when the page loads.
$(function(){
var studentID = $('#studentID').val();
if(studentID !==''){
createCourse(studentID);
var listCheckUsers = $('.courseList').find('input[type=checkbox]');
console.log(listCheckUsers);
if I put a breakpoint next to listCheckUsers and debug it, the result that is displayed in the console is shown below:
Object[input#MAC201.checkbox attribute value = "MATH 201",
input#ENC101.checkbox attribute value = "ENGLISH 101",....]
}
without the breakpoint, I see an empty object
Object[]
});
Updated: Adding the exact JQuery message.
//This is shown when I do not use a breakpoint.
1. jQuery.fn.init[0]
1. context: document
2. length: 0
3. prevObject: jQuery.fn.init[1]
1. 0: div#UserCheckList.Display
2. context: document
3. length: 1
4. selector: "#UserCheckList"
5. __proto__: jQuery[0]
4. selector: "#UserCheckList input[type=checkbox]"
5. __proto__: jQuery[0]
You were missing the className courseList in the table element.
update
I simulated an Ajax request by using setTimeout. You can remove the setTimeout code and put an Ajax request in place. When the data is returned run your callback function with the data.
function getResults(studentID, callback) {
// Async call.
setTimeout(function() {
// Replace generator with Ajax call
var result = [];
for (var i = 0; i < 10; i++) {
var item = {
ID: i,
"Description": "Result #" + i
};
result.push(item);
}
// Run this when data returns.
callback(result);
}, 3000);
// Show loading while we wait.
$('.UserCheckList').html('loading...');
}
function showResults(result) {
var StudentCourseList = '<table class="courseList"><tbody>';
$.each(result, function(index, item) {
StudentCourseList += '<tr><td valign="top" style="width:1%" id=td.ck.' +
item.ID + '><div class=""><input type="checkbox" class="checkbox"\
id="' + item.ID + '" value="' + item.ID + '" /></div></td>\
<td valign="top" style="width:30%;padding:.25em;" id="' + item.ID +
'"><span id="span.' + item.ID + '" title="' + item.Description + '">' + item.Description + '</span></td></tr>';
});
$('.UserCheckList').html(StudentCourseList);
}
$(function() {
var studentID = $('#studentID').val();
if (studentID !== '') {
getResults(studentID, function(results) {
// callback when results are complete.
showResults(results);
var listCheckUsers = $('.courseList').find('input[type=checkbox]');
console.log(listCheckUsers);
});
}
}); //end
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="UserCheckList"></div>

How to reload a jQuery plugin when appending new data to window. No reload() method provided

I'm working on a site where a user can create however many domains he wishes on a server. Each domain can belong to a group(this overall does nothing to the domain itself it's there for easier sorting).
A user can add/delete/modify each group separately.
I'm using a jQuery plugin called Spectrum so that a user can assign a color to each of his groups. See here.
I'm doing some ajax to dynamically update the groups(change the color/name). Everything is working great, except for one thing: the above mentioned plugin doesn't work properly for appended html(which I suppose is to be expected).
Normally for such a thing I'd reload the plugin, however I don't see any method in the documentation that would allow me to do that.
Is there some other way that I could reload it? Maybe some jQuery method? Bind to some event? Something?
Any help is appreciated.
function ajaxAddDomainGroup(group_color_add, group_name_add) {
$.ajax({
url: "<?= URL::route('domains_ajax_add_group'); ?>",
type: 'POST',
data: 'data[group_name]=' + group_name_add + '&data[group_color]=' + group_color_add,
success: function (data)
{
if(data.status == 'OK') {
$.notify('Group added successfully.', {
type: 'info',
delay: 120000
});
$('#js--groups_table tr:first').before(
'<tr>' +
'<td class="ccs-table__label" style="background-color: ' + data.data.group_color + '!important;"' + '>' + data.data.group_name + '</td>' +
' <td class="ccs-table__action js--groups_edit">' +
'<span class="icon-edit-ccs icon-ccs"></span>' +
'</td>' +
'<td class="ccs-table__action"><a id="delete_' + data.data.id + '" class="ccs-groups_delete" href="#"><span class="icon-delete-ccs icon-ccs"></span></a></td>' +
'</tr><tr><td colspan="3"><div class="js--edit_info css-hide_edit_info box__controls">' +
'<div class="col-md-6"> <input class="input--block js--input_group_name_edit" type="text" placeholder="New group name">' +
'</div><div class="col-md-6"><a class="btn btn--action btn--default js--group_edit btn__text" id="js--edit_' + data.data.id + '" href="#">Modify</a>' +
'<input class="js--spectrum-color-edit"/> <input type="hidden" class="js--group_color_edit" value="#000000"/> </div> </div> </td> ' +
'</tr>'
);
}
else {
$.notify('An error has occurred when trying to add the group.', {
type: 'info',
delay: 120000
});
}
}
});
}
function ajaxEditDomainGroup(group_name_edit, group_color_edit, group_id_edit) {
$.ajax({
url: "<?= URL::route('domains_ajax_edit_group'); ?>",
type: 'POST',
data: 'data[new_group_name]=' + group_name_edit + '&data[new_group_color]=' + group_color_edit + '&data[group_id]=' + group_id_edit,
success: function (data)
{
if(data.status == 'OK') {
$.notify('Group edited successfully.', {
type: 'info',
delay: 120000
});
$('#js--edit_' + group_id_edit).closest('tr').prev('tr').find('td:first-child').replaceWith(
'<td class="ccs-table__label" style="background-color: ' + group_color_edit + '!important;">' + group_name_edit + '</td>'
);
}
else {
$.notify('An error has occurred when trying to edit the group.', {
type: 'info',
delay: 120000
});
}
}
});
}
$('body').on('click','.js--group_edit', function() {
var group_name_edit = $(this).closest('td').find('.js--input_group_name_edit').val();
var group_color_edit = $(this).closest('td').find('.js--group_color_edit').val();
var group_id_edit = parseInt($(this).attr('id').replace(/[^\d]/g, ''), 10);
if($.trim(group_color_edit) == '') {
alert('The group color is required.');
return false;
}
else if( $.trim(group_name_edit) == '') {
alert('The group name is required.');
return false;
}
ajaxEditDomainGroup(group_name_edit, group_color_edit, group_id_edit);
});
Relevant html:
#foreach($domain_groups as $key => $domain_info)
<tr>
<td class="ccs-table__label"
#if(isset($domain_info['color']) && $domain_info['color'] != ''))
style="background-color: {{ $domain_info['color'] }}!important;"
#endif
>{{ $domain_info['group_name']; }}
</td>
<td class="ccs-table__action js--groups_edit">
<span class="icon-edit-ccs icon-ccs"></span>
</td>
<td class="ccs-table__action"><a id="delete_{{ $domain_info['id'] }}" class="ccs-groups_delete" href="#"><span class="icon-delete-ccs icon-ccs"></span></a></td>
</tr>
<tr>
<td colspan="3">
<div class="js--edit_info css-hide_edit_info box__controls">
<div class="col-md-6">
<input class="input--block js--input_group_name_edit" type="text" placeholder="New group name">
</div>
<div class="col-md-6">
<a class="btn btn--action btn--default js--group_edit btn__text" id="js--edit_{{ $domain_info['id'] }}" href="#">Modify</a>
<input class="js--spectrum-color-edit"/>
<input type="hidden" class="js--group_color_edit" value="#000000"/>
</div>
</div>
</td>
</tr>
#endforeach
Spectrum init and such:
$(".js--spectrum-color-edit").spectrum({
color: '#000',
showAlpha: true,showInput: true,
// Set the hext value of the color to a hidden input
move: function(color){
$(this).closest('td').find('.js--group_color_edit').val(color.toHexString());
}
});
I realize this isn't the most easy-on-the-eyes code. Odds are it's gonna be refactored in the future using angular or something like that.
You need to apply spectrum to any newly created matching elements within the dynamically loaded rows:
var $newtr = $('<tr>' +
'<td class="ccs-table__label" style="background-color: ' + data.data.group_color + '!important;"' + '>' + data.data.group_name + '</td>' +
' <td class="ccs-table__action js--groups_edit">' +
'<span class="icon-edit-ccs icon-ccs"></span>' +
'</td>' +
'<td class="ccs-table__action"><a id="delete_' + data.data.id + '" class="ccs-groups_delete" href="#"><span class="icon-delete-ccs icon-ccs"></span></a></td>' +
'</tr><tr><td colspan="3"><div class="js--edit_info css-hide_edit_info box__controls">' +
'<div class="col-md-6"> <input class="input--block js--input_group_name_edit" type="text" placeholder="New group name">' +
'</div><div class="col-md-6"><a class="btn btn--action btn--default js--group_edit btn__text" id="js--edit_' + data.data.id + '" href="#">Modify</a>' +
'<input class="js--spectrum-color-edit"/> <input type="hidden" class="js--group_color_edit" value="#000000"/> </div> </div> </td> ' +
'</tr>');
$('#js--groups_table tr:first').before($newtr)
$(".js--spectrum-color-edit", $newtr).spectrum({
color: '#000',
showAlpha: true,
showInput: true,
// Set the hext value of the color to a hidden input
move: function (color) {
$(this).closest('td').find('.js--group_color_edit').val(color.toHexString());
}
});

JQuery Click function not responding to a click

I have the following JQuery script :
<script>
$(document).ready(function() {
setInterval(function() {
$.ajax({
type: "GET",
url: "<?php echo base_url(); ?>transactions/user_requests",
dataType: "JSON",
success: function(request) {
request_list = $('#request_list').empty();
if (request === null) {
request_list.append("<p>No Active Requests</p>");
}
else {
$.each(request, function(i, request) {
request_list.append('<ul><a class="request_list" id="request_list" href="#active_request_list">' + request.department_name + '</a></ul>');
$.ajax({
type: "GET",
url: "<?php echo base_url(); ?>transactions/user_requests_detials",
dataType: "JSON",
success: function(request_list) {
request_list_details = $('#request_list_details').empty();
if (request_list === null) {
request_list_detials.append("<ul>No Active Requests</ul>");
} else {
$.each(request_list, function(i, request_list) {
request_list_details.append('<dt span="font_color:white !important;">' + request_list.department_name + '</dt>\n\
<dd><label style="float:left !important;">Commodity Name:</label><span style="color:red !important;">' + request_list.commodity_name + '</span></dd>\n\
<dd><label style="float:left !important;"> Quantity Requested:</lable><span style="color:red !important;">' + request_list.total_quantity_requested + '</span></dd>\n\
<dd><label style="float:left !important;">Request Order ID:</label><span style="color:red !important;">' + request_list.request_order_id + '</span></dd>\n\
<dd><label style="float:left !important;">Date Requested : </label><span style="color:red !important;">' + request_list.date_added + '</span></dd> \n\
<a class="approve" id="approve" href="#stock_details">Approve </a>');
});
}
},
error: function(data) {
}
});
});
}
},
error: function(data) {
// alert('An error occured, kindly try later');
}
});
}, 2000);
});
</script>
<div class='request'>
<p>Request List</p><br>
<ul id='request_list'></ul>
</div>
The above loads a list of all requests made and a link for approving the details of the requests, when the link is clicked, the following script is supposed to run:
<script>
$(document).ready(function() {
alert('Alert!!!');
$('.approve').click(function() {
alert('Alert!!');
request_order_id = $('#request_order_id').val();
alert(request_order_id);
html1 = '';
htmlhead1 = '';
$.ajax({
type: "GET",
url: "<?php echo base_url();?>transactions/to_be_issued_details/" + request_order_id,
dataType: "json",
success: function(data) {
for (i = 0; i < data.length; i++) {
html1 += '<tr>\n\
<td><input type="text" id="commodity_name' + i + '" name="commodity_name[]" value="' + data[i].commodity_name + '"/></td>\n\
<td><input type="text" class="SmallInput" id="batch_no' + i + '" name="batch_no[]" value="' + data[i].batch_no + '"/></td>\n\
<td><input type="text" class="SmallInput" id="total_quantity_requested' + i + '" name="total_quantity_requested[]" value="' + data[i].total_quantity_requested + '"/></td>\n\
<td><input type="text" id="request_order_id' + i + '" name="request_order_id[]" value="' + data[i].request_order_id + '"/></td>\n\
<td><input type="text" class="SmallInput" id="total_quantity' + i + '" name="total_quantity[]" value="' + data[i].total_quantity + '"/></td>\n\
<td><input type="text" class="SmallInput" id="department' + i + '" name="department[]" value="' + data[i].department + '"/></td>\n\
<td><input type="text" class="SmallInput" id="user_name' + i + '" name="user_name[]" value="' + data[i].user_name + '"></td> \n\
<td></td><td></td></tr> ';
}
htmlhead1 += '\n\
<th>Commodity Name</th>\n\
<th>Batch Number</th> \n\
<th> Category</th> \n\
<th>Units per Pack </th> \n\
<th>No of Packs</th>\n\
<th>Total Quantity</th>\n\
';
$('#thead1').empty();
$('#tbody1').empty();
$('#thead1').append(htmlhead1);
$('#tbody1').append(html1);
},
error: function(data) {
}
})
});
});
</script>
Which is supposed to give me more details about the request, when I click the Approve button, the click function does not respond at all, which is the best way I can approach this problem?
This is because you are assigning the click event to .approve before it even exists.
What you want is to do this:
$("body").on("click", ".approve", function () {
//Your code
});
This way, using delegation, you assign a listener to the body (but preferably you should assign it to a less generic container like #request_list_details if it exists at the time you create the event listener) and the click event "bubbles up" trying to find an element with the class approve. This way you can dynamically add elements with that class and they still will respond to that event.
You can read more about it at the official jQuery API Documentation page.
Using delegation with on():
$('#request_list_details').on('click','.approve',function(){
//...
});

Counting number of field and limiting to 10

I have some code which uses this to allow to keep the same function code but apply it to different form elements which can be seen on a jsFiddle demo
//latest
var maxFields = 10,
currentFields = 1;
$('.form').on('click', '.add', function () {
var value_src = $(this).prev();
var container = $(this).parent().prev();
if ($.trim(value_src.val()) != '') {
if (currentFields < maxFields) {
var value = value_src.val();
var html = '<div class="line">' +
'<input id="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
$(html).appendTo(container);
value_src.val('');
currentFields++;
} else {
alert("You tried to add a field when there are already " + maxFields);
}
} else {
alert("You didn't enter anything");
}
})
.on('click', '.remove', function () {
$(this).parents('.line').remove();
currentFields--;
});
My issue is that I still want to be able to limit each section to only have 10 <inputs>, but at the moment each section shares the counter, so 5 in requirements and 5 in qualifications would trigger the 10 limit.
Is there a nice clean way of keeping the input field counter separate for each section?
What you need to do is store the current number of children for each list in a context sensitive way. There are a couple ways you could structure this (it would be easy using MVC libraries or the likes), but the simplest solution for your code will be to just use the DOM. So instead of using your global currentFields variable, instead use container.children().length to get the number of notes in the list you are currently operating on.
http://jsfiddle.net/9sX6X/70/
//latest
var maxFields = 10;
$('.form').on('click', '.add', function () {
var value_src = $(this).prev();
var container = $(this).parent().prev();
if ($.trim(value_src.val()) != '') {
if (container.children().length < maxFields) {
var value = value_src.val();
var html = '<div class="line">' +
'<input id="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
$(html).appendTo(container);
value_src.val('');
} else {
alert("You tried to add a field when there are already " + maxFields);
}
} else {
alert("You didn't enter anything");
}
})
.on('click', '.remove', function () {
$(this).parents('.line').remove();
});
You can add a class to each row like form-row
var html = '<div class="line form-row">' +
'<input id="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
and count the length by using
console.log($(container).find('.form-row').length);
// Use +1 because initially it is 0
Fiddle http://jsfiddle.net/9sX6X/69/
You can make use of the placeholder property to identify which button triggered the function.
value_src.attr('placeholder');
This string can then be used to access three different counters in an associative array.
Code
var maxFields = 10;
var currentFields = new Object;
$('.form').on('click', '.add', function () {
var value_src = $(this).prev();
var container = $(this).parent().prev();
if ($.trim(value_src.val()) != '') {
var identity = value_src.attr('placeholder');
if(currentFields[identity] == undefined)
currentFields[identity] = 0;
if (currentFields[identity] < maxFields) {
var value = value_src.val();
var html = '<div class="line">' +
'<input id="accepted" type="text" value="' + value + '" />' +
'<input type="button" value="X" class="remove" />' +
'</div>';
$(html).appendTo(container);
value_src.val('');
currentFields[identity]++;
} else {
alert("You tried to add a field when there are already " + maxFields);
}
} else {
alert("You didn't enter anything");
}
})
.on('click', '.remove', function () {
$(this).parents('.line').remove();
currentFields--;
});
JSFiddle: http://jsfiddle.net/9sX6X/73/

Categories