Skip to content

Commit

Permalink
Merge 1ad58fd into f4a7dfc
Browse files Browse the repository at this point in the history
  • Loading branch information
caitp committed Apr 17, 2015
2 parents f4a7dfc + 1ad58fd commit caf1992
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 145 deletions.
1 change: 1 addition & 0 deletions angularDrop.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
angularDropFiles = {
'angularDropSrc': [
'src/utils.js',
'src/dndDOM.js',
'src/draggable.js',
'src/droppable.js',
'src/provider.js',
Expand Down
175 changes: 175 additions & 0 deletions src/dndDOM.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
'use strict';

/**
* @ngdoc object
* @module ui.drop
* @name ui.drop.$dndDOM
* @requires $document
* @requires $window
*
* @description
*
* A set of utility methods that can be use to retrieve and manipulate DOM properties.
*
* (based on https://github.com/angular-ui/bootstrap/blob/master/src/position/position.js)
*
*/
var $dndDOMFactory = ['$document', '$window', function ($document, $window) {

function getStyle(el, cssprop) {
if (el.currentStyle) { //IE
return el.currentStyle[cssprop];
} else if ($window.getComputedStyle) {
return $window.getComputedStyle(el)[cssprop];
}
// finally try and get inline style
return el.style[cssprop];
}

/**
* Checks if a given element is statically positioned
* @param element - raw DOM element
*/
function isStaticPositioned(element) {
return (getStyle(element, 'position') || 'static' ) === 'static';
}

/**
* returns the closest, non-statically positioned parentOffset of a given element
* @param element
*/
var parentOffsetEl = function (element) {
var docDomEl = $document[0];
var offsetParent = element.offsetParent || docDomEl;
while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) {
offsetParent = offsetParent.offsetParent;
}
return offsetParent || docDomEl;
};

function contains(a, b) {
var adown = a.nodeType === 9 ? a.documentElement : a,
bup = b && b.parentNode;
return a === bup || !!( bup && bup.nodeType === 1 && contains(adown, bup) );
};

function swapCss(element, css, callback, args) {
var ret, prop, old = {};
for (prop in css) {
old[prop] = element.style[prop];
element.style[prop] = css[prop];
}

ret = callback.apply(element, args || []);

for (prop in css) {
element.style[prop] = old[prop];
}

return ret;
};

var swapDisplay = /^(none|table(?!-c[ea]).+)/;

var cssShow = {
position: 'absolute',
visibility: 'hidden',
display: 'block'
};

return {
/**
* Provides read-only equivalent of jQuery's position function:
* http://api.jquery.com/position/
*/
position: function (element) {
var elBCR = this.offset(element);
var offsetParentBCR = { top: 0, left: 0 };
var offsetParentEl = parentOffsetEl(element[0]);
if (offsetParentEl != $document[0]) {
offsetParentBCR = this.offset(angular.element(offsetParentEl));
offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;
offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;
}

var boundingClientRect = element[0].getBoundingClientRect();
return {
width: boundingClientRect.width || element.prop('offsetWidth'),
height: boundingClientRect.height || element.prop('offsetHeight'),
top: elBCR.top - offsetParentBCR.top,
left: elBCR.left - offsetParentBCR.left
};
},

/**
* Provides read-only equivalent of jQuery's offset function:
* http://api.jquery.com/offset/
*/
offset: function (element) {

var doc = element[0] && element[0].ownerDocument;

if (!doc) {
return;
}

doc = doc.documentElement;

if (!contains(doc, element[0])) {
return { top: 0, left: 0 };
}

var boundingClientRect = element[0].getBoundingClientRect();
return {
width: boundingClientRect.width || element.prop('offsetWidth'),
height: boundingClientRect.height || element.prop('offsetHeight'),
top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop),
left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft)
};
},

/**
* Partial implementation of https://api.jquery.com/closest/
* @param element
* @param value
* @returns {angular.element}
*/
closest: function(element, value) {
element = angular.element(element);
if ($.fn && angular.isFunction($.fn.closest)) {
return element.closest(value);
}
// Otherwise, assume it's a tag name...
element = element[0];
value = value.toLowerCase();
do {
if (element.nodeName.toLowerCase() === value) {
return angular.element(element);
}
} while (element = element.parentNode);
},

size: function(element) {
var jq = angular.element(element);
element = element.nodeName ? element : element[0];
if (element.offsetWidth === 0 && swapDisplay.test(jq.css('display'))) {
return swapCss(element, cssShow, getHeightAndWidth, [element]);
}
return getHeightAndWidth(element);

function getHeightAndWidth(element) {
return {
width: element.offsetWidth,
height: element.offsetHeight
};
}
},

keepSize: function(element) {
var css = this.size(element);
css.width = css.width + 'px';
css.height = css.height + 'px';
return css;
}
};
}];
66 changes: 33 additions & 33 deletions src/draggable.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ var $dragProvider = function() {
* a mechanism to drag-enable any arbitrary element, which allows it to be used in
* custom directives, so that custom dragging behaviour can be achieved.
*/
this.$get = ['$document', '$drop', function($document, $drop) {
this.$get = ['$document', '$drop', '$dndDOM', function($document, $drop, $dndDOM) {
var $drag = {
/**
* @ngdoc method
Expand Down Expand Up @@ -197,7 +197,7 @@ var $dragProvider = function() {
currentDrag = self;

self.cssDisplay = self.element.css('display');
self.dimensions = DOM.size(self.element);
self.dimensions = $dndDOM.size(self.element);
if (!self.hanging) {
self.cssPosition = self.element.css("position");

Expand All @@ -206,23 +206,23 @@ var $dragProvider = function() {
width: self.element[0].style['width'],
height: self.element[0].style['height']
};
self.element.css(DOM.keepSize(self.element));
self.element.css($dndDOM.keepSize(self.element));
}
}

if (typeof self.options.dragWithin === 'string') {
self.constraints = dragConstraints(self.options.dragWithin, self.element);
}

self.offset = self.positionAbs = DOM.offset(self.element);
self.offset = $dndDOM.position(self.element);

self.offset.scroll = false;

angular.extend(self.offset, {
click: {
top: event.pageY - self.offset.top,
left: event.pageX - self.offset.left
},
}
});

self.lastMouseY = event.pageY;
Expand All @@ -232,8 +232,8 @@ var $dragProvider = function() {

self.element.css({
position: 'absolute',
left: self.offset.left,
top: self.offset.top
left: self.offset.left + 'px', //jqlite does not support raw Number
top: self.offset.top + 'px'
});

$document.on("mousemove", self.drag);
Expand Down Expand Up @@ -354,6 +354,32 @@ var $dragProvider = function() {
}
};

function dragConstraints(value, element) {
if (value.length === '') {
return;
}
if (/^(\.|#)/.test(value) && $.fn && angular.isFunction($.fn.closest)) {
// Find nearest element matching class
return constraintsFor(element.parent().closest(value));
}
if (/^(\^|parent)$/.test(value)) {
return constraintsFor(element.parent());
}
return constraintsFor($dndDOM.closest(element.parent(), value));
};

function constraintsFor(element) {
if (typeof element === 'undefined' || element.length === 0) {
return;
}
// Use offset + width/height for now?
var constraints = $dndDOM.offset(element),
dimensions = $dndDOM.size(element);
constraints.right = constraints.left + dimensions.width;
constraints.bottom = constraints.top + dimensions.height;
return constraints;
};

/**
* @ngdoc property
* @module ui.drop
Expand Down Expand Up @@ -409,32 +435,6 @@ var $dragProvider = function() {
return angular.isObject(thing) && thing.constructor === Draggable;
}

function dragConstraints(value, element) {
if (value.length === '') {
return;
}
if (/^(\.|#)/.test(value) && $.fn && angular.isFunction($.fn.closest)) {
// Find nearest element matching class
return constraintsFor(element.parent().closest(value));
}
if (/^(\^|parent)$/.test(value)) {
return constraintsFor(element.parent());
}
return constraintsFor(DOM.closest(element.parent(), value));
}

function constraintsFor(element) {
if (typeof element === 'undefined' || element.length === 0) {
return;
}
// Use offset + width/height for now?
var constraints = DOM.offset(element),
dimensions = DOM.size(element);
constraints.right = constraints.left + dimensions.width;
constraints.bottom = constraints.top + dimensions.height;
return constraints;
}

function withinConstraints(c, x, y, w, h) {
return x >= c.left && (x+w) <= c.right && y >= c.top && (y+h) <= c.bottom;
}
Expand Down
2 changes: 2 additions & 0 deletions src/public.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ function publishExternalAPI() {
}]).directive({
draggable: draggableDirective,
droppable: droppableDirective
}).factory({
$dndDOM: $dndDOMFactory
});
}
Loading

0 comments on commit caf1992

Please sign in to comment.