feature/Add_posibility_of_selecting_diferent_formats #18
@ -22,11 +22,12 @@ post '/api' => sub {
|
|||||||
status => 400
|
status => 400
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
my $format = $c->req->json->{format};
|
||||||
my $render_returned;
|
my $render_returned;
|
||||||
eval {
|
eval {
|
||||||
$render_returned = $c->render(
|
$render_returned = $c->render(
|
||||||
json => Peertube::DL::URLHandler::getDownloadDataFromURL(
|
json => Peertube::DL::URLHandler::getDownloadDataFromURL(
|
||||||
$url, { format => 18 }
|
$url, { ( ( defined $format ) ? ( format => $format ) : () ) },
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -43,7 +43,6 @@ sub youtube {
|
|||||||
: ()
|
: ()
|
||||||
);
|
);
|
||||||
my $mime_type = $format->{mimeType} =~ s/;.*$//r;
|
my $mime_type = $format->{mimeType} =~ s/;.*$//r;
|
||||||
say $mime_type;
|
|
||||||
my $extension = $mime_type =~ s/^.*?\///r =~ s/;.*$//r;
|
my $extension = $mime_type =~ s/^.*?\///r =~ s/;.*$//r;
|
||||||
if ( defined $format->{url} ) {
|
if ( defined $format->{url} ) {
|
||||||
return {
|
return {
|
||||||
@ -65,8 +64,6 @@ sub youtube {
|
|||||||
$url_data
|
$url_data
|
||||||
};
|
};
|
||||||
|
|
||||||
say Data::Dumper::Dumper $url_data;
|
|
||||||
|
|
||||||
my ($player_url) =
|
my ($player_url) =
|
||||||
$response->decoded_content =~ m/"jsUrl"\s*:\s*("[^"]+")/;
|
$response->decoded_content =~ m/"jsUrl"\s*:\s*("[^"]+")/;
|
||||||
$player_url = JSON::from_json( $player_url, { allow_nonref => 1 } );
|
$player_url = JSON::from_json( $player_url, { allow_nonref => 1 } );
|
||||||
@ -101,22 +98,36 @@ sub youtube {
|
|||||||
my $signature =
|
my $signature =
|
||||||
$js->callJSFunction( $function_name_regen_sig, $url_data->{s} );
|
$js->callJSFunction( $function_name_regen_sig, $url_data->{s} );
|
||||||
my $url = $url_data->{url} . "&sig=${signature}";
|
my $url = $url_data->{url} . "&sig=${signature}";
|
||||||
say Data::Dumper::Dumper $format;
|
|
||||||
say $url;
|
say $url;
|
||||||
return {
|
return {
|
||||||
url => $url,
|
url => $url,
|
||||||
filename => $microformat->{title}{simpleText} . '.' . $extension,
|
filename => $microformat->{title}{simpleText} . '.' . $extension,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
my @formats = map {
|
||||||
options => { list_formats => 1 },
|
|
||||||
title => $microformat->{title}{simpleText},
|
|
||||||
description => $microformat->{description}{simpleText},
|
|
||||||
formats => [
|
|
||||||
map {
|
|
||||||
{
|
{
|
||||||
id => $_->{itag},
|
id => $_->{itag},
|
||||||
mimeType => $_->{mimeType}
|
mimeType => $_->{mimeType},
|
||||||
|
(
|
||||||
|
( defined $_->{averageBitrate} && defined $_->{bitrate} )
|
||||||
|
? ( bitrate => $_->{averageBitrate} // $_->{bitrate} )
|
||||||
|
: ()
|
||||||
|
),
|
||||||
|
(
|
||||||
|
( defined $_->{qualityLabel} )
|
||||||
|
? ( qualityLabel => $_->{qualityLabel} =~ s/p$//r )
|
||||||
|
: ()
|
||||||
|
),
|
||||||
|
(
|
||||||
|
( defined $_->{audioSampleRate} )
|
||||||
|
? ( audioSampleRate => $_->{audioSampleRate} )
|
||||||
|
: ()
|
||||||
|
),
|
||||||
|
(
|
||||||
|
( defined $_->{quality} )
|
||||||
|
? ( quality => $_->{quality} )
|
||||||
|
: ()
|
||||||
|
),
|
||||||
}
|
}
|
||||||
} (
|
} (
|
||||||
scalar @{ $ytInitialPlayerResponse->{adaptiveFormats} }
|
scalar @{ $ytInitialPlayerResponse->{adaptiveFormats} }
|
||||||
@ -125,8 +136,32 @@ sub youtube {
|
|||||||
scalar @{ $ytInitialPlayerResponse->{formats} }
|
scalar @{ $ytInitialPlayerResponse->{formats} }
|
||||||
? @{ $ytInitialPlayerResponse->{formats} }
|
? @{ $ytInitialPlayerResponse->{formats} }
|
||||||
: ()
|
: ()
|
||||||
)
|
);
|
||||||
]
|
my $video_formats = [
|
||||||
|
sort {
|
||||||
|
$b->{qualityLabel} <=> $a->{qualityLabel}
|
||||||
|
|| $b->{bitrate} <=> $a->{bitrate}
|
||||||
|
} grep { defined $_->{qualityLabel} } @formats
|
||||||
|
];
|
||||||
|
my $audio_formats = [
|
||||||
|
sort {
|
||||||
|
$a->{audioSampleRate} <=> $b->{audioSampleRate}
|
||||||
|
|| $b->{bitrate} <=> $a->{bitrate}
|
||||||
|
} grep {
|
||||||
|
defined $_->{audioSampleRate}
|
||||||
|
&& $_->{mimeType} =~ /webm;/
|
||||||
|
} @formats
|
||||||
|
];
|
||||||
|
|
||||||
|
return {
|
||||||
|
options => { list_formats => 1 },
|
||||||
|
title => $microformat->{title}{simpleText},
|
||||||
|
description => $microformat->{description}{simpleText},
|
||||||
|
formats => {
|
||||||
|
video_formats => $video_formats,
|
||||||
|
audio_formats => $audio_formats,
|
||||||
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ sub getDownloadDataFromURL {
|
|||||||
die "No title." unless defined $download_data->{title};
|
die "No title." unless defined $download_data->{title};
|
||||||
die "No description." unless defined $download_data->{description};
|
die "No description." unless defined $download_data->{description};
|
||||||
die "No formats available." unless defined $download_data->{formats};
|
die "No formats available." unless defined $download_data->{formats};
|
||||||
die "Formats is not an arrayref." unless ref $download_data->{formats} eq 'ARRAY';
|
die "Formats is not a hash." unless ref $download_data->{formats} eq 'HASH';
|
||||||
say "The video title is $download_data->{title}.";
|
say "The video title is $download_data->{title}.";
|
||||||
say "The video description is $download_data->{description}.";
|
say "The video description is $download_data->{description}.";
|
||||||
say "The available formats are: @{[Data::Dumper::Dumper $download_data->{formats}]}.";
|
say "The available formats are: @{[Data::Dumper::Dumper $download_data->{formats}]}.";
|
||||||
|
@ -135,7 +135,7 @@ h2 {
|
|||||||
width: 10%;
|
width: 10%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.poping-notice {
|
#poping-notice {
|
||||||
display: none;
|
display: none;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
@ -149,17 +149,18 @@ h2 {
|
|||||||
max-height: 95%;
|
max-height: 95%;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
.poping-notice.active {
|
|
||||||
|
#poping-notice.active {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.poping-notice-container-bar {
|
#poping-notice-container-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
font-size: 5rem;
|
font-size: 5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-poping-notice {
|
#close-poping-notice {
|
||||||
width: 150px;
|
width: 150px;
|
||||||
height: 150px;
|
height: 150px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -172,14 +173,97 @@ h2 {
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-poping-notice:hover,.close-poping-notice:focus {
|
#close-poping-notice:hover,#close-poping-notice:focus {
|
||||||
background: black;
|
background: black;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#modal-format-selector {
|
||||||
|
display: none;
|
||||||
|
background: white;
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
border: black 1px solid;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#modal-format-selector.active {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#modal-format-selector > h2 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#modal-format-selector > p {
|
||||||
|
margin-left: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#modal-format-selector .format-list {
|
||||||
|
box-sizing: border-box;
|
||||||
|
background: #fff;
|
||||||
|
margin: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#close-modal-format-selector {
|
||||||
|
margin-top: 0.50rem;
|
||||||
|
margin-right: 0.50rem;
|
||||||
|
border: 1px solid black;
|
||||||
|
background: grey;
|
||||||
|
color: white;
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#close-modal-format-selector:hover,#close-modal-format-selector:focus {
|
||||||
|
background: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.format-list > div {
|
||||||
|
width: 100%;
|
||||||
|
display: grid;
|
||||||
|
grid-auto-columns: 50%;
|
||||||
|
grid-template-areas: "a a";
|
||||||
|
}
|
||||||
|
|
||||||
|
.format-list > div > a {
|
||||||
|
border: 1px solid black;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
padding-right: 5%;
|
||||||
|
padding-left: 5%;
|
||||||
|
text-decoration: none;
|
||||||
|
color: black;
|
||||||
|
background: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.format-list > div > a:hover {
|
||||||
|
background: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.format-list > div > a:after {
|
||||||
|
padding-bottom: 100%;
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
div.video-formats a {
|
||||||
|
background: #f00;
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 668px) {
|
@media (min-width: 668px) {
|
||||||
.poping-notice {
|
#poping-notice {
|
||||||
width: 629px;
|
width: 629px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,12 +12,27 @@
|
|||||||
<button class="block" id="download-form-button" >Fetch from api</button>
|
<button class="block" id="download-form-button" >Fetch from api</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="modal-format-selector">
|
||||||
|
<div class="video-container-bar">
|
||||||
|
<a id="close-modal-format-selector">x</a>
|
||||||
|
</div>
|
||||||
|
<h2>Example video</h2>
|
||||||
|
<p>Example description</p>
|
||||||
|
<div class="format-list">
|
||||||
|
<h3>Video Formats.</h3>
|
||||||
|
<div class="video-formats">
|
||||||
|
</div>
|
||||||
|
<h3>Audio Formats.</h3>
|
||||||
|
<div class="audio-formats">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div id="modal-loading">
|
<div id="modal-loading">
|
||||||
<embed src="img/spinner.svg"/>
|
<embed src="img/spinner.svg"/>
|
||||||
</div>
|
</div>
|
||||||
<div id="modal-video-container">
|
<div id="modal-video-container">
|
||||||
<div class="video-container-bar">
|
<div class="video-container-bar">
|
||||||
<a id="close-and-reset-video-container">X</a>
|
<a id="close-and-reset-video-container">x</a>
|
||||||
</div>
|
</div>
|
||||||
<div id="video-container">
|
<div id="video-container">
|
||||||
<div class="block">
|
<div class="block">
|
||||||
@ -30,8 +45,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="poping-notice">
|
<div id="poping-notice">
|
||||||
<div class="poping-notice-content">
|
<div id="poping-notice-content">
|
||||||
<p>This webpage is free as in freedom software, it is offered to you with the hope it will be useful, but without any warranty,
|
<p>This webpage is free as in freedom software, it is offered to you with the hope it will be useful, but without any warranty,
|
||||||
you can find the source code at <a href="https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl">my gitea</a> with docs to setup your own
|
you can find the source code at <a href="https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl">my gitea</a> with docs to setup your own
|
||||||
webpage like this, this software is licensed under the AGPLv3 license which means you MUST convey the source code in a human readable form
|
webpage like this, this software is licensed under the AGPLv3 license which means you MUST convey the source code in a human readable form
|
||||||
@ -45,8 +60,8 @@
|
|||||||
encouraged to frecuently delete your browser cookies to avoid those third parties tracking you on internet, Firefox offers you an
|
encouraged to frecuently delete your browser cookies to avoid those third parties tracking you on internet, Firefox offers you an
|
||||||
option to delete cookies as soon as you close the browser which may be a good idea to enable in the orwellian internet of today.</p>
|
option to delete cookies as soon as you close the browser which may be a good idea to enable in the orwellian internet of today.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="poping-notice-container-bar">
|
<div id="poping-notice-container-bar">
|
||||||
<a class="close-poping-notice" href="#">X</a>
|
<a id="close-poping-notice" href="#">X</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -15,11 +15,59 @@ let url;
|
|||||||
let popingNotice;
|
let popingNotice;
|
||||||
let popingNoticeContent;
|
let popingNoticeContent;
|
||||||
let closePopingNotice;
|
let closePopingNotice;
|
||||||
|
let titleModalFormatSelector;
|
||||||
|
let descriptionModalFormatSelector;
|
||||||
|
let modalFormatSelector;
|
||||||
|
let videoFormats;
|
||||||
|
let audioFormats;
|
||||||
|
let closeModalFormatSelector;
|
||||||
|
|
||||||
function downloadFormButtonHandler(event) {
|
function downloadFormButtonHandler(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
modalLoading.classList.add('active');
|
modalLoading.classList.add('active');
|
||||||
getRealURL(downloadFormUrl.value).then( (response) => {
|
askForURL(downloadFormUrl.value);
|
||||||
|
}
|
||||||
|
function askForURL(url, format) {
|
||||||
|
getRealURL(url, format).then( (response) => {
|
||||||
|
if ( response.options !== undefined && response.options.list_formats !== undefined && response.options.list_formats ) {
|
||||||
|
titleModalFormatSelector.innerText = response.title;
|
||||||
|
descriptionModalFormatSelector.innerText = response.description;
|
||||||
|
videoFormats.innerHTML = '';
|
||||||
|
audioFormats.innerHTML = '';
|
||||||
|
for ( let x of response.formats.audio_formats) {
|
||||||
|
let a = document.createElement('a');
|
||||||
|
a.innerText = 'Id: ' + x.id + "\n"
|
||||||
|
+ 'Format: ' + x.mimeType + "\n"
|
||||||
|
+ 'AudioSampleRate: ' + x.audioSampleRate + "\n"
|
||||||
|
+ 'Bitrate: ' + x.bitrate + ".\n";
|
||||||
|
a.addEventListener( 'click', (event) => {
|
||||||
|
modalLoading.classList.add('active');
|
||||||
|
askForURL(url, x.id );
|
||||||
|
});
|
||||||
|
audioFormats.appendChild(a);
|
||||||
|
modalLoading.classList.remove('active');
|
||||||
|
modalFormatSelector.classList.add('active');
|
||||||
|
}
|
||||||
|
for ( let x of response.formats.video_formats ) {
|
||||||
|
let a = document.createElement('a');
|
||||||
|
a.innerText = 'Id: ' + x.id + "\n"
|
||||||
|
+ 'Format: ' + x.mimeType + "\n"
|
||||||
|
+ 'QualityLabel: ' + x.qualityLabel + "p\n"
|
||||||
|
+ 'Bitrate: ' + x.bitrate + "\n"
|
||||||
|
+ (
|
||||||
|
( x.audioSampleRate !== undefined ) ?
|
||||||
|
'AudioSampleRate: ' + x.audioSampleRate + ".\n" :
|
||||||
|
"No audio."
|
||||||
|
);
|
||||||
|
a.addEventListener( 'click', (event) => {
|
||||||
|
modalLoading.classList.add('active');
|
||||||
|
askForURL(url, x.id );
|
||||||
|
});
|
||||||
|
videoFormats.appendChild(a);
|
||||||
|
modalLoading.classList.remove('active');
|
||||||
|
modalFormatSelector.classList.add('active');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
video.src = response.url;
|
video.src = response.url;
|
||||||
filename = response.filename;
|
filename = response.filename;
|
||||||
url = response.url;
|
url = response.url;
|
||||||
@ -27,14 +75,17 @@ function downloadFormButtonHandler(event) {
|
|||||||
modalLoading.classList.remove('active');
|
modalLoading.classList.remove('active');
|
||||||
modalVideoContainer.style.display = 'block';
|
modalVideoContainer.style.display = 'block';
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}).catch ( (error) => {
|
}).catch ( (error) => {
|
||||||
|
console.log(error);
|
||||||
modalLoading.classList.remove('active');
|
modalLoading.classList.remove('active');
|
||||||
popingNoticeContent.innerHTML = '';
|
popingNoticeContent.innerHTML = '';
|
||||||
let p = document.createElement('p');
|
let p = document.createElement('p');
|
||||||
p.appendChild(document.createTextNode('The url '));
|
p.appendChild(document.createTextNode('The url '));
|
||||||
let input_url = document.createElement('a');
|
let input_url = document.createElement('a');
|
||||||
input_url.href = downloadFormUrl.value;
|
input_url.href = url;
|
||||||
input_url.innerText = downloadFormUrl.value;
|
input_url.innerText = url;
|
||||||
p.appendChild(input_url)
|
p.appendChild(input_url)
|
||||||
p.appendChild(document.createTextNode(' is not supported, if you think this is an error, report it '));
|
p.appendChild(document.createTextNode(' is not supported, if you think this is an error, report it '));
|
||||||
let issues_url = 'https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl/issues';
|
let issues_url = 'https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl/issues';
|
||||||
@ -45,6 +96,7 @@ function downloadFormButtonHandler(event) {
|
|||||||
p.appendChild(document.createTextNode('.'));
|
p.appendChild(document.createTextNode('.'));
|
||||||
popingNoticeContent.appendChild(p);
|
popingNoticeContent.appendChild(p);
|
||||||
popingNotice.classList.add('active');
|
popingNotice.classList.add('active');
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +138,10 @@ async function generateBlobVideoByProxy(url) {
|
|||||||
return blob;
|
return blob;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getRealURL(url) {
|
async function getRealURL(url, format) {
|
||||||
|
let request = { url: url };
|
||||||
|
if (format !== undefined)
|
||||||
|
request.format = format;
|
||||||
const response = await fetch('/api', {
|
const response = await fetch('/api', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
mode: 'cors',
|
mode: 'cors',
|
||||||
@ -94,7 +149,7 @@ async function getRealURL(url) {
|
|||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({url: url}),
|
body: JSON.stringify(request),
|
||||||
});
|
});
|
||||||
return response.json();
|
return response.json();
|
||||||
}
|
}
|
||||||
@ -118,14 +173,23 @@ window.addEventListener('load', (event) => {
|
|||||||
downloadVideoPrepare = document.querySelector('#download-video-prepare');
|
downloadVideoPrepare = document.querySelector('#download-video-prepare');
|
||||||
closeAndResetVideoContainer = document.querySelector('#close-and-reset-video-container');
|
closeAndResetVideoContainer = document.querySelector('#close-and-reset-video-container');
|
||||||
modalLoading = document.querySelector('#modal-loading');
|
modalLoading = document.querySelector('#modal-loading');
|
||||||
popingNotice = document.querySelector('.poping-notice');
|
popingNotice = document.querySelector('#poping-notice');
|
||||||
popingNoticeContent = document.querySelector('.poping-notice-content');
|
popingNoticeContent = document.querySelector('#poping-notice-content');
|
||||||
closePopingNotice = document.querySelector('.close-poping-notice');
|
closePopingNotice = document.querySelector('#close-poping-notice');
|
||||||
|
titleModalFormatSelector = document.querySelector('#modal-format-selector h2');
|
||||||
|
descriptionModalFormatSelector = document.querySelector('#modal-format-selector p');
|
||||||
|
modalFormatSelector = document.querySelector('#modal-format-selector');
|
||||||
|
videoFormats = document.querySelector('#modal-format-selector .video-formats');
|
||||||
|
audioFormats = document.querySelector('#modal-format-selector .audio-formats');
|
||||||
|
closeModalFormatSelector = document.querySelector('#close-modal-format-selector');
|
||||||
|
|
||||||
downloadFormButton.addEventListener('click', downloadFormButtonHandler);
|
downloadFormButton.addEventListener('click', downloadFormButtonHandler);
|
||||||
downloadVideoPrepare.addEventListener('click', downloadVideoPrepareHandler);
|
downloadVideoPrepare.addEventListener('click', downloadVideoPrepareHandler);
|
||||||
downloadForm.addEventListener('submit', downloadFormHandler);
|
downloadForm.addEventListener('submit', downloadFormHandler);
|
||||||
closeAndResetVideoContainer.addEventListener('click', closeAndResetVideoContainerHandler);
|
closeAndResetVideoContainer.addEventListener('click', closeAndResetVideoContainerHandler);
|
||||||
|
closeModalFormatSelector.addEventListener('click', (event) => {
|
||||||
|
modalFormatSelector.classList.remove('active');
|
||||||
|
});
|
||||||
closePopingNotice.addEventListener('click', (event) => {
|
closePopingNotice.addEventListener('click', (event) => {
|
||||||
popingNotice.classList.remove('active');
|
popingNotice.classList.remove('active');
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user