Refreshing / Cycling through a parsed RSS feed every 5 mins - javascript

I am working on a monitor signage display and have a "welcome to RSS" feed with just a title and desc. I have code from feedEk that's been tweaked a bit to parse the feed and cycle it so I only have one title and desc. showing at a time. This feed could be added to or deleted info at any time so I need it to refresh every five mins. I've tried several solutions on here and just can't seem to work it out.
Here is the adjusted FeedEk code with comments on the adjustments:
(function (e) {
e.fn.FeedEk = function (t) {
var n = {
FeedUrl: "http://myrss.com/",
MaxCount: 1,
ShowDesc: true,
ShowPubDate: false,
CharacterLimit: 100,
TitleLinkTarget: "_self",
iterate: false
};
if (t) {
e.extend(n, t)
}
var r = e(this).attr("id");
var i;
processFeedData = function (t) {
//This just makes it flash too much
//e("#" + r).empty();
var s = "";
en = t.responseData.feed.entries;
if (n.iterate == true) {
//Setting a variable to store current item
i = window.feedcur = typeof(window.feedcur) === 'undefined' ? 0 : window.feedcur;
t = en[i];
s = makeString(t);
//incrementing the current for the next time we loop through
window.feedcur = ((i+1)%en.length);
} else {
for (i=0;i<en.length;i++) {
t = en[i];
s += makeString(t);
}
}
//Changing this to just replace what was there (less blinky feeling)
e("#" + r).html('<ul class="feedEkListSm">' + s + "</ul>");
}
makeString = function (t) {
s = '<li><div class="itemTitleSm"><a href="' + t.link + '" target="' + n.TitleLinkTarget + '" >' + t.title + "</a></div><br>";
if (n.ShowPubDate) {
i = new Date(t.publishedDate);
s += '<div class="itemDateSm">' + i.toLocaleDateString() + "</div>"
}
if (n.ShowDesc) {
if (n.DescCharacterLimit > 0 && t.content.length > n.DescCharacterLimit) {
s += '<div class="itemContentSm">' + t.content.substr(0, n.DescCharacterLimit) + "...</div>"
} else {
s += '<div class="itemContentSm">' + t.content + "</div>"
}
}
return s;
}
if (typeof(window.feedContent) === 'undefined') {
e("#" + r).empty().append('<div style="padding:3px;"><img src="loader.gif" /></div>');
e.ajax({
url: "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=" + n.MaxCount + "&output=json&q=" + encodeURIComponent(n.FeedUrl) + "&hl=en&callback=?",
dataType: "json",
success: function (t) {
window.feedContent = t;
processFeedData(window.feedContent);
}
});
} else {
processFeedData(window.feedContent);
}
}
})(jQuery)
On the php page I have the following code which cycles through on an interval. I've tried wrapping this into another function that refreshes it but that didn't work. I've also tried just refreshing the page, but that just makes the whole page blink and still doesn't refresh the feed. It seems to refresh every 12 to 24 hours.
<!-- this is for the rss feed -->
<script type="text/javascript" >
$(document).ready(function () {
feedsettings = {
FeedUrl: 'http://myrss.com/',
MaxCount: 100,
ShowDesc: true,
ShowPubDate: false,
DescCharacterLimit: 100,
iterate: true
}
$('#divRss').FeedEk(feedsettings);
setInterval(function(){
$('#divRss').FeedEk(feedsettings);
},7000);
});
</script>
<style>
.rssDiv{float:right; padding-left:35px;}
ul{width:500px !important}
</style>
<!-- end feed stuffs -->
Any help guidance assistance or direction is immensely appreciated. I have to make this self sustaining with little to no extra installations. I've also posted this on code review but I think that may have been the wrong place to post this initially.

Related

Add class to div in jQuery based on a date

I admit not being so great with JavaScript.
I've been tasked to build a utility that will run a check to see if a campaign date is going to expire in 2 weeks or less and add a class if it's going to.
The date is coming from a service and it's built (datatables map) as follows.
The data is coming back undefined but that's a different issue.
Any feedback would be greatly appreciated because I don't seem to be having any luck whatsoever.
Initially I had a date object in there but wasn't sure it was necessary.
/*HTML Rendered Out for that table cell (there are multiple but this is how it
comes out*/
<td class=" campaign_start_date small-screen small-screen-2-col">06/14/2017 -
<div class="campaign-end-date">06/29/2017</div></td>
JS
//Datatables Code & modified for our project
{title:ax.L(114), class:'campaign_start_date small-screen small-screen-2-col', data:function(row, type, val, meta) {
var campaignEndDate = ax.Utils.deNull(row.campaign_end_date, '');
campaignEndDate = ax.Utils.RFCFormat(campaignEndDate, { excludeTime: true });
var campaignStartDate = ax.Utils.deNull(row.campaign_start_date, '');
campaignStartDate = ax.Utils.RFCFormat(campaignStartDate, { excludeTime: true });
var campaignDateString;
if (campaignEndDate && campaignStartDate ) {
campaignDateString = campaignStartDate + ' - ' + '<div class="campaign-end-date">' + ax.Utils.campaignEndDateAlert(campaignEndDate) + '</div>';
} else {
if (!campaignEndDate && campaignStartDate) {
campaignDateString = campaignStartDate + ' - ? ';
}
else if (!campaignStartDate && campaignEndDate) {
campaignDateString = ' ? - ' + campaignEndDate;
}
else {
campaignDateString = ' ';
}
}
return campaignDateString
//My attempt at doing this from the Utility file - the code that i'm having no luck with.
publicMethods.campaignEndDateAlert = function (data) {
var campaignDateEnd = data.campaign_end_date;
var $orderTable = $('#order-table');
var $campaignDate = $orderTable.find('.campaign-end-date')
if (campaignDateEnd <= campaignDateEnd + 86400000) {
$campaignDate.addClass('green');
}
}

How to return a variable from a callback after building variable with .getjson and .each

The Problem
I'm trying to figure out how to return HTML that I've built from a JSON file with jQuery.
I seem to have gotten returnLocations() to wait until getLocations() is finished so that the variable locationsBody is finalized with information gathered from my .each loop. The trouble (I think) is my not being able to return that variable to output it to my HTML page.
The Question
How can I return the variable locationsBody?
Note
(there may be errors in the below code as I trimmed it down as best I could but I think it should illustrate the problem with or without them)
The jQuery
the global variables
var locationsFull = 'un d fined';
var locationsOpener = '' +
'<div class="locations-header">places youve been</div>' +
'<div class="locations-container">' +
'<div class="locations-nav left">left</div>' +
'<div class="locations-nav right">right</div>'
;
var locationsBody = '<div class="locations-inner">'; // opening of container
var locationsCloser = '</div>'; // closing of container
the function
function locationsFunction() {
function getLocations() {
var wait = $.Deferred();
var area = 'Area1';
var counter = 1;
$.getJSON("locations.json", function(data) {
$(data.places).each(function() {
var location = this.location;
var image = this.image;
if (this.area === 'Area1') {
if (counter == 2) {
locationsBody = locationsBody +
'<div class="locations-places">' +
'<img src="images/places/' + image + '">' +
'<div class="locations-places-image">' + location + '</div>' +
'</div></div>'
;
counter = 0; // added closing of container, reset to 0
} else {
locationsBody = locationsBody +
'<div class="locations-places">' +
'<img src="images/places/' + image + '">' +
'<div class="locations-places-image">' + location + '</div>' +
'</div>'
;
counter = counter + 1;
}
}
})
wait.resolve();
})
return wait;
}
function returnLocations() {
locationsFull = locationsOpener + locationsBody + locationsCloser; // works, proven in alert and console.log
//alert(locationsFull); // works
console.log(locationsFull); // works
//return locationsFull; // doesnt work
//return 'anything'; // doesnt work
}
getLocations().then(returnLocations);
}
the call
$(function() {
$('.locations-body').html(locationsFunction());
})
The JSON File
{"places":[
{
"area": "Area1",
"location": "Downtown",
"image": "downtown.jpg"
},
{
"area": "Area1",
"location": "Uptown",
"image": "uptown.jpg"
}
]}
The HTML
<div class="locations-body"></div>
Further Note: Questions similar to this have been asked dozens of times on stackoverflow alone and those questions and answers have hundreds of thousands of reads. I have read through all of the top ones and more over the last 2 days. My problem is my inability to thoroughly understand the answers and apply them to my exact situation as seems to be the problem of the dozens (hundreds/thousands?) of people asking these questions and the hundreds of thousands (millions?) of people that have been searching for solutions to asynchronous problems.
You could just call .html() inside the returnLocations() function if that's viable.
the function
function returnLocations() {
locationsFull = locationsOpener + locationsBody + locationsCloser;
$('.locations-body').html(locationsFull);
}
the call
$(function() {
locationsFunction();
}
Otherwise you'll need to look into callbacks, read this, if you need to do it this way I can update my answer with an example later on.
Have you tried
return wait.promise();
instead of returning the Deferred?
Then calling like this:
var deferredChain = $.Deferred();
deferredChain.then(getLocations).then(returnLocations);
deferredChain.resolve();
I discovered today that simply putting a .done at the end of $.getJSON seems to work just the same and is much easier than using $.Deferred and the associated lines of code to make it work.
function locationsFunction() {
var area = 'Area1';
var counter = 1;
$.getJSON("locations.json", function(data) {
$(data.places).each(function() {
var location = this.location;
var image = this.image;
if (this.area === 'Area1') {
if (counter == 2) {
locationsBody = locationsBody +
'<div class="locations-places">' +
'<img src="images/places/' + image + '">' +
'<div class="locations-places-image">' + location + '</div>' +
'</div></div>'
;
counter = 0; // added closing of container, reset to 0
} else {
locationsBody = locationsBody +
'<div class="locations-places">' +
'<img src="images/places/' + image + '">' +
'<div class="locations-places-image">' + location + '</div>' +
'</div>'
;
counter = counter + 1;
}
}
})
}).done(function() {
locationsFull = locationsOpener + locationsBody + locationsCloser;
$('.locations-body').html(locationsFull);
});
}

Having some code inside setInterval execute only once

I have a setInterval call inside my Javascript which checks if there are new notifications for the user. This interval makes an AJAX call and updates the DOM based on the response. This interval is set to repeat every 10 seconds.
There is a little box that needs to popup if there are new notifications and it is inside this interval. In the current code, this box shows up every 10 seconds if there are new notifications that are not marked as seen and that's pretty annoying.
Is there a way to make this little box appear only once per notification set? So for example there are X new notification and after 10 seconds this number didn't change, don't show this box. How do I achieve this? I'm stuck here.
This is how my interval code looks like:
setInterval(function(){
$.get(generate_site_url() + 'user.php?action=get_notifications', function(data) {
response = $.parseJSON(data);
if ('error' in response)
{
return;
}
if (response.notification_array.length == 0)
{
return;
}
$('.user-notification').text(response.notification_count);
$('.no-notes').hide();
var notificationStr = '';
for (var key in response.notification_array)
{
var notification = response.notification_array[key];
var notificationHTML = '<li' + ((notification.notification_seen == false) ? ' style="background: #fffaf1;"' : '') + '>';
notificationHTML += '<a href="' + notification.notification_target + '" id="nid-' + notification.notification_id + '">';
notificationHTML += '<span class="glyphicon glyphicon-' + ((notification.notification_type == 'like') ? 'thumbs-up' : (notification.notification_type == 'dislike') ? 'thumbs-down' : (notification.notification_type == 'favorite') ? 'heart' : 'bell') + '"></span> ';
notificationHTML += notification.notification_message;
notificationHTML += '</a></li>';
notificationStr += notification.notification_message + '<br />';
$('.notifications-dropdown').prepend($(notificationHTML));
}
display_alert(notificationStr, 'danger', 5000, 'bottom'); // This shows the box
});
}, 10000);
I'll expand my original comment answer here.
Set a variable accessible outside the interval function, in which you track the last count of new notifications. Next time the interval runs, compare the counts and check if there are any new ones.
var lastNewMessageCount = 0;
setInterval(function(){
// ajax stuff
if( response.notification_array.length > lastNewMessageCount ){
// show notices
}
lastNewMessageCount = response.notification_array.length;
});
Try making a global Array, then adding a conditional if(response.notification_array.length > nameOfGlobalArray.length) before the execution of display_alert() and update nameOfGlobalArray to match response.notification_array if the conditional returns true, like:
var notificationsArray = [];
setInterval(function(){
$.get(generate_site_url() + 'user.php?action=get_notifications', function(data) {
response = $.parseJSON(data);
if ('error' in response)
{
return;
}
if (response.notification_array.length == 0)
{
return;
}
$('.user-notification').text(response.notification_count);
$('.no-notes').hide();
var notificationStr = '';
for (var key in response.notification_array)
{
var notification = response.notification_array[key];
var notificationHTML = '<li' + ((notification.notification_seen == false) ? ' style="background: #fffaf1;"' : '') + '>';
notificationHTML += '<a href="' + notification.notification_target + '" id="nid-' + notification.notification_id + '">';
notificationHTML += '<span class="glyphicon glyphicon-' + ((notification.notification_type == 'like') ? 'thumbs-up' : (notification.notification_type == 'dislike') ? 'thumbs-down' : (notification.notification_type == 'favorite') ? 'heart' : 'bell') + '"></span> ';
notificationHTML += notification.notification_message;
notificationHTML += '</a></li>';
notificationStr += notification.notification_message + '<br />';
$('.notifications-dropdown').prepend($(notificationHTML));
}
if(response.notification_array.length > notificationsArray.length)
{
display_alert(notificationStr, 'danger', 5000, 'bottom');
notificationsArray = response.notification_array;
}
});
}, 10000);
[EDIT] BotskoNet's method uses less data, and apparently my brain wasn't turned on :P Both will work, though.
Does user.php mark a notification as seen once it has been delivered? I will assume not, but if so you just need to check if new notifications came in and only call the display_alert() if so.
Keeping track of notification count or comparing string is not enough. There are plenty of use cases where this will result in false positives. But I see there is a notification_id field:
var delivered= [];
setInterval(function(){
// ajax stuff
for (var key in response.notification_array){
var notification = response.notification_array[key];
// check if the notification has been delivered
if ($.inArray(notification.notification_id, delivered) === -1){
// notification has not been delivered
delivered.push(notification.notification_id);
// process notification as normal
}
}
// only display the alert if there is something to display...
if (notificationStr.length > 0)
display_alert(...);
}, 10000);

pagination with AJAX url

Im beginner in AJAX & JS so please bear with me.
I use this AJAX for the pagination :
$(function () {
var keyword = window.localStorage.getItem("keyword");
//pagination
var limit = 3;
var page = 0;
var offset = 0;
$("#btnLoad").on('click', function () {
page++;
if (page != 0)
offset = (page - 1) * limit;
$.ajax({
url: "http://localhost/jwmws/index.php/jwm/search/msmall/" + keyword + "/" + limit + "/" + offset, //This is the current doc
type: "GET",
error: function (jq, st, err) {
alert(st + " : " + err);
},
success: function (result) {
alert("offset=" + offset + " page =" + page);
//generate search result
$('#search').append('<p style="float:left;">Search for : ' + keyword + '</p>' + '<br/>' + '<p>Found ' + result.length + ' results</p>');
if (result.length == 0) {
//temp
alert("not found");
} else {
for (var i = 0; i < result.length; i++) {
//generate <li>
$('#list').append('<li class="box"><img class="picture" src="images/HotPromo/tagPhoto1.png"/><p class="name"><b>Name</b></p><p class="address">Address</p><p class="hidden"></p></li>');
}
var i = 0;
$(".box").each(function () {
var name, address, picture, id = "";
if (i < result.length) {
name = result[i].name;
address = result[i].address;
picture = result[i].boxpicture;
id = result[i].mallid;
}
$(this).find(".name").html(name);
$(this).find(".address").html(address);
$(this).find(".picture").attr("src", picture);
$(this).find(".hidden").html(id);
i++;
});
$(".box").click(function () {
//alert($('.hidden', this).html());
window.localStorage.setItem("id", $('.hidden', this).html());
$("#pagePort").load("pages/MallDetail.html", function () {});
});
}
}
});
}).trigger('click');
});
Please notice that i use the variables for pagination in the url:. I tried to alert the page and offset variable, and its working fine.
However, the AJAX only working for the first page (when page load). The rest is not working even though the page and offset variable's value is true.
Theres no warning/error in console. The data just not shown.
Any help is appreciated, Thanks :D
It is a bit hard to debug your code when the whole HTML is missing.
Could you put your code into JSFiddle, both HTML and JS.

IE not loading XML content until I open Developer tools?

I have a page that loads product information from an XML file using a jQuery AJAX get request. This works well in FF and Chrome however the content doesn't load in IE. It will however load the data after opening the developer window and refreshing the page! Does anyone know why?
Here is my jQuery AJAX request:
//Load the xml file
$.ajax({
type: "GET",
url: "xml/" + cat + ".xml",
dataType: ($.browser.msie) ? "text" : "xml",
success: function(data) {
alert('xml successfully loaded');
var xml;
if (typeof data == "string") {
xml = new ActiveXObject("Microsoft.XMLDOM");
xml.async = false;
xml.loadXML(data);
} else {
xml = data;
}
//Get total number of products in the category
$(xml).find('dataroot').each(function() {
var pTemp = $(this).attr('count');
catName = $(this).attr('catTitle');
console.log(catName);
pTotal = Number(pTemp);
});
//Fill the correct entries onto the page
while (count<=pTotal) {
$(xml).find('product').each(function() {
if (count>lCounter && count<hCounter) {
var pName = $(this).find('ProductName').text();
var pImage = $(this).find('Photo').text();
var pCode = $(this).find('ProductCode').text();
var pDesc = $(this).find('WebDescription').text();
if (cat.substring(0,2)=='cs') {
var pPrice = $(this).find('PartyShackPrice').text();
} else { var pPrice = $(this).find('RRP').text(); }
var pSize = $(this).find('size').text();
var pLink = '<a href="item.html?'+cat+'-'+pCode+'">';
var pHTML = '<div id="'+pCode+'" class="box">';
pHTML += pLink + '<img src="images/SMALL_IMAGE/' + pImage + '" width="70" height"100" /></a>';
pHTML += '<div class="boxText">';
pHTML += pLink + '<div class="boxTitle">'+pName+'</div></a>';
pHTML += '<div class="boxDesc">'+pDesc+'</div>';
if (pSize !== 'Not Applicable') { pHTML += '<div class="boxSize">'+pSize+'</div>'; }
pHTML += '<div class="boxPrice">£'+pPrice+'</div>';
pHTML += pLink + '<div class="boxBuy"></div></a>';
pHTML += '</div></div>';
$("#products").append(pHTML);
}
count +=1;
});
}
//Work out the total number of pages the product list is split up into
if (pTotal%50==0) { pageTotal = pTotal/50; }
else { pageTotal = Math.floor(pTotal/50) + 1; }
console.log('pageTotal - ' + pageTotal);
//Show path of the current page
getPath(cat, catName, 0);
//Depending on page number show previous and next buttons and display product counter
if (pageTotal==1) { //page 1 and only one page
$("#prev").css("visibility", "hidden");
$("#next").css("visibility", "hidden");
$("#counter").append('1 - ' + pTotal + ' of ' + pTotal);
} else if ((pageNum==1) && (pageTotal!=1)) { //page 1 and multiple pages
$("#prev").css("visibility", "hidden");
$("#next").append('Next >>');
$("#counter").append('1 - 50 of ' + pTotal);
} else if ((pageNum==pageTotal) && (pageTotal!=1)) { //last page when theres more than 1 page
$("#next").css("visibility", "hidden");
$("#prev").append('<< Previous');
$("#counter").append((((pageNum-1)*50)+1) + ' - ' + pTotal + ' of ' + pTotal);
} else { // a middle page
$("#next").append('Next >>');
$("#prev").append('<< Previous');
$("#counter").append((((pageNum-1)*50)+1) + ' - ' + (pageNum * 50) + ' of ' + pTotal);
}
//Display page number
$("#currentPage").append(' ' + pageNum + ' of ' + pageTotal);
},
error: function() { alert('failure'); }
});
});
Also IE should call either the success alert or the error alert however it does neither until opening the developer window and refreshing the page.
Thanks
I knew what the problem was just by reading the title of your question on the SO main page. And reading the code in the question confirms it. The problem you have is the line console.log(catName);
IE (and some other browsers) don't initialise the console object until the developer window is opened.
Prior to this, trying to use console will return undefined, and will cause your script to stop running.
The first lesson here is not to leave debugging code in your program after you're done with it. Calls to the console should only be there while you're testing the program; when you've finished with them, take them out.
The second lesson is that if you do need to have console calls in your code, you should wrap them in code that checks if console exists before it tries to use it. There are a number of ways to do this, from a simple if(console) {console.log(...);} all the way through to writing your own debugging class. How you do it is up to you, but it is generally a good idea to write all console code this way, even when you're just doing a bit of debugging, to avoid the kind of issue you're having here.
Hope that helps.
Let jQuery do what it does best. Replace all of this:
dataType: ($.browser.msie) ? "text" : "xml",
success: function(data) {
alert('xml successfully loaded');
var xml;
if (typeof data == "string") {
xml = new ActiveXObject("Microsoft.XMLDOM");
xml.async = false;
xml.loadXML(data);
} else {
xml = data;
}
...
With this:
dataType: "xml",
success: function(xml) {
alert('xml successfully loaded');
...

Categories