Countdown in Angular, with restart - javascript

I have created a simple dashboard with some data as a tryout in Angular. With PHP I get some weather data, news via Google News and 10 tweets about a keyword.
With the $interval I refresh the dashboard every 10 seconds, but I want a countdown from 10 to 0, which starts over and over when the interval is triggered.
Can somebody help me to achieve this?
Current code as submitbutton and $interval trigger:
$scope.formSubmit = function(){
$scope.getResults();
if($scope.interval){
intervalController();
}
}
function intervalController(){
$interval($scope.getResults, 10000);
}
$scope.getResults = function(){
if($scope.city){
$http({
method: 'POST',
url: 'server.php',
data: {city : $scope.city}
}).then(function successCallback(response){
console.log(response.data);
//some data processing here
}, function errorCallback(response){
})
}
}

$scope.initialCountDownValue = 10;
$scope.countDownValue = $scope.initialCountDownValue;
var intervalCanceller = null;
$scope.formSubmit = function(){
$scope.getResults();
if($scope.interval){
intervalController();
}
}
function decrementCountdown() {
$scope.countDownValue -= 1;
if ( $scope.countDownValue === 0) {
$scope.getResults();
$scope.countDownValue = $scope.initialCountDownValue;
}
}
function intervalController(){
intervalCanceller = $interval(decrementCountdown, 1000);
}
$scope.getResults = function(){
if($scope.city){
$http({
method: 'POST',
url: 'server.php',
data: {city : $scope.city}
}).then(function successCallback(response){
console.log(response.data);
//some data processing here
}, function errorCallback(response){
})
}
}
in $scope.countDownValue you have your countdown value to display to the user.
One additional point.
Do not to forget to unsubscribe your $interval on the scope destruction. Or you will have an interval living for ever for nothing.
Here is the way to destroy your interval properly :
$scope.$on('$destroy', function() {
if (intervalCanceller) {
$interval.cancel(intervalCanceller);
}
});

Related

Refresh data without reloading the page

I have a function for adding likes on the page
blade.php
<a href="/article/{{ $article->id }}?type=heart" class="comments-sub-header__item like-button">
<div class="comments-sub-header__item-icon-count">
{{ $article->like_heart }}
</div>
<a href="/article/{{ $article->id }}?type=finger" class="comments-sub-header__item like-button">
<div class="comments-sub-header__item-icon-count">
{{ $article->like_finger }}
</div>
js
$(function() {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
},
});
$('.like-button').on('click', function(event) {
event.preventDefault();
let href = $(this).attr('href');
$.ajax({
url: href,
type: 'POST',
success: function() {
window.location.reload();
},
});
});
});
But when I click on the like to update the data, I reload the page using window.location.reload();
Can this somehow be done without reloading the page?
This is how adding likes is implemented, they are added to cookies and stored for 24 hours
web routes
Route::post('article/{id}', 'App\Http\Controllers\ArticleController#postLike');
Article controller
public function postLike($id, Request $request) {
$article = Article::find($id);
if(!$article){
return abort(404);
}
$type = $request->input('type');
if ($article->hasLikedToday($type)) {
return response()
->json([
'message' => 'You have already liked the Article '.$article->id.' with '.$type.'.',
]);
}
$cookie = $article->setLikeCookie($type);
$article->increment("like_{$type}");
return response()
->json([
'message' => 'Liked the Article '.$article->id.' with '.$type.'.',
'cookie_json' => $cookie->getValue(),
])
->withCookie($cookie);
}
Article model
public function hasLikedToday(string $type)
{
$articleLikesJson = Cookie::get('article_likes', '{}');
$articleLikes = json_decode($articleLikesJson, true);
if (!array_key_exists($this->id, $articleLikes)) {
return false;
}
if (!array_key_exists($type, $articleLikes[$this->id])) {
return false;
}
$likeDatetime = Carbon::createFromFormat('Y-m-d H:i:s', $articleLikes[$this->id][$type]);
return ! $likeDatetime->addDay()->lt(now());
}
public function setLikeCookie(string $type)
{
$articleLikesJson = Cookie::get('article_likes', '[]');
$articleLikes = json_decode($articleLikesJson, true);
$articleLikes[$this->id][$type] = now()->format('Y-m-d H:i:s');
$articleLikesJson = json_encode($articleLikes);
return cookie()->forever('article_likes', $articleLikesJson);
}
Assuming those DIVs hold the number of hearts, if the response of the target page is the new number of hearts then:
success: function(data) {
targetElement.find(".comments-sub-header__item-icon-count").html(data)
}
elsewhere if you want to add +1 to current number regardless of server response:
success: function() {
var current= parseInt(targetElement.find(".comments-sub-header__item-icon-count").html());
targetElement.find(".comments-sub-header__item-icon-count").html(current+1)
}
Footnote: as the ajax request is nested inside the click function, the targetElement in my codes is the clicked element. You may get it in defferent ways e.g.
$('.like-button').on('click', function(event) {
var targetElement=$(this);
....
}
$(function() {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
},
});
$('.like-button').on('click', function(event) {
event.preventDefault();
let href = $(this).attr('href');
$.ajax({
url: href,
type: 'POST',
success: function(response) {
$(this).parent(".comments-sub-header__item-icon-count").html(
parseInt($(this).parent(".comments-sub-header__item-icon-count").html()) + 1
)
// or return like or heart count from server
$(this).parent(".comments-sub-header__item-icon-count").html(response)
},
});
});
});
This should work for you
$(function () {
$.ajaxSetup({
headers: {
"X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
},
});
$(".like-button").on("click", function (event) {
event.preventDefault();
const likeBtn = $(this);
$.ajax({
url: likeBtn.attr("href"),
type: "POST",
success: function () {
let currentCount = likeBtn.next().text();
likeBtn.next().text(parseInt(currentCount) + 1);
},
});
});
});
You can simply add the new count to the response from your controller.
return response()
->json([
'message' => 'Liked the Article '.$article->id.' with '.$type.'.',
'cookie_json' => $cookie->getValue(),
'new_count' => $article->{"like_{$type}"},
])
->withCookie($cookie);
Now you can use the updated count as new_count from the database.
$.ajax({
url: href,
type: 'POST',
success: function (response) {
$(this).next().text(response.new_count)
},
});

Why is my datasource not returning all my data in Angular grid application>?

Let me first preface this by saying...I'm a noob and have been pouring over documentation already but I have not found a resolution.
I have built a custom report in PowerSchool SIS using AngularJS to form my grid and am using JSON data to fill it. The problem I am currently having is the grid is only populating 100 items even though there are close to 200 record items.
This is my JS:
//Begin Module - Loads AngularJS
define(['angular', 'components/shared/index'], function(angular) {
var attApp = angular.module('attApp', ['powerSchoolModule']);
// var yearid = window.location.search.split("=")[1];
//Begin Controller
attApp.controller('attCtrl', ['$scope', 'getData', '$attrs', function($scope, getData, $attrs) {
$scope.curSchoolId = $attrs.ngCurSchoolId;
$scope.curYearId = $attrs.ngCurYearId;
loadingDialog();
$scope.attList = [];
//Sets definition of the var dataSource to pull PowerQueries
var dataSource = {
method: "POST",
url: "/ws/schema/query/com.cortevo.reporting.attendance.absencebymonthschoolgrade",
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
data: {yearid},
dataType: "json",
pages:"50",
};
console.log(dataSource);
//Sets definition of the var dataSource to pull from JSON files
console.log('loading dataSource');
//var dataSource= {method: "GET", url: "attendancedata.json"};
getData.getAttData(dataSource).then(function(retData) {
if (!retData.record) {
alert('There was no data returned');
closeLoading();
} else {
console.log(retData);
if (!!retData.record[retData.record.length]) {
// retData.record.pop();
}
var i = retData.record.length;
while (i--) {
retData.record[i].attendance_date = new Date(retData.record[i].attendance_date) // Changes the text of the attendance date to a JS data
}
//Sets scope of attList and attName
$scope.attList = retData.record;
$scope.attName = retData.name;
console.log($scope.attList);
closeLoading();
}
});
}]); //End Controller
//Begins factory and invokes PowerQueries if available, error message will trigger if no data returned
attApp.factory('getData', function($http) {
return {
getAttData: function(dataSource) {
return $http(dataSource).then(function successCallback(response) {
return response.data;
},
function errorCallback(response) {
alert('There was an error returning data');
});
}
}
}); //End Factory
}); //End Module
We have confirmed there is nothing wrong with my datasource. I'm stuck and could use a guiding word. Any advice would be appreciated.
Try to hit the same endpoint using PostMan, maybe the API is not working.
Also I'm not sure if this url is valid:
url: "/ws/schema/query/com.cortevo.reporting.attendance.absencebymonthschoolgrade"

How to execute a function to update a json source

I have a Leaflet map that show some weather data from a Json source. I have already a function that update the data every x minutes by a setInterval function.
setTimeout(function () {
refreshId = setInterval(function () {
$.ajax({
method: 'get',
dataType: 'text',
url: 'myURLfile.json',
success: function (data) {
if (data) {
markers = [];
var withoutMarkers = data.slice(10);
markers = JSON.parse(withoutMarkers);
//console.log(markers);
replaceMarkers(currentFactor);
}
},
error: function (err) {
console.error('there is not date for today.', err)
}
})
}, 300000);
},10000)
}
What I would to do now is assign this funtion to a button to execute the refresh fuction manually.
Something like
L.easyButton( 'fas fa-cloud-sun-rain', function(){
myfunction()
}, 'Refresh', {
position: 'topright'
})
But I don't understand what I have to call exactely to do it.
Factor your fetch code out of setInterval and use your newly made function both in setInterval and your button definition.
Something like
function fetchData() {
$.ajax({
method: 'get',
dataType: 'text',
url: 'myURLfile.json',
success: function (data) {
if (data) {
markers = [];
var withoutMarkers = data.slice(10);
markers = JSON.parse(withoutMarkers);
//console.log(markers);
replaceMarkers(currentFactor);
}
},
error: function (err) {
console.error('there is not date for today.', err)
}
});
}
// setup your interval
setInterval(fetchData, 300000);
// setup your button
L.easyButton( 'fas fa-cloud-sun-rain', fetchData, 'Condizioni', {
position: 'topright'
})

Change $scope value after http request

I am trying to show different divs depending the response I get from an http request.
$scope.firstStep = true;
$scope.secondStep = false;
$scope.thirdStep = false;
$http({
method: 'GET',
url: '/api-web/ec/cadastro/recuperar-acesso',
data: {
filiacao: $scope.currentFiliacao,
cnpj: $scope.currentCNPJ
},
headers: {'Content-Type': 'application/json'}
}).then(function(res){
$scope.firstStep === false;
if (res.data.code === -1) {
$timeout( function (){
$scope.secondStep === true; //here is the bug, it dont change to true
console.log("second", $scope.secondStep);
}, 3000)
}
})
I tried several things, like $apply(), _defer, switch from === to =
... and I have no idea why its happening.
Any ideas ?
Doesn't this work?
$timeout( function (){
$scope.secondStep = true;
$scope.apply();
console.log("second", $scope.secondStep);
}, 3000)

Kill Ajax Session Outside of Originating Function

I have an AJAX function I'd like to kill, but it is outside of the function. Take a look:
function waitForMsg(){
var heartbeat = $.ajax({
type: "GET",
url: "includes/push_events.php",
tryCount : 0,
retryLimit : 3,
async: true,
cache: false,
// timeout: 500,
success: function(data){
console.log(data);
if(data){
if(data.current_date_time){
updateTime(data.current_date_time);
}
if(data.color){
console.log("Receiving data");
displayAlert(data.color, data.notification_message, data.sound, data.title);
}
if(data.user_disabled){
console.log("Receiving data");
fastLogoff();
checkDisabled();
}
}
setTimeout(
waitForMsg,
5000
);
},
error: function(data){
if (data.status == 500) {
console.log("Connection Lost to Server (500)");
$.ajax(this);
} else {
console.log("Unknown Error. (Reload)");
$.ajax(this);
}
},
dataType: "json"
});
};
// Detect browser open.
$(document).ready(function(){
// window.onunload = function(){alert('closing')};
// mainmode();
$('#alertbox').click(function(){
$('#alertbox').slideUp("slow");
});
$(document).ready(function(){
$('#alertbox').click(function(){
$('#alertbox').slideUp("slow");
});
// Check focal point
var window_focus = true;
$(window).focus(function() {
window_focus = true;
console.log('Focus');
});
$(window).blur(function() {
window_focus = false;
console.log('Blur');
});
setInterval(function(){
if(window_focus == true){
console.log('in focus');
waitForMsg();
}else{
console.log('out of focus');
heartbeat.abort();
}
}, 5000);
});
});
If you notice, the ajax is outside of the document.ready. I am trying to kill the ajax calls if the user goes to a different window, then restart the calls once the return to the window. The start works, but if the user goes away from the window, it gives me the "heartbeat is not defined". Obviously this is because its outside of that function. Any work arounds?
I'd refactor a bit the code to avoid the usage of setInterval and clean up a bit the code.
You can abstract the logic in an object, let's say Request. You can add two methods to resume and stop which will handle the status of the underlying AJAX request.
var Request = function(options){
var request = this, xhr = null, aborted = false;
/* Resumes the operation.
* Starts a new request if there's none running.
*/
request.resume = function() {
aborted = false;
request.retry();
};
/* Retry loop.
*/
request.retry = function(){
if(!xhr) {
xhr = $.ajax(options).done(function(){
request.destroy();
!aborted && setTimeout(function(){
request.retry();
}, options.timeout);
});
}
};
/* Aborts the current operation.
*/
request.abort = function(){
aborted = true;
if(xhr) xhr.abort();
request.destroy();
};
/* Destroy.
*/
request.destroy = function(){
xhr = null;
};
return request;
};
Now, you can drop the setInterval.
$(function () {
var request = new Request({
type: "GET",
url: "includes/push_events.php",
timeout: 5000,
success: function(data){
/* Success handler */
},
error: function(data){
/* Error handler */
},
dataType: "json"
});
$(window).focus(function () {
request.resume();
}).blur(function () {
request.abort();
});
request.resume();
});
The Request constructor receives the $.ajax options which should contain an additional timeout parameter that specifies the delay between requests.
You need to stop further request after window.blur. restart request after window.focus.
Modified code
var setTimeoutConst;
function waitForMsg(){
if(!window_focus){
return; //this will stop further ajax request
}
var heartbeat = $.ajax({
type: "GET",
url: "includes/push_events.php",
tryCount : 0,
retryLimit : 3,
async: true,
cache: false,
// timeout: 500,
success: function(data){
console.log(data);
if(data){
if(data.current_date_time){
updateTime(data.current_date_time);
}
if(data.color){
console.log("Receiving data");
displayAlert(data.color, data.notification_message, data.sound, data.title);
}
if(data.user_disabled){
console.log("Receiving data");
fastLogoff();
checkDisabled();
}
}
setTimeoutConst= setTimeout(waitForMsg,5000);
},
error: function(data){
if (data.status == 500) {
console.log("Connection Lost to Server (500)");
// $.ajax(this);
} else {
console.log("Unknown Error. (Reload)");
//$.ajax(this);
}
setTimeoutConst= setTimeout(waitForMsg,5000); // continue sending request event if last request fail
},
dataType: "json"
});
};
var window_focus = true;
$(document).ready(function(){
$('#alertbox').click(function(){
$('#alertbox').slideUp("slow");
});
$('#alertbox').click(function(){
$('#alertbox').slideUp("slow");
});
// Check focal point
$(window).focus(function() {
if(window_focus ){return}
window_focus = true;
waitForMsg();
console.log('Focus');
});
$(window).blur(function() {
if(!window_focus ){return}
clearTimeout(setTimeoutConst);
window_focus = false;
console.log('Blur');
});
waitForMsg();
});

Categories

Resources