mouseup/down on entire SPA angular - javascript

In my component class I have
#HostListener('document:mousedown', ['$event'])
onMouseDown() {
this.holding = true;
}
#HostListener('document:mouseup', ['$event'])
onMouseUp() {
this.holding = false;
}
In this project I'm also using swiper library. My swiper is 200px height and 100% width. Swiper use some own events catching for "grabing" elements to make it actually swipeable.
Now when I have my mouse on top of swiper element and I click above code doesn't catch the event.
This shoudln't happen but it is. Also what make it even weirder is that it doesn't catch only the left mouse click, right click works correctly.
How to make it works even when mouse is on top of swiper?
Edit
For some reason I'm not able to reproduce issue at online code playground, so I've created very basic app with just two components and I pushed it to git.
In this project I'm displaying {{ holding }} and as you can see (if you clone and ng serve this app) when clicking at the top or bottom of page it change from false to true but when clicking on swiper it doesn't catch onMouseDown and the value doesn't change.

because Swiper prevent the dispatching of internal DOM element, you can use Event API from swiper to get what is happening inside Swiper main dom element.
For example on your case you can do something like this :
this.mySwiper = new Swiper('.nav', {
paginationClickable: false,
grabCursor: true,
loop: true,
autoplay: 1000,
slidesPerView: 3,
spaceBetween: 50
});
this.mySwiper.on('touchStart', () => {
this.touchService.triggerTouchStart();
});
this.mySwiper.on('touchEnd', () => {
this.touchService.triggerTouchStop();
});
You can introduce new service on your application to abstract to the rest of your application this trick to be binded on all mousedown | mouseup events. bellow you can find the implementation :
export class TouchService {
private _manualControl$: Subject<boolean>;
constructor() {
this._manualControl$ = new Subject();
// React to the document mouse event.
fromEvent(document, 'mousedown').subscribe(() => this.triggerTouchStart());
fromEvent(document, 'mouseup').subscribe(() => this.triggerTouchStop());
}
// Can be call manually to force new state.
triggerTouchStart(): void {
this._manualControl$.next(true);
}
triggerTouchStop(): void {
this._manualControl$.next(false);
}
get touch$(): Observable<boolean> {
return this._manualControl$.asObservable();
}
}
Now you have observable which react on native mousedown and mouseup events and can also be trigger by manual API call like
this.mySwiper.on('touchStart', () => {
this.touchService.triggerTouchStart();
});
this.mySwiper.on('touchEnd', () => {
this.touchService.triggerTouchStop();
});
Finally you can use this service like following :
constructor(private touchService: TouchService) {
this.touchService.touch$.subscribe(e => this.holding = e);
}
I can't prupose you pull request on your project because i don't have right to do it. You can see it in action here
git remote add fork https://bitbucket.org/yghidouche/ng-hover-issue
git fetch fork issues_1

Related

how can i Pause vue-panZoom

I have a Grid with vue-panZoom
inside it there is a vue-draggable-resizable area like in the image below
Image
When i drag the (vue-draggable-resizable) gray square, the black (pan-zoom) rectangle also moves.
when the gray square is selected, the panZoom must be locked or in the beforeMouseDown & beforeWheel mode state.
<panZoom :options="{transformOrigin: null, beforeWheel, beforeMouseDown}">
<vue-draggable-resizable ***#dragging="onDrag"*** ref="draggable" :active="true" #dragstop="updatePreview" #resizestop="updatePreview">
there is also this method in the panzoom documentation but i don't know if it could work in vue too:
Pause/resume the panzoom You can pause and resume the panzoom by
calling the following methods:
var element = document.getElementById('scene');
var instance = panzoom(element);
instance.isPaused(); // returns false
instance.pause(); // Pauses event handling
instance.isPaused(); // returns true now
instance.resume(); // Resume panzoom
instance.isPaused(); // returns false again
how can i solve? Thanks in advance
Yes, those methods should work with Vue.js. All you have to do is access $panZoomInstance via ref.
<pan-zoom ref='panZoom'>
<img src="https://picsum.photos/300">
</pan-zoom>
methods: {
pause() {
this.$refs.panZoom.$panZoomInstance.pause()
},
resume() {
this.$refs.panZoom.$panZoomInstance.resume()
}
}
Example

IntersectionObserver Lazy Loading not Working

This is my first time attempting Lazy Loading, and I wanted to use IntersectionObserver. Got started by following along with this website. I honestly just want the content of the page to wait to load until it is less than 50% of the viewport's width below the viewport. I'm not sure how to observe all content, so I just selected the classes for the widgets that are being displayed, as they are the main content. Unfortunately my code doesn't seem to be doing much. I added a console.log at the beginning to make sure the file was linked correctly, and I tried to add more console.logs to log when the widget moves in and out of the capture area. The first console.log works, but nothing else happens.
Here is what I have:
console.log('file loaded');
const widgets = document.querySelectorAll('.widget');
const config = {
root: null,
rootMargin: '-50px 0px -55% 0px',
threshold: .5
};
let isLeaving = false;
let observer = new IntersectionObserver(function(entries, self) {
entries.forEach(entry => {
if (entry.isIntersecting) {
// we are ENTERING the "capturing frame". Set the flag.
isLeaving = true;
// Do something with entering entry
console.log("Widget loaded.");
self.unobserve(entry.target);
} else if (isLeaving) {
// we are EXITING the "capturing frame"
isLeaving = false;
// Do something with exiting entry
console.log("Widget is exiting.")
}
});
}, config);
widgets.forEach(widget => {
observer.observe(widget);
});
This code is in it's own js file. Where should I be linking it in the HTML file?
I'd appreciate any help I can get! Let me know if I need to provide more information.

How to auto-slide the window out from behind keyboard when TextInput has focus?

I've seen this hack for native apps to auto scroll the window, but wondering best way to do it in React Native... When a <TextInput> field gets focus and is positioned low in the view, the keyboard will cover up the text field.
You can see this issue in example UIExplorer's TextInputExample.js view.
Does anyone have a good solution?
2017 Answer
The KeyboardAvoidingView is probably the best way to go now. Check out the docs here. It is really simple compared to Keyboard module which gives Developer more control to perform animations. Spencer Carli demonstrated all the possible ways on his medium blog.
2015 Answer
The correct way to do this in react-native does not require external libraries, takes advantage of native code, and includes animations.
First define a function that will handle the onFocus event for each TextInput (or any other component you would like to scroll to):
// Scroll a component into view. Just pass the component ref string.
inputFocused (refName) {
setTimeout(() => {
let scrollResponder = this.refs.scrollView.getScrollResponder();
scrollResponder.scrollResponderScrollNativeHandleToKeyboard(
React.findNodeHandle(this.refs[refName]),
110, //additionalOffset
true
);
}, 50);
}
Then, in your render function:
render () {
return (
<ScrollView ref='scrollView'>
<TextInput ref='username'
onFocus={this.inputFocused.bind(this, 'username')}
</ScrollView>
)
}
This uses the RCTDeviceEventEmitter for keyboard events and sizing, measures the position of the component using RCTUIManager.measureLayout, and calculates the exact scroll movement required in scrollResponderInputMeasureAndScrollToKeyboard.
You may want to play around with the additionalOffset parameter, to fit the needs of your specific UI design.
Facebook open sourced KeyboardAvoidingView in react native 0.29 to solve this problem. Documentation and usage example can be found here.
We combined some of the code form react-native-keyboard-spacer and the code from #Sherlock to create a KeyboardHandler component that can be wrapped around any View with TextInput elements. Works like a charm! :-)
/**
* Handle resizing enclosed View and scrolling to input
* Usage:
* <KeyboardHandler ref='kh' offset={50}>
* <View>
* ...
* <TextInput ref='username'
* onFocus={()=>this.refs.kh.inputFocused(this,'username')}/>
* ...
* </View>
* </KeyboardHandler>
*
* offset is optional and defaults to 34
* Any other specified props will be passed on to ScrollView
*/
'use strict';
var React=require('react-native');
var {
ScrollView,
View,
DeviceEventEmitter,
}=React;
var myprops={
offset:34,
}
var KeyboardHandler=React.createClass({
propTypes:{
offset: React.PropTypes.number,
},
getDefaultProps(){
return myprops;
},
getInitialState(){
DeviceEventEmitter.addListener('keyboardDidShow',(frames)=>{
if (!frames.endCoordinates) return;
this.setState({keyboardSpace: frames.endCoordinates.height});
});
DeviceEventEmitter.addListener('keyboardWillHide',(frames)=>{
this.setState({keyboardSpace:0});
});
this.scrollviewProps={
automaticallyAdjustContentInsets:true,
scrollEventThrottle:200,
};
// pass on any props we don't own to ScrollView
Object.keys(this.props).filter((n)=>{return n!='children'})
.forEach((e)=>{if(!myprops[e])this.scrollviewProps[e]=this.props[e]});
return {
keyboardSpace:0,
};
},
render(){
return (
<ScrollView ref='scrollView' {...this.scrollviewProps}>
{this.props.children}
<View style={{height:this.state.keyboardSpace}}></View>
</ScrollView>
);
},
inputFocused(_this,refName){
setTimeout(()=>{
let scrollResponder=this.refs.scrollView.getScrollResponder();
scrollResponder.scrollResponderScrollNativeHandleToKeyboard(
React.findNodeHandle(_this.refs[refName]),
this.props.offset, //additionalOffset
true
);
}, 50);
}
}) // KeyboardHandler
module.exports=KeyboardHandler;
First you need to install react-native-keyboardevents.
In XCode, in the project navigator, right click Libraries ➜ Add
Files to [your project's name] Go to node_modules ➜
react-native-keyboardevents and add the .xcodeproj file
In XCode, in the
project navigator, select your project. Add the lib*.a from the keyboardevents
project to your project's Build Phases ➜ Link Binary With Libraries Click
.xcodeproj file you added before in the project navigator and go the Build
Settings tab. Make sure 'All' is toggled on (instead of 'Basic').
Look for Header Search Paths and make sure it contains both
$(SRCROOT)/../react-native/React and $(SRCROOT)/../../React - mark
both as recursive.
Run your project (Cmd+R)
Then back in javascript land:
You need to import the react-native-keyboardevents.
var KeyboardEvents = require('react-native-keyboardevents');
var KeyboardEventEmitter = KeyboardEvents.Emitter;
Then in your view, add some state for the keyboard space and update from listening to the keyboard events.
getInitialState: function() {
KeyboardEventEmitter.on(KeyboardEvents.KeyboardDidShowEvent, (frames) => {
this.setState({keyboardSpace: frames.end.height});
});
KeyboardEventEmitter.on(KeyboardEvents.KeyboardWillHideEvent, (frames) => {
this.setState({keyboardSpace: 0});
});
return {
keyboardSpace: 0,
};
},
Finally, add a spacer to your render function beneath everything so when it increases size it bumps your stuff up.
<View style={{height: this.state.keyboardSpace}}></View>
It is also possible to use the animation api, but for simplicity's sake we just adjust after the animation.
react-native-keyboard-aware-scroll-view solved the problem for me.
react-native-keyboard-aware-scroll-view on GitHub
Try this:
import React, {
DeviceEventEmitter,
Dimensions
} from 'react-native';
...
getInitialState: function() {
return {
visibleHeight: Dimensions.get('window').height
}
},
...
componentDidMount: function() {
let self = this;
DeviceEventEmitter.addListener('keyboardWillShow', function(e: Event) {
self.keyboardWillShow(e);
});
DeviceEventEmitter.addListener('keyboardWillHide', function(e: Event) {
self.keyboardWillHide(e);
});
}
...
keyboardWillShow (e) {
let newSize = Dimensions.get('window').height - e.endCoordinates.height;
this.setState({visibleHeight: newSize});
},
keyboardWillHide (e) {
this.setState({visibleHeight: Dimensions.get('window').height});
},
...
render: function() {
return (<View style={{height: this.state.visibleHeight}}>your view code here...</View>);
}
...
It worked for me. The view basically shrinks when the keyboard is displayed, and grows back again when its hidden.
Just wanted to mention, now there is a KeyboardAvoidingView in RN. Just import it and use it as any other module in RN.
Here is the link to the commit on RN:
https://github.com/facebook/react-native/commit/8b78846a9501ef9c5ce9d1e18ee104bfae76af2e
It is available from 0.29.0
They have also included an example on UIExplorer.
Maybe is to late, but the best solution is to use a native library, IQKeyboardManager
Just drag and drop IQKeyboardManager directory from demo project to your iOS project. That's it. Also you can setup some valus, as isToolbar enabled, or the space between text input and keyboard in the AppDelegate.m file. More details about customisation are in the GitHub page link that I've added.
I used TextInput.onFocus and ScrollView.scrollTo.
...
<ScrollView ref="scrollView">
...
<TextInput onFocus={this.scrolldown}>
...
scrolldown: function(){
this.refs.scrollView.scrollTo(width*2/3);
},
#Stephen
If you don't mind not having the height animate at exactly the same rate that the keyboard appears, you can just use LayoutAnimation, so that at least the height doesn't jump into place. e.g.
import LayoutAnimation from react-native and add the following methods to your component.
getInitialState: function() {
return {keyboardSpace: 0};
},
updateKeyboardSpace: function(frames) {
LayoutAnimation.configureNext(animations.layout.spring);
this.setState({keyboardSpace: frames.end.height});
},
resetKeyboardSpace: function() {
LayoutAnimation.configureNext(animations.layout.spring);
this.setState({keyboardSpace: 0});
},
componentDidMount: function() {
KeyboardEventEmitter.on(KeyboardEvents.KeyboardDidShowEvent, this.updateKeyboardSpace);
KeyboardEventEmitter.on(KeyboardEvents.KeyboardWillHideEvent, this.resetKeyboardSpace);
},
componentWillUnmount: function() {
KeyboardEventEmitter.off(KeyboardEvents.KeyboardDidShowEvent, this.updateKeyboardSpace);
KeyboardEventEmitter.off(KeyboardEvents.KeyboardWillHideEvent, this.resetKeyboardSpace);
},
Some example animations are (I'm using the spring one above):
var animations = {
layout: {
spring: {
duration: 400,
create: {
duration: 300,
type: LayoutAnimation.Types.easeInEaseOut,
property: LayoutAnimation.Properties.opacity,
},
update: {
type: LayoutAnimation.Types.spring,
springDamping: 400,
},
},
easeInEaseOut: {
duration: 400,
create: {
type: LayoutAnimation.Types.easeInEaseOut,
property: LayoutAnimation.Properties.scaleXY,
},
update: {
type: LayoutAnimation.Types.easeInEaseOut,
},
},
},
};
UPDATE:
See #sherlock's answer below, as of react-native 0.11 the keyboard resizing can be solved using built in functionality.
You can combine a few of the methods into something a little simpler.
Attach a onFocus listener on your inputs
<TextInput ref="password" secureTextEntry={true}
onFocus={this.scrolldown.bind(this,'password')}
/>
Our scroll down method looks something like :
scrolldown(ref) {
const self = this;
this.refs[ref].measure((ox, oy, width, height, px, py) => {
self.refs.scrollView.scrollTo({y: oy - 200});
});
}
This tells our scroll view (remember to add a ref) to scroll to down to the position of our focused input - 200 (it's roughly the size of the keyboard)
componentWillMount() {
this.keyboardDidHideListener = Keyboard.addListener(
'keyboardWillHide',
this.keyboardDidHide.bind(this)
)
}
componentWillUnmount() {
this.keyboardDidHideListener.remove()
}
keyboardDidHide(e) {
this.refs.scrollView.scrollTo({y: 0});
}
Here we reset our scroll view back to the top,
I'm using a simpler method, but it's not animated yet. I have a component state called "bumpedUp" which I default to 0, but set to 1 when the textInput gets focus, like this:
On my textInput:
onFocus={() => this.setState({bumpedUp: 1})}
onEndEditing={() => this.setState({bumpedUp: 0})}
I also have style that gives the wrapping container of everything on that screen a bottom margin and negative top margin, like this:
mythingscontainer: {
flex: 1,
justifyContent: "center",
alignItems: "center",
flexDirection: "column",
},
bumpedcontainer: {
marginBottom: 210,
marginTop: -210,
},
And then on the wrapping container, I set the styles like this:
<View style={[styles.mythingscontainer, this.state.bumpedUp && styles.bumpedcontainer]}>
So, when the "bumpedUp" state gets set to 1, the bumpedcontainer style kicks in and moves the content up.
Kinda hacky and the margins are hardcoded, but it works :)
I use brysgo answer to raise the bottom of my scrollview. Then I use the onScroll to update the current position of the scrollview. I then found this React Native: Getting the position of an element to get the position of the textinput. I then do some simple math to figure out if the input is in the current view. Then I use scrollTo to move the minimum amount plus a margin. It's pretty smooth. Heres the code for the scrolling portion:
focusOn: function(target) {
return () => {
var handle = React.findNodeHandle(this.refs[target]);
UIManager.measureLayoutRelativeToParent( handle,
(e) => {console.error(e)},
(x,y,w,h) => {
var offs = this.scrollPosition + 250;
var subHeaderHeight = (Sizes.width > 320) ? Sizes.height * 0.067 : Sizes.height * 0.077;
var headerHeight = Sizes.height / 9;
var largeSpace = (Sizes.height - (subHeaderHeight + headerHeight));
var shortSpace = largeSpace - this.keyboardOffset;
if(y+h >= this.scrollPosition + shortSpace) {
this.refs.sv.scrollTo(y+h - shortSpace + 20);
}
if(y < this.scrollPosition) this.refs.sv.scrollTo(this.scrollPosition - (this.scrollPosition-y) - 20 );
}
);
};
},
I also meet this question. Finally, I resolve it by defining the height of each scene, such as:
<Navigator
...
sceneStyle={{height: **}}
/>
And, I also use a third-party module https://github.com/jaysoo/react-native-extra-dimensions-android to get the real height.

What does rootmodifers do in famo.us?

I am new to Famo.us, can anybody explain me what does rootmodifers do in famo.us, here is its example
function SlideshowView () {
Views.apply(this, arguments);
this.rootModifier = new StateModifier({
size:this.options.size
});
this.mainNode = this.add(this.rootModifier);
_createLightBox.call(this);
_createSlides.call(this);
}
this.rootMidifier just allows you to have a way to control the entire slideShow's position, opacity, origin, or alignment later in the applications. More importantly this.rootModifier is added to the render node like this this.mainNode = this.add(this.rootModifier); This code places the modifier at the top of the render tree for the slideshow branch and exposes access to the modifier for later use in the all. For example later in the app you could have a function that changes the opacity.
SlideShow.prototype.hide = function() {
this.rootModifier.setOpacity(0, {duration: 3000});
}

clicking items inside a famo.us scrollview

I have a scrollview with a number of images.
events are working such that the scrollview can be dragged around.
i want to be able to click on a single image to get a detail view so used a:
surface.on 'click', => #parent.navTo('detail')
however, this has the effect that if i click an image when scrolling the above event will also fire.
i guess this is the whole reason mobile browsers have that 300ms delay - to tell if you're clicking or dragging. does Famous have other events to listen for?
In inputs/FastClick.js i only see 'touchstart' 'touchmove' and 'touchend'
do we have to track if a drag motion happened, in our own code, or does the famous engine assist with this?
FWIW i'm using a GenericSync to pipe the events around, and to make the view also work on the desktop.
constructor: (#parentView, #data) ->
SCROLLDIR = 1 # 0 horiz, 1 vertical
super({
direction: SCROLLDIR
paginated: true
pageStopSpeed: 5
})
#addContent()
#mouseSync = new famous.inputs.MouseSync({direction: SCROLLDIR})
#mouseSync.pipe(this)
addContent: () ->
comics = Comics.find()
surfaces = []
#sequenceFrom(surfaces)
for item in comics.fetch()
div = document.createElement('div')
comp = UI.renderWithData(Template.comicCover, item)
UI.insert(comp, div)
surface = new famous.core.Surface({
content: div
size: [undefined, 400]
properties:
backgroundColor: "#eff"
})
surfaces.push(surface)
surface.pipe(this)
surface.on 'click', => #parentView.navTo('comicPages')
# surface.pipe(#mouseSync)
return #surface
I have encountered a similar issue. To get around it, I simply track when the scrollview is scrolling and then ensure not scrolling on click.
Here is the code that I would add.. Hope it helps!
# In constructor
this.sync.on 'update', () => #scrolling = true
this.sync.on 'end', () => #scrolling = false
# In addContent
surface.on 'click', () =>
if !#scrolling
#parentView.navTo('comicPages')

Categories

Resources