Search code examples
javascriptjquerytwitter-bootstrapjquery-uijquery-ui-resizable

Resizable stops working on div after its contents are updated


I am using jQuery UI's resizable function to make a div (bootstrap panel) that displays the contents of the file uploaded resizable. Resizable works on the div initially but after I update it with the contents of the file uploaded it stops working and the resizable cursor doesn't appear. This behavior can be observed in the snippet below and this jsfiddle.

$("#filePreview").resizable({
  handles: "n, s",
  minHeight: 100
});

function readFile(file) {
  var reader = new FileReader();
  reader.onload = readSuccess;

  function readSuccess(evt) {
    $('#filePreview').text(evt.target.result);
  };
  reader.readAsText(file);
}

$(document).on('change', '#inputFile', function() {
  readFile(this.files[0]);
});
.preview-panel {
  white-space: pre-line;
  overflow-y: scroll;
  min-height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.theme.css" rel="stylesheet"/>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>

<div class="container">
  <form class="form-inline">
    <div class="form-group">
      <label for="inputFile">File Input</label>
      <input type="file" class="form-control" id="inputFile">
    </div>
  </form>
  <div class="panel panel-default">
    <div class="panel-heading">File Preview</div>
    <div class="panel-body preview-panel" id="filePreview"></div>
  </div>
</div>

I have seen questions on resizable for dynamically added elements and tried reinitializing resizable after the div is updated with the new file content but it didn't work. How do I make resizable work on the div even after its content changes to display the preview of the last uploaded file?


Solution

  • Have you tried "destroying" the resizable div before setting the text and then re-initializing it after setting the text?

    function readFile(file) {
      var reader = new FileReader();
      reader.onload = readSuccess;
    
      function readSuccess(evt) {
        $('#filePreview').resizable('destroy');
        $('#filePreview').text(evt.target.result);
        $("#filePreview").resizable({
          handles: "n, s",
          minHeight: 100
        });
      };
      reader.readAsText(file);
    }
    

    I don't know if this is a quirk of the plugin, but you have to scroll to the top of the content in the div in order to see/use the resizable "handles".

    EDIT: To fix the issue with the "handle" losing its position when scrolling, I've added a helper function to add a top value using the the scrollTop value of #filePreview + the height of the .preview-panel + an additional offset (27px in this case). Whenever the scroll event is triggered on #filePreview, I'm adjusting the position of the handle accordingly.

    $("#filePreview").on('scroll', function() {
      adjustHandlePosition();
    });
    
    function adjustHandlePosition() {
      $('.ui-resizable-s').css('top', ($("#filePreview").scrollTop() + $('.preview-panel').height() + 27) + "px");
    }
    

    The adjustHandlePosition() method is also being called when the resize event occurs for #filePreview:

    $("#filePreview").resizable({
      handles: "n, s",
      minHeight: 100,
      resize: function(event, ui) {
        adjustHandlePosition();
      }
    });
    

    Updated Fiddle