javascriptjqueryhtmlpackery

Packery - Adding element by jquery click


I am intending to create a set of textboxes that can be rearranged. The user is to be allowed to create text boxes and then fill them with text. As he keeps rearranging them the text gets automatically updated in the textarea. I am using packery library

// external js: packery.pkgd.js, draggabilly.pkgd.js

$("#add_item").click(function(){
    $("#grid").append("<input type='text' class='grid-item'></input>");
});

var $grid = $('.grid').packery({
  itemSelector: '.grid-item',
  columnWidth: 100
});

// make all grid-items draggable
$grid.find('.grid-item').each( function( i, gridItem ) {
  var draggie = new Draggabilly( gridItem );
  // bind drag events to Packery
  $grid.packery( 'bindDraggabillyEvents', draggie );
});


// show item order after layout
function orderItems() {
  var itemElems = $grid.packery('getItemElements');
  var res_text = '';
  $( itemElems ).each( function( i, itemElem ) {
    res_text = ' '+$(itemElem).text();
  });
  $('#result_text').text(res_text);
}

$grid.on( 'layoutComplete', orderItems );
$grid.on( 'dragItemPositioned', orderItems );
* { box-sizing: border-box; } 

body { font-family: sans-serif; }

/* ---- grid ---- */

.grid {
  background: #DDD;
  max-width: 1200px;
}

/* clear fix */
.grid:after {
  content: '';
  display: block;
  clear: both;
}

/* ---- .grid-item ---- */

.grid-item {
  float: left;
  width: 100px;
  height: 100px;
  background: #C09;
  border: 2px solid hsla(0, 0%, 0%, 0.5);
  color: white;
  font-size: 20px;
  padding: 10px;
}

.grid-item--width2 { width: 200px; }
.grid-item--height2 { height: 200px; }

.grid-item:hover {
  border-color: hsla(0, 0%, 100%, 0.5);
  cursor: move;
}

.grid-item.is-dragging,
.grid-item.is-positioning-post-drag {
  background: #C90;
  z-index: 2;
}

.packery-drop-placeholder {
  outline: 3px dashed hsla(0, 0%, 0%, 0.5);
  outline-offset: -6px;
  -webkit-transition: -webkit-transform 0.2s;
          transition: transform 0.2s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://unpkg.com/packery@2.1.1/dist/packery.pkgd.js"></script>
<script src="https://unpkg.com/draggabilly@2.1.1/dist/draggabilly.pkgd.js"></script>
<h1>Packery - get item elements in order after drag</h1>

<button id="add_item" class="ui-button ui-widget ui-corner-all">A button element</button>

<div class="grid">
  <input type="text" class="grid-item"></input>
  <input type="text" class="grid-item"></input>
  <input type="text" class="grid-item"></input>
</div>
<textarea id="result_text" readonly></textarea>

However, I can not add boxes at will using the Button


Solution

  • You should use class grid instead :

    $(".grid").append("<input type='text' class='grid-item'/>");
    

    Instead of :

    $("#grid").append("<input type='text' class='grid-item'></input>");
    

    Then you should destroy and reinit the packery after adding new grid-item.

    NOTE : input tag is a sel-closing tag so it should be :

    <input type='text' class='grid-item'/>
    

    Runnable snippet:

    // external js: packery.pkgd.js, draggabilly.pkgd.js
    
    $("#add_item").click(function() {
      $(".grid").append("<input type='text' class='grid-item'/>");
      grid.packery('destroy');
      grid = initParckery();
    });
    
    function initParckery() {
      var grid = $('.grid').packery({
        itemSelector: '.grid-item',
        columnWidth: 100
      });
    
      // make all grid-items draggable
      grid.find('.grid-item').each(function(i, gridItem) {
        var draggie = new Draggabilly(gridItem);
        // bind drag events to Packery
        grid.packery('bindDraggabillyEvents', draggie);
      });
    
      return grid;
    }
    
    
    // show item order after layout
    function orderItems() {
      setTimeout(function() {
        var res_text = '';
        var items = grid.packery('getItemElements');
        items.forEach(function(itemElem) {
          res_text += ' ' + $(itemElem).val();
        });
        $('#result_text').val(res_text);
      }, 100)
    }
    
    var grid = initParckery();
    grid.on('layoutComplete', orderItems);
    grid.on('dragItemPositioned', orderItems);
    * {
      box-sizing: border-box;
    }
    
    body {
      font-family: sans-serif;
    }
    
    
    /* ---- grid ---- */
    
    .grid {
      background: #DDD;
      max-width: 1200px;
    }
    
    
    /* clear fix */
    
    .grid:after {
      content: '';
      display: block;
      clear: both;
    }
    
    
    /* ---- .grid-item ---- */
    
    .grid-item {
      float: left;
      width: 100px;
      height: 100px;
      background: #C09;
      border: 2px solid hsla(0, 0%, 0%, 0.5);
      color: white;
      font-size: 20px;
      padding: 10px;
    }
    
    .grid-item--width2 {
      width: 200px;
    }
    
    .grid-item--height2 {
      height: 200px;
    }
    
    .grid-item:hover {
      border-color: hsla(0, 0%, 100%, 0.5);
      cursor: move;
    }
    
    .grid-item.is-dragging,
    .grid-item.is-positioning-post-drag {
      background: #C90;
      z-index: 2;
    }
    
    .packery-drop-placeholder {
      outline: 3px dashed hsla(0, 0%, 0%, 0.5);
      outline-offset: -6px;
      -webkit-transition: -webkit-transform 0.2s;
      transition: transform 0.2s;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script src="https://unpkg.com/packery@2.1.1/dist/packery.pkgd.js"></script>
    <script src="https://unpkg.com/draggabilly@2.1.1/dist/draggabilly.pkgd.js"></script>
    <h1>Packery - get item elements in order after drag</h1>
    
    <button id="add_item" class="ui-button ui-widget ui-corner-all">A button element</button>
    
    <div class="grid">
      <input type="text" class="grid-item a"></input>
      <input type="text" class="grid-item b"></input>
      <input type="text" class="grid-item c"></input>
    </div>
    <textarea id="result_text" readonly></textarea>