el-table溢出隐藏 鼠标移入显示tooltip 逻辑
文件 element-ui/packages/table/src/table-body.js 截取部分代码
export default {
render(h) {
return (
<table>
<tbody>
{/* 表格内容 ... */}
{/* 一个表格 只渲染一个 tooltip */}
<el-tooltip effect={this.table.tooltipEffect} placement="top" ref="tooltip" content={this.tooltipContent}></el-tooltip>
</tbody>
</table>
);
},
created() {
this.activateTooltip = debounce(50, tooltip => tooltip.handleShowPopper());
},
methods: {
handleCellMouseEnter(event, row) { // 鼠标移入表格项 触发事件
const table = this.table;
const cell = getCell(event);
if (cell) {
const column = getColumnByCell(table, cell);
const hoverState = table.hoverState = { cell, column, row };
table.$emit('cell-mouse-enter', hoverState.row, hoverState.column, hoverState.cell, event);
}
// 判断是否text-overflow, 如果是就显示tooltip
const cellChild = event.target.querySelector('.cell');
if (!(hasClass(cellChild, 'el-tooltip') && cellChild.childNodes.length)) {
return;
}
// use range width instead of scrollWidth to determine whether the text is overflowing
// to address a potential FireFox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1074543#c3
const range = document.createRange();
range.setStart(cellChild, 0);
range.setEnd(cellChild, cellChild.childNodes.length);
const rangeWidth = range.getBoundingClientRect().width;
const padding = (parseInt(getStyle(cellChild, 'paddingLeft'), 10) || 0) +
(parseInt(getStyle(cellChild, 'paddingRight'), 10) || 0);
if ((rangeWidth + padding > cellChild.offsetWidth || cellChild.scrollWidth > cellChild.offsetWidth) && this.$refs.tooltip) {
// 1. 判断: 如果宽度溢出
const tooltip = this.$refs.tooltip;
// TODO 会引起整个 Table 的重新渲染,需要优化
this.tooltipContent = cell.innerText || cell.textContent; // 2. 表格项内容 赋值给 tooltip显示
tooltip.referenceElm = cell; // 3. 替换referenceElm, tooltip通过Popper.js 计算显示的tooltip和referenceElm的相对位置
tooltip.$refs.popper && (tooltip.$refs.popper.style.display = 'none');
tooltip.doDestroy(); // 取消tooltip上一系列绑定事件
tooltip.setExpectedState(true);
this.activateTooltip(tooltip); // 4. 显示tooltip
}
},
handleCellMouseLeave(event) { // 鼠标溢出表格项 触发事件
const tooltip = this.$refs.tooltip;
if (tooltip) {
tooltip.setExpectedState(false);
tooltip.handleClosePopper(); // 隐藏tooltip
}
const cell = getCell(event);
if (!cell) return;
const oldHoverState = this.table.hoverState || {};
this.table.$emit('cell-mouse-leave', oldHoverState.row, oldHoverState.column, oldHoverState.cell, event);
},
}
}
记录点
mouseenter/mouseleave(新),mouseover/mouseout(旧)el-tooltip 是 tbody的子节点,一个表格,只渲染一个 el-tooltipmouseenter,判断表格项内容是否溢出referenceElm, tooltip通过 Popper.js 计算显示的 tooltip 和 referenceElm 的相对位置mouseleave,隐藏 tooltip文件 element-ui/packages/tooltip/src/main.js 截取部分代码
const PopperJS = require('element-ui/src/utils/popper.js');
export default {
beforeCreate() {
this.popperVM = new Vue({
data: { node: '' },
render(h) {
return this.node;
}
}).$mount();
this.debounceClose = debounce(200, () => this.handleClosePopper());
},
render(h) {
if (this.popperVM) {
this.popperVM.node = (
<transition
name={ this.transition }
onAfterLeave={ this.doDestroy }>
<div
onMouseleave={ () => { this.setExpectedState(false); this.debounceClose(); } }
onMouseenter= { () => { this.setExpectedState(true); } }
ref="popper"
role="tooltip"
id={this.tooltipId}
aria-hidden={ (this.disabled || !this.showPopper) ? 'true' : 'false' }
v-show={!this.disabled && this.showPopper}
class={
['el-tooltip__popper', 'is-' + this.effect, this.popperClass]
}>
{/* 具名插槽 content 渲染在tooltip */}
{ this.$slots.content || this.content }
</div>
</transition>);
}
const firstElement = this.getFirstElement();
if (!firstElement) return null;
const data = firstElement.data = firstElement.data || {};
data.staticClass = this.addTooltipClass(data.staticClass);
return firstElement; // 找到默认插槽 default 显示在组件位置
},
mounted() {
this.referenceElm = this.$el;
// 给 referenceElm 绑定一系列事件, 包括: mouseenter mouseleave
// ...
if (this.value && this.popperVM) {
this.popperVM.$nextTick(() => {
if (this.value) {
this.updatePopper();
}
});
}
},
methods: {
updatePopper() {
const popperJS = this.popperJS;
if (popperJS) {
popperJS.update();
if (popperJS._popper) {
popperJS._popper.style.zIndex = PopupManager.nextZIndex();
}
} else {
this.createPopper();
}
},
createPopper() { // 省略...只剩下需要的逻辑
let reference = this.referenceElm = this.referenceElm || this.reference || this.$refs.reference;
const popper = this.popperElm = this.popperElm || this.popper || this.$refs.popper; // 提示信息ref 对应的DOM
const options = this.popperOptions;
if (!popper || !reference) return;
if (this.appendToBody) document.body.appendChild(this.popperElm); // 渲染在body节点下
/**
* reference: 默认插槽/鼠标移入移出显示tooltip相对的元素
* popper: 提示信息ref 对应的DOM (tooltip)
* option: 一些配置
*/
this.popperJS = new PopperJS(reference, popper, options);
// ...
}
}
}
记录点:
default 显示在组件位置transition + 具名插槽 content,鼠标移入referenceElm,显示提示信息mouseenter、mouseleave,调用 updatePoppercreatePopper
Popper.js 计算显示的 提示信息 和 referenceElm 的相对位置this.popperJS = new PopperJS(reference, popper, options);
referenceElm,鼠标移入移出显示 提示信息 相对的元素我得到了一个包含嵌套链接的表单。编辑时链接字段为空的问题。这是我的表格:Editingkategori{:action=>'update',:id=>@konkurrancer.id})do|f|%>'Trackingurl',:style=>'width:500;'%>'Editkonkurrence'%>|我的konkurrencer模型:has_one:link我的链接模型:classLink我的konkurrancer编辑操作:defedit@konkurrancer=Konkurrancer.find(params[:id])@konkurrancer.link_attrib
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择
我试图在索引页中创建一个超链接,但它没有显示,也没有给出任何错误。这是我的index.html.erb代码。ListingarticlesTitleTextssss我检查了我的路线,我认为它们也没有问题。PrefixVerbURIPatternController#Actionwelcome_indexGET/welcome/index(.:format)welcome#indexarticlesGET/articles(.:format)articles#indexPOST/articles(.:format)articles#createnew_articleGET/article
我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c
我需要一个表,其中行实际上是2行表,一个嵌套表是..我怎样才能在Prawn中做到这一点?也许我需要延期..但哪一个? 最佳答案 现在支持子表:Prawn::Document.generate("subtable.pdf")do|pdf|subtable=pdf.make_table([["sub"],["table"]])pdf.table([[subtable,"original"]])end 关于ruby-on-rails-PrawnPDF:Ineedtogeneratenested
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
目前,Itembelongs_toCompany和has_manyItemVariants。我正在尝试使用嵌套的fields_for通过Item表单添加ItemVariant字段,但是使用:item_variants不显示该表单。只有当我使用单数时才会显示。我检查了我的关联,它们似乎是正确的,这可能与嵌套在公司下的项目有关,还是我遗漏了其他东西?提前致谢。注意:下面的代码片段中省略了不相关的代码。编辑:不知道这是否相关,但我正在使用CanCan进行身份验证。routes.rbresources:companiesdoresources:itemsenditem.rbclassItemi
如果我在模型中设置验证消息validates:name,:presence=>{:message=>'Thenamecantbeblank.'}我如何让该消息显示在闪光警报中,这是我迄今为止尝试过的方法defcreate@message=Message.new(params[:message])if@message.valid?ContactMailer.send_mail(@message).deliverredirect_to(root_path,:notice=>"Thanksforyourmessage,Iwillbeintouchsoon")elseflash[:error]
我刚刚按照thebootsygempage上的安装说明进行操作在我保存并查看帖子内容之前,一切看起来都不错。这是输出在View中的样子:HeaderSubhead:似乎没有呈现任何html格式,因为它被引号或类似的东西转义了-其他人有这个问题吗?我没有在github页面或SO上看到任何问题来指出我正确的方向。除了遵循gem安装说明之外,我还没有做任何事情,但也许我错过了什么或者只是犯了一个愚蠢的错误。如果你还有什么想知道的,请尽管问。干杯 最佳答案 你需要有这样的东西,转义html: 关