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);
...