Sortable list numbers are not showing in order while dragging (using jQuery)

329
December 10, 2016, at 1:22 PM

I have the following jQuery\Javascript\HTML code for a sortable list, and it works fine, except while dragging the wrong numbers display. For example, when dragging character2 to the character1 slot, the number '3' is displayed. Does anyone know why this is and how to fix it? I have also included a Stack Snippet now so you can see what happens...

function menuClicked(menuId) { 
  switch (menuId) { 
    case "formation": 
      document.getElementById("storybox").innerHTML = "<h1>Formation</h1><h2>Drag characters to change positions</h2><ol class='sortable' id='charlist'><li><h3 class='charname'>Dragon-Bear</h3></li><li><h3 class='charname'>Deer-Wolf</h3></li></ol>"; 
      $(function() { 
        $(".sortable").sortable(); 
        $(".sortable").disableSelection(); 
      }); 
      break; 
  } 
}
.charname:hover   { 
  cursor: pointer;  
}
<script src="http://www.orderofthemouse.co.uk/js/vendor/jquery-1.11.3.min.js"></script> 
<script src="http://www.orderofthemouse.co.uk/js/vendor/jquery-ui.min.js"></script> 
<ol> 
  <li id="ChangeFormation" onclick="menuClicked('formation')"> 
    <a href="#formation">Change Formation</a> 
    <div id="storybox"></div> 
  </li> 
</ol>

Answer 1

As Kaivosukeltaja pointed out, the sortable plugin adds a placeholder li element with the CSS rule visibility: hidden. If you set the display of the element to none, it obviously won't be taken into consideration, and the numbering will work as expected. However, this defeats the entire point of having a placeholder element (because now, nothing will occupy the space of the element that is currently being dragged).

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

function menuClicked(menuId) { 
  switch (menuId) { 
    case "formation": 
      document.getElementById("storybox").innerHTML = "<h1>Formation</h1><h2>Drag characters to change positions</h2><ol class='sortable' id='charlist'><li><h3 class='charname'>Dragon-Bear</h3></li><li><h3 class='charname'>Deer-Wolf</h3></li></ol>"; 
      $(function() { 
        $(".sortable").sortable(); 
        $(".sortable").disableSelection(); 
      }); 
      break; 
  } 
}
.charname:hover { 
  cursor: pointer; 
} 
.ui-sortable-placeholder { 
  display: none; 
}
<script src="http://www.orderofthemouse.co.uk/js/vendor/jquery-1.11.3.min.js"></script> 
<script src="http://www.orderofthemouse.co.uk/js/vendor/jquery-ui.min.js"></script> 
<ol> 
  <li id="ChangeFormation" onclick="menuClicked('formation')"> 
    <a href="#formation">Change Formation</a> 
    <div id="storybox"></div> 
  </li> 
</ol>

If that's a problem, the better solution would be to remove the default numbering, and use CSS3 counters to exclude the placeholder element.

Here is a simple example using CSS3 counters that removes the default numbers using list-style: none, and then uses the :not() pseudo class to exclude the .ui-sortable-placeholder element from the numbering incrementing.

ol { 
  list-style: none; 
} 
ol li:not(.ui-sortable-placeholder) { 
  counter-increment: number; 
} 
ol li:before { 
  content: counter(number)'. '; 
} 
.ui-sortable-placeholder { 
  visibility: hidden; 
}
<ol> 
  <li>one</li> 
  <li class="ui-sortable-placeholder">two</li> 
  <li>three</li> 
</ol>

In your case, you could use the following:

function menuClicked(menuId) { 
  switch (menuId) { 
    case "formation": 
      document.getElementById("storybox").innerHTML = "<h1>Formation</h1><h2>Drag characters to change positions</h2><ol class='sortable' id='charlist'><li><h3 class='charname'>Dragon-Bear</h3></li><li><h3 class='charname'>Deer-Wolf</h3></li></ol>"; 
      $(function() { 
        $(".sortable").sortable(); 
        $(".sortable").disableSelection(); 
      }); 
      break; 
  } 
}
.charname:hover { 
  cursor: pointer; 
} 
.ui-sortable { 
  list-style: none; 
} 
.ui-sortable > li:not(.ui-sortable-placeholder) { 
  counter-increment: number; 
} 
.ui-sortable > li:before { 
  content: counter(number)'. '; 
} 
.ui-sortable-placeholder { 
  visibility: hidden; 
} 
.ui-sortable h3 { 
  display: inline-block; 
  margin-bottom: 0; 
}
<script src="http://www.orderofthemouse.co.uk/js/vendor/jquery-1.11.3.min.js"></script> 
<script src="http://www.orderofthemouse.co.uk/js/vendor/jquery-ui.min.js"></script> 
<ol> 
  <li id="ChangeFormation" onclick="menuClicked('formation')"> 
    <a href="#formation">Change Formation</a> 
    <div id="storybox"></div> 
  </li> 
</ol>

.ui-sortable {
  list-style: none;
}
.ui-sortable > li:not(.ui-sortable-placeholder) {
  counter-increment: number;
}
.ui-sortable > li:before {
  content: counter(number)'. ';
}
.ui-sortable-placeholder {
  visibility: hidden;
}
Answer 2

jQuery's Sortable plugin works by creating an extra <li> element that acts as a placeholder for the dragged item's new position. That will be counted by the browser, causing the number to increment even though the element is set to visibility: hidden.

There doesn't seem to be a way to omit <ol> numbers using CSS, so the best way to fix this would probably be to hide the list's native numbers and calculate them yourself, updating the numbers on the sortable's update event.

READ ALSO
Ajax Works in Firefox but not in Chrome

Ajax Works in Firefox but not in Chrome

Everything works well in firefox, all the data return a value, but on chrome, they are all undefinedI tried to empty my function with only a simple string return ex

447
conflict between multiple js files in wordpress install?

conflict between multiple js files in wordpress install?

Im really clueless on thisIm working on a Wordpress site for a friend and he gave me a free theme to use

336
jQuery animate.css not working correctly on Firefox only

jQuery animate.css not working correctly on Firefox only

I'm pretty much a novice at jQuery and i'm trying to use some animations which work fine except on Firefox

447