0
0
Fork 0

Delete old files

This commit is contained in:
Tyler-A 2020-07-29 22:41:52 -06:00
parent 510e4aeeb0
commit aca049f778
16 changed files with 0 additions and 744 deletions

84
app.js
View file

@ -1,84 +0,0 @@
var vue_config = {
el: `#app`,
data: {
api_base: `https://api.spotify.com/v1`,
duration: ``,
type: ``,
count: ``,
show: {
popularity_popup: false,
popularity_hover: false,
follower_hover: false,
modal_content: false,
modal: {
popularity: false,
track: false,
artist: false,
playlist_export: false,
}
},
error: {
main: ``,
auth: ``,
},
auth: {
alert: `We will only be able to access your top tracks and artists, nothing else. This is also only done on your browser. Our servers do not see any of the data from your account.`,
base_url: `https://accounts.spotify.com/authorize`,
redirect: `http://oliver.akins.me/top-lists`,
client_id: `3a1795e9d55445b0aa0c05dd74c866fb`,
scopes: [
`user-top-read`
],
show_dialog: false,
use_state: false
},
user: {
name: ``,
image: ``
},
data: {
tracks: [],
artists: []
}
},
computed: {
spotify_auth_url: auth_url,
is_authed: verify_auth,
button_type: get_button_text,
},
methods: {
get_token: function () {
let params = new URLSearchParams(window.location.hash.slice(1));
return params.get(`access_token`);
},
get_user: function () {
axios.get(
`${this.api_base}/me`,
{ headers: { Authorization: `Bearer ${this.get_token()}` } }
).then((response) => {
if (response.error) {
window.location.hash = ``;
window.location.href = this.auth.redirect;
return
}
let data = response.data;
// Set the Vue user object
this.user.name = data.display_name;
this.user.image = data.images.length > 0 ? data.images[0].url : ``;
}).catch((err) => {
window.location.hash = ``;
window.location.href = this.auth.redirect;
return
})
},
get_data: fetch_data,
hide_modal: function () {
this.show.modal.popularity = false;
this.show.modal.track = false;
this.show.modal.artist = false;
this.show.modal.playlist_export = false;
}
}
};

View file

@ -1,17 +0,0 @@
<div class="card">
<div class="image">
<img v-if="artist.image" :src="artist.image.url" :alt="artist.name + 's profile picture'" target="_blank" rel="noopener">
<div class="missing-image" v-else>
<music-note colour="#1DB954"></music-note>
</div>
</div>
<div class="info">
<span class="title">
<a :href="artist.link" target="_blank" rel="noopener">{{artist.name}}</a>
</span>
<br>
<span class="subtitle">{{genres}}</span>
</div>
<div class="bottom left corner popularity" v-tooltip="popularity_tooltip" @click.self="show_popularity_modal()">{{artist.popularity}}</div>
<div class="bottom right corner followers" v-tooltip="followers_tooltip">{{artist.follower_count.toLocaleString()}}</div>
</div>

View file

@ -1,43 +0,0 @@
Vue.component(
`artist`,
{
props: [ `artist` ],
data: function () {
return {
popularity_tooltip: `Popularity`,
followers_tooltip: `Followers`,
};
},
computed: {
genres: function () {
let genres = [];
for (var genre of this.artist.genres) {
genres.push(genre.toTitleCase());
};
return genres.join(`, `);
}
},
methods: {
show_popularity_modal: function () {
this.$emit(`popularity_click`)
}
},
template: `<div class="card">
<div class="image">
<img v-if="artist.image" :src="artist.image.url" :alt="artist.name + 's profile picture'" target="_blank" rel="noopener">
<div class="missing-image" v-else>
<music-note colour="#1DB954"></music-note>
</div>
</div>
<div class="info">
<span class="title">
<a :href="artist.link" target="_blank" rel="noopener">{{artist.name}}</a>
</span>
<br>
<span class="subtitle">{{genres}}</span>
</div>
<div class="bottom left corner popularity" v-tooltip="popularity_tooltip" @click.self="show_popularity_modal()">{{artist.popularity}}</div>
<div class="bottom right corner followers" v-tooltip="followers_tooltip">{{artist.follower_count.toLocaleString()}}</div>
</div>`
}
)

View file

@ -1,16 +0,0 @@
Vue.component(
`music-note`,
{
props: [ `colour` ],
template: `<svg width="72" height="72" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="24" height="24" fill="none" rx="0" ry="0"></rect><path fill-rule="evenodd" clip-rule="evenodd" d="M17.4911 2.11667L21.4511 4.09667C21.9411 4.34667 22.1411 4.93667 21.8911 5.43667C21.6411 5.93667 21.0411 6.13667 20.5511 5.88667L18.0011 4.61667L17.9911 16.4367C17.9911 16.4467 17.9936 16.4567 17.9961 16.4667C17.9986 16.4767 18.0011 16.4867 18.0011 16.4967C18.0011 18.4267 16.4311 19.9967 14.5011 19.9967C12.5711 19.9967 11.0011 18.4267 11.0011 16.4967C11.0011 14.5667 12.5711 12.9967 14.5011 12.9967C15.0411 12.9967 15.5411 13.1267 16.0011 13.3467L16.0111 3.10667C15.9911 2.99667 16.0011 2.87667 16.0311 2.75667C16.1711 2.14667 16.9411 1.80667 17.4911 2.11667ZM12.8911 5.43664C12.6511 5.93664 12.0511 6.13664 11.5511 5.88664L9.0011 4.61664L8.9911 18.4366C8.9911 18.4466 8.9936 18.4566 8.9961 18.4666C8.9986 18.4766 9.0011 18.4866 9.0011 18.4966C9.0011 20.4266 7.4311 21.9966 5.5011 21.9966C3.5711 21.9966 2.0011 20.4266 2.0011 18.4966C2.0011 16.5666 3.5711 14.9966 5.5011 14.9966C6.0411 14.9966 6.5411 15.1266 7.0011 15.3466L7.0111 3.10664C6.9911 2.99664 7.0011 2.87664 7.0311 2.76664C7.1711 2.14664 7.9411 1.81664 8.4911 2.12664L12.4411 4.09664C12.9411 4.34664 13.1411 4.94664 12.8911 5.43664Z" :fill="colour || '#ffffff'"></path></svg>`
}
);
Vue.component(
`close`,
{
props: [ `colour` ],
template: `<svg width="72" height="72" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="24" height="24" fill="none" rx="0" ry="0"></rect><path fill-rule="evenodd" clip-rule="evenodd" d="M13.4049 12.0025L18.6949 6.7125C19.0849 6.3225 19.0849 5.6925 18.6949 5.3025C18.3049 4.9125 17.6749 4.9125 17.2849 5.3025L11.9949 10.5925L6.70494 5.2925C6.31494 4.9025 5.68494 4.9025 5.29494 5.2925C4.90494 5.6825 4.90494 6.3125 5.29494 6.7025L10.5849 12.0025L5.29494 17.2925C4.90494 17.6825 4.90494 18.3125 5.29494 18.7025C5.48494 18.9025 5.73494 19.0025 5.99494 19.0025C6.25494 19.0025 6.50494 18.9025 6.70494 18.7125L11.9949 13.4125L17.2849 18.7025C17.4849 18.9025 17.7349 19.0025 17.9949 19.0025C18.2549 19.0025 18.5049 18.9025 18.7049 18.7125C19.0949 18.3225 19.0949 17.6925 18.7049 17.3025L13.4049 12.0025Z" :fill="colour || '#ffffff'"></path></svg>`
}
)

View file

@ -1,22 +0,0 @@
<div class="card">
<div class="image">
<a v-if="track.album.image.url" :href="track.album.link" target="_blank" rel="noopener">
<img :src="track.album.image.url" :alt="track.album.name + ' Cover Image'" class="cover">
</a>
<a v-else :href="track.album.link" target="_blank" rel="noopener">
<div class="missing-image">
<music-note colour="#1DB954"></music-note>
</div>
</a>
</div>
<div class="info">
<span class="title remote" v-if="!track.locality">
<a :href="track.link" target="_blank" rel="noopener">{{track.name}}</a>
</span>
<span class="title local" v-else>{{track.name}}</span>
<br>
<span class="subtitle" v-html="artists"></span>
</div>
<div class="popularity bottom left corner" v-tooltip="popularity_tooltip" @click.self="show_popularity_modal()">{{track.popularity}}</div>
<div class="duration bottom right corner">{{duration}}</div>
</div>

View file

@ -1,70 +0,0 @@
Vue.component(
`track-card`,
{
props: [ `track` ],
data: function () {
return {
popularity_tooltip: `Popularity`
}
},
computed: {
duration: function () {
let timestamp = ``;
// Converting to seconds
let duration = Math.trunc(this.track.duration / 1000);
let seconds = duration % 60;
// Converting to minutes
duration = Math.trunc(duration / 60);
let minutes = duration % 60
// Converting to hours
duration = Math.trunc(duration / 60);
let hours = duration % 24;
if (seconds < 10) {
seconds = `0${seconds}`
};
return `${hours > 0 ? `${hours}:` : ''}${minutes}:${seconds}`;
},
artists: function () {
let artists = [];
for (var artist of this.track.artists) {
artists.push(
`<a href="${artist.external_urls.spotify}" target="_blank" rel="noopener">${artist.name}</a>`
)
}
return artists.join(`, `)
},
},
methods: {
show_popularity_modal: function () {
this.$emit('popularity_click')
}
},
template: `<div class="card">
<div class="image">
<a v-if="track.album.image.url" :href="track.album.link" target="_blank" rel="noopener">
<img :src="track.album.image.url" :alt="track.album.name + ' Cover Image'" class="cover">
</a>
<a v-else :href="track.album.link" target="_blank" rel="noopener">
<div class="missing-image">
<music-note colour="#1DB954"></music-note>
</div>
</a>
</div>
<div class="info">
<span class="title remote" v-if="!track.locality">
<a :href="track.link" target="_blank" rel="noopener">{{track.name}}</a>
</span>
<span class="title local" v-else>{{track.name}}</span>
<br>
<span class="subtitle" v-html="artists"></span>
</div>
<div class="popularity bottom left corner" v-tooltip="popularity_tooltip" @click.self="show_popularity_modal()">{{track.popularity}}</div>
<div class="duration bottom right corner">{{duration}}</div>
</div>`
}
);

View file

@ -1,87 +0,0 @@
div.card {
/* Card only variables */
--border-radius: 5px;
background-color: var(--card-colour);
color: var(--card-text);
border-radius: var(--border-radius);
border-style: none;
padding: 10px;
padding-top: 20px;
margin: 5px auto;
width: 90%;
position: relative;
display: flex;
flex-direction: column;
}
div.card > div.image {
text-align: center;
}
div.card > div.image img {
--size: 200px;
width: var(--size);
height: var(--size);
}
div.card div.missing-image {
background-color: #3a3a3aaa;
justify-content: center;
border-radius: 100px;
align-items: center;
margin-bottom: 5px;
margin: 0 auto;
display: flex;
height: 200px;
width: 200px;
}
div.card > div.info {
text-align: center;
padding-bottom: 20px;
margin: 0;
}
div.card > div.info > .title { font-size: larger; }
div.card > div.info > .subtitle { font-size: smaller; }
/* Positioning For Absolute Elements */
div.card .corner {
position: absolute;
padding: 1px 6px;
background-color: var(--on-card-colour);
color: var(--on-card-text);
}
div.card .right { right: 0; }
div.card .left { left: 0; }
div.card .top { top: 0; }
div.card .bottom { bottom: 0; }
/* border-radius: top-left top-right lower-right lower-left */
div.card .popularity {
border-radius: 0 var(--border-radius) 0 var(--border-radius);
cursor: pointer;
}
div.card .followers,
div.card .duration { border-radius: var(--border-radius) 0 var(--border-radius) 0; }
div.card a {
color: var(--text-on-card);
text-decoration: none;
}
div.card a:hover {
text-decoration: underline;
}
/* DESKTOP STYLES */
@media only screen and (min-width: 768px) {
div.card {
width: 230px;
margin: 5px;
}
}

View file

@ -1,56 +0,0 @@
div.modal-container {
width: 100%;
height: 100%;
z-index: 5;
background-color: var(--modal-container-background);
position: fixed;
left: 0;
top: 0;
display: flex;
align-items: center;
justify-content: center;
}
div.modal {
z-index: 6;
width: 90%;
max-height: 85%;
background-color: var(--modal-background);
border-radius: 5px;
padding: 0 15px;
position: relative;
}
div.modal * { color: var(--modal-text); }
div.modal h2 { margin-top: 30px; }
div.modal p { padding: 0px 5px 15px 5px; }
div.modal .close-modal {
width: 25px;
height: 25px;
position: absolute;
right: 10px;
top: 10px;
color: var(--spotify-green);
}
div.modal .close-modal:hover {
color: var(--error);
transform: scale(1.2, 1.2);
transition: ease-in-out;
cursor: pointer;
}
@media only screen and (min-width: 768px) {
div.modal {
width: 50%;
max-height: 75%;
}
div.modal h2 {
margin-top: 19.920px;
}
}

View file

@ -1,62 +0,0 @@
/* Transition for modal background appearing/disappearing */
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
/* Transition for modal card appearing disappearing */
.burst-enter-active {
animation: burst-in .5s;
}
.burst-leave-active { animation: burst-out .5s; }
@keyframes burst-in {
0% {
transform: scale(0);
}
100% {
transform: scale(1);
}
}
@keyframes burst-out {
0% {
transform: scale(1);
}
100% {
transform: scale(0);
}
}
@media only screen and (min-width: 768px) {
@keyframes burst-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.25);
}
100% {
transform: scale(1);
}
}
@keyframes burst-out {
0% {
transform: scale(1);
}
50% {
transform: scale(1.25);
}
100% {
transform: scale(0);
}
}
}

View file

@ -1,119 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Top Lists For Spotify</title>
<!-- Stylesheets -->
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="./css/card.css">
<link rel="stylesheet" href="./css/modal.css">
<link rel="stylesheet" href="./css/transitions.css">
<!-- Javascript Imports -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="./components/artist.js" defer async></script>
<script src="./components/track.js" defer async></script>
<script src="./components/icons.js" defer async></script>
<script src="https://unpkg.com/v-tooltip"></script>
<script src="./js/text_computation.js"></script>
<script src="./js/prototypes.js" async></script>
<script src="./js/dev/data.js" async></script>
<script src="./js/auth.js"></script>
<script src="./js/data.js"></script>
</head>
<body>
<div id="app" v-cloak>
<div id="login" v-if="!is_authed">
<div class="center">
<a :href="spotify_auth_url">
<button id="spotify-login">Login With Spotify</button>
</a>
<p class="error" v-if="error.auth">{{error.auth}}</p>
<p>{{auth.alert}}</p>
</div>
</div>
<div id="main" v-else v-cloak>
<div class="flex-row">
<div v-cloak class="account-info">
<img v-if="user.image" :src="user.image" :alt="`${user.name}'s profile picture`" class="profile-picture">
{{user.name}}
</div>
<div class="type">
<select v-model="type">
<option value="" disabled>Please Select A Type</option>
<option value="Tracks">Tracks</option>
<option value="Artists">Artists</option>
</select>
</div>
<div class="duration">
<select v-model="duration">
<option value="" disabled>Please Select A Duration</option>
<option value="long_term">Several Years</option>
<option value="medium_term">~6 Months</option>
<option value="short_term">~4 Weeks</option>
</select>
</div>
<div class="limit">
<input type="number" v-model="count" placeholder="How Many?">
</div>
<div id="submit-button" v-if="button_type && duration">
<button @click="get_data()">Get Top {{count > 1 ? count : `10`}} {{button_type}}</button>
</div>
</div>
<div class="flex-row error" v-if="error.main">{{error.main}}</div>
<div class="body" v-if="data.tracks.length > 0">
<track-card
v-for="top_track in data.tracks"
:track="top_track"
:key="top_track.id"
@popularity_click="show.modal.popularity = true"
></track-card>
</div>
<div class="body" v-if="data.artists.length > 0">
<artist
v-for="top_artist in data.artists"
:artist="top_artist"
:key="top_artist.id"
@popularity_click="show.modal.popularity = true"
></artist>
</div>
<!-- Modals Needed -->
<transition name="fade" @after-enter="show.modal_content = true">
<div
v-if="Object.values(this.show.modal).includes(true)"
class="modal-container"
@click.self="show.modal_content = false"
>
<transition name="burst" @after-leave="hide_modal">
<div v-if="show.modal_content && show.modal.popularity" class="modal">
<span @click="show.modal_content = false">
<close class="close-modal" colour="#ffffff80" @click="show.modal_content = false"></close>
</span>
<h2 class="center">How is Popularity Calculated?</h2>
<p class="center">
Popularity is a value between 0 and 100 that is calculated by Spotify based on how many plays the song/artist has recieved and how recent those plays are.
</p>
<p class="center">
This means that an artist/song that has had 100 plays today will have a higher popularity than a song/artist that has 100 from a month ago.
</p>
<p class="center">
This number is not updated in real time so refreshing the page will not reflect it's absolute accurate value.
</p>
</div>
</transition>
</div>
</transition>
</div>
</div>
<script src="./app.js"></script>
<script src="./js/dev/app_modifications.js"></script>
<script>
let app = new Vue(vue_config)
</script>
</body>
</html>

View file

@ -1,53 +0,0 @@
function auth_url () {
let params = [
`client_id=${this.auth.client_id}`,
`response_type=token`,
`redirect_uri=${encodeURIComponent(this.auth.redirect)}`,
`scope=${encodeURIComponent(this.auth.scopes.join(" "))}`,
`show_dialog=${this.auth.show_dialog}`
];
// Create the state data if we are using it
if (this.auth.use_state) {
let state = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
params.push(`state=${state}`);
localStorage.setItem(`top-spotify-state`, state);
};
return `${this.auth.base_url}?${params.join("&")}`;
};
function verify_auth () {
let params = new URLSearchParams(window.location.hash.slice(1));
// Check to ensure the authorization was a success
if (params.get(`access_token`)) {
this.get_user()
// Check if we compare state
if (this.use_state) {
// Compare given state to localstorage state
let LS_state = localStorage.getItem(`top-spotify-state`);
if (LS_state = params.get(`state`)) {
console.info(`State compare success`)
this.authed = true;
return true
}
console.error(`State compare failed`)
return false
} else {
return true
}
} else {
let error = (new URLSearchParams(window.location.search)).get(`error`)
// Authorization failed, error to the user
if (error !== null) {
this.error.auth = `Authentication failed or was cancelled, please try again.`;
window.location.hash = ``;
}
return false;
}
}

View file

@ -1,57 +0,0 @@
function fetch_data () {
let url = `${this.api_base}/me/top/${this.type.toLowerCase()}`;
let limit = parseInt(this.count);
if (!limit) { limit = 10; };
url += `?limit=${limit}&time_range=${this.duration}`;
axios.get(
url,
{ headers: { Authorization: `Bearer ${this.get_token()}` } }
).then((response) => {
this.data.artists = [];
this.data.tracks = [];
this.error.main = ``;
switch (this.type) {
case `Tracks`:
for (var track of response.data.items) {
this.data.tracks.push({
name: track.name,
popularity: track.popularity,
artists: track.artists,
link: track.external_urls.spotify,
duration: track.duration_ms,
locality: track.is_local,
id: track.uri,
album: {
name: track.album.name,
image: track.album.images[1],
link: track.album.external_urls.spotify
}
});
};
break;
case `Artists`:
for (var artist of response.data.items) {
this.data.artists.push({
name: artist.name,
id: artist.id,
popularity: artist.popularity,
follower_count: artist.followers.total,
image: artist.images[1],
genres: artist.genres,
link: artist.external_urls.spotify
});
};
break;
default:
this.error.main = `TypeError: ${this.type} is not a supported category`;
break
};
}).catch((err) => {
this.error.main = `${err.name}: ${err.message}`
})
}

View file

@ -1,28 +0,0 @@
let params = new URLSearchParams(window.location.search);
let dev_mode = !(params.get(`dev`) == null || params.get(`dev`) === `false`);
let preview = !(params.get(`preview`) == null || params.get(`preview`) === `false`);
function get_dev_data () {
switch (this.type) {
case `Artists`:
this.data.artists = dev_artists;
this.data.tracks = [];
break;
case `Tracks`:
this.data.artists = [];
this.data.tracks = dev_tracks;
break;
default:
this.data.tracks = [];
this.data.artists = [];
break;
}
}
if (dev_mode || preview) {
vue_config.data.user.name = `Preview Mode`;
vue_config.methods.get_data = get_dev_data;
vue_config.computed.is_authed = function () { return true; };
};

View file

@ -1 +0,0 @@
const dev_tracks = [{name:"Into the Unknown",popularity:34,locality:false,link:"https://open.spotify.com/track/37POsvF7xupvgDnYYIXoYX",id:"spotify:track:37POsvF7xupvgDnYYIXoYX",duration:225273,artists:[{external_urls:{spotify:"https://open.spotify.com/artist/6ls5A8Wys9Swixpz4v6kj3"},href:"https://api.spotify.com/v1/artists/6ls5A8Wys9Swixpz4v6kj3",id:"6ls5A8Wys9Swixpz4v6kj3",name:"The Lighthouse And The Whaler",type:"artist",uri:"spotify:artist:6ls5A8Wys9Swixpz4v6kj3"}],album:{name:"Into the Unknown",link:"https://open.spotify.com/album/6NpAhMmG0TkOpapqs6NFnj",image:{url:"https://i.scdn.co/image/ab67616d00001e02e0f91ea6315c150d84e031be"}}},{name:"The Science Love Song",popularity:35,locality:false,link:"https://open.spotify.com/track/0DkvyLEW2VG5e2ruf7kTS9",id:"spotify:track:0DkvyLEW2VG5e2ruf7kTS9",duration:200054,artists:[{external_urls:{spotify:"https://open.spotify.com/artist/7E8gU2qkctwGqHBizPRH9A"},href:"https://api.spotify.com/v1/artists/7E8gU2qkctwGqHBizPRH9A",id:"7E8gU2qkctwGqHBizPRH9A",name:"AsapSCIENCE",type:"artist",uri:"spotify:artist:7E8gU2qkctwGqHBizPRH9A"}],album:{name:"The Science Love Song",link:"https://open.spotify.com/album/13sXGjZuZgXuvjAZfXOXfP",image:{url:"https://i.scdn.co/image/ab67616d00001e02d5e24468d455c3140f0581b2"}}}]; const dev_artists = [{popularity:87,name:"Avicii",link:"https://open.spotify.com/artist/1vCWHaC5f2uS3yhpwWbIA6",image:{url:"https://i.scdn.co/image/9c0d8fa969a9f5db6ff860203d6880a125e501d2"},id:"1vCWHaC5f2uS3yhpwWbIA6",genres:["big room","dance pop","edm","pop"],follower_count:17671212},{popularity:52,name:"'Come From Away' Company",link:"https://open.spotify.com/artist/3yVB4N2PhQy60dAxzCoNdQ",image:undefined,id:"3yVB4N2PhQy60dAxzCoNdQ",genres:["broadway","show tunes"],follower_count:3143}];

10
js/prototypes.js vendored
View file

@ -1,10 +0,0 @@
String.prototype.toTitleCase = function () {
let words = this.split(` `);
let new_words = [];
for (var word of words) {
new_words.push(
`${word[0].toUpperCase()}${word.slice(1).toLowerCase()}`
);
};
return new_words.join(` `);
}

View file

@ -1,19 +0,0 @@
function get_button_text () {
if (this.count === ``) {
return this.type;
}
else if (this.count === `1`) {
this.error.main = ``;
return this.type.slice(0,-1);
}
else if (this.count <= 0) {
this.error.main = `Cannot get 0 or fewer ${this.type.toLowerCase()}`;
return false;
}
else if (this.count > 50) {
this.error.main = `Cannot get more than 50 ${this.type.toLowerCase()}`;
return false;
};
this.error.main = ``;
return this.type;
};