2

我正在尝试使用 Extjs 的 dragSource 实现拖放。用户应该能够选择文本并将其拖放到放置区域中。当用户选择一些文本时,我创建了一个拖动源实例。

该代码在 Extjs 3.0 版中运行良好。现在,我已移至版本 3.4,这导致了以下问题。

当我向下滚动窗口并选择最初不可见的文本时,我无法拖动它。文本被正确选择并应用了正确的样式,但它不可拖动。在可见部分一切都很好,问题是当你必须向下滚动一些文本时。

下面是创建拖动源的代码。

handleTextSelection:function() {
    var range = this.getRangeObject();
    if (range) {
        if ( (range.text && range.text.length == 0) || (range.toString && range.toString().length == 0)) {
            this.lastUserSelection = null;
            return;
        }
        var node = document.createElement("div");
        node.id = "user_selection_" + SEM.util.getUID();
        node.className = "anno_user_selection";
        if (range.surroundContents) {
            range.surroundContents(node);
        } 
        node.style.display = "inline";
        var el = Ext.get(node.id);
        this.lastUserSelection = el;
        if (el) {
            el.dragSource = new Ext.dd.DragSource(el);
            el.dragSource.dragData = {
                objectType:SEM.JSGraph.USER_SELECTION_TYPE,
                nodes:[node],
                text:el.dom.textContent.trim(),
                title:el.dom.textContent.trim()
            };
        }
    }else if (!SEM.JSGraph.currentEditor.selectionstate){
        if (this.lastUserSelection) {
            var el = this.lastUserSelection;
            Ext.DomHelper.insertAfter(el.dom.previousSibling, el.dom.textContent);
            el.dom.parentNode.removeChild(el.dom);
            //Ext.DomHelper.overwrite(el, el.dom.textContent);
        }
        this.lastUserSelection = null;          
    }       

以下是用于创建范围对象的 getRangeObject 函数。

getRangeObject:function() {
    var selection = null;
    if (window.getSelection) {
        selection = window.getSelection();
    }else if (document.getSelection) {
        selection = document.getSelection();
    }else if (document.selection) {
        selection = document.selection.createRange();
    }
    var range = null;
    if (selection != "") {
        if (selection.getRangeAt) {
            range = selection.getRangeAt(0);
        }else if(document.createRange) {
            range = document.createRange();
            range.setStart(selection.anchorNode, selection.anchorOffset);
            range.setEnd(selection.focusNode, selection.focusOffset);
        } else {
            range = selection;
        }
    }
    return range;
}

我已经使用 mouseUp 事件注册了函数 handleTextSelection。

Ext.getBody().on("mouseup",this.handleTextSelection.createDelegate(this));

此代码与 Extjs 3.0 完美配合。但是在与 Extjs 3.4 一起使用时会遇到上述问题。

我在调试时发现了以下事实,这可能会有所帮助。

1:我注册了,监听拖拽源的以下事件。

el.dragSource.startDrag = function(){
    alert('startDrag');
};
el.dragSource.b4Drag = function(){
    alert('b4Drag');
};
el.dragSource.onBeforeDrag = function(){
    alert('onBeforeDrag');
};
el.dragSource.onStartDrag = function(){
    alert('onStartDrag');
};

正如预期的那样,这些事件是针对最初可见的文本触发的。但是对于最初不可见的文本,只会触发 onBeforeDrag 事件。

2:fireFox 和 chrome 的行为相同。因此,这似乎不是特定于浏览器的问题。

上述代码中的 Extjs 3.4 规范有什么问题吗?谁能指出为什么 Extjs 3.4 会面临这个问题?

4

1 回答 1

0

好的,我找到了解决方案。

Extjs 3.4 的 ext-all-debug.js 中的一些代码导致了问题。3.0 版本中没有此代码。

要解决此问题,请在 ext-all-debug.js 中搜索“getLocation: function(oDD) {”并注释掉以下代码。

         /*
         * The code below is to ensure that large scrolling elements will
         * only have their visible area recognized as a drop target, otherwise it 
         * can potentially erronously register as a target when the element scrolls
         * over the top of something below it.
         */
        el = Ext.get(el.parentNode);
        while (el && region) {
            if (el.isScrollable()) {
                // check whether our element is visible in the view port:
                region = region.intersect(el.getRegion());
            }
            el = el.parent();
        }

正如评论中所解释的那样,它可以解决一些问题,但随后它导致了上述指定的问题。

我不知道他们的意思

         * otherwise it 
         * can potentially erronously register as a target when the element scrolls
         * over the top of something below it. 

如果有人可以详细说明它会很有帮助。

于 2013-06-25T13:44:27.380 回答