im looking for some javascript events that trigger at the start and at the end navigating via dragging on flot plots so that i can do some ajax updates, however, I've been looking around online for some code to help me. I've found a few things, most didn't work worked or had bugs.
The best thing I've found so far is an answer from DNS, however it has unintentional behavior, when you hold the mouse click button down and stop panning the event triggers.
var delay = null;
element.on("plotpan", function() {
if (delay) clearTimeout(delay);
delay = setTimeout(function() {
// do your stuff here
delay = null;
}, 500);
});
The navigate plugin should really pass the event on to you; then you could easily check the state of the mouse buttons in your handler.
Since it doesn't, you'll need to attach your own mousedown/mouseup listeners to the overlay canvas; the child of your plot placeholder with class 'flot-overlay'. You can use these to update a shared variable with the state of the left button, then check that value in your handler above.
Related
I have a website that I am creating and there are different divs each with their own content. All of them are hidden except the main one that shows up on the homepage. The transitions are pretty long, and I like it that way, but the problem is that if somebody spams the navbar buttons it opens up all those divs ontop of each other. So to prevent that I want to temporarily disable the onClick for an <a></a> element. Then enable it after the transition is done. Currently I am able to disable it, but cannot find a way to re-enable it.
function disable(){
$(".bar").unbind();
$(".bar").removeAttr("onClick");
}
I know how to call a function after a certain amount of time, but what is the "enable" equivalent to the code in this function?
The exact opposite would be to set the onClick back on the element.
$('.bar').attr('onClick', function() { alert('blah'); });
or with vanilla js
document.querySelector(".bar")
.setAttribute('onClick', function() {...});
However, this is difficult to manage for many elements with the same functionality. It would be easier to have this entirely managed with javascript (and jQuery in this case).
function clickEvent(event) {
var self = $(this);
// Unbind the event
self.off(clickEvent);
// Click logic here
// Rebind event
self.on('click', clickEvent);
}
$('.bar').on('click', clickEvent);
Instead of disabling the event on the DOM, you can just add an extra piece of logic to your dynamic divs:
$('#mydiv').click(function() {
if(!inTransition())
// DO A THING
else
// DON'T DO A THING
});
As a side note: If you're doing a lot of dynamic DOM manipulation, you may want to look into using a data binding framework such as Angular or Knockout. jQuery is nice for simple DOM manipulations, but it can quickly become messy and hard to maintain if you're doing something complex (which it sounds like you are).
As somewhat of an extension to nmg49's answer, I'd like to provide a solution that's a little more in depth.
Essentially what you'll want to do is create a flag to determine whether or not you are currently transitioning, and cancel the onClick if it is true (disabling it after the transition is complete).
var isTransitioning = false;
$('.bar').onClick(function(){
if(isTransitioning) return;
isTransitioning = true;
// DO TRANSITION
});
Once the transition is complete, you simply set isTransitioning to false (either in a callback, or at the end of your onClick function; which ever one applies to your code).
This will ensure that, no matter how many times they click the button, they will not be able to transition if they're already in transition.
OpenLayers3 API has a map.on("moveend") , however I cannot find a movestart. Any one know how I can achieve this? Is there a equivalent event?
OpenLayers 2 had a movestart event on map. I am looking an exact parallel in OpenLayers3
Here's a basic jsFiddle. If someone want's to play around. I did add a movestart event there, to show what I want, but it doesn't actually exist I think.
Use Case! one might ask: I have stops on maps that have nearly fullscreen infowindows. Users can switch to next marker from infowindow. I make the windows translucent to show the map panning underneath, so users get a context of where next location is. This work's great in OpenLayers2 with movestart and moveend events. But in the new OL3 version of the map, I can't get the movestart event.
Update: I did answer the question my self, but I am still offering bounty if anyone would like to propose a better solution.
UPDATE v4.2.0 now supports native movestart and moveend events
map.on('movestart', function(event) {
//To Remove after first use: ol.Observable.unByKey(event);
});
map.on('moveend', function(event) {
//To Remove after first use: ol.Observable.unByKey(event);
});
For OpenLayers 3 versions before release of v4.2.0
Okay so in the mean while without the movestart event, and with the moveend only triggering if there is a actual movement in map, here's how I was able to achive movestart and moveend behavior.
jsFiddle:
var pan = ol.animation.pan({
duration: 700,
source: this.map.getView().getCenter()
});
map.beforeRender(function(map, frameState) {
var stillPanning = pan(map, frameState); // returns false panning is done
if (stillPanning) {
// do movestart stuff here
if (!everDone) {
doSomething();
everDone = true;
}
} else {
// do move end stuff here
undoSomething();
everDone = false;
}
return stillPanning;
});
map.getView().setCenter(geom);
So why this works?
ol.animation.pan returns a ol.PreRenderFunction, which returns false if animation is not complete
Writing custom function and providing it to map.renderBefore can be now used to write a wrapper around pan animation as shown above
The whole business with everDone is because, stillPanning section will get called multiple times. This is okay if what you want to do there can take repeated calls, but if you want to toggle something then you want to do it only once.
behavior of 'moveend'
moveend callback is only triggered if map actually moves. This is fine, but it prevents us from doing pre-animation activities, by just doing them before animation done. If you had a scenario where map doesn't actually move, then what ever you did before animation will never undo because that behavior is in moveend which never gets called!
Hope this helps someone. I had to spend good two hours to get it to work for me, because a movestart callback is absent :(
UPDATE
Upon more discussion on this thread there is another solution as suggested by #ahocevar. That is to use the propertychange event on the view like so:
function onpropertychange() {
map.dispatchEvent('movestart');
var view = map.getView();
view.un('propertychange', onpropertychange);
map.on('moveend', function() {
view.on('propertychange', onpropertychange);
});
};
map.getView().on('propertychange', onpropertychange);
Here's a working example of this approach: jsFiddle
you could use the pointerdrag or pointermove event, but you will want to debounce them. I did so here with a variable called dragStarted
http://jsfiddle.net/sean9999/j2cP4/115/
http://openlayers.org/en/v3.8.2/apidoc/ol.MapBrowserEvent.html
I have created a Kineticjs scene with a scrollable background. On top of this background is a rect with an event listener attached. My question is, what could cause this event listener to not fire after I move the background and draw the scene. I don't know what it could be and I am even calling .moveToTop() on everything to see if I could move the shape back to the top even though I am pretty sure it still is. So what could cause an event listener to stop firing after a draw?
Does anybody know a fix for this? I figure I could might be able to attach another event listener to the shape, but this seems unnecessary if I am doing something fundamentally wrong.
Thanks in advance!
Edit: Here is some code.
// Here is the event listener attached to scroll bar
hscroll4.on('dragmove', updateBackgroundPos4);
// Here is code to move background
var updateBackgroundPos4 = function() {
var hscrollPos = hscroll4.getX();
console.log("mb4: ", mainBody4Dynamic.getX());
mainDynamicWrapper.setX(-hscrollPos+120); //the BG I am moving on scroll
// my attempt at getting it to work
dynamicLayer4.moveToTop();
mainBody4.moveToTop();
mainDynamicWrapper.moveToTop();
newFolder.moveToTop();
dynamicLayer4.draw();
//stage4.drawHit();
};
// Here is the group which contains the rectangle
folderGroup.on('mouseover', function() { //---- this isn't firing after draw
document.body.style.cursor = 'pointer';
console.log("change text");
updateTestText();
});
folderGroup.on('mouseout', function() {
document.body.style.cursor = 'default';
});
Edit 2: even my suggestion does not work. Adding the event listener back does not make it clickable again :(
Alright I got it! I found a thread which said to create an dragend event on the scrollbar then call layer.moveToTop() and layer.draw(). So putting it in dragmove was not enough for the program to register click events. The reasoning behind this was:
"When you use a drag event, KineticJS create a temporary layer on top as a result of which your events where not getting registered after the dragmove."
Here is the thread if anybody is interested:
LINK TO THREAD
I am in the process of profiling Sencha Touch applications and came across the fact that a click of a button triggers action faster as opposed to a click of a list item from Ext.List for the same action. My timeline profiling data indicates that the action is performed on Timer Fired condition for list item. This timer's timeout is 300ms. Now, for buttons there's no timer, so the action is performed as soon as there's touch end (and other Sencha processing common to all clicks).
In my case, the action is a simple transition to another view without any animation.
Following are the screenshot of my timeline data running application on an iPhone 4.
Transition by button click/tap:
Transition by list item click/tap:
I tried to dig into the source code, but could not understand why this is actually happening. My hypothesis is that list waits for that 300ms to see if it was actually a tap action or a scroll action. But is this true? If not, can anyone point me towards the right direction to verify if this hypothesis is true or not?
Any help would be highly appreciated!
I think is because of the pressedDelay config, which for Ext.Button default is 0 and for Ext.DataView is 100 ms.
Aditionally, the button fires directly the handler function. And the dataView executes store.getAt(index) to find the record object and pass it to the itemTap callback what adds some ms.
Got it!
This 300ms wasn't because of the scroll event, rather it was to recognize if its a single or a double tap event. If you look at DoubleTap recognizer source code, it has a maxDuration of 300 ms in the config object. This is used to set the time out for firing singleclick event.
onEnd function:
else {
this.singleTapTimer = setTimeout(function() {
me.fireSingleTap(e, touch);
}, maxDuration);
}
And on every touchStart event, this timeout is cleared.
onTouchStart: function(e) {
if (this.callParent(arguments) === false) {
return false;
}
this.startTime = e.time;
clearTimeout(this.singleTapTimer);
},
To note, this is a private class, so we cannot rely on it. But if anyone wants to decrease the duration between a tap event and firing off its logic, reduce this time. I have noticed that setting it to 150ms will make list item click much much faster, but at the same time, it also opens up the room for ghost click in other screens, since the events are queued up.
You can disable or edit recognizers configuration in Ext.application: http://www.sencha.com/forum/showthread.php?205692-Reduce-delay-of-itemsingletap-on-xtype-list
a need to speed up links with onClick attr in Phonegap app.
I would like to use Fast buttons plugin, that i found here:
https://developers.google.com/mobile/articles/fast_buttons
But i dont know, how to right use this plugin should i add this after pageinit or where?
Maybe is it quite silly question, but if i tried to find some examples, with no luck.
Could You add somebody add put here some example, how solve this problem?
Many thanks.
The touchstart (or touchend) event works great if you know the user won't be scrolling. That's actually the reason click events take so long to resolve on mobile devices, the device is waiting to see if the user is scrolling or clicking.
This will perform quite fast as there is no delay for dispatching this event:
$('#myButton').on('touchstart', function () {
//run click code now
});
You can also use jQuery Mobile's vclick event which attempts to use the native touch events but it's main problem is that you can dispatch multiple events using vclick so you should set a timeout to only allow one click at a time, for example:
var clickOk = true;
$('#myButton').on('vclick', function () {
if (clickOk === true) {
clickOk = false;
setTimeout(function () {
clickOk = true;
}, 350);
//run click code now
}
return false;
});
This will allow the event handler to run only once per 350ms which will take care of the multiple events being dispatched since the second event will be ignored.
I would set these event handlers up in a delegated event handler that runs when a pseudo-page gets initialized:
$(document).on('pageinit', '.ui-page', function () {
//bind "fast-click" event handlers now, use "$(this).find(...)" to only bind to elements of the current pseudo-page
});
Jiri If it's not too late I had to do the same thing for my app and needed to pass parameters to the function. I did it by placing the parameters in the id of the button (separarted by underscores) and using this function which grabs the id from every clicked button with a classname of "clickbutton" and splits it into the individual parameters.
$('.clickbutton').live('click', function(event) {
event.preventDefault();
var id = $(this).attr('id');
var parts = $(this).attr('id').split("_");
var item = parts[0];
var button = parts[1];
var type = parts[2];
console.log(item+button+type);
getItemCondition(item,type);
return false;
});
Still having issues with unresponsiveness from JQM click event though!
What about fastclick ?
FastClick is a simple, easy-to-use library for eliminating the 300ms delay between a physical tap and the firing of a click event on mobile browsers. The aim is to make your application feel less laggy and more responsive while avoiding any interference with your current logic.