Added new and improved drag-and-drop. Works between stores and on touch-devices.
parent
fe7ae67f1e
commit
1479893234
|
@ -155,7 +155,7 @@ body.dollars span.price::after {
|
|||
|
||||
.drag-over {
|
||||
border-bottom: dashed 3px red;
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-width: 1px !important;
|
||||
}
|
||||
|
||||
#totalPriceWrapper {
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
(function(factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['jquery', 'hammerjs'], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
factory(require('jquery'), require('hammerjs'));
|
||||
} else {
|
||||
factory(jQuery, Hammer);
|
||||
}
|
||||
}(function($, Hammer) {
|
||||
function hammerify(el, options) {
|
||||
var $el = $(el);
|
||||
if(!$el.data("hammer")) {
|
||||
$el.data("hammer", new Hammer($el[0], options));
|
||||
}
|
||||
}
|
||||
|
||||
$.fn.hammer = function(options) {
|
||||
return this.each(function() {
|
||||
hammerify(this, options);
|
||||
});
|
||||
};
|
||||
|
||||
// extend the emit method to also trigger jQuery events
|
||||
Hammer.Manager.prototype.emit = (function(originalEmit) {
|
||||
return function(type, data) {
|
||||
originalEmit.call(this, type, data);
|
||||
$(this.element).trigger({
|
||||
type: type,
|
||||
gesture: data
|
||||
});
|
||||
};
|
||||
})(Hammer.Manager.prototype.emit);
|
||||
}));
|
File diff suppressed because it is too large
Load Diff
|
@ -311,7 +311,6 @@ function initStore($storeName){
|
|||
$matchingStores = $storeCheckRes->fetch_row()[0];
|
||||
|
||||
if($matchingStores == 1){
|
||||
// $sql = "UPDATE plan_store SET null WHERE `user_id` = '$user_id' AND `name` = '$storeName';";
|
||||
$sql = "SELECT plan_store_id FROM plan_store WHERE `space_id` = '$spaceID' AND `name` = '$storeName';";
|
||||
|
||||
if( ($res = $db->query($sql)) !== false){
|
||||
|
@ -343,6 +342,7 @@ function renameStore($storeID, $newName){
|
|||
if($db->query($renameStoreSql) !== false){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function deleteStore($storeID, $storeName, $itemsLength){
|
||||
|
@ -385,9 +385,9 @@ function addItem($storeID, $name, $price){
|
|||
}
|
||||
|
||||
function checkItem($storeID, $itemID, $checked){
|
||||
global $db, $spaceID;
|
||||
global $db;
|
||||
|
||||
$verifyUserOwnershipSQL = "SELECT `plan_store_id` FROM plan_store WHERE `space_id` = '$spaceID' AND `plan_store_id` = '$storeID'";
|
||||
$verifyUserOwnershipSQL = getVerifyStoreOwnerSQL($storeID);
|
||||
$findRowSql = "SELECT `plan_item_id` FROM plan_store_item WHERE `plan_store_id` = ($verifyUserOwnershipSQL) AND `plan_item_id` = '$itemID'";
|
||||
$checkItemSql = "UPDATE plan_store_item SET `checked` = ".($checked?1:0)." WHERE `plan_item_id` = ($findRowSql);";
|
||||
if($db->query($checkItemSql)){
|
||||
|
@ -397,9 +397,9 @@ function checkItem($storeID, $itemID, $checked){
|
|||
}
|
||||
|
||||
function remItem($storeID, $itemID, $price){
|
||||
global $db, $spaceID;
|
||||
global $db;
|
||||
|
||||
$verifyUserOwnershipSQL = "SELECT `plan_store_id` FROM plan_store WHERE `space_id` = '$spaceID' AND `plan_store_id` = '$storeID'";
|
||||
$verifyUserOwnershipSQL = getVerifyStoreOwnerSQL($storeID);
|
||||
$findRowSql = "SELECT `plan_item_id` FROM plan_store_item WHERE `plan_store_id` = ($verifyUserOwnershipSQL) AND `plan_item_id` = '$itemID'";
|
||||
$removeItemSql = "DELETE FROM plan_store_item WHERE `plan_item_id` = ($findRowSql) AND `price` = '$price';";
|
||||
if($db->query($removeItemSql) && mysqli_affected_rows($db) > 0){
|
||||
|
@ -409,9 +409,23 @@ function remItem($storeID, $itemID, $price){
|
|||
}
|
||||
|
||||
function moveItem($storeID, $itemID, $afterID){
|
||||
global $db, $spaceID;
|
||||
global $db;
|
||||
|
||||
$verifyUserOwnershipSQL = "SELECT `plan_store_id` FROM plan_store WHERE `space_id` = '$spaceID' AND `plan_store_id` = '$storeID'";
|
||||
$verifyUserOwnershipSQL = getVerifyStoreOwnerSQL($storeID);
|
||||
$sameStoreCheckSQL = "SELECT (SELECT plan_store_id FROM plan_store_item WHERE `plan_item_id` = $itemID AND `plan_store_id` = ($verifyUserOwnershipSQL)) moved, (SELECT plan_store_id FROM plan_store_item WHERE plan_item_id = $afterID) after";
|
||||
|
||||
$differentStoreAddSQL = "";
|
||||
if($sameStoreCheck = $db->query($sameStoreCheckSQL)){
|
||||
$stores = $sameStoreCheck->fetch_array();
|
||||
|
||||
if($stores[0] != $stores[1]){
|
||||
// DIFFERENT STORES
|
||||
$storeID = $stores[1];
|
||||
$differentStoreAddSQL = ", plan_store_id = $storeID";
|
||||
}
|
||||
}
|
||||
|
||||
$verifyUserOwnershipSQL = getVerifyStoreOwnerSQL($storeID);
|
||||
$getStoreItemsSQL = "SELECT plan_item_id FROM plan_store_item WHERE `plan_store_id` = ($verifyUserOwnershipSQL) ORDER BY if(pos is \N,1,0), pos;";
|
||||
|
||||
if($getStoreItems = $db->query($getStoreItemsSQL)){
|
||||
|
@ -420,19 +434,19 @@ function moveItem($storeID, $itemID, $afterID){
|
|||
$newQuery = "";
|
||||
|
||||
if($afterID == 0){
|
||||
$newQuery .= "UPDATE plan_store_item SET pos = $position WHERE plan_item_id = $itemID;";
|
||||
$newQuery .= "UPDATE plan_store_item SET pos = $position $differentStoreAddSQL WHERE plan_item_id = $itemID;";
|
||||
$position++;
|
||||
}
|
||||
|
||||
while($row = $getStoreItems->fetch_assoc()){
|
||||
|
||||
if($row['plan_item_id'] != $itemID){
|
||||
$newQuery .= "UPDATE plan_store_item SET pos = $position WHERE plan_item_id = $row[plan_item_id];";
|
||||
$newQuery .= "UPDATE plan_store_item SET pos = $position $differentStoreAddSQL WHERE plan_item_id = $row[plan_item_id];";
|
||||
$position++;
|
||||
}
|
||||
|
||||
if($row['plan_item_id'] == $afterID){
|
||||
$newQuery .= "UPDATE plan_store_item SET pos = $position WHERE plan_item_id = $itemID;";
|
||||
$newQuery .= "UPDATE plan_store_item SET pos = $position $differentStoreAddSQL WHERE plan_item_id = $itemID;";
|
||||
$position++;
|
||||
}
|
||||
}
|
||||
|
@ -445,9 +459,9 @@ function moveItem($storeID, $itemID, $afterID){
|
|||
}
|
||||
|
||||
function setItemAmount($storeID, $itemID, $newAmount = 1){
|
||||
global $db, $spaceID;
|
||||
global $db;
|
||||
|
||||
$verifyUserOwnershipSQL = "SELECT `plan_store_id` FROM plan_store WHERE `space_id` = '$spaceID' AND `plan_store_id` = '$storeID'";
|
||||
$verifyUserOwnershipSQL = getVerifyStoreOwnerSQL($storeID);
|
||||
$updateAmountSQL = "UPDATE plan_store_item SET amount = $newAmount WHERE plan_item_id = $itemID AND plan_store_id = ($verifyUserOwnershipSQL);";
|
||||
|
||||
if($db->query($updateAmountSQL)){
|
||||
|
@ -458,9 +472,9 @@ function setItemAmount($storeID, $itemID, $newAmount = 1){
|
|||
}
|
||||
|
||||
function setState($storeID, $newState){
|
||||
global $db, $spaceID;
|
||||
global $db;
|
||||
|
||||
$verifyUserOwnershipSQL = "SELECT `plan_store_id` FROM plan_store WHERE `space_id` = '$spaceID' AND `plan_store_id` = '$storeID'";
|
||||
$verifyUserOwnershipSQL = getVerifyStoreOwnerSQL($storeID);
|
||||
$setStateSQL = "UPDATE plan_store SET state = '$newState' WHERE plan_store_id = ($verifyUserOwnershipSQL);";
|
||||
|
||||
if($db->query($setStateSQL)){
|
||||
|
@ -468,4 +482,10 @@ function setState($storeID, $newState){
|
|||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getVerifyStoreOwnerSQL($storeID): string {
|
||||
global $spaceID;
|
||||
|
||||
return "SELECT `plan_store_id` FROM plan_store WHERE `space_id` = '$spaceID' AND `plan_store_id` = '$storeID'";
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
|
||||
class Draggable {
|
||||
constructor(draggableClass, holderClass, hoverClassName, parentIdentifier, doneMovingFunc) {
|
||||
this.parentIdentifier = parentIdentifier+" " || '';
|
||||
this.moveableClass = draggableClass || "moveable";
|
||||
this.holderClass = holderClass || "holder";
|
||||
this.hoverClass = hoverClassName || "elementHover";
|
||||
this.activeDragging = false;
|
||||
this.draggingElem = null;
|
||||
|
||||
this.doneMoving = doneMovingFunc || function(draggedElement, afterPosElement){ console.log("No custom done-moving-function.", draggedElement, afterPosElement); };
|
||||
|
||||
this.update();
|
||||
}
|
||||
|
||||
update(){
|
||||
let hammerOptions = {};
|
||||
let elemHolderHtml = "<div class='elemHolder' style='position: absolute;'></div>";
|
||||
|
||||
$(this.parentIdentifier+"."+this.moveableClass+":not(:eq(0))").off().hammer(hammerOptions).bind('panstart panend panmove', ev => {
|
||||
if(ev.type === "panmove") {
|
||||
this.moveDraggingElem(ev);
|
||||
}
|
||||
else if(ev.type === "panstart") {
|
||||
// console.log("start", ev);
|
||||
this.activeDragging = true;
|
||||
this.draggingElem = $(ev.currentTarget);
|
||||
|
||||
if($(".elemHolder").length < 1){
|
||||
$("body").append(elemHolderHtml);
|
||||
}
|
||||
this.draggingElem.clone().appendTo(".elemHolder");
|
||||
this.draggingElem.css('opacity', '30%');
|
||||
|
||||
$(".elemHolder").css('height', '').css('height', ($(".elemHolder").height()+10)+"px");
|
||||
}
|
||||
else if(ev.type === "panend"){
|
||||
// console.log("end", ev);
|
||||
|
||||
this.activeDragging = false;
|
||||
this.draggingElem.css('opacity', '');
|
||||
$(document).off('mousemove');
|
||||
$(".elemHolder").html('');
|
||||
|
||||
let moveAfterElem = $("."+this.hoverClass);
|
||||
if(moveAfterElem.length === 1){
|
||||
if(!this.draggingElem.hasClass(this.hoverClass)){
|
||||
this.doneMoving(this.draggingElem, moveAfterElem);
|
||||
|
||||
this.draggingElem.detach().insertAfter("."+this.hoverClass);
|
||||
}
|
||||
}
|
||||
|
||||
this.draggingElem = null;
|
||||
$('.'+this.hoverClass).removeClass(this.hoverClass);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
moveDraggingElem(event){
|
||||
// console.log(event);
|
||||
let elem = $('.elemHolder');
|
||||
|
||||
let x = event.gesture.center.x;
|
||||
let y = event.gesture.center.y;
|
||||
|
||||
elem.css({ left: ((window.scrollX + x) - elem.width() / 4), top: ((window.scrollY + y)+4) });
|
||||
|
||||
|
||||
$('.'+this.hoverClass).removeClass(this.hoverClass);
|
||||
|
||||
// let elemAtPos = $(document.elementFromPoint(x, y));
|
||||
let elemAtPos = this.findClosestPos(x, y);
|
||||
if(elemAtPos !== null){
|
||||
elemAtPos.addClass(this.hoverClass);
|
||||
}
|
||||
}
|
||||
|
||||
findClosestPos(posX, posY){
|
||||
let elemAtPos = $(document.elementFromPoint(posX, posY));
|
||||
// let posClass = "posBelow";
|
||||
|
||||
let closest = elemAtPos.closest("."+this.moveableClass);
|
||||
if(closest.length === 1){
|
||||
return closest.first();
|
||||
}
|
||||
|
||||
if(elemAtPos.hasClass(this.holderClass)){
|
||||
if(posY < (elemAtPos.offset().top + elemAtPos.height()/2)){
|
||||
return elemAtPos.find("."+this.moveableClass).first();
|
||||
}
|
||||
return elemAtPos.find("."+this.moveableClass).last();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@
|
|||
</div>
|
||||
|
||||
<script src='plan.js'></script>
|
||||
<script src='draggingClass.js'></script>
|
||||
</div>
|
||||
<?php include $rPath.'webdata/footer.html'; ?>
|
||||
</div>
|
||||
|
|
|
@ -10,7 +10,7 @@ class Store {
|
|||
this.storeID = storeID || null;
|
||||
|
||||
let html = "";
|
||||
html += "<div class='card store' style='width: 25rem; max-width: 90vw;'>";
|
||||
html += "<div class='card store' style='width: 25rem; max-width: 90vw;' id='store"+storeNum+"'>";
|
||||
html += " <div class='iconWrapper' style='position: absolute; top: 1px; left: 1px;'>";
|
||||
html += " <nav aria-label='State changer'><ul class='pagination'>";
|
||||
html += " <li class='page-item planningState "+(this.state === 'planning'?"active":"")+"'><span class='page-link'><img src='../icon/list-check.svg' class='ariaButton' alt='Planning state' title='Planning state' data-toggle='tooltip' tabindex=0 role='button' /></span></li>";
|
||||
|
@ -25,8 +25,9 @@ class Store {
|
|||
html += " </div>";
|
||||
html += " <div class='card-header'>"+this.title+"</div>";
|
||||
html += " <div class='card-body'>";
|
||||
html += " <div class='draggable' style='width: 100%; height: 10px; border-width: 1px;'></div> <ul class='list-group list-group-flush storeItems'>";
|
||||
html += " <ul class='list-group list-group-flush storeItems dragHolder'>";
|
||||
html += " <li class='list-group-item emptyList'>No items added</li>";
|
||||
html += " <li class='list-group-item draggable' style='height: 10px; width: 100%;'></li>";
|
||||
html += " </ul>";
|
||||
|
||||
html += " <span class='addItemFormWrapper'>";
|
||||
|
@ -93,6 +94,22 @@ class Store {
|
|||
$(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
});
|
||||
|
||||
// INIT DRAGGING
|
||||
this.draggingClass = new Draggable("draggable", 'dragHolder', 'drag-over', "#store"+storeNum,(moved, after)=> {
|
||||
// console.log(moved, after);
|
||||
|
||||
let movedID = moved.attr('data-itemid');
|
||||
let afterID = after.attr('data-itemid');
|
||||
if(typeof movedID !== "undefined" && typeof afterID !== "undefined"){
|
||||
this.setItemPosition(movedID, afterID);
|
||||
|
||||
if(moved.parent().parent().parent().attr('id') !== after.parent().parent().parent().attr('id')){
|
||||
console.info("Moved item to different store, so refreshing all");
|
||||
$("#refreshAll").trigger('click');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setState(state, animTime){
|
||||
|
@ -215,7 +232,7 @@ class Store {
|
|||
this.itemsObj[itemID] = { text: text, price: price, itemID: itemID, amount: amount, checked: checked };
|
||||
|
||||
let html = "\n";
|
||||
html += "<li class='list-group-item draggable"+(checked?' checkedItem':'')+"' id='item_"+itemID+"' data-itemid='"+itemID+"' draggable='true'>";
|
||||
html += "<li class='list-group-item draggable"+(checked?' checkedItem':'')+"' id='item_"+itemID+"' data-itemid='"+itemID+"' style='height: 100%; min-width: 200px;'>"; // draggable='true'
|
||||
html += " <span style='float: left; display: none; margin-right: 5px;' class='checkItems'><input type='checkbox'"+(checked?" checked":"")+"></span>";
|
||||
html += " <span style='float: left;'>"+text+"</span>";
|
||||
|
||||
|
@ -390,7 +407,8 @@ class Store {
|
|||
});
|
||||
|
||||
// DRAGGABLE
|
||||
let draggingObj = null, dragPos = null;
|
||||
this.draggingClass.update();
|
||||
/*let draggingObj = null, dragPos = null;
|
||||
this.selector.find('.draggable').unbind().on('dragstart dragover dragenter dragleave dragend', ev => {
|
||||
// this.selector.find('.draggable').hammer().bind('swipe', ev => {
|
||||
if(ev.type === 'dragover' || ev.type === 'dragenter'){
|
||||
|
@ -432,6 +450,7 @@ class Store {
|
|||
$('.drag-over').removeClass('drag-over');
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
// BIND remove-buttons
|
||||
$(this.selector).find(".remItem").each((key, val) => {
|
||||
|
@ -509,9 +528,10 @@ $("#addStore").click(ev => {
|
|||
stores.push(new Store());
|
||||
});
|
||||
|
||||
$("#refreshAll").click(ev => {
|
||||
$("#refreshAll").on('click', ev => {
|
||||
$("#stores").css('height', $("#stores").height());
|
||||
$(".tooltip").remove();
|
||||
getStores(spaceID);
|
||||
getStores(spaceID).done(json => { $("#stores").css('height', ''); });
|
||||
});
|
||||
|
||||
$("body").on('click', function(ev){
|
||||
|
@ -582,7 +602,7 @@ function getStores(spaceID){
|
|||
options = { plan: '', space: spaceID }
|
||||
}
|
||||
|
||||
$.getJSON('do.php', options)
|
||||
return $.getJSON('do.php', options)
|
||||
.done(json => {
|
||||
if(handleJsonErrors(json)){
|
||||
return;
|
||||
|
|
|
@ -54,9 +54,9 @@ function getHtmlHeaders($prepend = ""){
|
|||
<script src='".$prepend."js/jquery-3.5.1.min.js'></script>
|
||||
<script src='".$prepend."js/popper.min.js'></script>
|
||||
<script src='".$prepend."js/bootstrap.min.js'></script>
|
||||
<!--<script src='//cdn.jsdelivr.net/npm/marked/marked.min.js'></script>
|
||||
<!--<script src='//cdn.jsdelivr.net/npm/marked/marked.min.js'></script>-->
|
||||
<script src='".$prepend."js/hammer.js'></script>
|
||||
<script src='".$prepend."js/hammer.jquery.js'></script>-->
|
||||
<script src='".$prepend."js/hammer.jquery.js'></script>
|
||||
\n";
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue