diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bae7d4..a4add6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,10 @@ +## 2.2.0 (2017-09-05) + +`holdToDrag` option introduced in 1.x is now available in 2.x + +Thanks to @altschuler and @matte00 :+1: + ## 2.1.0 (2017-07-27) This release adds a minor change to the API surface. diff --git a/bower.json b/bower.json index 88ed1a0..00800de 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "mobile-drag-drop", "description": "Polyfill for making HTML5 drag and drop possible in all browsers.", - "version": "2.1.0", + "version": "2.2.0", "main": [ "release/index.js", "release/default.css" diff --git a/package.json b/package.json index d9edc4a..3345499 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mobile-drag-drop", - "version": "2.1.0", + "version": "2.2.0", "description": "Polyfill for making HTML5 drag and drop possible in all browsers.", "main": "index.min.js", "types": "index.d.ts", @@ -39,7 +39,8 @@ "Matt Oakley ", "James Smith ", "James Shore ", - "Paul Shirren " + "Paul Shirren ", + "Simon Altschuler " ], "license": "MIT", "bugs": { diff --git a/release/index.d.ts b/release/index.d.ts index 1397980..d4fcd4d 100644 --- a/release/index.d.ts +++ b/release/index.d.ts @@ -7,6 +7,7 @@ export interface Config { dragStartConditionOverride?: (event: TouchEvent) => boolean; dragImageTranslateOverride?: DragImageTranslateOverrideFn; defaultActionOverride?: (event: TouchEvent) => void; + holdToDrag?: number; } export declare function polyfill(override?: Config): boolean; export interface Point { diff --git a/release/index.js b/release/index.js index f9e8032..caee567 100644 --- a/release/index.js +++ b/release/index.js @@ -57,7 +57,12 @@ } console.log("dnd-poly: Applying mobile drag and drop polyfill."); supportsPassive = supportsPassiveEventListener(); - addDocumentListener("touchstart", onTouchstart, false); + if (config.holdToDrag) { + addDocumentListener("touchstart", onDelayTouchstart, false); + } + else { + addDocumentListener("touchstart", onTouchstart, false); + } return true; } var activeDragOperation; @@ -733,6 +738,36 @@ } return DROP_EFFECTS[0]; } + function onDelayTouchstart(evt) { + var el = evt.target; + var heldItem = function () { + end.off(); + cancel.off(); + scroll.off(); + onTouchstart(evt); + }; + var onReleasedItem = function () { + end.off(); + cancel.off(); + scroll.off(); + clearTimeout(timer); + }; + var timer = setTimeout(heldItem, config.holdToDrag); + var end = onEvt(el, 'touchend', onReleasedItem, this); + var cancel = onEvt(el, 'touchcancel', onReleasedItem, this); + var scroll = onEvt(window, 'scroll', onReleasedItem, this); + } + function onEvt(el, event, handler, context) { + if (context) { + handler = handler.bind(context); + } + el.addEventListener(event, handler); + return { + off: function () { + return el.removeEventListener(event, handler); + } + }; + } exports.polyfill = polyfill; diff --git a/release/index.js.map b/release/index.js.map index 67d294f..f40601b 100644 --- a/release/index.js.map +++ b/release/index.js.map @@ -1 +1 @@ -{"version":3,"file":null,"sources":["/Users/stefansteinhart/Development/Web/ios-html5-drag-drop-shim/src/index.ts"],"sourcesContent":["// debug mode, which will highlight drop target, immediate user selection and events fired as you interact.\nconst DEBUG = false;\n\n//\n\ninterface DetectedFeatures {\n draggable:boolean;\n dragEvents:boolean;\n touchEvents:boolean;\n userAgentSupportingNativeDnD:boolean;\n}\n\nfunction detectFeatures():DetectedFeatures {\n\n let features:DetectedFeatures = {\n dragEvents: (\"ondragstart\" in document.documentElement),\n draggable: (\"draggable\" in document.documentElement),\n touchEvents: (\"ontouchstart\" in document.documentElement),\n userAgentSupportingNativeDnD: undefined\n };\n\n const isBlinkEngine = !!((window).chrome) || /chrome/i.test(navigator.userAgent);\n\n features.userAgentSupportingNativeDnD = !(\n // if is mobile safari or android browser -> no native dnd\n (/iPad|iPhone|iPod|Android/.test(navigator.userAgent))\n || // OR\n //if is blink(chrome/opera) with touch events enabled -> no native dnd\n (isBlinkEngine && features.touchEvents)\n );\n\n if (DEBUG) {\n Object.keys(features).forEach(function (key) {\n console.log(\"dnd-poly: detected feature '\" + key + \" = \" + features[key] + \"'\");\n });\n }\n\n return features;\n}\n\nlet supportsPassive:boolean;\n\nfunction supportsPassiveEventListener():boolean {\n\n let supportsPassiveEventListeners = false;\n\n // reference https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n try {\n let opts = Object.defineProperty({}, \"passive\", {\n get: function () {\n supportsPassiveEventListeners = true;\n }\n });\n window.addEventListener(\"test\", null, opts);\n }\n // tslint:disable-next-line:no-empty\n catch (e) {\n }\n\n return supportsPassiveEventListeners;\n}\n\n//\n\n//\n\n// function signature for the dragImageTranslateOverride hook\nexport type DragImageTranslateOverrideFn = (// corresponding touchmove event\n event:TouchEvent,\n // the processed touch event viewport coordinates\n hoverCoordinates:Point,\n // the element under the calculated touch coordinates\n hoveredElement:HTMLElement,\n // callback for updating the drag image offset\n translateDragImageFn:(offsetX:number, offsetY:number) => void) => void;\n\nexport interface Config {\n // flag to force the polyfill being applied and not rely on internal feature detection\n forceApply?:boolean;\n // useful for when you want the default drag image but still want to apply\n // some static offset from touch coordinates to drag image coordinates\n // defaults to (0,0)\n dragImageOffset?:Point;\n // if the dragImage shall be centered on the touch coordinates\n // defaults to false\n dragImageCenterOnTouch?:boolean;\n // the drag and drop operation involves some processing. here you can specify in what interval this processing takes place.\n // defaults to 150ms\n iterationInterval?:number;\n // hook for custom logic that decides if a drag operation should start\n dragStartConditionOverride?:(event:TouchEvent) => boolean;\n // hook for custom logic that can manipulate the drag image translate offset\n dragImageTranslateOverride?:DragImageTranslateOverrideFn;\n // hook for custom logic that can override the default action based on the original touch event when the drag never started\n // be sure to call event.preventDefault() if handling the default action in the override to prevent the browser default.\n defaultActionOverride?:(event:TouchEvent) => void;\n}\n\n// default config\nconst config:Config = {\n iterationInterval: 150,\n};\n\nexport function polyfill(override?:Config):boolean {\n\n if (override) {\n // overwrite default config with user config\n Object.keys(override).forEach(function (key) {\n config[key] = override[key];\n });\n }\n\n // only do feature detection when config does not force apply the polyfill\n if (!config.forceApply) {\n\n // feature/browser detection\n const detectedFeatures = detectFeatures();\n\n // check if native drag and drop support is there\n if (detectedFeatures.userAgentSupportingNativeDnD\n && detectedFeatures.draggable\n && detectedFeatures.dragEvents) {\n // no polyfilling required\n return false;\n }\n }\n\n console.log(\"dnd-poly: Applying mobile drag and drop polyfill.\");\n\n supportsPassive = supportsPassiveEventListener();\n\n // add listeners suitable for detecting a potential drag operation\n addDocumentListener(\"touchstart\", onTouchstart, false);\n\n return true;\n}\n\n//\n\n//\n\n// reference the currently active drag operation\nlet activeDragOperation:DragOperationController;\n\n/**\n * event handler listening for initial events that possibly start a drag and drop operation.\n */\nfunction onTouchstart(e:TouchEvent) {\n\n console.log(\"dnd-poly: global touchstart\");\n\n // From the moment that the user agent is to initiate the drag-and-drop operation,\n // until the end of the drag-and-drop operation, device input events (e.g. mouse and keyboard events) must be suppressed.\n\n // only allow one drag operation at a time\n if (activeDragOperation) {\n console.log(\"dnd-poly: drag operation already active\");\n return;\n }\n\n let dragTarget = tryFindDraggableTarget(e);\n\n // If there is no such element, then nothing is being dragged; abort these\n // steps, the drag-and-drop operation is never started.\n if (!dragTarget) {\n return;\n }\n\n try {\n activeDragOperation = new DragOperationController(e, config, dragTarget, dragOperationEnded);\n }\n catch (err) {\n dragOperationEnded(config, e, DragOperationState.CANCELLED);\n // rethrow exception after cleanup\n throw err;\n }\n}\n\n/**\n * Search for a possible draggable item upon an event that can initialize a drag operation.\n */\nfunction tryFindDraggableTarget(event:TouchEvent):Element {\n\n //1. Determine what is being dragged, as follows:\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the drag operation was invoked on a selection, then it is the selection that is being dragged.\n //if( (event.target).nodeType === 3 ) {\n //\n // config.log( \"drag on text\" );\n // return event.target;\n //}\n //Otherwise, if the drag operation was invoked on a Document, it is the first element, going up the ancestor chain, starting at the node that the\n // user tried to drag, that has the IDL attribute draggable set to true.\n //else {\n\n let el = event.target;\n\n do {\n if (el.draggable === false) {\n continue;\n }\n if (el.getAttribute && el.getAttribute(\"draggable\") === \"true\") {\n return el;\n }\n } while ((el = el.parentNode) && el !== document.body);\n}\n\n/**\n * Implements callback invoked when a drag operation has ended or crashed.\n */\nfunction dragOperationEnded(_config:Config, event:TouchEvent, state:DragOperationState) {\n\n // we need to make the default action happen only when no drag operation took place\n if (state === DragOperationState.POTENTIAL) {\n\n console.log(\"dnd-poly: Drag never started. Last event was \" + event.type);\n\n // when lifecycle hook is present\n if (_config.defaultActionOverride) {\n\n try {\n\n _config.defaultActionOverride(event);\n\n if (event.defaultPrevented) {\n\n console.log(\"dnd-poly: defaultActionOverride has taken care of triggering the default action. preventing default on original event\");\n }\n\n }\n catch (e) {\n\n console.log(\"dnd-poly: error in defaultActionOverride: \" + e);\n }\n }\n }\n\n // reset drag operation container\n activeDragOperation = null;\n}\n\n//\n\n//\n\n/**\n * For tracking the different states of a drag operation.\n */\nconst enum DragOperationState {\n // initial state of a controller, if no movement is detected the operation ends with this state\n POTENTIAL,\n // after movement is detected the drag operation starts and keeps this state until it ends\n STARTED,\n // when the drag operation ended normally\n ENDED,\n // when the drag operation ended with a cancelled input event\n CANCELLED\n}\n\n// contains all possible values of the effectAllowed property\nconst enum EFFECT_ALLOWED {\n NONE = 0,\n COPY = 1,\n COPY_LINK = 2,\n COPY_MOVE = 3,\n LINK = 4,\n LINK_MOVE = 5,\n MOVE = 6,\n ALL = 7\n}\n\nconst ALLOWED_EFFECTS = [\"none\", \"copy\", \"copyLink\", \"copyMove\", \"link\", \"linkMove\", \"move\", \"all\"];\n\n// contains all possible values of the dropEffect property\nconst enum DROP_EFFECT {\n NONE = 0,\n COPY = 1,\n MOVE = 2,\n LINK = 3,\n}\n\nconst DROP_EFFECTS = [\"none\", \"copy\", \"move\", \"link\"];\n\n// cross-browser css transform property prefixes\nconst TRANSFORM_CSS_VENDOR_PREFIXES = [\"\", \"-webkit-\"];\n// css classes\nconst CLASS_PREFIX = \"dnd-poly-\";\nconst CLASS_DRAG_IMAGE = CLASS_PREFIX + \"drag-image\";\nconst CLASS_DRAG_IMAGE_SNAPBACK = CLASS_PREFIX + \"snapback\";\nconst CLASS_DRAG_OPERATION_ICON = CLASS_PREFIX + \"icon\";\n\n/**\n * Aims to implement the HTML5 d'n'd spec (https://html.spec.whatwg.org/multipage/interaction.html#dnd) as close as it can get.\n * Note that all props that are private should start with an underscore to enable better minification.\n *\n * TODO remove lengthy spec comments in favor of short references to the spec\n */\nclass DragOperationController {\n\n private _dragOperationState:DragOperationState = DragOperationState.POTENTIAL;\n\n private _dragImage:HTMLElement;\n private _dragImageTransforms:string[];\n private _dragImagePageCoordinates:Point; // the current page coordinates of the dragImage\n private _dragImageOffset:Point; // offset of the drag image relative to the coordinates\n\n private _currentHotspotCoordinates:Point; // the point relative to viewport for determining the immediate user selection\n\n private _immediateUserSelection:HTMLElement = null; // the element the user currently hovers while dragging\n private _currentDropTarget:HTMLElement = null; // the element that was selected as a valid drop target by the d'n'd operation\n\n private _dragDataStore:DragDataStore;\n private _dataTransfer:DataTransfer;\n\n private _currentDragOperation:string; // the current drag operation set according to the d'n'd processing model\n\n private _initialTouch:Touch; // the identifier for the touch that initiated the drag operation\n private _touchMoveHandler:EventListener;\n private _touchEndOrCancelHandler:EventListener;\n private _lastTouchEvent:TouchEvent;\n\n private _iterationLock:boolean;\n private _iterationIntervalId:number;\n\n constructor(private _initialEvent:TouchEvent,\n private _config:Config,\n private _sourceNode:HTMLElement,\n private _dragOperationEndedCb:(config:Config, event:TouchEvent, state:DragOperationState) => void) {\n\n console.log(\"dnd-poly: setting up potential drag operation..\");\n\n this._lastTouchEvent = _initialEvent;\n this._initialTouch = _initialEvent.changedTouches[0];\n\n // create bound event listeners\n this._touchMoveHandler = this._onTouchMove.bind(this);\n this._touchEndOrCancelHandler = this._onTouchEndOrCancel.bind(this);\n addDocumentListener(\"touchmove\", this._touchMoveHandler, false);\n addDocumentListener(\"touchend\", this._touchEndOrCancelHandler, false);\n addDocumentListener(\"touchcancel\", this._touchEndOrCancelHandler, false);\n\n // the only thing we do is setup the touch listeners. if drag will really start is decided in touch move handler.\n\n //\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // 3. Establish which DOM node is the source node, as follows:\n // If it is a selection that is being dragged, then the source node is the text node that the user started the drag on (typically the text node\n // that the user originally clicked). If the user did not specify a particular node, for example if the user just told the user agent to begin\n // a drag of \"the selection\", then the source node is the first text node containing a part of the selection. Otherwise, if it is an element\n // that is being dragged, then the source node is the element that is being dragged. Otherwise, the source node is part of another document or\n // application. When this specification requires that an event be dispatched at the source node in this case, the user agent must instead\n // follow the platform-specific conventions relevant to that situation.\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // 4. Determine the list of dragged nodes, as follows:\n\n // If it is a selection that is being dragged, then the list of dragged nodes contains, in tree order, every node that is partially or\n // completely included in the selection (including all their ancestors).\n\n // Otherwise, the list of dragged nodes contains only the source node, if any.\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // 5. If it is a selection that is being dragged, then add an item to the drag data store item list, with its properties set as follows:\n\n //The drag data item type string\n //\"text/plain\"\n //The drag data item kind\n //Plain Unicode string\n //The actual data\n //The text of the selection\n //Otherwise, if any files are being dragged, then add one item per file to the drag data store item list, with their properties set as follows:\n //\n //The drag data item type string\n //The MIME type of the file, if known, or \"application/octet-stream\" otherwise.\n // The drag data item kind\n //File\n //The actual data\n //The file's contents and name.\n //Dragging files can currently only happen from outside a browsing context, for example from a file system manager application.\n //\n // If the drag initiated outside of the application, the user agent must add items to the drag data store item list as appropriate for the data\n // being dragged, honoring platform conventions where appropriate; however, if the platform conventions do not use MIME types to label dragged\n // data, the user agent must make a best-effort attempt to map the types to MIME types, and, in any case, all the drag data item type strings must\n // be converted to ASCII lowercase. Perform drag-and-drop initialization steps defined in any other applicable specifications.\n\n //\n }\n\n //\n\n /**\n * Setup dragImage, input listeners and the drag\n * and drop process model iteration interval.\n */\n private _setup():boolean {\n console.log(\"dnd-poly: starting drag and drop operation\");\n\n this._dragOperationState = DragOperationState.STARTED;\n\n this._currentDragOperation = DROP_EFFECTS[DROP_EFFECT.NONE];\n\n this._dragDataStore = {\n _data: {},\n _effectAllowed: undefined,\n _mode: DragDataStoreMode.PROTECTED,\n _types: [],\n };\n\n this._currentHotspotCoordinates = {\n x: null,\n y: null\n };\n\n this._dragImagePageCoordinates = {\n x: null,\n y: null\n };\n\n let dragImageSrc:HTMLElement = this._sourceNode;\n\n this._dataTransfer = new DataTransfer(this._dragDataStore, (element:HTMLElement, x:number, y:number) => {\n\n dragImageSrc = element;\n\n if (typeof x === \"number\" || typeof y === \"number\") {\n this._dragImageOffset = {\n x: x || 0,\n y: y || 0\n };\n }\n });\n\n // 9. Fire a DND event named dragstart at the source node.\n this._dragDataStore._mode = DragDataStoreMode.READWRITE;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n if (dispatchDragEvent(\"dragstart\", this._sourceNode, this._lastTouchEvent, this._dragDataStore, this._dataTransfer)) {\n console.log(\"dnd-poly: dragstart cancelled\");\n // dragstart has been prevented -> cancel d'n'd\n this._dragOperationState = DragOperationState.CANCELLED;\n this._cleanup();\n return false;\n }\n\n updateCentroidCoordinatesOfTouchesIn(\"page\", this._lastTouchEvent, this._dragImagePageCoordinates);\n this._dragImage = createDragImage(dragImageSrc);\n this._dragImageTransforms = extractTransformStyles(this._dragImage);\n\n if (!this._dragImageOffset) {\n\n // apply specific offset\n if (this._config.dragImageOffset) {\n\n this._dragImageOffset = {\n x: this._config.dragImageOffset.x,\n y: this._config.dragImageOffset.y\n };\n }\n // center drag image on touch coordinates\n else if (this._config.dragImageCenterOnTouch) {\n\n const cs = getComputedStyle(dragImageSrc);\n this._dragImageOffset = {\n x: 0 - parseInt(cs.marginLeft, 10),\n y: 0 - parseInt(cs.marginTop, 10)\n };\n }\n // by default initialize drag image offset the same as desktop\n else {\n\n const targetRect = dragImageSrc.getBoundingClientRect();\n const cs = getComputedStyle(dragImageSrc);\n this._dragImageOffset = {\n x: targetRect.left - this._initialTouch.clientX - parseInt(cs.marginLeft, 10) + targetRect.width / 2,\n y: targetRect.top - this._initialTouch.clientY - parseInt(cs.marginTop, 10) + targetRect.height / 2\n };\n }\n }\n\n translateDragImage(this._dragImage, this._dragImagePageCoordinates, this._dragImageTransforms, this._dragImageOffset, this._config.dragImageCenterOnTouch);\n document.body.appendChild(this._dragImage);\n\n // 10. Initiate the drag-and-drop operation in a manner consistent with platform conventions, and as described below.\n this._iterationIntervalId = setInterval(() => {\n\n // If the user agent is still performing the previous iteration of the sequence (if any) when the next iteration becomes due,\n // abort these steps for this iteration (effectively \"skipping missed frames\" of the drag-and-drop operation).\n if (this._iterationLock) {\n console.log(\"dnd-poly: iteration skipped because previous iteration hast not yet finished.\");\n return;\n }\n this._iterationLock = true;\n\n this._dragAndDropProcessModelIteration();\n\n this._iterationLock = false;\n }, this._config.iterationInterval);\n\n return true;\n }\n\n private _cleanup() {\n\n console.log(\"dnd-poly: cleanup\");\n\n if (this._iterationIntervalId) {\n clearInterval(this._iterationIntervalId);\n this._iterationIntervalId = null;\n }\n\n removeDocumentListener(\"touchmove\", this._touchMoveHandler);\n removeDocumentListener(\"touchend\", this._touchEndOrCancelHandler);\n removeDocumentListener(\"touchcancel\", this._touchEndOrCancelHandler);\n\n if (this._dragImage) {\n this._dragImage.parentNode.removeChild(this._dragImage);\n this._dragImage = null;\n }\n\n this._dragOperationEndedCb(this._config, this._lastTouchEvent, this._dragOperationState);\n }\n\n //\n\n //\n\n private _onTouchMove(event:TouchEvent) {\n\n // filter unrelated touches\n if (isTouchIdentifierContainedInTouchEvent(event, this._initialTouch.identifier) === false) {\n return;\n }\n\n // update the reference to the last received touch event\n this._lastTouchEvent = event;\n\n // drag operation did not start yet but on movement it should start\n if (this._dragOperationState === DragOperationState.POTENTIAL) {\n\n let startDrag:boolean;\n\n // is a lifecycle hook present?\n if (this._config.dragStartConditionOverride) {\n\n try {\n startDrag = this._config.dragStartConditionOverride(event);\n }\n catch (e) {\n console.error(\"dnd-poly: error in dragStartConditionOverride hook: \" + e);\n startDrag = false;\n }\n }\n else {\n\n // by default only allow a single moving finger to initiate a drag operation\n startDrag = (event.touches.length === 1);\n }\n\n if (!startDrag) {\n\n this._cleanup();\n return;\n }\n\n // setup will return true when drag operation starts\n if (this._setup() === true) {\n\n // prevent scrolling when drag operation starts\n this._initialEvent.preventDefault();\n event.preventDefault();\n }\n\n return;\n }\n\n console.log(\"dnd-poly: moving draggable..\");\n\n // we emulate d'n'd so we dont want any defaults to apply\n event.preventDefault();\n\n // populate shared coordinates from touch event\n updateCentroidCoordinatesOfTouchesIn(\"client\", event, this._currentHotspotCoordinates);\n updateCentroidCoordinatesOfTouchesIn(\"page\", event, this._dragImagePageCoordinates);\n\n if (this._config.dragImageTranslateOverride) {\n\n try {\n\n let handledDragImageTranslate = false;\n\n this._config.dragImageTranslateOverride(\n event,\n {\n x: this._currentHotspotCoordinates.x,\n y: this._currentHotspotCoordinates.y\n },\n this._immediateUserSelection,\n (offsetX:number, offsetY:number) => {\n\n // preventing translation of drag image when there was a drag operation cleanup meanwhile\n if (!this._dragImage) {\n return;\n }\n\n handledDragImageTranslate = true;\n\n this._currentHotspotCoordinates.x += offsetX;\n this._currentHotspotCoordinates.y += offsetY;\n this._dragImagePageCoordinates.x += offsetX;\n this._dragImagePageCoordinates.y += offsetY;\n\n translateDragImage(\n this._dragImage,\n this._dragImagePageCoordinates,\n this._dragImageTransforms,\n this._dragImageOffset,\n this._config.dragImageCenterOnTouch\n );\n }\n );\n\n if (handledDragImageTranslate) {\n return;\n }\n }\n catch (e) {\n console.log(\"dnd-poly: error in dragImageTranslateOverride hook: \" + e);\n }\n }\n\n translateDragImage(this._dragImage, this._dragImagePageCoordinates, this._dragImageTransforms, this._dragImageOffset, this._config.dragImageCenterOnTouch);\n }\n\n private _onTouchEndOrCancel(event:TouchEvent) {\n\n // filter unrelated touches\n if (isTouchIdentifierContainedInTouchEvent(event, this._initialTouch.identifier) === false) {\n return;\n }\n\n // let the dragImageTranslateOverride know that its over\n if (this._config.dragImageTranslateOverride) {\n try {\n /* tslint:disable */\n this._config.dragImageTranslateOverride(undefined, undefined, undefined, function () {\n });\n }\n catch (e) {\n console.log(\"dnd-poly: error in dragImageTranslateOverride hook: \" + e);\n }\n }\n\n // drag operation did not even start\n if (this._dragOperationState === DragOperationState.POTENTIAL) {\n this._cleanup();\n return;\n }\n\n // we emulate d'n'd so we dont want any defaults to apply\n event.preventDefault();\n\n this._dragOperationState = (event.type === \"touchcancel\") ? DragOperationState.CANCELLED : DragOperationState.ENDED;\n }\n\n //\n\n //\n\n /**\n * according to https://html.spec.whatwg.org/multipage/interaction.html#drag-and-drop-processing-model\n */\n private _dragAndDropProcessModelIteration():void {\n\n if (DEBUG) {\n var debug_class = CLASS_PREFIX + \"debug\",\n debug_class_user_selection = CLASS_PREFIX + \"immediate-user-selection\",\n debug_class_drop_target = CLASS_PREFIX + \"current-drop-target\";\n }\n\n const previousDragOperation = this._currentDragOperation;\n\n // Fire a DND event named drag event at the source node.\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n const dragCancelled = dispatchDragEvent(\"drag\", this._sourceNode, this._lastTouchEvent, this._dragDataStore, this._dataTransfer);\n if (dragCancelled) {\n console.log(\"dnd-poly: drag event cancelled.\");\n // If this event is canceled, the user agent must set the current drag operation to \"none\" (no drag operation).\n this._currentDragOperation = DROP_EFFECTS[DROP_EFFECT.NONE];\n }\n\n // Otherwise, if the user ended the drag-and-drop operation (e.g. by releasing the mouse button in a mouse-driven drag-and-drop interface),\n // or if the drag event was canceled, then this will be the last iteration.\n if (dragCancelled || this._dragOperationState === DragOperationState.ENDED || this._dragOperationState === DragOperationState.CANCELLED) {\n\n const dragFailed = this._dragOperationEnded(this._dragOperationState);\n\n // if drag failed transition snap back\n if (dragFailed) {\n\n applyDragImageSnapback(this._sourceNode, this._dragImage, this._dragImageTransforms, () => {\n this._finishDragOperation();\n });\n return;\n }\n\n // Otherwise immediately\n // Fire a DND event named dragend at the source node.\n this._finishDragOperation();\n return;\n }\n\n // If the drag event was not canceled and the user has not ended the drag-and-drop operation,\n // check the state of the drag-and-drop operation, as follows:\n const newUserSelection:HTMLElement = document.elementFromPoint(this._currentHotspotCoordinates.x, this._currentHotspotCoordinates.y);\n\n console.log(\"dnd-poly: new immediate user selection is: \" + newUserSelection);\n\n const previousTargetElement = this._currentDropTarget;\n\n // If the user is indicating a different immediate user selection than during the last iteration (or if this is the first iteration),\n // and if this immediate user selection is not the same as the current target element,\n // then fire a DND event named dragexit at the current target element,\n // and then update the current target element as follows:\n if (newUserSelection !== this._immediateUserSelection && newUserSelection !== this._currentDropTarget) {\n\n if (DEBUG) {\n\n if (this._immediateUserSelection) {\n this._immediateUserSelection.classList.remove(debug_class_user_selection);\n }\n\n if (newUserSelection) {\n newUserSelection.classList.add(debug_class);\n newUserSelection.classList.add(debug_class_user_selection);\n }\n }\n\n this._immediateUserSelection = newUserSelection;\n\n if (this._currentDropTarget !== null) {\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n dispatchDragEvent(\"dragexit\", this._currentDropTarget, this._lastTouchEvent, this._dragDataStore, this._dataTransfer, false);\n }\n\n // If the new immediate user selection is null\n if (this._immediateUserSelection === null) {\n //Set the current target element to null also.\n this._currentDropTarget = this._immediateUserSelection;\n\n console.log(\"dnd-poly: current drop target changed to null\");\n }\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the new immediate user selection is in a non-DOM document or application\n // else if() {\n // Set the current target element to the immediate user selection.\n // this.currentDropTarget = this.immediateUserSelection;\n // return;\n // }\n // Otherwise\n else {\n // Fire a DND event named dragenter at the immediate user selection.\n //the polyfill cannot determine if a handler even exists as browsers do to silently\n // allow drop when no listener existed, so this event MUST be handled by the client\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = determineDropEffect(this._dragDataStore._effectAllowed, this._sourceNode);\n if (dispatchDragEvent(\"dragenter\", this._immediateUserSelection, this._lastTouchEvent, this._dragDataStore, this._dataTransfer)) {\n console.log(\"dnd-poly: dragenter default prevented\");\n // If the event is canceled, then set the current target element to the immediate user selection.\n this._currentDropTarget = this._immediateUserSelection;\n this._currentDragOperation = determineDragOperation(this._dataTransfer.effectAllowed, this._dataTransfer.dropEffect);\n }\n // Otherwise, run the appropriate step from the following list:\n else {\n\n // NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n //console.log( \"dnd-poly: dragenter not prevented, searching for dropzone..\" );\n //var newTarget = DragOperationController.FindDropzoneElement( this.immediateUserSelection );\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the current target element is a text field (e.g. textarea, or an input element whose type attribute is in the Text state) or an\n // editable element, and the drag data store item list has an item with the drag data item type string \"text/plain\" and the drag data\n // item kind Plain Unicode string\n //if( ElementIsTextDropzone( this.immediateUserSelection, this.dragDataStore ) ) {\n //Set the current target element to the immediate user selection anyway.\n //this.currentDropTarget = this.immediateUserSelection;\n //}\n //else\n // If the current target element is an element with a dropzone attribute that matches the drag data store\n //if( newTarget === this.immediateUserSelection &&\n // DragOperationController.GetOperationForMatchingDropzone( this.immediateUserSelection, this.dragDataStore ) !== \"none\" ) {\n // Set the current target element to the immediate user selection anyway.\n // this.currentDropTarget = this.immediateUserSelection;\n //}\n // If the immediate user selection is an element that itself has an ancestor element\n // with a dropzone attribute that matches the drag data store\n // NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n //else if( newTarget !== null && DragOperationController.GetOperationForMatchingDropzone( newTarget, this.dragDataStore ) ) {\n\n // If the immediate user selection is new target, then leave the current target element unchanged.\n\n // Otherwise, fire a DND event named dragenter at new target, with the current target element\n // as the specific related target. Then, set the current target element to new target,\n // regardless of whether that event was canceled or not.\n //this.dragenter( newTarget, this.currentDropTarget );\n //this.currentDropTarget = newTarget;\n //}\n // If the current target element is not the body element\n //else\n if (this._immediateUserSelection !== document.body) {\n // Fire a DND event named dragenter at the body element, and set the current target element to the body element, regardless of\n // whether that event was canceled or not.\n // Note: If the body element is null, then the event will be fired at the Document object (as\n // required by the definition of the body element), but the current target element would be set to null, not the Document object.\n\n // We do not listen to what the spec says here because this results in doubled events on the body/document because if the first one\n // was not cancelled it will have bubbled up to the body already ;)\n // this.dragenter( window.document.body );\n this._currentDropTarget = document.body;\n }\n // Otherwise\n //else {\n // leave the current drop target unchanged\n //}\n }\n }\n }\n\n // If the previous step caused the current target element to change,\n // and if the previous target element was not null or a part of a non-DOM document,\n // then fire a DND event named dragleave at the previous target element.\n if (previousTargetElement !== this._currentDropTarget && (isDOMElement(previousTargetElement) )) {\n\n if (DEBUG) {\n previousTargetElement.classList.remove(debug_class_drop_target);\n }\n\n console.log(\"dnd-poly: current drop target changed.\");\n\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n dispatchDragEvent(\"dragleave\", previousTargetElement, this._lastTouchEvent, this._dragDataStore, this._dataTransfer, false, this._currentDropTarget);\n }\n\n // If the current target element is a DOM element, then fire a DND event named dragover at this current target element.\n if (isDOMElement(this._currentDropTarget)) {\n\n if (DEBUG) {\n this._currentDropTarget.classList.add(debug_class);\n this._currentDropTarget.classList.add(debug_class_drop_target);\n }\n\n // If the dragover event is not canceled, run the appropriate step from the following list:\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = determineDropEffect(this._dragDataStore._effectAllowed, this._sourceNode);\n if (dispatchDragEvent(\"dragover\", this._currentDropTarget, this._lastTouchEvent, this._dragDataStore, this._dataTransfer) === false) {\n\n console.log(\"dnd-poly: dragover not prevented on possible drop-target.\");\n // NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the current target element is a text field (e.g. textarea, or an input element whose type attribute is in the Text state) or\n // an editable element, and the drag data store item list has an item with the drag data item type string \"text/plain\" and the drag\n // data item kind Plain Unicode string\n //if( ElementIsTextDropzone( this.currentDropTarget, this.dragDataStore ) ) {\n // Set the current drag operation to either \"copy\" or \"move\", as appropriate given the platform conventions.\n //this.currentDragOperation = \"copy\"; //or move. spec says its platform specific behaviour.\n //}\n //else {\n // If the current target element is an element with a dropzone attribute that matches the drag data store\n //this.currentDragOperation = DragOperationController.GetOperationForMatchingDropzone( this.currentDropTarget, this.dragDataStore );\n //}\n // when dragover is not prevented and no dropzones are there, no drag operation\n this._currentDragOperation = DROP_EFFECTS[DROP_EFFECT.NONE];\n }\n // Otherwise (if the dragover event is canceled), set the current drag operation based on the values of the effectAllowed and\n // dropEffect attributes of the DragEvent object's dataTransfer object as they stood after the event dispatch finished\n else {\n\n console.log(\"dnd-poly: dragover prevented.\");\n\n this._currentDragOperation = determineDragOperation(this._dataTransfer.effectAllowed, this._dataTransfer.dropEffect);\n }\n }\n\n console.log(\"dnd-poly: d'n'd iteration ended. current drag operation: \" + this._currentDragOperation);\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // Otherwise, if the current target element is not a DOM element, use platform-specific mechanisms to determine what drag operation is\n // being performed (none, copy, link, or move), and set the current drag operation accordingly.\n\n //Update the drag feedback (e.g. the mouse cursor) to match the current drag operation, as follows:\n // ---------------------------------------------------------------------------------------------------------\n // Drag operation |\tFeedback\n // \"copy\"\t | Data will be copied if dropped here.\n // \"link\"\t | Data will be linked if dropped here.\n // \"move\"\t | Data will be moved if dropped here.\n // \"none\"\t | No operation allowed, dropping here will cancel the drag-and-drop operation.\n // ---------------------------------------------------------------------------------------------------------\n\n if (previousDragOperation !== this._currentDragOperation) {\n this._dragImage.classList.remove(CLASS_PREFIX + previousDragOperation);\n }\n\n const currentDragOperationClass = CLASS_PREFIX + this._currentDragOperation;\n\n if (this._dragImage.classList.contains(currentDragOperationClass) === false) {\n this._dragImage.classList.add(currentDragOperationClass);\n }\n }\n\n /**\n * according to https://html.spec.whatwg.org/multipage/interaction.html#drag-and-drop-processing-model\n */\n private _dragOperationEnded(state:DragOperationState):boolean {\n\n console.log(\"dnd-poly: drag operation end detected with \" + this._currentDragOperation);\n\n if (DEBUG) {\n\n var debug_class_user_selection = CLASS_PREFIX + \"immediate-user-selection\",\n debug_class_drop_target = CLASS_PREFIX + \"current-drop-target\";\n\n if (this._currentDropTarget) {\n this._currentDropTarget.classList.remove(debug_class_drop_target);\n\n }\n if (this._immediateUserSelection) {\n this._immediateUserSelection.classList.remove(debug_class_user_selection);\n }\n }\n\n //var dropped:boolean = undefined;\n\n // Run the following steps, then stop the drag-and-drop operation:\n\n // If the current drag operation is \"none\" (no drag operation), or,\n // if the user ended the drag-and-drop operation by canceling it (e.g. by hitting the Escape key), or\n // if the current target element is null, then the drag operation failed.\n const dragFailed = (this._currentDragOperation === DROP_EFFECTS[DROP_EFFECT.NONE]\n || this._currentDropTarget === null\n || state === DragOperationState.CANCELLED);\n if (dragFailed) {\n\n // Run these substeps:\n\n // Let dropped be false.\n //dropped = false;\n\n // If the current target element is a DOM element, fire a DND event named dragleave at it;\n if (isDOMElement(this._currentDropTarget)) {\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n dispatchDragEvent(\"dragleave\", this._currentDropTarget, this._lastTouchEvent, this._dragDataStore, this._dataTransfer, false);\n }\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // otherwise, if it is not null, use platform-specific conventions for drag cancellation.\n //else if( this.currentDropTarget !== null ) {\n //}\n }\n // Otherwise, the drag operation was as success; run these substeps:\n else {\n\n // Let dropped be true.\n //dropped = true;\n\n // If the current target element is a DOM element, fire a DND event named drop at it;\n if (isDOMElement(this._currentDropTarget)) {\n\n // If the event is canceled, set the current drag operation to the value of the dropEffect attribute of the\n // DragEvent object's dataTransfer object as it stood after the event dispatch finished.\n\n this._dragDataStore._mode = DragDataStoreMode.READONLY;\n this._dataTransfer.dropEffect = this._currentDragOperation;\n if (dispatchDragEvent(\"drop\", this._currentDropTarget, this._lastTouchEvent, this._dragDataStore, this._dataTransfer) ===\n true) {\n\n this._currentDragOperation = this._dataTransfer.dropEffect;\n }\n // Otherwise, the event is not canceled; perform the event's default action, which depends on the exact target as follows:\n else {\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the current target element is a text field (e.g. textarea, or an input element whose type attribute is in the Text state)\n // or an editable element,\n // and the drag data store item list has an item with the drag data item type string \"text/plain\"\n // and the drag data item kind Plain Unicode string\n //if( ElementIsTextDropzone( this.currentDropTarget, this.dragDataStore ) ) {\n // Insert the actual data of the first item in the drag data store item list to have a drag data item type string of\n // \"text/plain\" and a drag data item kind that is Plain Unicode string into the text field or editable element in a manner\n // consistent with platform-specific conventions (e.g. inserting it at the current mouse cursor position, or inserting it at\n // the end of the field).\n //}\n // Otherwise\n //else {\n // Reset the current drag operation to \"none\".\n this._currentDragOperation = DROP_EFFECTS[DROP_EFFECT.NONE];\n //}\n }\n }\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // otherwise, use platform-specific conventions for indicating a drop.\n //else {\n //}\n }\n\n return dragFailed;\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n //if( this.dragend( this.sourceNode ) ) {\n // return;\n //}\n\n // Run the appropriate steps from the following list as the default action of the dragend event:\n\n //if( !dropped ) {\n // return;\n //}\n // dropped is true\n\n //if( this.currentDragOperation !== \"move\" ) {\n // return;\n //}\n //// drag operation is move\n //\n //if( ElementIsTextDropzone( this.currentDropTarget ) === false ) {\n // return;\n //}\n //// element is textfield\n //\n //// and the source of the drag-and-drop operation is a selection in the DOM\n //if( this.sourceNode.nodeType === 1 ) {\n // // The user agent should delete the range representing the dragged selection from the DOM.\n //}\n //// and the source of the drag-and-drop operation is a selection in a text field\n //else if( this.sourceNode.nodeType === 3 ) {\n // // The user agent should delete the dragged selection from the relevant text field.\n //}\n //// Otherwise, The event has no default action.\n }\n\n // dispatch dragend event and cleanup drag operation\n private _finishDragOperation():void {\n console.log(\"dnd-poly: dragimage snap back transition ended\");\n\n // Fire a DND event named dragend at the source node.\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = this._currentDragOperation;\n dispatchDragEvent(\"dragend\", this._sourceNode, this._lastTouchEvent, this._dragDataStore, this._dataTransfer, false);\n\n // drag operation over and out\n this._dragOperationState = DragOperationState.ENDED;\n this._cleanup();\n }\n\n //\n}\n\n//\n\n//\n\n/**\n * Polyfills https://html.spec.whatwg.org/multipage/interaction.html#drag-data-store-mode\n */\nconst enum DragDataStoreMode {\n _DISCONNECTED, // adding an extra mode here because we need a special state to disconnect the data store from dataTransfer instance\n READONLY,\n READWRITE,\n PROTECTED\n}\n\n/**\n * Polyfills https://html.spec.whatwg.org/multipage/interaction.html#the-drag-data-store\n */\ninterface DragDataStore {\n _mode:DragDataStoreMode;\n _data:{ [type:string]:any };\n _types:Array;\n _effectAllowed:string;\n}\n\n/**\n * Polyfills https://html.spec.whatwg.org/multipage/interaction.html#datatransfer\n * TODO fail with errors when somebody uses it wrong so they know they are doing it wrong?\n */\nclass DataTransfer {\n\n private _dropEffect:string = DROP_EFFECTS[DROP_EFFECT.NONE];\n\n constructor(private _dataStore:DragDataStore,\n private _setDragImageHandler:(image:Element, x:number, y:number) => void) {\n }\n\n //public get files():FileList {\n // return undefined;\n //}\n //\n //public get items():DataTransferItemList {\n // return undefined;\n //}\n\n public get types():ReadonlyArray {\n if (this._dataStore._mode !== DragDataStoreMode._DISCONNECTED) {\n return Object.freeze(this._dataStore._types);\n }\n }\n\n public setData(type:string, data:string):void {\n if (this._dataStore._mode === DragDataStoreMode.READWRITE) {\n\n if (type.indexOf(\" \") > -1) {\n throw new Error(\"illegal arg: type contains space\");\n }\n\n this._dataStore._data[type] = data;\n\n if (this._dataStore._types.indexOf(type) === -1) {\n this._dataStore._types.push(type);\n }\n }\n }\n\n public getData(type:string):string {\n if (this._dataStore._mode === DragDataStoreMode.READONLY\n || this._dataStore._mode === DragDataStoreMode.READWRITE) {\n return this._dataStore._data[type] || \"\";\n }\n }\n\n public clearData(format?:string):void {\n if (this._dataStore._mode === DragDataStoreMode.READWRITE) {\n // delete data for format\n if (format && this._dataStore._data[format]) {\n delete this._dataStore._data[format];\n var index = this._dataStore._types.indexOf(format);\n if (index > -1) {\n this._dataStore._types.splice(index, 1);\n }\n return;\n }\n // delete all data\n this._dataStore._data = {};\n this._dataStore._types = [];\n }\n }\n\n public setDragImage(image:Element, x:number, y:number):void {\n if (this._dataStore._mode === DragDataStoreMode.READWRITE) {\n this._setDragImageHandler(image, x, y);\n }\n }\n\n public get effectAllowed() {\n return this._dataStore._effectAllowed;\n }\n\n public set effectAllowed(value) {\n if (this._dataStore._mode === DragDataStoreMode.READWRITE\n && ALLOWED_EFFECTS.indexOf(value) > -1) {\n this._dataStore._effectAllowed = value;\n }\n }\n\n public get dropEffect() {\n return this._dropEffect;\n }\n\n public set dropEffect(value) {\n if (this._dataStore._mode !== DragDataStoreMode._DISCONNECTED\n && ALLOWED_EFFECTS.indexOf(value) > -1) {\n this._dropEffect = value;\n }\n }\n}\n\n//\n\n//\n\nexport interface Point {\n x:number;\n y:number;\n}\n\nfunction addDocumentListener(ev:string, handler:EventListener, passive:boolean = true) {\n\n (document as EventTarget).addEventListener(ev, handler, supportsPassive ? {passive: passive} : false);\n}\n\nfunction removeDocumentListener(ev:string, handler:EventListener) {\n document.removeEventListener(ev, handler);\n}\n\nfunction average(array:Array) {\n if (array.length === 0) {\n return 0;\n }\n return array.reduce((function (s, v) {\n return v + s;\n }), 0) / array.length;\n}\n\nfunction isDOMElement(object:any) {\n return object && object.tagName;\n}\n\nfunction isTouchIdentifierContainedInTouchEvent(newTouch:TouchEvent, touchIdentifier:number) {\n for (let i = 0; i < newTouch.changedTouches.length; i++) {\n const touch = newTouch.changedTouches[i];\n if (touch.identifier === touchIdentifier) {\n return true;\n }\n }\n return false;\n}\n\nfunction createDragEventFromTouch(targetElement:Element,\n e:TouchEvent,\n type:string,\n cancelable:boolean,\n window:Window,\n dataTransfer:DataTransfer,\n relatedTarget:Element = null) {\n\n const touch:Touch = e.changedTouches[0];\n\n const dndEvent:DragEvent = new Event(type, {\n bubbles: true,\n cancelable: cancelable\n });\n\n // cast our polyfill\n (dndEvent as any).dataTransfer = dataTransfer;\n (dndEvent as any).relatedTarget = relatedTarget;\n\n // set the coordinates\n (dndEvent as any).screenX = touch.screenX;\n (dndEvent as any).screenY = touch.screenY;\n (dndEvent as any).clientX = touch.clientX;\n (dndEvent as any).clientY = touch.clientY;\n (dndEvent as any).pageX = touch.pageX;\n (dndEvent as any).pageY = touch.pageY;\n\n const targetRect = targetElement.getBoundingClientRect();\n (dndEvent as any).offsetX = dndEvent.clientX - targetRect.left;\n (dndEvent as any).offsetY = dndEvent.clientY - targetRect.top;\n\n return dndEvent;\n}\n\n/**\n * Calc center of polygon spanned by multiple touches in page (full page size, with hidden scrollable area) coordinates\n * or in viewport (screen coordinates) coordinates.\n */\nfunction updateCentroidCoordinatesOfTouchesIn(coordinateProp:string, event:TouchEvent, outPoint:Point):void {\n const pageXs:Array = [], pageYs:Array = [];\n for (let i = 0; i < event.touches.length; i++) {\n const touch = event.touches[i];\n pageXs.push(touch[coordinateProp + \"X\"]);\n pageYs.push(touch[coordinateProp + \"Y\"]);\n }\n outPoint.x = average(pageXs);\n outPoint.y = average(pageYs);\n}\n\nfunction prepareNodeCopyAsDragImage(srcNode:HTMLElement, dstNode:HTMLElement) {\n // Is this node an element?\n if (srcNode.nodeType === 1) {\n\n // Clone the style\n const cs = getComputedStyle(srcNode);\n for (let i = 0; i < cs.length; i++) {\n const csName = cs[i];\n dstNode.style.setProperty(csName, cs.getPropertyValue(csName), cs.getPropertyPriority(csName));\n }\n\n // no interaction with the drag image, pls! this is also important to make the drag image transparent for hit-testing\n // hit testing is done in the drag and drop iteration to find the element the user currently is hovering over while dragging.\n // if pointer-events is not none or a browser does behave in an unexpected way than the hit test transparency on the drag image\n // will break\n dstNode.style.pointerEvents = \"none\";\n\n // Remove any potential conflict attributes\n dstNode.removeAttribute(\"id\");\n dstNode.removeAttribute(\"class\");\n dstNode.removeAttribute(\"draggable\");\n }\n\n // Do the same for the children\n if (srcNode.hasChildNodes()) {\n for (let i = 0; i < srcNode.childNodes.length; i++) {\n prepareNodeCopyAsDragImage(srcNode.childNodes[i], dstNode.childNodes[i]);\n }\n }\n}\n\nfunction createDragImage(sourceNode:HTMLElement):HTMLElement {\n\n const dragImage = sourceNode.cloneNode(true);\n\n // this removes any id's and stuff that could interfere with drag and drop\n prepareNodeCopyAsDragImage(sourceNode, dragImage);\n\n // set layout styles for freely moving it around\n dragImage.style.position = \"absolute\";\n dragImage.style.left = \"0px\";\n dragImage.style.top = \"0px\";\n // on top of all\n dragImage.style.zIndex = \"999999\";\n\n // add polyfill class for default styling\n dragImage.classList.add(CLASS_DRAG_IMAGE);\n dragImage.classList.add(CLASS_DRAG_OPERATION_ICON);\n\n return dragImage;\n}\n\nfunction extractTransformStyles(sourceNode:HTMLElement):string[] {\n\n return TRANSFORM_CSS_VENDOR_PREFIXES.map(function (prefix) {\n\n let transform = sourceNode.style[prefix + \"transform\"];\n\n if (!transform || transform === \"none\") {\n return \"\";\n }\n\n // TODO what about translateX(x), translateY(x), translateZ(z), translate3d(x,y,z), matrix(*,*,*,*,x,y) ?\n\n // removes translate(x,y)\n return transform.replace(/translate\\(\\D*\\d+[^,]*,\\D*\\d+[^,]*\\)\\s*/g, \"\");\n });\n}\n\nfunction translateDragImage(dragImage:HTMLElement, pnt:Point, originalTransforms:string[], offset?:Point, centerOnCoordinates = true):void {\n\n let x = pnt.x, y = pnt.y;\n\n if (offset) {\n x += offset.x;\n y += offset.y;\n }\n\n if (centerOnCoordinates) {\n x -= (parseInt(dragImage.offsetWidth, 10) / 2);\n y -= (parseInt(dragImage.offsetHeight, 10) / 2);\n }\n\n // using translate3d for best performance\n const translate = \"translate3d(\" + x + \"px,\" + y + \"px, 0)\";\n\n for (let i = 0; i < TRANSFORM_CSS_VENDOR_PREFIXES.length; i++) {\n const transformProp = TRANSFORM_CSS_VENDOR_PREFIXES[i] + \"transform\";\n dragImage.style[transformProp] = translate + \" \" + originalTransforms[i];\n }\n}\n\n/**\n * calculates the coordinates of the drag source and transitions the drag image to those coordinates.\n * the drag operation is finished after the transition has ended.\n */\nfunction applyDragImageSnapback(sourceEl:HTMLElement, dragImage:HTMLElement, dragImageTransforms:string[], transitionEndCb:Function):void {\n\n const cs = getComputedStyle(sourceEl);\n\n if (cs.visibility === \"hidden\" || cs.display === \"none\") {\n console.log(\"dnd-poly: source node is not visible. skipping snapback transition.\");\n // shortcut to end the drag operation\n transitionEndCb();\n return;\n }\n // add class containing transition rules\n dragImage.classList.add(CLASS_DRAG_IMAGE_SNAPBACK);\n\n const csDragImage = getComputedStyle(dragImage);\n const durationInS = parseFloat(csDragImage.transitionDuration);\n if (isNaN(durationInS) || durationInS === 0) {\n console.log(\"dnd-poly: no transition used - skipping snapback\");\n transitionEndCb();\n return;\n }\n\n console.log(\"dnd-poly: starting dragimage snap back\");\n\n // calc source node position\n const rect = sourceEl.getBoundingClientRect();\n\n const pnt:Point = {\n x: rect.left,\n y: rect.top\n };\n\n // add scroll offset of document\n pnt.x += (document.body.scrollLeft || document.documentElement.scrollLeft);\n pnt.y += (document.body.scrollTop || document.documentElement.scrollTop);\n\n //TODO this sometimes fails.. find out when exactly and how to detect\n pnt.x -= parseInt(cs.marginLeft, 10);\n pnt.y -= parseInt(cs.marginTop, 10);\n\n const delayInS = parseFloat(csDragImage.transitionDelay);\n const durationInMs = Math.round((durationInS + delayInS) * 1000);\n\n // apply the translate\n translateDragImage(dragImage, pnt, dragImageTransforms, undefined, false);\n\n setTimeout(transitionEndCb, durationInMs);\n}\n\n//\n\n//\n\n/**\n * Implements \"6.\" in the processing steps defined for a dnd event\n * https://html.spec.whatwg.org/multipage/interaction.html#dragevent\n */\nfunction determineDropEffect(effectAllowed:string, sourceNode:Element) {\n\n // uninitialized\n if (!effectAllowed) {\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n //if( sourceNode.nodeType === 1 ) {\n //\n //return \"move\";\n //}\n\n // link\n if (sourceNode.nodeType === 3 && (sourceNode).tagName === \"A\") {\n return DROP_EFFECTS[DROP_EFFECT.LINK];\n }\n\n // copy\n return DROP_EFFECTS[DROP_EFFECT.COPY];\n }\n\n // none\n if (effectAllowed === ALLOWED_EFFECTS[EFFECT_ALLOWED.NONE]) {\n return DROP_EFFECTS[DROP_EFFECT.NONE];\n }\n // copy or all\n if (effectAllowed.indexOf(ALLOWED_EFFECTS[EFFECT_ALLOWED.COPY]) === 0 || effectAllowed === ALLOWED_EFFECTS[EFFECT_ALLOWED.ALL]) {\n return DROP_EFFECTS[DROP_EFFECT.COPY];\n }\n // link\n if (effectAllowed.indexOf(ALLOWED_EFFECTS[EFFECT_ALLOWED.LINK]) === 0) {\n return DROP_EFFECTS[DROP_EFFECT.LINK];\n }\n // move\n if (effectAllowed === ALLOWED_EFFECTS[EFFECT_ALLOWED.MOVE]) {\n return DROP_EFFECTS[DROP_EFFECT.MOVE];\n }\n\n // copy\n return DROP_EFFECTS[DROP_EFFECT.COPY];\n}\n\n/**\n * Reference https://html.spec.whatwg.org/multipage/interaction.html#dndevents\n */\nfunction dispatchDragEvent(dragEvent:string,\n targetElement:Element,\n touchEvent:TouchEvent,\n dataStore:DragDataStore,\n dataTransfer:DataTransfer,\n cancelable = true,\n relatedTarget:Element = null):boolean {\n\n console.log(\"dnd-poly: dispatching \" + dragEvent);\n\n if (DEBUG) {\n var debug_class = CLASS_PREFIX + \"debug\",\n debug_class_event_target = CLASS_PREFIX + \"event-target\",\n debug_class_event_related_target = CLASS_PREFIX + \"event-related-target\";\n targetElement.classList.add(debug_class);\n targetElement.classList.add(debug_class_event_target);\n if (relatedTarget) {\n relatedTarget.classList.add(debug_class);\n relatedTarget.classList.add(debug_class_event_related_target);\n }\n }\n\n const leaveEvt = createDragEventFromTouch(targetElement, touchEvent, dragEvent, cancelable, document.defaultView, dataTransfer, relatedTarget);\n const cancelled = !targetElement.dispatchEvent(leaveEvt);\n\n dataStore._mode = DragDataStoreMode._DISCONNECTED;\n\n if (DEBUG) {\n targetElement.classList.remove(debug_class_event_target);\n if (relatedTarget) {\n relatedTarget.classList.remove(debug_class_event_related_target);\n }\n }\n\n return cancelled;\n}\n\n/**\n * according to https://html.spec.whatwg.org/multipage/interaction.html#drag-and-drop-processing-model\n */\nfunction determineDragOperation(effectAllowed:string, dropEffect:string):string {\n\n // unitialized or all\n if (!effectAllowed || effectAllowed === ALLOWED_EFFECTS[7]) {\n return dropEffect;\n }\n\n if (dropEffect === DROP_EFFECTS[DROP_EFFECT.COPY]) {\n if (effectAllowed.indexOf(DROP_EFFECTS[DROP_EFFECT.COPY]) === 0) {\n return DROP_EFFECTS[DROP_EFFECT.COPY];\n }\n }\n else if (dropEffect === DROP_EFFECTS[DROP_EFFECT.LINK]) {\n if (effectAllowed.indexOf(DROP_EFFECTS[DROP_EFFECT.LINK]) === 0 || effectAllowed.indexOf(\"Link\") > -1) {\n return DROP_EFFECTS[DROP_EFFECT.LINK];\n }\n }\n else if (dropEffect === DROP_EFFECTS[DROP_EFFECT.MOVE]) {\n if (effectAllowed.indexOf(DROP_EFFECTS[DROP_EFFECT.MOVE]) === 0 || effectAllowed.indexOf(\"Move\") > -1) {\n return DROP_EFFECTS[DROP_EFFECT.MOVE];\n }\n }\n\n return DROP_EFFECTS[DROP_EFFECT.NONE];\n}\n\n//\n\n//\n\n/**\n * // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n */\n//public static ElementIsTextDropzone( element:HTMLElement, dragDataStore?:DragDataStore ) {\n//\n// if( dragDataStore && !dragDataStore.data[ \"text/plain\" ] ) {\n// return false;\n// }\n//\n// if( element.isContentEditable ) {\n// return true;\n// }\n//\n// if( element.tagName === \"TEXTAREA\" ) {\n// return true;\n// }\n//\n// if( element.tagName === \"INPUT\" ) {\n// if( element.getAttribute( \"type\" ) === \"text\" ) {\n// return true;\n// }\n// }\n//\n// return false;\n//}\n\n/**\n * NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n *\n * Helper method for recursively go from a nested element up the ancestor chain\n * to see if any element has a dropzone.\n */\n//private static FindDropzoneElement( element:HTMLElement ):HTMLElement {\n//\n// if( !element || !element.hasAttribute || typeof element.hasAttribute !== \"function\" ) {\n// return null;\n// }\n//\n// if( element.hasAttribute( \"dropzone\" ) ) {\n// return element;\n// }\n//\n// if( element === window.document.body ) {\n// return null;\n// }\n//\n// return DragOperationController.FindDropzoneElement( element.parentElement );\n//}\n\n/**\n * NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n *\n * Polyfills https://html.spec.whatwg.org/multipage/interaction.html#the-dropzone-attribute\n * by implementing the dropzone processing steps.\n */\n//private static GetOperationForMatchingDropzone( element:HTMLElement, dragDataStore:DragDataStore ):string {\n\n// If the current target element is an element with a dropzone attribute that matches the drag data store and specifies an operation\n// Set the current drag operation to the operation specified by the dropzone attribute of the current target element.\n// If the current target element is an element with a dropzone attribute that matches the drag data store and does not specify an operation\n// Set the current drag operation to \"copy\".\n// Otherwise\n// Reset the current drag operation to \"none\".\n//var value = element.getAttribute( \"dropzone\" );\n//if( !value ) {\n//\n// return \"none\";\n//}\n//\n//var matched = false;\n//var operation;\n//var keywords = value.split( \" \" );\n//\n//for( var i:number = 0; i < keywords.length; i++ ) {\n// var keyword = keywords[ i ];\n//\n// if( keyword === \"copy\" || keyword === \"move\" || keyword === \"link\" ) {\n// if( !operation ) {\n// operation = keyword;\n// }\n// continue;\n// }\n//\n// if( keyword.length < 3 || keyword[ 1 ] !== \":\" ) {\n// continue;\n// }\n//\n// var splitKeyword = keyword.split( \":\" );\n// var kind = splitKeyword[ 0 ].toLowerCase();\n// var type = splitKeyword[ 1 ].toLowerCase();\n//\n// if( dragDataStore.types.indexOf( type ) > -1 ) {\n// matched = true;\n// }\n//}\n//\n//if( !matched ) {\n// return \"none\";\n//}\n//\n//if( !operation ) {\n// return \"copy\";\n//}\n//\n//return operation;\n//}\n\n//\n"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":null,"sources":["/Users/stefansteinhart/Development/Web/ios-html5-drag-drop-shim/src/index.ts"],"sourcesContent":["// debug mode, which will highlight drop target, immediate user selection and events fired as you interact.\nconst DEBUG = false;\n\n//\n\ninterface DetectedFeatures {\n draggable:boolean;\n dragEvents:boolean;\n touchEvents:boolean;\n userAgentSupportingNativeDnD:boolean;\n}\n\nfunction detectFeatures():DetectedFeatures {\n\n let features:DetectedFeatures = {\n dragEvents: (\"ondragstart\" in document.documentElement),\n draggable: (\"draggable\" in document.documentElement),\n touchEvents: (\"ontouchstart\" in document.documentElement),\n userAgentSupportingNativeDnD: undefined\n };\n\n const isBlinkEngine = !!((window).chrome) || /chrome/i.test(navigator.userAgent);\n\n features.userAgentSupportingNativeDnD = !(\n // if is mobile safari or android browser -> no native dnd\n (/iPad|iPhone|iPod|Android/.test(navigator.userAgent))\n || // OR\n //if is blink(chrome/opera) with touch events enabled -> no native dnd\n (isBlinkEngine && features.touchEvents)\n );\n\n if (DEBUG) {\n Object.keys(features).forEach(function (key) {\n console.log(\"dnd-poly: detected feature '\" + key + \" = \" + features[key] + \"'\");\n });\n }\n\n return features;\n}\n\nlet supportsPassive:boolean;\n\nfunction supportsPassiveEventListener():boolean {\n\n let supportsPassiveEventListeners = false;\n\n // reference https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n try {\n let opts = Object.defineProperty({}, \"passive\", {\n get: function () {\n supportsPassiveEventListeners = true;\n }\n });\n window.addEventListener(\"test\", null, opts);\n }\n // tslint:disable-next-line:no-empty\n catch (e) {\n }\n\n return supportsPassiveEventListeners;\n}\n\n//\n\n//\n\n// function signature for the dragImageTranslateOverride hook\nexport type DragImageTranslateOverrideFn = (// corresponding touchmove event\n event:TouchEvent,\n // the processed touch event viewport coordinates\n hoverCoordinates:Point,\n // the element under the calculated touch coordinates\n hoveredElement:HTMLElement,\n // callback for updating the drag image offset\n translateDragImageFn:(offsetX:number, offsetY:number) => void) => void;\n\nexport interface Config {\n // flag to force the polyfill being applied and not rely on internal feature detection\n forceApply?:boolean;\n // useful for when you want the default drag image but still want to apply\n // some static offset from touch coordinates to drag image coordinates\n // defaults to (0,0)\n dragImageOffset?:Point;\n // if the dragImage shall be centered on the touch coordinates\n // defaults to false\n dragImageCenterOnTouch?:boolean;\n // the drag and drop operation involves some processing. here you can specify in what interval this processing takes place.\n // defaults to 150ms\n iterationInterval?:number;\n // hook for custom logic that decides if a drag operation should start\n dragStartConditionOverride?:(event:TouchEvent) => boolean;\n // hook for custom logic that can manipulate the drag image translate offset\n dragImageTranslateOverride?:DragImageTranslateOverrideFn;\n // hook for custom logic that can override the default action based on the original touch event when the drag never started\n // be sure to call event.preventDefault() if handling the default action in the override to prevent the browser default.\n defaultActionOverride?: (event: TouchEvent) => void;\n // Drag action delay on touch devices (\"hold to drag\" functionality, useful for scrolling draggable items). Defaults to no delay.\n holdToDrag?: number;\n}\n\n// default config\nconst config:Config = {\n iterationInterval: 150,\n};\n\nexport function polyfill(override?:Config):boolean {\n\n if (override) {\n // overwrite default config with user config\n Object.keys(override).forEach(function (key) {\n config[key] = override[key];\n });\n }\n\n // only do feature detection when config does not force apply the polyfill\n if (!config.forceApply) {\n\n // feature/browser detection\n const detectedFeatures = detectFeatures();\n\n // check if native drag and drop support is there\n if (detectedFeatures.userAgentSupportingNativeDnD\n && detectedFeatures.draggable\n && detectedFeatures.dragEvents) {\n // no polyfilling required\n return false;\n }\n }\n\n console.log(\"dnd-poly: Applying mobile drag and drop polyfill.\");\n\n supportsPassive = supportsPassiveEventListener();\n\n // add listeners suitable for detecting a potential drag operation\n if (config.holdToDrag) {\n addDocumentListener(\"touchstart\", onDelayTouchstart, false);\n } else {\n addDocumentListener(\"touchstart\", onTouchstart, false);\n }\n\n return true;\n}\n\n//\n\n//\n\n// reference the currently active drag operation\nlet activeDragOperation:DragOperationController;\n\n/**\n * event handler listening for initial events that possibly start a drag and drop operation.\n */\nfunction onTouchstart(e:TouchEvent) {\n\n console.log(\"dnd-poly: global touchstart\");\n\n // From the moment that the user agent is to initiate the drag-and-drop operation,\n // until the end of the drag-and-drop operation, device input events (e.g. mouse and keyboard events) must be suppressed.\n\n // only allow one drag operation at a time\n if (activeDragOperation) {\n console.log(\"dnd-poly: drag operation already active\");\n return;\n }\n\n let dragTarget = tryFindDraggableTarget(e);\n\n // If there is no such element, then nothing is being dragged; abort these\n // steps, the drag-and-drop operation is never started.\n if (!dragTarget) {\n return;\n }\n\n try {\n activeDragOperation = new DragOperationController(e, config, dragTarget, dragOperationEnded);\n }\n catch (err) {\n dragOperationEnded(config, e, DragOperationState.CANCELLED);\n // rethrow exception after cleanup\n throw err;\n }\n}\n\n/**\n * Search for a possible draggable item upon an event that can initialize a drag operation.\n */\nfunction tryFindDraggableTarget(event:TouchEvent):Element {\n\n //1. Determine what is being dragged, as follows:\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the drag operation was invoked on a selection, then it is the selection that is being dragged.\n //if( (event.target).nodeType === 3 ) {\n //\n // config.log( \"drag on text\" );\n // return event.target;\n //}\n //Otherwise, if the drag operation was invoked on a Document, it is the first element, going up the ancestor chain, starting at the node that the\n // user tried to drag, that has the IDL attribute draggable set to true.\n //else {\n\n let el = event.target;\n\n do {\n if (el.draggable === false) {\n continue;\n }\n if (el.getAttribute && el.getAttribute(\"draggable\") === \"true\") {\n return el;\n }\n } while ((el = el.parentNode) && el !== document.body);\n}\n\n/**\n * Implements callback invoked when a drag operation has ended or crashed.\n */\nfunction dragOperationEnded(_config:Config, event:TouchEvent, state:DragOperationState) {\n\n // we need to make the default action happen only when no drag operation took place\n if (state === DragOperationState.POTENTIAL) {\n\n console.log(\"dnd-poly: Drag never started. Last event was \" + event.type);\n\n // when lifecycle hook is present\n if (_config.defaultActionOverride) {\n\n try {\n\n _config.defaultActionOverride(event);\n\n if (event.defaultPrevented) {\n\n console.log(\"dnd-poly: defaultActionOverride has taken care of triggering the default action. preventing default on original event\");\n }\n\n }\n catch (e) {\n\n console.log(\"dnd-poly: error in defaultActionOverride: \" + e);\n }\n }\n }\n\n // reset drag operation container\n activeDragOperation = null;\n}\n\n//\n\n//\n\n/**\n * For tracking the different states of a drag operation.\n */\nconst enum DragOperationState {\n // initial state of a controller, if no movement is detected the operation ends with this state\n POTENTIAL,\n // after movement is detected the drag operation starts and keeps this state until it ends\n STARTED,\n // when the drag operation ended normally\n ENDED,\n // when the drag operation ended with a cancelled input event\n CANCELLED\n}\n\n// contains all possible values of the effectAllowed property\nconst enum EFFECT_ALLOWED {\n NONE = 0,\n COPY = 1,\n COPY_LINK = 2,\n COPY_MOVE = 3,\n LINK = 4,\n LINK_MOVE = 5,\n MOVE = 6,\n ALL = 7\n}\n\nconst ALLOWED_EFFECTS = [\"none\", \"copy\", \"copyLink\", \"copyMove\", \"link\", \"linkMove\", \"move\", \"all\"];\n\n// contains all possible values of the dropEffect property\nconst enum DROP_EFFECT {\n NONE = 0,\n COPY = 1,\n MOVE = 2,\n LINK = 3,\n}\n\nconst DROP_EFFECTS = [\"none\", \"copy\", \"move\", \"link\"];\n\n// cross-browser css transform property prefixes\nconst TRANSFORM_CSS_VENDOR_PREFIXES = [\"\", \"-webkit-\"];\n// css classes\nconst CLASS_PREFIX = \"dnd-poly-\";\nconst CLASS_DRAG_IMAGE = CLASS_PREFIX + \"drag-image\";\nconst CLASS_DRAG_IMAGE_SNAPBACK = CLASS_PREFIX + \"snapback\";\nconst CLASS_DRAG_OPERATION_ICON = CLASS_PREFIX + \"icon\";\n\n/**\n * Aims to implement the HTML5 d'n'd spec (https://html.spec.whatwg.org/multipage/interaction.html#dnd) as close as it can get.\n * Note that all props that are private should start with an underscore to enable better minification.\n *\n * TODO remove lengthy spec comments in favor of short references to the spec\n */\nclass DragOperationController {\n\n private _dragOperationState:DragOperationState = DragOperationState.POTENTIAL;\n\n private _dragImage:HTMLElement;\n private _dragImageTransforms:string[];\n private _dragImagePageCoordinates:Point; // the current page coordinates of the dragImage\n private _dragImageOffset:Point; // offset of the drag image relative to the coordinates\n\n private _currentHotspotCoordinates:Point; // the point relative to viewport for determining the immediate user selection\n\n private _immediateUserSelection:HTMLElement = null; // the element the user currently hovers while dragging\n private _currentDropTarget:HTMLElement = null; // the element that was selected as a valid drop target by the d'n'd operation\n\n private _dragDataStore:DragDataStore;\n private _dataTransfer:DataTransfer;\n\n private _currentDragOperation:string; // the current drag operation set according to the d'n'd processing model\n\n private _initialTouch:Touch; // the identifier for the touch that initiated the drag operation\n private _touchMoveHandler:EventListener;\n private _touchEndOrCancelHandler:EventListener;\n private _lastTouchEvent:TouchEvent;\n\n private _iterationLock:boolean;\n private _iterationIntervalId:number;\n\n constructor(private _initialEvent:TouchEvent,\n private _config:Config,\n private _sourceNode:HTMLElement,\n private _dragOperationEndedCb:(config:Config, event:TouchEvent, state:DragOperationState) => void) {\n\n console.log(\"dnd-poly: setting up potential drag operation..\");\n\n this._lastTouchEvent = _initialEvent;\n this._initialTouch = _initialEvent.changedTouches[0];\n\n // create bound event listeners\n this._touchMoveHandler = this._onTouchMove.bind(this);\n this._touchEndOrCancelHandler = this._onTouchEndOrCancel.bind(this);\n addDocumentListener(\"touchmove\", this._touchMoveHandler, false);\n addDocumentListener(\"touchend\", this._touchEndOrCancelHandler, false);\n addDocumentListener(\"touchcancel\", this._touchEndOrCancelHandler, false);\n\n // the only thing we do is setup the touch listeners. if drag will really start is decided in touch move handler.\n\n //\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // 3. Establish which DOM node is the source node, as follows:\n // If it is a selection that is being dragged, then the source node is the text node that the user started the drag on (typically the text node\n // that the user originally clicked). If the user did not specify a particular node, for example if the user just told the user agent to begin\n // a drag of \"the selection\", then the source node is the first text node containing a part of the selection. Otherwise, if it is an element\n // that is being dragged, then the source node is the element that is being dragged. Otherwise, the source node is part of another document or\n // application. When this specification requires that an event be dispatched at the source node in this case, the user agent must instead\n // follow the platform-specific conventions relevant to that situation.\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // 4. Determine the list of dragged nodes, as follows:\n\n // If it is a selection that is being dragged, then the list of dragged nodes contains, in tree order, every node that is partially or\n // completely included in the selection (including all their ancestors).\n\n // Otherwise, the list of dragged nodes contains only the source node, if any.\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // 5. If it is a selection that is being dragged, then add an item to the drag data store item list, with its properties set as follows:\n\n //The drag data item type string\n //\"text/plain\"\n //The drag data item kind\n //Plain Unicode string\n //The actual data\n //The text of the selection\n //Otherwise, if any files are being dragged, then add one item per file to the drag data store item list, with their properties set as follows:\n //\n //The drag data item type string\n //The MIME type of the file, if known, or \"application/octet-stream\" otherwise.\n // The drag data item kind\n //File\n //The actual data\n //The file's contents and name.\n //Dragging files can currently only happen from outside a browsing context, for example from a file system manager application.\n //\n // If the drag initiated outside of the application, the user agent must add items to the drag data store item list as appropriate for the data\n // being dragged, honoring platform conventions where appropriate; however, if the platform conventions do not use MIME types to label dragged\n // data, the user agent must make a best-effort attempt to map the types to MIME types, and, in any case, all the drag data item type strings must\n // be converted to ASCII lowercase. Perform drag-and-drop initialization steps defined in any other applicable specifications.\n\n //\n }\n\n //\n\n /**\n * Setup dragImage, input listeners and the drag\n * and drop process model iteration interval.\n */\n private _setup():boolean {\n console.log(\"dnd-poly: starting drag and drop operation\");\n\n this._dragOperationState = DragOperationState.STARTED;\n\n this._currentDragOperation = DROP_EFFECTS[DROP_EFFECT.NONE];\n\n this._dragDataStore = {\n _data: {},\n _effectAllowed: undefined,\n _mode: DragDataStoreMode.PROTECTED,\n _types: [],\n };\n\n this._currentHotspotCoordinates = {\n x: null,\n y: null\n };\n\n this._dragImagePageCoordinates = {\n x: null,\n y: null\n };\n\n let dragImageSrc:HTMLElement = this._sourceNode;\n\n this._dataTransfer = new DataTransfer(this._dragDataStore, (element:HTMLElement, x:number, y:number) => {\n\n dragImageSrc = element;\n\n if (typeof x === \"number\" || typeof y === \"number\") {\n this._dragImageOffset = {\n x: x || 0,\n y: y || 0\n };\n }\n });\n\n // 9. Fire a DND event named dragstart at the source node.\n this._dragDataStore._mode = DragDataStoreMode.READWRITE;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n if (dispatchDragEvent(\"dragstart\", this._sourceNode, this._lastTouchEvent, this._dragDataStore, this._dataTransfer)) {\n console.log(\"dnd-poly: dragstart cancelled\");\n // dragstart has been prevented -> cancel d'n'd\n this._dragOperationState = DragOperationState.CANCELLED;\n this._cleanup();\n return false;\n }\n\n updateCentroidCoordinatesOfTouchesIn(\"page\", this._lastTouchEvent, this._dragImagePageCoordinates);\n this._dragImage = createDragImage(dragImageSrc);\n this._dragImageTransforms = extractTransformStyles(this._dragImage);\n\n if (!this._dragImageOffset) {\n\n // apply specific offset\n if (this._config.dragImageOffset) {\n\n this._dragImageOffset = {\n x: this._config.dragImageOffset.x,\n y: this._config.dragImageOffset.y\n };\n }\n // center drag image on touch coordinates\n else if (this._config.dragImageCenterOnTouch) {\n\n const cs = getComputedStyle(dragImageSrc);\n this._dragImageOffset = {\n x: 0 - parseInt(cs.marginLeft, 10),\n y: 0 - parseInt(cs.marginTop, 10)\n };\n }\n // by default initialize drag image offset the same as desktop\n else {\n\n const targetRect = dragImageSrc.getBoundingClientRect();\n const cs = getComputedStyle(dragImageSrc);\n this._dragImageOffset = {\n x: targetRect.left - this._initialTouch.clientX - parseInt(cs.marginLeft, 10) + targetRect.width / 2,\n y: targetRect.top - this._initialTouch.clientY - parseInt(cs.marginTop, 10) + targetRect.height / 2\n };\n }\n }\n\n translateDragImage(this._dragImage, this._dragImagePageCoordinates, this._dragImageTransforms, this._dragImageOffset, this._config.dragImageCenterOnTouch);\n document.body.appendChild(this._dragImage);\n\n // 10. Initiate the drag-and-drop operation in a manner consistent with platform conventions, and as described below.\n this._iterationIntervalId = setInterval(() => {\n\n // If the user agent is still performing the previous iteration of the sequence (if any) when the next iteration becomes due,\n // abort these steps for this iteration (effectively \"skipping missed frames\" of the drag-and-drop operation).\n if (this._iterationLock) {\n console.log(\"dnd-poly: iteration skipped because previous iteration hast not yet finished.\");\n return;\n }\n this._iterationLock = true;\n\n this._dragAndDropProcessModelIteration();\n\n this._iterationLock = false;\n }, this._config.iterationInterval);\n\n return true;\n }\n\n private _cleanup() {\n\n console.log(\"dnd-poly: cleanup\");\n\n if (this._iterationIntervalId) {\n clearInterval(this._iterationIntervalId);\n this._iterationIntervalId = null;\n }\n\n removeDocumentListener(\"touchmove\", this._touchMoveHandler);\n removeDocumentListener(\"touchend\", this._touchEndOrCancelHandler);\n removeDocumentListener(\"touchcancel\", this._touchEndOrCancelHandler);\n\n if (this._dragImage) {\n this._dragImage.parentNode.removeChild(this._dragImage);\n this._dragImage = null;\n }\n\n this._dragOperationEndedCb(this._config, this._lastTouchEvent, this._dragOperationState);\n }\n\n //\n\n //\n\n private _onTouchMove(event:TouchEvent) {\n\n // filter unrelated touches\n if (isTouchIdentifierContainedInTouchEvent(event, this._initialTouch.identifier) === false) {\n return;\n }\n\n // update the reference to the last received touch event\n this._lastTouchEvent = event;\n\n // drag operation did not start yet but on movement it should start\n if (this._dragOperationState === DragOperationState.POTENTIAL) {\n\n let startDrag:boolean;\n\n // is a lifecycle hook present?\n if (this._config.dragStartConditionOverride) {\n\n try {\n startDrag = this._config.dragStartConditionOverride(event);\n }\n catch (e) {\n console.error(\"dnd-poly: error in dragStartConditionOverride hook: \" + e);\n startDrag = false;\n }\n }\n else {\n\n // by default only allow a single moving finger to initiate a drag operation\n startDrag = (event.touches.length === 1);\n }\n\n if (!startDrag) {\n\n this._cleanup();\n return;\n }\n\n // setup will return true when drag operation starts\n if (this._setup() === true) {\n\n // prevent scrolling when drag operation starts\n this._initialEvent.preventDefault();\n event.preventDefault();\n }\n\n return;\n }\n\n console.log(\"dnd-poly: moving draggable..\");\n\n // we emulate d'n'd so we dont want any defaults to apply\n event.preventDefault();\n\n // populate shared coordinates from touch event\n updateCentroidCoordinatesOfTouchesIn(\"client\", event, this._currentHotspotCoordinates);\n updateCentroidCoordinatesOfTouchesIn(\"page\", event, this._dragImagePageCoordinates);\n\n if (this._config.dragImageTranslateOverride) {\n\n try {\n\n let handledDragImageTranslate = false;\n\n this._config.dragImageTranslateOverride(\n event,\n {\n x: this._currentHotspotCoordinates.x,\n y: this._currentHotspotCoordinates.y\n },\n this._immediateUserSelection,\n (offsetX:number, offsetY:number) => {\n\n // preventing translation of drag image when there was a drag operation cleanup meanwhile\n if (!this._dragImage) {\n return;\n }\n\n handledDragImageTranslate = true;\n\n this._currentHotspotCoordinates.x += offsetX;\n this._currentHotspotCoordinates.y += offsetY;\n this._dragImagePageCoordinates.x += offsetX;\n this._dragImagePageCoordinates.y += offsetY;\n\n translateDragImage(\n this._dragImage,\n this._dragImagePageCoordinates,\n this._dragImageTransforms,\n this._dragImageOffset,\n this._config.dragImageCenterOnTouch\n );\n }\n );\n\n if (handledDragImageTranslate) {\n return;\n }\n }\n catch (e) {\n console.log(\"dnd-poly: error in dragImageTranslateOverride hook: \" + e);\n }\n }\n\n translateDragImage(this._dragImage, this._dragImagePageCoordinates, this._dragImageTransforms, this._dragImageOffset, this._config.dragImageCenterOnTouch);\n }\n\n private _onTouchEndOrCancel(event:TouchEvent) {\n\n // filter unrelated touches\n if (isTouchIdentifierContainedInTouchEvent(event, this._initialTouch.identifier) === false) {\n return;\n }\n\n // let the dragImageTranslateOverride know that its over\n if (this._config.dragImageTranslateOverride) {\n try {\n /* tslint:disable */\n this._config.dragImageTranslateOverride(undefined, undefined, undefined, function () {\n });\n }\n catch (e) {\n console.log(\"dnd-poly: error in dragImageTranslateOverride hook: \" + e);\n }\n }\n\n // drag operation did not even start\n if (this._dragOperationState === DragOperationState.POTENTIAL) {\n this._cleanup();\n return;\n }\n\n // we emulate d'n'd so we dont want any defaults to apply\n event.preventDefault();\n\n this._dragOperationState = (event.type === \"touchcancel\") ? DragOperationState.CANCELLED : DragOperationState.ENDED;\n }\n\n //\n\n //\n\n /**\n * according to https://html.spec.whatwg.org/multipage/interaction.html#drag-and-drop-processing-model\n */\n private _dragAndDropProcessModelIteration():void {\n\n if (DEBUG) {\n var debug_class = CLASS_PREFIX + \"debug\",\n debug_class_user_selection = CLASS_PREFIX + \"immediate-user-selection\",\n debug_class_drop_target = CLASS_PREFIX + \"current-drop-target\";\n }\n\n const previousDragOperation = this._currentDragOperation;\n\n // Fire a DND event named drag event at the source node.\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n const dragCancelled = dispatchDragEvent(\"drag\", this._sourceNode, this._lastTouchEvent, this._dragDataStore, this._dataTransfer);\n if (dragCancelled) {\n console.log(\"dnd-poly: drag event cancelled.\");\n // If this event is canceled, the user agent must set the current drag operation to \"none\" (no drag operation).\n this._currentDragOperation = DROP_EFFECTS[DROP_EFFECT.NONE];\n }\n\n // Otherwise, if the user ended the drag-and-drop operation (e.g. by releasing the mouse button in a mouse-driven drag-and-drop interface),\n // or if the drag event was canceled, then this will be the last iteration.\n if (dragCancelled || this._dragOperationState === DragOperationState.ENDED || this._dragOperationState === DragOperationState.CANCELLED) {\n\n const dragFailed = this._dragOperationEnded(this._dragOperationState);\n\n // if drag failed transition snap back\n if (dragFailed) {\n\n applyDragImageSnapback(this._sourceNode, this._dragImage, this._dragImageTransforms, () => {\n this._finishDragOperation();\n });\n return;\n }\n\n // Otherwise immediately\n // Fire a DND event named dragend at the source node.\n this._finishDragOperation();\n return;\n }\n\n // If the drag event was not canceled and the user has not ended the drag-and-drop operation,\n // check the state of the drag-and-drop operation, as follows:\n const newUserSelection:HTMLElement = document.elementFromPoint(this._currentHotspotCoordinates.x, this._currentHotspotCoordinates.y);\n\n console.log(\"dnd-poly: new immediate user selection is: \" + newUserSelection);\n\n const previousTargetElement = this._currentDropTarget;\n\n // If the user is indicating a different immediate user selection than during the last iteration (or if this is the first iteration),\n // and if this immediate user selection is not the same as the current target element,\n // then fire a DND event named dragexit at the current target element,\n // and then update the current target element as follows:\n if (newUserSelection !== this._immediateUserSelection && newUserSelection !== this._currentDropTarget) {\n\n if (DEBUG) {\n\n if (this._immediateUserSelection) {\n this._immediateUserSelection.classList.remove(debug_class_user_selection);\n }\n\n if (newUserSelection) {\n newUserSelection.classList.add(debug_class);\n newUserSelection.classList.add(debug_class_user_selection);\n }\n }\n\n this._immediateUserSelection = newUserSelection;\n\n if (this._currentDropTarget !== null) {\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n dispatchDragEvent(\"dragexit\", this._currentDropTarget, this._lastTouchEvent, this._dragDataStore, this._dataTransfer, false);\n }\n\n // If the new immediate user selection is null\n if (this._immediateUserSelection === null) {\n //Set the current target element to null also.\n this._currentDropTarget = this._immediateUserSelection;\n\n console.log(\"dnd-poly: current drop target changed to null\");\n }\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the new immediate user selection is in a non-DOM document or application\n // else if() {\n // Set the current target element to the immediate user selection.\n // this.currentDropTarget = this.immediateUserSelection;\n // return;\n // }\n // Otherwise\n else {\n // Fire a DND event named dragenter at the immediate user selection.\n //the polyfill cannot determine if a handler even exists as browsers do to silently\n // allow drop when no listener existed, so this event MUST be handled by the client\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = determineDropEffect(this._dragDataStore._effectAllowed, this._sourceNode);\n if (dispatchDragEvent(\"dragenter\", this._immediateUserSelection, this._lastTouchEvent, this._dragDataStore, this._dataTransfer)) {\n console.log(\"dnd-poly: dragenter default prevented\");\n // If the event is canceled, then set the current target element to the immediate user selection.\n this._currentDropTarget = this._immediateUserSelection;\n this._currentDragOperation = determineDragOperation(this._dataTransfer.effectAllowed, this._dataTransfer.dropEffect);\n }\n // Otherwise, run the appropriate step from the following list:\n else {\n\n // NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n //console.log( \"dnd-poly: dragenter not prevented, searching for dropzone..\" );\n //var newTarget = DragOperationController.FindDropzoneElement( this.immediateUserSelection );\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the current target element is a text field (e.g. textarea, or an input element whose type attribute is in the Text state) or an\n // editable element, and the drag data store item list has an item with the drag data item type string \"text/plain\" and the drag data\n // item kind Plain Unicode string\n //if( ElementIsTextDropzone( this.immediateUserSelection, this.dragDataStore ) ) {\n //Set the current target element to the immediate user selection anyway.\n //this.currentDropTarget = this.immediateUserSelection;\n //}\n //else\n // If the current target element is an element with a dropzone attribute that matches the drag data store\n //if( newTarget === this.immediateUserSelection &&\n // DragOperationController.GetOperationForMatchingDropzone( this.immediateUserSelection, this.dragDataStore ) !== \"none\" ) {\n // Set the current target element to the immediate user selection anyway.\n // this.currentDropTarget = this.immediateUserSelection;\n //}\n // If the immediate user selection is an element that itself has an ancestor element\n // with a dropzone attribute that matches the drag data store\n // NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n //else if( newTarget !== null && DragOperationController.GetOperationForMatchingDropzone( newTarget, this.dragDataStore ) ) {\n\n // If the immediate user selection is new target, then leave the current target element unchanged.\n\n // Otherwise, fire a DND event named dragenter at new target, with the current target element\n // as the specific related target. Then, set the current target element to new target,\n // regardless of whether that event was canceled or not.\n //this.dragenter( newTarget, this.currentDropTarget );\n //this.currentDropTarget = newTarget;\n //}\n // If the current target element is not the body element\n //else\n if (this._immediateUserSelection !== document.body) {\n // Fire a DND event named dragenter at the body element, and set the current target element to the body element, regardless of\n // whether that event was canceled or not.\n // Note: If the body element is null, then the event will be fired at the Document object (as\n // required by the definition of the body element), but the current target element would be set to null, not the Document object.\n\n // We do not listen to what the spec says here because this results in doubled events on the body/document because if the first one\n // was not cancelled it will have bubbled up to the body already ;)\n // this.dragenter( window.document.body );\n this._currentDropTarget = document.body;\n }\n // Otherwise\n //else {\n // leave the current drop target unchanged\n //}\n }\n }\n }\n\n // If the previous step caused the current target element to change,\n // and if the previous target element was not null or a part of a non-DOM document,\n // then fire a DND event named dragleave at the previous target element.\n if (previousTargetElement !== this._currentDropTarget && (isDOMElement(previousTargetElement) )) {\n\n if (DEBUG) {\n previousTargetElement.classList.remove(debug_class_drop_target);\n }\n\n console.log(\"dnd-poly: current drop target changed.\");\n\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n dispatchDragEvent(\"dragleave\", previousTargetElement, this._lastTouchEvent, this._dragDataStore, this._dataTransfer, false, this._currentDropTarget);\n }\n\n // If the current target element is a DOM element, then fire a DND event named dragover at this current target element.\n if (isDOMElement(this._currentDropTarget)) {\n\n if (DEBUG) {\n this._currentDropTarget.classList.add(debug_class);\n this._currentDropTarget.classList.add(debug_class_drop_target);\n }\n\n // If the dragover event is not canceled, run the appropriate step from the following list:\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = determineDropEffect(this._dragDataStore._effectAllowed, this._sourceNode);\n if (dispatchDragEvent(\"dragover\", this._currentDropTarget, this._lastTouchEvent, this._dragDataStore, this._dataTransfer) === false) {\n\n console.log(\"dnd-poly: dragover not prevented on possible drop-target.\");\n // NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the current target element is a text field (e.g. textarea, or an input element whose type attribute is in the Text state) or\n // an editable element, and the drag data store item list has an item with the drag data item type string \"text/plain\" and the drag\n // data item kind Plain Unicode string\n //if( ElementIsTextDropzone( this.currentDropTarget, this.dragDataStore ) ) {\n // Set the current drag operation to either \"copy\" or \"move\", as appropriate given the platform conventions.\n //this.currentDragOperation = \"copy\"; //or move. spec says its platform specific behaviour.\n //}\n //else {\n // If the current target element is an element with a dropzone attribute that matches the drag data store\n //this.currentDragOperation = DragOperationController.GetOperationForMatchingDropzone( this.currentDropTarget, this.dragDataStore );\n //}\n // when dragover is not prevented and no dropzones are there, no drag operation\n this._currentDragOperation = DROP_EFFECTS[DROP_EFFECT.NONE];\n }\n // Otherwise (if the dragover event is canceled), set the current drag operation based on the values of the effectAllowed and\n // dropEffect attributes of the DragEvent object's dataTransfer object as they stood after the event dispatch finished\n else {\n\n console.log(\"dnd-poly: dragover prevented.\");\n\n this._currentDragOperation = determineDragOperation(this._dataTransfer.effectAllowed, this._dataTransfer.dropEffect);\n }\n }\n\n console.log(\"dnd-poly: d'n'd iteration ended. current drag operation: \" + this._currentDragOperation);\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // Otherwise, if the current target element is not a DOM element, use platform-specific mechanisms to determine what drag operation is\n // being performed (none, copy, link, or move), and set the current drag operation accordingly.\n\n //Update the drag feedback (e.g. the mouse cursor) to match the current drag operation, as follows:\n // ---------------------------------------------------------------------------------------------------------\n // Drag operation |\tFeedback\n // \"copy\"\t | Data will be copied if dropped here.\n // \"link\"\t | Data will be linked if dropped here.\n // \"move\"\t | Data will be moved if dropped here.\n // \"none\"\t | No operation allowed, dropping here will cancel the drag-and-drop operation.\n // ---------------------------------------------------------------------------------------------------------\n\n if (previousDragOperation !== this._currentDragOperation) {\n this._dragImage.classList.remove(CLASS_PREFIX + previousDragOperation);\n }\n\n const currentDragOperationClass = CLASS_PREFIX + this._currentDragOperation;\n\n if (this._dragImage.classList.contains(currentDragOperationClass) === false) {\n this._dragImage.classList.add(currentDragOperationClass);\n }\n }\n\n /**\n * according to https://html.spec.whatwg.org/multipage/interaction.html#drag-and-drop-processing-model\n */\n private _dragOperationEnded(state:DragOperationState):boolean {\n\n console.log(\"dnd-poly: drag operation end detected with \" + this._currentDragOperation);\n\n if (DEBUG) {\n\n var debug_class_user_selection = CLASS_PREFIX + \"immediate-user-selection\",\n debug_class_drop_target = CLASS_PREFIX + \"current-drop-target\";\n\n if (this._currentDropTarget) {\n this._currentDropTarget.classList.remove(debug_class_drop_target);\n\n }\n if (this._immediateUserSelection) {\n this._immediateUserSelection.classList.remove(debug_class_user_selection);\n }\n }\n\n //var dropped:boolean = undefined;\n\n // Run the following steps, then stop the drag-and-drop operation:\n\n // If the current drag operation is \"none\" (no drag operation), or,\n // if the user ended the drag-and-drop operation by canceling it (e.g. by hitting the Escape key), or\n // if the current target element is null, then the drag operation failed.\n const dragFailed = (this._currentDragOperation === DROP_EFFECTS[DROP_EFFECT.NONE]\n || this._currentDropTarget === null\n || state === DragOperationState.CANCELLED);\n if (dragFailed) {\n\n // Run these substeps:\n\n // Let dropped be false.\n //dropped = false;\n\n // If the current target element is a DOM element, fire a DND event named dragleave at it;\n if (isDOMElement(this._currentDropTarget)) {\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n dispatchDragEvent(\"dragleave\", this._currentDropTarget, this._lastTouchEvent, this._dragDataStore, this._dataTransfer, false);\n }\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // otherwise, if it is not null, use platform-specific conventions for drag cancellation.\n //else if( this.currentDropTarget !== null ) {\n //}\n }\n // Otherwise, the drag operation was as success; run these substeps:\n else {\n\n // Let dropped be true.\n //dropped = true;\n\n // If the current target element is a DOM element, fire a DND event named drop at it;\n if (isDOMElement(this._currentDropTarget)) {\n\n // If the event is canceled, set the current drag operation to the value of the dropEffect attribute of the\n // DragEvent object's dataTransfer object as it stood after the event dispatch finished.\n\n this._dragDataStore._mode = DragDataStoreMode.READONLY;\n this._dataTransfer.dropEffect = this._currentDragOperation;\n if (dispatchDragEvent(\"drop\", this._currentDropTarget, this._lastTouchEvent, this._dragDataStore, this._dataTransfer) ===\n true) {\n\n this._currentDragOperation = this._dataTransfer.dropEffect;\n }\n // Otherwise, the event is not canceled; perform the event's default action, which depends on the exact target as follows:\n else {\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the current target element is a text field (e.g. textarea, or an input element whose type attribute is in the Text state)\n // or an editable element,\n // and the drag data store item list has an item with the drag data item type string \"text/plain\"\n // and the drag data item kind Plain Unicode string\n //if( ElementIsTextDropzone( this.currentDropTarget, this.dragDataStore ) ) {\n // Insert the actual data of the first item in the drag data store item list to have a drag data item type string of\n // \"text/plain\" and a drag data item kind that is Plain Unicode string into the text field or editable element in a manner\n // consistent with platform-specific conventions (e.g. inserting it at the current mouse cursor position, or inserting it at\n // the end of the field).\n //}\n // Otherwise\n //else {\n // Reset the current drag operation to \"none\".\n this._currentDragOperation = DROP_EFFECTS[DROP_EFFECT.NONE];\n //}\n }\n }\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // otherwise, use platform-specific conventions for indicating a drop.\n //else {\n //}\n }\n\n return dragFailed;\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n //if( this.dragend( this.sourceNode ) ) {\n // return;\n //}\n\n // Run the appropriate steps from the following list as the default action of the dragend event:\n\n //if( !dropped ) {\n // return;\n //}\n // dropped is true\n\n //if( this.currentDragOperation !== \"move\" ) {\n // return;\n //}\n //// drag operation is move\n //\n //if( ElementIsTextDropzone( this.currentDropTarget ) === false ) {\n // return;\n //}\n //// element is textfield\n //\n //// and the source of the drag-and-drop operation is a selection in the DOM\n //if( this.sourceNode.nodeType === 1 ) {\n // // The user agent should delete the range representing the dragged selection from the DOM.\n //}\n //// and the source of the drag-and-drop operation is a selection in a text field\n //else if( this.sourceNode.nodeType === 3 ) {\n // // The user agent should delete the dragged selection from the relevant text field.\n //}\n //// Otherwise, The event has no default action.\n }\n\n // dispatch dragend event and cleanup drag operation\n private _finishDragOperation():void {\n console.log(\"dnd-poly: dragimage snap back transition ended\");\n\n // Fire a DND event named dragend at the source node.\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = this._currentDragOperation;\n dispatchDragEvent(\"dragend\", this._sourceNode, this._lastTouchEvent, this._dragDataStore, this._dataTransfer, false);\n\n // drag operation over and out\n this._dragOperationState = DragOperationState.ENDED;\n this._cleanup();\n }\n\n //\n}\n\n//\n\n//\n\n/**\n * Polyfills https://html.spec.whatwg.org/multipage/interaction.html#drag-data-store-mode\n */\nconst enum DragDataStoreMode {\n _DISCONNECTED, // adding an extra mode here because we need a special state to disconnect the data store from dataTransfer instance\n READONLY,\n READWRITE,\n PROTECTED\n}\n\n/**\n * Polyfills https://html.spec.whatwg.org/multipage/interaction.html#the-drag-data-store\n */\ninterface DragDataStore {\n _mode:DragDataStoreMode;\n _data:{ [type:string]:any };\n _types:Array;\n _effectAllowed:string;\n}\n\n/**\n * Polyfills https://html.spec.whatwg.org/multipage/interaction.html#datatransfer\n * TODO fail with errors when somebody uses it wrong so they know they are doing it wrong?\n */\nclass DataTransfer {\n\n private _dropEffect:string = DROP_EFFECTS[DROP_EFFECT.NONE];\n\n constructor(private _dataStore:DragDataStore,\n private _setDragImageHandler:(image:Element, x:number, y:number) => void) {\n }\n\n //public get files():FileList {\n // return undefined;\n //}\n //\n //public get items():DataTransferItemList {\n // return undefined;\n //}\n\n public get types():ReadonlyArray {\n if (this._dataStore._mode !== DragDataStoreMode._DISCONNECTED) {\n return Object.freeze(this._dataStore._types);\n }\n }\n\n public setData(type:string, data:string):void {\n if (this._dataStore._mode === DragDataStoreMode.READWRITE) {\n\n if (type.indexOf(\" \") > -1) {\n throw new Error(\"illegal arg: type contains space\");\n }\n\n this._dataStore._data[type] = data;\n\n if (this._dataStore._types.indexOf(type) === -1) {\n this._dataStore._types.push(type);\n }\n }\n }\n\n public getData(type:string):string {\n if (this._dataStore._mode === DragDataStoreMode.READONLY\n || this._dataStore._mode === DragDataStoreMode.READWRITE) {\n return this._dataStore._data[type] || \"\";\n }\n }\n\n public clearData(format?:string):void {\n if (this._dataStore._mode === DragDataStoreMode.READWRITE) {\n // delete data for format\n if (format && this._dataStore._data[format]) {\n delete this._dataStore._data[format];\n var index = this._dataStore._types.indexOf(format);\n if (index > -1) {\n this._dataStore._types.splice(index, 1);\n }\n return;\n }\n // delete all data\n this._dataStore._data = {};\n this._dataStore._types = [];\n }\n }\n\n public setDragImage(image:Element, x:number, y:number):void {\n if (this._dataStore._mode === DragDataStoreMode.READWRITE) {\n this._setDragImageHandler(image, x, y);\n }\n }\n\n public get effectAllowed() {\n return this._dataStore._effectAllowed;\n }\n\n public set effectAllowed(value) {\n if (this._dataStore._mode === DragDataStoreMode.READWRITE\n && ALLOWED_EFFECTS.indexOf(value) > -1) {\n this._dataStore._effectAllowed = value;\n }\n }\n\n public get dropEffect() {\n return this._dropEffect;\n }\n\n public set dropEffect(value) {\n if (this._dataStore._mode !== DragDataStoreMode._DISCONNECTED\n && ALLOWED_EFFECTS.indexOf(value) > -1) {\n this._dropEffect = value;\n }\n }\n}\n\n//\n\n//\n\nexport interface Point {\n x:number;\n y:number;\n}\n\nfunction addDocumentListener(ev:string, handler:EventListener, passive:boolean = true) {\n\n (document as EventTarget).addEventListener(ev, handler, supportsPassive ? {passive: passive} : false);\n}\n\nfunction removeDocumentListener(ev:string, handler:EventListener) {\n document.removeEventListener(ev, handler);\n}\n\nfunction average(array:Array) {\n if (array.length === 0) {\n return 0;\n }\n return array.reduce((function (s, v) {\n return v + s;\n }), 0) / array.length;\n}\n\nfunction isDOMElement(object:any) {\n return object && object.tagName;\n}\n\nfunction isTouchIdentifierContainedInTouchEvent(newTouch:TouchEvent, touchIdentifier:number) {\n for (let i = 0; i < newTouch.changedTouches.length; i++) {\n const touch = newTouch.changedTouches[i];\n if (touch.identifier === touchIdentifier) {\n return true;\n }\n }\n return false;\n}\n\nfunction createDragEventFromTouch(targetElement:Element,\n e:TouchEvent,\n type:string,\n cancelable:boolean,\n window:Window,\n dataTransfer:DataTransfer,\n relatedTarget:Element = null) {\n\n const touch:Touch = e.changedTouches[0];\n\n const dndEvent:DragEvent = new Event(type, {\n bubbles: true,\n cancelable: cancelable\n });\n\n // cast our polyfill\n (dndEvent as any).dataTransfer = dataTransfer;\n (dndEvent as any).relatedTarget = relatedTarget;\n\n // set the coordinates\n (dndEvent as any).screenX = touch.screenX;\n (dndEvent as any).screenY = touch.screenY;\n (dndEvent as any).clientX = touch.clientX;\n (dndEvent as any).clientY = touch.clientY;\n (dndEvent as any).pageX = touch.pageX;\n (dndEvent as any).pageY = touch.pageY;\n\n const targetRect = targetElement.getBoundingClientRect();\n (dndEvent as any).offsetX = dndEvent.clientX - targetRect.left;\n (dndEvent as any).offsetY = dndEvent.clientY - targetRect.top;\n\n return dndEvent;\n}\n\n/**\n * Calc center of polygon spanned by multiple touches in page (full page size, with hidden scrollable area) coordinates\n * or in viewport (screen coordinates) coordinates.\n */\nfunction updateCentroidCoordinatesOfTouchesIn(coordinateProp:string, event:TouchEvent, outPoint:Point):void {\n const pageXs:Array = [], pageYs:Array = [];\n for (let i = 0; i < event.touches.length; i++) {\n const touch = event.touches[i];\n pageXs.push(touch[coordinateProp + \"X\"]);\n pageYs.push(touch[coordinateProp + \"Y\"]);\n }\n outPoint.x = average(pageXs);\n outPoint.y = average(pageYs);\n}\n\nfunction prepareNodeCopyAsDragImage(srcNode:HTMLElement, dstNode:HTMLElement) {\n // Is this node an element?\n if (srcNode.nodeType === 1) {\n\n // Clone the style\n const cs = getComputedStyle(srcNode);\n for (let i = 0; i < cs.length; i++) {\n const csName = cs[i];\n dstNode.style.setProperty(csName, cs.getPropertyValue(csName), cs.getPropertyPriority(csName));\n }\n\n // no interaction with the drag image, pls! this is also important to make the drag image transparent for hit-testing\n // hit testing is done in the drag and drop iteration to find the element the user currently is hovering over while dragging.\n // if pointer-events is not none or a browser does behave in an unexpected way than the hit test transparency on the drag image\n // will break\n dstNode.style.pointerEvents = \"none\";\n\n // Remove any potential conflict attributes\n dstNode.removeAttribute(\"id\");\n dstNode.removeAttribute(\"class\");\n dstNode.removeAttribute(\"draggable\");\n }\n\n // Do the same for the children\n if (srcNode.hasChildNodes()) {\n for (let i = 0; i < srcNode.childNodes.length; i++) {\n prepareNodeCopyAsDragImage(srcNode.childNodes[i], dstNode.childNodes[i]);\n }\n }\n}\n\nfunction createDragImage(sourceNode:HTMLElement):HTMLElement {\n\n const dragImage = sourceNode.cloneNode(true);\n\n // this removes any id's and stuff that could interfere with drag and drop\n prepareNodeCopyAsDragImage(sourceNode, dragImage);\n\n // set layout styles for freely moving it around\n dragImage.style.position = \"absolute\";\n dragImage.style.left = \"0px\";\n dragImage.style.top = \"0px\";\n // on top of all\n dragImage.style.zIndex = \"999999\";\n\n // add polyfill class for default styling\n dragImage.classList.add(CLASS_DRAG_IMAGE);\n dragImage.classList.add(CLASS_DRAG_OPERATION_ICON);\n\n return dragImage;\n}\n\nfunction extractTransformStyles(sourceNode:HTMLElement):string[] {\n\n return TRANSFORM_CSS_VENDOR_PREFIXES.map(function (prefix) {\n\n let transform = sourceNode.style[prefix + \"transform\"];\n\n if (!transform || transform === \"none\") {\n return \"\";\n }\n\n // TODO what about translateX(x), translateY(x), translateZ(z), translate3d(x,y,z), matrix(*,*,*,*,x,y) ?\n\n // removes translate(x,y)\n return transform.replace(/translate\\(\\D*\\d+[^,]*,\\D*\\d+[^,]*\\)\\s*/g, \"\");\n });\n}\n\nfunction translateDragImage(dragImage:HTMLElement, pnt:Point, originalTransforms:string[], offset?:Point, centerOnCoordinates = true):void {\n\n let x = pnt.x, y = pnt.y;\n\n if (offset) {\n x += offset.x;\n y += offset.y;\n }\n\n if (centerOnCoordinates) {\n x -= (parseInt(dragImage.offsetWidth, 10) / 2);\n y -= (parseInt(dragImage.offsetHeight, 10) / 2);\n }\n\n // using translate3d for best performance\n const translate = \"translate3d(\" + x + \"px,\" + y + \"px, 0)\";\n\n for (let i = 0; i < TRANSFORM_CSS_VENDOR_PREFIXES.length; i++) {\n const transformProp = TRANSFORM_CSS_VENDOR_PREFIXES[i] + \"transform\";\n dragImage.style[transformProp] = translate + \" \" + originalTransforms[i];\n }\n}\n\n/**\n * calculates the coordinates of the drag source and transitions the drag image to those coordinates.\n * the drag operation is finished after the transition has ended.\n */\nfunction applyDragImageSnapback(sourceEl:HTMLElement, dragImage:HTMLElement, dragImageTransforms:string[], transitionEndCb:Function):void {\n\n const cs = getComputedStyle(sourceEl);\n\n if (cs.visibility === \"hidden\" || cs.display === \"none\") {\n console.log(\"dnd-poly: source node is not visible. skipping snapback transition.\");\n // shortcut to end the drag operation\n transitionEndCb();\n return;\n }\n // add class containing transition rules\n dragImage.classList.add(CLASS_DRAG_IMAGE_SNAPBACK);\n\n const csDragImage = getComputedStyle(dragImage);\n const durationInS = parseFloat(csDragImage.transitionDuration);\n if (isNaN(durationInS) || durationInS === 0) {\n console.log(\"dnd-poly: no transition used - skipping snapback\");\n transitionEndCb();\n return;\n }\n\n console.log(\"dnd-poly: starting dragimage snap back\");\n\n // calc source node position\n const rect = sourceEl.getBoundingClientRect();\n\n const pnt:Point = {\n x: rect.left,\n y: rect.top\n };\n\n // add scroll offset of document\n pnt.x += (document.body.scrollLeft || document.documentElement.scrollLeft);\n pnt.y += (document.body.scrollTop || document.documentElement.scrollTop);\n\n //TODO this sometimes fails.. find out when exactly and how to detect\n pnt.x -= parseInt(cs.marginLeft, 10);\n pnt.y -= parseInt(cs.marginTop, 10);\n\n const delayInS = parseFloat(csDragImage.transitionDelay);\n const durationInMs = Math.round((durationInS + delayInS) * 1000);\n\n // apply the translate\n translateDragImage(dragImage, pnt, dragImageTransforms, undefined, false);\n\n setTimeout(transitionEndCb, durationInMs);\n}\n\n//\n\n//\n\n/**\n * Implements \"6.\" in the processing steps defined for a dnd event\n * https://html.spec.whatwg.org/multipage/interaction.html#dragevent\n */\nfunction determineDropEffect(effectAllowed:string, sourceNode:Element) {\n\n // uninitialized\n if (!effectAllowed) {\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n //if( sourceNode.nodeType === 1 ) {\n //\n //return \"move\";\n //}\n\n // link\n if (sourceNode.nodeType === 3 && (sourceNode).tagName === \"A\") {\n return DROP_EFFECTS[DROP_EFFECT.LINK];\n }\n\n // copy\n return DROP_EFFECTS[DROP_EFFECT.COPY];\n }\n\n // none\n if (effectAllowed === ALLOWED_EFFECTS[EFFECT_ALLOWED.NONE]) {\n return DROP_EFFECTS[DROP_EFFECT.NONE];\n }\n // copy or all\n if (effectAllowed.indexOf(ALLOWED_EFFECTS[EFFECT_ALLOWED.COPY]) === 0 || effectAllowed === ALLOWED_EFFECTS[EFFECT_ALLOWED.ALL]) {\n return DROP_EFFECTS[DROP_EFFECT.COPY];\n }\n // link\n if (effectAllowed.indexOf(ALLOWED_EFFECTS[EFFECT_ALLOWED.LINK]) === 0) {\n return DROP_EFFECTS[DROP_EFFECT.LINK];\n }\n // move\n if (effectAllowed === ALLOWED_EFFECTS[EFFECT_ALLOWED.MOVE]) {\n return DROP_EFFECTS[DROP_EFFECT.MOVE];\n }\n\n // copy\n return DROP_EFFECTS[DROP_EFFECT.COPY];\n}\n\n/**\n * Reference https://html.spec.whatwg.org/multipage/interaction.html#dndevents\n */\nfunction dispatchDragEvent(dragEvent:string,\n targetElement:Element,\n touchEvent:TouchEvent,\n dataStore:DragDataStore,\n dataTransfer:DataTransfer,\n cancelable = true,\n relatedTarget:Element = null):boolean {\n\n console.log(\"dnd-poly: dispatching \" + dragEvent);\n\n if (DEBUG) {\n var debug_class = CLASS_PREFIX + \"debug\",\n debug_class_event_target = CLASS_PREFIX + \"event-target\",\n debug_class_event_related_target = CLASS_PREFIX + \"event-related-target\";\n targetElement.classList.add(debug_class);\n targetElement.classList.add(debug_class_event_target);\n if (relatedTarget) {\n relatedTarget.classList.add(debug_class);\n relatedTarget.classList.add(debug_class_event_related_target);\n }\n }\n\n const leaveEvt = createDragEventFromTouch(targetElement, touchEvent, dragEvent, cancelable, document.defaultView, dataTransfer, relatedTarget);\n const cancelled = !targetElement.dispatchEvent(leaveEvt);\n\n dataStore._mode = DragDataStoreMode._DISCONNECTED;\n\n if (DEBUG) {\n targetElement.classList.remove(debug_class_event_target);\n if (relatedTarget) {\n relatedTarget.classList.remove(debug_class_event_related_target);\n }\n }\n\n return cancelled;\n}\n\n/**\n * according to https://html.spec.whatwg.org/multipage/interaction.html#drag-and-drop-processing-model\n */\nfunction determineDragOperation(effectAllowed:string, dropEffect:string):string {\n\n // unitialized or all\n if (!effectAllowed || effectAllowed === ALLOWED_EFFECTS[7]) {\n return dropEffect;\n }\n\n if (dropEffect === DROP_EFFECTS[DROP_EFFECT.COPY]) {\n if (effectAllowed.indexOf(DROP_EFFECTS[DROP_EFFECT.COPY]) === 0) {\n return DROP_EFFECTS[DROP_EFFECT.COPY];\n }\n }\n else if (dropEffect === DROP_EFFECTS[DROP_EFFECT.LINK]) {\n if (effectAllowed.indexOf(DROP_EFFECTS[DROP_EFFECT.LINK]) === 0 || effectAllowed.indexOf(\"Link\") > -1) {\n return DROP_EFFECTS[DROP_EFFECT.LINK];\n }\n }\n else if (dropEffect === DROP_EFFECTS[DROP_EFFECT.MOVE]) {\n if (effectAllowed.indexOf(DROP_EFFECTS[DROP_EFFECT.MOVE]) === 0 || effectAllowed.indexOf(\"Move\") > -1) {\n return DROP_EFFECTS[DROP_EFFECT.MOVE];\n }\n }\n\n return DROP_EFFECTS[DROP_EFFECT.NONE];\n}\n\nfunction onDelayTouchstart(evt: TouchEvent) {\n const el = evt.target;\n\n const heldItem = () => {\n end.off();\n cancel.off();\n scroll.off();\n onTouchstart(evt);\n };\n\n const onReleasedItem = () => {\n end.off();\n cancel.off();\n scroll.off();\n clearTimeout(timer);\n };\n\n const timer = setTimeout(heldItem, config.holdToDrag);\n\n const end = onEvt(el, 'touchend', onReleasedItem, this);\n const cancel = onEvt(el, 'touchcancel', onReleasedItem, this);\n const scroll = onEvt(window, 'scroll', onReleasedItem, this);\n}\n\nfunction onEvt(el: EventTarget, event: string, handler: () => any, context: any) {\n if (context) {\n handler = handler.bind(context);\n }\n\n el.addEventListener(event, handler);\n\n return {\n off() {\n return el.removeEventListener(event, handler);\n }\n };\n}\n\n//\n\n//\n\n/**\n * // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n */\n//public static ElementIsTextDropzone( element:HTMLElement, dragDataStore?:DragDataStore ) {\n//\n// if( dragDataStore && !dragDataStore.data[ \"text/plain\" ] ) {\n// return false;\n// }\n//\n// if( element.isContentEditable ) {\n// return true;\n// }\n//\n// if( element.tagName === \"TEXTAREA\" ) {\n// return true;\n// }\n//\n// if( element.tagName === \"INPUT\" ) {\n// if( element.getAttribute( \"type\" ) === \"text\" ) {\n// return true;\n// }\n// }\n//\n// return false;\n//}\n\n/**\n * NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n *\n * Helper method for recursively go from a nested element up the ancestor chain\n * to see if any element has a dropzone.\n */\n//private static FindDropzoneElement( element:HTMLElement ):HTMLElement {\n//\n// if( !element || !element.hasAttribute || typeof element.hasAttribute !== \"function\" ) {\n// return null;\n// }\n//\n// if( element.hasAttribute( \"dropzone\" ) ) {\n// return element;\n// }\n//\n// if( element === window.document.body ) {\n// return null;\n// }\n//\n// return DragOperationController.FindDropzoneElement( element.parentElement );\n//}\n\n/**\n * NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n *\n * Polyfills https://html.spec.whatwg.org/multipage/interaction.html#the-dropzone-attribute\n * by implementing the dropzone processing steps.\n */\n//private static GetOperationForMatchingDropzone( element:HTMLElement, dragDataStore:DragDataStore ):string {\n\n// If the current target element is an element with a dropzone attribute that matches the drag data store and specifies an operation\n// Set the current drag operation to the operation specified by the dropzone attribute of the current target element.\n// If the current target element is an element with a dropzone attribute that matches the drag data store and does not specify an operation\n// Set the current drag operation to \"copy\".\n// Otherwise\n// Reset the current drag operation to \"none\".\n//var value = element.getAttribute( \"dropzone\" );\n//if( !value ) {\n//\n// return \"none\";\n//}\n//\n//var matched = false;\n//var operation;\n//var keywords = value.split( \" \" );\n//\n//for( var i:number = 0; i < keywords.length; i++ ) {\n// var keyword = keywords[ i ];\n//\n// if( keyword === \"copy\" || keyword === \"move\" || keyword === \"link\" ) {\n// if( !operation ) {\n// operation = keyword;\n// }\n// continue;\n// }\n//\n// if( keyword.length < 3 || keyword[ 1 ] !== \":\" ) {\n// continue;\n// }\n//\n// var splitKeyword = keyword.split( \":\" );\n// var kind = splitKeyword[ 0 ].toLowerCase();\n// var type = splitKeyword[ 1 ].toLowerCase();\n//\n// if( dragDataStore.types.indexOf( type ) > -1 ) {\n// matched = true;\n// }\n//}\n//\n//if( !matched ) {\n// return \"none\";\n//}\n//\n//if( !operation ) {\n// return \"copy\";\n//}\n//\n//return operation;\n//}\n\n//\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/release/index.min.js b/release/index.min.js index 7c0a35e..67d3fa2 100644 --- a/release/index.min.js +++ b/release/index.min.js @@ -1,3 +1,3 @@ -/*! mobile-drag-drop 2.0.0 | Copyright (c) 2017 Tim Ruffles | MIT License */ -!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?b(exports):"function"==typeof define&&define.amd?define(["exports"],b):b(a.MobileDragDrop=a.MobileDragDrop||{})}(this,function(a){"use strict";function b(){var a={dragEvents:"ondragstart"in document.documentElement,draggable:"draggable"in document.documentElement,touchEvents:"ontouchstart"in document.documentElement,userAgentSupportingNativeDnD:void 0},b=!!window.chrome||/chrome/i.test(navigator.userAgent);return a.userAgentSupportingNativeDnD=!(/iPad|iPhone|iPod|Android/.test(navigator.userAgent)||b&&a.touchEvents),y&&Object.keys(a).forEach(function(a){}),a}function c(){var a=!1;try{var b=Object.defineProperty({},"passive",{get:function(){a=!0}});window.addEventListener("test",null,b)}catch(a){}return a}function d(a){if(a&&Object.keys(a).forEach(function(b){z[b]=a[b]}),!z.forceApply){var d=b();if(d.userAgentSupportingNativeDnD&&d.draggable&&d.dragEvents)return!1}return w=c(),h("touchstart",e,!1),!0}function e(a){if(!x){var b=f(a);if(b)try{x=new H(a,z,b,g)}catch(b){throw g(z,a,3),b}}}function f(a){var b=a.target;do if(b.draggable!==!1&&b.getAttribute&&"true"===b.getAttribute("draggable"))return b;while((b=b.parentNode)&&b!==document.body)}function g(a,b,c){if(0===c&&a.defaultActionOverride)try{a.defaultActionOverride(b),b.defaultPrevented}catch(a){}x=null}function h(a,b,c){void 0===c&&(c=!0),document.addEventListener(a,b,!!w&&{passive:c})}function i(a,b){document.removeEventListener(a,b)}function j(a){return 0===a.length?0:a.reduce(function(a,b){return b+a},0)/a.length}function k(a){return a&&a.tagName}function l(a,b){for(var c=0;c-1)return B[3]}else if(b===B[2]&&(0===a.indexOf(B[2])||a.indexOf("Move")>-1))return B[2];return B[0]}var w,x,y=!1,z={iterationInterval:150},A=["none","copy","copyLink","copyMove","link","linkMove","move","all"],B=["none","copy","move","link"],C=["","-webkit-"],D="dnd-poly-",E=D+"drag-image",F=D+"snapback",G=D+"icon",H=function(){function a(a,b,c,d){this.h=a,this.i=b,this.j=c,this.k=d,this.l=0,this.m=null,this.o=null,this.p=a,this.q=a.changedTouches[0],this.s=this.t.bind(this),this.u=this.v.bind(this),h("touchmove",this.s,!1),h("touchend",this.u,!1),h("touchcancel",this.u,!1)}return a.prototype.A=function(){var a=this;this.l=1,this.B=B[0],this.C={D:{},F:void 0,g:3,G:[]},this.H={x:null,y:null},this.I={x:null,y:null};var b=this.j;if(this.J=new I(this.C,function(c,d,e){b=c,"number"!=typeof d&&"number"!=typeof e||(a.K={x:d||0,y:e||0})}),this.C.g=2,this.J.dropEffect=B[0],u("dragstart",this.j,this.p,this.C,this.J))return this.l=3,this.L(),!1;if(n("page",this.p,this.I),this.M=p(b),this.N=q(this.M),!this.K)if(this.i.dragImageOffset)this.K={x:this.i.dragImageOffset.x,y:this.i.dragImageOffset.y};else if(this.i.dragImageCenterOnTouch){var c=getComputedStyle(b);this.K={x:0-parseInt(c.marginLeft,10),y:0-parseInt(c.marginTop,10)}}else{var d=b.getBoundingClientRect(),c=getComputedStyle(b);this.K={x:d.left-this.q.clientX-parseInt(c.marginLeft,10)+d.width/2,y:d.top-this.q.clientY-parseInt(c.marginTop,10)+d.height/2}}return r(this.M,this.I,this.N,this.K,this.i.dragImageCenterOnTouch),document.body.appendChild(this.M),this.O=setInterval(function(){a.P||(a.P=!0,a.R(),a.P=!1)},this.i.iterationInterval),!0},a.prototype.L=function(){this.O&&(clearInterval(this.O),this.O=null),i("touchmove",this.s),i("touchend",this.u),i("touchcancel",this.u),this.M&&(this.M.parentNode.removeChild(this.M),this.M=null),this.k(this.i,this.p,this.l)},a.prototype.t=function(a){var b=this;if(l(a,this.q.identifier)!==!1){if(this.p=a,0===this.l){var c=void 0;if(this.i.dragStartConditionOverride)try{c=this.i.dragStartConditionOverride(a)}catch(a){c=!1}else c=1===a.touches.length;return c?void(this.A()===!0&&(this.h.preventDefault(),a.preventDefault())):void this.L()}if(a.preventDefault(),n("client",a,this.H),n("page",a,this.I),this.i.dragImageTranslateOverride)try{var d=!1;if(this.i.dragImageTranslateOverride(a,{x:this.H.x,y:this.H.y},this.m,function(a,c){b.M&&(d=!0,b.H.x+=a,b.H.y+=c,b.I.x+=a,b.I.y+=c,r(b.M,b.I,b.N,b.K,b.i.dragImageCenterOnTouch))}),d)return}catch(a){}r(this.M,this.I,this.N,this.K,this.i.dragImageCenterOnTouch)}},a.prototype.v=function(a){if(l(a,this.q.identifier)!==!1){if(this.i.dragImageTranslateOverride)try{this.i.dragImageTranslateOverride(void 0,void 0,void 0,function(){})}catch(a){}if(0===this.l)return void this.L();a.preventDefault(),this.l="touchcancel"===a.type?3:2}},a.prototype.R=function(){var a=this;if(y)var b=D+"debug",c=D+"immediate-user-selection",d=D+"current-drop-target";var e=this.B;this.C.g=3,this.J.dropEffect=B[0];var f=u("drag",this.j,this.p,this.C,this.J);if(f&&(this.B=B[0]),f||2===this.l||3===this.l){var g=this.S(this.l);return g?void s(this.j,this.M,this.N,function(){a.T()}):void this.T()}var h=document.elementFromPoint(this.H.x,this.H.y),i=this.o;h!==this.m&&h!==this.o&&(y&&(this.m&&this.m.classList.remove(c),h&&(h.classList.add(b),h.classList.add(c))),this.m=h,null!==this.o&&(this.C.g=3,this.J.dropEffect=B[0],u("dragexit",this.o,this.p,this.C,this.J,!1)),null===this.m?this.o=this.m:(this.C.g=3,this.J.dropEffect=t(this.C.F,this.j),u("dragenter",this.m,this.p,this.C,this.J)?(this.o=this.m,this.B=v(this.J.effectAllowed,this.J.dropEffect)):this.m!==document.body&&(this.o=document.body))),i!==this.o&&k(i)&&(y&&i.classList.remove(d),this.C.g=3,this.J.dropEffect=B[0],u("dragleave",i,this.p,this.C,this.J,!1,this.o)),k(this.o)&&(y&&(this.o.classList.add(b),this.o.classList.add(d)),this.C.g=3,this.J.dropEffect=t(this.C.F,this.j),u("dragover",this.o,this.p,this.C,this.J)===!1?this.B=B[0]:this.B=v(this.J.effectAllowed,this.J.dropEffect)),e!==this.B&&this.M.classList.remove(D+e);var j=D+this.B;this.M.classList.contains(j)===!1&&this.M.classList.add(j)},a.prototype.S=function(a){if(y){var b=D+"immediate-user-selection",c=D+"current-drop-target";this.o&&this.o.classList.remove(c),this.m&&this.m.classList.remove(b)}var d=this.B===B[0]||null===this.o||3===a;return d?k(this.o)&&(this.C.g=3,this.J.dropEffect=B[0],u("dragleave",this.o,this.p,this.C,this.J,!1)):k(this.o)&&(this.C.g=1,this.J.dropEffect=this.B,u("drop",this.o,this.p,this.C,this.J)===!0?this.B=this.J.dropEffect:this.B=B[0]),d},a.prototype.T=function(){this.C.g=3,this.J.dropEffect=this.B,u("dragend",this.j,this.p,this.C,this.J,!1),this.l=2,this.L()},a}(),I=function(){function a(a,b){this.U=a,this.V=b,this.W=B[0]}return Object.defineProperty(a.prototype,"types",{get:function(){if(0!==this.U.g)return Object.freeze(this.U.G)},enumerable:!0,configurable:!0}),a.prototype.setData=function(a,b){if(2===this.U.g){if(a.indexOf(" ")>-1)throw new Error("illegal arg: type contains space");this.U.D[a]=b,this.U.G.indexOf(a)===-1&&this.U.G.push(a)}},a.prototype.getData=function(a){if(1===this.U.g||2===this.U.g)return this.U.D[a]||""},a.prototype.clearData=function(a){if(2===this.U.g){if(a&&this.U.D[a]){delete this.U.D[a];var b=this.U.G.indexOf(a);return void(b>-1&&this.U.G.splice(b,1))}this.U.D={},this.U.G=[]}},a.prototype.setDragImage=function(a,b,c){2===this.U.g&&this.V(a,b,c)},Object.defineProperty(a.prototype,"effectAllowed",{get:function(){return this.U.F},set:function(a){2===this.U.g&&A.indexOf(a)>-1&&(this.U.F=a)},enumerable:!0,configurable:!0}),Object.defineProperty(a.prototype,"dropEffect",{get:function(){return this.W},set:function(a){0!==this.U.g&&A.indexOf(a)>-1&&(this.W=a)},enumerable:!0,configurable:!0}),a}();a.polyfill=d,Object.defineProperty(a,"__esModule",{value:!0})}); +/*! mobile-drag-drop 2.1.0 | Copyright (c) 2017 Tim Ruffles | MIT License */ +!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?b(exports):"function"==typeof define&&define.amd?define(["exports"],b):b(a.MobileDragDrop=a.MobileDragDrop||{})}(this,function(a){"use strict";function b(){var a={dragEvents:"ondragstart"in document.documentElement,draggable:"draggable"in document.documentElement,touchEvents:"ontouchstart"in document.documentElement,userAgentSupportingNativeDnD:void 0},b=!!window.chrome||/chrome/i.test(navigator.userAgent);return a.userAgentSupportingNativeDnD=!(/iPad|iPhone|iPod|Android/.test(navigator.userAgent)||b&&a.touchEvents),A&&Object.keys(a).forEach(function(a){}),a}function c(){var a=!1;try{var b=Object.defineProperty({},"passive",{get:function(){a=!0}});window.addEventListener("test",null,b)}catch(a){}return a}function d(a){if(a&&Object.keys(a).forEach(function(b){B[b]=a[b]}),!B.forceApply){var d=b();if(d.userAgentSupportingNativeDnD&&d.draggable&&d.dragEvents)return!1}return y=c(),B.holdToDrag?h("touchstart",w,!1):h("touchstart",e,!1),!0}function e(a){if(!z){var b=f(a);if(b)try{z=new J(a,B,b,g)}catch(b){throw g(B,a,3),b}}}function f(a){var b=a.target;do if(b.draggable!==!1&&b.getAttribute&&"true"===b.getAttribute("draggable"))return b;while((b=b.parentNode)&&b!==document.body)}function g(a,b,c){if(0===c&&a.defaultActionOverride)try{a.defaultActionOverride(b),b.defaultPrevented}catch(a){}z=null}function h(a,b,c){void 0===c&&(c=!0),document.addEventListener(a,b,!!y&&{passive:c})}function i(a,b){document.removeEventListener(a,b)}function j(a){return 0===a.length?0:a.reduce(function(a,b){return b+a},0)/a.length}function k(a){return a&&a.tagName}function l(a,b){for(var c=0;c-1)return D[3]}else if(b===D[2]&&(0===a.indexOf(D[2])||a.indexOf("Move")>-1))return D[2];return D[0]}function w(a){var b=a.target,c=function(){g.off(),h.off(),i.off(),e(a)},d=function(){g.off(),h.off(),i.off(),clearTimeout(f)},f=setTimeout(c,B.holdToDrag),g=x(b,"touchend",d,this),h=x(b,"touchcancel",d,this),i=x(window,"scroll",d,this)}function x(a,b,c,d){return d&&(c=c.bind(d)),a.addEventListener(b,c),{off:function(){return a.removeEventListener(b,c)}}}var y,z,A=!1,B={iterationInterval:150},C=["none","copy","copyLink","copyMove","link","linkMove","move","all"],D=["none","copy","move","link"],E=["","-webkit-"],F="dnd-poly-",G=F+"drag-image",H=F+"snapback",I=F+"icon",J=function(){function a(a,b,c,d){this.h=a,this.i=b,this.j=c,this.k=d,this.l=0,this.m=null,this.o=null,this.p=a,this.q=a.changedTouches[0],this.s=this.t.bind(this),this.u=this.v.bind(this),h("touchmove",this.s,!1),h("touchend",this.u,!1),h("touchcancel",this.u,!1)}return a.prototype.A=function(){var a=this;this.l=1,this.B=D[0],this.C={D:{},F:void 0,g:3,G:[]},this.H={x:null,y:null},this.I={x:null,y:null};var b=this.j;if(this.J=new K(this.C,function(c,d,e){b=c,"number"!=typeof d&&"number"!=typeof e||(a.K={x:d||0,y:e||0})}),this.C.g=2,this.J.dropEffect=D[0],u("dragstart",this.j,this.p,this.C,this.J))return this.l=3,this.L(),!1;if(n("page",this.p,this.I),this.M=p(b),this.N=q(this.M),!this.K)if(this.i.dragImageOffset)this.K={x:this.i.dragImageOffset.x,y:this.i.dragImageOffset.y};else if(this.i.dragImageCenterOnTouch){var c=getComputedStyle(b);this.K={x:0-parseInt(c.marginLeft,10),y:0-parseInt(c.marginTop,10)}}else{var d=b.getBoundingClientRect(),c=getComputedStyle(b);this.K={x:d.left-this.q.clientX-parseInt(c.marginLeft,10)+d.width/2,y:d.top-this.q.clientY-parseInt(c.marginTop,10)+d.height/2}}return r(this.M,this.I,this.N,this.K,this.i.dragImageCenterOnTouch),document.body.appendChild(this.M),this.O=setInterval(function(){a.P||(a.P=!0,a.R(),a.P=!1)},this.i.iterationInterval),!0},a.prototype.L=function(){this.O&&(clearInterval(this.O),this.O=null),i("touchmove",this.s),i("touchend",this.u),i("touchcancel",this.u),this.M&&(this.M.parentNode.removeChild(this.M),this.M=null),this.k(this.i,this.p,this.l)},a.prototype.t=function(a){var b=this;if(l(a,this.q.identifier)!==!1){if(this.p=a,0===this.l){var c=void 0;if(this.i.dragStartConditionOverride)try{c=this.i.dragStartConditionOverride(a)}catch(a){c=!1}else c=1===a.touches.length;return c?void(this.A()===!0&&(this.h.preventDefault(),a.preventDefault())):void this.L()}if(a.preventDefault(),n("client",a,this.H),n("page",a,this.I),this.i.dragImageTranslateOverride)try{var d=!1;if(this.i.dragImageTranslateOverride(a,{x:this.H.x,y:this.H.y},this.m,function(a,c){b.M&&(d=!0,b.H.x+=a,b.H.y+=c,b.I.x+=a,b.I.y+=c,r(b.M,b.I,b.N,b.K,b.i.dragImageCenterOnTouch))}),d)return}catch(a){}r(this.M,this.I,this.N,this.K,this.i.dragImageCenterOnTouch)}},a.prototype.v=function(a){if(l(a,this.q.identifier)!==!1){if(this.i.dragImageTranslateOverride)try{this.i.dragImageTranslateOverride(void 0,void 0,void 0,function(){})}catch(a){}if(0===this.l)return void this.L();a.preventDefault(),this.l="touchcancel"===a.type?3:2}},a.prototype.R=function(){var a=this;if(A)var b=F+"debug",c=F+"immediate-user-selection",d=F+"current-drop-target";var e=this.B;this.C.g=3,this.J.dropEffect=D[0];var f=u("drag",this.j,this.p,this.C,this.J);if(f&&(this.B=D[0]),f||2===this.l||3===this.l){var g=this.S(this.l);return g?void s(this.j,this.M,this.N,function(){a.T()}):void this.T()}var h=document.elementFromPoint(this.H.x,this.H.y),i=this.o;h!==this.m&&h!==this.o&&(A&&(this.m&&this.m.classList.remove(c),h&&(h.classList.add(b),h.classList.add(c))),this.m=h,null!==this.o&&(this.C.g=3,this.J.dropEffect=D[0],u("dragexit",this.o,this.p,this.C,this.J,!1)),null===this.m?this.o=this.m:(this.C.g=3,this.J.dropEffect=t(this.C.F,this.j),u("dragenter",this.m,this.p,this.C,this.J)?(this.o=this.m,this.B=v(this.J.effectAllowed,this.J.dropEffect)):this.m!==document.body&&(this.o=document.body))),i!==this.o&&k(i)&&(A&&i.classList.remove(d),this.C.g=3,this.J.dropEffect=D[0],u("dragleave",i,this.p,this.C,this.J,!1,this.o)),k(this.o)&&(A&&(this.o.classList.add(b),this.o.classList.add(d)),this.C.g=3,this.J.dropEffect=t(this.C.F,this.j),u("dragover",this.o,this.p,this.C,this.J)===!1?this.B=D[0]:this.B=v(this.J.effectAllowed,this.J.dropEffect)),e!==this.B&&this.M.classList.remove(F+e);var j=F+this.B;this.M.classList.contains(j)===!1&&this.M.classList.add(j)},a.prototype.S=function(a){if(A){var b=F+"immediate-user-selection",c=F+"current-drop-target";this.o&&this.o.classList.remove(c),this.m&&this.m.classList.remove(b)}var d=this.B===D[0]||null===this.o||3===a;return d?k(this.o)&&(this.C.g=3,this.J.dropEffect=D[0],u("dragleave",this.o,this.p,this.C,this.J,!1)):k(this.o)&&(this.C.g=1,this.J.dropEffect=this.B,u("drop",this.o,this.p,this.C,this.J)===!0?this.B=this.J.dropEffect:this.B=D[0]),d},a.prototype.T=function(){this.C.g=3,this.J.dropEffect=this.B,u("dragend",this.j,this.p,this.C,this.J,!1),this.l=2,this.L()},a}(),K=function(){function a(a,b){this.U=a,this.V=b,this.W=D[0]}return Object.defineProperty(a.prototype,"types",{get:function(){if(0!==this.U.g)return Object.freeze(this.U.G)},enumerable:!0,configurable:!0}),a.prototype.setData=function(a,b){if(2===this.U.g){if(a.indexOf(" ")>-1)throw new Error("illegal arg: type contains space");this.U.D[a]=b,this.U.G.indexOf(a)===-1&&this.U.G.push(a)}},a.prototype.getData=function(a){if(1===this.U.g||2===this.U.g)return this.U.D[a]||""},a.prototype.clearData=function(a){if(2===this.U.g){if(a&&this.U.D[a]){delete this.U.D[a];var b=this.U.G.indexOf(a);return void(b>-1&&this.U.G.splice(b,1))}this.U.D={},this.U.G=[]}},a.prototype.setDragImage=function(a,b,c){2===this.U.g&&this.V(a,b,c)},Object.defineProperty(a.prototype,"effectAllowed",{get:function(){return this.U.F},set:function(a){2===this.U.g&&C.indexOf(a)>-1&&(this.U.F=a)},enumerable:!0,configurable:!0}),Object.defineProperty(a.prototype,"dropEffect",{get:function(){return this.W},set:function(a){0!==this.U.g&&C.indexOf(a)>-1&&(this.W=a)},enumerable:!0,configurable:!0}),a}();a.polyfill=d,Object.defineProperty(a,"__esModule",{value:!0})}); //# sourceMappingURL=index.min.js.map \ No newline at end of file diff --git a/release/index.min.js.map b/release/index.min.js.map index 6d7010d..f0f852c 100644 --- a/release/index.min.js.map +++ b/release/index.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["/Users/stefansteinhart/Development/Web/ios-html5-drag-drop-shim/src/index.ts"],"names":["detectFeatures","features","dragEvents","document","documentElement","draggable","touchEvents","userAgentSupportingNativeDnD","undefined","isBlinkEngine","window","test","navigator","userAgent","DEBUG","Object","keys","forEach","key","supportsPassiveEventListener","supportsPassiveEventListeners","opts","defineProperty","get","addEventListener","e","polyfill","override","config","forceApply","detectedFeatures","supportsPassive","addDocumentListener","onTouchstart","activeDragOperation","dragTarget","tryFindDraggableTarget","DragOperationController","dragOperationEnded","err","event","el","target","getAttribute","parentNode","body","_config","state","defaultActionOverride","defaultPrevented","ev","handler","passive","removeDocumentListener","removeEventListener","average","array","length","reduce","s","v","isDOMElement","object","tagName","isTouchIdentifierContainedInTouchEvent","newTouch","touchIdentifier","i","changedTouches","touch","identifier","createDragEventFromTouch","targetElement","type","cancelable","dataTransfer","relatedTarget","dndEvent","Event","bubbles","screenX","screenY","clientX","clientY","pageX","pageY","targetRect","getBoundingClientRect","offsetX","left","offsetY","top","updateCentroidCoordinatesOfTouchesIn","coordinateProp","outPoint","pageXs","pageYs","touches","push","x","y","prepareNodeCopyAsDragImage","srcNode","dstNode","nodeType","cs","getComputedStyle","csName","style","setProperty","getPropertyValue","getPropertyPriority","pointerEvents","removeAttribute","hasChildNodes","childNodes","createDragImage","sourceNode","dragImage","cloneNode","position","zIndex","classList","add","CLASS_DRAG_IMAGE","CLASS_DRAG_OPERATION_ICON","extractTransformStyles","TRANSFORM_CSS_VENDOR_PREFIXES","map","prefix","transform","replace","translateDragImage","pnt","originalTransforms","offset","centerOnCoordinates","parseInt","offsetWidth","offsetHeight","translate","transformProp","applyDragImageSnapback","sourceEl","dragImageTransforms","transitionEndCb","visibility","display","CLASS_DRAG_IMAGE_SNAPBACK","csDragImage","durationInS","parseFloat","transitionDuration","isNaN","rect","scrollLeft","scrollTop","marginLeft","marginTop","delayInS","transitionDelay","durationInMs","Math","round","setTimeout","determineDropEffect","effectAllowed","ALLOWED_EFFECTS","DROP_EFFECTS","indexOf","dispatchDragEvent","dragEvent","touchEvent","dataStore","debug_class","CLASS_PREFIX","debug_class_event_target","debug_class_event_related_target","leaveEvt","defaultView","cancelled","dispatchEvent","_mode","remove","determineDragOperation","dropEffect","iterationInterval","_initialEvent","_sourceNode","_dragOperationEndedCb","this","_dragOperationState","_immediateUserSelection","_currentDropTarget","_lastTouchEvent","_initialTouch","_touchMoveHandler","_onTouchMove","bind","_touchEndOrCancelHandler","_onTouchEndOrCancel","prototype","_setup","_this","_currentDragOperation","_dragDataStore","D","F","g","G","_currentHotspotCoordinates","_dragImagePageCoordinates","dragImageSrc","_dataTransfer","DataTransfer","element","_dragImageOffset","_cleanup","_dragImage","_dragImageTransforms","dragImageOffset","dragImageCenterOnTouch","width","height","appendChild","_iterationIntervalId","setInterval","_iterationLock","_dragAndDropProcessModelIteration","clearInterval","removeChild","startDrag","dragStartConditionOverride","preventDefault","dragImageTranslateOverride","handledDragImageTranslate_1","debug_class_user_selection","debug_class_drop_target","previousDragOperation","dragCancelled","dragFailed","_dragOperationEnded","_finishDragOperation","newUserSelection","elementFromPoint","previousTargetElement","_effectAllowed","currentDragOperationClass","contains","_dataStore","_setDragImageHandler","_dropEffect","freeze","_types","setData","data","Error","_data","getData","clearData","format","index","splice","setDragImage","image","value"],"mappings":";kNAYA,SAAAA,KAEI,GAAIC,IACAC,WAAa,eAAiBC,UAASC,gBACvCC,UAAY,aAAeF,UAASC,gBACpCE,YAAc,gBAAkBH,UAASC,gBACzCG,6BAA8BC,QAG5BC,IAAyBC,OAAc,QAAK,UAAUC,KAAKC,UAAUC,UAgB3E,OAdAZ,GAASM,+BAEJ,2BAA2BI,KAAKC,UAAUC,YAG1CJ,GAAiBR,EAASK,aAG3BQ,GACAC,OAAOC,KAAKf,GAAUgB,QAAQ,SAAUC,MAKrCjB,EAKX,QAAAkB,KAEI,GAAIC,IAAgC,CAGpC,KACI,GAAIC,GAAON,OAAOO,kBAAmB,WACjCC,IAAK,WACDH,GAAgC,IAGxCV,QAAOc,iBAAiB,OAAQ,KAAMH,GAG1C,MAAOI,IAGP,MAAOL,GA4CX,QAAAM,GAAyBC,GAUrB,GARIA,GAEAZ,OAAOC,KAAKW,GAAUV,QAAQ,SAAUC,GACpCU,EAAOV,GAAOS,EAAST,MAK1BU,EAAOC,WAAY,CAGpB,GAAMC,GAAmB9B,GAGzB,IAAI8B,EAAiBvB,8BACduB,EAAiBzB,WACjByB,EAAiB5B,WAEpB,OAAO,EAWf,MALA6B,GAAkBZ,IAGlBa,EAAoB,aAAcC,GAAc,IAEzC,EAaX,QAAAA,GAAsBR,GAQlB,IAAIS,EAAJ,CAKA,GAAIC,GAAaC,EAAuBX,EAIxC,IAAKU,EAIL,IACID,EAAsB,GAAIG,GAAwBZ,EAAGG,EAAqBO,EAAYG,GAE1F,MAAOC,GAGH,KAFAD,GAAmBV,EAAQH,EAAC,GAEtBc,IAOd,QAAAH,GAAgCI,GAe5B,GAAIC,GAAkBD,EAAME,MAE5B,GACI,IAAID,EAAGpC,aAAc,GAGjBoC,EAAGE,cAAiD,SAAjCF,EAAGE,aAAa,aACnC,MAAOF,UAELA,EAAkBA,EAAGG,aAAeH,IAAOtC,SAAS0C,MAMlE,QAAAP,GAA4BQ,EAAgBN,EAAkBO,GAG1D,GAAS,IAALA,GAKID,EAAQE,sBAER,IAEIF,EAAQE,sBAAsBR,GAE1BA,EAAMS,iBAMd,MAAOxB,IAQfS,EAAsB,KAq7B1B,QAAAF,GAA6BkB,EAAWC,EAAuBC,GAAA,SAAAA,IAAAA,GAAA,GAE1DjD,SAAyBqB,iBAAiB0B,EAAIC,IAASpB,IAAmBqB,QAASA,IAGxF,QAAAC,GAAgCH,EAAWC,GACvChD,SAASmD,oBAAoBJ,EAAIC,GAGrC,QAAAI,GAAiBC,GACb,MAAqB,KAAjBA,EAAMC,OACC,EAEJD,EAAME,OAAM,SAAYC,EAAGC,GAC9B,MAAOA,GAAID,GACX,GAAKH,EAAMC,OAGnB,QAAAI,GAAsBC,GAClB,MAAOA,IAAUA,EAAOC,QAG5B,QAAAC,GAAgDC,EAAqBC,GACjE,IAAK,GAAIC,GAAI,EAAGA,EAAIF,EAASG,eAAeX,OAAQU,IAAK,CACrD,GAAME,GAAQJ,EAASG,eAAeD,EACtC,IAAIE,EAAMC,aAAeJ,EACrB,OAAO,EAGf,OAAO,EAGX,QAAAK,GAAkCC,EACA/C,EACAgD,EACAC,EACAhE,EACAiE,EACAC,GAAA,SAAAA,IAAAA,EAAA,KAE9B,IAAMP,GAAc5C,EAAE2C,eAAe,GAE/BS,EAAgC,GAAIC,OAAML,GAC5CM,SAAS,EACTL,WAAYA,GAIfG,GAAiBF,aAAoBA,EACrCE,EAAiBD,cAAgBA,EAGjCC,EAAiBG,QAAUX,EAAMW,QACjCH,EAAiBI,QAAUZ,EAAMY,QACjCJ,EAAiBK,QAAUb,EAAMa,QACjCL,EAAiBM,QAAUd,EAAMc,QACjCN,EAAiBO,MAAQf,EAAMe,MAC/BP,EAAiBQ,MAAQhB,EAAMgB,KAEhC,IAAMC,GAAad,EAAce,uBAIjC,OAHCV,GAAiBW,QAAUX,EAASK,QAAUI,EAAWG,KACzDZ,EAAiBa,QAAUb,EAASM,QAAUG,EAAWK,IAEnDd,EAOX,QAAAe,GAA8CC,EAAuBrD,EAAkBsD,GAEnF,IAAK,GADCC,MAA2BC,KACxB7B,EAAI,EAAGA,EAAI3B,EAAMyD,QAAQxC,OAAQU,IAAK,CAC3C,GAAME,GAAQ7B,EAAMyD,QAAQ9B,EAC5B4B,GAAOG,KAAK7B,EAAMwB,EAAiB,MACnCG,EAAOE,KAAK7B,EAAMwB,EAAiB,MAEvCC,EAASK,EAAI5C,EAAQwC,GACrBD,EAASM,EAAI7C,EAAQyC,GAGzB,QAAAK,GAAoCC,EAAqBC,GAErD,GAAyB,IAArBD,EAAQE,SAAgB,CAIxB,IAAK,GADCC,GAAKC,iBAAiBJ,GACnBnC,EAAI,EAAGA,EAAIsC,EAAGhD,OAAQU,IAAK,CAChC,GAAMwC,GAASF,EAAGtC,EAClBoC,GAAQK,MAAMC,YAAYF,EAAQF,EAAGK,iBAAiBH,GAASF,EAAGM,oBAAoBJ,IAO1FJ,EAAQK,MAAMI,cAAgB,OAG9BT,EAAQU,gBAAgB,MACxBV,EAAQU,gBAAgB,SACxBV,EAAQU,gBAAgB,aAI5B,GAAIX,EAAQY,gBACR,IAAK,GAAI/C,GAAI,EAAGA,EAAImC,EAAQa,WAAW1D,OAAQU,IAC3CkC,EAAwCC,EAAQa,WAAWhD,GAAiBoC,EAAQY,WAAWhD,IAK3G,QAAAiD,GAAyBC,GAErB,GAAMC,GAAyBD,EAAWE,WAAU,EAgBpD,OAbAlB,GAA2BgB,EAAYC,GAGvCA,EAAUV,MAAMY,SAAW,WAC3BF,EAAUV,MAAMnB,KAAO,MACvB6B,EAAUV,MAAMjB,IAAM,MAEtB2B,EAAUV,MAAMa,OAAS,SAGzBH,EAAUI,UAAUC,IAAIC,GACxBN,EAAUI,UAAUC,IAAIE,GAEjBP,EAGX,QAAAQ,GAAgCT,GAE5B,MAAOU,GAA8BC,IAAI,SAAUC,GAE/C,GAAIC,GAAYb,EAAWT,MAAMqB,EAAS,YAE1C,OAAKC,IAA2B,SAAdA,EAOXA,EAAUC,QAAQ,2CAA4C,IAN1D,KAUnB,QAAAC,GAA4Bd,EAAuBe,EAAWC,EAA6BC,EAAeC,GAAA,SAAAA,IAAAA,GAAA,EAEtG,IAAIrC,GAAIkC,EAAIlC,EAAGC,EAAIiC,EAAIjC,CAEnBmC,KACApC,GAAKoC,EAAOpC,EACZC,GAAKmC,EAAOnC,GAGZoC,IACArC,GAAMsC,SAAcnB,EAAUoB,YAAa,IAAM,EACjDtC,GAAMqC,SAAcnB,EAAUqB,aAAc,IAAM,EAMtD,KAAK,GAFCC,GAAY,eAAiBzC,EAAI,MAAQC,EAAI,SAE1CjC,EAAI,EAAGA,EAAI4D,EAA8BtE,OAAQU,IAAK,CAC3D,GAAM0E,GAAgBd,EAA8B5D,GAAK,WACzDmD,GAAUV,MAAMiC,GAAiBD,EAAY,IAAMN,EAAmBnE,IAQ9E,QAAA2E,GAAgCC,EAAsBzB,EAAuB0B,EAA8BC,GAEvG,GAAMxC,GAAKC,iBAAiBqC,EAE5B,IAAsB,WAAlBtC,EAAGyC,YAA0C,SAAfzC,EAAG0C,QAIjC,WADAF,IAIJ3B,GAAUI,UAAUC,IAAIyB,EAExB,IAAMC,GAAc3C,iBAAiBY,GAC/BgC,EAAcC,WAAWF,EAAYG,mBAC3C,IAAIC,MAAMH,IAAgC,IAAhBA,EAGtB,WADAL,IAOJ,IAAMS,GAAOX,EAASxD,wBAEhB8C,GACFlC,EAAGuD,EAAKjE,KACRW,EAAGsD,EAAK/D,IAIZ0C,GAAIlC,GAAMhG,SAAS0C,KAAK8G,YAAcxJ,SAASC,gBAAgBuJ,WAC/DtB,EAAIjC,GAAMjG,SAAS0C,KAAK+G,WAAazJ,SAASC,gBAAgBwJ,UAG9DvB,EAAIlC,GAAKsC,SAAShC,EAAGoD,WAAY,IACjCxB,EAAIjC,GAAKqC,SAAShC,EAAGqD,UAAW,GAEhC,IAAMC,GAAWR,WAAWF,EAAYW,iBAClCC,EAAeC,KAAKC,MAAiC,KAA1Bb,EAAcS,GAG/C3B,GAAmBd,EAAWe,EAAKW,EAAqBxI,QAAW,GAEnE4J,WAAWnB,EAAiBgB,GAWhC,QAAAI,GAA6BC,EAAsBjD,GAG/C,MAAKiD,GAkBDA,IAAkBC,EAAe,GAC1BC,EAAY,GAG6C,IAAhEF,EAAcG,QAAQF,EAAe,KAAgCD,IAAkBC,EAAe,GAC/FC,EAAY,GAG6C,IAAhEF,EAAcG,QAAQF,EAAe,IAC9BC,EAAY,GAGnBF,IAAkBC,EAAe,GAC1BC,EAAY,GAIhBA,EAAY,GA1Ba,IAAxBnD,EAAWb,UAAwD,MAAxBa,EAAYtD,QAChDyG,EAAY,GAIhBA,EAAY,GA2B3B,QAAAE,GAA2BC,EACAnG,EACAoG,EACAC,EACAlG,EACAD,EACAE,GAIvB,GALuB,SAAAF,IAAAA,GAAA,GACA,SAAAE,IAAAA,EAAA,MAInB9D,EAAO,CACP,GAAIgK,GAAcC,EAAe,QAC7BC,EAA2BD,EAAe,eAC1CE,EAAmCF,EAAe,sBACtDvG,GAAckD,UAAUC,IAAImD,GAC5BtG,EAAckD,UAAUC,IAAIqD,GACxBpG,IACAA,EAAc8C,UAAUC,IAAImD,GAC5BlG,EAAc8C,UAAUC,IAAIsD,IAIpC,GAAMC,GAAW3G,EAAyBC,EAAeoG,EAAYD,EAAWjG,EAAYvE,SAASgL,YAAaxG,EAAcC,GAC1HwG,GAAa5G,EAAc6G,cAAcH,EAW/C,OATAL,GAAUS,EAAK,EAEXxK,IACA0D,EAAckD,UAAU6D,OAAOP,GAC3BpG,GACAA,EAAc8C,UAAU6D,OAAON,IAIhCG,EAMX,QAAAI,GAAgClB,EAAsBmB,GAGlD,IAAKnB,GAAiBA,IAAkBC,EAAgB,GACpD,MAAOkB,EAGX,IAAIA,IAAejB,EAAY,IAC3B,GAA8D,IAA1DF,EAAcG,QAAQD,EAAY,IAClC,MAAOA,GAAY,OAGtB,IAAIiB,IAAejB,EAAY,IAChC,GAA8D,IAA1DF,EAAcG,QAAQD,EAAY,KAA6BF,EAAcG,QAAQ,SAAU,EAC/F,MAAOD,GAAY,OAGtB,IAAIiB,IAAejB,EAAY,KAC8B,IAA1DF,EAAcG,QAAQD,EAAY,KAA6BF,EAAcG,QAAQ,SAAU,GAC/F,MAAOD,GAAY,EAI3B,OAAOA,GAAY,GAv/CvB,GAuCIzI,GAsGAG,EA7IEpB,GAAQ,EAkGRc,GACF8J,kBAAmB,KA4KjBnB,GAAmB,OAAQ,OAAQ,WAAY,WAAY,OAAQ,WAAY,OAAQ,OAUvFC,GAAgB,OAAQ,OAAQ,OAAQ,QAGxCzC,GAAiC,GAAI,YAErCgD,EAAe,YACfnD,EAAmBmD,EAAe,aAClC3B,EAA4B2B,EAAe,WAC3ClD,EAA4BkD,EAAe,OAQjD1I,EAAA,WA2BI,QAAAA,GAAoBsJ,EACA7I,EACA8I,EACAC,GAHAC,KAAAH,EAAAA,EACAG,KAAAhJ,EAAAA,EACAgJ,KAAAF,EAAAA,EACAE,KAAAD,EAAAA,EA5BZC,KAAAC,EAAmB,EASnBD,KAAAE,EAAsC,KACtCF,KAAAG,EAAiC,KAsBrCH,KAAKI,EAAkBP,EACvBG,KAAKK,EAAgBR,EAAcvH,eAAe,GAGlD0H,KAAKM,EAAoBN,KAAKO,EAAaC,KAAKR,MAChDA,KAAKS,EAA2BT,KAAKU,EAAoBF,KAAKR,MAC9D9J,EAAoB,YAAa8J,KAAKM,GAAmB,GACzDpK,EAAoB,WAAY8J,KAAKS,GAA0B,GAC/DvK,EAAoB,cAAe8J,KAAKS,GAA0B,GA+sB1E,MAvpBYlK,GAAAoK,UAAAC,EAAR,WAAA,GAAAC,GAAAb,IAGIA,MAAKC,EAAmB,EAExBD,KAAKc,EAAwBpC,EAAY,GAEzCsB,KAAKe,GACDC,KACAC,EAAgBvM,OAChBwM,EAAK,EACLC,MAGJnB,KAAKoB,GACD/G,EAAG,KACHC,EAAG,MAGP0F,KAAKqB,GACDhH,EAAG,KACHC,EAAG,KAGP,IAAIgH,GAA2BtB,KAAKF,CAiBpC,IAfAE,KAAKuB,EAAgB,GAAIC,GAAaxB,KAAKe,EAAgB,SAACU,EAAqBpH,EAAUC,GAEvFgH,EAAeG,EAEE,gBAANpH,IAA+B,gBAANC,KAChCuG,EAAKa,GACDrH,EAAGA,GAAK,EACRC,EAAGA,GAAK,MAMpB0F,KAAKe,EAAevB,EAAK,EACzBQ,KAAKuB,EAAc5B,WAAajB,EAAY,GACxCE,EAAkB,YAAaoB,KAAKF,EAAaE,KAAKI,EAAiBJ,KAAKe,EAAgBf,KAAKuB,GAKjG,MAFAvB,MAAKC,EAAmB,EACxBD,KAAK2B,KACE,CAOX,IAJA7H,EAAqC,OAAQkG,KAAKI,EAAiBJ,KAAKqB,GACxErB,KAAK4B,EAAatG,EAAgBgG,GAClCtB,KAAK6B,EAAuB7F,EAAuBgE,KAAK4B,IAEnD5B,KAAK0B,EAGN,GAAI1B,KAAKhJ,EAAQ8K,gBAEb9B,KAAK0B,GACDrH,EAAG2F,KAAKhJ,EAAQ8K,gBAAgBzH,EAChCC,EAAG0F,KAAKhJ,EAAQ8K,gBAAgBxH,OAInC,IAAI0F,KAAKhJ,EAAQ+K,uBAAwB,CAE1C,GAAMpH,GAAKC,iBAAiB0G,EAC5BtB,MAAK0B,GACDrH,EAAG,EAAIsC,SAAShC,EAAGoD,WAAY,IAC/BzD,EAAG,EAAIqC,SAAShC,EAAGqD,UAAW,SAIjC,CAED,GAAMxE,GAAa8H,EAAa7H,wBAC1BkB,EAAKC,iBAAiB0G,EAC5BtB,MAAK0B,GACDrH,EAAGb,EAAWG,KAAOqG,KAAKK,EAAcjH,QAAUuD,SAAShC,EAAGoD,WAAY,IAAMvE,EAAWwI,MAAQ,EACnG1H,EAAGd,EAAWK,IAAMmG,KAAKK,EAAchH,QAAUsD,SAAShC,EAAGqD,UAAW,IAAMxE,EAAWyI,OAAS,GAwB9G,MAnBA3F,GAAmB0D,KAAK4B,EAAY5B,KAAKqB,EAA2BrB,KAAK6B,EAAsB7B,KAAK0B,EAAkB1B,KAAKhJ,EAAQ+K,wBACnI1N,SAAS0C,KAAKmL,YAAYlC,KAAK4B,GAG/B5B,KAAKmC,EAAuBC,YAAY,WAIhCvB,EAAKwB,IAITxB,EAAKwB,GAAiB,EAEtBxB,EAAKyB,IAELzB,EAAKwB,GAAiB,IACvBrC,KAAKhJ,EAAQ4I,oBAET,GAGHrJ,EAAAoK,UAAAgB,EAAR,WAIQ3B,KAAKmC,IACLI,cAAcvC,KAAKmC,GACnBnC,KAAKmC,EAAuB,MAGhC5K,EAAuB,YAAayI,KAAKM,GACzC/I,EAAuB,WAAYyI,KAAKS,GACxClJ,EAAuB,cAAeyI,KAAKS,GAEvCT,KAAK4B,IACL5B,KAAK4B,EAAW9K,WAAW0L,YAAYxC,KAAK4B,GAC5C5B,KAAK4B,EAAa,MAGtB5B,KAAKD,EAAsBC,KAAKhJ,EAASgJ,KAAKI,EAAiBJ,KAAKC,IAOhE1J,EAAAoK,UAAAJ,EAAR,SAAqB7J,GAArB,GAAAmK,GAAAb,IAGI,IAAI9H,EAAuCxB,EAAOsJ,KAAKK,EAAc7H,eAAgB,EAArF,CAQA,GAHAwH,KAAKI,EAAkB1J,EAGK,IAAxBsJ,KAAKC,EAAsD,CAE3D,GAAIwC,GAAS,MAGb,IAAIzC,KAAKhJ,EAAQ0L,2BAEb,IACID,EAAYzC,KAAKhJ,EAAQ0L,2BAA2BhM,GAExD,MAAOf,GAEH8M,GAAY,MAMhBA,GAAsC,IAAzB/L,EAAMyD,QAAQxC,MAG/B,OAAK8K,QAODzC,KAAKY,OAAa,IAGlBZ,KAAKH,EAAc8C,iBACnBjM,EAAMiM,uBATN3C,MAAK2B,IAwBb,GANAjL,EAAMiM,iBAGN7I,EAAqC,SAAUpD,EAAOsJ,KAAKoB,GAC3DtH,EAAqC,OAAQpD,EAAOsJ,KAAKqB,GAErDrB,KAAKhJ,EAAQ4L,2BAEb,IAEI,GAAIC,IAA4B,CAiChC,IA/BA7C,KAAKhJ,EAAQ4L,2BACTlM,GAEI2D,EAAG2F,KAAKoB,EAA2B/G,EACnCC,EAAG0F,KAAKoB,EAA2B9G,GAEvC0F,KAAKE,EACL,SAACxG,EAAgBE,GAGRiH,EAAKe,IAIViB,GAA4B,EAE5BhC,EAAKO,EAA2B/G,GAAKX,EACrCmH,EAAKO,EAA2B9G,GAAKV,EACrCiH,EAAKQ,EAA0BhH,GAAKX,EACpCmH,EAAKQ,EAA0B/G,GAAKV,EAEpC0C,EACIuE,EAAKe,EACLf,EAAKQ,EACLR,EAAKgB,EACLhB,EAAKa,EACLb,EAAK7J,EAAQ+K,2BAKrBc,EACA,OAGR,MAAOlN,IAKX2G,EAAmB0D,KAAK4B,EAAY5B,KAAKqB,EAA2BrB,KAAK6B,EAAsB7B,KAAK0B,EAAkB1B,KAAKhJ,EAAQ+K,0BAG/HxL,EAAAoK,UAAAD,EAAR,SAA4BhK,GAGxB,GAAIwB,EAAuCxB,EAAOsJ,KAAKK,EAAc7H,eAAgB,EAArF,CAKA,GAAIwH,KAAKhJ,EAAQ4L,2BACb,IAEI5C,KAAKhJ,EAAQ4L,2BAA2BlO,OAAWA,OAAWA,OAAW,cAG7E,MAAOiB,IAMX,GAA4B,IAAxBqK,KAAKC,EAEL,WADAD,MAAK2B,GAKTjL,GAAMiM,iBAEN3C,KAAKC,EAAsC,gBAAfvJ,EAAMiC,KAAsB,EAAA,IAUpDpC,EAAAoK,UAAA2B,EAAR,WAAA,GAAAzB,GAAAb,IAEI,IAAIhL,EACA,GAAIgK,GAAcC,EAAe,QAC7B6D,EAA6B7D,EAAe,2BAC5C8D,EAA0B9D,EAAe,qBAGjD,IAAM+D,GAAwBhD,KAAKc,CAGnCd,MAAKe,EAAevB,EAAK,EACzBQ,KAAKuB,EAAc5B,WAAajB,EAAY,EAC5C,IAAMuE,GAAgBrE,EAAkB,OAAQoB,KAAKF,EAAaE,KAAKI,EAAiBJ,KAAKe,EAAgBf,KAAKuB,EASlH,IARI0B,IAGAjD,KAAKc,EAAwBpC,EAAY,IAKzCuE,GAAyC,IAAxBjD,KAAKC,GAA4E,IAAxBD,KAAKC,EAAsD,CAErI,GAAMiD,GAAalD,KAAKmD,EAAoBnD,KAAKC,EAGjD,OAAIiD,OAEAlG,GAAuBgD,KAAKF,EAAaE,KAAK4B,EAAY5B,KAAK6B,EAAsB,WACjFhB,EAAKuC,UAObpD,MAAKoD,IAMT,GAAMC,GAA4ChP,SAASiP,iBAAiBtD,KAAKoB,EAA2B/G,EAAG2F,KAAKoB,EAA2B9G,GAIzIiJ,EAAwBvD,KAAKG,CAM/BkD,KAAqBrD,KAAKE,GAA2BmD,IAAqBrD,KAAKG,IAE3EnL,IAEIgL,KAAKE,GACLF,KAAKE,EAAwBtE,UAAU6D,OAAOqD,GAG9CO,IACAA,EAAiBzH,UAAUC,IAAImD,GAC/BqE,EAAiBzH,UAAUC,IAAIiH,KAIvC9C,KAAKE,EAA0BmD,EAEC,OAA5BrD,KAAKG,IACLH,KAAKe,EAAevB,EAAK,EACzBQ,KAAKuB,EAAc5B,WAAajB,EAAY,GAC5CE,EAAkB,WAAYoB,KAAKG,EAAoBH,KAAKI,EAAiBJ,KAAKe,EAAgBf,KAAKuB,GAAe,IAIrF,OAAjCvB,KAAKE,EAELF,KAAKG,EAAqBH,KAAKE,GAgB/BF,KAAKe,EAAevB,EAAK,EACzBQ,KAAKuB,EAAc5B,WAAapB,EAAoByB,KAAKe,EAAeyC,EAAgBxD,KAAKF,GACzFlB,EAAkB,YAAaoB,KAAKE,EAAyBF,KAAKI,EAAiBJ,KAAKe,EAAgBf,KAAKuB,IAG7GvB,KAAKG,EAAqBH,KAAKE,EAC/BF,KAAKc,EAAwBpB,EAAuBM,KAAKuB,EAAc/C,cAAewB,KAAKuB,EAAc5B,aAuCrGK,KAAKE,IAA4B7L,SAAS0C,OAS1CiJ,KAAKG,EAAqB9L,SAAS0C,QAa/CwM,IAA0BvD,KAAKG,GAAuBpI,EAAawL,KAE/DvO,GACAuO,EAAsB3H,UAAU6D,OAAOsD,GAK3C/C,KAAKe,EAAevB,EAAK,EACzBQ,KAAKuB,EAAc5B,WAAajB,EAAY,GAC5CE,EAAkB,YAAa2E,EAAuBvD,KAAKI,EAAiBJ,KAAKe,EAAgBf,KAAKuB,GAAe,EAAOvB,KAAKG,IAIjIpI,EAAaiI,KAAKG,KAEdnL,IACAgL,KAAKG,EAAmBvE,UAAUC,IAAImD,GACtCgB,KAAKG,EAAmBvE,UAAUC,IAAIkH,IAI1C/C,KAAKe,EAAevB,EAAK,EACzBQ,KAAKuB,EAAc5B,WAAapB,EAAoByB,KAAKe,EAAeyC,EAAgBxD,KAAKF,GACzFlB,EAAkB,WAAYoB,KAAKG,EAAoBH,KAAKI,EAAiBJ,KAAKe,EAAgBf,KAAKuB,MAAmB,EAkB1HvB,KAAKc,EAAwBpC,EAAY,GAQzCsB,KAAKc,EAAwBpB,EAAuBM,KAAKuB,EAAc/C,cAAewB,KAAKuB,EAAc5B,aAmB7GqD,IAA0BhD,KAAKc,GAC/Bd,KAAK4B,EAAWhG,UAAU6D,OAAOR,EAAe+D,EAGpD,IAAMS,GAA4BxE,EAAee,KAAKc,CAElDd,MAAK4B,EAAWhG,UAAU8H,SAASD,MAA+B,GAClEzD,KAAK4B,EAAWhG,UAAUC,IAAI4H,IAO9BlN,EAAAoK,UAAAwC,EAAR,SAA4BlM,GAIxB,GAAIjC,EAAO,CAEP,GAAI8N,GAA6B7D,EAAe,2BAC5C8D,EAA0B9D,EAAe,qBAEzCe,MAAKG,GACLH,KAAKG,EAAmBvE,UAAU6D,OAAOsD,GAGzC/C,KAAKE,GACLF,KAAKE,EAAwBtE,UAAU6D,OAAOqD,GAWtD,GAAMI,GAAclD,KAAKc,IAA0BpC,EAAY,IAC5B,OAA5BsB,KAAKG,GACA,IAALlJ,CAkEP,OAjEIiM,GAQInL,EAAaiI,KAAKG,KAClBH,KAAKe,EAAevB,EAAK,EACzBQ,KAAKuB,EAAc5B,WAAajB,EAAY,GAC5CE,EAAkB,YAAaoB,KAAKG,EAAoBH,KAAKI,EAAiBJ,KAAKe,EAAgBf,KAAKuB,GAAe,IAevHxJ,EAAaiI,KAAKG,KAKlBH,KAAKe,EAAevB,EAAK,EACzBQ,KAAKuB,EAAc5B,WAAaK,KAAKc,EACjClC,EAAkB,OAAQoB,KAAKG,EAAoBH,KAAKI,EAAiBJ,KAAKe,EAAgBf,KAAKuB,MACnG,EAEAvB,KAAKc,EAAwBd,KAAKuB,EAAc5B,WAmBhDK,KAAKc,EAAwBpC,EAAY,IAU9CwE,GAoCH3M,EAAAoK,UAAAyC,EAAR,WAIIpD,KAAKe,EAAevB,EAAK,EACzBQ,KAAKuB,EAAc5B,WAAaK,KAAKc,EACrClC,EAAkB,UAAWoB,KAAKF,EAAaE,KAAKI,EAAiBJ,KAAKe,EAAgBf,KAAKuB,GAAe,GAG9GvB,KAAKC,EAAmB,EACxBD,KAAK2B,KAIbpL,KA8BAiL,EAAA,WAII,QAAAA,GAAoBmC,EACAC,GADA5D,KAAA2D,EAAAA,EACA3D,KAAA4D,EAAAA,EAHZ5D,KAAA6D,EAAqBnF,EAAY,GAsF7C,MAxEIzJ,QAAAO,eAAWgM,EAAAb,UAAA,aAAX,WACI,GAAyB,IAArBX,KAAK2D,EAAWnE,EAChB,MAAOvK,QAAO6O,OAAO9D,KAAK2D,EAAWI,oCAItCvC,EAAAb,UAAAqD,QAAP,SAAerL,EAAasL,GACxB,GAAyB,IAArBjE,KAAK2D,EAAWnE,EAAuC,CAEvD,GAAI7G,EAAKgG,QAAQ,MAAO,EACpB,KAAM,IAAIuF,OAAM,mCAGpBlE,MAAK2D,EAAWQ,EAAMxL,GAAQsL,EAE1BjE,KAAK2D,EAAWI,EAAOpF,QAAQhG,MAAU,GACzCqH,KAAK2D,EAAWI,EAAO3J,KAAKzB,KAKjC6I,EAAAb,UAAAyD,QAAP,SAAezL,GACX,GAAyB,IAArBqH,KAAK2D,EAAWnE,GACQ,IAArBQ,KAAK2D,EAAWnE,EACnB,MAAOQ,MAAK2D,EAAWQ,EAAMxL,IAAS,IAIvC6I,EAAAb,UAAA0D,UAAP,SAAiBC,GACb,GAAyB,IAArBtE,KAAK2D,EAAWnE,EAAuC,CAEvD,GAAI8E,GAAUtE,KAAK2D,EAAWQ,EAAMG,GAAS,OAClCtE,MAAK2D,EAAWQ,EAAMG,EAC7B,IAAIC,GAAQvE,KAAK2D,EAAWI,EAAOpF,QAAQ2F,EAI3C,aAHIC,GAAQ,GACRvE,KAAK2D,EAAWI,EAAOS,OAAOD,EAAO,IAK7CvE,KAAK2D,EAAWQ,KAChBnE,KAAK2D,EAAWI,OAIjBvC,EAAAb,UAAA8D,aAAP,SAAoBC,EAAerK,EAAUC,GAChB,IAArB0F,KAAK2D,EAAWnE,GAChBQ,KAAK4D,EAAqBc,EAAOrK,EAAGC,IAI5CrF,OAAAO,eAAWgM,EAAAb,UAAA,qBAAX,WACI,MAAOX,MAAK2D,EAAWH,OAG3B,SAAyBmB,GACI,IAArB3E,KAAK2D,EAAWnE,GACbf,EAAgBE,QAAQgG,IAAS,IACpC3E,KAAK2D,EAAWH,EAAiBmB,oCAIzC1P,OAAAO,eAAWgM,EAAAb,UAAA,kBAAX,WACI,MAAOX,MAAK6D,OAGhB,SAAsBc,GACO,IAArB3E,KAAK2D,EAAWnE,GACbf,EAAgBE,QAAQgG,IAAS,IACpC3E,KAAK6D,EAAcc,oCAG/BnD","file":"index.min.js","sourcesContent":["// debug mode, which will highlight drop target, immediate user selection and events fired as you interact.\nconst DEBUG = false;\n\n//\n\ninterface DetectedFeatures {\n draggable:boolean;\n dragEvents:boolean;\n touchEvents:boolean;\n userAgentSupportingNativeDnD:boolean;\n}\n\nfunction detectFeatures():DetectedFeatures {\n\n let features:DetectedFeatures = {\n dragEvents: (\"ondragstart\" in document.documentElement),\n draggable: (\"draggable\" in document.documentElement),\n touchEvents: (\"ontouchstart\" in document.documentElement),\n userAgentSupportingNativeDnD: undefined\n };\n\n const isBlinkEngine = !!((window).chrome) || /chrome/i.test(navigator.userAgent);\n\n features.userAgentSupportingNativeDnD = !(\n // if is mobile safari or android browser -> no native dnd\n (/iPad|iPhone|iPod|Android/.test(navigator.userAgent))\n || // OR\n //if is blink(chrome/opera) with touch events enabled -> no native dnd\n (isBlinkEngine && features.touchEvents)\n );\n\n if (DEBUG) {\n Object.keys(features).forEach(function (key) {\n console.log(\"dnd-poly: detected feature '\" + key + \" = \" + features[key] + \"'\");\n });\n }\n\n return features;\n}\n\nlet supportsPassive:boolean;\n\nfunction supportsPassiveEventListener():boolean {\n\n let supportsPassiveEventListeners = false;\n\n // reference https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n try {\n let opts = Object.defineProperty({}, \"passive\", {\n get: function () {\n supportsPassiveEventListeners = true;\n }\n });\n window.addEventListener(\"test\", null, opts);\n }\n // tslint:disable-next-line:no-empty\n catch (e) {\n }\n\n return supportsPassiveEventListeners;\n}\n\n//\n\n//\n\n// function signature for the dragImageTranslateOverride hook\nexport type DragImageTranslateOverrideFn = (// corresponding touchmove event\n event:TouchEvent,\n // the processed touch event viewport coordinates\n hoverCoordinates:Point,\n // the element under the calculated touch coordinates\n hoveredElement:HTMLElement,\n // callback for updating the drag image offset\n translateDragImageFn:(offsetX:number, offsetY:number) => void) => void;\n\nexport interface Config {\n // flag to force the polyfill being applied and not rely on internal feature detection\n forceApply?:boolean;\n // useful for when you want the default drag image but still want to apply\n // some static offset from touch coordinates to drag image coordinates\n // defaults to (0,0)\n dragImageOffset?:Point;\n // if the dragImage shall be centered on the touch coordinates\n // defaults to false\n dragImageCenterOnTouch?:boolean;\n // the drag and drop operation involves some processing. here you can specify in what interval this processing takes place.\n // defaults to 150ms\n iterationInterval?:number;\n // hook for custom logic that decides if a drag operation should start\n dragStartConditionOverride?:(event:TouchEvent) => boolean;\n // hook for custom logic that can manipulate the drag image translate offset\n dragImageTranslateOverride?:DragImageTranslateOverrideFn;\n // hook for custom logic that can override the default action based on the original touch event when the drag never started\n // be sure to call event.preventDefault() if handling the default action in the override to prevent the browser default.\n defaultActionOverride?:(event:TouchEvent) => void;\n}\n\n// default config\nconst config:Config = {\n iterationInterval: 150,\n};\n\nexport function polyfill(override?:Config):boolean {\n\n if (override) {\n // overwrite default config with user config\n Object.keys(override).forEach(function (key) {\n config[key] = override[key];\n });\n }\n\n // only do feature detection when config does not force apply the polyfill\n if (!config.forceApply) {\n\n // feature/browser detection\n const detectedFeatures = detectFeatures();\n\n // check if native drag and drop support is there\n if (detectedFeatures.userAgentSupportingNativeDnD\n && detectedFeatures.draggable\n && detectedFeatures.dragEvents) {\n // no polyfilling required\n return false;\n }\n }\n\n console.log(\"dnd-poly: Applying mobile drag and drop polyfill.\");\n\n supportsPassive = supportsPassiveEventListener();\n\n // add listeners suitable for detecting a potential drag operation\n addDocumentListener(\"touchstart\", onTouchstart, false);\n\n return true;\n}\n\n//\n\n//\n\n// reference the currently active drag operation\nlet activeDragOperation:DragOperationController;\n\n/**\n * event handler listening for initial events that possibly start a drag and drop operation.\n */\nfunction onTouchstart(e:TouchEvent) {\n\n console.log(\"dnd-poly: global touchstart\");\n\n // From the moment that the user agent is to initiate the drag-and-drop operation,\n // until the end of the drag-and-drop operation, device input events (e.g. mouse and keyboard events) must be suppressed.\n\n // only allow one drag operation at a time\n if (activeDragOperation) {\n console.log(\"dnd-poly: drag operation already active\");\n return;\n }\n\n let dragTarget = tryFindDraggableTarget(e);\n\n // If there is no such element, then nothing is being dragged; abort these\n // steps, the drag-and-drop operation is never started.\n if (!dragTarget) {\n return;\n }\n\n try {\n activeDragOperation = new DragOperationController(e, config, dragTarget, dragOperationEnded);\n }\n catch (err) {\n dragOperationEnded(config, e, DragOperationState.CANCELLED);\n // rethrow exception after cleanup\n throw err;\n }\n}\n\n/**\n * Search for a possible draggable item upon an event that can initialize a drag operation.\n */\nfunction tryFindDraggableTarget(event:TouchEvent):Element {\n\n //1. Determine what is being dragged, as follows:\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the drag operation was invoked on a selection, then it is the selection that is being dragged.\n //if( (event.target).nodeType === 3 ) {\n //\n // config.log( \"drag on text\" );\n // return event.target;\n //}\n //Otherwise, if the drag operation was invoked on a Document, it is the first element, going up the ancestor chain, starting at the node that the\n // user tried to drag, that has the IDL attribute draggable set to true.\n //else {\n\n let el = event.target;\n\n do {\n if (el.draggable === false) {\n continue;\n }\n if (el.getAttribute && el.getAttribute(\"draggable\") === \"true\") {\n return el;\n }\n } while ((el = el.parentNode) && el !== document.body);\n}\n\n/**\n * Implements callback invoked when a drag operation has ended or crashed.\n */\nfunction dragOperationEnded(_config:Config, event:TouchEvent, state:DragOperationState) {\n\n // we need to make the default action happen only when no drag operation took place\n if (state === DragOperationState.POTENTIAL) {\n\n console.log(\"dnd-poly: Drag never started. Last event was \" + event.type);\n\n // when lifecycle hook is present\n if (_config.defaultActionOverride) {\n\n try {\n\n _config.defaultActionOverride(event);\n\n if (event.defaultPrevented) {\n\n console.log(\"dnd-poly: defaultActionOverride has taken care of triggering the default action. preventing default on original event\");\n }\n\n }\n catch (e) {\n\n console.log(\"dnd-poly: error in defaultActionOverride: \" + e);\n }\n }\n }\n\n // reset drag operation container\n activeDragOperation = null;\n}\n\n//\n\n//\n\n/**\n * For tracking the different states of a drag operation.\n */\nconst enum DragOperationState {\n // initial state of a controller, if no movement is detected the operation ends with this state\n POTENTIAL,\n // after movement is detected the drag operation starts and keeps this state until it ends\n STARTED,\n // when the drag operation ended normally\n ENDED,\n // when the drag operation ended with a cancelled input event\n CANCELLED\n}\n\n// contains all possible values of the effectAllowed property\nconst enum EFFECT_ALLOWED {\n NONE = 0,\n COPY = 1,\n COPY_LINK = 2,\n COPY_MOVE = 3,\n LINK = 4,\n LINK_MOVE = 5,\n MOVE = 6,\n ALL = 7\n}\n\nconst ALLOWED_EFFECTS = [\"none\", \"copy\", \"copyLink\", \"copyMove\", \"link\", \"linkMove\", \"move\", \"all\"];\n\n// contains all possible values of the dropEffect property\nconst enum DROP_EFFECT {\n NONE = 0,\n COPY = 1,\n MOVE = 2,\n LINK = 3,\n}\n\nconst DROP_EFFECTS = [\"none\", \"copy\", \"move\", \"link\"];\n\n// cross-browser css transform property prefixes\nconst TRANSFORM_CSS_VENDOR_PREFIXES = [\"\", \"-webkit-\"];\n// css classes\nconst CLASS_PREFIX = \"dnd-poly-\";\nconst CLASS_DRAG_IMAGE = CLASS_PREFIX + \"drag-image\";\nconst CLASS_DRAG_IMAGE_SNAPBACK = CLASS_PREFIX + \"snapback\";\nconst CLASS_DRAG_OPERATION_ICON = CLASS_PREFIX + \"icon\";\n\n/**\n * Aims to implement the HTML5 d'n'd spec (https://html.spec.whatwg.org/multipage/interaction.html#dnd) as close as it can get.\n * Note that all props that are private should start with an underscore to enable better minification.\n *\n * TODO remove lengthy spec comments in favor of short references to the spec\n */\nclass DragOperationController {\n\n private _dragOperationState:DragOperationState = DragOperationState.POTENTIAL;\n\n private _dragImage:HTMLElement;\n private _dragImageTransforms:string[];\n private _dragImagePageCoordinates:Point; // the current page coordinates of the dragImage\n private _dragImageOffset:Point; // offset of the drag image relative to the coordinates\n\n private _currentHotspotCoordinates:Point; // the point relative to viewport for determining the immediate user selection\n\n private _immediateUserSelection:HTMLElement = null; // the element the user currently hovers while dragging\n private _currentDropTarget:HTMLElement = null; // the element that was selected as a valid drop target by the d'n'd operation\n\n private _dragDataStore:DragDataStore;\n private _dataTransfer:DataTransfer;\n\n private _currentDragOperation:string; // the current drag operation set according to the d'n'd processing model\n\n private _initialTouch:Touch; // the identifier for the touch that initiated the drag operation\n private _touchMoveHandler:EventListener;\n private _touchEndOrCancelHandler:EventListener;\n private _lastTouchEvent:TouchEvent;\n\n private _iterationLock:boolean;\n private _iterationIntervalId:number;\n\n constructor(private _initialEvent:TouchEvent,\n private _config:Config,\n private _sourceNode:HTMLElement,\n private _dragOperationEndedCb:(config:Config, event:TouchEvent, state:DragOperationState) => void) {\n\n console.log(\"dnd-poly: setting up potential drag operation..\");\n\n this._lastTouchEvent = _initialEvent;\n this._initialTouch = _initialEvent.changedTouches[0];\n\n // create bound event listeners\n this._touchMoveHandler = this._onTouchMove.bind(this);\n this._touchEndOrCancelHandler = this._onTouchEndOrCancel.bind(this);\n addDocumentListener(\"touchmove\", this._touchMoveHandler, false);\n addDocumentListener(\"touchend\", this._touchEndOrCancelHandler, false);\n addDocumentListener(\"touchcancel\", this._touchEndOrCancelHandler, false);\n\n // the only thing we do is setup the touch listeners. if drag will really start is decided in touch move handler.\n\n //\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // 3. Establish which DOM node is the source node, as follows:\n // If it is a selection that is being dragged, then the source node is the text node that the user started the drag on (typically the text node\n // that the user originally clicked). If the user did not specify a particular node, for example if the user just told the user agent to begin\n // a drag of \"the selection\", then the source node is the first text node containing a part of the selection. Otherwise, if it is an element\n // that is being dragged, then the source node is the element that is being dragged. Otherwise, the source node is part of another document or\n // application. When this specification requires that an event be dispatched at the source node in this case, the user agent must instead\n // follow the platform-specific conventions relevant to that situation.\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // 4. Determine the list of dragged nodes, as follows:\n\n // If it is a selection that is being dragged, then the list of dragged nodes contains, in tree order, every node that is partially or\n // completely included in the selection (including all their ancestors).\n\n // Otherwise, the list of dragged nodes contains only the source node, if any.\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // 5. If it is a selection that is being dragged, then add an item to the drag data store item list, with its properties set as follows:\n\n //The drag data item type string\n //\"text/plain\"\n //The drag data item kind\n //Plain Unicode string\n //The actual data\n //The text of the selection\n //Otherwise, if any files are being dragged, then add one item per file to the drag data store item list, with their properties set as follows:\n //\n //The drag data item type string\n //The MIME type of the file, if known, or \"application/octet-stream\" otherwise.\n // The drag data item kind\n //File\n //The actual data\n //The file's contents and name.\n //Dragging files can currently only happen from outside a browsing context, for example from a file system manager application.\n //\n // If the drag initiated outside of the application, the user agent must add items to the drag data store item list as appropriate for the data\n // being dragged, honoring platform conventions where appropriate; however, if the platform conventions do not use MIME types to label dragged\n // data, the user agent must make a best-effort attempt to map the types to MIME types, and, in any case, all the drag data item type strings must\n // be converted to ASCII lowercase. Perform drag-and-drop initialization steps defined in any other applicable specifications.\n\n //\n }\n\n //\n\n /**\n * Setup dragImage, input listeners and the drag\n * and drop process model iteration interval.\n */\n private _setup():boolean {\n console.log(\"dnd-poly: starting drag and drop operation\");\n\n this._dragOperationState = DragOperationState.STARTED;\n\n this._currentDragOperation = DROP_EFFECTS[DROP_EFFECT.NONE];\n\n this._dragDataStore = {\n _data: {},\n _effectAllowed: undefined,\n _mode: DragDataStoreMode.PROTECTED,\n _types: [],\n };\n\n this._currentHotspotCoordinates = {\n x: null,\n y: null\n };\n\n this._dragImagePageCoordinates = {\n x: null,\n y: null\n };\n\n let dragImageSrc:HTMLElement = this._sourceNode;\n\n this._dataTransfer = new DataTransfer(this._dragDataStore, (element:HTMLElement, x:number, y:number) => {\n\n dragImageSrc = element;\n\n if (typeof x === \"number\" || typeof y === \"number\") {\n this._dragImageOffset = {\n x: x || 0,\n y: y || 0\n };\n }\n });\n\n // 9. Fire a DND event named dragstart at the source node.\n this._dragDataStore._mode = DragDataStoreMode.READWRITE;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n if (dispatchDragEvent(\"dragstart\", this._sourceNode, this._lastTouchEvent, this._dragDataStore, this._dataTransfer)) {\n console.log(\"dnd-poly: dragstart cancelled\");\n // dragstart has been prevented -> cancel d'n'd\n this._dragOperationState = DragOperationState.CANCELLED;\n this._cleanup();\n return false;\n }\n\n updateCentroidCoordinatesOfTouchesIn(\"page\", this._lastTouchEvent, this._dragImagePageCoordinates);\n this._dragImage = createDragImage(dragImageSrc);\n this._dragImageTransforms = extractTransformStyles(this._dragImage);\n\n if (!this._dragImageOffset) {\n\n // apply specific offset\n if (this._config.dragImageOffset) {\n\n this._dragImageOffset = {\n x: this._config.dragImageOffset.x,\n y: this._config.dragImageOffset.y\n };\n }\n // center drag image on touch coordinates\n else if (this._config.dragImageCenterOnTouch) {\n\n const cs = getComputedStyle(dragImageSrc);\n this._dragImageOffset = {\n x: 0 - parseInt(cs.marginLeft, 10),\n y: 0 - parseInt(cs.marginTop, 10)\n };\n }\n // by default initialize drag image offset the same as desktop\n else {\n\n const targetRect = dragImageSrc.getBoundingClientRect();\n const cs = getComputedStyle(dragImageSrc);\n this._dragImageOffset = {\n x: targetRect.left - this._initialTouch.clientX - parseInt(cs.marginLeft, 10) + targetRect.width / 2,\n y: targetRect.top - this._initialTouch.clientY - parseInt(cs.marginTop, 10) + targetRect.height / 2\n };\n }\n }\n\n translateDragImage(this._dragImage, this._dragImagePageCoordinates, this._dragImageTransforms, this._dragImageOffset, this._config.dragImageCenterOnTouch);\n document.body.appendChild(this._dragImage);\n\n // 10. Initiate the drag-and-drop operation in a manner consistent with platform conventions, and as described below.\n this._iterationIntervalId = setInterval(() => {\n\n // If the user agent is still performing the previous iteration of the sequence (if any) when the next iteration becomes due,\n // abort these steps for this iteration (effectively \"skipping missed frames\" of the drag-and-drop operation).\n if (this._iterationLock) {\n console.log(\"dnd-poly: iteration skipped because previous iteration hast not yet finished.\");\n return;\n }\n this._iterationLock = true;\n\n this._dragAndDropProcessModelIteration();\n\n this._iterationLock = false;\n }, this._config.iterationInterval);\n\n return true;\n }\n\n private _cleanup() {\n\n console.log(\"dnd-poly: cleanup\");\n\n if (this._iterationIntervalId) {\n clearInterval(this._iterationIntervalId);\n this._iterationIntervalId = null;\n }\n\n removeDocumentListener(\"touchmove\", this._touchMoveHandler);\n removeDocumentListener(\"touchend\", this._touchEndOrCancelHandler);\n removeDocumentListener(\"touchcancel\", this._touchEndOrCancelHandler);\n\n if (this._dragImage) {\n this._dragImage.parentNode.removeChild(this._dragImage);\n this._dragImage = null;\n }\n\n this._dragOperationEndedCb(this._config, this._lastTouchEvent, this._dragOperationState);\n }\n\n //\n\n //\n\n private _onTouchMove(event:TouchEvent) {\n\n // filter unrelated touches\n if (isTouchIdentifierContainedInTouchEvent(event, this._initialTouch.identifier) === false) {\n return;\n }\n\n // update the reference to the last received touch event\n this._lastTouchEvent = event;\n\n // drag operation did not start yet but on movement it should start\n if (this._dragOperationState === DragOperationState.POTENTIAL) {\n\n let startDrag:boolean;\n\n // is a lifecycle hook present?\n if (this._config.dragStartConditionOverride) {\n\n try {\n startDrag = this._config.dragStartConditionOverride(event);\n }\n catch (e) {\n console.error(\"dnd-poly: error in dragStartConditionOverride hook: \" + e);\n startDrag = false;\n }\n }\n else {\n\n // by default only allow a single moving finger to initiate a drag operation\n startDrag = (event.touches.length === 1);\n }\n\n if (!startDrag) {\n\n this._cleanup();\n return;\n }\n\n // setup will return true when drag operation starts\n if (this._setup() === true) {\n\n // prevent scrolling when drag operation starts\n this._initialEvent.preventDefault();\n event.preventDefault();\n }\n\n return;\n }\n\n console.log(\"dnd-poly: moving draggable..\");\n\n // we emulate d'n'd so we dont want any defaults to apply\n event.preventDefault();\n\n // populate shared coordinates from touch event\n updateCentroidCoordinatesOfTouchesIn(\"client\", event, this._currentHotspotCoordinates);\n updateCentroidCoordinatesOfTouchesIn(\"page\", event, this._dragImagePageCoordinates);\n\n if (this._config.dragImageTranslateOverride) {\n\n try {\n\n let handledDragImageTranslate = false;\n\n this._config.dragImageTranslateOverride(\n event,\n {\n x: this._currentHotspotCoordinates.x,\n y: this._currentHotspotCoordinates.y\n },\n this._immediateUserSelection,\n (offsetX:number, offsetY:number) => {\n\n // preventing translation of drag image when there was a drag operation cleanup meanwhile\n if (!this._dragImage) {\n return;\n }\n\n handledDragImageTranslate = true;\n\n this._currentHotspotCoordinates.x += offsetX;\n this._currentHotspotCoordinates.y += offsetY;\n this._dragImagePageCoordinates.x += offsetX;\n this._dragImagePageCoordinates.y += offsetY;\n\n translateDragImage(\n this._dragImage,\n this._dragImagePageCoordinates,\n this._dragImageTransforms,\n this._dragImageOffset,\n this._config.dragImageCenterOnTouch\n );\n }\n );\n\n if (handledDragImageTranslate) {\n return;\n }\n }\n catch (e) {\n console.log(\"dnd-poly: error in dragImageTranslateOverride hook: \" + e);\n }\n }\n\n translateDragImage(this._dragImage, this._dragImagePageCoordinates, this._dragImageTransforms, this._dragImageOffset, this._config.dragImageCenterOnTouch);\n }\n\n private _onTouchEndOrCancel(event:TouchEvent) {\n\n // filter unrelated touches\n if (isTouchIdentifierContainedInTouchEvent(event, this._initialTouch.identifier) === false) {\n return;\n }\n\n // let the dragImageTranslateOverride know that its over\n if (this._config.dragImageTranslateOverride) {\n try {\n /* tslint:disable */\n this._config.dragImageTranslateOverride(undefined, undefined, undefined, function () {\n });\n }\n catch (e) {\n console.log(\"dnd-poly: error in dragImageTranslateOverride hook: \" + e);\n }\n }\n\n // drag operation did not even start\n if (this._dragOperationState === DragOperationState.POTENTIAL) {\n this._cleanup();\n return;\n }\n\n // we emulate d'n'd so we dont want any defaults to apply\n event.preventDefault();\n\n this._dragOperationState = (event.type === \"touchcancel\") ? DragOperationState.CANCELLED : DragOperationState.ENDED;\n }\n\n //\n\n //\n\n /**\n * according to https://html.spec.whatwg.org/multipage/interaction.html#drag-and-drop-processing-model\n */\n private _dragAndDropProcessModelIteration():void {\n\n if (DEBUG) {\n var debug_class = CLASS_PREFIX + \"debug\",\n debug_class_user_selection = CLASS_PREFIX + \"immediate-user-selection\",\n debug_class_drop_target = CLASS_PREFIX + \"current-drop-target\";\n }\n\n const previousDragOperation = this._currentDragOperation;\n\n // Fire a DND event named drag event at the source node.\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n const dragCancelled = dispatchDragEvent(\"drag\", this._sourceNode, this._lastTouchEvent, this._dragDataStore, this._dataTransfer);\n if (dragCancelled) {\n console.log(\"dnd-poly: drag event cancelled.\");\n // If this event is canceled, the user agent must set the current drag operation to \"none\" (no drag operation).\n this._currentDragOperation = DROP_EFFECTS[DROP_EFFECT.NONE];\n }\n\n // Otherwise, if the user ended the drag-and-drop operation (e.g. by releasing the mouse button in a mouse-driven drag-and-drop interface),\n // or if the drag event was canceled, then this will be the last iteration.\n if (dragCancelled || this._dragOperationState === DragOperationState.ENDED || this._dragOperationState === DragOperationState.CANCELLED) {\n\n const dragFailed = this._dragOperationEnded(this._dragOperationState);\n\n // if drag failed transition snap back\n if (dragFailed) {\n\n applyDragImageSnapback(this._sourceNode, this._dragImage, this._dragImageTransforms, () => {\n this._finishDragOperation();\n });\n return;\n }\n\n // Otherwise immediately\n // Fire a DND event named dragend at the source node.\n this._finishDragOperation();\n return;\n }\n\n // If the drag event was not canceled and the user has not ended the drag-and-drop operation,\n // check the state of the drag-and-drop operation, as follows:\n const newUserSelection:HTMLElement = document.elementFromPoint(this._currentHotspotCoordinates.x, this._currentHotspotCoordinates.y);\n\n console.log(\"dnd-poly: new immediate user selection is: \" + newUserSelection);\n\n const previousTargetElement = this._currentDropTarget;\n\n // If the user is indicating a different immediate user selection than during the last iteration (or if this is the first iteration),\n // and if this immediate user selection is not the same as the current target element,\n // then fire a DND event named dragexit at the current target element,\n // and then update the current target element as follows:\n if (newUserSelection !== this._immediateUserSelection && newUserSelection !== this._currentDropTarget) {\n\n if (DEBUG) {\n\n if (this._immediateUserSelection) {\n this._immediateUserSelection.classList.remove(debug_class_user_selection);\n }\n\n if (newUserSelection) {\n newUserSelection.classList.add(debug_class);\n newUserSelection.classList.add(debug_class_user_selection);\n }\n }\n\n this._immediateUserSelection = newUserSelection;\n\n if (this._currentDropTarget !== null) {\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n dispatchDragEvent(\"dragexit\", this._currentDropTarget, this._lastTouchEvent, this._dragDataStore, this._dataTransfer, false);\n }\n\n // If the new immediate user selection is null\n if (this._immediateUserSelection === null) {\n //Set the current target element to null also.\n this._currentDropTarget = this._immediateUserSelection;\n\n console.log(\"dnd-poly: current drop target changed to null\");\n }\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the new immediate user selection is in a non-DOM document or application\n // else if() {\n // Set the current target element to the immediate user selection.\n // this.currentDropTarget = this.immediateUserSelection;\n // return;\n // }\n // Otherwise\n else {\n // Fire a DND event named dragenter at the immediate user selection.\n //the polyfill cannot determine if a handler even exists as browsers do to silently\n // allow drop when no listener existed, so this event MUST be handled by the client\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = determineDropEffect(this._dragDataStore._effectAllowed, this._sourceNode);\n if (dispatchDragEvent(\"dragenter\", this._immediateUserSelection, this._lastTouchEvent, this._dragDataStore, this._dataTransfer)) {\n console.log(\"dnd-poly: dragenter default prevented\");\n // If the event is canceled, then set the current target element to the immediate user selection.\n this._currentDropTarget = this._immediateUserSelection;\n this._currentDragOperation = determineDragOperation(this._dataTransfer.effectAllowed, this._dataTransfer.dropEffect);\n }\n // Otherwise, run the appropriate step from the following list:\n else {\n\n // NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n //console.log( \"dnd-poly: dragenter not prevented, searching for dropzone..\" );\n //var newTarget = DragOperationController.FindDropzoneElement( this.immediateUserSelection );\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the current target element is a text field (e.g. textarea, or an input element whose type attribute is in the Text state) or an\n // editable element, and the drag data store item list has an item with the drag data item type string \"text/plain\" and the drag data\n // item kind Plain Unicode string\n //if( ElementIsTextDropzone( this.immediateUserSelection, this.dragDataStore ) ) {\n //Set the current target element to the immediate user selection anyway.\n //this.currentDropTarget = this.immediateUserSelection;\n //}\n //else\n // If the current target element is an element with a dropzone attribute that matches the drag data store\n //if( newTarget === this.immediateUserSelection &&\n // DragOperationController.GetOperationForMatchingDropzone( this.immediateUserSelection, this.dragDataStore ) !== \"none\" ) {\n // Set the current target element to the immediate user selection anyway.\n // this.currentDropTarget = this.immediateUserSelection;\n //}\n // If the immediate user selection is an element that itself has an ancestor element\n // with a dropzone attribute that matches the drag data store\n // NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n //else if( newTarget !== null && DragOperationController.GetOperationForMatchingDropzone( newTarget, this.dragDataStore ) ) {\n\n // If the immediate user selection is new target, then leave the current target element unchanged.\n\n // Otherwise, fire a DND event named dragenter at new target, with the current target element\n // as the specific related target. Then, set the current target element to new target,\n // regardless of whether that event was canceled or not.\n //this.dragenter( newTarget, this.currentDropTarget );\n //this.currentDropTarget = newTarget;\n //}\n // If the current target element is not the body element\n //else\n if (this._immediateUserSelection !== document.body) {\n // Fire a DND event named dragenter at the body element, and set the current target element to the body element, regardless of\n // whether that event was canceled or not.\n // Note: If the body element is null, then the event will be fired at the Document object (as\n // required by the definition of the body element), but the current target element would be set to null, not the Document object.\n\n // We do not listen to what the spec says here because this results in doubled events on the body/document because if the first one\n // was not cancelled it will have bubbled up to the body already ;)\n // this.dragenter( window.document.body );\n this._currentDropTarget = document.body;\n }\n // Otherwise\n //else {\n // leave the current drop target unchanged\n //}\n }\n }\n }\n\n // If the previous step caused the current target element to change,\n // and if the previous target element was not null or a part of a non-DOM document,\n // then fire a DND event named dragleave at the previous target element.\n if (previousTargetElement !== this._currentDropTarget && (isDOMElement(previousTargetElement) )) {\n\n if (DEBUG) {\n previousTargetElement.classList.remove(debug_class_drop_target);\n }\n\n console.log(\"dnd-poly: current drop target changed.\");\n\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n dispatchDragEvent(\"dragleave\", previousTargetElement, this._lastTouchEvent, this._dragDataStore, this._dataTransfer, false, this._currentDropTarget);\n }\n\n // If the current target element is a DOM element, then fire a DND event named dragover at this current target element.\n if (isDOMElement(this._currentDropTarget)) {\n\n if (DEBUG) {\n this._currentDropTarget.classList.add(debug_class);\n this._currentDropTarget.classList.add(debug_class_drop_target);\n }\n\n // If the dragover event is not canceled, run the appropriate step from the following list:\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = determineDropEffect(this._dragDataStore._effectAllowed, this._sourceNode);\n if (dispatchDragEvent(\"dragover\", this._currentDropTarget, this._lastTouchEvent, this._dragDataStore, this._dataTransfer) === false) {\n\n console.log(\"dnd-poly: dragover not prevented on possible drop-target.\");\n // NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the current target element is a text field (e.g. textarea, or an input element whose type attribute is in the Text state) or\n // an editable element, and the drag data store item list has an item with the drag data item type string \"text/plain\" and the drag\n // data item kind Plain Unicode string\n //if( ElementIsTextDropzone( this.currentDropTarget, this.dragDataStore ) ) {\n // Set the current drag operation to either \"copy\" or \"move\", as appropriate given the platform conventions.\n //this.currentDragOperation = \"copy\"; //or move. spec says its platform specific behaviour.\n //}\n //else {\n // If the current target element is an element with a dropzone attribute that matches the drag data store\n //this.currentDragOperation = DragOperationController.GetOperationForMatchingDropzone( this.currentDropTarget, this.dragDataStore );\n //}\n // when dragover is not prevented and no dropzones are there, no drag operation\n this._currentDragOperation = DROP_EFFECTS[DROP_EFFECT.NONE];\n }\n // Otherwise (if the dragover event is canceled), set the current drag operation based on the values of the effectAllowed and\n // dropEffect attributes of the DragEvent object's dataTransfer object as they stood after the event dispatch finished\n else {\n\n console.log(\"dnd-poly: dragover prevented.\");\n\n this._currentDragOperation = determineDragOperation(this._dataTransfer.effectAllowed, this._dataTransfer.dropEffect);\n }\n }\n\n console.log(\"dnd-poly: d'n'd iteration ended. current drag operation: \" + this._currentDragOperation);\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // Otherwise, if the current target element is not a DOM element, use platform-specific mechanisms to determine what drag operation is\n // being performed (none, copy, link, or move), and set the current drag operation accordingly.\n\n //Update the drag feedback (e.g. the mouse cursor) to match the current drag operation, as follows:\n // ---------------------------------------------------------------------------------------------------------\n // Drag operation |\tFeedback\n // \"copy\"\t | Data will be copied if dropped here.\n // \"link\"\t | Data will be linked if dropped here.\n // \"move\"\t | Data will be moved if dropped here.\n // \"none\"\t | No operation allowed, dropping here will cancel the drag-and-drop operation.\n // ---------------------------------------------------------------------------------------------------------\n\n if (previousDragOperation !== this._currentDragOperation) {\n this._dragImage.classList.remove(CLASS_PREFIX + previousDragOperation);\n }\n\n const currentDragOperationClass = CLASS_PREFIX + this._currentDragOperation;\n\n if (this._dragImage.classList.contains(currentDragOperationClass) === false) {\n this._dragImage.classList.add(currentDragOperationClass);\n }\n }\n\n /**\n * according to https://html.spec.whatwg.org/multipage/interaction.html#drag-and-drop-processing-model\n */\n private _dragOperationEnded(state:DragOperationState):boolean {\n\n console.log(\"dnd-poly: drag operation end detected with \" + this._currentDragOperation);\n\n if (DEBUG) {\n\n var debug_class_user_selection = CLASS_PREFIX + \"immediate-user-selection\",\n debug_class_drop_target = CLASS_PREFIX + \"current-drop-target\";\n\n if (this._currentDropTarget) {\n this._currentDropTarget.classList.remove(debug_class_drop_target);\n\n }\n if (this._immediateUserSelection) {\n this._immediateUserSelection.classList.remove(debug_class_user_selection);\n }\n }\n\n //var dropped:boolean = undefined;\n\n // Run the following steps, then stop the drag-and-drop operation:\n\n // If the current drag operation is \"none\" (no drag operation), or,\n // if the user ended the drag-and-drop operation by canceling it (e.g. by hitting the Escape key), or\n // if the current target element is null, then the drag operation failed.\n const dragFailed = (this._currentDragOperation === DROP_EFFECTS[DROP_EFFECT.NONE]\n || this._currentDropTarget === null\n || state === DragOperationState.CANCELLED);\n if (dragFailed) {\n\n // Run these substeps:\n\n // Let dropped be false.\n //dropped = false;\n\n // If the current target element is a DOM element, fire a DND event named dragleave at it;\n if (isDOMElement(this._currentDropTarget)) {\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n dispatchDragEvent(\"dragleave\", this._currentDropTarget, this._lastTouchEvent, this._dragDataStore, this._dataTransfer, false);\n }\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // otherwise, if it is not null, use platform-specific conventions for drag cancellation.\n //else if( this.currentDropTarget !== null ) {\n //}\n }\n // Otherwise, the drag operation was as success; run these substeps:\n else {\n\n // Let dropped be true.\n //dropped = true;\n\n // If the current target element is a DOM element, fire a DND event named drop at it;\n if (isDOMElement(this._currentDropTarget)) {\n\n // If the event is canceled, set the current drag operation to the value of the dropEffect attribute of the\n // DragEvent object's dataTransfer object as it stood after the event dispatch finished.\n\n this._dragDataStore._mode = DragDataStoreMode.READONLY;\n this._dataTransfer.dropEffect = this._currentDragOperation;\n if (dispatchDragEvent(\"drop\", this._currentDropTarget, this._lastTouchEvent, this._dragDataStore, this._dataTransfer) ===\n true) {\n\n this._currentDragOperation = this._dataTransfer.dropEffect;\n }\n // Otherwise, the event is not canceled; perform the event's default action, which depends on the exact target as follows:\n else {\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the current target element is a text field (e.g. textarea, or an input element whose type attribute is in the Text state)\n // or an editable element,\n // and the drag data store item list has an item with the drag data item type string \"text/plain\"\n // and the drag data item kind Plain Unicode string\n //if( ElementIsTextDropzone( this.currentDropTarget, this.dragDataStore ) ) {\n // Insert the actual data of the first item in the drag data store item list to have a drag data item type string of\n // \"text/plain\" and a drag data item kind that is Plain Unicode string into the text field or editable element in a manner\n // consistent with platform-specific conventions (e.g. inserting it at the current mouse cursor position, or inserting it at\n // the end of the field).\n //}\n // Otherwise\n //else {\n // Reset the current drag operation to \"none\".\n this._currentDragOperation = DROP_EFFECTS[DROP_EFFECT.NONE];\n //}\n }\n }\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // otherwise, use platform-specific conventions for indicating a drop.\n //else {\n //}\n }\n\n return dragFailed;\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n //if( this.dragend( this.sourceNode ) ) {\n // return;\n //}\n\n // Run the appropriate steps from the following list as the default action of the dragend event:\n\n //if( !dropped ) {\n // return;\n //}\n // dropped is true\n\n //if( this.currentDragOperation !== \"move\" ) {\n // return;\n //}\n //// drag operation is move\n //\n //if( ElementIsTextDropzone( this.currentDropTarget ) === false ) {\n // return;\n //}\n //// element is textfield\n //\n //// and the source of the drag-and-drop operation is a selection in the DOM\n //if( this.sourceNode.nodeType === 1 ) {\n // // The user agent should delete the range representing the dragged selection from the DOM.\n //}\n //// and the source of the drag-and-drop operation is a selection in a text field\n //else if( this.sourceNode.nodeType === 3 ) {\n // // The user agent should delete the dragged selection from the relevant text field.\n //}\n //// Otherwise, The event has no default action.\n }\n\n // dispatch dragend event and cleanup drag operation\n private _finishDragOperation():void {\n console.log(\"dnd-poly: dragimage snap back transition ended\");\n\n // Fire a DND event named dragend at the source node.\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = this._currentDragOperation;\n dispatchDragEvent(\"dragend\", this._sourceNode, this._lastTouchEvent, this._dragDataStore, this._dataTransfer, false);\n\n // drag operation over and out\n this._dragOperationState = DragOperationState.ENDED;\n this._cleanup();\n }\n\n //\n}\n\n//\n\n//\n\n/**\n * Polyfills https://html.spec.whatwg.org/multipage/interaction.html#drag-data-store-mode\n */\nconst enum DragDataStoreMode {\n _DISCONNECTED, // adding an extra mode here because we need a special state to disconnect the data store from dataTransfer instance\n READONLY,\n READWRITE,\n PROTECTED\n}\n\n/**\n * Polyfills https://html.spec.whatwg.org/multipage/interaction.html#the-drag-data-store\n */\ninterface DragDataStore {\n _mode:DragDataStoreMode;\n _data:{ [type:string]:any };\n _types:Array;\n _effectAllowed:string;\n}\n\n/**\n * Polyfills https://html.spec.whatwg.org/multipage/interaction.html#datatransfer\n * TODO fail with errors when somebody uses it wrong so they know they are doing it wrong?\n */\nclass DataTransfer {\n\n private _dropEffect:string = DROP_EFFECTS[DROP_EFFECT.NONE];\n\n constructor(private _dataStore:DragDataStore,\n private _setDragImageHandler:(image:Element, x:number, y:number) => void) {\n }\n\n //public get files():FileList {\n // return undefined;\n //}\n //\n //public get items():DataTransferItemList {\n // return undefined;\n //}\n\n public get types():ReadonlyArray {\n if (this._dataStore._mode !== DragDataStoreMode._DISCONNECTED) {\n return Object.freeze(this._dataStore._types);\n }\n }\n\n public setData(type:string, data:string):void {\n if (this._dataStore._mode === DragDataStoreMode.READWRITE) {\n\n if (type.indexOf(\" \") > -1) {\n throw new Error(\"illegal arg: type contains space\");\n }\n\n this._dataStore._data[type] = data;\n\n if (this._dataStore._types.indexOf(type) === -1) {\n this._dataStore._types.push(type);\n }\n }\n }\n\n public getData(type:string):string {\n if (this._dataStore._mode === DragDataStoreMode.READONLY\n || this._dataStore._mode === DragDataStoreMode.READWRITE) {\n return this._dataStore._data[type] || \"\";\n }\n }\n\n public clearData(format?:string):void {\n if (this._dataStore._mode === DragDataStoreMode.READWRITE) {\n // delete data for format\n if (format && this._dataStore._data[format]) {\n delete this._dataStore._data[format];\n var index = this._dataStore._types.indexOf(format);\n if (index > -1) {\n this._dataStore._types.splice(index, 1);\n }\n return;\n }\n // delete all data\n this._dataStore._data = {};\n this._dataStore._types = [];\n }\n }\n\n public setDragImage(image:Element, x:number, y:number):void {\n if (this._dataStore._mode === DragDataStoreMode.READWRITE) {\n this._setDragImageHandler(image, x, y);\n }\n }\n\n public get effectAllowed() {\n return this._dataStore._effectAllowed;\n }\n\n public set effectAllowed(value) {\n if (this._dataStore._mode === DragDataStoreMode.READWRITE\n && ALLOWED_EFFECTS.indexOf(value) > -1) {\n this._dataStore._effectAllowed = value;\n }\n }\n\n public get dropEffect() {\n return this._dropEffect;\n }\n\n public set dropEffect(value) {\n if (this._dataStore._mode !== DragDataStoreMode._DISCONNECTED\n && ALLOWED_EFFECTS.indexOf(value) > -1) {\n this._dropEffect = value;\n }\n }\n}\n\n//\n\n//\n\nexport interface Point {\n x:number;\n y:number;\n}\n\nfunction addDocumentListener(ev:string, handler:EventListener, passive:boolean = true) {\n\n (document as EventTarget).addEventListener(ev, handler, supportsPassive ? {passive: passive} : false);\n}\n\nfunction removeDocumentListener(ev:string, handler:EventListener) {\n document.removeEventListener(ev, handler);\n}\n\nfunction average(array:Array) {\n if (array.length === 0) {\n return 0;\n }\n return array.reduce((function (s, v) {\n return v + s;\n }), 0) / array.length;\n}\n\nfunction isDOMElement(object:any) {\n return object && object.tagName;\n}\n\nfunction isTouchIdentifierContainedInTouchEvent(newTouch:TouchEvent, touchIdentifier:number) {\n for (let i = 0; i < newTouch.changedTouches.length; i++) {\n const touch = newTouch.changedTouches[i];\n if (touch.identifier === touchIdentifier) {\n return true;\n }\n }\n return false;\n}\n\nfunction createDragEventFromTouch(targetElement:Element,\n e:TouchEvent,\n type:string,\n cancelable:boolean,\n window:Window,\n dataTransfer:DataTransfer,\n relatedTarget:Element = null) {\n\n const touch:Touch = e.changedTouches[0];\n\n const dndEvent:DragEvent = new Event(type, {\n bubbles: true,\n cancelable: cancelable\n });\n\n // cast our polyfill\n (dndEvent as any).dataTransfer = dataTransfer;\n (dndEvent as any).relatedTarget = relatedTarget;\n\n // set the coordinates\n (dndEvent as any).screenX = touch.screenX;\n (dndEvent as any).screenY = touch.screenY;\n (dndEvent as any).clientX = touch.clientX;\n (dndEvent as any).clientY = touch.clientY;\n (dndEvent as any).pageX = touch.pageX;\n (dndEvent as any).pageY = touch.pageY;\n\n const targetRect = targetElement.getBoundingClientRect();\n (dndEvent as any).offsetX = dndEvent.clientX - targetRect.left;\n (dndEvent as any).offsetY = dndEvent.clientY - targetRect.top;\n\n return dndEvent;\n}\n\n/**\n * Calc center of polygon spanned by multiple touches in page (full page size, with hidden scrollable area) coordinates\n * or in viewport (screen coordinates) coordinates.\n */\nfunction updateCentroidCoordinatesOfTouchesIn(coordinateProp:string, event:TouchEvent, outPoint:Point):void {\n const pageXs:Array = [], pageYs:Array = [];\n for (let i = 0; i < event.touches.length; i++) {\n const touch = event.touches[i];\n pageXs.push(touch[coordinateProp + \"X\"]);\n pageYs.push(touch[coordinateProp + \"Y\"]);\n }\n outPoint.x = average(pageXs);\n outPoint.y = average(pageYs);\n}\n\nfunction prepareNodeCopyAsDragImage(srcNode:HTMLElement, dstNode:HTMLElement) {\n // Is this node an element?\n if (srcNode.nodeType === 1) {\n\n // Clone the style\n const cs = getComputedStyle(srcNode);\n for (let i = 0; i < cs.length; i++) {\n const csName = cs[i];\n dstNode.style.setProperty(csName, cs.getPropertyValue(csName), cs.getPropertyPriority(csName));\n }\n\n // no interaction with the drag image, pls! this is also important to make the drag image transparent for hit-testing\n // hit testing is done in the drag and drop iteration to find the element the user currently is hovering over while dragging.\n // if pointer-events is not none or a browser does behave in an unexpected way than the hit test transparency on the drag image\n // will break\n dstNode.style.pointerEvents = \"none\";\n\n // Remove any potential conflict attributes\n dstNode.removeAttribute(\"id\");\n dstNode.removeAttribute(\"class\");\n dstNode.removeAttribute(\"draggable\");\n }\n\n // Do the same for the children\n if (srcNode.hasChildNodes()) {\n for (let i = 0; i < srcNode.childNodes.length; i++) {\n prepareNodeCopyAsDragImage(srcNode.childNodes[i], dstNode.childNodes[i]);\n }\n }\n}\n\nfunction createDragImage(sourceNode:HTMLElement):HTMLElement {\n\n const dragImage = sourceNode.cloneNode(true);\n\n // this removes any id's and stuff that could interfere with drag and drop\n prepareNodeCopyAsDragImage(sourceNode, dragImage);\n\n // set layout styles for freely moving it around\n dragImage.style.position = \"absolute\";\n dragImage.style.left = \"0px\";\n dragImage.style.top = \"0px\";\n // on top of all\n dragImage.style.zIndex = \"999999\";\n\n // add polyfill class for default styling\n dragImage.classList.add(CLASS_DRAG_IMAGE);\n dragImage.classList.add(CLASS_DRAG_OPERATION_ICON);\n\n return dragImage;\n}\n\nfunction extractTransformStyles(sourceNode:HTMLElement):string[] {\n\n return TRANSFORM_CSS_VENDOR_PREFIXES.map(function (prefix) {\n\n let transform = sourceNode.style[prefix + \"transform\"];\n\n if (!transform || transform === \"none\") {\n return \"\";\n }\n\n // TODO what about translateX(x), translateY(x), translateZ(z), translate3d(x,y,z), matrix(*,*,*,*,x,y) ?\n\n // removes translate(x,y)\n return transform.replace(/translate\\(\\D*\\d+[^,]*,\\D*\\d+[^,]*\\)\\s*/g, \"\");\n });\n}\n\nfunction translateDragImage(dragImage:HTMLElement, pnt:Point, originalTransforms:string[], offset?:Point, centerOnCoordinates = true):void {\n\n let x = pnt.x, y = pnt.y;\n\n if (offset) {\n x += offset.x;\n y += offset.y;\n }\n\n if (centerOnCoordinates) {\n x -= (parseInt(dragImage.offsetWidth, 10) / 2);\n y -= (parseInt(dragImage.offsetHeight, 10) / 2);\n }\n\n // using translate3d for best performance\n const translate = \"translate3d(\" + x + \"px,\" + y + \"px, 0)\";\n\n for (let i = 0; i < TRANSFORM_CSS_VENDOR_PREFIXES.length; i++) {\n const transformProp = TRANSFORM_CSS_VENDOR_PREFIXES[i] + \"transform\";\n dragImage.style[transformProp] = translate + \" \" + originalTransforms[i];\n }\n}\n\n/**\n * calculates the coordinates of the drag source and transitions the drag image to those coordinates.\n * the drag operation is finished after the transition has ended.\n */\nfunction applyDragImageSnapback(sourceEl:HTMLElement, dragImage:HTMLElement, dragImageTransforms:string[], transitionEndCb:Function):void {\n\n const cs = getComputedStyle(sourceEl);\n\n if (cs.visibility === \"hidden\" || cs.display === \"none\") {\n console.log(\"dnd-poly: source node is not visible. skipping snapback transition.\");\n // shortcut to end the drag operation\n transitionEndCb();\n return;\n }\n // add class containing transition rules\n dragImage.classList.add(CLASS_DRAG_IMAGE_SNAPBACK);\n\n const csDragImage = getComputedStyle(dragImage);\n const durationInS = parseFloat(csDragImage.transitionDuration);\n if (isNaN(durationInS) || durationInS === 0) {\n console.log(\"dnd-poly: no transition used - skipping snapback\");\n transitionEndCb();\n return;\n }\n\n console.log(\"dnd-poly: starting dragimage snap back\");\n\n // calc source node position\n const rect = sourceEl.getBoundingClientRect();\n\n const pnt:Point = {\n x: rect.left,\n y: rect.top\n };\n\n // add scroll offset of document\n pnt.x += (document.body.scrollLeft || document.documentElement.scrollLeft);\n pnt.y += (document.body.scrollTop || document.documentElement.scrollTop);\n\n //TODO this sometimes fails.. find out when exactly and how to detect\n pnt.x -= parseInt(cs.marginLeft, 10);\n pnt.y -= parseInt(cs.marginTop, 10);\n\n const delayInS = parseFloat(csDragImage.transitionDelay);\n const durationInMs = Math.round((durationInS + delayInS) * 1000);\n\n // apply the translate\n translateDragImage(dragImage, pnt, dragImageTransforms, undefined, false);\n\n setTimeout(transitionEndCb, durationInMs);\n}\n\n//\n\n//\n\n/**\n * Implements \"6.\" in the processing steps defined for a dnd event\n * https://html.spec.whatwg.org/multipage/interaction.html#dragevent\n */\nfunction determineDropEffect(effectAllowed:string, sourceNode:Element) {\n\n // uninitialized\n if (!effectAllowed) {\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n //if( sourceNode.nodeType === 1 ) {\n //\n //return \"move\";\n //}\n\n // link\n if (sourceNode.nodeType === 3 && (sourceNode).tagName === \"A\") {\n return DROP_EFFECTS[DROP_EFFECT.LINK];\n }\n\n // copy\n return DROP_EFFECTS[DROP_EFFECT.COPY];\n }\n\n // none\n if (effectAllowed === ALLOWED_EFFECTS[EFFECT_ALLOWED.NONE]) {\n return DROP_EFFECTS[DROP_EFFECT.NONE];\n }\n // copy or all\n if (effectAllowed.indexOf(ALLOWED_EFFECTS[EFFECT_ALLOWED.COPY]) === 0 || effectAllowed === ALLOWED_EFFECTS[EFFECT_ALLOWED.ALL]) {\n return DROP_EFFECTS[DROP_EFFECT.COPY];\n }\n // link\n if (effectAllowed.indexOf(ALLOWED_EFFECTS[EFFECT_ALLOWED.LINK]) === 0) {\n return DROP_EFFECTS[DROP_EFFECT.LINK];\n }\n // move\n if (effectAllowed === ALLOWED_EFFECTS[EFFECT_ALLOWED.MOVE]) {\n return DROP_EFFECTS[DROP_EFFECT.MOVE];\n }\n\n // copy\n return DROP_EFFECTS[DROP_EFFECT.COPY];\n}\n\n/**\n * Reference https://html.spec.whatwg.org/multipage/interaction.html#dndevents\n */\nfunction dispatchDragEvent(dragEvent:string,\n targetElement:Element,\n touchEvent:TouchEvent,\n dataStore:DragDataStore,\n dataTransfer:DataTransfer,\n cancelable = true,\n relatedTarget:Element = null):boolean {\n\n console.log(\"dnd-poly: dispatching \" + dragEvent);\n\n if (DEBUG) {\n var debug_class = CLASS_PREFIX + \"debug\",\n debug_class_event_target = CLASS_PREFIX + \"event-target\",\n debug_class_event_related_target = CLASS_PREFIX + \"event-related-target\";\n targetElement.classList.add(debug_class);\n targetElement.classList.add(debug_class_event_target);\n if (relatedTarget) {\n relatedTarget.classList.add(debug_class);\n relatedTarget.classList.add(debug_class_event_related_target);\n }\n }\n\n const leaveEvt = createDragEventFromTouch(targetElement, touchEvent, dragEvent, cancelable, document.defaultView, dataTransfer, relatedTarget);\n const cancelled = !targetElement.dispatchEvent(leaveEvt);\n\n dataStore._mode = DragDataStoreMode._DISCONNECTED;\n\n if (DEBUG) {\n targetElement.classList.remove(debug_class_event_target);\n if (relatedTarget) {\n relatedTarget.classList.remove(debug_class_event_related_target);\n }\n }\n\n return cancelled;\n}\n\n/**\n * according to https://html.spec.whatwg.org/multipage/interaction.html#drag-and-drop-processing-model\n */\nfunction determineDragOperation(effectAllowed:string, dropEffect:string):string {\n\n // unitialized or all\n if (!effectAllowed || effectAllowed === ALLOWED_EFFECTS[7]) {\n return dropEffect;\n }\n\n if (dropEffect === DROP_EFFECTS[DROP_EFFECT.COPY]) {\n if (effectAllowed.indexOf(DROP_EFFECTS[DROP_EFFECT.COPY]) === 0) {\n return DROP_EFFECTS[DROP_EFFECT.COPY];\n }\n }\n else if (dropEffect === DROP_EFFECTS[DROP_EFFECT.LINK]) {\n if (effectAllowed.indexOf(DROP_EFFECTS[DROP_EFFECT.LINK]) === 0 || effectAllowed.indexOf(\"Link\") > -1) {\n return DROP_EFFECTS[DROP_EFFECT.LINK];\n }\n }\n else if (dropEffect === DROP_EFFECTS[DROP_EFFECT.MOVE]) {\n if (effectAllowed.indexOf(DROP_EFFECTS[DROP_EFFECT.MOVE]) === 0 || effectAllowed.indexOf(\"Move\") > -1) {\n return DROP_EFFECTS[DROP_EFFECT.MOVE];\n }\n }\n\n return DROP_EFFECTS[DROP_EFFECT.NONE];\n}\n\n//\n\n//\n\n/**\n * // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n */\n//public static ElementIsTextDropzone( element:HTMLElement, dragDataStore?:DragDataStore ) {\n//\n// if( dragDataStore && !dragDataStore.data[ \"text/plain\" ] ) {\n// return false;\n// }\n//\n// if( element.isContentEditable ) {\n// return true;\n// }\n//\n// if( element.tagName === \"TEXTAREA\" ) {\n// return true;\n// }\n//\n// if( element.tagName === \"INPUT\" ) {\n// if( element.getAttribute( \"type\" ) === \"text\" ) {\n// return true;\n// }\n// }\n//\n// return false;\n//}\n\n/**\n * NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n *\n * Helper method for recursively go from a nested element up the ancestor chain\n * to see if any element has a dropzone.\n */\n//private static FindDropzoneElement( element:HTMLElement ):HTMLElement {\n//\n// if( !element || !element.hasAttribute || typeof element.hasAttribute !== \"function\" ) {\n// return null;\n// }\n//\n// if( element.hasAttribute( \"dropzone\" ) ) {\n// return element;\n// }\n//\n// if( element === window.document.body ) {\n// return null;\n// }\n//\n// return DragOperationController.FindDropzoneElement( element.parentElement );\n//}\n\n/**\n * NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n *\n * Polyfills https://html.spec.whatwg.org/multipage/interaction.html#the-dropzone-attribute\n * by implementing the dropzone processing steps.\n */\n//private static GetOperationForMatchingDropzone( element:HTMLElement, dragDataStore:DragDataStore ):string {\n\n// If the current target element is an element with a dropzone attribute that matches the drag data store and specifies an operation\n// Set the current drag operation to the operation specified by the dropzone attribute of the current target element.\n// If the current target element is an element with a dropzone attribute that matches the drag data store and does not specify an operation\n// Set the current drag operation to \"copy\".\n// Otherwise\n// Reset the current drag operation to \"none\".\n//var value = element.getAttribute( \"dropzone\" );\n//if( !value ) {\n//\n// return \"none\";\n//}\n//\n//var matched = false;\n//var operation;\n//var keywords = value.split( \" \" );\n//\n//for( var i:number = 0; i < keywords.length; i++ ) {\n// var keyword = keywords[ i ];\n//\n// if( keyword === \"copy\" || keyword === \"move\" || keyword === \"link\" ) {\n// if( !operation ) {\n// operation = keyword;\n// }\n// continue;\n// }\n//\n// if( keyword.length < 3 || keyword[ 1 ] !== \":\" ) {\n// continue;\n// }\n//\n// var splitKeyword = keyword.split( \":\" );\n// var kind = splitKeyword[ 0 ].toLowerCase();\n// var type = splitKeyword[ 1 ].toLowerCase();\n//\n// if( dragDataStore.types.indexOf( type ) > -1 ) {\n// matched = true;\n// }\n//}\n//\n//if( !matched ) {\n// return \"none\";\n//}\n//\n//if( !operation ) {\n// return \"copy\";\n//}\n//\n//return operation;\n//}\n\n//\n"]} \ No newline at end of file +{"version":3,"sources":["/Users/stefansteinhart/Development/Web/ios-html5-drag-drop-shim/src/index.ts"],"names":["detectFeatures","features","dragEvents","document","documentElement","draggable","touchEvents","userAgentSupportingNativeDnD","undefined","isBlinkEngine","window","test","navigator","userAgent","DEBUG","Object","keys","forEach","key","supportsPassiveEventListener","supportsPassiveEventListeners","opts","defineProperty","get","addEventListener","e","polyfill","override","config","forceApply","detectedFeatures","supportsPassive","holdToDrag","addDocumentListener","onDelayTouchstart","onTouchstart","activeDragOperation","dragTarget","tryFindDraggableTarget","DragOperationController","dragOperationEnded","err","event","el","target","getAttribute","parentNode","body","_config","state","defaultActionOverride","defaultPrevented","ev","handler","passive","removeDocumentListener","removeEventListener","average","array","length","reduce","s","v","isDOMElement","object","tagName","isTouchIdentifierContainedInTouchEvent","newTouch","touchIdentifier","i","changedTouches","touch","identifier","createDragEventFromTouch","targetElement","type","cancelable","dataTransfer","relatedTarget","dndEvent","Event","bubbles","screenX","screenY","clientX","clientY","pageX","pageY","targetRect","getBoundingClientRect","offsetX","left","offsetY","top","updateCentroidCoordinatesOfTouchesIn","coordinateProp","outPoint","pageXs","pageYs","touches","push","x","y","prepareNodeCopyAsDragImage","srcNode","dstNode","nodeType","cs","getComputedStyle","csName","style","setProperty","getPropertyValue","getPropertyPriority","pointerEvents","removeAttribute","hasChildNodes","childNodes","createDragImage","sourceNode","dragImage","cloneNode","position","zIndex","classList","add","CLASS_DRAG_IMAGE","CLASS_DRAG_OPERATION_ICON","extractTransformStyles","TRANSFORM_CSS_VENDOR_PREFIXES","map","prefix","transform","replace","translateDragImage","pnt","originalTransforms","offset","centerOnCoordinates","parseInt","offsetWidth","offsetHeight","translate","transformProp","applyDragImageSnapback","sourceEl","dragImageTransforms","transitionEndCb","visibility","display","CLASS_DRAG_IMAGE_SNAPBACK","csDragImage","durationInS","parseFloat","transitionDuration","isNaN","rect","scrollLeft","scrollTop","marginLeft","marginTop","delayInS","transitionDelay","durationInMs","Math","round","setTimeout","determineDropEffect","effectAllowed","ALLOWED_EFFECTS","DROP_EFFECTS","indexOf","dispatchDragEvent","dragEvent","touchEvent","dataStore","debug_class","CLASS_PREFIX","debug_class_event_target","debug_class_event_related_target","leaveEvt","defaultView","cancelled","dispatchEvent","_mode","remove","determineDragOperation","dropEffect","evt","heldItem","end","off","cancel","scroll","onReleasedItem","clearTimeout","timer","onEvt","this","context","bind","iterationInterval","_initialEvent","_sourceNode","_dragOperationEndedCb","_dragOperationState","_immediateUserSelection","_currentDropTarget","_lastTouchEvent","_initialTouch","_touchMoveHandler","_onTouchMove","_touchEndOrCancelHandler","_onTouchEndOrCancel","prototype","_setup","_this","_currentDragOperation","_dragDataStore","D","F","g","G","_currentHotspotCoordinates","_dragImagePageCoordinates","dragImageSrc","_dataTransfer","DataTransfer","element","_dragImageOffset","_cleanup","_dragImage","_dragImageTransforms","dragImageOffset","dragImageCenterOnTouch","width","height","appendChild","_iterationIntervalId","setInterval","_iterationLock","_dragAndDropProcessModelIteration","clearInterval","removeChild","startDrag","dragStartConditionOverride","preventDefault","dragImageTranslateOverride","handledDragImageTranslate_1","debug_class_user_selection","debug_class_drop_target","previousDragOperation","dragCancelled","dragFailed","_dragOperationEnded","_finishDragOperation","newUserSelection","elementFromPoint","previousTargetElement","_effectAllowed","currentDragOperationClass","contains","_dataStore","_setDragImageHandler","_dropEffect","freeze","_types","setData","data","Error","_data","getData","clearData","format","index","splice","setDragImage","image","value"],"mappings":"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","file":"index.min.js","sourcesContent":["// debug mode, which will highlight drop target, immediate user selection and events fired as you interact.\nconst DEBUG = false;\n\n//\n\ninterface DetectedFeatures {\n draggable:boolean;\n dragEvents:boolean;\n touchEvents:boolean;\n userAgentSupportingNativeDnD:boolean;\n}\n\nfunction detectFeatures():DetectedFeatures {\n\n let features:DetectedFeatures = {\n dragEvents: (\"ondragstart\" in document.documentElement),\n draggable: (\"draggable\" in document.documentElement),\n touchEvents: (\"ontouchstart\" in document.documentElement),\n userAgentSupportingNativeDnD: undefined\n };\n\n const isBlinkEngine = !!((window).chrome) || /chrome/i.test(navigator.userAgent);\n\n features.userAgentSupportingNativeDnD = !(\n // if is mobile safari or android browser -> no native dnd\n (/iPad|iPhone|iPod|Android/.test(navigator.userAgent))\n || // OR\n //if is blink(chrome/opera) with touch events enabled -> no native dnd\n (isBlinkEngine && features.touchEvents)\n );\n\n if (DEBUG) {\n Object.keys(features).forEach(function (key) {\n console.log(\"dnd-poly: detected feature '\" + key + \" = \" + features[key] + \"'\");\n });\n }\n\n return features;\n}\n\nlet supportsPassive:boolean;\n\nfunction supportsPassiveEventListener():boolean {\n\n let supportsPassiveEventListeners = false;\n\n // reference https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md\n try {\n let opts = Object.defineProperty({}, \"passive\", {\n get: function () {\n supportsPassiveEventListeners = true;\n }\n });\n window.addEventListener(\"test\", null, opts);\n }\n // tslint:disable-next-line:no-empty\n catch (e) {\n }\n\n return supportsPassiveEventListeners;\n}\n\n//\n\n//\n\n// function signature for the dragImageTranslateOverride hook\nexport type DragImageTranslateOverrideFn = (// corresponding touchmove event\n event:TouchEvent,\n // the processed touch event viewport coordinates\n hoverCoordinates:Point,\n // the element under the calculated touch coordinates\n hoveredElement:HTMLElement,\n // callback for updating the drag image offset\n translateDragImageFn:(offsetX:number, offsetY:number) => void) => void;\n\nexport interface Config {\n // flag to force the polyfill being applied and not rely on internal feature detection\n forceApply?:boolean;\n // useful for when you want the default drag image but still want to apply\n // some static offset from touch coordinates to drag image coordinates\n // defaults to (0,0)\n dragImageOffset?:Point;\n // if the dragImage shall be centered on the touch coordinates\n // defaults to false\n dragImageCenterOnTouch?:boolean;\n // the drag and drop operation involves some processing. here you can specify in what interval this processing takes place.\n // defaults to 150ms\n iterationInterval?:number;\n // hook for custom logic that decides if a drag operation should start\n dragStartConditionOverride?:(event:TouchEvent) => boolean;\n // hook for custom logic that can manipulate the drag image translate offset\n dragImageTranslateOverride?:DragImageTranslateOverrideFn;\n // hook for custom logic that can override the default action based on the original touch event when the drag never started\n // be sure to call event.preventDefault() if handling the default action in the override to prevent the browser default.\n defaultActionOverride?: (event: TouchEvent) => void;\n // Drag action delay on touch devices (\"hold to drag\" functionality, useful for scrolling draggable items). Defaults to no delay.\n holdToDrag?: number;\n}\n\n// default config\nconst config:Config = {\n iterationInterval: 150,\n};\n\nexport function polyfill(override?:Config):boolean {\n\n if (override) {\n // overwrite default config with user config\n Object.keys(override).forEach(function (key) {\n config[key] = override[key];\n });\n }\n\n // only do feature detection when config does not force apply the polyfill\n if (!config.forceApply) {\n\n // feature/browser detection\n const detectedFeatures = detectFeatures();\n\n // check if native drag and drop support is there\n if (detectedFeatures.userAgentSupportingNativeDnD\n && detectedFeatures.draggable\n && detectedFeatures.dragEvents) {\n // no polyfilling required\n return false;\n }\n }\n\n console.log(\"dnd-poly: Applying mobile drag and drop polyfill.\");\n\n supportsPassive = supportsPassiveEventListener();\n\n // add listeners suitable for detecting a potential drag operation\n if (config.holdToDrag) {\n addDocumentListener(\"touchstart\", onDelayTouchstart, false);\n } else {\n addDocumentListener(\"touchstart\", onTouchstart, false);\n }\n\n return true;\n}\n\n//\n\n//\n\n// reference the currently active drag operation\nlet activeDragOperation:DragOperationController;\n\n/**\n * event handler listening for initial events that possibly start a drag and drop operation.\n */\nfunction onTouchstart(e:TouchEvent) {\n\n console.log(\"dnd-poly: global touchstart\");\n\n // From the moment that the user agent is to initiate the drag-and-drop operation,\n // until the end of the drag-and-drop operation, device input events (e.g. mouse and keyboard events) must be suppressed.\n\n // only allow one drag operation at a time\n if (activeDragOperation) {\n console.log(\"dnd-poly: drag operation already active\");\n return;\n }\n\n let dragTarget = tryFindDraggableTarget(e);\n\n // If there is no such element, then nothing is being dragged; abort these\n // steps, the drag-and-drop operation is never started.\n if (!dragTarget) {\n return;\n }\n\n try {\n activeDragOperation = new DragOperationController(e, config, dragTarget, dragOperationEnded);\n }\n catch (err) {\n dragOperationEnded(config, e, DragOperationState.CANCELLED);\n // rethrow exception after cleanup\n throw err;\n }\n}\n\n/**\n * Search for a possible draggable item upon an event that can initialize a drag operation.\n */\nfunction tryFindDraggableTarget(event:TouchEvent):Element {\n\n //1. Determine what is being dragged, as follows:\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the drag operation was invoked on a selection, then it is the selection that is being dragged.\n //if( (event.target).nodeType === 3 ) {\n //\n // config.log( \"drag on text\" );\n // return event.target;\n //}\n //Otherwise, if the drag operation was invoked on a Document, it is the first element, going up the ancestor chain, starting at the node that the\n // user tried to drag, that has the IDL attribute draggable set to true.\n //else {\n\n let el = event.target;\n\n do {\n if (el.draggable === false) {\n continue;\n }\n if (el.getAttribute && el.getAttribute(\"draggable\") === \"true\") {\n return el;\n }\n } while ((el = el.parentNode) && el !== document.body);\n}\n\n/**\n * Implements callback invoked when a drag operation has ended or crashed.\n */\nfunction dragOperationEnded(_config:Config, event:TouchEvent, state:DragOperationState) {\n\n // we need to make the default action happen only when no drag operation took place\n if (state === DragOperationState.POTENTIAL) {\n\n console.log(\"dnd-poly: Drag never started. Last event was \" + event.type);\n\n // when lifecycle hook is present\n if (_config.defaultActionOverride) {\n\n try {\n\n _config.defaultActionOverride(event);\n\n if (event.defaultPrevented) {\n\n console.log(\"dnd-poly: defaultActionOverride has taken care of triggering the default action. preventing default on original event\");\n }\n\n }\n catch (e) {\n\n console.log(\"dnd-poly: error in defaultActionOverride: \" + e);\n }\n }\n }\n\n // reset drag operation container\n activeDragOperation = null;\n}\n\n//\n\n//\n\n/**\n * For tracking the different states of a drag operation.\n */\nconst enum DragOperationState {\n // initial state of a controller, if no movement is detected the operation ends with this state\n POTENTIAL,\n // after movement is detected the drag operation starts and keeps this state until it ends\n STARTED,\n // when the drag operation ended normally\n ENDED,\n // when the drag operation ended with a cancelled input event\n CANCELLED\n}\n\n// contains all possible values of the effectAllowed property\nconst enum EFFECT_ALLOWED {\n NONE = 0,\n COPY = 1,\n COPY_LINK = 2,\n COPY_MOVE = 3,\n LINK = 4,\n LINK_MOVE = 5,\n MOVE = 6,\n ALL = 7\n}\n\nconst ALLOWED_EFFECTS = [\"none\", \"copy\", \"copyLink\", \"copyMove\", \"link\", \"linkMove\", \"move\", \"all\"];\n\n// contains all possible values of the dropEffect property\nconst enum DROP_EFFECT {\n NONE = 0,\n COPY = 1,\n MOVE = 2,\n LINK = 3,\n}\n\nconst DROP_EFFECTS = [\"none\", \"copy\", \"move\", \"link\"];\n\n// cross-browser css transform property prefixes\nconst TRANSFORM_CSS_VENDOR_PREFIXES = [\"\", \"-webkit-\"];\n// css classes\nconst CLASS_PREFIX = \"dnd-poly-\";\nconst CLASS_DRAG_IMAGE = CLASS_PREFIX + \"drag-image\";\nconst CLASS_DRAG_IMAGE_SNAPBACK = CLASS_PREFIX + \"snapback\";\nconst CLASS_DRAG_OPERATION_ICON = CLASS_PREFIX + \"icon\";\n\n/**\n * Aims to implement the HTML5 d'n'd spec (https://html.spec.whatwg.org/multipage/interaction.html#dnd) as close as it can get.\n * Note that all props that are private should start with an underscore to enable better minification.\n *\n * TODO remove lengthy spec comments in favor of short references to the spec\n */\nclass DragOperationController {\n\n private _dragOperationState:DragOperationState = DragOperationState.POTENTIAL;\n\n private _dragImage:HTMLElement;\n private _dragImageTransforms:string[];\n private _dragImagePageCoordinates:Point; // the current page coordinates of the dragImage\n private _dragImageOffset:Point; // offset of the drag image relative to the coordinates\n\n private _currentHotspotCoordinates:Point; // the point relative to viewport for determining the immediate user selection\n\n private _immediateUserSelection:HTMLElement = null; // the element the user currently hovers while dragging\n private _currentDropTarget:HTMLElement = null; // the element that was selected as a valid drop target by the d'n'd operation\n\n private _dragDataStore:DragDataStore;\n private _dataTransfer:DataTransfer;\n\n private _currentDragOperation:string; // the current drag operation set according to the d'n'd processing model\n\n private _initialTouch:Touch; // the identifier for the touch that initiated the drag operation\n private _touchMoveHandler:EventListener;\n private _touchEndOrCancelHandler:EventListener;\n private _lastTouchEvent:TouchEvent;\n\n private _iterationLock:boolean;\n private _iterationIntervalId:number;\n\n constructor(private _initialEvent:TouchEvent,\n private _config:Config,\n private _sourceNode:HTMLElement,\n private _dragOperationEndedCb:(config:Config, event:TouchEvent, state:DragOperationState) => void) {\n\n console.log(\"dnd-poly: setting up potential drag operation..\");\n\n this._lastTouchEvent = _initialEvent;\n this._initialTouch = _initialEvent.changedTouches[0];\n\n // create bound event listeners\n this._touchMoveHandler = this._onTouchMove.bind(this);\n this._touchEndOrCancelHandler = this._onTouchEndOrCancel.bind(this);\n addDocumentListener(\"touchmove\", this._touchMoveHandler, false);\n addDocumentListener(\"touchend\", this._touchEndOrCancelHandler, false);\n addDocumentListener(\"touchcancel\", this._touchEndOrCancelHandler, false);\n\n // the only thing we do is setup the touch listeners. if drag will really start is decided in touch move handler.\n\n //\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // 3. Establish which DOM node is the source node, as follows:\n // If it is a selection that is being dragged, then the source node is the text node that the user started the drag on (typically the text node\n // that the user originally clicked). If the user did not specify a particular node, for example if the user just told the user agent to begin\n // a drag of \"the selection\", then the source node is the first text node containing a part of the selection. Otherwise, if it is an element\n // that is being dragged, then the source node is the element that is being dragged. Otherwise, the source node is part of another document or\n // application. When this specification requires that an event be dispatched at the source node in this case, the user agent must instead\n // follow the platform-specific conventions relevant to that situation.\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // 4. Determine the list of dragged nodes, as follows:\n\n // If it is a selection that is being dragged, then the list of dragged nodes contains, in tree order, every node that is partially or\n // completely included in the selection (including all their ancestors).\n\n // Otherwise, the list of dragged nodes contains only the source node, if any.\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // 5. If it is a selection that is being dragged, then add an item to the drag data store item list, with its properties set as follows:\n\n //The drag data item type string\n //\"text/plain\"\n //The drag data item kind\n //Plain Unicode string\n //The actual data\n //The text of the selection\n //Otherwise, if any files are being dragged, then add one item per file to the drag data store item list, with their properties set as follows:\n //\n //The drag data item type string\n //The MIME type of the file, if known, or \"application/octet-stream\" otherwise.\n // The drag data item kind\n //File\n //The actual data\n //The file's contents and name.\n //Dragging files can currently only happen from outside a browsing context, for example from a file system manager application.\n //\n // If the drag initiated outside of the application, the user agent must add items to the drag data store item list as appropriate for the data\n // being dragged, honoring platform conventions where appropriate; however, if the platform conventions do not use MIME types to label dragged\n // data, the user agent must make a best-effort attempt to map the types to MIME types, and, in any case, all the drag data item type strings must\n // be converted to ASCII lowercase. Perform drag-and-drop initialization steps defined in any other applicable specifications.\n\n //\n }\n\n //\n\n /**\n * Setup dragImage, input listeners and the drag\n * and drop process model iteration interval.\n */\n private _setup():boolean {\n console.log(\"dnd-poly: starting drag and drop operation\");\n\n this._dragOperationState = DragOperationState.STARTED;\n\n this._currentDragOperation = DROP_EFFECTS[DROP_EFFECT.NONE];\n\n this._dragDataStore = {\n _data: {},\n _effectAllowed: undefined,\n _mode: DragDataStoreMode.PROTECTED,\n _types: [],\n };\n\n this._currentHotspotCoordinates = {\n x: null,\n y: null\n };\n\n this._dragImagePageCoordinates = {\n x: null,\n y: null\n };\n\n let dragImageSrc:HTMLElement = this._sourceNode;\n\n this._dataTransfer = new DataTransfer(this._dragDataStore, (element:HTMLElement, x:number, y:number) => {\n\n dragImageSrc = element;\n\n if (typeof x === \"number\" || typeof y === \"number\") {\n this._dragImageOffset = {\n x: x || 0,\n y: y || 0\n };\n }\n });\n\n // 9. Fire a DND event named dragstart at the source node.\n this._dragDataStore._mode = DragDataStoreMode.READWRITE;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n if (dispatchDragEvent(\"dragstart\", this._sourceNode, this._lastTouchEvent, this._dragDataStore, this._dataTransfer)) {\n console.log(\"dnd-poly: dragstart cancelled\");\n // dragstart has been prevented -> cancel d'n'd\n this._dragOperationState = DragOperationState.CANCELLED;\n this._cleanup();\n return false;\n }\n\n updateCentroidCoordinatesOfTouchesIn(\"page\", this._lastTouchEvent, this._dragImagePageCoordinates);\n this._dragImage = createDragImage(dragImageSrc);\n this._dragImageTransforms = extractTransformStyles(this._dragImage);\n\n if (!this._dragImageOffset) {\n\n // apply specific offset\n if (this._config.dragImageOffset) {\n\n this._dragImageOffset = {\n x: this._config.dragImageOffset.x,\n y: this._config.dragImageOffset.y\n };\n }\n // center drag image on touch coordinates\n else if (this._config.dragImageCenterOnTouch) {\n\n const cs = getComputedStyle(dragImageSrc);\n this._dragImageOffset = {\n x: 0 - parseInt(cs.marginLeft, 10),\n y: 0 - parseInt(cs.marginTop, 10)\n };\n }\n // by default initialize drag image offset the same as desktop\n else {\n\n const targetRect = dragImageSrc.getBoundingClientRect();\n const cs = getComputedStyle(dragImageSrc);\n this._dragImageOffset = {\n x: targetRect.left - this._initialTouch.clientX - parseInt(cs.marginLeft, 10) + targetRect.width / 2,\n y: targetRect.top - this._initialTouch.clientY - parseInt(cs.marginTop, 10) + targetRect.height / 2\n };\n }\n }\n\n translateDragImage(this._dragImage, this._dragImagePageCoordinates, this._dragImageTransforms, this._dragImageOffset, this._config.dragImageCenterOnTouch);\n document.body.appendChild(this._dragImage);\n\n // 10. Initiate the drag-and-drop operation in a manner consistent with platform conventions, and as described below.\n this._iterationIntervalId = setInterval(() => {\n\n // If the user agent is still performing the previous iteration of the sequence (if any) when the next iteration becomes due,\n // abort these steps for this iteration (effectively \"skipping missed frames\" of the drag-and-drop operation).\n if (this._iterationLock) {\n console.log(\"dnd-poly: iteration skipped because previous iteration hast not yet finished.\");\n return;\n }\n this._iterationLock = true;\n\n this._dragAndDropProcessModelIteration();\n\n this._iterationLock = false;\n }, this._config.iterationInterval);\n\n return true;\n }\n\n private _cleanup() {\n\n console.log(\"dnd-poly: cleanup\");\n\n if (this._iterationIntervalId) {\n clearInterval(this._iterationIntervalId);\n this._iterationIntervalId = null;\n }\n\n removeDocumentListener(\"touchmove\", this._touchMoveHandler);\n removeDocumentListener(\"touchend\", this._touchEndOrCancelHandler);\n removeDocumentListener(\"touchcancel\", this._touchEndOrCancelHandler);\n\n if (this._dragImage) {\n this._dragImage.parentNode.removeChild(this._dragImage);\n this._dragImage = null;\n }\n\n this._dragOperationEndedCb(this._config, this._lastTouchEvent, this._dragOperationState);\n }\n\n //\n\n //\n\n private _onTouchMove(event:TouchEvent) {\n\n // filter unrelated touches\n if (isTouchIdentifierContainedInTouchEvent(event, this._initialTouch.identifier) === false) {\n return;\n }\n\n // update the reference to the last received touch event\n this._lastTouchEvent = event;\n\n // drag operation did not start yet but on movement it should start\n if (this._dragOperationState === DragOperationState.POTENTIAL) {\n\n let startDrag:boolean;\n\n // is a lifecycle hook present?\n if (this._config.dragStartConditionOverride) {\n\n try {\n startDrag = this._config.dragStartConditionOverride(event);\n }\n catch (e) {\n console.error(\"dnd-poly: error in dragStartConditionOverride hook: \" + e);\n startDrag = false;\n }\n }\n else {\n\n // by default only allow a single moving finger to initiate a drag operation\n startDrag = (event.touches.length === 1);\n }\n\n if (!startDrag) {\n\n this._cleanup();\n return;\n }\n\n // setup will return true when drag operation starts\n if (this._setup() === true) {\n\n // prevent scrolling when drag operation starts\n this._initialEvent.preventDefault();\n event.preventDefault();\n }\n\n return;\n }\n\n console.log(\"dnd-poly: moving draggable..\");\n\n // we emulate d'n'd so we dont want any defaults to apply\n event.preventDefault();\n\n // populate shared coordinates from touch event\n updateCentroidCoordinatesOfTouchesIn(\"client\", event, this._currentHotspotCoordinates);\n updateCentroidCoordinatesOfTouchesIn(\"page\", event, this._dragImagePageCoordinates);\n\n if (this._config.dragImageTranslateOverride) {\n\n try {\n\n let handledDragImageTranslate = false;\n\n this._config.dragImageTranslateOverride(\n event,\n {\n x: this._currentHotspotCoordinates.x,\n y: this._currentHotspotCoordinates.y\n },\n this._immediateUserSelection,\n (offsetX:number, offsetY:number) => {\n\n // preventing translation of drag image when there was a drag operation cleanup meanwhile\n if (!this._dragImage) {\n return;\n }\n\n handledDragImageTranslate = true;\n\n this._currentHotspotCoordinates.x += offsetX;\n this._currentHotspotCoordinates.y += offsetY;\n this._dragImagePageCoordinates.x += offsetX;\n this._dragImagePageCoordinates.y += offsetY;\n\n translateDragImage(\n this._dragImage,\n this._dragImagePageCoordinates,\n this._dragImageTransforms,\n this._dragImageOffset,\n this._config.dragImageCenterOnTouch\n );\n }\n );\n\n if (handledDragImageTranslate) {\n return;\n }\n }\n catch (e) {\n console.log(\"dnd-poly: error in dragImageTranslateOverride hook: \" + e);\n }\n }\n\n translateDragImage(this._dragImage, this._dragImagePageCoordinates, this._dragImageTransforms, this._dragImageOffset, this._config.dragImageCenterOnTouch);\n }\n\n private _onTouchEndOrCancel(event:TouchEvent) {\n\n // filter unrelated touches\n if (isTouchIdentifierContainedInTouchEvent(event, this._initialTouch.identifier) === false) {\n return;\n }\n\n // let the dragImageTranslateOverride know that its over\n if (this._config.dragImageTranslateOverride) {\n try {\n /* tslint:disable */\n this._config.dragImageTranslateOverride(undefined, undefined, undefined, function () {\n });\n }\n catch (e) {\n console.log(\"dnd-poly: error in dragImageTranslateOverride hook: \" + e);\n }\n }\n\n // drag operation did not even start\n if (this._dragOperationState === DragOperationState.POTENTIAL) {\n this._cleanup();\n return;\n }\n\n // we emulate d'n'd so we dont want any defaults to apply\n event.preventDefault();\n\n this._dragOperationState = (event.type === \"touchcancel\") ? DragOperationState.CANCELLED : DragOperationState.ENDED;\n }\n\n //\n\n //\n\n /**\n * according to https://html.spec.whatwg.org/multipage/interaction.html#drag-and-drop-processing-model\n */\n private _dragAndDropProcessModelIteration():void {\n\n if (DEBUG) {\n var debug_class = CLASS_PREFIX + \"debug\",\n debug_class_user_selection = CLASS_PREFIX + \"immediate-user-selection\",\n debug_class_drop_target = CLASS_PREFIX + \"current-drop-target\";\n }\n\n const previousDragOperation = this._currentDragOperation;\n\n // Fire a DND event named drag event at the source node.\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n const dragCancelled = dispatchDragEvent(\"drag\", this._sourceNode, this._lastTouchEvent, this._dragDataStore, this._dataTransfer);\n if (dragCancelled) {\n console.log(\"dnd-poly: drag event cancelled.\");\n // If this event is canceled, the user agent must set the current drag operation to \"none\" (no drag operation).\n this._currentDragOperation = DROP_EFFECTS[DROP_EFFECT.NONE];\n }\n\n // Otherwise, if the user ended the drag-and-drop operation (e.g. by releasing the mouse button in a mouse-driven drag-and-drop interface),\n // or if the drag event was canceled, then this will be the last iteration.\n if (dragCancelled || this._dragOperationState === DragOperationState.ENDED || this._dragOperationState === DragOperationState.CANCELLED) {\n\n const dragFailed = this._dragOperationEnded(this._dragOperationState);\n\n // if drag failed transition snap back\n if (dragFailed) {\n\n applyDragImageSnapback(this._sourceNode, this._dragImage, this._dragImageTransforms, () => {\n this._finishDragOperation();\n });\n return;\n }\n\n // Otherwise immediately\n // Fire a DND event named dragend at the source node.\n this._finishDragOperation();\n return;\n }\n\n // If the drag event was not canceled and the user has not ended the drag-and-drop operation,\n // check the state of the drag-and-drop operation, as follows:\n const newUserSelection:HTMLElement = document.elementFromPoint(this._currentHotspotCoordinates.x, this._currentHotspotCoordinates.y);\n\n console.log(\"dnd-poly: new immediate user selection is: \" + newUserSelection);\n\n const previousTargetElement = this._currentDropTarget;\n\n // If the user is indicating a different immediate user selection than during the last iteration (or if this is the first iteration),\n // and if this immediate user selection is not the same as the current target element,\n // then fire a DND event named dragexit at the current target element,\n // and then update the current target element as follows:\n if (newUserSelection !== this._immediateUserSelection && newUserSelection !== this._currentDropTarget) {\n\n if (DEBUG) {\n\n if (this._immediateUserSelection) {\n this._immediateUserSelection.classList.remove(debug_class_user_selection);\n }\n\n if (newUserSelection) {\n newUserSelection.classList.add(debug_class);\n newUserSelection.classList.add(debug_class_user_selection);\n }\n }\n\n this._immediateUserSelection = newUserSelection;\n\n if (this._currentDropTarget !== null) {\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n dispatchDragEvent(\"dragexit\", this._currentDropTarget, this._lastTouchEvent, this._dragDataStore, this._dataTransfer, false);\n }\n\n // If the new immediate user selection is null\n if (this._immediateUserSelection === null) {\n //Set the current target element to null also.\n this._currentDropTarget = this._immediateUserSelection;\n\n console.log(\"dnd-poly: current drop target changed to null\");\n }\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the new immediate user selection is in a non-DOM document or application\n // else if() {\n // Set the current target element to the immediate user selection.\n // this.currentDropTarget = this.immediateUserSelection;\n // return;\n // }\n // Otherwise\n else {\n // Fire a DND event named dragenter at the immediate user selection.\n //the polyfill cannot determine if a handler even exists as browsers do to silently\n // allow drop when no listener existed, so this event MUST be handled by the client\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = determineDropEffect(this._dragDataStore._effectAllowed, this._sourceNode);\n if (dispatchDragEvent(\"dragenter\", this._immediateUserSelection, this._lastTouchEvent, this._dragDataStore, this._dataTransfer)) {\n console.log(\"dnd-poly: dragenter default prevented\");\n // If the event is canceled, then set the current target element to the immediate user selection.\n this._currentDropTarget = this._immediateUserSelection;\n this._currentDragOperation = determineDragOperation(this._dataTransfer.effectAllowed, this._dataTransfer.dropEffect);\n }\n // Otherwise, run the appropriate step from the following list:\n else {\n\n // NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n //console.log( \"dnd-poly: dragenter not prevented, searching for dropzone..\" );\n //var newTarget = DragOperationController.FindDropzoneElement( this.immediateUserSelection );\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the current target element is a text field (e.g. textarea, or an input element whose type attribute is in the Text state) or an\n // editable element, and the drag data store item list has an item with the drag data item type string \"text/plain\" and the drag data\n // item kind Plain Unicode string\n //if( ElementIsTextDropzone( this.immediateUserSelection, this.dragDataStore ) ) {\n //Set the current target element to the immediate user selection anyway.\n //this.currentDropTarget = this.immediateUserSelection;\n //}\n //else\n // If the current target element is an element with a dropzone attribute that matches the drag data store\n //if( newTarget === this.immediateUserSelection &&\n // DragOperationController.GetOperationForMatchingDropzone( this.immediateUserSelection, this.dragDataStore ) !== \"none\" ) {\n // Set the current target element to the immediate user selection anyway.\n // this.currentDropTarget = this.immediateUserSelection;\n //}\n // If the immediate user selection is an element that itself has an ancestor element\n // with a dropzone attribute that matches the drag data store\n // NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n //else if( newTarget !== null && DragOperationController.GetOperationForMatchingDropzone( newTarget, this.dragDataStore ) ) {\n\n // If the immediate user selection is new target, then leave the current target element unchanged.\n\n // Otherwise, fire a DND event named dragenter at new target, with the current target element\n // as the specific related target. Then, set the current target element to new target,\n // regardless of whether that event was canceled or not.\n //this.dragenter( newTarget, this.currentDropTarget );\n //this.currentDropTarget = newTarget;\n //}\n // If the current target element is not the body element\n //else\n if (this._immediateUserSelection !== document.body) {\n // Fire a DND event named dragenter at the body element, and set the current target element to the body element, regardless of\n // whether that event was canceled or not.\n // Note: If the body element is null, then the event will be fired at the Document object (as\n // required by the definition of the body element), but the current target element would be set to null, not the Document object.\n\n // We do not listen to what the spec says here because this results in doubled events on the body/document because if the first one\n // was not cancelled it will have bubbled up to the body already ;)\n // this.dragenter( window.document.body );\n this._currentDropTarget = document.body;\n }\n // Otherwise\n //else {\n // leave the current drop target unchanged\n //}\n }\n }\n }\n\n // If the previous step caused the current target element to change,\n // and if the previous target element was not null or a part of a non-DOM document,\n // then fire a DND event named dragleave at the previous target element.\n if (previousTargetElement !== this._currentDropTarget && (isDOMElement(previousTargetElement) )) {\n\n if (DEBUG) {\n previousTargetElement.classList.remove(debug_class_drop_target);\n }\n\n console.log(\"dnd-poly: current drop target changed.\");\n\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n dispatchDragEvent(\"dragleave\", previousTargetElement, this._lastTouchEvent, this._dragDataStore, this._dataTransfer, false, this._currentDropTarget);\n }\n\n // If the current target element is a DOM element, then fire a DND event named dragover at this current target element.\n if (isDOMElement(this._currentDropTarget)) {\n\n if (DEBUG) {\n this._currentDropTarget.classList.add(debug_class);\n this._currentDropTarget.classList.add(debug_class_drop_target);\n }\n\n // If the dragover event is not canceled, run the appropriate step from the following list:\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = determineDropEffect(this._dragDataStore._effectAllowed, this._sourceNode);\n if (dispatchDragEvent(\"dragover\", this._currentDropTarget, this._lastTouchEvent, this._dragDataStore, this._dataTransfer) === false) {\n\n console.log(\"dnd-poly: dragover not prevented on possible drop-target.\");\n // NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the current target element is a text field (e.g. textarea, or an input element whose type attribute is in the Text state) or\n // an editable element, and the drag data store item list has an item with the drag data item type string \"text/plain\" and the drag\n // data item kind Plain Unicode string\n //if( ElementIsTextDropzone( this.currentDropTarget, this.dragDataStore ) ) {\n // Set the current drag operation to either \"copy\" or \"move\", as appropriate given the platform conventions.\n //this.currentDragOperation = \"copy\"; //or move. spec says its platform specific behaviour.\n //}\n //else {\n // If the current target element is an element with a dropzone attribute that matches the drag data store\n //this.currentDragOperation = DragOperationController.GetOperationForMatchingDropzone( this.currentDropTarget, this.dragDataStore );\n //}\n // when dragover is not prevented and no dropzones are there, no drag operation\n this._currentDragOperation = DROP_EFFECTS[DROP_EFFECT.NONE];\n }\n // Otherwise (if the dragover event is canceled), set the current drag operation based on the values of the effectAllowed and\n // dropEffect attributes of the DragEvent object's dataTransfer object as they stood after the event dispatch finished\n else {\n\n console.log(\"dnd-poly: dragover prevented.\");\n\n this._currentDragOperation = determineDragOperation(this._dataTransfer.effectAllowed, this._dataTransfer.dropEffect);\n }\n }\n\n console.log(\"dnd-poly: d'n'd iteration ended. current drag operation: \" + this._currentDragOperation);\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // Otherwise, if the current target element is not a DOM element, use platform-specific mechanisms to determine what drag operation is\n // being performed (none, copy, link, or move), and set the current drag operation accordingly.\n\n //Update the drag feedback (e.g. the mouse cursor) to match the current drag operation, as follows:\n // ---------------------------------------------------------------------------------------------------------\n // Drag operation |\tFeedback\n // \"copy\"\t | Data will be copied if dropped here.\n // \"link\"\t | Data will be linked if dropped here.\n // \"move\"\t | Data will be moved if dropped here.\n // \"none\"\t | No operation allowed, dropping here will cancel the drag-and-drop operation.\n // ---------------------------------------------------------------------------------------------------------\n\n if (previousDragOperation !== this._currentDragOperation) {\n this._dragImage.classList.remove(CLASS_PREFIX + previousDragOperation);\n }\n\n const currentDragOperationClass = CLASS_PREFIX + this._currentDragOperation;\n\n if (this._dragImage.classList.contains(currentDragOperationClass) === false) {\n this._dragImage.classList.add(currentDragOperationClass);\n }\n }\n\n /**\n * according to https://html.spec.whatwg.org/multipage/interaction.html#drag-and-drop-processing-model\n */\n private _dragOperationEnded(state:DragOperationState):boolean {\n\n console.log(\"dnd-poly: drag operation end detected with \" + this._currentDragOperation);\n\n if (DEBUG) {\n\n var debug_class_user_selection = CLASS_PREFIX + \"immediate-user-selection\",\n debug_class_drop_target = CLASS_PREFIX + \"current-drop-target\";\n\n if (this._currentDropTarget) {\n this._currentDropTarget.classList.remove(debug_class_drop_target);\n\n }\n if (this._immediateUserSelection) {\n this._immediateUserSelection.classList.remove(debug_class_user_selection);\n }\n }\n\n //var dropped:boolean = undefined;\n\n // Run the following steps, then stop the drag-and-drop operation:\n\n // If the current drag operation is \"none\" (no drag operation), or,\n // if the user ended the drag-and-drop operation by canceling it (e.g. by hitting the Escape key), or\n // if the current target element is null, then the drag operation failed.\n const dragFailed = (this._currentDragOperation === DROP_EFFECTS[DROP_EFFECT.NONE]\n || this._currentDropTarget === null\n || state === DragOperationState.CANCELLED);\n if (dragFailed) {\n\n // Run these substeps:\n\n // Let dropped be false.\n //dropped = false;\n\n // If the current target element is a DOM element, fire a DND event named dragleave at it;\n if (isDOMElement(this._currentDropTarget)) {\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = DROP_EFFECTS[DROP_EFFECT.NONE];\n dispatchDragEvent(\"dragleave\", this._currentDropTarget, this._lastTouchEvent, this._dragDataStore, this._dataTransfer, false);\n }\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // otherwise, if it is not null, use platform-specific conventions for drag cancellation.\n //else if( this.currentDropTarget !== null ) {\n //}\n }\n // Otherwise, the drag operation was as success; run these substeps:\n else {\n\n // Let dropped be true.\n //dropped = true;\n\n // If the current target element is a DOM element, fire a DND event named drop at it;\n if (isDOMElement(this._currentDropTarget)) {\n\n // If the event is canceled, set the current drag operation to the value of the dropEffect attribute of the\n // DragEvent object's dataTransfer object as it stood after the event dispatch finished.\n\n this._dragDataStore._mode = DragDataStoreMode.READONLY;\n this._dataTransfer.dropEffect = this._currentDragOperation;\n if (dispatchDragEvent(\"drop\", this._currentDropTarget, this._lastTouchEvent, this._dragDataStore, this._dataTransfer) ===\n true) {\n\n this._currentDragOperation = this._dataTransfer.dropEffect;\n }\n // Otherwise, the event is not canceled; perform the event's default action, which depends on the exact target as follows:\n else {\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // If the current target element is a text field (e.g. textarea, or an input element whose type attribute is in the Text state)\n // or an editable element,\n // and the drag data store item list has an item with the drag data item type string \"text/plain\"\n // and the drag data item kind Plain Unicode string\n //if( ElementIsTextDropzone( this.currentDropTarget, this.dragDataStore ) ) {\n // Insert the actual data of the first item in the drag data store item list to have a drag data item type string of\n // \"text/plain\" and a drag data item kind that is Plain Unicode string into the text field or editable element in a manner\n // consistent with platform-specific conventions (e.g. inserting it at the current mouse cursor position, or inserting it at\n // the end of the field).\n //}\n // Otherwise\n //else {\n // Reset the current drag operation to \"none\".\n this._currentDragOperation = DROP_EFFECTS[DROP_EFFECT.NONE];\n //}\n }\n }\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n // otherwise, use platform-specific conventions for indicating a drop.\n //else {\n //}\n }\n\n return dragFailed;\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n //if( this.dragend( this.sourceNode ) ) {\n // return;\n //}\n\n // Run the appropriate steps from the following list as the default action of the dragend event:\n\n //if( !dropped ) {\n // return;\n //}\n // dropped is true\n\n //if( this.currentDragOperation !== \"move\" ) {\n // return;\n //}\n //// drag operation is move\n //\n //if( ElementIsTextDropzone( this.currentDropTarget ) === false ) {\n // return;\n //}\n //// element is textfield\n //\n //// and the source of the drag-and-drop operation is a selection in the DOM\n //if( this.sourceNode.nodeType === 1 ) {\n // // The user agent should delete the range representing the dragged selection from the DOM.\n //}\n //// and the source of the drag-and-drop operation is a selection in a text field\n //else if( this.sourceNode.nodeType === 3 ) {\n // // The user agent should delete the dragged selection from the relevant text field.\n //}\n //// Otherwise, The event has no default action.\n }\n\n // dispatch dragend event and cleanup drag operation\n private _finishDragOperation():void {\n console.log(\"dnd-poly: dragimage snap back transition ended\");\n\n // Fire a DND event named dragend at the source node.\n this._dragDataStore._mode = DragDataStoreMode.PROTECTED;\n this._dataTransfer.dropEffect = this._currentDragOperation;\n dispatchDragEvent(\"dragend\", this._sourceNode, this._lastTouchEvent, this._dragDataStore, this._dataTransfer, false);\n\n // drag operation over and out\n this._dragOperationState = DragOperationState.ENDED;\n this._cleanup();\n }\n\n //\n}\n\n//\n\n//\n\n/**\n * Polyfills https://html.spec.whatwg.org/multipage/interaction.html#drag-data-store-mode\n */\nconst enum DragDataStoreMode {\n _DISCONNECTED, // adding an extra mode here because we need a special state to disconnect the data store from dataTransfer instance\n READONLY,\n READWRITE,\n PROTECTED\n}\n\n/**\n * Polyfills https://html.spec.whatwg.org/multipage/interaction.html#the-drag-data-store\n */\ninterface DragDataStore {\n _mode:DragDataStoreMode;\n _data:{ [type:string]:any };\n _types:Array;\n _effectAllowed:string;\n}\n\n/**\n * Polyfills https://html.spec.whatwg.org/multipage/interaction.html#datatransfer\n * TODO fail with errors when somebody uses it wrong so they know they are doing it wrong?\n */\nclass DataTransfer {\n\n private _dropEffect:string = DROP_EFFECTS[DROP_EFFECT.NONE];\n\n constructor(private _dataStore:DragDataStore,\n private _setDragImageHandler:(image:Element, x:number, y:number) => void) {\n }\n\n //public get files():FileList {\n // return undefined;\n //}\n //\n //public get items():DataTransferItemList {\n // return undefined;\n //}\n\n public get types():ReadonlyArray {\n if (this._dataStore._mode !== DragDataStoreMode._DISCONNECTED) {\n return Object.freeze(this._dataStore._types);\n }\n }\n\n public setData(type:string, data:string):void {\n if (this._dataStore._mode === DragDataStoreMode.READWRITE) {\n\n if (type.indexOf(\" \") > -1) {\n throw new Error(\"illegal arg: type contains space\");\n }\n\n this._dataStore._data[type] = data;\n\n if (this._dataStore._types.indexOf(type) === -1) {\n this._dataStore._types.push(type);\n }\n }\n }\n\n public getData(type:string):string {\n if (this._dataStore._mode === DragDataStoreMode.READONLY\n || this._dataStore._mode === DragDataStoreMode.READWRITE) {\n return this._dataStore._data[type] || \"\";\n }\n }\n\n public clearData(format?:string):void {\n if (this._dataStore._mode === DragDataStoreMode.READWRITE) {\n // delete data for format\n if (format && this._dataStore._data[format]) {\n delete this._dataStore._data[format];\n var index = this._dataStore._types.indexOf(format);\n if (index > -1) {\n this._dataStore._types.splice(index, 1);\n }\n return;\n }\n // delete all data\n this._dataStore._data = {};\n this._dataStore._types = [];\n }\n }\n\n public setDragImage(image:Element, x:number, y:number):void {\n if (this._dataStore._mode === DragDataStoreMode.READWRITE) {\n this._setDragImageHandler(image, x, y);\n }\n }\n\n public get effectAllowed() {\n return this._dataStore._effectAllowed;\n }\n\n public set effectAllowed(value) {\n if (this._dataStore._mode === DragDataStoreMode.READWRITE\n && ALLOWED_EFFECTS.indexOf(value) > -1) {\n this._dataStore._effectAllowed = value;\n }\n }\n\n public get dropEffect() {\n return this._dropEffect;\n }\n\n public set dropEffect(value) {\n if (this._dataStore._mode !== DragDataStoreMode._DISCONNECTED\n && ALLOWED_EFFECTS.indexOf(value) > -1) {\n this._dropEffect = value;\n }\n }\n}\n\n//\n\n//\n\nexport interface Point {\n x:number;\n y:number;\n}\n\nfunction addDocumentListener(ev:string, handler:EventListener, passive:boolean = true) {\n\n (document as EventTarget).addEventListener(ev, handler, supportsPassive ? {passive: passive} : false);\n}\n\nfunction removeDocumentListener(ev:string, handler:EventListener) {\n document.removeEventListener(ev, handler);\n}\n\nfunction average(array:Array) {\n if (array.length === 0) {\n return 0;\n }\n return array.reduce((function (s, v) {\n return v + s;\n }), 0) / array.length;\n}\n\nfunction isDOMElement(object:any) {\n return object && object.tagName;\n}\n\nfunction isTouchIdentifierContainedInTouchEvent(newTouch:TouchEvent, touchIdentifier:number) {\n for (let i = 0; i < newTouch.changedTouches.length; i++) {\n const touch = newTouch.changedTouches[i];\n if (touch.identifier === touchIdentifier) {\n return true;\n }\n }\n return false;\n}\n\nfunction createDragEventFromTouch(targetElement:Element,\n e:TouchEvent,\n type:string,\n cancelable:boolean,\n window:Window,\n dataTransfer:DataTransfer,\n relatedTarget:Element = null) {\n\n const touch:Touch = e.changedTouches[0];\n\n const dndEvent:DragEvent = new Event(type, {\n bubbles: true,\n cancelable: cancelable\n });\n\n // cast our polyfill\n (dndEvent as any).dataTransfer = dataTransfer;\n (dndEvent as any).relatedTarget = relatedTarget;\n\n // set the coordinates\n (dndEvent as any).screenX = touch.screenX;\n (dndEvent as any).screenY = touch.screenY;\n (dndEvent as any).clientX = touch.clientX;\n (dndEvent as any).clientY = touch.clientY;\n (dndEvent as any).pageX = touch.pageX;\n (dndEvent as any).pageY = touch.pageY;\n\n const targetRect = targetElement.getBoundingClientRect();\n (dndEvent as any).offsetX = dndEvent.clientX - targetRect.left;\n (dndEvent as any).offsetY = dndEvent.clientY - targetRect.top;\n\n return dndEvent;\n}\n\n/**\n * Calc center of polygon spanned by multiple touches in page (full page size, with hidden scrollable area) coordinates\n * or in viewport (screen coordinates) coordinates.\n */\nfunction updateCentroidCoordinatesOfTouchesIn(coordinateProp:string, event:TouchEvent, outPoint:Point):void {\n const pageXs:Array = [], pageYs:Array = [];\n for (let i = 0; i < event.touches.length; i++) {\n const touch = event.touches[i];\n pageXs.push(touch[coordinateProp + \"X\"]);\n pageYs.push(touch[coordinateProp + \"Y\"]);\n }\n outPoint.x = average(pageXs);\n outPoint.y = average(pageYs);\n}\n\nfunction prepareNodeCopyAsDragImage(srcNode:HTMLElement, dstNode:HTMLElement) {\n // Is this node an element?\n if (srcNode.nodeType === 1) {\n\n // Clone the style\n const cs = getComputedStyle(srcNode);\n for (let i = 0; i < cs.length; i++) {\n const csName = cs[i];\n dstNode.style.setProperty(csName, cs.getPropertyValue(csName), cs.getPropertyPriority(csName));\n }\n\n // no interaction with the drag image, pls! this is also important to make the drag image transparent for hit-testing\n // hit testing is done in the drag and drop iteration to find the element the user currently is hovering over while dragging.\n // if pointer-events is not none or a browser does behave in an unexpected way than the hit test transparency on the drag image\n // will break\n dstNode.style.pointerEvents = \"none\";\n\n // Remove any potential conflict attributes\n dstNode.removeAttribute(\"id\");\n dstNode.removeAttribute(\"class\");\n dstNode.removeAttribute(\"draggable\");\n }\n\n // Do the same for the children\n if (srcNode.hasChildNodes()) {\n for (let i = 0; i < srcNode.childNodes.length; i++) {\n prepareNodeCopyAsDragImage(srcNode.childNodes[i], dstNode.childNodes[i]);\n }\n }\n}\n\nfunction createDragImage(sourceNode:HTMLElement):HTMLElement {\n\n const dragImage = sourceNode.cloneNode(true);\n\n // this removes any id's and stuff that could interfere with drag and drop\n prepareNodeCopyAsDragImage(sourceNode, dragImage);\n\n // set layout styles for freely moving it around\n dragImage.style.position = \"absolute\";\n dragImage.style.left = \"0px\";\n dragImage.style.top = \"0px\";\n // on top of all\n dragImage.style.zIndex = \"999999\";\n\n // add polyfill class for default styling\n dragImage.classList.add(CLASS_DRAG_IMAGE);\n dragImage.classList.add(CLASS_DRAG_OPERATION_ICON);\n\n return dragImage;\n}\n\nfunction extractTransformStyles(sourceNode:HTMLElement):string[] {\n\n return TRANSFORM_CSS_VENDOR_PREFIXES.map(function (prefix) {\n\n let transform = sourceNode.style[prefix + \"transform\"];\n\n if (!transform || transform === \"none\") {\n return \"\";\n }\n\n // TODO what about translateX(x), translateY(x), translateZ(z), translate3d(x,y,z), matrix(*,*,*,*,x,y) ?\n\n // removes translate(x,y)\n return transform.replace(/translate\\(\\D*\\d+[^,]*,\\D*\\d+[^,]*\\)\\s*/g, \"\");\n });\n}\n\nfunction translateDragImage(dragImage:HTMLElement, pnt:Point, originalTransforms:string[], offset?:Point, centerOnCoordinates = true):void {\n\n let x = pnt.x, y = pnt.y;\n\n if (offset) {\n x += offset.x;\n y += offset.y;\n }\n\n if (centerOnCoordinates) {\n x -= (parseInt(dragImage.offsetWidth, 10) / 2);\n y -= (parseInt(dragImage.offsetHeight, 10) / 2);\n }\n\n // using translate3d for best performance\n const translate = \"translate3d(\" + x + \"px,\" + y + \"px, 0)\";\n\n for (let i = 0; i < TRANSFORM_CSS_VENDOR_PREFIXES.length; i++) {\n const transformProp = TRANSFORM_CSS_VENDOR_PREFIXES[i] + \"transform\";\n dragImage.style[transformProp] = translate + \" \" + originalTransforms[i];\n }\n}\n\n/**\n * calculates the coordinates of the drag source and transitions the drag image to those coordinates.\n * the drag operation is finished after the transition has ended.\n */\nfunction applyDragImageSnapback(sourceEl:HTMLElement, dragImage:HTMLElement, dragImageTransforms:string[], transitionEndCb:Function):void {\n\n const cs = getComputedStyle(sourceEl);\n\n if (cs.visibility === \"hidden\" || cs.display === \"none\") {\n console.log(\"dnd-poly: source node is not visible. skipping snapback transition.\");\n // shortcut to end the drag operation\n transitionEndCb();\n return;\n }\n // add class containing transition rules\n dragImage.classList.add(CLASS_DRAG_IMAGE_SNAPBACK);\n\n const csDragImage = getComputedStyle(dragImage);\n const durationInS = parseFloat(csDragImage.transitionDuration);\n if (isNaN(durationInS) || durationInS === 0) {\n console.log(\"dnd-poly: no transition used - skipping snapback\");\n transitionEndCb();\n return;\n }\n\n console.log(\"dnd-poly: starting dragimage snap back\");\n\n // calc source node position\n const rect = sourceEl.getBoundingClientRect();\n\n const pnt:Point = {\n x: rect.left,\n y: rect.top\n };\n\n // add scroll offset of document\n pnt.x += (document.body.scrollLeft || document.documentElement.scrollLeft);\n pnt.y += (document.body.scrollTop || document.documentElement.scrollTop);\n\n //TODO this sometimes fails.. find out when exactly and how to detect\n pnt.x -= parseInt(cs.marginLeft, 10);\n pnt.y -= parseInt(cs.marginTop, 10);\n\n const delayInS = parseFloat(csDragImage.transitionDelay);\n const durationInMs = Math.round((durationInS + delayInS) * 1000);\n\n // apply the translate\n translateDragImage(dragImage, pnt, dragImageTransforms, undefined, false);\n\n setTimeout(transitionEndCb, durationInMs);\n}\n\n//\n\n//\n\n/**\n * Implements \"6.\" in the processing steps defined for a dnd event\n * https://html.spec.whatwg.org/multipage/interaction.html#dragevent\n */\nfunction determineDropEffect(effectAllowed:string, sourceNode:Element) {\n\n // uninitialized\n if (!effectAllowed) {\n\n // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n //if( sourceNode.nodeType === 1 ) {\n //\n //return \"move\";\n //}\n\n // link\n if (sourceNode.nodeType === 3 && (sourceNode).tagName === \"A\") {\n return DROP_EFFECTS[DROP_EFFECT.LINK];\n }\n\n // copy\n return DROP_EFFECTS[DROP_EFFECT.COPY];\n }\n\n // none\n if (effectAllowed === ALLOWED_EFFECTS[EFFECT_ALLOWED.NONE]) {\n return DROP_EFFECTS[DROP_EFFECT.NONE];\n }\n // copy or all\n if (effectAllowed.indexOf(ALLOWED_EFFECTS[EFFECT_ALLOWED.COPY]) === 0 || effectAllowed === ALLOWED_EFFECTS[EFFECT_ALLOWED.ALL]) {\n return DROP_EFFECTS[DROP_EFFECT.COPY];\n }\n // link\n if (effectAllowed.indexOf(ALLOWED_EFFECTS[EFFECT_ALLOWED.LINK]) === 0) {\n return DROP_EFFECTS[DROP_EFFECT.LINK];\n }\n // move\n if (effectAllowed === ALLOWED_EFFECTS[EFFECT_ALLOWED.MOVE]) {\n return DROP_EFFECTS[DROP_EFFECT.MOVE];\n }\n\n // copy\n return DROP_EFFECTS[DROP_EFFECT.COPY];\n}\n\n/**\n * Reference https://html.spec.whatwg.org/multipage/interaction.html#dndevents\n */\nfunction dispatchDragEvent(dragEvent:string,\n targetElement:Element,\n touchEvent:TouchEvent,\n dataStore:DragDataStore,\n dataTransfer:DataTransfer,\n cancelable = true,\n relatedTarget:Element = null):boolean {\n\n console.log(\"dnd-poly: dispatching \" + dragEvent);\n\n if (DEBUG) {\n var debug_class = CLASS_PREFIX + \"debug\",\n debug_class_event_target = CLASS_PREFIX + \"event-target\",\n debug_class_event_related_target = CLASS_PREFIX + \"event-related-target\";\n targetElement.classList.add(debug_class);\n targetElement.classList.add(debug_class_event_target);\n if (relatedTarget) {\n relatedTarget.classList.add(debug_class);\n relatedTarget.classList.add(debug_class_event_related_target);\n }\n }\n\n const leaveEvt = createDragEventFromTouch(targetElement, touchEvent, dragEvent, cancelable, document.defaultView, dataTransfer, relatedTarget);\n const cancelled = !targetElement.dispatchEvent(leaveEvt);\n\n dataStore._mode = DragDataStoreMode._DISCONNECTED;\n\n if (DEBUG) {\n targetElement.classList.remove(debug_class_event_target);\n if (relatedTarget) {\n relatedTarget.classList.remove(debug_class_event_related_target);\n }\n }\n\n return cancelled;\n}\n\n/**\n * according to https://html.spec.whatwg.org/multipage/interaction.html#drag-and-drop-processing-model\n */\nfunction determineDragOperation(effectAllowed:string, dropEffect:string):string {\n\n // unitialized or all\n if (!effectAllowed || effectAllowed === ALLOWED_EFFECTS[7]) {\n return dropEffect;\n }\n\n if (dropEffect === DROP_EFFECTS[DROP_EFFECT.COPY]) {\n if (effectAllowed.indexOf(DROP_EFFECTS[DROP_EFFECT.COPY]) === 0) {\n return DROP_EFFECTS[DROP_EFFECT.COPY];\n }\n }\n else if (dropEffect === DROP_EFFECTS[DROP_EFFECT.LINK]) {\n if (effectAllowed.indexOf(DROP_EFFECTS[DROP_EFFECT.LINK]) === 0 || effectAllowed.indexOf(\"Link\") > -1) {\n return DROP_EFFECTS[DROP_EFFECT.LINK];\n }\n }\n else if (dropEffect === DROP_EFFECTS[DROP_EFFECT.MOVE]) {\n if (effectAllowed.indexOf(DROP_EFFECTS[DROP_EFFECT.MOVE]) === 0 || effectAllowed.indexOf(\"Move\") > -1) {\n return DROP_EFFECTS[DROP_EFFECT.MOVE];\n }\n }\n\n return DROP_EFFECTS[DROP_EFFECT.NONE];\n}\n\nfunction onDelayTouchstart(evt: TouchEvent) {\n const el = evt.target;\n\n const heldItem = () => {\n end.off();\n cancel.off();\n scroll.off();\n onTouchstart(evt);\n };\n\n const onReleasedItem = () => {\n end.off();\n cancel.off();\n scroll.off();\n clearTimeout(timer);\n };\n\n const timer = setTimeout(heldItem, config.holdToDrag);\n\n const end = onEvt(el, 'touchend', onReleasedItem, this);\n const cancel = onEvt(el, 'touchcancel', onReleasedItem, this);\n const scroll = onEvt(window, 'scroll', onReleasedItem, this);\n}\n\nfunction onEvt(el: EventTarget, event: string, handler: () => any, context: any) {\n if (context) {\n handler = handler.bind(context);\n }\n\n el.addEventListener(event, handler);\n\n return {\n off() {\n return el.removeEventListener(event, handler);\n }\n };\n}\n\n//\n\n//\n\n/**\n * // THIS IS SKIPPED SINCE SUPPORT IS ONLY AVAILABLE FOR DOM ELEMENTS\n */\n//public static ElementIsTextDropzone( element:HTMLElement, dragDataStore?:DragDataStore ) {\n//\n// if( dragDataStore && !dragDataStore.data[ \"text/plain\" ] ) {\n// return false;\n// }\n//\n// if( element.isContentEditable ) {\n// return true;\n// }\n//\n// if( element.tagName === \"TEXTAREA\" ) {\n// return true;\n// }\n//\n// if( element.tagName === \"INPUT\" ) {\n// if( element.getAttribute( \"type\" ) === \"text\" ) {\n// return true;\n// }\n// }\n//\n// return false;\n//}\n\n/**\n * NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n *\n * Helper method for recursively go from a nested element up the ancestor chain\n * to see if any element has a dropzone.\n */\n//private static FindDropzoneElement( element:HTMLElement ):HTMLElement {\n//\n// if( !element || !element.hasAttribute || typeof element.hasAttribute !== \"function\" ) {\n// return null;\n// }\n//\n// if( element.hasAttribute( \"dropzone\" ) ) {\n// return element;\n// }\n//\n// if( element === window.document.body ) {\n// return null;\n// }\n//\n// return DragOperationController.FindDropzoneElement( element.parentElement );\n//}\n\n/**\n * NO DROPZONE SUPPORT SINCE NATIVE IMPLEMENTATIONS IN BROWSERS ALSO DO NOT\n *\n * Polyfills https://html.spec.whatwg.org/multipage/interaction.html#the-dropzone-attribute\n * by implementing the dropzone processing steps.\n */\n//private static GetOperationForMatchingDropzone( element:HTMLElement, dragDataStore:DragDataStore ):string {\n\n// If the current target element is an element with a dropzone attribute that matches the drag data store and specifies an operation\n// Set the current drag operation to the operation specified by the dropzone attribute of the current target element.\n// If the current target element is an element with a dropzone attribute that matches the drag data store and does not specify an operation\n// Set the current drag operation to \"copy\".\n// Otherwise\n// Reset the current drag operation to \"none\".\n//var value = element.getAttribute( \"dropzone\" );\n//if( !value ) {\n//\n// return \"none\";\n//}\n//\n//var matched = false;\n//var operation;\n//var keywords = value.split( \" \" );\n//\n//for( var i:number = 0; i < keywords.length; i++ ) {\n// var keyword = keywords[ i ];\n//\n// if( keyword === \"copy\" || keyword === \"move\" || keyword === \"link\" ) {\n// if( !operation ) {\n// operation = keyword;\n// }\n// continue;\n// }\n//\n// if( keyword.length < 3 || keyword[ 1 ] !== \":\" ) {\n// continue;\n// }\n//\n// var splitKeyword = keyword.split( \":\" );\n// var kind = splitKeyword[ 0 ].toLowerCase();\n// var type = splitKeyword[ 1 ].toLowerCase();\n//\n// if( dragDataStore.types.indexOf( type ) > -1 ) {\n// matched = true;\n// }\n//}\n//\n//if( !matched ) {\n// return \"none\";\n//}\n//\n//if( !operation ) {\n// return \"copy\";\n//}\n//\n//return operation;\n//}\n\n//\n"]} \ No newline at end of file diff --git a/release/package.json b/release/package.json index d9edc4a..5d4ea39 100644 --- a/release/package.json +++ b/release/package.json @@ -1,6 +1,6 @@ { "name": "mobile-drag-drop", - "version": "2.1.0", + "version": "2.2.0", "description": "Polyfill for making HTML5 drag and drop possible in all browsers.", "main": "index.min.js", "types": "index.d.ts",