HTMLAudioElement sound delay on keyboard clicks
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
1
down vote
favorite
I am using Vue.js to play mp3 sounds on keyboard clicks. Even though each mp3 is less than 40 KB, there is a 95ms delay on heroku, on each request.
Is there a way to download sounds when dom is ready and not when clicking the buttons?
let a = 'sound1.mp3',
b = 'sound2.mp3';
new Vue(
created()
this.onKeyDown = this.onKeyDown.bind(this);
document.getElementById('btn-sound').addEventListener('keydown', this.onKeyDown);
,
destroyed()
document.getElementById('btn-sound').removeEventListener('keydown', this.onKeyDown);
,
methods:
playSound(sound)
if (sound)
var audio = new Audio(sound);
audio.play();
,
onKeyDown(e)
switch (e.keyCode)
case 12:
this.playSound(a);
break;
case 13:
this.playSound(b);
break;
);
javascript html audio vue.js
add a comment |Â
up vote
1
down vote
favorite
I am using Vue.js to play mp3 sounds on keyboard clicks. Even though each mp3 is less than 40 KB, there is a 95ms delay on heroku, on each request.
Is there a way to download sounds when dom is ready and not when clicking the buttons?
let a = 'sound1.mp3',
b = 'sound2.mp3';
new Vue(
created()
this.onKeyDown = this.onKeyDown.bind(this);
document.getElementById('btn-sound').addEventListener('keydown', this.onKeyDown);
,
destroyed()
document.getElementById('btn-sound').removeEventListener('keydown', this.onKeyDown);
,
methods:
playSound(sound)
if (sound)
var audio = new Audio(sound);
audio.play();
,
onKeyDown(e)
switch (e.keyCode)
case 12:
this.playSound(a);
break;
case 13:
this.playSound(b);
break;
);
javascript html audio vue.js
add a comment |Â
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I am using Vue.js to play mp3 sounds on keyboard clicks. Even though each mp3 is less than 40 KB, there is a 95ms delay on heroku, on each request.
Is there a way to download sounds when dom is ready and not when clicking the buttons?
let a = 'sound1.mp3',
b = 'sound2.mp3';
new Vue(
created()
this.onKeyDown = this.onKeyDown.bind(this);
document.getElementById('btn-sound').addEventListener('keydown', this.onKeyDown);
,
destroyed()
document.getElementById('btn-sound').removeEventListener('keydown', this.onKeyDown);
,
methods:
playSound(sound)
if (sound)
var audio = new Audio(sound);
audio.play();
,
onKeyDown(e)
switch (e.keyCode)
case 12:
this.playSound(a);
break;
case 13:
this.playSound(b);
break;
);
javascript html audio vue.js
I am using Vue.js to play mp3 sounds on keyboard clicks. Even though each mp3 is less than 40 KB, there is a 95ms delay on heroku, on each request.
Is there a way to download sounds when dom is ready and not when clicking the buttons?
let a = 'sound1.mp3',
b = 'sound2.mp3';
new Vue(
created()
this.onKeyDown = this.onKeyDown.bind(this);
document.getElementById('btn-sound').addEventListener('keydown', this.onKeyDown);
,
destroyed()
document.getElementById('btn-sound').removeEventListener('keydown', this.onKeyDown);
,
methods:
playSound(sound)
if (sound)
var audio = new Audio(sound);
audio.play();
,
onKeyDown(e)
switch (e.keyCode)
case 12:
this.playSound(a);
break;
case 13:
this.playSound(b);
break;
);
javascript html audio vue.js
edited May 12 at 21:22
asked May 12 at 21:10
csandreas1
1097
1097
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
2
down vote
accepted
SFC
Consider using Single File Components instead of the declarative syntax you are using right now. It removes a lot of the headache of dealing with the this
keyword, and removes the necessity of having to deal with handlers. See the documentation for more information.
Life cycle hooks
Vue has a couple of life cycle hooks. You are currently using two of them. However, your code currently only works, because your html is not part of the component you just wrote. The destroyed
life cycle hook is called after everything has been torn down, so there would be no html element to remove the handler from. You should be using the beforeDestroy
hook instead. See this lifecycle diagram for more information.
Internal data
Your sound filenames should be internal data of your component, not some random variables outside it. They should also have descriptive names.
Sound playback delay
You are experiencing playback delay, because you load the sounds when you want to play them, instead of pre-loading them. You have two ways of dealing with this problem. If your sound file names are hardcoded, you can simply use the data
initialisation function to create HTMLAudioElement
s you can then later start or stop. See mdn for more information.
data ()
return
sounds:
enter: new Audio('sound1.wav'),
whatevercode12is: new Audio('sound2.mp3')
If you pass these sounds as properties, you need to be a bit more clever about it. You can use the created
lifecycle hook to fill the sounds
object like we created above, but would instead be initialised as an empty object, or you could put a watcher on the property with the immediate flag on true
, and fill the sounds
object as needed.
In either case you must play and immediately pause them once so they are downloaded. Then you can look them up and play them whenever you like:
this.playSound('enter')
and
playSound (soundName)
const playableSound = this.sounds[soundName];
if (!playableSound)
throw new Error(`Called 'playSound' with unknown identifier [$soundName]`);
playableSound.play();
Implementing it all
When you implement all that, you will end up with something like this:
<template>
<div id="app">
<input v-on:keydown.prevent="onKeyDown" value="Just focus me and press keys" />
</div>
</template>
<script>
export default
name: "App",
data()
return
sounds:
enter: new Audio(
"http://www.pacdv.com/sounds/miscellaneous_sounds/air_blower_1.wav"
),
shift: new Audio(
"http://www.pacdv.com/sounds/miscellaneous_sounds/bottle_pop_1.wav"
)
;
,
created()
for (const sound of Object.values(this.sounds))
// This makes sure the sounds are loaded, but not played
sound.play().then(() =>
sound.pause();
);
,
methods:
playSound(soundName)
const playableSound = this.sounds[soundName];
if (!playableSound)
throw new Error(
`Called 'playSound' with unknown identifier [$soundName]`
);
if (!playableSound.paused)
// The previous sound is playing. We could reset the current sound with
// playableSound.currentTime = 0
// but we probably don't want to cut off that sound, so lets make a copy of the
// sound and dereference the previous one
this.sounds[soundName] = new Audio(playableSound.src);
this.sounds[soundName].play();
,
onKeyDown(e)
switch (e.keyCode)
case 13:
return this.playSound("enter");
case 16:
return this.playSound("shift");
default:
// Do nothing
break;
;
</script>
Can you show a small completed example based on my code? I would appreciate it.
â csandreas1
Jun 8 at 6:45
I will try to look at it in the weekend
â Sumurai8
Jun 8 at 12:48
I have made an edit and I have created a Code Sandbox where you can try editing it.
â Sumurai8
Jun 9 at 15:44
1
It plays the sounds simultaneously for me. It does not cut off the previous sound. You can probably usecurrentTime
to seek to the beginning.
â Sumurai8
Jun 9 at 19:54
1
Sorry, this site is for code reviews and to point out things that can be done better in current code. I don't think your current use of Vue is particularly well implemented, so I showed you how SFC's work. Read the documentation and probably also read up on how to use webpack with Vue. There is a boilerplate readily available.
â Sumurai8
Jun 11 at 17:27
 |Â
show 3 more comments
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
SFC
Consider using Single File Components instead of the declarative syntax you are using right now. It removes a lot of the headache of dealing with the this
keyword, and removes the necessity of having to deal with handlers. See the documentation for more information.
Life cycle hooks
Vue has a couple of life cycle hooks. You are currently using two of them. However, your code currently only works, because your html is not part of the component you just wrote. The destroyed
life cycle hook is called after everything has been torn down, so there would be no html element to remove the handler from. You should be using the beforeDestroy
hook instead. See this lifecycle diagram for more information.
Internal data
Your sound filenames should be internal data of your component, not some random variables outside it. They should also have descriptive names.
Sound playback delay
You are experiencing playback delay, because you load the sounds when you want to play them, instead of pre-loading them. You have two ways of dealing with this problem. If your sound file names are hardcoded, you can simply use the data
initialisation function to create HTMLAudioElement
s you can then later start or stop. See mdn for more information.
data ()
return
sounds:
enter: new Audio('sound1.wav'),
whatevercode12is: new Audio('sound2.mp3')
If you pass these sounds as properties, you need to be a bit more clever about it. You can use the created
lifecycle hook to fill the sounds
object like we created above, but would instead be initialised as an empty object, or you could put a watcher on the property with the immediate flag on true
, and fill the sounds
object as needed.
In either case you must play and immediately pause them once so they are downloaded. Then you can look them up and play them whenever you like:
this.playSound('enter')
and
playSound (soundName)
const playableSound = this.sounds[soundName];
if (!playableSound)
throw new Error(`Called 'playSound' with unknown identifier [$soundName]`);
playableSound.play();
Implementing it all
When you implement all that, you will end up with something like this:
<template>
<div id="app">
<input v-on:keydown.prevent="onKeyDown" value="Just focus me and press keys" />
</div>
</template>
<script>
export default
name: "App",
data()
return
sounds:
enter: new Audio(
"http://www.pacdv.com/sounds/miscellaneous_sounds/air_blower_1.wav"
),
shift: new Audio(
"http://www.pacdv.com/sounds/miscellaneous_sounds/bottle_pop_1.wav"
)
;
,
created()
for (const sound of Object.values(this.sounds))
// This makes sure the sounds are loaded, but not played
sound.play().then(() =>
sound.pause();
);
,
methods:
playSound(soundName)
const playableSound = this.sounds[soundName];
if (!playableSound)
throw new Error(
`Called 'playSound' with unknown identifier [$soundName]`
);
if (!playableSound.paused)
// The previous sound is playing. We could reset the current sound with
// playableSound.currentTime = 0
// but we probably don't want to cut off that sound, so lets make a copy of the
// sound and dereference the previous one
this.sounds[soundName] = new Audio(playableSound.src);
this.sounds[soundName].play();
,
onKeyDown(e)
switch (e.keyCode)
case 13:
return this.playSound("enter");
case 16:
return this.playSound("shift");
default:
// Do nothing
break;
;
</script>
Can you show a small completed example based on my code? I would appreciate it.
â csandreas1
Jun 8 at 6:45
I will try to look at it in the weekend
â Sumurai8
Jun 8 at 12:48
I have made an edit and I have created a Code Sandbox where you can try editing it.
â Sumurai8
Jun 9 at 15:44
1
It plays the sounds simultaneously for me. It does not cut off the previous sound. You can probably usecurrentTime
to seek to the beginning.
â Sumurai8
Jun 9 at 19:54
1
Sorry, this site is for code reviews and to point out things that can be done better in current code. I don't think your current use of Vue is particularly well implemented, so I showed you how SFC's work. Read the documentation and probably also read up on how to use webpack with Vue. There is a boilerplate readily available.
â Sumurai8
Jun 11 at 17:27
 |Â
show 3 more comments
up vote
2
down vote
accepted
SFC
Consider using Single File Components instead of the declarative syntax you are using right now. It removes a lot of the headache of dealing with the this
keyword, and removes the necessity of having to deal with handlers. See the documentation for more information.
Life cycle hooks
Vue has a couple of life cycle hooks. You are currently using two of them. However, your code currently only works, because your html is not part of the component you just wrote. The destroyed
life cycle hook is called after everything has been torn down, so there would be no html element to remove the handler from. You should be using the beforeDestroy
hook instead. See this lifecycle diagram for more information.
Internal data
Your sound filenames should be internal data of your component, not some random variables outside it. They should also have descriptive names.
Sound playback delay
You are experiencing playback delay, because you load the sounds when you want to play them, instead of pre-loading them. You have two ways of dealing with this problem. If your sound file names are hardcoded, you can simply use the data
initialisation function to create HTMLAudioElement
s you can then later start or stop. See mdn for more information.
data ()
return
sounds:
enter: new Audio('sound1.wav'),
whatevercode12is: new Audio('sound2.mp3')
If you pass these sounds as properties, you need to be a bit more clever about it. You can use the created
lifecycle hook to fill the sounds
object like we created above, but would instead be initialised as an empty object, or you could put a watcher on the property with the immediate flag on true
, and fill the sounds
object as needed.
In either case you must play and immediately pause them once so they are downloaded. Then you can look them up and play them whenever you like:
this.playSound('enter')
and
playSound (soundName)
const playableSound = this.sounds[soundName];
if (!playableSound)
throw new Error(`Called 'playSound' with unknown identifier [$soundName]`);
playableSound.play();
Implementing it all
When you implement all that, you will end up with something like this:
<template>
<div id="app">
<input v-on:keydown.prevent="onKeyDown" value="Just focus me and press keys" />
</div>
</template>
<script>
export default
name: "App",
data()
return
sounds:
enter: new Audio(
"http://www.pacdv.com/sounds/miscellaneous_sounds/air_blower_1.wav"
),
shift: new Audio(
"http://www.pacdv.com/sounds/miscellaneous_sounds/bottle_pop_1.wav"
)
;
,
created()
for (const sound of Object.values(this.sounds))
// This makes sure the sounds are loaded, but not played
sound.play().then(() =>
sound.pause();
);
,
methods:
playSound(soundName)
const playableSound = this.sounds[soundName];
if (!playableSound)
throw new Error(
`Called 'playSound' with unknown identifier [$soundName]`
);
if (!playableSound.paused)
// The previous sound is playing. We could reset the current sound with
// playableSound.currentTime = 0
// but we probably don't want to cut off that sound, so lets make a copy of the
// sound and dereference the previous one
this.sounds[soundName] = new Audio(playableSound.src);
this.sounds[soundName].play();
,
onKeyDown(e)
switch (e.keyCode)
case 13:
return this.playSound("enter");
case 16:
return this.playSound("shift");
default:
// Do nothing
break;
;
</script>
Can you show a small completed example based on my code? I would appreciate it.
â csandreas1
Jun 8 at 6:45
I will try to look at it in the weekend
â Sumurai8
Jun 8 at 12:48
I have made an edit and I have created a Code Sandbox where you can try editing it.
â Sumurai8
Jun 9 at 15:44
1
It plays the sounds simultaneously for me. It does not cut off the previous sound. You can probably usecurrentTime
to seek to the beginning.
â Sumurai8
Jun 9 at 19:54
1
Sorry, this site is for code reviews and to point out things that can be done better in current code. I don't think your current use of Vue is particularly well implemented, so I showed you how SFC's work. Read the documentation and probably also read up on how to use webpack with Vue. There is a boilerplate readily available.
â Sumurai8
Jun 11 at 17:27
 |Â
show 3 more comments
up vote
2
down vote
accepted
up vote
2
down vote
accepted
SFC
Consider using Single File Components instead of the declarative syntax you are using right now. It removes a lot of the headache of dealing with the this
keyword, and removes the necessity of having to deal with handlers. See the documentation for more information.
Life cycle hooks
Vue has a couple of life cycle hooks. You are currently using two of them. However, your code currently only works, because your html is not part of the component you just wrote. The destroyed
life cycle hook is called after everything has been torn down, so there would be no html element to remove the handler from. You should be using the beforeDestroy
hook instead. See this lifecycle diagram for more information.
Internal data
Your sound filenames should be internal data of your component, not some random variables outside it. They should also have descriptive names.
Sound playback delay
You are experiencing playback delay, because you load the sounds when you want to play them, instead of pre-loading them. You have two ways of dealing with this problem. If your sound file names are hardcoded, you can simply use the data
initialisation function to create HTMLAudioElement
s you can then later start or stop. See mdn for more information.
data ()
return
sounds:
enter: new Audio('sound1.wav'),
whatevercode12is: new Audio('sound2.mp3')
If you pass these sounds as properties, you need to be a bit more clever about it. You can use the created
lifecycle hook to fill the sounds
object like we created above, but would instead be initialised as an empty object, or you could put a watcher on the property with the immediate flag on true
, and fill the sounds
object as needed.
In either case you must play and immediately pause them once so they are downloaded. Then you can look them up and play them whenever you like:
this.playSound('enter')
and
playSound (soundName)
const playableSound = this.sounds[soundName];
if (!playableSound)
throw new Error(`Called 'playSound' with unknown identifier [$soundName]`);
playableSound.play();
Implementing it all
When you implement all that, you will end up with something like this:
<template>
<div id="app">
<input v-on:keydown.prevent="onKeyDown" value="Just focus me and press keys" />
</div>
</template>
<script>
export default
name: "App",
data()
return
sounds:
enter: new Audio(
"http://www.pacdv.com/sounds/miscellaneous_sounds/air_blower_1.wav"
),
shift: new Audio(
"http://www.pacdv.com/sounds/miscellaneous_sounds/bottle_pop_1.wav"
)
;
,
created()
for (const sound of Object.values(this.sounds))
// This makes sure the sounds are loaded, but not played
sound.play().then(() =>
sound.pause();
);
,
methods:
playSound(soundName)
const playableSound = this.sounds[soundName];
if (!playableSound)
throw new Error(
`Called 'playSound' with unknown identifier [$soundName]`
);
if (!playableSound.paused)
// The previous sound is playing. We could reset the current sound with
// playableSound.currentTime = 0
// but we probably don't want to cut off that sound, so lets make a copy of the
// sound and dereference the previous one
this.sounds[soundName] = new Audio(playableSound.src);
this.sounds[soundName].play();
,
onKeyDown(e)
switch (e.keyCode)
case 13:
return this.playSound("enter");
case 16:
return this.playSound("shift");
default:
// Do nothing
break;
;
</script>
SFC
Consider using Single File Components instead of the declarative syntax you are using right now. It removes a lot of the headache of dealing with the this
keyword, and removes the necessity of having to deal with handlers. See the documentation for more information.
Life cycle hooks
Vue has a couple of life cycle hooks. You are currently using two of them. However, your code currently only works, because your html is not part of the component you just wrote. The destroyed
life cycle hook is called after everything has been torn down, so there would be no html element to remove the handler from. You should be using the beforeDestroy
hook instead. See this lifecycle diagram for more information.
Internal data
Your sound filenames should be internal data of your component, not some random variables outside it. They should also have descriptive names.
Sound playback delay
You are experiencing playback delay, because you load the sounds when you want to play them, instead of pre-loading them. You have two ways of dealing with this problem. If your sound file names are hardcoded, you can simply use the data
initialisation function to create HTMLAudioElement
s you can then later start or stop. See mdn for more information.
data ()
return
sounds:
enter: new Audio('sound1.wav'),
whatevercode12is: new Audio('sound2.mp3')
If you pass these sounds as properties, you need to be a bit more clever about it. You can use the created
lifecycle hook to fill the sounds
object like we created above, but would instead be initialised as an empty object, or you could put a watcher on the property with the immediate flag on true
, and fill the sounds
object as needed.
In either case you must play and immediately pause them once so they are downloaded. Then you can look them up and play them whenever you like:
this.playSound('enter')
and
playSound (soundName)
const playableSound = this.sounds[soundName];
if (!playableSound)
throw new Error(`Called 'playSound' with unknown identifier [$soundName]`);
playableSound.play();
Implementing it all
When you implement all that, you will end up with something like this:
<template>
<div id="app">
<input v-on:keydown.prevent="onKeyDown" value="Just focus me and press keys" />
</div>
</template>
<script>
export default
name: "App",
data()
return
sounds:
enter: new Audio(
"http://www.pacdv.com/sounds/miscellaneous_sounds/air_blower_1.wav"
),
shift: new Audio(
"http://www.pacdv.com/sounds/miscellaneous_sounds/bottle_pop_1.wav"
)
;
,
created()
for (const sound of Object.values(this.sounds))
// This makes sure the sounds are loaded, but not played
sound.play().then(() =>
sound.pause();
);
,
methods:
playSound(soundName)
const playableSound = this.sounds[soundName];
if (!playableSound)
throw new Error(
`Called 'playSound' with unknown identifier [$soundName]`
);
if (!playableSound.paused)
// The previous sound is playing. We could reset the current sound with
// playableSound.currentTime = 0
// but we probably don't want to cut off that sound, so lets make a copy of the
// sound and dereference the previous one
this.sounds[soundName] = new Audio(playableSound.src);
this.sounds[soundName].play();
,
onKeyDown(e)
switch (e.keyCode)
case 13:
return this.playSound("enter");
case 16:
return this.playSound("shift");
default:
// Do nothing
break;
;
</script>
edited Jun 9 at 20:01
answered Jun 7 at 19:00
Sumurai8
2,260315
2,260315
Can you show a small completed example based on my code? I would appreciate it.
â csandreas1
Jun 8 at 6:45
I will try to look at it in the weekend
â Sumurai8
Jun 8 at 12:48
I have made an edit and I have created a Code Sandbox where you can try editing it.
â Sumurai8
Jun 9 at 15:44
1
It plays the sounds simultaneously for me. It does not cut off the previous sound. You can probably usecurrentTime
to seek to the beginning.
â Sumurai8
Jun 9 at 19:54
1
Sorry, this site is for code reviews and to point out things that can be done better in current code. I don't think your current use of Vue is particularly well implemented, so I showed you how SFC's work. Read the documentation and probably also read up on how to use webpack with Vue. There is a boilerplate readily available.
â Sumurai8
Jun 11 at 17:27
 |Â
show 3 more comments
Can you show a small completed example based on my code? I would appreciate it.
â csandreas1
Jun 8 at 6:45
I will try to look at it in the weekend
â Sumurai8
Jun 8 at 12:48
I have made an edit and I have created a Code Sandbox where you can try editing it.
â Sumurai8
Jun 9 at 15:44
1
It plays the sounds simultaneously for me. It does not cut off the previous sound. You can probably usecurrentTime
to seek to the beginning.
â Sumurai8
Jun 9 at 19:54
1
Sorry, this site is for code reviews and to point out things that can be done better in current code. I don't think your current use of Vue is particularly well implemented, so I showed you how SFC's work. Read the documentation and probably also read up on how to use webpack with Vue. There is a boilerplate readily available.
â Sumurai8
Jun 11 at 17:27
Can you show a small completed example based on my code? I would appreciate it.
â csandreas1
Jun 8 at 6:45
Can you show a small completed example based on my code? I would appreciate it.
â csandreas1
Jun 8 at 6:45
I will try to look at it in the weekend
â Sumurai8
Jun 8 at 12:48
I will try to look at it in the weekend
â Sumurai8
Jun 8 at 12:48
I have made an edit and I have created a Code Sandbox where you can try editing it.
â Sumurai8
Jun 9 at 15:44
I have made an edit and I have created a Code Sandbox where you can try editing it.
â Sumurai8
Jun 9 at 15:44
1
1
It plays the sounds simultaneously for me. It does not cut off the previous sound. You can probably use
currentTime
to seek to the beginning.â Sumurai8
Jun 9 at 19:54
It plays the sounds simultaneously for me. It does not cut off the previous sound. You can probably use
currentTime
to seek to the beginning.â Sumurai8
Jun 9 at 19:54
1
1
Sorry, this site is for code reviews and to point out things that can be done better in current code. I don't think your current use of Vue is particularly well implemented, so I showed you how SFC's work. Read the documentation and probably also read up on how to use webpack with Vue. There is a boilerplate readily available.
â Sumurai8
Jun 11 at 17:27
Sorry, this site is for code reviews and to point out things that can be done better in current code. I don't think your current use of Vue is particularly well implemented, so I showed you how SFC's work. Read the documentation and probably also read up on how to use webpack with Vue. There is a boilerplate readily available.
â Sumurai8
Jun 11 at 17:27
 |Â
show 3 more comments
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f194280%2fhtmlaudioelement-sound-delay-on-keyboard-clicks%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password