My jQuery script is quite a large file however I have trimmed it down to the most relevant parts for this question as seen below;
$(document).ready(function() {
"use strict";
$(document).on('click', function(e) {
if (($(e.target).attr('data-action')) || $(e.target).parent().data('action')) {
if ($(e.target).attr('data-action')) {
action = $(e.target).data('action');
} else {
action = $(e.target).parent().data('action');
}
switch (action) {
case 'mail-pin':
// Code for 'mail-pin' click
break;
default:
return;
}
}
});
});
<!-- === INBOX LIST STARTS === -->
<div class="inbox-content clearfix">
<div class="Head">
<!-- Code for inbox header -->
</div>
<div class="Body clearfix">
<div class="Pinned">
<div class="Mail clearfix" data-mail-ID="1234">
<!-- Mail Item -->
</div>
<div class="Mail clearfix" data-mail-ID="1235">
<!-- Mail Item -->
</div>
</div>
<div class="Standard">
<div class="Mail clearfix" data-mail-ID="1233">
<!-- Mail Item -->
</div>
<div class="Mail clearfix" data-mail-ID="1236">
<!-- Mail Item -->
</div>
</div>
</div>
</div>
First of all, I know how to check where the item is to be moved either from the .Pinned
element or the .Standard
to the other element via such means seen below;
case 'mail-pin':
console.log('Hello');
if ($(e.target).closest('.Mail').parent().hasClass('Pinned')) {
console.log('It is pinned.');
} else {
console.log('It is not pinned.');
}
break;
What I don't understand how to achieve is how to append the content in the correct location and by this I refer to the order taken from the data-mail-ID="1233"
so that upon clicking to either pin or unpin, the content will be appended to the place, so if you click to pin mail ID X it will append after X - 1 and visa versa if the item is unpinned.
Each list only displays 20 items per page and upon clicking to go to the next or previous page, the page fetches the content which would have been modified upon clicking to pin or unpin therefore this script would only be relevant for those ID's which can be found on that page, thus meaning if you unpin ID 123 and 122 cannot be found, it is simply removed and for pinning, the append part would only occur if .Pinned
is visible otherwise that item just removes.
Search the first mail with a larger id and append the clicked element before it.
(The function below uses a closure to store the relevant DOM parts so I only need to query the DOM once. It's not really needed but that's the way I'm doing such things^^)
var togglePinState = (function () {
var pinned = document.querySelector(".Pinned"),
unpinned = document.querySelector(".Standard"),
pinnedMails = pinned.getElementsByClassName("Mail"),
unpinnedMails = unpinned.getElementsByClassName("Mail");
// .getElementsByClassName() because it returns a live HTMLCollection
// pinnedMails and unpinnedMails will always have the currently un/pinned "mails" without re-querying the DOM
return function (mailItem) {
var mailId = parseInt(mailItem.getAttribute("data-mail-ID"), 10),
mailItemIsPinned = (mailItem.parentNode.className === "Pinned"),
newParent = (mailItemIsPinned ? unpinned : pinned),
mailsToCheck = (mailItemIsPinned ? unpinnedMails : pinnedMails),
// variables for the loop below
i = 0,
l = mailsToCheck.length,
currentId;
for (; i < l; i++) {
currentId = parseInt(mailsToCheck[i].getAttribute("data-mail-ID"), 10);
if (currentId > mailId) {
// insert before first pinned mail with a bigger id
mailsToCheck[i].insertAdjacentElement("beforebegin", mailItem);
return;
}
}
// at this point we have not found a mail with a bigger id so we can safely append it at the end of the list
newParent.appendChild(mailItem);
}
}());
To use it in your script just call it in the mail-pin
branch:
case 'mail-pin':
togglePinState(e.target);
break;
And here is the function in action:
var togglePinState = (function() {
var pinned = document.querySelector(".Pinned"),
unpinned = document.querySelector(".Standard"),
pinnedMails = pinned.getElementsByClassName("Mail"),
unpinnedMails = unpinned.getElementsByClassName("Mail");
// .getElementsByClassName() because it returns a live HTMLCollection
// pinnedMails and unpinnedMails will always have the currently un/pinned "mails" without re-querying the DOM
return function(mailItem) {
var mailId = parseInt(mailItem.getAttribute("data-mail-ID"), 10),
mailItemIsPinned = (mailItem.parentNode.className === "Pinned"),
newParent = (mailItemIsPinned ? unpinned : pinned),
mailsToCheck = (mailItemIsPinned ? unpinnedMails : pinnedMails),
// variables for the loop below
i = 0,
l = mailsToCheck.length,
currentId;
for (; i < l; i++) {
currentId = parseInt(mailsToCheck[i].getAttribute("data-mail-ID"), 10);
if (currentId > mailId) {
// insert before first pinned mail with a bigger id
mailsToCheck[i].insertAdjacentElement("beforebegin", mailItem);
return;
}
}
// at this point we have not found a mail with a bigger id so we can safely append it at the end of the list
newParent.appendChild(mailItem);
}
}());
document.querySelector("div.inbox-content")
.addEventListener("click", function(e) {
if (e.target.nodeName === "DIV" && e.target.classList.contains("Mail")) {
togglePinState(e.target);
}
});
div { padding: 2px }
div.Mail {
border: dotted 1px black;
text-align: center;
}
.Pinned { border: solid 1px red }
.Standard { border: solid 1px blue }
<!-- === INBOX LIST STARTS === -->
<div class="inbox-content clearfix">
<div class="Head">
<!-- Code for inbox header -->
</div>
<div class="Body clearfix">
<div class="Pinned">
<div class="Mail clearfix" data-mail-ID="1234">1234</div>
<div class="Mail clearfix" data-mail-ID="1237">1237</div>
</div>
<div class="Standard">
<div class="Mail clearfix" data-mail-ID="1233">1233</div>
<div class="Mail clearfix" data-mail-ID="1235">1235</div>
<div class="Mail clearfix" data-mail-ID="1236">1236</div>
<div class="Mail clearfix" data-mail-ID="1238">1238</div>
</div>
</div>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With