Selecting zones for touch events with jQuery - javascript

I'm using https://github.com/n33/jquery.touch for creating touch events.
Wanting to use some gestures around all the body but the only map object with id "map".
I'm trying with:
$('body').not('#map');
and other variations, but these gestures still work in the map.
My code:
var touch = $('#body').not('#map');
touch.enableTouch({useMouse: true});
touch.on('doubleTap', function() { gestures("double"); });

If you are trying to add an event handler you'd need to do something like:
var touch = $('#body'),
exclude = $('#map');
touch.enableTouch({useMouse: true});
touch.on('doubleTap', function(e) {
var $touchedElement = $(e.target);
if (!$touchedElement.is(exclude) {
gestures("double");
}
});

You probably have to set this in the selector itself.
$('body:not(#map)').touchFunction();

Related

Add event listener to element after DOMContentLoaded

I have some trouble with adding event listener to element after DOM updating.
I have some page, that sort two lists and save the stage.
I can move elements between this lists by d&d and by clicking special button. And it work fine for me.
https://jsfiddle.net/bmj32ma0/2/
But, I have to save stage of this lists, and after reloading I have to extract stage, so I write code below.
function saveFriendsLists(e) {
if(e.target.classList.contains("b--drugofilter--save-button")){
var vkFriends = document.querySelector('.b--friends-from-vk .js--friends-container').innerHTML;
var choosenFriends = document.querySelector('.b--friends-choosen .js--friends-container').innerHTML;
localStorage.setItem('vkFriends', vkFriends);
localStorage.setItem('choosenFriends', choosenFriends);
}
}
function loadFriensListFromStorage() {
if(localStorage&&localStorage.choosenFriends&&localStorage.vkFriends){
document.querySelector('.b--friends-from-vk .js--friends-container').innerHTML = localStorage.vkFriends;
document.querySelector('.b--friends-choosen .js--friends-container').innerHTML = localStorage.choosenFriends;
}
}
document.addEventListener("DOMContentLoaded", loadFriensListFromStorage);
But after adding this, the preview functionality like D&D doesn't work. And I can't provide you valid jsfidle because, as I can understand, localStoradge reason or something.
When I tried to move my addEventListener to loadFriensListFromStorage function, like this:
function loadFriensListFromStorage() {
if(localStorage&&localStorage.choosenFriends&&localStorage.vkFriends){
document.querySelector('.b--friends-from-vk .js--friends-container').innerHTML = localStorage.vkFriends;
document.querySelector('.b--friends-choosen .js--friends-container').innerHTML = localStorage.choosenFriends;
}
[].forEach.call(friends, function(friend) {
friend.addEventListener('dragstart', handleDragStart, false);
});
}
But that doesn't have any effect.
How can I fix this issue? Thx.

Javascript events on top-of-window enter and leave?

I'm seeking a mouse event to detect when the mouse enter the top of the window, and leaves the top of the window. I don't mean the top of the webpage, but the top of the window.
There's no pre-existing "element" on the page i'm trying to attach the event to, but i think programmatically adding an invisible, fixed html element to the top of the page might be ok.
I like the clientY method with onmousemove, but that will fire repeatedly, which i don't want-- only want firing on enter and leave. Don't want my code to have to handle multiple firings.
This should work with ANY webpage-- i do not have any control over the HTML on the page (except for elements i add to the page programmatically).
Need only support modern browsers, simplest method possible, no jquery.
This method works great! But it prevents clicking elements behind it, which is not ok.
(function (){
var oBanana = document.createElement("div");
oBanana.style.position = "fixed"
oBanana.style.top = "0"
oBanana.style.left = "0"
oBanana.style.height= "100px"
oBanana.style.width = "100%"
oBanana.addEventListener("mouseover", function(event) {alert('in');});
oBanana.addEventListener("mouseout", function(event) {alert('out');});
document.body.appendChild(oBanana);
})();
Next i tried this, which inserts a small hotzone at the top of the page. I realized that, due to my scenario, i DON'T want mouse-out on the hotzone-- rather i want mouseover on everything BELOW the hotzone. Here's my first attempt at that, but fails because the hotzone gets the body event, plus the body event fires repeatedly:
(function (){
var oHotzone = document.createElement("div");
oHotzone.id = "fullscreen-hotzone"
oHotzone.style.position = "fixed"
oHotzone.style.top = "0"
oHotzone.style.left = "0"
oHotzone.style.height= "10px"
oHotzone.style.width = "100%"
oHotzone.addEventListener("mouseover", function(event) {alert('hotzone');});
document.body.appendChild(oHotzone);
document.body.style.marginTop = "10px"
document.body.addEventListener("mouseover", function(event) {alert('body');});
})();
Appreciate any help!
Thx!
It's the simplest you can do with vanilla javascript.
Function:
// create a one-time event
function onetime(node, type, callback) {
// create event
node.addEventListener(type, function(e) {
// remove event
e.target.removeEventListener(e.type, arguments.callee);
// call handler
return callback(e);
});
}
Implementation:
// one-time event
onetime(document.getElementById("hiddenTopElement"), "mouseenter", handler);
onetime(document.getElementById("hiddenTopElement"), "mouseleave" , hanlder);
// handler function
function handler(e) {
alert("You'll only see this once!");
}
my OP could have probably been stated better, but i'm happy with this solution. The fixed div blocked hover events on the body below, so the body hover event does not happen until the mouse leaves the hotzone. Perfect.
// create hotzone and add event
var oHotzone = document.createElement("div");
oHotzone.id = "fullscreen-hotzone"
oHotzone.style.position = "fixed"
oHotzone.style.top = "0"
oHotzone.style.left = "0"
oHotzone.style.height= "10px"
oHotzone.style.width = "100%"
oHotzone.addEventListener("mouseenter", function(event) {alert('hotzone');});
document.body.appendChild(oHotzone);
document.body.addEventListener("mouseenter", function(event) {alert('body');});

How to implement Swipe Gesture in IonicFramework?

I want to attach swipe left & swipe right on an image using IonicFramework.
From the documentation, I only got these, but no example yet:
http://ionicframework.com/docs/api/service/$ionicGesture/
http://ionicframework.com/docs/api/utility/ionic.EventController/#onGesture
Can anyone help provide sample HTML & JS to listen to gesture event?
P.S.: Previously, I managed to implement it using angularjs SwipeLeft and SwipeRight directive: https://docs.angularjs.org/api/ngTouch/service/$swipe . But now I wish to use the functions provided by ionicframework.
Ionic has a set of directives that you can use to manage various gestures and events. This will attach a listener to an element and fire the event when the particular event is detected. There are events for holding, tapping, swiping, dragging, and more. Drag and swipe also have specific directives to only fire when the element is dragged/swiped in a direction (such as on-swipe-left).
Ionic docs: http://ionicframework.com/docs/api/directive/onSwipe/
Markup
<img src="image.jpg" on-swipe-left="swipeLeft()" />
Controller
$scope.swipeLeft = function () {
// Do whatever here to manage swipe left
};
You can see some of sample which you can do with ionic from this site. One of the drawback is that the gesture will fire multiple instances during drag. If you catch it with a counter you can check how much the instances being fired per gesture. This is my hack method within the firing mechanism of of drag gesture you might need to change the dragCount integer to see which one is suite for your instance.
var dragCount = 0;
var element = angular.element(document.querySelector('#eventPlaceholder'));
var events = [{
event: 'dragup',
text: 'You dragged me UP!'
},{
event: 'dragdown',
text: 'You dragged me Down!'
},{
event: 'dragleft',
text: 'You dragged me Left!'
},{
event: 'dragright',
text: 'You dragged me Right!'
}];
angular.forEach(events, function(obj){
var dragGesture = $ionicGesture.on(obj.event, function (event) {
$scope.$apply(function () {
$scope.lastEventCalled = obj.text;
//console.log(obj.event)
if (obj.event == 'dragleft'){
if (dragCount == 5){
// do what you want here
}
dragCount++;
if (dragCount > 10){
dragCount = 0;
}
//console.log(dragCount)
}
if (obj.event == 'dragright'){
if (dragCount == 5){
// do what you want here
}
dragCount++;
if (dragCount > 10){
dragCount = 0;
}
//console.log(dragCount)
}
});
}, element);
});
add this line in your html template
<ion-content id="eventPlaceholder" has-bouncing="false">{{lastEventCalled}}</ion-content>

Openlayers and catching drag event

Im using OpenLayers and i need to be able to tell difference between when map has been moved by my own scrip or by user. Yeah im aware that i can use moveend. But it also triggers when the same script is moving or repositioning map based on incoming data from ajax calls. So moveend or other map events wont work.
I did some googling and found OpenLayers.Hander.Drag. But all that i managed with it was to stop users from dragging map.
My script:
this.dragger = new OpenLayers.Handler.Drag('',{
'dragStart': function(evt){
this.userdragged = true;
console.log('drag');
}},{
'map':this.mymap
});
this.dragger.activate();
As you can see, i tried to set userdragged variable to true to use this same variable in moveend event later. Unfortunately all this did was to stop my map from beeing draggable.
Can someone assist me please?
Alan
Got it!
What got it working was :
dragcontrol = new OpenLayers.Control.DragPan({'map':this.mymap, 'panMapDone':function(evt){
this.userdragged = true;
console.log('drag');
}});
dragcontrol.draw();
this.mymap.addControl(dragcontrol);
dragcontrol.activate();
Booyaka!
Edit:
Actually this.userdragged wont work in there... the scope of this is different there. you would need to do something like var that = this; before that object initialization and use that.userdragged = true....
Edit2:
I later found, that this panMapDone function overwrites DragPans own method which has same name. With just my previous example, you can end up with map that results in vector features going out of sync with map, when user drags map. To stop that from happening, you should copy the original functionality into that function too... to make it look something like that:
dragcontrol = new OpenLayers.Control.DragPan({'map':this.mymap, 'panMapDone':function(xy){
if(this.panned) {
var res = null;
if (this.kinetic) {
res = this.kinetic.end(xy);
}
this.map.pan(
this.handler.last.x - xy.x,
this.handler.last.y - xy.y,
{dragging: !!res, animate: false}
);
if (res) {
var self = this;
this.kinetic.move(res, function(x, y, end) {
self.map.pan(x, y, {dragging: !end, animate: false});
});
}
this.panned = false;
}
that.userdragged = true;
// do whatever you want here
}});
dragcontrol.draw();
this.mymap.addControl(dragcontrol);
dragcontrol.activate();
Alan
Looking at the documentation on Drag handlers, it states that it's supposed to be used with a Control object. Are you using it that way? Maybe the code snippet doesn't show it?
"If a handler is being used without a control, the handlers setMap method must be overridden to deal properly with the map."
I haven't tried it, but it seems as you should go for something like this:
var myControl = new OpenLayers.Control();
var dragger = new OpenLayers.Handler.Drag{
control: myControl,
callbacks: { 'done': function() { // do something }},
options: {}
}
myMap.addControl(myControl);
myControl.activate();
Just posting an example here of executing an arbitrary function when the user drag the map, without interfering with the normal click-drag used to pan the map, because this page was the most frequent result during my search to find how to do that.
var CustomDragControl = OpenLayers.Class(OpenLayers.Control, {
defaultHandlerOptions: {
'stopDown': false
/* important, otherwise it prevent the click-drag event from
triggering the normal click-drag behavior on the map to pan it */
},
initialize: function(options) {
this.handlerOptions = OpenLayers.Util.extend(
{}, this.defaultHandlerOptions
);
OpenLayers.Control.prototype.initialize.apply(
this, arguments
);
this.handler = new OpenLayers.Handler.Drag(
this, {
'down': this.onDown //could be also 'move', 'up' or 'out'
}, this.handlerOptions
);
},
onDown: function(evt) {
// do something when the user clic on the map (so on drag start)
console.log('user clicked down on the map');
}
});
then add the control to you map's controls list when creating the map instance, or with a map.addControl(), with
new CustomDragControl ({'autoActivate': true})
i have use that in OpenLayers 6:
map.on('pointerdrag', function (event) {
is_map_center = false;
})
hf gl!

Webkit transitionEnd event grouping

I have a HTML element to which I have attached a webkitTransitionEnd event.
function transEnd(event) {
alert( "Finished transition!" );
}
var node = document.getElementById('node');
node.addEventListener( 'webkitTransitionEnd', transEnd, false );
Then I proceed to change its CSS left and top properties like:
node.style.left = '400px';
node.style.top = '400px';
This causes the DIV to move smoothly to the new position. But, when it finishes, 2 alert boxes show up, while I was expecting just one at the end of the animation. When I changed just the CSS left property, I get one alert box - so this means that the two changes to the style are being registered as two separate events. I want to specify them as one event, how do I do that?
I can't use a CSS class to apply both the styles at the same time because the left and top CSS properties are variables which I will only know at run time.
Check the propertyName event:
function transEnd(event) {
if (event.propertyName === "left") {
alert( "Finished transition!" );
}
}
var node = document.getElementById('node');
node.addEventListener( 'webkitTransitionEnd', transEnd, false );
That way, it will only fire when the "left" property is finished. This would probably work best if both properties are set to the same duration and delay. Also, this will work if you change only "left", or both, but not if you change only "top".
Alternatively, you could use some timer trickery:
var transEnd = function anon(event) {
if (!anon.delay) {
anon.delay = true;
clearTimeout(anon.timer);
anon.timer = setTimeout(function () {
anon.delay = false;
}, 100);
alert( "Finished transition!" );
}
};
var node = document.getElementById('node');
node.addEventListener( 'webkitTransitionEnd', transEnd, false );
This should ensure that your code will run at most 1 time every 100ms. You can change the setTimeout delay to suit your needs.
just remove the event:
var transEnd = function(event) {
event.target.removeEventListener("webkitTransitionEnd",transEnd);
};
it will fire for the first property and not for the others.
If you prefer it in JQuery, try this out.
Note there is an event param to store the event object and use within the corresponding function.
$("#divId").bind('oTransitionEnd transitionEnd webkitTransitionEnd', event, function() {
alert(event.propertyName)
});
from my point of view the expected behaviour of the code would be to
trigger an alert only when the last transition has completed
support transitions on any property
support 1, 2, many transitions seamlessly
Lately I've been working on something similar for a page transition manager driven by CSS timings.
This is the idea
// Returs the computed value of a CSS property on a DOM element
// el: DOM element
// styleName: CSS property name
function getStyleValue(el, styleName) {
// Not cross browser!
return window.getComputedStyle(el, null).getPropertyValue(styleName);
}
// The DOM element
var el = document.getElementById('el');
// Applies the transition
el.className = 'transition';
// Retrieves the number of transitions applied to the element
var transitionProperties = getStyleValue(el, '-webkit-transition-property');
var transitionCount = transitionProperties.split(',').length;
// Listener for the transitionEnd event
function eventListener(e) {
if (--transitionCount === 0) {
alert('Transition ended!');
el.removeEventListener('webkitTransitionEnd', eventListener);
}
}
el.addEventListener('webkitTransitionEnd', eventListener, false);
You can test here this implementation or the (easier) jQuery version, both working on Webkit only
If you are using webkit I assume you are mobilizing a web-application for cross platform access.
If so have you considered abstracting the cross platform access at the web-app presentation layer ?
Webkit does not provide native look-and-feel on mobile devices but this is where a new technology can help.

Categories

Resources