How to get clicked element only in stencilJS when shadow is set to true - shadow-dom

I am getting a problem that when I am setting shadow as true in my component I am getting whole dom when any image(other element too) clicked instead of the element which is clicked.
How can I resolve this issue.
Thanks in advance

Here is the answer:
#Listen('click')
onHandleClickEvent(ev) {
// This will give you the clicked element (composedPath()[0])
console.log('===== 31 =====', ev.composedPath()[0]);
}

You can use the currentTarget property of the event arguments object which is passed to the event handler in order to get the element which was clicked. For example, look at the following code:
import { Component, Prop } from '#stencil/core';
#Component({
tag: 'my-component',
styleUrl: 'my-component.css',
shadow: true
})
export class MyComponent {
#Prop() first: string;
#Prop() middle: string;
#Prop() last: string;
constructor() {
this.imgClicked = this.imgClicked.bind(this);
}
format(): string {
return (
(this.first || '') +
(this.middle ? ` ${this.middle}` : '') +
(this.last ? ` ${this.last}` : '')
);
}
imgClicked(evt) {
console.log(evt.currentTarget);
}
render() {
return <div>Hello, World! I'm {this.format()}<img src="https://twitter.com/gilfink" onClick={this.imgClicked}/></div>;
}
}
In the code, the onClick handler (which is the imgClicked function) will print the image element which was clicked to the console.

Related

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

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();
}, []);

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.

Select2 - Infinite loop with trigger('change')

Here is my case:
$('select').select2();
$('select').on('change', function () {
// calling a function
myFunction();
});
function myFunction() {
// changes my select values
// so I need to update the select for seing the news values
$('select').trigger('change');
// hehe I fire the change event so myFunction is called again and again
}
What can I do to avoid that behavior? Regards...
This is a bug in Select2. I had the same issue with the following code:
var FID = $(location).attr('href').split("/")[5];
$('#facility').children().each(function () {
if ($(this).val().trim() == FID.trim()) {
$(this).attr('selected', 'selected').trigger('change');
}
});
The following isn't ideal, but it does fix the issue. Note that you will need to redefine your Select2 options (mine shown).
var FID = $(location).attr('href').split("/")[5];
$('#facility').children().each(function () {
if ($(this).val().trim() == FID.trim()) {
$(this).attr('selected', 'selected');
$('#facility').select2({
placeholder: "",
minimumResultsForSearch: -1
});
}
});

Extjs4 set tooltip on each column hover in gridPanel

I am getting tooltip on mouse hover by each row for current column but I am unable to get next column tooltip on continue hover on same row.
But I can get it if I hover on another row & again hover any column of the previous row by using:
listeners:{
'itemmouseenter': function (view, record, item, index, e, eOpts) {
var gridColums = view.getGridColumns();
var column = gridColums[e.getTarget(this.view.cellSelector).cellIndex];
Ext.fly(item).set({ 'data-qtip': 'Des:' + column.dataIndex });
}
}
Can anyone show me what I'm missing or point me in the right direction?
I have an easy one, using the renderer function:
{
xtype : 'gridcolumn',
dataIndex : 'status',
text : 'Status',
renderer : function(value, metadata) {
metadata.tdAttr = 'data-qtip="' + value + '"';
return value;
}
}
I was looking through this. I could manage to get the tool tip for each cell by doing something like this:
Ext.getCmp('DynamicDemandGrid').getView().on('render', function(view) {
view.tip = Ext.create('Ext.tip.ToolTip', {
// The overall target element.
target: view.el,
// Each grid row causes its own seperate show and hide.
delegate: view.cellSelector,
// Moving within the row should not hide the tip.
trackMouse: true,
// Render immediately so that tip.body can be referenced prior to the first show.
renderTo: Ext.getBody(),
listeners: {
// Change content dynamically depending on which element triggered the show.
beforeshow: function updateTipBody(tip) {
var gridColums = view.getGridColumns();
var column = gridColums[tip.triggerElement.cellIndex];
var val=view.getRecord(tip.triggerElement.parentNode).get(column.dataIndex);
tip.update(val);
}
}
});
});
Let me know if it helps
{
text: name,
width: 80,
dataIndex: dataIndex,
sortable: true,
listeners: {
afterrender: function ()
{
Ext.create('Ext.ToolTip',
{
target: this.getEl(),
anchor: direction | "top",
trackMouse: true,
html: this.text
});
}
}
}

How to override the handler for a button in ckeditor?

I would like to have a custom handler for the save button.
How can I override the default command?
The current top answer messed up the toolbar grouping for me (put the save button at the end), and the other answer did not work in ckeditor v4.
Here's how to do it in ckeditor 4:
html:
<textarea id="CKEditor1"></textarea>
javascript:
<script>
// Need to wait for the ckeditor instance to finish initialization
// because CKEDITOR.instances.editor.commands is an empty object
// if you try to use it immediately after CKEDITOR.replace('editor');
CKEDITOR.on('instanceReady', function (ev) {
// Create a new command with the desired exec function
var editor = ev.editor;
var overridecmd = new CKEDITOR.command(editor, {
exec: function(editor){
// Replace this with your desired save button code
alert(editor.document.getBody().getHtml());
}
});
// Replace the old save's exec function with the new one
ev.editor.commands.save.exec = overridecmd.exec;
});
CKEDITOR.replace('CKEditor1');
</script>
CKEDITOR.plugins.registered['save']=
{
init : function( editor )
{
var command = editor.addCommand( 'save',
{
modes : { wysiwyg:1, source:1 },
exec : function( editor ) {
//YOUR CODE
}
}
);
editor.ui.addButton( 'Save',{label : 'YOUR LABEL',command : 'save'});
}
}
If you want to override the save command for just one instance, you can try the following code:
var editor = $('#myTextarea').ckeditorGet(); // Retrieving CKeditor instance with jQuery
editor.getCommand('save').exec = function(editor) {
// Do whatever you need to
...
return true;
};
This should work for any CKEditor command.
function configureEditor(id) {
var editor = CKEDITOR.replace(id);
editor.on("instanceReady", function () {
// overwrite the default save function
editor.addCommand("save", {
modes: { wysiwyg: 1, source: 1 },
exec: function () {
// get the editor content
var theData = editor.getData();
alert("insert your code here");
}
});
editor.ui.addButton('Save', { label: 'My Save', command: 'save', enabled: 'true' });
var saveButton = $('#cke_' + id).find('.cke_button__save');
saveButton.removeClass('cke_button_disabled');
});
}
In CKEditor 4, the save plugin is meant to be cancelable. If unsure, one can always have a look at the source. You can cancel the event and apply your own logic in a handler, like in this example:
//assuming editor is a CKEDITOR.editor instance
editor.on('save', function (event) {
event.cancel();
//your custom command logic
//(you can access the editor instance through event.editor)
});
I would advise against creating a new command and replacing the default with it, as it is an unnecessary workaround.

Resources