Sorry for my English. I made some test client for test our web server, but I am unhappy with my work. Please help me improve my code.
I want to make serial HTTP requests. I have Array with test requests:
Aua.Queries = ko.observableArray([
new Query("/srv?key=value&key2=someValue", 300, "comment for this request"),
new Query("/srv?someKey=SomeValue", 0, "comment for this request")
]);
(in Aua.Queries array 24 queries)
My wrapper for Aua.Queries observableArray:
function Query(query, result, comment) {
var me = this;
me.Query = "http://mydomain.com?" + query;
me.Result = result;
me.Comment = comment;
me.Selected = ko.observable(false);
}
When click send handler, I do this:
Aua.SendHandler = function () {
Aua.Loading(true);
Aua.Responses([]);
if (Aua.Advanced() == true) {
var queries = Aua.Queries();
console.log("Selected Request Count: ",
Enumerable.From(queries).Where("$.Selected() == true").Select(function(query) {
console.log("Result: ", query.Result);
Aua.Url(query.Query);
query.Selected(false);
sendRequest();
}).Count());
}
else if (Aua.RequestCount() > 1) {
for (var i = Aua.RequestCount(); i > 0; i--) {
Aua.RequestCount(i);
setUrlByStatus();
sendRequest();
}
}
else
sendRequest();
};
And sendRequest Handler:
function sendRequest() {
console.log("Sending request to: ", Aua.Url());
$.ajax(Aua.Url(), {
dataType: 'text',
cache: false,
type: 'GET',
success: function(data, status, xhr) {
Aua.Responses.push({
"Data": data,
"Status": xhr.status + " " + xhr.statusText
});
prettyPrint();
},
error: function(xhr, status, data) {
Aua.Responses.push({
"Data": data,
"Status": xhr.status + " " + xhr.statusText
});
prettyPrint();
console.log("Error: ", Aua.Responses());
},
complete: function() {
Aua.Loading(false);
}
});
}
Set type of request format.
function setUrlByStatus() {
if (Aua.RequestStatus() === "error")
Aua.Url(Aua.Queries()[Math.floor(Math.random() * Aua.Queries().length)].Query);
else
Aua.Url(
"http://mydomain.com?" +
"action=" + Aua.Action() +
"&number=" + Aua.Number());
}
A have 3 types of sending request.
Send multiple request from Aua.Queries array.
Send requests by depent in count.
And Send 1 request in input.
I do my self.
And i learned how organaize my code
/*
Client requests for tes our server
Make different demands on the Serer.
Query setings:
Send something that is in the input.
Send to a specified number of times queries and allow the user to choose what kind of answer he wants, success or error.
For successful actions are random data request: email, account, paper.
Send requests from the table.
All the answers to print. Prettify XML response.
After the data to make a progress report
The following table show: Status Code, Comments, Quantity.
HTTP status display for each response received and paint the fatal errors in red.
*/
(function (global, undefined) {
function ajaxObject(url, query, response, loading) {
console.log("Query: ", query());
var catched = query();
return $.ajax({
cache: false,
dataType: "text",
type: "GET",
url: url() + catched,
success: function (data, status, xhr) {
response.push({
Data: data,
Query: catched,
Status: xhr.status + ' ' + xhr.statusText
});
},
error: function (xhr, status, data) {
response.push({
Data: data,
Query: catched,
Status: xhr.status + " " + xhr.statusText
});
},
complete: function () {
loading(false);
prettyPrint();
}
});
}
function Query(query, result, comment) {
var me = this;
me.Query = query;
me.Result = result;
me.Comment = comment;
me.Selected = ko.observable(false);
me.Describtion = ko.observable(comment);
me.DescribtionComment = function (data) { me.Describtion(data.Comment); };
me.DescribtionQuery = function (data) { me.Describtion(data.Query); };
}
var queries = [
new Query("/zibaba?paper=go&id=1&account=someacc&date=20130221174323", 453, "Error. Expected parameter test"),
new Query("/zibaba?paper=go&account=someacc", 0, "Expected parameter test"),
new Query("/zibaba?paper=do&id=3&account=someacc&date=20130221174323", 1, " Forbidden"))
];
var Aua = global.Aua = new function Aua() { };
Aua.Configuration = {
Advanced: {
Queries: queries,
QueriesSelectAll: ko.observable(false),
Toggle: ko.observable(false)
},
Counter: ko.observable(1),
Query: ko.observable(),
Url: ko.observable(),
Status: ko.observable("success")
};
Aua.Configuration.Advanced.QueriesSelectAll.subscribe(function () {
var qs = Aua.Configuration.Advanced.Queries;
for (var i = 0; i < qs.length; i++)
qs[i].Selected(!qs[i].Selected());
});
Aua.IsLoading = ko.observable(false);
Aua.SendHandler = function() {
Aua.IsLoading(true);
Aua.Responses([]);
if (Aua.Configuration.Advanced.Toggle() === true) {
$.when(Enumerable.From(Aua.Configuration.Advanced.Queries)
.Where("$.Selected() === true")
.Select(function(current) {
Aua.Configuration.Query(current.Query);
return ajaxObject(Aua.Configuration.Url, Aua.Configuration.Query, Aua.Responses, Aua.IsLoading);
}).ToArray());
} else {
$.when(Enumerable.Generate(function() {
var papers;
if (Aua.Configuration.Status() == "success") {
papers = ["do", "go"];
Aua.Configuration.Query(
"?account=" + Math.floor(Math.random() * 1234567 + 1) +
("&paper=" + papers[Math.floor(Math.random() * papers.length)]) +
("&id=" + Math.floor(Math.random() * 123754 + 1)));
} else if (Aua.Configuration.Status() == "error") {
papers = ["do", "go", "justdoit"];
var accounts = [Math.floor(Math.random() * 1234567 + 1), " ", Math.floor(Math.random() * 4532 + 1)],
ids = [" ", (Math.floor(Math.random() * 123754 + 1)), (Math.floor(Math.random()))];
Aua.Configuration.Query(
"?account=" + accounts[Math.floor(Math.random() * accounts.length)] +
"&paper=" + (papers[Math.floor(Math.random() * papers.length)]) +
"&id=" + (ids[Math.floor(Math.random() * ids.length)]));
}
return ajaxObject(Aua.Configuration.Url, Aua.Configuration.Query, Aua.Responses, Aua.IsLoading);
}, Aua.Configuration.Counter()).ToArray());
}
};
Aua.ResetHandler = function () { location.reload(); };
Aua.Statistics = {
Code: ko.observable(0),
Comment: ko.observable(0),
Quantity: ko.observable(0)
};
Aua.Responses = ko.observableArray([{
Data: ko.observable(),
Status: ko.observable(-1)
}]);
Aua.Responses([]);
$(document).on("ready", function () {
ko.applyBindings(Aua);
});
})(window);
Sorry for my English
Related
class ProductInfoDetailsViewModel {
constructor(parent, productInfoWindowId, inventoryId, productId, supplierId, store) {
this._parent = parent;
this._created = false;
this._productInfoWindowId = productInfoWindowId;
this._inventoryId = inventoryId;
this._productId = productId;
this._supplierId = supplierId;
this._store = store;
}
_getMvvmData(inventoryId, productId, supplierId) {
return new Promise(function (resolve, reject) {
$.ajax({
url: '/ProductRowInfoSite/GetInventoryControl',
data: {
'inventoryId': inventoryId,
'productId': productId,
'supplierId': supplierId,
},
dataType: 'json', // "jsonp" is required for cross-domain requests; use "json" for same-domain requests
success: function (result) {
resolve(result);
},
error: function (jqXHR, textStatus, errorThrown) {
reject([jqXHR, textStatus, errorThrown]);
},
type: 'POST',
});
});
}
async create() {
let self = this;
let userStore = new UserStore();
//productInfoTextGrid
this._productInfoDetailsViewModel = kendo.observable({
value: {},
close: function () {
//$("#generalProductInfoWindow").data("kendoWindow").close();
//closeWindow();
},
not: function (value) {
return !this.get(value);
},
save: function (e) {
let productInfoTextGrid = $(self._productInfoWindowId + ' ' + '#productInfoTextGrid').data('kendoGrid');
/* productInfoTextGrid.saveChanges();*/
let orderUnitsGrid = $(self._productInfoWindowId + ' ' + '#orderUnitsGrid').data('kendoGrid');
let selectedRefHistProd = null;
try {
selectedRefHistProd = this.get('value.SelectedRefHistProd').ProductId;
} catch (error) {
// may be set to null and that's fine/TK.
}
var data = {
ProductId: self._productId,
InventoryId: self._inventoryId,
SupplierId: self._supplierId,
Fmean: this.get('value.Fmean'),
FMAD: this.get('value.FMAD'),
FTrend: this.get('value.FTrend'),
SelectedSeason: this.get('value.SelectedSeason').SeasonId,
MinQuantity: this.get('value.MinQuantity'),
SelectedOrderUnitNo: this.get('value.SelectedOrderUnit').UnitNo,
LeadTime: this.get('value.LeadTime'),
LeadTimeDeviation: this.get('value.LeadTimeDeviation'),
StockKeepInterest: this.get('value.StockKeepInterest'),
MaxLevel: this.get('value.MaxLevel'),
MinLevel: this.get('value.MinLevel'),
OrderQuantity: this.get('value.OrderQuantity'),
ReorderLevel: this.get('value.ReorderLevel'),
EnableManualSetRAndQ: this.get('value.EnableManualSetRAndQ'),
ForecastError: this.get('value.ForecastError'),
SelectedHistoryProductId: selectedRefHistProd,
};
var dataString = JSON.stringify(data);
$.ajax({
url: '/ProductRowInfoSite/SaveParameters',
data: {
data: dataString,
},
dataType: 'json',
// "jsonp" is required for cross-domain requests; use "json" for same-domain requests
success: function (result) {
// notify the data source that the request succeeded
//options.success(result);
self._store.dispatch({ type: ActionProductInfoWindow.Saving });
self._parent.refreshParentGrids();
},
error: function (result) {
displayAjaxError(result);
},
type: 'POST',
});
let userStore = new UserStore();
let finishSaved = userStore.translatedString('SOLOSupplier.ProductInfoWindows.FinishSaved');
displaySuccess(finishSaved);
productInfoTextGrid.saveChanges();
orderUnitsGrid.saveChanges();
},
recalc: function () {
var validator = $(self._productInfoWindowId).kendoValidator().data('kendoValidator');
var a = validator.validate();
},
products: new kendo.data.DataSource({
type: 'json',
serverFiltering: true,
pageSize: 100,
transport: {
read: function (options) {
$.ajax({
url: '/ProductRowInfoSite/GetProductInventoryList',
data:
{
'inventoryId': self._inventoryId,
'productId': self._productId,
'data': options.data,
},
//"filter": filter
dataType: 'json', // "jsonp" is required for cross-domain requests; use "json" for same-domain requests
success: function (result) {
// notify the data source that the request succeeded
options.success(result.HistProducts);
},
error: function (result) {
// notify the data source that the request failed
options.error(result);
},
type: 'POST',
});
},
parameterMap: function (data, type) {
return kendo.stringify($.extend({ 'text': $(data.filter.filters).get(0).value }, data));
},
},
}),
isEnabled: true,
onValidate: function (e) {
console.log('onValidate');
let maxLevel = this.get('value.MaxLevel');
let minLevel = this.get('value.MinLevel');
let userStore = new UserStore();
let validationErrorMessage = userStore.translatedString('uctrlSupplierWeb.MaxLevelMinLevelWarning');
let validator = $(self._productInfoWindowId).kendoValidator({
messages: {
custom: validationErrorMessage,
},
rules: {
custom: function (input) {
if (input.is('[name=minLevelParameter]') && input.val() === '') {
return true;
} else if (input.is('[name=minLevelParameter]') && input.val() !== '' && maxLevel !== null) {
return maxLevel > minLevel;
}
if (input.is('[name=maxLevelParameter]') && input.val() === '') {
return true;
} else if (input.is('[name=maxLevelParameter]') && input.val() !== '' && minLevel !== null) {
return maxLevel > minLevel;
} else {
return true;
}
},
},
},
).data('kendoValidator');
if (validator.validate() === true) {
self._store.dispatch({ type: ActionProductInfoWindow.Changing });
} else {
self._store.dispatch({ type: ActionProductInfoWindow.Cancelling });
}
},
});
kendo.bind($(self._productInfoWindowId + ' ' + '#tabInventoryControl'), self._productInfoDetailsViewModel);
try {
let result = await self._getMvvmData(self._inventoryId, self._productId, self._supplierId);
self._productInfoDetailsViewModel.products.read();
self._productInfoDetailsViewModel.set('value', result);
if (result.UnitsOnOrderAfterLeadtime === true) {
if ($(self._productInfoWindowId + ' ' + '#valueUnitsOnOrder').data('kendoNumericTextBox')) {
let widget = $(self._productInfoWindowId + ' ' + '#valueUnitsOnOrder').data('kendoNumericTextBox');
widget.wrapper.find('input').addClass('lightRed');
}
}
if ($(self._productInfoWindowId + ' ' + '#minLevelParameterId').data('kendoNumericTextBox')) {
$(self._productInfoWindowId + ' ' + '#minLevelParameterId')
.data('kendoNumericTextBox')
.min(result.MinLevelDefault);
}
if ($(self._productInfoWindowId + ' ' + '#maxLevelParameterId').data('kendoNumericTextBox')) {
$(self._productInfoWindowId + ' ' + '#maxLevelParameterId')
.data('kendoNumericTextBox')
.min(result.MinLevelDefault);
}
var validator = $(self._productInfoWindowId).kendoValidator().data('kendoValidator');
validator.validate();
let element = $(self._productInfoWindowId);
window.kendo.ui.progress(element, false);
} catch ([jqXHR, textStatus, errorThrown]) {
displayAjaxError(jqXHR, textStatus, errorThrown);
productInfoDetailsViewModel.set('value', []);
window.kendo.ui.progress(element, false);
}
}
}
Saving edits in product info modal deletes used filters on products grid
if (productNo === null) {
let newFilter = await self._getFilterOnlyFromLocalStorage();
let totalFilter = $(self._gridId).data("kendoGrid").dataSource.filter();
totalFilter.filters.push.apply(totalFilter.filters, newFilter.filters);
$(self._gridId).data("kendoGrid").dataSource.filter(newFilter);
self._setPredefinedFilterButton(self);
}
}
I have the following issue: When I make an Ajax call to give people an option to "autofill" a field, it offers the same string (as seen in the image below). The problem is, that the Ajax call uses an URL where the string appears in an XML multiple times.
For example, when calling
/tools/_api/web/lists/getbytitle('Besucheranmeldung')/Items?&$filter=substringof('Aalen', FirmaNeu)&$select=FirmaNeu
the XML will look something like that:
<?xml version="1.0" encoding="utf-8"?><feed xml:base="https://mylink/tools/_api/" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml"><id>fbe3c761-2113-4be6-b8dd-599cf842df2f</id><title /><updated>2020-12-16T12:58:45Z</updated><entry m:etag=""2""><id>Web/Lists(guid'5d3a8bf8-7edf-4b7e-aab8-5df6cd818573')/Items(10891)</id><category term="SP.Data.BesucheranmeldungListItem" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /><link rel="edit" href="Web/Lists(guid'5d3a8bf8-7edf-4b7e-aab8-5df6cd818573')/Items(10891)" /><title /><updated>2020-12-16T12:58:45Z</updated><author><name /></author><content type="application/xml"><m:properties><d:FirmaNeu>IGM Aalen</d:FirmaNeu></m:properties></content></entry><entry m:etag=""2""><id>Web/Lists(guid'5d3a8bf8-7edf-4b7e-aab8-5df6cd818573')/Items(10893)</id><category term="SP.Data.BesucheranmeldungListItem" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /><link rel="edit" href="Web/Lists(guid'5d3a8bf8-7edf-4b7e-aab8-5df6cd818573')/Items(10893)" /><title /><updated>2020-12-16T12:58:45Z</updated><author><name /></author><content type="application/xml"><m:properties><d:FirmaNeu>'IGM Aalen</d:FirmaNeu></m:properties></content></entry><entry m:etag=""2""><id>Web/Lists(guid'5d3a8bf8-7edf-4b7e-aab8-5df6cd818573')/Items(10894)</id><category term="SP.Data.BesucheranmeldungListItem" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /><link rel="edit" href="Web/Lists(guid'5d3a8bf8-7edf-4b7e-aab8-5df6cd818573')/Items(10894)" /><title /><updated>2020-12-16T12:58:45Z</updated><author><name /></author><content type="application/xml"><m:properties><d:FirmaNeu>IGM Aalen</d:FirmaNeu></m:properties></content></entry><entry m:etag=""2""><id>Web/Lists(guid'5d3a8bf8-7edf-4b7e-aab8-5df6cd818573')/Items(10895)</id><category term="SP.Data.BesucheranmeldungListItem"
I use the following code to get the dropdown:
var requestHeaders = {
"Accept": "application/json;odata=verbose",
"X-RequestDigest": NWF$("#__REQUESTDIGEST").val()
};
function startAutoComplete(varTextBoxId, listname) {
console.log("startAutoComplete called!");
NWF$("#" + varTextBoxId).autocomplete({
source: function (request, response) {
var query = getQuery(request.term, listname);
var testurl = "/tools/_api/web/lists/getbytitle('" + listname + "')/Items?&$filter=" + query;
console.log("testurl: " + testurl);
NWF$.ajax({
url: "/tools/_api/web/lists/getbytitle('" + listname + "')/Items?&$filter=" + query,
contentType: "application/json;odata=verbose",
headers: requestHeaders,
error: function (xhr, ajaxOptions, thrownError) {
alert("error:" + thrownError + "\n" + xhr.status);
},
success: function (data) {
response(NWF$.map(data.d.results, function (item) {
switch (listname) {
case "Besucheranmeldung":
return {
label: item.FirmaNeu,
value: item.FirmaNeu,
id: item.FirmaNeu,
listname: listname
}
break;
}
}));
}
});
},
minLength: 2,
select: function (event, ui) {
},
open: function () {
NWF$(this).removeClass("ui-corner-all").addClass("ui-corner-top");
},
close: function () {
NWF$(this).removeClass("ui-corner-top").addClass("ui-corner-all");
}
});
}
function getQuery(requestStr, listname) {
var retvalue = "";
requestStr = encodeURIComponent(requestStr);
switch (listname) {
case "Besucheranmeldung":
retvalue = "substringof('" + requestStr + "', FirmaNeu)" + "&$select=FirmaNeu";
break;
}
// console.log("retvalue: " + retvalue);
return retvalue;
}
How can this be avoided? Is there a way to make an if statement which checks whether the dropdown contains the same string twice to avoid letting it appear there multiple times?
When I do console.log(data.d.results);, I get the following:
Fixed it by changing the code:
var requestHeaders = {
"Accept": "application/json;odata=verbose",
"X-RequestDigest": NWF$("#__REQUESTDIGEST").val()
};
function startAutoComplete(varTextBoxId, listname) {
console.log("startAutoComplete called!");
NWF$("#" + varTextBoxId).autocomplete({
source: function (request, response) {
var query = getQuery(request.term, listname);
NWF$.ajax({
url: "/tools/_api/web/lists/getbytitle('" + listname + "')/Items?&$filter=" + query,
contentType: "application/json;odata=verbose",
headers: requestHeaders,
error: function (xhr, ajaxOptions, thrownError) {
alert("error:" + thrownError + "\n" + xhr.status);
},
success: function (data) {
// console.log(data.d.results);
var firmaResults;
var firmen = [];
firmaResults = groupBy(data.d.results,'FirmaNeu');
// console.log(firmaResults);
for (var i = 0; i < firmaResults.length; i++ ){
firmen[i] = firmaResults[i];
}
var counter = -1;
response(NWF$.map(data.d.results, function (item) {
switch (listname) {
case "Besucheranmeldung":
counter++;
if (counter > firmaResults.length){
return;
}
return {
label: firmen[counter],
value: firmen[counter],
id: firmen[counter],
listname: listname
}
break;
}
}));
}
});
},
minLength: 2,
select: function (event, ui) {
},
open: function () {
NWF$(this).removeClass("ui-corner-all").addClass("ui-corner-top");
},
close: function () {
NWF$(this).removeClass("ui-corner-top").addClass("ui-corner-all");
}
});
}
function getQuery(requestStr, listname) {
var retvalue = "";
requestStr = encodeURIComponent(requestStr);
switch (listname) {
case "Besucheranmeldung":
retvalue = "substringof('" + requestStr + "', FirmaNeu)" + "&$select=FirmaNeu";
break;
}
// console.log("retvalue: " + retvalue);
return retvalue;
}
function groupBy(items,propertyName)
{
var result = [];
$.each(items, function(index, item) {
if ($.inArray(item[propertyName], result) == -1) {
result.push(item[propertyName]);
}
});
return result;
}
I am making a project with a DataTable (https://datatables.net) and the issue I am having is pretty strange.
Sometimes when I load the page, everything works 100% and other times when I load the page I get this error from DataTables in a popup:
DataTables warning: table id=resdatatable - Cannot reinitialise DataTable. For more information about this error, please see http://datatables.net/tn/3
As I have said, there's no sure fire way to trigger this. If I hit refresh sometimes it will work, sometimes it will give me that error.
I am not trying to reinitialize the DataTable, so I am a bit confused on why this is happening. I checked the link in the description but I am not understanding how to remedy this.
Here is my code:
let statusList = getStatusList();
function getRes(callback) { // ADDED CALLBACK
let city = document.getElementById("cityselect").value;
$.ajax({
type: 'get',
url: 'getreservationstable.php?city='+city,
dataType: 'json',
cache: false,
success: callback // USED CALLBACK
});
}
function changeCity()
{
$('#resdatatable').DataTable().ajax.reload();
}
getRes(function (result) { // APPLIED CALLBACK
$('#resdatatable').DataTable({
data: result, // YOUR RESULT
columns: [
{ data: 'id', title: 'ID' },
{ data: 'bookingdatetime', title: 'Booking Date' },
{ data: 'name', title: 'Name' },
{ data: 'class', title: 'Class' },
{ data: 'pickupdatetime', title: 'Pick up' },
{ data: 'duration', title: 'Duration' },
{ data: 'dropdatetime', title: 'Drop off' },
{ data: 'age', title: 'Age' },
{ data: 'coverage', title: 'Coverage' },
{ data: 'quote', title: 'Quote' },
{
data: 'status',
title: 'Status',
render: function(data, type, row) {
let isKnown = statusList.filter(function(k) { return k.id === data; }).length > 0;
if (isKnown) {
return $('<select id ="resstatus' + row.id + '" onchange="changeResStatus(' + row.id + ')">', {
id: 'resstatus-' + row.id, // custom id
value: data
}).append(statusList.map(function(knownStatus) {
let $option = $('<option>', {
text: knownStatus.text,
value: knownStatus.id
});
if (row.status === knownStatus.id) {
$option.attr('selected', 'selected');
}
return $option;
})).on('change', function() {
changeresstatus(row.id); // Call change with row ID
}).prop('outerHTML');
} else {
return data;
}
}
}
]
});
});
/**
* jQuery plugin to convert text in a cell to a dropdown
*/
(function($) {
$.fn.createDropDown = function(items) {
let oldTxt = this.text();
let isKnown = items.filter(function(k) { return k.id === oldTxt; }).length > 0;
if (isKnown) {
this.empty().append($('<select>').append(items.map(function(item) {
let $option = $('<option>', {
text: item.text,
value: item.id
});
if (item.id === oldTxt) {
$option.attr('selected', 'selected');
}
return $option;
})));
}
return this;
};
})(jQuery);
// If you remove the renderer above and change this to true,
// you can call this, but it will run once...
if (false) {
$('#resdatatable > tbody tr').each(function(i, tr) {
$(tr).find('td').last().createDropDown(statusList);
});
}
function getStatusList() {
return [{
id: 'Confirmed',
text: 'Confirmed'
}, {
id: 'Unconfirmed',
text: 'Unconfirmed'
}, {
id: 'Open',
text: 'Open'
}, {
id: 'Closed',
text: 'Closed'
}, {
id: 'Canceled',
text: 'Canceled'
}];
}
function changeResStatus(str1) {
var id = str1;
var status = document.getElementById("resstatus" + id).value;
var mailres = "";
var r = confirm("Change Status for ID # " + id + " to " + status + "?");
if (r == true) {
if (document.getElementById("resstatus" + id).value == "Confirmed"){
var s = confirm("Send ID # " + id + " a confirmation email?");
if (s == true) {
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("result").setAttribute ("data-notify-msg", this.responseText);
document.getElementById("result").setAttribute ("data-notify-type", "info");
SEMICOLON.widget.notifications(document.getElementById("result"));
}
};
xmlhttp.open("GET","sendconfirmationemail.php?id="+id,true);
xmlhttp.send();
}
}
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("result").setAttribute ("data-notify-msg", this.responseText);
document.getElementById("result").setAttribute ("data-notify-type", "info");
SEMICOLON.widget.notifications(document.getElementById("result"));
}
};
xmlhttp.open("GET","changeresstatus.php?id="+id+"&status="+status,true);
xmlhttp.send();
}else{
document.getElementById("result").setAttribute ("data-notify-msg", "Change status action aborted");
document.getElementById("result").setAttribute ("data-notify-type", "error");
SEMICOLON.widget.notifications(document.getElementById("result"));
}
}
$(document).ready(function() {
var table = $('#resdatatable').DataTable();
$('#resdatatable tbody').on('click', 'tr', function () {
var data = table.row( this ).data().id;
$.ajax({
type: 'POST',
url: 'getreservationsdetails.php',
dataType: 'json',
data: { id:data, },
success: function(response) {
$('#resulttitle').html("Booking ID # " + response[0].id);
$('#resdetname').html(response[0].name);
$('#resdetbdate').html(response[0].bookingdatetime);
$('#resdetadd').html("<br>" + response[0].address + "<br>" + response[0].city + "<br>" + response[0].state + " " + response[0].post);
$('#resdetphone').html(response[0].phone);
$('#resdetemail').html(response[0].email);
$('#resdetdln').html(response[0].dlnum);
$('#resdetdle').html(response[0].dlexp);
$('#resdetdlc').html(response[0].dlcountry);
$('#resdetpickup').html(response[0].pickuploc + " " + response[0].pickupdatetime);
$('#resdetduration').html(response[0].duration);
$('#resdetdrop').html(response[0].droploc + " " + response[0].dropdatetime);
$('#resdetclass').html(response[0].class);
$('#resdetcoverage').html(response[0].coverage);
$('#resdetage').html(response[0].age);
$('#resdetnumofdrivers').html(response[0].numofdrivers);
$('#resdetroadside').html(response[0].roadsideass);
$('#resdetafterhoursdrop').html(response[0].afterhoursdrop);
$('#resdetpromo').html(response[0].promo);
$('#resdetquote').html(response[0].quote);
$('#resdetaddcomments').html(response[0].name);
$('#resdetip').html(response[0].ip);
$("#modalresult").modal();
}
});
} );
} );
Edit:
Upon further examination, this error seems to be caused by the line var table = $('#resdatatable').DataTable(); in $(document).ready(function() { - if I remove that line, everything works just fine. How do I make this work???
Your error come from the fact you try to access a Database object which has not been initialized yet by getRes().
Because on $(document).ready you were creating a first database with no options, when getRes got trigger you should update its content instead of creating a second Database() on top of the same element (which explain the "Cannot reinitialise DataTable")
Try to move the table var from your document ready to your on event:
$(document).ready(function() {
$('#resdatatable tbody').on('click', 'tr', function () {
var table = $('#resdatatable').DataTable();
var data = table.row( this ).data().id;
Or maybe init the $('#resdatatable tbody').on on getRes() as it might not have access to tbody yet:
getRes(function (result) { // APPLIED CALLBACK
$('#resdatatable').DataTable({
...
});
$('#resdatatable tbody').on('click', 'tr', function () {
...
How I fixed this problem:
I added a 1ms delay for the code to run:
setTimeout(function() {
$(document).ready(function() {
var table = $('#resdatatable').DataTable();
$('#resdatatable tbody').on('click', 'tr', function () {
var data = table.row( this ).data().id;
$.ajax({
type: 'POST',
url: 'getreservationsdetails.php',
dataType: 'json',
data: { id:data, },
success: function(response) {
$('#resulttitle').html("Booking ID # " + response[0].id);
$('#resdetname').html(response[0].name);
$('#resdetbdate').html(response[0].bookingdatetime);
$('#resdetadd').html("<br>" + response[0].address + "<br>" + response[0].city + "<br>" + response[0].state + " " + response[0].post);
$('#resdetphone').html(response[0].phone);
$('#resdetemail').html(response[0].email);
$('#resdetdln').html(response[0].dlnum);
$('#resdetdle').html(response[0].dlexp);
$('#resdetdlc').html(response[0].dlcountry);
$('#resdetpickup').html(response[0].pickuploc + " " + response[0].pickupdatetime);
$('#resdetduration').html(response[0].duration);
$('#resdetdrop').html(response[0].droploc + " " + response[0].dropdatetime);
$('#resdetclass').html(response[0].class);
$('#resdetcoverage').html(response[0].coverage);
$('#resdetage').html(response[0].age);
$('#resdetnumofdrivers').html(response[0].numofdrivers);
$('#resdetroadside').html(response[0].roadsideass);
$('#resdetafterhoursdrop').html(response[0].afterhoursdrop);
$('#resdetpromo').html(response[0].promo);
$('#resdetquote').html(response[0].quote);
$('#resdetaddcomments').html(response[0].name);
$('#resdetip').html(response[0].ip);
$("#modalresult").modal();
}
});
I have a problem sending a parameter to the class. I want to do a class that supports error in AJAX. The working function looks like this:
function GetLastChangePass(UserId) {
var field =
{
id: UserId,
}
var fieldStringified = JSON.stringify(field)
$.ajax({
url: "/Users/LastChangePass",
method: 'PUT',
data: fieldStringified,
contentType: 'application/json; charset=utf-8',
success: (result) => {
if (result.includes('12.12.2000')) {
document.querySelector('#user-tslog').append('')
} else if (result == 'Not_tslog') {
document.querySelector('#user-tslog').append('')
}
else {
document.querySelector('#user-tslog').append(result)
}
},
error: (result) => {
addNewMessage("error", "Error")
console.error("fail responseText: " + result.responseText)
console.error("fail contentstatusText : " + result.statusText)
console.error("fail status TEST: " + result.status)
}
});
}
I made a class that looks like this:
class ErrorConsole {
constructor(result) {
this.result = result
}
error() {
console.error("fail responseText: " + this.result.responseText)
console.error("fail contentstatusText : " + this.result.statusText)
console.error("fail status : " + this.result.status)
}
}
Why is the parameter undefined after converting the function to what is below?
error: (result) => {
console.log(result) //===> there is object
addNewMessage("error", "Error");
err.error(result) //===> there is indefined
console.error("fail responseText: " + result.responseText)
console.error("fail contentstatusText : " + result.statusText)
console.error("fail status TEST: " + result.status)
}
You should create the ErrorConsole and passing result in the constructor and not in the function, so that way you can print object attributes:
error: (result) => {
console.log(result) //===> there is object
const err = new ErrorConsole(result)
addNewMessage("error", "Error");
err.error()
console.error("fail responseText: " + result.responseText)
console.error("fail contentstatusText : " + result.statusText)
console.error("fail status TEST: " + result.status)
}
I have created a jQuery function extending its own object $. This function translate those elements attached to the element this:
$.fn.extend({
translate: function(sourceLang, targetLang) {
if($(this).text().trim().length < 1 || !isNaN(parseInt($(this).text().trim())) || sourceLang == targetLang)
return;
let $function = this;
$($function).each(function() {
let $each = this;
$.ajax({
url: 'https://translate.yandex.net/api/v1.5/tr.json/translate',
method: 'GET',
dataType: 'JSONP',
crossDomain: true,
data: {
key: /* my-secret-key */,
text: $($each).text(),
lang: sourceLang + '-' + targetLang
},
success: function(response) {
try {
if(response.code !== 200)
throw "Response: " + response.code;
$($each).text(response.text[0])
} catch(error) {
console.error('Translation error on element: ', $($function).text());
console.error('Message returned by the server:', error);
}
},
error: function(xhr, status, error) {
console.error('Translation error on element: ', $($function).text());
console.error('Message returned by the server:', xhr.responseText);
}
});
});
}
});
After loading the code I do this:
$(document).ready(function() {
let lang = $('html').attr('lang').split('-')[0];
$('td td:visible').translate(lang, "en");
});
Note: the HTML tag looks like this <html lang="es-ES"> depending on the logged user language.
The issue I have is the table loads after a couple of seconds (since we are not in Production environment they could be more than 30). Therefore the previous code block is not useful.
Note: the <tbody> tag is created when the data is added.
What I have tried is:
1. Create a setInterval() and clearInterval() when the $('td:visible').length is greater than 0:
let iv = setInterval(function() {
let lang = $('html').attr('lang').split('-')[0];
let rows = $('tbody td:visible');
if(rows.length > 0) {
rows.translate(lang, "en");
clearInterval(iv);
}
}, 1000);
2. Set a .delay() before the translation:
let isTranslated = false;
while(!isTranslated) {
let lang = $('html').attr('lang').split('-')[0];
let rows = $('tbody td:visible');
if(rows.length > 0) {
rows.delay(1000).translate(lang, "en");
isTranslated = true;
}
}
The memory consumed by the browser is greater than 200MB. I also tried with $('table').on('DOMSubstreeModified', 'tbody', function() {}) but it didn't work.
So, what approach would you recommend to use this translation plugin on this table after it loads its tbody?
Edit 1:
I have changed my code so I perform less API requests, thanks to the recommendation of #lucifer63:
let $function = this;
let collection = [];
let translation = '';
$(this).each(function() {
collection.push($(this).text());
});
let text = collection.join('::');
$.ajax({
url: 'https://translate.yandex.net/api/v1.5/tr.json/translate',
method: 'GET',
dataType: 'JSONP',
crossDomain: true,
data: {
key: /* my-secret-key */,
text: text,
lang: sourceLang + '-' + targetLang
},
success: function(response) {
try {
if(response.code !== 200) {
throw "Response: " + response.code;
}
translation = response.text[0].split('::');
$($function).each(function() {
$(this).text(translation.shift());
});
} catch(error) {
console.error('Message returned by the server:', error);
}
},
error: function(xhr, status, error) {
console.error('Message returned by the server:', xhr.responseText);
}
});
But still, I need to figure out how to print after data has loaded.
Well... I think I found the answer I was seeking:
$('body').on('DOMNodeInserted', 'table', function() {
$('td:visible').translate('es', 'en');
});
It seems it is working correctly.