QuizDragAndDrop.prototype = {
- init: function() {
+ init: function () {
gsap.registerPlugin(InertiaPlugin);
gsap.registerPlugin(Draggable);
},
- start: function() {
+ start: function () {
const $this = this
this.isMobile = this.quiz.resize.isMobile()
this.activeScreen = this.quiz.screens.getActiveScreen()
target = $this.activeScreen.find(".list-item:first-child"),
zone = false;
- if(move === "ARROWLEFT") {
+ if (move === "ARROWLEFT") {
zone = $this.zone1
- }else {
+ } else {
zone = $this.zone2
}
target.addClass("isValidated").next().addClass("isNext")
- $this.slapping(zone,target)
+ $this.slapping(zone, target)
- if($this.activeScreen.find(".list-item").length === 0) {
- $this.toggleScreen(0,"none")
+ if ($this.activeScreen.find(".list-item").length === 0) {
+ $this.toggleScreen(0, "none")
}
})
this.retreiveAnswer()
},
- createDraggable: function($this) {
+ createDraggable: function ($this) {
Draggable.create($this.item, {
type: $this.isMobile ? "y" : "x,y",
edgeResistance: 0.2,
inertia: false,
bounds: "#quiz",
onDragParams: [{}],
- onDrag: function() {
+ onDrag: function () {
$(".zone-1,.zone-2").removeClass("notDrag")
$(this.target).addClass("isDragging").removeClass("isNext")
})
//set rotation on desktop
- if(!$this.isMobile) {
+ if (!$this.isMobile) {
$this.rotateItem(this, direction)
}
$this.enterZone(zone)
// actions when leave zone
- if(!zone) {
+ if (!zone) {
$this.leaveZone()
}
},
- onDragEnd: function() {
+ onDragEnd: function () {
//
let zone = $this.getZoneOverlap(this.target)
let slot = false
- if(zone) {
+ if (zone) {
slot = $this.getSlotInformations(zone)
}
heightTarget = $(this.target).height()
//
- if(slot) {
+ if (slot) {
let rules = {
width: slot.w,
height: slot.h,
padding: "7px 8px",
borderRadius: "8px",
}
- if($this.isMobile) {
+ if ($this.isMobile) {
rules = {
scale: 0.8,
duration: .3,
}
gsap.timeline()
- .to(this.target, {
- ...rules,
- onStart: function () {
- target.addClass("isValidated")
- gsap.set(target.next(), {opacity: 1})
- },
- onComplete: function () {
- $this.slapping(zone,target)
- }
- })
- .to(".list .overlay", {
- y: -heightTarget,
- opacity: 0,
- onStart: function () {
- $(".list-item.isValidated").next().addClass("isNext")
- }
- }, "<")
- .to(".list .overlay", {
- y: 0,
- opacity: 1,
- duration: 0
- }, "+=0.3")
+ .to(this.target, {
+ ...rules,
+ onStart: function () {
+ target.addClass("isValidated")
+ gsap.set(target.next(), {opacity: 1})
+ },
+ onComplete: function () {
+ $this.slapping(zone, target)
+ }
+ })
+ .to(".list .overlay", {
+ y: -heightTarget,
+ opacity: 0,
+ onStart: function () {
+ $(".list-item.isValidated").next().addClass("isNext")
+ }
+ }, "<")
+ .to(".list .overlay", {
+ y: 0,
+ opacity: 1,
+ duration: 0
+ }, "+=0.3")
}
},
- onRelease: function() {
+ onRelease: function () {
//
$(".zone-1,.zone-2").addClass("notDrag")
$this.leaveZone()
//
- if(!$this.getZoneOverlap(this.target)) {
+ if (!$this.getZoneOverlap(this.target)) {
gsap.to(this.target, {
x: 0,
y: 0,
}
//
- if($this.activeScreen.find(".list-item:not(.isDragging)").length === 0) {
- $this.toggleScreen(0,"none")
+ if ($this.activeScreen.find(".list-item:not(.isDragging)").length === 0) {
+ $this.toggleScreen(0, "none")
}
$(this.target).removeClass("isDragging")
});
},
- rotateItem: function($this, direction) {
+ rotateItem: function ($this, direction) {
let rotation = 0;
- if(direction.includes("right")) {
+ if (direction.includes("right")) {
rotation = 5
} else {
rotation = -5
}
- if($this.endX === 0) {
+ if ($this.endX === 0) {
rotation = 0
}
})
},
- enterZone: function(zone) {
+ enterZone: function (zone) {
$(zone).addClass("active")
},
- leaveZone: function() {
+ leaveZone: function () {
$(".zone-1,.zone-2").removeClass("active").removeClass("isDragging")
},
- slapping: function(zone,target) {
+ slapping: function (zone, target) {
const $this = this
- let text = target.text(),
- id = "answer-"+target.data("id")
+ let title = target.find('h4').text();
+ let text = target.find('p').text();
+ let id = "answer-" + target.data("id");
- if(!this.isMobile) {
- $(zone).find(".slot:not(.active)").eq(0).addClass("active").append("<span>"+text+"</span>").attr('data-order',target.data("id"))
+ if (!this.isMobile) {
+ $(zone).find(".slot:not(.active)").eq(0).addClass("active").append("<h4>" + title + "</h4><p>"+text+"</p>").attr('data-order', target.data("id"))
}
- $this.saveAnswer(zone,id)
+ $this.saveAnswer(zone, id)
target.remove()
},
- toggleScreen: function(opacity,pointer) {
+ toggleScreen: function (opacity, pointer) {
gsap.to(".active-screen .screen", {
opacity: opacity,
pointerEvents: pointer
})
},
- getZoneOverlap: function(target) {
+ getZoneOverlap: function (target) {
let zone = false
var rectSelection = target.getBoundingClientRect();
// Iterate over all LI elements.
- [].forEach.call(document.querySelectorAll(".zone-content"), function(div) {
+ [].forEach.call(document.querySelectorAll(".zone-content"), function (div) {
var rect = div.getBoundingClientRect();
- if(rect.bottom > rectSelection.top
+ if (rect.bottom > rectSelection.top
&& rect.right > rectSelection.left
&& rect.top < rectSelection.bottom
&& rect.left < rectSelection.right) {
div.classList.add("active")
- }else {
+ } else {
div.classList.remove("active")
}
});
- if($(".zone-content.active").length > 0) {
- zone = "."+$(".zone-content.active").parent().data("zone")
+ if ($(".zone-content.active").length > 0) {
+ zone = "." + $(".zone-content.active").parent().data("zone")
}
return zone
},
- getSlotInformations: function(zone) {
+ getSlotInformations: function (zone) {
let x = ($(zone).find(".slot:not(.active)").offset().left - this.list.offset().left),
y = ($(zone).find(".slot:not(.active)").offset().top - this.list.offset().top),
w = $(zone).find(".slot").innerWidth(),
h = $(zone).find(".slot").innerHeight(),
el = $(zone).find(".slot")
- return {"x" : x, "y" : y, "w" : w, "h": h, "el": el}
+ return {"x": x, "y": y, "w": w, "h": h, "el": el}
},
- retreiveAnswer: function() {
+ retreiveAnswer: function () {
//
const htmlList = this.quiz.draganddrop.listHtml
const htmlZone1 = this.quiz.draganddrop.htmlZone1
this.quiz.animations.setAnimItemDragAndDrop(tl)
},
- saveAnswer: function(zone,id) {
- $(zone).find("input[id="+id+"]").prop("checked", true)
+ saveAnswer: function (zone, id) {
+ $(zone).find("input[id=" + id + "]").prop("checked", true)
this.quiz.screens.updateUserAnswers();
}
}
//
this.quiz.screens.intro.resize(this.ww, this.hh);
//
- if (this.ww <= 992) {
+ if (this.isMobile()) {
$(".btn.reset .text").html(iconReset)
} else {
$(".btn.reset .text").html(textReset)
}
+
+ },
+
+ updateViewport: function () {
+ if (this.isMobile()) {
+ $('meta[name="viewport"]').attr('content', 'width=device-width, user-scalable=no, initial-scale=1.0, shrink-to-fit=no');
+ } else {
+ $('meta[name="viewport"]').attr('content', 'width=390, user-scalable=no, initial-scale=1.0, shrink-to-fit=no');
+ }
},
isMobile: function () {
height: 20px
.container
- +flex-config(center,false,false,center)
+ +flex-config(center, false, false, center)
min-height: 100vh
#quiz
+padding-container()
position: relative
overflow: hidden
+ border-radius: 20px
+ box-shadow: 0 0 30px rgba(0, 0, 0, 0.2)
+
+ .m &
+ border-radius: 0
+ box-shadow: 0
+
.btn
padding: 0 12px
cursor: pointer
display: inline-block
height: 58px
- +flex-config(center,false,false,center)
+ +flex-config(center, false, false, center)
@extend .radius
+font-size(20)
+
&.primary
background: radial-gradient(at 16% 6px, rgb(255, 102, 186) -7%, #D0167C 74%)
- box-shadow: 0 4px 6px rgba(0,0,0,.2)
+ box-shadow: 0 4px 6px rgba(0, 0, 0, .2)
overflow: hidden
+
&.countdown
&:after
content: ""
position: absolute
right: 0
top: 0
- +opacity(.32,background-color,$texts-color)
+ +opacity(.32, background-color, $texts-color)
+
span
z-index: 1
+
&.secondary
+opacity(.16)
padding-left: 22px
+
&.reset
//max-width: 144px
.text svg
width: 50%
+
&.info
max-width: 177px
+opacity(.16)
text-transform: uppercase
margin-left: 16px
- +flex-config(center,false,false,center)
+ +flex-config(center, false, false, center)
border: 0
+
&.space
width: 70px
+
&.infos
width: 40px
+
&.ok
+opacity(.24, background-color, $ok-color)
&.missed
svg
color: $ok-color
+
&.nok
+opacity(.24, background-color, $nok-color)
+
svg
color: $nok-color
+
&.ok,
&.nok,
&.missed
.screen
position: relative
z-index: 1
+
&-image
position: absolute
top: 0
height: 100%
width: 100%
z-index: 0
+
img.mobile
display: none
height: 100%
width: 100%
object-fit: cover
+
&.question-multiple
object-position: top
.screen-image
img.mobile
display: inline
+
img:not(.mobile)
display: none
.btn
height: 56px
+
&:first-of-type:not(:last-of-type),
&.toggle-answers-review
margin-right: 16px
+
&.primary
flex: 1
+
&.reset
width: 56px
flex-shrink: 0
padding: 0
+
.text
- +flex-config(center,false,false,center)
+ +flex-config(center, false, false, center)
.access:not(.missed):not(.ok):not(.nok)
display: none
width: 124px
padding: 12px 0
+font-size(20)
- +opacity(.16,background-color,$texts-color)
+ +opacity(.16, background-color, $texts-color)
border-radius: 16px
text-align: center
+ cursor: pointer
+
&.left .access
transform: rotate(-90deg)
+
&.right .access
transform: rotate(90deg)
+
p
margin-bottom: 5px
+
.access
margin: 0 auto
+
span
display: flex
+
svg
color: $texts-color
+.only-mobile
+ display: none
+
+.only-desktop
+ display: inherit
+
.m
.controls
display: none
+
+ .only-desktop
+ display: none
+
+ .only-mobile
+ display: inherit
.container-screen.question-draganddrop
.screen-image
width: auto
+
img
height: 100%
+
&.zone-1
.zone-content
left: 24px
+
&.zone-2
+ text-align: right
left: initial
right: 0
+
+ img
+ position: absolute
+ right: 0
+
.zone-content
right: 24px
&.zone-1,
&.zone-2
&.active
- .zone-content
- +opacity(.2,background-color,$texts-color)
+ .card-holder
+ +opacity(.2, background-color, $texts-color)
.zone-content
position: absolute
top: 50%
transform: translateY(-50%)
- width: 100%
- max-width: 180px
- height: 70%
- padding: 8px
- border: 1px dashed rgba($texts-color,.4)
- +radius(16px)
+ width: 180px
+ height: 50%
+ padding: 0 8px
+
transition: background-color .2s ease
+ .card-holder
+ +opacity(.08, background-color, $texts-color)
+ +radius(16px)
+ min-height: 196px
+ padding: 8px
+
.text
margin-bottom: 21px
+
h2
font-size: 20px
margin-bottom: 8px
+
.slot
width: 100%
height: 51px
- //border: 1px solid rgba($texts-color,.24)
transition: all .3s
+radius(8px)
padding: 7px 8px
font-size: 14px
margin-bottom: 8px
+
+
&.active
- border: 1px solid rgba($texts-color,.24)
+ background-color: rgba(0, 0, 0, 0.25)
+ border: 1px solid rgba($texts-color, .24)
+
span
display: -webkit-box
display: -moz-box
.screen
+flex-config(center, false, false, center)
margin-top: 92px
+
.list
position: relative
width: 100%
max-width: 368px
height: 225px
margin: 0 16px
+
&-item
position: absolute
width: 100%
+radius(16px)
padding: 20px
border: 2px solid transparent
+
+ h4
+ font-size: 20px
+ font-weight: 600
+
+ p
+ font-size: 16px
+ font-weight: 400
+ margin-top: 5px
+ white-space: pre-line
+
&:not(.overlay)
transition: top .3s
opacity: 0
z-index: 4
border: 2px solid $texts-color
top: 0
+
&.isNext
transform: scale(1) !important
transition: all .3s
+
&.complete
opacity: 1
&:not(.isDragging)
&:nth-child(2)
- +opacity(.8,background-color,$neutral-color)
+ +opacity(.8, background-color, $neutral-color)
transform: scale(.92) !important
z-index: 3
top: 30px
+
&.complete
opacity: .64 !important
&:nth-child(3)
- +opacity(.8,background-color,$neutral-color)
+ +opacity(.8, background-color, $neutral-color)
transform: scale(.83) !important
z-index: 2
top: 60px
+
&.complete
opacity: .4 !important
&:nth-child(4)
- +opacity(.8,background-color,$neutral-color)
+ +opacity(.8, background-color, $neutral-color)
transform: scale(0.75) !important
z-index: 1
top: 87px
+
&.complete
opacity: .16 !important
- &:not(:nth-child(-n+4)) // on cache les items à partir du 5ème
- opacity: 0 !important
- visibility: hidden
+ &:not(:nth-child(-n+4))
+ // on cache les items à partir du 5ème
+ opacity: 0 !important
+ visibility: hidden
+
&.isValidated
font-size: 14px
- border: 1px solid rgba($texts-color,.24)
+ border: 1px solid rgba($texts-color, .24)
transition: border .3s, font-size .3s
+
&:not(:nth-child(1))
clip-path: polygon(0 90%, 100% 90%, 100% 100%, 0 100%)
transition: all .3s
pointer-events: none
+
&.isNext
clip-path: polygon(0 0, 100% 0%, 100% 100%, 0 100%)
transition: all .3s
&[data-direction=right]
transform: rotate(25deg)
+
&[data-direction=left]
transform: rotate(-25deg)
.overlay
@extend .list-item
- +opacity(.16,background-color,$neutral-color)
- border: 1px dashed rgba($texts-color,.24)
+ +opacity(.16, background-color, $neutral-color)
+ border: 1px dashed rgba($texts-color, .24)
z-index: 3
.m
width: 100%
height: auto
left: 0
+
.zone-content
max-width: 95%
height: auto
padding: 18px 40px
border-radius: 8px
border-width: 2px
+
.text
text-align: center
margin: 0
+
h2
margin-bottom: 5px
+
p
font-size: 14px
- +opacity(.8,color,$texts-color)
+ +opacity(.8, color, $texts-color)
+
.slot
display: none
&.zone-1
width: 100%
height: auto
+
.zone-content
top: 29px
top: initial
bottom: -3px
left: 0
+
.zone-content
top: initial
bottom: 78px
.header-question
top: 130px
+
.progress-container
margin: 4px 0
&:not(.isDragging)
&:nth-child(2)
top: 24px
+
&:nth-child(3)
top: 47px
+
&:nth-child(4)
top: 67px
@endfor
</div>
- @if($data['type'] === "draganddrop")
+ @if($question['type'] === "draganddrop")
<h1 id="titleQuestion">
<span class="only-desktop">{{$__('Drag and drop each card in the right container')}}</span>
- <span class="only-mobile">{{$__('Swipe up or down each card in the right container')}}></span>
+ <span class="only-mobile">{{$__('Swipe up or down each card in the right container')}}</span>
</h1>
<h2 class="subtitle"
class="only-desktop">{{$__('Use arrow keys to move the cards to the corresponding zone')}}</h2>
- @elseif($data['type']==='match')
+ @elseif($question['type']==='match')
<h1 id="titleQuestion">
{{$__('Answer the question by swiping left or right to select the most appropriate answer')}}
</h1>
</div>
</div>
<script src="js/quiz.js"></script>
-<script>
- function changeViewportSize () {
- const mvp = document.getElementById('myViewport');
- if (screen.width > 390) {
- mvp.setAttribute('content','width=device-width, user-scalable=no, initial-scale=1.0, shrink-to-fit=no');
- }else {
- mvp.setAttribute('content','width=390, user-scalable=no, initial-scale=1.0, shrink-to-fit=no');
- }
- }
- window.addEventListener("onload", changeViewportSize)
- window.addEventListener("resize", changeViewportSize)
-</script>
</body>
</html>
--- /dev/null
+@php
+ if($side==='left'){
+ $text=$__('Move left');
+ $key='ARROWLEFT';
+ }else{
+ $text=$__('Move right');
+ $key='ARROWRIGHT';
+ }
+@endphp
+
+<div class="controls {{$side}} move-card" aria-keyshortcuts="{{$key}}">
+ <p>{{$text}}</p>
+ <div class="access">
+ <span data-icon="arrow"></span>
+ </div>
+</div>
<div class="container-screen none question-draganddrop" data-screen="q-{{$position}}">
- <div class="screen-image zone-1 notDrag" data-zone="zone-1">
- <img src="{{$theme->draganddropArea1Image}}" />
- <img class="mobile" src="{{$theme->draganddropArea1ImageMobile}}"/>
- <div class="zone-content">
- <div class="text">
- <h2>{{ $question['area_1']['title'] }}</h2>
- <p>{{ $question['area_1']['text'] }}</p>
- </div>
- <form>
- @foreach($question['answers'] as $key => $answer)
- <div class="slot">
- <input type="checkbox"
- id="answer-{{$key}}" class="none" value="{{$key}}">
- </div>
- @endforeach
- </form>
- </div>
- </div>
- @include('header_question', ['data' => $data, 'max' => $max, 'position' => $position])
+ @include('screens.question_draganddrop_area',['area'=>1,'question'=>$question,'theme'=>$theme])
+ @include('header_question', ['question' => $question, 'data' => $data, 'max' => $max, 'position' => $position])
<div class="screen question-draganddrop">
- <div class="controls left">
- <p>{{$__('Move left')}}</p>
- <button class="access move-card" aria-keyshortcuts="ARROWLEFT"><span data-icon="arrow"></span></button>
- </div>
+ @include('screens.arrow',['side'=>'left'])
<ul class="list">
@foreach($question['answers'] as $key => $answer)
<li class="list-item {{ $key === 0 ? 'current' : '' }}" data-id="{{$key}}">
- {{$answer['answer']}}
+ <h4>{{$answer['answer']}}</h4>
+ <p>{{$answer['answer_text']}}</p>
</li>
@endforeach
<li class="overlay"></li>
</ul>
- <div class="controls right">
- <p>{{$__('Move right')}}</p>
- <button class="access move-card" aria-keyshortcuts="ARROWRIGHT"><span data-icon="arrow"></span></button>
- </div>
- </div>
- <div class="screen-image zone-2 notDrag" data-zone="zone-2">
- <img src="{{$theme->draganddropArea2Image}}" />
- <img class="mobile" src="{{$theme->draganddropArea2ImageMobile}}"/>
- <div class="zone-content">
- <div class="text">
- <h2>{{ $question['area_2']['title'] }}</h2>
- <p>{{ $question['area_2']['text'] }}</p>
- </div>
- <form>
- @foreach($question['answers'] as $key => $answer)
- <div class="slot"></div>
- @endforeach
- </form>
- </div>
+ @include('screens.arrow',['side'=>'right'])
</div>
+ @include('screens.question_draganddrop_area',['area'=>2,'question'=>$question,'theme'=>$theme])
@include('footer', ['question' => $question,'data' => $data, 'reset' => true, 'text' => $__('Validate answer'), 'info' => true])
</div>
--- /dev/null
+@php
+ $desktopImageKey='draganddropArea'.$area.'Image';
+ $mobileImageKey='draganddropArea'.$area.'ImageMobile';
+@endphp
+<div class="screen-image zone-{{$area}} notDrag" data-zone="zone-{{$area}}">
+ <img src="{{$theme->$desktopImageKey}}"/>
+ <img class="mobile" src="{{$theme->$mobileImageKey}}"/>
+ <div class="zone-content">
+ <div class="text">
+ <h2>{{ $question['area_'.$area]['title'] }}</h2>
+ <p>{{ $question['area_'.$area]['text'] }}</p>
+ </div>
+ <div class="card-holder">
+ <form>
+ @foreach($question['answers'] as $key => $answer)
+ <div class="slot">
+ <input type="checkbox"
+ id="answer-{{$key}}" class="none" value="{{$key}}">
+ <h4></h4>
+ <p></p>
+ </div>
+ @endforeach
+ </form>
+ </div>
+ </div>
+</div>
<div class="screen">
<div class="top-slider-container">
- <div class="controls left">
- <p>{{$__('Move left')}}</p>
- <button class="access move-slide" aria-keyshortcuts="ARROWLEFT">
- <span data-icon="arrow"></span>
- </button>
- </div>
+ @include('screens.arrow',['side'=>'left'])
<div class="swiper-container top-slider">
<div class="swiper-pagination-top"></div>
<div class="swiper-wrapper">
@endforeach
</div>
</div>
- <div class="controls right">
- <p>{{$__('Move right')}}</p>
- <button class="access move-slide" aria-keyshortcuts="ARROWRIGHT">
- <span data-icon="arrow"></span>
- </button>
- </div>
+ @include('screens.arrow',['side'=>'right'])
</div>
<div class="swiper-container bottom-slider">