Custom Resizable Handles in JQuery UI
Asked Answered
T

6

17

I've been attempting to create a resizable textbox (ASP.NET multiline TextBox / HTML textarea) and use JQuery UI to make it resizable, but seem to be running into a few issues involving custom drag handles.

The JQuery documentation on the Resizable method (specifically that on the handles option) suggests that I can set any of the handles to use a custom HTML element. I have managed to get the resizable textbox working perfectly well using the default resizable handles, but trying to set custom ones (i.e. an HTML element that I have defined in markup) creates the following issue: the resizable container leaves the correct amount of space for the div handle at the bottom (for the South handle), yet leaves the space empty and shows the element below (outside of) the resizable container (verified using Firebug).

Here is my markup (ASP.NET/XHTML) and JavaScript code:

<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>

Of course, I can't make the resizable handle div (class resizable-s) a child of the TextBox/textarea, but this should not be a problem according to the JQuery docs.

Judging by the searching I've done, I'm not the only person who's had this problem. (Unfortunately, the JQuery docs fail to give an example of using custom resizable handles, so we're all left unsure of precisely the right code.) If anyone could suggest a fix to this, or indeed confirmation that it is a JQuery bug, that would be very much appreciated.

Tuscany answered 5/6, 2009 at 22:18 Comment(0)
G
24

From a bit of digging I did in the jquery-ui code, I think I can confirm that a custom handle outside the resizable element doesn't work.

The problem is that the mouse events are initialized for the resizable element (or a wrapper element in the case of textarea). If the handle is not a child of where the mouse events are handled, it won't trigger the mousedown event on the handle, thus not making it draggable.

As a proof of concept I patched around a bit in jquery-ui until I got things to (sort of) work. No guarantees about the code, but it should point out what kind of changes would need to happen to make it work.

Around line 140 in ui.resizable.js I changed:

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

to

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

Then I added the following code (part of mouseInit from ui.core.js, probably should use the whole function) in ui.resizable.js (around line 180) after the mouseInit is called for the resizable element:

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

This allows me to make a resize handle that is not a child of the resizable element. My handle is a div with id 'south' and is attached to the resizable element. Here is the HTML snippit:

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

And the javascript code:

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

Hope this helps!

Graubert answered 10/6, 2009 at 8:16 Comment(8)
Thanks for investigating into this. I didn't expect a hack to fix the JS files, but it would be great to have one! Unfortunately, I've tried incorperating your changes, but without any luck. The "south" div appears as very small text and does not at all behave as a handle (setting font-size: 100%; makes the text clearly visible, but no more). Perhaps there are some other changes you made?Tuscany
Totally right, I missed one line I meddled with. I've put height/width/background color in the CSS for the south div in my own tests - that makes it easier to find the handle. Just with font-size 100% works though, so I didn't add the CSS rules to the analysis.Graubert
Strange... I'm still getting no results, and I've double-checked that my code matches what you've posted identically. Any ideas? Would it at all be possible for you to upload your test page and modified ui.resizable.js file?Tuscany
Sure: ringbreak.dnd.utwente.nl/~ylebre/stackoverflow I'm using FF3 and IE7 to test - in both cases dragging the 'south' div will resize the textarea. It still doesn't quite work like a 'regular' handle because the south div isn't repositioning though.Graubert
Ah, thanks for that. And yeah, I've managed to get it working now.( It seems I was just missing a reference.) Interesting that the south handle allows resizing horizontally as well - I can't figure out how to stop this.Tuscany
Ah, got it. If you add the class 'ui-resizable-s' to the south div it will only allow south/north dragging. This is my south div now: <div id="south" class="ui-resizable-handle ui-resizable-s">south</div>Graubert
@ylebre: Thanks. :) With a bit more playing around, I may be able to get something usable for my purposes. Hopefully this will get fixed in the next version of jQuery UI. (I'll try to submit a bug report.)Tuscany
2015 and I had to use your solution - this still hasn't been fixed. Many thanks.Comyns
I
3

Yeah, looks like a bug to me. Here's a complete sample, for those trying locally:

<!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>

This jQuery UI bug may be related.

Other things I tried:

  • Replace 'latest' with '1.6' and 'jquery-1.3.2' with 'jquery-1.2.6' to try with an older version of jQuery UI to see if it's a regression. Doesn't look like it.
  • Add ui-resizable-s and/or ui-resizable-handle CSS classes to #southgrip. No dice. However, if #southgrip is inside #resizable, it works. But, this doesn't solve your problem.
  • Using { 's': $('#southgrip').get(0) } for the handles option. No dice.
Irick answered 10/6, 2009 at 7:33 Comment(3)
BTW, while you're figuring out why jQuery UI isn't working, you may want to just use the Interface library's version of resizable textarea: interface.eyecon.ro/demos/resize_textarea.htmlIrick
Thanks for the reply... It does indeed now appear to be a bug. If I can't get ylebre's hack solution working (a jQueryUI solution is still slightly preferable), I'll definitely go with the Interface library, as that seems to be just what I want.Tuscany
I would not suggest using the hacked up version I posted - its more a proof that there is actually a problem with the jquery-ui code, and in which direction a solution could be manufactured. I would not recommend taking that code into production anywhere :)Graubert
E
1

I had the same problem 4 years after. It sames they never fixed that. I though to use Interface but it did not have any updates since 2007. So I decided to fix the bug by myself and make a request pull in the jQuery UI project in Github. https://github.com/jquery/jquery-ui/pull/1134 I hope they accept it and merge it soon. I added a test so I'm sure it will work in any case because all the tests of resizable from Jquery UI works with this modification.

I started using ylebre code but it did not work. So I made some little changes.

Ewell answered 13/11, 2013 at 14:16 Comment(0)
E
0

Finally found an extremely effective solution after hours of trying to get over this annoying bug. Simply, append your handle element in the ui class. The function below has been tested and works fine with South and West handles. Hope that helps!

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

When you call the function like below, your custom handle will be placed in the right location and will work probably. PS: the function works with 'n' and 's' handles.

resizables($("#draggable"), $("#handle"), 's');
Ear answered 29/10, 2014 at 14:36 Comment(0)
D
0

in 2020, this simple solution works..

$('.your-class').each(function (index) {
        $(this).resizable({
            handles: { e: $(this).find('.child-div .handle-resize-class') },
Discursion answered 4/8, 2020 at 7:36 Comment(0)
S
-1

I had a similar issue but my need was to set the hadlers dynamically to multiple elements:

            $.each($(".imagecontainer"),function() {
                $(this).resizable({
                    handles: {se: $(this).closest(".spaciator").find(".ui-resizable-se")}
                });
            };
Scrummage answered 17/8, 2015 at 16:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.