JavaScript timer is not working - javascript

I have created a file named ExtremeNotifications.js and added to the _Layout.cshtml master layout.
The ExtremeNotifications.js includes the following JavaScript code:
var extremeNotifications = extremeNotifications || {};
extremeNotifications = (function () {
var baseURL = document.baseURI;
var url = baseURL + 'api/usernotifications';
var isNotificationServiceStarted = false;
var timer;
function getPendingNotifications() {
$.ajax({ url: url, success: dataRetrieved, type: 'GET', dataType: 'json' });
}
function dataRetrieved(data) {
alert(data);
}
function startNotifications() {
if (!isNotificationServiceStarted) {
timer = setInterval(getPendingNotifications, 3000);
isNotificationServiceStarted = true;
}
}
function stopNotifications() {
clearInterval(timer);
isNotificationServiceStarted = false;
}
return {
start: startNotifications(),
getPendingNotifications: getPendingNotifications(),
isNotificationServiceStarted: isNotificationServiceStarted,
stop: stopNotifications()
}
})();
Then in my Home Index.cshtml I start the notifications with the following code and only if User.Identity.IsAuthenticated:
<script>
extremeNotifications.start();
</script>
So now when my page starts and I'm authenticated user I get an alert box in the first time but I never see another alert after 3 seconds.
Any comments?

You're close, but you're creating that returned object incorrectly:
return {
start: startNotifications,
getPendingNotifications: getPendingNotifications,
isNotificationServiceStarted: isNotificationServiceStarted,
stop: stopNotifications
};
By including the () after the function names, your code was calling the functions and returning their return values instead of returning references to the functions themselves.

Related

'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() {});

Why doesn't the setInterval function stop?

I'm trying to clear the time interval which runs every 15 seconds.
Here is the ajax request:
function extras()
{
$x = {
action:'extras'
};
var r;
$.ajax({
type:'POST',
url:'services.php',
data:$x,
beforeSend:function() {
$('input[name="stop_"]').trigger("click");
},
success:function(response) {
r = response;
//console.log(response)
},
complete:function() {
console.log(r);
$('input[name="re_start"]').trigger("click");
}
});
}
So, in my buttons re_start and stop_ i have:
$('input[name="re_start"]').click(function (event) {
event.preventDefault();
clearInterval(check);
var check = setInterval(function() {
extras();
},15000);
console.log('Starting again...');
});
$('input[name="stop_"]').click(function (event) {
event.preventDefault();
clearInterval(check);
console.log('Stop');
});
In my DOM in jQuery I initialize the function extras() and keep it in a variable called "check" where I initialize the time interval as follows:
<input type="button" style="display:none;" name="re_start">
<input type="button" style="display:none;" name="stop_">
<script type="text/javascript">
(function() {
extras();
var check = setInterval(function() {
extras();
},15000);
})();
function extras()
{
$x = {
action:'extras'
};
var r;
$.ajax({
type:'POST',
url:'services.php',
data:$x,
beforeSend:function() {
$('input[name="stop_"]').trigger("click");
},
success:function(response) {
r = response;
//console.log(response)
},
complete:function() {
console.log(r);
//message_smart(r);
$('input[name="re_start"]').trigger("click");
}
});
}
</script>
Then I can not understand how it is possible that the first 30 seconds work and when they pass 60 seconds seem to start doing things twice at once, then three and so on! It seems like if I change the interval every second and will run faster and faster. What is the problem?
The problem is here:
(function() {
extras();
var check = setInterval(function() {
extras();
},15000);
})();
You are creating a variable check in a new function scope that is inaccessible outside of that scope. Microsoft has a good example of scope in javascript. Additionally you can see this question.
Now to solve your problem you need to put the check variable in the global scope so remove the function wrapper.
extras();
var check = setInterval(function() {
extras();
},15000);
You also need to change the restart handler to reassign the variable, like so:
$('input[name="re_start"]').click(function (event) {
event.preventDefault();
clearInterval(check);
check = setInterval(function() {
extras();
},15000);
console.log('Starting again...');
});
Now they should all be using the same check variable and work as expected when clearing the timeout.

2 javascripts are conflicting

I have 2 javascripts that are conflicting with eachother, the newer one (Zeroclipboard) conflicts with the older one (delete row) and won't let the delete row one work. The moment i removed the zeroclipboard one, delete worked.
Tried adding jQuery.noConflict(); but didn't seem to work. By reading few solutions, I decided to remove $ signs, but still no.
I have a files.php file, including the header.php file. I am adding the custom.js file in header.php, which holds many functions for operations across the project, including the delete row function. Whereas, the newer script for ZerClipboard is in files.php itself.
Older one, to delete a table row on delete icon click, which won't work after I add the next:
custom.js
function deleteRow()
{
var current = window.event.srcElement;
while ( (current = current.parentElement) && current.tagName !="TR");
current.parentElement.removeChild(current);
}
$(document).ready(function()
{
$('table#delTable td a.delete').click(function()
{
if (confirm("Are you sure you want to delete?"))
{
var fid = $(this).parent().parent().attr('fid');
var str=$(this).attr('rel');
var data = 'fid=' + $(this).attr('rel') + '&uid=' + $(this).parent().attr('rel');
var deletethis = '#tr' + $(this).attr('rel');
var parent = $(this).parent().parent();
$.ajax(
{
type: "POST",
url: "delete.php",
data: data,
cache: false,
success: function(msg)
{
$(deletethis).fadeOut('slow', function() {$(this).remove();});
}
});
}
});
$('table#delTable tr:odd').css('background',' #FFFFFF');
});
ZeroClipboard's JS and SWF, along with this js to copy some text on clipboard on Share icon click:
files.php
<script type="text/javascript" src="js/ZeroClipboard.js"></script>
<script language="JavaScript">
var clip = null;
function $(id) { return document.getElementById(id); }
function init()
{
clip = new ZeroClipboard.Client();
clip.setHandCursor( true );
}
function move_swf(ee)
{
copything = document.getElementById(ee.id+"_text").value;
clip.setText(copything);
if (clip.div)
{
clip.receiveEvent('mouseout', null);
clip.reposition(ee.id); }
else{ clip.glue(ee.id); }
clip.receiveEvent('mouseover', null);
}
</script>
I used this blog post for implementing multiple zerclipboard - http://blog.aajit.com/easy-multiple-copy-to-clipboard-by-zeroclipboard/
And, here's the HTML source generated by the files.php page - http://jpst.it/tlGU
Remove the follow function definition of your second script:
function $(id) { return document.getElementById(id); }
Because this is redefining your $ object in window context, due when you use $ in your first script you're not using jquery, instead you're using your new function definition.
Hope this helps,
Here is how you should use noConflict() :
function deleteRow()
{
var current = window.event.srcElement;
while ( (current = current.parentElement) && current.tagName !="TR");
current.parentElement.removeChild(current);
}
jQuery.noConflict(); // Reinitiating $ to its previous state
jQuery(document).ready(function($) // "Protected" jQuery code : $ is referencing jQuery inside this function, but not necessarily outside
{
$('table#delTable td a.delete').click(function()
{
if (confirm("Are you sure you want to delete?"))
{
var fid = $(this).parent().parent().attr('fid');
var str=$(this).attr('rel');
var data = 'fid=' + $(this).attr('rel') + '&uid=' + $(this).parent().attr('rel');
var deletethis = '#tr' + $(this).attr('rel');
var parent = $(this).parent().parent();
$.ajax(
{
type: "POST",
url: "delete.php",
data: data,
cache: false,
success: function(msg)
{
$(deletethis).fadeOut('slow', function() {$(this).remove();});
}
});
}
});
$('table#delTable tr:odd').css('background',' #FFFFFF');
});
And in files.php:
<script src="js/ZeroClipboard.js"></script>
<script>
var clip = null;
function $(id) {
return document.getElementById(id);
}
function init() {
clip = new ZeroClipboard.Client();
clip.setHandCursor(true);
}
function move_swf(ee) {
copything = document.getElementById(ee.id + "_text").value;
clip.setText(copything);
if (clip.div) {
clip.receiveEvent('mouseout', null);
clip.reposition(ee.id);
} else {
clip.glue(ee.id);
}
clip.receiveEvent('mouseover', null);
}
</script>

How do I test to see if <DIV> contents have changed before displaying them

Ive got a div with the id "responsecontainer" and I want to load a page. If the contents of the DIV have changed then update the DIV otherwise just leave it the same.
Here is my code, which doesnt work;
<script>
$(document).ready(function () {
$("#responsecontainer").load("qr.asp");
var refreshId = setInterval(function () {
$.get("qr.asp?randval=" + Math.random(), function (result) {
var newContent = $('.result').html(result);
if (newContent != $("#responsecontainer")) {
$("#responsecontainer").html(result);
};
});
}, 5000);
$.ajaxSetup({
cache: false
});
});
</script>
This:
if (newContent != $("#responsecontainer")) {
Should be this:
if (newContent != $("#responsecontainer").html()) {
I wouldn't rely on .html() representations for string comparison.
The browser decides how the HTML string should be rendered, and the developer won't be able to have any control if the browser decides it should be displayed differently one time.
You should have a variable that is accessible to each interval invocation, and do a string comparison between the old and new responses.
$(document).ready(function () {
var prev_response;
$("#responsecontainer").load("qr.asp", function(resp) {
prev_response = resp;
});
var refreshId = setInterval(function () {
$.get("qr.asp?randval=" + Math.random(), function (result) {
if (prev_response !== result) {
prev_response = result;
$("#responsecontainer").html(result);
}
});
}, 5000);
$.ajaxSetup({
cache: false
});
});

Categories

Resources