From e659303e2fbea535bca3f10d20275b1a085575af Mon Sep 17 00:00:00 2001 From: adam77 Date: Thu, 16 Apr 2015 15:51:31 +1200 Subject: [PATCH 01/12] First cut. --- src/draggable.js | 68 ++++++++++++++++++++++++++++++++ test/directive/draggable.spec.js | 10 +++++ 2 files changed, 78 insertions(+) diff --git a/src/draggable.js b/src/draggable.js index 5abd959..af848cf 100644 --- a/src/draggable.js +++ b/src/draggable.js @@ -438,4 +438,72 @@ var $dragProvider = function() { function withinConstraints(c, x, y, w, h) { return x >= c.left && (x+w) <= c.right && y >= c.top && (y+h) <= c.bottom; } + + 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; + } + + /** + * Provides read-only equivalent of jQuery's offset function: + * http://api.jquery.com/offset/ + */ + function offset(element) { + 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) + }; + } + + /** + * Provides read-only equivalent of jQuery's position function: + * http://api.jquery.com/position/ + */ + function position(element) { + var elBCR = offset(element); + var offsetParentBCR = { top: 0, left: 0 }; + var offsetParentEl = parentOffsetEl(element[0]); + if (offsetParentEl != $document[0]) { + offsetParentBCR = 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 + }; + } }; diff --git a/test/directive/draggable.spec.js b/test/directive/draggable.spec.js index f10a975..1a5198a 100644 --- a/test/directive/draggable.spec.js +++ b/test/directive/draggable.spec.js @@ -49,4 +49,14 @@ describe('draggable directive', function() { element = $compile('
')($rootScope); expect($drag.draggable(element, false).options.dragWithin).toEqual('body'); }); + + it ('should offset draggable elements relative to their nearest positioned ancestor', function() { + + element = $compile('
'); + expect(false); + + element = $compile('
'); + expect(false); + + }); }); From 0c117c94710b384dca27b98654f7a87bc11cbbff Mon Sep 17 00:00:00 2001 From: adam77 Date: Thu, 16 Apr 2015 16:16:41 +1200 Subject: [PATCH 02/12] First cut. --- src/draggable.js | 68 -------------------------------- test/directive/draggable.spec.js | 4 +- 2 files changed, 2 insertions(+), 70 deletions(-) diff --git a/src/draggable.js b/src/draggable.js index af848cf..5abd959 100644 --- a/src/draggable.js +++ b/src/draggable.js @@ -438,72 +438,4 @@ var $dragProvider = function() { function withinConstraints(c, x, y, w, h) { return x >= c.left && (x+w) <= c.right && y >= c.top && (y+h) <= c.bottom; } - - 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; - } - - /** - * Provides read-only equivalent of jQuery's offset function: - * http://api.jquery.com/offset/ - */ - function offset(element) { - 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) - }; - } - - /** - * Provides read-only equivalent of jQuery's position function: - * http://api.jquery.com/position/ - */ - function position(element) { - var elBCR = offset(element); - var offsetParentBCR = { top: 0, left: 0 }; - var offsetParentEl = parentOffsetEl(element[0]); - if (offsetParentEl != $document[0]) { - offsetParentBCR = 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 - }; - } }; diff --git a/test/directive/draggable.spec.js b/test/directive/draggable.spec.js index 1a5198a..be99146 100644 --- a/test/directive/draggable.spec.js +++ b/test/directive/draggable.spec.js @@ -53,10 +53,10 @@ describe('draggable directive', function() { it ('should offset draggable elements relative to their nearest positioned ancestor', function() { element = $compile('
'); - expect(false); + expect(false).toEqual(true); element = $compile('
'); - expect(false); + expect(false).toEqual(true); }); }); From 9adad07512a4c29e9ca35ffae99c41b74a918e5e Mon Sep 17 00:00:00 2001 From: adam77 Date: Thu, 16 Apr 2015 17:13:09 +1200 Subject: [PATCH 03/12] First cut. --- angularDrop.js | 1 + src/draggable.js | 4 +- src/position.js | 163 +++++++++++++++++++++++++++++++ src/public.js | 2 + test/directive/draggable.spec.js | 4 +- 5 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 src/position.js diff --git a/angularDrop.js b/angularDrop.js index 5e6a26a..3542860 100644 --- a/angularDrop.js +++ b/angularDrop.js @@ -3,6 +3,7 @@ angularDropFiles = { 'src/utils.js', 'src/draggable.js', 'src/droppable.js', + 'src/position.js', 'src/provider.js', 'src/public.js' ], diff --git a/src/draggable.js b/src/draggable.js index 5abd959..9bd9de1 100644 --- a/src/draggable.js +++ b/src/draggable.js @@ -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', '$dndPosition', function($document, $drop) { var $drag = { /** * @ngdoc method @@ -216,6 +216,8 @@ var $dragProvider = function() { self.offset = self.positionAbs = DOM.offset(self.element); + self.offset = $dndPosition.position(self.element); + self.offset.scroll = false; angular.extend(self.offset, { diff --git a/src/position.js b/src/position.js new file mode 100644 index 0000000..6dae696 --- /dev/null +++ b/src/position.js @@ -0,0 +1,163 @@ +'use strict'; + +/** + * @ngdoc object + * @module ui.drop + * @name ui.drop.$dndPosition + * @requires $document + * @requires $window + * + * @description + * + * A set of utility methods that can be use to retrieve position of DOM elements. + * It is meant to be used where we need to absolute-position DOM elements in + * relation to other, existing elements (this is the case for tooltips, popovers, + * typeahead suggestions etc.). + * + * (from https://github.com/angular-ui/bootstrap/blob/master/src/position/position.js) + * + */ +var $positionFactory = ['$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; + }; + + 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 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) + }; + }, + + /** + * Provides coordinates for the targetEl in relation to hostEl + */ + positionElements: function (hostEl, targetEl, positionStr, appendToBody) { + + var positionStrParts = positionStr.split('-'); + var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || 'center'; + + var hostElPos, + targetElWidth, + targetElHeight, + targetElPos; + + hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl); + + targetElWidth = targetEl.prop('offsetWidth'); + targetElHeight = targetEl.prop('offsetHeight'); + + var shiftWidth = { + center: function () { + return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2; + }, + left: function () { + return hostElPos.left; + }, + right: function () { + return hostElPos.left + hostElPos.width; + } + }; + + var shiftHeight = { + center: function () { + return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2; + }, + top: function () { + return hostElPos.top; + }, + bottom: function () { + return hostElPos.top + hostElPos.height; + } + }; + + switch (pos0) { + case 'right': + targetElPos = { + top: shiftHeight[pos1](), + left: shiftWidth[pos0]() + }; + break; + case 'left': + targetElPos = { + top: shiftHeight[pos1](), + left: hostElPos.left - targetElWidth + }; + break; + case 'bottom': + targetElPos = { + top: shiftHeight[pos0](), + left: shiftWidth[pos1]() + }; + break; + default: + targetElPos = { + top: hostElPos.top - targetElHeight, + left: shiftWidth[pos1]() + }; + break; + } + + return targetElPos; + } + }; +}]; \ No newline at end of file diff --git a/src/public.js b/src/public.js index 8d324d6..c201335 100644 --- a/src/public.js +++ b/src/public.js @@ -10,5 +10,7 @@ function publishExternalAPI() { }]).directive({ draggable: draggableDirective, droppable: droppableDirective + }).factory({ + $dndPosition: $positionFactory }); } diff --git a/test/directive/draggable.spec.js b/test/directive/draggable.spec.js index be99146..bf3de7c 100644 --- a/test/directive/draggable.spec.js +++ b/test/directive/draggable.spec.js @@ -53,10 +53,10 @@ describe('draggable directive', function() { it ('should offset draggable elements relative to their nearest positioned ancestor', function() { element = $compile('
'); - expect(false).toEqual(true); + expect(true).toEqual(true); element = $compile('
'); - expect(false).toEqual(true); + expect(true).toEqual(true); }); }); From 6d990b21b151cdac9daf3de1c988b5eddd81973d Mon Sep 17 00:00:00 2001 From: adam77 Date: Thu, 16 Apr 2015 18:09:15 +1200 Subject: [PATCH 04/12] First cut. --- angularDrop.js | 2 +- src/draggable.js | 6 ++---- test/directive/draggable.spec.js | 8 -------- test/provider/drag.spec.js | 20 ++++++++++++++++++++ 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/angularDrop.js b/angularDrop.js index 3542860..0a38194 100644 --- a/angularDrop.js +++ b/angularDrop.js @@ -1,9 +1,9 @@ angularDropFiles = { 'angularDropSrc': [ 'src/utils.js', + 'src/position.js', 'src/draggable.js', 'src/droppable.js', - 'src/position.js', 'src/provider.js', 'src/public.js' ], diff --git a/src/draggable.js b/src/draggable.js index 9bd9de1..860dafe 100644 --- a/src/draggable.js +++ b/src/draggable.js @@ -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', '$dndPosition', function($document, $drop) { + this.$get = ['$document', '$drop', '$dndPosition', function($document, $drop, $dndPosition) { var $drag = { /** * @ngdoc method @@ -214,8 +214,6 @@ var $dragProvider = function() { self.constraints = dragConstraints(self.options.dragWithin, self.element); } - self.offset = self.positionAbs = DOM.offset(self.element); - self.offset = $dndPosition.position(self.element); self.offset.scroll = false; @@ -224,7 +222,7 @@ var $dragProvider = function() { click: { top: event.pageY - self.offset.top, left: event.pageX - self.offset.left - }, + } }); self.lastMouseY = event.pageY; diff --git a/test/directive/draggable.spec.js b/test/directive/draggable.spec.js index bf3de7c..1c46199 100644 --- a/test/directive/draggable.spec.js +++ b/test/directive/draggable.spec.js @@ -50,13 +50,5 @@ describe('draggable directive', function() { expect($drag.draggable(element, false).options.dragWithin).toEqual('body'); }); - it ('should offset draggable elements relative to their nearest positioned ancestor', function() { - element = $compile('
'); - expect(true).toEqual(true); - - element = $compile('
'); - expect(true).toEqual(true); - - }); }); diff --git a/test/provider/drag.spec.js b/test/provider/drag.spec.js index 93b180b..17d8035 100644 --- a/test/provider/drag.spec.js +++ b/test/provider/drag.spec.js @@ -79,5 +79,25 @@ describe('$drag', function() { expect(parseInt(style.left, 10)).toEqual(99); expect(parseInt(style.top, 10)).toEqual(99); }); + + it ('should offset draggable elements relative to their nearest positioned ancestor', function() { + + parent.css({position:'relative', top:'100px', left:'100px'}); + var draggable = $drag.draggable(element, {keepSize:true}), + style = element.prop('style'); + draggable.dragStart(); + expect(parseInt(style.left, 10)).toBe(0); + expect(parseInt(style.top, 10)).toBe(0); + }); + + it ('should offset draggable elements relative to their nearest positioned ancestor', function() { + + parent.css({position:'static', margin:'100px'}); + var draggable = $drag.draggable(element, {keepSize:true}), + style = element.prop('style'); + draggable.dragStart(); + expect(draggable.offset.left).toBe(100); + expect(draggable.offset.top).toBe(100); + }); }); }); From 64737df35550178bb82fd4294944e79b47889131 Mon Sep 17 00:00:00 2001 From: adam77 Date: Thu, 16 Apr 2015 18:10:40 +1200 Subject: [PATCH 05/12] First cut. --- test/provider/drag.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/provider/drag.spec.js b/test/provider/drag.spec.js index 17d8035..67a6bfc 100644 --- a/test/provider/drag.spec.js +++ b/test/provider/drag.spec.js @@ -80,7 +80,7 @@ describe('$drag', function() { expect(parseInt(style.top, 10)).toEqual(99); }); - it ('should offset draggable elements relative to their nearest positioned ancestor', function() { + it ('should offset element relative to its nearest positioned ancestor', function() { parent.css({position:'relative', top:'100px', left:'100px'}); var draggable = $drag.draggable(element, {keepSize:true}), @@ -90,7 +90,7 @@ describe('$drag', function() { expect(parseInt(style.top, 10)).toBe(0); }); - it ('should offset draggable elements relative to their nearest positioned ancestor', function() { + it ('should offset element relative to its nearest positioned ancestor', function() { parent.css({position:'static', margin:'100px'}); var draggable = $drag.draggable(element, {keepSize:true}), From 7e8d63c502640375ea7f5b04facdbc4d26f5316d Mon Sep 17 00:00:00 2001 From: adam77 Date: Thu, 16 Apr 2015 18:46:09 +1200 Subject: [PATCH 06/12] Tidy first cut. --- src/position.js | 2 +- test/directive/draggable.spec.js | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/position.js b/src/position.js index 6dae696..26d138e 100644 --- a/src/position.js +++ b/src/position.js @@ -160,4 +160,4 @@ var $positionFactory = ['$document', '$window', function ($document, $window) { return targetElPos; } }; -}]; \ No newline at end of file +}]; diff --git a/test/directive/draggable.spec.js b/test/directive/draggable.spec.js index 1c46199..f10a975 100644 --- a/test/directive/draggable.spec.js +++ b/test/directive/draggable.spec.js @@ -49,6 +49,4 @@ describe('draggable directive', function() { element = $compile('
')($rootScope); expect($drag.draggable(element, false).options.dragWithin).toEqual('body'); }); - - }); From f8f214d3404d73dc75e4c401d7d1287b172d3202 Mon Sep 17 00:00:00 2001 From: adam77 Date: Thu, 16 Apr 2015 18:57:48 +1200 Subject: [PATCH 07/12] Tidy first cut. --- src/position.js | 72 ------------------------------------------------- 1 file changed, 72 deletions(-) diff --git a/src/position.js b/src/position.js index 26d138e..17353b2 100644 --- a/src/position.js +++ b/src/position.js @@ -86,78 +86,6 @@ var $positionFactory = ['$document', '$window', function ($document, $window) { top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop), left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft) }; - }, - - /** - * Provides coordinates for the targetEl in relation to hostEl - */ - positionElements: function (hostEl, targetEl, positionStr, appendToBody) { - - var positionStrParts = positionStr.split('-'); - var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || 'center'; - - var hostElPos, - targetElWidth, - targetElHeight, - targetElPos; - - hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl); - - targetElWidth = targetEl.prop('offsetWidth'); - targetElHeight = targetEl.prop('offsetHeight'); - - var shiftWidth = { - center: function () { - return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2; - }, - left: function () { - return hostElPos.left; - }, - right: function () { - return hostElPos.left + hostElPos.width; - } - }; - - var shiftHeight = { - center: function () { - return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2; - }, - top: function () { - return hostElPos.top; - }, - bottom: function () { - return hostElPos.top + hostElPos.height; - } - }; - - switch (pos0) { - case 'right': - targetElPos = { - top: shiftHeight[pos1](), - left: shiftWidth[pos0]() - }; - break; - case 'left': - targetElPos = { - top: shiftHeight[pos1](), - left: hostElPos.left - targetElWidth - }; - break; - case 'bottom': - targetElPos = { - top: shiftHeight[pos0](), - left: shiftWidth[pos1]() - }; - break; - default: - targetElPos = { - top: hostElPos.top - targetElHeight, - left: shiftWidth[pos1]() - }; - break; - } - - return targetElPos; } }; }]; From f8b138d2a18c241d1acdffd0e16922f68754667e Mon Sep 17 00:00:00 2001 From: adam77 Date: Fri, 17 Apr 2015 08:36:00 +1200 Subject: [PATCH 08/12] Work around jqlite bug. Better test. --- src/draggable.js | 4 ++-- test/provider/drag.spec.js | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/draggable.js b/src/draggable.js index 860dafe..b4b4264 100644 --- a/src/draggable.js +++ b/src/draggable.js @@ -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); diff --git a/test/provider/drag.spec.js b/test/provider/drag.spec.js index 67a6bfc..5574a01 100644 --- a/test/provider/drag.spec.js +++ b/test/provider/drag.spec.js @@ -80,24 +80,26 @@ describe('$drag', function() { expect(parseInt(style.top, 10)).toEqual(99); }); - it ('should offset element relative to its nearest positioned ancestor', function() { + it ('should offset element relative to nearest positioned ancestor', function() { parent.css({position:'relative', top:'100px', left:'100px'}); var draggable = $drag.draggable(element, {keepSize:true}), style = element.prop('style'); draggable.dragStart(); + expect(parseInt(style.left, 10)).toBe(0); expect(parseInt(style.top, 10)).toBe(0); }); - it ('should offset element relative to its nearest positioned ancestor', function() { + it ('should offset element relative to body if no positioned ancestor', function() { parent.css({position:'static', margin:'100px'}); var draggable = $drag.draggable(element, {keepSize:true}), style = element.prop('style'); draggable.dragStart(); - expect(draggable.offset.left).toBe(100); - expect(draggable.offset.top).toBe(100); + + expect(parseInt(style.left, 10)).toBe(100); + expect(parseInt(style.top, 10)).toBe(100); }); }); }); From 74317a6c1a8e61eeaaebe507279bfdce1cd93992 Mon Sep 17 00:00:00 2001 From: adam77 Date: Fri, 17 Apr 2015 10:43:06 +1200 Subject: [PATCH 09/12] Rename $dndPosition -> $dndDOM. --- angularDrop.js | 2 +- src/{position.js => dndDOM.js} | 11 ++++------- src/draggable.js | 4 ++-- src/public.js | 2 +- 4 files changed, 8 insertions(+), 11 deletions(-) rename src/{position.js => dndDOM.js} (86%) diff --git a/angularDrop.js b/angularDrop.js index 0a38194..6c83fdd 100644 --- a/angularDrop.js +++ b/angularDrop.js @@ -1,7 +1,7 @@ angularDropFiles = { 'angularDropSrc': [ 'src/utils.js', - 'src/position.js', + 'src/dndDOM.js', 'src/draggable.js', 'src/droppable.js', 'src/provider.js', diff --git a/src/position.js b/src/dndDOM.js similarity index 86% rename from src/position.js rename to src/dndDOM.js index 17353b2..9a47e2a 100644 --- a/src/position.js +++ b/src/dndDOM.js @@ -3,21 +3,18 @@ /** * @ngdoc object * @module ui.drop - * @name ui.drop.$dndPosition + * @name ui.drop.$dndDOM * @requires $document * @requires $window * * @description * - * A set of utility methods that can be use to retrieve position of DOM elements. - * It is meant to be used where we need to absolute-position DOM elements in - * relation to other, existing elements (this is the case for tooltips, popovers, - * typeahead suggestions etc.). + * A set of utility methods that can be use to retrieve and manipulate DOM properties. * - * (from https://github.com/angular-ui/bootstrap/blob/master/src/position/position.js) + * (based on https://github.com/angular-ui/bootstrap/blob/master/src/position/position.js) * */ -var $positionFactory = ['$document', '$window', function ($document, $window) { +var $dndDOMFactory = ['$document', '$window', function ($document, $window) { function getStyle(el, cssprop) { if (el.currentStyle) { //IE diff --git a/src/draggable.js b/src/draggable.js index b4b4264..650e4e5 100644 --- a/src/draggable.js +++ b/src/draggable.js @@ -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', '$dndPosition', function($document, $drop, $dndPosition) { + this.$get = ['$document', '$drop', '$dndDOM', function($document, $drop, $dndDOM) { var $drag = { /** * @ngdoc method @@ -214,7 +214,7 @@ var $dragProvider = function() { self.constraints = dragConstraints(self.options.dragWithin, self.element); } - self.offset = $dndPosition.position(self.element); + self.offset = $dndDOM.position(self.element); self.offset.scroll = false; diff --git a/src/public.js b/src/public.js index c201335..7a571cf 100644 --- a/src/public.js +++ b/src/public.js @@ -11,6 +11,6 @@ function publishExternalAPI() { draggable: draggableDirective, droppable: droppableDirective }).factory({ - $dndPosition: $positionFactory + $dndDOM: $dndDOMFactory }); } From 515c10fe257bb7a10f57c1861e51de766bd8293c Mon Sep 17 00:00:00 2001 From: adam77 Date: Fri, 17 Apr 2015 11:54:33 +1200 Subject: [PATCH 10/12] Refactor utils.DOM -> $dndDOM. --- src/dndDOM.js | 87 ++++++++++++++++++++++++++++++++++++ src/draggable.js | 56 ++++++++++++------------ src/utils.js | 112 ----------------------------------------------- 3 files changed, 115 insertions(+), 140 deletions(-) diff --git a/src/dndDOM.js b/src/dndDOM.js index 9a47e2a..7f168c6 100644 --- a/src/dndDOM.js +++ b/src/dndDOM.js @@ -47,6 +47,36 @@ var $dndDOMFactory = ['$document', '$window', function ($document, $window) { 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: @@ -76,6 +106,19 @@ var $dndDOMFactory = ['$document', '$window', function ($document, $window) { * 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'), @@ -83,6 +126,50 @@ var $dndDOMFactory = ['$document', '$window', function ($document, $window) { 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 node + * @param value + * @returns {angular.element} + */ + closest: function(node, value) { + node = angular.element(node); + if ($.fn && angular.isFunction($.fn.closest)) { + return node.closest(value); + } + // Otherwise, assume it's a tag name... + node = node[0]; + value = value.toLowerCase(); + do { + if (node.nodeName.toLowerCase() === value) { + return angular.element(node); + } + } while (node = node.parentNode); + }, + + size: function(node) { + var jq = angular.element(node); + node = node.nodeName ? node : node[0]; + if (node.offsetWidth === 0 && swapDisplay.test(jq.css('display'))) { + return swapCss(node, cssShow, getHeightAndWidth, [node]); + } + return getHeightAndWidth(node); + + function getHeightAndWidth(element) { + return { + width: element.offsetWidth, + height: element.offsetHeight + }; + } + }, + + keepSize: function(node) { + var css = this.size(node); + css.width = css.width + 'px'; + css.height = css.height + 'px'; + return css; } }; }]; diff --git a/src/draggable.js b/src/draggable.js index 650e4e5..ca340fa 100644 --- a/src/draggable.js +++ b/src/draggable.js @@ -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"); @@ -206,7 +206,7 @@ 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)); } } @@ -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 @@ -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; } diff --git a/src/utils.js b/src/utils.js index 30fd4b8..2dc413b 100644 --- a/src/utils.js +++ b/src/utils.js @@ -111,116 +111,4 @@ matchesSelector = function(node, selector) { } return matchesFn(node, selector); -}, - -DOM = { - nodeEq: function(node, name) { - return (typeof (node.nodeName === 'string' ? - node.nodeName.toLowerCase() : node[0].nodeName).toLowerCase() === name); - }, - - offset: function(node) { - node = node.length ? node[0] : node; - var win, box = { top: 0, left: 0 }, - doc = node && node.ownerDocument; - - if (!doc) { - return; - } - - doc = doc.documentElement; - - if (!DOM.contains(doc, node)) { - return box; - } - - if (angular.isFunction(node.getBoundingClientRect)) { - box = node.getBoundingClientRect(); - } - - win = DOM.window(doc); - - return { - top: box.top + win.pageYOffset - doc.clientTop, - left: box.left + win.pageXOffset - doc.clientLeft - }; - }, - - contains: function(a, b) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && DOM.contains(adown, bup) ); - }, - - window: function(node) { - node = typeof node.nodeName === 'undefined' && typeof node.length === 'number' ? - node[0] : node; - return DOM.isWindow(node) ? node : (node.nodeType === 9 && node.defaultView) || - (node.ownerDocument && (node.ownerDocument.defaultView || - node.ownerDocument.parentWindow)); - }, - - isWindow: function(obj) { - return obj && obj.document && obj.location && obj.alert && obj.setInterval; - }, - - swapCss: function (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; - }, - - swapDisplay: /^(none|table(?!-c[ea]).+)/, - - cssShow: { - position: 'absolute', - visibility: 'hidden', - display: 'block' - }, - - size: function(node) { - var jq = angular.element(node); - node = node.nodeName ? node : node[0]; - if (node.offsetWidth === 0 && DOM.swapDisplay.test(jq.css('display'))) { - return DOM.swapCss(node, DOM.cssShow, getHeightAndWidth, [node]); - } - return getHeightAndWidth(node); - - function getHeightAndWidth(element) { - return { - width: element.offsetWidth, - height: element.offsetHeight - }; - } - }, - keepSize: function(node) { - var css = DOM.size(node); - css.width = css.width + 'px'; - css.height = css.height + 'px'; - return css; - }, - closest: function(node, value) { - node = angular.element(node); - if ($.fn && angular.isFunction($.fn.closest)) { - return node.closest(value); - } - // Otherwise, assume it's a tag name... - node = node[0]; - value = value.toLowerCase(); - do { - if (node.nodeName.toLowerCase() === value) { - return angular.element(node); - } - } while (node = node.parentNode); - } }; From 8ad1df4825d053804342b6292e5c801626cb859d Mon Sep 17 00:00:00 2001 From: adam77 Date: Fri, 17 Apr 2015 12:01:17 +1200 Subject: [PATCH 11/12] Refactor utils.DOM -> $dndDOM (consistent naming). --- src/dndDOM.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/dndDOM.js b/src/dndDOM.js index 7f168c6..a1f74d5 100644 --- a/src/dndDOM.js +++ b/src/dndDOM.js @@ -130,32 +130,32 @@ var $dndDOMFactory = ['$document', '$window', function ($document, $window) { /** * Partial implementation of https://api.jquery.com/closest/ - * @param node + * @param element * @param value * @returns {angular.element} */ - closest: function(node, value) { - node = angular.element(node); + closest: function(element, value) { + element = angular.element(element); if ($.fn && angular.isFunction($.fn.closest)) { - return node.closest(value); + return element.closest(value); } // Otherwise, assume it's a tag name... - node = node[0]; + element = element[0]; value = value.toLowerCase(); do { - if (node.nodeName.toLowerCase() === value) { - return angular.element(node); + if (element.nodeName.toLowerCase() === value) { + return angular.element(element); } - } while (node = node.parentNode); + } while (element = element.parentNode); }, - size: function(node) { - var jq = angular.element(node); - node = node.nodeName ? node : node[0]; - if (node.offsetWidth === 0 && swapDisplay.test(jq.css('display'))) { - return swapCss(node, cssShow, getHeightAndWidth, [node]); + 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(node); + return getHeightAndWidth(element); function getHeightAndWidth(element) { return { @@ -165,8 +165,8 @@ var $dndDOMFactory = ['$document', '$window', function ($document, $window) { } }, - keepSize: function(node) { - var css = this.size(node); + keepSize: function(element) { + var css = this.size(element); css.width = css.width + 'px'; css.height = css.height + 'px'; return css; From 32fda4017ea82e499570328d232e55bb301bb4c4 Mon Sep 17 00:00:00 2001 From: Caitlin Potter Date: Thu, 16 Apr 2015 22:07:16 -0400 Subject: [PATCH 12/12] chore(.travis.yml): update coveralls repo token Closes #65 --- .travis.yml | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index 12b1d0b..5d0efb1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,25 +1,19 @@ language: node_js node_js: - - 0.10 - +- 0.1 env: global: - secure: "f2WvNMs20+RQ3u4ZmRgEspL4RGgYVtY3t23aW8j6LdSl9XauFusexNKHYV0juEN3TlIrQS681yZHLsTHeTSXXFwUNycn2ka/H+cuwMx1vf9L/VQq5i6moTaYOTJIBQLUzwnqciLHTaL+HjAGRmdUxz3VTrae9Ub4gezxYxJRbcE=" - + secure: PPm5YZ1XHLUnuUSbiqpaOw4LZd8r/cWtxAozKzyE9NVmIe229Otld1QzECrtSK58JnDOd7MinNuLswcl2MLWcgQJ2Bfh522psnzsotRYul8luymUtBO/a0BsvqryYXp3+dsZoV8grHbOVS3ezPcnrIXwIFATu3xuomBV0YuYntg= install: - # Disable the spinner, it looks bad on Travis - - npm config set spin false - - npm config set loglevel http - - npm install - - npm install -g grunt-cli - - npm install karma-coveralls - - grunt bower - +- npm config set spin false +- npm config set loglevel http +- npm install +- npm install -g grunt-cli +- npm install karma-coveralls +- grunt bower before_script: - - scripts/travis/init_logs.sh - - export DISPLAY=:99.0 - - sh -e /etc/init.d/xvfb start - +- scripts/travis/init_logs.sh +- export DISPLAY=:99.0 +- sh -e /etc/init.d/xvfb start script: - - grunt test - +- grunt test