I've been attempting to make an infinite (well semi-infinite) scroll that feeds itself from hard-coded divs (because I don't know any back-end languages yet). My research has turned up a ton of great jQuery for infinite scrolls, but they are all meant to be used with a database, not hard-coded content.
What I'm trying to achieve, ultimately, is an infinite scroll that starts by loading X div into the DOM, and as the user reaches the bottom of the page, loads X more divs, and repeats until no more divs are left to load.
Do any of you know of some good or relevant scripts or any fiddles that may help me? Part of my issue is that I'm still in that learning curve of JS; I often understand what's going on when I look at a script but I still have a hard time writing my own from scratch.
Any help or direction is appreciated. Thanks in advance!!
Based on the code here: Alert using Jquery when Scroll to end of Page
Create a new <div> element when you reach the bottom of the page
$(window).scroll(function() {
if (document.documentElement.clientHeight + $(document).scrollTop() >= document.body.offsetHeight)
{
$('body').append('<div></div>');
}
});
Your HTML needs to be stored somewhere and if you have enough of it to think about infinite scrolling you probably don’t want to load it all with the initial request, so let’s say each “post” is stored in an individual HTML file on your server: /posts/1.html. And you want to append those to a div in your main document: <div id="posts"></div>.
You need a method to download a given post and append it to your div:
function loadPost (id) {
$.get('/posts/'+id+'.html').done(function (html) {
$('#posts').append(html);
});
}
Now you need a way to trigger loadPost() when you scroll to the bottom of the page. This example uses jQuery Waypoints to call a handler function when the bottom of the div comes into view:
var currentPost = 1;
$('#posts').waypoint({
offset: 'bottom-in-view',
handler: function () {
loadPost(currentPost++);
}
});
Related
I've created this code to print data from an iFrame
function (data) {
var frame = $("<iframe>", {
name: "iFrame",
class: "printFrame"
});
frame.appendTo("body");
var head = $("<head></head>");
_.each($("head link[rel=stylesheet]"), function (link) {
var csslink = $("<link/>", { rel: "stylesheet", href: $(link).prop("href") })
head.append(csslink);
;});
frame.contents().find("head")
.replaceWith(head);
frame.contents().find("body")
.append(this.html());
window.frames["iFrame"].focus();
window.frames["iFrame"].print();
}
This creates an iFrame, adds a head to where it sets all the css links that are needed for this website. Then it creates the body.
Trouble is, the styling won't get applied to the print, unless I break at line frame.contents().find("head").replaceWith(head), which means that something in that part is running asynchronously.
Question is, can I somehow get the code to wait for a short while before running that line, or is there perhaps another way to do this? Unfortunately I'm not all that familiar with iFrames, so I have no clue what it's trying to do there.
This turned out to be a real hassle. I've always been reluctant to using iframes, but since there are many resources saying that using an iframe for printing more stuff than what's on the screen, we figured we'd give it a try.
This was instead solved by putting the data inside a hidden div which then was shown before a window.print(). At the same time, all other elements on the page were given a "hidden-print" class which is a class we're already using to hide elements for prints.
This might not be as elegant for the user (The div will show briefly before the user exits the print dialogue), but it's a way more simpler code to use and manage.
I think you could / should move the last focus() and print() calls to a onload handler for the iframe, to get it to happen after styles are loaded and applied.
I've just run into the same issue and did the following:
setTimeout(() => {
window.frames["iFrame"].focus();
window.frames["iFrame"].print();
}, 500)
This appears to have sorted it for me. I hate using timeout and the length is guess work at best but as it's not system critical it's something I can run with for now.
I have a photo gallery powered by Isotope.Images are requested from external resource on page load and every time a user scrolls to the bottom of the page. New images are to be appended to the current isotope layout. The problem is with Isotope - it doesn't seem to execute the 'appended' method.
Searching for a solution on StackExchange and Google revealed I am not the only one having this problem. I have been tinkering with this for past couple of days and tried almost every solution I could find but so far I have not found anything that could fix my problem.
CodePen: I have created a CodePen here - http://codepen.io/Writech/pen/pBoEt
WebPage: As the custom event 'resizestop' is not working in codepen the same code is found as a webpage here - http://writech.net.ee/sandbox/
To see the problem open the CodePen or WebPage provided above and scroll to the bottom of the page which initiates loading of additional images. Then you see the new images are just appended to the container by jQuery. But they are not appended to the isotope layout instance as they are supposed to.
The problematic part lays in a custom function named isotopeAppend(). This function is called on page load and then the second part of 'if-else' statement is executed. When initialization is done and first images are added to the container then the next time isotopeAppend() is called (it's when user reaches to the bottom of the page) the first part of 'if-else' statement is executed and this is where the problematic Isotope 'appended' method is called.
A code snippet below from problematic javascript code. The results of the ajax request to external resource are applied to the variable newElems. When adding an alert('something') or console.log inside the 'appended' callback - nothing happens.
Does the problem lay in Isotope itself or does it have anything to do with my coding error?
I would really like to find a solution for this!
var elements = $(newElems).css({ opacity: 1, 'width' : columnWidthVar + 'px' });
$('#photos_section_container').append( elements );
$('#photos_section_container').imagesLoaded(function(){
$('#photos_section_container').isotope( 'appended', elements, function(){
hideLoader(function(){
elements.animate({ opacity: 1 });
});
});
});
In the initialization change
itemSelector : $('.photos_section_wrap'),
to
itemSelector : '.photos_section_wrap',
I forked your pen.
itemSelector is used by isotope to filter elements to layout and $() returns array of objects. In result there no elements to layout. If you are interested you may look at the _getAtoms method (isotope script) in debug to see what's goinig on.
So I'm trying to implement the popular inifnite scroll plugin to replace my current home made infinite scroll script:
http://www.infinite-scroll.com/
&
https://github.com/paulirish/infinite-scroll
Anyway it seems like this plugin requires there to be html pagination on the page. Namely due to these options:
nextSelector: "div.navigation a:first",
navSelector: "div.navigation",
I don't have pagination markup on the page. I don't care if my site isn't compatible for crawlers/js disabled users.
So is there a way to implement this plugin without a physical html pagination?
In my custom script I was doing something like:
var $page = 1;
// Load content for $page
$page++;
Anything like this, i.e. I can pass in the starting page as an integer?
Take a look at this, very simplified version of infinite scroll, that doesn't require any pagination elements.
http://www.innovativephp.com/demo/infinitescroll/
You can create it easily with jQuery/javascript.
It's a bit hard to write a universal for anything now, but the main principle is this:
If you're loading latest content (newest first, older scrolled):
Load first set of elements (weather it be blogsposts, images, quotes) that takes a bit more than screen height. Keep the last item's ID in a variable.
use setInterval to detect if user scrolled the page, then load data that has lower ID than your last ID that you saved. Then keep saving last ID's and load new content.
Good luck!
Something like this:
function loadnewdata()
{
// do ajax stuff, update data.
}
setInterval(
function (){
if(($(document).height() - $(window).height() - $(document).scrollTop()) < 500){
loadnewdata();
}
},
500
);
You'd write the loadNewData() function for yourself, of course. Depends on your data.
This loads new data each 500 if the user has scrolled the page.
I have div with vertical scroll bar. Div is being updated dynamically via ajax and html is inserted using jQuery's .html method.
After div is updated scroll bar returns to top and I am trying to keep it in the previous position.
This is how I'm trying it:
var scrollPos = $('div#some_id').scrollTop(); //remember scroll pos
$.ajax({...
success: function(data) {
$('div#some_id').html(data.html_content); //insert html content
$('div#some_id').scrollTop(scrollPos); //restore scroll pos
}
});
This fails. My best guess is that it is failing due to inserted html not rendered (ie. no scroll).
For example this works.
setTimeout(function(){
$('div#some_id').scrollTop(scrollPos);
}, 200);
But this is dirty hack in my opinion. I have no way of knowing that some browsers won't take more then these 200ms to render inserted content.
Is there a way to wait for browser to finish rendering inserted html before continuing ?
It's still a hack, and there really is no callback available for when the HTML is actually inserted and ready, but you could check if the elements in html_content is inserted every 200ms to make sure they really are ready etc.
Check the last element in the HTML from the ajax call:
var timer = setInterval(function(){
if ($("#lastElementFromAjaxID").length) {
$('div#some_id').scrollTop(scrollPos);
clearInterval(timer);
}
}, 200);
For a more advanced option you could probably do something like this without the interval, and bind it to DOMnodeInserted, and check if the last element is inserted.
I will just like to point out one difference here: One thing, is when the .html() have completed loading, but the browser actually render the content is something different. If the loaded content is somewhat complex, like tables, divs, css styling, images, etc - the rendering will complete somewhat later than all the dom ellements are present on the page. To check if everything is there, does not mean the rendering is complete. I have been looking for an answer to this by myself, as now I use the setTimeout function.
Such callback does not exists because .html() always works synchronously
If you are waiting for images loading, there's one approach https://github.com/desandro/imagesloaded
I am using some JS code to transform my menu into a drilldown menu.
The problem is before it runs the JS you see a BIG UGLY mess of links. On their site its solved by putting the js at the top. Using recommendations by yahoo/YSlow i am keeping the JS files at the bottom.
I tried hiding the menu with display:none then using jquery to .show(), .css('display', ''), .css('display', 'block') and they all lead up to a messsed up looking menu (i get the title but not the title background color or any links of the menu)
How do i properly hide a div/menu and show it after being rendered?
In the <head> place this:
<script>document.documentElement.className = 'js';</script>
Now, it will .js class to your html element. And it will be the very first thing done by the javascript on the page.
In your CSS you can write:
.js #menu {
display:none;
}
And then:
$(document).ready(function() {
$('#menu').css('display','block').fancyMenu();
});
This is an excellent technique, that allows you to make your pages "progressively enhanced", if your user has JavaScript disabled – she will still be able to see the content, and you can also separate non-JS styling with styling, that is relevant only for JS version of your menu, perhaps "position:absolute" and things like that.
At the top of your page put:
<script type="text/javascript">
document.write('<style type="text/css">');
document.write('#mylinks { display:none; }');
document.write('</style>');
</script>
And at the end of your "processing", call $('#mylinks').show();
document.write is evaluated as the DOM is processed, which means this dynamic style block will be registered in the style rules before the page is first displayed in the viewport.
This is a good case where progressive enhancement works really well - if your users have JS available & enabled, you hide the links until they are ready; but if not, they are still available, albeit ugly.
Life will be gentler with you if you try not to make pages that look like "a big ugly mess" without javascript. Have a heart.
Whatever yahoo says, it would probably be worth it for you to insert a little script that adds a style element with a few rules to the head of ypur document, before the body renders.
I found the solution. I should let the links be hidden with css then .show() BEFORE the ddMenu code executes instead of after. The ddMenu seems to check the parents width and sinces its hidden i guess its 0. The time between .show() and ddMenu is fast enough not to show the ugly links (on my machine/browser). The the majority of the time (page loading, http req for the JS files, JS compiling/exec etc) the links are hidden so it looks pretty good.
$(function () {
$('.menuT1').show(); //do it before not after in this case.
$('.menuT1 > ul').ddMenu({
Well, If you are familiar with jquery then I would do something like this
$("#mybuttom").click(function() {
$("#mydiv").hide(); //hide the div at the start of process
$.post( "mypostpage.php",
{ testvar: testdata },
function(data) {
//callback function after successful post
$('#mydiv').show(); //show it again
}
);
});