1

I'm trying to do something similar to this jsFiddle but instead of dropping manually the widget on the containment I would like to click the widget and the widget goes automatically on the x=0 and y=0 of the containment. And of course then be able to drag and drop (but for that this code works well).

The reason behind this is I want to avoid any grid offset. So once I get x=0 and y=0 I can trust my grid inside the containment by doing:

if (ui.draggable[0].id) {
                        $(this).append($(ui.helper).clone().draggable({
                        grid: [ 40, 40 ],   
                            containment: "#builder",                          
                        }));

                    } 

I have double checked on google it seems to be impossible to snap a grid that would begin by the x=0 and y=0 of the containment. There will always be an offset due to the web architecture of the page. but if you have a solution, I'm taking it !

2 Answers2

0

To make this work you can attach a click handler to the widgets that clones and appends them to #builder manually. To make them appear in the top left by default you simply need to set position: relative in the CSS of #builder, then specify the positioning of the clone before it's appended:

$widgets.click(function() {
  $('#builder').append($(this).clone().removeAttr('id').css({
    position: 'absolute',
    top: 0,
    left: 0
  }).draggable({
    containment: "#builder",
    scroll: false
  }));
});

Updated example

You should however note that there are a lot of issues you need to address in this code:

  • Massively outdated version of jQuery (1.6.3) - update it
  • Move inline styling to an eternal stylesheet
  • Use common classes to group elements instead of gigantic selectors, eg $('#widget1, widget2, .... #widgetN')
  • Invalid HTML; div elements cannot be children of a ul, only li can
  • Several unused containing elements which can be removed.
  • The 'trash' feature doesn't work for larger sized widgets
  • Using HTML comments in JS
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • Thanks a lot that's very kind to warn me about all the issues you've noticed. I 100% agree. The thing is that wasn't my fiddle and I've been lazy to duplicate it. On my code, the architecture is much more complicated and would have been irrelevant for this particular problem to show it... Concerning your code, it's awesome, exactly what I needed! thanks !! –  Feb 14 '18 at 15:37
  • if you've a paypal or equivalent, would be happy to buy you a drink! have a lovely day ! –  Feb 14 '18 at 15:48
0

A few updates:

$(function() {
  function makeDrag(o) {
    o.draggable({
      grid: [40, 40],
      containment: "#builder"
    });
  }

  $("#catalog .widget").click(function(e) {
    var w = $(this).clone().removeAttr("id");
    w.appendTo("#builder").position({
      my: "left top",
      at: "left top",
      of: $(this)
    });
    w.animate({
      top: 0,
      left: 0
    }, "fast");
    makeDrag(w);
  });

  $("#trashWidget").droppable({
    greedy: 'true',
    accept: function() {
      return true;
    },
    drop: function(event, ui) {
      tolerance: 'fit',
      $(ui.draggable).remove();
    }
  });
});
#products {
  width: 200px;
  float: left;
}

#catalog {
  padding: 20px 0px 0px 0px;
  border: 1px dotted rgb(204, 204, 204);
}

.widget {
  border: 1px dotted rgb(204, 204, 204);
  width: 50px;
  height: 50px;
  background-color: #eae9e4;
}

#builder {
  padding: 0px 0px 0px 0px;
  float: left;
  border: 1px dotted rgb(204, 204, 204);
  width: 500px;
  height: 400px;
  position: relative;
}

#builder .widget {
  position: absolute;
  background-color: #eae9ff;
  border: 1px dotted rgb(175, 175, 175);
}

#trashWidget {
  width: 46px;
  height: 46px;
  float: right;
  padding: 0px 0px 0px 0px;
  border: 1px dotted rgb(204, 204, 204);
}

a {
  color: 0076A3;
  text-decoration: none;
  outline: none;
  font: normal 11px/13px Verdana, Helvetica, sans-serif;
}

a:active {
  color: #0076A3;
  text-decoration: underline;
}

a:visited {
  color: #0076A3;
  text-decoration: none;
}

a:hover {
  color: #0076A3;
  text-decoration: underline;
}

span {
  font: normal 11px/13px Verdana, Helvetica, sans-serif;
}

div {
  font: normal 11px/13px Verdana, Helvetica, sans-serif;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div>
  <div style="width:750px; display: block;">
    <div id="products">
      <span style="color:#D8781A;">WIDGET SELECTOR</span>
      <div id="catalog" align="left">
        <div>
          <ul style="list-style:none;">
            <div id="widget1" class="widget" style="width:50px; height: 50px;"></div>WIDGET 1
            <div id="widget2" class="widget" style="width:100px; height:100px;"></div>WIDGET 2
            <div id="widget3" class="widget" style="width:75px; height:75px;"></div>WIDGET 3
          </ul>
        </div>
      </div>
    </div>
    <div style="padding:0px 0px 0px 0px; float:left;">
      <br />
    </div>
    <span style="color:#D8781A;">WIDGET BUILDER</span>
    <br />
    <div id="builder">
      <div>
        <div id="trashWidget">trash</div>
      </div>
    </div>
  </div>
</div>

Lots of cleaning done. Updated to more modern version of jQuery and jQuery UI. Animated the movement from start to (0, 0) of #builder. Moved a lot of styles to CSS from style attribute. added relative position to #builder to ensure proper absolute positioning of child elements.

Good luck!

Twisty
  • 30,304
  • 2
  • 26
  • 45