jQuery UI draggable with selective mousebutton (left-right simultaniously) on selective elements - javascript

I use jQuery UI to drag div elements. There is a div, it is draggable, when I drag with the left mouse button. I'd like to drag it with the right mouse button, too. So I want the item to be dragged with the left and the right mouse button. But only this div element, other elements are draggable only with left mouse button.
I modify the jQuery UI js file, like this:
$(document).ready(function () {
//override jQuery UI draggable
$.extend($.ui.draggable.prototype, {
_mouseDown: function (event) {
// we may have missed mouseup (out of window)
(this._mouseStarted && this._mouseUp(event));
this._mouseDownEvent = event;
var that = this,
btnIsLeft = (event.type === 'mousedown'),
// event.target.nodeName works around a bug in IE 8 with
// disabled inputs (#7620)
elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
return true;
}
this.mouseDelayMet = !this.options.delay;
if (!this.mouseDelayMet) {
this._mouseDelayTimer = setTimeout(function () {
that.mouseDelayMet = true;
}, this.options.delay);
}
if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
this._mouseStarted = (this._mouseStart(event) !== false);
if (!this._mouseStarted) {
event.preventDefault();
return true;
}
}
// Click event may never have fired (Gecko & Opera)
if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
$.removeData(event.target, this.widgetName + ".preventClickEvent");
}
// these delegates are required to keep context
this._mouseMoveDelegate = function (event) {
return that._mouseMove(event);
};
this._mouseUpDelegate = function (event) {
return that._mouseUp(event);
};
$(document)
.bind("mousemove." + this.widgetName, this._mouseMoveDelegate)
.bind("mouseup." + this.widgetName, this._mouseUpDelegate);
event.preventDefault();
mouseHandled = true;
return true;
}
});
});
The change is here:
btnIsLeft = (event.type === 'mousedown'),
With this code my specific div element works fine, it works with the left and right mouse button, too, but other elements are draggable with both mouse button what I don't want.
My div element is this (I'd like to apply only this with the right and left draggable function):
$('.mydiv_with_right_and_left_drag').draggable({
scroll: false,
delay: 0,
distance: 0,
cursor: 'hand',
snap: false,
cursor: 'pointer',
stack: '.mydiv_with_right_and_left_drag',
containment: 'parent',
opacity: 0.35,
});
JSFIDDLE SOURCE
It can be workable somehow? Thanks.

Related

CKEDITOR Widgets drag drop into needed element

I have a problem with ckeditor widgets. I have inline non-editable text widget which I can drag drop enywhere in editor (using its default functionality). So I need to check where I'm dropping my widget and if this place is undroppable (according my rules it us TABLE) do cancel events propagations and widget should stay on previous place.
editor.widgets.add('customWidgetAdd', {
inline: true,
template: '<span class="simplebox">' +
'<span class="simplebox-title" ></span>' +
'</span>',
init: function(){
var that = this;
that.widgetData = ko.observable(self.activeWidgetData);
var subscription = that.widgetData.subscribe(function (value) {
$(that.element.$).find('.simplebox-title').text(value.name);
if (that.isSelected) {
self.activeWidgetData = value;
}
});
var destroyListener = function(ev){
subscription.dispose();
};
that.once('destroy', destroyListener);
that.on('doubleclick', function (evt) {
editor.execCommand(editAction.command);
});
that.on('select', function (evt){
that.isSelected = true;
self.activeWidgetData = that.widgetData();
});
that.on('deselect', function (evt){
try {
var endContainer = editor.getSelection().getRanges()[0].endContainer.getName();
} catch (e) {
}
that.isSelected = false;
if (endContainer == 'td' || endContainer == 'th') {
//SO here comes the problem. My rule is executed and
//I want CKEDITOR do nothing from here... but stil widget is getting cutted from DOM and inserted to place where I have dropped it...
//that.removeListener('destroy', destroyListener);
//that.removeAllListeners();
evt.cancel();
evt.stop();
return false;
}
});
}
});
Unfortunately there is no easy solution in this situation.
The only one way you can do it is to subscribe to editor's drop event, and cancel it if needed, like:
editor.on('contentDom', function() {
var editable = editor.editable(),
// #11123 Firefox needs to listen on document, because otherwise event won't be fired.
// #11086 IE8 cannot listen on document.
dropTarget = (CKEDITOR.env.ie && CKEDITOR.env.version < 9) || editable.isInline() ? editable : editor.document;
editable.attachListener(dropTarget, 'drop', function(evt) {
//do all checks here
});
});
You can find how it works in CKEditor (See code of function setupDragAndDrop)

jquery angularjs how to know if mouse down event is trigger by scrollbar of browser

I have a small panel which i close if mouse down button is pressed anywhere else than that panel, basically it clears the data to display and just with the help of angularjs ng-show i hide it if there is no data...application is in angularjs and jquery
please find the code below
var closeSearchResultsIfClickedOutside = function (e) {
if ($(e.target).parents('.searchResults').length === 0) {
var scope = angular.element($("#searchContainer")).scope();
scope.$apply(function () {
/*Cancels any existing search*/
if ($scope.defer != undefined) {
$scope.defer.resolve();
}
$scope.showSearchResults = false;
reinitialize();
});
$("html").off("mousedown", closeSearchResultsIfClickedOutside);
reinitializePanelsWidth();
}
};
but i dont want to close this panel if mouse down is on scrollbar of browser window or any scrollbar..please tell me how to do that
to fix the above problem i am not capturing both event, mouse down and click, if the target element on both event matches then only i am closing the panel.
/*
If mouse down and click on the same control, then only close the panel,
Click event closing is added to avoid closing panel on scrollbar click.
*/
var closeSearchResultsIfClickedOutside = function (e) {
if (e.type === 'mousedown') { /* only if mouse down is outside of search panel then only close the panel. */
if($(e.target).parents('.searchResults').length === 0)
{
isMouseDownOnSearchPanel = true;
}
else {
isMouseDownOnSearchPanel = false;
}
}
else if (e.type === 'click' && isMouseDownOnSearchPanel) { /*click event is implemented to avoid closing when mouse down is on scrollbar. you dont get click get event for scrollbar*/
var scope = angular.element($("#searchContainer")).scope();
$("html").off("mousedown", closeSearchResultsIfClickedOutside);
$("html").off("click", closeSearchResultsIfClickedOutside);
isMouseDownOnSearchPanel = false;
reinitializePanelsWidth();
}
};

Using jQuery draggable API to scroll sideways or drag down

The image below illustrates a problem that I'm experiencing with jQuery's Draggable method. I have a list of products. When users swipe left or right, the products should scroll accordingly. When users swipe down, they should be able to drag the items downward. Here's the issue: although I can successfully differentiate between vertical and horizontal swipes, I can't enable and disable jQuery drag functionality at the right times.
Here is my code:
var touchPos = {
x: null,
y: null,
threshold: {
x: 20,
y: 20
}
};
// Shortcut for getting finger position from touch event
// This is working correctly
var getClient = function (ev, axis) {
var touches = ev.touches || ev.originalEvent.touches;
return touches[0]['client' + axis];
};
// All of the products are draggable by default
$el.draggable({
containment: '.pageWrapper',
cursor: 'move',
revert: 'invalid',
helper: 'clone',
disabled: false
});
function disableDragging () {
$el.draggable('option', 'cancel', '.planSquare');
$el.draggable("option", "disabled", true );
}
function enableDragging () {
$el.draggable('option', 'cancel', '.pageWrapper');
$el.draggable("option", "disabled", false);
}
// When the user starts moving a product
element.bind('touchstart', function (event) {
// Capture finger position
touchPos.x = getClient(event, 'X');
touchPos.y = getClient(event, 'Y');
if ($el.hasClass('unselectable')) {
return false;
}
$el.css('border-color', 'transparent');
});
element.bind('touchmove', function(event) {
// Update the position of the user's finger
var newY = getClient(event, 'Y');
var newX = getClient(event, 'X');
var draggingDown = newY - touchPos.y >= touchPos.threshold.y;
var draggingSideways = Math.abs(newX - touchPos.x) >= touchPos.threshold.x;
if (!draggingDown && draggingSideways) {
disableDragging();
}
});
// When the user stops moving a square
element.bind('touchend', function () {
touchPos.x = null;
touchPos.y = null;
enableDragging();
$el.css('border-color', '#ccc')
});
The enableDragging and disableDragging have the desired effect when I call them outside the context of the touch event. My hypothesis is that, using jQuery UI, I can't disable dragging once a drag event has already begun. To recap, my goal is to disable dragging and switch to native horizontal scrolling if the user is not dragging down.
Can someone recommend a good approach for toggling between dragging and native scrolling behavior?

Can I toggle popup after a click event with a mouseout event?

I'm using twitter bootstrap to display popovers with a click event. I'm requesting the info with the click event but I want to hide the popover after it looses focus so the user isn't required to click it again. Is this possible?
Basically I want to show the popover with a click event but then when the launch point looses focus from the mouse the popover is hidden.
Here is a link to the popover doc from twitter-bootstrap: http://twitter.github.com/bootstrap/javascript.html#popovers
This is what I'm currently doing:
jQuery:
$('.knownissue').on('click', function() {
var el = $(this);
if (el.data('showissue') == 'true') {
el.popover('toggle');
el.data('showissue', 'false');
return;
}
$.post('functions/get_known_issues.php', function(data) {
if (data.st) {
el.attr('data-content', data.issue);
el.popover('toggle');
el.data('showissue', 'true');
}
}, "json");
});
Any thoughts?
The following should work.
$('.knownissue').mouseleave(function() {
$(this).popover('hide');
});
Here is a custom jQuery event I call 'clickoutside'. It gets fired if and only if you click the mouse outside of the target element. It could easily be adapted for other event types (mousemove, keydown, etc). In your case, when fired it could close your modal.
(function ($) {
var count = 0;
$.fn.clickoutside = function (handler) {
// If the source element does not have an ID, give it one, so we can reference it
var self = $(this);
var id = self.attr('id');
if (id === '') {
id = 'clickoutside' + count++;
self.attr('id', id);
}
// Watch for the event everywhere
$('html').click(function (e) {
var source = $(e.target);
// ... but, stop it from propagating if it is inside the target
// element. The result being only events outside the target
// propagate to the top.
if (source.attr('id') == id || source.parents('#' + id).length > 0) {
return;
}
handler.call(this, e);
})
};
})(jQuery);
$('#targetElement').clickoutside(function(){
});
EDIT: Example JSFiddle.

Fabric.js right mouse click

Is there a way to receive right click mouse events on a Fabric.js canvas?
The following code works only with left click:
canvas.observe('mouse:down', function(){console.log('mouse down'));
NOTE: Most answers above are outdated; this answer applies to the latest Fabric version 2.7.0
Simply enable firing right/middle click events for your Fabric canvas
The config for firing right click and middle click events in the canvas can be found here for fireRightClick and here for fireMiddleClick and are set to false by default. This means right and middle click events are by default disabled.
The parameter stopContextMenu for stopping context menu to show up on the canvas when right clicking can be found here
You can enable these simply by setting the values when creating your canvas:
var canvas = new fabric.Canvas('canvas', {
height: height,
width: width,
fireRightClick: true, // <-- enable firing of right click events
fireMiddleClick: true, // <-- enable firing of middle click events
stopContextMenu: true, // <-- prevent context menu from showing
});
Now your mousedown event will fire for all clicks and you can distinguish them by using the button identifier on the event:
For canvas:
canvas.on('mouse:down', (event) => {
if(event.button === 1) {
console.log("left click");
}
if(event.button === 2) {
console.log("middle click");
}
if(event.button === 3) {
console.log("right click");
}
}
For objects:
object.on('mousedown', (event) => {
if(event.button === 1) {
console.log("left click");
}
if(event.button === 2) {
console.log("middle click");
}
if(event.button === 3) {
console.log("right click");
}
}
When clicking on objects you can reach the "real" mouse dom event through event.e:
if(event.button === 3){
console.log(event.e);
}
I've implemented right click by extending the fabric.Canvas class. Take a look here the _onMouseDown method.
Basically the right mouse down event for an object was disabled in fabricjs by default.
If you want to handle right clicks (on canvas or its objects), then set context menu listener on upper-canvas element. Using canvas method findTarget you can check if any target was clicked and if so, you can check type of the target.
let scope = this;
jQuery(".upper-canvas").on('contextmenu', function (options: any) {
let target: any = scope.canvas.findTarget(options, false);
if (target) {
let type: string = target.type;
if (type === "group") {
console.log('right click on group');
} else {
scope.canvas.setActiveObject(target);
console.log('right click on target, type: ' + type);
}
} else {
scope.canvas.discardActiveObject();
scope.canvas.discardActiveGroup();
scope.canvas.renderAll();
console.log('right click on canvas');
}
options.preventDefault();
});
The way I did this was to listen for a right click event across the entire canvas and match up the x,y coordinates of the click event to the object which is currently sitting at the given location. This solution feels a little like a hack but hey, it works!
$('#my_canvas').bind('contextmenu', function (env) {
var x = env.offsetX;
var y = env.offsetY;
$.each (canvas._objects, function(i, e) {
// e.left and e.top are the middle of the object use some "math" to find the outer edges
var d = e.width / 2;
var h = e.height / 2;
if (x >= (e.left - d) && x <= (e.left+d)) {
if(y >= (e.top - h) && y <= (e.top+h)) {
console.log("clicked canvas obj #"+i);
//TODO show custom menu at x, y
return false; //in case the icons are stacked only take action on one.
}
}
});
return false; //stops the event propigation
});
Here's what I did, which makes use of some built-in fabric object detection code:
$('.upper-canvas').bind('contextmenu', function (e) {
var objectFound = false;
var clickPoint = new fabric.Point(e.offsetX, e.offsetY);
e.preventDefault();
canvas.forEachObject(function (obj) {
if (!objectFound && obj.containsPoint(clickPoint)) {
objectFound = true;
//TODO: whatever you want with the object
}
});
});

Categories