How to toggle-off the react-native-elements tooltip from another component - tooltip

I want to manually close the tooltip but there are no documents on the react-native-elements site.
So I look over the tooltip code from github and noticed that it has a toggleTooltip function to toggle. Unfortunately I couldn't make it work.
This is the sample code for the tooltip
import { Tooltip } from 'react-native-elements';
render() {
return (
<Tooltip
ref="tooltip"
popover={
<ComponentTest
toggle={this.refs.tooltip}
>
>
<Text>Click me</Text>
</Tooltip>
);
}
The sample code for the ComponentTest
import { Button } from 'react-native-elements';
toggleOff = () => {
this.props.toggleTooltip;
}
render() {
return (
<Button
title="hide"
type="outline"
onPress={this.toggleOff}
/>
);
}
And this is the function from the tooltip.js that I am trying to use. The full code of the tooltip can found here https://github.com/react-native-training/react-native-elements/blob/master/src/tooltip/Tooltip.js
toggleTooltip = () => {
const { onClose } = this.props;
this.getElementPosition();
this.setState(prevState => {
if (prevState.isVisible && !isIOS) {
onClose && onClose();
}
return { isVisible: !prevState.isVisible };
});
};

i am new to react-native and was trying to use tooltip, what i found out that whenever u click inside the component which is popovered , it navigates to whatever onpress function u have written on that particular component and the tooltip doesn't closes,,it also remain mounted when u navigate to other pages,,one solution to it is that use react-native-popup-menu.its the best that we can use for now as a tooltip https://www.npmjs.com/package/react-native-popup-menu

It may be a stupid solution, but did you tried using this.props.toggleTooltip() ?
OH , and ref is not a string anymore, it's a function
<Tooltip
ref={ref => (this.tooltip = ref)}
popover={
<ComponentTest
toggle={this.tooltip}
>
>

On line 191 of Tooltip.js:
<TouchableOpacity onPress={this.toggleTooltip}>
{this.renderContent(true)}
</TouchableOpacity>
and in the definition of renderContent:112 on line 137, it is rendered your popover:
Thus wherever you touch in your popover will make it disappear. I don't know how to disable this behaviour, but I still want to know if and how the visibility of the popover can be controlled from the Tooltip's child element at least.

Just set its style to display:'none' after you touch your popover.
maybe try this way:
state = { theDisplay: 'flex' };
...
componentDidUpdate(prevProps: any) {
if (!prevProps.isFocused && this.props.isFocused) {
this.setState({ theDisplay: 'flex' });
}
}
...
<Popover.Item
value={'response'}
onSelect={() => {
this.setState({ theDisplay: 'none' });
navigate('NoticeResponse', { id: item.id });
}}>
<Text style={styles.toolsItem}>已读信息</Text>
</Popover.Item>
This is my own way of dealing with it. I hope it will help you.

DISCLAIMER I used the ref example in order to get my code to work, but it's something like this:
const tooltipRef = useRef(null);
const foo = (event, index) => {
event.stopPropagation();
tooltipRef.current.toggleTooltip()
}
...
<Tooltip
height={200}
ref={tooltipRef}
popover={<TouchableOpacity onPress={(event) => foo(event, index)}
/>
I had originally tried to implement this by simply using the tooltipRef.current.toggleTooltip() like in the example but it never ended up working because the event was propagating and continuing to toggle it on its own (effectively toggling it twice).

Without any 3rd party library, simple tooltip for both iOS and android can be implemented as follows:
onPress={() =>
Alert.alert("My Title", "My Msg", [], {
cancelable: true
})
}

React native elements documentation show that we can manually turn off the tooltip.
Docs
Store a reference to the Tooltip in your component by using the ref prop provided by React
const tooltipRef = useRef(null);
...
<Tooltip
ref={tooltipRef}
...
/>
Then you can manually trigger tooltip from anywhere for example when screen loads:
useEffect(() => {
tooltipRef.current.toggleTooltip();
}, []);

Related

Intersection Observer API not working in ios device when opening a webview in it but working perfectly in web, android , safari browser

`Below mentioned is my code for intersection observer
useIntersectionObserver
/* eslint-disable #typescript-eslint/no-shadow */
import { RefObject, useEffect, useState } from 'react';
export default function useIntersectionObserver(
elementRef: RefObject<Element>,
{ threshold = 0, root = null, rootMargin = '0%' }
) {
const [entry, setEntry] = useState<IntersectionObserverEntry>();
const callBackFunction = ([entry]: IntersectionObserverEntry[]): void => {
setEntry(entry);
};
useEffect(() => {
const node = elementRef?.current; // DOM Ref
const isIOSupported = !!window.IntersectionObserver;
if (!isIOSupported || !node) return;
const observerOptions = { threshold, root, rootMargin };
const observer = new IntersectionObserver(
callBackFunction,
observerOptions
);
observer.observe(node);
return () => observer.disconnect();`your text`
}, [elementRef, JSON.stringify(threshold), root, rootMargin]);
return entry;
}
Below is the code mentioned where I am calling useInterSectionObserver hook
const scrollDivElementRef = useRef<null | HTMLDivElement>(null);
const chatDivRef = useRef<null | HTMLDivElement>(null);
const entry = useIntersectionObserver(scrollDivElementRef, {});
const isVisible = !!entry?.isIntersecting;
Here scrollDivElementRef is the ref of div which we are observing for the intersection.It is basically our sentinal element.
Below mentioned is the useEffect hook which is going to perform some action when isVisible will become true.
Below mentioned is a code in react-native webview ,basically we are opening our react web app inside ios app , but our intersection observer is not able to detect changes . We have implemented intersection observer for infinite loading of messages. Every time user will scroll upwards , we will get "isVisible" as true and we will make an API call to fetch more messages.
useEffect(() => {
if (isVisible) {
dispatch(
getPostsForChannel(inputChannelId, true, channelMessages[0].timestamp)
);
}
}, [isVisible]);
<View style={styles.container}>
<WebView
style={{ marginTop: 40 }}
//TODO: Update the url
source={{ uri: 'http://192.168.1.2:3000' }}
onLoad={(syntheticEvent) => {
const { nativeEvent } = syntheticEvent;
}}
javaScriptEnabled={true}
onError={(e) => {
const { nativeEvent } = e;
setUrl(HOME_URL);
}}
onHttpError={() => {
setUrl(HOME_URL);
}}
onMessage={onMessage}
limitsNavigationsToAppBoundDomains={true}
// injectedJavaScript="window.octNativeApp=true"
injectedJavaScriptBeforeContentLoaded={initializeNativeApp}
scalesPageToFit={false}
setBuiltInZoomControls={false}
useWebView2
allowsInlineMediaPlayback={true}
mediaPlaybackRequiresUserAction={false}
></WebView>
</View>`
It will be really very helpful , if you people can help me with this problem.
Thanks & Regards
Mohit
I tried giving the height & width to the webview but it is also not working.Tried almost every piece of advise available in other platforms but not able to fic this`

Slatejs how to make one specific node non-editable?

I want to set one specific node non-editable by
Transforms.setNodes(editor,{at:[1]},{voids:true})
But it seems not working. Does anyone know how to do it? Thanks!
You need to make your element render with contentEditable prop to false
contentEditable={false} can also add style={{ userSelect: "none" }} to make it non selectable. You can make it dynamic base on the node props and set them them with the trasnformer.
export default function (props: any) {
const { attributes, children, element } = props;
const selected = useSelected()
const focused = useFocused()
return (
<span
{...attributes}
contentEditable={false}
style={{ userSelect: "none" }}
>
{
element.content
?
`【${element.content}】`
: null
}
{children}
</span>
)
}

Does Dart have childSelector in event function like jQuery on()?

Does Dart have childSelector in event function like jQuery on()? Because I want fire contextmenu event only if mouse hover specific element type.
This is my javascript code.
var $contextMenu = $("#context-menu");
$("body").on("contextmenu", "table tr", function(e) {
$contextMenu.css({
display: "block",
left: e.pageX,
top: e.pageY });
return false;
});
But I don't know how to check if hover "table tr" in my Dart code.
var body = querySelector('body');
var contextMenu =querySelector('#context-menu');
// fire in everywhere
body.onContextMenu.listen((e) {
e.preventDefault();
contextMenu.style.display = 'block';
contextMenu.style.left = "${e.page.x}px";
contextMenu.style.top = "${e.page.y}px";
}
You can filter events :
body.onContextMenu.where((e) => e.target.matchesWithAncestors("table tr"))
.listen((e) {
e.preventDefault();
contextMenu.style.display = 'block';
contextMenu.style.left = "${e.page.x}px";
contextMenu.style.top = "${e.page.y}px";
});
the problem is the following:
$("body") gives you a set of elements that does not change. The `.on(..., 'sub selector') however is actually bad, because it checks the subselector against the target of the event EVERY TIME for every event.
I see two solutions here:
The first is to select all children and add the event listener to all of the elements:
var body = querySelector('body');
body.querySelectorAll('table tr')... onContextMenu...
But this will not work if you insert tr into the table later.
The other way is to check the .target of your event and see if it's a tr and if its in your table. I hope this already helps. If you need more detailed help let me know!
Regards
Robert

Angularjs: jquery selectable

i have created a directive to handle selectable provided by Jquery
mydirectives.directive('uiSelectable', function ($parse) {
return {
link: function (scope, element, attrs, ctrl) {
element.selectable({
stop: function (evt, ui) {
var collection = scope.$eval(attrs.docArray)
var selected = element.find('div.parent.ui-selected').map(function () {
var idx = $(this).index();
return { document: collection[idx] }
}).get();
scope.selectedItems = selected;
scope.$apply()
}
});
}
}
});
to use in html
<div class="margin-top-20px" ui-selectable doc-array="documents">
where documents is an array that get returned by server in ajax response.
its working fine i can select multiple items or single item
Issue: i want to clear selection on close button
http://plnkr.co/edit/3cSef9h7MeYSM0cgYUIX?p=preview
i can write jquery in controller to remove .ui-selected class but its not recommended approach
can some one guide me whats the best practice to achieve these type of issue
Update:
i fixed the issue by broadcasting event on cancel and listening it on directive
$scope.clearSelection=function() {
$scope.selectedItems = [];
$timeout(function () {
$rootScope.$broadcast('clearselection', '');
}, 100);
}
and in directive
scope.$on('clearselection', function (event, document) {
element.find('.ui-selected').removeClass('ui-selected')
});
is this the right way of doing it or what is the best practice to solve the issue.
http://plnkr.co/edit/3cSef9h7MeYSM0cgYUIX?p=preview

Set Umbraco Property Editor Input to jQueryUI Datepicker

I'm close but still can't quite get this to work.
I have a new custom property editor that is loading correctly and is doing almost everything expected until I try to set the text field to be a jQuery UI element.
As soon as I add a directive in Angular for setting it to call the jQuery UI datepicker function, I get the following error suggesting it hasn't loaded the jQueryUI script library correctly:
TypeError: Object [object Object] has no method 'datepicker'
Trouble is, I can't see where I should be adding it as the logical places (to my mind, at least) seem to make no difference. Here is the code in full:
function MultipleDatePickerController($scope, assetsService) {
//tell the assetsService to load the markdown.editor libs from the markdown editors
//plugin folder
//assetsService
// .load([
// "http://code.jquery.com/ui/1.10.4/jquery-ui.min.js"
// ])
// .then(function () {
// //this function will execute when all dependencies have loaded
// });
//load the seperat css for the editor to avoid it blocking our js loading
assetsService.loadCss("/css/jquery-ui.custom.min.css");
if (!$scope.model.value) {
$scope.model.value = [];
}
//add any fields that there isn't values for
//if ($scope.model.config.min > 0) {
if ($scope.model.value.length > 0) {
for (var i = 0; i < $scope.model.value.length; i++) {
if ((i + 1) > $scope.model.value.length) {
$scope.model.value.push({ value: "" });
}
}
}
$scope.add = function () {
//if ($scope.model.config.max <= 0 || $scope.model.value.length < $scope.model.config.max) {
if ($scope.model.value.length <= 52) {
$scope.model.value.push({ value: "" });
}
};
$scope.remove = function (index) {
var remainder = [];
for (var x = 0; x < $scope.model.value.length; x++) {
if (x !== index) {
remainder.push($scope.model.value[x]);
}
}
$scope.model.value = remainder;
};
}
var datePicker = angular.module("umbraco").controller("AcuIT.MultidateController", MultipleDatePickerController);
datePicker.directive('jqdatepicker', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModelCtrl) {
$(function () {
element.datepicker({
dateFormat: 'dd/mm/yy',
onSelect: function (date) {
scope.$apply(function () {
ngModelCtrl.$setViewValue(date);
});
}
});
});
}
}
});
I faced the same problem when adapting a jQuery Date Range Picker for my Date Range Picker package for Umbraco 7. It's frustrating! The problem (I think) is that Angular's ng-model listens for "input" changes to trigger events and so doesn't pick up on a jQuery triggered event.
The way around it I found was to force the input event of the element you wish to update to fire manually, using jQuery's .trigger() event.
For example, the date picker I was using had this code for when a date was changed:
updateInputText: function () {
if (this.element.is('input')) {
this.element.val(this.startDate.format(this.format) + this.separator + this.endDate.format(this.format));
}
},
I just adapted it to force an input trigger by adding this.element.trigger('input') to the code block, so it now reads:
updateInputText: function () {
if (this.element.is('input')) {
this.element.val(this.startDate.format(this.format) + this.separator + this.endDate.format(this.format));
this.element.trigger('input');
}
},
This forces Angular to "see" the change and then ng-model is updated. There may well be a more elegant way (as I'm an Angular newbie), but I know this worked for me.
Got it. This is probably a bit of a hack, but it's simple and effective so it's a win nonetheless.
The assetsService call is the key, where I've put code into the deferred .then statement to call jQueryUI's datepicker on any item that has the "jqdp" CSS class:
//tell the assetsService to load the markdown.editor libs from the markdown editors
//plugin folder
assetsService
.load([
"/App_Plugins/Multidate/jquery-ui.min.js"
])
.then(function () {
//this function will execute when all dependencies have loaded
$('.jqdp').datepicker({ dateFormat: 'dd/mm/yy' });
});
I've then gone and added that class to my view:
<input type="text" jqdatepicker name="item_{{$index}}" ng-model="item.value" class="jqdp" id="dp-{{model.alias}}-{{$index}}" />
Finally, I've added a directive to ensure that dynamically-added items also display a datepicker:
datePicker.directive('jqdatepicker', function () {
return function (scope, element, attrs) {
scope.$watch("jqdatepicker", function () {
try{
$(element).datepicker({ dateFormat: 'dd/mm/yy' });
}
catch(e)
{}
});
};
});
As I said, this is possibly a bit hacky but it achieves the right result and seems like a simple solution.

Resources