When Jquery jScrollPane is reinitialized, it goes back to the top. Why? - javascript

I'm using jquery library jScrollPane to set the custom scroll bar for the whole page.
scroll_bar = $('body>div').jScrollPane(
{
autoReinitialise: true,
showArrows: true,
maintainPosition: false
}).data('jsp');
When new content is added at the bottom of the page (while user is at the bottom of the page), I call:
scroll_bar.getContentPane().find(".content").append(some_content);
scroll_bar.reinitialise();
This reinitializes the scroll bar, but it takes the user to the top of the page. I would like the window to stay at the same spot. Any solutions?

Are you sure you're getting the data needed, I have no idea if this works, but have you tried:
scroll_bar = $('body>div').jScrollPane(
{
autoReinitialise: true,
showArrows: true,
maintainPosition: false
});
scroll_bar.data('jsp');
And would'nt you normally use the .scroll-pane class for this, and not the body>div selector ?
I would think maybe it should be something like this:
var api = scroll_bar.data('jsp');
api.reinitialise();

If you want the scroll bar to retain its position, you should set the
maintainPosition: true
Also, try reconstruct the code like this:
// Use jscrollpane api function to enable reinitialization
var scrollelement = $('body>div').jScrollPane({ maintainPosition: true});
var api = scrollelement.data('jsp');
api.getContentPane().html(result);
// Needed to apply jscrollpane after change new container type
api.reinitialise();
Hope this help :)

From the docs:
maintainPosition [boolean] - Whether you want the contents of the scroll pane to maintain it's position when you re-initialise it - so it doesn't scroll as you add more content (default true)
You set it to false.

For people who have issues re-initializing after the above:
function reinitialiseScrollpane() {
var settings = {
maintainPosition: true,
// add your settings here, below are examples
arrowButtonSpeed: 1,
showArrows: true,
animateScroll: true
};
pane.jScrollPane(settings);
var api = pane.data('jsp');
api.getContentPane().append();
api.reinitialise();
}
The important part is using the settings. Without re-initialising the settings, it can be glitchy. I have put it in a function call, so you simply call this whenever content is altered in any of your scroll panes (assuming you kept the .scroll-pane class with all regions)

Related

Disable Locomotive Scroll for a specific page

I'm building a Woocommerce website and I would like to disable Locomotive Scroll on the Checkout page.
I tried this code, but it doesn't work. How could I disable Locomotive for a specific page? My website is not running with Ajax.
const scroll = new LocomotiveScroll({
el: document.querySelector('[data-scroll-container]'),
smooth: true,
smoothMobile: true,
getSpeed: true,
getDirection: true
});
window.addEventListener("load", function() {
if ($('.woocommerce-checkout').length) {
scroll.stop();
scroll.destroy();
}
});
Thanks!
You could prevent the initialization of Locomotive Scroll by declaring it within a function like this:
let scroll;
function initLocoScroll() {
if (document.querySelector('.woocommerce-checkout')) return;
scroll = new LocomotiveScroll({
el: document.querySelector('[data-scroll-container]'),
smooth: true,
smoothMobile: true,
getSpeed: true,
getDirection: true
});
}
initLocoScroll();
// if you are concerned that JavaScript will be unable to find the element
// because it is loaded before the DOM,
// you could replace the previous line with this one:
// window.addEventListener("load", initLocoScroll);
I don't think the '.length'-property is necessary. The jQuery (or querySelector) statement alone should be enough to determine if the element exists.
Another issue might be that the element you are trying to use to determine whether Locomotive Scroll should be active or not cannot be found. Be sure to check that if the error persists.
I hope this was helpful!

stop tabulator ajax calls from scrolling window to top of page

I have the tabulator plugin set up and working with my data. Currently, using the remote pagination feature but whenever the pagination buttons are clicked it loads the data and then scrolls to the top of the page. The pagination buttons do not contain href="#" so it shouldn't be trying to load a browser state.
The really odd thing is it is doing this behavior on any ajax call I make relative to tabulator. I used the setData function to load updated data and it scrolled to the top of the page again.
Here's a very simplified version of my code:
<div id="#tabulator"></div>
<script>
$("#tabulator").tabulator({
movableColumns: true,
layout: "fitColumns",
pagination: "remote",
paginationSize: 10,
ajaxURL: "rosterusers_tabulator_data-json.cfm",
ajaxParams: {/* url params here */},
columns: [/* columns set here*/]
});
/*then I have a modal dialog update event which calls the following*/
$("#tabulator").tabulator(
"setData",
"rosterusers_tabulator_data-json.cfm",
{/*url params here*/}
);
</script>
I don't think I'm doing anything bizarre here but each time the table data gets updated via ajax in anyway (page change, data change, filter change, etc.) it scrolls to the top of the page.
Here is solution for various scroll to top related issues. It involves extending the tabulator.js with two functions:
Tabulator.prototype.getVerticalScroll = function () {
var rowHolder = this.rowManager.getElement();
var scrollTop = rowHolder.scrollTop;
return scrollTop;
}
Tabulator.prototype.setVerticalScroll = function (top) {
var rowHolder = this.rowManager.getElement();
rowHolder.scrollTop = top;
}
Then get and set like this:
let pos = table.getVerticalScroll();
// do table management e.g. setColumns
table.setVerticalScroll(pos);
The replaceData function can be used to set data in the table without changing the scroll position:
$("#example-table").tabulator("replaceData", "rosterusers_tabulator_data-json.cfm")

How to add msnry.reloadItems() to vanilla JS script

I am very new in js, javascript, ajax, etc., I am using php and build only wordpress sites. Today I trying make to my site the hybrid pagination, what someone call it the "HolyScroll or Holy Scroll", the target this:
http://scrollsample.appspot.com/items
So I working on the infinite-scroll.com with Desandro's Masonry and my code now it looks like this (I did this in the last 5 hours...):
var grid = document.querySelector('.container');
var msnry;
imagesLoaded( grid, function() {
// init Isotope after all images have loaded
msnry = new Masonry( grid, {
itemSelector: '.item'
});
});
// -----------
var elem = document.querySelector('.container');
var infScroll = new InfiniteScroll( elem, {
// options
path: 'page/{{#}}/',
append: '.item',
history: 'push',
historyTitle: true,
prefill: true,
// load pages on init until user can scroll
scrollThreshold: 1000,
// trigger scrollThreshold event when viewport is <100px from bottom of scroll area
status: '.page-load-status',
});
// element argument can be a selector string
// for an individual element
var infScroll = new InfiniteScroll( '.container', {
// options
});
So finally works the infinite scroll, the history, the masonry (only on the first call) and the imagesLoaded, And now need paste to this the reloadItems option, but dont working...
Here is the guide: https://masonry.desandro.com/methods.html#reloaditems
Please, someone could help me? I can not find a simple tutorial to this with Vanilla JS, in turn the JQuery versions not working for me...
*Unfortunately MarkovskI drew my attention not everyone can click on a link, so I copy here, what Desandro write on his site:
"For frameworks like Angular and React, reloadItems may be useful to apply changes to the DOM to Masonry."
// vanilla JS
msnry.reloadItems()
So here is the "Holy Scroll", the hybrid, ajax / js loaded infinite scroll WITH pagination, what search engines loves, so this totally user and SEO friendly:
Source sites:
https://infinite-scroll.com/
https://masonry.desandro.com/
https://imagesloaded.desandro.com/
So, I just now learning php, I am only webdesigner and after I realized, the ALL wordpress plugins what promises you "infinite scroll" (like Ajax Load More, Ajax Pagination & infinite Scroll, DMD Infinite Scroll, Jetpack, YITH Infinite Scroll and etc.) rip-off and KILL YOUR ALL SEO if you using these plugins without LICENSE, I started looking the solution on the net. The first what it comes face to face the Google' Webmaster Central Blog:
https://webmasters.googleblog.com/2014/02/infinite-scroll-search-friendly.html
So after this article I knew what I wanted, but by the time, what I found it the keywords (thus: the browser history about infinite scroll) and the simple fact, that now need building my masonry layout (because up to now I using the Ajax Load More plugin, and this did it the masonry to me), so I never learning JS... I worked on this in the last ~35 hours, but you can instantly learn to do it yourself, as you read it all along. (The long introductory serving the keywords, to find you here too.)
So, you can modify your infinite scroll options off this official guide:
https://infinite-scroll.com/options.html
The VERY IMPORTANT THING, WHAT NEED FOR YOU, IS THIS:
https://infinite-scroll.com/options.html#history
So, put these links (or follow these steps: https://infinite-scroll.com/#install) to your footer (Or header, but Google recommend that call .js and .css files in footer, thus reduce it you pageload.):
<script src="https://unpkg.com/infinite-scroll#3/dist/infinite-scroll.pkgd.min.js"></script>
<script src="https://unpkg.com/masonry-layout#4/dist/masonry.pkgd.min.js"></script>
<script src="https://unpkg.com/imagesloaded#4/imagesloaded.pkgd.min.js"></script>
And here is so the full "Holy Scroll" code with masonry layout what using images Loaded (imagesLoaded), so never more overlapping your images.
Just Put This code to your footer between: <script></script>
var grid = document.querySelector('.container');
var msnry = new Masonry( grid, {
itemSelector: '.youritem', // select none at first
});
// initial items reveal
imagesLoaded( grid, function() {
msnry.options.itemSelector = '.youritem';
var items = grid.querySelectorAll('.youritem');
msnry.reloadItems( items ); // This reload the masonry layout after the first call
msnry.layout(); // This restrain the overlapping on the first call
});
//-------------------------------------//
// init Infinte Scroll
var infScroll = new InfiniteScroll( grid, {
// options
path: 'page/{{#}}/', // YOUR PAGINATION STRUCTURE !!!IMPORTANT!!! REPLACE IT
append: '.youritem',
history: 'push',
historyTitle: true,
prefill: true,
// load pages on init until user can scroll
scrollThreshold: 1000,
// trigger scrollThreshold event when viewport is <100px from bottom of scroll area
// (I using 1000, that my users never have to wait for the loading of the next page...
// The calling it will start to working, before the screen shows the bottom of the page...)
status: '.page-load-status',
outlayer: msnry,
});
Okay, so replace it the .container to YOUR site container what includes the items (items = posts, images, anything) and replace it the .youritem to your grid item (so the div what include ONE item)!
Very important, that you replace the value of the path: to your pagination structure, where the current page's number is {{#}}! (So if your site works thus: yourdomain.com/page/2/ your path value is: 'page/{{#}}/')
Finally you make your design with .css (Included the masonry parameters (width, etc.)!)

jQuery: infinite scroll and the back button

OK so I know this causes problems with everyone, and it's causing problems with me too. I'm using the infinite scroll plugin on a client's site, in combination with the isotope plugin to load in their products sequentially, the problem is though as they have 1000's of products, anyone browsing the site then clicking into a product, when they click the back button they'll be returned back to the top (or just above the fold of page one), which is causing quite a lot of issues.
My markup is as follows below:
$(window).load(function () {
var $container = $('.products-grid-wrap');
$container.imagesLoaded(function () {
$container.isotope({
itemSelector: '.products-grid-block',
filter: '*:not(.hidden), .products-grid-block',
animationEngine: 'best-available',
layoutMode: "perfectMasonry",
perfectMasonry: {
columnWidth: 280,
rowHeight: 310
}
});
$container.infinitescroll({
navSelector: '#page_nav', // selector for the paged navigation
nextSelector: '#page_nav a', // selector for the NEXT link (to page 2)
itemSelector: '.regular-product-block, .products-grid-block', // selector for all items you'll retrieve
pixelsFromNavToBottom: Math.round($(window).height() * 1.5),
bufferPx: Math.round($(window).height() * 1.5),
loading: {
finishedMsg: 'No more products to load.',
img: 'http://www.by-form.net/wp-content/uploads/2014/11/ajax-loader-big.gif'
}
},
// call Isotope as a callback
function (newElements) {
var $newElems = $(newElements);
$newElems.imagesLoaded(function () {
$container.isotope('insert', $newElems);
$('.products-grid-rollover-block').hide();
if(newElements.length > 0){
setTimeout(function () {
$container.infinitescroll('retrieve');
$('.products-grid-wrap').isotope('reLayout');
//$('.products-grid-wrap').isotope({
//sortBy: 'category',
//sortAscending: false });
}, 1000);
}
});
});
setTimeout(function () {
$container.infinitescroll('retrieve');
}, 3000);
});
});
Any solutions or suggestions would be massively appreciated!
You can try scroll-frame.It is a bit old may be the answer for you. Here is a link to an infinite scroll demo using it.
scrollFrame will hijack the user's click for elements that match the query selector you pass in and instead of reloading the page it will append a modal-like iframe that sits on top of your viewport and points to the element's href. It then uses HTML5 history APIs to make the back-button function as expected.
This can be a bit new solution of such problems.
https://github.com/highrisehq/snapback_cache
This is what is say's ...
Many apps today have some concept of an infinite scrolling feed: Facebook, Twitter, LinkedIn and many more. Almost all of them suffer from the same problem. If you click on something in the feed that brings you to a new page, when you hit the back button or try to return to that original feed, your place is lost. All the scrolling is gone.
At Highrise we had that same problem. So this is the library we use to fix that. We call it our Snapback Cache, and it's made a big improvement to how people can use infinite scroll in our app and still get a lot of work done without losing their place.
We solved this problem with a combination of (1) opening the page linked to on the infinite scroll page in a new tab; (2) using javascript to return to the parent.
Since I have seen a lot of comment about the difficulty of returning to the parent, I am posting our code for that below. The two functions are put into onclick attributes in the anchor tags used for the navigation buttons.
Using the name of the parent window solves the problem of intervening tabs opened before returning to the parent; without this, the tab returned to could be the most recently opened tab, rather than the parent.
/**
* open url in separate tab
* saves name of parent window for easy return
* #param url
*/
function gotoTab(url)
{
window.name = 'parent';
window.open(url);
}
/**
* uses name of parent
*/
function returnToParent()
{
var goBack = window.open('', window.opener.name);
window.top.close();
goBack.focus();
}

ExtJs grid.Panel store: keep scrollbar position after load/reload

I'm using grid.Panel in Sencha ExtJs 4.0.2a and I reload a Json Store every 60 seconds.
I was wondering if there is a way to preserve the position of the scrollbar after a data load.
So that the user can continue to look at the records he was looking before the load..
I reload the data in the grid using a Task:
var task = {
run: function(){
Ext.getCmp(panelGridId).getStore().load({
//Callback function after loaded records
callback: function(records) {
//Hide grid if empty records
if (Ext.isEmpty(records)) {
Ext.getCmp(panelGridId).setVisible(false);
}
else {
if (Ext.getCmp(panelGridId).isHidden()) {
Ext.getCmp(panelGridId).setVisible(true);
Ext.getCmp(panelGridId).doComponentLayout();
}
}
}
});
},
interval: 60000 //60 seconds
};
Ext.TaskManager.start(task);
After the data load the scrollbar position is reset to the top..
Q: Is there a way to maintain the scrollbar position after the data load?
Thanks in advance!
Try this bad boy to preserve scroll position on refresh:
http://docs-devel.sencha.com/extjs/4.2.1/#!/api/Ext.grid.View-cfg-preserveScrollOnRefresh
This works for me on my tree view.
viewConfig: {
preserveScrollOnRefresh: true
}
Here's how you would use preserveScrollOnRefresh in your Grid :
Ext.define('js.grid.MyGrid', {
extend: 'Ext.grid.Panel',
viewConfig: {
preserveScrollOnRefresh: true
}
Here's a JSFiddle which demonstrates this :
http://jsfiddle.net/cdbm6r0o/7/
However when you select a row it doesn't seem to work quite right. I am not sure if this is a bug.
The 'refresh' event is triggered from this code :
grid.store.loadData(dataToLoad);
I'm unaware of any other events which trigger a 'refresh'
Additional Notes :
I had the Ext.toolbar.Paging as a require. Even though I didn't use it, it screwed up the scroll preserve when I had one or more rows selected, so make sure you remove the Paging from your requires.
The scroll preserve does not appear to work if I use the bufferedrenderer plugin on the table at the same time.
tablePanel.getView().focusRow(recrow) is also interesting to look at, but also does not work with bufferedrenderer.
You can use the preserveScrollOnReload view config property:
viewConfig: {
preserveScrollOnReload: true
},

Categories