New drag-and-drop system
parent
b3fe240f55
commit
de091bf3ab
|
@ -1,3 +1,4 @@
|
||||||
|
2022-02-09 Fixed drag-and-drop on iOS.
|
||||||
2022-02-02 Fixed wrong strikethrough.
|
2022-02-02 Fixed wrong strikethrough.
|
||||||
2022-01-26 Search for products and some UI-fixes.
|
2022-01-26 Search for products and some UI-fixes.
|
||||||
2022-01-19 Revamped the login-system.
|
2022-01-19 Revamped the login-system.
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,76 @@
|
||||||
|
(function (factory) {
|
||||||
|
"use strict";
|
||||||
|
var sortable,
|
||||||
|
jq,
|
||||||
|
_this = this
|
||||||
|
;
|
||||||
|
|
||||||
|
if (typeof define === "function" && define.amd) {
|
||||||
|
try {
|
||||||
|
define(["sortablejs", "jquery"], function(Sortable, $) {
|
||||||
|
sortable = Sortable;
|
||||||
|
jq = $;
|
||||||
|
checkErrors();
|
||||||
|
factory(Sortable, $);
|
||||||
|
});
|
||||||
|
} catch(err) {
|
||||||
|
checkErrors();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else if (typeof exports === 'object') {
|
||||||
|
try {
|
||||||
|
sortable = require('sortablejs');
|
||||||
|
jq = require('jquery');
|
||||||
|
} catch(err) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof jQuery === 'function' || typeof $ === 'function') {
|
||||||
|
jq = jQuery || $;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof Sortable !== 'undefined') {
|
||||||
|
sortable = Sortable;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkErrors() {
|
||||||
|
if (!jq) {
|
||||||
|
throw new Error('jQuery is required for jquery-sortablejs');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sortable) {
|
||||||
|
throw new Error('SortableJS is required for jquery-sortablejs (https://github.com/SortableJS/Sortable)');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkErrors();
|
||||||
|
factory(sortable, jq);
|
||||||
|
})(function (Sortable, $) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
$.fn.sortable = function (options) {
|
||||||
|
var retVal,
|
||||||
|
args = arguments;
|
||||||
|
|
||||||
|
this.each(function () {
|
||||||
|
var $el = $(this),
|
||||||
|
sortable = $el.data('sortable');
|
||||||
|
|
||||||
|
if (!sortable && (options instanceof Object || !options)) {
|
||||||
|
sortable = new Sortable(this, options);
|
||||||
|
$el.data('sortable', sortable);
|
||||||
|
} else if (sortable) {
|
||||||
|
if (options === 'destroy') {
|
||||||
|
sortable.destroy();
|
||||||
|
$el.removeData('sortable');
|
||||||
|
} else if (options === 'widget') {
|
||||||
|
retVal = sortable;
|
||||||
|
} else if (typeof sortable[options] === 'function') {
|
||||||
|
retVal = sortable[options].apply(sortable, [].slice.call(args, 1));
|
||||||
|
} else if (options in sortable.options) {
|
||||||
|
retVal = sortable.option.apply(sortable, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (retVal === void 0) ? this : retVal;
|
||||||
|
};
|
||||||
|
});
|
|
@ -152,7 +152,7 @@ if(!empty($data) && isset($user_id)){
|
||||||
returns("Missing a value: $temp", 1);
|
returns("Missing a value: $temp", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( moveItem($data['storeID'], $data['itemID'], $data['afterID']) ){
|
if( moveItem($data['storeID'], $data['itemID'], $data['afterID'], @$data['newStoreId']) ){
|
||||||
returns();
|
returns();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,10 +412,10 @@ function remItem($storeID, $itemID, $price){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveItem($storeID, $itemID, $afterID){
|
function moveItem($storeID, $itemID, $afterID, $newStoreId = null){
|
||||||
global $db;
|
global $db;
|
||||||
|
|
||||||
$verifyUserOwnershipSQL = getVerifyStoreOwnerSQL($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";
|
$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 = "";
|
$differentStoreAddSQL = "";
|
||||||
|
@ -427,6 +427,13 @@ function moveItem($storeID, $itemID, $afterID){
|
||||||
$storeID = $stores[1];
|
$storeID = $stores[1];
|
||||||
$differentStoreAddSQL = ", plan_store_id = $storeID";
|
$differentStoreAddSQL = ", plan_store_id = $storeID";
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
$differentStoreAddSQL = "";
|
||||||
|
|
||||||
|
if($newStoreId != null){
|
||||||
|
$storeID = $newStoreId;
|
||||||
|
$differentStoreAddSQL = ", plan_store_id = $storeID";
|
||||||
}
|
}
|
||||||
|
|
||||||
$verifyUserOwnershipSQL = getVerifyStoreOwnerSQL($storeID);
|
$verifyUserOwnershipSQL = getVerifyStoreOwnerSQL($storeID);
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
<head>
|
<head>
|
||||||
<?=getHtmlHeaders($rPath);?>
|
<?=getHtmlHeaders($rPath);?>
|
||||||
<title>Plan - PaperBag - Plan Your Shopping</title>
|
<title>Plan - PaperBag - Plan Your Shopping</title>
|
||||||
|
|
||||||
|
<!-- jsDelivr :: Sortable :: Latest (https://www.jsdelivr.com/package/npm/sortablejs) -->
|
||||||
|
<script src="/js/sortable/Sortable.min.js"></script> <!-- CDN: https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js -->
|
||||||
|
<script src="/js/sortable/jquery-sortable.js"></script> <!-- CDN: https://cdn.jsdelivr.net/npm/jquery-sortablejs@latest/jquery-sortable.js -->
|
||||||
</head>
|
</head>
|
||||||
<body id='plan'>
|
<body id='plan'>
|
||||||
<div id="page-container">
|
<div id="page-container">
|
||||||
|
@ -37,7 +41,7 @@
|
||||||
<script src='plan.js'></script>
|
<script src='plan.js'></script>
|
||||||
<script src='recipe.js'></script>
|
<script src='recipe.js'></script>
|
||||||
<script src='product.js'></script>
|
<script src='product.js'></script>
|
||||||
<script src='draggingClass.js'></script>
|
<!-- <script src='draggingClass.js'></script>-->
|
||||||
</div>
|
</div>
|
||||||
<?php include $rPath.'webdata/footer.html'; ?>
|
<?php include $rPath.'webdata/footer.html'; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
/*jshint sub:true, esversion: 6, -W083 */
|
/*jshint sub:true, esversion: 6, -W083 */
|
||||||
|
|
||||||
|
const debug = false;
|
||||||
|
|
||||||
// Default timer for jquery slide, except set to 0 if the user prefers reduced motion.
|
// Default timer for jquery slide, except set to 0 if the user prefers reduced motion.
|
||||||
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||||
const slideTimer = prefersReducedMotion?0:400;
|
const slideTimer = prefersReducedMotion?0:400;
|
||||||
|
@ -29,7 +32,7 @@ class Store {
|
||||||
html += " <div class='card-body'>";
|
html += " <div class='card-body'>";
|
||||||
html += " <ul class='list-group list-group-flush storeItems dragHolder'>";
|
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 emptyList'>No items added</li>";
|
||||||
html += " <li class='list-group-item draggable' data-itemid='0' data-storeid='"+this.storeID+"' style='height: 10px; width: 100%;'></li>";
|
// html += " <li class='list-group-item draggable' data-itemid='0' data-storeid='"+this.storeID+"' style='height: 10px; width: 100%;'></li>";
|
||||||
html += " </ul>";
|
html += " </ul>";
|
||||||
|
|
||||||
html += HtmlElements.store.addItemSection;
|
html += HtmlElements.store.addItemSection;
|
||||||
|
@ -62,12 +65,10 @@ class Store {
|
||||||
|
|
||||||
if($(ev.currentTarget).hasClass('planningState')){
|
if($(ev.currentTarget).hasClass('planningState')){
|
||||||
this.setState('planning');
|
this.setState('planning');
|
||||||
// this.selector.find(".newItemName").first().focus();
|
|
||||||
this.selector.find(".card-body").focus();
|
this.selector.find(".card-body").focus();
|
||||||
}
|
}
|
||||||
else if($(ev.currentTarget).hasClass('shoppingState')){
|
else if($(ev.currentTarget).hasClass('shoppingState')){
|
||||||
this.setState('shopping');
|
this.setState('shopping');
|
||||||
// this.selector.find(".checkItems input").first().focus();
|
|
||||||
this.selector.find(".card-body").focus();
|
this.selector.find(".card-body").focus();
|
||||||
}
|
}
|
||||||
else if($(ev.currentTarget).hasClass('closedState')){
|
else if($(ev.currentTarget).hasClass('closedState')){
|
||||||
|
@ -88,7 +89,46 @@ class Store {
|
||||||
});
|
});
|
||||||
|
|
||||||
// INIT DRAGGING
|
// INIT DRAGGING
|
||||||
this.draggingClass = new Draggable("draggable", 'dragHolder', 'drag-over', "#store"+storeNum,(moved, after)=> {
|
this.selector.find('.dragHolder').sortable({
|
||||||
|
handle: '.draggable',
|
||||||
|
filter: '.priceWrapper, .itemButtons',
|
||||||
|
group: 'shared',
|
||||||
|
ghostClass: 'bg-secondary',
|
||||||
|
delay: 100,
|
||||||
|
delayOnTouchOnly: true,
|
||||||
|
onEnd: (evt) => {
|
||||||
|
let newStore;
|
||||||
|
if(evt.from !== evt.to){
|
||||||
|
console.info("Item is moved to a new list.");
|
||||||
|
|
||||||
|
let fromStoreElem= $(evt.from);
|
||||||
|
if(fromStoreElem.find("li").length <= 1){
|
||||||
|
fromStoreElem.find('.emptyList').show();
|
||||||
|
}
|
||||||
|
|
||||||
|
let toStoreElem= $(evt.to);
|
||||||
|
newStore = toStoreElem.attr('data-storeid');
|
||||||
|
toStoreElem.find('.emptyList').hide();
|
||||||
|
}
|
||||||
|
else if(evt.oldIndex === evt.newIndex){
|
||||||
|
console.warn("Item wasn't moved! (?)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let itemElem = $(evt.item);
|
||||||
|
let itemId = itemElem.attr('data-itemid');
|
||||||
|
|
||||||
|
let afterId = itemElem.prev().attr('data-itemid');
|
||||||
|
|
||||||
|
if(typeof afterId === "undefined"){
|
||||||
|
afterId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setItemPosition(itemId, afterId, newStore);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/*this.draggingClass = new Draggable("draggable", 'dragHolder', 'drag-over', "#store"+storeNum,(moved, after)=> {
|
||||||
// console.log(moved, after);
|
// console.log(moved, after);
|
||||||
|
|
||||||
let movedID = moved.attr('data-itemid');
|
let movedID = moved.attr('data-itemid');
|
||||||
|
@ -101,7 +141,7 @@ class Store {
|
||||||
$("#refreshAll").trigger('click');
|
$("#refreshAll").trigger('click');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});*/
|
||||||
}
|
}
|
||||||
|
|
||||||
setState(state, animTime){
|
setState(state, animTime){
|
||||||
|
@ -110,22 +150,22 @@ class Store {
|
||||||
|
|
||||||
if(state === "planning"){
|
if(state === "planning"){
|
||||||
this.state = "planning";
|
this.state = "planning";
|
||||||
this.selector.find('ul').addClass('storePlanState');
|
this.selector.find('ul').addClass('storePlanState').find('li:not(.emptyList)').addClass('draggable');
|
||||||
this.selector.find('li:not(.checkedItem) .itemAmountButtons').slideDown(animTime);
|
this.selector.find('li:not(.checkedItem) .itemAmountButtons').slideDown(animTime);
|
||||||
// this.selector.find('li:not(.checkedItem) .itemAmountText').slideUp(animTime);
|
// this.selector.find('li:not(.checkedItem) .itemAmountText').slideUp(animTime);
|
||||||
// this.selector.find('.checkedItem .itemAmountText:not(.oneItem)').slideDown(animTime);
|
// this.selector.find('.checkedItem .itemAmountText:not(.oneItem)').slideDown(animTime);
|
||||||
|
|
||||||
this.selector.find('.addItemFormWrapper').slideDown(animTime);
|
this.selector.find('.addItemFormWrapper').slideDown(animTime);
|
||||||
this.selector.find('.remItem').show();
|
this.selector.find('.remItem').show();
|
||||||
this.draggingClass.unpause();
|
// this.draggingClass.unpause();
|
||||||
}
|
}
|
||||||
if(state !== "planning"){
|
if(state !== "planning"){
|
||||||
this.selector.find('ul').removeClass('storePlanState');
|
this.selector.find('ul').removeClass('storePlanState').find('li').removeClass('draggable');
|
||||||
this.selector.find('.itemAmountButtons').slideUp(animTime);
|
this.selector.find('.itemAmountButtons').slideUp(animTime);
|
||||||
// this.selector.find('.itemAmountText:not(.oneItem)').slideDown(animTime);
|
// this.selector.find('.itemAmountText:not(.oneItem)').slideDown(animTime);
|
||||||
this.selector.find('.addItemFormWrapper').slideUp(animTime);
|
this.selector.find('.addItemFormWrapper').slideUp(animTime);
|
||||||
this.selector.find('.remItem').hide();
|
this.selector.find('.remItem').hide();
|
||||||
this.draggingClass.pause();
|
// this.draggingClass.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state === "shopping"){
|
if(state === "shopping"){
|
||||||
|
@ -291,7 +331,7 @@ class Store {
|
||||||
|
|
||||||
if(newChecked === true){
|
if(newChecked === true){
|
||||||
this.selector.find('#item_'+itemID).addClass("checkedItem");
|
this.selector.find('#item_'+itemID).addClass("checkedItem");
|
||||||
this.draggingClass.moveToBottomAnimated('#item_'+itemID);
|
// this.draggingClass.moveToBottomAnimated('#item_'+itemID);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.selector.find('#item_'+itemID).removeClass("checkedItem");
|
this.selector.find('#item_'+itemID).removeClass("checkedItem");
|
||||||
|
@ -353,10 +393,12 @@ class Store {
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
setItemPosition(itemID, afterID){
|
setItemPosition(itemID, afterID, newStore){
|
||||||
afterID = afterID || 0;
|
afterID = afterID || 0;
|
||||||
|
newStore = newStore || this.storeID;
|
||||||
|
|
||||||
if(itemID !== afterID){
|
if(itemID !== afterID){
|
||||||
return ajaxReq({ plan: 'moveItem', storeID: this.storeID, itemID: itemID, afterID: afterID });
|
return ajaxReq({ plan: 'moveItem', storeID: this.storeID, itemID: itemID, afterID: afterID, newStoreId: newStore });
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -414,7 +456,7 @@ class Store {
|
||||||
});
|
});
|
||||||
|
|
||||||
// DRAGGABLE
|
// DRAGGABLE
|
||||||
this.draggingClass.update();
|
// this.draggingClass.update();
|
||||||
/*let draggingObj = null, dragPos = null;
|
/*let draggingObj = null, dragPos = null;
|
||||||
this.selector.find('.draggable').unbind().on('dragstart dragover dragenter dragleave dragend', ev => {
|
this.selector.find('.draggable').unbind().on('dragstart dragover dragenter dragleave dragend', ev => {
|
||||||
// this.selector.find('.draggable').hammer().bind('swipe', ev => {
|
// this.selector.find('.draggable').hammer().bind('swipe', ev => {
|
||||||
|
|
Loading…
Reference in New Issue