How to stop Javascript from repeating the function? - javascript

Guys I have a javascript which has a each loop in which I am calling a particular function for each index value. This script executes on mouse scroll event upon reaching page end (lazy loading).
This is the main section of the script :
function (data) {
$.each(data, function (index, value) {
BindNotice(value);
});
}
Now the problem is, after the index reaches it max value, it restarts from the 0 index. So I am getting repeated data in my view. I want to restrict this script to only execute until the index has reached the max value. How would I go about doing this ?
EDIT : ADDED COMPLETE FUNCTION
function callMoreData()
{
$.ajax(
{
type: "GET",
url: "/api/values/getnotice",
dataType: "json",
crossDomain: true,
async: true,
cache: false,
allow: true,
success: function (data) {
$.each(data, function (index, value) {
BindNotice(value);
});
},
error: function (x, e) {
alert('problem while fetching records!');
}
} );}
From JS file :
$(".mainwrap .innnerwrap").mCustomScrollbar({
autoDraggerLength:true,
autoHideScrollbar:true,
scrollInertia:100,
advanced:{
updateOnBrowserResize: true,
updateOnContentResize: true,
autoScrollOnFocus: false
},
callbacks:{
whileScrolling:function(){WhileScrolling();},
onTotalScroll: function () {
callMoreData();
}
}
});

You could call another function, and then set it to do nothing after first go through.
function (data) {
updateData(data);
}
function updateData(data) {
updateData = function(data) {};
$.each(data, function (index, value) {
BindNotice(value);
});
}
Demo using alerts.
I made some edits to the code because it sounds more like you're getting multiple events and they are writing over previous events. After the first call, the function is basically set to do nothing. Thus the first callback will be the only callback that calls BindNotice.
Edit
As I mentioned in the comments, to ever receive data again through this channel, you need to restore updateData. Here's an example:
function restoreUpdateData() {
updateData = function(data) {
updateData = function(data) {};
$.each(data, function (index, value) {
BindNotice(value);
});
};
}

Use a global variable to block other requests to this function.
Something like:
var allow = true;
function (data) {
if(allow == true){
allow = false;
$.each(data, function (index, value) {
BindNotice(value);
});
allow = true;
}
}

Related

JavaScript/jQuery: How to run a function after an each() loop has finished?

I have the following. What is basically happening is I'm prefilling all the dropdowns/select options. I then retrieve the data for the current record and select the appropriate value for each dropdown/select option.
$(dropdowns_sql).each(function (key, value) {
var sql = value.sql;
var dropdown = value.dropdown;
$.post(d + '/inc/db.asp', {
type: value.sql
}, function (data) {
json_object = JSON.parse(data);
}).done(function () {
$.each(json_object, function (k, v) {
$('#' + dropdown).append($("<option></option>").attr("value", v[sql]).text(v[sql]));
});
});
});
get_record_data();
My question is how I can ensure that get_record_data(); is run after the loop has finished? As you can see I make POST requests within the loop so what I am finding is that sometimes these don't finish before get_record_data(); is called.
I did try:
$( document ).ajaxStop(function() {
get_record_data();
});
However since get_record_data(); is doing an AJAX request as well, I am finding it just goes into an infinite loop
function get_record_data() {
$.post(d + '/inc/db.asp', {
type: 'get_record',
id: complex_record_id
}, function (data) {
...
Any suggestions? I need support for IE11 as well.
Thanks.
Know how many elements are in dropdowns_sql, make a count var and include the get_record_data call within the done function for the last element.
Something like:
var count = dropdowns_sql.length;
$(dropdowns_sql).each(function (key, value) {
var sql = value.sql;
var dropdown = value.dropdown;
$.post(d + '/inc/db.asp', {
type: value.sql
}, function (data) {
json_object = JSON.parse(data);
}).done(function () {
$.each(json_object, function (k, v) {
$('#' + dropdown).append($("<option></option>").attr("value", v[sql]).text(v[sql]));
});
if (!--count) get_record_data();
});
});

'No Data' view getting opens first and then Detail Page opens with the data in Fiori

I am developing a Master Detail application in which if the service URL doesn't return data, then a view called 'NoData' should open. But what actually is happening that first, the 'NoData' view opens and then the Detail Page with the data gets displayed. I don't know why and how that 'NoData' page is appearing first. Below is my code for Master Page :
Controller.js :
onInit: function () {
this.router = sap.ui.core.UIComponent.getRouterFor(this);
this._custTemp = this.getView().byId("listItemTemp").clone();
this.refreshFlag = true; // Flag to get new data or not for customers
this.totalModel = sap.ui.getCore().getModel("totalModel");
this.getView().setModel(this.totalModel, "totalModel");
this.oDataModel = sap.ui.getCore().getModel("DataModel");
this.getView().setModel(this.oDataModel, "DataModel");
this.oInitialLoadFinishedDeferred = jQuery.Deferred();
var oEventBus = sap.ui.getCore().getEventBus();
this.getView().byId("listId").attachEvent("updateFinished", function () {
this.oInitialLoadFinishedDeferred.resolve();
oEventBus.publish("MasterPage", "InitialLoadFinished", {
oListItem: this.getView().byId("listId").getItems()[0]
});
if (!sap.ui.Device.system.phone) {
this._getFirstItem();
}
}, this);
this.functionData = [];
},
waitForInitialListLoading: function (fnToExecute) {
jQuery.when(this.oInitialLoadFinishedDeferred).then(jQuery.proxy(fnToExecute, this));
},
_getFirstItem: function () {
sap.ui.core.BusyIndicator.show();
this.waitForInitialListLoading(function () {
// On the empty hash select the first item
var list = this.getView().byId("listId");
var selectedItem = list.getItems()[0];
if (selectedItem) {
list.setSelectedItem(selectedItem, true);
var data = list.getBinding("items").getContexts()[0];
sap.ui.getCore().getModel("detailModel").setData(data.getObject());
this.router.navTo('DetailPage', {
QueryNo: data.EICNO
});
sap.ui.core.BusyIndicator.hide();
} else {
this.router.navTo('NoData');
}
}, this);
},
onBeforeRendering: function () {
this._fnGetData();
},
_fnGetData: function (oEvent) {
var that = this;
this.getView().setModel(this.totalModel, "totalModel");
if (this.refreshFlag === true) {
sap.ui.core.BusyIndicator.show(0);
$.ajax({
url: "/sap/opu/odata/sap/ZHR_V_CARE_SRV/EmpQueryInitSet('10002001')?$expand=QueryLoginToQueryList/QueryToLog",
method: "GET",
dataType: "json",
success: function (data) {
that.getView().getModel("totalModel").setData(data.d.QueryLoginToQueryList);
that.refreshFlag = false;
sap.ui.core.BusyIndicator.hide();
that.statusList();
},
error: function (err) {
sap.ui.core.BusyIndicator.hide();
MessageBox.information(err.responseText + "Please try again");
}
});
}
}
totalModel is a json model, right? You'll get two updateFinished events on app load. The first one is triggered once the list control is rendered and binding is done (when the model has no data), and the second comes after your $.ajax call updates data to totalModel.
I think you can solve it by moving your NoData navigation to both 'success' and 'error' callbacks of your $.ajax call. Doing so may cover other use cases e.g. if you are using URL navigation parameters and a user changes the entity ID in the URL to some random number, it'd navigate to your NoDatapage.

Repeated Ajax calls using SetTimeout javascript, unexpected execution

I list of users in a html table that is dynamically created on page load. Each row has an inline button and each button has onclick="functionName(userId)", calls the following functions:On click show the bootstrap model pop up and then after starts calling ajax. The problem is stopping the ajax calls after user has closed model,and if user clicks on another row/user pass the current userId. for some reason, sometimes ajax calls stop and sometimes dont. Previous userId is also being saved somewhere which is resulting double or triple calls in a given interval. Thank you for your insights.
//This function gets called from each row passing its userId:
var timer = null;
function RTLS(id) {
$('#RTLSModal').modal('show');
window.clearTimeout(timer);
$('#RTLSModal').on('hidden.bs.modal',
function() {
window.clearTimeout(timer);
timer = 0;
$('#RTLSModal .modal-body').html("");
$('#RTLSModal').data('bs.modal', null);
});
$('#RTLSModal').on('shown.bs.modal',
function () {
GetRealTimeScans(id);
});
}
function GetRealTimeScans(id) {
var html = '';
$.ajax({
url: '/api/v1/computers/GetRealTimeKeys?computerId=' + id,
typr: "GET",
contentType: "application/json;charset=UTF-8",
dataType: "json",
success: function (scans) {
if (scans.length > 0) {
$.each(scans,
function (index, value) {
//create html
});
$('#RTLSModal .modal-body').html(html);
} else {
html += '<div class=""><h3 style="text-align: center;">No one around</h3></div>';
$('#RTLSModal .modal-body').html(html);
}
},
complete: function () {
timer = setTimeout('GetRealTimeScans('+id+')', 10000);
}
});
}
So abort the Ajax call so it stops
var timer = null;
var ajaxCall;
function cleanUp () {
if (timer) window.clearTimeout(timer);
if (ajaxCall) ajaxCall.abort()
}
and when you make the call
cleanUp()
ajaxCall = $.ajax({})
.done( function () {
ajaxCall = null
timer = window.setTimeout(function(){}, 10000)
});
And when you bind the events to the modal, you need to remove the previous event handler.
$('#RTLSModal')
.off('hidden.bs.modal shown.bs.modal')
.on('hidden.bs.modal', function() {})
.on('shown.bs.modal', function() {});

Issue with javascript and setting selected index of a select

I've got a piece of code that populates a dropdown based on the selection of another dropdown. This propogates through 4 dropdowns so:
selection -> selection based on 1 -> selection based on 1 & 2 -> selection based on 1, 2, & 3.
My issue is that sometimes the selection only comes up as 1 item, making it such that the user cannot "fire" the onchanged event. As such, upon population, I want to set the selected index to 0. Easy peasy, right?
So here's my code (edited to include full javascript function):
function FillProject() {
var BusinessAreaDropDown = document.getElementById("BusinessAreaDropDown");
var BusinessAreaSelection = BusinessAreaDropDown.options[BusinessAreaDropDown.selectedIndex].text
var GenericProjectDropDown = document.getElementById("GenericProjectDropDown");
if (GenericProjectDropDown.selectedIndex == -1) {
GenericProjectDropDown.selectedIndex = 0;
}
var GenericProjectSelection = GenericProjectDropDown.options[GenericProjectDropDown.selectedIndex].text
#* Get list from C# for GenericProjects matching *#
$.ajax({
url: '/Home/FillProject',
type: "GET",
dataType: "JSON",
data: { BusinessArea: BusinessAreaSelection, GenericProject: GenericProjectSelection },
error: function (error) {
alert(error);
},
success: function (Projects) {
$("#ProjectDropDown").html("");
$.each(Projects, function (i, project) {
$("#ProjectDropDown").append(
$('<option></option>').val(project).html(project));
});
}
})
}
This generates an error. If I place an alert after the if statement, it says that the selected index is still -1. Here's where stuff gets weird. If I place an alert INSIDE the if statement it pops up saying that the selected index is -1 before changing, 0 after changing, and actually changes the selectedIndex to 0, causing the code to work. If I remove the alert statement, it goes back to failing. What's happening here?
Examples:
Works->
if (GenericProjectDropDown.selectedIndex == -1) {
alert(GenericProjectDropDown.selectedIndex);
GenericProjectDropDown.selectedIndex = 0;
}
Works->
if (GenericProjectDropDown.selectedIndex == -1) {
GenericProjectDropDown.selectedIndex = 0;
alert(GenericProjectDropDown.selectedIndex);
}
Fails ->
if (GenericProjectDropDown.selectedIndex == -1) {
GenericProjectDropDown.selectedIndex = 0;
}
Solution! Thanks to #charlietfl
I had some ajax that was running in a previous code chunk populating the dropdown and it wasn't finixshed before running the second script because it was asynchronous. By adding:
$.ajax({
url: '/Home/FillProject',
type: "GET",
dataType: "JSON",
async: false, //this line
data: { BusinessArea: BusinessAreaSelection, GenericProject: GenericProjectSelection },
error: function (error) {
alert(error);
},
success: function (Projects) {
$("#ProjectDropDown").html("");
$.each(Projects, function (i, project) {
$("#ProjectDropDown").append(
$('<option></option>').val(project).html(project));
});
The issue was resolved!

autofocus(autotab) on next element is not working for dynamically created fields

$("#destination1" + countVar).autocomplete({
minLength : 3,
source : function(request, response) {
var url = configOptions.icaocodeUrl;
var term = request.term;
url=url+term;
console.log(url);
$.ajax({
url : url,
type : "GET",
data : request,
dataType : "json",
success : function(data) {
response(data.slice(0, 10));
//alert(data);
},error: function(xhr, textStatus) {
alert('error');
}
});
},
change:function(event,ui){
console.log("fired in dest2");
},close:function(event,ui){
console.log("close in dest2"+'#dof1'+countVar);
console.log(countVar);
$(this).parents('form').find('#dof1'+countVar)
.filter(function () { return $(this).val() === ''; })
.first().focus();
}
});
above is my code for autocomplete and autotab(autofocus) to next field for dynamically created elements.autotab(autofocus ) is working fine for normal html but it is not working for dynamically created elements only.
Are you trying to focus() on a tab that is being dynamically added? If so, you might be triggering focus() to soon and the DOM element might not be there.
Try wrapping the focus function into a setTimeout() function to test it out.
setTimeout(function () {
$(this).parents('form').find('#dof1'+countVar)
.filter(function () { return $(this).val() === ''; })
.first().focus();
}, 2000); // 2 seconds

Categories

Resources