How to make infinite-scroll plugin works in a DIV? - javascript

There is a fixed-height div, which has scrollbar. When its only-child element ol being scrolled to the bottom, the ol needs to load more new li.
I'm using jQuery infinite-scroll plugin.
I can't get the plugin to work in the aforementioned situation on desktop browsers.
In iOS, it sorta works, and is buggy. When I scroll the ol to the bottom, it doesn't load. And then when I try to scroll the ol more (it actually can't be scrolled more), it successfully loads.
Here is a simple demonstration of my code.
Here is the demonstration code.

Taken from the infinite-scroll documentation:
To scroll inside an element having overflow, use the local behavior.
So rather than having a #container element that has the overflow, just use the infinite scroll on the list:
$('#container').infinitescroll({
behavior: 'local',
binder: $('#container'),
bufferPx: 0,
navSelector : '#nav', // selector for the paged navigation
nextSelector : '#nav a', // selector for the NEXT link (to page 2)
itemSelector : 'li' // selector for all items you'll retrieve
});
Having the ol as the #container:
<ol id="container">
Here's a working example and there's the relevant documentation.
EDIT
It seems that to use the local behaviour, you need to override a method responsible for determining if the scroll is near the bottom (although this doesn't seem to appear anywhere in the documentation). There is a file in the repository /behaviors/local.js that would need to be included to make this work, but I tried it and is doesn't seem to work properly. So instead you can use this code to take care of the those computations:
jQuery.extend(jQuery.infinitescroll.prototype, {
_nearbottom_local: function infscr_nearbottom_local()
{
var opts = this.options;
var binder = $(opts.binder);
return (binder.scrollTop() + binder.innerHeight() >= binder[0].scrollHeight - opts.bufferPx);
}
});

Related

Slidedown() not working with display:none

I have the following code for sliding down my submenus,
$('#nav-menu > ul#nav > li').hover(function(){
var $this = $(this);
$this.siblings('li').find('.subnav-hover').stop().slideUp(200 , function(){
$this.children('.subnav-hover').stop().slideDown();
});
}, function(){
$(this).children('.subnav-hover').stop().slideUp();
});
I use the above code for multiple sites and it works absolutely fine, but on the following site --> link here, it does't quite work smoothly.
If you hover over the tab "Deficiency" , multiple times , you will see that the 2nd or 3rd time the submenu ul does't come into full view , because the height is not calculated correctly. In earlier sites i noticed slideDown() had issues with the property transition or when a fixed height was given, but in this case i am unable to locate the problem , and i am not sure why my slidedown() is not working.

Simplebar scrollbar plugin - Scroll to top / reset position in function

I need to be able to scroll back to the top of a page within my ui-routed angular one-page site when a function is triggered, but I've used the simplebar scrollbar plugin as a custom scroller, so can't use the window scrolltop method to take the user back to the top of the page.
I can't use any window/document scrolling method as the container that utilises simplebar is a fixed 100vh container, therefore the window is always scrolled to the top.
I've tried using the jquery method below to reset the position of the scrollbar back to the top, but can't get it working, and there are no error messages in the console.
angular.element('#mainContent').simplebar('getScrollElement').scrollTop(0);
I've also tried this in plain js, which returns 'is not a function' in the console:
var mainContent = new SimpleBar(document.getElementById('mainContent'));
mainContent.SimpleBar.getScrollElement().scrollTop = 0;
It seems that the new SimpleBar(xxx) approach does not work with data-simplebar html attribute.
I don't want to initialize the SimpleBar programmatically so I used this in stead:
$('#mainContent .simplebar-content-wrapper').scrollTop(some_value)
The actual scrollable element would have simplebar-content-wrapper class, and it would be inside the element that you've added SimpleBar for.
The class simplebar-content-wrapper was mentioned in its documentation and can be expected to be consistent across versions.
There would be problem if you have cascaded SimpleBars. Solutions:
$('#mainContent .simplebar-content-wrapper')[0].scrollTop = some_value: This would only scroll the correct SimpleBar because the elements returned by nowaday JQuery is in document order.
$('#mainContent>>>>.simplebar-content-wrapper').scrollTop(some_value): The hierarchy of SimpleBar components is not guaranteed to be unchanged in future versions and this may fail in the future.
I have found the solution. You can access scroll element:
const el = new SimpleBar(document.getElementById('layout'));
el.scrollContentEl.scrollTop = 0;
You can try .animate for this:
$("body").animate({ scrollTop: 0 }, "slow");
var el = new SimpleBar(document.getElementById('myElement'));
el.getScrollElement().scrollTop = 0;

show/hide() changing block level element's width/behaviour?

I'm really stuck with this one and have no idea how to solve this, I use jQuery ~ usually without too many problems. But as I don't write JS I do get stuck :(
I've searched and searched for answers and tried out too many approaches and not getting anywhere... :( I bet I'm missing something very obvious or simple, hoping someone might be able to help...
ok - the problem:
I have a website for my webdesign course which shows the main nav in the left column. For the smallest screens (ie below 420px width) - I want to hide the menu, displaying a 'view menu' link instead which uses the jQuery toggle() function to show / hide the menu on demand.
Initially, I did this via a straight forward toggle alone - all fine - apart from the issue that the menu would remain hidden once it was shown and hidden once on a small screen. If the window is resized - it would remain hidden.
That was the problem I set out to solve, mentioning it here as I might be going down the wrong path entirely here ~ doubting whether I'm doing this in the right way :'(
Now - I am using JS to hide the 'view menu' link for all screens, only showing on screens smaller than 420px. I've added the resize() function as well to allow more dynamic behaviour.
Everything is working as intended for the showing and hiding of my menu - BUT....
The toggle link itself is set to display:block - when the window loads below 420px, it displays as intended: set to block (spanning full width for a nicely solid active link) with the text centred.
However, when I load the page at larger window size, then resize to below 420px width - the toggle link seems to become inline? Not at full width any longer, text appears to be left aligned as the element no longer is full width...?!
I've tried setting width in CSS, tried resetting with via resize() element, via assigning 100% width via JS....nothing is working - I'm sure I'm missing something....
I'd really appreciate any pointers or thoughts ~ feel like I'm missing something very basic here....
the website: webeyedea.info
here's my JS code, following the link to jQuery:
// check for window size size on page load and show relevant content only
$(function() {
if ($(window).width() > 420) {
$('#toggle-nav').hide();
$('nav ul').show();
}
else {
$('#toggle-nav').show();
$('nav ul').hide();
}
});
// check for window resize - show nav again for larger screens after hiding
$(window).resize(function() {
if ($(window).width() > 420) {
$('#toggle-nav').hide();
$('nav ul').show();
}
else {
$('#toggle-nav').show();
$('nav ul').hide();
}
});
// show menu (smallest screens)
$('nav #toggle-nav').click(function() {
$('nav ul').slideToggle('slow', function() {
// Animation complete.
});
$('ul').addClass('view');
});
UPDATE: SEE JSFIDDLE
When you call .show() on an element it sets the display property to the previous value and if it does not exist I believe it takes the default browser value which may be inline in your case. Try setting it explicitly to block.
I'm not sure what is doing what here since I don't have a mobile to test it, but could you try to replace your hide/show with a css function that toggle between display:none and display:block ?
Like this :
$('#toggle-nav').css('display','none');
$('#toggle-nav').css('display','block');
ALMOST ! NOT SOLVED
one solution, thanks to Vlad Radulescu (on Forrst) ~ via this jsfiddle fork
$('a#toggle-nav').css('display','none');
// Show the menu if Window width is less than 420
$(window).resize(function() {
if ( $(window).width() > 420 ) {
$('#toggle-nav').css('display','none');
$('nav ul').show();
}
else {
$('#toggle-nav').css('display','block');
$('nav ul').hide();
}
});
// Slide the Menu on smaller screens
$('nav #toggle-nav').click(function() {
$('nav ul').slideToggle('slow');
});
See my revised fiddle
http://jsfiddle.net/HWmp3/9/
I tested this on the iphone simulator and it works. My test was I copied the codes to a local file and tested. I put all the js inside of document.ready
make sure you have the meta in the header
<meta name = "viewport" content = "width=device-width, initial-scale=1.0">

Scroll to an html element with a particular id in javascript or jquery

I have html elements with id's assigned. Now I want to scroll to those elements. I see jQuery has a scrollTop which takes an integer value.. How do I easily just make a particular html element with an id scroll to the top? Ideally, with nice and smooth animation.
A quick search showed many scrolling plugins... if a plugin is needed for the above functionality, what's the most popular one? I'm also using jquery-ui.
You could use something like this to scroll to #someElement when the page loads:
$(document).ready(function() {
$("html, body").animate({scrollTop: $("#someElement").offset().top}, 1000);
});
It simply animates the scrollTop property of the body element, and uses the top offset of some specific element as the position to scroll to. The animation lasts for 1000ms.
Note: it selects both html and body so it works across browsers. I'm not sure on the specifics, but some quick tests show that Chrome uses body, but Firefox and IE use html.
Here's a working example.
Consider the following snippet:
$('#myDiv').bind('click',function(){
var pos = $(this).offset().top,
scrollSpeed = 2;
for (var i = pos; i > 0; i=i-scrollSpeed) {
$(window).scrollTop(i);
}
});
It scrolling was binded to #myDiv element on click just for example. Code determines a position of #myDiv element, than calculates number of scroll steps (speed/smoothness). Than does jQuery .scrollTop() thing.

jCarousel with unknown content width

I am trying to use jCarousel plugin for jQuery in order to provide my website users with scrollable (horizontal) content.
The content I am mentioning is basically user defined <li> elements, styled so that they have a feel and look of a tab. so basically I am trying to achieve the same effect of the tabs in pageflakes.com. As you may imagine, the users are creating tabs and providing tab names by themselves..
jCarousel needs you to specify a fixed width for the content e.g., all their examples are based upon images that have fixed height and width. but in my case I have not control over what the user will name his/her tab...making it impossible for me to guess the width of the total container div.
I have tried using a silly method such as guessing the width programatically assuming each letter being approx 5 pixels and multiplying 5 with the length of the word they have given as a name for a tab. even in this case, i needed to manipulate the css file dynamically which I am not sure how to do and even if it is feasable to do so..
Any solutions appreciated...
<lu>
<li class='MyTab' id='578'>This is my tab</li>
<li class='MyTab' id='579'>of which I can</li>
<li class='MyTab' id='580'>never guess</li>
<li class='MyTab' id='581'><img src='img/bullet_key.png' /> The length of</li>
</lu>
The above html is produced programatically through ajax_tabs_output.aspx, loaded into a javascript array and the jCarousel takes care of the rest..
function outputTabsArray() {
$.ajax({
url: 'ajax_tabs_output.aspx',
type: 'get',
data: 'q=array',
async: false,
success: function(out)
{
tabs_array = out;
}
});
}// end outputTabsArray
function mycarousel_itemLoadCallback(carousel, state)
{
for (var i = carousel.first; i <= carousel.last; i++) {
if (carousel.has(i)) {
continue;
}
if (i > tabs_array.length) {
break;
}
carousel.add(i, mycarousel_getItemHTML(tabs_array[i-1]));
}
};
/**
* Item html creation helper.
*/
function mycarousel_getItemHTML(item)
{
return '<div class="MyTab" id="' + item.tab_id + "'>" + item.tab_name + '</div>';
};
$('#mycarousel').jcarousel({
size: tabs_array.length,
itemLoadCallback: {onBeforeAnimation: mycarousel_itemLoadCallback}
});
The closest thing to what you want is probably jscrollhorizontalpane. I've never used it so I can't vouch for it's effectiveness as a solution to this specific problem.
This sort of widget shouldn't be to hard to make if you want to attempt it. I'll break down the approximate method I would use:
Make sure to use plenty of wrappers.
<div class="scrollable">
<div class="window">
<div class="space">
<ul class="tabs">
<li class="tab">...</li>
<li class="tab">...</li>
<li class="tab">...</li>
</ul>
</div>
</div>
←
→
</div>
What we'll be doing is shifting the "space" element back and forth inside "window" element. This can be done by setting position:relative to "window" and position:absolute to "space" and then shift it about using left:-??px, but I'll use the scrollLeft property.
Add some CSS.
.window {
overflow : hidden;
width : 100%;
}
.space {
width : 999em; /* lots of space for tabs */
overflow : hidden; /* clear floats */
}
.tabs {
float : left; /* shrink so we can determine tabs width */
}
.tab {
float : left; /* line tabs up */
}
This is just the basic stuff that the technique needs. Some of this stuff could be applied by jQuery,
Add events to window resize.
$(window)
.resize(function () {
var sz = $('.window');
var ul = sz.find('ul');
if ( sz.width() < ul.width() ) {
$('.scrollable a.left, .scrollable a.right').show();
}
else {
$('.scrollable a.left, .scrollable a.right').hide();
}
})
.trigger('resize');
Add events to scroll buttons.
$('.scrollable a.left').hover(
function (e) {
var sz = $('.window');
sz.animate({ scrollLeft : 0 }, 1000, 'linear');
},
function (e) {
$('.window').stop();
});
$('.scrollable a.right').hover(
function (e) {
var sz = $('.window');
var margin = sz.find('ul').width() - sz.width();
sz.animate({ scrollLeft : margin }, 1000, 'linear');
},
function (e) {
$('.window').stop();
});
Done!
The widths could also be calculated by looping through the "tab" elements and summing upp outerWidth. This is unnecessary if you have full control but might be a better choice for a full standalone plugin.
From what I can tell, you're trying make JCarousel do something it was never designed to do. Based on what I read on the JCarousel website it appears to be an image rotator.
What it sounds like you want is a tabbed interface. See JQuery UI Tabs for a demo and documentation on how to implement it.
If I'm totally wrong and all you're looking for is a tutorial on how to do proper CSS tabs, have a look at:
http://unraveled.com/projects/css_tabs/
Soviut,
You are actually quite right! I am trying to make JCarousel do something it wasn't designed for.
However, I also wouldn't like to use a tab plugin or any similar stuf as I NEED FULL CONTROL over my output. Such as injecting more elements into the tabs when needed such as double clicking, loading and many other etc. etc.
Actually what I am looking for a way to scroll horizontally the content within a div with arrows on the left and right.. To be more precise, I need the exact same structure of the tabs seen in www.pageflakes.com
The user will be able to create tabs by clicking on a link (or any other element for that matter), they will be able to inline edit its name, whenever they have more tabs then the length of the div, the buttons will be visible allowing them to slide inside the div, I will have events bound to their load, click and double click events.
To summarize I have everything ready and working except for the sliding/scrolling part. Its only I have to get help from you guys regarding how to achieve this functionality..
Kind regards,
What you're looking for isn't tabs, but draggable panels. One example can be found here, called JQuery Portlets. The related blog entry about Portlets can be found here.
You may also want to look into JQuery UI's Draggable, Droppable, and Sortable plugins.

Categories