есть блок с draggable элементами, добавил js, все хорошо работает, но если постараться потянуть за край drag элемента - drag event применяется ко всем элементам
<html>
<head>
<script src="https://code.jquery.com/jquery-3.5.0.js"></script>
</head>
<body>
<div class="sequence-scale"></div>
<div class="promt"></div>
</body>
</html>
вот js, который строит шкалу, хотя я уверен проблема не в нем
let zones = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24];
const build = () =>
{
const elem = // list of different elements
{
topLine: '<div class="scale__line top-line" draggable="false"><span></span></div>',
topLineReverse: '<div class="scale__line top-line-reverse" draggable="false"><span style="left: 0;"></span></div>',
middleLine: '<div class="scale__line middle-line" draggable="false"></div>',
bottomLine: '<div class="scale__line bottom-line" draggable="false"><span></span></div>',
halfroundDefault: '<div class="scale__halfround default-halfround"></div>',
halfroundReverse: '<div class="scale__halfround reverse-halfround"></div>',
},
inLine = 6, // max amount of elements at one line
$scale = $(".sequence-scale");
// data for constructing the scale
let reverse = inverseBuild = false,
amount = zones.length,
lines = Math.ceil( amount / inLine ),
halfrounds = lines - 1,
total = Math.trunc(amount / lines),
remainder = amount - total * lines;
// console.log("total: "+ total + ", remainder: " + remainder + ", amount: " + amount)
// constructing top line
if(halfrounds % 2 == 0)
{
$scale.append(elem.topLineReverse); // top line - reverse
reverse = inverseBuild = true;
}
else
$scale.append(elem.topLine); // top line - default
// constructing middle lines and bottom line
for(let i = 0; i < halfrounds; i++)
{
if(inverseBuild && halfrounds !== 0)
$scale.append(elem.halfroundReverse);
else
$scale.append(elem.halfroundDefault);
if(i == halfrounds - 1)
$scale.append(elem.bottomLine);
else
$scale.append(elem.middleLine);
inverseBuild = !inverseBuild;
}
const append = function($list)
{
$list.append('<div draggable="true" data-order="' + amount +'" data-zone-id="' + amount +'" class="zone__list">' + amount + '</div>');
amount--;
};
// appending (adding) element at line
for(let i = 0; i < lines; i++)
{
let $line = $('.scale__line').eq(i); // The line on which is appending (adding) elements on the current iteration of the loop
if(!reverse)
$line.addClass('order-reverse');
if(i + remainder >= lines) // if there is remainder
{
for(let i = 0; i < (total + 1); i++) // append (add) elements at a line with remainder
{
append($line);
}
}
else
{
for(let i = 0; i < total; i++) // append (add) elements at a line
{
append($line);
}
}
reverse = !reverse
}
};
build();
js, который меняет порядок и обрабатывает drag events
const items = () =>
{
const $list = $('.scale__line'),
$items = $('.zone__list');
// function that reads data- attribute and writes it to array
const readData = function()
{
let data = []; // array with objects for every item parameters
$items.each( function(i)
{
let $this = $(this);
data[( $items.length - 1 - i)] = //
{
id: $this.attr('data-zone-id'),
order: $this.attr('data-order')
};
});
return data;
};
// function that changes the item order on the scale
const changeOrder = function()
{
let data = readData(), // read data-
by_order = [], // data array by order
quantity = [], // amount of elements on the every line (row)
addingNum = 0;
// write value to the quantity array
for(let i = 0; i < $list.length; i++)
{
quantity[i] = $list.eq(i).children('div').length;
}
// filling array (by_order) and detach elements
for(let i = 0; i < data.length; i++)
{
let result = data.find(elem => elem.order == i + 1); // get needed element
if(!result)
return;
let elem = $(".zone__list[data-zone-id='" + result.id +"']").detach(); // detach element by id
// console.log("| elem = " + elem.text() + "|order = " + result.order + "|id = " + result.id ); // for debugging
by_order[i] = // write values to array
{
order: result.order,
id: result.id,
element: elem
};
}
// append elements back in new order
for(let i = 0; i < $list.length; i++) // ratio: i = 0 to i = max AS top line to bottom line, how much lines - so many loops
{
let $this = $list.eq(i),
len = quantity[i];
for(let i = 0; i < len; i++) // append elements at aline at the same amount, in order
{
by_order[by_order.length -( addingNum + i + 1)].element.appendTo($this); // append elements back
}
addingNum += len;
}
};
let $active, $over, contains, thisCenter,
changeable = false,
insert = ["insert After", "insert Before"], inserted;
$items.prop("draggable", true);
const dragStart = function(e)
{
e.stopPropagation();
$(this).addClass('selected');
}
const dragEnter = function(e)
{
e.preventDefault();
e.stopPropagation();
let $current = $(e.target);
$active = $('.selected');
changeable = false;
if(!($active[0] !== $current[0]))
return;
$over = $current;
$over.addClass('over');
changeable = true;
contains = ($over.parent().attr("class").split(' ')).includes('order-reverse');
if(contains)
[insert[0], insert[1]] = [insert[1], insert[0]];
let thisCoord = $current[0].getBoundingClientRect();
thisCenter = thisCoord.x + thisCoord.width / 2;
$('.promt').css(
{
'top': (thisCoord.top - 35) + "px",
'left': (thisCoord.left - 28) + "px",
'opacity': "1"
});
}
const dragOver = function(e)
{
e.stopPropagation();
e.preventDefault();
if(!changeable)
return;
if(window.event.clientX > thisCenter)
{
$('.promt').text(insert[1]);
$over.css('background','linear-gradient(270deg, #4d774e 50%, transparent 50%)');
inserted = insert[1] ;
}
else
{
$('.promt').text(insert[0]);
$over.css('background','linear-gradient(90deg, #4d774e 50%, transparent 50%)');
inserted = insert[0];
}
}
const dragLeave = function(e)
{
setDefault();
}
const dragEnd = function(e)
{
e.preventDefault();
e.stopPropagation();
if(!changeable)
{
$('.selected').removeClass('selected');
return;
}
let newData = parseInt($over.attr('data-order')),
oldData = parseInt($active.attr('data-order')),
affectedNum;
if(inserted === 'insert After')
inserted = 1;
else
inserted = 0;
if(newData > oldData)
{
affectedNum = newData - oldData;
if(!inserted)
affectedNum--;
for(let i = 0; i < affectedNum; i++ )
{
let currentElem = oldData + i + 1,
$this = $(".zone__list[data-order='" + currentElem +"']");
$this.attr('data-order', currentElem - 1 );
}
$active.attr("data-order", affectedNum + oldData);
}
else
{
affectedNum = oldData - newData;
if(inserted)
affectedNum--;
for(let i = 0; i < affectedNum; i++ )
{
let currentElem = oldData - i - 1,
$this = $(".zone__list[data-order='" + currentElem +"']");
$this.attr('data-order', currentElem + 1 );
}
$active.attr("data-order", oldData - affectedNum);
}
changeOrder();
setDefault();
$('.selected').removeClass('selected');
}
const setDefault = function()
{
if(!changeable)
return;
$over.css('background','rgb(77, 119, 78)').removeClass('over');
$('.promt').css('opacity','0');
if(contains)
[insert[0], insert[1]] = [insert[1], insert[0]];
contains = false;
}
$items.on('dragstart', dragStart);
$items.on('dragenter', dragEnter);
$items.on('dragover', dragOver);
$items.on('dragleave', dragLeave);
$items.on('dragend', dragEnd);
}
items();
и сss
*, *::before, *::after
{
padding: 0%;
margin: 0%;
box-sizing: border-box;
font-size: 8pt;
}
body
{
font-family: sans-serif;
font-weight: normal;
background-color: rgb(157, 200, 141);
padding: 10px;
}
.sequence-scale
{
max-width: 500px;
display: flex;
flex-direction: column;
margin-top: 40px;
--line-height: 6px;
--halfround-height: 9px;
--background:rgb(22, 74, 65);
pointer-events: none;
}
.scale__line
{
position: relative;
height: var(--line-height);
background-color: var(--background);
width: calc(100% - 50px);
z-index:2;
display: flex;
justify-content: space-between;
pointer-events: none;
}
.top-line
{
margin-bottom: calc( (var(--halfround-height) + var(--line-height)) / 2 * -1 );
margin-left: auto;
padding: 0 70px 0 20px;
}
.top-line-reverse
{
margin-bottom: calc( (var(--halfround-height) + var(--line-height)) / 2 * -1 );
margin-right: auto;
padding: 0 20px 0 70px;
}
.middle-line
{
margin-bottom: calc( (var(--halfround-height) + var(--line-height)) / 2 * -1 );
margin-top: calc( (var(--halfround-height) + var(--line-height)) / 2 * -1 );
width: calc(100% - 100px);
margin-left: auto;
margin-right: auto;
padding: 0 20px;
}
.bottom-line
{
margin-top: calc( (var(--halfround-height) + var(--line-height)) / 2 * -1 );
margin-left: auto;
padding: 0 70px 0 20px;
}
.order-reverse
{
flex-direction: row-reverse;
}
.scale__halfround
{
position: relative;
height: 80px;
width: 80px;
border: var(--halfround-height) solid var(--background);
z-index: 1;
}
.default-halfround
{
border-radius: 50% 0 0 50%;
border-right: transparent;
}
.reverse-halfround
{
margin-left: auto;
border-radius: 0 50% 50% 0;
border-left: transparent;
}
.zone__list
{
pointer-events: auto;
list-style-type: none;
margin-top: -10px;
width: 30px;
height: 30px;
background-color: rgb(77, 119, 78);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
cursor: grab;
transition: transform 0.2s;
}
.scale__line span
{
position: absolute;
height: 15px;
width: 6px;
background-color: var(--background);
top: calc( ( 15px - 6px ) / -2);
right: 0;
}
.selected
{
filter: brightness(0.6);
}
.over
{
transform: scale(1.5);
filter: brightness(1.45);
content: '';
}
.promt
{
position: absolute;
width:75px;
height:10px;
padding:4px 5px;
background: rgba(22, 74, 65, .6);
color:rgb(255, 255, 255);
text-align: center;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
box-sizing: content-box;
font-family: Verdana, Geneva, Tahoma, sans-serif;
opacity: 0;
transition: opacity 0.4s;
}
.promt::before
{
content:'';
position:absolute;
bottom:-8px;
left:calc(50% - 8px);
border-left:8px solid transparent;
border-right:8px solid transparent;
border-top:8px solid rgba(22, 74, 65, .6);
}
Проблема была: при попытке потянуть за край выделялся объект и полностью ломал всю логику javascript, все решилось при добавление в сss
body
{
user-select:none;
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Делаю fetch-запрос на сервер, но получаю предупреждение о corsКак можно обработать POST-запрос на сервер
Как сделать чтобы при открытии балуна метка оставалась окрашенной? При закрытии балуна метки должны быть черными
Допустим есть две страницы, хранящиеся в одной папкеНа каждой странице есть по две кнопки
Хотите улучшить этот вопрос? Добавьте больше подробностей и уточните проблему, отредактировав это сообщение