jQuery plugin only working on last selector - javascript

In my quest for learning more Javascript I'm trying to create a jQuery plugin that creates my own custom scrollbars. It is working fine for one scrollbar at a time but if I try to do two of them only the last one works.
JSFiddle: http://jsfiddle.net/JoelCool/K4mW7/1/
I've noticed the variable "scrolling" is not true on the first scrollbar in the HandleMouseMove() function so it seems like it might be a scoping thing?
HTML
Scrollbar Test
.scroller-bar {
background-color:#ccc;border:1px solid black;float:left;position:relative;cursor:pointer;
}
.noSelect
{
user-select:none;
-o-user-select:none;
-moz-user-select:none;
-khtml-user-select:none;
-webkit-user-select:none;
}
<div id="container" style="width:600px;height:300px;background-color:#ccc;overflow:hidden;position:relative;">
<div id="content" style="background-color:blue;width:800px;height:283px;position:relative;left:0;">
12345678901234567890123456789012345678901234567890
</div>
<div style="top:0;left:0;height:300px;width:100px;background-color:yellow;z-index:100;position:absolute;"></div>
<div id="scroll-track-h" style="position:absolute;bottom:0;right:0;height:17px;width:500px;background-color:cyan;"></div>
<div id="scroll-track-v" style="position:absolute;top:0;right:0;height:283px;width:17px;background-color:orange;"></div>
</div>
<br /><br />
<script src="jquery-2.1.0.min.js"></script>
<script src="scroller.js"></script>
<script>
$('#scroll-track-v').scroller();
$('#scroll-track-h').scroller();
//$('#scroll-track-v, #scroll-track-h').scroller();
</script>
Javascript
(function( $ ) {
$.fn.scroller = function( options ) {
options = $.extend( $.fn.scroller.defaults, options );
// Plugin code
return this.each(function () {
var $elem = $(this),
scrolling = false,
mouseStartPos = 0,
barPos = 0,
xy = $elem.width() > $elem.height() ? 'x' : 'y', // x = horizontal, y = vertical
trackLength = xy == 'x' ? $elem.width() : $elem.height(),
barLength = (trackLength * options.barPct / 100) - 2, // should make it figure out the border width
travelLength = trackLength - barLength - 2;
console.log($elem);
var $bar = $('<div class="scroller-bar"></div>')
.width( xy == 'x' ? barLength : $elem.innerWidth() - 2)
.height( xy == 'x' ? $elem.innerHeight() - 2 : barLength);
$elem.append($bar);
$elem.on('mousedown', function (evt) {
scrolling = true;
$("body").addClass("noSelect"); // turn off text selection while scrolling
mouseStartPos = xy == 'x' ? evt.pageX : evt.pageY;
barPos = xy == 'x' ? $bar.position().left : $bar.position().top;
$(document).on('mousemove', function (evt) { HandleMouseMove(evt); });
});
$(document).on('mouseup', function (evt) {
if (scrolling) {
$("body").removeClass("noSelect");
$(document).off('mousemove');
mouseStartPos = 0;
scrolling = false;
}
});
HandleMouseMove = function (evt) {
console.log(scrolling);
if (scrolling) {
var mouseMovedBy = xy == 'x' ? evt.pageX - mouseStartPos : evt.pageY - mouseStartPos,
newBarPos = barPos + mouseMovedBy;
if (newBarPos < 0) { newBarPos = 0; }
if (newBarPos > travelLength) { newBarPos = travelLength; }
$bar.css(xy == 'x' ? 'left' : 'top', newBarPos);
var pct = newBarPos / travelLength;
}
}
});
}
// Set up the default options.
$.fn.scroller.defaults = {
barPct : 25,
onScroll : null
};
})( jQuery );
$('#scroll-track-v').scroller();
$('#scroll-track-h').scroller();
I'm calling it on the vertical bar first and then the horizontal and only the horizontal works. If I switch them then only the vertical works.
Can anyone give me a clue? Am I doing it completely wrong?

Your function HandleMouseMove() was not binded to the Element. It was getting mixed values for the 'scrolling' Boolean value.
I just added $elem. before the function name. and made it as $elem.HandleMouseMove(event);
Check the code
(function( $ ) {
$.fn.scroller = function( options ) {
options = $.extend( $.fn.scroller.defaults, options );
// Plugin code
return this.each(function () {
var $elem = $(this),
scrolling = false,
mouseStartPos = 0,
barPos = 0,
xy = $elem.width() > $elem.height() ? 'x' : 'y', // x = horizontal, y = vertical
trackLength = xy == 'x' ? $elem.width() : $elem.height(),
barLength = (trackLength * options.barPct / 100) - 2, // should make it figure out the border width
travelLength = trackLength - barLength - 2;
console.log($elem);
var $bar = $('<div class="scroller-bar"></div>')
.width( xy == 'x' ? barLength : $elem.innerWidth() - 2)
.height( xy == 'x' ? $elem.innerHeight() - 2 : barLength);
$elem.append($bar);
$elem.on('mousedown', function (evt) {
scrolling = true;
$("body").addClass("noSelect"); // turn off text selection while scrolling
mouseStartPos = xy == 'x' ? evt.pageX : evt.pageY;
barPos = xy == 'x' ? $bar.position().left : $bar.position().top;
$(document).on('mousemove', function (evt) { $elem.HandleMouseMove(evt); });
});
$(document).on('mouseup', function (evt) {
if (scrolling) {
$("body").removeClass("noSelect");
$(document).off('mousemove');
mouseStartPos = 0;
scrolling = false;
}
});
$elem.HandleMouseMove = function (evt) {
console.log(scrolling);
if (scrolling) {
var mouseMovedBy = xy == 'x' ? evt.pageX - mouseStartPos : evt.pageY - mouseStartPos,
newBarPos = barPos + mouseMovedBy;
if (newBarPos < 0) { newBarPos = 0; }
if (newBarPos > travelLength) { newBarPos = travelLength; }
$bar.css(xy == 'x' ? 'left' : 'top', newBarPos);
var pct = newBarPos / travelLength;
}
}
});
}
// Set up the default options.
$.fn.scroller.defaults = {
barPct : 25,
onScroll : null
};
})( jQuery );
$('#scroll-track-v').scroller();
$('#scroll-track-h').scroller();
Check the Updated jsfiddle http://jsfiddle.net/shinde87sagar/K4mW7/3/

I've updated your code to work using data objects. When you have multiple DOM elements being worked on in a plugin, you should explicitly state which objects you're referring to. Keeping them global as you did makes it impossible for the mousemove and mouseup events to know which element to refer to. This way is cleaner and you only have to worry about the scope inside each event handler.
edit: this doesn't move the content pane yet, but this should give you an idea how to proceed correctly.
http://jsfiddle.net/ozzy_og_kush/K4mW7/2/
$.fn.scroller = function( options ) {
options = $.extend( $.fn.scroller.defaults, options );
// Plugin code
return this.each(function () {
var $elem = $(this);
var xy = ($elem.width() > $elem.height() ? 'x' : 'y');
var trackLength = (xy == 'x' ? $elem.width() : $elem.height());
var barLength = (trackLength * options.barPct / 100) - 2;
$elem.data({
'scrolling' : false,
'xy' : xy,
'barPos' : 0,
'mouseStartPos' : 0,
'trackLength' : trackLength,
'barLength' : barLength,
'travelLength' : trackLength - barLength - 2
});
console.log($elem);
var $bar = $('<div class="scroller-bar"></div>')
.width($elem.data('xy') == 'x' ?
$elem.data('barLength') :
$elem.innerWidth() - 2
)
.height($elem.data('xy') == 'x' ?
$elem.innerHeight() - 2 :
$elem.data('barLength')
);
$elem.append($bar).data('bar', $bar);
$elem.on('mousedown', { elem : $elem }, function(evt) {
evt.data.elem.data('scrolling', true);
$thisBar = evt.data.elem.data('bar');
$("body").addClass("noSelect");
evt.data.elem.data('mouseStartPos', (
evt.data.elem.data('xy') == 'x' ?
evt.pageX :
evt.pageY
));
evt.data.elem.data('barPos', (
evt.data.elem.data('xy') == 'x' ?
$thisBar.position().left :
$thisBar.position().top
));
$(document).on(
'mousemove',
{ elem : evt.data.elem },
HandleMouseMove
);
});
$(document).on('mouseup', { elem : $elem }, function(evt) {
if (evt.data.elem.data('scrolling') === true) {
$("body").removeClass("noSelect");
$(document).off('mousemove');
mouseStartPos = 0;
evt.data.elem.data('scrolling', false);
}
});
HandleMouseMove = function(evt) {
console.log(evt.data.elem.data('scrolling'));
if (evt.data.elem.data('scrolling') === true) {
var mouseMovedBy = (
evt.data.elem.data('xy') == 'x' ?
evt.pageX - evt.data.elem.data('mouseStartPos') :
evt.pageY - evt.data.elem.data('mouseStartPos')
),
newBarPos = evt.data.elem.data('barPos') + mouseMovedBy;
if (newBarPos < 0) { newBarPos = 0; }
if (newBarPos > evt.data.elem.data('travelLength')) {
newBarPos = evt.data.elem.data('travelLength');
}
evt.data.elem.data('bar').css(
(
evt.data.elem.data('xy') == 'x' ?
'left' :
'top'
),
newBarPos + "px"
);
//var pct = newBarPos / evt.data.elem.data('travelLength');
}
}
});
}
// Set up the default options.
$.fn.scroller.defaults = {
barPct : 25,
onScroll : null
};
$('#scroll-track-v').scroller();
$('#scroll-track-h').scroller();

Related

Using jQuery Pan and Zoomooz together to pan and zoom DOM element

Seen a few similar questions on here but most seem to refer to zooming and panning images, I can't find anything that answers my problem.
I'm looking to create something like https://timmywil.com/panzoom/demo/, but I want to have a DOM element zoom on click, then pan around on mouse move.
I've been able to come up with something that's very nearly there, example here. https://jsfiddle.net/kevngibsn/5okxr8n3/29/
For this I'm using Zoomooz to handle the zoom, and jQuery Pan to take care of the panning. The issue with this example is that jQuery Pan works out the size of the DOM element on page load and doesn't take into account the increased size after zoom, so mouse move doesn't pan to the edges.
Here's the code from jQuery Pan:
(function( $ ){
var getSize = function($element) {
return {
'width': $element.width(),
'height': $element.height()
};
};
var toCoords = function(x, y) {
return {'x': x, 'y': y};
};
var vectorsEqual = function(v1, v2) {
return v1.x == v2.x && v1.y == v2.y;
}
$.fn.pan = function(options) {
//Container is element this plugin is applied to;
//we're pan it's child element, content
var container = this;
var content = this.children(':first');
//Precalculate the limits of panning - offset stores
//the current amount of pan throughout
var offset = toCoords(
Number(content.css('left').replace('px', '')) | 0,
Number(content.css('top').replace('px', '')) | 0
);
var containerSize = getSize(container);
var contentSize = getSize(content);
var minOffset = toCoords(
-contentSize.width + containerSize.width,
-contentSize.height + containerSize.height
);
var maxOffset = toCoords(0, 0);
//By default, assume mouse sensitivity border
//is 25% of the smallest dimension
var defaultMouseEdge = 0.25 * Math.min(
containerSize.width,
containerSize.height
);
var settings = $.extend( {
'autoSpeedX' : 0,
'autoSpeedY' : 0,
'mouseControl' : 'kinetic',
'kineticDamping' : 0.8,
'mouseEdgeSpeed' : 5,
'mouseEdgeWidth' : defaultMouseEdge,
'proportionalSmoothing' : 0.5,
'updateInterval' : 50,
'mousePan' : null
}, options);
//Mouse state variables, set by bound mouse events below
var mouseOver = false;
var mousePanningDirection = toCoords(0, 0);
var mousePosition = toCoords(0, 0);
var dragging = false;
var lastMousePosition = null;
var kineticVelocity = toCoords(0, 0);
//Delay in ms between updating position of content
var updateInterval = settings.updateInterval;
var onInterval = function() {
if (container.hasClass('pan-off')) return false; //Temporarily disabling pan add/remove class pan-off
var mouseControlHandlers = {
'edge' : updateEdge,
'proportional' : updateProportional,
'kinetic' : updateKinetic
};
var currentHandler = settings.mouseControl;
if(!mouseControlHandlers[currentHandler]()) {
//The handler isn't active - just pan normally
offset.x += settings.autoSpeedX;
offset.y += settings.autoSpeedY;
}
//If the previous updates have take the content
//outside the allowed min/max, bring it back in
constrainToBounds();
//If we're panning automatically, make sure we're
//panning in the right direction if the content has
//moved as far as it can go
if(offset.x == minOffset.x) settings.autoSpeedX = Math.abs(settings.autoSpeedX);
if(offset.x == maxOffset.x) settings.autoSpeedX = -Math.abs(settings.autoSpeedX);
if(offset.y == minOffset.y) settings.autoSpeedY = Math.abs(settings.autoSpeedY);
if(offset.y == maxOffset.y) settings.autoSpeedY = -Math.abs(settings.autoSpeedY);
//Finally, update the position of the content
//with our carefully calculated value
content.css('left', offset.x + "px");
content.css('top', offset.y + "px");
}
var updateEdge = function() {
if(!mouseOver) return false;
//The user's possibly maybe mouse-navigating,
//so we'll find out what direction in case we need
//to handle any callbacks
var newDirection = toCoords(0, 0);
//If we're in the interaction zones to either
//end of the element, pan in response to the
//mouse position.
if(mousePosition.x < settings.mouseEdgeWidth) {
offset.x += settings.mouseEdgeSpeed;
newDirection.x = -1;
}
if (mousePosition.x > containerSize.width - settings.mouseEdgeWidth) {
offset.x -= settings.mouseEdgeSpeed;
newDirection.x = 1;
}
if(mousePosition.y < settings.mouseEdgeWidth) {
offset.y += settings.mouseEdgeSpeed;
newDirection.y = -1;
}
if (mousePosition.y > containerSize.height - settings.mouseEdgeWidth) {
offset.y -= settings.mouseEdgeSpeed;
newDirection.y = 1;
}
updateMouseDirection(newDirection);
return true;
}
var updateProportional = function() {
if(!mouseOver) return false;
var rx = mousePosition.x / containerSize.width;
var ry = mousePosition.y / containerSize.height;
targetOffset = toCoords(
(minOffset.x - maxOffset.x) * rx + maxOffset.x,
(minOffset.y - maxOffset.y) * ry + maxOffset.y
);
var damping = 1 - settings.proportionalSmoothing;
offset = toCoords(
(targetOffset.x - offset.x) * damping + offset.x,
(targetOffset.y - offset.y) * damping + offset.y
)
return true;
}
var updateKinetic = function() {
if(dragging) {
if(lastMousePosition == null) {
lastMousePosition = toCoords(mousePosition.x, mousePosition.y);
}
kineticVelocity = toCoords(
mousePosition.x - lastMousePosition.x,
mousePosition.y - lastMousePosition.y
);
lastMousePosition = toCoords(mousePosition.x, mousePosition.y);
}
offset.x += kineticVelocity.x;
offset.y += kineticVelocity.y;
kineticVelocity = toCoords(
kineticVelocity.x * settings.kineticDamping,
kineticVelocity.y * settings.kineticDamping
);
//If the kinetic velocity is still greater than a small threshold, this
//function is still controlling movement so we return true so autopanning
//doesn't interfere.
var speedSquared = Math.pow(kineticVelocity.x, 2) + Math.pow(kineticVelocity.y, 2);
return speedSquared > 0.01
}
var constrainToBounds = function() {
if(offset.x < minOffset.x) offset.x = minOffset.x;
if(offset.x > maxOffset.x) offset.x = maxOffset.x;
if(offset.y < minOffset.y) offset.y = minOffset.y;
if(offset.y > maxOffset.y) offset.y = maxOffset.y;
}
var updateMouseDirection = function(newDirection) {
if(!vectorsEqual(newDirection, mousePanningDirection)) {
mousePanningDirection = newDirection;
if(settings.mousePan) {
settings.mousePan(mousePanningDirection);
}
}
}
this.bind('mousemove', function(evt) {
mousePosition.x = evt.pageX - container.offset().left;
mousePosition.y = evt.pageY - container.offset().top;
mouseOver = true;
});
this.bind('mouseleave', function(evt) {
mouseOver = false;
dragging = false;
lastMousePosition = null;
updateMouseDirection(toCoords(0, 0));
});
this.bind('mousedown', function(evt) {
dragging = true;
return false; //Prevents FF from thumbnailing & dragging
});
this.bind('mouseup', function(evt) {
dragging = false;
lastMousePosition = null;
});
//Kick off the main panning loop and return
//this to maintain jquery chainability
setInterval(onInterval, updateInterval);
return this;
};
})( jQuery );
I'd at about my limit on this one, any advice on how to get that panning the whole element?

How to prevent draggable handles in range slider form overlapping?

I have to prevent dragable handles in range slider form overlapping . It is vanilla js plugin.
I tried to disable updating offset if the difference between two handles position is lower than 20px. It works sometimes, but the barrier is not precise. The movement is choppy when the handles are near to each other.The handle cannot be dragged immediately, but after few movements.
Here are the fragments of the plugin code:
// HELPERS
// map slider range to value range
Number.prototype.map = function(in_min, in_max, out_min, out_max) {
return (this - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
// round to nearest multiple
Number.prototype.roundTo = function(num) {
var resto = this % num;
if (resto <= (num / 2)) {
return this - resto;
} else {
return this + num - resto;
}
}
//EVENTS
var EVmove = ('ontouchstart' in document.documentElement) ? 'touchmove' : 'mousemove',
EVmove = ('ontouchstart' in document.documentElement) ? 'touchmove' : 'mousemove',
EVend = ('ontouchstart' in document.documentElement) ? 'touchend' : 'mouseup';
document.addEventListener(EVmove, actions.move, false);
document.addEventListener(EVend, function() {
return movebar = false;
}, false);
document.addEventListener(EVstart, function() {
return movebar = true;
}, false);
var movebar = true;
// MOVE HANDLE
actions.move = function(event) {
var clientX = ('ontouchstart' in document.documentElement) ? event.touches[0].clientX : event.clientX;
leftOffset = clientX - posX;
// move handle bar
if (movebar) {
element.style.left = leftOffset + "px";
var v = leftOffset.map(0, elWidth, 0, window.range); // 0
var value = v.roundTo(step);
output.innerHTML = value.toFixed(2);
// prevent handles ovelaping
if (vsOpts.range) {
var diff = Math.abs(parseInt(handle1.offsetLeft) - parseInt(handle2.offsetLeft));
if (diff < 20) {
movebar = false;
}
}
}
}
I solved it by assigning position of the opposite handle as a limit position of the current handle
document.addEventListener(EVstart, function(event) {
if (event.target.id == "vslider-handle1") {
useHandle1 = true
} else {
useHandle1 = false
}
return movebar = true;
}, false);
}
handle1Limit=parseInt(handle2.offsetLeft);
handle2Limit=parseInt(handle1.offsetLeft);
handle1Pos= parseInt(handle1.offsetLeft);
handle2Pos= parseInt(handle2.offsetLeft);
if(useHandle1){
if(handle1Pos>=handle1Limit){
handle1.style.left = handle1Limit + "px";
handle2.style.left = handle1Limit + "px";
}
}
else{
if(handle2Pos<=handle2Limit){
handle2.style.left = handle2Limit + "px";
handle1.style.left = handle2Limit + "px";
}
}

How to make a element follow another element when dragging with jquery?

I need make a element follow another element when dragging, but with delay in the animation, is similar to "Chat heads of facebook's messenger", you know, the bubbles on Android.
This is my jQuery plugin:
// Draggable plugin
(function($) {
$.fn.drag = function(options) {
options = $.extend({
handle: null,
cursor: 'move',
draggingClass: 'dragging',
heads: null
}, options);
var $handle = this,
$drag = this;
if( options.handle ) {
$handle = $(options.handle);
}
$handle
.css('cursor', options.cursor)
.on("mousedown", function(e) {
var x = $drag.offset().left - e.pageX,
y = $drag.offset().top - e.pageY,
z = $drag.css('z-index');
$drag.css('z-index', 100000);
$(document.documentElement)
.on('mousemove.drag', function(e) {
var chats = $($(options.heads).get().reverse());
chats.each(function(i) {
$(chats[i]).css({ left: $drag.position().left - (10*i)});
$(chats[i]).css({top: $drag.position().top});
});
$drag.offset({
left: x + e.pageX,
top: y + e.pageY
});
})
.one('mouseup', function() {
$(this).off('mousemove.drag');
$drag.css('z-index', z);
var window_width = $(window).width();
var window_height = $(window).height();
var head_wpostion = $(options.heads).position().left;
var head_hposition = $(options.heads).position().top;
if( head_wpostion > (window_width / 2) )
{
$(options.heads).animate({left: (window_width-40)+"px"}, 300 );
$(options.heads).animate({left: (window_width-50)+"px"}, 300 );
}
else
{
$(options.heads).animate({left: "-15px"}, 300 );
$(options.heads).animate({left: "-5px"}, 300 );
}
if( head_hposition > (window_height - 50) )
{
$(options.heads).animate({top: (window_height-75)+"px"}, 200 );
$(options.heads).animate({top: (window_height-65)+"px"}, 200 );
}
if( head_hposition < 0 )
{
$(options.heads).animate({top: "15px"}, 150 );
$(options.heads).animate({top: "5px"}, 150 );
}
});
// disable selection
e.preventDefault();
});
};
})(jQuery);
the only way you can do that is if you position the element you want to to be dragged along relevant to the drag-able element.

Backbone.js Mobile Slider - Passing Variable through View Functions

I'm following this tutorial to build a mobile slider: http://mobile.smashingmagazine.com/2012/06/21/play-with-hardware-accelerated-css/
The only difference is, I'm trying to incorporate it into Backbone. However, I've run into a variable problem. Can anyone offer some advice as to how to get this to work. Passing these variables throughout the View's functions is the problem:
var sliding = startClientX = startPixelOffset = pixelOffset = currentSlide = 0,
slideCount = $('.slide').length;
Full Backbone View:
WhiteDeals.Views.EditorView = Backbone.View.extend({
initialize: function() {
_.bindAll(this, 'render', 'slideStart', 'slide');
var sliding = startClientX = startPixelOffset = pixelOffset = currentSlide = 0,
slideCount = $('#dealSlide').length;
},
events: {
"touchstart" : "slideStart",
"mousedown" : "slideStart",
"mouseup" : "slideEnd",
"touchend" : "slideEnd",
"mousemove" : "slide",
"touchmove" : "slide"
},
slideStart: function(event) {
if (event.originalEvent.touches)
event = event.originalEvent.touches[0];
if (sliding == 0) {
sliding = 1;
startClientX = event.clientX;
}
}, // End slideStart
slide: function(event) {
event.preventDefault();
if (event.originalEvent.touches)
event = event.originalEvent.touches[0];
var deltaSlide = event.clientX - startClientX;
if (sliding == 1 && deltaSlide != 0) {
sliding = 2;
startPixelOffset = pixelOffset;
}
if (sliding == 2) {
var touchPixelRatio = 1;
if ((currentSlide == 0 && event.clientX > startClientX) ||
(currentSlide == slideCount - 1 && event.clientX < startClientX))
touchPixelRatio = 3;
pixelOffset = startPixelOffset + deltaSlide / touchPixelRatio;
$('#dealSlider').css('transform', 'translate3d(' + pixelOffset + 'px,0,0)').removeClass();
}
},
slideEnd: function(event) {
if (sliding == 2) {
sliding = 0;
currentSlide = pixelOffset < startPixelOffset ? currentSlide + 1 : currentSlide - 1;
currentSlide = Math.min(Math.max(currentSlide, 0), slideCount - 1);
pixelOffset = currentSlide * -$('body').width();
$('#temp').remove();
$('<style id="temp">#dealSlider.animate{transform:translate3d(' + pixelOffset + 'px,0,0)}</style>').appendTo('head');
$('#dealSlider').addClass('animate').css('transform', '');
}
}, // End slideEnd
render: function() {
this.$el.html(JST['editor/view']());
return this;
}
}); // End of Views EditorView
I would pack those variable into a model, like:
var CoordsModel = Backbone.Model.extend({})
var coord = new CoordsModel();
then pass it to the WhiteDeals view:
var view = new WhiteDeals({model: coord});
then accros all functions, through models' getters/setter I have access to its variables, for example:
initialize: function() {
_.bindAll(this, 'render', 'slideStart', 'slide');
// var sliding = startClientX = startPixelOffset = pixelOffset = currentSlide = 0
this.model.set('sliding', 0);
this.model.set('startClientX', 0);
...
this.model.set('currentSlide', 0);
slideCount = $('#dealSlide').length;
},
...
slideStart: function(event) {
if (event.originalEvent.touches)
event = event.originalEvent.touches[0];
if (sliding == 0) {
// sliding = 1;
// startClientX = event.clientX;
this.model.set('sliding', 1);
this.model.set('startClientX', event.clientX);
}
}, // End slideStart

Find the place of a cursor in rectangle

I don't know how to find the place part (one of 4 triangles) of a cursor in a rectangle.
This image is more efficient than my explication :s
Im in javascript (so the rectangle is a DIV, 0,0 placed)
I have those varaibles :
var cursor_x = e.clientX + $(document).scrollLeft()
var cursor_y = e.clientY + $(document).scrollTop()
var rect_w = $( rectangle ).width()
var rect_h = $( rectangle ).height()
I just want to know mathematically where is the cursor, in the triangle 1, 2, 3 or 4
What I think is the easiest way is to first normalize y so the computation is the same as for a square and then check for on which side of the diagonals you are...
var ynorm = y * w / h;
var s1 = x > ynorm ? 0 : 1;
var s2 = (w - x) > ynorm ? 0 : 1;
var area = s1*2 + s2;
the final area variable is a number between 0 and 3 telling in which of the four parts you are.
#6502: Thk you, its very helpful.
For more info, im working on an experimental light sortable jquery plugin, that can work with floating placement (top, left, right, bottom)
the code :
simply use $( ..selector.. ).sortable({ items: ..selector.. })
-
$.fn.sortable = function( o ) {
o.self = this;
o.helper = null;
$(document).bind('mouseup.sortable', function(e) {
if( o.sortable ) {
o.sortable.css({ opacity: ''});
if( o.target ) {
if( o.area == 's' ) {
o.sortable.css({ float: '' })
}
else if( o.area == 'n' ) {
o.sortable.css({ float: '' })
o.target.css({ float: '' })
}
else if( o.area == 'w' ) {
o.target.css({ float: 'left' })
o.sortable.css({ float: 'left' })
}
else if( o.area == 'e' ) {
o.target.css({ float: 'left' })
o.sortable.css({ float: 'left' })
}
o.target[ o.area == 's' || o.area == 'e' ? 'before':'after']( o.sortable );
o.target[0].style.setProperty( 'cursor', false , false);
o.target = null;
}
o.helper.remove();
o.sortable = null;
}
}).bind('mousemove.sortable', function(e) {
if( o.sortable ) {
o.ex = e.clientX + $(document).scrollLeft() + 10
o.ey = e.clientY + $(document).scrollTop() - o.sortable[0]._height - 10
o.helper.css({ left: o.ex, top: o.ey });
}
});
return $( this.selector ).delegate( o.items, 'mousemove.sortable', function(e) {
if( o.sortable && o.sortable[0] != this ) {
var self = $(this)
var x = e.clientX + $(document).scrollLeft() - self.offset().left
var y = e.clientY + $(document).scrollTop() - self.offset().top
var w = self.width()
var h = self.height()
var ynorm = y * w / h;
o.area = (w - x) > ynorm ? ( x > ynorm ? 's':'e' ) : ( x > ynorm ? 'w':'n' );
this.style.setProperty( 'cursor', o.area+'-resize', 'important');
o.target = self;
}
}).delegate( o.items, 'mousedown.sortable', function( e ) {
o.sortable = $(this).css({ opacity: 0.4 });
this._width = o.sortable.width();
this._height = o.sortable.height();
o.helper = o.sortable.clone().css({ position: 'absolute', left: -99999, top: 0 })
$('body').append( o.helper )
return false;
});
}

Categories