Commit 000be1260acc9f7077982eb52cda3afd89bdf633
1 parent
a7eab5c5
changed options poition from left-right to bottom.
This fixes the issue of dropping back options and also ipad ovelap options on image issue
Showing
4 changed files
with
504 additions
and
93 deletions
400-SOURCECODE/AIAHTML5.Web/app/controllers/LabExercController.js
... | ... | @@ -175,8 +175,10 @@ function ($scope, $rootScope, pages, log, $http,$timeout, DataService, $filter, |
175 | 175 | $scope.Title = result.LabExercise[index].Questions[index1].Title; |
176 | 176 | $scope.Imagepath = keywords.labexercise + "/" + result.LabExercise[index].Questions[index1].ImagePath; |
177 | 177 | } |
178 | - $scope.ShowHideDiv(result.LabExercise[index].Questions[index1].Options[0].textalign); | |
179 | - | |
178 | + //$scope.ShowHideDiv(result.LabExercise[index].Questions[index1].Options[0].textalign); | |
179 | + | |
180 | + $scope.ShowHideDiv("bottom"); | |
181 | + | |
180 | 182 | } |
181 | 183 | }); |
182 | 184 | $timeout(function () |
... | ... | @@ -398,10 +400,10 @@ function ($scope, $rootScope, pages, log, $http,$timeout, DataService, $filter, |
398 | 400 | |
399 | 401 | |
400 | 402 | $scope.handleDragStart = function (e) { |
401 | - | |
403 | + | |
402 | 404 | this.style.opacity = '0.4'; |
403 | 405 | var $ua = navigator.userAgent; |
404 | - if ($.browser.msie || ($ua.match(/(iPod|iPhone|iPad|android)/i))) { | |
406 | + if ($.browser.msie) { | |
405 | 407 | localStorage.setItem("text", this.innerHTML); |
406 | 408 | } |
407 | 409 | else |
... | ... | @@ -410,6 +412,8 @@ function ($scope, $rootScope, pages, log, $http,$timeout, DataService, $filter, |
410 | 412 | } |
411 | 413 | |
412 | 414 | $scope.dragableId = $(this).attr("Id"); |
415 | + $scope.a = $scope.dragableId; | |
416 | + | |
413 | 417 | console.log($scope.dragableId); |
414 | 418 | $scope.dragableText = $("#" + $scope.dragableId).text(); |
415 | 419 | // alert($("#" + $scope.dragableId).text()); |
... | ... | @@ -451,12 +455,13 @@ function ($scope, $rootScope, pages, log, $http,$timeout, DataService, $filter, |
451 | 455 | }; |
452 | 456 | |
453 | 457 | $scope.handleDrop = function (e) { |
458 | + | |
454 | 459 | e.preventDefault(); |
455 | 460 | e.stopPropagation(); |
456 | 461 | var x = $("#droppable").offset(); |
457 | 462 | |
458 | 463 | var id = $(this).attr("id"); |
459 | - | |
464 | + | |
460 | 465 | // $scope.dragableText = $("#" + $scope.dragableId).text(); |
461 | 466 | |
462 | 467 | //$rootScope.selectedDivArray.push({ |
... | ... | @@ -471,7 +476,7 @@ function ($scope, $rootScope, pages, log, $http,$timeout, DataService, $filter, |
471 | 476 | |
472 | 477 | var keywords = $location.search(); |
473 | 478 | var $ua = navigator.userAgent; |
474 | - if ($.browser.msie || ($ua.match(/(iPod|iPhone|iPad|android)/i))) { | |
479 | + if ($.browser.msie) { | |
475 | 480 | dataText = localStorage.getItem("text"); |
476 | 481 | localStorage.setItem("text", ''); |
477 | 482 | } |
... | ... | @@ -481,30 +486,27 @@ function ($scope, $rootScope, pages, log, $http,$timeout, DataService, $filter, |
481 | 486 | |
482 | 487 | if (id == "divoptions" || id == "divleft" || id == "divright") { |
483 | 488 | |
484 | - var item = $('#' + $scope.dragableId).html(); | |
485 | - var rindex = $scope.DraggedList.indexOf(item); | |
489 | + $scope.item = $('#' + $scope.dragableId).html(); | |
490 | + var rindex = $scope.DraggedList.indexOf($scope.item); | |
491 | + console.log($scope.DraggedList); | |
486 | 492 | var labExerciseModulePath = '~/../content/data/json/le/' + keywords.labexercise + '.json'; |
487 | 493 | DataService.getAnotherJson(labExerciseModulePath).then( |
488 | 494 | function (result) { |
489 | - | |
490 | 495 | $.each(result.LabExercise, function (index, value) { |
491 | 496 | if (result.LabExercise[index].Slug == keywords.labexercise) { |
492 | 497 | $.each(result.LabExercise[index].Questions, function (index1, value1) { |
493 | 498 | if (result.LabExercise[index].Questions[index1].Number == $scope.quiznumber) { |
494 | 499 | var Options = result.LabExercise[index].Questions[index1].Options; |
495 | - | |
496 | - | |
497 | 500 | $.each(Options, function (inx, value2) { |
498 | - if (Options[inx].OptionTitle == item) { | |
501 | + if (Options[inx].OptionTitle == $scope.item) { | |
499 | 502 | if ($scope.DraggedList != null) { |
500 | 503 | $.each($scope.DraggedList, function (inx1, value3) { |
501 | 504 | $scope.UserAttempt.push({ "BlankBoxName": id.split('-')[1], "OptionName": $scope.dragableId.split('-')[1] }); |
502 | - //var balnkBox=id.split('-')[1]; | |
503 | - //$scope.UserAttempt.push({balnkBox :+ $scope.dragableId.split('-')[1] }); | |
504 | - if ($scope.DraggedList[inx1].Value == item) { | |
505 | + if ($scope.DraggedList[inx1].id == $scope.a.split('-')[1]) { | |
506 | + $scope.b = $scope.DraggedList[inx1].blockID; | |
505 | 507 | $scope.DraggedList.splice(inx1, 1); |
506 | - $('#block-' + Options[inx].OptionNumber).css("display", "block"); | |
507 | - $('#blockans-' + Options[inx].OptionNumber).css("background-color", "transparent !important"); | |
508 | + $('#' + $scope.b).css({ "display": "block", "color": "#000000!important" }); | |
509 | + $('#blockans-' + $scope.b.split('-')[1]).css("background-color","transparent !important"); | |
508 | 510 | } |
509 | 511 | }); |
510 | 512 | } |
... | ... | @@ -526,7 +528,6 @@ function ($scope, $rootScope, pages, log, $http,$timeout, DataService, $filter, |
526 | 528 | $(this).each(function (key, value) { |
527 | 529 | |
528 | 530 | var droppedID = $(this).attr("id").split("-"); |
529 | - | |
530 | 531 | if (droppedID[0] == 'blockbox') { |
531 | 532 | var labExerciseModulePath = '~/../content/data/json/le/' + keywords.labexercise + '.json'; |
532 | 533 | DataService.getAnotherJson(labExerciseModulePath).then( |
... | ... | @@ -551,7 +552,9 @@ function ($scope, $rootScope, pages, log, $http,$timeout, DataService, $filter, |
551 | 552 | continue; |
552 | 553 | } |
553 | 554 | |
554 | - if ($scope.DraggedList[i].Value == dataText) { | |
555 | + | |
556 | + //if ($scope.DraggedList[i].Value == dataText) { | |
557 | + if ($scope.DraggedList[i].id == id.split('-')[1]) { | |
555 | 558 | $scope.DraggedList.splice(i, 1); |
556 | 559 | } |
557 | 560 | } |
... | ... | @@ -559,10 +562,10 @@ function ($scope, $rootScope, pages, log, $http,$timeout, DataService, $filter, |
559 | 562 | // $scope.UserAttempt.push({ "BlankBoxName": id.split('-')[1], "OptionName": $scope.dragableId.split('-')[1] }); |
560 | 563 | //$scope.UserAttempt.push({ balnkBox: +$scope.dragableId.split('-')[1] }); |
561 | 564 | $scope.UserAttempt.push({ "BlankBoxName": id.split('-')[1], "OptionName": $scope.dragableId.split('-')[1] }); |
562 | - $scope.DraggedList.push({ "id": id.split('-')[1], "optionName": id.split('-')[1], "Value": dataText, "topcoord": Options[inx].topcoord, "leftcoord": Options[inx].leftcoord }); | |
565 | + $scope.DraggedList.push({ "blockID": $scope.dragableId, "id": id.split('-')[1], "optionName": id.split('-')[1], "Value": dataText, "topcoord": Options[inx].topcoord, "leftcoord": Options[inx].leftcoord }); | |
563 | 566 | $('#' + $scope.dragableId).css("display", "none"); |
564 | 567 | $('#blockans-' + Options[inx].OptionNumber).css("background-color", "transparent !important"); |
565 | - | |
568 | + $scope.a = $scope.dragableId; | |
566 | 569 | } |
567 | 570 | }); |
568 | 571 | } |
... | ... | @@ -1078,8 +1081,8 @@ AIA.directive('draggable', function () { |
1078 | 1081 | element[0].addEventListener('dragstart', $scope.handleDragStart, false); |
1079 | 1082 | element[0].addEventListener('dragend', $scope.handleDragEnd, false); |
1080 | 1083 | |
1081 | - element[0].addEventListener('touchstart', $scope.handleDragStart, false); | |
1082 | - element[0].addEventListener('touchend', $scope.handleDragEnd, false); | |
1084 | + // element[0].addEventListener('touchstart', $scope.handleDragStart, false); | |
1085 | + // element[0].addEventListener('touchend', $scope.handleDragEnd, false); | |
1083 | 1086 | } |
1084 | 1087 | } |
1085 | 1088 | }); |
... | ... | @@ -1090,8 +1093,8 @@ AIA.directive('droppable', function () { |
1090 | 1093 | element[0].addEventListener('drop', $scope.handleDrop, false); |
1091 | 1094 | element[0].addEventListener('dragover', $scope.handleDragOver, false); |
1092 | 1095 | |
1093 | - element[0].addEventListener('touchmove', $scope.handleDragOver, false); | |
1094 | - element[0].addEventListener('touchend', $scope.handleDrop, false); | |
1096 | + // element[0].addEventListener('touchmove', $scope.handleDragOver, false); | |
1097 | + // element[0].addEventListener('touchend', $scope.handleDrop, false); | |
1095 | 1098 | } |
1096 | 1099 | } |
1097 | 1100 | }); | ... | ... |
400-SOURCECODE/AIAHTML5.Web/app/views/LabExerc/LabExerc-view.html
400-SOURCECODE/AIAHTML5.Web/app/views/LabExerc/lab-exercises-detail.html
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | <div class="" ng-init="InitializeLabExercise()"> |
6 | 6 | <div class="col-sm-12 pageHeading" id="LabExPageHeading"> |
7 | 7 | <!--<button type="button" class="btn btn-default pull-left toggleBar hidden-lg"> <i class="fa fa-bars"></i> </button> |
8 | - <div class=" pull-left toggleBar toggleHeadingButton" data-toggle="tooltip" data-placement="top" title="Show/Hide Sidebar"> <i class="fa fa-bars"></i> </div>--> | |
8 | + <div class=" pull-left toggleBar toggleHeadingButton" data-toggle="tooltip" data-placement="top" title="Show/Hide Sidebar"> <i class="fa fa-bars"></i> </div>--> | |
9 | 9 | <h4 class="pull-left">Lab Exercise - {{LabExerciseName}}</h4> |
10 | 10 | <div class="pull-right btn-group paddTop4"> <a href="#" class="btn btn-xs btn-default" ng-click="minLabExPanel()"><i class="fa fa-minus"></i></a> <a href="#" class="btn btn-xs btn-default"><i class="fa fa-clone"></i></a> <a href="lab-exercises" ng-click="IsVisible()" class="btn btn-xs btn-default"><i class="fa fa-close"></i></a> </div> |
11 | 11 | <div class="clearfix"></div> |
... | ... | @@ -22,7 +22,7 @@ |
22 | 22 | |
23 | 23 | <div class="container-fluid main-full"> |
24 | 24 | <div class="row"> |
25 | - <div class="panel panel-default" id="questionHtml"> | |
25 | + <div class="panel panel-default" id="questionHtml" style="margin-bottom:0;"> | |
26 | 26 | <div class="col-xs-12 panel-heading"> |
27 | 27 | <div class="col-xs-3" style="padding-left:5px;"> |
28 | 28 | {{activityTitle}} |
... | ... | @@ -38,34 +38,34 @@ |
38 | 38 | <div ng-bind-html="deliberatelyTrustDangerousSnippet(optionbox.QuizText)"></div> |
39 | 39 | </div> |
40 | 40 | <!--<ul> |
41 | - <li ng-repeat="optionbox in LabExerciseModules.OptionBox" droppable="true" ng-bind-html="'{{optionbox.QuizText}}' | to_trusted"></li> | |
42 | - </ul>--> | |
41 | + <li ng-repeat="optionbox in LabExerciseModules.OptionBox" droppable="true" ng-bind-html="'{{optionbox.QuizText}}' | to_trusted"></li> | |
42 | + </ul>--> | |
43 | 43 | </div> |
44 | 44 | <div align="center" class="dragger"> |
45 | - <div class="col-sm-1" style="padding-top: 150px; height: 500px; " id="divleft" droppable="true"> | |
46 | - <div draggable="true" ng-repeat="option in LabExerciseModules.Options | filter:{'textalign':'left'}" ng-style="{'width': '150px', 'height':'40px','font-size':'8px;','valign':'middle','text-align':'center', 'vertical-align:middle','background-color': '#808080','margin':'10px !important','float':'{{option.textalign}}'} " style="margin-bottom: 10px !important; width: 180px; z-index:9;" class="thumbnail caption col-sm-2 col-lg-3 ui-draggable marginR5 " id="block-{{option.OptionNumber}}">{{option.OptionTitle}}</div> | |
47 | - </div> | |
48 | - <div class="col-sm-9"> | |
49 | - <div style="position: relative; margin-left: 85px;" id="imgdiv"> | |
45 | + <!--<div class="col-sm-2" style="padding-top: 150px; height: 500px; " id="divleft" droppable="true"> | |
46 | + <div draggable="true" ng-repeat="option in LabExerciseModules.Options | filter:{'textalign':'left'}" ng-style="{'width': '150px', 'height':'40px','font-size':'8px;','valign':'middle','text-align':'center', 'vertical-align:middle','background-color': '#808080','margin':'10px !important','float':'{{option.textalign}}'} " style="margin-bottom: 10px !important; width: 180px; z-index:9;" class="thumbnail caption col-sm-2 col-lg-3 ui-draggable marginR5 " id="block-{{option.OptionNumber}}">{{option.OptionTitle}}</div> | |
47 | + </div>--> | |
48 | + <div class="col-sm-12"> | |
49 | + <div style="position: relative;" id="imgdiv"> | |
50 | 50 | <div id="imgblock"> |
51 | - <img id="droppable" ng-src="content/images/LE/{{Imagepath}}" alt="" ng-click="onClick()" ondragstart="return false;" imageonload /> | |
51 | + <img id="droppable" ng-src="content/images/LE/{{Imagepath}}" alt="" ng-click="onClick()" ondragstart="return false;" imageonload /> | |
52 | 52 | </div> |
53 | 53 | |
54 | 54 | <div ng-show="IsVisible" ng-repeat="optionbox in LabExerciseModules.OptionBox" droppable="true" class="droppable ui-droppable options" id="blockbox-{{optionbox.BoxName}}" ng-style="{'top':{{optionbox.topcoord}}, 'left':{{optionbox.leftcoord}},'position': 'absolute', 'width': '155px', 'height':'30px', 'border':'0px solid #333', 'background': '#E8E8E8' }">{{optionbox.Answervalue}}</div> |
55 | 55 | <div draggable="true" ng-repeat="ans in DraggedList" droppable="true" class="droppable ui-droppable answerdroppable" id="blockans-{{ans.id}}" ng-style="{'top':{{ans.topcoord}}, 'left':{{ans.leftcoord}},'position': 'absolute', 'width': '158px', 'height':'30px', 'border':'0px solid #333', 'background': 'transparent','font-size': '12px','border-color':'#FF0000','padding-top':'5px'}">{{ans.Value}}</div> |
56 | 56 | </div> |
57 | 57 | |
58 | - <div class="col-sm-12" style="margin-left: 215px; margin-top: 10px; height:80px;" id="divoptions" droppable="true"> | |
59 | - <!--<div class="col-sm-3 col-lg-3 ui-draggable" >--> | |
60 | - <div draggable="true" ng-repeat="option in LabExerciseModules.Options | filter:{'textalign':'bottom'}" ng-style="{'width': '150px', 'height':'40px','font-size':'8px;','valign':'middle','text-align':'center', 'vertical-align:middle','background-color': '#808080','margin':'5px !important','float':'{{option.textalign}}'} " style="margin-bottom: 5px !important; width: 180px;" class="thumbnail caption col-sm-2 col-lg-3 ui-draggable marginR5 " id="block-{{option.OptionNumber}}">{{option.OptionTitle}}</div> | |
61 | - <!--</div>--> | |
58 | + <div class="col-sm-12" style=" margin-top: 20px; min-height:100px;" id="divoptions" droppable="true"> | |
59 | + <!--<div class="col-sm-3 col-lg-3 ui-draggable" >--> | |
60 | + <div draggable="true" ng-repeat="option in LabExerciseModules.Options" ng-style="{'width': '150px', 'height':'40px','font-size':'8px;','valign':'middle','text-align':'center', 'vertical-align:middle','background-color': '#808080','margin':'5px !important','float':'{{option.textalign}}'} " style="margin-bottom: 5px !important; width: 180px;" class="thumbnail caption col-sm-2 col-lg-3 ui-draggable marginR5 " id="block-{{option.OptionNumber}}">{{option.OptionTitle}}</div> | |
62 | 61 | </div> |
63 | 62 | </div> |
64 | - <div class="col-sm-1" style="padding-top: 150px; height: 500px; " id="divright" droppable="true"> | |
65 | - <div draggable="true" ng-repeat="option in LabExerciseModules.Options | filter:{'textalign':'right'}" ng-style="{'width': '150px', 'height':'40px','font-size':'8px;','valign':'middle','text-align':'center', 'vertical-align:middle','background-color': '#808080','margin':'10px !important','float':'{{option.textalign}}'} " style="margin-bottom: 10px !important; width: 180px; z-index: 9;" class="thumbnail caption col-sm-2 col-lg-3 ui-draggable marginR5 " id="block-{{option.OptionNumber}}">{{option.OptionTitle}}</div> | |
66 | - </div> | |
67 | 63 | </div> |
64 | + <!--<div class="col-sm-12" style="padding-top: 15px;min-height:100px;" id="divright" droppable="true"> | |
65 | + <div draggable="true" ng-repeat="option in LabExerciseModules.Options" ng-style="{'width': '150px', 'height':'40px','font-size':'8px;','valign':'middle','text-align':'center', 'vertical-align:middle','background-color': '#808080','margin':'10px !important','float':'{{option.textalign}}'} " style="margin-bottom: 10px !important; width: 180px; z-index: 9;" class="thumbnail caption col-sm-2 col-lg-3 ui-draggable marginR5 " id="block-{{option.OptionNumber}}">{{option.OptionTitle}}</div> | |
66 | + </div>--> | |
68 | 67 | </div> |
68 | + | |
69 | 69 | <div class="panel-footer"> |
70 | 70 | <div class="pull-left"> |
71 | 71 | <!--<p>Question <strong>{{quiznumber}}</strong> of {{TotalNumberofQuiz}}</p>--> |
... | ... | @@ -85,74 +85,74 @@ |
85 | 85 | </div> |
86 | 86 | <div class="clearfix"></div> |
87 | 87 | </div> |
88 | - | |
89 | 88 | </div> |
89 | + </div> | |
90 | 90 | |
91 | 91 | |
92 | - <div class="panel panel-default" id="submitResultHtml" style="display:none;"> | |
93 | - <div class="panel-heading"> | |
94 | - <div class="row"> | |
95 | - <div class="col-sm-4 text-left"><strong>Cardiovascula System</strong></div> | |
96 | - <div class="col-sm-4 text-center">Performace Report</div> | |
97 | - <div class="col-sm-4 text-right">Score:{{scoreResult}}% </div> | |
98 | - </div> | |
92 | + <div class="panel panel-default" id="submitResultHtml" style="display:none;"> | |
93 | + <div class="panel-heading"> | |
94 | + <div class="row"> | |
95 | + <div class="col-sm-4 text-left"><strong>Cardiovascula System</strong></div> | |
96 | + <div class="col-sm-4 text-center">Performace Report</div> | |
97 | + <div class="col-sm-4 text-right">Score:{{scoreResult}}% </div> | |
99 | 98 | </div> |
100 | - <div class="panel-body no-padding"> | |
101 | - <div class="row"> | |
102 | - <div class="col-sm-12 table-responsive "> | |
103 | - <table class="table table-hover table-condensed bg-white"> | |
104 | - <thead> | |
105 | - <tr class="active"> | |
106 | - <th class="text-center">Total Question</th> | |
107 | - <th class="text-center">Correct Answers</th> | |
108 | - <th class="text-center">Incorrect Answers</th> | |
109 | - </tr> | |
110 | - </thead> | |
111 | - <tbody> | |
112 | - <tr class="text-center"> | |
113 | - <td>{{TotalNumberofQuiz}}</td> | |
114 | - <td>{{CorrectAnswer}}</td> | |
115 | - <td>{{inCorrectAnswer}}</td> | |
116 | - </tr> | |
117 | - </tbody> | |
118 | - </table> | |
99 | + </div> | |
100 | + <div class="panel-body no-padding"> | |
101 | + <div class="row"> | |
102 | + <div class="col-sm-12 table-responsive "> | |
103 | + <table class="table table-hover table-condensed bg-white"> | |
104 | + <thead> | |
105 | + <tr class="active"> | |
106 | + <th class="text-center">Total Question</th> | |
107 | + <th class="text-center">Correct Answers</th> | |
108 | + <th class="text-center">Incorrect Answers</th> | |
109 | + </tr> | |
110 | + </thead> | |
111 | + <tbody> | |
112 | + <tr class="text-center"> | |
113 | + <td>{{TotalNumberofQuiz}}</td> | |
114 | + <td>{{CorrectAnswer}}</td> | |
115 | + <td>{{inCorrectAnswer}}</td> | |
116 | + </tr> | |
117 | + </tbody> | |
118 | + </table> | |
119 | 119 | |
120 | - </div> | |
121 | - <div class="col-sm-12 table-responsive"> | |
122 | - <table class="table table-hover table-condensed bg-white"> | |
123 | - <thead> | |
124 | - <tr class="active"> | |
125 | - <th>Question</th> | |
126 | - <th>Activity Title</th> | |
127 | - <th>Status</th> | |
128 | - <th>Action</th> | |
129 | - </tr> | |
130 | - </thead> | |
131 | - <tbody id="resultLabData"></tbody> | |
132 | - </table> | |
133 | - </div> | |
134 | 120 | </div> |
135 | - </div> | |
136 | - <div class="panel-footer"> | |
137 | - <div class="text-center"> | |
138 | - <button class="btn btn-sm btn-primary"> | |
139 | ||
140 | - </button> | |
141 | - | |
121 | + <div class="col-sm-12 table-responsive"> | |
122 | + <table class="table table-hover table-condensed bg-white"> | |
123 | + <thead> | |
124 | + <tr class="active"> | |
125 | + <th>Question</th> | |
126 | + <th>Activity Title</th> | |
127 | + <th>Status</th> | |
128 | + <th>Action</th> | |
129 | + </tr> | |
130 | + </thead> | |
131 | + <tbody id="resultLabData"></tbody> | |
132 | + </table> | |
142 | 133 | </div> |
143 | - <div class="clearfix"></div> | |
144 | 134 | </div> |
145 | - | |
146 | 135 | </div> |
136 | + <div class="panel-footer"> | |
137 | + <div class="text-center"> | |
138 | + <button class="btn btn-sm btn-primary"> | |
139 | ||
140 | + </button> | |
147 | 141 | |
142 | + </div> | |
143 | + <div class="clearfix"></div> | |
144 | + </div> | |
148 | 145 | |
149 | 146 | </div> |
147 | + | |
148 | + | |
150 | 149 | </div> |
151 | 150 | </div> |
151 | + </div> | |
152 | 152 | |
153 | 153 | |
154 | 154 | |
155 | - </div> | |
155 | +</div> | |
156 | 156 | </div> |
157 | 157 | |
158 | 158 | ... | ... |
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 | 408 | \ No newline at end of file | ... | ... |