I am using javascript drag and drop API to recreate a similar board from this website: http://en.battleship-game.org/
The below code shows how I tried implementing it
const ship = document.querySelector('.ship');
const cells = document.querySelectorAll('.cell');
ship.addEventListener("dragstart",(e)=>{
e.dataTransfer.setData('text/plain',e.target.id);
});
cells.forEach((cell)=>{
cell.addEventListener('dragenter',dragEnter);
cell.addEventListener('dragover',dragOver);
cell.addEventListener('dragleave',dragLeave);
cell.addEventListener('drop',drop);
});
function dragEnter(e){
e.preventDefault();
e.target.classList.add('drag-over');
console.log('drag enter');
}
function dragOver(e) {
e.preventDefault();
e.target.classList.add('drag-over');
}
function dragLeave(e) {
e.target.classList.remove('drag-over');
}
function drop(e) {
e.target.classList.remove('drag-over');
// get the draggable element
const id = e.dataTransfer.getData('text/plain');
const draggable = document.getElementById(id);
// add it to the drop target
e.target.appendChild(draggable);
}
.row{
display: flex;
}
.cell{
background-color: lightblue;
width: 32px;
height: 32px;
border: 1px solid black;
user-select: none;
position: relative;
}
.ship{
z-index: 2;
display: flex;
position: absolute;
top: 0;
left: 0;
cursor: move;
}
.ship>div{
background-color: rgb(255, 221, 226);
border: 1px solid black;
width: 32px;
height: 32px;
}
.drag-over {
border: dashed 3px red;
}
<div class="row">
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
</div>
<div class="row">
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell">
<div class="ship" draggable="true" id="ship">
<div> </div>
<div> </div>
<div> </div>
</div>
</div>
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
</div>
<div class="row">
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
<div class="cell"> </div>
</div>
When I drag and drop the 3rd pink box I want it to not drop with respect to the first pink box. How can this be done?
Dashed red border shows wrt to which box the pink div will be placed
Related
I am trying to make my own custom drag and drop with html and Javascript drag and drop I have prepared a snippet:
/* draggable element */
var tempParentContainer = '';
var placeholder = document.createElement('div');
placeholder.className = 'drag-state-placeholder';
function enableDragDrop(containerClass, draggableClass) {
let tempElem = document.querySelectorAll(draggableClass);
tempElem.forEach(item => {
item.addEventListener('dragstart', dragStart);
});
let tempContainer = document.querySelectorAll(containerClass);
tempContainer.forEach(box => {
box.addEventListener('dragenter', dragEnter)
box.addEventListener('dragover', dragOver);
box.addEventListener('dragleave', dragLeave);
box.addEventListener('drop', drop);
});
}
function dragStart(e) {
tempParentContainer = e.target.parentNode;
e.dataTransfer.setData('text/plain', e.target.id);
setTimeout(() => {
e.target.classList.add('hide');
placeholder.style.height = e.target.clientHeight + 'px';
tempParentContainer.appendChild(placeholder);
}, 0);
dragSrcEl = this;
e.dataTransfer.effectAllowed = 'move';
}
function dragEnter(e) {
e.preventDefault();
}
function dragOver(e) {
e.preventDefault();
e.currentTarget.appendChild(placeholder);
}
function dragLeave(e) {
e.preventDefault();
}
function drop(e) {
placeholder.remove();
// get the draggable element
const id = e.dataTransfer.getData('text/plain');
const draggable = document.getElementById(id);
// add it to the drop target
e.currentTarget.appendChild(draggable);
// display the draggable element
draggable.classList.remove('hide');
}
.view_container {
width: 100%;
}
.data-container {
transform: scale(1);
width: fit-content;
background: rgb(255, 255, 255);
display: flex;
flex: 0 0 100%;
height: 100%;
min-width: 1px;
overflow: auto;
position: relative;
margin: 0 10px;
transform-origin: left top;
transition: 0.3s;
}
.table-main {
position: relative;
border-collapse: separate;
display: table;
white-space: normal;
width: 100%;
}
.table-head {
display: table-header-group;
vertical-align: middle;
}
.table-tr {
display: table-row;
vertical-align: inherit;
height: 100%;
}
.table-body {
display: table-row-group;
vertical-align: middle;
}
.table-th {
min-width: 330px;
background-color: #607d8b;
color: #fff;
border-right: 2px solid rgb(255, 255, 255);
border-bottom: 0px solid rgb(255, 255, 255);
z-index: 3;
padding: 0;
height: 30px;
line-height: 30px;
vertical-align: top;
display: table-cell;
padding: 10px;
}
.table-td {
display: table-cell;
vertical-align: top;
border-bottom: 4px solid rgb(255, 255, 255);
border-right: 4px solid rgb(255, 255, 255);
padding: 10px;
min-height: 153px;
background-color: rgb(243, 243, 243);
min-width: 301px;
max-width: 301px;
}
.drag-state-placeholder {
background-color: #fbf9ed;
border: 1px dashed rgb(177, 147, 59) !important;
}
.resourceDropLi {
border: 1px solid #e7e7e7;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<body>
<div class="view_container">
<div class="data-container" id="board-container">
<div class="table-main h-100">
<div class="table-head">
<div class="table-tr" id="laneContainer">
<div class="table-th">
<label>first</label>
</div>
<div class="table-th">
<label>Second</label>
</div>
<div class="table-th">
<label>third</label>
</div>
<div class="table-th">
<label>fourth</label>
</div>
<div class="table-th">
<label>fifth</label>
</div>
<div class="table-th">
<label>sixth</label>
</div>
<div class="table-th">
<label>seventh</label>
</div>
<div class="table-th">
<label>eirght</label>
</div>
</div>
</div>
<div class="table-body" id="storyContainer">
<div class="table-td ui-sortable">
<div class="resourceDragDrop" draggable="true">
<p>
item f1
</p>
</div>
<div class="resourceDragDrop" draggable="true">
<p>
item f2
</p>
</div>
<div class="resourceDragDrop" draggable="true">
<p>
item f3
</p>
</div>
<div class="resourceDragDrop" draggable="true">
<p>
item f4
</p>
</div>
</div>
<div class="table-td ui-sortable">
<div class="resourceDragDrop" draggable="true">
<p>
item s1
</p>
</div>
<div class="resourceDragDrop" draggable="true">
<p>
item s2
</p>
</div>
<div class="resourceDragDrop" draggable="true">
<p>
item s3
</p>
</div>
</div>
<div class="table-td ui-sortable">
<div class="resourceDragDrop" draggable="true">
<p>
item t1
</p>
</div>
<div class="resourceDragDrop" draggable="true">
<p>
item t2
</p>
</div>
</div>
<div class="table-td ui-sortable">
<div class="resourceDragDrop" draggable="true">
<p>
item f1
</p>
</div>
</div>
<div class="table-td ui-sortable">
<div class="resourceDragDrop" draggable="true">
<p>
item fi1
</p>
</div>
<div class="resourceDragDrop" draggable="true">
<p>
item fi2
</p>
</div>
<div class="resourceDragDrop" draggable="true">
<p>
item fi3
</p>
</div>
<div class="resourceDragDrop" draggable="true">
<p>
item fi4
</p>
</div>
<div class="resourceDragDrop" draggable="true">
<p>
item fi5
</p>
</div>
</div>
<div class="table-td ui-sortable">
<div class="resourceDragDrop" draggable="true">
<p>
item s1
</p>
</div>
</div>
<div class="table-td ui-sortable">
<div class="resourceDragDrop" draggable="true">
<p>
item sev1
</p>
</div>
</div>
<div class="table-td ui-sortable">
<div class="resourceDragDrop" draggable="true">
<p>
item e1
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<script type="text/javascript">
$(document).ready(function() {
enableDragDrop('.table-td', '.resourceDragDrop');
});
</script>
</html>
I want drag an item from one container to another and in the same container as well like jQuery sortable plugin.
when I drag an item from one container to another is working fine but I am able to drop it at the last position of the container.
Here I am facing an issue while I am dragging an item I want to place it any where I want, like between elements or the first position or between other elements.
I don't know how to make it work anyone please help me
Thanks
I think the problem is that you only have 1 element with the ability to accept a drop: the container. That element cannot "tell" any more granular position than you've already done.
You should enable the singular items to handle dragover and/or drop, and create a rule, like: if the element is dropped on another element, then it goes before that element; if it's dropped on the container, then it goes at the end. This rule handles all positions in your list.
function dragStart({
originalEvent: e
}) {
e.dataTransfer.setData("text/plain", e.target.id)
e.dataTransfer.effectAllowed = 'move'
}
jQuery(document).ready(function($) {
$('.draggable').on('dragstart', dragStart);
$('.droppable').on('dragover', function(e) {
e.preventDefault()
$(this).css('background', 'rgba(0, 0, 0, 0.25)')
})
$('.droppable').on('dragenter', function(e) {
e.preventDefault()
$(this).css('background', 'rgba(0, 0, 0, 0.25)')
})
$('.droppable').on('dragleave', function(e) {
e.preventDefault()
$(this).css('background', 'white')
})
$('.droppable').on('drop', function(e) {
// stop propagation so you don't trigger drop more than once
// if the drop zone is inside another drop zone
e.stopPropagation()
const draggedId = e.originalEvent.dataTransfer.getData("text")
// here's the rule I wrote: if it's a column, then
// the dragged item is appended, if it's not a column
// then the dragged item is inserted before
// the item it's dropped on
if (!$(e.target).hasClass('column')) {
$(e.target).before($(`#${ draggedId }`))
$(this).parent().css('background', 'white')
} else {
$(e.target).append($(`#${ draggedId }`))
}
$(this).css('background', 'white')
})
});
#container {
width: 100%;
height: 100%;
display: flex;
justify-content: space-around;
background: white;
}
.column {
border: 1px solid black;
display: flex;
flex-direction: column;
padding: 8px 16px;
}
.draggable {
border: 1px solid black;
padding: 8px 16px;
display: block;
background: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
<div class="column droppable">
<div id="left-1" class="draggable droppable" draggable="true">
left 1
</div>
<div id="left-2" class="draggable droppable" draggable="true">
left 2
</div>
</div>
<div class="column droppable">
<div id="center-1" class="draggable droppable" draggable="true">
center 1
</div>
<div id="center-2" class="draggable droppable" draggable="true">
center 2
</div>
</div>
<div class="column droppable">
<div id="right-1" class="draggable droppable" draggable="true">
right 1
</div>
<div id="right-2" class="draggable droppable" draggable="true">
right 2
</div>
</div>
</div>
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>
As you can see I have a number of dots lined vertically! On scrolling down it works, as one scrolls the next dot gets a class thats chnages the style of the ball, I want the exact same to happen when i scroll up but it is not working! Please any input is appreciated!
Here is a code pen for your reference!
below the html, css and javascript:
var activeMilestone = function() {
var milestoneBalls = $('.dot');
milestoneBalls[0].classList.add("active");
window.onscroll = function() {
milestoneBalls.each(function(i, v) {
var thisBall = $(this);
var nextBall = milestoneBalls[i + 1];
var prevBall = milestoneBalls[i - 1];
var thisPositionTop = thisBall.offset().top + ($(this).parent().height() / 3);
var winScroll = window.scrollY;
if (thisPositionTop <= winScroll) {
nextBall.classList.add("active");
thisBall.addClass("inactive");
}
if (thisPositionTop >= winScroll) {
//this.classList.add("inactive_ball");
}
});
}
}
$(document).ready(activeMilestone);
.wrapper {
height: 1000px;
background-color: wheat;
}
.info_wrapper {
margin-top: 70px;
}
.container {
height: 50%;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
.dot {
width: 30px;
height: 30px;
border-radius: 20px;
background-color: maroon;
border: solid 4px green;
}
.active {
border: solid 4px yellow;
background-color: red;
}
.inactive {
background-color: maroon;
border: solid 4px green;
}
.text {}
.header {
width: 100%;
height: 50px;
background-color: lightblue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div class="header"></div>
<div class="container">
<div class="info_wrapper">
<div class="text"></div>
<div class="dot "></div>
</div>
<div class="info_wrapper">
<div class="text"></div>
<div class="dot "></div>
</div>
<div class="info_wrapper">
<div class="text"></div>
<div class="dot "></div>
</div>
<div class="info_wrapper">
<div class="text"></div>
<div class="dot"></div>
</div>
<div class="info_wrapper">
<div class="text"></div>
<div class="dot"></div>
</div>
<div class="info_wrapper">
<div class="text"></div>
<div class="dot"></div>
</div>
<div class="info_wrapper">
<div class="text"></div>
<div class="dot"></div>
</div>
<div class="info_wrapper">
<div class="text"></div>
<div class="dot"></div>
</div>
</div>
</div>
So this logic performs the same that you were doing already. With the added logic of, if the element should not advance, and we are not the first element, we check to see if the previous ball should be active. And if so, we make it active.
var activeMilestone = function() {
var milestoneBalls = $('.dot');
milestoneBalls.eq(0).addClass('active');
window.addEventListener('scroll', function() {
var activeBall = milestoneBalls.filter('.active');
var activeBallIndex = milestoneBalls.index( activeBall );
var activeBallPositionTop = activeBall.offset().top + (activeBall.parent().height() / 3);
if (activeBallPositionTop <= window.scrollY) {
activeBall.removeClass('active');
milestoneBalls.eq( activeBallIndex + 1).addClass('active');
} else if ( activeBallIndex ) {
var previousBall = milestoneBalls.eq( activeBallIndex - 1 );
var previousBallPositionTop = previousBall.offset().top + (previousBall.parent().height() / 3);
if (previousBallPositionTop > window.scrollY) {
activeBall.removeClass('active');
previousBall.addClass('active');
}
}
});
}
$(document).ready(activeMilestone);
.wrapper {
height: 1000px;
background-color: wheat;
}
.info_wrapper {
margin-top: 70px;
}
.container {
height: 50%;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
.dot {
width: 30px;
height: 30px;
border-radius: 20px;
background-color: maroon;
border: solid 4px green;
}
.active {
border: solid 4px yellow;
background-color: red;
}
.inactive {
background-color: maroon;
border: solid 4px green;
}
.text {}
.header {
width: 100%;
height: 50px;
background-color: lightblue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div class="header"></div>
<div class="container">
<div class="info_wrapper">
<div class="text"></div>
<div class="dot "></div>
</div>
<div class="info_wrapper">
<div class="text"></div>
<div class="dot "></div>
</div>
<div class="info_wrapper">
<div class="text"></div>
<div class="dot "></div>
</div>
<div class="info_wrapper">
<div class="text"></div>
<div class="dot"></div>
</div>
<div class="info_wrapper">
<div class="text"></div>
<div class="dot"></div>
</div>
<div class="info_wrapper">
<div class="text"></div>
<div class="dot"></div>
</div>
<div class="info_wrapper">
<div class="text"></div>
<div class="dot"></div>
</div>
<div class="info_wrapper">
<div class="text"></div>
<div class="dot"></div>
</div>
</div>
</div>
You can use on wheel from jQuery.
$(window).on('wheel',function(e) {
var mov = e.originalEvent.deltaY;
if(mov > 0) {
alert("up");
}else {
alert("down");
}
});
This will sort out your problem regarding detection of scrolling direction.
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>
When I click on one of the smaller divs on the left (inside of the div with the class "smallitems", I want for the div on the right (with the class "items") to auto-scroll to the appropriate larger div.
HTML:
<div class="smallitems">
<div class="col">1</div>
<div class="col"> 2 </div>
<div class="col"> 3</div>
<div class="col">4</div>
<div class="col"> 5 </div>
<div class="col">6 </div>
<div class="col"> 7</div>
<div class="col">8</div>
</div>
<div class="items">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">5</div>
</div>
JavaScript (with JQuery):
$('.smallitems .col').on("click", function(){
//how use scroll items show
});
Example:
This is before I click on a div in the left div ("smallitems").
I've now clicked on the number 5 (<div class="col">5</div>) in the left div. As you can see the right div has scrolled to the 5th div (<div class="item">5</div>).
Similar to the above, I've clicked on the number 4, and subsequently have had the right div auto-scroll to the 4th div.
see jfiddle http://jsfiddle.net/h7bLK/
This can be done with anchors. If you replace your div.cols with anchor tags and add an ID to your div.items like this:
<div class="smallitems">
<a class="col" href="#item1">1</a>
<a class="col" href="#item2">2</a>
. . .
</div>
<div class="items">
<div class="item" id="item1">1</div>
<div class="item" id="item2">2</div>
. . .
</div>
Fiddle link
BONUS: You'll be able to link externally to the correct item.
CONS: If the content is smaller than the frame it is rendered in, the whole frame will scroll.
According to requirement, no-need to use javascript or jquery. Its done only using css.
<div class="main-container">
<div class="smallitems">
<div class="col">1</div>
<div class="col"> 2 </div>
<div class="col last-child">3</div>
<div class="col">4</div>
<div class="col">5 </div>
<div class="col last-child">6 </div>
<div class="col"> 7</div>
<div class="col">8</div>
</div>
<div class="items">
<div class="scroll">
<div class="item" id="one">1</div>
<div class="item" id="two">2</div>
<div class="item" id="three">3</div>
<div class="item" id="four">4</div>
<div class="item" id="five">5</div>
<div class="item" id="six">6</div>
<div class="item" id="seven">7</div>
<div class="item" id="eight">8</div>
</div>
</div>
</div>
**Css** :
.main-container{
margin: 20px auto;
width:960px;
overflow: hidden;
border: 1px solid #bababa;
padding: 5px;
}
.smallitems{
overflow: hidden;
float: left;
width:330px;
border: 1px solid #bababa;
display: table;
padding: 10px;
}
.col a{
display: block;
padding: 41px 0;
text-decoration: none;
}
.col{
float:left;
display: table-cell;
vertical-align: middle;
text-align: center;
font-size: 14px;
font-weight: 700;
cursor: pointer;
border: 1px solid #bababa;
height: 100px;
width: 100px;
margin: 0 10px 10px 0;
}
.items{
float: right;
width:580px;
border: 1px solid #bababa;
overflow-y: hidden;
white-space: nowrap;
padding: 10px;
}
.col:nth-child(3),.last-child{
margin-right: 0;
}
.item{
display: inline-block;
text-align: center;
position:relative;
font-size: 14px;
font-weight: 700;
border: 1px solid #bababa;
height: 440px;
width: 180px;
margin: 0 10px 10px 0;
}
$('.smallitems .col').on("click", function(){
var index = $(this).index();
var items = $('.items');
var item = items.children().eq(index);
items.scrollLeft((item.width() - 50) * index);
});
When you add a new div to the items play around with the value of 50.
<div class="container">
<div class="smallitems">
<div class="col">1</div>
<div class="col"> 2 </div>
<div class="col"> 3</div>
<div class="col">4</div>
<div class="col"> 5 </div>
<div class="col">6 </div>
<div class="col"> 7</div>
<div class="col">8</div>
</div>
<div class="items" id="maindiv"> // set id
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">5</div>
</div>
</div>
$('.smallitems').on("click", function(e){
// get click element text and calculate scrollLeft
var scrollLeft = (parseInt($(e.target).text())-1) * 200;
// use jquery animation function
$('#maindiv').animate({scrollLeft :scrollLeft},1100)
});