Skip to content

Commit

Permalink
Convert sortable from jQueryUI to vanilla js
Browse files Browse the repository at this point in the history
  • Loading branch information
sunnavy committed Jan 2, 2025
1 parent b466228 commit c49b798
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 63 deletions.
2 changes: 1 addition & 1 deletion share/html/Elements/ShowSelectSearch
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ $search_type => undef
$possibly_hidden => 0
</%ARGS>
% my $alt = loc('Remove');
<li data-type="<% $type %>" data-id="<% $id %>" data-name="<% $name %>" data-search-type="<% $search_type || '' %>" data-search-id="<% $search_id || '' %>" data-description="<% $label %>">
<li draggable="true" data-type="<% $type %>" data-id="<% $id %>" data-name="<% $name %>" data-search-type="<% $search_type || '' %>" data-search-id="<% $search_id || '' %>" data-description="<% $label %>">
<a href="#" class="remove lh-1">
<% GetSVGImage( Name => 'close-circle', Title => $alt ) |n %>
</a> <% $prefix ? $prefix . ': ' : '' %>
Expand Down
1 change: 1 addition & 0 deletions share/html/Widgets/SearchSelection
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
% for my $item (@{ $selected{$pane} }) {
<& /Elements/ShowSelectSearch, %$item &>
% }
<p class="rt-drop-placeholder m-1 p-2 border rounded"><% loc('Place here') %></p>
</ul>
</div>
</div>
Expand Down
20 changes: 18 additions & 2 deletions share/static/css/elevator/forms.css
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,19 @@ div.row>div.label>span.prev-icon-helper+.icon-helper {
margin-left: -0.8em;
}

.rt-drop-placeholder {
display: none;
--bs-border-style: dotted;
--bs-border-width: 2px;
}

.rt-drop-placeholder.active {
display: block;
}

[draggable=true].current {
opacity: 0.7;
}

[data-bs-theme=light] {

Expand Down Expand Up @@ -586,8 +599,7 @@ div.row>div.label>span.prev-icon-helper+.icon-helper {
border-color: #ccc;
}

.selectionbox-js .contents li,
.selectionbox-js .contents .placeholder {
.selectionbox-js .contents li {
border-color: #aaa;
background-color: #eee;
}
Expand All @@ -599,6 +611,10 @@ div.row>div.label>span.prev-icon-helper+.icon-helper {
.selectionbox-js .contents::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, .5);
}

.rt-drop-placeholder {
--bs-border-color: #ffc107;
}
}

[data-bs-theme=dark] {
Expand Down
158 changes: 98 additions & 60 deletions share/static/js/forms.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,105 @@
(function(){
let dragged;
const selectionBox = RT.selectionBox ||= {
dragstart: function(e) {
dragged = e.target;
e.effectAllowed = "copy";

e.target.classList.add('current');

bootstrap.Tooltip.getInstance(e.target.querySelector('span.content'))?.dispose();
},

dragend: function(e) {
e.target.classList.remove('current');
document.querySelector('.rt-drop-placeholder.active')?.classList.remove('active');
},

dragenter: function(e) {
e.preventDefault();
const area = e.target.closest('ul');
const placeholder = area.querySelector('.rt-drop-placeholder');
if ( e.target.closest('li') ) {
if ( e.target.closest('li') === dragged ) {
placeholder.classList.remove('active');
return;
}
area.insertBefore(placeholder, e.target.closest('li'));
}
else if ( e.target === area ) {
area.insertBefore(placeholder, null);
}
placeholder.classList.add('active');
},

dragleave: function(e) {},

dragover: function(e) {
e.preventDefault();
},

drop: function(e) {

let source;
if (dragged.closest('.destination')) {
source = dragged;
}
else {
source = dragged.cloneNode(true);
source.querySelector('a.remove').addEventListener('click', selectionBox.deleteItem);
selectionBox.registerDrag(source);
}

let sibling = e.target.closest('li') || e.target.closest('.rt-drop-placeholder')?.nextSibling;
let area = e.target.closest('ul');

if (sibling) {
area.insertBefore(source, sibling);
}
else {
area.appendChild(source);
}
},
registerDrag: function(elt) {
for (let event of ['dragstart', 'dragend']) {
elt.addEventListener(event, selectionBox[event]);
}
},
registerDrop: function(elt) {
for (let event of ['dragenter', 'dragover', 'dragleave', 'drop']) {
elt.addEventListener(event, selectionBox[event]);
}
},

deleteItem: function(e) {
e.preventDefault();
let item = e.target.closest('li');
item.querySelectorAll('[data-bs-toggle=tooltip]').forEach((elt) => {
bootstrap.Tooltip.getInstance(elt)?.hide();
});
item.remove();
return false;
}
};

htmx.onLoad(function(elt) {

elt.querySelectorAll('.selectionbox-js').forEach(editor => {
editor.querySelectorAll('.contents li').forEach((elt) => {
selectionBox.registerDrag(elt);
elt.querySelector('a.remove').addEventListener('click', selectionBox.deleteItem);
});
selectionBox.registerDrop(editor.querySelector('.destination ul'));
});
});

htmx.onLoad(function() {
jQuery('.selectionbox-js').each(function () {
var container = jQuery(this);
var source = container.find('.source');
var form = container.closest('form');
var submit = form.find('input[name=UpdateSearches]');

var copyHelper;
var draggedIntoDestination;

container.find('.destination ul').sortable({
connectWith: '.destination ul',
placeholder: 'placeholder',
forcePlaceholderSize: true,
cancel: '.remove',

// drag a clone of the source item
receive: function (e, ui) {
draggedIntoDestination = true;
copyHelper = null;
},
over: function () {
removeIntent = false;
},
out: function () {
removeIntent = true;
},
beforeStop: function (event, ui) {
if(removeIntent == true){
ui.item.remove();
}
},
}).on('click', '.remove', function (e) {
e.preventDefault();
jQuery(e.target).closest('li').remove();
return false;
});

source.find('ul').sortable({
connectWith: '.destination ul',
containment: container,
placeholder: 'placeholder',
forcePlaceholderSize: true,

// drag a clone of the source item
helper: function (e, li) {
copyHelper = li.clone().insertAfter(li);
return li.clone();
},

start: function (e, ui) {
draggedIntoDestination = false;
},

stop: function (e, ui) {
if (copyHelper) {
copyHelper.remove();
}

if (!draggedIntoDestination) {
jQuery(this).sortable('cancel');
}
}
});

var searchField = source.find('input[name=search]');
var filterField = source.find('select[name=filter]');

Expand Down Expand Up @@ -134,8 +171,7 @@ htmx.onLoad(function() {
var name = pane.data('pane');

pane.find('li').each(function () {
var item = jQuery(this).data();
delete item.sortableItem;
const item = jQuery(this).data();
form.append('<input type="hidden" name="' + name + '" value="' + item.type + '-' + (item.id || item.name) + '" />');
});
});
Expand All @@ -144,3 +180,5 @@ htmx.onLoad(function() {
});
});
});

})();

0 comments on commit c49b798

Please sign in to comment.