This repository has been archived on 2024-07-11. You can view files and clone it, but cannot push or open issues or pull requests.
yoshop/web/assets/common/js/jquery.dad.js

308 lines
9.2 KiB
JavaScript
Raw Permalink Normal View History

2020-04-25 22:20:29 +08:00
/*!
* jquery.dad.js v1 (http://konsolestudio.com/dad)
* Author William Lima
*/
(function ($) {
'use strict';
var supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints;
$.fn.dad = function (opts) {
var _this = this;
var defaults = {
target: '>div',
draggable: false,
placeholder: '',
callback: false,
containerClass: 'dad-container',
childrenClass: 'dads-children',
cloneClass: 'dads-children-clone',
active: true,
};
var options = $.extend({}, defaults, opts);
$(this).each(function () {
var active = options.active;
var $daddy = $(this);
var childrenClass = options.childrenClass;
var cloneClass = options.cloneClass;
var jQclass = '.' + childrenClass;
var $target = $daddy.find(options.target);
var placeholder = options.placeholder;
var callback = options.callback;
var dragClass = 'dad-draggable-area';
var holderClass = 'dads-children-placeholder';
// HANDLE MOUSE
var mouse = {
x: 0,
y: 0,
target: false,
clone: false,
placeholder: false,
cloneoffset: {
x: 0,
y: 0,
},
updatePosition: function (e) {
this.x = e.pageX;
this.y = e.pageY;
},
move: function (e) {
this.updatePosition(e);
if (this.clone !== false && _this.target !== false) {
this.clone.css({
left: this.x - this.cloneoffset.x,
top: this.y - this.cloneoffset.y,
});
}
},
};
$(window).on('mousemove touchmove', function (e) {
var ev = e;
if (mouse.clone !== false && mouse.target !== false) e.preventDefault();
if (supportsTouch && e.type == 'touchmove') {
ev = e.originalEvent.touches[0];
var mouseTarget = document.elementFromPoint(ev.clientX, ev.clientY);
$(mouseTarget).trigger('touchenter');
}
mouse.move(ev);
});
$daddy.addClass(options.containerClass);
if (!$daddy.hasClass('dad-active') && active === true) {
$daddy.addClass('dad-active');
};
_this.addDropzone = function (selector, func) {
$(selector).on('mouseenter touchenter', function () {
if (mouse.target !== false) {
mouse.placeholder.css({ display: 'none' });
mouse.target.css({ display: 'none' });
$(this).addClass('active');
}
}).on('mouseup touchend', function () {
if (mouse.target != false) {
mouse.placeholder.css({ display: 'block' });
mouse.target.css({ display: 'block' });
func(mouse.target);
dadEnd();
};
$(this).removeClass('active');
}).on('mouseleave touchleave', function () {
if (mouse.target !== false) {
mouse.placeholder.css({ display: 'block' });
mouse.target.css({ display: 'block' });
}
$(this).removeClass('active');
});
};
// GET POSITION FUNCTION
_this.getPosition = function () {
var positionArray = [];
$(this).find(jQclass).each(function () {
positionArray[$(this).attr('data-dad-id')] = parseInt($(this).attr('data-dad-position'));
});
return positionArray;
};
_this.activate = function () {
active = true;
if (!$daddy.hasClass('dad-active')) {
$daddy.addClass('dad-active');
}
return _this;
};
// DEACTIVATE FUNCTION
_this.deactivate = function () {
active = false;
$daddy.removeClass('dad-active');
return _this;
};
// DEFAULT DROPPING
$daddy.on('DOMNodeInserted', function (e) {
var $thisTarget = $(e.target);
if (!$thisTarget.hasClass(childrenClass) && !$thisTarget.hasClass(holderClass)) {
$thisTarget.addClass(childrenClass);
}
});
$(document).on('mouseup touchend', function () {
dadEnd();
});
// ORDER ELEMENTS
var order = 1;
$target.addClass(childrenClass).each(function () {
if ($(this).data('dad-id') == undefined) {
$(this).attr('data-dad-id', order);
}
$(this).attr('data-dad-position', order);
order++;
});
// CREATE REORDER FUNCTION
function updatePosition(e) {
var order = 1;
e.find(jQclass).each(function () {
$(this).attr('data-dad-position', order);
order++;
});
}
// END EVENT
function dadEnd() {
if (mouse.target != false && mouse.clone != false) {
if (callback != false) {
callback(mouse.target);
}
var appear = mouse.target;
var desappear = mouse.clone;
var holder = mouse.placeholder;
var bLeft = 0;
var bTop = 0;
// Maybe we will use this in the future
//Math.floor(parseFloat($daddy.css('border-left-width')));
//Math.floor(parseFloat($daddy.css('border-top-width')));
if ($.contains($daddy[0], mouse.target[0])) {
mouse.clone.animate({
top: mouse.target.offset().top - $daddy.offset().top - bTop,
left: mouse.target.offset().left - $daddy.offset().left - bLeft,
}, 300, function () {
appear.css({
visibility: 'visible',
}).removeClass('active');
desappear.remove();
});
} else {
mouse.clone.fadeOut(300, function () {
desappear.remove();
});
}
holder.remove();
mouse.clone = false;
mouse.placeholder = false;
mouse.target = false;
updatePosition($daddy);
}
$('html, body').removeClass('dad-noSelect');
}
// UPDATE EVENT
function dadUpdate(obj) {
if (mouse.target !== false && mouse.clone !== false) {
var $origin = $('<span style="display:none"></span>');
var $newplace = $('<span style="display:none"></span>');
if (obj.prevAll().hasClass('active')) {
obj.after($newplace);
} else {
obj.before($newplace);
}
mouse.target.before($origin);
$newplace.before(mouse.target);
// UPDATE PLACEHOLDER
mouse.placeholder.css({
top: mouse.target.offset().top - $daddy.offset().top,
left: mouse.target.offset().left - $daddy.offset().left,
width: mouse.target.outerWidth() - 10,
height: mouse.target.outerHeight() - 10,
});
$origin.remove();
$newplace.remove();
}
}
// GRABBING EVENT
var jq = (options.draggable !== false) ? options.draggable : jQclass;
$daddy.find(jq).addClass(dragClass);
$daddy.on('mousedown touchstart', jq, function (e) {
// For touchstart we must update "mouse" position
if (e.type == 'touchstart') {
mouse.updatePosition(e.originalEvent.touches[0]);
}
if (mouse.target == false && active == true && (e.which == 1 || e.type == 'touchstart')) {
var $self = $(this);
// GET TARGET
if (options.draggable !== false) {
mouse.target = $daddy.find(jQclass).has(this);
} else {
mouse.target = $self;
}
// ADD CLONE
mouse.clone = mouse.target.clone();
mouse.target.css({ visibility: 'hidden' }).addClass('active');
mouse.clone.addClass(cloneClass);
$daddy.append(mouse.clone);
// ADD PLACEHOLDER
var $placeholder = $('<div></div>');
mouse.placeholder = $placeholder;
mouse.placeholder.addClass(holderClass);
mouse.placeholder.css({
top: mouse.target.offset().top - $daddy.offset().top,
left: mouse.target.offset().left - $daddy.offset().left,
width: mouse.target.outerWidth() - 10,
height: mouse.target.outerHeight() - 10,
lineHeight: mouse.target.height() - 18 + 'px',
textAlign: 'center',
}).text(placeholder);
$daddy.append(mouse.placeholder);
// GET OFFSET FOR CLONE
var bLeft = Math.floor(parseFloat($daddy.css('border-left-width')));
var bTop = Math.floor(parseFloat($daddy.css('border-top-width')));
var difx = mouse.x - mouse.target.offset().left + $daddy.offset().left + bLeft;
var dify = mouse.y - mouse.target.offset().top + $daddy.offset().top + bTop;
mouse.cloneoffset.x = difx;
mouse.cloneoffset.y = dify;
// REMOVE THE CHILDREN DAD CLASS AND SET THE POSITION ON SCREEN
mouse.clone.removeClass(childrenClass).css({
position: 'absolute',
top: mouse.y - mouse.cloneoffset.y,
left: mouse.x - mouse.cloneoffset.x,
});
// UNABLE THE TEXT SELECTION AND SET THE GRAB CURSOR
$('html,body').addClass('dad-noSelect');
}
});
$daddy.on('mouseenter touchenter', jQclass, function () {
dadUpdate($(this));
});
});
return this;
};
})(jQuery);