Fetching more shots using Jribbble - javascript

So, a question that I've been asking myself is how one should load more shots using the jRibbble plugin. Sadly, I couldn't find anything on this subject that makes sense to me. I've only been using JavaScript for about a week now, so I apologize if this appears clumsy. My code so far is as follows:
$(document).ready(function () {
// this is jRibbble example code if I recall correctly
$.jribbble.getShotsByPlayerId('name', function (playerShots) {
var html = [];
$.each(playerShots.shots, function (i, shot) {
html.push('<li><a href="' + shot.url + '">');
html.push('<img src="' + shot.image_url + '" alt="' + shot.title + '"></a></li>');
});
$('#grid').html(html.join(''));
}, {page: 1, per_page: 6});
$(window).on('load resize', function () {
window.shotHeight = $('#grid li').outerHeight(true);
});
});
$(window).scroll(function () {
if ($(window).scrollTop() + shotHeight > $(document).height() - $(window).height()) {
// so that there's a time buffer between the time of request and when the user reaches the bottom of the page (and thus expects new posts)
}
});
I don't think that it's necessary to mention how thankful I'd be if someone could at least provide some pointers.
Note: as I've already received a downvote I'd like to explain that I'd like to get some pointers, and not that I'm too lazy to code myself.

So, I've found the answer to my question. All I've to do is rerun the getShotsByPlayer, increasing the 'per_page' every time I do so. Then, just merge the two arrays. I should've known this.

Related

Function with attr() function not executing all statements when there are multiple elements on screen created dynamically by a function

The function below creates a red dot on the right end of the screen, animate() to move it left and when clicked, its src file should be changed, along with a few other things as you can see below:
function spawnEnemy()
{
$("body").prepend("<img src='red_dot.png' class='enemies' id='enemy' style='left:calc(" + thewidth/2 + "px)'/>");
$("#enemy").attr("id", "enemy"+i);
$("#enemy"+i).css({"left" : thewidth+'px', "top" : (randomInt(10,500))+'px'});
$("#enemy"+i).animate({left :'-400px'}, 20000);
$("#enemy"+i).click(function()
{
var snd = new Audio("laser.mp3");
snd.play(); //function stops here
$("#enemy"+i).stop();
$("#enemy"+i).attr("src","explosion.gif");
$("#enemy"+i).css({"transform" : "scale(0.11,0.11)"});
setTimeout(function()
{
$('#enemy'+i).hide();
}, 350);
});
i+=1;
}
This function is executed every six seconds. If, however, the element is not clicked before a new element is created, then all of the elements when clicked stop executing at the line where I have placed a comment. I checked the console, and I couldn't find anything of value, although I know that the problem isn't with the ids as they all have different ids in the console, and since I can hear the sound from snd.play() and none of the effects of the statements after snd.play() are seen, I'm sure the problem lies there. This problem is only when multiple elements are created, as they all execute fine if I click the element before six seconds, i.e, before the function is executed again. Also, thewidth is just a pre-defined global var, so it's not related.
I'm very new to jquery, so I apologize if there's something obvious I'm missing.
Edit: Okay, now all the statements aren't executing even if there is only one element on the screen. I'm quite lost.
Ok, I think I see what's happening. You need to reference enemy with $(this) inside the callback, because i is in the encapsulating scope, which means it can change and break the internal scope of that callback:
While at it, I cleaned up your jQuery code a little to simplify it.
function spawnEnemy() {
$('<img />', {
id: 'enemy' + i,
src: 'red_dot.png',
className: 'enemies',
style: 'left: ' + thewidth / 2 + 'px; top: ' + randomInt(10,500) + 'px'
})
.prependTo($('body'));
.animate({left :'-400px'}, 20000);
.click(function() {
var snd = new Audio("laser.mp3");
snd.play(); //function stops here
$(this).stop();
$(this).attr("src","explosion.gif");
$(this).css({"transform" : "scale(0.11,0.11)"});
setTimeout(function() {
$(this).hide();
}.bind(this), 350);
});
i+=1;
}

angularjs position div pixel perfectly despite browser resize or device/orientation, on page load not working

I am new to AngularJS, and since I have been pursuing a solution to the problem for several days (perhaps a week), it indicates to me that I am not using it correctly.
The problem: the need to position 30 divs in the following way:
1) each of which displays a number indicating one of the 30 days of a month, in sequential, increasing order from '01' to '30' (so a strict integer won't work for display)
2) positioning on the right side of the viewport, at all times, with any device/orientation (limited to screen height > 525 px and phones in portrait orientation
3) and in such a way that the maincontroller 'knows' the exact pixel distance from the top after page load and every resize
4) such that each div is uniquely identified with an index number corresponding to a 0-based array numbering scheme
And now for some serious convolution:
1) I am loading a json file of this format using $http
[
{
"dayDisplay" : "01", "isPayDay" : false, "positionX" : "0"
},
{
"dayDisplay" : "02", "isPayDay" : false, "positionX" : "0"
},
{
"dayDisplay" : "03", "isPayDay" : false, "positionX" : "0"
},
{
"dayDisplay" : "04", "isPayDay" : false, "positionX" : "0"
},
...
and ng-repeating through it with a 'partial' view:
<div id="days-list-control" ng-controller="DayListController">
<div x-day-index="{{$index}}" day-position-update distribute-days-vertically class="day-div" ng-repeat="item in allDayData">
<span ng-class="{'pay-day':(item.isPayDay === true), 'pay-day-hidden':(item.isPayDay === false || $index === state._currentDayIndex)}">$</span>
<span ng-class="{'hide-day':($index === state._currentDayIndex), 'day':($index > state._currentDayIndex), 'past-day':($index < state._currentDayIndex)}">{{item.dayDisplay}}</span>
</div>
</div>
And using these 2 directives to massage the DOM and position these divs the way I want to:
layoutManagerDirectives.directive('dayPositionUpdate', ['$window', '$parse', function($window, $parse) {
return {
priority: 1,
link : function(scope, element, attrs) {
angular.element($window).bind('load', function() {
var position = $parse(element[0].attributes['x-daydivtop'].nodeValue)(scope);
var elementId = $parse(element[0].attributes['x-day-index'].nodeValue)(scope);
scope.$apply("updateDayPositions('" + position + "','" + elementId + "')");
});
angular.element($window).bind('resize', function() {
var position = $parse(element[0].attributes['x-daydivtop'].nodeValue)(scope);
var elementId = $parse(element[0].attributes['x-day-index'].nodeValue)(scope);
scope.$apply("updateDayPositions('" + position + "','" + elementId + "')");
});
}
};
}]);
layoutManagerDirectives.directive('distributeDaysVertically', ['$window', function($window) {
return {
priority: 0,
link : function(scope, element, attr) {
angular.element($window).bind('resize', function(e) {
var containerElement = angular.element(document.getElementById('days-list-container'));
var dayDivTop = element[0].offsetTop;
if ($window.innerHeight < 645) {
element.css('line-height', ($window.innerHeight)/42 + 'px');
element.attr('x-dayDivTop', dayDivTop );
} else {
element.css('line-height', ($window.innerHeight)/42 + 'px');
element.attr('x-dayDivTop', dayDivTop );
}
});
angular.element(window).bind('load', function() {
var containerElement = angular.element(document.getElementById('days-list-container'));
var dayDivTop = element[0].offsetTop;
if ($window.innerHeight < 645) {
element.css('line-height', ($window.innerHeight)/42 + 'px');
element.attr('x-dayDivTop', dayDivTop );
} else {
element.css('line-height', ($window.innerHeight)/42 + 'px');
element.attr('x-dayDivTop', dayDivTop );
}
});
}
}
}]);
and the function in MainController invoked in the directive above is:
$scope.updateDayPositions = function(p, id) {
$scope.allDayData[id].positionX = p;
}
which simply updates the json-inspired object ("allDayData" which lives in the MainController) with the positioning info from the DOM attributes of all the divs ng-repeated thru (see the partial view: "ng-repeat='item in allDayData'"). This is so I can position yet another graphic element very precisely over each of the day numbers, programmatically, based on user input.
This works perfectly after I re-size the browser window. On load, I believe that the DOM elements aren't on screen and in a knowable position, since the allDayData object is not updated from its original positionX values of '0'. I am getting sporadic and odd behaviors after refreshing the page but most commonly, I see that the positionX data is not updated until I resize the browser window, after which point it works quite well. I have tried the following ways to invoke the directive:
1)
angular.element(window).bind('load', function() {
...
});
2)
angular.element(document).ready(function() {
...
});
3)
$timeout
4)
putting the code into a controller which in theory executes when loaded
Phew. I may have left something out, but hopefully there's enough here to say generally which direction I should go in if indeed a different one is optimal. Apologies for the astonishingly long question, and thanks in advance for any guidance.
First, there's a lot of weird things going on here. You should definitely never try to use document.getElementById... ever, but especially not in an angular directive. You should also shy away from using things like $window and document unless it's really that necessary. I think that resizing is probably a good enough case.
Please read this:
"Thinking in AngularJS" if I have a jQuery background?
Hopefully that helps shift your paradigm a little bit. Now onto the root of your problem. The load event is only triggered when you load things like an iframe or image, so you don't need to listen to that event. As a matter of fact, you can assume the DOM is ready by the time the link function is called in the directive, because angular is cool like that (it has already compiled the html). So, to keep things DRY you need to move your resize functions into their own variable, bind them to the resize event, and call it once from the link function like so
// Inside directive
var myResizeFunction = function(e) {
// Handle window resize
};
element.resize(myResizeFunction);
myResizeFunction();
On a side note, a lot of what you're doing looks at a glance like it might be better solved by CSS. There's a lot of cool stuff you can do with responsive designs these days. Maybe you should consider that as an option?

How to implement autoscroll to follow my div

I've looked at several tutorials online and a few similar questions on SO but not been able to work out how to make the screen autoscroll left and right so that my #sheep stays in the centre of the screen.
I'm using javascript and jquery to move a simple div across the screen.
Here's my jsfiddle
http://jsfiddle.net/JosephByrne/CkkVr/
What's the best method of making the screen follow my div?
I think you're trying to move the wrong element left/right. I think you need to leave your sheep in the middle of the screen then move the background.
Something like:
var walkLeft = function() {
$('#background').animate({left:"-=10px",top:"-=2px"}, 100);
$('#background').animate({left:"-=10px",top:"+=2px"}, 100);
};
var walkRight = function() {
$('#background').animate({left:"+=10px",top:"-=2px"}, 100);
$('#background').animate({left:"+=10px",top:"+=2px"}, 100);
};
http://jsfiddle.net/CkkVr/22/ (you'll need to "jump right" to see the sheep), but you get the general idea!
You need something similar to this:
function scrollContainer() {
var $sheep = $("#sheep");
$("body").scrollLeft($sheep.position().left + $sheep.width());
}
That utilizes jQuery's scrollLeft() function as well as the position() function (on the sheep).
You just need to keep messing with the math until it works out properly...
I've implemented it on the "jump" functions here:
http://jsfiddle.net/Dxe8a/11/
function scrollContainer() {
var $sheep = $("#sheep");
var $body = $("body");
var windowWidthOver2 = ($(window).width()/2);
var pos = $sheep.position().left + windowWidthOver2 - $sheep.width() - 80;
if($body.width() <= (pos + windowWidthOver2 - $sheep.width() - 80)) {
$body.width($body.width() + windowWidthOver2);
}
$body.scrollLeft(pos);
}
You should alter it so that it looks a bit better, but at least it follows your sheep somewhat.
P.S. it works better in fiddle if you view it in "/show": http://jsfiddle.net/Dxe8a/11/show

ajax infinite scroll - having trouble with post

I'm trying to get infinite scroll to work, and so far I have this:
$(window).scroll(function () {
var load = 0;
if ($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
load++;
$('#posts').append(load);
$.post("includes/ajax.php", {
load: load
}, function (data) {
$('#posts').append(data);
});
}
});
And here is the contents of ajax.php
$load = htmlentities(strip_tags($_POST['load'])) * 2;
echo $load;
I have two problems that I don't really understand. 1. When I append load to #posts directly as a test, it works fine, but it keeps saying 1, 1, 1, instead of adding to itself. 2. When I try to do it using the post ajax to my php file, nothing happens. I followed a video tutorial exactly, but it's not working for me.
put the var= 0 outside of the function

PushState() PopState() integration

I have a website that serves content like so, using .js:
var FluidNav = {
init: function() {
$("a[href*=#]").click(function(e) {
e.preventDefault();
if($(this).attr("href").split("#")[1]) {
FluidNav.goTo($(this).attr("href").split("#")[1]);
}
});
this.goTo("home");
},
goTo: function(page) {
var next_page = $("#"+page);
var nav_item = $('nav ul li a[href=#'+page+']');
$("nav ul li").removeClass("current");
nav_item.parent().addClass("current");
FluidNav.resizePage((next_page.height() + 40), true, function() {
$(".page").removeClass("current"); next_page.addClass("current");
});
$(".page").fadeOut(500);
next_page.fadeIn(500);
FluidNav.centerArrow(nav_item);
},
centerArrow: function(nav_item, animate) {
var left_margin = (nav_item.parent().position().left + nav_item.parent().width()) + 24 - (nav_item.parent().width() / 2);
if(animate != false) {
$("nav .arrow").animate({
left: left_margin - 8
}, 500, function() { $(this).show(); });
} else {
$("nav .arrow").css({ left: left_margin - 8 });
}
},
resizePage: function(size, animate, callback) {
if(size) { var new_size = size; } else { var new_size = $(".page.current").height() + 40; }
if(!callback) { callback = function(){}; }
if(animate) {
$("#pages").animate({ height: new_size }, 400, function() { callback.call(); });
} else {
$("#pages").css({ height: new_size });
}
}};
So far so good, but the client wants a browser back button functionality integrated. I did my homework and with the help of SO and other sources found out that the pushState and popState are the best way to achieve this.
If you take a second to read the code above, you will find out the following:
If you type website.com/#team in your browser, you are going to get the front page, not the #team page. If you want to navigate to #team, you are going to have to click from there.
If you navigate to #team and then want to go back to the front page, and you press the back button, you are going to get redirected to where you were before vising the website. Kicked out so to speak.
This is done with the purpose of a smoother browsing experience.
However, I now need to achieve the following, and I am a bit lost as to what changes I am going to have to make to my .js file above:
Achieve a working back-button functionality (manipulate the
browser's history storage)
When I type website.com/#team in the
URL bar, to go to that page and not the front page.
Here is an example website built with this functionality so you can see how it functions. http://themes.two2twelve.com/site/fluidapp/light/
You might try integrating a library that handles browsers incapable of pushState (fallback to hash urls like you're describing. I've had some luck with History.js in the past. (Get it??)
NOTE: This answer was provided by the asker as an edit to the question, rather than as an answer. I have moved it here to conform to site standards.
I did the following:
Download and unzip History.js to my server as instructed here: https://github.com/browserstate/history.js/
Follow the install here: https://github.com/browserstate/ajaxify
Installed the StateRouter from here Can't understand History.js, need it simplified? and here https://github.com/aknuds1/staterouter.js/tree/master/lib
So far what has been achieved:
Now the URLs actually change with the back button, meaning:
I go to Home -> Users -> Staff and then using the Back button the URL in the URL bar will change like so: www.123.com/#staff -> www.123.com/#users -> www.123.com/#home . However, only the URl changes and not the content. Any ideas what I am missing?

Categories

Resources