Fancy Box 2 - Window jumping to top on click - javascript

This is my first time implementing FancyBox in a project for me. I have separated the image from the link. So when you hover over the image the link to view the large image appears. Everything there works fine. My issues is the window keeps jumping/scrolling to the top when the link is clicked. I have used jquery to disable the default action of it by using preventDefault but that didn't solve my issue. Any suggestions? You can see what I'm trying to accomplish at www.labpixls.com
I need to resolve this soon. I am creating a wordpress theme I plan on giving to the wp community.

The problem is that fancyBox changes the overflow value of the body in order to hide the browser scrollbars. This can actually be done with a helper in Fancybox 2.
$('.image').fancybox({
padding: 0,
helpers: {
overlay: {
locked: false
}
}
});

I realize this question has been asked a while ago, but I think I have found a good solution for it.
The problem is that fancy box changes the overflow value of the body in order to hide the browser scrollbars.
As Thorn points out, we can stop fancy box from doing this by adding the following parameters:
$('.image').fancybox({
padding: 0,
helpers: {
overlay: {
locked: false
}
}
});
But, now we can scroll the main page while looking at our fancy box window. It is better than jumping to the top of the page, but it is probably not what we really want.
We can prevent scrolling the right way by adding the next parameters:
$('.image').fancybox({
padding: 0,
helpers: {
overlay: {
locked: false
}
},
'beforeLoad': function(){
disable_scroll();
},
'afterClose': function(){
enable_scroll();
}
});
And add these functions from galambalaz. See: How to disable scrolling temporarily?
var keys = [37, 38, 39, 40];
function preventDefault(e) {
e = e || window.event;
if (e.preventDefault) e.preventDefault();
e.returnValue = false;
}
function keydown(e) {
for (var i = keys.length; i--;) {
if (e.keyCode === keys[i]) {
preventDefault(e);
return;
}
}
}
function wheel(e) {
preventDefault(e);
}
function disable_scroll() {
if (window.addEventListener) {
window.addEventListener('DOMMouseScroll', wheel, false);
}
window.onmousewheel = document.onmousewheel = wheel;
document.onkeydown = keydown;
}
function enable_scroll() {
if (window.removeEventListener) {
window.removeEventListener('DOMMouseScroll', wheel, false);
}
window.onmousewheel = document.onmousewheel = document.onkeydown = null;
}

Related

Smooth scrolling for whole webpage

I am trying to add a smooth scroll to my website. Most of you think of a smooth scrolling animation when clicking on a button. But no! That's not what I want to achieve. When a user presses the key down, key upper or scrolls with the mouse wheel, I want to make a smooth animation to the point he scrolls to. I know it is possible. At this website, you can get a pure vanilla javascript code when you make a yearly subscription: http://www.smoothscroll.net/ . And I know that it works because I already saw it at other websites. My idea to achieve this by myself:
/*/////////////////////////////////////////////////////////////////////////////////////////////*/
/* S M O O T H S C R O L L */
/*/////////////////////////////////////////////////////////////////////////////////////////////*/
var keys = {37: 1, 38: 1, 39: 1, 40: 1};
function preventDefault(e) {
e.preventDefault();
}
function preventDefaultForScrollKeys(e) {
if (keys[e.keyCode]) {
preventDefault(e);
return false;
}
}
var supportsPassive = false;
try {
window.addEventListener("test", null, Object.defineProperty({}, 'passive', {
get: function () { supportsPassive = true; }
}));
} catch(e) {}
var wheelOpt = supportsPassive ? { passive: false } : false;
var wheelEvent = 'onwheel' in document.createElement('div') ? 'wheel' : 'mousewheel';
// call this to Disable
function disableScroll() {
window.addEventListener('DOMMouseScroll', preventDefault, false); // older FF
window.addEventListener(wheelEvent, preventDefault, wheelOpt); // modern desktop
window.addEventListener('touchmove', preventDefault, wheelOpt); // mobile
window.addEventListener('keydown', preventDefaultForScrollKeys, false);
}
// call this to Enable
function enableScroll() {
window.removeEventListener('DOMMouseScroll', preventDefault, false);
window.removeEventListener(wheelEvent, preventDefault, wheelOpt);
window.removeEventListener('touchmove', preventDefault, wheelOpt);
window.removeEventListener('keydown', preventDefaultForScrollKeys, false);
}
disableScroll();
This is a stackoverflow answer. You can find the answer here: https://stackoverflow.com/a/4770179/12419967. The Problem now: I need to find out how much the user scrolled and than I could scroll it via script. But how? Or is there another solution or library we can use?

Enable scrolling with drag-n-drop on touch devices

Re-arranging columns and click is now working on touch devices. Now facing the issue with scrolling. I tried to resolve it with iScroll plugin but it didn't work. The screenshot I took from device mode of chrome browser.
Table columns can be added on-the-fly and so number of columns may vary.
Is there any css way to work scrolling properly ??? If not how do I implement it with javascript or jquery ???
Update:
-webkit-overflow-scrolling: touch; is not working.
Update 2:
Tried with below code:
if (Modernizr.touch) {
$('.container-fluid').css('overflow', 'auto');
}
and this one as well:
if (Modernizr.touch) {
//iScroll plugin
var myScroll = new IScroll('#tblGrid', {
scrollbars: true
});
}
None of them worked.
Update 3:
Below is the code to enable dragging of table columns and click event:
var clickms = 200;
var lastTouchDown = -1;
function touchHandler(event) {
var touch = event.changedTouches[0];
var d = new Date(); var type = "";
switch (event.type) {
case "touchstart": type = "mousedown"; lastTouchDown = d.getTime(); break;
case "touchmove": type = "mousemove"; lastTouchDown = -1; break;
case "touchend": if (lastTouchDown > -1 && (d.getTime() - lastTouchDown) < clickms) { lastTouchDown = -1; type = "click"; break; } type = "mouseup"; break;
default: return;
}
var simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent(type, true, true, window, 1,
touch.screenX, touch.screenY,
touch.clientX, touch.clientY, false,
false, false, false, 0, null);
touch.target.dispatchEvent(simulatedEvent);
event.preventDefault();
}
function init() {
document.addEventListener("touchstart", touchHandler, true);
document.addEventListener("touchmove", touchHandler, true);
document.addEventListener("touchend", touchHandler, true);
document.addEventListener("touchcancel", touchHandler, true);
}
$(document).ready(function () {
init();
var myScroll;
function loaded() {
myScroll = new IScroll('#tblGrid', {
mouseWheel: true,
scrollbars: true,
click: true,
eventPassthrough: true,
tap: true
});
}
if (Modernizr.touch) {
loaded();
}
});
Update 4:
I tried to use iScroll 4 and scrolling now works. But when I rearrange/drag-drop columns, the scrolling also works and in that case Drag-drop does not work properly due to touchmove event.
And jquery.floatThead also stopped working which fixes the headers.
I'm not entirely sure what your end goal is, but let me see if I understand:
You want to be able to scroll your table horizontally on touch devices. This works right now.
You want to be able to drag and drop your columns to rearrange them. You want to do this by dragging the column headers. Right now, when you do this the touchmove listener is causing the whole table to scroll horizontally when you drag a column, which is a problem.
If I'm correct on the two points above, then I think what might fix your problem is to change init() so that it adds the touch listeners only to your table headers (instead of the entire document). Something like this:
function init() {
$( "th" ).each(function( index ) {
this.addEventListener("touchstart", touchHandler, true);
this.addEventListener("touchmove", touchHandler, true);
this.addEventListener("touchend", touchHandler, true);
this.addEventListener("touchcancel", touchHandler, true);
});
}
You would also need to apply the four event listeners to any new column headers added to the table (wherever you're currently handling you 'add column' logic).
I'm not certain this will 100% work - if you could post a repro of the problem somewhere like http://jsfiddle.net/, it might be easier to help you debug it.

disable webapp scrolling without killing click (tap) events in javascript

This is my first post so ill try to explain it clear:
Im working on a web application, but the main point is, that i want let my users feel like its a native app. In a native app you cant scroll like in iOS safari so i tried to disable scrolling with event.preventDefault. This works great except that form elements and links arent tapable anymore. My solution to that was this little script, but if you start a touch on one of the escaped elements, it scrolls anyway. Not a big deal but its driving me insane...
notes to script:
isTouch returns true/false if its a touchable device
the .contains method returns true/false if an array contains a string
if (isTouch) {
window.addEventListener("touchstart", function (evt) {
var target = evt.touches[0].target;
var tags = 'a input textarea button'.split(' ');
if ( tags.contains(target.tagName) === false ) {
evt.preventDefault();
}
}, false);
}
EDIT
My main question is, is there a solution to fire the tap event without a touchmove event to allow scrolling
EDIT 2
I solved the problem. My solution is, to emulate the events on interactive elements:
var eventFire = function (el, etype) {
if (el.fireEvent) {
(el.fireEvent('on' + etype));
}
else {
var evObj = document.createEvent('Events');
evObj.initEvent(etype, true, false);
el.dispatchEvent(evObj);
}
}
if (isTouch) {
window.addEventListener("touchstart", function (evt) {
var target = evt.touches[0].target;
var foc = 'input textarea'.split(' ');
var clck = 'a button'.split(' ');
if ( foc.contains(target.tagName) ) {
target.focus();
eventFire(target,'click');
evt.preventDefault();
}
else {
evt.preventDefault();
}
}, false);
}

how to prevent jumping site when scrolling?

I'm trying to write mechanism on site which prevents users to scroll normally. When user scrolls down or up the site is smoothscrolling to next or previous slide (depends on scrolling direction) and stops there (like when you click on a navbar). See live preview: CLICK HERE
But there's an annoying problem. It works almost good in FF (no jumping), but breaks in another browsers (Chrome, Safari, IE)- it jumps. How can I prevent this?Here are snippets from my code.
I have a ScrollControl object where I prevent scrolling:
scrollControl = {
keys : [32, 37, 38, 39, 40],
scrollTimer : 0,
lastScrollFireTime : 0,
preventDefault : function(e){
e = e || window.event;
if (e.preventDefault)
e.preventDefault();
e.returnValue = false;
},
keydown : function(e){
for (var i = scrollControl.keys.length; i--;) {
if (e.keyCode === scrollControl.keys[i]) {
scrollControl.preventDefault(e);
return;
}
}
},
wheel : function(e){
scrollControl.preventDefault(e);
},
disableScroll : function(){
if (window.addEventListener) {
window.addEventListener('DOMMouseScroll', scrollControl.wheel, false);
}
window.onmousewheel = document.onmousewheel = scrollControl.wheel;
document.onkeydown = scrollControl.keydown;
},
enableScroll : function(){
if (window.removeEventListener) {
window.removeEventListener('DOMMouseScroll', scrollControl.wheel, false);
}
window.onmousewheel = document.onmousewheel = document.onkeydown = null;
}
}
Then I'm listening if mousewheel occurs and trying to execute function only once (I'm using this plugin to detect mousewheel PLUGIN )
$(window).mousewheel(function(objEvent, intDelta){
var minScrollTime = 1000;
var now = new Date().getTime();
function processScroll() {
console.log("scrolling");
if(intDelta>0){
$.smoothScroll({
speed:med.effectDuration,
easing:med.scrollEase,
scrollTarget:med.prevPage,
afterScroll: function(){
med.currentPage = med.prevPage;
med.setActiveNav();
med.setSlides();
med.runAnimations();
}});
}else if(intDelta<0){
//scrollControl.disableScroll();
$.smoothScroll({
speed:med.effectDuration,
easing:med.scrollEase,
scrollTarget:med.nextPage,
afterScroll: function(){
med.currentPage = med.nextPage;
med.setActiveNav();
med.setSlides();
med.runAnimations();
}});
}
}
if (!scrollControl.scrollTimer) {
if (now - scrollControl.lastScrollFireTime > (3 * minScrollTime)) {
processScroll(); // fire immediately on first scroll
scrollControl.lastScrollFireTime = now;
}
scrollTimer = setTimeout(function() {
scrollControl.scrollTimer = null;
scrollControl.lastScrollFireTime = new Date().getTime();
processScroll();
}, minScrollTime);
}
});
I'm executing scrollControl.disableScroll function on DOM ready event when users starts website. And actually scrolling once prevention doesn't works prefectly and sometimes it triggers smoothscrolling twice. What am I doing wrong? Thanks in advance for any suggestions!
I had the same issue the Mouse Wheel Event was fired Twice.
function wheelDisabled(event){
event.preventDefault();
event.stopImmediatePropagation();
return false;
}
Also you might use both of these Events.
window.addEventListener('DOMMouseScroll', wheel, false);
window.addEventListener('mousewheel', wheel, false);
Instead of trying to prevent scrolling with Javascript, I would try a different approach. This approach includes CSS and Javascript to make sure the website is never bigger then the viewport (hence no scrollbars!).
Use CSS to force the main wrapping div (a div that wraps all the content on the site) to have overflow: hidden. Then use Javascript to dynamically ensure that the height and width of this div is always equal to the viewport's height and width.
In this scenario, if you want to implement scrolling in a predefined way you choose you can dynamically add negative margin-top (or negative margin-left for horizontal scrolling) to the parent wrapping div to give it the appearance that it is scrolling.

Catch scrolling event on overflow:hidden element

Any insights on how to catch a scrolling event on a element that has overflow:hidden? I would like to scroll in a column without showing a scrollbar to the user.
This is actually a somewhat indepth process. What I do is set global flags when users mouse enters and leaves the element that you want to scroll. Then, on the mousewheel event for the body I check to see if the MOUSE_OVER flag is true, then stop propagation of the event. This is so the main body doesnt scroll in case your entire page has overflow.
Note that with overflow hidden, the default scrolling ability is lost so you must create it yourself. To do this you can set a mousewheel listener on your div in question and use the event.wheelDelta property to check whether the user is scrolling up or down. This value is different according to browser, but it is generally negative if scrolling down and positive if scrolling up. You can then change position of your div accordingly.
This code is hacked up quickly but it would essentially look like this...
var MOUSE_OVER = false;
$('body').bind('mousewheel', function(e){
if(MOUSE_OVER){
if(e.preventDefault) { e.preventDefault(); }
e.returnValue = false;
return false;
}
});
$('#myDiv').mouseenter(function(){ MOUSE_OVER=true; });
$('#myDiv').mouseleave(function(){ MOUSE_OVER=false; });
$('#myDiv').bind('mousewheel', function(e){
var delta = e.wheelDelta;
if(delta > 0){
//go up
}
else{
//go down
}
});
I use overflow:scroll, but also Absolutely position a div over the scroll bar in order to hide it.
$("body").css("overflow", "hidden")
$(document).bind('mousewheel', function(evt) {
var delta = evt.originalEvent.wheelDelta
console.log(delta)
})
works for me. adapted from How do I get the wheelDelta property?
I edited #anson s answer to Vanilla Javascript since it may be useful for others. Also note that "mousewheel" event is deprecated. So my code uses "wheel" instead. Next to that I added arrow functions for practical access the to "this".
fixScrollBehavior(elem) {
elem.addEventListener('scroll', (e) => {
console.log('scrolling');
});
let MOUSE_OVER = false;
elem.addEventListener('wheel', (e) => {
if (MOUSE_OVER) {
if (e.preventDefault) {
e.preventDefault();
}
e.returnValue = false;
return false;
}
});
elem.addEventListener('mouseenter', () => {
MOUSE_OVER = true;
});
elem.addEventListener('mouseleave', () => {
MOUSE_OVER = false;
});
elem.addEventListener('wheel', (e) => {
let delta = e.wheelDelta;
if (delta > 0) {
//go up
} else {
//go down
}
});
}
Note that this does not fix the mobile touch-"scroll"s.
$("div").on('wheel', function (e) {
if (e.originalEvent.deltaY < 0) {
console.log("Scroll up");
} else {
console.log("Scroll down");
}
});
This did the trick for me.
JSFiddle
StackFiddle:
$("div").on('wheel', function(e) {
if (e.originalEvent.deltaY < 0) {
console.log("Scroll up");
} else {
console.log("Scroll down");
}
});
div {
height: 50px;
width: 300px;
background-color: black;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
I am late, but I think I have a better answer.
Style your container as overflow: overlay, this will free up space of scrollbar, then style scrollbar or hide it or make its handle height/width 0,
Then you should get scroll events also.
Note : styling the scrollbar is not supported in all web browsers.

Categories