$().each(function() not getting proper dynamic data - javascript

I have an existing table with data coming from the database inside <input></input>. If I want to click the Add button or press Enter key, it should append a new row.
Once I enter a data in the newly added row, I compare it with my existing array or previously added data on the same table. If there's an existing data in either my array or in the same table, the <input></input> shall remain empty until I enter a data that is unique and automatically appends a new row and so on.
Currently, only the first Enter keypress is working.
Here's my HTML:
<table id="datatable-boxes" class="table table-hover table-bordered table-striped forex-datatable">
<thead>
<tr>
<th>Courier Tracking #</th>
<th>Courier</th>
<th>Vendor</th>
<th width="20%">Action</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="text" form="edit-boxes-form" class="form-control input-sm retrieve_track_no from_db" name="retrieve_courier_tracking_no[]" id="retrieve_courier_tracking_no_1" value="4987176601285" /></td>
<td><input type="text" form="edit-boxes-form" class="form-control input-sm from_db" name="retrieve_courier_name[]" id="retrieve_courier_name_1" value="Philpost" /></td>
<td><input type="text" form="edit-boxes-form" class="form-control input-sm from_db" name="retrieve_vendor_name[]" id="retrieve_vendor_name_1" value="Ebay" /></td>
<td class="box-action"><button class="btn btn-danger btn-xs clear-data" data-toggle="tooltip" data-toggle="modal" title="Delete Box data" data-target="#delete_box_modal_1"><span class='glyphicon glyphicon-trash' aria-hidden="true"></span></button></td>
</tr>
</tbody>
</table>
My JS:
$(function(){
// GET ID OF last row and increment it by one - Edit Boxes
var $lastRetChar = 1, $newRetRow;
$get_lastRetID = function(){
var str = $('#datatable-boxes tr:last-child td:first-child input').attr("id");
var index = str.lastIndexOf("_");
var result = str.substr(index+1);
var prev_char = $lastRetChar = parseInt(result);
var courier_name = $('#retrieve_courier_name_'+prev_char).val();
var vendor_name = $('#retrieve_vendor_name_'+prev_char).val();
$lastRetChar = $lastRetChar + 1;
$newRetRow = "<tr><td><input type='text' form='edit-boxes-form' class='form-control input-sm retrieve_track_no' name='retrieve_courier_tracking_no[]' id='retrieve_courier_tracking_no_"+$lastRetChar+"' autofocus='true'/></td><td><input form='edit-boxes-form' type='text' class='form-control input-sm' name='retrieve_courier_name[]' id='retrieve_courier_name_"+$lastRetChar+"' value='"+courier_name+"'/></td><td><input form='edit-boxes-form' type='text' class='form-control input-sm' name='retrieve_vendor_name[]' id='retrieve_vendor_name_"+$lastRetChar+"' value='"+vendor_name+"' /></td><td class='box-action'><button class='btn btn-danger btn-xs del_RetrieveBox'><span class='glyphicon glyphicon-trash' data-toggle='tooltip' title='Delete row'></span></button></td></tr>";
return $newRetRow;
}
$('#datatable-boxes').on('keypress','input[name^="retrieve_courier_tracking_no[]"]:last',function(e){
console.log(this);
$get_lastRetID();
if (e.which == 13) {
var seen = {};
$('input[name^="retrieve_courier_tracking_no[]"]').each(function() {
var ret_txt = $(this).val();
alert(ret_txt);
found = findItem(boxes_array, ret_txt);
if (seen[ret_txt] || found){
if($(this).hasClass("from_db")){
checker = true;
return true;
} else {
$('.alert-batch-box-data').css('visibility', 'visible');
if(seen[ret_txt]){
$('.alert').append('<p class="text-left">You scanned <strong>'+ret_txt+'</strong> more than once.</p>');
}
if (found) {
$('.alert').append('<p class="text-left"><strong>'+ret_txt+'</strong> already exists in Batch # <strong>'+found.batch_no+'</strong>.</p>');
}
$(this).val('');
box_qty = parseInt($('#datatable-boxes tbody>tr').length);
$('#retrieve_box_qty').val(box_qty);
checker = false;
return false;
}
} else{
if(ret_txt == ''){
alert('eto ata yun');
checker = false;
return false;
}
seen[ret_txt] = true;
if($('#retrieve_courier_tracking_no_1').val() == ''){
$('#add_RetrieveBox').css('visibility', 'hidden');
$('#update_RetrieveBox').css('visibility', 'hidden');
checker = false;
return false;
} else {
checker = true;
return true;
}
}
});
if(checker == true){
$('#datatable-boxes tbody').append($newRetRow);
$(this).closest('tr').next().find('input.retrieve_track_no').focus();
e.preventDefault();
$('#retrieve_box_qty').val($lastRetChar);
$('#add_RetrieveBox').css('visibility', 'visible');
$('#update_RetrieveBox').css('visibility', 'visible');
}
}
});
//Append new row on edit boxes > receive
$('#add_RetrieveBox').on("click", function(){
$get_lastRetID();
$('#datatable-boxes tbody').append($newRetRow);
$('#retrieve_box_qty').val($lastRetChar);
});
//Delete newly added row on frontend - Edit boxes-form
$('#datatable-boxes').on('click','tr .del_RetrieveBox',function(e){
e.preventDefault();
$(this).closest('tr').remove();
$lastRetChar = $lastRetChar-1;
$('#retrieve_box_qty').val($lastRetChar);
});
});
When I tried to alert() the current value that's being called on the second row, it just calls the first row and then returns empty twice. Since empty already showed twice, it will return false so there will be no new row.
Example:
1st data = 4987176601285 (This is from the database)
2nd data = 123 (This is in frontend)
After hitting enter to have a 3rd row, the alerts are these:
4987176601285
*blank*
*blank*
eto na yun
I'm not sure why my newly entered data is not being picked up. Any help is highly appreciated. Thanks!

I changed my each() function with filter(). I'm not entirely sure why this one worked and the other one did not.
$('#datatable-boxes input[name^="retrieve_courier_tracking_no[]"]').filter(function() {
value = $(this).val();
ret_found = findItem(boxes_array, value);
if (existing.indexOf(value) >= 0) {
// console.log($(this).val());
ret_checker = false;
if(ret_found){
$('.alert-batch-box-data').css('display', 'visible');
$('.alert').append('<p class="text-left"><strong>'+value+'</strong> already exists in Batch # <strong>'+ret_found.batch_no+'</strong>.</p>');
} else if((ret_checker == false) && (!ret_found)){
frontend_duplicate = true;
if($(this).val() == ''){
frontend_duplicate = false;
}
} else {
frontend_duplicate = false;
}
$(this).val('');
} else {
ret_checker = true;
frontend_duplicate = false
}
existing.push(value);
});
Then I modified it to fit with my previous code.

Related

Javascript Uncaught TypeError: value.toUpperCase is not a function

I am trying to use the following script to let the user filter the rows in a table based on the value they type. They can update that row, after the update event happend the page gets refreshed/relouded and the page shows all rows again. I am trying to find a way to keep the rows they filtered after the refresh/reload occrured. In other words as if the refresh never happend.
I get the following error: Uncaught TypeError: value.toUpperCase is not a function
at filterTable (accounts.php:1270)
at HTMLInputElement.<anonymous> (accounts.php:1291)
at HTMLInputElement.<anonymous>
This is the code;
<table class="userprof" align='left'>
<tr>
<td class="footer">Filter:
<input type="text" id="myInput" name="filter" style="color:black !important;" placeholder="Filter table" />
</td>
</tr>
</table>
</p><br /><br /><br />
</head>
<table width="99%" id="myTable" class="sortable" >
<tr>
<td class="header" style="padding: 1px;">Name</td>
<td class="header">Email</td></tr>
<? //Selecteer accounts.
$stmt = $mysqli->prepare("SELECT * FROM account WHERE purpose= ?");
$stmt->bind_param("s", $status);
$stmt->execute();
$result = $stmt->get_result();
}
while ($row = $result->fetch_assoc()) {
<td style="color:<?= htmlspecialchars($cat_color) ?> ", class="footer"><?= htmlspecialchars($row['name']) ?></td>
<td style="color:<?= htmlspecialchars($cat_color) ?> ", class="footer"><?= htmlspecialchars($row['email']) ?></td>
<td class="footer" width="1px"><input type="button" value="Edit" id="<?php echo htmlspecialchars($row['id']); ?>" onClick="this.style.color='gold';"
class="submit edit_data" /></td>
</form>
</tr>
<? } ?>
</table><div id="bottom"></div>
<script type="text/javascript">
// Store the input in a variable for reference.
var myInput = document.getElementById("myInput");
var savedValue = getSavedValue("myInput");
// Immediately filter the table and set the input value.
filterTable(savedValue);
myInput.value = savedValue;
//Save the value function - save it to localStorage as (ID, VALUE)
function saveValue(e) {
var id = e.id; // get the sender's id to save it .
var val = e.value; // get the value.
localStorage.setItem(id, val); // Every time user writing something, the localStorage's value will override .
}
//get the saved value function - return the value of "v" from localStorage.
function getSavedValue(v) {
if (!localStorage.getItem(v)) {
return ""; // You can change this to your default value.
}
return localStorage.getItem(v);
}
function filterTable(value) {
console.log(value);
var filter = value.toUpperCase();
var rows = document.querySelector("#myTable tbody").rows;
for (var i = 0; i < rows.length; i++) {
var nameCol = rows[i].cells[1].textContent.toUpperCase();
var rankCol = rows[i].cells[2].textContent.toUpperCase();
var rankerCol = rows[i].cells[5].textContent.toUpperCase();
var typeCol = rows[i].cells[6].textContent.toUpperCase();
var emailCol = rows[i].cells[3].textContent.toUpperCase();
if (nameCol.indexOf(filter) > -1 || rankCol.indexOf(filter) > -1 || rankerCol.indexOf(filter) > -1 || typeCol.indexOf(filter) > -1 || emailCol.indexOf(filter) > -1) {
rows[i].style.display = "";
} else {
rows[i].style.display = "none";
}
}
}
myInput.addEventListener('keyup', function(event) {
console.log(event); // Check if the event is fired.
var value = event.target;
saveValue(event);
filterTable(value);
});
</script>
myInput.addEventListener('keyup', function(event) {
console.log(event); // Check if the event is fired.
var value = event.target.value;
saveValue(event);
filterTable(value);
});
It should be event.target.value. You missed the value property

knockout automatically presses button after updating view

I have a table with TRbind in foreach loop:
<tbody data-bind="foreach: data">
<tr>
<td><input type="text" class="form-control" data-bind="value: DeviceSerialNumber" required /></td>
<td><input type="datetime" class="form-control datepicker" placeholder="Od" data-bind="value: StartDate" required /></td>
<td><button class="btn btn-default" data-bind='click: $root.removeRow'>Delete</button></td>
</tr>
</tbody>
the button is bind to this function:
self.removeRow = function (eq) {
self.data.removeAll([eq]);
};
I add data in this way:
var a = new Eq();
console.log(self);
a.StartDate(self.StartDateTemp());
a.DeviceId(self.DeviceTemp());
console.log(a);
console.log(self.data().length);
self.data.push(a);
console.log(self.data().length);
and data is:
var ViewModel = function () {
var self = this;
self.DeviceTemp = ko.observable();
self.StartDateTemp = ko.observable();
self.data = ko.observableArray([]);
}
The problem is occurring only in IE10. If I add anything to the data array the view is Updated. As in the view I add the is button bind to remove at the end of the tr. For unknown reason knockout or browser clicks that button and removes freshly added row.
Can You help me?
JSFIDDLE
Try adding return false after self.data.push(a); self.Test(""); to prevent event from bubbling:
self.searchKeyboardCmd = function (data, event) {
if (event.keyCode == 13) {
if ((self.StartDateTemp() === undefined)
|| (self.number() != 1 && self.Test() != undefined)
&& (self.number() != 1 && self.Test() != "")) {
alert("Bledna konfiguracja. Urzadzenia posiadajace numer seryjny nie moga byc dodane wiecej niz 1 raz")
return true;
}
if (self.number() < 1 || isNaN(self.number())) {
alert("Bledna ilosc");
return true;
}
var a = new Eq();
a.StorageId(self.StorageTemp());
a.StartDate(self.StartDateTemp());
a.DeviceSerialNumber(self.Test());
a.DeviceId(self.DeviceTemp());
a.Issue(self.Issue())
a.IssueDesc(self.IssueDesc());
a.Quantity(self.number());
a.Project(self.Project());
a.MeUser(self.MeUser());
self.data.push(a);
self.Test("");
return false;
}
return true;
};

Form validation linking fields as required

I am looking to do some client size validation. Below you will find an example of my template.
When this form is submitted it is okay for a line to be empty. However I want to be sure if even one item in a line is selected/has an entry that all lines will have an entry. For example. There should always be either Nothing OR require a Date, start Time, stop time, and class. (the class is populated by a button in another location) The validation will be used to warn the individual if they are missing anything and if they submit we will disregard the record as incomplete.
I have looked at jquery Validation as we are already using it on other forms in our project but, I have been unable to find a way to link row items together.
<form>
<table id="payableEventTable" class="table table-condensed table-striped">
<thead>
<tr>
<th>Date</th>
<th>Class/Scenario</th>
<th>Start</th>
<th>Stop</th>
<th>Break</th>
</tr>
</thead>
<tbody id="payableEventTableBody">
<c:forEach begin="0" end="5" varStatus="i">
<tr>
<td><input type="date" class="input-small" name="claimForm.payableEvents[${i.index}].eventDate" /></td>
<td>
<select class="classSelect" name="claimForm.payableEvents[${i.index}].event">
<option></option>
</select>
</td>
<td><input type="text" class="input-small" name="claimForm.payableEvents[${i.index}].eventStartTime" /></td>
<td><input type="text" class="input-small" name="claimForm.payableEvents[${i.index}].eventStopTime" /></td>
<td>
<select>
<option value="0" selected>No Break taken</option>
<option value="15">15 Minutes</option>
<option value="30">30 Minutes</option>
<option value="45">45 Minutes</option>
</select>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</form>
Technology we are willing to use. HTML, CSS, javaScript, jQuery, (lightweight plugins for jquery). We also have to make sure the solution works back to IE8.
Edit:
I built a JSFiddle. To help with visualization.
Edit:
I have come up with an answer. However, if anyone is able to improve on my answer, streamline it/make it look nicer I would still be willing to give out the Bounty to that person.
Here is my suggestion: To make your code more legible, you can combine the three functions validateRow(), isRowEmpty(), isRowComplete() into one simpler validateRow() function. Also it is a lot faster, because you only need to go through all elements and check their values once instead of twice.
I also created a simple to use validateForm() function to tidy things up.
The validateForm() function can now be used in an event handler:
// Event Handler
$('#validate').bind('click', function(e){
e.preventDefault();
if(validateForm()) {
alert("next");
//$('#claimWizard').wizard('next');
}
});
// Form Validation
var validateForm = function(){
var valid = true;
$('#payableEventTableBody tr').each(function() {
if (validateRow($(this))) {
$(this).removeClass("error");
}
else {
valid = false;
$(this).addClass('error');
}
});
return valid;
}
var validateRow = function(row){
var state = null,
valid = true;
row.find('input, select').each(function() {
var value = $(this).val(),
isEmpty = (value != 0 && value !== '');
//if its the first element just save the state
if(state === null) {
state = isEmpty;
}
// if this field has not the same state as the rest
else if(state !== isEmpty) {
valid = false;
}
})
return valid;
}
And here's your fiddle with my code implemented: http://jsfiddle.net/KNDLF/
So, what I came up with:
Three methods: isRowValid(), isRowEmpty(), isRowComplete()
The rows need to be either empty or complete.
//The following code is part of my logic on continuing
var valid = true;
$('#payableEventTableBody tr').each(function() {
$(this).removeClass('error');
if (!isRowValid($(this))) {
valid = false;
$(this).addClass('error');
return;
}
});
if (valid) {
$('#claimWizard').wizard('next');
}
//The following is my validation methods
<script type="text/javascript">
function isRowValid($tr) {
return (isRowEmpty($tr) || isRowComplete($tr));
}
function isRowEmpty($tr) {
var isEmpty = true;
$tr.find('input, select').each(function() {
var value = $(this).val();
if (value != 0 && value !== '') {
isEmpty = false;
}
});
return isEmpty;
}
function isRowComplete($tr) {
var isComplete = true;
$tr.find('input, select').each(function(){
var value = $(this).val();
if(value === ''){
isComplete = false;
}
});
return isComplete;
}
</script>
This should be good to start with
http://jsfiddle.net/rJaPR/
$('#validate').bind('click', function(e){
e.preventDefault();
$('#payableEventTable tr').each(function(){
var tr = $(this);
var newRowValue=0;
$(tr).find('input, select').each(function(){
var value = $(this).val();
switch(newRowValue){
case 0:
// first input/select
newRowValue = ((value!=0 && value!='') ? 1 : -1);
break;
case 1:
// there are some values in this row
if (value==0 || value=='')
tr.css('backgroundColor', 'red');
break;
case -1:
// this row should be empty
if (value!=0 && value!='')
tr.css('backgroundColor', 'red');
break;
}
})
})
})

How to hide/show messages in javascript when they should be hidden/shown?

I have a code below where it contains a form which contains text inputs a drop down menu:
$editsession = "
<form id='updateCourseForm'>
<p><strong>Current Course Details:</strong></p>
<table>
<tr>
<th>Course ID:</th>
<td><input type='text' id='currentCourseNo' name='CourseNocurrent' readonly='readonly' value='' /> </td>
</tr>
</table>
<div id='currentAlert'></div>
<p><strong>New Course Details:</strong></p>
<table>
<tr>
<th>Course ID:</th>
<td><input type='text' id='newCourseNo' name='CourseNoNew' value='' /> </td>
</tr>
</table>
<div id='newAlert'></div>
</form>
<p id='submitupdatebtn'><button id='updateSubmit'>Update Course</button></p>
";
echo $editsession;
Now I want to validate the form using Javascript and below is the code for the javascript validation:
function editvalidation() {
var isDataValid = true;
var currentCourseO = document.getElementById("currentCourseNo");
var newCourseNoO = document.getElementById("newCourseNo");
var currentCourseMsgO = document.getElementById("currentAlert");
var newCourseMsgO = document.getElementById("newAlert");
if (currentCourseO.value == ""){
currentCourseMsgO.innerHTML = "Please Select a Course to edit from the Course Drop Down Menu";
$('#newAlert').hide();
isDataValid = false;
}else{
currentCourseMsgO.innerHTML = "";
}
if (newCourseNoO.value == ""){
newCourseMsgO.innerHTML = "Please fill in the Course ID in your Edit";
$('#newAlert').show();
isDataValid = false;
} else{
newCourseMsgO.innerHTML = "";
}
return isDataValid;
}
Now this is the problem I am getting:
What I am trying to state in my javascript validation is that if the #currentCourseNo is empty (text input is blank), then it displays the error message for this which belongs to the div tag #currentAlert, but it hides messages which are displayed in the div tag #newAlert. If the #currentCourseNois not empty then show the #newAlert error messages if there are any.
The problem I am having is that it is still showing the #newAlert error messages when the #currentCourseNo text input is empty, when it really should be hidden. What needs to be changed in the javascript above in order to achieve what I want to achieve?
First, learn about jQuery.
For your process, my common flow is to add a first pass of validation on the blur event of the inputs, and a second (exactly the same) pas of validation on the submit event of the form, something like :
var error = $('.errormsg');
var checks =
{
"fieldName1": function(val) { return /*true or an error string*/ },
"fieldName2": function(val) { return /*true or an error string*/ }
};
$('input')
.focus(function()
{
$(this).removeClass('error');
})
.blur(function()
{
error.slideUp(200);
var check = checks[this.name];
if (!check) { return; }
var validation = check(this.value);
if (typeof validation === "string")
{
$(this).addClass('error');
error.text(validation).slideDown(200);
}
});
$('form').submit(function(e)
{
//e.preventDefault();
if ($('input.error').length != -1)
{
error.text('All fields are required').slideDown(200);
return;
}
for(var check in checks)
{
var field = $('input[name="' + check + '"]');
if (field.length == -1) { continue; }
var validation = check(field.val());
if (typeof validation === "string")
{
field.addClass('error');
error.text(validation).slideDown(200);
return;
}
}
});

Apply value to a jquery generated input field

my TD's are generated by grid object on a fly
i'm trying to change value of the fist empty input that is positioned inside :
$("#get_isrc").click(function(){
$.ajax({
url: 'xtras/isrc.php',
success: function(data){
$("#new_isrc").val(data);
$("#get_isrc").val('Apply');
$("#get_isrc").addClass('apply');
}
}).error(function(){
alert('Error');
});
});
$(".apply").live("click", function(){
var s = $("td[col=ISRC] input").val();
if (s === "") {
$(this).val(($("#new_isrc").val()));
}
});
html - static:
<h3>Generate next ISRC</h3>
<input id="new_isrc" type="text" />
<input id="get_isrc" type="button" value="Get next ISRC" />
html generated by jquery:
<tr id="4"><td><input class="editableInput" type="text" /></td><td col="ISRC" class="editableCell"><input class="editableInput " type="text"></td></tr>
<tr id="1"><td><input class="editableInput" type="text" /></td><td col="ISRC" class="editableCell"><input class="editableInput " type="text"></td></tr>
<tr id="2"><td><input class="editableInput" type="text" /></td><td col="ISRC" class="editableCell"><input class="editableInput " type="text"></td></tr>
<tr id="3"><td><input class="editableInput" type="text" /></td><td col="ISRC" class="editableCell"><input class="editableInput " type="text"></td></tr>
tr's 1 and 2 have ISRC values from database, tr 3 is empty, but positioned last
tr 4 - is newly added empty line and i want a generated isrc applied to it...
code i provided above doesn't work. why?
You are calling .val() into an array of inputs, do this:
$("td[col=ISRC] input").each(function() {
// each iteration function
var s = $(this).val();
if (s === "") {
$(this).val(($("#new_isrc").val()));
return false; // stops each iteration
}
});
Edit:
If you want to add the same value to all inputs, do this:
$("td[col=ISRC] input").each(function() {
var s = $(this).val();
if (s === "") {
$(this).val(($("#new_isrc").val()));
}
});
If you want to add dynamic values to all inputs, do this:
$("td[col=ISRC] input").each(function() {
var s = $(this).val();
if (s === "") {
$(this).val(getNextValue());
}
});
function getNextValue() {
// your business implementation here
}

Categories

Resources