Identify the first and last two posts - javascript

I am using the script below to show the latest 5 posts on my Blogger blog. How can I wrap the first and last 2 posts in different div containers? Currently all the 5 posts are inside a wrapper container stored in the item variable:
<script type='text/javascript'>
function mycallback(json) {
for (var i = 0; i < json.feed.entry.length; i++) {
for (var j = 0; j < json.feed.entry[i].link.length; j++) {
if (json.feed.entry[i].link[j].rel == 'alternate') {
var postUrl = json.feed.entry[i].link[j].href;
break;
}
}
var postTitle = json.feed.entry[i].title.$t;
var postAuthor = json.feed.entry[i].author[0].name.$t;
var postSummary = json.feed.entry[i].summary.$t;
var entryShort = postSummary.substring(0,400);
var entryEnd = entryShort.lastIndexOf(" ");
var postContent = entryShort.substring(0, entryEnd) + '...';
var postImage = json.feed.entry[i].media$thumbnail.url.replace('s72-c/','s1600/');
var item = '<div class="wrapper"><img src="' + postImage + '"/><h3><a href=' + postUrl + '>' + postTitle + '</h3></a><span>'+ postAuthor + '</span><p>' + postContent + '</p></div>';
document.write(item);
}
}
</script>
<script src="/feeds/posts/summary?orderby=published&max-results=5&alt=json-in-script&callback=mycallback"></script>

More generic solution would not check for last and previous to last elements checking for 3 or 4 but should be based on total length of your posts (it can be 3 it can be 10000).
Checks below should be place in your loop.
if(i === 0 || i === 1)
Always use === operator as it is typesafe.
Also group your checks in a way that is easy to understand (check for first and second in one if and for last and previous to last in another if:
if(i === json.feed.entry.length || i === json.feed.entry.length - 1) - this check is based on length of your entries, not some fixed value like 3 or 4.
This way if your displayed entries value will change in future (to ex. 10), you don't need to adjust your code here. All code you write should strive to work without such adjustments when code it uses changes.

Check desired elements through loop
// to check first or fourth element
if (i == 0 || i == 3)
// to check second or fifth element
if (i == 1 || i == 4)
Wrap them by adding HTML tages
<script type='text/javascript'>
function mycallback(json) {
for (var i = 0; i < json.feed.entry.length; i++) {
for (var j = 0; j < json.feed.entry[i].link.length; j++) {
if (json.feed.entry[i].link[j].rel == 'alternate') {
var postUrl = json.feed.entry[i].link[j].href;
break;
}
}
var postTitle = json.feed.entry[i].title.$t;
var postAuthor = json.feed.entry[i].author[0].name.$t;
var postSummary = json.feed.entry[i].summary.$t;
var entryShort = postSummary.substring(0,400);
var entryEnd = entryShort.lastIndexOf(" ");
var postContent = entryShort.substring(0, entryEnd) + '...';
var postImage = json.feed.entry[i].media$thumbnail.url.replace('s72-c/','s1600/');
var item = '<div class="wrapper"><img src="' + postImage + '"/><h3><a href=' + postUrl + '>' + postTitle + '</h3></a><span>'+ postAuthor + '</span><p>' + postContent + '</p></div>';
if (i == 0 || i == 3) document.write('<div>');
document.write(item);
if (i == 1 || i == 4) document.write('</div>');
}
}
</script>
<script src="/feeds/posts/summary?orderby=published&max-results=5&alt=json-in-script&callback=mycallback"></script>

Related

how to fix if .media$thumbnail.url not found?

I'm Building a widget for blogger
<script type="text/javascript">
function mycallback(json) {
for (var i = 0; i < json.feed.entry.length; i++) {
for (var j = 0; j < json.feed.entry[i].link.length; j++) {
if (json.feed.entry[i].link[j].rel == 'alternate') {
var postUrl = json.feed.entry[i].link[j].href;
break;
}
}
var postTitle = json.feed.entry[i].title.$t;
var postSummary = json.feed.entry[i].summary.$t;
var Thumb = json.feed.entry[i].media$thumbnail.url;
var item = '<div class="wrapper"><img src='+ Thumb +' /><h3><a href=' + postUrl + '>' + postTitle + '</h3></a><p>' + postSummary + '</p></div>';
document.write(item);
}
}
</script>
<script src="https://smag-soratemplates.blogspot.com/feeds/posts/summary?max-results=5&alt=json-in-script&callback=mycallback"></script>
but if there is no image in the post or cant find .media$thumbnail.url
the widget stops working , anyone know how to fix that ? or to show an alternative image?
sorry i'm a beginner
If it's failing when the thumbnail does not exist, then you can put a check for the thumbnail
<script type="text/javascript">
function mycallback(json) {
for (var i = 0; i < json.feed.entry.length; i++) {
for (var j = 0; j < json.feed.entry[i].link.length; j++) {
if (json.feed.entry[i].link[j].rel == 'alternate') {
var postUrl = json.feed.entry[i].link[j].href;
break;
}
}
var postTitle = json.feed.entry[i].title.$t;
var postSummary = json.feed.entry[i].summary.$t;
var Thumb = json.feed.entry[i].media$thumbnail.url;
if( typeof Thumb == "undefined" ) {
Thumb = '/Your custom image url';
}
var item = '<div class="wrapper"><img src='+ Thumb +' /><h3><a href=' + postUrl + '>' + postTitle + '</h3></a><p>' + postSummary + '</p></div>';
document.write(item);
}
}
</script>
<script src="https://smag-soratemplates.blogspot.com/feeds/posts/summary?max-results=5&alt=json-in-script&callback=mycallback"></script>
You need to use or(||) in the Thumb definition like that
var Thumb = json.feed.entry[i].media$thumbnail.url || 'https://i.imgur.com/5WMAvAu.gif';
Here, if json.feed.entry[i].media$thumbnail.url is undefine/false/null, Thumb is set to 'https://i.imgur.com/5WMAvAu.gif' as your default image.
You need to check that all of the values are present:
json.feed.entry[i].media$thumbnail.url
as any of these items could be null / undefined:
json
json.feed
json.feed.entry[i]
json.feed.entry[i].media$thumbnail
json.feed.entry[i].media$thumbnail.url
At the least, you should check:
if(json.feed.entry[i].media$thumbnail && json.feed.entry[i].media$thumbnail.url)
Also, it's probably worth rewriting this code as follows:
let entry = json.feed.entry[i];
to save yourself some typing (and to stop all the object look ups each time when using dots to reference nested objects).
The code then becomes:
let url = '';
if (entry.media$thumbnail && media$thumbnail.url) {
url = entry.media$thumbnail.url;
}
else {
url = 'the default image URL';
}
Thank you all i found the solution
by replacing this code
var Thumb = json.feed.entry[i].media$thumbnail.url;
with this code
if (json.feed.entry[i].media$thumbnail)
{
Thumb = json.feed.entry[i].media$thumbnail.url;
}
else
{
Thumb= "'Image url'";
}

js/json: why can't I add json.feed.entry[i].Content.$t to this variable definition?

Moving on from my previous question. Same little project. Different inquiry altogether.
Here's the updated code:
<script type="text/javascript">
function recentpostslist(json) {
document.write('<ul>');
var i;
var j;
for (i = 0; i < json.feed.entry.length; i++)
{
for (j = 0; j < json.feed.entry[i].link.length; j++) {
if (json.feed.entry[i].link[j].rel == 'alternate') {
break;
}
}
var postUrl = "'" + json.feed.entry[i].link[j].href + "'";//bs
var postTitle = json.feed.entry[i].title.$t;
var item = "<h2>" + '' + postTitle + " </h2>";
document.write(item);
}
document.write('</ul>');
}
</script>
<script src="https://xxxxxxxxxx.blogspot.com/feeds/posts/summary/-/recommended?max-results=3&alt=json-in-script&callback=recentpostslist"></script>
What it does is list the titles of a blog's 3 latest posts that have been labeled "recommended".
I figured I might declare another variable, just above the var item definition, as in...
var postContent = json.feed.entry[i].content.$t;
...and add that to the 'var item' value, as in...
var item = "<h2>" + '' + postTitle + " </h2> <p>" + postContent + "</p>";
...or something like that; my intention being to include posts' content (not just title) to what's being displayed.
But that doesn't seem to work. Am I missing something?
The URL you're using contains the word summary; if you use default instead, the json data will also contain the content, apparently.

Wrapping every three elements while iterating through an array

I have a two-dimensional array (affiliates) where each array item consists of an image URL and a link URL. randArray is simply a generated list of random numbers (non-repeating) that matches the length of affiliates.
I've gotten to the point where I can successfully generate an HTML string for randomized image/url combinations.
(The above might be more information than needed but I wanted to provide a little background.)
What I'm trying to do is group every three iterations together and wrap in <p> tags. I've tried doing a nested loop inside the current one but could only get to where it was wrapping three of the same line in a <p> tag, whereas I need them to be three successive lines. I feel like this should be pretty easy, but I'm stumped. Any help would be much appreciated.
for(var y=0; y < randArray.length; y++) {
var image = affiliates[randArray[y]][0];
var url = affiliates[randArray[y]][1];
var fullString = '<img src="' + image + '">';
console.log(fullString);
}
WIthin your loop, y % 3 == 0 will be true on the first iteration and every third after it, so output your <p> when y % 3 == 0 and your </p> when y % 3 == 2 and after your loop if length % 3 != 0.
But a nested loop is probably easier to do and maintain:
var x, image, url;
var fullString = "";
var y = 0;
while (y < randArray.length) {
fullString += '<p>';
for (x = 0; x < 3 && y < randArray.length; ++x, ++y) {
image = affiliates[randArray[y]][0];
url = affiliates[randArray[y]][1];
fullString += '<img src="' + image + '">';
}
fullString += '</p>';
}
for(var y=0; y < randArray.length; y++) {
var image = affiliates[randArray[y]][0];
var url = affiliates[randArray[y]][1];
var fullString = '';
if(y%3 == 2){
fullString += '<p>';
}
fullString = '<img src="' + image + '">';
if(y%3 == 2){
fullString += '</p>';
}
console.log(fullString);
}
I am not sure if I understand, but...
var t = [];
for(var i=0;i<affiliates.length;i++) t.push(i);
while(t.length>2){
var str = '';
for(var i=0;i<3;i++){
str += '<a href="';
var r = Math.floor(Math.random()*t.length);
str += affiliates[t[r]][1] + '"><img src="';
str += affiliates[t[r]][0] + '"></a>';
t.splice(r,1);
}
str = '<p>'+str+'</p>';
console.log(str);
}
I would do something like this, but it's not optimized code, sorry :/
var counter = 1; //external counter for module (%3)
var open = false;
var tagOpen = '<p>';
var tagClose = '</p>';
var fullstring = '';
var buffer = ''
for(var y=0; y < randArray.length; y++) {
var image = affiliates[randArray[y]][0];
var url = affiliates[randArray[y]][1];
//groups entries
buffer += '<img src="' + image + '">';
if(counter % 3 == 0){
fullstring = tagOpen + buffer + tagClose; //concat strings
console.log(fullString);
open = false; //set open to false
} else {
open = true;
}
counter++;
}
//if at the end of the loop there's still an open tag, close it
if(open){
fullstring += tagClose;
}

Jquery -Combining string & Variable

I am new to jQuery and I cant seem to get the following code working..
for ( var i = 0; i < 2; i++ ) {
$status[i] = $('select[name="status'+ i +'"] option:selected').val();
$odd_a[i] = $("input:text[name='odd_a"+ 1 +"']").val();
$odd_b[i] = $("input:text[name='odd_b"+ 1 +"']").val();
$term[i] = $("select[name='term"+ 1 +"'] option:selected").val();
$dh_place[i] = $("input:text[name='dh_place"+ 1 +"']").val();
$dh_total[i] = $("input:text[name='dh_total"+ 1 +"']").val();
}
I have several text boxes "status1, status2, status3 etc. I need to call their name by the for loop. If I replace the "i" with the "1" it works. I cant seem to call the variable "i" at that position.
Try with
$status[i] = $('select[name="status'+ i +'"]').val();
and You need to start i value from 1 like
for ( var i = 1; i < 2; i++ ) {
One problem I can see is the i starts with 0 where as your input starts with 1, so the first loop will not return any elements.
for (var i = 0; i < 2; i++) {
$status[i] = $('select[name="status' + (i + 1) + '"]').val();
$odd_a[i] = $("input:text[name='odd_a" + (i + 1) + "']").val();
$odd_b[i] = $("input:text[name='odd_b" + (i + 1) + "']").val();
$term[i] = $("select[name='term" + (i + 1) + "']").val();
$dh_place[i] = $("input:text[name='dh_place" + (i + 1) + "']").val();
$dh_total[i] = $("input:text[name='dh_total" + (i + 1) + "']").val();
}

Javascript Hanging UI on IE6/7

Could anyone suggest performance improvements for the function I've written (below, javascript with bits of jquery)? Or point out any glaring, basic flaws? Essentially I have a javascript Google map and a set of list based results too, and the function is fired by a checkbox click, which looks at the selection of checkboxes (each identifying a 'filter') and whittles the array data down accordingly, altering the DOM and updating the Google map markers according to that. There's a 'fake' loader image in there too at the mo that's just on a delay so that it animates before the UI hangs!
function updateFilters(currentCheck) {
if (currentCheck == undefined || (currentCheck != undefined && currentCheck.disabled == false)) {
var delay = 0;
if(document.getElementById('loader').style.display == 'none') {
$('#loader').css('display', 'block');
delay = 750;
}
$('#loader').delay(delay).hide(0, function(){
if (markers.length > 0) {
clearMarkers();
}
var filters = document.aspnetForm.filters;
var markerDataArray = [];
var filterCount = 0;
var currentfilters = '';
var infoWindow = new google.maps.InfoWindow({});
for (i = 0; i < filters.length; i++) {
var currentFilter = filters[i];
if (currentFilter.checked == true) {
var filtername;
if (currentFilter.parentNode.getElementsByTagName('a')[0].textContent != undefined) {
filtername = currentFilter.parentNode.getElementsByTagName('a')[0].textContent;
} else {
filtername = currentFilter.parentNode.getElementsByTagName('a')[0].innerText;
}
currentfilters += '<li>' + $.trim(filtername) +
$.trim(document.getElementById('remhide').innerHTML).replace('#"','#" onclick="toggleCheck(\'' + currentFilter.id + '\');return false;"');
var nextFilterArray = [];
filterCount++;
for (k = 0; k < filterinfo.length; k++) {
var filtertype = filterinfo[k][0];
if (filterinfo[k][0] == currentFilter.id) {
var sitearray = filterinfo[k][1];
for (m = 0; m < sitearray.length; m++) {
var thissite = sitearray[m].split(',');
if (filterCount > 1) {
nextFilterArray.push(thissite[2] + '|' + thissite[1]
+ '|' + thissite[0]);
} else {
markerDataArray.push(thissite[2] + '|' + thissite[1]
+ '|' + thissite[0]);
}
}
}
}
if (filterCount > 1) {
var itemsToRemove = [];
for (j = 0; j < markerDataArray.length; j++) {
var exists = false;
for (k = 0; k < nextFilterArray.length; k++) {
if (markerDataArray[j] == nextFilterArray[k]) {
exists = true;
}
}
if (exists == false) {
itemsToRemove.push(j);
}
}
var itemsRemoved = 0;
for (j = 0; j < itemsToRemove.length; j++) {
markerDataArray.splice(itemsToRemove[j]-itemsRemoved,1);
itemsRemoved++;
}
}
}
}
if (currentfilters != '') {
document.getElementById('appliedfilters').innerHTML = currentfilters;
document.getElementById('currentfilters').style.display = 'block';
} else {
document.getElementById('currentfilters').style.display = 'none';
}
if (filterCount < 1) {
for (j = 0; j < filterinfo.length; j++) {
var filtertype = filterinfo[j][0];
if (filterinfo[j][0] == 'allvalidsites') {
var sitearray = filterinfo[j][1];
for (m = 0; m < sitearray.length; m++) {
var thissite = sitearray[m].split(',');
markerDataArray.push(thissite[2] + '|' + thissite[1]
+ '|' + thissite[0]);
}
}
}
}
var infoWindow = new google.maps.InfoWindow({});
var resultHTML = '<div id="page1" class="page"><ul>';
var count = 0;
var page = 1;
var paging = '<li class="selected">1</li>';
for (i = 0; i < markerDataArray.length; i++) {
var markerInfArray = markerDataArray[i].split('|');
var url = '';
var name = '';
var placename = '';
var region = '';
var summaryimage = 'images/controls/placeholder.gif';
var summary = '';
var flag = 'images/controls/placeholderf.gif';
for (j = 0; j < tsiteinfo.length; j++) {
var thissite = tsiteinfo[j].split('|');
if (thissite[0] == markerInfArray[2]) {
name = thissite[1];
placename = thissite[2];
region = thissite[3];
if (thissite[4] != '') {
summaryimage = thissite[4];
}
summary = thissite[5];
if (thissite[6] != '') {
flag = thissite[6];
}
}
}
for (k = 0; k < sitemapperinfo.length; k++) {
var thissite = sitemapperinfo[k].split('|');
if (thissite[0] == markerInfArray[2]) {
url = thissite[1];
}
}
var markerLatLng = new google.maps.LatLng(markerInfArray[1].toString(), markerInfArray[0].toString());
var infoWindowContent = '<div class="infowindow">' + markerInfArray[2] + ': ';
var siteurl = approot + '/sites/' + url;
infoWindowContent += '<strong>' + name + '</strong>';
infoWindowContent += '<br /><br/><em>' + placename + ', ' + region + '</em></div>';
marker = new google.maps.Marker({
position: markerLatLng,
title: $("<div/>").html(name).text(),
shadow: shadow,
icon: image
});
addInfo(infoWindow, marker, infoWindowContent);
markers.push(marker);
count++;
if ((count > 20) && ((count % 20) == 1)) { // 20 per page
page++;
resultHTML += '</ul></div><div id="page' + page + '" class="page"><ul>';
paging += '<li>' + page + '</li>';
}
resultHTML += '<li><div class="namehead"><h2>' + name + ' <span>' + placename + ', ' + region + '</span></h2></div>' +
'<div class="codehead"><h2><img alt="' + region + '" src="' + approot +
'/' + flag + '" /> ' + markerInfArray[2] + '</h2></div>' +
'<div class="resultcontent"><img alt="' + name + '" src="' + approot +
'/' + summaryimage +'" />' + '<p>' + summary + '</p>' + document.getElementById('buttonhide').innerHTML.replace('#',siteurl) + '</div></li>';
}
$('#filteredmap .paging').each(function(){
$(this).html(paging);
});
document.getElementById('resultslist').innerHTML = resultHTML + '</ul></div>';
document.getElementById('count').innerHTML = count + ' ';
document.getElementById('page1').style.display = 'block';
for (t = 0; t < markers.length; t++) {
markers[t].setMap(filteredMap);
}
});
}
}
function clearMarkers() {
for (i = 0; i < markers.length; i++) {
markers[i].setMap(null);
markers[i] = null;
}
markers.length = 0;
}
However, I'm suffering from performance issues (UI hanging) specifically in IE6 and 7 when the number of results is high, but not in any other modern browsers, i.e. FF, Chrome, Safari etc. It is much worse when the Google map markers are being created and added (if I remove this portion it is still slugglish, but not to the same degree). Can you suggest where I'm going wrong with this?
Thanks in advance :) Please be gentle if you can, I don't do much javascript work and I'm pretty new to it and jquery!
This looks like a lot of work to do at the client no matter what.
Why don't you do this at the server instead, constructing all the HTML there, and just refresh the relevant sections with the results of an ajax query?

Categories

Resources