I have a component called countdowntimer.vue which is obviously just a countdown timer, I use it for an online examination page, I want to apply an onbeforeunload event on the window object but I also want the timer to submit automatically when it's done without being interrupted by that window event, I tried putting the code in the vuejs component but it just doesn't respond, it either doesn't allow me to submit without interrupting, or it doesn't work at all and lets any event get out of the page without interrupting it.
Here's the code for the countdown timer:
<template>
<div>
<div v-if="finished" v-text="expiredText"></div>
<div v-else>
<span>{{ remaining.minutes }} Minutes, </span>
<span>{{ remaining.seconds }} Seconds</span>
left...
</div>
</div>
</template>
<script>
import moment from 'moment';
export default {
props: {
until: { default: 600000},
expiredText: { default: 'TIME IS UP' }
},
data () {
return { limiter: this.until * 10000};
},
created () {
this.refreshEverySecond();
document.addEventListener('beforeunload', this.redirect());
},
computed: {
finished () {
return this.remaining.total <= 0;
},
remaining () {
let remaining = moment.duration(this.limiter);
if (remaining <= 0) this.$emit('finished');
return {
total: remaining,
minutes: remaining.minutes(),
seconds: remaining.seconds()
};
},
},
methods: {
refreshEverySecond () {
let interval = setInterval(() => this.limiter = this.limiter - 1000, 1000);
this.$on('finished', () => clearInterval(interval));
this.$on('finished', () => this.timeUp());
},
timeUp() {
const form = document.querySelector('[data-form-submit]');
const radios = document.querySelectorAll('input[type=radio]');
radios.forEach(radio => radio.style.display = 'none');
form.submit(function(e) {
console.log(e);
});
},
redirect () {
// if(this.$on('finished')) {
// console.log(this.finished)
// window.onbeforeunload = function() {
// return "Do you really want to leave our brilliant application?";
// };
// }
// console.log(this.finished())
// return;
}
},
}
</script>
I have tried setting the method as a computed property and as a watcher with different if statements but it just doesn't work as I mentioned above.
And here's the blade template I am using it in
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<form method="POST" onsubmit="clicked()" data-form-submit>
{{ csrf_field() }}
<div class="panel panel-danger">
<div class="panel-heading">
{{ $quiz->quiz_name }}
</div>
<div class="panel-body">
<ol>
@foreach($quiz->questions as $index => $question)
<li><h4>{{ $question->title }} ? </h4></li>
<ul>
<div class="flex-align-baseline">
<li>{{$question->option_1}}</li>
<input type="radio" name="{{$index}}" value="{{ $question->option_1 }}">
<hr>
</div>
<div class="flex-align-baseline">
<li>{{$question->option_2}}</li>
<input type="radio" name="{{$index}}" value="{{ $question->option_2 }}">
<hr>
</div>
<div class="flex-align-baseline">
<li>{{$question->option_3}}</li>
<input type="radio" name="{{$index}}" value="{{ $question->option_3 }}">
<hr>
</div>
<div class="flex-align-baseline">
<li>{{$question->option_4}}</li>
<input type="radio" name="{{$index}}" value="{{ $question->option_4 }}">
<hr>
</div>
</ul>
<hr>
@endforeach
</ol>
<input type="submit" class="btn btn-success" onclick="clicked()" value="Submit">
</div>
</div>
</form>
</div>
<timer :until="{{ count($quiz->questions) }}" class="countdown col-md-3"></timer>
</div>
</div>
@endsection
<script>
let submitForm = false;
function clicked() {
submitForm = true;
}
window.onbeforeunload = function(e) {
if (submitForm) {
return null;
}
return "Do you really want to leave our brilliant application?";
};
</script>
As you can see I have a script tag outside of the @endsection, what I came to understand is that you probably can't do that, it won't connect to any element from the blade template itself, I tried to grab the form object like I was doing in the vue component but it returns null or undefined I can't remember, and you can't attach an event listener to undefined, but if I run the same logic in the console of the browser it works as expected, the onsubmit="" event that I have on the form doesn't not reach those script tags at the bottom for some reason, the value of the submitForm variable doesn't change, but weirdly enough if I clicked the submit button manually it does trigger the function clicked(), so I am very confused here, I don't know if I can achieve this with just vue or not, and if not I don't know why the onsubmit="" event is not working, and of course I cannot move the script tags inside the @section because vue will squack, if you have any idea what I should do with this bit of code I'd be grateful.