javascript – Tagfield滚动无效

我正在使用6.0
有时候我在ExtJS 6标签中遇到了奇怪的问题.我正在使用带有growMax的tagfield:3.现在当为tagfield选择的值超过三个tyhen时,我在tagfield中获得了一个指针上下选项.

这很好现在,当我点击向下箭头时,这个部分正好让我完全按照字段的底部.我无法看到其中放置了什么其他值.有什么办法可以减慢那些值的移动速度.

我的小提琴:Fiddle

重现的步骤.

>选择几个值(超过2或3)
>单击向下指针. (图中红框)

它可能会跳过第二个第三个值并引导您结束.

注意:有时我需要在tagfield中为100个数据执行此操作.甚至看不出我选择的是什么和所有.我也无法改变身高.

点击滚动按钮是否有任何更激烈的事件.

解决方法

更新(实际实现继承)

好吧,看起来你真的需要一个基于继承的解决方案.这段代码显然不是惯用的ExtJS,但似乎对我有用.首先定义一个自定义子类SingleLineTag并将’singleline-tagfield’指定为其xtype(在“旧答案”部分中有一些关于此代码背后主要思想的描述)

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);
        }
    }
});

现在更改items集合中的xtype

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,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',show: 'Star Wars: Christmas Special'}
    ]
});


var pnl = Ext.create('Ext.form.Panel',items: [{
        xtype: 'tagfield',growMax: 18,}]
});

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,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,beforeDeselect);
};

attachCustomScroll(window.tagField);

相关文章

kindeditor4.x代码高亮功能默认使用的是prettify插件,prett...
这一篇我将介绍如何让kindeditor4.x整合SyntaxHighlighter代...
js如何实现弹出form提交表单?(图文+视频)
js怎么获取复选框选中的值
js如何实现倒计时跳转页面
如何用js控制图片放大缩小