Run function, disable scroll, but enable on callback - javascript

I want to make a infinite scroll page, but I have a problem.
My loadElements works with $.get, like this:
loadElements: function() {
// fades out page
$.get(//..).done(function() {// fades in page});
}
And scrolling:
$(window).scroll(function() {
Functions.loadElements();
});
What I want is to run Functions.loadElements(); once on scroll, wait for the // fades in page, then reenable scrolling again. I tried bind/unbind, but with no success. How can I achieve this?
EDIT:
I tried using bind and unbind like this:
$(window).scroll(function() {
Functions.loadElements();
$(window).unbind('scroll');
}
and in loadElements:
loadElements: function() {
// fades out page
$.get(//..).done(function() {// fades in page; $(window).bind('scroll'); });
}
But it didn't work.

I can't give you a solution exactly. but try something like this. You can maintain a status with a globle variable.
var isLoading = false;
$(window).scroll(function(e) {
if( !isLoading )
{
Functions.loadElements();
isLoading = true;
}
e.preventDefault();
}
loadElements: function() {
// fades out page
$.get(//..).done(function() {// fades in page; isLoading = false; });
}

Maybe instead of rebinding the scroll function that contains the logic, try binding a function that "disables" scrolling and then remove this function once your content is ready to scroll again. You could use jquery namespace events for this
Try with
$(window).scroll(function() {
Functions.loadElements();
$(window).bind('scroll.StopScroll', function (e) {
e.preventDefault(); e.stopImmediatePropagation();
});
}
And then in the .done unbind it
$(window).unbind('scroll.StopScroll');

I'd do it with the get promise
var waiting;
$(window).scroll(function(e) {
if(waiting){
e.preventDefault();
return;
}
Functions.loadElements().then(function(){
waiting = false;
});
waiting = true;
});
and return the get promise from loadElements
loadElements: function() {
// fades out page
return $.get(...).done(function() {...});
}

Related

On / Off function after a certain period of time

Wondering how you can make .off() only happen for a specific period of time. I have a div which once clicked i want to disable the click event for 2 seconds, and then be allowed to click again. At the moment all I have is the div can be clicked, then once clicked it is off.
Here is a brief example of what I am asking:
$('.test').on('click', function() {
// *do stuff*
$('.test').off('click'); *for a certain perdiod of time*
});
It's a much simpler task to use a boolean variable as a flag to state whether the click handler should be executed, instead of attaching/detaching events from multiple elements. Try this:
var clickEnabled = true;
$('div').click(function() {
clickEnabled = false;
setTimeout(function() {
clickEnabled = true;
}, 2000);
});
$('.test').on('click', function(e) {
if (!clickEnabled) {
e.preventDefault();
} else {
// do stuff...
}
});
Note that you should also make the fact that .test is disabled visible in the UI, otherwise you'll just confuse and annoy your visitors when they click an element expecting an action, but nothing happens.
What about activate on after a certain period of time?
function myFunction() {
...do stuff
$('.test').off('click'); for a certain perdiod of time
setTimeout(function(){ $('.test').on('click', myFunction)}, 2000);
}
Using the setTimeout you may do something like:
var enabled = true;
var timeoutSeconds = 2;
$(function () {
$('.test').on('click', function(e) {
if (enabled) {
// *do stuff*
enabled = false;
window.setTimeout(function() {
enabled = true;
}, timeoutSeconds * 1000);
} else {
e.preventDefault();
}
});
});
You could do it like this.
function onClick() {
// do stuff here
$('.test').off('click');
setTimeout(function(){
$('.test').on('click', onClick);
}, 2000)
}
$('.test').on('click', onClick);
Or you can do it with css and toggleClass
// css
.disabled {
pointer-events: none;
}
// js
$('.test').on('click', function(){
// do stuff here
$('.test').addClass('disabled');
setTimeout(function(){
$('.test').removeClass('disabled');
}, 2000);
});

jQuery Event Duplicating function

The issue I'm having is every time you resize the browser a function is called, that function will make a side panel into an accordion if the screen width is a certain number or below or on a larger screen it's just displaying like an open side panel with no interaction.
In the resize event I call the sidepanel function. Unfortunately every time I resize the browser my side panel function is duplicated. I've been seeing stuff on unbinding but nothing that seems to make sense for how I'm calling the side panel function.
Is there a way in the resize.js to unbind the sidepanel function and rebind to the window so it's only called once every time the window is resized?
Resize.js
$(document).ready(function() {
var resizeTimer;
$(window).on('resize', function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function() {
sidePanelAccordion();
}, 250);
});
});
Side-panel.js
function sidePanelAccordion() {
var panelAccordion = $('.side-panel-accordion');
var panelHeader = $('.side-panel-header');
var panelBody = $('.side-panel-body');
var panelHeaderActive = $('.mobile-header-active');
if (userScreen.type === 'mobile') {
panelAccordion.find(panelBody).hide();
panelAccordion.find(panelHeader).addClass('mobile-header-active');
} else if (userScreen.type === 'desktop') {
panelAccordion.find(panelBody).show().removeClass('open');
panelHeader.removeClass('mobile-header-active');
}
panelHeaderActive.on('click', function(e) {
console.log('clicked');
if (panelBody.hasClass('open')) {
panelBody.removeClass('open').stop(true, true).slideUp().clearQueue();
//console.log('panel had class open');
e.stopPropagation();
return false;
} else {
panelBody.addClass('open').stop(true, true).slideDown().clearQueue();
//console.log('panel now has class open');
e.stopPropagation();
return false;
}
});
}
Try this code:
panelHeaderActive.unbind('click').on('click', function(e){
console.log('clicked');
if (panelBody.hasClass('open')) {
panelBody.removeClass('open').stop(true,true).slideUp().clearQueue();
//console.log('panel had class open');
e.stopPropagation();
return false;
} else {
panelBody.addClass('open').stop(true,true).slideDown().clearQueue();
//console.log('panel now has class open');
e.stopPropagation();
return false;
}
});

toggle() not working for content loaded with ajax?

$('.slideArrow').toggle(function (event) {
//some code
}, function (event) {
//some code
});
This works fine for content which are loaded on page-load.But the same function does not work for content loaded with ajax.It just does not intercept the click.
What should I do?
In an other scenario,i faced a same problem(not for toggle,for click) and sorted it this way.I dont know what to do for toggle?
$('.common-parent').on('click','.target-of-click',function(){
//some code
})
The flag method :
var flag = false;
$(document).on('click', '.slideArrow', function(event) {
if (flag) {
// do one thing
}else{
// do another thing
}
flag = !flag;
});
the data method
$(document).on('click', '.slideArrow', function(event) {
if ( $(this).data('flag') ) {
// do one thing
}else{
// do another thing
}
$(this).data('flag', !$(this).data('flag'));
});

cancel jquery tooltip during dynamic loading of content

I'm using the jQuery tooltip to show content that is dynamically loaded (javascript below). In some cases when the mouse moves away from the element the tooltip doesn't go away. My theory is that the loading of the dynamic content introduces a slight delay so the mouse moves away from the element just before the tooltip function completes and so it doesn't consume the mouseleave event. Any way to resolve this?
element.tooltip(
{
items: "table.orderlist label",
open: function (event, ui)
{
ui.tooltip.css("max-width", "600px");
ui.tooltip.css("max-height", "300px");
ui.tooltip.css("overflow", "hidden");
},
content: function (callback)
{
//Get the contents as the tooltip is popping up
MyAjaxCall(iID,
function (result)
{
try
{
//success
callback(result) //returns the result
}
catch (e)
{
DisplayError(e);
}
},
function (result)
{
//Error
DisplayError(result);
});
}
});
Your content function should be a bit more complicated, the possible solution is:
content: function (callback)
{
var $this = $(this), isMouseOn = true;
// check if tooltip ajax-request is in progress
// really needed for slow scripts only
if($this.data('tt-busy')) return;
// check if el is hovered (in jquery <= 1.8 you can simly use .is(':hover')
$this
.data('tt-busy', true)
.on('mouseenter.xxx', function() { isMouseOn = true; })
.on('mouseleave.xxx', function() { isMouseOn = false; });
//
$.get('slow.script', function(d) {
if(isMouseOn) callback(d);
}).always(function() {
// even if result fails set loading var to false and unbind hover events
$this
.data('tt-busy', false)
.off('.xxx');
});
}

Wait until div is not visible to process next line

I need to write some code which is supposed to wait until a predefined div is no longer visible in order to process the next line. I plan on using jQuery( ":visible" ) for this, and was thinking I could have some type of while loop. Does anyone have a good suggestion on how to accomplish this task?
$( document ).ready(function() {
$(".scroller-right" ).mouseup(function( event ) {
alert('right');
pollVisibility();
});
});
function pollVisibility() {
if ($(".mstrWaitBox").attr("visibility")!== 'undefined') || $(".mstrWaitBox").attr("visibility") !== false) {
alert('inside else');
microstrategy.getViewerBone().commands.exec('refresh');
} else {
setTimeout(pollVisibility, 100);
}
}
$( document ).ready(function() {
$(".scroller-right" ).mouseup(function( event ) {
alert('right');
pollVisibility();
});
});
function pollVisibility() {
if (!$(".mstrWaitBox").is(":visible")) {
alert('inside if');
microstrategy.getViewerBone().commands.exec('refresh');
} else {
setTimeout(pollVisibility, 100);
}
}
div when not visible:
<div class=​"mstrWaitBox" id=​"divWaitBox" scriptclass=​"mstrDialogImpl" dg=​"1" ty=​"edt">​
</div>​
div when visible:
<div class=​"mstrWaitBox" id=​"divWaitBox" scriptclass=​"mstrDialogImpl" dg=​"1" ty=​"edt" visibility="visible">​
</div>​
You can use the setTimeout function to poll the display status of the div. This implementation checks to see if the div is invisible every 1/2 second, once the div is no longer visible, execute some code. In my example we show another div, but you could easily call a function or do whatever.
http://jsfiddle.net/vHmq6/1/
Script
$(function() {
setTimeout(function() {
$("#hideThis").hide();
}, 3000);
pollVisibility();
function pollVisibility() {
if (!$("#hideThis").is(":visible")) {
// call a function here, or do whatever now that the div is not visible
$("#thenShowThis").show();
} else {
setTimeout(pollVisibility, 500);
}
}
}
Html
<div id='hideThis' style="display:block">
The other thing happens when this is no longer visible in about 3s</div>
<div id='thenShowThis' style="display:none">Hi There</div>
If your code is running in a modern browser you could always use the MutationObserver object and fallback on polling with setInterval or setTimeout when it's not supported.
There seems to be a polyfill as well, however I have never tried it and it's the first time I have a look at the project.
FIDDLE
var div = document.getElementById('test'),
divDisplay = div.style.display,
observer = new MutationObserver(function () {
var currentDisplay = div.style.display;
if (divDisplay !== currentDisplay) {
console.log('new display is ' + (divDisplay = currentDisplay));
}
});
//observe changes
observer.observe(div, { attributes: true });
div.style.display = 'none';
setTimeout(function () {
div.style.display = 'block';
}, 500);
However an even better alternative in my opinion would be to add an interceptor to third-party function that's hiding the div, if possible.
E.g
var hideImportantElement = function () {
//hide logic
};
//intercept
hideImportantElement = (function (fn) {
return function () {
fn.apply(this, arguments);
console.log('element was hidden');
};
})(hideImportantElement);
I used this approach to wait for an element to disappear so I can execute the other functions after that.
Let's say doTheRestOfTheStuff(parameters) function should only be called after the element with ID the_Element_ID disappears, we can use,
var existCondition = setInterval(function() {
if ($('#the_Element_ID').length <= 0) {
console.log("Exists!");
clearInterval(existCondition);
doTheRestOfTheStuff(parameters);
}
}, 100); // check every 100ms

Categories

Resources