Strange variable behavior in Draggabilly jQuery plugin - javascript

Ok guys, i have no idea what's going on here. Im using this plugin (http://draggabilly.desandro.com/) and making a drag & drop grid (or something similar). Here's the pen (http://codepen.io/anon/pen/QbKjzx) and here the code:
// external js: draggabilly.pkgd.js
$(document).ready( function() {
for(var i=1;i<=12;i++) {
$(".inventory").append('<div class="item"></div>');
}
for (var i = 0; $('.item').length + 1 > i; i++){
var n = i.toString();
var $item = $('.item:nth-child(' + i + ')');
$item.text(n);
var offsetX = $item.css("left");
var offsetY = $item.css("top");
$item.addClass(n);
$item.draggabilly();
$item.css("background-color","green");
$("." + n).on("dragStart",function(){
$(this).css({"transition": "none", "z-index": "9999", "background-color": "red"})
.mousemove(function(e){
$(this).on("dragEnd",function(){
$(this).css("top",offsetY);
$(this).css("left",offsetX);
var posX = e.pageX;
var posY = e.pageY;
var thisItsTheVariable = $("p").height();
$(this).css({"transition": "all .3s", "z-index": "1"});
})
})
})
}
})
The weird thing comes with thisItsTheVariable. When you assign to the variable any other value, there is an animation when you drop the dive and this come back to its original place. Even with $("p").css("background-color") or something similar works. But when you use .css("top"), .css("left"), .css("height"), .css("width"), .height(), .width() and possibly other (i didn't try it all), the animation dissapears! What is happening here?

Calling $("p").height() after you start the animation seems to fix it.
// external js: draggabilly.pkgd.js
$(document).ready(function () {
for (var i = 1; i <= 12; i++) {
$(".inventory").append('<div class="item"></div>');
}
for (var i = 0; $('.item').length + 1 > i; i++) {
var n = i.toString();
var $item = $('.item:nth-child(' + i + ')');
$item.text(n);
var offsetX = $item.css("left");
var offsetY = $item.css("top");
$item.addClass(n);
$item.draggabilly();
$item.css("background-color", "green");
$("." + n).on("dragStart", function () {
$(this).css({
"transition": "none",
"z-index": "9999",
"background-color": "red"
})
.mousemove(function (e) {
$(this).on("dragEnd", function () {
$(this).css("top", offsetY);
$(this).css("left", offsetX);
var posX = e.pageX;
var posY = e.pageY;
$(this).css({"transition": "all .3s", "z-index": "1"});
var thisItsTheVariable = $("p").height();
})
})
})
}
})
body, html {
height: 100%;
width: 100%;
padding: 0;
border: 0;
}
.inventory {
height: 300px;
width: 400px;
border: 1px black solid;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.item {
width: 100px;
height: 100px;
background: #F90;
box-sizing: border-box;
border: 1px black solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/draggabilly/1.2.0/draggabilly.pkgd.js"></script>
<div class="inventory"></div>
<p></p>

Related

How to drag images in JS

I have a large background image and some much smaller images for the user to drag around on the background. I need this to be efficient in terms of performance, so i'm trying to avoid libraries. I'm fine with drag 'n' drop if it work's well, but im trying to get drag.
Im pretty much trying to do this. But after 8 years there must be a cleaner way to do this right?
I currently have a drag 'n' drop system that almost works, but when i drop the smaller images, they are just a little off and it's very annoying. Is there a way to fix my code, or do i need to take a whole different approach?
This is my code so far:
var draggedPoint;
function dragStart(event) {
draggedPoint = event.target; // my global var
}
function drop(event) {
event.preventDefault();
let xDiff = draggedPoint.x - event.pageX;
let yDiff = draggedPoint.y - event.pageY;
let left = draggedPoint.style.marginLeft; // get margins
let top = draggedPoint.style.marginTop;
let leftNum = Number(left.substring(0, left.length - 2)); // cut off px from the end
let topNum = Number(top.substring(0, top.length - 2));
let newLeft = leftNum - xDiff + "px" // count new margins and put px back to the end
let newTop = topNum - yDiff + "px"
draggedPoint.style.marginLeft = newLeft;
draggedPoint.style.marginTop = newTop;
}
function allowDrop(event) {
event.preventDefault();
}
let imgs = [
"https://upload.wikimedia.org/wikipedia/commons/6/67/Orange_juice_1_edit1.jpg",
"https://upload.wikimedia.org/wikipedia/commons/f/ff/Solid_blue.svg",
"https://upload.wikimedia.org/wikipedia/commons/b/b4/Litoria_infrafrenata_-_Julatten.jpg"
]
/* my smaller images: */
for (let i = 0; i < 6; i++) {
let sensor = document.createElement("img");
sensor.src = imgs[i % imgs.length];
sensor.alt = i;
sensor.draggable = true;
sensor.classList.add("sensor");
sensor.style.marginLeft = `${Math.floor(Math.random() * 900)}px`
sensor.style.marginTop = `${Math.floor(Math.random() * 500)}px`
sensor.onclick = function() {
sensorClick(logs[i].id)
};
sensor.addEventListener("dragstart", dragStart, null);
let parent = document.getElementsByClassName("map")[0];
parent.appendChild(sensor);
}
<!-- my html: -->
<style>
.map {
width: 900px;
height: 500px;
align-content: center;
margin: 150px auto 150px auto;
}
.map .base {
position: absolute;
width: inherit;
height: inherit;
}
.map .sensor {
position: absolute;
width: 50px;
height: 50px;
}
</style>
<div class="map" onDrop="drop(event)" ondragover="allowDrop(event)">
<img src='https://upload.wikimedia.org/wikipedia/commons/f/f7/Plan-Oum-el-Awamid.jpg' alt="pohja" class="base" draggable="false">
<div>
With the answers from here and some time i was able to get a smooth drag and click with pure js.
Here is a JSFiddle to see it in action.
let maxLeft;
let maxTop;
const minLeft = 0;
const minTop = 0;
let timeDelta;
let imgs = [
"https://upload.wikimedia.org/wikipedia/commons/6/67/Orange_juice_1_edit1.jpg",
"https://upload.wikimedia.org/wikipedia/commons/f/ff/Solid_blue.svg",
"https://upload.wikimedia.org/wikipedia/commons/b/b4/Litoria_infrafrenata_-_Julatten.jpg"
]
var originalX;
var originalY;
window.onload = function() {
document.onmousedown = startDrag;
document.onmouseup = stopDrag;
}
function sensorClick () {
if (Date.now() - timeDelta < 150) { // check that we didn't drag
createPopup(this);
}
}
// create a popup when we click
function createPopup(parent) {
let p = document.getElementById("popup");
if (p) {
p.parentNode.removeChild(p);
}
let popup = document.createElement("div");
popup.id = "popup";
popup.className = "popup";
popup.style.top = parent.y - 110 + "px";
popup.style.left = parent.x - 75 + "px";
let text = document.createElement("span");
text.textContent = parent.id;
popup.appendChild(text);
var map = document.getElementsByClassName("map")[0];
map.appendChild(popup);
}
// when our base is loaded
function baseOnLoad() {
var map = document.getElementsByClassName("map")[0];
let base = document.getElementsByClassName("base")[0];
maxLeft = base.width - 50;
maxTop = base.height - 50;
/* my smaller images: */
for (let i = 0; i < 6; i++) {
let sensor = document.createElement("img");
sensor.src = imgs[i % imgs.length];
sensor.alt = i;
sensor.id = i;
sensor.draggable = true;
sensor.classList.add("sensor");
sensor.classList.add("dragme");
sensor.style.left = `${Math.floor(Math.random() * 900)}px`
sensor.style.top = `${Math.floor(Math.random() * 500)}px`
sensor.onclick = sensorClick;
let parent = document.getElementsByClassName("map")[0];
parent.appendChild(sensor);
}
}
function startDrag(e) {
timeDelta = Date.now(); // get current millis
// determine event object
if (!e) var e = window.event;
// prevent default event
if(e.preventDefault) e.preventDefault();
// IE uses srcElement, others use target
targ = e.target ? e.target : e.srcElement;
originalX = targ.style.left;
originalY = targ.style.top;
// check that this is a draggable element
if (!targ.classList.contains('dragme')) return;
// calculate event X, Y coordinates
offsetX = e.clientX;
offsetY = e.clientY;
// calculate integer values for top and left properties
coordX = parseInt(targ.style.left);
coordY = parseInt(targ.style.top);
drag = true;
document.onmousemove = dragDiv; // move div element
return false; // prevent default event
}
function dragDiv(e) {
if (!drag) return;
if (!e) var e = window.event;
// move div element and check for borders
let newLeft = coordX + e.clientX - offsetX;
if (newLeft < maxLeft && newLeft > minLeft) targ.style.left = newLeft + 'px'
let newTop = coordY + e.clientY - offsetY;
if (newTop < maxTop && newTop > minTop) targ.style.top = newTop + 'px'
return false; // prevent default event
}
function stopDrag() {
if (typeof drag == "undefined") return;
if (drag) {
if (Date.now() - timeDelta > 150) { // we dragged
let p = document.getElementById("popup");
if (p) {
p.parentNode.removeChild(p);
}
} else {
targ.style.left = originalX;
targ.style.top = originalY;
}
}
drag = false;
}
.map {
width: 900px;
height: 500px;
margin: 50px
position: relative;
}
.map .base {
position: absolute;
width: inherit;
height: inherit;
}
.map .sensor {
display: inline-block;
position: absolute;
width: 50px;
height: 50px;
}
.dragme {
cursor: move;
left: 0px;
top: 0px;
}
.popup {
position: absolute;
display: inline-block;
width: 200px;
height: 100px;
background-color: #9FC990;
border-radius: 10%;
}
.popup::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -10px;
border-width: 10px;
border-style: solid;
border-color: #9FC990 transparent transparent transparent;
}
.popup span {
width: 90%;
margin: 10px;
display: inline-block;
text-align: center;
}
<div class="map" width="950px" height="500px">
<img src='https://upload.wikimedia.org/wikipedia/commons/f/f7/Plan-Oum-el-Awamid.jpg' alt="pohja" class="base" draggable="false" onload="baseOnLoad()">
<div>

Collision detection using pure jQuery is not giving desired output

I am trying to develop a very simple game where the ship (red box) will move left-right when user clicks on playground.
There are some moving walls (black boxes) as obstacles that the ship should avoid colliding with.
If any collision happens, the walls will stop moving and a text will be printed out in console.
I have succeeded to get this as close as I can. But its working sometime, not always. You can see it in the code below, try to collide with wall. Sometime it will stop them and print text, sometime it will just ignore the collision as if nothing happens.
I have no clue why this is happening.
Here is the code.
$('document').ready(function() {
var $totalHeight = $('.inner').height(); //of walls
var $maxHeight = Math.ceil(Math.ceil($totalHeight / 3) - (Math.ceil($totalHeight / 3) * 30) / 100); //30% of total wall height
$('.wall').each(function(i, obj) {
$(this).height($maxHeight);
$('.wall.four').css({
'height': $wallGap
});
})
var $wallGap = Math.ceil($totalHeight / 3) - $maxHeight;
var $wallOneTop = 0;
var $wallTwoTop = $maxHeight + $wallGap;
var $wallThreeTop = ($maxHeight * 2) + ($wallGap * 2);
var $wallFourTop = -$('.wall.four').height() - $wallGap;
$('.wall.one').css({
'top': $wallOneTop
});
$('.wall.two').css({
'top': $wallTwoTop
});
$('.wall.three').css({
'top': $wallThreeTop
});
$('.wall.four').css({
'top': $wallFourTop
});
function moveWall(wallObj) {
var $currentTop = wallObj.position().top;
var $limitTop = $('.inner').height();
if ($currentTop >= $limitTop) {
var $rand = Math.floor(Math.random() * ($maxHeight - $wallGap + 1) + $wallGap);
wallObj.height($rand);
var $top = -(wallObj.height());
} else {
var $top = (wallObj.position().top) + 5;
}
var $collide = checkCollision(wallObj);
wallObj.css({
'top': $top
});
return $collide;
}
var $wallTimer = setInterval(function() {
$('.wall').each(function(i, obj) {
var $status = moveWall($(this));
if ($status == true) {
clearInterval($wallTimer);
}
})
}, 40);
function checkCollision(wallObj) {
var $ship = $('.ship');
var $shipWidth = $ship.width();
var $shipHeight = $ship.height();
var $shipLeft = $ship.position().left;
var $shipRight = $shipLeft + $shipWidth;
var $shipTop = $ship.position().top;
var $shipBottom = $shipTop + $shipHeight;
var $wall = wallObj;
var $wallWidth = wallObj.width();
var $wallHeight = wallObj.height();
var $wallLeft = wallObj.position().left;
var $wallRight = $wallLeft + $wallWidth;
var $wallTop = wallObj.position().top;
var $wallBottom = $wallTop + $wallHeight;
if (
$shipLeft >= $wallRight ||
$shipRight <= $wallLeft ||
$shipTop >= $wallBottom ||
$shipBottom <= $wallTop
) {
return false;
} else {
console.log("dhumm!");
return true;
}
}
$('.outer .inner').click(function() {
var $ship;
$ship = $('.ship');
$shipLeft = $ship.position().left;
$shipRight = $shipLeft + $ship.width();
$inner = $('.inner');
$innerLeft = $inner.position().left;
$innerRight = $innerLeft + $inner.width();
if (($shipLeft < $inner.width() - $ship.width())) {
$ship.animate({
"left": $inner.width() - $ship.width()
}, 500, "linear");
} else if (($shipRight >= $inner.width())) {
$ship.animate({
"left": '0'
}, 500, "linear");
}
});
});
.outer {
background: #fff;
border: 20px solid #efefef;
width: 400px;
height: 600px;
display: inline-block;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
overflow: hidden;
}
.outer .inner {
background: #fff;
height: 100%;
width: 100%;
margin: auto;
position: relative;
overflow: hidden;
}
.outer .inner .wall {
width: 5px;
position: absolute;
left: 50%;
transform: translateX(-50%);
background: #000;
}
.outer .inner .ship {
width: 15px;
height: 15px;
background: red;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="outer">
<div class="inner">
<div class="wall one"></div>
<div class="wall two"></div>
<div class="wall three"></div>
<div class="wall four"></div>
<div class="ship"></div>
</div>
</div>
As freefomn-m already said.
Check for collision in the animation cycle of the ship, not the walls.
For this I use the second type of parameters for jQuery's .animate method
.animate( properties, options )
I use the "progress" option to check the collision in every movement cycle of the ship.
console.clear();
$('document').ready(function() {
var collided = false;
var collidedWith = null;
var $ship = $('.ship');
var $walls = $('.wall')
var $totalHeight = $('.inner').height(); //of walls
var $maxHeight = Math.ceil(Math.ceil($totalHeight / 3) - (Math.ceil($totalHeight / 3) * 30) / 100); //30% of total wall height
$('.wall').each(function(i, obj) {
$(this).height($maxHeight);
$('.wall.four').css({
'height': $wallGap
});
})
var $wallGap = Math.ceil($totalHeight / 3) - $maxHeight;
var $wallOneTop = 0;
var $wallTwoTop = $maxHeight + $wallGap;
var $wallThreeTop = ($maxHeight * 2) + ($wallGap * 2);
var $wallFourTop = -$('.wall.four').height() - $wallGap;
$('.wall.one').css({
'top': $wallOneTop
});
$('.wall.two').css({
'top': $wallTwoTop
});
$('.wall.three').css({
'top': $wallThreeTop
});
$('.wall.four').css({
'top': $wallFourTop
});
function moveWall(wallObj) {
var $currentTop = wallObj.position().top;
var $limitTop = $('.inner').height();
if ($currentTop >= $limitTop) {
var $rand = Math.floor(Math.random() * ($maxHeight - $wallGap + 1) + $wallGap);
wallObj.height($rand);
var $top = -(wallObj.height());
} else {
var $top = (wallObj.position().top) + 5;
}
// var $collide = checkCollision(wallObj);
wallObj.css({
'top': $top
});
// return $collide;
}
var $wallTimer = setInterval(function() {
$walls.each(function(i, obj) {
moveWall($(this));
if (collided) {
clearInterval($wallTimer);
}
})
}, 40);
function checkCollision() {
var $shipWidth = $ship.width();
var $shipHeight = $ship.height();
var $shipLeft = $ship.position().left;
var $shipRight = $shipLeft + $shipWidth;
var $shipTop = $ship.position().top;
var $shipBottom = $shipTop + $shipHeight;
$('.wall').each(function(i) {
var $wall = $(this);
var $wallWidth = $wall.width();
var $wallHeight = $wall.height();
var $wallLeft = $wall.position().left;
var $wallRight = $wallLeft + $wallWidth;
var $wallTop = $wall.position().top;
var $wallBottom = $wallTop + $wallHeight;
if (
$shipLeft < $wallRight &&
$shipRight > $wallLeft &&
$shipTop < $wallBottom &&
$shipBottom > $wallTop
) {
console.log("dhumm!");
collided = true;
collidedWith = $wall
$wall.addClass('crashed')
$ship.addClass('crashed')
$ship.stop();
return false;
}
})
}
$('.outer .inner').click(function() {
var $ship;
$ship = $('.ship');
$shipLeft = $ship.position().left;
$shipRight = $shipLeft + $ship.width();
$inner = $('.inner');
$innerLeft = $inner.position().left;
$innerRight = $innerLeft + $inner.width();
if (($shipLeft < $inner.width() - $ship.width())) {
$ship.animate({
"left": $inner.width() - $ship.width()
}, {
"duration": 500,
"easing": "linear",
"progress": checkCollision,
});
} else if (($shipRight >= $inner.width())) {
$ship.animate({
"left": '0'
}, {
"duration": 500,
"easing": "linear",
"progress": checkCollision,
});
}
});
});
.outer {
background: #fff;
border: 20px solid #efefef;
width: 400px;
height: 600px;
display: inline-block;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
overflow: hidden;
}
.outer .inner {
background: #fff;
height: 100%;
width: 100%;
margin: auto;
position: relative;
overflow: hidden;
}
.outer .inner .wall {
width: 5px;
position: absolute;
left: 50%;
transform: translateX(-50%);
background: #000;
}
.outer .inner .wall.crashed {
background: red;
}
.outer .inner .ship {
width: 15px;
height: 15px;
background: orange;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.outer .inner .ship.crashed {
background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="outer">
<div class="inner">
<div class="wall one"></div>
<div class="wall two"></div>
<div class="wall three"></div>
<div class="wall four"></div>
<div class="ship"></div>
</div>
</div>
As a recommendation how I would do this from scratch.
Use an update cycle that is called by either setInterval or setTimeout, or even better with requestAnimationFrame. The updatecycle would be responsible for the time progress and orchestrate the different objects. The structure would be like this.
jQuery(function($) { // same as $('document').ready()
var ship = ...;
var boundaries = ...;
var walls = ...;
var clickEvents = [];
document.addEventListener('click', function(e) {clickEvents.push(e)})
var handleEvents = function() {}
var setupWalls = function () {}
var setupShip= function () {}
var moveWalls = function () {}
var moveShip = function () {}
var checkCollision() {}
var setup = function() {
setupWalls();
setupShip();
// set the initial positions of the ships and the walls
}
var update = function() {
handleEvents();
moveWalls();
moveShips();
var collided = checkCollision();
if (!collided) {
setTimeout(update, 30);
}
}
setup();
update();
})

Responsive jQuery sketch application failing when div size is < 7px

I'm trying to build a responsive sketch application with jQuery. It works, except for when the size for the divs within the .box class become less than 7px. I tried to make a fiddle but I couldn't see any output. I'll just leave the code here and hope for the best!
var wide = 150;
$(document).ready(function() {
makeGrid(wide);
$('body').on('mousedown mouseup', function mouseState(e) {
if (e.type == "mousedown") {
$(".box").mouseenter(function() {
$(this).css("background-color", "black");
});
} else {
$(".box").unbind('mouseenter mouseleave');
}
});
});
var makeGrid = function(wide) {
var boxSide = calculateBoxSide(wide);
var boxRowNumber = calculateRowNumbers(boxSide);
var boxSideLength = boxSide + "px";
$("body").css("line-height", boxSideLength);
for (i = 0; i < wide; i++) {
for (j = 0; j < boxRowNumber; j++) {
$box = $('<div class="box">').appendTo(".sketchpad")
$box.css("width", boxSideLength);
$box.css("height", boxSideLength);
}
}
}
var calculateBoxSide = function(wide) {
return $(".sketchpad").width() / wide;
}
var calculateRowNumbers = function(boxSideLength) {
return Math.round($(".sketchpad").height() / boxSideLength);
}
.sketchpad {
margin: 0 auto;
width: 50%;
height: 500px;
text-align: center;
}
.box {
display: inline-block;
background-color: grey;
vertical-align: top;
}
.box:hover {
background-color: black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class="sketchpad"></div>

can't achieve touch compatibility with my jQuery zoom plugin

I modified an MIT licensed Zoom Plugins to fit my needs and it works perfectly well. However, it came from a time before smartphones and tablets and I really want to support them.
I have built a jsFiddle to illustrate my case:
https://jsfiddle.net/xLr86bs8/
Neccessary code:
JavaScript:
(function($){
var defaults = {
cursorColor:'237,241,244',
cursorOpacity: 1,
//cursorBorder: '1px solid black',
//cursorBorderThickness: 1,
cursor:'pointer',
zoomviewsize: [0,0],
magnification: 5,
};
var minitraversalzoomCursor,minitraversalzoomView,minitraversalsettings,minitraversalImageWidth,minitraversalImageHeight,minitraversalOffset,minitraversalzoomimage;
var minitraversalMethods = {
init : function(options){
$this = $(this),
minitraversalzoomCursor = $('.minitraversalzoom-cursor'),
minitraversalzoomView = $('.minitraversalzoom-view'),
minitraversalzoomimage = $('#MiniTraversalZoomImage'),
// This makes the complete addon independent from the size of the zoomwindow
//defaults.zoomviewsize = [$('#RadialBox').width(),$('#RadialBox').height()];
$(document).on('mouseenter touchstart',$this.selector,function(e){
var data = $(this).data();
minitraversalsettings = $.extend({},defaults,options,data);
minitraversalOffset = $(this).offset();
minitraversalImageWidth = $(this).width();
minitraversalImageHeight = $(this).height();
minitraversalsettings.zoomviewsize = [$(this).parent().width(),$(this).parent().height()];
cursorSize = [(minitraversalsettings.zoomviewsize[0]/minitraversalsettings.magnification),(minitraversalsettings.zoomviewsize[1]/minitraversalsettings.magnification)];
$original = $(this);
minitraversalZoomSource = $(this).attr('data-minitraversalzoom');
minitraversalSource = $(this).attr('src');
var posX = e.pageX,posY = e.pageY,zoomViewPositionX;
$('body').prepend('<div class="minitraversalzoom-cursor"> </div>');
$('#MiniZoomBox').addClass('minitraversalzoom-view').prepend('<img id="MiniTraversalZoomImage" src="' + minitraversalZoomSource + '">');
$(minitraversalzoomView.selector).css({
'position':'relative',
'z-index': 7,
'overflow':'hidden',
});
$(minitraversalzoomView.selector).children('img[id="MiniTraversalZoomImage"]').css({
'position':'relative',
'width': minitraversalImageWidth*minitraversalsettings.magnification,
'height': minitraversalImageHeight*minitraversalsettings.magnification,
});
$(minitraversalzoomCursor.selector).css({
'position':'absolute',
'width':cursorSize[0],
'height':cursorSize[1],
'background-color':'rgb('+ minitraversalsettings.cursorColor +')',
'z-index': 7,
'opacity':minitraversalsettings.cursorOpacity,
'cursor':minitraversalsettings.cursor,
'border':minitraversalsettings.cursorBorder,
});
$(minitraversalzoomCursor.selector).css({'top':posY-(cursorSize[1]/2),'left':posX});
$(document).on('mousemove move',document.body,minitraversalMethods.cursorPos);
});
},
cursorPos:function(e){
var posX = e.pageX,posY = e.pageY;
if(posY < minitraversalOffset.top || posX < minitraversalOffset.left || posY > (minitraversalOffset.top+minitraversalImageHeight) || posX > (minitraversalOffset.left+minitraversalImageWidth)){
$(minitraversalzoomCursor.selector).remove();
$(minitraversalzoomimage.selector).remove();
//$(minitraversalzoomView.selector).empty();
//$('#ZoomImage').remove();
//$(this).siblings('img').remove();
//$('#RadialBox > img').remove();
//$('#MiniZoomBox > img[id!="TraversalZoomImage10x"]').remove();
$('#MiniZoomBox').removeClass('minitraversalzoom-view');//.append('<img data-minitraversalzoom="' + minitraversalZoomSource + '" src="' + minitraversalSource + '" class="minitraversalzoom">');
//$('#MiniZoomBox').empty().removeClass('minitraversalzoom-view').append('<img data-minitraversalzoom="' + minitraversalZoomSource + '" src="' + minitraversalSource + '" class="minitraversalzoom">');
//$('#RadialBox').removeClass('minitraversalzoom-view').prepend($original.prop('outerHTML'));
return;
}
if(posX-(cursorSize[0]/2) < minitraversalOffset.left){
posX = minitraversalOffset.left+(cursorSize[0]/2);
}else if(posX+(cursorSize[0]/2) > minitraversalOffset.left+minitraversalImageWidth){
posX = (minitraversalOffset.left+minitraversalImageWidth)-(cursorSize[0]/2);
}
if(posY-(cursorSize[1]/2) < minitraversalOffset.top){
posY = minitraversalOffset.top+(cursorSize[1]/2);
}else if(posY+(cursorSize[1]/2) > minitraversalOffset.top+minitraversalImageHeight){
posY = (minitraversalOffset.top+minitraversalImageHeight)-(cursorSize[1]/2);
}
$(minitraversalzoomCursor.selector).css({'top':posY-(cursorSize[1]/2),'left':posX-(cursorSize[0]/2)});
$(minitraversalzoomView.selector).children('img').css({'top':((minitraversalOffset.top-posY)+(cursorSize[1]/2))*minitraversalsettings.magnification,'left':((minitraversalOffset.left-posX)+(cursorSize[0]/2))*minitraversalsettings.magnification});
/*
$(minitraversalzoomCursor.selector).mouseleave(function(){
$(this).remove();
});*/
}
};
$.fn.minitraversalZoom = function(method){
if(minitraversalMethods[method]){
return minitraversalMethods[method].apply( this, Array.prototype.slice.call(arguments,1));
}else if( typeof method === 'object' || ! method ) {
return minitraversalMethods.init.apply(this,arguments);
}else{
$.error(method);
}
}
$(document).ready(function(){
$('[data-minitraversalzoom]').minitraversalZoom();
});
})(jQuery);
HTML:
<div class="ZoomWindow" id="MiniZoomBox"><img class="minitraversalzoom" data-minitraversalzoom="http://placekitten.com/234/351" src="http://placekitten.com/234/351"/></div>
<div class=""></div>
CSS:
.ZoomWindowContainer{
display: inline-block;
position: relative;
vertical-align: top;
}
.ZoomWindow{
/* display: inline-block;
*/ height: 351px;
width: 234px;
margin-top: 4px;
border: 1px solid #a3b7c7;
}
#MiniZoomBox > img.miniradialzoom, #MiniZoomBox > img.minitraversalzoom, #MiniZoomBox > img.minitangentialzoom{
height: 100%;
}
#MiniZoomBox{
background-color: #0072bd;
/*background: url("/css/styling/magnifier_background-gradient-right.png") repeat-y scroll 0% 0% transparent;*/
/* background: url('/css/styling/10x.png') #0072bd;
*/ background-size: 100%;
overflow: hidden;
}
Could somebody help me to tweek it, in order to make it work?
Update:
I implemented the jQuery.event.move plugin to get new options like movestart, move, etc… and with it, I could get my plugin to work correctly on touchscreens, however, scrolling does not work at all on the site now. So i solved one problem and got another one. Does anyone know, to fix either one of them?
Update Jan. 1st 2016:
I continued programming and this is still the last problem I am facing. Any help is welcomed here ;)

How to color every second row using jQuery when the number of element in a row is variable?

Consider the following example which should color every second row: (live demo here)
JS:
$(function() {
var wrapper = $("<div></div>")
for (i = 0; i < 100; i++) {
wrapper.append("<span></span>");
}
$("body").append(wrapper);
color_rows();
});
function color_rows() {
$("span").each(function(i) {
if (i % 10 >= 5) {
$(this).css("background-color", "red");
}
});
}
CSS:
div {
width: 450px;
height: 400px;
background-color: #ccc;
overflow: auto;
}
span {
display: inline-block;
width: 50px;
height: 50px;
background-color: #777;
margin: 0 30px 30px 0;
}
The output is:
As you can see, color_rows() function assumes that there are 5 elements per row. If, for example, I change the width of the div to be 350px, the color_rows() function will not work properly (i.e. will not color every second row).
How could I fix color_rows() so that it will work for every width of the div ?
this is my solution:
this works based on the top offset of each element and by comparing the it to the top offset of last element in the loop it detects if new row is seen or not, and then based on the number of row colors rows.
function color_rows() {
var lastTop = -1;
var rowCount = 0;
$("span").each(function(i) {
var top = $(this).position().top;
if (top != lastTop) {
rowCount++;
lastTop = top;
}
if(rowCount % 2 == 0)
{
$(this).css("background-color", "red");
}
});
}
jsFiddle: http://jsfiddle.net/Ug6wD/4/
Look at my fixes http://jsfiddle.net/Ug6wD/5/
I am getting Container width, itemWidth + margin. And calculating how many items per row. Get margin-right from span item.
Then minus 20 to the container width, coz of overflow scrollbar.
function color_rows() {
var containerWidth = $('div').width()-20;
var itemWidth = $('span:first').width() + parseInt($('span:first').css('margin-right'));
var itemsPerRow = parseInt(containerWidth / itemWidth);
$("span").each(function(i) {
if (i % (itemsPerRow *2) >= itemsPerRow ) {
$(this).css("background-color", "red");
}
});
}
UPDATE with dynamic margin-right value from CSS AND Right scrollbar fix causing breakage : http://jsfiddle.net/Ug6wD/5/
Edit: This only works on some div-widths.. -.- Nevermind, then..
This should do it:
function color_rows() {
var divW = $('div').width();
var spanW = $('span').outerWidth(true); //Get margin too
var cnt = parseInt(divW/spanW, 10); //Remove decimals
$("span").each(function(i) {
if (i % (cnt*2) >= cnt) {
$(this).css("background-color", "red");
}
});
}
fiddle: http://jsfiddle.net/gn5QW/1/
html
<div id="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
js
$(document).ready(function(){
var box = $(".box");
var con = $("#container");
var box_per_line = Math.floor(parseInt($("#container").width())/ (parseInt( $(".box").width()) +10*2/*px*/));
var style = "black";
$(".box").each(function(i){
if(i % box_per_line == 0){ style = (style == "black") ? "grey" : "black"; }
$(this).css("background-color",style);
});
});
css
.box {
width: 100px;
height: 100px;
float: left;
margin: 10px;
}
#conainer {
background-color: grey;
display: inline-block;
}
I've fixed your code, but please PLEASE don't do this. The internet the in pain,
$(function() {
var wrapper = $("<div></div>")
for (i = 0; i < 100; i++) {
wrapper.append("<span></span>");
}
$("body").append(wrapper);
color_rows();
});
function color_rows() {
var rowWidth = Number( $('div:first').css('width').slice(0,-2) );
var itemWidth = Number( $('span:first').css('width').slice(0,-2) ) + Number( $('span:first').css('margin-right').slice(0,-2) );
var perRow = Math.floor( rowWidth/itemWidth );
$("span").each(function(i) {
if (i % 10 >= perRow ) {
$(this).css("background-color", "red");
}
});
}
There is a simpler way:
$('tr:even').css("background-color", "red");

Categories