views:

562

answers:

2

I've got a simple setup using jQuery UI's default sortable/draggable functionality.

I now need to add a 'palette' which will will be a list of all items in all lists (and some that may not be in any lists). Like this:

<ul id="palette" class="ui-sortable">
 <li class="used">A</li>
 <li>B</li>
 <li class="used">C</li>
 <li class="used">D</li>
 <li>E</li>
 <li>F</li>
</ul>

<ol id="box1" class="ui-sortable box">
 <li>A</li>
 <li>D</li>
</ol>

<ol id="box2" class="ui-sortable box">
</ol>

<ol id="box3" class="ui-sortable box">
 <li>C</li>
</ol>

At the moment, the palette doesn't do anything different - dragging items in and out simply moves them.

The functionality I need is that when I drag out of the palette, it copies rather than moving, and when I drag into the palette, it removes from the source list but doesn't add to the palette. (The boxes can store multiple copies of palette items.)

I've used the sortable's receive event to create something that does all this - and I've added that as an answer below - but I want some things that my existing solution doesn't provide:

  • preserve (visually, at least) the item in the palette from start of drag (rather than restoring it after dropping).
  • persist the original palette order, preventing sortability (but preserving ability to connect with it from boxes).

Can anyone suggest how best to implement these?

A: 

Here's my current solution:

<!DOCTYPE html>

 <title>jQuery UI Sortable / Palette test</title>

 <style>
  *{margin:0;padding:0;}

  ul,ol
  {list-style: none;}

  #palette
  {
   display: block;
   width: 114px;
   margin: 5px;

   float:left;clear:none;

   background: yellow;
  }

  .box
  {
   display:block;
   width: 114px;
   min-height: 5em;
   margin: 5px;

   float: left; clear:none;

   background:silver;
  }

  .box li,#palette li
  {
   display: block;
   width: 32px;
   height: 32px;
   margin: 2px;

   float: left; clear:none;

   text-align: center;
   border: solid 1px black;
  }

  #palette li{font-weight:bold}
  #palette li.used{font-weight:normal}

  #palette .ui-sortable-placeholder
  {
   display:none;
  }

 </style>

 <script src="jquery-1.3.2.min.js"></script>
 <script src="jquery-ui-1.7.2.custom.min.js"></script>

 <script>
  $j = jQuery.noConflict();

  $j(document).ready(init);

  function init()
  {
   var SortParams =
   { connectWith:'.box,#palette'
   , dropOnEmpty:true
   , receive: doPaletteMagic
   }

   $j('.box,#palette').sortable( SortParams )
  }

  function doPaletteMagic( event , ui )
  {
   if ( ui.sender.is('#palette') )
   {
    ui.item
     .clone()
     .addClass('used')
     .appendTo('#palette')

    // TODO: fix #palette ordering
   }
   else
   if ( ui.item.parent().is('#palette') )
   {
    var ItemContent = ui.item.text();

    ui.item.remove()

    if ( ! isUsed( ItemContent ) )
    {
     $j('#palette li:contains('+ItemContent+')')
      .removeClass('used')
      ;
    }

   }
  }

  function isUsed(Content)
  {
   return ($j('.box li:contains('+Content+')').length > 0)
  }

 </script>

<body>

 <ul id="palette" class="ui-sortable">
  <li class="used">A</li>
  <li>B</li>
  <li class="used">C</li>
  <li class="used">D</li>
  <li>E</li>
  <li>F</li>
 </ul>

 <ol id="box1" class="ui-sortable box">
  <li>A</li>
  <li>D</li>
 </ol>

 <ol id="box2" class="ui-sortable box">
 </ol>

 <ol id="box3" class="ui-sortable box">
  <li>C</li>
 </ol>

 <br class="break"/>

</html>
Peter Boughton
+1  A: 

preserve (visually, at least) the item in the palette from start of drag (rather than restoring it after dropping).

I presume you've already tried setting the palette's sortable helper to 'clone'?

var SortParams = {
  ...,
  helper: "clone",
}
RobM