how to sort and move elements inside a grid - javascript

el should be movable:
up and down - inside the parent - so columns should be sortable
and left-right - from one column to another
Any help
$("#cola, #colb, #colc, #cold").sortable({
containment: "parent"
});
$("#cola, #colb, #colc, #cold").droppable();
$('.el').draggable({
});
.grid{
display:grid;
grid-template-columns:1fr 1fr 1fr 1fr;
width:50%;
}
.col{
height:100vh;
overflow-y:scroll;
}
.el{
line-height:25px;
text-align:center;
cursor:pointer;
margin:14px 0;
background:gold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class='grid'>
<div class='col' id='cola'>
<div class='el'>A</div>
<div class='el'>A</div>
<div class='el'>A</div>
</div>
<div class='col' id='colb'>
<div class='el'>B</div>
<div class='el'>B</div>
<div class='el'>B</div>
</div>
<div class='col' id='colc'>
<div class='el'>C</div>
<div class='el'>C</div>
<div class='el'>C</div>
</div>
<div class='col' id='cold'>
<div class='el'>D</div>
<div class='el'>D</div>
<div class='el'>D</div>
</div>
</div>

I think you're over complicating it. Here is a basic sortable, you will want to use items and connectWith options.
$(".col").sortable({
containment: ".grid",
items: "> div.el",
connectWith: ".col"
});
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
width: 50%;
}
.col {
height: 100vh;
overflow-y: scroll;
}
.el {
line-height: 25px;
text-align: center;
cursor: pointer;
margin: 14px 0;
background: gold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class='grid'>
<div class='col' id='cola'>
<div class='el'>A-1</div>
<div class='el'>A-2</div>
<div class='el'>A-3</div>
</div>
<div class='col' id='colb'>
<div class='el'>B-1</div>
<div class='el'>B-2</div>
<div class='el'>B-3</div>
</div>
<div class='col' id='colc'>
<div class='el'>C-1</div>
<div class='el'>C-2</div>
<div class='el'>C-3</div>
</div>
<div class='col' id='cold'>
<div class='el'>D-1</div>
<div class='el'>D-2</div>
<div class='el'>D-3</div>
</div>
</div>

Related

Table with CSS Grid: give all columns of same type width of entry with widest content?

I have the following table design, laid out with CSS Grid (see first snippet).
Is it possible to make all columns of the same type/class (e.g. .Table_col_day) as wide as the column of that type/class with the widest content, with CSS/without JS? The solution doesn’t have to be CSS Grid based.
See the second code snippet for a quick JS-based solution, to illustrate what I'd like to do.
.Table__row {
background-color: plum;
display: grid;
grid-template-columns: 0.5fr 0.5fr 1fr;
}
.Table__row:nth-of-type(even) {
background-color: lime;
}
<div class="Table">
<div class="Table__row">
<div class="Table__day">Mon</div>
<div class="Table__time">10am</div>
<div class="Table__title">Some event</div>
</div>
<div class="Table__row">
<div class="Table__day">Tue</div>
<div class="Table__time">12:30pm</div>
<div class="Table__title">Another event</div>
</div>
<div class="Table__row">
<div class="Table__day">Wed</div>
<div class="Table__time">9:00am</div>
<div class="Table__title">A different event</div>
</div>
</div>
Javascript-based solution (determine widest column content, then manually set grid column styles of row element)
function resizeColumns(SELECTOR) {
const colElements = document.querySelectorAll(SELECTOR);
//////
const widths = [...colElements].map(el => el.querySelector('span').offsetWidth);
const width_max = Math.max(...widths);
//////
for(let col of colElements) {
col.parentNode.style.gridTemplateColumns = `${width_max}px 0.5fr 1fr`;
}
}
resizeColumns('.Table__col_day');
.Table__row {
background-color: plum;
display: grid;
grid-template-columns: 0.5fr 0.5fr 1fr;
}
.Table__row:nth-of-type(even) {
background-color: lime;
}
<div class="Table">
<div class="Table__row">
<div class="Table__col_day">
<span>Mon</span>
</div>
<div class="Table__col_time">
<span>10am</span>
</div>
<div class="Table__col_title">
<span>Some event</span>
</div>
</div>
<div class="Table__row">
<div class="Table__col_day">
<span>Tue</span>
</div>
<div class="Table__col_time">
<span>12:30pm</span>
</div>
<div class="Table__col_title">
<span>Another event</span>
</div>
</div>
<div class="Table__row">
<div class="Table__col_day">
<span>Wed</span>
</div>
<div class="Table__col_time">
<span>9:00am</span>
</div>
<div class="Table__col_title">
<span>A different event</span>
</div>
</div>
</div>
You said it at the beginning: "table design" so use table
.Table {
display: table;
width: 100%;
}
.Table__row {
background-color: plum;
display: table-row;
}
.Table__row > * {
display: table-cell;
white-space: nowrap;
}
.Table__row > *:not(.Table__day) {
width: 50%;
}
.Table__row:nth-of-type(even) {
background-color: lime;
}
<div class="Table">
<div class="Table__row">
<div class="Table__day">Mon</div>
<div class="Table__time">10am</div>
<div class="Table__title">Some event</div>
</div>
<div class="Table__row">
<div class="Table__day">Tue</div>
<div class="Table__time">12:30pm</div>
<div class="Table__title">Another event</div>
</div>
<div class="Table__row">
<div class="Table__day">Wed</div>
<div class="Table__time">9:00am</div>
<div class="Table__title">A different event</div>
</div>
</div>
Or consider display:contents if you want to keep display:grid;
.Table {
display: grid;
grid-template-columns: auto 1fr 1fr;
}
.Table__row {
display: contents;
}
.Table__row > * {
background-color: plum;
}
.Table__row:nth-of-type(even) > * {
background-color: lime;
}
<div class="Table">
<div class="Table__row">
<div class="Table__day">Mon</div>
<div class="Table__time">10am</div>
<div class="Table__title">Some event</div>
</div>
<div class="Table__row">
<div class="Table__day">Tue</div>
<div class="Table__time">12:30pm</div>
<div class="Table__title">Another event</div>
</div>
<div class="Table__row">
<div class="Table__day">Wed</div>
<div class="Table__time">9:00am</div>
<div class="Table__title">A different event</div>
</div>
</div>

Only change class in this scope

I have a card which has onclick change functionality.
If I include two of these cards on my page, the classes will duplicate. But it's also changing the class in the second card when a change occurs in the first and vice versa.
Here is a demo:
$('div[data-item="item--1"]').addClass('active');
$('.header').click(function() {
var myEm = $(this).attr('data-item');
$('.header, .subheader').removeClass('active');
$('.header[data-item = '+myEm+'], .subheader[data-item = '+myEm+']').addClass('active');
});
.card{
display: flex;
flex-direction: column;
padding: 30px;
background: lightblue;
}
.headers{
padding: 20px;
margin-bottom: 40px;
}
.header{
cursor: pointer;
opacity: 0.4;
}
.header.active{
opacity: 1;
}
.subheader{
display: none;
padding: 0px 20px;
}
.header.active,
.subheader.active{
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
<div class="card">
<div class="headers">
<div class="header" data-item="item--1">Test</div>
<div class="header" data-item="item--2">Test 2</div>
</div>
<div class="subheaders">
<div class="subheader" data-item="item--1">Subheader for Test</div>
<div class="subheader" data-item="item--2">Subheader for Test 2</div>
</div>
</div>
<div class="card">
<div class="headers">
<div class="header" data-item="item--1">Another Test</div>
<div class="header" data-item="item--2">Another Test 2</div>
</div>
<div class="subheaders">
<div class="subheader" data-item="item--1">Subheader for Another Test</div>
<div class="subheader" data-item="item--2">Subheader for Another Test 2</div>
</div>
</div>
How can I prevent this?
You can pass the closest .card ancestor as the context of the selectors.
$('.header').click(function() {
var myEm = $(this).attr('data-item');
$('.header, .subheader', $(this).closest('.card')).removeClass('active');
$('.header[data-item = '+myEm+'], .subheader[data-item = '+myEm+']',
$(this).closest('.card')).addClass('active');
});
Live Example:
$('div[data-item="item--1"]').addClass('active');
$('.header').click(function() {
var myEm = $(this).attr('data-item');
$('.header, .subheader', $(this).closest('.card')).removeClass('active');
$('.header[data-item = '+myEm+'], .subheader[data-item = '+myEm+']', $(this).closest('.card')).addClass('active');
});
.card{
display: flex;
flex-direction: column;
padding: 30px;
background: lightblue;
}
.headers{
padding: 20px;
margin-bottom: 40px;
}
.header{
cursor: pointer;
opacity: 0.4;
}
.header.active{
opacity: 1;
}
.subheader{
display: none;
padding: 0px 20px;
}
.header.active,
.subheader.active{
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
<div class="card">
<div class="headers">
<div class="header" data-item="item--1">Test</div>
<div class="header" data-item="item--2">Test 2</div>
</div>
<div class="subheaders">
<div class="subheader" data-item="item--1">Subheader for Test</div>
<div class="subheader" data-item="item--2">Subheader for Test 2</div>
</div>
</div>
<div class="card">
<div class="headers">
<div class="header" data-item="item--1">Another Test</div>
<div class="header" data-item="item--2">Another Test 2</div>
</div>
<div class="subheaders">
<div class="subheader" data-item="item--1">Subheader for Another Test</div>
<div class="subheader" data-item="item--2">Subheader for Another Test 2</div>
</div>
</div>

CSS Grid - Highlight cells up to the hovered cell

In a grid, I want to highlight group of cells - a rectangle shape - starting from top left cell up to the cell under the mouse position.
Let's say our grid initially looks like this:
.grid {
display: grid;
grid-template-columns: repeat(5, 50px);
grid-template-rows: repeat(5, 50px);
gap: 5px;
}
.grid-item {
display: flex;
justify-content: center;
align-items: center;
background: lightgray;
}
<div class="grid">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
<div class="grid-item">9</div>
<div class="grid-item">10</div>
<div class="grid-item">11</div>
<div class="grid-item">12</div>
<div class="grid-item">13</div>
<div class="grid-item">14</div>
<div class="grid-item">15</div>
<div class="grid-item">16</div>
<div class="grid-item">17</div>
<div class="grid-item">18</div>
<div class="grid-item">19</div>
<div class="grid-item">20</div>
<div class="grid-item">21</div>
<div class="grid-item">22</div>
<div class="grid-item">23</div>
<div class="grid-item">24</div>
<div class="grid-item">25</div>
</div>
And now the user hovers with the mouse over cell number 18. The grid should look like this now:
.grid {
display: grid;
grid-template-columns: repeat(5, 50px);
grid-template-rows: repeat(5, 50px);
gap: 5px;
}
.grid-item {
display: flex;
justify-content: center;
align-items: center;
background: lightgray;
}
.grid-item-blue {
background: lightblue;
}
<div class="grid">
<div class="grid-item grid-item-blue">1</div>
<div class="grid-item grid-item-blue">2</div>
<div class="grid-item grid-item-blue">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item grid-item-blue">6</div>
<div class="grid-item grid-item-blue">7</div>
<div class="grid-item grid-item-blue">8</div>
<div class="grid-item">9</div>
<div class="grid-item">10</div>
<div class="grid-item grid-item-blue">11</div>
<div class="grid-item grid-item-blue">12</div>
<div class="grid-item grid-item-blue">13</div>
<div class="grid-item">14</div>
<div class="grid-item">15</div>
<div class="grid-item grid-item-blue">16</div>
<div class="grid-item grid-item-blue">17</div>
<div class="grid-item grid-item-blue">18</div>
<div class="grid-item">19</div>
<div class="grid-item">20</div>
<div class="grid-item">21</div>
<div class="grid-item">22</div>
<div class="grid-item">23</div>
<div class="grid-item">24</div>
<div class="grid-item">25</div>
</div>
I prefer css solution.
Is is possible using css only? If not, how would you do this in JS?
Here's a pure css Idea if you don't mind nesting the content on more level just to put it over the fake background.
.grid {
overflow:hidden;
display: grid;
grid-template-columns: repeat(5, 50px);
grid-template-rows: repeat(5, 50px);
gap: 5px;
}
.grid-item {
background: lightgray;
position: relative;
display: flex;
}
.grid-item>span {
z-index: 2;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.grid-item:hover:before {
position: absolute;
content: '';
background: linear-gradient(to left,#ff000000 0px 50px,#ffffff 50px 55px) 0 0/55px, linear-gradient(to top,lightblue 0px 50px,#ffffff00 50px 55px) 0 0/1px 55px ;
z-index: 1;
width: calc(55px * 9);
height: calc(55px * 9);
bottom: 0;
right: 0;
}
<div class="grid">
<div class="grid-item"><span>1</span></div>
<div class="grid-item"><span>2</span></div>
<div class="grid-item"><span>3</span></div>
<div class="grid-item"><span>4</span></div>
<div class="grid-item"><span>5</span></div>
<div class="grid-item"><span>6</span></div>
<div class="grid-item"><span>7</span></div>
<div class="grid-item"><span>8</span></div>
<div class="grid-item"><span>9</span></div>
<div class="grid-item"><span>10</span></div>
<div class="grid-item"><span>11</span></div>
<div class="grid-item"><span>12</span></div>
<div class="grid-item"><span>13</span></div>
<div class="grid-item"><span>14</span></div>
<div class="grid-item"><span>15</span></div>
<div class="grid-item"><span>16</span></div>
<div class="grid-item"><span>17</span></div>
<div class="grid-item"><span>18</span></div>
<div class="grid-item"><span>19</span></div>
<div class="grid-item"><span>20</span></div>
<div class="grid-item"><span>21</span></div>
<div class="grid-item"><span>22</span></div>
<div class="grid-item"><span>23</span></div>
<div class="grid-item"><span>24</span></div>
<div class="grid-item"><span>25</span></div>
</div>
Here is pure CSS solution with flexbox but too complex.
.grid {
display: flex;
flex-wrap: wrap;
flex-flow: wrap-reverse;
direction: rtl;
width: calc(50px*5 + 5px*4);
}
.grid-item {
width: 50px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
background: lightgray;
margin-bottom: 5px;
}
.grid-item:not(:nth-child(5n + 1)) {
margin-right: 5px;
}
.grid-item:nth-child(5n - 4):hover,
.grid-item:nth-child(5n - 4):hover~.grid-item,
.grid-item:nth-child(5n - 3):hover,
.grid-item:nth-child(5n - 3):hover~.grid-item:not(:nth-child(5n + 1)),
.grid-item:nth-child(5n - 2):hover,
.grid-item:nth-child(5n - 2):hover~.grid-item:not(:nth-child(5n + 1)):not(:nth-child(5n + 2)),
.grid-item:nth-child(5n - 1):hover,
.grid-item:nth-child(5n - 1):hover~.grid-item:not(:nth-child(5n + 1)):not(:nth-child(5n + 2)):not(:nth-child(5n + 3)),
.grid-item:nth-child(5n):hover,
.grid-item:nth-child(5n):hover~.grid-item:not(:nth-child(5n + 1)):not(:nth-child(5n + 2)):not(:nth-child(5n + 3)):not(:nth-child(5n + 4))
{
background: lightblue;
}
<div class="grid">
<div class="grid-item">25</div>
<div class="grid-item">24</div>
<div class="grid-item">23</div>
<div class="grid-item">22</div>
<div class="grid-item">21</div>
<div class="grid-item">20</div>
<div class="grid-item">19</div>
<div class="grid-item">18</div>
<div class="grid-item">17</div>
<div class="grid-item">16</div>
<div class="grid-item">15</div>
<div class="grid-item">14</div>
<div class="grid-item">13</div>
<div class="grid-item">12</div>
<div class="grid-item">11</div>
<div class="grid-item">10</div>
<div class="grid-item">9</div>
<div class="grid-item">8</div>
<div class="grid-item">7</div>
<div class="grid-item">6</div>
<div class="grid-item">5</div>
<div class="grid-item">4</div>
<div class="grid-item">3</div>
<div class="grid-item">2</div>
<div class="grid-item">1</div>
</div>
I think it very hard to do this with pure CSS, especially if you plan to expand this grid. However it can be done with javascript
document.querySelector('.grid').addEventListener("mouseover", function (event) {
Array.from(this.querySelectorAll('.grid-item')).forEach(node => {
var nodePosition = node.getBoundingClientRect();
if (nodePosition.x <= event.clientX && nodePosition.y <= event.clientY) {
node.classList.add('grid-item-blue')
}
else {
node.classList.remove('grid-item-blue')
}
})
});
.grid {
display: grid;
grid-template-columns: repeat(5, 50px);
grid-template-rows: repeat(5, 50px);
gap: 5px;
}
.grid-item {
display: flex;
justify-content: center;
align-items: center;
background: lightgray;
}
.grid-item-blue {
background: lightblue;
}
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div class="grid">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
<div class="grid-item">9</div>
<div class="grid-item">10</div>
<div class="grid-item">11</div>
<div class="grid-item">12</div>
<div class="grid-item">13</div>
<div class="grid-item">14</div>
<div class="grid-item">15</div>
<div class="grid-item">16</div>
<div class="grid-item">17</div>
<div class="grid-item">18</div>
<div class="grid-item">19</div>
<div class="grid-item">20</div>
<div class="grid-item">21</div>
<div class="grid-item">22</div>
<div class="grid-item">23</div>
<div class="grid-item">24</div>
<div class="grid-item">25</div>
</div>
</body>
You can also use debouncing to reduce the number of times the mouseover callback function is triggered.

How to Let Float Items Split the Blank Area in Average?

Please run this demo:
.app {
background:pink;
width: 90vw;
overflow: hidden;
}
.app__item {
background: lightblue;
width: 200px;
float :left;
margin:5px;
height: 40px;
}
.app__item:last-child {
float: right;
}
.app__item--size2 {
height: 90px;
}
<div class="app">
<div class="app__item app__item--size2">1</div>
<div class="app__item">2</div>
<div class="app__item">3</div>
<div class="app__item">4</div>
<div class="app__item">5</div>
<div class="app__item">6</div>
<div class="app__item">7</div>
<div class="app__item">8</div>
<div class="app__item">9</div>
<div class="app__item">10</div>
<div class="app__item">
<button>search</button>
</div>
</div>
Please notice the red color text which is what I want:
How to Let Float Items Split the Blank Area in Average?
This gif point out what I want and also the reason why I am using float layout.
If using flex, the result would be
.app {
background:pink;
width: 80vw;
display: flex;
flex-flow: row wrap;
}
.app__item,
.app__item_wrapper {
margin:5px;
width: 200px;
flex: 0 0 auto;
}
.app__item {
background: lightblue;
height: 40px;
}
.app__item_wrapper {
display: flex;
flex-flow: column;
justify-content: space-between;
}
.app__item--size2 {
height: 90px;
}
.app__item--inner {
margin:0;
flex: 0 0 auto;
}
<div class="app">
<div class="app__item app__item--size2">1</div>
<div class=" app__item_wrapper app__item--size2">
<div class="app__item app__item--inner">2</div>
<div class="app__item app__item--inner">3</div>
</div>
<div class=" app__item_wrapper app__item--size2">
<div class="app__item app__item--inner">4</div>
<div class="app__item app__item--inner">5</div>
</div>
<div class="app__item">6</div>
<div class="app__item">7</div>
<div class="app__item">8</div>
<div class="app__item">
<button>search</button>
</div>
</div>
And the con is that it won't work well when viewport is changing. See this:
and this is the con:
If I understand correctly, you're wanting the cells to the right of "cell 1" to stretch-to-fill the reaming horizontal space of the enclosing div (with pink background).
You could use CSS Grid to achieve this as shown below:
.app {
background:pink;
width: 90vw;
padding:5px;
display:grid;
/* Cause first column with to be 200px, remaining two columns
to scale to fit remaining width */
grid-template-columns: 200px repeat(2, 1fr);
/* Set spacing between cells */
grid-gap:10px;
}
.app__item {
background: lightblue;
width: 100%;
height: 40px;
}
.app__item--size2 {
/* Cause top left cell to occupy two rows */
grid-row: 1 / 3;
height:100%;
}
<div class="app">
<div class="app__item app__item--size2">1</div>
<div class="app__item">2</div>
<div class="app__item">3</div>
<div class="app__item">4</div>
<div class="app__item">5</div>
<div class="app__item">6</div>
<div class="app__item">7</div>
<div class="app__item">8</div>
<div class="app__item">9</div>
<div class="app__item">10</div>
<div class="app__item">
<button>search</button>
</div>
</div>
Thank #Dacre Denny for giving me inspiration. Finally, I got it.
.app {
background:pink;
width: 90vw;
padding:5px;
display:grid;
grid-template-columns: repeat(auto-fit,200px);
justify-content:space-evenly;
grid-gap: 5px;
}
.app__item {
background: lightblue;
width: 200px;
height: 40px;
}
.app__item--size2 {
/* Cause top left cell to occupy two rows */
grid-row: 1 / 3;
height:100%;
}
.app__item:last-child {
grid-column-end: -1
}
<div class="app">
<div class="app__item app__item--size2">1</div>
<div class="app__item">2</div>
<div class="app__item">3</div>
<div class="app__item">4</div>
<div class="app__item">5</div>
<div class="app__item">6</div>
<div class="app__item">7</div>
<div class="app__item">8</div>
<div class="app__item">9</div>
<div class="app__item">10</div>
<div class="app__item">
<button>search</button>
</div>
</div>
See this gif when viewport is changing.

How to drop a draggable into a sortable, the droppped item is not the original element but a custom helper

The jQuery draggeble/sortable demo only shows how to drop a clone of the draggable (draggable and sortable items have the same structure). I want to drop a different DOM structure. For instance, when I drag a simply div, the dragged element gets converted into a complexer DOM structure. See the jsfidler example, notice how the helper changes, I want to drop the helper but instead the original item gets dropped.
Using a simply draggable item and droppable container works but I want to be able to drop the item in any part of the sortable container and be able to reorder the elements.
Any idea how to achieve what I'm looking for?
$(function() {
$(".portlet-container").sortable({
handle: ".portlet-header",
cursor: "move",
placeholder: "ui-state-highlight"
}).droppable({
accept: ".portlet-clone",
drop: function(event, ui) {
return $(ui.helper).clone(true, true)
.removeClass('ui-draggable-dragging')
.removeClass('portlet-clone')
.css("position", "")
.css("left", "")
.css("top", "").appendTo(this);
}
});
$('.portlet-name').draggable({
connectToSortable: ".portlet-container",
cursor: 'move',
revert: 'invalid',
opacity: 0.7,
helper: portletHelper
});
function portletHelper(event) {
var portletWrapperStr = "<div class='portlet-wrapper portlet-clone' style='height:" + $(this).data("div-height") + "px; width:" + $(this).data("div-width") + "px;'/>";
var portletStr = "<div class='portlet' " +
"style='height:" + ($(this).data("div-height") - 40 - 2) + "px;'>" +
"<div class='portlet-header'>" + $(this).html() + "</div>" +
"</div>";
var portlet = $(portletStr);
var portletWrapper = $(portletWrapperStr).append(portlet);
return portletWrapper;
}
});
.portlet-container {
display: inline-block;
margin-top: 10px;
margin-bottom: 10px;
width: 960px;
}
.portlet-wrapper {
overflow: hidden;
}
.portlet {
border-radius: 4px;
border: 1px solid #bbb;
background-color: white;
padding: 10px 10px;
margin-top: 10px;
margin-bottom: 10px;
position: relative;
overflow: hidden;
}
.portlet-header {
height: 25px;
}
.portlet-content {
margin-bottom: 10px;
}
.portlet-options {
float: right;
}
.portlet-placeholder {
border: 1px dotted black;
margin: 0 1em 1em 0;
height: 95%;
}
.portlets-items {
width: 220px;
}
.portlet-item {
margin: 2px;
display: inline-block;
width: 220px;
height: 25px;
}
.portlet-name {
width: 140px;
font-family: Akkurat, Helvetica, Arial, sans-serif;
font-size: 12px;
color: #5c5e5f;
border-radius: 2px;
border: 1px solid #bbb;
padding: 2px;
display: inline-block;
}
<title>Drag and Drop</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script src="dragndrop.js"></script>
<body>
<div class="portlet-items">
<div class="portlet-item">
<div class="portlet-name" data-div-width="460" data-div-height="230">
dragabble narrow 1
</div>
</div>
<div class="portlet-item">
<div class="portlet-name" data-div-width="460" data-div-height="230">
dragabble narrow 2
</div>
</div>
<div class="portlet-item">
<div class="portlet-name" data-div-width="960" data-div-height="230">
dragabble wide 1
</div>
</div>
<div class="portlet-item">
<div class="portlet-name" data-div-width="960" data-div-height="230">
dragabble wide 2
</div>
</div>
<div class="portlet-item">
<div class="portlet-name" data-div-width="960" data-div-height="230">
dragabble wide 3
</div>
</div>
<div class="portlet-item">
<div class="portlet-name" data-div-width="960" data-div-height="230">
dragabble wide 4
</div>
</div>
<div class="portlet-item">
<div class="portlet-name" data-div-width="960" data-div-height="230">
dragabble wide 5
</div>
</div>
</div>
<div class="portlet-container">
<div class="portlet-wrapper" style="height:230px;">
<div class="portlet" style="height:188px;">
<div class="portlet-header">Portlet 6</div>
<div class="portlet-content">content</div>
</div>
</div>
<div class="portlet-wrapper" style="height:230px;">
<div class="portlet" style="height:188px;">
<div class="portlet-header">Portlet 5</div>
<div class="portlet-content">content</div>
</div>
</div>
<div class="portlet-wrapper" style="height:230px;">
<div class="portlet" style="height:188px;">
<div class="portlet-header">Portlet 1</div>
<div class="portlet-content">content</div>
</div>
</div>
<div class="portlet-wrapper" style="height:230px;">
<div class="portlet" style="height:188px;">
<div class="portlet-header">Portlet 3</div>
<div class="portlet-content">content</div>
</div>
</div>
<div class="portlet-wrapper" style="height:230px;">
<div class="portlet" style="height:188px;">
<div class="portlet-header">Portlet 2</div>
<div class="portlet-content">content</div>
</div>
</div>
<div class="portlet-wrapper" style="height:230px;">
<div class="portlet" style="height:188px;">
<div class="portlet-header">Portlet 9</div>
<div class="portlet-content">content</div>
</div>
</div>
<div class="portlet-wrapper" style="height:230px;">
<div class="portlet" style="height:188px;">
<div class="portlet-header">Portlet 8</div>
<div class="portlet-content">content</div>
</div>
</div>
</div>
</body>
Ok the following fixes your problems:
JSFiddle
When we drop the element on the sortable we have to update the dropped elements html and set it to what you want.
You don't have to add the droppable when you already linked the draggable to the sortable list.
$( function() {
$( ".portlet-container" ).sortable({
cursor : "move",
placeholder: "ui-state-highlight",
handle: ".portlet-header",
update: function(event, ui){
if($(ui.item).hasClass('portlet-wrapper')){
// we don't add one if we're sorting a pre-existing item
} else {
ui.item.html(portletClone(ui.item))
ui.item.removeClass('portlet-item portlet-name ui-draggable')
.addClass('portlet-wrapper');
}
}
});
$('.portlet-name').draggable( {
connectToSortable: ".portlet-container",
cursor: 'move',
revert: 'invalid',
opacity: 0.7,
helper: portletHelper
});
function portletHelper( event ) {
return portletClone(this);
}
function portletClone(item){
var portletWrapperStr = "<div class='portlet-wrapper portlet-clone' style='height:"+$(item).data("div-height")+"px; width:"+$(item).data "div-width")+"px;'/>";
var portletStr ="<div class='portlet' "+
" style='height:"+($(item).data("div-height")-40-2) +"px;'>"+
" <div class='portlet-header'>"+$(item).html()+"</div>"+
"</div>";
var portlet = $(portletStr);
var portletWrapper = $(portletWrapperStr).append(portlet);
return portletWrapper;
}
});
.portlet-container{
display: inline-block;
margin-top:10px;
margin-bottom:10px;
width: 960px;
}
.portlet-wrapper{
overflow:hidden;
}
.portlet{
border-radius: 4px;
border: 1px solid #bbb;
background-color: white;
padding: 10px 10px;
margin-top: 10px;
margin-bottom: 10px;
position:relative;
overflow:hidden;
}
.portlet-header{
height: 25px;
}
.portlet-content{
margin-bottom: 10px;
}
.portlet-options{
float: right;
}
.portlet-placeholder {
border: 1px dotted black;
margin: 0 1em 1em 0;
height: 95%;
}
.portlets-items{
width: 220px;
}
.portlet-item{
margin: 2px;
display: inline-block;
width: 220px;
height: 25px;
}
.portlet-name{
width: 140px;
font-family: Akkurat, Helvetica, Arial, sans-serif;
font-size: 12px;
color: #5c5e5f;
border-radius: 2px;
border: 1px solid #bbb;
padding: 2px;
display: inline-block;
}
.portlet-action{
width: 50px;
margin-left:5px;
color: #5c5e5f;
padding: 2px;
display: inline-block;
}
<title>Drag and Drop</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js"></script>
<script src="dragndrop.js"></script>
<body>
<div class="portlet-items">
<div class="portlet-item">
<div class="portlet-name" data-div-width="460" data-div-height="230" >
dragabble narrow 1
</div>
</div>
<div class="portlet-item">
<div class="portlet-name" data-div-width="460" data-div-height="230" >
dragabble narrow 2
</div>
</div>
<div class="portlet-item">
<div class="portlet-name" data-div-width="940" data-div-height="230">
dragabble wide 1
</div>
</div>
<div class="portlet-item">
<div class="portlet-name" data-div-width="940" data-div-height="230" >
dragabble wide 2
</div>
</div>
<div class="portlet-item">
<div class="portlet-name" data-div-width="940" data-div-height="230" >
dragabble wide 3
</div>
</div>
<div class="portlet-item">
<div class="portlet-name" data-div-width="940" data-div-height="230" >
dragabble wide 4
</div>
</div>
<div class="portlet-item">
<div class="portlet-name" data-div-width="940" data-div-height="230" >
dragabble wide 5
</div>
</div>
</div>
<div class="portlet-container">
<div class="portlet-wrapper" style="height:230px;">
<div class="portlet" style="height:188px;">
<div class="portlet-header">Portlet 6</div>
<div class="portlet-content">content</div>
</div>
</div>
<div class="portlet-wrapper" style="height:230px;">
<div class="portlet" style="height:188px;">
<div class="portlet-header">Portlet 5</div>
<div class="portlet-content">content</div>
</div>
</div>
<div class="portlet-wrapper" style="height:230px;">
<div class="portlet"
style="height:188px;">
<div class="portlet-header">Portlet 1</div>
<div class="portlet-content">content</div>
</div>
</div>
<div class="portlet-wrapper" style="height:230px;">
<div class="portlet"
style="height:188px;">
<div class="portlet-header">Portlet 3</div>
<div class="portlet-content">content</div>
</div>
</div>
<div class="portlet-wrapper" style="height:230px;">
<div class="portlet"
style="height:188px;">
<div class="portlet-header">Portlet 2</div>
<div class="portlet-content">content</div>
</div>
</div>
<div class="portlet-wrapper" style="height:230px;">
<div class="portlet"
style="height:188px;">
<div class="portlet-header">Portlet 9</div>
<div class="portlet-content">content</div>
</div>
</div>
<div class="portlet-wrapper" style="height:230px;">
<div class="portlet" style="height:188px;">
<div class="portlet-header">Portlet 8</div>
<div class="portlet-content">content</div>
</div>
</div>
</div>
</body>

Categories

Resources