Facebook API disrupting rest of page until it loads data - javascript

I'm using the Facebook Javascript SDK to provide some features, but it's making the functionality of the rest of the page lag out/not work until it's done loading. To experience this, please go on http://beta.speedsums.com and click the (poorly placed) Facebook login button and then try to click inside the answer box. Alternatively, you may be able to spot something from the code here:
<!DOCTYPE HTML>
<html>
<head>
<title>Speedsums - do maths fast</title>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-46469577-1', 'speedsums.com');
ga('send', 'pageview');
</script>
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Lato:100,300,400,700,900,100italic,300italic,400italic,700italic,900italic' rel='stylesheet' type='text/css'>
<style type="text/css">
css stuff
</style>
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
<script src="jquery.runner-min.js" type="text/javascript"></script>
<script src="chart.js" type="text/javascript"></script>
<script src="jquery.animate-colors-min.js" type="text/javascript"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
var data2;
var jsonn;
var myLine;
</script>
<script type="text/javascript">
var fbid;var fbid = 0;
var operators = ['+','-','x','\xF7'];
var properties = {
borderColor: 'green',
borderWidth: '3px',
height: '37px'
};
var user = {};
var friends = [];
var friendscores = [];
var friendpics = [];
var fbconnect;
var operand1;
var operand2;
var operator;
var answers;
var time;
var name;
var one;
var two;
var iteration = 0;
var unique;
var times = [];
var start;
var finish;
function drawuserchart(id){
console.log('drawuserchart() initialised');
$.ajax({
url: 'userchart.php',
data: {id: id},
type: 'post',
dataType:"json",
success: function(data22){
console.log(data22);
var labelarray = new Array();
for (var i=0;i<data22.length;i++) {
labelarray.push("");
}
data2 = {
labels : labelarray,
datasets : [
{
fillColor : "rgba(151,187,205,0.5)",
strokeColor : "rgba(131,167,185,1)",
data : data22
}
]
}
var options = {
//Boolean - If we show the scale above the chart data
scaleOverlay : false,
}
myLine2 = new Chart(document.getElementById("userchart").getContext("2d")).Line(data2,options);
}, error: function(xhr,err){
alert("readyState: "+xhr.readyState+"\nstatus: "+xhr.status);
alert("responseText: "+xhr.responseText);
}
});
}
function generateproblems(number){
operand1 = []; operand2 = []; operator = []; answers = [];
for (var i=0; i < number; i++){
//generating questions
operator.push(operators[Math.floor(Math.random() * 4)]);
if (operator[i] == '\xF7'){
denominator = Math.floor((Math.random()*12)+1);
numerator = denominator * Math.floor((Math.random()*12)+1);
operand1.push(numerator);
operand2.push(denominator);
} else if (operator[i] == '-'){
one = Math.floor((Math.random()*12)+1);
two = Math.floor((Math.random()*12)+1);
operand1.push(Math.max(one,two));
operand2.push(Math.min(one,two));
} else {
operand1.push(Math.floor((Math.random()*12)+1));
operand2.push(Math.floor((Math.random()*12)+1));
}
//calculating answers
if (operator[i] == '+'){
answers.push(operand1[i] + operand2[i]);
} else if (operator[i] == '-'){
answers.push(operand1[i] - operand2[i]);
} else if (operator[i] == 'x'){
answers.push(operand1[i] * operand2[i]);
} else if (operator[i] == '\xF7'){
answers.push(operand1[i] / operand2[i]);
}
}
}
function runtest(number){
$('#question').append('' + operand1[iteration] + ' ' + operator[iteration] + ' ' + operand2[iteration] + ' = ');
$('#answer').keyup(function() {
if ($('#answer').val() == answers[iteration]){
finish = Date.now();
times.push(finish-start);
console.log(finish-start)
if(iteration == 0){
start = Date.now();
$('#runner').runner('start');
$('#counter').html(iteration);
};
iteration++;
correct(number);
}
});
}
function percentile(score){
$.ajax({
url: 'percentile.php',
data: {score: score},
type: 'post',
success: function(data){
$('#percentile').html('You beat <b>'+ data +'% </b>of people.');
}
});
}
function correct(number){
if(iteration == number){
$('#runner').runner('stop');
$('#runner').append('s');
time = parseInt($('#runner').html()) / (number - 1);
$('#runner').prepend('Total time: ');
$('body').append('Time per question: ' + time + 's');
stoptest();
} else {
$('#question').empty();
$('#counter').html(iteration);
$('#answer').val('');
$('#question').append('' + operand1[iteration] + ' ' + operator[iteration] + ' ' + operand2[iteration] + ' = ');
start = Date.now();
}
}
function stoptest(){
operand1 = [];
operand2 = [];
answers = [];
operator = [];
$('#question').remove();
$('#answer').remove();
console.log(times);
}
function gethighscore(id){
$.ajax({
async: false,
url: 'gethighscore.php',
data: {id: id},
type: 'post',
success: function(data){
friendscores.push(data);
console.log(data);
}
});
}
function getuserhighscore(id){
$.ajax({
async: false,
url: 'gethighscore.php',
data: {id: id},
type: 'post',
success: function(data){
user['highscore'] = data;
}
});
}
function userpercentile(score){
$.ajax({
url: 'percentile.php',
async: false,
data: {score: score},
type: 'post',
success: function(data){
user['percentile'] = data;
}
});
}
function post(name,score,unique){
$.ajax({
url: 'post.php',
data: {name: name, score: score, unique: unique},
type: 'post',
success: function(data){
$('#main').html('');
$('#main').append('<br><br><br><br><span id="message">Submitted! ok now try again</span><br><br>');
$('#main').append('<div id="restart">restart</div>');
}
});
}
function logg(score,unique,fb){
console.log('attempting to log');
$.ajax({
url: 'log.php',
data: {score: score, unique: unique, fb: fb},
type: 'post',
success: function(data){
console.log(data);
}
});
}
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
function portrait(){
console.log('success');
}
$(document).ready(function(){
$.ajax({
url: 'total.php',
data: {},
type: 'post',
dataType: 'html',
success: function(data){
console.log(data);
$('.total').append('<b>'+numberWithCommas(data)+'</b>');
}
});
$('#form').hide();
$('#runner').runner({
countdown: true,
startAt: 30 * 1000,
stopAt: 0
}).on('runnerFinish', function(eventObject, info) {
times[0] = 0;
times[times.length - 1] = 0;
if(times[2] == times[3] == times[4] == times[5]){
window.location.replace("http://en.wikipedia.org/wiki/Hacker_(computer_security)");
}
unique = 15*iteration + 4;
percentile(iteration);
logg(iteration,unique,fbid);
var slowesttime = Math.max.apply(Math,times);
var position = times.indexOf(slowesttime);
var slowestq = '' + operand1[position] + ' ' + operator[position] + ' ' + operand2[position] + '';
var slowesta = answers[position];
$('#counter, #solidus, #runner').remove();
$('body').animate({backgroundColor: '#f0f0f0'});
$('#wrapper').fadeIn("fast");
if(fbconnect == true){
$('#sidebar').fadeIn("fast");
}
$('#score').append('<div id="results1">Total: <b>' + iteration + '</b></div>');
$('#score').append('<div id="percentile"></div>');
$('#score').append('<div id="other">Time per question: <b>' + (30/iteration).toFixed(2) + 's</b></div>');
$('#score').append('<div id="other">For future reference, <b>' + slowestq + ' = ' + slowesta + '</b>. It should not take <b>' + (slowesttime/1000).toFixed(2) + 's</b> to solve that next time. </div>');
$('#form').show();
$('#tweet').click(function(){
window.open('https://twitter.com/intent/tweet?text=omg+i+just+did+'+iteration+'+maths+problems+in+30s!+try+and+beat+me!&hashtags=speedsums&url=http%3A%2F%2Fwww.speedsums.com', 'Tweet', "height=300,width=500");
});
stoptest();
});
generateproblems(120);
runtest(120);
$('#answer').focus(function(){
$('body').animate({backgroundColor: '#BDC3C7'});
$('#wrapper').fadeOut("fast");
$('#instructions').fadeOut("fast");
$('#sidebar').fadeOut("fast");
});
$('#answer').blur(function(){
$('#wrapper').fadeIn("fast");
$('#instructions').fadeIn("fast");
if(fbconnect == true){
$('#sidebar').fadeIn("fast");
}
$('body').animate({backgroundColor: '#f0f0f0'});
});
$('#post').click(function(){
name = $('#name').val();
unique = 15*iteration + 4;
post(name,iteration,unique);
});
$('body').on('click','#restart, #retry', function() {
window.location.href = "index.html";
});
//Get context with jQuery - using jQuery's .get() method.
var ctx = $("#myChart").get(0).getContext("2d");
//This will get the first returned node in the jQuery collection.
var myNewChart = new Chart(ctx);
var ctx2 = $("#userchart").get(0).getContext("2d");
//This will get the first returned node in the jQuery collection.
var userchart = new Chart(ctx2);
$.ajax({
url: 'distribution.php',
data: {},
type: 'get',
dataType:"json",
success: function(data22){
var dataarray = new Array();
for (var i=0;i<46;i++) {
dataarray.push(data22[i]);
}
data2 = {
labels : ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42"],
datasets : [
{
fillColor : "rgba(151,187,205,0.5)",
strokeColor : "rgba(151,187,205,1)",
data : dataarray
}
]
}
var options = {
//Boolean - If we show the scale above the chart data
scaleOverlay : false,
}
myLine = new Chart(document.getElementById("myChart").getContext("2d")).Bar(data2,options);
}
});
});
</script>
</head>
<body>
<div id="fb-root"></div>
<!--
Below we include the Login Button social plugin. This button uses the JavaScript SDK to
present a graphical Login button that triggers the FB.login() function when clicked.<span class="total">Total sums done: </span> -->
<div id="header"><div class="page"><a class="nav1">TEST</a><div id="logo"></div><a class="nav2">PRACTICE</a><div id="thumbnail"><div class="fb-login-button" id="fbloginbutton" data-max-rows="1" data-size="medium" data-show-faces="false" data-auto-logout-link="false"></div></div></div></div><div id="sidebar" style="display:none"><h2>FRIENDS</h2><div id="friendcontainer"></div><div id="statscontainer"><h2>YOUR STATS</h2></div><canvas id="userchart" width="250" height="200"></canvas></div>
<div id="notice">Speedsums is under renovation - there's gonna be a bunch of cool new stuff soon, so keep checking back! -Taimur</a></div>
<br><div class="instructions"><span id="instructions">Click inside the box below to begin</span></div><div id="spacer"></div>
<div id="main">
<div id="question"></div><br>
<div><input id="answer" type="text" autocomplete="off"></div><br>
<div id="runner"></div><span id="solidus">/</span><div id="counter">0</div>
<div id="score"></div>
<div id="form">
<div id="tweet">Tweet Score</div><br>
<div id="retry">Retry</div>
</div><br><br>
</div>
<canvas id="myChart" width="1440" ></canvas>
<script>
// Include the UserVoice JavaScript SDK (only needed once on a page)
UserVoice=window.UserVoice||[];(function(){var uv=document.createElement('script');uv.type='text/javascript';uv.async=true;uv.src='//widget.uservoice.com/aIRVe5TPDRSYNkW7H1CAg.js';var s=document.getElementsByTagName('script')[0];s.parentNode.insertBefore(uv,s)})();
//
// UserVoice Javascript SDK developer documentation:
// https://www.uservoice.com/o/javascript-sdk
//
// Set colors
UserVoice.push(['set', {
accent_color: '#448dd6',
trigger_color: 'white',
trigger_background_color: '#448dd6'
}]);
// Identify the user and pass traits
// To enable, replace sample data with actual user traits and uncomment the line
UserVoice.push(['identify', {
//email: 'john.doe#example.com', // User’s email address
//name: 'John Doe', // User’s real name
//created_at: 1364406966, // Unix timestamp for the date the user signed up
//id: 123, // Optional: Unique id of the user (if set, this should not change)
//type: 'Owner', // Optional: segment your users by type
//account: {
// id: 123, // Optional: associate multiple users with a single account
// name: 'Acme, Co.', // Account name
// created_at: 1364406966, // Unix timestamp for the date the account was created
// monthly_rate: 9.99, // Decimal; monthly rate of the account
// ltv: 1495.00, // Decimal; lifetime value of the account
// plan: 'Enhanced' // Plan name for the account
//}
}]);
// Add default trigger to the bottom-right corner of the window:
UserVoice.push(['addTrigger', { mode: 'satisfaction', trigger_position: 'top-left' }]);
// Or, use your own custom trigger:
//UserVoice.push(['addTrigger', '#id', { mode: 'satisfaction' }]);
// Autoprompt for Satisfaction and SmartVote (only displayed under certain conditions)
UserVoice.push(['autoprompt', {}]);
</script>
<script>
window.fbAsyncInit = function() {
FB.init({
appId : '219892158204692',
status : true, // check login status
cookie : true, // enable cookies to allow the server to access the session
xfbml : true // parse XFBML
});
// Here we subscribe to the auth.authResponseChange JavaScript event. This event is fired
// for any authentication related change, such as login, logout or session refresh. This means that
// whenever someone who was previously logged out tries to log in again, the correct case below
// will be handled.
FB.Event.subscribe('auth.authResponseChange', function(response) {
// Here we specify what we do with the response anytime this event occurs.
if (response.status === 'connected') {
if(fbconnect == true){
} else {
fbconnect = true;
$('#fbloginbutton').hide();
$('#friendcontainer').append('<span id="loader"><center>Loading...</center></span>');
// The response object is returned with a status field that lets the app know the current
// login status of the person. In this case, we're handling the situation where they
// have logged in to the app.
FB.api(
"/me",
function (response) {
if (response && !response.error) {
fbid = response['id'];
user['id'] = response['id'];
getuserhighscore(user['id']);
userpercentile(parseInt(user['highscore']));
$('#statscontainer').append('<span class="label">Highest Score</span>: '+user['highscore']+'<br>');
$('#statscontainer').append('<span class="label">Percentile (global)</span>: '+user['percentile']+'<br>');
drawuserchart(user['id']);
}
}
);
FB.api(
"/fql?q=select%20uid%2C%20first_name%2C%20is_app_user%20from%20user%20where%20uid%20in%20(select%20uid2%20from%20friend%20where%20uid1%3Dme())%20and%20is_app_user%3D1",
function (response) {
console.log('friends installed:');
console.log(response);
console.log(response['data'][0].id);
var responseArray = [];
responseArray.push(response);
console.log(responseArray);
user['friends'] = response['data'].length;
if (response && !response.error) {
for (var i=0;i<response['data'].length;i++){
friend = response['data'][i];
console.log('friend coming up');
console.log(friend);
friends.push(friend.uid);
$('#friendcontainer').append('<div class="friendbox" id="'+friend.uid+'"></div>');
$('#'+friend.uid+'').append('<img class="friendpic" src="https://graph.facebook.com/'+friend.uid+'/picture?height=60&width=60&type=square">');
$('#'+friend.uid+'').append('<div class="friendname">'+friend.first_name+'</div>');
gethighscore(friend.uid);
$('#'+friend.uid+'').append(' - '+friendscores[i]+'');
console.log(friendscores);
}
$('#loader').remove();
user['friendrank'] = 1;
for (var i=0;i<friendscores.length;i++){
if(friendscores[i] > user['highscore']){
user['friendrank']++;
}
}
$('#statscontainer').append('<span class="label">Rank (among friends)</span>: '+user['friendrank']+'<br>');
} else {
console.log(response.error)
}
}
);
console.log(friends);
console.log(user)
FB.api(
"/me/picture",
{
"redirect": false,
"height": "100",
"type": "normal",
"width": "100"
},
function (response) {
if (response && !response.error) {
user['picture'] = response['data']['url'];
console.log(user['picture']);
$('#thumbnail').append('<img id="thumbnailpic" src="'+user['picture']+'">');
}
}
);
}
testAPI();
} else if (response.status === 'not_authorized') {
// In this case, the person is logged into Facebook, but not into the app, so we call
// FB.login() to prompt them to do so.
// In real-life usage, you wouldn't want to immediately prompt someone to login
// like this, for two reasons:
// (1) JavaScript created popup windows are blocked by most browsers unless they
// result from direct interaction from people using the app (such as a mouse click)
// (2) it is a bad experience to be continually prompted to login upon page load.
FB.login();
} else {
// In this case, the person is not logged into Facebook, so we call the login()
// function to prompt them to do so. Note that at this stage there is no indication
// of whether they are logged into the app. If they aren't then they'll see the Login
// dialog right after they log in to Facebook.
// The same caveats as above apply to the FB.login() call here.
FB.login();
}
});
};
// Load the SDK asynchronously
(function(d){
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
}(document));
// Here we run a very simple test of the Graph API after login is successful.
// This testAPI() function is only called in those cases.
function testAPI() {
console.log('Welcome! Fetching your information.... ');
FB.api('/me', function(response) {
console.log('Good to see you, ' + response.name + '.');
$('#sidebar').slideDown("slow");
});
}
</script>
</body>
</html>
Sorry that the code is so messy and bad - I'm not sure how much of the Javascript stuff I need to include for the problem to be diagnosed so I've just put it all in. I'm not sure why the Facebook stuff is disrupting everything else, because it's right at the very bottom of the page...
Thanks

Well, at least I notice two things in your code:
The call of testAPI() is from my perspective unneccessary and "out of context"
You can save at least one API call if you combine the first with the third one like this
FB.api('/me?fields=id,picture', function { ... });

Related

WordPress REST API Ajax show more posts button

PHP/HTML:
<ul id="load-more-div"></ul>
<a id="load-more" data-ppp="<?php echo get_option('posts_per_page'); ?>">load more</a>
JavaScripts:
(function($) {
// Grab the load more button, since I only want to run the code if the button is on the page
var loadMoreButton = $("#load-more");
if (loadMoreButton) {
// Get the posts_per_page number set in Reading Options
var ppp = loadMoreButton.data("ppp");
// Initialize function
var loadPosts = function(page) {
var theData, loadMoreContainer, errorStatus, errorMessage;
// The AJAX request
$.ajax({
url: "/wp-json/wp/v2/posts",
dataType: "json",
data: {
// Match the query that was already run on the page
per_page: ppp,
page: page,
type: "post",
orderby: "date"
},
success: function(data) {
// Remove the button if the response returns no items
if (data.length < 1) {
loadMoreButton.remove();
}
// Create a place to store exactly what I need
// Alternatively, the response can be filtered to only return the needed data, which is probably more efficient as the following loop wont be needed
theData = [];
// Get only what I need, and store it
for (i = 0; i < data.length; i++) {
theData[i] = {};
theData[i].id = data[i].id;
theData[i].link = data[i].link;
theData[i].title = data[i].title.rendered;
theData[i].content = data[i].content.rendered;
}
// Grab the container where my data will be inserted
loadMoreContainer = $("#load-more-div");
// For each object in my newly formed array, build a new element to store that data, and insert it into the DOM
$.each(theData, function(i) {
loadMoreContainer.append(
'<li><a href="' +
theData[i].link +
'">' +
theData[i].title +
"</a></li>"
);
});
},
error: function(jqXHR, textStatus, errorThrown) {
errorStatus = jqXHR.status + " " + jqXHR.statusText + "\n";
errorMessage = jqXHR.responseJSON.message;
// Show me what the error was
console.log(errorStatus + errorMessage);
}
});
};
// Since our AJAX query is the same as the original query on the page (page 1), start with page 2
var getPage = 2;
// Actually implement the functionality when the button is clicked
loadMoreButton.on("click", function() {
loadPosts(getPage);
// Increment the page, so on the next click we get the next page of results
getPage++;
});
}
})(jQuery);
This is the trouble part, it doesn't remove the link.
// Remove the button if the response returns no items
if (data.length < 1) {
loadMoreButton.remove();
}
Console errors when click the load more link after reaching the end of posts:
400 Bad Request The page number requested is larger than the number of pages available.
I found two ways to solve it:
###Using data attribute
Get the max number of pages in the template, assign it to a data attribute, and access it in the scripts. Then check current page against total page numbers, and set disabled states to the load more button when it reaches the last page.
PHP/HTML:
<ul id="ajax-content"></ul>
<button type="button" id="ajax-button" data-endpoint="<?php echo get_rest_url(null, 'wp/v2/posts'); ?>" data-ppp="<?php echo get_option('posts_per_page'); ?>" data-pages="<?php echo $wp_query->max_num_pages; ?>">Show more</button>
JavaScripts:
(function($) {
var loadMoreButton = $('#ajax-button');
var loadMoreContainer = $('#ajax-content');
if (loadMoreButton) {
var endpoint = loadMoreButton.data('endpoint');
var ppp = loadMoreButton.data('ppp');
var pages = loadMoreButton.data('pages');
var loadPosts = function(page) {
var theData, errorStatus, errorMessage;
$.ajax({
url: endpoint,
dataType: 'json',
data: {
per_page: ppp,
page: page,
type: 'post',
orderby: 'date'
},
beforeSend: function() {
loadMoreButton.attr('disabled', true);
},
success: function(data) {
theData = [];
for (i = 0; i < data.length; i++) {
theData[i] = {};
theData[i].id = data[i].id;
theData[i].link = data[i].link;
theData[i].title = data[i].title.rendered;
theData[i].content = data[i].content.rendered;
}
$.each(theData, function(i) {
loadMoreContainer.append('<li>' + theData[i].title + '</li>');
});
loadMoreButton.attr('disabled', false);
if (getPage == pages) {
loadMoreButton.attr('disabled', true);
}
getPage++;
},
error: function(jqXHR) {
errorStatus = jqXHR.status + ' ' + jqXHR.statusText + '\n';
errorMessage = jqXHR.responseJSON.message;
console.log(errorStatus + errorMessage);
}
});
};
var getPage = 2;
loadMoreButton.on('click', function() {
loadPosts(getPage);
});
}
})(jQuery);
###Using jQuery complete event
Get the total pages x-wp-totalpages from the HTTP response headers. Then change the button states when reaches last page.
PHP/HTML:
<ul id="ajax-content"></ul>
<button type="button" id="ajax-button" data-endpoint="<?php echo get_rest_url(null, 'wp/v2/posts'); ?>" data-ppp="<?php echo get_option('posts_per_page'); ?>">Show more</button>
JavaScripts:
(function($) {
var loadMoreButton = $('#ajax-button');
var loadMoreContainer = $('#ajax-content');
if (loadMoreButton) {
var endpoint = loadMoreButton.data('endpoint');
var ppp = loadMoreButton.data('ppp');
var pager = 0;
var loadPosts = function(page) {
var theData, errorStatus, errorMessage;
$.ajax({
url: endpoint,
dataType: 'json',
data: {
per_page: ppp,
page: page,
type: 'post',
orderby: 'date'
},
beforeSend: function() {
loadMoreButton.attr('disabled', true);
},
success: function(data) {
theData = [];
for (i = 0; i < data.length; i++) {
theData[i] = {};
theData[i].id = data[i].id;
theData[i].link = data[i].link;
theData[i].title = data[i].title.rendered;
theData[i].content = data[i].content.rendered;
}
$.each(theData, function(i) {
loadMoreContainer.append('<li>' + theData[i].title + '</li>');
});
loadMoreButton.attr('disabled', false);
},
error: function(jqXHR) {
errorStatus = jqXHR.status + ' ' + jqXHR.statusText + '\n';
errorMessage = jqXHR.responseJSON.message;
console.log(errorStatus + errorMessage);
},
complete: function(jqXHR) {
if (pager == 0) {
pager = jqXHR.getResponseHeader('x-wp-totalpages');
}
pager--;
if (pager == 1) {
loadMoreButton.attr('disabled', true);
}
}
});
};
var getPage = 2;
loadMoreButton.on('click', function() {
loadPosts(getPage);
getPage++;
});
}
})(jQuery);
The problem appears to be an invalid query to that endpoint so the success: function() is never being run in this circumstance.
Add to All API Errors
You could add the same functionality for all errors like this...
error: function(jqXHR, textStatus, errorThrown) {
loadMoreButton.remove();
....
}
Though that may not be the desired way of handling of all errors.
Test for Existing Error Message
Another option could be to remove the button if you receive an error with that exact message...
error: function(jqXHR, textStatus, errorThrown) {
if (jqXHR.statusText === 'The page number requested is larger than the number of pages available.') {
loadMoreButton.remove();
}
....
}
but this would be susceptible to breaking with any changes to that error message.
Return Custom Error Code from API
The recommended way to handle it would be to return specific error code (along with HTTP status code 400) to specify the exact situation in a more reliable format...
error: function(jqXHR, textStatus, errorThrown) {
if (jqXHR.statusCode === '215') {
loadMoreButton.remove();
}
....
}
Here's an example on how to configure error handling in an API: Best Practices for API Error Handling
Return 200 HTTP Status Code
The last option would be to change the way your API endpoint handles this type of "error"/situation, by returning a 200 level HTTP status code instead, which would invoke the success: instead of the error: callback instead.

JS not autopopulating SharePoint User

I've included a snippet of code that doesn't seem to be doing what I want it to. In the past I've been able to use this to autopopulate a name based on the users name within SharePoint. There's no obvious errors, everything else in the script runs fine, and it appears this does to, it just doesn't do what's intended.
function getWebUserData() {
context = new SP.ClientContext.get_current();
web = context.get_web();
currentUser = web.get_currentUser();
currentUser.retrieve();
context.load(web);
context.executeQueryAsync(Function.createDelegate(this, this.onSuccessMethod),
Function.createDelegate(this, this.onFailureMethod));
}
function onSuccessMethod(sender, args) {
var userObject = web.get_currentUser();
$("input[Title='Requester']").val(userObject.get_title());
$("input[Title='Requester']").attr('disabled','disabled');
}
Below code works in my local SharePoint 2013. referenced thread
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script type="text/javascript">
$(document).ready(function () {
function GetCurrentUser() {
var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/web/currentuser";
var requestHeaders = { "accept": "application/json;odata=verbose" };
$.ajax({
url: requestUri,
contentType: "application/json;odata=verbose",
headers: requestHeaders,
success: onSuccess,
error: onError
});
}
function onSuccess(data, request) {
var userName = data.d.LoginName;
//parse the value.
userName = userName.toString().split("i:0#.w|")[1];
SetUserFieldValue("Requester", userName);
}
function onError(error) {
//alert(error);
}
function SetUserFieldValue(fieldName, userName) {
var _PeoplePicker = $("div[title='" + fieldName + "']");
var _PeoplePickerTopId = _PeoplePicker.attr('id');
var _PeoplePickerEditer = $("input[title='" + fieldName + "']");
_PeoplePickerEditer.val(userName);
var _PeoplePickerOject = SPClientPeoplePicker.SPClientPeoplePickerDict[_PeoplePickerTopId];
_PeoplePickerOject.AddUnresolvedUserFromEditor(true);
}
GetCurrentUser();
});
</script>

Infinite scrolling: Loading more data with Ajax call?

I’m trying to implement an infinite scroll table that displays user’s name, address and email. First, I imported json-server package and created an API endpoint with fakerjs in a separate file called users.js to serve on localhost:
var faker = require('faker')
function generateUsers () {
var users = [];
var loading = true;
for(var i=0;i<50;i++) {
var name = faker.name.findName()
var email = faker.internet.email()
var city = faker.address.city()
var country = faker.address.country()
users.push({
"name": name,
"email": email,
"city": city,
"country": country
})
}
return { "users": users }
}
module.exports = generateUsers
My question is “How can I load another batch of 50 users every time I scroll to the end of the page?” On initial loading, it only loads in 50 users as specified in the user.js file. I was thinking I could push more data into the user array in the ajax success function, but I'm not sure how to implement it.
$(document).ready(function(){
var currentPageNumber = 1;
loadMore(currentPageNumber);
$(window).scroll(function() {
if($(window).scrollTop() == $(document).height()- $(window).height())
{
loadMore(currentPageNumber);
currentPageNumber +=1;
}
});
function loadMore(currentPage){
$.ajax({
method: "GET",
url: "http://localhost:3000/users?_page="+ currentPage,
dataType: 'json',
success: function(data) {
var last = data[data.length-1];
for(var i=0;i<data.length;i++) {
$('tbody').append("<tr><td>"+ data[i].name+"</td><td>"+
data[i].email+"</td><td>"
+ data[i].city + "," + data[i].country+ "</td></tr>")
},
error: function(data) {
console.log("Something went wrong!");
}
})
}
There are some typos in your javascript, try with the code below (I wrote you some comments with my suggestions)
var currentPageNumber = 1; // initialization before all functions
$(document).ready(function(){
loadMore(currentPageNumber);
});
$(window).scroll(function() {
if( $(window).scrollTop() == $(document).height() - $(window).height() ){
currentPageNumber++; //increment by one before calling again loadMore()
loadMore(currentPageNumber);
}
});
function loadMore(currentPage){
$.ajax({
method: "GET",
url: "http://localhost:3000/users?_page="+ currentPage,
dataType: 'json',
cache: false, //avoid browser cache ajax requests
success: function(data) {
$.each(data, function(key, val) { // use jQuery.each, easier and clean
$('tbody').append("<tr><td>"+ val.name+"</td><td>"+
val.email+"</td><td>"
+ val.city + "," + val.country+ "</td></tr>");
});
},
error: function(data) {
console.log("Something went wrong!")
}
});
}

SharePoint 2013 get current user using JavaScript

How to get current user name using JavaScript in Script Editor web part?
Here is the code that worked for me:
<script src="/SiteAssets/jquery.SPServices-2013.02a.js" type="text/javascript"></script>
<script src="/SiteAssets/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
var userid= _spPageContextInfo.userId;
var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/web/getuserbyid(" + userid + ")";
var requestHeaders = { "accept" : "application/json;odata=verbose" };
$.ajax({
url : requestUri,
contentType : "application/json;odata=verbose",
headers : requestHeaders,
success : onSuccess,
error : onError
});
function onSuccess(data, request){
var loginName = data.d.Title;
alert(loginName);
}
function onError(error) {
alert("error");
}
</script>
I found a much easier way, it doesn't even use SP.UserProfiles.js. I don't know if it applies to each one's particular case, but definitely worth sharing.
//assume we have a client context called context.
var web = context.get_web();
var user = web.get_currentUser(); //must load this to access info.
context.load(user);
context.executeQueryAsync(function(){
alert("User is: " + user.get_title()); //there is also id, email, so this is pretty useful.
}, function(){alert(":(");});
Anyways, thanks to your answers, I got to mingle a bit with UserProfiles, even though it is not really necessary for my case.
If you are in a SharePoint Page just use:
_spPageContextInfo.userId;
How about this:
$.getJSON(_spPageContextInfo.webServerRelativeUrl + "/_api/web/currentuser")
.done(function(data){
console.log(data.Title);
})
.fail(function() { console.log("Failed")});
You can use the SharePoint JSOM to get your current user's account information. This code (when added as the snippet in the Script Editor web part) will just pop up the user's display and account name in the browser - you'll want to add whatever else in gotAccount to get the name in the format you want.
<script type="text/javascript" src="/_layouts/15/SP.js"></script>
<script type="text/javascript" src="/_layouts/15/SP.UserProfiles.js"></script>
<script type="text/javascript">
var personProperties;
SP.SOD.executeOrDelayUntilScriptLoaded(getCurrentUser, 'SP.UserProfiles.js');
function getCurrentUser() {
var clientContext = new SP.ClientContext.get_current();
personProperties = new SP.UserProfiles.PeopleManager(clientContext).getMyProperties();
clientContext.load(personProperties);
clientContext.executeQueryAsync(gotAccount, requestFailed);
}
function gotAccount(sender, args) {
alert("Display Name: "+ personProperties.get_displayName() +
", Account Name: " + personProperties.get_accountName());
}
function requestFailed(sender, args) {
alert('Cannot get user account information: ' + args.get_message());
}
</script>
See the SP.UserProfiles.PersonProperties documentation in MSDN for more info.
To get current user info:
jQuery.ajax({
url: _spPageContextInfo.webServerRelativeUrl + "/_api/web/currentuser",
type: "GET",
headers: { "Accept": "application/json;odata=verbose" }
}).done(function( data ){
console.log( data );
console.log( data.d.Title );
}).fail(function(){
console.log( failed );
});
U can use javascript to achive that like this:
function loadConstants() {
this.clientContext = new SP.ClientContext.get_current();
this.clientContext = new SP.ClientContext.get_current();
this.oWeb = clientContext.get_web();
currentUser = this.oWeb.get_currentUser();
this.clientContext.load(currentUser);
completefunc:this.clientContext.executeQueryAsync(Function.createDelegate(this,this.onQuerySucceeded), Function.createDelegate(this,this.onQueryFailed));
}
//U must set a timeout to recivie the exactly user u want:
function onQuerySucceeded(sender, args) {
window.setTimeout("ttt();",1000);
}
function onQueryFailed(sender, args) {
console.log(args.get_message());
}
//By using a proper timeout, u can get current user :
function ttt(){
var clientContext = new SP.ClientContext.get_current();
var groupCollection = clientContext.get_web().get_siteGroups();
visitorsGroup = groupCollection.getByName('OLAP Portal Members');
t=this.currentUser .get_loginName().toLowerCase();
console.log ('this.currentUser .get_loginName() : '+ t);
}
I had to do it using XML, put the following in a Content Editor Web Part by adding a Content Editor Web Part, Edit the Web Part, then click the Edit Source button and paste in this:
<input type="button" onclick="GetUserInfo()" value="Show Domain, Username and Email"/>
<script type="text/javascript">
function GetUserInfo() {
$.ajax({
type: "GET",
url: "https://<ENTER YOUR DOMAIN HERE>/_api/web/currentuser",
dataType: "xml",
error: function (e) {
alert("An error occurred while processing XML file" + e.toString());
console.log("XML reading Failed: ", e);
},
success: function (response) {
var content = $(response).find("content");
var spsEmail = content.find("d\\:Email").text();
var rawLoginName = content.find("d\\:LoginName").text();
var spsDomainUser = rawLoginName.slice(rawLoginName.indexOf('|') + 1);
var indexOfSlash = spsDomainUser.indexOf('\\') + 1;
var spsDomain = spsDomainUser.slice(0, indexOfSlash - 1);
var spsUser = spsDomainUser.slice(indexOfSlash);
alert("Domain: " + spsDomain + " User: " + spsUser + " Email: " + spsEmail);
}
});
}
</script>
Check the following link to see if your data is XML or JSON:
https://<Your_Sharepoint_Domain>/_api/web/currentuser
In the accepted answer Kate uses this method:
var userid= _spPageContextInfo.userId;
var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/web/getuserbyid(" + userid + ")
you can use below function if you know the id of the user:
function getUser(id){
var returnValue;
jQuery.ajax({
url: "http://YourSite/_api/Web/GetUserById(" + id + ")",
type: "GET",
headers: { "Accept": "application/json;odata=verbose" },
success: function(data) {
var dataResults = data.d;
alert(dataResults.Title);
}
});
}
or you can try
var listURL = _spPageContextInfo.webAbsoluteUrl + "/_api/web/currentuser";
try this code..
function GetCurrentUsers() {
var context = new SP.ClientContext.get_current();
this.website = context.get_web();
var currentUser = website.get_currentUser();
context.load(currentUser);
context.executeQueryAsync(Function.createDelegate(this, onQuerySucceeded), Function.createDelegate(this, onQueryFailed));
function onQuerySucceeded() {
var currentUsers = currentUser.get_title();
document.getElementById("txtIssued").innerHTML = currentUsers;
}
function onQueryFailed(sender, args) {
alert('request failed ' + args.get_message() + '\n' + args.get_stackTrace());
}
}
You can use sp page context info:
_spPageContextOnfo.userLoginName

CouchDB document attachments via html form and jquery

I'm trying to create web form that, when submitted will create a couchdb document and add attachment(s) to the doc. I've seen from tutorials/other forums that it's necessary to do this with a two stage process (as futon does). I can get the document to upload, but can't seem to get the attachment to upload. I've tried a number of ways, currently I do something like:
html file with:
<!DOCTYPE HTML>
<html>
<head>
<title>Document submission</title>
<style type="TEXT/CSS" media="all">
</style>
</head>
<body>
<table>
<form id="form" name="form" action="">
<tr>
<td>Field</td>
<td><input type="text" required="required" name="field">
<span id="required">*</span></td>
</tr><tr>
</tr><tr>
<td></td><td><button type="button" id="submit">Select Attachment</button><td>
</tr>
</form>
</table>
</body>
<script src="/_utils/script/json2.js"></script>
<script src="/_utils/script/jquery.js"></script>
<script src="/_utils/script/jquery.couch.js"></script>
<script src="/_utils/script/jquery.form.js"></script>
<script src="/_utils/script/jquery.dialog.js"></script>
<script type="text/javascript" src="basic.js"></script>
</html>
and then a file called basic.js with:
function create_document(){
var db_name = 'uploader';
var db = $.couch.db(db_name);
var data={}
data['fname']=document.form.field.value;
db.saveDoc(data, {
success: function (data) {
add_attachment(db,data);
},
error: function () {
alert("Cannot save the thread.");
}
});
}
function add_attachment(db,data){
var docID = data.id;
var dbName = db.name;
var form = $("#upload-form");
$.showDialog("dialogue.html", {
load: function(elem) {
$("input[name='_rev']", elem).val(data._rev);
},
submit: function(data, callback) {
if (!data._attachments || data._attachments.length == 0) {
callback({_attachments: "Please select a file to upload."});
return;
}
var form = $("#upload-form");
form.find("#progress").css("visibility", "visible");
form.ajaxSubmit({
url: db.uri + $.couch.encodeDocId(docID),
success: function(resp) {
form.find("#progress").css("visibility", "hidden");
location.href = "?" + encodeURIComponent(dbName) +
"/" + $.couch.encodeDocId(docID);
}
});
}
});
}
$(document).ready(function() {
$("button#submit").click(function(event) {
create_document();
});
});
This javascript is pretty much taken from the futon.browse.js uploadAttachment segment. The dialogue.html file is also just straight copy of couchdb's www/dialog/_upload_attachment.html. All files (the main html, basic.js and dialogue.html) are then uploaded to a CouchDB design document (in a database called uploader).
The document is created fine, but no matter what I do, the attachment is never saved. The various methods I've tried either result in an error about multi-part forms or, in this case, no discernible error at all.
Does anyone know what I'm doing wrong?
I inherited this code, so I don't know if it's optimal or not. But it does work:
jQuery.fn.sendForm = function(itemID, itemType) {
// Get all of the values from the form fields
var itemTitle = $('.settingsForm input#title').val(),
itemAuthor = $('.settingsForm input#author').val(),
itemDescription = $('.settingsForm textarea#description').val(),
itemDate = $('.settingsForm input#date').val(),
itemRev = $('.settingsForm input#_rev').val(),
itemDelete = $('.settingsForm input#delete:checked').val(),
itemType = $('.settingsForm select').val(),
itemFilename = $('.settingsForm input:file').val();
// Check for new uploaded file
if (itemFilename == undefined || itemFilename == ""){
$('.settingsForm input:file').remove();
itemFilename = "";
}
else {
itemFilename = itemFilename.replace(/^C:\\fakepath\\/i, '');
}
// If no new file, then fall back on the old filename
if (!itemFilename || itemFilename.length == 0) {
itemFilename = $('.settingsForm input#filename').val();
}
// Force to add a title (the only required field)
if (!itemTitle || itemTitle.length == 0) {
alert(libLang.addTitle); // Get text for language
return;
}
// Check if size of db is above the limit
dbSize = maxDBSize;
$.ajax({
url: "/"+ homeURL,
dataType: 'json',
async: false,
success: function(dbInfo){
dbSize = dbInfo.data_size;
}
});
if (itemDelete != 'Yes' && dbSize >= maxDBSize){
alert(libLang.noSpace);
return;
}
if (itemDelete != 'Yes'){
if (itemID != 'add'){
// Update existing record
$(this).ajaxSubmit({
url: "/"+ homeURL +"/"+ itemID,
data: {"filename":itemFilename},
success: function(resp) {
$.getJSON("/"+ homeURL +"/"+ itemID, function(revData) {
itemRev = revData._rev;
itemAttachment = revData._attachments;
user = revData.user;
if (!revData._attachments || revData._attachments.length == 0) {
$.couch.db(homeURL).saveDoc({
"_id": itemID,
"_rev": itemRev,
"filename":itemFilename,
"title":itemTitle,
"author":itemAuthor,
"type":itemType,
"description":itemDescription,
"date":itemDate,
"user":user
}, {
success: function() {
alert(libLang.saved); // Get text for language
window.location.replace("index.html");
}
});
}
else {
$.couch.db(homeURL).saveDoc({
"_id": itemID,
"_rev": itemRev,
"filename":itemFilename,
"title":itemTitle,
"author":itemAuthor,
"type":itemType,
"description":itemDescription,
"date":itemDate,
"user":user,
"_attachments":itemAttachment
}, {
success: function() {
alert(libLang.saved); // Get text for language
window.location.replace("index.html");
}
});
};
});
}
});
}
else {
// Add new record
uniqueID = $.couch.newUUID();
itemID = itemTitle.replace(/[\s]/g,'_');
itemID = homeUser +'-'+ itemType.charAt(0).toUpperCase() + itemType.slice(1) +'-'+ encodeURI(itemID) +'-'+ uniqueID;
itemID = itemID.replace(/[^a-z 0-9 _ -]+/gi,'');
$('form .settingsForm').attr({"action":"/"+ homeURL +"/"+ itemID});
// Save information
$.couch.db(homeURL).saveDoc({
"_id": itemID,
"filename":itemFilename,
"title":itemTitle,
"author":itemAuthor,
"type":itemType,
"description":itemDescription,
"date":itemDate,
"user":homeUser
}, {
success: function(){
// Get saved info, then add attachment to item
$.getJSON("/"+ homeURL +"/"+ itemID, function(revData) {
$('.settingsForm input#_rev').val(revData._rev);
var data = {};
$.each($("form :input").serializeArray(), function(i, field) {
data[field.name] = field.value;
});
$("form :file").each(function() {
data[this.name] = this.value.replace(/^C:\\fakepath\\/g, ''); // file inputs need special handling
});
itemFilename = data._attachments;
$('form.settingsForm').ajaxSubmit({
url: "/"+ homeURL +"/"+ itemID,
success: function(resp) {
$.getJSON("/"+ homeURL +"/"+ itemID, function(saveData) {
itemRev = saveData._rev;
itemAttachment = saveData._attachments;
// Resave all information
$.couch.db(homeURL).saveDoc({
"_id": itemID,
"_rev": itemRev,
"filename":itemFilename,
"title":itemTitle,
"author":itemAuthor,
"type":itemType,
"description":itemDescription,
"date":itemDate,
"user":homeUser,
"_attachments":itemAttachment
}, {
success: function() {
alert(libLang.saved); // Get text for language
window.location.replace("index.html");
}
});
});
}
});
});
}
});
};
} else {
// Delete the item from the library
$.couch.db(homeURL).removeDoc({'_id': itemID, "_rev": itemRev});
window.location.replace("index.html");
}
};

Categories

Resources