jQuery UI 中的自定义可调整大小的手柄

17
我一直在尝试创建一个可调整大小的文本框(ASP.NET 多行 TextBox / HTML textarea),并使用 JQuery UI 实现可调整大小,但似乎遇到了一些涉及自定义拖动句柄的问题。
JQuery 关于 Resizable 方法的文档(特别是 handles 选项)建议我可以设置任何句柄来使用自定义 HTML 元素。我已经成功地使用默认可调整大小的句柄使可调整大小的文本框正常工作,但尝试设置自定义句柄(即我在标记中定义的 HTML 元素)会出现以下问题:可调整大小的容器为底部的 div 句柄留下了正确的空间(对于南侧句柄),但留下了空白的空间,并显示了可调整大小容器之外(使用 Firebug 验证)。
以下是我的标记(ASP.NET/XHTML)和 JavaScript 代码:
<asp:TextBox runat="server" ID="codeTextBox" TextMode="MultiLine" Wrap="false" Rows="15">
</asp:TextBox>
<div class="resizable-s" style="width: 100%; height: 22px; background: red;">
</div>

<script type="text/javascript">

    $(function() {
        var codeTextBox = $("#<%= codeTextBox.ClientID %>");

        codeTextBox.resizable({
            handles: { s : $(".resizable-s") },
            minHeight: 80,
            maxHeight: 400
        });
    });

</script>

当然,我不能将可调整大小的句柄 div(class “resizable-s”)作为TextBox/textarea的子代,但根据JQuery文档,这不应该是一个问题。 从我所做的搜索来看,我并不是唯一遇到这个问题的人。(不幸的是,JQuery文档没有给出使用自定义可调整大小句柄的示例,因此我们都不确定正确的代码。)如果有人能提出修复方法或确实确认这是一个JQuery错误,那将非常感激。
6个回答

24

我在jquery-ui的代码中进行了一些探索,我认为我可以确认自定义的把手不能放置在可缩放元素之外。

问题在于鼠标事件是针对可缩放元素(或文本区域的包装元素)进行初始化的。如果把手不是在处理鼠标事件的子级中,则不会触发把手上的mousedown事件,因此它无法被拖动。

作为一个概念验证,我在jquery-ui中进行了一些修补,直到事情(在某种程度上)能够工作为止。不能保证代码的稳定性,但它应该指出需要进行哪些更改才能使其正常工作。

在ui.resizable.js的第140行左右,我做了以下更改:

this._handles = $('.ui-resizable-handle', this.element)
    .disableSelection();
this._handles = $('.ui-resizable-handle')
    .disableSelection();

然后我在 ui.resizable.js 文件中的 mouseInit 函数中添加了以下代码(来自 ui.core.js 的 mouseInit 函数,可能需要使用整个函数),位置在 resizable 元素的 mouseInit 被调用后,大约在第180行:

   ...
   //Initialize the mouse interaction
   this._mouseInit();

   // Add mouse events for the handles as well - ylebre
   for (i in this.handles) {
      $(this.handles[i]).bind('mousedown.resizable', function(event) {
        return self._mouseDown(event);
      });
   }

这使我能够创建一个不是可调整大小元素的子元素的调整大小句柄。我的句柄是一个带有id“south”的div,并附加到可调整大小的元素上。这是HTML片段:

<textarea id="resizable" class="ui-widget-content">
    <h3 class="ui-widget-header">Resizable</h3>
</textarea>
<div id="south" class="ui-resizable-handle">south</div>

还有 JavaScript 代码:

    $("#resizable").resizable(
        {handles: {s: document.getElementById("south")}}
    );

希望这能有所帮助!


感谢您对此进行调查。我没有想到会有一个黑客来修复JS文件,但如果有一个的话那就太好了!不幸的是,我尝试了将您的更改合并进去,但没有成功。 "south" div 显示为非常小的文本,并且根本不像一个手柄(设置 font-size: 100%; 可以使文本清晰可见,但没有更多效果)。也许您还做了其他一些更改? - Noldorin
完全正确,我错过了一行我搞砸了。在我的测试中,我将高度/宽度/背景颜色放在CSS中的南部div中 - 这使得更容易找到手柄。只有字体大小为100%的情况下才有效,因此我没有将CSS规则添加到分析中。 - ylebre
奇怪...我仍然没有得到任何结果,而且我已经仔细检查了我的代码是否与您发布的完全相同。有什么想法吗?您能否上传您的测试页面和修改后的ui.resizable.js文件? - Noldorin
@ylebre:谢谢。 :) 再多玩一下,我可能能够得到一些对我的目的有用的东西。希望这个问题会在下一个版本的jQuery UI中得到解决。(我会尝试提交一个错误报告。) - Noldorin
2015年我不得不使用你的解决方案 - 这个问题仍未被修复。非常感谢。 - Jimbo
显示剩余3条评论

3

是的,看起来像是一个bug。以下是一个完整的示例,供那些正在本地尝试的人使用:

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="http://jqueryui.com/latest/themes/base/ui.all.css" type="text/css"/>
  <script src="http://jquery-ui.googlecode.com/svn/tags/latest/jquery-1.3.2.js" type="text/javascript"></script>
  <script src="http://jquery-ui.googlecode.com/svn/tags/latest/ui/ui.core.js" type="text/javascript"></script>
  <script src="http://jquery-ui.googlecode.com/svn/tags/latest/ui/ui.resizable.js" type="text/javascript"></script>
  <style type="text/css">
    #resizable { width: 100px; height: 100px; background: silver; }
    #southgrip { width: 100px; height: 10px; background-color: blue; }
  </style>
  <script type="text/javascript">
    $(function() {
      $('#resizable').resizable({
        handles: { 's': $('#southgrip') },
        minHeight: 80,
        maxHeight: 400
      });
    });
  </script>
</head>
<body>

<div id="resizable"></div>
<div id="southgrip"></div>

</body>
</html>

这个jQuery UI的bug 可能会有关系。

我尝试了其他方法:

  • 将“latest”替换为“1.6”,将“jquery-1.3.2”替换为“jquery-1.2.6”,以尝试使用旧版本的jQuery UI来查看它是否是一个回归问题。看起来不像。
  • #southgrip添加ui-resizable-s和/或ui-resizable-handleCSS类。没有成功。然而,如果#southgrip#resizable内部,则可以工作。但是,这并不能解决您的问题。
  • 对于handles选项,使用{'s': $('#southgrip').get(0)}。没有成功。

1
顺便说一句,当你在弄清楚为什么jQuery UI不起作用时,你可能想要使用Interface库的可调整大小的textarea版本:http://interface.eyecon.ro/demos/resize_textarea.html - Roman Nurik
感谢回复...看起来现在确实是一个bug。如果我无法让ylebre的hack解决方案运行(jQueryUI解决方案仍然稍微优选),我肯定会选择Interface库,因为那似乎正是我想要的东西。 - Noldorin
我不建议使用我发布的那个被修改过的版本 - 它更多是一个证明jquery-ui代码确实存在问题的证据,以及可以制造解决方案的方向。我不建议在任何生产环境中使用那段代码 :) - ylebre

1
我在四年后也遇到了相同的问题。看起来他们从未修复过这个问题。我考虑使用接口,但自2007年以来就没有任何更新了。 所以,我决定自己修复这个bug,并在Github上的jQuery UI项目中发出请求合并。https://github.com/jquery/jquery-ui/pull/1134 我希望他们能很快接受并合并它。 我添加了一个测试,所以我确信它会在任何情况下都有效,因为来自Jquery UI的所有可调整大小的测试都可以通过这个修改。 我开始使用ylebre的代码,但它没有起作用。所以我做了一些小改动。

0

在经过数小时的尝试后,终于找到了一种极其有效的解决方案,以克服这个令人烦恼的错误。简单地将您的句柄元素附加到ui类中即可。下面的函数已经经过测试,并且与南部和西部的句柄一起正常工作。希望这可以帮助到您!

function resizables(element, handle, type){

 var height = handle.height();
 var place = type =="s"? "bottom":"top";
 var css = {};
        css["height"] = height+"px";
        css[place] = -height+"px";


 element.resizable({handles: type});
 var jqclass = element.find(".ui-resizable-"+type);

        handle.css({"cursor": type+"-resize"});
        jqclass.append(handle); 
        jqclass.css(css);
}

当您像下面这样调用函数时,您的自定义句柄将被放置在正确的位置,并且可能会正常工作。 PS:该函数适用于“n”和“s”句柄。
resizables($("#draggable"), $("#handle"), 's');

0

在2020年,这个简单的解决方案有效。

$('.your-class').each(function (index) {
        $(this).resizable({
            handles: { e: $(this).find('.child-div .handle-resize-class') },

-1

我遇到了类似的问题,但我的需求是动态地将处理程序设置为多个元素:

            $.each($(".imagecontainer"),function() {
                $(this).resizable({
                    handles: {se: $(this).closest(".spaciator").find(".ui-resizable-se")}
                });
            };

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接