将 addEventDelegate 限制为仅父 hbox
restrict addEventDelegate to parent hbox only
这是为我之前的问题创建的自定义控件
我有两个 span
元素彼此相邻。他们坐在FormattedText
。 FormattedText
本身位于 HBox
中。
我希望当用户鼠标从 hbox
移动 over/out 时触发弹出窗口。不幸的是,因为我有 2 个跨度,所以当用户将鼠标悬停在它们上方时会单独触发(因此显示 2 个单独的弹出窗口,而实际上它应该是一个)。我的假设是,这是因为 onmouseover/out
附加到引擎盖下的两个跨度。我可以将这些事件限制为仅 hbox
吗?
sap.ui.define([
'sap/ui/core/Control',
'sap/m/FormattedText',
'sap/m/HBox',
], function (Control, FormattedText, HBox) {
return Control.extend('drex.control.TherapyCosts', {
metadata: {
properties: {
rank: {
type: 'int',
defaultValue: 0
},
},
aggregations: {
_rankedTherapyCost: {type: 'sap.m.FormattedText', multiple: false, singularName: '_rankedTherapyCost'},
_popover: {type: 'sap.m.Popover', multiple: false, singularName: '_popover'},
_hbox: {type: 'sap.m.HBox', multiple: false}
}
},
init: function () {
Control.prototype.init.apply(this, arguments);
},
onBeforeRendering: function () {
const highlighedCurrency = this.getCurrency().repeat(this.getRank());
const fadedCurrency = this.getCurrency().repeat(7 - this.getRank());
const _popover = new sap.m.Popover({
showHeader: false,
placement: 'VerticalPreferredBottom',
content: new sap.m.Text({text: 'test'})
});
this.setAggregation('_popover', _popover);
const _formattedText = new FormattedText({
htmlText:
`<span class="currencyHighlighted">${highlighedCurrency}</span>` +
`<span class="currencyFaded">${fadedCurrency}</span>`
});
this.setAggregation('_rankedTherapyCost', _formattedText);
const _hbox = new HBox(
{ items: [this.getAggregation('_rankedTherapyCost')]})
.addEventDelegate({
onmouseover: () => {
this.getAggregation('_popover').openBy(this);
},
onmouseout: () => {
this.getAggregation('_popover').close()
}
});
this.setAggregation('_hbox', _hbox)
},
renderer: function (rm, oControl) {
const _hbox = oControl.getAggregation('_hbox');
rm.write('<div');
rm.writeControlData(oControl);
rm.write('>');
rm.renderControl(_hbox);
rm.write('</div>');
}
});
});
这是问题的视频
https://streamable.com/fjw408
我想你可以不用 hbox;只要有两个格式化文本或任何 sapui5 控件也可以。
sap.ui.define([
'sap/ui/core/Control',
'sap/m/FormattedText',
], function (Control, FormattedText) {
Control.extend('TherapyCosts', {
metadata: {
properties: {
rank: {
type: 'int',
defaultValue: 0
},
currency: {
type: "string",
defaultValue: "$"
}
},
aggregations: {
_highlighted: {type: 'sap.m.FormattedText', multiple: false},
_faded: {type: 'sap.m.FormattedText', multiple: false},
_popover: {type: 'sap.m.Popover', multiple: false, singularName: '_popover'}
}
},
init: function () {
Control.prototype.init.apply(this, arguments);
this.addStyleClass('therapy-cost')
},
onBeforeRendering: function () {
const highlighedCurrency = this.getCurrency().repeat(this.getRank());
const highlight = new FormattedText({
htmlText: highlighedCurrency
});
this.setAggregation('_highlighted', highlight);
const fadedCurrency = this.getCurrency().repeat(7 - this.getRank());
const faded = new FormattedText({
htmlText: fadedCurrency
});
this.setAggregation('_faded', faded);
const _popover = new sap.m.Popover({
showHeader: false,
placement: 'VerticalPreferredBottom',
content: new sap.m.Text({text: 'test'})
});
this.setAggregation('_popover', _popover);
},
renderer: function (rm, oControl) {
rm.write('<div');
rm.writeControlData(oControl);
rm.writeClasses(oControl);
rm.writeStyles(oControl);
rm.write('>');
rm.renderControl(oControl.getAggregation('_highlighted'));
rm.renderControl(oControl.getAggregation('_faded'));
rm.write('</div>');
},
onAfterRendering: function () {
const popOver = this.getAggregation('_popover');
const highlighted = this.getAggregation("_highlighted");
highlighted.$().addClass("currency-highlighted");
highlighted.$().hover(function() {
popOver.openBy(highlighted);
}, function() {
popOver.close();
});
const faded = this.getAggregation("_faded");
faded.$().addClass("currency-faded");
},
});
(new TherapyCosts({
rank: 5
})).placeAt('content')
});
这里的关键是mouseout事件,当鼠标移出监听该事件的元素的任意子元素时触发。在这种情况下,例如,从强调文本移动到淡入淡出的文本,当离开强调文本时会发生 mouseout 事件,关闭弹出窗口,然后在淡入淡出的文本上发生鼠标悬停事件,再次打开它。
由于打开一个已经打开的弹出窗口不会执行任何操作,因此您只需要在 mouseout 上添加一行来检查您转到的元素。如果它不是当前元素的子元素,则只关闭弹出窗口。
if (!this.getDomRef().contains(e.toElement)) {
popOver.close()
}
基于 D.Seah 的回答,我已将其添加到 JSBin。我个人不喜欢像这样使用 onBeforeRendering
和 onAfterRendering
,所以我重构了一点以在 init 上构建所有内容并简单地更改 属性 更改上的控件。这样,出于性能原因,您可以减少渲染工作。
sap.ui.define([
'sap/ui/core/Control',
'sap/m/FormattedText',
], function (Control, FormattedText) {
Control.extend('TherapyCosts', {
metadata: {
properties: {
rank: {
type: 'int',
defaultValue: 0
},
currency: {
type: "string",
defaultValue: "$"
}
},
aggregations: {
_highlighted: {type: 'sap.m.FormattedText', multiple: false},
_faded: {type: 'sap.m.FormattedText', multiple: false},
_popover: {type: 'sap.m.Popover', multiple: false, singularName: '_popover'}
}
},
init: function () {
Control.prototype.init.apply(this, arguments);
this.addStyleClass('therapy-cost');
const highlight = new FormattedText();
highlight.addStyleClass("currency-highlight");
this.setAggregation('_highlighted', highlight);
const faded = new FormattedText();
faded.addStyleClass("currency-faded");
this.setAggregation('_faded', faded);
const _popover = new sap.m.Popover({
showHeader: false,
placement: 'VerticalPreferredBottom',
content: new sap.m.Text({text: 'test'})
});
this.setAggregation('_popover', _popover);
},
_changeAggr: function () {
const highlighedCurrency = this.getCurrency().repeat(this.getRank());
const highlight = this.getAggregation("_highlighted");
highlight.setHtmlText(highlighedCurrency);
const fadedCurrency = this.getCurrency().repeat(7 - this.getRank());
const faded = this.getAggregation("_faded");
faded.setHtmlText(fadedCurrency);
},
setRank: function(rank) {
if (this.getProperty("rank") !== rank) {
this.setProperty("rank", rank);
this._changeAggr();
}
},
setCurrency: function(curr) {
if (this.getProperty("currency") !== curr) {
this.setProperty("currency", curr);
this._changeAggr();
}
},
renderer: function (rm, oControl) {
rm.write('<div');
rm.writeControlData(oControl);
rm.writeClasses(oControl);
rm.writeStyles(oControl);
rm.write('>');
rm.renderControl(oControl.getAggregation('_highlighted'));
rm.renderControl(oControl.getAggregation('_faded'));
rm.write('</div>');
},
onmouseover: function (e) {
const popOver = this.getAggregation('_popover');
popOver.openBy(this);
},
onmouseout: function (e) {
if (!this.getDomRef().contains(e.toElement)) {
const popOver = this.getAggregation('_popover');
popOver.close();
}
}
});
(new TherapyCosts({
rank: 5,
currency: "£"
})).placeAt('content')
});
.therapy-cost {
display: inline-flex;
flex-direction: row;
}
.therapy-cost .currency-highlighted {
color: black;
}
.therapy-cost .currency-faded {
color: lightgrey;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script
src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-xx-bindingSyntax="complex"
data-sap-ui-libs="sap.m"></script>
</head>
<body class="sapUiBody sapUiSizeCompact">
<div id='content'></div>
</body>
</html>
这是为我之前的问题创建的自定义控件
我有两个 span
元素彼此相邻。他们坐在FormattedText
。 FormattedText
本身位于 HBox
中。
我希望当用户鼠标从 hbox
移动 over/out 时触发弹出窗口。不幸的是,因为我有 2 个跨度,所以当用户将鼠标悬停在它们上方时会单独触发(因此显示 2 个单独的弹出窗口,而实际上它应该是一个)。我的假设是,这是因为 onmouseover/out
附加到引擎盖下的两个跨度。我可以将这些事件限制为仅 hbox
吗?
sap.ui.define([
'sap/ui/core/Control',
'sap/m/FormattedText',
'sap/m/HBox',
], function (Control, FormattedText, HBox) {
return Control.extend('drex.control.TherapyCosts', {
metadata: {
properties: {
rank: {
type: 'int',
defaultValue: 0
},
},
aggregations: {
_rankedTherapyCost: {type: 'sap.m.FormattedText', multiple: false, singularName: '_rankedTherapyCost'},
_popover: {type: 'sap.m.Popover', multiple: false, singularName: '_popover'},
_hbox: {type: 'sap.m.HBox', multiple: false}
}
},
init: function () {
Control.prototype.init.apply(this, arguments);
},
onBeforeRendering: function () {
const highlighedCurrency = this.getCurrency().repeat(this.getRank());
const fadedCurrency = this.getCurrency().repeat(7 - this.getRank());
const _popover = new sap.m.Popover({
showHeader: false,
placement: 'VerticalPreferredBottom',
content: new sap.m.Text({text: 'test'})
});
this.setAggregation('_popover', _popover);
const _formattedText = new FormattedText({
htmlText:
`<span class="currencyHighlighted">${highlighedCurrency}</span>` +
`<span class="currencyFaded">${fadedCurrency}</span>`
});
this.setAggregation('_rankedTherapyCost', _formattedText);
const _hbox = new HBox(
{ items: [this.getAggregation('_rankedTherapyCost')]})
.addEventDelegate({
onmouseover: () => {
this.getAggregation('_popover').openBy(this);
},
onmouseout: () => {
this.getAggregation('_popover').close()
}
});
this.setAggregation('_hbox', _hbox)
},
renderer: function (rm, oControl) {
const _hbox = oControl.getAggregation('_hbox');
rm.write('<div');
rm.writeControlData(oControl);
rm.write('>');
rm.renderControl(_hbox);
rm.write('</div>');
}
});
});
这是问题的视频 https://streamable.com/fjw408
我想你可以不用 hbox;只要有两个格式化文本或任何 sapui5 控件也可以。
sap.ui.define([
'sap/ui/core/Control',
'sap/m/FormattedText',
], function (Control, FormattedText) {
Control.extend('TherapyCosts', {
metadata: {
properties: {
rank: {
type: 'int',
defaultValue: 0
},
currency: {
type: "string",
defaultValue: "$"
}
},
aggregations: {
_highlighted: {type: 'sap.m.FormattedText', multiple: false},
_faded: {type: 'sap.m.FormattedText', multiple: false},
_popover: {type: 'sap.m.Popover', multiple: false, singularName: '_popover'}
}
},
init: function () {
Control.prototype.init.apply(this, arguments);
this.addStyleClass('therapy-cost')
},
onBeforeRendering: function () {
const highlighedCurrency = this.getCurrency().repeat(this.getRank());
const highlight = new FormattedText({
htmlText: highlighedCurrency
});
this.setAggregation('_highlighted', highlight);
const fadedCurrency = this.getCurrency().repeat(7 - this.getRank());
const faded = new FormattedText({
htmlText: fadedCurrency
});
this.setAggregation('_faded', faded);
const _popover = new sap.m.Popover({
showHeader: false,
placement: 'VerticalPreferredBottom',
content: new sap.m.Text({text: 'test'})
});
this.setAggregation('_popover', _popover);
},
renderer: function (rm, oControl) {
rm.write('<div');
rm.writeControlData(oControl);
rm.writeClasses(oControl);
rm.writeStyles(oControl);
rm.write('>');
rm.renderControl(oControl.getAggregation('_highlighted'));
rm.renderControl(oControl.getAggregation('_faded'));
rm.write('</div>');
},
onAfterRendering: function () {
const popOver = this.getAggregation('_popover');
const highlighted = this.getAggregation("_highlighted");
highlighted.$().addClass("currency-highlighted");
highlighted.$().hover(function() {
popOver.openBy(highlighted);
}, function() {
popOver.close();
});
const faded = this.getAggregation("_faded");
faded.$().addClass("currency-faded");
},
});
(new TherapyCosts({
rank: 5
})).placeAt('content')
});
这里的关键是mouseout事件,当鼠标移出监听该事件的元素的任意子元素时触发。在这种情况下,例如,从强调文本移动到淡入淡出的文本,当离开强调文本时会发生 mouseout 事件,关闭弹出窗口,然后在淡入淡出的文本上发生鼠标悬停事件,再次打开它。
由于打开一个已经打开的弹出窗口不会执行任何操作,因此您只需要在 mouseout 上添加一行来检查您转到的元素。如果它不是当前元素的子元素,则只关闭弹出窗口。
if (!this.getDomRef().contains(e.toElement)) {
popOver.close()
}
基于 D.Seah 的回答,我已将其添加到 JSBin。我个人不喜欢像这样使用 onBeforeRendering
和 onAfterRendering
,所以我重构了一点以在 init 上构建所有内容并简单地更改 属性 更改上的控件。这样,出于性能原因,您可以减少渲染工作。
sap.ui.define([
'sap/ui/core/Control',
'sap/m/FormattedText',
], function (Control, FormattedText) {
Control.extend('TherapyCosts', {
metadata: {
properties: {
rank: {
type: 'int',
defaultValue: 0
},
currency: {
type: "string",
defaultValue: "$"
}
},
aggregations: {
_highlighted: {type: 'sap.m.FormattedText', multiple: false},
_faded: {type: 'sap.m.FormattedText', multiple: false},
_popover: {type: 'sap.m.Popover', multiple: false, singularName: '_popover'}
}
},
init: function () {
Control.prototype.init.apply(this, arguments);
this.addStyleClass('therapy-cost');
const highlight = new FormattedText();
highlight.addStyleClass("currency-highlight");
this.setAggregation('_highlighted', highlight);
const faded = new FormattedText();
faded.addStyleClass("currency-faded");
this.setAggregation('_faded', faded);
const _popover = new sap.m.Popover({
showHeader: false,
placement: 'VerticalPreferredBottom',
content: new sap.m.Text({text: 'test'})
});
this.setAggregation('_popover', _popover);
},
_changeAggr: function () {
const highlighedCurrency = this.getCurrency().repeat(this.getRank());
const highlight = this.getAggregation("_highlighted");
highlight.setHtmlText(highlighedCurrency);
const fadedCurrency = this.getCurrency().repeat(7 - this.getRank());
const faded = this.getAggregation("_faded");
faded.setHtmlText(fadedCurrency);
},
setRank: function(rank) {
if (this.getProperty("rank") !== rank) {
this.setProperty("rank", rank);
this._changeAggr();
}
},
setCurrency: function(curr) {
if (this.getProperty("currency") !== curr) {
this.setProperty("currency", curr);
this._changeAggr();
}
},
renderer: function (rm, oControl) {
rm.write('<div');
rm.writeControlData(oControl);
rm.writeClasses(oControl);
rm.writeStyles(oControl);
rm.write('>');
rm.renderControl(oControl.getAggregation('_highlighted'));
rm.renderControl(oControl.getAggregation('_faded'));
rm.write('</div>');
},
onmouseover: function (e) {
const popOver = this.getAggregation('_popover');
popOver.openBy(this);
},
onmouseout: function (e) {
if (!this.getDomRef().contains(e.toElement)) {
const popOver = this.getAggregation('_popover');
popOver.close();
}
}
});
(new TherapyCosts({
rank: 5,
currency: "£"
})).placeAt('content')
});
.therapy-cost {
display: inline-flex;
flex-direction: row;
}
.therapy-cost .currency-highlighted {
color: black;
}
.therapy-cost .currency-faded {
color: lightgrey;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script
src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-xx-bindingSyntax="complex"
data-sap-ui-libs="sap.m"></script>
</head>
<body class="sapUiBody sapUiSizeCompact">
<div id='content'></div>
</body>
</html>