I've tried to make a cube game and have a couple of issues. I can't seem to make the blocks in front cover up the ones behind. Is there a way I can inherit a z-index css property from the object the cube is dropped on?
The other problem is that I can't make the helper: clone, function to work in my situation. The clone doesn't snap to the grid and just returns to it's position.
css:
/*gameResources*/
.drop_zone {
height: 350px;
width: 650px;
background-image: url("/wordpress/wp-content/themes/tadek/img/one_game.svg");
margin: 0 auto;
position: relative;
}
.drop_zone * {
height: 55px;
width: 108px;
background-color: red;
position: absolute;
transform: translate(-50%, -50%);
}
.drop_block_1 {
top: 50px;
left: 325px;
}
.drop_block_2 {
top: 90px;
left: 255px;
}
.drop_block_3 {
top: 90px;
left: 395px;
}
.drop_block_4 {
top: 130px;
left: 185px;
}
.drop_block_5 {
top: 130px;
left: 325px;
}
.drop_block_6 {
top: 130px;
left: 465px;
}
.drop_block_7 {
top: 175px;
left: 115px;
}
.drop_block_8 {
top: 175px;
left: 255px;
}
.drop_block_9 {
top: 175px;
left: 395px;
}
.drop_block_10 {
top: 175px;
left: 535px;
}
.drop_block_11 {
top: 215px;
left: 185px;
}
.drop_block_12 {
top: 215px;
left: 325px;
}
.drop_block_13 {
top: 215px;
left: 465px;
}
.drop_block_14 {
top: 255px;
left: 255px;
}
.drop_block_15 {
top: 255px;
left: 395px;
}
.drop_block_16 {
top: 295px;
left: 325px;
}
#gameFull {
margin: 0 auto;
width: 650px;
padding: 10px 0 0 0;
}
.gameRow1 {
text-align: center;
margin: 50px;
}
.gameRow2 {
text-align: center;
margin: 50px;
}
.gameRow3 {
text-align: center;
margin:50px;
}
.gameCell {
display: inline-block;
width: 146px;
height: 170px;
margin: 0 -0.15%;
}
.singleCube {
cursor: move;
cursor: grab;
height: 170px;
width: 146px;
}
.cubic_one_game {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
max-width: 800px;
margin: 0 auto;
text-align: center;
font-size: 14pt;
letter-spacing: 2pt;
}
javascript, jQueryUI, javasript and html:
<script type="text/javascript">
$( init0 );
function init0() {
$( ".makeMeDroppable1" ).droppable({
accept: "#makeMeDraggable1, #makeMeDraggable2, #makeMeDraggable3",
drop: function(event, ui) {
var $this = $(this);
ui.draggable.position({
my: "center",
at: "center",
of: $this,
using: function(pos) {
$(this).animate(pos, 200, "linear");
}
});
}
});
}
$( init1 );
function init1() {
$('#makeMeDraggable1').draggable( {
containment: '#gameFull',
cursor: 'move',
revert: "invalid",
appendTo: ".makeMeDroppable1"
} );
}
$( init2 );
function init2() {
$('#makeMeDraggable2').draggable( {
containment: '#gameFull',
cursor: 'move',
revert: "invalid",
appendTo: ".makeMeDroppable1"
} );
}
$( init3 );
function init3() {
$('#makeMeDraggable3').draggable( {
containment: '#gameFull',
cursor: 'move',
revert: "invalid",
appendTo: ".makeMeDroppable1"
} );
}
</script>
<div id="gameFull">
<div class="drop_zone">
<div class="drop_block_1 makeMeDroppable1"></div>
<div class="drop_block_2 makeMeDroppable1"></div><div class="drop_block_3 makeMeDroppable1"></div>
<div class="drop_block_4 makeMeDroppable1"></div><div class="drop_block_5 makeMeDroppable1"></div><div class="drop_block_6 makeMeDroppable1"></div>
<div class="drop_block_7 makeMeDroppable1"></div><div class="drop_block_8 makeMeDroppable1"></div><div class="drop_block_9 makeMeDroppable1"></div><div class="drop_block_10 makeMeDroppable1"></div>
<div class="drop_block_11 makeMeDroppable1"></div><div class="drop_block_12 makeMeDroppable1"></div><div class="drop_block_13 makeMeDroppable1"></div>
<div class="drop_block_14 makeMeDroppable1"></div><div class="drop_block_15 makeMeDroppable1"></div>
<div class="drop_block_16 makeMeDroppable1"></div>
</div>
<div class="cubic_one_game">
<div>
<img id="makeMeDraggable1" class="singleCube" src="../wordpress/wp-content/themes/tadek/img/cube_one_game-01.svg">
<p>moduł kuchenny</p>
</div>
<div>
<img id="makeMeDraggable2" class="singleCube" src="../wordpress/wp-content/themes/tadek/img/cube_one_game-02.svg">
<p>moduł sypialniany</p>
</div>
<div>
<img id="makeMeDraggable3" class="singleCube" src="../wordpress/wp-content/themes/tadek/img/cube_one_game-03.svg">
<p>moduł łazienkowy</p>
</div>
</div>
</div>
game example:
http://cubichouse.eu/game/
For this, I would first advise separating your class and id attributes. This will make things more explicit in CSS and make your code easier to assign.
Here is what I suggest:
HTML
<div id="gameFull">
<div class="drop_zone">
<div class="drop_block" id="block_1" data-row="1"></div>
<div class="drop_block" id="block_2" data-row="2"></div>
<div class="drop_block" id="block_3" data-row="2"></div>
<div class="drop_block" id="block_4" data-row="3"></div>
<div class="drop_block" id="block_5" data-row="3"></div>
<div class="drop_block" id="block_6" data-row="3"></div>
<div class="drop_block" id="block_7" data-row="4"></div>
<div class="drop_block" id="block_8" data-row="4"></div>
<div class="drop_block" id="block_9" data-row="4"></div>
<div class="drop_block" id="block_10" data-row="4"></div>
<div class="drop_block" id="block_11" data-row="5"></div>
<div class="drop_block" id="block_12" data-row="5"></div>
<div class="drop_block" id="block_13" data-row="5"></div>
<div class="drop_block" id="block_14" data-row="6"></div>
<div class="drop_block" id="block_15" data-row="6"></div>
<div class="drop_block" id="block_16" data-row="7"></div>
</div>
<div class="cubic_one_game">
<div>
<img id="cube_1" class="singleCube" src="http://cubichouse.eu/wp-content/themes/cubic/img/cube_one_game-01.svg">
<p>moduł kuchenny</p>
</div>
<div>
<img id="cube_2" class="singleCube" src="http://cubichouse.eu/wp-content/themes/cubic/img/cube_one_game-02.svg">
<p>moduł sypialniany</p>
</div>
<div>
<img id="cube_3" class="singleCube" src="http://cubichouse.eu/wp-content/themes/cubic/img/cube_one_game-03.svg">
<p>moduł łazienkowy</p>
</div>
</div>
</div>
CSS
/*gameResources*/
.drop_zone {
height: 350px;
width: 650px;
background-image: url("http://cubichouse.eu/wp-content/themes/cubic/img/one_game.svg");
margin: 0 auto;
position: relative;
}
.drop_zone .drop_block {
height: 55px;
width: 108px;
// background-color: red;
position: absolute;
transform: translate(-50%, -50%);
z-index: 999;
}
#block_1 {
top: 50px;
left: 325px;
}
#block_2 {
top: 90px;
left: 255px;
}
#block_3 {
top: 90px;
left: 395px;
}
#block_4 {
top: 130px;
left: 185px;
}
#block_5 {
top: 130px;
left: 325px;
}
#block_6 {
top: 130px;
left: 465px;
}
#block_7 {
top: 175px;
left: 115px;
}
#block_8 {
top: 175px;
left: 255px;
}
#block_9 {
top: 175px;
left: 395px;
}
#block_10 {
top: 175px;
left: 535px;
}
#block_11 {
top: 215px;
left: 185px;
}
#block_12 {
top: 215px;
left: 325px;
}
#block_13 {
top: 215px;
left: 465px;
}
#block_14 {
top: 255px;
left: 255px;
}
#block_15 {
top: 255px;
left: 395px;
}
#block_16 {
top: 295px;
left: 325px;
}
#gameFull {
margin: 0 auto;
width: 650px;
padding: 10px 0 0 0;
}
.gameRow1 {
text-align: center;
margin: 50px;
}
.gameRow2 {
text-align: center;
margin: 50px;
}
.gameRow3 {
text-align: center;
margin: 50px;
}
.gameCell {
display: inline-block;
width: 146px;
height: 170px;
margin: 0 -0.15%;
}
.singleCube {
cursor: move;
cursor: grab;
height: 170px;
width: 146px;
z-index: 1000;
}
.cubic_one_game {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
max-width: 800px;
margin: 0 auto;
text-align: center;
font-size: 14pt;
letter-spacing: 2pt;
}
.cubic_one_game img {
height: 346px;
}
JavaScript
$(function() {
$(".drop_block").droppable({
accept: ".singleCube",
drop: function(e, ui) {
var $this = $(this);
ui.draggable.position({
my: "center",
at: "center",
of: $this,
using: function(pos) {
$(this).animate(pos, 200, "linear");
}
});
ui.draggable.css({
"z-index": 1000 + $(this).data("row")
});
}
});
$('.singleCube').draggable({
containment: '#gameFull',
cursor: 'move',
revert: "invalid"
});
});
It may seem like a bit of work at first, yet it's a really helpful practice for some cases. Now we can easily manage many items or individual items as needed.
For the perspective effect, the element that appears closest to the user should have the highest z-index. I added data-row attribute to each drop_box for easier management. When an item is dropped, it is then assigned a new z-index based on it's row. This ensures the proper perspective.
You may want to consider when dragging an item, to force it's z-index to an even higher value so that it will appear above the other elements. Moving an item from a "back" row forward, has the effect of passing behind "closer" elements. Simple to do in CSS:
.singleCube.ui-draggable-dragging {
z-index: 2000;
}
Working Example: https://jsfiddle.net/Twisty/4nj4fqkk/3/
Hope that helps.
Related
How can I make a loop inside currentSlide(1) so I want everytime .each work to add currentSlide(1) then currentSlide(2) then currentSlide(3) and so on.
<div class="approach" id="app">
<style>
#media (max-width: 600px){
.btn {
padding: 2px 2px 2px 2px !important; */
}}
#myBtnContainer{
display: flex;
}
/* Create three equal columns that floats next to each other */
.column {
float: left;
display: none;
margin: 5px;
border: 1px solid #ccc;
float: left;
width: 282px;
}
.column:hover{
border: 1px solid #777;
}
/* Clear floats after rows */
.row:after {
content: "";
display: table;
clear: both;
}
/* Content */
.content {
width: 100%;
height: 400px;
overflow: hidden;
/*display: flex;*/
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
}
.content img{
object-fit: cover;
height: auto;
width: 100%;
position: absolute;
}
/* The "show" class is added to the filtered elements */
.show {
display: block;
}
/* Style the buttons */
.btn {
border: none;
outline: none;
padding: 10px 10px;
background-color: #333333;
cursor: pointer;
color: white;
}
.btn:hover {
background-color: #ddd;
}
.btn.active {
background-color: #666;
color: white;
}
.modal {
display: none;
position: fixed;
z-index: 1;
padding-top: 100px;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: black;
}
/* Modal Content */
.modal-content {
position: relative;
background-color: #fefefe;
margin: auto;
padding: 0;
width: 90%;
max-width: 500px;
}
/* The Close Button */
.close {
color: white !important;
position: absolute;
top: 170px;
right: 25px;
font-size: 35px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #999;
text-decoration: none;
cursor: pointer;
}
.mySlides {
display: none;
}
.cursor {
cursor: pointer
}
/* Next & previous buttons */
.prev,
.next {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
padding: 16px;
margin-top: -50px;
color: white;
font-weight: bold;
font-size: 20px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
-webkit-user-select: none;
}
/* Position the "next button" to the right */
.next {
right: 0;
border-radius: 3px 0 0 3px;
}
/* On hover, add a black background color with a little bit see-through */
.prev:hover,
.next:hover {
background-color: rgba(0, 0, 0, 0.8);
}
/* Number text (1/3 etc) */
.numbertext {
color: #f2f2f2;
font-size: 12px;
padding: 8px 12px;
position: absolute;
top: 0;
}
img {
margin-bottom: -4px;
}
.caption-container {
text-align: center;
background-color: black;
padding: 2px 16px;
color: white;
}
.demo {
opacity: 0.6;
}
.active,
.demo:hover {
opacity: 1;
}
img.hover-shadow {
transition: 0.3s
}
.hover-shadow:hover {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19)
}
.mySlides img{
padding-top: 70px;
background-color: black;
}
div.desc {
padding: 15px;
text-align: center;
}
#media (max-width:600px) {
.close {
color: white !important;
position: absolute;
top: 120px;
right: 25px;
font-size: 45px;
font-weight: bold;
z-index: 1000;
}
.column {
float: left;
display: none;
margin: 5px;
border: 1px solid #ccc;
float: left;
width: 83px;
}
}
#media (max-width: 320px){
.column {
float: left;
display: none;
margin: 5px;
border: 1px solid #ccc;
float: left;
width: 70px;
}
}
#media only screen and (min-width: 812px) {
.column {
float: left;
display: none;
margin: 5px;
border: 1px solid #ccc;
float: left;
width: 90px;
} }
</style>
<body>
<!-- MAIN (Center website) -->
<div class="container">
<h1>GALLERY</h1>
<div id="myBtnContainer">
<button class="btn" onclick="filterSelection('conversion')"> Conversion</button>
<button class="btn" onclick="filterSelection('fixed-hybrid')"> Fixed Hybrid</button>
<button class="btn" onclick="filterSelection('removal-bar-over-denture')"> Removable Bar Over Denture</button>
<button class="btn" onclick="filterSelection('surgical-guides')"> Surgical Guides</button>
<button class="btn active" onclick="filterSelection('all')"> Show all</button>
</div>
<br>
<!-- Portfolio Gallery Grid -->
<div class="row">
<% #galleries.each do |g| %>
<% [g.image1, g.image2, g.image3, g.image4, g.image5].compact.each_with_index do |image, index| %>
<div class="column <%= g.product_name %>">
<div class="content">
<%= image_tag image.url, style: "width:100%", onclick: "openModal();currentSlide(#{index + 1})" ,class: "hover-shadow cursor"%>
</div>
</div>
<% end %>
<% end %>
<!-- END GRID -->
</div>
<!-- END MAIN -->
</div>
<div id="myModal" class="modal">
<span class="close cursor" onclick="closeModal()">×</span>
<div class="modal-content">
<% #galleries.each do |g| %>
<% [g.image1, g.image2, g.image3, g.image4, g.image5].compact.each_with_index do |image, index| %>
<div class="mySlides">
<div class="numbertext">1 / 4</div>
<%= image_tag image.url, style: "width:100%" %>
</div>
<% end %>
<% end %>
<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>
<div class="caption-container">
<p id="caption">hr</p>
</div>
</div>
<script>
filterSelection("all")
function filterSelection(c) {
var x, i;
x = document.getElementsByClassName("column");
if (c == "all") c = "";
for (i = 0; i < x.length; i++) {
w3RemoveClass(x[i], "show");
if (x[i].className.indexOf(c) > -1) w3AddClass(x[i], "show");
}
}
function w3AddClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
if (arr1.indexOf(arr2[i]) == -1) {element.className += " " + arr2[i];}
}
}
function w3RemoveClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
while (arr1.indexOf(arr2[i]) > -1) {
arr1.splice(arr1.indexOf(arr2[i]), 1);
}
}
element.className = arr1.join(" ");
}
// Add active class to the current button (highlight it)
var btnContainer = document.getElementById("myBtnContainer");
var btns = btnContainer.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function(){
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
</script>
</div>
<script>
function openModal() {
document.getElementById('myModal').style.display = "block";
}
function closeModal() {
document.getElementById('myModal').style.display = "none";
}
var slideIndex = 1;
showSlides(slideIndex);
function plusSlides(n) {
showSlides(slideIndex += n);
}
function currentSlide(n) {
showSlides(slideIndex = n);
}
function showSlides(n) {
var i;
var slides = document.getElementsByClassName("mySlides");
var dots = document.getElementsByClassName("demo");
var captionText = document.getElementById("caption");
if (n > slides.length) {slideIndex = 1}
if (n < 1) {slideIndex = slides.length}
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active", "");
}
slides[slideIndex-1].style.display = "block";
dots[slideIndex-1].className += " active";
captionText.innerHTML = dots[slideIndex-1].alt;
}
</script>
Looks like you just need an index to interpolate into currentSlide.
Start by removing duplication and instead of checking every related image with <% if g.image1.present? %> put them into an array and iterate over it with:
<% [g.image1, g.image2, g.image3].compact.each_with_index do |image, index|
compact will make sure that only present images are there, so you don't have to use if present any more.
And then use onclick: "openModal();currentSlide(#{index + 1})" (as index starts at 0, and you seem to need it to start from 1)
Update:
<% #galleries.each do |g| %>
<% [g.image1, g.image2, g.image3, g.image4, g.image5].compact.each_with_index do |image, index| %>
<div class="column <%= g.product_name %>">
<div class="content">
<%= image_tag image.url,
alt: "conversion",
style: "width:100%",
onclick: "openModal();currentSlide(#{index + 1})",
class: "hover-shadow cursor" %>
</div>
</div>
I am working on the below demo. How can I detect when .draggable hits top and bottom of its containment?
$(function(){
var draggableRight;
var draggableWidth = $('.draggable').height();
var parentWidth = $('#parent').height();
$('.draggable').draggable({
containment: 'parent',
axis: "y",
drag: function(e, ui){
// ==> if .draggable hits top of parent change it's background red
// $(document).trigger("mouseup");
// $('.draggable').css({ background: 'red' });
// ==> if .draggable hits bottom of parent change it's background blue
// $(document).trigger("mouseup");
// $('.draggable').css({ background: 'blue' });
}
});
});
#parent {
background: khaki;
width: 400px;
height: 200px;
position: relative;
margin:20px;
padding:0px;
}
.draggable {
background: #fff;
width: 400px;
height: 50px;
margin:0px;
background: red;
}
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="parent">
<div class="draggable"></div>
</div>
You will want to use the position or offset from the UI object.
Consider the following:
$(function() {
var draggableRight;
var draggableWidth = $('.draggable').height();
var parentWidth = $('#parent').height();
$('.draggable').draggable({
containment: 'parent',
axis: "y",
drag: function(e, ui) {
var p = {
top: ui.offset.top - $("#parent").offset().top,
bottom: (ui.offset.top - $("#parent").offset().top) + $(this).height()
};
$("#log").html(p.top + ", " + p.bottom);
if (p.top == 0) {
console.log("Hit Top");
}
if (p.bottom == $("#parent").height()) {
console.log("Hit Bottom");
}
}
});
});
#parent {
background: khaki;
width: 400px;
height: 200px;
position: relative;
margin: 20px;
padding: 0px;
}
.draggable {
background: #fff;
width: 400px;
height: 50px;
margin: 0px;
background: red;
}
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="parent">
<div class="draggable"></div>
</div>
<div id="log"></div>
I have this message thread component that has a header, content and a textarea and everytime. The issue here is in mobile views, when I want to type a message the keyboard on IOS (Iphones) pushes the divs up so the header would be hidden, I don't want this behavior, for Android it doesn't behave like this. This app is using React and scss and the code is this:
<div className="message-thread-wrapper d-flex flex-column">
<div className="messages-header d-flex flex-row justify-content-between align-items-center">
<Icon
className="back-btn d-lg-none"
icon="chevron-left"
onClick={(e) => {
e.stopPropagation();
actions.closeMessage();
}}
/>
<h5 className="messages-title text-truncate">
{participant.firstname && participant.lastname ? `${participant.firstname} ${participant.lastname}` : participant.name}
</h5>
<div className="messages-header-right d-flex flex-row align-items-center">
<Icon
className="settings-btn"
icon="settings"
onClick={(e) => {
e.stopPropagation();
this.toggleDeleteMenu();
}}
/>
}
<Icon
className="close-btn-cross d-none d-lg-block"
icon="cross"
onClick={(e) => {
e.stopPropagation();
this.setState(
{isMinimized: false},
actions.closeMessage
);
}}
/>
</div>
</div>
{showDeleteMenu &&
<DeleteMenu onClick={this.archiveMessage} onClickOutside={this.toggleDeleteMenu}/>
}
{
this.renderMessages()
}
<div
className="bottom-actions d-flex flex-row flex-nowrap justify-content-between align-items-center">
<TextArea
ref={ref => this.messageInput = ref}
className="input blue d-block"
name="msgText"
placeholder="Type your message..."
.
.
.
.
autoFocus
/>
<Button
className={`send-btn circle ${IS_SAFARI ? 'safari-fix-button' : ''}`}
icon="paper-plane"
onClick={this.onSendMessage}
/>
</div>
}
</div>
and the scss file:
.message-thread-wrapper {
width: 100%;
height: 100%;
position: absolute;
top: 0px;
left: 0;
z-index: 950;
.messages-header {
padding: 19px 16px 14px 16px;
width: 100%;
flex-basis: 57px;
color: white;
pointer-events: none;
position:sticky;
.back-btn {
pointer-events: auto;
}
.close-btn-cross {
width: 18px;
height: 18px;
pointer-events: auto;
}
.settings-btn {
width: 25px;
height: 26px;
pointer-events: auto;
}
}
.delete-menu {
border-radius: 2px;
background-color: white;
position: absolute;
top: 53px;
right: 0px;
z-index: 1;
.menu-arrow {
width: 15px;
height: 15px;
position: absolute;
top: 0;
right: 0;
background: white;
border-right: none;
border-bottom: none;
}
a {
padding: 18px;
font-size: 16px;
line-height: 1.5;
text-decoration: none;
z-index: 1;
cursor: pointer;
}
}
.messages-content {
height: 100%;
padding: 16px;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
.dateline {
margin: 28px 0 11px 0;
line-height: 1.33;
text-align: center;
}
}
.bottom-actions {
bottom: 0;
width: 100%;
max-height: 130px;
min-height: 70px;
overflow-y: hidden;
padding: 0 0 0 24px;
background-color: white;
box-shadow: 0 -1px 3px 0 #d9dbdc;
.form-group-wrapper {
padding-top: 10px;
width: 100%;
align-self: stretch;
overflow: auto;
&.text-area-wrapper {
padding-right: 71px;
textarea {
min-height: 48px;
}
.form-bar {
display: none;
}
}
}
.button.circle {
width: 34px;
height: 34px;
padding: 9px 12px 9px 8px;
position: fixed;
right: 26px;
&.safari-fix-button {
bottom: 22px;
}
}
}
}
Note I deleted the properties that are not important for this question so it won't be too long.
This is how it currently behaves:
Iphone:
Android - Pixel 2XL:
I would appreciate if Any could help me. Thank you in advance!
I wrote some kind of that: http://jsfiddle.net/py3DE/203/ but when element is dragged into proper container, we can override it by dragging other div into its area. Could you tel me how i can block dragged elements, and if someone will try to override any element, div returns back into area with undragged divs?
if (!ui.draggable.closest('.empty').length) item = item.draggable()'
There is a simple way to do this. Basically, we'll remove the class empty and use the disable method.
Working Example: http://jsfiddle.net/Twisty/5rdxmp4p/
Minor CSS Change
.filled .item .closer {
display: block;
}
Drop Function
drop: function(ev, ui) {
if ($(this).hasClass("empty")) {
$(this).removeClass("empty").addClass("filled");
$(this).droppable("disable");
} else {
return false;
}
var item = ui.draggable;
if (!ui.draggable.closest('.empty').length) item = item.draggable(); // if item was dragged from the source list - clone it
this.innerHTML = ''; // clean the placeholder
item.css({
top: 0,
left: 0
}).appendTo(this); // append item to placeholder
}
Swapping the class allows the X button to appear. We then run the disable method to ensure that this specific item will no longer accept a dragged item. If the user drags an item to this spot, it is then reverted.
Update
Using Sortable: http://jsfiddle.net/Twisty/5rdxmp4p/2/
HTML
<div id="dragItems" class="source">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
</div>
<div id="sortItems" class="target">
</div>
CSS
body {
background: #fff;
}
.source,
.target {
margin: 20px;
min-height: 190px;
width: 400px;
border: 1px solid green;
}
.target {
border: 1px solid blue;
}
.item {
height: 20px;
margin: 5px;
padding: 5px;
border: 1px solid gray;
background-color: #cd8;
position: relative;
}
.closer {
float: right;
width: 20px;
height: 20px;
border: 0;
background-color: transparent;
}
.closer:hover {
background-color: transparent;
border: 0;
}
.empty {
height: 30px;
margin: 5px;
background: #eee;
border: 1px dashed #999;
}
.highlight {
border: 1px solid red;
background: #fff;
}
.highlight .item {
opacity: 0.3;
}
.ui-draggable-dragging {
z-index: 99;
opacity: 1 !important;
width: 378px;
}
jQuery
$(function() {
$("#sortItems").sortable({
axis: "y",
items: "> div",
placeholder: "empty",
dropOnEmpty: true,
stop: function(e, ui) {
var $it = ui.item;
if ($it.find(".closer").length == 0) {
var closeBtn = $("<span>", {
class: "closer"
});
$it.append(closeBtn);
closeBtn.button({
icon: "ui-icon-close",
label: "Close",
showLabel: false
}).click(function(ev) {
console.log("[INFO]: Closing ", $it);
$it.fadeTo(200, 0.0, function() {
$it.remove();
$("#sortItems").sortable("refresh");
});
});
}
}
});
$("#dragItems .item").draggable({
connectToSortable: "#sortItems",
revert: "invalid"
});
$("#sortItems").disableSelection();
});
Seems like I can choose only 2. :)
Here's where I'm at. I can sort the droppable divs and I can drag the ui-draggable, but I cannot drop ui-draggable into the ui-widget-header divs. :/
HTML:
<div class="large-9 small-9 columns">
<div id="paginationPageDisplay" class="dropme paginationContainer ui-sortable">
<div class="droppable ui-widget-header">
<div class="droppable ui-widget-header">
</div>
</div>
<div class="large-3 small-3 columns">
<div id="paginationAdDisplay" class="paginationContainer">
<div class="adThing ui-draggable">1/4</div>
<div class="adThing ui-draggable">1/2</div>
<div class="adThing ui-draggable">Full Page</div>
</div>
</div>
CSS:
.paginationContainer {
height: 1500px;
margin-right: 1px;
border: 1px solid #CCCCCC;
}
.adThing {
display: inline-block;
width: auto;
height: auto;
padding: 8px 15px;
border: 1px solid #ccc;
text-align: center;
background: #eee;
}
.dropme {
display: inline-block;
width: auto;
height: auto;
overflow: hidden;
margin-top: 20px;
}
.droppable {
height: 120px;
width: 90px;
padding: 2px;
margin: 10px 3px;
background: #F9F9F9;
border: 1px solid #CCCCCC;
float: right;
}
JS:
$('.adThing').draggable({
cursor: 'pointer',
connectWith: '.dropme',
helper: 'clone',
opacity: 0.5,
zIndex: 10
});
$('.dropme').sortable({
connectWith: '.dropme',
cursor: 'pointer'
});
$('.droppable').droppable({
drop: function( event, ui ) {
$( this )
.addClass( "ui-state-highlight" )
.find( "p" )
.html( "Dropped!" );
}
});
$("#paginationLoadButton").click(function() {
var pageCount, i, $pageDisplay = $("#paginationPageDisplay"), pageWidget;
$pageDisplay.html('');
pageCount = $("#paginationPageCount").val();
for (i=1; i<=pageCount; i++) {
pageWidget = '<div class="droppable ui-widget-header">' + i + '<p></p></div>';
$pageDisplay.html($pageDisplay.html() + pageWidget);
}
});
The problem was that I was binding droppable on document ready but those elements are generated by the button click. I moved the droppable bind into the button click event and it's resolved.
$("#paginationLoadButton").click(function() {
var pageCount, i, $pageDisplay = $("#paginationPageDisplay"), pageWidget;
$pageDisplay.html('');
pageCount = $("#paginationPageCount").val();
for (i=1; i<=pageCount; i++) {
pageWidget = '<div class="droppable ui-widget-header">' + i + '<p></p></div>';
$pageDisplay.html($pageDisplay.html() + pageWidget);
}
$('.droppable').droppable({
drop: function( event, ui ) {
$( this )
.addClass( "ui-state-highlight" )
.find( "p" )
.html( "Dropped!" );
}
});
});