├── README.md ├── assets ├── favicon.webp ├── stars │ ├── star-1.webp │ ├── star-10.webp │ ├── star-11.webp │ ├── star-12.webp │ ├── star-13.webp │ ├── star-14.webp │ ├── star-15.webp │ ├── star-16.webp │ ├── star-17.webp │ ├── star-18.webp │ ├── star-19.webp │ ├── star-2.webp │ ├── star-20.webp │ ├── star-21.webp │ ├── star-22.webp │ ├── star-23.webp │ ├── star-24.webp │ ├── star-25.webp │ ├── star-26.webp │ ├── star-27.webp │ ├── star-28.webp │ ├── star-29.webp │ ├── star-3.webp │ ├── star-30.webp │ ├── star-31.webp │ ├── star-32.webp │ ├── star-33.webp │ ├── star-34.webp │ ├── star-35.webp │ ├── star-36.webp │ ├── star-37.webp │ ├── star-38.webp │ ├── star-39.webp │ ├── star-4.webp │ ├── star-40.webp │ ├── star-41.webp │ ├── star-42.webp │ ├── star-43.webp │ ├── star-44.webp │ ├── star-45.webp │ ├── star-46.webp │ ├── star-47.webp │ ├── star-48.webp │ ├── star-49.webp │ ├── star-5.webp │ ├── star-50.webp │ ├── star-6.webp │ ├── star-7.webp │ ├── star-8.webp │ └── star-9.webp └── svgPlayList.svg ├── preview ├── preview.avif └── preview-og.avif ├── playlist ├── assets │ ├── n1.avif │ ├── favicon.webp │ ├── preview.avif │ ├── svgSpriteCardMusical.svg │ └── svgSprite.svg ├── index.css ├── index.js └── index.html ├── license.txt └── index.html /README.md: -------------------------------------------------------------------------------- 1 | [![Foto Preview](preview/preview.avif)](https://20essentials.github.io/20TracksForEachOne/) 2 | -------------------------------------------------------------------------------- /assets/favicon.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/favicon.webp -------------------------------------------------------------------------------- /preview/preview.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/preview/preview.avif -------------------------------------------------------------------------------- /playlist/assets/n1.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/playlist/assets/n1.avif -------------------------------------------------------------------------------- /preview/preview-og.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/preview/preview-og.avif -------------------------------------------------------------------------------- /assets/stars/star-1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-1.webp -------------------------------------------------------------------------------- /assets/stars/star-10.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-10.webp -------------------------------------------------------------------------------- /assets/stars/star-11.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-11.webp -------------------------------------------------------------------------------- /assets/stars/star-12.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-12.webp -------------------------------------------------------------------------------- /assets/stars/star-13.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-13.webp -------------------------------------------------------------------------------- /assets/stars/star-14.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-14.webp -------------------------------------------------------------------------------- /assets/stars/star-15.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-15.webp -------------------------------------------------------------------------------- /assets/stars/star-16.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-16.webp -------------------------------------------------------------------------------- /assets/stars/star-17.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-17.webp -------------------------------------------------------------------------------- /assets/stars/star-18.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-18.webp -------------------------------------------------------------------------------- /assets/stars/star-19.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-19.webp -------------------------------------------------------------------------------- /assets/stars/star-2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-2.webp -------------------------------------------------------------------------------- /assets/stars/star-20.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-20.webp -------------------------------------------------------------------------------- /assets/stars/star-21.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-21.webp -------------------------------------------------------------------------------- /assets/stars/star-22.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-22.webp -------------------------------------------------------------------------------- /assets/stars/star-23.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-23.webp -------------------------------------------------------------------------------- /assets/stars/star-24.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-24.webp -------------------------------------------------------------------------------- /assets/stars/star-25.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-25.webp -------------------------------------------------------------------------------- /assets/stars/star-26.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-26.webp -------------------------------------------------------------------------------- /assets/stars/star-27.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-27.webp -------------------------------------------------------------------------------- /assets/stars/star-28.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-28.webp -------------------------------------------------------------------------------- /assets/stars/star-29.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-29.webp -------------------------------------------------------------------------------- /assets/stars/star-3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-3.webp -------------------------------------------------------------------------------- /assets/stars/star-30.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-30.webp -------------------------------------------------------------------------------- /assets/stars/star-31.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-31.webp -------------------------------------------------------------------------------- /assets/stars/star-32.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-32.webp -------------------------------------------------------------------------------- /assets/stars/star-33.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-33.webp -------------------------------------------------------------------------------- /assets/stars/star-34.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-34.webp -------------------------------------------------------------------------------- /assets/stars/star-35.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-35.webp -------------------------------------------------------------------------------- /assets/stars/star-36.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-36.webp -------------------------------------------------------------------------------- /assets/stars/star-37.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-37.webp -------------------------------------------------------------------------------- /assets/stars/star-38.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-38.webp -------------------------------------------------------------------------------- /assets/stars/star-39.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-39.webp -------------------------------------------------------------------------------- /assets/stars/star-4.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-4.webp -------------------------------------------------------------------------------- /assets/stars/star-40.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-40.webp -------------------------------------------------------------------------------- /assets/stars/star-41.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-41.webp -------------------------------------------------------------------------------- /assets/stars/star-42.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-42.webp -------------------------------------------------------------------------------- /assets/stars/star-43.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-43.webp -------------------------------------------------------------------------------- /assets/stars/star-44.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-44.webp -------------------------------------------------------------------------------- /assets/stars/star-45.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-45.webp -------------------------------------------------------------------------------- /assets/stars/star-46.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-46.webp -------------------------------------------------------------------------------- /assets/stars/star-47.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-47.webp -------------------------------------------------------------------------------- /assets/stars/star-48.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-48.webp -------------------------------------------------------------------------------- /assets/stars/star-49.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-49.webp -------------------------------------------------------------------------------- /assets/stars/star-5.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-5.webp -------------------------------------------------------------------------------- /assets/stars/star-50.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-50.webp -------------------------------------------------------------------------------- /assets/stars/star-6.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-6.webp -------------------------------------------------------------------------------- /assets/stars/star-7.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-7.webp -------------------------------------------------------------------------------- /assets/stars/star-8.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-8.webp -------------------------------------------------------------------------------- /assets/stars/star-9.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/assets/stars/star-9.webp -------------------------------------------------------------------------------- /playlist/assets/favicon.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/playlist/assets/favicon.webp -------------------------------------------------------------------------------- /playlist/assets/preview.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/20essentials/20TracksForEachOne/HEAD/playlist/assets/preview.avif -------------------------------------------------------------------------------- /assets/svgPlayList.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notzice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /playlist/assets/svgSpriteCardMusical.svg: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /playlist/assets/svgSprite.svg: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 20 Tracks For Each One 7 | 8 | 9 | 10 | 11 | 15 | 19 | 20 | 21 | 22 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 40 | 41 | 42 | 43 | 44 |
45 |
46 | 52 | 53 | 0/20 54 | 55 |
○-
56 |
-○
57 |
58 |
59 | 60 | 61 |
62 | 68 | 69 | 0/20 70 |
71 | 72 | 133 | 134 |
135 | 136 | 173 | 174 |
175 |
176 |
177 |
178 | 179 |
180 | 181 | 182 |
183 |
184 | 190 | 191 |
192 |
193 |
194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 |
213 |
214 |
215 |

The Playlists are saved in your LocalStorage (LS)

216 | 217 |
218 |
219 |

Things you should know about localStorage

220 | 231 |
232 |

Actions that could lead to the deletion of the data stored in LS

233 | 242 |
243 |

244 | I recommend making a backup of your playlists by obtaining a JSON object 245 | that will contain both the playlist name and its respective songs, with 246 | the URLs for each song. 247 |

248 |
249 |

250 | I recommend saving that JSON in 251 | Google Keep, which is free. 252 |

253 | 254 |
255 | 258 |
259 | 266 | 267 | 268 | 269 |
270 |
271 | 278 |
279 | 287 |
288 | 289 | 290 | 291 |
292 |
293 | 294 | 297 |
298 | 305 | 306 | 307 | 308 |
309 |
310 | 317 |
318 | 326 |
327 | 328 | 329 | 330 |
331 | 332 |
333 | 334 |
335 | 336 |
337 | 338 | 341 |
342 | 348 |
349 | 357 |
358 | 359 | 360 |
361 |
362 | 363 | 364 |
365 | 381 | 382 | 383 |
384 |
385 | 386 | 387 |
388 | 414 | 415 | 416 |
417 |
418 | 419 | 420 |
421 |
422 | 423 |
Number of Performers: 0
424 |
Number of songs: 0
425 | 426 | 427 |
428 | gota 429 |
430 | 431 | -------------------------------------------------------------------------------- /playlist/index.css: -------------------------------------------------------------------------------- 1 | *, 2 | *::after, 3 | *::before { 4 | box-sizing: border-box; 5 | margin: 0; 6 | padding: 0; 7 | font-family: sans-serif, Geneva, Tahoma; 8 | font-weight: 600; 9 | user-select: none; 10 | cursor: auto; 11 | } 12 | 13 | html { 14 | min-width: 350px; 15 | max-width: 1600px; 16 | display: block; 17 | margin-inline: auto; 18 | background-color: black; 19 | align-content: center; 20 | height: 100vh; 21 | } 22 | 23 | html, 24 | body { 25 | scroll-behavior: smooth; 26 | } 27 | 28 | body { 29 | --sb-track-color: transparent; 30 | --sb-thumb-color: linear-gradient( 31 | to bottom, 32 | var(--color1), 33 | var(--color2), 34 | var(--color3) 35 | ); 36 | --sb-size: 10px; 37 | } 38 | 39 | body::-webkit-scrollbar { 40 | width: var(--sb-size); 41 | } 42 | 43 | body::-webkit-scrollbar-track { 44 | background: var(--sb-track-color); 45 | } 46 | 47 | body::-webkit-scrollbar-thumb { 48 | background: var(--sb-thumb-color); 49 | } 50 | 51 | @supports not selector(::-webkit-scrollbar) { 52 | body { 53 | scrollbar-color: var(--sb-thumb-color) var(--sb-track-color); 54 | } 55 | } 56 | 57 | .am-modal { 58 | margin: auto; 59 | border: none; 60 | width: 100%; 61 | max-width: 275px; 62 | height: max-content; 63 | padding: 1rem; 64 | padding-top: 2rem; 65 | background-color: #111; 66 | box-shadow: 0 0 1px #0008; 67 | border-radius: 20px; 68 | color: gray; 69 | overflow: hidden; 70 | scale: 0; 71 | transition: scale 0.25s ease, display 0.25s allow-discrete, 72 | overlay 0.25s allow-discrete; 73 | 74 | &[open] { 75 | scale: 1; 76 | transition: scale 0.25s; 77 | 78 | @starting-style { 79 | scale: 0; 80 | } 81 | } 82 | 83 | .tituto-modal { 84 | text-wrap: balance; 85 | width: 80%; 86 | margin-bottom: 0.7rem; 87 | } 88 | 89 | h3 { 90 | font-size: 0.85rem; 91 | } 92 | 93 | .cerrar { 94 | position: absolute; 95 | top: 0.8rem; 96 | right: 0.8rem; 97 | padding: 0.4rem; 98 | border: none; 99 | transform: scale(0.9); 100 | border-radius: 50%; 101 | background-color: #000; 102 | box-shadow: 0 0 9px 0 #fff inset; 103 | overflow: hidden; 104 | font-size: 0.8rem; 105 | transition: box-shadow 0.5s ease; 106 | 107 | &:hover { 108 | background-color: #000; 109 | box-shadow: 0 0 28px 0 #fff2 inset; 110 | } 111 | } 112 | 113 | .nav-of-options-of-the-modal { 114 | width: 100%; 115 | height: 24px; 116 | display: flex; 117 | padding: 3px; 118 | gap: 6px; 119 | 120 | .am-button-nav-modal { 121 | width: 20%; 122 | height: 100%; 123 | margin: 0; 124 | border-radius: 4px; 125 | border: 0; 126 | display: flex; 127 | flex-wrap: wrap; 128 | place-content: center; 129 | background-color: #e9e9e9; 130 | 131 | &.button-nav-selected { 132 | background-color: #333; 133 | 134 | svg { 135 | color: #fff; 136 | } 137 | } 138 | 139 | svg { 140 | width: 100%; 141 | height: 90%; 142 | pointer-events: none; 143 | } 144 | } 145 | } 146 | 147 | .container-modal { 148 | display: flex; 149 | flex-direction: column; 150 | margin-top: 0.5rem; 151 | min-height: 90px; 152 | height: 100%; 153 | max-height: 300px; 154 | padding-bottom: 0.9rem; 155 | scroll-behavior: smooth; 156 | scrollbar-gutter: both-edges; 157 | overflow-y: auto; 158 | scrollbar-width: thin; 159 | scrollbar-color: white transparent; 160 | overscroll-behavior: contain; 161 | 162 | @media (width <= 1111px) and (orientation: landscape) { 163 | max-height: 150px; 164 | } 165 | 166 | .fila { 167 | display: flex; 168 | column-gap: 0.2rem; 169 | padding: 0.5rem; 170 | 171 | input { 172 | accent-color: lime; 173 | } 174 | } 175 | 176 | label { 177 | color: white; 178 | font-size: 0.8rem; 179 | background-color: transparent; 180 | width: 100%; 181 | align-content: center; 182 | } 183 | 184 | abbr { 185 | font-size: 0.8rem; 186 | } 187 | } 188 | 189 | &::backdrop { 190 | background-image: linear-gradient(to top, #2228 20%, #4448 40%); 191 | } 192 | 193 | input[type='checkbox'] { 194 | margin-right: 0.5rem; 195 | } 196 | 197 | .container-add-playlist { 198 | --validate-color: #00ff7f; 199 | --invalid-color: #f00f; 200 | position: relative; 201 | width: 100%; 202 | height: 100%; 203 | left: 0; 204 | bottom: 0; 205 | color: #fff; 206 | display: flex; 207 | align-items: center; 208 | padding: 12px 18px; 209 | border-top: 2px solid #fff2; 210 | transition: background-color 0.3s ease, padding 0.3s linear; 211 | z-index: 1000; 212 | 213 | &::after { 214 | content: ''; 215 | display: block; 216 | position: absolute; 217 | opacity: 0; 218 | left: -50%; 219 | transform-origin: left; 220 | transform: scaleX(0); 221 | transition: transform 0.5s; 222 | } 223 | 224 | &.mode-active { 225 | h3 { 226 | pointer-events: none; 227 | opacity: 0; 228 | display: none; 229 | } 230 | 231 | .container-inputs { 232 | display: flex; 233 | opacity: 1; 234 | } 235 | } 236 | 237 | h3 { 238 | z-index: 99999; 239 | font-family: Arial, Helvetica, sans-serif; 240 | pointer-events: none; 241 | transform: translateY(5px); 242 | align-content: center; 243 | text-transform: capitalize; 244 | font-size: 0.9rem; 245 | opacity: 1; 246 | visibility: visible; 247 | transition: opacity 0.7s ease; 248 | 249 | &::before { 250 | content: '+'; 251 | font-size: 24px; 252 | margin-right: 8px; 253 | vertical-align: -3px; 254 | } 255 | } 256 | 257 | .container-inputs { 258 | opacity: 0; 259 | display: none; 260 | z-index: 99999; 261 | width: 100%; 262 | position: relative; 263 | padding-bottom: 10px; 264 | transition: opacity 0.5s ease, display 0.5s ease allow-discrete; 265 | } 266 | 267 | span { 268 | position: absolute; 269 | left: 80%; 270 | font-size: 0.7rem; 271 | color: #fff8; 272 | position: relative; 273 | font-style: italic; 274 | top: 26px; 275 | } 276 | 277 | input { 278 | border: none; 279 | outline: none; 280 | font-family: Arial, Helvetica, sans-serif; 281 | color: var(--validate-color); 282 | 283 | &[type='text'] { 284 | width: 88%; 285 | background-color: transparent; 286 | height: 20px; 287 | position: absolute; 288 | top: 0%; 289 | border-bottom: 2px solid #fff8; 290 | 291 | &::placeholder { 292 | color: #fff8; 293 | } 294 | 295 | &.valid { 296 | color: var(--validate-color); 297 | border-bottom: 2px solid var(--validate-color); 298 | caret-color: var(--validate-color); 299 | } 300 | 301 | &.invalid { 302 | color: var(--invalid-color); 303 | border-bottom: 2px solid var(--invalid-color); 304 | caret-color: var(--invalid-color); 305 | } 306 | } 307 | 308 | &[type='submit'] { 309 | width: 17%; 310 | background-color: transparent; 311 | aspect-ratio: 1; 312 | transform: scale(0.8); 313 | border-radius: 999px; 314 | box-shadow: inset 0 0 0 8px #0003; 315 | position: absolute; 316 | background-color: #0f08; 317 | right: -12px; 318 | top: -20%; 319 | display: flex; 320 | flex-wrap: wrap; 321 | place-content: center; 322 | line-height: 1rem; 323 | font-size: 1em; 324 | transition: box-shadow 0.4s ease; 325 | 326 | &:hover { 327 | box-shadow: inset 0 0 0 0 #0003; 328 | } 329 | } 330 | } 331 | } 332 | } 333 | 334 | .myHeader { 335 | display: block; 336 | height: 5.5rem; 337 | position: relative; 338 | z-index: 5; 339 | background-image: linear-gradient( 340 | 45deg, 341 | var(--color1, #ee82ee), 342 | var(--color2, #87ceeb), 343 | var(--color3, #00ff7f) 344 | ); 345 | display: flex; 346 | flex-wrap: wrap; 347 | justify-content: center; 348 | align-items: center; 349 | flex-direction: column; 350 | row-gap: 0.5rem; 351 | padding-block: 0.6rem; 352 | --black: #0003; 353 | 354 | img { 355 | inline-size: 2.5rem; 356 | block-size: 2.5rem; 357 | filter: drop-shadow(1px 0px 0px var(--black)) 358 | drop-shadow(-1px 0px 0px var(--black)) drop-shadow(0px 1px 0px var(--black)) 359 | drop-shadow(0px -1px 0px var(--black)); 360 | } 361 | 362 | .namePlaylist { 363 | text-transform: uppercase; 364 | color: #fff; 365 | font-size: clamp(0.6rem, 0.4794rem + 0.2072vw, 0.69rem); 366 | } 367 | } 368 | 369 | .myNav { 370 | display: flex; 371 | width: 100%; 372 | height: 2rem; 373 | background-color: #222; 374 | flex-wrap: wrap; 375 | justify-content: center; 376 | top: -1px; 377 | align-items: center; 378 | position: sticky; 379 | z-index: 99999; 380 | box-shadow: 2px 2px 3px #2228; 381 | 382 | a, 383 | button { 384 | border: none; 385 | outline: none; 386 | min-height: 100%; 387 | margin-inline: 6px; 388 | background-color: transparent; 389 | align-content: center; 390 | padding: 0.2rem; 391 | 392 | @media (width >= 1000px) { 393 | &:hover, 394 | &.nav-btn-active { 395 | svg { 396 | fill: #fff; 397 | } 398 | } 399 | } 400 | 401 | @media (width <= 999px) { 402 | &.nav-btn-active, 403 | &.home:hover, 404 | &.recarga:hover { 405 | svg { 406 | fill: #fff; 407 | } 408 | } 409 | } 410 | 411 | * { 412 | pointer-events: none; 413 | } 414 | 415 | svg { 416 | transition: 0s; 417 | display: flex; 418 | flex-wrap: wrap; 419 | place-content: center; 420 | align-content: center; 421 | } 422 | } 423 | 424 | a { 425 | -webkit-tap-highlight-color: transparent; 426 | } 427 | 428 | .nav-playbutton { 429 | svg { 430 | scale: 0.9; 431 | } 432 | } 433 | 434 | .nav-list-momentary { 435 | position: relative; 436 | 437 | .btn-tooltip { 438 | --duration: 7s; 439 | --easing: linear; 440 | --c-color-1: rgba(26, 163, 255, 0.7); 441 | /* Changed color */ 442 | --c-color-2: #1aff1a; 443 | /* Changed color */ 444 | --c-color-3: #ff1a75; 445 | /* Changed color */ 446 | --c-color-4: rgba(26, 232, 255, 0.7); 447 | /* Changed color */ 448 | --c-shadow: rgba(87, 223, 255, 0.5); 449 | /* Changed color */ 450 | --c-shadow-inset-top: rgba(52, 223, 255, 0.9); 451 | /* Changed color */ 452 | --c-shadow-inset-bottom: rgba(215, 250, 255, 0.8); 453 | /* Changed color */ 454 | --c-radial-inner: #15d2ff; 455 | /* Changed color */ 456 | --c-radial-outer: #72faff; 457 | /* Changed color */ 458 | --c-color: #fff; 459 | appearance: none; 460 | outline: none; 461 | -webkit-tap-highlight-color: transparent; 462 | position: absolute; 463 | cursor: pointer; 464 | border: none; 465 | display: flex; 466 | border-radius: 24px; 467 | padding: 0; 468 | margin: 0; 469 | text-align: center; 470 | font-weight: 600; 471 | font-size: 16px; 472 | letter-spacing: 0.02em; 473 | line-height: 1.5; 474 | color: var(--c-color); 475 | background: radial-gradient( 476 | circle, 477 | var(--c-radial-inner), 478 | var(--c-radial-outer) 80% 479 | ); 480 | transform: scale(0); 481 | z-index: 200; 482 | box-shadow: 0 0 14px var(--c-shadow); 483 | pointer-events: auto; 484 | top: 150%; 485 | right: -36px; 486 | min-width: 250px; 487 | transition: transform 0.3s ease-in-out; 488 | 489 | &.tooltip-active { 490 | transform: scale(0.8); 491 | } 492 | 493 | svg { 494 | width: 25px; 495 | height: 40px; 496 | zoom: 0.4; 497 | align-content: center; 498 | pointer-events: none; 499 | position: relative; 500 | transform: translateY(10px); 501 | z-index: 50; 502 | } 503 | 504 | .triangle { 505 | width: 40px; 506 | height: 20px; 507 | background-color: #6ef7ff; 508 | position: absolute; 509 | right: 10px; 510 | top: -12px; 511 | z-index: -1; 512 | clip-path: polygon(0% 100%, 50% 0, 100% 100%); 513 | } 514 | } 515 | 516 | .btn-tooltip:before { 517 | content: ''; 518 | pointer-events: none; 519 | position: absolute; 520 | z-index: 3; 521 | left: 0; 522 | top: 0; 523 | right: 0; 524 | bottom: 0; 525 | border-radius: 24px; 526 | box-shadow: inset 0 3px 12px var(--c-shadow-inset-top), 527 | inset 0 -3px 4px var(--c-shadow-inset-bottom); 528 | } 529 | 530 | .btn-tooltip .wrapper { 531 | mask-image: radial-gradient(white, black); 532 | overflow: hidden; 533 | border-radius: 24px; 534 | padding: 8px 0; 535 | display: flex; 536 | text-align: center; 537 | justify-content: center; 538 | align-content: center; 539 | width: 100%; 540 | } 541 | 542 | .btn-tooltip .wrapper span { 543 | display: inline-block; 544 | position: relative; 545 | z-index: 200; 546 | } 547 | 548 | .btn-tooltip .wrapper .circle { 549 | position: absolute; 550 | left: 0; 551 | top: 0; 552 | width: 40px; 553 | height: 40px; 554 | border-radius: 50%; 555 | filter: blur(var(--blur, 8px)); 556 | background: var(--background, transparent); 557 | transform: translate(var(--x, 0), var(--y, 0)) translateZ(0); 558 | animation: var(--animation, none) var(--duration) alternate var(--easing) 559 | infinite; 560 | } 561 | 562 | .btn-tooltip .wrapper .circle.circle-1, 563 | .btn-tooltip .wrapper .circle.circle-9, 564 | .btn-tooltip .wrapper .circle.circle-10 { 565 | --background: var(--c-color-4); 566 | } 567 | 568 | .btn-tooltip .wrapper .circle.circle-3, 569 | .btn-tooltip .wrapper .circle.circle-4 { 570 | --background: var(--c-color-2); 571 | --blur: 14px; 572 | } 573 | 574 | .btn-tooltip .wrapper .circle.circle-5, 575 | .btn-tooltip .wrapper .circle.circle-6 { 576 | --background: var(--c-color-3); 577 | --blur: 16px; 578 | } 579 | 580 | .btn-tooltip .wrapper .circle.circle-2, 581 | .btn-tooltip .wrapper .circle.circle-7, 582 | .btn-tooltip .wrapper .circle.circle-8, 583 | .btn-tooltip .wrapper .circle.circle-11, 584 | .btn-tooltip .wrapper .circle.circle-12 { 585 | --background: var(--c-color-1); 586 | --blur: 12px; 587 | } 588 | 589 | .btn-tooltip .wrapper .circle.circle-1 { 590 | --x: 50px; 591 | --y: -40px; 592 | --animation: circle-1; 593 | } 594 | 595 | .btn-tooltip .wrapper .circle.circle-2 { 596 | --x: 180px; 597 | --y: 8px; 598 | --animation: circle-2; 599 | } 600 | 601 | .btn-tooltip .wrapper .circle.circle-3 { 602 | --x: 200px; 603 | --y: -12px; 604 | --animation: circle-3; 605 | } 606 | 607 | .btn-tooltip .wrapper .circle.circle-4 { 608 | --x: 80px; 609 | --y: -12px; 610 | --animation: circle-4; 611 | } 612 | 613 | .btn-tooltip .wrapper .circle.circle-5 { 614 | --x: 12px; 615 | --y: -4px; 616 | --animation: circle-5; 617 | } 618 | 619 | .btn-tooltip .wrapper .circle.circle-6 { 620 | --x: 120px; 621 | --y: 16px; 622 | --animation: circle-6; 623 | } 624 | 625 | .btn-tooltip .wrapper .circle.circle-7 { 626 | --x: 180px; 627 | --y: 28px; 628 | --animation: circle-7; 629 | } 630 | 631 | .btn-tooltip .wrapper .circle.circle-8 { 632 | --x: 200px; 633 | --y: -4px; 634 | --animation: circle-8; 635 | } 636 | 637 | .btn-tooltip .wrapper .circle.circle-9 { 638 | --x: 100px; 639 | --y: -12px; 640 | --animation: circle-9; 641 | } 642 | 643 | .btn-tooltip .wrapper .circle.circle-10 { 644 | --x: 150px; 645 | --y: 16px; 646 | --animation: circle-10; 647 | } 648 | 649 | .btn-tooltip .wrapper .circle.circle-11 { 650 | --x: 200px; 651 | --y: 4px; 652 | --animation: circle-11; 653 | } 654 | 655 | .btn-tooltip .wrapper .circle.circle-12 { 656 | --blur: 190px; 657 | --x: 52px; 658 | --y: 4px; 659 | --animation: circle-12; 660 | } 661 | } 662 | 663 | svg { 664 | fill: #999; 665 | width: 18px; 666 | height: 18px; 667 | transition: 0.3s; 668 | } 669 | 670 | .nav-arrow-down { 671 | display: none; 672 | } 673 | 674 | @media (width <=1080px) { 675 | .nav-arrow-down { 676 | display: block; 677 | } 678 | } 679 | } 680 | 681 | .background-container { 682 | position: fixed; 683 | inset: 0; 684 | z-index: -1; 685 | 686 | .star-1 { 687 | width: var(--size); 688 | height: var(--size); 689 | background-color: #fff; 690 | border-radius: 50%; 691 | box-shadow: var(--shadow-layer); 692 | position: absolute; 693 | z-index: -1; 694 | animation: risingStars var(--duration) linear infinite; 695 | } 696 | } 697 | 698 | @keyframes moveLuz { 699 | 0% { 700 | left: -100%; 701 | } 702 | 100% { 703 | left: 100%; 704 | } 705 | } 706 | 707 | main { 708 | width: 100%; 709 | max-width: 1600px; 710 | min-height: max-content; 711 | padding: 1rem; 712 | display: grid; 713 | grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); 714 | grid-template-rows: repeat(auto-fit, auto); 715 | align-content: start; 716 | gap: 1rem; 717 | 718 | .card { 719 | height: 150px; 720 | min-height: max-content; 721 | height: auto; 722 | display: flex; 723 | border-radius: 1rem; 724 | color: var(--color3, #00ff7f); 725 | animation: boxShadowMove 5s alternate ease infinite; 726 | 727 | .img { 728 | width: 90%; 729 | height: 90%; 730 | border-radius: 16px; 731 | background-position: center; 732 | background-size: cover; 733 | aspect-ratio: 1; 734 | background-image: var(--image-bg); 735 | position: relative; 736 | overflow: hidden; 737 | box-shadow: 0 0 10px 0 #0005, inset 0 0 20px 5px #0003; 738 | 739 | .input-range { 740 | width: 100%; 741 | position: absolute; 742 | left: 50%; 743 | transform: translateX(-50%) scale(0.7); 744 | bottom: 3px; 745 | accent-color: chartreuse; 746 | display: none; 747 | } 748 | 749 | &:hover { 750 | &::after { 751 | animation: moveLuz 0.5s linear forwards; 752 | } 753 | } 754 | 755 | &::after { 756 | content: ''; 757 | position: absolute; 758 | width: 100%; 759 | height: 100%; 760 | left: -100%; 761 | top: 0; 762 | background: linear-gradient(90deg, transparent, #fff2, transparent); 763 | } 764 | } 765 | 766 | .card-left { 767 | width: 55%; 768 | display: flex; 769 | flex-wrap: wrap; 770 | place-content: center; 771 | } 772 | 773 | .card-right { 774 | width: 45%; 775 | overflow: hidden; 776 | border-radius: 1rem; 777 | border-top-left-radius: 0; 778 | border-bottom-left-radius: 0; 779 | display: flex; 780 | flex-direction: column; 781 | 782 | .card-right-top { 783 | font-size: clamp(0.5208rem, 0.4794rem + 0.2072vw, 0.64rem); 784 | height: 50%; 785 | margin-top: 0.7rem; 786 | margin-inline: auto; 787 | margin-bottom: 0.5rem; 788 | max-width: 90%; 789 | text-align: center; 790 | text-wrap: balance; 791 | display: flex; 792 | justify-content: center; 793 | align-items: center; 794 | color: #fff; 795 | overflow-wrap: anywhere; 796 | 797 | @media (width <= 1400px) { 798 | font-size: clamp(0.6508rem, 0.4794rem + 0.2072vw, 0.54rem); 799 | } 800 | } 801 | 802 | .card-right-down { 803 | height: 50%; 804 | display: flex; 805 | justify-content: center; 806 | align-items: end; 807 | margin-bottom: 0.7rem; 808 | 809 | .card-right-buttons { 810 | display: grid; 811 | margin-inline: auto; 812 | grid-template-columns: repeat(3, auto); 813 | justify-content: center; 814 | gap: 0.7rem; 815 | 816 | button { 817 | background-color: black; 818 | width: 1.4rem; 819 | height: 1.4rem; 820 | border-radius: 50%; 821 | align-content: center; 822 | outline: none; 823 | border: none; 824 | transition: background-color 0.3s linear; 825 | pointer-events: auto; 826 | 827 | * { 828 | pointer-events: none !important; 829 | } 830 | 831 | &.card-btn-active { 832 | background-color: #fff; 833 | 834 | svg { 835 | filter: invert(1); 836 | } 837 | } 838 | 839 | &.blocked { 840 | pointer-events: none; 841 | } 842 | 843 | svg { 844 | all: initial; 845 | display: block; 846 | margin-inline: auto; 847 | fill: #fff; 848 | width: 0.8rem; 849 | height: 0.8rem; 850 | transition: 0.3s ease filter; 851 | } 852 | } 853 | 854 | @media (hover: hover) { 855 | button { 856 | &:hover, 857 | &.card-btn-active { 858 | background-color: #fff; 859 | 860 | svg { 861 | filter: invert(1); 862 | } 863 | } 864 | } 865 | } 866 | 867 | .card-playbutton, 868 | .card-downloadbutton { 869 | svg { 870 | scale: 0.8; 871 | } 872 | } 873 | 874 | .card-downloadbutton { 875 | pointer-events: none; 876 | -webkit-tap-highlight-color: transparent; 877 | 878 | a { 879 | display: block; 880 | width: 100%; 881 | height: 100%; 882 | background-color: transparent; 883 | border-radius: inherit; 884 | align-content: center; 885 | } 886 | 887 | a.pointerEventsActivo { 888 | pointer-events: auto !important; 889 | } 890 | } 891 | 892 | .card-downloadbutton, 893 | .card-playlistbutton { 894 | &.card-btn-active, 895 | &:hover { 896 | background-color: #fff; 897 | 898 | svg { 899 | filter: invert(1); 900 | } 901 | } 902 | } 903 | 904 | .card-playlistbutton { 905 | &.buttonConPointerEvents { 906 | pointer-events: auto !important; 907 | } 908 | } 909 | 910 | .playlistbutton { 911 | svg { 912 | scale: 1.2; 913 | } 914 | } 915 | } 916 | } 917 | } 918 | } 919 | 920 | .card:nth-child(even) { 921 | color: var(--color1, #ee82ee); 922 | animation: boxShadowMove 5s alternate-reverse ease infinite; 923 | } 924 | 925 | .card.targeado:target { 926 | color: #fff !important; 927 | scroll-margin-top: 3rem; 928 | } 929 | } 930 | 931 | @keyframes boxShadowMove { 932 | 0% { 933 | box-shadow: 0 0 10px currentColor inset; 934 | } 935 | 936 | 100% { 937 | box-shadow: 0 0 300px currentColor inset; 938 | } 939 | } 940 | 941 | @keyframes recorrer { 942 | 0% { 943 | transform: translate(0, 0); 944 | } 945 | 946 | 50% { 947 | transform: translate(-90%, 0); 948 | } 949 | 950 | 100% { 951 | transform: translate(15%, 0); 952 | } 953 | } 954 | 955 | @keyframes risingStars { 956 | 0% { 957 | transform: translateY(0); 958 | } 959 | 960 | 100% { 961 | transform: translateY(-100vh); 962 | } 963 | } 964 | 965 | @keyframes change { 966 | from { 967 | scale: 0; 968 | translate: 50px; 969 | } 970 | 971 | to { 972 | scale: 1; 973 | translate: 0; 974 | } 975 | } 976 | 977 | @media (width <= 546px) { 978 | main { 979 | .card { 980 | transition: transform 0.3s ease, scale 0.3s ease; 981 | 982 | .card-right { 983 | .card-right-top { 984 | font-size: clamp(0.75rem, 0.6538rem + 0.44vw, 1.0938rem); 985 | } 986 | 987 | .card-right-down { 988 | .card-right-buttons { 989 | .card-infinitybutton { 990 | &:hover { 991 | background-color: black; 992 | 993 | svg { 994 | filter: invert(0); 995 | } 996 | } 997 | 998 | &.card-btn-active { 999 | background-color: #fff; 1000 | 1001 | svg { 1002 | filter: invert(1); 1003 | } 1004 | } 1005 | } 1006 | } 1007 | } 1008 | } 1009 | } 1010 | 1011 | .card:nth-child(even) { 1012 | animation: boxShadowMove 5s ease alternate infinite, 1013 | change auto linear forwards; 1014 | animation-timeline: auto, view(); 1015 | animation-composition: add; 1016 | animation-range: cover -50% cover 5%; 1017 | } 1018 | 1019 | .card:nth-child(odd) { 1020 | animation: boxShadowMove 5s ease alternate-reverse infinite, 1021 | change auto linear forwards; 1022 | animation-timeline: auto, view(); 1023 | animation-composition: add; 1024 | animation-range: cover -50% cover 5%; 1025 | } 1026 | 1027 | .card:nth-child(even).stopped-animation { 1028 | animation: boxShadowMove 5s ease alternate infinite; 1029 | } 1030 | 1031 | .card:nth-child(odd).stopped-animation { 1032 | animation: boxShadowMove 5s ease alternate-reverse infinite; 1033 | } 1034 | 1035 | .card:nth-child(4n + 1) { 1036 | color: var(--color1, #ee82ee); 1037 | } 1038 | .card:nth-child(4n + 2) { 1039 | color: var(--color2, #00ff7f); 1040 | } 1041 | .card:nth-child(4n + 3) { 1042 | color: var(--color3, #0099ff); 1043 | } 1044 | .card:nth-child(4n + 4) { 1045 | color: var(--color4, #ff0000); 1046 | } 1047 | } 1048 | } 1049 | 1050 | /* 2 columnas */ 1051 | @media (548px <= width < 824px) { 1052 | main { 1053 | .card:nth-child(2), 1054 | .card:nth-child(3), 1055 | .card:nth-child(6), 1056 | .card:nth-child(7), 1057 | .card:nth-child(10), 1058 | .card:nth-child(11), 1059 | .card:nth-child(14), 1060 | .card:nth-child(15), 1061 | .card:nth-child(18), 1062 | .card:nth-child(19) { 1063 | color: var(--color1, #ee82ee); 1064 | animation: boxShadowMove 5s ease alternate infinite; 1065 | } 1066 | 1067 | .card:nth-child(1), 1068 | .card:nth-child(4), 1069 | .card:nth-child(5), 1070 | .card:nth-child(8), 1071 | .card:nth-child(9), 1072 | .card:nth-child(12), 1073 | .card:nth-child(13), 1074 | .card:nth-child(16), 1075 | .card:nth-child(17), 1076 | .card:nth-child(20) { 1077 | color: var(--color3, #00ff7f); 1078 | animation: boxShadowMove 5s ease alternate-reverse infinite; 1079 | } 1080 | } 1081 | } 1082 | 1083 | @media (1080px <=width < 1346px) { 1084 | main { 1085 | .card:nth-child(2), 1086 | .card:nth-child(4), 1087 | .card:nth-child(5), 1088 | .card:nth-child(7), 1089 | .card:nth-child(10), 1090 | .card:nth-child(12), 1091 | .card:nth-child(13), 1092 | .card:nth-child(15), 1093 | .card:nth-child(18), 1094 | .card:nth-child(20) { 1095 | color: var(--color1, #ee82ee); 1096 | animation: boxShadowMove 5s ease alternate infinite; 1097 | } 1098 | 1099 | .card:nth-child(1), 1100 | .card:nth-child(3), 1101 | .card:nth-child(6), 1102 | .card:nth-child(8), 1103 | .card:nth-child(9), 1104 | .card:nth-child(11), 1105 | .card:nth-child(14), 1106 | .card:nth-child(16), 1107 | .card:nth-child(17), 1108 | .card:nth-child(19) { 1109 | color: var(--color3, #00ff7f); 1110 | animation: boxShadowMove 5s ease alternate-reverse infinite; 1111 | } 1112 | } 1113 | } 1114 | /* ===========================VIEW TRANSITIONS========================= */ 1115 | 1116 | html { 1117 | view-transition-name: transitionPage; 1118 | } 1119 | 1120 | @view-transition { 1121 | navigation: auto; 1122 | } 1123 | 1124 | ::view-transition-new(transitionPage) { 1125 | animation: fadeIn 1s ease forwards; 1126 | } 1127 | ::view-transition-old(transitionPage) { 1128 | animation: fadeIn 1s ease reverse forwards; 1129 | } 1130 | 1131 | @keyframes fadeIn { 1132 | 0% { 1133 | clip-path: circle(0% at 50% 50%); 1134 | } 1135 | 100% { 1136 | clip-path: circle(100% at 50% 50%); 1137 | } 1138 | } 1139 | 1140 | /* ===========================TOOLTIP========================= */ 1141 | @keyframes circle-1 { 1142 | 33% { 1143 | transform: translate(0px, 16px) translateZ(0); 1144 | } 1145 | 1146 | 66% { 1147 | transform: translate(12px, 64px) translateZ(0); 1148 | } 1149 | } 1150 | 1151 | @keyframes circle-2 { 1152 | 33% { 1153 | transform: translate(80px, -10px) translateZ(0); 1154 | } 1155 | 1156 | 66% { 1157 | transform: translate(72px, -48px) translateZ(0); 1158 | } 1159 | } 1160 | 1161 | @keyframes circle-3 { 1162 | 33% { 1163 | transform: translate(20px, 12px) translateZ(0); 1164 | } 1165 | 1166 | 66% { 1167 | transform: translate(12px, 4px) translateZ(0); 1168 | } 1169 | } 1170 | 1171 | @keyframes circle-4 { 1172 | 33% { 1173 | transform: translate(76px, -12px) translateZ(0); 1174 | } 1175 | 1176 | 66% { 1177 | transform: translate(112px, -8px) translateZ(0); 1178 | } 1179 | } 1180 | 1181 | @keyframes circle-5 { 1182 | 33% { 1183 | transform: translate(84px, 28px) translateZ(0); 1184 | } 1185 | 1186 | 66% { 1187 | transform: translate(40px, -32px) translateZ(0); 1188 | } 1189 | } 1190 | 1191 | @keyframes circle-6 { 1192 | 33% { 1193 | transform: translate(28px, -16px) translateZ(0); 1194 | } 1195 | 1196 | 66% { 1197 | transform: translate(76px, -56px) translateZ(0); 1198 | } 1199 | } 1200 | 1201 | @keyframes circle-7 { 1202 | 33% { 1203 | transform: translate(8px, 28px) translateZ(0); 1204 | } 1205 | 1206 | 66% { 1207 | transform: translate(20px, -60px) translateZ(0); 1208 | } 1209 | } 1210 | 1211 | @keyframes circle-8 { 1212 | 33% { 1213 | transform: translate(32px, -4px) translateZ(0); 1214 | } 1215 | 1216 | 66% { 1217 | transform: translate(56px, -20px) translateZ(0); 1218 | } 1219 | } 1220 | 1221 | @keyframes circle-9 { 1222 | 33% { 1223 | transform: translate(20px, -12px) translateZ(0); 1224 | } 1225 | 1226 | 66% { 1227 | transform: translate(80px, -8px) translateZ(0); 1228 | } 1229 | } 1230 | 1231 | @keyframes circle-10 { 1232 | 33% { 1233 | transform: translate(68px, 20px) translateZ(0); 1234 | } 1235 | 1236 | 66% { 1237 | transform: translate(100px, 28px) translateZ(0); 1238 | } 1239 | } 1240 | 1241 | @keyframes circle-11 { 1242 | 33% { 1243 | transform: translate(4px, 4px) translateZ(0); 1244 | } 1245 | 1246 | 66% { 1247 | transform: translate(68px, 20px) translateZ(0); 1248 | } 1249 | } 1250 | 1251 | @keyframes circle-12 { 1252 | 33% { 1253 | transform: translate(56px, 0px) translateZ(0); 1254 | } 1255 | 1256 | 66% { 1257 | transform: translate(60px, -32px) translateZ(0); 1258 | } 1259 | } 1260 | -------------------------------------------------------------------------------- /playlist/index.js: -------------------------------------------------------------------------------- 1 | /******************** DINAMICO LOCAL STORAGE ********************/ 2 | 3 | let nameSongs = []; 4 | let arraySongs = []; 5 | let lastNameCard = null; 6 | let listNumbersSongs = []; 7 | let arrayPosters = []; 8 | 9 | const MAXIMUM_LENGTH_OF_PLAYLIST = 20; 10 | function updateRowsModalAndButtonActive() { 11 | setTimeout(() => { 12 | updateButtonNavActive($('.am-button-nav-modal.order'), 'button-nav-selected'); 13 | scrollToBottomContainerModal(); 14 | }, 50); 15 | } 16 | 17 | if (localStorage.getItem('lastNameCardClicked')) { 18 | lastNameCard = localStorage.getItem('lastNameCardClicked'); 19 | let listNameCards = JSON.parse(localStorage.getItem('listname-cards')); 20 | let currentArray = listNameCards[lastNameCard]; 21 | if (currentArray.length > 0) { 22 | nameSongs = currentArray.map(el => { 23 | let name = el[0].replace(/\&\;/g, '&'); 24 | return name?.trim(); 25 | }); 26 | 27 | arraySongs = currentArray.map(el => el[1]); 28 | arrayPosters = arraySongs.map((linkPoster, i) => { 29 | const numPhoto = (i % 4) + 1; 30 | return linkPoster.replace( 31 | /\/songs\/n\d+\.mp3/, 32 | `/assets/n${numPhoto}.avif` 33 | ); 34 | }); 35 | } 36 | } 37 | 38 | document.addEventListener('visibilitychange', function () { 39 | if (!document.hidden) { 40 | localStorage.setItem('playbackUrl', location.href); 41 | } else { 42 | history.replaceState(null, '', location.pathname + location.search); 43 | } 44 | }); 45 | 46 | localStorage.setItem('iframeUrl', location.href); 47 | 48 | /******************** MEDIA SESSION CONFIG ********************/ 49 | const playlist = nameSongs.map((song, i) => ({ 50 | title: song, 51 | artist: lastNameCard, 52 | url: arraySongs[i] 53 | })); 54 | 55 | function toCapitalize(text = '') { 56 | return text 57 | .split(' ') 58 | .map(el => { 59 | if (el.length === 0) return ''; 60 | if (el.length < 2) 61 | return `${el[0].toUpperCase()}${el.slice(1).toLowerCase()}`; 62 | let secondLetter = 63 | el[0] === '(' ? el[1].toUpperCase() : el[1].toLowerCase(); 64 | return `${el[0].toUpperCase()}${secondLetter}${el.slice(2).toLowerCase()}`; 65 | }) 66 | .join(' ') 67 | .replace(/\s+/g, ' '); 68 | } 69 | 70 | function updateMetadata(currentIndex = 0) { 71 | navigator.mediaSession.metadata = new MediaMetadata({ 72 | title: `${toCapitalize(playlist[currentIndex].title)}`, 73 | artist: `${toCapitalize(playlist[currentIndex].artist)}`, 74 | artwork: [ 75 | { 76 | src: arrayPosters[currentIndex], 77 | sizes: '128x128', 78 | type: 'image/avif' 79 | } 80 | ] 81 | }); 82 | } 83 | 84 | navigator.mediaSession.setActionHandler('play', () => { 85 | $audio.play(); 86 | navigator.mediaSession.playbackState = 'playing'; 87 | }); 88 | 89 | navigator.mediaSession.setActionHandler('pause', () => { 90 | $audio.pause(); 91 | navigator.mediaSession.playbackState = 'paused'; 92 | }); 93 | 94 | navigator.mediaSession.setActionHandler('seekbackward', details => { 95 | $audio.currentTime = Math.max($audio.currentTime - 10, 0); 96 | }); 97 | 98 | navigator.mediaSession.setActionHandler('seekforward', details => { 99 | $audio.currentTime = Math.min($audio.currentTime + 10, $audio.duration); 100 | }); 101 | 102 | function previousTrack(currentIndex) { 103 | navigator.mediaSession.setActionHandler('previoustrack', () => { 104 | currentIndex = (currentIndex - 1 + playlist.length) % playlist.length; 105 | updateMetadata(currentIndex); 106 | $audio.pause(); 107 | $audio.currentTime = 0; 108 | $audio.src = arraySongs[currentIndex]; 109 | $audio.loop = false; 110 | actualButtonPlayActive(currentIndex); 111 | nextTrack(currentIndex); 112 | showTitle(currentIndex); 113 | }); 114 | } 115 | 116 | function nextTrack(currentIndex) { 117 | navigator.mediaSession.setActionHandler('nexttrack', () => { 118 | currentIndex = (currentIndex + 1) % playlist.length; 119 | updateMetadata(currentIndex); 120 | $audio.pause(); 121 | $audio.currentTime = 0; 122 | $audio.src = arraySongs[currentIndex]; 123 | $audio.loop = false; 124 | actualButtonPlayActive(currentIndex); 125 | previousTrack(currentIndex); 126 | showTitle(currentIndex); 127 | }); 128 | } 129 | 130 | /******************** GLOBAL ********************/ 131 | const d = document; 132 | const $ = el => d.querySelector(el); 133 | const $$ = el => d.querySelectorAll(el); 134 | let regExP = /^(?![\s0-9\-_])[\w\s\-]{1,20}(? { 210 | [...$$('.card-pausebutton')].forEach(el => el.classList.add('blocked')); 211 | [...$$('.card-stopbutton')].forEach(el => el.classList.add('blocked')); 212 | [...$$('.card-infinitybutton')].forEach(el => el.classList.add('blocked')); 213 | }; 214 | 215 | const generateStars = (totalStars, selector, size, duration) => { 216 | const shadowLayers = []; 217 | 218 | for (let i = 0; i < totalStars; i++) { 219 | const x = Math.floor(Math.random() * 100); 220 | const y = Math.floor(Math.random() * 100); 221 | shadowLayers.push(` 222 | ${x}vw ${y}vh 0 #fff, 223 | ${x}vw ${y + 100}vh 0 #fff 224 | `); 225 | } 226 | 227 | const star = document.querySelector(selector); 228 | star.style.setProperty('--shadow-layer', shadowLayers.join(',')); 229 | star.style.setProperty('--size', size); 230 | star.style.setProperty('--duration', duration); 231 | }; 232 | 233 | const removeClassBlockedButtonNextSiblings = el => { 234 | [...el.closest('.card-right-buttons').querySelectorAll('button')].forEach(btn => 235 | btn.classList.remove('blocked') 236 | ); 237 | }; 238 | 239 | const _removeClassBlockedButtonNextSiblings = index => { 240 | [ 241 | ...$$('.card') 242 | [index].querySelector('.card-right-buttons') 243 | .querySelectorAll('button') 244 | ].forEach(btn => btn.classList.remove('blocked')); 245 | }; 246 | 247 | const actualButtonPlayActive = (index = 0) => { 248 | let element = $$('.card')[index].querySelector(cardPlayButtonClass); 249 | 250 | [...$$('.card-btn-active')].forEach(el => { 251 | el.classList.remove('card-btn-active'); 252 | }); 253 | element.classList.add('card-btn-active'); 254 | 255 | [...$$('.input-range')].forEach(el => { 256 | el.style.display = 'none'; 257 | }); 258 | const $inputRange = element.closest('.card').querySelector('.img input'); 259 | $inputRange.style.display = 'block'; 260 | 261 | setTimeout(() => { 262 | $audio.play(); 263 | }, 30); 264 | 265 | $audio.ontimeupdate = function () { 266 | $inputRange.max = Math.floor(this.duration); 267 | $inputRange.value = this.currentTime; 268 | }; 269 | 270 | d.addEventListener('input', e => { 271 | if (e.target === $inputRange) { 272 | $audio.currentTime = e.target.value; 273 | $audio.play(); 274 | } 275 | }); 276 | }; 277 | 278 | const toKebabCase = (sentence = '') => { 279 | let words = sentence.trim().split(' '); 280 | return words.length === 1 281 | ? words.join('').toLowerCase() 282 | : words.join('-').toLowerCase(); 283 | }; 284 | 285 | const putTitle = title => (d.title = `${title}`); 286 | 287 | const showTitle = elIndex => { 288 | putTitle(nameSongs[elIndex]); 289 | }; 290 | 291 | const playAllSongs = (songs, selector) => { 292 | if (listNumbersSongs?.length > 0) { 293 | let arrayCards = listNumbersSongs.map(i => $$('.card')[i]); 294 | let arrayColors = listNumbersSongs.map(i => $$('.card')[i].dataset.colorCard); 295 | arrayCards.forEach((card, i) => (card.style.color = arrayColors[i])); 296 | listNumbersSongs = []; 297 | } 298 | 299 | let index = 0; 300 | const $btnsPlay = $$(selector); 301 | 302 | const nextSong = () => { 303 | blockPlayPauseStopBUTTON(); 304 | 305 | if (index < songs.length) { 306 | if ($audio.src) { 307 | $audio.pause(); 308 | $audio.currentTime = 0; 309 | } 310 | $audio.src = songs[index]; 311 | removeClassBlockedButtonNextSiblings($btnsPlay[index]); 312 | showTitle(index); 313 | 314 | actualButtonPlayActive(index); 315 | updateMetadata(index); 316 | 317 | function actualAudio(currentIndex) { 318 | updateMetadata(currentIndex); 319 | blockPlayPauseStopBUTTON(); 320 | _removeClassBlockedButtonNextSiblings(currentIndex); 321 | $audio.pause(); 322 | $audio.currentTime = 0; 323 | $audio.src = arraySongs[currentIndex]; 324 | $audio.loop = false; 325 | actualButtonPlayActive(currentIndex); 326 | showTitle(currentIndex); 327 | } 328 | 329 | function previousTrack(currentIndex) { 330 | navigator.mediaSession.setActionHandler('previoustrack', () => { 331 | index--; 332 | currentIndex = (currentIndex - 1 + playlist.length) % playlist.length; 333 | if (index === -1) index = currentIndex + 1; 334 | 335 | nextTrack(currentIndex); 336 | actualAudio(currentIndex); 337 | }); 338 | } 339 | 340 | function nextTrack(currentIndex) { 341 | navigator.mediaSession.setActionHandler('nexttrack', () => { 342 | index++; 343 | currentIndex = (currentIndex + 1) % playlist.length; 344 | previousTrack(currentIndex); 345 | actualAudio(currentIndex); 346 | }); 347 | } 348 | 349 | previousTrack(index); 350 | nextTrack(index); 351 | 352 | showTitle(index); 353 | index++; 354 | $audio.onended = nextSong; 355 | } else { 356 | location.reload(); 357 | } 358 | }; 359 | 360 | nextSong(); 361 | }; 362 | 363 | const playRandomSongs = (songs, selector) => { 364 | if (listNumbersSongs?.length > 0) { 365 | let arrayCards = listNumbersSongs.map(i => $$('.card')[i]); 366 | let arrayColors = listNumbersSongs.map(i => $$('.card')[i].dataset.colorCard); 367 | arrayCards.forEach((card, i) => (card.style.color = arrayColors[i])); 368 | listNumbersSongs = []; 369 | } 370 | 371 | let unArray = [], 372 | valor; 373 | 374 | for (let i = 0; i < songs.length; i++) { 375 | do { 376 | valor = Math.floor(Math.random() * songs.length); 377 | } while (unArray.includes(valor)); 378 | 379 | unArray.push(valor); 380 | } 381 | 382 | let index = 0; 383 | const $btnsPlay = $$(selector); 384 | const nextSong = () => { 385 | blockPlayPauseStopBUTTON(); 386 | 387 | if (index < songs.length) { 388 | if ($audio.src) { 389 | $audio.pause(); 390 | $audio.currentTime = 0; 391 | } 392 | $audio.src = songs[unArray[index]]; 393 | removeClassBlockedButtonNextSiblings($btnsPlay[unArray[index]]); 394 | showTitle(unArray[index]); 395 | 396 | actualButtonPlayActive(unArray[index]); 397 | updateMetadata(unArray[index]); 398 | 399 | function actualAudio(currentIndex) { 400 | $audio.pause(); 401 | blockPlayPauseStopBUTTON(); 402 | _removeClassBlockedButtonNextSiblings(unArray[currentIndex]); 403 | $audio.currentTime = 0; 404 | $audio.src = arraySongs[unArray[currentIndex]]; 405 | $audio.loop = false; 406 | updateMetadata(unArray[currentIndex]); 407 | actualButtonPlayActive(unArray[currentIndex]); 408 | showTitle(unArray[currentIndex]); 409 | } 410 | 411 | function previousTrackOfRandomSongs(currentIndex) { 412 | navigator.mediaSession.setActionHandler('previoustrack', () => { 413 | index--; 414 | currentIndex = (currentIndex - 1 + playlist.length) % playlist.length; 415 | if (index === -1) index = currentIndex + 1; 416 | nextTrackOfRandomSongs(currentIndex); 417 | actualAudio(currentIndex); 418 | }); 419 | } 420 | 421 | function nextTrackOfRandomSongs(currentIndex) { 422 | navigator.mediaSession.setActionHandler('nexttrack', () => { 423 | index++; 424 | currentIndex = (currentIndex + 1) % playlist.length; 425 | previousTrackOfRandomSongs(currentIndex); 426 | actualAudio(currentIndex); 427 | }); 428 | } 429 | 430 | previousTrackOfRandomSongs(index); 431 | nextTrackOfRandomSongs(index); 432 | index++; 433 | $audio.onended = nextSong; 434 | } else { 435 | location.reload(); 436 | } 437 | }; 438 | 439 | nextSong(); 440 | }; 441 | 442 | const removeClassNavButtonActive = () => { 443 | [...$$('.nav-btn-active')].forEach(el => el.classList.remove('nav-btn-active')); 444 | }; 445 | 446 | const playSelectedSongs = (songs, selector, listNumber) => { 447 | let index = 0; 448 | const $btnsPlay = $$(selector); 449 | 450 | const nextSong = () => { 451 | blockPlayPauseStopBUTTON(); 452 | 453 | if (index < songs.length) { 454 | if ($audio.src) { 455 | $audio.pause(); 456 | $audio.currentTime = 0; 457 | } 458 | $audio.src = songs[index]; 459 | removeClassBlockedButtonNextSiblings($btnsPlay[listNumber[index]]); 460 | showTitle(listNumber[index]); 461 | 462 | actualButtonPlayActive(listNumber[index]); 463 | updateMetadata(listNumber[index]); 464 | 465 | function actualAudio(currentIndex) { 466 | $audio.pause(); 467 | blockPlayPauseStopBUTTON(); 468 | _removeClassBlockedButtonNextSiblings(listNumber[currentIndex]); 469 | $audio.currentTime = 0; 470 | $audio.src = arraySongs[listNumber[currentIndex]]; 471 | $audio.loop = false; 472 | updateMetadata(listNumber[currentIndex]); 473 | actualButtonPlayActive(listNumber[currentIndex]); 474 | showTitle(listNumber[currentIndex]); 475 | } 476 | 477 | function previousTrackOfSelectedSongs(currentIndex) { 478 | navigator.mediaSession.setActionHandler('previoustrack', () => { 479 | index--; 480 | currentIndex = 481 | (currentIndex - 1 + listNumber.length) % listNumber.length; 482 | 483 | if (index === -1) index = currentIndex + 1; 484 | nextTrackOfSelectedSongs(currentIndex); 485 | actualAudio(currentIndex); 486 | }); 487 | } 488 | 489 | function nextTrackOfSelectedSongs(currentIndex) { 490 | navigator.mediaSession.setActionHandler('nexttrack', () => { 491 | index++; 492 | currentIndex = (currentIndex + 1) % listNumber.length; 493 | previousTrackOfSelectedSongs(currentIndex); 494 | actualAudio(currentIndex); 495 | }); 496 | } 497 | 498 | previousTrackOfSelectedSongs(index); 499 | nextTrackOfSelectedSongs(index); 500 | 501 | index++; 502 | $audio.onended = nextSong; 503 | } else { 504 | window.history.replaceState(null, null, window.location.pathname); 505 | location.reload(); 506 | } 507 | }; 508 | 509 | nextSong(); 510 | }; 511 | 512 | /******************** EXECUTING FUNCTIONS ********************/ 513 | generateStars(200, '.star-1', '2px', '20s'); 514 | 515 | (function headerCustomProperties() { 516 | const { body } = document; 517 | let numberRandom = Math.floor(Math.random() * Object.keys(headerColors).length); 518 | const [color1, color2, color3, color4] = headerColors[numberRandom]; 519 | body.style.setProperty('--color1', color1); 520 | body.style.setProperty('--color2', color2); 521 | body.style.setProperty('--color3', color3); 522 | body.style.setProperty('--color4', color4); 523 | })(); 524 | 525 | (function addTitlesToCards() { 526 | [...$$('.card-right-top')].forEach((title, index) => { 527 | if (!nameSongs[index]) { 528 | $$('.card')[index].style.pointerEvents = 'none'; 529 | $$('.card')[index].style.opacity = '0.3'; 530 | let buttons = $$('.card')[index].querySelector( 531 | '.card-right .card-right-buttons' 532 | ); 533 | [...buttons.querySelectorAll('button')].forEach( 534 | el => (el.style.pointerEvents = 'none') 535 | ); 536 | [...buttons.querySelectorAll('a')].forEach(el => 537 | el.classList.remove('pointerEventsActivo') 538 | ); 539 | [...buttons.querySelectorAll('.buttonConPointerEvents')].forEach(el => 540 | el.classList.remove('buttonConPointerEvents') 541 | ); 542 | } 543 | title.innerHTML = nameSongs[index] || ''; 544 | title.closest('.card').dataset.url = arraySongs[index]; 545 | }); 546 | })(); 547 | 548 | (function addHrefAndDownloads() { 549 | [...$$('.anchor-download')].forEach((el, i) => { 550 | el.href = arraySongs[i] || ''; 551 | let nameBandFirstChar = nameBand[0].toUpperCase(); 552 | let nameBandComplete = nameBand.substring(1).toLowerCase(); 553 | el.download = `${nameBandFirstChar}${nameBandComplete} - ${toCapitalize( 554 | nameSongs[i] 555 | )}.mp3`; 556 | }); 557 | })(); 558 | 559 | (function getHref() { 560 | localStorage.setItem('formUrl', location.href); 561 | })(); 562 | 563 | /******************** EVENT DELEGATION ********************/ 564 | d.addEventListener('click', e => { 565 | /******************** EVENT DELEGATION CARDS ********************/ 566 | if (e.target.matches(cardPlayButtonClass)) { 567 | if (listNumbersSongs?.length > 0) { 568 | let arrayCards = listNumbersSongs.map(i => $$('.card')[i]); 569 | let arrayColors = listNumbersSongs.map( 570 | i => $$('.card')[i].dataset.colorCard 571 | ); 572 | arrayCards.forEach((card, i) => (card.style.color = arrayColors[i])); 573 | listNumbersSongs = []; 574 | } 575 | const arrayPlayButtons = [...$$(cardPlayButtonClass)]; 576 | 577 | blockPlayPauseStopBUTTON(); 578 | let index = arrayPlayButtons.indexOf(e.target); 579 | _removeClassBlockedButtonNextSiblings(index); 580 | 581 | let audioActual = d.createElement('audio'); 582 | audioActual.src = arraySongs[index]; 583 | 584 | if (!$audio.src) { 585 | $audio.src = arraySongs[index]; 586 | } 587 | 588 | if ($audio.src !== audioActual.src) { 589 | $audio.pause(); 590 | $audio.currentTime = 0; 591 | $audio.src = arraySongs[index]; 592 | $audio.loop = false; 593 | } 594 | 595 | actualButtonPlayActive(index); 596 | updateMetadata(index); 597 | previousTrack(index); 598 | nextTrack(index); 599 | showTitle(index); 600 | 601 | if ($audio.loop) { 602 | e.target.nextElementSibling.nextElementSibling.nextElementSibling.classList.toggle( 603 | 'card-btn-active' 604 | ); 605 | return; 606 | } 607 | 608 | $audio.onended = () => { 609 | index = index = (index + 1) % playlist.length; 610 | const btnPlayNew = arrayPlayButtons[index]; 611 | if (index === 0) return; 612 | btnPlayNew.click(); 613 | }; 614 | 615 | return; 616 | } 617 | 618 | if (e.target.matches(cardPauseButtonClass)) { 619 | $audio.pause(); 620 | e.target.previousElementSibling.classList.remove('card-btn-active'); 621 | e.target.classList.add('card-btn-active'); 622 | return; 623 | } 624 | 625 | if (e.target.matches(cardStopButtonClass)) { 626 | $audio.pause(); 627 | $audio.currentTime = 0; 628 | blockPlayPauseStopBUTTON(); 629 | e.target.previousElementSibling.previousElementSibling.classList.remove( 630 | 'card-btn-active' 631 | ); 632 | return; 633 | } 634 | 635 | if (e.target.matches(cardLoopButtonClass)) { 636 | if ($audio.loop) { 637 | $audio.loop = false; 638 | e.target.classList.remove('card-btn-active'); 639 | return; 640 | } 641 | $audio.loop = true; 642 | e.target.classList.add('card-btn-active'); 643 | } 644 | 645 | if (e.target.matches(cardPlayListButton)) { 646 | let index = [...$$('.card')].indexOf(e.target.closest('.card')); 647 | let currentNameSong = [...$$('.card')][index].querySelector( 648 | '.card-right-top' 649 | ).innerHTML; 650 | localStorage.setItem('lastCurrentNameSong', currentNameSong); 651 | localStorage.setItem('ultimoCardIndex', index); 652 | RenderPlaylistItems(); 653 | $('.am-modal').showModal(); 654 | let $tituloModal = $('.tituto-modal'); 655 | $tituloModal.innerHTML = `Save ${currentNameSong} in..`; 656 | return; 657 | } 658 | 659 | if (e.target.matches('.cerrar')) { 660 | e.target.parentElement.close(); 661 | setTimeout(() => { 662 | $('.am-modal') 663 | .querySelector('.container-add-playlist') 664 | .classList.remove('mode-active'); 665 | }, 500); 666 | $('#agregarPlaylistInput').value = ''; 667 | updateButtonNavActive($('.am-button-nav-modal.order'), 'button-nav-selected'); 668 | return; 669 | } 670 | 671 | if (e.target.matches('.container-add-playlist')) { 672 | e.target.classList.add('mode-active'); 673 | d.getElementById('agregarPlaylistInput').focus(); 674 | return; 675 | } 676 | 677 | if (e.target.matches('.container-inputs input[type=submit]')) { 678 | let input = e.target.previousElementSibling.previousElementSibling; 679 | let inputValor = 680 | e.target.previousElementSibling.previousElementSibling.value.trim(); 681 | 682 | if (comprobeExistThisProperty(inputValor)) { 683 | input.classList.remove('valid'); 684 | input.classList.add('invalid'); 685 | return; 686 | } 687 | 688 | if (!regExP.test(inputValor) || comprobeExistThisProperty(input)) { 689 | return; 690 | } 691 | 692 | if (!localStorage.getItem('listname-cards')) { 693 | localStorage.setItem( 694 | 'listname-cards', 695 | JSON.stringify({ 696 | [`${inputValor}`]: '' 697 | }) 698 | ); 699 | RenderPlaylistItems(); 700 | updateRowsModalAndButtonActive(); 701 | input.value = ''; 702 | return; 703 | } 704 | 705 | let objectListNameCards = JSON.parse(localStorage.getItem('listname-cards')); 706 | let newObjectListNameCards = JSON.stringify({ 707 | ...objectListNameCards, 708 | [`${inputValor}`]: '' 709 | }); 710 | 711 | localStorage.setItem('listname-cards', newObjectListNameCards); 712 | RenderPlaylistItems(); 713 | updateRowsModalAndButtonActive(); 714 | input.value = ''; 715 | } 716 | 717 | /******************** EVENT DELEGATION NAV ********************/ 718 | if (e.target.matches(navPlayButton)) { 719 | removeClassNavButtonActive(); 720 | e.target.classList.add('nav-btn-active'); 721 | playAllSongs(arraySongs, cardPlayButtonClass); 722 | return; 723 | } 724 | if (e.target.matches(navRandomButton)) { 725 | removeClassNavButtonActive(); 726 | e.target.classList.add('nav-btn-active'); 727 | playRandomSongs(arraySongs, cardPlayButtonClass); 728 | return; 729 | } 730 | if (e.target.matches(navMomentaryListButton)) { 731 | listNumbersSongs = []; 732 | $('.tooltip').classList.toggle('tooltip-active'); 733 | e.target.classList.add('nav-btn-active'); 734 | 735 | if (e.target.classList.contains('nav-btn-active')) { 736 | let allCards = [...$$('.card')]; 737 | 738 | removeClassNavButtonActive(); 739 | e.target.classList.add('nav-btn-active'); 740 | pickCards(allCards, listNumbersSongs); 741 | return; 742 | } 743 | 744 | return; 745 | } 746 | if (e.target.matches(navArrowDownButton)) { 747 | if ($audio.src) { 748 | e.target.classList.add('nav-btn-active'); 749 | let arrayButtons = [...$$('.card-playbutton')]; 750 | let $btnPlayActive = $('.card-playbutton.card-btn-active'); 751 | if (!$btnPlayActive?.closest('.card')) { 752 | return; 753 | } 754 | let indexActual = arrayButtons.indexOf($btnPlayActive) + 1; 755 | e.target.href = `#song-${indexActual}`; 756 | 757 | $btnPlayActive.closest('.card').classList.add('targeado'); 758 | setTimeout(() => { 759 | $btnPlayActive.closest('.card').classList.remove('targeado'); 760 | e.target.classList.remove('nav-btn-active'); 761 | history.replaceState(null, '', location.pathname); 762 | }, 3000); 763 | } 764 | return; 765 | } 766 | }); 767 | 768 | d.addEventListener('change', e => { 769 | if (e.target.matches(`input[type=checkbox]`)) { 770 | let currentNameSong = localStorage.getItem('lastCurrentNameSong'); 771 | let cardCorriente = [...$$('.card')][localStorage.getItem('ultimoCardIndex')]; 772 | let url = cardCorriente.dataset.url; 773 | let currentId = e.target.id; 774 | let objectListNameCards = JSON.parse(localStorage.getItem('listname-cards')); 775 | if (!objectListNameCards) return; 776 | let clase = e.target.getAttribute('data-clase'); 777 | let $output = $(`.${clase}`); 778 | 779 | if (e.target.checked) { 780 | let newObject = { 781 | ...objectListNameCards, 782 | [`${currentId}`]: [ 783 | ...objectListNameCards[currentId], 784 | [currentNameSong, url] 785 | ] 786 | }; 787 | 788 | localStorage.setItem('listname-cards', JSON.stringify(newObject)); 789 | 790 | $output.innerHTML = Number($output.innerHTML) + 1; 791 | /* RenderPlaylistItems(); */ 792 | return; 793 | } 794 | 795 | let indiceReal = null; 796 | for (let i = 0; i < objectListNameCards[currentId].length; i++) { 797 | if (objectListNameCards[currentId][i][0] === currentNameSong) { 798 | indiceReal = i; 799 | break; 800 | } 801 | } 802 | 803 | let newArrray = objectListNameCards[`${currentId}`].toSpliced(indiceReal, 1); 804 | 805 | let newObject = { 806 | ...objectListNameCards, 807 | [`${currentId}`]: [...newArrray] 808 | }; 809 | 810 | localStorage.setItem('listname-cards', JSON.stringify(newObject)); 811 | $output.innerHTML = Number($output.innerHTML) - 1; 812 | RenderPlaylistItems(); 813 | return; 814 | } 815 | }); 816 | 817 | d.addEventListener('input', e => { 818 | if (e.target.matches('#agregarPlaylistInput')) { 819 | let $output = $('.container-inputs output'); 820 | $output.innerHTML = e.target.value.length; 821 | 822 | if (e.target.value.length === 0) { 823 | e.target.classList.remove('valid'); 824 | e.target.classList.remove('invalid'); 825 | return; 826 | } 827 | 828 | if ( 829 | regExP.test(e.target.value) && 830 | !comprobeExistThisProperty(e.target.value) 831 | ) { 832 | e.target.classList.remove('invalid'); 833 | e.target.classList.add('valid'); 834 | } else { 835 | e.target.classList.remove('valid'); 836 | e.target.classList.add('invalid'); 837 | } 838 | } 839 | }); 840 | 841 | d.addEventListener('keydown', e => { 842 | if (e.target.matches('#agregarPlaylistInput')) { 843 | if (e.key !== 'Enter') return; 844 | let input = e.target; 845 | let inputValor = e.target.value.trim(); 846 | 847 | if (comprobeExistThisProperty(inputValor)) { 848 | input.classList.remove('valid'); 849 | input.classList.add('invalid'); 850 | return; 851 | } 852 | 853 | if (!regExP.test(inputValor) || comprobeExistThisProperty(input)) { 854 | return; 855 | } 856 | 857 | if (!localStorage.getItem('listname-cards')) { 858 | localStorage.setItem( 859 | 'listname-cards', 860 | JSON.stringify({ 861 | [`${inputValor}`]: '' 862 | }) 863 | ); 864 | RenderPlaylistItems(); 865 | updateRowsModalAndButtonActive(); 866 | input.value = ''; 867 | return; 868 | } 869 | 870 | let objectListNameCards = JSON.parse(localStorage.getItem('listname-cards')); 871 | let newObjectListNameCards = JSON.stringify({ 872 | ...objectListNameCards, 873 | [`${inputValor}`]: '' 874 | }); 875 | 876 | localStorage.setItem('listname-cards', newObjectListNameCards); 877 | RenderPlaylistItems(); 878 | updateRowsModalAndButtonActive(); 879 | input.value = ''; 880 | } 881 | }); 882 | 883 | /******************** MODAL FUNCTIONS ********************/ 884 | 885 | function existThisSongInSomePlaylist(currentName) { 886 | let nameCurrent = currentName ?? ''; 887 | if (localStorage.getItem('listname-cards')) { 888 | let objetoNamePlaylists = JSON.parse(localStorage.getItem('listname-cards')); 889 | let playlistsWhereExistsCurrenName = []; 890 | let namesPlaylists = []; 891 | 892 | for (let property in objetoNamePlaylists) { 893 | namesPlaylists = [...namesPlaylists, property]; 894 | } 895 | 896 | for (let i = 0; i < namesPlaylists.length; i++) { 897 | let currentPlaylist = namesPlaylists[i]; 898 | let multiArrayCurrent = objetoNamePlaylists[currentPlaylist]; 899 | 900 | for (let j = 0; j < multiArrayCurrent.length; j++) { 901 | if (multiArrayCurrent[j].includes(nameCurrent.toString())) { 902 | playlistsWhereExistsCurrenName.push(currentPlaylist); 903 | break; 904 | } 905 | } 906 | } 907 | 908 | return playlistsWhereExistsCurrenName; 909 | } 910 | } 911 | 912 | function RenderPlaylistItems() { 913 | if (localStorage.getItem('listname-cards')) { 914 | let currentName = localStorage.getItem('lastCurrentNameSong'); 915 | let objectNames = JSON.parse(localStorage.getItem('listname-cards')); 916 | let $template = $('.template-modal-fila').content; 917 | let $tituloModal = $('.tituto-modal'); 918 | $tituloModal.innerHTML = `Save ${currentName} in..`; 919 | let myFragment = d.createDocumentFragment(); 920 | let $containerModal = $('.container-modal'); 921 | $containerModal.innerHTML = ''; 922 | let arrayCorriente = existThisSongInSomePlaylist(currentName); 923 | let guardarKey = null; 924 | 925 | for (let key in objectNames) { 926 | let clon = $template.cloneNode(true); 927 | clon.querySelector('input').id = key; 928 | clon.querySelector('input').dataset.clase = toKebabCase(key); 929 | clon.querySelector('label').setAttribute('for', key); 930 | clon.querySelector('label').innerHTML = key; 931 | clon.querySelector('output').setAttribute('class', toKebabCase(key)); 932 | clon.querySelector('output').innerHTML = objectNames[key].length; 933 | if (objectNames[key].length === MAXIMUM_LENGTH_OF_PLAYLIST) { 934 | clon.querySelector('input[type=checkbox]').disabled = 'true'; 935 | guardarKey = key; 936 | } 937 | myFragment.appendChild(clon); 938 | } 939 | 940 | $containerModal.appendChild(myFragment); 941 | 942 | if (currentName === objectNames?.[guardarKey]?.[19][0]) { 943 | setTimeout(() => { 944 | let dataclase = toKebabCase(guardarKey); 945 | $containerModal.querySelector( 946 | `input[data-clase=${dataclase}` 947 | ).disabled = false; 948 | }, 100); 949 | } 950 | 951 | for (let i = 0; i < arrayCorriente.length; i++) { 952 | let checkboxCurrent = toKebabCase(arrayCorriente[i]); 953 | let checkboxActual = $containerModal.querySelector( 954 | `[data-clase='${checkboxCurrent}']` 955 | ); 956 | checkboxActual.checked = true; 957 | checkboxActual.disabled = false; 958 | } 959 | } 960 | } 961 | 962 | function comprobeExistThisProperty(nameProperty) { 963 | if (localStorage.getItem('listname-cards')) { 964 | let object = JSON.parse(localStorage.getItem('listname-cards')); 965 | return object.hasOwnProperty(nameProperty) ? true : false; 966 | } 967 | } 968 | 969 | d.addEventListener('DOMContentLoaded', () => { 970 | blockPlayPauseStopBUTTON(); 971 | putTitle(nameBand); 972 | updateMetadata(); 973 | }); 974 | 975 | function findDuplicates(array, element) { 976 | let filterArray = array.filter(el => el === element); 977 | return filterArray.length; 978 | } 979 | 980 | (function addDataAttributeColor() { 981 | [...$$('.card')].forEach(el => { 982 | el.dataset.colorCard = getComputedStyle(el).getPropertyValue('color'); 983 | }); 984 | })(); 985 | 986 | function pickCards(allCards, listNumbersSongs) { 987 | d.addEventListener('click', e => { 988 | if (e.target.matches('.card *')) { 989 | let actualCard = e.target.closest('.card'); 990 | let index = allCards.indexOf(actualCard); 991 | 992 | if ($('.tooltip').classList.contains('tooltip-active')) { 993 | listNumbersSongs.push(index); 994 | 995 | if (findDuplicates(listNumbersSongs, index) > 1) { 996 | actualCard.style.color = actualCard.dataset.colorCard; 997 | let newArray = listNumbersSongs.filter(el => el !== index); 998 | listNumbersSongs = newArray; 999 | return; 1000 | } 1001 | 1002 | actualCard.style.color = '#fff'; 1003 | } 1004 | } 1005 | 1006 | if (e.target.matches('.tooltip')) { 1007 | e.target.classList.remove('tooltip-active'); 1008 | $('.nav-list-momentary').classList.remove('nav-btn-active'); 1009 | let canciones = listNumbersSongs.map(el => arraySongs[el]); 1010 | playSelectedSongs(canciones, cardPlayButtonClass, listNumbersSongs); 1011 | 1012 | [...$$('.card')].forEach(el => (el.style.color = el.dataset.colorCard)); 1013 | listNumbersSongs.forEach(el => { 1014 | [...$$('.card')][el].style.color = '#fff'; 1015 | }); 1016 | } 1017 | }); 1018 | } 1019 | 1020 | /******************** REMOVE ANIMATION VIEW() OF CARDS ********************/ 1021 | const cards = document.querySelectorAll('.card'); 1022 | 1023 | const observer = new IntersectionObserver( 1024 | (entries, observer) => { 1025 | entries.forEach(entry => { 1026 | if (entry.isIntersecting) { 1027 | entry.target.classList.add('stopped-animation'); 1028 | observer.unobserve(entry.target); 1029 | } 1030 | }); 1031 | }, 1032 | { threshold: 0.5 } 1033 | ); 1034 | 1035 | cards.forEach(card => observer.observe(card)); 1036 | 1037 | /******************** BUTTON NAV MODAL ********************/ 1038 | 1039 | let containerModal = document.querySelector('.container-modal'); 1040 | 1041 | function RenderPlaylistItemsOfTheContainerBottom(objectOfCards) { 1042 | const currentName = localStorage.getItem('lastCurrentNameSong'); 1043 | 1044 | if (!currentName) return; 1045 | 1046 | const objectNames = 1047 | objectOfCards ?? JSON.parse(localStorage.getItem('listname-cards')); 1048 | const template = $('.template-modal-fila').content; 1049 | const tituloModal = $('.tituto-modal'); 1050 | const containerModal = $('.container-modal'); 1051 | 1052 | tituloModal.textContent = `Save ${currentName} in..`; 1053 | containerModal.innerHTML = ''; 1054 | 1055 | const fragment = d.createDocumentFragment(); 1056 | const currentPlaylists = existThisSongInSomePlaylist(currentName); 1057 | 1058 | for (const name in objectNames) { 1059 | const kebabName = toKebabCase(name); 1060 | const playlist = objectNames[name]; 1061 | const clone = template.cloneNode(true); 1062 | 1063 | const input = clone.querySelector('input'); 1064 | const label = clone.querySelector('label'); 1065 | const output = clone.querySelector('output'); 1066 | 1067 | input.id = name; 1068 | input.dataset.clase = kebabName; 1069 | input.disabled = playlist.length === MAXIMUM_LENGTH_OF_PLAYLIST; 1070 | 1071 | label.htmlFor = name; 1072 | label.textContent = name; 1073 | 1074 | output.className = kebabName; 1075 | output.textContent = playlist.length; 1076 | 1077 | fragment.appendChild(clone); 1078 | } 1079 | 1080 | containerModal.appendChild(fragment); 1081 | 1082 | currentPlaylists.forEach(name => { 1083 | const checkbox = containerModal.querySelector( 1084 | `[data-clase="${toKebabCase(name)}"]` 1085 | ); 1086 | if (checkbox) { 1087 | checkbox.checked = true; 1088 | checkbox.disabled = false; 1089 | } 1090 | }); 1091 | } 1092 | 1093 | function updateButtonNavActive(target, classNameToAdd) { 1094 | if (!target.classList.contains(classNameToAdd)) { 1095 | $(`.${classNameToAdd}`).classList.remove(classNameToAdd); 1096 | let timer = setTimeout(() => { 1097 | target.classList.add(classNameToAdd); 1098 | clearTimeout(timer); 1099 | }, 20); 1100 | } 1101 | } 1102 | 1103 | function scrollToTopContainerModal() { 1104 | $('.container-modal').scrollTop = 0; 1105 | } 1106 | 1107 | function scrollToBottomContainerModal() { 1108 | $('.container-modal').scrollTop = $('.container-modal').scrollHeight; 1109 | } 1110 | 1111 | document.addEventListener('click', e => { 1112 | const target = e.target; 1113 | if (target.matches('.am-button-nav-modal')) { 1114 | if (target.matches('.order')) { 1115 | containerModal.innerHTML = ''; 1116 | 1117 | updateButtonNavActive(target, 'button-nav-selected'); 1118 | scrollToTopContainerModal(); 1119 | RenderPlaylistItemsOfTheContainerBottom(); 1120 | return; 1121 | } 1122 | 1123 | if (target.matches('.unorder')) { 1124 | containerModal.innerHTML = ''; 1125 | updateButtonNavActive(target, 'button-nav-selected'); 1126 | scrollToTopContainerModal(); 1127 | 1128 | const objectNames = JSON.parse(localStorage.getItem('listname-cards')); 1129 | if (!objectNames) return; 1130 | const reversedObj = Object.entries(objectNames) 1131 | .reverse() 1132 | .reduce((acc, [key, value]) => { 1133 | acc[key] = value; 1134 | return acc; 1135 | }, {}); 1136 | 1137 | RenderPlaylistItemsOfTheContainerBottom(reversedObj); 1138 | return; 1139 | } 1140 | 1141 | if (target.matches('.random')) { 1142 | containerModal.innerHTML = ''; 1143 | updateButtonNavActive(target, 'button-nav-selected'); 1144 | scrollToTopContainerModal(); 1145 | 1146 | const objectNames = JSON.parse(localStorage.getItem('listname-cards')); 1147 | if (!objectNames) return; 1148 | const shuffledEntries = Object.entries(objectNames).sort( 1149 | () => Math.random() - 0.5 1150 | ); 1151 | 1152 | const shuffledObj = Object.fromEntries(shuffledEntries); 1153 | RenderPlaylistItemsOfTheContainerBottom(shuffledObj); 1154 | return; 1155 | } 1156 | 1157 | if (target.matches('.a-to-z')) { 1158 | containerModal.innerHTML = ''; 1159 | updateButtonNavActive(target, 'button-nav-selected'); 1160 | scrollToTopContainerModal(); 1161 | 1162 | const objectNames = JSON.parse(localStorage.getItem('listname-cards')); 1163 | if (!objectNames) return; 1164 | const sortedEntries = Object.entries(objectNames).sort((a, b) => 1165 | a[0].localeCompare(b[0]) 1166 | ); 1167 | 1168 | const sortedObj = Object.fromEntries(sortedEntries); 1169 | RenderPlaylistItemsOfTheContainerBottom(sortedObj); 1170 | return; 1171 | } 1172 | 1173 | if (target.matches('.z-to-a')) { 1174 | containerModal.innerHTML = ''; 1175 | updateButtonNavActive(target, 'button-nav-selected'); 1176 | scrollToTopContainerModal(); 1177 | 1178 | const objectNames = JSON.parse(localStorage.getItem('listname-cards')); 1179 | if (!objectNames) return; 1180 | const sortedEntries = Object.entries(objectNames).sort((a, b) => 1181 | b[0].localeCompare(a[0]) 1182 | ); 1183 | 1184 | const sortedObj = Object.fromEntries(sortedEntries); 1185 | RenderPlaylistItemsOfTheContainerBottom(sortedObj); 1186 | return; 1187 | } 1188 | } 1189 | }); 1190 | -------------------------------------------------------------------------------- /playlist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 19 | 20 | 21 | 22 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
38 | logo 39 |
40 |
41 | 42 | 43 |

Save the audio in...

44 | 45 | 106 |
107 | 108 | 114 | 115 | 131 |
132 | 133 | 195 | 196 |
197 |
198 |
199 | 202 |
203 |
204 |
205 |
206 |
207 | 212 | 217 | 222 | 229 | 242 | 249 |
250 |
251 |
252 |
253 |
254 |
255 | 258 |
259 |
260 |
261 |
262 |
263 | 268 | 273 | 278 | 285 | 298 | 305 |
306 |
307 |
308 |
309 |
310 |
311 | 314 |
315 |
316 |
317 |
318 |
319 | 324 | 329 | 334 | 341 | 354 | 361 |
362 |
363 |
364 |
365 |
366 |
367 | 370 |
371 |
372 |
373 |
374 |
375 | 380 | 385 | 390 | 397 | 410 | 417 |
418 |
419 |
420 |
421 |
422 |
423 | 426 |
427 |
428 |
429 |
430 |
431 | 436 | 441 | 446 | 453 | 466 | 473 |
474 |
475 |
476 |
477 |
478 |
479 | 482 |
483 |
484 |
485 |
486 |
487 | 492 | 497 | 502 | 509 | 522 | 529 |
530 |
531 |
532 |
533 |
534 |
535 | 538 |
539 |
540 |
541 |
542 |
543 | 548 | 553 | 558 | 565 | 578 | 585 |
586 |
587 |
588 |
589 |
590 |
591 | 594 |
595 |
596 |
597 |
598 |
599 | 604 | 609 | 614 | 621 | 634 | 641 |
642 |
643 |
644 |
645 |
646 |
647 | 650 |
651 |
652 |
653 |
654 |
655 | 660 | 665 | 670 | 677 | 690 | 697 |
698 |
699 |
700 |
701 |
702 |
703 | 706 |
707 |
708 |
709 |
710 |
711 | 716 | 721 | 726 | 733 | 746 | 753 |
754 |
755 |
756 |
757 |
758 |
759 | 762 |
763 |
764 |
765 |
766 |
767 | 772 | 777 | 782 | 789 | 802 | 809 |
810 |
811 |
812 |
813 |
814 |
815 | 818 |
819 |
820 |
821 |
822 |
823 | 828 | 833 | 838 | 845 | 858 | 865 |
866 |
867 |
868 |
869 |
870 |
871 | 874 |
875 |
876 |
877 |
878 |
879 | 884 | 889 | 894 | 901 | 914 | 921 |
922 |
923 |
924 |
925 |
926 |
927 | 930 |
931 |
932 |
933 |
934 |
935 | 940 | 945 | 950 | 957 | 970 | 977 |
978 |
979 |
980 |
981 |
982 |
983 | 986 |
987 |
988 |
989 |
990 |
991 | 996 | 1001 | 1006 | 1013 | 1026 | 1033 |
1034 |
1035 |
1036 |
1037 |
1038 |
1039 | 1042 |
1043 |
1044 |
1045 |
1046 |
1047 | 1052 | 1057 | 1062 | 1069 | 1078 | 1085 |
1086 |
1087 |
1088 |
1089 |
1090 |
1091 | 1094 |
1095 |
1096 |
1097 |
1098 |
1099 | 1104 | 1109 | 1114 | 1121 | 1134 | 1141 |
1142 |
1143 |
1144 |
1145 |
1146 |
1147 | 1150 |
1151 |
1152 |
1153 |
1154 |
1155 | 1160 | 1165 | 1170 | 1177 | 1190 | 1197 |
1198 |
1199 |
1200 |
1201 |
1202 |
1203 | 1206 |
1207 |
1208 |
1209 |
1210 |
1211 | 1216 | 1221 | 1226 | 1233 | 1246 | 1253 |
1254 |
1255 |
1256 |
1257 |
1258 |
1259 | 1262 |
1263 |
1264 |
1265 |
1266 |
1267 | 1272 | 1277 | 1282 | 1289 | 1302 | 1309 |
1310 |
1311 |
1312 |
1313 |
1314 | 1315 |
1316 |
1317 |
1318 | 1319 | --------------------------------------------------------------------------------