我正在使用6.0
有时候我在ExtJS 6标签中遇到了奇怪的问题。我正在使用带有growMax : 3
的标记字段。现在当为tagfield选择的值超过三个tyhen时,我在tagfield中获得了一个指针向上和向下选项。
这很好现在,当我点击向下箭头时,这个部分就是我正好把我带到了田野的底部。我无法看到其中放置了什么其他值。有什么方法可以减慢那些值的移动速度。
我的小提琴:Fiddle
重现的步骤。
答案 0 :(得分:4)
更新(实际上是实现继承)
好的,看起来你真的需要一个基于继承的解决方案。这段代码显然不是一个惯用的ExtJS,但它似乎对我有用。首先定义自定义子类SingleLineTag
并将'singleline-tagfield'
指定为其xtype
(在#34;旧答案&#34;部分中对此代码背后的主要想法有一些描述)< / p>
Ext.define('Ext.form.field.SingleLineTag', {
extend: 'Ext.form.field.Tag',
xtype: 'singleline-tagfield',
initEvents: function () {
var me = this;
me.callParent(arguments);
me.itemList.el.dom.parentElement.addEventListener('scroll', Ext.bind(me.zzzOnTagScroll, me));
},
zzzGetTagLastScroll: function () {
var me = this;
return me.zzzLastScroll = me.zzzLastScroll || {
lastIndex: 0,
lastTop: 0,
lastTimeStamp: 0
};
},
zzzScrollToTagIndex: function (index) {
var tagField = this;
var lastScroll = tagField.zzzLastScroll;
if (lastScroll) {
var lstDom = tagField.itemList.el.dom;
var childrenDom = lstDom.children;
var containerDom = tagField.itemList.el.dom.parentElement;
if ((index >= 0) && (index < childrenDom.length)) {
lastScroll.lastIndex = index;
containerDom.scrollTop = lastScroll.lastTop = childrenDom[index].offsetTop - lstDom.offsetTop;
}
}
},
zzzOnTagScroll: function (ev) {
var me = this;
var lastScroll = me.zzzGetTagLastScroll();
// throttle scroll events as thy occur to often and we might scroll to much
if (Math.abs(lastScroll.lastTimeStamp - ev.timeStamp) < 200) {
ev.preventDefault();
return;
}
lastScroll.lastTimeStamp = ev.timeStamp;
var lstDom = me.itemList.el.dom;
var childrenDom = lstDom.children;
var containerDom = me.itemList.el.dom.parentElement;
var scrollTop = containerDom.scrollTop;
var index = lastScroll.lastIndex;
if (index >= childrenDom.length)
index = childrenDom.length - 1;
if (index < 0)
index = 0;
var lstTop = lstDom.offsetTop;
if (scrollTop > lastScroll.lastTop) {
// scrolling down, find next element
for (; index < childrenDom.length; index++) {
if (childrenDom[index].offsetTop - lstTop > scrollTop) {
break;
}
}
if (index < childrenDom.length) {
// we've found the next element so change scroll position to it's top
me.zzzScrollToTagIndex(index);
}
else {
lastScroll.lastIndex = childrenDom.length;
lastScroll.lastTop = containerDom.scrollTop;
}
}
else {
// scrolling up, find prev element
for (; index >= 0; index--) {
if (childrenDom[index].offsetTop - lstTop < scrollTop) {
break;
}
}
if (index >= 0) {
// we've found the prev element so change scroll position to it's top
me.zzzScrollToTagIndex(index);
}
else {
lastScroll.lastIndex = 0;
lastScroll.lastTop = 0;
}
}
},
onBeforeDeselect: function (list, record) {
var me = this;
me.callParent(arguments);
var value = record.get(me.valueField);
var index = me.getValue().indexOf(value);
var lastScroll = me.zzzGetTagLastScroll();
if (lastScroll.lastIndex > index)
lastScroll.lastIndex -= 1;
var nextIndex = (lastScroll.lastIndex > index) ? lastScroll.lastIndex - 1 : lastScroll.lastIndex;
setTimeout(function () {
me.zzzScrollToTagIndex(nextIndex);
}, 0);
},
onItemListClick: function(ev) {
var me = this;
// HACK for IE: throttle click events after scroll
// click on the scrollbar seem to generate click on the "itemList" as well
// which lead to showing of the dropdown
var lastScroll = me.zzzGetTagLastScroll();
if (Math.abs(lastScroll.lastTimeStamp - ev.timeStamp) > 200) {
me.callParent(arguments);
}
}
});
现在更改xtype
个收藏集中的items
var shows = Ext.create('Ext.data.Store', {
fields: ['id', 'show'],
data: [
{id: 0, show: 'Battlestar Galactica'},
{id: 11, show: 'Doctor Who'},
{id: 2, show: 'Farscape'},
{id: 3, show: 'Firefly'},
{id: 4, show: 'Star Trek'},
{id: 5, show: 'Star Wars: Christmas Special'}
]
});
Ext.create('Ext.form.Panel', {
renderTo: Ext.getBody(),
title: 'Sci-Fi Television',
height: 200,
width: 300,
items: [{
//xtype: 'tagfield', // old
xtype: 'singleline-tagfield', // new
growMax: 18,
fieldLabel: 'Select a Show',
store: shows,
displayField: 'show',
valueField: 'id',
queryMode: 'local',
filterPickList: true,
}]
});
请注意,如果您没有将此元素配置为实际只采用单行高度,则在滚动方面它会表现得很奇怪。
请参阅此Sencha fiddle
的合并代码旧答案
我对ExtJS并不擅长,但我认为一些不那么好的答案总比没有答案好。首先,我同意growMax以像素为单位,因此3太少了。仍在考虑你的问题,似乎没有足够的空间来完成一个完整的滚动条,因此唯一的方法是添加自定义滚动逻辑。可能最好创建一个继承自Tag
的新类,但我不确定在ExtJS中如何正确地完成它,所以这里有一些自定义的,可能是非惯用的代码。
function findComponentByElement(node) {
var topmost = document.body,
target = node,
cmp;
while (target && target.nodeType === 1 && target !== topmost) {
cmp = Ext.getCmp(target.id);
if (cmp) {
return cmp;
}
target = target.parentNode;
}
return null;
}
var getTagLastScroll = function (tagField) {
return tagField.zzzLastScroll = tagField.zzzLastScroll || {
lastIndex: 0,
lastTop: 0,
lastTimeStamp: 0
};
};
var scrollToTagIndex = function (tagField, index) {
var lastScroll = tagField.zzzLastScroll;
if (lastScroll) {
var lstDom = tagField.itemList.el.dom;
var childrenDom = lstDom.children;
var containerDom = tagField.itemList.el.dom.parentElement;
if ((index >= 0) && (index < childrenDom.length)) {
lastScroll.lastIndex = index;
containerDom.scrollTop = lastScroll.lastTop = childrenDom[index].offsetTop - lstDom.offsetTop;
//console.log("Scroll to " + containerDom.scrollTop);
//console.log(lastScroll);
}
}
};
var onTagScroll = function (ev) {
var tagField = findComponentByElement(ev.target);
var lastScroll = getTagLastScroll(tagField);
// need to throttle scroll events or will scroll to much
if (Math.abs(lastScroll.lastTimeStamp - ev.timeStamp) < 200) {
ev.preventDefault();
return;
}
//console.log(ev);
lastScroll.lastTimeStamp = ev.timeStamp;
var lstDom = tagField.itemList.el.dom;
var childrenDom = lstDom.children;
var containerDom = tagField.itemList.el.dom.parentElement;
var scrollTop = containerDom.scrollTop;
//console.log("Before " + containerDom.scrollTop);
//console.log(lastScroll);
var index = lastScroll.lastIndex;
if (index >= childrenDom.length)
index = childrenDom.length - 1;
if (index < 0)
index = 0;
var lstTop = lstDom.offsetTop;
if (scrollTop > lastScroll.lastTop) {
// scrolling down, find next element
for (; index < childrenDom.length; index++) {
if (childrenDom[index].offsetTop - lstTop > scrollTop) {
break;
}
}
if (index < childrenDom.length) {
// we've found the next element so change scroll position to it's top
scrollToTagIndex(tagField, index);
}
else {
lastScroll.lastIndex = childrenDom.length;
lastScroll.lastTop = containerDom.scrollTop;
}
}
else {
// scrolling up, find prev element
for (; index >= 0; index--) {
if (childrenDom[index].offsetTop - lstTop < scrollTop) {
break;
}
}
if (index >= 0) {
// we've found the prev element so change scroll position to it's top
scrollToTagIndex(tagField, index);
}
else {
lastScroll.lastIndex = 0;
lastScroll.lastTop = 0;
}
}
//console.log("After " + containerDom.scrollTop);
//console.log(lastScroll);
};
var beforeDeselect = function (tagField, record) {
var value = record.get(tagField.valueField);
var index = tagField.getValue().indexOf(value);
var lastScroll = getTagLastScroll(tagField);
if (lastScroll.lastIndex > index)
lastScroll.lastIndex -= 1;
var nextIndex = (lastScroll.lastIndex > index) ? lastScroll.lastIndex - 1 : lastScroll.lastIndex;
setTimeout(function () {
scrollToTagIndex(tagField, nextIndex);
}, 0);
};
var attachCustomScroll = function (tagField) {
var containerDom = tagField.itemList.el.dom.parentElement;
containerDom.addEventListener('scroll', onTagScroll);
tagField.on('beforeDeselect', beforeDeselect);
};
您只需执行类似
的操作即可使用它var pnl = Ext.create('Ext.form.Panel', {
...
});
var tagField = pnl.items.items[0];
attachCustomScroll(tagField);
我的代码的主要思想是截取包含ul
的容器元素的滚动事件和所选项目,并将事件视为真正的滚动,而不是将一个元素滚动到它的方向。正常工作所需的数据以希望独特的zzzLastScroll
名称附加到小部件。
另外还有一些逻辑可以在删除某些项目时使滚动看起来更好。
<小时/> 完整代码(而不是小提琴)
不幸的是,我没有ExtJS帐户,没有它我无法在那里创建一个新的小提琴,所以以下是我使用的修改后的 app.js 的完整代码测试我的代码。
var shows = Ext.create('Ext.data.Store', {
fields: ['id', 'show'],
data: [
{id: 0, show: 'Battlestar Galactica'},
{id: 11, show: 'Doctor Who'},
{id: 2, show: 'Farscape'},
{id: 3, show: 'Firefly'},
{id: 4, show: 'Star Trek'},
{id: 5, show: 'Star Wars: Christmas Special'}
]
});
var pnl = Ext.create('Ext.form.Panel', {
renderTo: Ext.getBody(),
title: 'Sci-Fi Television',
height: 200,
width: 300,
items: [{
xtype: 'tagfield',
growMax: 18,
fieldLabel: 'Select a Show',
store: shows,
displayField: 'show',
valueField: 'id',
queryMode: 'local',
filterPickList: true,
}]
});
window.tagField = pnl.items.items[0];
window.lstDom = window.tagField.itemList.el.dom;
window.container = window.lstDom.parentElement;
tagField.setValue([11, 3, 4, 5]);
function findComponentByElement(node) {
var topmost = document.body,
target = node,
cmp;
while (target && target.nodeType === 1 && target !== topmost) {
cmp = Ext.getCmp(target.id);
if (cmp) {
return cmp;
}
target = target.parentNode;
}
return null;
}
var getTagLastScroll = function (tagField) {
return tagField.zzzLastScroll = tagField.zzzLastScroll || {
lastIndex: 0,
lastTop: 0,
lastTimeStamp: 0
};
};
var scrollToTagIndex = function (tagField, index) {
var lastScroll = tagField.zzzLastScroll;
if (lastScroll) {
var lstDom = tagField.itemList.el.dom;
var childrenDom = lstDom.children;
var containerDom = tagField.itemList.el.dom.parentElement;
if ((index >= 0) && (index < childrenDom.length)) {
lastScroll.lastIndex = index;
containerDom.scrollTop = lastScroll.lastTop = childrenDom[index].offsetTop - lstDom.offsetTop;
//console.log("Scroll to " + containerDom.scrollTop);
//console.log(lastScroll);
}
}
};
var onTagScroll = function (ev) {
var tagField = findComponentByElement(ev.target);
var lastScroll = getTagLastScroll(tagField);
if (Math.abs(lastScroll.lastTimeStamp - ev.timeStamp) < 200) {
ev.preventDefault();
return;
}
//console.log(ev);
lastScroll.lastTimeStamp = ev.timeStamp;
var lstDom = tagField.itemList.el.dom;
var childrenDom = lstDom.children;
var containerDom = tagField.itemList.el.dom.parentElement;
var scrollTop = containerDom.scrollTop;
//console.log("Before " + containerDom.scrollTop);
//console.log(lastScroll);
var index = lastScroll.lastIndex;
if (index >= childrenDom.length)
index = childrenDom.length - 1;
if (index < 0)
index = 0;
var lstTop = lstDom.offsetTop;
if (scrollTop > lastScroll.lastTop) {
// scrolling down, find next element
for (; index < childrenDom.length; index++) {
if (childrenDom[index].offsetTop - lstTop > scrollTop) {
break;
}
}
if (index < childrenDom.length) {
// we've found the next element so change scroll position to it's top
scrollToTagIndex(tagField, index);
}
else {
lastScroll.lastIndex = childrenDom.length;
lastScroll.lastTop = containerDom.scrollTop;
}
}
else {
// scrolling up, find prev element
for (; index >= 0; index--) {
if (childrenDom[index].offsetTop - lstTop < scrollTop) {
break;
}
}
if (index >= 0) {
// we've found the prev element so change scroll position to it's top
scrollToTagIndex(tagField, index);
}
else {
lastScroll.lastIndex = 0;
lastScroll.lastTop = 0;
}
}
//console.log("After " + containerDom.scrollTop);
//console.log(lastScroll);
};
var beforeDeselect = function (tagField, record) {
var value = record.get(tagField.valueField);
var index = tagField.getValue().indexOf(value);
var lastScroll = getTagLastScroll(tagField);
if (lastScroll.lastIndex > index)
lastScroll.lastIndex -= 1;
var nextIndex = (lastScroll.lastIndex > index) ? lastScroll.lastIndex - 1 : lastScroll.lastIndex;
setTimeout(function () {
scrollToTagIndex(tagField, nextIndex);
}, 0);
};
var attachCustomScroll = function (tagField) {
var containerDom = tagField.itemList.el.dom.parentElement;
containerDom.addEventListener('scroll', onTagScroll);
tagField.on('beforeDeselect', beforeDeselect);
};
attachCustomScroll(window.tagField);
答案 1 :(得分:1)