Commit c1a9ec901fbaffa802c29f5986f28de8a34ed094
1 parent
6ae22fe0
this is solution for the bug touch with labex
Showing
3 changed files
with
410 additions
and
8 deletions
400-SOURCECODE/AIAHTML5.Web/app/controllers/LabExercController.js
@@ -401,7 +401,7 @@ function ($scope, $rootScope, pages, log, $http,$timeout, DataService, $filter, | @@ -401,7 +401,7 @@ function ($scope, $rootScope, pages, log, $http,$timeout, DataService, $filter, | ||
401 | 401 | ||
402 | this.style.opacity = '0.4'; | 402 | this.style.opacity = '0.4'; |
403 | var $ua = navigator.userAgent; | 403 | var $ua = navigator.userAgent; |
404 | - if ($.browser.msie || ($ua.match(/(iPod|iPhone|iPad|android)/i))) { | 404 | + if ($.browser.msie) { |
405 | localStorage.setItem("text", this.innerHTML); | 405 | localStorage.setItem("text", this.innerHTML); |
406 | } | 406 | } |
407 | else | 407 | else |
@@ -471,7 +471,7 @@ function ($scope, $rootScope, pages, log, $http,$timeout, DataService, $filter, | @@ -471,7 +471,7 @@ function ($scope, $rootScope, pages, log, $http,$timeout, DataService, $filter, | ||
471 | 471 | ||
472 | var keywords = $location.search(); | 472 | var keywords = $location.search(); |
473 | var $ua = navigator.userAgent; | 473 | var $ua = navigator.userAgent; |
474 | - if ($.browser.msie || ($ua.match(/(iPod|iPhone|iPad|android)/i))) { | 474 | + if ($.browser.msie) { |
475 | dataText = localStorage.getItem("text"); | 475 | dataText = localStorage.getItem("text"); |
476 | localStorage.setItem("text", ''); | 476 | localStorage.setItem("text", ''); |
477 | } | 477 | } |
@@ -1051,9 +1051,6 @@ AIA.directive('draggable', function () { | @@ -1051,9 +1051,6 @@ AIA.directive('draggable', function () { | ||
1051 | link: function ($scope, element, attrs) { | 1051 | link: function ($scope, element, attrs) { |
1052 | element[0].addEventListener('dragstart', $scope.handleDragStart, false); | 1052 | element[0].addEventListener('dragstart', $scope.handleDragStart, false); |
1053 | element[0].addEventListener('dragend', $scope.handleDragEnd, false); | 1053 | element[0].addEventListener('dragend', $scope.handleDragEnd, false); |
1054 | - | ||
1055 | - element[0].addEventListener('touchstart', $scope.handleDragStart, false); | ||
1056 | - element[0].addEventListener('touchend', $scope.handleDragEnd, false); | ||
1057 | } | 1054 | } |
1058 | } | 1055 | } |
1059 | }); | 1056 | }); |
@@ -1063,9 +1060,6 @@ AIA.directive('droppable', function () { | @@ -1063,9 +1060,6 @@ AIA.directive('droppable', function () { | ||
1063 | link: function ($scope, element, attrs) { | 1060 | link: function ($scope, element, attrs) { |
1064 | element[0].addEventListener('drop', $scope.handleDrop, false); | 1061 | element[0].addEventListener('drop', $scope.handleDrop, false); |
1065 | element[0].addEventListener('dragover', $scope.handleDragOver, false); | 1062 | element[0].addEventListener('dragover', $scope.handleDragOver, false); |
1066 | - | ||
1067 | - element[0].addEventListener('touchmove', $scope.handleDragOver, false); | ||
1068 | - element[0].addEventListener('touchend', $scope.handleDrop, false); | ||
1069 | } | 1063 | } |
1070 | } | 1064 | } |
1071 | }); | 1065 | }); |
400-SOURCECODE/AIAHTML5.Web/app/views/LabExerc/LabExerc-view.html
400-SOURCECODE/AIAHTML5.Web/libs/DragDropTouch.js
0 → 100644
1 | +var DragDropTouch; | ||
2 | +(function (DragDropTouch_1) { | ||
3 | + 'use strict'; | ||
4 | + /** | ||
5 | + * Object used to hold the data that is being dragged during drag and drop operations. | ||
6 | + * | ||
7 | + * It may hold one or more data items of different types. For more information about | ||
8 | + * drag and drop operations and data transfer objects, see | ||
9 | + * <a href="https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer">HTML Drag and Drop API</a>. | ||
10 | + * | ||
11 | + * This object is created automatically by the @see:DragDropTouch singleton and is | ||
12 | + * accessible through the @see:dataTransfer property of all drag events. | ||
13 | + */ | ||
14 | + var DataTransfer = (function () { | ||
15 | + function DataTransfer() { | ||
16 | + this._dropEffect = 'move'; | ||
17 | + this._effectAllowed = 'all'; | ||
18 | + this._data = {}; | ||
19 | + } | ||
20 | + Object.defineProperty(DataTransfer.prototype, "dropEffect", { | ||
21 | + /** | ||
22 | + * Gets or sets the type of drag-and-drop operation currently selected. | ||
23 | + * The value must be 'none', 'copy', 'link', or 'move'. | ||
24 | + */ | ||
25 | + get: function () { | ||
26 | + return this._dropEffect; | ||
27 | + }, | ||
28 | + set: function (value) { | ||
29 | + this._dropEffect = value; | ||
30 | + }, | ||
31 | + enumerable: true, | ||
32 | + configurable: true | ||
33 | + }); | ||
34 | + Object.defineProperty(DataTransfer.prototype, "effectAllowed", { | ||
35 | + /** | ||
36 | + * Gets or sets the types of operations that are possible. | ||
37 | + * Must be one of 'none', 'copy', 'copyLink', 'copyMove', 'link', | ||
38 | + * 'linkMove', 'move', 'all' or 'uninitialized'. | ||
39 | + */ | ||
40 | + get: function () { | ||
41 | + return this._effectAllowed; | ||
42 | + }, | ||
43 | + set: function (value) { | ||
44 | + this._effectAllowed = value; | ||
45 | + }, | ||
46 | + enumerable: true, | ||
47 | + configurable: true | ||
48 | + }); | ||
49 | + Object.defineProperty(DataTransfer.prototype, "types", { | ||
50 | + /** | ||
51 | + * Gets an array of strings giving the formats that were set in the @see:dragstart event. | ||
52 | + */ | ||
53 | + get: function () { | ||
54 | + return Object.keys(this._data); | ||
55 | + }, | ||
56 | + enumerable: true, | ||
57 | + configurable: true | ||
58 | + }); | ||
59 | + /** | ||
60 | + * Removes the data associated with a given type. | ||
61 | + * | ||
62 | + * The type argument is optional. If the type is empty or not specified, the data | ||
63 | + * associated with all types is removed. If data for the specified type does not exist, | ||
64 | + * or the data transfer contains no data, this method will have no effect. | ||
65 | + * | ||
66 | + * @param type Type of data to remove. | ||
67 | + */ | ||
68 | + DataTransfer.prototype.clearData = function (type) { | ||
69 | + if (type != null) { | ||
70 | + delete this._data[type]; | ||
71 | + } | ||
72 | + else { | ||
73 | + this._data = null; | ||
74 | + } | ||
75 | + }; | ||
76 | + /** | ||
77 | + * Retrieves the data for a given type, or an empty string if data for that type does | ||
78 | + * not exist or the data transfer contains no data. | ||
79 | + * | ||
80 | + * @param type Type of data to retrieve. | ||
81 | + */ | ||
82 | + DataTransfer.prototype.getData = function (type) { | ||
83 | + return this._data[type] || ''; | ||
84 | + }; | ||
85 | + /** | ||
86 | + * Set the data for a given type. | ||
87 | + * | ||
88 | + * For a list of recommended drag types, please see | ||
89 | + * https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Recommended_Drag_Types. | ||
90 | + * | ||
91 | + * @param type Type of data to add. | ||
92 | + * @param value Data to add. | ||
93 | + */ | ||
94 | + DataTransfer.prototype.setData = function (type, value) { | ||
95 | + this._data[type] = value; | ||
96 | + }; | ||
97 | + /** | ||
98 | + * Set the image to be used for dragging if a custom one is desired. | ||
99 | + * | ||
100 | + * @param img An image element to use as the drag feedback image. | ||
101 | + * @param offsetX The horizontal offset within the image. | ||
102 | + * @param offsetY The vertical offset within the image. | ||
103 | + */ | ||
104 | + DataTransfer.prototype.setDragImage = function (img, offsetX, offsetY) { | ||
105 | + var ddt = DragDropTouch._instance; | ||
106 | + ddt._imgCustom = img; | ||
107 | + ddt._imgOffset = { x: offsetX, y: offsetY }; | ||
108 | + }; | ||
109 | + return DataTransfer; | ||
110 | + }()); | ||
111 | + DragDropTouch_1.DataTransfer = DataTransfer; | ||
112 | + /** | ||
113 | + * Defines a class that adds support for touch-based HTML5 drag/drop operations. | ||
114 | + * | ||
115 | + * The @see:DragDropTouch class listens to touch events and raises the | ||
116 | + * appropriate HTML5 drag/drop events as if the events had been caused | ||
117 | + * by mouse actions. | ||
118 | + * | ||
119 | + * The purpose of this class is to enable using existing, standard HTML5 | ||
120 | + * drag/drop code on mobile devices running IOS or Android. | ||
121 | + * | ||
122 | + * To use, include the DragDropTouch.js file on the page. The class will | ||
123 | + * automatically start monitoring touch events and will raise the HTML5 | ||
124 | + * drag drop events (dragstart, dragenter, dragleave, drop, dragend) which | ||
125 | + * should be handled by the application. | ||
126 | + * | ||
127 | + * For details and examples on HTML drag and drop, see | ||
128 | + * https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Drag_operations. | ||
129 | + */ | ||
130 | + var DragDropTouch = (function () { | ||
131 | + /** | ||
132 | + * Initializes the single instance of the @see:DragDropTouch class. | ||
133 | + */ | ||
134 | + function DragDropTouch() { | ||
135 | + this._lastClick = 0; | ||
136 | + // enforce singleton pattern | ||
137 | + if (DragDropTouch._instance) { | ||
138 | + throw 'DragDropTouch instance already created.'; | ||
139 | + } | ||
140 | + // detect passive event support | ||
141 | + // https://github.com/Modernizr/Modernizr/issues/1894 | ||
142 | + var supportsPassive = false; | ||
143 | + document.addEventListener('test', function () { }, { | ||
144 | + get passive() { | ||
145 | + supportsPassive = true; | ||
146 | + return true; | ||
147 | + } | ||
148 | + }); | ||
149 | + // listen to touch events | ||
150 | + if ('ontouchstart' in document) { | ||
151 | + var d = document, ts = this._touchstart.bind(this), tm = this._touchmove.bind(this), te = this._touchend.bind(this), opt = supportsPassive ? { passive: false, capture: false } : false; | ||
152 | + d.addEventListener('touchstart', ts, opt); | ||
153 | + d.addEventListener('touchmove', tm, opt); | ||
154 | + d.addEventListener('touchend', te); | ||
155 | + d.addEventListener('touchcancel', te); | ||
156 | + } | ||
157 | + } | ||
158 | + /** | ||
159 | + * Gets a reference to the @see:DragDropTouch singleton. | ||
160 | + */ | ||
161 | + DragDropTouch.getInstance = function () { | ||
162 | + return DragDropTouch._instance; | ||
163 | + }; | ||
164 | + // ** event handlers | ||
165 | + DragDropTouch.prototype._touchstart = function (e) { | ||
166 | + var _this = this; | ||
167 | + if (this._shouldHandle(e)) { | ||
168 | + // raise double-click and prevent zooming | ||
169 | + if (Date.now() - this._lastClick < DragDropTouch._DBLCLICK) { | ||
170 | + if (this._dispatchEvent(e, 'dblclick', e.target)) { | ||
171 | + e.preventDefault(); | ||
172 | + this._reset(); | ||
173 | + return; | ||
174 | + } | ||
175 | + } | ||
176 | + // clear all variables | ||
177 | + this._reset(); | ||
178 | + // get nearest draggable element | ||
179 | + var src = this._closestDraggable(e.target); | ||
180 | + if (src) { | ||
181 | + // give caller a chance to handle the hover/move events | ||
182 | + if (!this._dispatchEvent(e, 'mousemove', e.target) && | ||
183 | + !this._dispatchEvent(e, 'mousedown', e.target)) { | ||
184 | + // get ready to start dragging | ||
185 | + this._dragSource = src; | ||
186 | + this._ptDown = this._getPoint(e); | ||
187 | + this._lastTouch = e; | ||
188 | + e.preventDefault(); | ||
189 | + // show context menu if the user hasn't started dragging after a while | ||
190 | + setTimeout(function () { | ||
191 | + if (_this._dragSource == src && _this._img == null) { | ||
192 | + if (_this._dispatchEvent(e, 'contextmenu', src)) { | ||
193 | + _this._reset(); | ||
194 | + } | ||
195 | + } | ||
196 | + }, DragDropTouch._CTXMENU); | ||
197 | + } | ||
198 | + } | ||
199 | + } | ||
200 | + }; | ||
201 | + DragDropTouch.prototype._touchmove = function (e) { | ||
202 | + if (this._shouldHandle(e)) { | ||
203 | + // see if target wants to handle move | ||
204 | + var target = this._getTarget(e); | ||
205 | + if (this._dispatchEvent(e, 'mousemove', target)) { | ||
206 | + this._lastTouch = e; | ||
207 | + e.preventDefault(); | ||
208 | + return; | ||
209 | + } | ||
210 | + // start dragging | ||
211 | + if (this._dragSource && !this._img) { | ||
212 | + var delta = this._getDelta(e); | ||
213 | + if (delta > DragDropTouch._THRESHOLD) { | ||
214 | + this._dispatchEvent(e, 'dragstart', this._dragSource); | ||
215 | + this._createImage(e); | ||
216 | + this._dispatchEvent(e, 'dragenter', target); | ||
217 | + } | ||
218 | + } | ||
219 | + // continue dragging | ||
220 | + if (this._img) { | ||
221 | + this._lastTouch = e; | ||
222 | + e.preventDefault(); // prevent scrolling | ||
223 | + if (target != this._lastTarget) { | ||
224 | + this._dispatchEvent(this._lastTouch, 'dragleave', this._lastTarget); | ||
225 | + this._dispatchEvent(e, 'dragenter', target); | ||
226 | + this._lastTarget = target; | ||
227 | + } | ||
228 | + this._moveImage(e); | ||
229 | + this._dispatchEvent(e, 'dragover', target); | ||
230 | + } | ||
231 | + } | ||
232 | + }; | ||
233 | + DragDropTouch.prototype._touchend = function (e) { | ||
234 | + if (this._shouldHandle(e)) { | ||
235 | + // see if target wants to handle up | ||
236 | + if (this._dispatchEvent(this._lastTouch, 'mouseup', e.target)) { | ||
237 | + e.preventDefault(); | ||
238 | + return; | ||
239 | + } | ||
240 | + // user clicked the element but didn't drag, so clear the source and simulate a click | ||
241 | + if (!this._img) { | ||
242 | + this._dragSource = null; | ||
243 | + this._dispatchEvent(this._lastTouch, 'click', e.target); | ||
244 | + this._lastClick = Date.now(); | ||
245 | + } | ||
246 | + // finish dragging | ||
247 | + this._destroyImage(); | ||
248 | + if (this._dragSource) { | ||
249 | + if (e.type.indexOf('cancel') < 0) { | ||
250 | + this._dispatchEvent(this._lastTouch, 'drop', this._lastTarget); | ||
251 | + } | ||
252 | + this._dispatchEvent(this._lastTouch, 'dragend', this._dragSource); | ||
253 | + this._reset(); | ||
254 | + } | ||
255 | + } | ||
256 | + }; | ||
257 | + // ** utilities | ||
258 | + // ignore events that have been handled or that involve more than one touch | ||
259 | + DragDropTouch.prototype._shouldHandle = function (e) { | ||
260 | + return e && | ||
261 | + !e.defaultPrevented && | ||
262 | + e.touches && e.touches.length < 2; | ||
263 | + }; | ||
264 | + // clear all members | ||
265 | + DragDropTouch.prototype._reset = function () { | ||
266 | + this._destroyImage(); | ||
267 | + this._dragSource = null; | ||
268 | + this._lastTouch = null; | ||
269 | + this._lastTarget = null; | ||
270 | + this._ptDown = null; | ||
271 | + this._dataTransfer = new DataTransfer(); | ||
272 | + }; | ||
273 | + // get point for a touch event | ||
274 | + DragDropTouch.prototype._getPoint = function (e, page) { | ||
275 | + if (e && e.touches) { | ||
276 | + e = e.touches[0]; | ||
277 | + } | ||
278 | + return { x: page ? e.pageX : e.clientX, y: page ? e.pageY : e.clientY }; | ||
279 | + }; | ||
280 | + // get distance between the current touch event and the first one | ||
281 | + DragDropTouch.prototype._getDelta = function (e) { | ||
282 | + var p = this._getPoint(e); | ||
283 | + return Math.abs(p.x - this._ptDown.x) + Math.abs(p.y - this._ptDown.y); | ||
284 | + }; | ||
285 | + // get the element at a given touch event | ||
286 | + DragDropTouch.prototype._getTarget = function (e) { | ||
287 | + var pt = this._getPoint(e), el = document.elementFromPoint(pt.x, pt.y); | ||
288 | + while (el && getComputedStyle(el).pointerEvents == 'none') { | ||
289 | + el = el.parentElement; | ||
290 | + } | ||
291 | + return el; | ||
292 | + }; | ||
293 | + // create drag image from source element | ||
294 | + DragDropTouch.prototype._createImage = function (e) { | ||
295 | + // just in case... | ||
296 | + if (this._img) { | ||
297 | + this._destroyImage(); | ||
298 | + } | ||
299 | + // create drag image from custom element or drag source | ||
300 | + var src = this._imgCustom || this._dragSource; | ||
301 | + this._img = src.cloneNode(true); | ||
302 | + this._copyStyle(src, this._img); | ||
303 | + this._img.style.top = this._img.style.left = '-9999px'; | ||
304 | + // if creating from drag source, apply offset and opacity | ||
305 | + if (!this._imgCustom) { | ||
306 | + var rc = src.getBoundingClientRect(), pt = this._getPoint(e); | ||
307 | + this._imgOffset = { x: pt.x - rc.left, y: pt.y - rc.top }; | ||
308 | + this._img.style.opacity = DragDropTouch._OPACITY.toString(); | ||
309 | + } | ||
310 | + // add image to document | ||
311 | + this._moveImage(e); | ||
312 | + document.body.appendChild(this._img); | ||
313 | + }; | ||
314 | + // dispose of drag image element | ||
315 | + DragDropTouch.prototype._destroyImage = function () { | ||
316 | + if (this._img && this._img.parentElement) { | ||
317 | + this._img.parentElement.removeChild(this._img); | ||
318 | + } | ||
319 | + this._img = null; | ||
320 | + this._imgCustom = null; | ||
321 | + }; | ||
322 | + // move the drag image element | ||
323 | + DragDropTouch.prototype._moveImage = function (e) { | ||
324 | + var _this = this; | ||
325 | + if (this._img) { | ||
326 | + requestAnimationFrame(function () { | ||
327 | + var pt = _this._getPoint(e, true), s = _this._img.style; | ||
328 | + s.position = 'absolute'; | ||
329 | + s.pointerEvents = 'none'; | ||
330 | + s.zIndex = '999999'; | ||
331 | + s.left = Math.round(pt.x - _this._imgOffset.x) + 'px'; | ||
332 | + s.top = Math.round(pt.y - _this._imgOffset.y) + 'px'; | ||
333 | + }); | ||
334 | + } | ||
335 | + }; | ||
336 | + // copy properties from an object to another | ||
337 | + DragDropTouch.prototype._copyProps = function (dst, src, props) { | ||
338 | + for (var i = 0; i < props.length; i++) { | ||
339 | + var p = props[i]; | ||
340 | + dst[p] = src[p]; | ||
341 | + } | ||
342 | + }; | ||
343 | + DragDropTouch.prototype._copyStyle = function (src, dst) { | ||
344 | + // remove potentially troublesome attributes | ||
345 | + DragDropTouch._rmvAtts.forEach(function (att) { | ||
346 | + dst.removeAttribute(att); | ||
347 | + }); | ||
348 | + // copy canvas content | ||
349 | + if (src instanceof HTMLCanvasElement) { | ||
350 | + var cSrc = src, cDst = dst; | ||
351 | + cDst.width = cSrc.width; | ||
352 | + cDst.height = cSrc.height; | ||
353 | + cDst.getContext('2d').drawImage(cSrc, 0, 0); | ||
354 | + } | ||
355 | + // copy style (without transitions) | ||
356 | + var cs = getComputedStyle(src); | ||
357 | + for (var i = 0; i < cs.length; i++) { | ||
358 | + var key = cs[i]; | ||
359 | + if (key.indexOf('transition') < 0) { | ||
360 | + dst.style[key] = cs[key]; | ||
361 | + } | ||
362 | + } | ||
363 | + dst.style.pointerEvents = 'none'; | ||
364 | + // and repeat for all children | ||
365 | + for (var i = 0; i < src.children.length; i++) { | ||
366 | + this._copyStyle(src.children[i], dst.children[i]); | ||
367 | + } | ||
368 | + }; | ||
369 | + DragDropTouch.prototype._dispatchEvent = function (e, type, target) { | ||
370 | + if (e && target) { | ||
371 | + var evt = document.createEvent('Event'), t = e.touches ? e.touches[0] : e; | ||
372 | + evt.initEvent(type, true, true); | ||
373 | + evt.button = 0; | ||
374 | + evt.which = evt.buttons = 1; | ||
375 | + this._copyProps(evt, e, DragDropTouch._kbdProps); | ||
376 | + this._copyProps(evt, t, DragDropTouch._ptProps); | ||
377 | + evt.dataTransfer = this._dataTransfer; | ||
378 | + target.dispatchEvent(evt); | ||
379 | + return evt.defaultPrevented; | ||
380 | + } | ||
381 | + return false; | ||
382 | + }; | ||
383 | + // gets an element's closest draggable ancestor | ||
384 | + DragDropTouch.prototype._closestDraggable = function (e) { | ||
385 | + for (; e; e = e.parentElement) { | ||
386 | + if (e.hasAttribute('draggable') && e.draggable) { | ||
387 | + return e; | ||
388 | + } | ||
389 | + } | ||
390 | + return null; | ||
391 | + }; | ||
392 | + return DragDropTouch; | ||
393 | + }()); | ||
394 | + /*private*/ DragDropTouch._instance = new DragDropTouch(); // singleton | ||
395 | + // constants | ||
396 | + DragDropTouch._THRESHOLD = 5; // pixels to move before drag starts | ||
397 | + DragDropTouch._OPACITY = 0.5; // drag image opacity | ||
398 | + DragDropTouch._DBLCLICK = 500; // max ms between clicks in a double click | ||
399 | + DragDropTouch._CTXMENU = 900; // ms to hold before raising 'contextmenu' event | ||
400 | + // copy styles/attributes from drag source to drag image element | ||
401 | + DragDropTouch._rmvAtts = 'id,class,style,draggable'.split(','); | ||
402 | + // synthesize and dispatch an event | ||
403 | + // returns true if the event has been handled (e.preventDefault == true) | ||
404 | + DragDropTouch._kbdProps = 'altKey,ctrlKey,metaKey,shiftKey'.split(','); | ||
405 | + DragDropTouch._ptProps = 'pageX,pageY,clientX,clientY,screenX,screenY'.split(','); | ||
406 | + DragDropTouch_1.DragDropTouch = DragDropTouch; | ||
407 | +})(DragDropTouch || (DragDropTouch = {})); | ||
0 | \ No newline at end of file | 408 | \ No newline at end of file |