jquery/javascript error - too much recursion - with self-calling function - javascript

I have a small problem with a function that calls itself from within itself.
The following function pretty much works, as can be seen here ...
http://jsfiddle.net/justinayles/frPZ8/2/
but if you click a square and after that click the back link and go back and forth a few times, eventually it will slow down and ultimately crash with a 'too much recursion error'. I cant really see any other way to achieve what I am trying to do here ? I kind of understand what the problem is, but was wondering if there was another way to do this, maybe rename the function? im trying to avoid duplication too much code. any help appreciated, thanks.
var questionArray = [];
var cardArray = [];
// extend array for IE !!
if (!Array.prototype.filter) {
Array.prototype.filter = function(fun /*, thisp*/) {
var len = this.length >>> 0;
if (typeof fun != "function")
throw new TypeError();
var res = [];
var thisp = arguments[1];
for (var i = 0; i < len; i++) {
if (i in this) {
var val = this[i]; // in case fun mutates this
if (fun.call(thisp, val, i, this))
res.push(val);
}
}
return res;
};
}
function setupPage(whichpage, questionArray) {
var html = "",
backlink = "",
activestep = "",
undertext = "",
qArray = questionArray;
switch(whichpage) {
case '1':
var pg1 = questionArray.filter(function (el) {
return el.page == "step1";
});
$.each(pg1, function(key,val) {
html += '<a class="quest ' + val.star + '" href="' + val.path + '" target="' + val.target + '">' + val.title + '</a>';
});
backlink = "0";
activestep = "1";
undertext = "";
break;
case '2a':
var pg2a = questionArray.filter(function (el) {
return el.page == "step2a";
});
$.each(pg2a, function(key,val) {
html += '<a class="quest ' + val.star + '" href="' + val.path + '" target="' + val.target + '">' + val.title + '</a>';
});
backlink = "1";
activestep = "2";
undertext = "";
break;
case '2b':
var pg2b = questionArray.filter(function (el) {
return el.page == "step2b";
});
$.each(pg2b, function(key,val) {
html += '<a class="quest ' + val.star + '" href="' + val.path + '" target="' + val.target + '">' + val.title + '</a>';
});
backlink = "1";
activestep = "2";
undertext = "";
break;
case '3a':
var pg3a = cardArray.filter(function (el) {
return el.page == "3a";
});
$.each(pg3a, function(key,val) {
html += '<div class="cardblock"><a class="wrapcard" href="' + val.path + '" target="' + val.target + '"><img border="0" alt="' + val.title + '" src="http://dummyimage.com/178x112/000/00ffd5.png" alt="placeholder image" /></a>';
html += '<a class="cardtitle" href="' + val.path + '" target="' + val.target + '">' + val.title + '</a></div>';
});
backlink = "2a";
activestep = "3";
undertext = "Choose a programme";
break;
case '3b':
var pg3b = cardArray.filter(function (el) {
return el.page == "3b";
});
$.each(pg3b, function(key,val) {
html += '<div class="cardblock"><a class="wrapcard" href="' + val.path + '" target="' + val.target + '"><img border="0" alt="' + val.title + '" src="http://dummyimage.com/178x112/000/00ffd5.png" /></a>';
html += '<a class="cardtitle" href="' + val.path + '" target="' + val.target + '">' + val.title + '</a></div>';
});
backlink = "2b";
activestep = "3";
undertext = "Choose a programme";
break;
}
// make the dom changes..
if ( backlink !== "0" ) {
html += '<a id="backlink" href="' + backlink + '"><< back a step</a>';
}
$('.wrapdots span').removeClass('active');
$('.wrapdots span.step'+activestep).addClass('active');
$('p.underdots').html(undertext);
$('#wrapper').fadeOut('fast', function() {
$(this).html(html).fadeIn('fast');
});
$('#wrapper').on('click', '#backlink', function(e) {
e = e || window.event;
e.target = e.target || e.srcElement;
var goto = e.target.href;
goto = goto.split('/');
goto = goto.pop();
switch(goto) {
case '1':
e.preventDefault();
setupPage('1', qArray);
break;
case '2a':
e.preventDefault();
setupPage('2a', qArray);
break;
case '2b':
e.preventDefault();
setupPage('2b', qArray);
break;
case '3a':
e.preventDefault();
setupPage('3a', qArray);
break;
case '3b':
e.preventDefault();
setupPage('3b', qArray);
break;
}
});
$('#wrapper').on('click', '.quest', function(e) {
e = e || window.event;
e.target = e.target || e.srcElement;
var goto = e.target.href;
goto = goto.split('/');
goto = goto.pop();
switch(goto) {
case '1':
e.preventDefault();
setupPage('1', qArray);
break;
case '2a':
e.preventDefault();
setupPage('2a', qArray);
break;
case '2b':
e.preventDefault();
setupPage('2b', qArray);
break;
case '3a':
e.preventDefault();
setupPage('3a', qArray);
break;
case '3b':
e.preventDefault();
setupPage('3b', qArray);
break;
default:
e.preventDefault();
break;
}
});
}
// doc ready...
$(function() {
// do questions
$('question').each(function() {
var qobj = {
title : $(this).attr('qTitle'),
star : $(this).attr('class'),
path : $(this).attr('path'),
page : $(this).attr('page'),
target : $(this).attr('target')
}
questionArray.push(qobj);
});
// got the questions, lets now setup page 1 !!
setupPage('1', questionArray);
// do cards
$('card').each(function() {
var cobj = {
title : $(this).attr('cTitle'),
path : $(this).attr('path'),
img : $(this).attr('img'),
page : $(this).attr('page'),
target : $(this).attr('target')
}
cardArray.push(cobj);
});
});

This isn't a case you'd want to use recursion. Every click binds more events to the DOM but never releases them. I'd recommend pulling your $('#wrapper').on('click'... code out of your setupPage function that way your click events are only bound once.
Recursive functions are best used for situations like scanning list trees where you don't know how deep they go. FYI, Code Academy has section on recursion that I found helpful.

Related

Sorting results from SharePoint RestAPI

I'm trying to build some semi-dynamic staff directory pages from a Sharepoint List, using their REST API.
I know enough Javascript to get me in trouble, so I have a feeling my solution is not as elegant as it could be and probably not ideal.
The goal is to allow our web editors to create unique pages for various departments by simply adding a short script and the employee's email address. Another option I've thought about is simply adding a field in the list for each program but it's not consistent enough across the board, so being able to set the list and sort on each page is probably the best option.
The solution works just fine but occasionally the sort order gets out of wack, I'm guessing because of the order the script reads the list.
Here's the front end code:
<script type="text/javascript"
src="getstaffdirectory2.js"></script>
<script>
$(document).ready(function() {
GetStaffDirectory('email1#dcccd.edu');
GetStaffDirectory('email2#dcccd.edu');
GetStaffDirectory('email3#dcccd.edu');
GetStaffDirectory('email4#dcccd.edu');
GetStaffDirectory('email5#dcccd.edu');
});
</script>
<div class="white-space-2"></div>
<div class="row">
<div id="GetStaffDirectory"></div>
</div>
Rather un-elegant? :-)
Here's the script:
function GetStaffDirectory(UserEmail) {
var res;
var selectStr = '$select=';
var expandStr = '$expand=';
var filterStr = '$filter=(EMAIL eq \''+UserEmail+'\')';
var requestURL = '/_api/web/lists/GetByTitle(\'Staff
Directory\')/items?'+filterStr; // + '?' + selectStr + '&' + expandStr + '&'
+ filterStr;
console.log(requestURL);
$.ajax({
url: requestURL,
headers: {
Accept: 'application/json;odata=verbose'
},
method: 'GET',
//Success Function
success: function (data) {
res = data.d.results;
console.log(res);
// College Name Function
switch(res[0].LOC){
case "BHC" : {
loc1="Brookhaven College";
break;
}
case "CVC" : {
loc1="Cedar Valley College";
break;
}
case "EFC" : {
loc1="Eastfield College";
break;
}
case "ECC" : {
loc1="El Centro College";
break;
}
case "MVC" : {
loc1="Mountain View College";
break;
}
case "NLC" : {
loc1="North Lake College";
break;
}
case "RLC" : {
loc1="Richland College";
break;
}
case "DCO" : {
loc1="Lecroy Center/ Dallas Colleges Online";
break;
}
case "DSC" : {
loc1="District Service Center";
break;
}
case "DO" : {
loc1="District Office";
break;
}
default : {
loc1="";
break;
}
}
if((res[0].Office_x0020_Number == null)||(res[0].Office_x0020_Number
== undefined)){
officeNum = "";
}
else {
officeNum = '<li class="contact-office">' +
res[0].Office_x0020_Number + '</li>\n'
}
if((res[0].biolink == null)||(res[0].biolink == undefined)){
biolinkURL = "";
}
else {
biolinkURL = '<li class="contact-bio">Online Bio<span class="sr-only"> for ' + res[0].Title + '</span></li>\n'
}
if((res[0].staff_x002d_photo == null)||(res[0].staff_x002d_photo
== undefined)){
staffphoto = '/logo-' +
res[0].LOC + '-square.svg'
}
else {
staffphoto = res[0].staff_x002d_photo;
}
var contactString =
'<div class="col-sm-4">\n' +
'<div class="contact-box height-sm-400 ' + res[0].LOC + '">\n' +
'<img class="contact-photo" src="' + staffphoto + '">\n' +
'<div class="contact-name">' + res[0].FIRST + ' ' + res[0].Title +
'</div>\n' +
'<div class="contact-title">' + res[0].Title1 + '</div>\n' +
'<div class="contact-dept">' + res[0].department + '</div>\n' +
'<ul class="contact-info">\n' +
'<li class="contact-location">' + loc1 + '</li>\n' +
officeNum +
'<li class="contact-email"><a href="mailto:' + res[0].EMAIL + '">' +
res[0].EMAIL + '</a></li>\n' +
'<li class="contact-phone">' + res[0].PHONE + '</li>\n' +
biolinkURL +
'</ul>\n</div>\n</div>\n</div>\n';
$("#GetStaffDirectory").append(contactString);
},
//Error Function
error: function (jQxhr, errorCode, errorThrown) {
res = jQxhr;
console.log(res);
$("#AjaxLoader0").hide();
$(".AjaxMessage").html(errorThrown);
},
dataType: 'json' //Make me a JSON
});
};
Is there an easier way to ensure the script pulls the data in the order listed on the page? I'm guessing there's some method with an array but I'm not as familiar with how they work.
It is better to do everything you need in one request for better performance. Change GetStaffDirectory() to work with a string array and filter like this;
var filterStr = '$filter=((EMAIL eq userEmails[0]) or (EMAIL eq userEmails[1]))'
And also, you can now add your sorting logic;
$orderby=EMAIL desc

I have javascript code to view a news from RSS as a vertical list. I need help to move the list of topics as horizontal one by one, in one line

I have javascript code to view a news from RSS as a vertical list.
(function ($) {
$.fn.FeedEk = function (opt) {
var def = $.extend({
MaxCount: 5,
ShowDesc: true,
ShowPubDate: true,
DescCharacterLimit: 0,
TitleLinkTarget: "_blank",
DateFormat: "",
DateFormatLang:"en"
}, opt);
var id = $(this).attr("id"), i, s = "", dt;
$("#" + id).empty();
if (def.FeedUrl == undefined) return;
$("#" + id).append('<img src="loader.gif" />');
var YQLstr = 'SELECT channel.item FROM feednormalizer WHERE output="rss_2.0" AND url ="' + def.FeedUrl + '" LIMIT ' + def.MaxCount;
$.ajax({
url: "https://query.yahooapis.com/v1/public/yql?q=" + encodeURIComponent(YQLstr) + "&format=json&diagnostics=false&callback=?",
dataType: "json",
success: function (data) {
$("#" + id).empty();
if (!(data.query.results.rss instanceof Array)) {
data.query.results.rss = [data.query.results.rss];
}
$.each(data.query.results.rss, function (e, itm) {
s += '<li><div class="itemTitle"><a href="' + itm.channel.item.link + '" target="' + def.TitleLinkTarget + '" >' + itm.channel.item.title + '</a></div>';
if (def.ShowPubDate){
dt = new Date(itm.channel.item.pubDate);
s += '<div class="itemDate">';
if ($.trim(def.DateFormat).length > 0) {
try {
moment.lang(def.DateFormatLang);
s += moment(dt).format(def.DateFormat);
}
catch (e){s += dt.toLocaleDateString();}
}
else {
s += dt.toLocaleDateString();
}
s += '</div>';
}
if (def.ShowDesc) {
s += '<div class="itemContent">';
if (def.DescCharacterLimit > 0 && itm.channel.item.description.length > def.DescCharacterLimit) {
s += itm.channel.item.description.substring(0, def.DescCharacterLimit) + '...';
}
else {
s += itm.channel.item.description;
}
s += '</div>';
}
});
$("#" + id).append('<ul class="feedEkList">' + s + '</ul>');
}
});
};
})(jQuery);
I need help to move the list of topics as horizontal one by one, in one line. by used javascript code. this code display just 5 topics, which I need it, but I have problem to how can I movement it as horizontal.

Facebook Graph API get original picture size not working

Need some help to get a normal or larger image from posts using the Facebook Graph API, at the moment it only gives a 130 x 130 px image in the object.
function fbFetch() {
var access_token = "";
var url = "https://graph.facebook.com/?ids=intel&fields=posts.limit(5){message,created_time,picture.type(normal)}&access_token=' + access_token;
$.getJSON(url, function(response) {
var messages = [];
Object.getOwnPropertyNames(response).forEach(function(page, idx, array) {
response[page].posts.data.forEach(function(post, idx, array) {
messages.push(post);
});
});
function compare(a, b) {
if (a.created_time < b.created_time)
return -1;
if (a.created_time > b.created_time)
return 1;
return 0;
}
var html = "<ul>";
$.each(messages.sort(compare), function(i, fb) {
if (typeof fb.picture != "undefined") {
html += "<li>" + fb.message + "</br>" + '<img SRC="' + fb.picture + '">' + "</br>" + fb.created_time + "</li></br>";
} else {
html += "<li>" + fb.message + "</br>" + fb.created_time + "</li></br>";
}
});
html += "</ul>";
$('.facebookfeed').html(html);
});
}
fbFetch();
<div class="facebookfeed"></div>
Fiddle here: http://jsfiddle.net/6fhq3dat/17/
use full_picture instead of picture
var url = "https://graph.facebook.com/?ids=intel&fields=posts.limit(3){message,created_time,full_picture}&access_token=" + access_token;
demo

javascript inline code link generating chrome extension

I'm trying to make an extension for chrome that grabs data from a website and I'm having trouble making the links clickable. I CAN NOT use javascript inside the link (ex: href="javascript:myfunction(param);")
I need to create a div for each title, then create a onclick function that handles the div's innerhtml, and I can't get it to work.
here is my code so far:
document.addEventListener('DOMContentLoaded', function () {
$().ready(function () {
var url = 'http://somewebsite';
$.get(url, function (data) {
data = data.split("<tr name=\"hover\">");
var name;
var link;
var count = data.length;
count++;
for(var i = 1; i < data.length; i++){
data[i] = data[i].replace("<br>","<br />");
data[i] = data[i].replace("class=\"thread_link\"", "");
data[i] = data[i].replace("<td class=\"forum_thread_post\" align=\"center\">0</td>","");
data[i] = data[i].replace("<td class=\"forum_thread_post\">","");
data[i] = data[i].replace("</td>","");
data[i] = data[i].replace('<td class="forum_thread_post" align="center">0</td>','');
if(i != data.length-1){
data[i] = data[i].replace("<a href=\"", "");
data[i] = data[i].replace("</a>", "");
data[i] = data[i].split("\" >");
data[i][1] = data[i][1].split("<");
document.write('<div id="' + data[i][1][0] + '">' + data[i][1][0] + data[i][0] + "</div><br /><br />");
}else{
data[i] = data[i].split("</table>")[0];
data[i] = data[i].replace("<a href=\"", "");
data[i] = data[i].replace("</a>", "");
data[i] = data[i].split("\" >");
data[i][1] = data[i][1].split("<");
document.write('<div id="' + data[i][1][0] + '">' + data[i][1][0] + data[i][0] + "</div>");
}
}
//document.body.innerHTML = '';
//console.log(data);
});
});
});
document.write('</script>');
function getshow(url){
alert(url);
document.body.innerHTML = '';
$.get("http://somewebsite" + url, function (dat) {
document.write(dat);
});
}

Extension stopped working with Google Chrome manifest v2

I am developing an extension for Google Chrome that was working perfectly, but now stopped working with version 2 of the manifest.
It is giving me the following error:
Uncaught SyntaxError: Unexpected end of input
popup.js:
chrome.tabs.getSelected(null, function (aba) {
link = aba.url;
titulo = aba.title;
document.getElementById('mensagem').value = link;
});
function GrabIFrameURL(feedDescription) {
var regex = new RegExp("iframe(?:.*?)src='(.*?)'", 'g');
var matches = regex.exec(feedDescription);
var url = '';
if (matches.length == 2) {
url = matches[1];
}
var quebra = url.split("/");
return quebra[4];
}
$(document).ready(function () {
if (localStorage.nome == '' || localStorage.nome == null || localStorage.email == '' || localStorage.email == null) {
jQuery('#formulario').hide();
jQuery('#erros').html('Configure seus dados aqui');
}
jQuery("#resposta").ajaxStart(function () {
jQuery(this).html("<img src='img/loading.gif'> <b>Sugestão sendo enviada, aguarde...</b>");
});
jQuery('#submit').click(function () {
var nome = localStorage.nome;
var email = localStorage.email;
var mensagem = titulo + "\n\n<br><br>" + link;
jQuery('#formulario').hide();
jQuery.post('http://blabloo.com.br/naosalvo/mail.php', {
nome: nome,
email: email,
mensagem: mensagem
},
function (data, ajaxStart) {
jQuery('#resposta').html(data);
console.log(data);
});
return false;
});
//Listagem de posts
var bkg = chrome.extension.getBackgroundPage();
jQuery('#close').click(function () {
window.close();
});
jQuery('#markeall').click(function () {
bkg.lidoAll();
$('.naolido').attr('class', 'lido');
});
jQuery.each(bkg.getFeed(), function (id, item) {
if (item.naolido == '1')
lidoClass = 'naolido';
else
lidoClass = 'lido';
var thumb = GrabIFrameURL(item.description);
$('#feed').append('<li><a id="' + item.id + '" href="' + item.link + '" class="' + lidoClass + '"><img src="' + $.jYoutube(thumb, 'small') + '" class="' + lidoClass + '"/>' + item.title + '</a></li>');
});
$('.naolido').click(function (e) {
e.preventDefault();
klicked = $(this).attr('id');
console.log(klicked);
bkg.setLido(klicked);
$(this).attr('class', 'lido');
openLink($(this).attr('href'));
});
$('.lido').click(function (e) {
openLink($(this).attr('href'));
});
var openLink = function (link) {
chrome.tabs.create({
'url': link,
'selected': true
});
window.close();
}
});
I think the problem is in this part of popup.js:
jQuery.each(bkg.getFeed(), function (id, item) {
if (item.naolido == '1')
lidoClass = 'naolido';
else
lidoClass = 'lido';
var thumb = GrabIFrameURL(item.description);
$('#feed').append('<li><a id="' + item.id + '" href="' + item.link + '" class="' + lidoClass + '"><img src="' + $.jYoutube(thumb, 'small') + '" class="' + lidoClass + '"/>' + item.title + '</a></li>');
});
You problem is actually in background.js on lines 12 and 20, you set localStorage.items to '' initially but then try to run a JSON.parse() on it later, but it's not JSON data so JSON.parse returns Unexpected end of input. And, JSON.parse isn't a function you define but a native browser function so, it shows the error as being on "line 1".
Try defining it as an empty array initially and then "pushing" to it as you are now.

Categories