aardio封装的HTMLayout库真的很好用,这里先感谢前辈们的努力和分享精神!
今天我们来实现给标准的tabs添加关闭按钮功能,并做成一个behavior

**思路: **
1、给tabs的strip定义一个behavior,我这里命名 为“horizontalTabsClose”
2、响应onAttach 事件,创建实现关闭的button,并设置适当的css样式
3、响应onButtonClick 事件,实现关闭一个“标签”的过程
4、使用时,只需要给div.strip 添加一个css属性,behavior:horizontalTabsClose; 即可

不能上传图片,大家运行下面代码看效果吧!

代码如下:


import win.ui;
/*DSG{{*/
var winform = ..win.form( bottom=399;parent=...;text="aardio Form";right=599 )
winform.add( )
/*}}*/

import web.layout;
import web.layout.behavior.tabs;

var wbLayout = web.layout(winform);

import web.layout.debug; //导入该库以显示HTMLayout错误
wbLayout.attachEventHandler( web.layout.debug ); //为CSSS!添加全局函数 debug;

namespace web.layout.behavior.horizontalTabsClose{
onAttach = function( ltEle ){
ltEle.style.position ="relative "
ltEle.style["padding-right"] = "25px"
var btn = ltEle.createElement("button")
with btn.style{
position = "absolute"
cursor = "pointer"
right = "-15px"
top = "0"
size = "22px"
background = "url(data:image/png;base64,
iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAACXBIWXMAAAsTAAAL
EwEAmpwYAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAA
dTAAAOpgAAA6mAAAF2+SX8VGAAAE3klEQVR42mL8//8/Ay0AQAAx4hBnAhH6+vpM
UlJSDM+ePfvj7OzMwggEa9eu/a2kpMT4+vVr5suXL4NcBcL/0A0ACCAWLBYxs7Ky
MgENZQ8KChJzdHQ0YWJiMmZjYxP98eMHg42NzUthYeGrGzduPPLkyZMXnz59+gsE
IIP/Qi0BA4AAQjeUhYeHh8vHx0d47969qcBgOgfEH759+/b/8ePH/x88ePD/58+f
QKH/X//8+XO2srIyWFVVlZeFhYUTqJcVOQQAAgjFUE5OTt6AgACZCxcudAI1/zhz
5sz/1NTUv2JiYl+BofAZhAUEBL7GxMT8uXTpEsiCT2fPnu2xtLSUAvqKB2o4GAAE
ENz7QMxtaGgotWvXriqQjtmzZ/8VERH5DBT/BMSf0fAnYNh/mTZt2l+Q2v3793cD
XS4OFOeEBi8jQACBDQYCdkFBQeEJEybEAtW9Wrly5X9mZmachiLTkydP/gfU8y0l
JSUWGA/8QDEOUOQDBBDIYGaQN1xcXDRv3bq16u3bt/+Bsf4FpImXl/dze3v7z7S0
tB8ww8zNzb/NmDHjl5GR0VcQH+igz/fu3fv/6tWrvTIyMhpAMVCQsAAEECxlCAUG
BroBbb41Z86cf6CwBBkkLS395d8/kIP+/8/JyfkBDMuvwEgECyBb1tjY+Aco9EVO
Ts4VZBYQswEEEMhgNg4ODpno6OgUoOS/xMTEnzBvgiyIjY39/vHjx3/AJPX/3bt3
YENnzZr1C6gHHjz+/v7fQA4oBAIgXxIU1gABxATUzASMaXZgRImAwvvz58/wtAjK
lYsXL/4N9PpvYHAxAL3NCEwpf3Nzc3+C0jQMANMyAzAZMgCDQgLqWmaAAGICaQa6
iPnRo0egBM4AdAlKOrS2tmYJDg5mgVmkrq7OlJmZyQZ0EFwNMJn+B0Ycw4sXL37D
0jNAAIGz7vfv30GJ/yOQ+R6oEZ4bRUVFGdetW8ehrKzMBExav4HB9AOYGRj7+/vZ
wsPDYepAkc0C9NGvffv2PYfpBQggmOS/X79+fbx58+Y9YFgb9/X1Mb5//x4scfr0
6X+3b9/+V1VV9QvkAGBY/4iLi2MFyoPLCaBLGYGWsL158wao7PZraLnxHyCAGKBh
IgtU4Ar04nSgd783Nzf/gUUMFxcXejr+zM3NDWeDUgcoQgsKChYDXe0EMgsUOgAB
BHO1KBCbAguXDKDXj4EUAi35iSVzoGBgEv3x+/fv/ydPnrwqLi6eDRQzgZrFBhBA
DNDszAfEakDsDwzPhkOHDl0BGT5//vzfurq639ANBKr5OnHixJ+gAun69etPgPHS
DhT3gZoBMosFIIBgZQUoKYgBsTEQRwDLgQ5gZB0FavwExP+AYf9/yZIlf4BJ78+V
K1f+gUo7oEu/rFq16rysrGwfUE84VK8YLEsDBBAjUiHEDsSCQCwFxMpArALMvhoR
EREqQBfKAjEPKC0DU8+3O3fuPAEaeufw4cNXgepuA/E9IH4GSlVADArCvwABhFx+
skIDHeQVUEklDbUE5AphBQUFAWDuYnj69CmoZAfF/iuoYU+B+CU0t34HYlBaZgAI
IEYsxSfI5dxAzA/1gQC0YIGVtSCNoELqA9SFoPT/FeZSWFIDCCBsdR4zFLNCMTs0
MphgaR6I/0AN+g3Ff6EYDgACDAA4HEdcvRpfPwAAAABJRU5ErkJggg==) no-repeat"
}
}
onButtonClick = function (ltTarget,ltEle,reason,behaviorParams) {
var tabs = ltEle.queryParent("div.tabs")
var tabid = ltEle.getAttribute("panel")
if(tabs and tabid){
if(ltEle.test("[selected]")){
var ltEle2 = ltEle.previousSibling(): ltEle.nextSibling()
if(!ltEle2) return ; //阻止删除最后一个
tabs.xcall("select",ltEle2.getAttribute("panel"))
}
tabs.querySelector("div[name='"+tabid+"']").delete()
ltEle.delete()
}
}
}

wbLayout.html = /*********
<html>
<head>
<style>
.tabs
{
font:system;
behavior:tabs;
height:100%%;
width:100%%;
overflow:hidden;
}
.tabs > .strip /* tab strip */
{
flow: h-flow;
margin-bottom:-1px;
padding: 2px 2px 0 2px;
}
.tabs > .strip > [panel] /* all tabs, passive by default */
{
padding: 3px 8px;
margin-bottom:1px;
height: 100%%;
max-width: max-intrinsic; /* not wider than max-intrinsic */
background-image:url(theme:tab-item-normal);
background-repeat:stretch;
behavior:horizontalTabsClose;
}
.tabs > .strip > [panel]:hover /* passive tab */
{
background-image:url(theme:tab-item-hover);
transition:blend;
}
.tabs > .strip > [panel]:current /*active tab*/
{
background-image:url(theme:tab-item-selected);
margin:-2px -2px -1px -2px;
padding: 4px 10px 5px 10px;
position:relative;
}
.tabs > .strip > [panel]:current:hover /*active tab*/
{
background-image:url(theme:tab-item-selected);
transition:none;
}
.tabs > .strip > [panel]:current:first-child,
.tabs > .strip > [panel]:current:hover:first-child
{
background-image:url(theme:tab-item-leftmost-selected);
}
/*.tabs:focus .strip [panel]:current
{
background-image:url(theme:tab-item-focused);
}*/
.tabs:tab-focus > .strip > [panel]:current > * /* outline active tab content if we've gotten focus by tab*/
{
outline: 1px dotted invert;
}
.tabs > [name] { display:none; }
.tabs > [name]:expanded
{
background-image:url(theme:tab-panel);
background-repeat:stretch;
padding:4px;
display:block;
height:100%%;
}
</style>
</head>
<body>
<div class="tabs" #test>
<div class="strip"> <!-- our tab strip, can be placed on any side of tab container. -->
<div panel="panel-id1" selected >tab1 caption</div>
<div panel="panel-id2" >tab2 caption</div>
<div panel="panel-id3" >tab3 caption</div>
<div panel="panel-id4" >tab3 caption</div>
<div panel="panel-id5" >tab3 caption</div>
</div>
<div name="panel-id1" selected> first panel content </div>
<div name="panel-id2"> second panel content <button>Test1</button> </div>
<div name="panel-id3"> third panel content </div>
<div name="panel-id4"> third panel content </div>
<div name="panel-id5"> third panel content </div>
</div>

</body>
</html>
*********/

winform.show()
win.loopMessage();

感谢分享源码,写的很好,
不过behavior主要用于写逻辑,而界面有关的部分应当尽量留给CSS,不宜在behavior写过多的CSS,或者把图片这些都写进去,这样在使用behavior的时候就不能自由定制外观了。

标准库的tabs对于动态创建的选项卡有一个添加关闭按钮的实现,他只是预留了一个节点以方便CSS自定义样式,可以参考下。