old and new position - range

by rwone

HTML

<div class="objective">
  <p>move a range of items programmatically</p>
</div>
<div class="container">
  <div class="list">
    <ol start="0">
      <li data-id="Pies">Pies</li>
      <li data-id="Cakes">Cakes</li>
      <li data-id="Trees">Trees</li>
      <li data-id="Oranges">Oranges</li>
      <li data-id="Apples">Apples</li>
      <li data-id="Pineapples">Pineapples</li>
      <li data-id="Hamburgers">Hamburgers</li>
      <li data-id="Pizzas">Pizzas</li>
      <li data-id="Limes">Limes</li>
      <li data-id="Sunshine">Sunshine</li>
    </ol>
  </div>
  <div class="control">
    <div id="right_top">
      <div id="inputs">
        <div>
          <input id="range_start" type="number" placeholder="enter range start"><input id="range_end" type="number" placeholder="enter range end (inclusive)">
        </div>
        <div>
          <select id="before_or_after">
            <option value="before">before</option>
            <option value="after">after</option>
          </select>
        </div>
        <div>
          <input id="new_position" type="number" placeholder="enter new position">
        </div>
        <div>
          <button id="calculate">
            submit
          </button>
        </div>
      </div>
      <div id="errors">
      </div>
    </div>
    <div id="output">
      <p>
        <b>logic (values are populated on button click):</b>
      </p>
      <p>
        move items between <span id="range_start_span" class="var"></span> (<span class="range_start_text"></span>) and <span id="range_end_span" class="var"></span> (<span class="range_end_text"></span>), <span id="before_or_after_span" class="var"></span> item at position <span id="new_position_span" class="var"></span> (<span class="new_position_text"></span>)
      </p>
      <p>
        '<span class="range_start_text"></span>' old index: <span id="old_index" class="var"></span>
      </p>
      <p>
        '<span class="range_start_text"></span>' new index: <span id="new_index"...

CSS

.container {
  display: flex;
}

#right_top {
  display: flex;
}

#inputs {
  background: lavender;
  width: 50%;
}

#errors {
  background: lightyellow;
  width: 50%;
  padding: 10px;
  font-family: arial;
  color: red;
}

.list {
  width: 180px;
  background: salmon;
}

.control {
  background: #666;
  width: calc(100% - 180px);
  padding: 5px;
}

input,
select,
button {
  padding: 10px;
  width: 100%;
  margin-bottom: 5px;
}

button {
  cursor: pointer;
  background: black;
  color: white;
}

* {
  box-sizing: border-box;
}

#output {
  padding: 10px;
  background: #eee;
}

li {
  padding: 5px;

}

.var {
  width: 50px;
  padding: 5px;
  background: #dddddd;
  text-align: center;
  display: inline-block;
  min-height: 20px;
}

p,
li,
input {
  font-family: arial;
}

.objective {
  padding: 10px;
  background: beige;
  margin-bottom: 10px;
}

JavaScript

$(document).on("click", "#calculate", function() {

  // reset error mesage
  $("#errors").text("");

  // get form values
  var range_start = $("#range_start").val();
  var range_end = $("#range_end").val();
  var before_or_after = $("#before_or_after").val();
  var new_position = $("#new_position").val();


  // validations - part one

  // make sure all input fields have values
  if (range_start === "" || range_end === "" || new_position === "") {
    $("#errors").text("please add all input values!");
    return;
  }

  // convert input values to numbers
  range_start = Number(range_start);
  range_end = Number(range_end);
  new_position = Number(new_position);

  // validations - part two

  // don't reposition at same place  
  // eg:  
  // 1 before 2
  // 1 before 1
  // 1 after 1  
  if ((new_position === (range_start + 1) && before_or_after === "before") || (new_position === range_start && before_or_after === "before") || (new_position === range_start && before_or_after === "after")) {
    $("#errors").text("cannot move to the same place!");
    return;
  }



  // get corresponding list item text for logic area
  var range_start_text = $("li").eq(range_start).text();
  var range_end_text = $("li").eq(range_end).text();
  var new_position_text = $("li").eq(new_position).text();

  // re-arrange the items correctly   
  // this seems to work because each element
  // is referenced at the same point in time 
  // ie even if order of lists shifts it is
  // accounted for, or something :)  
  // move the range of divs before or after the specified new position  
  if (before_or_after === "before") {
    $("li").eq(new_position).before($("li").slice(range_start, range_end + 1));
  } else if (before_or_after === "after") {
    $("li").eq(new_position).after($("li").slice(range_start, range_end + 1));
  }


  // populate logic area  
  $("#range_start_span").text(range_start);
  $(".range_start_text").text(range_start_text);
 ...