jQuery Scroll - Triggering a function ONCE when entering/exiting a scroll region - javascript

I am working in JavaScript / jQuery (1.3.2) and have two functions:
open() and close()
The functions need to be called when based on a predefined point on the page which we wil call posY.
The open function needs to be triggered once the user scrolls below posY and the close function needs to be triggered once the person scrolls above posY again.
This is pretty easily done using the jQuery scroll feature.
My issue is that I only want the functions to be triggered ONCE - Open needs to be triggered ONE TIME on entering and Close needs to be triggered ONE TIME on exiting.
I have been trying for ages now, with different solutions that get more and more complicated than I thing it needs to be. Hopefully I'm being an idiot, missing a really simple solution.
For this project I cannot use any jQuery features above 1.3.2 and I want to avoid adding any external plugins if it can be avoided.
Thanks in advance!
edit:
I got asked to add some example code. This is the code I found on a different post on Stackoverflow, that I based my experiments on - I tried to stop it from triggering constantly by monitoring a variable, but it got a bit too complicated for me.
:
$(window).on('scroll', function() {
var y_scroll_pos = window.pageYOffset;
var scroll_pos_test = 150; // set to whatever you want it to be
if(y_scroll_pos > scroll_pos_test) {
//do stuff
}
});

Simple!
.unbind();
Just unbind the event.
http://api.jquery.com/unbind/

Sounds like you need this http://api.jquery.com/one/ . Need to see some code as well for a better explanation.

Related

Infinite loop when overriding graphHandlerMouseUp on MxGraph using Angular

I have a difficult question to explain and I'm way out of my comfort zone as far as expertise in Javascript, TrueType, Angular and MxGraph are concerned... Hope to be able to explain.
I have an Angular component displaying and MxGraph. I was able to integrate MxGraph with Angular following this link (How to integrate mxGraph with Angular 4?). Even if I use Angular 7, the solution still works...
The graph is displayed correctly on the page and everything works fine, including my override of the function graphHandlerMouseUp, which I do with this code:
// Save the position of the mouse when releasing the button: used for
// detecting the target in a drag and drop
mx.graphHandlerMouseUp = mx.mxGraphHandler.prototype.mouseUp;
mx.mxGraphHandler.prototype.mouseUp = function( graph, evt ) {
currentdropX = evt.graphX;
currentdropY = evt.graphY;
mx.graphHandlerMouseUp.apply(this, arguments);
}
When I run this page for the first time, no problem happens.
Then through a button I call a page with another component (through routing). If from this page I go back to the first component (again through a routerlink) the page and the component with the MxGraph loads correctly, BUT when I use this function (i.e., release the mouse button).
It seems to me a recoursive problem, as when I put a console output like this:
// Save the position of the mouse when releasing the button: used for
// detecting the target in a drag and drop
mx.graphHandlerMouseUp = mx.mxGraphHandler.prototype.mouseUp;
mx.mxGraphHandler.prototype.mouseUp = function( graph, evt ) {
currentdropX = evt.graphX;
currentdropY = evt.graphY;
// INIFINTE LOOP HERE
console.log("Test");
mx.graphHandlerMouseUp.apply(this, arguments);
}
The "Test" is written a number of times which is continuously growing. Yet, if I understood, this was the correct way of overriding the function. Of course on the first load of the page, "Test" is displayed once. Passing to another component and then back on this it is displayed an "infinite" number of times (until I reach the: "ERROR RangeError: Maximum call stack size exceeded")...
I tried also to remove that override, and besides the obvious lack of the functionality, the very same problem happened to the function "mxDragSource", which is overridden with the same approach.
As I said: I'm not expert enough in javascript, truetype, MxGraph or Angular, so any hint, even if obvious, is very welcome!
Thanks!
The first time you run your code, you store mx library's mouseUp event in a variable and you assign a new function to mouseUp event in which you call the old mouseUpEvent.
The second time you run your code, you store your current mouseUp event (that you have modified) and you assign a function in which you call the old mouseUpEvent, which is the same you stored previously. There goes your recursion !
What you need to do is override the third-party function properly, so you don't execute your code twice.
How to do it ?
You can create a mixin and use this mixin in your componentB/ If you have no idea what is it and how to do it, please reproduce your problem in a stackblitz I'll be glad to help you to implement it.

jQuery bring DIV infront without reseting iframe

Point
The code I have here is from my "operating system" I'm trying to create inside a browser by putting iframes in AppWindows with PHP code as the backend or the (main program process).
Now in every GUI system you have the ability to move windows, stack one on top of each others and such, but I'm not able to do efficiently in HTML using jQuery & jQuery-UI.
I'm using draggable() and some tricks I've found on StackOverflow to be able to bring the div AppWindow on top.
The problem
The code for bringing the **AppWindow** on top works fine but the problem is the iframe inside that window gets reset, because what this code is doing is that it stacks the current div as the first div above all the others inside the parent container.
If you notice the AppWindow 1 iframe blinks when you click on that window, I don't want that.
Code (jQuery)
$(function() {
// Don't know what I'm doing with iframe here...
$('.AppWindow iframe').click(function(){
$(this).parent().child.parent().append(this);
});
$('.AppWindow').click(function(){
$(this).parent().append($(this));
});
$('.AppWindow').draggable({handle:".DragHandle"});
});
Conclusion
If there is a way of preventing this from happening feel free to write an answer below. If you have a better way such as "JavaScript OS UI Framework" or something like that you're even more free to write below.I want something like **os.js** or **windows93.net** type of thing. All I need is a working taskbar, working window and a way to easily embed a PHP page inside that window that will mimic the work of the application.
I don't think it's possible. Take a look at here.
But
why do you reorder windows by change their positions in the dom in the first place? You could simply work with z-index. A basic example where you just set an active class of the targeted frame.
$(function() {
$('.AppWindow').draggable({
handle:".DragHandle",
drag: function(event, ui){
updateActiveWindow(event.target);
}
});
$('.AppWindow').on('click', function(){
updateActiveWindow(this);
});
function updateActiveWindow(el) {
$('.AppWindow').removeClass('active');
$(el).addClass('active');
}
});
with following css changes
.AppWindow.ui-draggable-dragging,
.AppWindow.active {
z-index: 1;
}
Edit: optimized the js a bit so that the window turns active once you start dragging.

Detect if user will leave site like Bounce Exchange

Bounce Exchange has figured out an almost perfect way of detecting if a user will leave the website. They do this based on tracking mouse gestures, mouse velocity, and breaking of the browser plane. If they detect someone is leaving they fire off a popup on a lightbox.
I can poorly emulate this, by the following:
$("body").mouseleave(function() {
jQuery('#avoid-bounce').show();
});
The only problem is this is rather annoying. Even if it captures someone, the moment they leave the body it fires again.
How probable would it be to factor in mouse speed and allow the event to fire only once? I'm still fairly new to JavaScript and jQuery, but I'm learning.
This is exactly what .one() is for:
$("body").one('mouseleave', function() {
jQuery('#avoid-bounce').show();
});
You can add a flag to your code:
$("body").mouseleave(function() {
if ( jQuery('#avoid-bounce').data('shown') != true ) {
jQuery('#avoid-bounce').data('shown', true).show();
}
});
Creating a flag will make sure the show() code will not be called the second time.
Or you can try OuiBounce,the bounce exchange alternative: https://github.com/carlsednaoui/bounce-exchange-alternative

Impromptu - prompt will not close

I am trying Impromptu in my javascript and for some reason it will load fine, all the functionality I apply within works but calling a close or using the 'x' in the upper right will not close the prompt. The opacity of the overlay lightens slightly but the prompt is model and I can continue to interact with it but not the underlying page.
I have gone back to basics and I am using this function;
$Kurve.prototype.tooltip = function(){
$.prompt('Hello World',{ opacity: 0.1 });
}
It is being called a part of a JQPlot chart;
$l_jqPlotArg.highlighter.tooltipContentEditor = $.jqplot.eventListenerHooks.push(['jqplotClick', this.tooltip]);
Any help appreciated and if you need more info I will do my best to supply it...also, if you have a better suggestion on an overlaying prompt (with good appearance) that can handle a JSON please don't hesitate to tell me!
I have asked th
Thanks
C
Ok, I figured this out...the click listener was fine but I had to move the handler to a var inside the chart function. All is well :)

Speeded up a slow jQuery Mobile page transition - why?

Background: I have a jQuery mobile app (single .htm, multi-jqm pages) where one of the pages contains a listview with a reasonably large number of list items (300-500 say). I'm testing the boundaries of performance here so currently my custom "paging" will use CSS to hide all but 25 of the items at a time. The app is deployed to devices using PhoneGap.
So, to my question.
I've found that when clicking on an item in the list, navigation to the page the list item links to is extremely sluggish on devices when I use the code below. This handles the click, extracts an id from the list item and stores it, then allows the click to perform the page navigation:
$('#largeListView').on('vclick', 'a[href="#subView"]', function (e) {
theSubView.setId($(this).data("id"));
});
However, the code below is much quicker. It stores the id also but then prevents the click causing the navigation and manually changes the page instead:
$('#largeListView').on('vclick', 'a[href="#subView"]', function (e) {
theSubView.setId($(this).data("id"));
e.preventDefault();
$.mobile.changePage('#subView');
});
The only downside of the quicker solution (as far as I know) is that the item does not show any UI feedback that a click occurred.
Does anyone know why I get the vast speed improvement here and if there is a way of speeding up option 1 instead?
I don't like circumventing the design in this way and would prefer to use option 1 if I can get good performance.
Thanks!
Chris.
just a guess but maybe this happens due to the fact that the default browser behavior triggers custom events and invokes some scrolling mechanism whereas the $.mobile call avoids this overhead...
I do not think you can improve that so easily but maybe try to use a small delay to perform this asynchronously
$('#largeListView').on('vclick', 'a[href="#subView"]', function (e) {
var id = $(this).data("id");
setTimeout(function() {
theSubView.setId(id);
}, 0);
});

Categories

Resources