onclick clone() a draggable at x&y=0 of the containment to avoid any offset

214 Views Asked by At

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

There are 2 best solutions below

2
On BEST ANSWER

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

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!