New custom code: display two blocks next to each other with a "drag border" feature

Hi all,

First: a demo, to be viewed on desktop -Feature made to be disabled on mobile devices => https://test-play.softr.app/two-columns-draggable

Now the codes to insert.

I) In a custom code block, in my example, just below the hero block (reduce the padding top and bottom of this custom code block to not disturb your page design)

<div class="row">
  <div class="column left-column">
    <div class="draggable-border"></div>
    <span id="tocolumn1"></span>
  </div>
  <div class="column right-column">
    <div class="draggable-border"></div>
    <span id="tocolumn2"></span>
  </div>
</div>

II) In the header code of the page settings:

<style>
.column {
  float: left;
}

.left-column {
  width: 50%;
  border-right: 1px solid #ebebeb;
  position: relative;
}

.right-column {
  width: 50%;
  position: relative;
}

.draggable-border {
  position: absolute;
  top: 0;
  width: 6px;
  height: 100%;
  cursor: col-resize;
  z-index: 1;
  background-color: #ebebeb;
  border-radius: 4px;
}

.left-column .draggable-border {
  right: -3px;
}

.right-column .draggable-border {
  left: -3px;
}

.left-column:hover .draggable-border,
.right-column:hover .draggable-border {
  background-color: #ddd;
}

.row:after {
  content: "";
  display: table;
  clear: both;
}

@media screen and (max-width: 600px) {
  .column {
    width: 100%;
  }
}
</style>

III) In the footer code of the page settings Replace #chart1 and #chart2 by the block ids you want

<script>
$("#chart1").insertAfter($("#tocolumn1"));
$("#chart2").insertAfter($("#tocolumn2"));
</script>

<script>
$(function() {
  var dragging = false;
  var leftColumn = $('.left-column');
  var rightColumn = $('.right-column');
  var border = $('.draggable-border');

  border.mousedown(function(e) {
    e.preventDefault();
    dragging = true;
  });

  $(document).mouseup(function() {
    dragging = false;
  });

  $(document).mousemove(function(e) {
    if (dragging) {
      var offset = e.pageX - leftColumn.offset().left;
      var newLeftWidth = offset / leftColumn.parent().width() * 100;
      var newRightWidth = 100 - newLeftWidth;

      if (newLeftWidth < 30) {
        rightColumn.css('pointer-events', 'none');
      } else if (newRightWidth < 30) {
        leftColumn.css('pointer-events', 'none');
      } else {
        leftColumn.css('pointer-events', 'auto');
        rightColumn.css('pointer-events', 'auto');
        leftColumn.css('width', newLeftWidth + '%');
        rightColumn.css('width', newRightWidth + '%');
      }
    }
  });
});
</script>

IMPORTANT: I made impossible to drag one or the other column if their width is below 30% of their original width. Otherwise it is going to be a disgusting design.

That being said, you can overwrite it by changing the value ‘30’ of these code lines:
if (newLeftWidth < 30) {
and
} else if (newRightWidth < 30) {

The look of the draggable border is fully customizable in this part of the code

.draggable-border {
  position: absolute;
  top: 0;
  width: 6px;
  height: 100%;
  cursor: col-resize;
  z-index: 1;
  background-color: #ebebeb;
  border-radius: 4px;
}

If you want to change the wifth of the .draggable-border you will also need to change this part of the code

.left-column .draggable-border {
  right: -3px;
}

.right-column .draggable-border {
  left: -3px;
}

Let’s take an example: you want the width of the .draggable-border to be 10px. You will need to change the -3px to -5px, otherwise two draggable borders will appear.

3 Likes

This is really cool!

Thanks for sharing. thats breakthrough to my use case.
btw how to add each block item inside this custom code block?

That part of the code does the job. Change #chart1 and #chart2 by the ID of your blocks

Is there a way to have multiple code blocks on one page that are like this?

Yes, this is possible to add as many code blocks in any Softr page.

How would I do that?

If you want to achieve this: https://test-play.softr.app/two-columns-draggable-multiple

You need to add a second custom code block with this code inside (you can play with padding top of the custom code block to add space between the two column blocks)

<div class="row2">
  <div class="column left-column2">
    <div class="draggable-border2"></div>
    <span id="tocolumn3"></span>
  </div>
  <div class="column right-column2">
    <div class="draggable-border2"></div>
    <span id="tocolumn4"></span>
  </div>
</div>

Change the code inside the header code in the page settings by:

<style>
.column {
  float: left;
}

.left-column {
  width: 50%;
  position: relative;
}

.left-column2 {
  width: 50%;
  position: relative;
}

.right-column {
  width: 50%;
  position: relative;
}

.right-column2 {
  width: 50%;
  position: relative;
}

.draggable-border {
  position: absolute;
  top: 0;
  width: 6px;
  height: 100%;
  cursor: col-resize;
  z-index: 1;
  background-color: #ebebeb;
  border-radius: 8px;
}

.draggable-border2 {
  position: absolute;
  top: 0;
  width: 6px;
  height: 100%;
  cursor: col-resize;
  z-index: 1;
  background-color: #ebebeb;
  border-radius: 8px;
}

.left-column .draggable-border {
  right: -3px;
}

.left-column2 .draggable-border2 {
  right: -3px;
}

.right-column .draggable-border {
  left: -3px;
}

.right-column2 .draggable-border2 {
  left: -3px;
}

.left-column:hover .draggable-border,
.right-column:hover .draggable-border {
  background-color: #ddd;
}

.left-column2:hover .draggable-border2,
.right-column2:hover .draggable-border2 {
  background-color: #ddd;
}

.row:after {
  content: "";
  display: table;
  clear: both;
}

.row2:after {
  content: "";
  display: table;
  clear: both;
}

@media screenand (max-width: 600px) {
  .column {
    width: 100%;
  }
}
</style>

Change the code in the footer code of the page settings by

<script>
$(function() {
  // Move chart1 and chart2
  $("#chart1").insertAfter($("#tocolumn1"));
  $("#chart2").insertAfter($("#tocolumn2"));

  // Move calendar1 and chart3
  $("#calendar1").insertAfter($("#tocolumn3"));
  $("#chart3").insertAfter($("#tocolumn4"));

  // Dragging functionality for the first border
  var dragging1 = false;
  var leftColumn1 = $('.left-column');
  var rightColumn1 = $('.right-column');
  var border1 = $('.draggable-border');

  border1.mousedown(function(e) {
    e.preventDefault();
    dragging1 = true;
  });

  $(document).mouseup(function() {
    dragging1 = false;
  });

  $(document).mousemove(function(e) {
    if (dragging1) {
      var offset = e.pageX - leftColumn1.offset().left;
      var newLeftWidth = offset / leftColumn1.parent().width() * 100;
      var newRightWidth = 100 - newLeftWidth;

      if (newLeftWidth < 30) {
        rightColumn1.css('pointer-events', 'none');
      } else if (newRightWidth < 30) {
        leftColumn1.css('pointer-events', 'none');
      } else {
        leftColumn1.css('pointer-events', 'auto');
        rightColumn1.css('pointer-events', 'auto');
        leftColumn1.css('width', newLeftWidth + '%');
        rightColumn1.css('width', newRightWidth + '%');
      }
    }
  });

  // Dragging functionality for the second border
  var dragging2 = false;
  var leftColumn2 = $('.left-column2');
  var rightColumn2 = $('.right-column2');
  var border2 = $('.draggable-border2');

  border2.mousedown(function(e) {
    e.preventDefault();
    dragging2 = true;
  });

  $(document).mouseup(function() {
    dragging2 = false;
  });

  $(document).mousemove(function(e) {
    if (dragging2) {
      var offset = e.pageX - leftColumn2.offset().left;
      var newLeftWidth = offset / leftColumn2.parent().width() * 100;
      var newRightWidth = 100 - newLeftWidth;

      if (newLeftWidth < 30) {
        rightColumn2.css('pointer-events', 'none');
      } else if (newRightWidth < 30) {
        leftColumn2.css('pointer-events', 'none');
      } else {
        leftColumn2.css('pointer-events', 'auto');
        rightColumn2.css('pointer-events', 'auto');
        leftColumn2.css('width', newLeftWidth + '%');
        rightColumn2.css('width', newRightWidth + '%');
      }
    }
  });
});
</script>

Important note to understand how everything is setup: in my soft studio, blocks are added this way (you won’t see anything different in the edit mode, only the preview and live modes can show you the effects of custom code)

  1. Header block with the title of the page (this is jsut the block to present the page, with the image on the right)
  2. Custom code block 1
  3. Chart block1
  4. Chart block 2
  5. Custom code block 2
  6. Calendar block
  7. Chart block 3

And this would only add the additional split block, right? So then my page would max out at 2 split code blocks?

You can add as many split code blocks as you wish, just replicate the pattern I created. You need to try. If you can’t do it, unfortunately I won’t be of any help. Just try out by checking the differences between the first post of this thread and the post where I created your type of use case.
This way you will be able to have 2, 3, 4 or more split code blocks.

1 Like