├── .gitignore ├── LICENSE ├── README.md ├── dist ├── css │ └── main.css └── js │ ├── bundle.js │ └── maps │ └── bundle.js.map ├── fonts ├── glyphicons-halflings-regular.eot ├── glyphicons-halflings-regular.svg ├── glyphicons-halflings-regular.ttf └── glyphicons-halflings-regular.woff ├── gulpfile.js ├── img ├── demo.png ├── favicon-144.png ├── favicon-192.png ├── favicon-48.png ├── favicon-512.png ├── favicon-72.png ├── favicon-96.png ├── icon.ico └── icon.png ├── index.html ├── package.json ├── sass ├── abstracts │ ├── _mixins.scss │ └── _variables.scss ├── base │ ├── _base.scss │ ├── _reset.scss │ └── _typograph.scss ├── components │ ├── _buttons.scss │ ├── _card.scss │ ├── _divider.scss │ ├── _dropdown.scss │ ├── _flip-card.scss │ ├── _icons.scss │ ├── _input-range.scss │ ├── _list.scss │ ├── _loading.scss │ ├── _sound-waves.scss │ └── _table.scss ├── layouts │ ├── _player.scss │ └── _user-settings.scss ├── main.scss ├── utils │ ├── _animations.scss │ ├── _colors.scss │ ├── _helpers.scss │ └── _shadows.scss └── vendors │ └── _normalize.scss └── src └── js ├── components ├── dropdown.js └── player.js ├── helpers └── time.js ├── index.js └── main.js /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Carlos Alberto Silva Junior 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > Web Music Player 2 | 3 | ![elementary](https://raw.githubusercontent.com/csilva2810/webmplayer/master/img/demo.png) 4 | 5 | It's a MP3 music player made with only Javascript, CSS and HTML5 Audio API.\ 6 | It uses Javascript's File API to read the music files and reproduce them.\ 7 | A have used [Sass](https://sass-lang.com/) pre-compiler to create modular theming styles, so you can choose a dark or light theme and you can also change the player color for your favorite.\ 8 | The player also uses localStorage API to storage your last theme personalizations. So when you comeback to listen to your musics, the player will be like as you left it.\ 9 | And finally it also use's [Unsplash's API](https://source.unsplash.com/) to set the player background image.\ 10 | 11 | [See it working](http://csilva2810.github.io/webmplayer/index.html) 12 | -------------------------------------------------------------------------------- /dist/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | IMPORT ORDER 3 | 1 - abstracts/ 4 | 2 - vendors/ 5 | 3 - utils/ 6 | 4 - base/ 7 | 5 - layout/ 8 | 6 - components/ 9 | 7 - pages/ 10 | 8 - themes/ 11 | */ 12 | /* 13 | * TYPOGRAPH 14 | */ 15 | /** 16 | * COLORS FOR PAGES AND ELEMENTS 17 | */ 18 | /* 19 | * COLORS FOR USE IN THEMES 20 | */ 21 | /*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */ 22 | /** 23 | * 1. Change the default font family in all browsers (opinionated). 24 | * 2. Correct the line height in all browsers. 25 | * 3. Prevent adjustments of font size after orientation changes in 26 | * IE on Windows Phone and in iOS. 27 | */ 28 | /* Document 29 | ========================================================================== */ 30 | html { 31 | font-family: sans-serif; 32 | /* 1 */ 33 | line-height: 1.15; 34 | /* 2 */ 35 | -ms-text-size-adjust: 100%; 36 | /* 3 */ 37 | -webkit-text-size-adjust: 100%; 38 | /* 3 */ } 39 | 40 | /* Sections 41 | ========================================================================== */ 42 | /** 43 | * Remove the margin in all browsers (opinionated). 44 | */ 45 | body { 46 | margin: 0; } 47 | 48 | /** 49 | * Add the correct display in IE 9-. 50 | */ 51 | article, 52 | aside, 53 | footer, 54 | header, 55 | nav, 56 | section { 57 | display: block; } 58 | 59 | /** 60 | * Correct the font size and margin on `h1` elements within `section` and 61 | * `article` contexts in Chrome, Firefox, and Safari. 62 | */ 63 | h1 { 64 | font-size: 2em; 65 | margin: 0.67em 0; } 66 | 67 | /* Grouping content 68 | ========================================================================== */ 69 | /** 70 | * Add the correct display in IE 9-. 71 | * 1. Add the correct display in IE. 72 | */ 73 | figcaption, 74 | figure, 75 | main { 76 | /* 1 */ 77 | display: block; } 78 | 79 | /** 80 | * Add the correct margin in IE 8. 81 | */ 82 | figure { 83 | margin: 1em 40px; } 84 | 85 | /** 86 | * 1. Add the correct box sizing in Firefox. 87 | * 2. Show the overflow in Edge and IE. 88 | */ 89 | hr { 90 | box-sizing: content-box; 91 | /* 1 */ 92 | height: 0; 93 | /* 1 */ 94 | overflow: visible; 95 | /* 2 */ } 96 | 97 | /** 98 | * 1. Correct the inheritance and scaling of font size in all browsers. 99 | * 2. Correct the odd `em` font sizing in all browsers. 100 | */ 101 | pre { 102 | font-family: monospace, monospace; 103 | /* 1 */ 104 | font-size: 1em; 105 | /* 2 */ } 106 | 107 | /* Text-level semantics 108 | ========================================================================== */ 109 | /** 110 | * 1. Remove the gray background on active links in IE 10. 111 | * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. 112 | */ 113 | a { 114 | background-color: transparent; 115 | /* 1 */ 116 | -webkit-text-decoration-skip: objects; 117 | /* 2 */ } 118 | 119 | /** 120 | * Remove the outline on focused links when they are also active or hovered 121 | * in all browsers (opinionated). 122 | */ 123 | a:active, 124 | a:hover { 125 | outline-width: 0; } 126 | 127 | /** 128 | * 1. Remove the bottom border in Firefox 39-. 129 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 130 | */ 131 | abbr[title] { 132 | border-bottom: none; 133 | /* 1 */ 134 | text-decoration: underline; 135 | /* 2 */ 136 | text-decoration: underline dotted; 137 | /* 2 */ } 138 | 139 | /** 140 | * Prevent the duplicate application of `bolder` by the next rule in Safari 6. 141 | */ 142 | b, 143 | strong { 144 | font-weight: inherit; } 145 | 146 | /** 147 | * Add the correct font weight in Chrome, Edge, and Safari. 148 | */ 149 | b, 150 | strong { 151 | font-weight: bolder; } 152 | 153 | /** 154 | * 1. Correct the inheritance and scaling of font size in all browsers. 155 | * 2. Correct the odd `em` font sizing in all browsers. 156 | */ 157 | code, 158 | kbd, 159 | samp { 160 | font-family: monospace, monospace; 161 | /* 1 */ 162 | font-size: 1em; 163 | /* 2 */ } 164 | 165 | /** 166 | * Add the correct font style in Android 4.3-. 167 | */ 168 | dfn { 169 | font-style: italic; } 170 | 171 | /** 172 | * Add the correct background and color in IE 9-. 173 | */ 174 | mark { 175 | background-color: #ff0; 176 | color: #000; } 177 | 178 | /** 179 | * Add the correct font size in all browsers. 180 | */ 181 | small { 182 | font-size: 80%; } 183 | 184 | /** 185 | * Prevent `sub` and `sup` elements from affecting the line height in 186 | * all browsers. 187 | */ 188 | sub, 189 | sup { 190 | font-size: 75%; 191 | line-height: 0; 192 | position: relative; 193 | vertical-align: baseline; } 194 | 195 | sub { 196 | bottom: -0.25em; } 197 | 198 | sup { 199 | top: -0.5em; } 200 | 201 | /* Embedded content 202 | ========================================================================== */ 203 | /** 204 | * Add the correct display in IE 9-. 205 | */ 206 | audio, 207 | video { 208 | display: inline-block; } 209 | 210 | /** 211 | * Add the correct display in iOS 4-7. 212 | */ 213 | audio:not([controls]) { 214 | display: none; 215 | height: 0; } 216 | 217 | /** 218 | * Remove the border on images inside links in IE 10-. 219 | */ 220 | img { 221 | border-style: none; } 222 | 223 | /** 224 | * Hide the overflow in IE. 225 | */ 226 | svg:not(:root) { 227 | overflow: hidden; } 228 | 229 | /* Forms 230 | ========================================================================== */ 231 | /** 232 | * 1. Change the font styles in all browsers (opinionated). 233 | * 2. Remove the margin in Firefox and Safari. 234 | */ 235 | button, 236 | input, 237 | optgroup, 238 | select, 239 | textarea { 240 | font-family: sans-serif; 241 | /* 1 */ 242 | font-size: 100%; 243 | /* 1 */ 244 | line-height: 1.15; 245 | /* 1 */ 246 | margin: 0; 247 | /* 2 */ } 248 | 249 | /** 250 | * Show the overflow in IE. 251 | * 1. Show the overflow in Edge. 252 | */ 253 | button, 254 | input { 255 | /* 1 */ 256 | overflow: visible; } 257 | 258 | /** 259 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 260 | * 1. Remove the inheritance of text transform in Firefox. 261 | */ 262 | button, 263 | select { 264 | /* 1 */ 265 | text-transform: none; } 266 | 267 | /** 268 | * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` 269 | * controls in Android 4. 270 | * 2. Correct the inability to style clickable types in iOS and Safari. 271 | */ 272 | button, 273 | html [type="button"], 274 | [type="reset"], 275 | [type="submit"] { 276 | -webkit-appearance: button; 277 | /* 2 */ } 278 | 279 | /** 280 | * Remove the inner border and padding in Firefox. 281 | */ 282 | button::-moz-focus-inner, 283 | [type="button"]::-moz-focus-inner, 284 | [type="reset"]::-moz-focus-inner, 285 | [type="submit"]::-moz-focus-inner { 286 | border-style: none; 287 | padding: 0; } 288 | 289 | /** 290 | * Restore the focus styles unset by the previous rule. 291 | */ 292 | button:-moz-focusring, 293 | [type="button"]:-moz-focusring, 294 | [type="reset"]:-moz-focusring, 295 | [type="submit"]:-moz-focusring { 296 | outline: 1px dotted ButtonText; } 297 | 298 | /** 299 | * Change the border, margin, and padding in all browsers (opinionated). 300 | */ 301 | fieldset { 302 | border: 1px solid #c0c0c0; 303 | margin: 0 2px; 304 | padding: 0.35em 0.625em 0.75em; } 305 | 306 | /** 307 | * 1. Correct the text wrapping in Edge and IE. 308 | * 2. Correct the color inheritance from `fieldset` elements in IE. 309 | * 3. Remove the padding so developers are not caught out when they zero out 310 | * `fieldset` elements in all browsers. 311 | */ 312 | legend { 313 | box-sizing: border-box; 314 | /* 1 */ 315 | color: inherit; 316 | /* 2 */ 317 | display: table; 318 | /* 1 */ 319 | max-width: 100%; 320 | /* 1 */ 321 | padding: 0; 322 | /* 3 */ 323 | white-space: normal; 324 | /* 1 */ } 325 | 326 | /** 327 | * 1. Add the correct display in IE 9-. 328 | * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. 329 | */ 330 | progress { 331 | display: inline-block; 332 | /* 1 */ 333 | vertical-align: baseline; 334 | /* 2 */ } 335 | 336 | /** 337 | * Remove the default vertical scrollbar in IE. 338 | */ 339 | textarea { 340 | overflow: auto; } 341 | 342 | /** 343 | * 1. Add the correct box sizing in IE 10-. 344 | * 2. Remove the padding in IE 10-. 345 | */ 346 | [type="checkbox"], 347 | [type="radio"] { 348 | box-sizing: border-box; 349 | /* 1 */ 350 | padding: 0; 351 | /* 2 */ } 352 | 353 | /** 354 | * Correct the cursor style of increment and decrement buttons in Chrome. 355 | */ 356 | [type="number"]::-webkit-inner-spin-button, 357 | [type="number"]::-webkit-outer-spin-button { 358 | height: auto; } 359 | 360 | /** 361 | * 1. Correct the odd appearance in Chrome and Safari. 362 | * 2. Correct the outline style in Safari. 363 | */ 364 | [type="search"] { 365 | -webkit-appearance: textfield; 366 | /* 1 */ 367 | outline-offset: -2px; 368 | /* 2 */ } 369 | 370 | /** 371 | * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. 372 | */ 373 | [type="search"]::-webkit-search-cancel-button, 374 | [type="search"]::-webkit-search-decoration { 375 | -webkit-appearance: none; } 376 | 377 | /** 378 | * 1. Correct the inability to style clickable types in iOS and Safari. 379 | * 2. Change font properties to `inherit` in Safari. 380 | */ 381 | ::-webkit-file-upload-button { 382 | -webkit-appearance: button; 383 | /* 1 */ 384 | font: inherit; 385 | /* 2 */ } 386 | 387 | /* Interactive 388 | ========================================================================== */ 389 | /* 390 | * Add the correct display in IE 9-. 391 | * 1. Add the correct display in Edge, IE, and Firefox. 392 | */ 393 | details, 394 | menu { 395 | display: block; } 396 | 397 | /* 398 | * Add the correct display in all browsers. 399 | */ 400 | summary { 401 | display: list-item; } 402 | 403 | /* Scripting 404 | ========================================================================== */ 405 | /** 406 | * Add the correct display in IE 9-. 407 | */ 408 | canvas { 409 | display: inline-block; } 410 | 411 | /** 412 | * Add the correct display in IE. 413 | */ 414 | template { 415 | display: none; } 416 | 417 | /* Hidden 418 | ========================================================================== */ 419 | /** 420 | * Add the correct display in IE 10-. 421 | */ 422 | [hidden] { 423 | display: none; } 424 | 425 | @-webkit-keyframes blink { 426 | 0% { 427 | opacity: 0; } 428 | 50% { 429 | opacity: 1; } 430 | 100% { 431 | opacity: 0; } } 432 | 433 | @keyframes blink { 434 | 0% { 435 | opacity: 0; } 436 | 50% { 437 | opacity: 1; } 438 | 100% { 439 | opacity: 0; } } 440 | 441 | /* 442 | Generating classes to apply colors to elements 443 | E.G: .bg-blue, .text-blue 444 | */ 445 | .bg-green { 446 | background-color: #66bb6a !important; } 447 | 448 | .text-green { 449 | color: #66bb6a !important; } 450 | 451 | .bg-green-lighten { 452 | background-color: #78c37b !important; } 453 | 454 | .text-green-lighten { 455 | color: #78c37b !important; } 456 | 457 | .bg-green-darken { 458 | background-color: #54b359 !important; } 459 | 460 | .text-green-darken { 461 | color: #54b359 !important; } 462 | 463 | .bg-blue { 464 | background-color: #4fc3f7 !important; } 465 | 466 | .text-blue { 467 | color: #4fc3f7 !important; } 468 | 469 | .bg-blue-lighten { 470 | background-color: #67cbf8 !important; } 471 | 472 | .text-blue-lighten { 473 | color: #67cbf8 !important; } 474 | 475 | .bg-blue-darken { 476 | background-color: #37bbf6 !important; } 477 | 478 | .text-blue-darken { 479 | color: #37bbf6 !important; } 480 | 481 | .bg-red { 482 | background-color: #ff5555 !important; } 483 | 484 | .text-red { 485 | color: #ff5555 !important; } 486 | 487 | .bg-red-lighten { 488 | background-color: #ff6f6f !important; } 489 | 490 | .text-red-lighten { 491 | color: #ff6f6f !important; } 492 | 493 | .bg-red-darken { 494 | background-color: #ff3c3c !important; } 495 | 496 | .text-red-darken { 497 | color: #ff3c3c !important; } 498 | 499 | .bg-pink { 500 | background-color: #f06292 !important; } 501 | 502 | .text-pink { 503 | color: #f06292 !important; } 504 | 505 | .bg-pink-lighten { 506 | background-color: #f279a2 !important; } 507 | 508 | .text-pink-lighten { 509 | color: #f279a2 !important; } 510 | 511 | .bg-pink-darken { 512 | background-color: #ee4b82 !important; } 513 | 514 | .text-pink-darken { 515 | color: #ee4b82 !important; } 516 | 517 | .bg-purple { 518 | background-color: #ba68c8 !important; } 519 | 520 | .text-purple { 521 | color: #ba68c8 !important; } 522 | 523 | .bg-purple-lighten { 524 | background-color: #c37bcf !important; } 525 | 526 | .text-purple-lighten { 527 | color: #c37bcf !important; } 528 | 529 | .bg-purple-darken { 530 | background-color: #b155c1 !important; } 531 | 532 | .text-purple-darken { 533 | color: #b155c1 !important; } 534 | 535 | .bg-cyan { 536 | background-color: #4dd0e1 !important; } 537 | 538 | .text-cyan { 539 | color: #4dd0e1 !important; } 540 | 541 | .bg-cyan-lighten { 542 | background-color: #63d6e5 !important; } 543 | 544 | .text-cyan-lighten { 545 | color: #63d6e5 !important; } 546 | 547 | .bg-cyan-darken { 548 | background-color: #37cadd !important; } 549 | 550 | .text-cyan-darken { 551 | color: #37cadd !important; } 552 | 553 | .bg-teal { 554 | background-color: #00bfa5 !important; } 555 | 556 | .text-teal { 557 | color: #00bfa5 !important; } 558 | 559 | .bg-teal-lighten { 560 | background-color: #00d9bb !important; } 561 | 562 | .text-teal-lighten { 563 | color: #00d9bb !important; } 564 | 565 | .bg-teal-darken { 566 | background-color: #00a68f !important; } 567 | 568 | .text-teal-darken { 569 | color: #00a68f !important; } 570 | 571 | .bg-yellow { 572 | background-color: #fbc02d !important; } 573 | 574 | .text-yellow { 575 | color: #fbc02d !important; } 576 | 577 | .bg-yellow-lighten { 578 | background-color: #fbc846 !important; } 579 | 580 | .text-yellow-lighten { 581 | color: #fbc846 !important; } 582 | 583 | .bg-yellow-darken { 584 | background-color: #fbb814 !important; } 585 | 586 | .text-yellow-darken { 587 | color: #fbb814 !important; } 588 | 589 | .bg-orange { 590 | background-color: #ff7043 !important; } 591 | 592 | .text-orange { 593 | color: #ff7043 !important; } 594 | 595 | .bg-orange-lighten { 596 | background-color: #ff835d !important; } 597 | 598 | .text-orange-lighten { 599 | color: #ff835d !important; } 600 | 601 | .bg-orange-darken { 602 | background-color: #ff5d2a !important; } 603 | 604 | .text-orange-darken { 605 | color: #ff5d2a !important; } 606 | 607 | .right { 608 | float: right !important; } 609 | 610 | .left { 611 | float: left !important; } 612 | 613 | .clearfix::after { 614 | content: ''; 615 | display: table; 616 | clear: both !important; } 617 | 618 | .inline { 619 | display: inline !important; } 620 | 621 | .inline-block { 622 | display: inline-block !important; } 623 | 624 | .block { 625 | display: block !important; } 626 | 627 | .half-width { 628 | width: 50% !important; } 629 | 630 | .one-third-width { 631 | width: 33.3333% !important; } 632 | 633 | .text-right { 634 | text-align: right !important; } 635 | 636 | .text-center { 637 | text-align: center !important; } 638 | 639 | .text-left { 640 | text-align: left !important; } 641 | 642 | .text-justify { 643 | text-align: justify !important; } 644 | 645 | .no-margin, .divider { 646 | margin: 0 !important; } 647 | 648 | .no-padding { 649 | padding: 0 !important; } 650 | 651 | .valign-middle { 652 | vertical-align: middle !important; } 653 | 654 | .valign-top { 655 | vertical-align: top !important; } 656 | 657 | .valign-bottom { 658 | vertical-align: bottom !important; } 659 | 660 | .valign-base { 661 | vertical-align: baseline !important; } 662 | 663 | .m-0 { 664 | margin: 0 !important; } 665 | 666 | .m-t-0 { 667 | margin-top: 0 !important; } 668 | 669 | .m-b-0 { 670 | margin-bottom: 0 !important; } 671 | 672 | .m-l-0 { 673 | margin-left: 0 !important; } 674 | 675 | .m-r-0 { 676 | margin-right: 0 !important; } 677 | 678 | .m-5 { 679 | margin: 5px !important; } 680 | 681 | .m-t-5 { 682 | margin-top: 5px !important; } 683 | 684 | .m-b-5 { 685 | margin-bottom: 5px !important; } 686 | 687 | .m-l-5 { 688 | margin-left: 5px !important; } 689 | 690 | .m-r-5 { 691 | margin-right: 5px !important; } 692 | 693 | .m-10 { 694 | margin: 10px !important; } 695 | 696 | .m-t-10 { 697 | margin-top: 10px !important; } 698 | 699 | .m-b-10 { 700 | margin-bottom: 10px !important; } 701 | 702 | .m-l-10 { 703 | margin-left: 10px !important; } 704 | 705 | .m-r-10 { 706 | margin-right: 10px !important; } 707 | 708 | .m-15 { 709 | margin: 15px !important; } 710 | 711 | .m-t-15 { 712 | margin-top: 15px !important; } 713 | 714 | .m-b-15 { 715 | margin-bottom: 15px !important; } 716 | 717 | .m-l-15 { 718 | margin-left: 15px !important; } 719 | 720 | .m-r-15 { 721 | margin-right: 15px !important; } 722 | 723 | .m-20 { 724 | margin: 20px !important; } 725 | 726 | .m-t-20 { 727 | margin-top: 20px !important; } 728 | 729 | .m-b-20 { 730 | margin-bottom: 20px !important; } 731 | 732 | .m-l-20 { 733 | margin-left: 20px !important; } 734 | 735 | .m-r-20 { 736 | margin-right: 20px !important; } 737 | 738 | .m-25 { 739 | margin: 25px !important; } 740 | 741 | .m-t-25 { 742 | margin-top: 25px !important; } 743 | 744 | .m-b-25 { 745 | margin-bottom: 25px !important; } 746 | 747 | .m-l-25 { 748 | margin-left: 25px !important; } 749 | 750 | .m-r-25 { 751 | margin-right: 25px !important; } 752 | 753 | .m-30 { 754 | margin: 30px !important; } 755 | 756 | .m-t-30 { 757 | margin-top: 30px !important; } 758 | 759 | .m-b-30 { 760 | margin-bottom: 30px !important; } 761 | 762 | .m-l-30 { 763 | margin-left: 30px !important; } 764 | 765 | .m-r-30 { 766 | margin-right: 30px !important; } 767 | 768 | .p-0 { 769 | padding: 0 !important; } 770 | 771 | .p-t-0 { 772 | padding-top: 0 !important; } 773 | 774 | .p-b-0 { 775 | padding-bottom: 0 !important; } 776 | 777 | .p-l-0 { 778 | padding-left: 0 !important; } 779 | 780 | .p-r-0 { 781 | padding-right: 0 !important; } 782 | 783 | .p-5 { 784 | padding: 5px !important; } 785 | 786 | .p-t-5 { 787 | padding-top: 5px !important; } 788 | 789 | .p-b-5 { 790 | padding-bottom: 5px !important; } 791 | 792 | .p-l-5 { 793 | padding-left: 5px !important; } 794 | 795 | .p-r-5 { 796 | padding-right: 5px !important; } 797 | 798 | .p-10 { 799 | padding: 10px !important; } 800 | 801 | .p-t-10 { 802 | padding-top: 10px !important; } 803 | 804 | .p-b-10 { 805 | padding-bottom: 10px !important; } 806 | 807 | .p-l-10 { 808 | padding-left: 10px !important; } 809 | 810 | .p-r-10 { 811 | padding-right: 10px !important; } 812 | 813 | .p-15 { 814 | padding: 15px !important; } 815 | 816 | .p-t-15 { 817 | padding-top: 15px !important; } 818 | 819 | .p-b-15 { 820 | padding-bottom: 15px !important; } 821 | 822 | .p-l-15 { 823 | padding-left: 15px !important; } 824 | 825 | .p-r-15 { 826 | padding-right: 15px !important; } 827 | 828 | .p-20 { 829 | padding: 20px !important; } 830 | 831 | .p-t-20 { 832 | padding-top: 20px !important; } 833 | 834 | .p-b-20 { 835 | padding-bottom: 20px !important; } 836 | 837 | .p-l-20 { 838 | padding-left: 20px !important; } 839 | 840 | .p-r-20 { 841 | padding-right: 20px !important; } 842 | 843 | .p-25 { 844 | padding: 25px !important; } 845 | 846 | .p-t-25 { 847 | padding-top: 25px !important; } 848 | 849 | .p-b-25 { 850 | padding-bottom: 25px !important; } 851 | 852 | .p-l-25 { 853 | padding-left: 25px !important; } 854 | 855 | .p-r-25 { 856 | padding-right: 25px !important; } 857 | 858 | .p-30 { 859 | padding: 30px !important; } 860 | 861 | .p-t-30 { 862 | padding-top: 30px !important; } 863 | 864 | .p-b-30 { 865 | padding-bottom: 30px !important; } 866 | 867 | .p-l-30 { 868 | padding-left: 30px !important; } 869 | 870 | .p-r-30 { 871 | padding-right: 30px !important; } 872 | 873 | .f-8 { 874 | font-size: 8px !important; } 875 | 876 | .f-9 { 877 | font-size: 9px !important; } 878 | 879 | .f-10 { 880 | font-size: 10px !important; } 881 | 882 | .f-11 { 883 | font-size: 11px !important; } 884 | 885 | .f-12 { 886 | font-size: 12px !important; } 887 | 888 | .f-13 { 889 | font-size: 13px !important; } 890 | 891 | .f-14 { 892 | font-size: 14px !important; } 893 | 894 | .f-15 { 895 | font-size: 15px !important; } 896 | 897 | .f-16 { 898 | font-size: 16px !important; } 899 | 900 | .f-17 { 901 | font-size: 17px !important; } 902 | 903 | .f-18 { 904 | font-size: 18px !important; } 905 | 906 | .f-19 { 907 | font-size: 19px !important; } 908 | 909 | .f-20 { 910 | font-size: 20px !important; } 911 | 912 | .f-300 { 913 | font-weight: 300 !important; } 914 | 915 | .f-400 { 916 | font-weight: 400 !important; } 917 | 918 | .f-500 { 919 | font-weight: 500 !important; } 920 | 921 | .f-700 { 922 | font-weight: 700 !important; } 923 | 924 | .close, body { 925 | font-weight: 400; } 926 | 927 | .p-relative { 928 | position: relative !important; } 929 | 930 | .p-absolute { 931 | position: absolute !important; } 932 | 933 | .p-fixed { 934 | position: fixed !important; } 935 | 936 | .p-static { 937 | position: static !important; } 938 | 939 | #main, .h-inner, .hi-trigger, body { 940 | position: relative; } 941 | 942 | .o-hidden { 943 | overflow: hidden !important; } 944 | 945 | .o-visible { 946 | overflow: visible !important; } 947 | 948 | .no-shadow { 949 | box-shadow: none !important; } 950 | 951 | .is-timer { 952 | font-family: "Consolas", "Courier New", "Courier", "Lucida Sans Typewriter", "Lucida Typewriter", "monaco", monospace; } 953 | 954 | .shadow-1, .btn { 955 | box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.075), 0 1px 3px 0 rgba(0, 0, 0, 0.1); } 956 | 957 | .shadow-2, .btn:hover, .btn:focus, .card, .dropdown-menu { 958 | box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.075), 0 3px 4px 0 rgba(0, 0, 0, 0.1); } 959 | 960 | .shadow-3, .btn:active, .dropdown-menu:hover { 961 | box-shadow: 0 1px 8px 0 rgba(0, 0, 0, 0.075), 0 3px 12px 0 rgba(0, 0, 0, 0.1); } 962 | 963 | .shadow-4, .card:hover { 964 | box-shadow: 0 3px 14px 0 rgba(0, 0, 0, 0.075), 0 4px 20px 0 rgba(0, 0, 0, 0.1); } 965 | 966 | *, 967 | *::before, 968 | *::after { 969 | box-sizing: border-box; } 970 | 971 | ::-webkit-scrollbar { 972 | width: 9px; 973 | height: 9px; } 974 | 975 | ::-webkit-scrollbar-track { 976 | background-color: transparent; } 977 | 978 | ::-webkit-scrollbar-thumb { 979 | background-color: #ddd; } 980 | 981 | ::-webkit-scrollbar-thumb:hover { 982 | background-color: #ccc; } 983 | 984 | ::-webkit-scrollbar-thumb:active { 985 | background-color: #bbb; } 986 | 987 | .dark ::-webkit-scrollbar-thumb { 988 | background-color: #555; } 989 | 990 | .dark ::-webkit-scrollbar-thumb:hover { 991 | background-color: #444; } 992 | 993 | .dark ::-webkit-scrollbar-thumb:active { 994 | background-color: #333; } 995 | 996 | html, 997 | body { 998 | margin: 0; 999 | padding: 0; 1000 | width: 100%; 1001 | height: 100%; 1002 | font-family: "Rubik", "Helvetica", "Segoe UI", sans-serif; 1003 | font-size: 100%; 1004 | color: #757575; } 1005 | 1006 | body { 1007 | background-color: #EAEDF1; 1008 | background-image: url("https://source.unsplash.com/weekly?music"); 1009 | background-size: cover; 1010 | background-repeat: no-repeat; } 1011 | body.dark { 1012 | color: #eceff1; 1013 | background-color: #5A5D61; } 1014 | 1015 | .container { 1016 | position: fixed; 1017 | top: 8%; 1018 | right: 0; 1019 | bottom: 0; 1020 | left: 0; 1021 | margin: auto; 1022 | display: block; 1023 | width: 80%; 1024 | height: auto; } 1025 | 1026 | .logo { 1027 | font-size: 1.5em; } 1028 | .green .logo { 1029 | color: #66bb6a; } 1030 | .blue .logo { 1031 | color: #4fc3f7; } 1032 | .red .logo { 1033 | color: #ff5555; } 1034 | .pink .logo { 1035 | color: #f06292; } 1036 | .purple .logo { 1037 | color: #ba68c8; } 1038 | .cyan .logo { 1039 | color: #4dd0e1; } 1040 | .teal .logo { 1041 | color: #00bfa5; } 1042 | .yellow .logo { 1043 | color: #fbc02d; } 1044 | .orange .logo { 1045 | color: #ff7043; } 1046 | 1047 | .music-name { 1048 | display: block; 1049 | padding: 8px; 1050 | margin-top: 3px; 1051 | border-radius: 3px; 1052 | overflow: hidden; 1053 | white-space: nowrap; 1054 | text-overflow: ellipsis; 1055 | box-shadow: inset 0 1px 2px 0 rgba(0, 0, 0, 0.1); } 1056 | .light .music-name { 1057 | background-color: #ededed; } 1058 | .dark .music-name { 1059 | background-color: #2e3034; } 1060 | 1061 | .play-list-wrap { 1062 | width: 100%; 1063 | height: 200px; 1064 | max-height: 200px; 1065 | overflow-y: auto; } 1066 | 1067 | .player-wrap { 1068 | display: block; 1069 | width: 100%; } 1070 | 1071 | .dropdown-menu.user-settings { 1072 | width: 120px; } 1073 | 1074 | .theme, 1075 | .color { 1076 | display: block; 1077 | width: 100%; 1078 | padding: 0; 1079 | margin: 0; 1080 | list-style: none; } 1081 | 1082 | .theme .theme-item-btn { 1083 | display: block; 1084 | width: 100%; 1085 | height: 40px; 1086 | line-height: 40px; 1087 | text-align: center; 1088 | text-decoration: none; 1089 | color: inherit; 1090 | cursor: pointer; 1091 | transition: .3s; } 1092 | .theme .theme-item-btn:hover { 1093 | background: rgba(0, 0, 0, 0.05); } 1094 | 1095 | .color > .color-item { 1096 | margin: 0; } 1097 | 1098 | /*--- buttons ---*/ 1099 | .btn { 1100 | display: inline-block; 1101 | padding: 8px 10px; 1102 | border: 1px solid transparent; 1103 | border-radius: 3px; 1104 | outline: none; 1105 | color: #757575; 1106 | text-align: center; 1107 | cursor: pointer; 1108 | transition: .3s; 1109 | will-change: box-shadow, background-color; } 1110 | .light .btn { 1111 | background-color: #ededed; } 1112 | .dark .btn { 1113 | background-color: #2e3034; } 1114 | .light .btn:hover, .light .btn:focus { 1115 | background-color: #ededed; } 1116 | .dark .btn:hover, .dark .btn:focus { 1117 | background-color: #2e3034; } 1118 | .btn.btn-primary { 1119 | color: white; } 1120 | .green .btn.btn-primary { 1121 | background-color: #66bb6a; } 1122 | .blue .btn.btn-primary { 1123 | background-color: #4fc3f7; } 1124 | .red .btn.btn-primary { 1125 | background-color: #ff5555; } 1126 | .pink .btn.btn-primary { 1127 | background-color: #f06292; } 1128 | .purple .btn.btn-primary { 1129 | background-color: #ba68c8; } 1130 | .cyan .btn.btn-primary { 1131 | background-color: #4dd0e1; } 1132 | .teal .btn.btn-primary { 1133 | background-color: #00bfa5; } 1134 | .yellow .btn.btn-primary { 1135 | background-color: #fbc02d; } 1136 | .orange .btn.btn-primary { 1137 | background-color: #ff7043; } 1138 | .green .btn.btn-primary:hover, .green .btn.btn-primary:focus { 1139 | background-color: #78c37b; } 1140 | .blue .btn.btn-primary:hover, .blue .btn.btn-primary:focus { 1141 | background-color: #67cbf8; } 1142 | .red .btn.btn-primary:hover, .red .btn.btn-primary:focus { 1143 | background-color: #ff6f6f; } 1144 | .pink .btn.btn-primary:hover, .pink .btn.btn-primary:focus { 1145 | background-color: #f279a2; } 1146 | .purple .btn.btn-primary:hover, .purple .btn.btn-primary:focus { 1147 | background-color: #c37bcf; } 1148 | .cyan .btn.btn-primary:hover, .cyan .btn.btn-primary:focus { 1149 | background-color: #63d6e5; } 1150 | .teal .btn.btn-primary:hover, .teal .btn.btn-primary:focus { 1151 | background-color: #00d9bb; } 1152 | .yellow .btn.btn-primary:hover, .yellow .btn.btn-primary:focus { 1153 | background-color: #fbc846; } 1154 | .orange .btn.btn-primary:hover, .orange .btn.btn-primary:focus { 1155 | background-color: #ff835d; } 1156 | .btn.btn-circle { 1157 | padding: 0; 1158 | width: 50px; 1159 | height: 50px; 1160 | line-height: 50px; 1161 | border-radius: 50%; } 1162 | .btn.btn-circle.btn-large { 1163 | font-size: 1.25em; 1164 | width: 75px; 1165 | height: 75px; 1166 | line-height: 75px; } 1167 | .btn.btn-circle.btn-small { 1168 | font-size: 1em; 1169 | width: 35px; 1170 | height: 35px; 1171 | line-height: 35px; } 1172 | .btn.btn-circle:hover { 1173 | color: white; } 1174 | .green .btn.btn-circle:hover { 1175 | background-color: #66bb6a; } 1176 | .blue .btn.btn-circle:hover { 1177 | background-color: #4fc3f7; } 1178 | .red .btn.btn-circle:hover { 1179 | background-color: #ff5555; } 1180 | .pink .btn.btn-circle:hover { 1181 | background-color: #f06292; } 1182 | .purple .btn.btn-circle:hover { 1183 | background-color: #ba68c8; } 1184 | .cyan .btn.btn-circle:hover { 1185 | background-color: #4dd0e1; } 1186 | .teal .btn.btn-circle:hover { 1187 | background-color: #00bfa5; } 1188 | .yellow .btn.btn-circle:hover { 1189 | background-color: #fbc02d; } 1190 | .orange .btn.btn-circle:hover { 1191 | background-color: #ff7043; } 1192 | .green .btn.is-on { 1193 | box-shadow: 0 0 5px #66bb6a; } 1194 | .blue .btn.is-on { 1195 | box-shadow: 0 0 5px #4fc3f7; } 1196 | .red .btn.is-on { 1197 | box-shadow: 0 0 5px #ff5555; } 1198 | .pink .btn.is-on { 1199 | box-shadow: 0 0 5px #f06292; } 1200 | .purple .btn.is-on { 1201 | box-shadow: 0 0 5px #ba68c8; } 1202 | .cyan .btn.is-on { 1203 | box-shadow: 0 0 5px #4dd0e1; } 1204 | .teal .btn.is-on { 1205 | box-shadow: 0 0 5px #00bfa5; } 1206 | .yellow .btn.is-on { 1207 | box-shadow: 0 0 5px #fbc02d; } 1208 | .orange .btn.is-on { 1209 | box-shadow: 0 0 5px #ff7043; } 1210 | .green .btn.is-on { 1211 | color: #66bb6a; } 1212 | .blue .btn.is-on { 1213 | color: #4fc3f7; } 1214 | .red .btn.is-on { 1215 | color: #ff5555; } 1216 | .pink .btn.is-on { 1217 | color: #f06292; } 1218 | .purple .btn.is-on { 1219 | color: #ba68c8; } 1220 | .cyan .btn.is-on { 1221 | color: #4dd0e1; } 1222 | .teal .btn.is-on { 1223 | color: #00bfa5; } 1224 | .yellow .btn.is-on { 1225 | color: #fbc02d; } 1226 | .orange .btn.is-on { 1227 | color: #ff7043; } 1228 | .btn.is-on:hover { 1229 | color: white; } 1230 | .btn.btn-color { 1231 | display: inline-block; 1232 | width: 24px; 1233 | height: 24px; 1234 | margin: 3px; 1235 | box-shadow: none; } 1236 | .btn.btn-color:hover, .btn.btn-color:focus { 1237 | box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.1); } 1238 | 1239 | .card { 1240 | display: block; 1241 | width: 100%; 1242 | margin: 0 auto; 1243 | border-radius: 3px; 1244 | transition: .2s; 1245 | will-change: box-shadow; } 1246 | .light .card { 1247 | background-color: #fafafa; } 1248 | .dark .card { 1249 | background-color: #3A3D41; } 1250 | .card > .card-header { 1251 | display: block; 1252 | padding: 5px 10px; 1253 | border-radius: 3px 3px 0 0; } 1254 | .card > .card-header .btn-header { 1255 | padding: 0; 1256 | width: 32px; 1257 | height: 32px; 1258 | line-height: 32px; } 1259 | 1260 | .dropdown-wrapper { 1261 | position: relative; } 1262 | 1263 | .dropdown-menu { 1264 | z-index: 2; 1265 | position: absolute; 1266 | right: 0; 1267 | top: 120%; 1268 | display: block; 1269 | min-width: 50px; 1270 | padding: 0; 1271 | margin: 0; 1272 | list-style: none; 1273 | border-radius: 3px; 1274 | overflow: hidden; 1275 | opacity: 0; 1276 | visibility: hidden; 1277 | transform-origin: top right; 1278 | transform: translateY(-10px); 1279 | transition: 0.4s ease; } 1280 | .light .dropdown-menu { 1281 | background-color: white; } 1282 | .dark .dropdown-menu { 1283 | background-color: #464a4e; } 1284 | .light .dropdown-menu { 1285 | color: #757575; } 1286 | .dark .dropdown-menu { 1287 | color: #eceff1; } 1288 | .dropdown-menu.is-active { 1289 | opacity: 1; 1290 | visibility: visible; 1291 | transform: translateY(0); } 1292 | .dropdown-menu.dropdown-up { 1293 | top: -100%; 1294 | transform: translateY(10px); } 1295 | .dropdown-menu > .item { 1296 | display: block; 1297 | width: 100%; 1298 | line-height: normal; } 1299 | .dropdown-menu > .item.divider { 1300 | display: block; 1301 | height: 1px; 1302 | margin: 0; 1303 | border: none; 1304 | background-color: #eee; 1305 | background: linear-gradient(to right, transparent, #eee, transparent); } 1306 | .dropdown-menu > .item > .link { 1307 | display: block; 1308 | width: 100%; 1309 | padding: 12px 8px; 1310 | color: #555; 1311 | text-decoration: none; 1312 | transition: .2s; } 1313 | .dropdown-menu > .item > .link:hover, .dropdown-menu > .item > .link:focus { 1314 | background-color: #fafafa; } 1315 | .dropdown-menu > .item > .link:first-child { 1316 | border-radius: 3px 3px 0 0; } 1317 | .dropdown-menu > .item > .link:last-child { 1318 | border-radius: 0 0 3px 3px; } 1319 | .dropdown-menu > .item > .link > .icon { 1320 | display: inline-block; 1321 | margin-right: 5px; 1322 | height: 22px; 1323 | line-height: 22px; 1324 | vertical-align: middle; } 1325 | 1326 | .flip-container { 1327 | perspective: 1000; } 1328 | 1329 | .flip-container, 1330 | .front, 1331 | .back { 1332 | display: inline-block; 1333 | width: 80px; 1334 | height: 75px; 1335 | position: relative; 1336 | top: 25px; 1337 | z-index: 1; } 1338 | 1339 | .flipper { 1340 | position: relative; 1341 | transition: 0.6s; 1342 | transform-style: preserve-3d; } 1343 | 1344 | .flip-container.is-flipped .flipper { 1345 | transform: rotateY(180deg); } 1346 | 1347 | .front, 1348 | .back { 1349 | position: absolute; 1350 | top: 0; 1351 | left: 0; 1352 | backface-visibility: hidden; } 1353 | 1354 | .front { 1355 | z-index: 2; 1356 | transform: rotateY(0deg); } 1357 | 1358 | .back { 1359 | z-index: 1; 1360 | transform: rotateY(180deg); } 1361 | 1362 | @font-face { 1363 | font-family: 'Glyphicons Halflings'; 1364 | src: url("../../fonts/glyphicons-halflings-regular.eot"); 1365 | src: url("../../fonts/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"), url("../../fonts/glyphicons-halflings-regular.woff") format("woff"), url("../../fonts/glyphicons-halflings-regular.ttf") format("truetype"), url("../../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg"); } 1366 | 1367 | .icon { 1368 | position: relative; 1369 | top: 1px; 1370 | display: inline-block; 1371 | font-family: 'Glyphicons Halflings'; 1372 | font-style: normal; 1373 | font-weight: normal; 1374 | line-height: 1; 1375 | -webkit-font-smoothing: antialiased; 1376 | -moz-osx-font-smoothing: grayscale; } 1377 | 1378 | .icon-headphones:before { 1379 | content: "\e035"; } 1380 | 1381 | .icon-cog:before { 1382 | content: "\e019"; } 1383 | 1384 | .icon-music:before { 1385 | content: "\e002"; } 1386 | 1387 | .icon-repeat:before { 1388 | content: "\e030"; } 1389 | 1390 | .icon-chevron-left:before { 1391 | content: "\e079"; } 1392 | 1393 | .icon-chevron-right:before { 1394 | content: "\e080"; } 1395 | 1396 | .icon-play:before { 1397 | content: "\e072"; } 1398 | 1399 | .icon-pause:before { 1400 | content: "\e073"; } 1401 | 1402 | .icon-random:before { 1403 | content: "\e110"; } 1404 | 1405 | .icon-volume-down:before { 1406 | content: "\e037"; } 1407 | 1408 | .icon-volume-up:before { 1409 | content: "\e038"; } 1410 | 1411 | .range { 1412 | width: 100%; 1413 | height: 6px; 1414 | position: relative; 1415 | top: -3px; 1416 | border: none; 1417 | outline: none; 1418 | border-radius: 100px; 1419 | box-shadow: inset 0 1px 1px 0 rgba(25, 25, 25, 0.1); 1420 | transition: .2s; 1421 | -webkit-appearance: none; 1422 | -webkit-tap-highlight-color: rgba(255, 255, 255, 0); } 1423 | .light .range { 1424 | background-color: #ededed; } 1425 | .dark .range { 1426 | background-color: #2e3034; } 1427 | .range::-moz-range-track, .range::-ms-fill-lower, .range::-ms-fill-upper, .range::-ms-track { 1428 | border: none; 1429 | color: transparent; 1430 | background-color: transparent; } 1431 | .range::-ms-tooltip { 1432 | display: none; } 1433 | .range::-webkit-slider-thumb { 1434 | -webkit-appearance: none; 1435 | width: 18px; 1436 | height: 18px; 1437 | border: none; 1438 | border-radius: 50%; 1439 | will-change: transform; 1440 | transition: .2s; } 1441 | .green .range::-webkit-slider-thumb { 1442 | background-color: #66bb6a; } 1443 | .blue .range::-webkit-slider-thumb { 1444 | background-color: #4fc3f7; } 1445 | .red .range::-webkit-slider-thumb { 1446 | background-color: #ff5555; } 1447 | .pink .range::-webkit-slider-thumb { 1448 | background-color: #f06292; } 1449 | .purple .range::-webkit-slider-thumb { 1450 | background-color: #ba68c8; } 1451 | .cyan .range::-webkit-slider-thumb { 1452 | background-color: #4dd0e1; } 1453 | .teal .range::-webkit-slider-thumb { 1454 | background-color: #00bfa5; } 1455 | .yellow .range::-webkit-slider-thumb { 1456 | background-color: #fbc02d; } 1457 | .orange .range::-webkit-slider-thumb { 1458 | background-color: #ff7043; } 1459 | .range:active::-webkit-slider-thumb { 1460 | transform: scale(1.2); 1461 | box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.1); } 1462 | .range::-moz-range-thumb { 1463 | width: 18px; 1464 | height: 18px; 1465 | border: none; 1466 | border-radius: 50%; 1467 | will-change: transform; 1468 | transition: .3s; } 1469 | .green .range::-moz-range-thumb { 1470 | background-color: #66bb6a; } 1471 | .blue .range::-moz-range-thumb { 1472 | background-color: #4fc3f7; } 1473 | .red .range::-moz-range-thumb { 1474 | background-color: #ff5555; } 1475 | .pink .range::-moz-range-thumb { 1476 | background-color: #f06292; } 1477 | .purple .range::-moz-range-thumb { 1478 | background-color: #ba68c8; } 1479 | .cyan .range::-moz-range-thumb { 1480 | background-color: #4dd0e1; } 1481 | .teal .range::-moz-range-thumb { 1482 | background-color: #00bfa5; } 1483 | .yellow .range::-moz-range-thumb { 1484 | background-color: #fbc02d; } 1485 | .orange .range::-moz-range-thumb { 1486 | background-color: #ff7043; } 1487 | .range:active::-moz-range-thumb { 1488 | transform: scale(1.2); } 1489 | .range::-ms-thumb { 1490 | width: 18px; 1491 | height: 18px; 1492 | border: none; 1493 | border-radius: 50%; 1494 | will-change: transform; 1495 | transition: .3s; } 1496 | .green .range::-ms-thumb { 1497 | background-color: #66bb6a; } 1498 | .blue .range::-ms-thumb { 1499 | background-color: #4fc3f7; } 1500 | .red .range::-ms-thumb { 1501 | background-color: #ff5555; } 1502 | .pink .range::-ms-thumb { 1503 | background-color: #f06292; } 1504 | .purple .range::-ms-thumb { 1505 | background-color: #ba68c8; } 1506 | .cyan .range::-ms-thumb { 1507 | background-color: #4dd0e1; } 1508 | .teal .range::-ms-thumb { 1509 | background-color: #00bfa5; } 1510 | .yellow .range::-ms-thumb { 1511 | background-color: #fbc02d; } 1512 | .orange .range::-ms-thumb { 1513 | background-color: #ff7043; } 1514 | .range:active::-ms-thumb { 1515 | transform: scale(1.2); } 1516 | 1517 | .play-list { 1518 | list-style: none; 1519 | width: 100%; 1520 | margin: 0 auto; 1521 | padding: 0; } 1522 | .play-list > .list-item { 1523 | padding: 8px; 1524 | transition: background-color .2s; 1525 | font-size: 0.8em; } 1526 | .play-list > .list-item:hover { 1527 | background-color: rgba(0, 0, 0, 0.05); } 1528 | .play-list > .list-item.is-active { 1529 | background-color: rgba(0, 0, 0, 0.05); } 1530 | .play-list > .list-item > .btn { 1531 | padding: 0; 1532 | width: 30px; 1533 | height: 30px; 1534 | line-height: 30px; 1535 | margin-right: 10px; } 1536 | 1537 | .dark .play-list > .lit-item.is-active { 1538 | background-color: rgba(0, 0, 0, 0.1); } 1539 | 1540 | .loading { 1541 | margin: 4px; 1542 | display: none; } 1543 | 1544 | .loading.show { 1545 | display: block; 1546 | -webkit-animation: blink 1s ease-in-out 0s infinite alternate; 1547 | -moz-animation: blink 1s ease-in-out 0s infinite alternate; 1548 | animation: blink 1s ease-in-out 0s infinite alternate; } 1549 | 1550 | .sound-wave { 1551 | display: inline-block; 1552 | position: relative; 1553 | margin-left: 10px; 1554 | vertical-align: middle; } 1555 | 1556 | .sound-wave .bar { 1557 | position: absolute; 1558 | height: 2px; 1559 | width: 6px; } 1560 | 1561 | .sound-wave.is-active .bar { 1562 | -webkit-animation: sound 0.5s linear infinite alternate; 1563 | -moz-animation: sound 0.5s linear infinite alternate; 1564 | animation: sound 0.5s linear infinite alternate; } 1565 | 1566 | .sound-wave .bar:nth-child(1) { 1567 | left: 0; 1568 | -webkit-animation-delay: 0s; 1569 | -moz-animation-delay: 0s; 1570 | animation-delay: 0s; } 1571 | 1572 | .sound-wave .bar:nth-child(2) { 1573 | left: 8px; 1574 | -webkit-animation-delay: 0.5s; 1575 | -moz-animation-delay: 0.5s; 1576 | animation-delay: 0.5s; } 1577 | 1578 | .sound-wave .bar:nth-child(3) { 1579 | left: 16px; 1580 | -webkit-animation-delay: 0.75s; 1581 | -moz-animation-delay: 0.75s; 1582 | animation-delay: 0.75s; } 1583 | 1584 | @-webkit-keyframes sound { 1585 | 0% { 1586 | height: 4px; 1587 | top: 0; 1588 | background: #66CCFF; } 1589 | 100% { 1590 | height: 10px; 1591 | top: -6px; 1592 | background: #CC99FF; } } 1593 | 1594 | @keyframes sound { 1595 | 0% { 1596 | height: 2px; 1597 | top: 0; 1598 | background: #66CCFF; } 1599 | 100% { 1600 | height: 10px; 1601 | top: -8px; 1602 | background: #CC99FF; } } 1603 | 1604 | .divider { 1605 | display: block; 1606 | height: 1px; 1607 | border: none; 1608 | background-color: rgba(0, 0, 0, 0.04); 1609 | border-bottom: 1px solid white; } 1610 | 1611 | .dark .divider { 1612 | background-color: rgba(0, 0, 0, 0.3); 1613 | border-bottom: 1px solid rgba(255, 255, 255, 0.15); } 1614 | 1615 | .table { 1616 | width: 100%; 1617 | border: none; 1618 | background-color: transparent; 1619 | border-collapse: collapse; } 1620 | 1621 | .table td { 1622 | padding: 4px; } 1623 | -------------------------------------------------------------------------------- /dist/js/bundle.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o -1 ? true : false; 9 | }; 10 | 11 | if (toggles) { 12 | toggles.forEach(function (toggle) { 13 | toggle.addEventListener('click', function (e) { 14 | 15 | e.stopPropagation(); 16 | 17 | var target = this.getAttribute('data-dropdown'); 18 | if (!target) return false; 19 | 20 | var dropdown = document.querySelector('#' + target); 21 | if (!dropdown) return false; 22 | 23 | if (hasClass(dropdown, 'is-active')) { 24 | dropdown.classList.remove('is-active'); 25 | } else { 26 | dropdown.classList.add('is-active'); 27 | dropdowns.push(dropdown); 28 | dropdown.addEventListener('click', function (e) { 29 | e.stopPropagation(); 30 | }, false); 31 | } 32 | }, false); 33 | }); 34 | 35 | document.body.addEventListener('click', function () { 36 | 37 | dropdowns.forEach(function (dropdown) { 38 | if (hasClass(dropdown, 'is-active')) { 39 | dropdown.classList.remove('is-active'); 40 | dropdowns.splice(dropdowns.indexOf(dropdown), 1); 41 | } 42 | }); 43 | }, false); 44 | } 45 | 46 | },{}],2:[function(require,module,exports){ 47 | "use strict"; 48 | 49 | var timeHelper = require('../helpers/time'); 50 | 51 | var audio = document.querySelector("#player"), 52 | btnPlay = document.querySelector("#btn-play"), 53 | btnPause = document.querySelector("#btn-pause"), 54 | btnPrev = document.querySelector("#prev"), 55 | btnNext = document.querySelector("#next"), 56 | btnRepeat = document.querySelector("#repeat"), 57 | btnRandom = document.querySelector("#random"), 58 | volumeControl = document.querySelector("#volume"), 59 | timeLine = document.querySelector("#timeline"), 60 | musicTimeCount = document.querySelector("#time-count"), 61 | musicTime = document.querySelector("#time"), 62 | musicName = document.querySelector("#music-name"), 63 | playListElement = document.querySelector("#play-list"), 64 | loading = document.querySelector("#loading-music"), 65 | flip = document.querySelector("#flip-container"), 66 | rd = new FileReader(); 67 | 68 | var Player = { 69 | currentTrack: 0, 70 | isPlaying: false, 71 | isRepeating: false, 72 | isRandomized: false, 73 | playList: [] 74 | }; 75 | 76 | var setPlayList = function setPlayList(music) { 77 | Player.playList.push(music); 78 | }; 79 | 80 | var activateListItem = function activateListItem(id) { 81 | document.querySelector("#list-item-" + id).classList.add("is-active"); 82 | document.querySelector("#list-icon-" + id).classList.add("is-active"); 83 | }; 84 | 85 | var inactivateListItem = function inactivateListItem(id) { 86 | document.querySelector("#list-item-" + id).classList.remove("is-active"); 87 | document.querySelector("#list-icon-" + id).classList.remove("is-active"); 88 | }; 89 | 90 | var clearPlayList = function clearPlayList() { 91 | Player.playList = []; 92 | }; 93 | 94 | var showLoading = function showLoading() { 95 | loading.classList.add("show"); 96 | }; 97 | 98 | var hideLoading = function hideLoading() { 99 | loading.classList.remove("show"); 100 | }; 101 | 102 | var playMusic = function playMusic(track) { 103 | 104 | rd.onloadstart = function () { 105 | showLoading(); 106 | }; 107 | 108 | rd.onload = function () { 109 | audio.src = this.result; 110 | }; 111 | 112 | rd.readAsDataURL(Player.playList[track]); 113 | 114 | audio.onloadeddata = function () { 115 | 116 | audio.play(); 117 | 118 | flip.classList.add('is-flipped'); 119 | if (Player.currentTrack > -1) { 120 | inactivateListItem(Player.currentTrack); 121 | } 122 | 123 | activateListItem(track); 124 | 125 | Player.isPlaying = true; 126 | Player.currentTrack = track; 127 | 128 | hideLoading(); 129 | setMusicName(Player.playList[track].name); 130 | setTimeLineMax(this.duration); 131 | setMusicTime(this.duration); 132 | }; 133 | }; 134 | 135 | var pause = function pause() { 136 | 137 | if (audio.src == "") return false; 138 | 139 | flip.classList.remove('is-flipped'); 140 | inactivateListItem(Player.currentTrack); 141 | 142 | Player.isPlaying = false; 143 | audio.pause(); 144 | }; 145 | 146 | var resume = function resume() { 147 | 148 | if (audio.src == "") return false; 149 | 150 | flip.classList.add('is-flipped'); 151 | activateListItem(Player.currentTrack); 152 | 153 | Player.isPlaying = true; 154 | audio.play(); 155 | }; 156 | 157 | var playPrev = function playPrev() { 158 | 159 | if (audio.src == "") return false; 160 | 161 | var prev = Player.currentTrack - 1; 162 | prev > -1 ? playMusic(prev) : playMusic(0); 163 | }; 164 | 165 | var playNext = function playNext() { 166 | 167 | if (audio.src == "") return false; 168 | 169 | var next = Player.currentTrack + 1; 170 | var lastMusic = Player.playList.length - 1; 171 | var random = Math.round(Math.random() * lastMusic); 172 | 173 | if (!Player.isRandomized) { 174 | next <= lastMusic ? playMusic(next) : playMusic(0); 175 | } else { 176 | playMusic(random); 177 | } 178 | }; 179 | 180 | var repeat = function repeat() { 181 | if (!Player.isRepeating) { 182 | btnRepeat.classList.add('is-on'); 183 | audio.setAttribute("loop", ""); 184 | Player.isRepeating = true; 185 | } else { 186 | btnRepeat.classList.remove('is-on'); 187 | audio.removeAttribute("loop"); 188 | Player.isRepeating = false; 189 | } 190 | }; 191 | 192 | var randomize = function randomize() { 193 | if (!Player.isRandomized) { 194 | btnRandom.classList.add('is-on'); 195 | Player.isRandomized = true; 196 | } else { 197 | btnRandom.classList.remove('is-on'); 198 | Player.isRandomized = false; 199 | } 200 | }; 201 | 202 | var changeVolume = function changeVolume() { 203 | audio.volume = volumeControl.value / 10; 204 | }; 205 | 206 | var changeTime = function changeTime() { 207 | if (audio.readyState != 0) audio.currentTime = timeLine.value; 208 | }; 209 | 210 | var timeLineUpdate = function timeLineUpdate() { 211 | timeLine.value = audio.currentTime; 212 | }; 213 | 214 | var setTimeLineMax = function setTimeLineMax(time) { 215 | timeLine.setAttribute("max", Math.round(time)); 216 | }; 217 | 218 | var setMusicTime = function setMusicTime(time) { 219 | musicTime.innerHTML = timeHelper.secondsToTime(Math.round(time)); 220 | }; 221 | 222 | var musicCountUpdate = function musicCountUpdate(time) { 223 | musicTimeCount.innerHTML = timeHelper.secondsToTime(Math.round(time)); 224 | }; 225 | 226 | var setMusicName = function setMusicName(name) { 227 | musicName.innerHTML = name.replace(".mp3", ""); 228 | }; 229 | 230 | var createPlayList = function createPlayList() { 231 | 232 | var musicName, 233 | i, 234 | li, 235 | button, 236 | span, 237 | len = Player.playList.length; 238 | 239 | playListElement.innerHTML = ""; 240 | 241 | for (i = 0; i < len; i += 1) { 242 | 243 | musicName = document.createTextNode(Player.playList[i].name.replace(".mp3", "")); 244 | 245 | li = document.createElement("li"); 246 | button = document.createElement("button"); 247 | span = document.createElement("span"); 248 | 249 | button.setAttribute("type", "button"); 250 | button.setAttribute("class", "btn btn-circle btn-small"); 251 | button.innerHTML = ''; 252 | 253 | (function (id) { 254 | button.addEventListener('click', function () { 255 | playMusic(id); 256 | }, false); 257 | })(i); 258 | 259 | span.setAttribute("id", "list-icon-" + i); 260 | span.setAttribute("class", "sound-wave"); 261 | span.innerHTML = ""; 262 | 263 | li.setAttribute("id", "list-item-" + i); 264 | li.setAttribute("class", "list-item"); 265 | li.appendChild(button); 266 | li.appendChild(musicName); 267 | li.appendChild(span); 268 | playListElement.appendChild(li); 269 | }; 270 | }; 271 | 272 | //botões 273 | btnPlay.addEventListener("click", resume, false); 274 | btnPause.addEventListener("click", pause, false); 275 | btnPrev.addEventListener("click", playPrev, false); 276 | btnNext.addEventListener("click", playNext, false); 277 | btnRepeat.addEventListener("click", repeat, false); 278 | btnRandom.addEventListener("click", randomize, false); 279 | 280 | //volume 281 | volumeControl.addEventListener("change", changeVolume, false); 282 | 283 | //timeLine 284 | timeLine.addEventListener("change", changeTime, false); 285 | timeLine.addEventListener("mousedown", function () { 286 | audio.removeEventListener("timeupdate", timeLineUpdate); 287 | }, false); 288 | timeLine.addEventListener("mouseup", function () { 289 | audio.addEventListener("timeupdate", timeLineUpdate, false); 290 | }, false); 291 | 292 | //player 293 | audio.addEventListener("ended", playNext, false); 294 | audio.addEventListener("timeupdate", timeLineUpdate, false); 295 | audio.addEventListener("timeupdate", function () { 296 | musicCountUpdate(Math.floor(this.currentTime)); 297 | }, false); 298 | 299 | module.exports = { 300 | setPlayList: setPlayList, 301 | clearPlayList: clearPlayList, 302 | playMusic: playMusic, 303 | createPlayList: createPlayList 304 | }; 305 | 306 | },{"../helpers/time":3}],3:[function(require,module,exports){ 307 | 'use strict'; 308 | 309 | function padLeft(n, width, z) { 310 | z = z || '0'; 311 | n = n + ''; 312 | return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; 313 | } 314 | 315 | var secondsToTime = function secondsToTime(seconds) { 316 | 317 | if (isNaN(seconds) || seconds == "" || typeof seconds != 'number') return "00:00"; 318 | 319 | var hours = parseInt(seconds / 3600) % 24, 320 | minutes = parseInt(seconds / 60) % 60, 321 | seconds = parseInt(seconds % 60); 322 | 323 | if (hours > 0) { 324 | var result = padLeft(hours, 2, 0) + ':' + padLeft(minutes, 2, 0) + ':' + padLeft(seconds, 2, 0); 325 | } else { 326 | var result = padLeft(minutes, 2, 0) + ':' + padLeft(seconds, 2, 0); 327 | } 328 | 329 | return result; 330 | }; 331 | 332 | module.exports = { 333 | secondsToTime: secondsToTime 334 | }; 335 | 336 | },{}],4:[function(require,module,exports){ 337 | 'use strict'; 338 | 339 | require('./components/dropdown.js'); 340 | 341 | var Player = require('./components/player.js'); 342 | 343 | (function () { 344 | 345 | var btnUpload = document.querySelector("#btn-upload"), 346 | fileElement = document.querySelector("#file-element"), 347 | themeLight = document.querySelector("#theme-light"), 348 | themeDark = document.querySelector("#theme-dark"), 349 | btnsTheme = document.querySelectorAll('.theme-item-btn'), 350 | btnsColor = document.querySelectorAll('.btn-color'), 351 | setLocalStorage = function setLocalStorage(item, value) { 352 | if (window.hasOwnProperty('localStorage')) { 353 | localStorage.setItem(item, value); 354 | } 355 | }, 356 | getLocalStorage = function getLocalStorage(item) { 357 | if (window.hasOwnProperty('localStorage')) { 358 | return localStorage.getItem(item); 359 | } 360 | }, 361 | setTheme = function setTheme(theme) { 362 | 363 | theme = theme || "light"; 364 | document.body.classList.remove('dark', 'light'); 365 | document.body.classList.add(theme); 366 | setLocalStorage("theme", theme); 367 | }, 368 | setColor = function setColor(color) { 369 | 370 | color = color || "green"; 371 | document.body.className = document.body.className.replace(/(blue|red|green|pink|purple|cyan|teal|yellow|orange)/g, ''); 372 | document.body.classList.add(color); 373 | setLocalStorage("color", color); 374 | }; 375 | 376 | if (window.hasOwnProperty('localStorage')) { 377 | setTheme(getLocalStorage('theme')); 378 | setColor(getLocalStorage('color')); 379 | } 380 | 381 | btnUpload.addEventListener("click", function (e) { 382 | 383 | e.stopPropagation(); 384 | e.preventDefault(); 385 | 386 | if (fileElement) { 387 | fileElement.click(); 388 | } 389 | }, false); 390 | 391 | fileElement.addEventListener("change", function () { 392 | 393 | Player.clearPlayList(); 394 | 395 | for (var i = 0, len = this.files.length; i < len; i += 1) { 396 | Player.setPlayList(this.files[i]); 397 | } 398 | 399 | Player.createPlayList(); 400 | Player.playMusic(0); 401 | }, false); 402 | 403 | btnsTheme.forEach(function (btnTheme) { 404 | btnTheme.addEventListener('click', function () { 405 | var themeScheme = this.getAttribute('data-theme-scheme'); 406 | setTheme(themeScheme); 407 | }, false); 408 | }); 409 | 410 | btnsColor.forEach(function (btnColor) { 411 | btnColor.addEventListener('click', function () { 412 | var color = this.getAttribute('data-theme-color'); 413 | setColor(color); 414 | }, false); 415 | }); 416 | })(); 417 | 418 | },{"./components/dropdown.js":1,"./components/player.js":2}],5:[function(require,module,exports){ 419 | 'use strict'; 420 | 421 | require('./index.js'); 422 | 423 | },{"./index.js":4}]},{},[5]); 424 | 425 | //# sourceMappingURL=maps/bundle.js.map 426 | -------------------------------------------------------------------------------- /dist/js/maps/bundle.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"names":[],"mappings":"","sources":["bundle.js"],"sourcesContent":["(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o -1 ? true : false;\n};\n\nif (toggles) {\n\ttoggles.forEach(function (toggle) {\n\t\ttoggle.addEventListener('click', function (e) {\n\n\t\t\te.stopPropagation();\n\n\t\t\tvar target = this.getAttribute('data-dropdown');\n\t\t\tif (!target) return false;\n\n\t\t\tvar dropdown = document.querySelector('#' + target);\n\t\t\tif (!dropdown) return false;\n\n\t\t\tif (hasClass(dropdown, 'is-active')) {\n\t\t\t\tdropdown.classList.remove('is-active');\n\t\t\t} else {\n\t\t\t\tdropdown.classList.add('is-active');\n\t\t\t\tdropdowns.push(dropdown);\n\t\t\t\tdropdown.addEventListener('click', function (e) {\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t}, false);\n\t\t\t}\n\t\t}, false);\n\t});\n\n\tdocument.body.addEventListener('click', function () {\n\n\t\tdropdowns.forEach(function (dropdown) {\n\t\t\tif (hasClass(dropdown, 'is-active')) {\n\t\t\t\tdropdown.classList.remove('is-active');\n\t\t\t\tdropdowns.splice(dropdowns.indexOf(dropdown), 1);\n\t\t\t}\n\t\t});\n\t}, false);\n}\n\n},{}],2:[function(require,module,exports){\n\"use strict\";\n\nvar timeHelper = require('../helpers/time');\n\nvar audio = document.querySelector(\"#player\"),\n btnPlay = document.querySelector(\"#btn-play\"),\n btnPause = document.querySelector(\"#btn-pause\"),\n btnPrev = document.querySelector(\"#prev\"),\n btnNext = document.querySelector(\"#next\"),\n btnRepeat = document.querySelector(\"#repeat\"),\n btnRandom = document.querySelector(\"#random\"),\n volumeControl = document.querySelector(\"#volume\"),\n timeLine = document.querySelector(\"#timeline\"),\n musicTimeCount = document.querySelector(\"#time-count\"),\n musicTime = document.querySelector(\"#time\"),\n musicName = document.querySelector(\"#music-name\"),\n playListElement = document.querySelector(\"#play-list\"),\n loading = document.querySelector(\"#loading-music\"),\n flip = document.querySelector(\"#flip-container\"),\n rd = new FileReader();\n\nvar Player = {\n currentTrack: 0,\n isPlaying: false,\n isRepeating: false,\n isRandomized: false,\n playList: []\n};\n\nvar setPlayList = function setPlayList(music) {\n Player.playList.push(music);\n};\n\nvar activateListItem = function activateListItem(id) {\n document.querySelector(\"#list-item-\" + id).classList.add(\"is-active\");\n document.querySelector(\"#list-icon-\" + id).classList.add(\"is-active\");\n};\n\nvar inactivateListItem = function inactivateListItem(id) {\n document.querySelector(\"#list-item-\" + id).classList.remove(\"is-active\");\n document.querySelector(\"#list-icon-\" + id).classList.remove(\"is-active\");\n};\n\nvar clearPlayList = function clearPlayList() {\n Player.playList = [];\n};\n\nvar showLoading = function showLoading() {\n loading.classList.add(\"show\");\n};\n\nvar hideLoading = function hideLoading() {\n loading.classList.remove(\"show\");\n};\n\nvar playMusic = function playMusic(track) {\n\n rd.onloadstart = function () {\n showLoading();\n };\n\n rd.onload = function () {\n audio.src = this.result;\n };\n\n rd.readAsDataURL(Player.playList[track]);\n\n audio.onloadeddata = function () {\n\n audio.play();\n\n flip.classList.add('is-flipped');\n if (Player.currentTrack > -1) {\n inactivateListItem(Player.currentTrack);\n }\n\n activateListItem(track);\n\n Player.isPlaying = true;\n Player.currentTrack = track;\n\n hideLoading();\n setMusicName(Player.playList[track].name);\n setTimeLineMax(this.duration);\n setMusicTime(this.duration);\n };\n};\n\nvar pause = function pause() {\n\n if (audio.src == \"\") return false;\n\n flip.classList.remove('is-flipped');\n inactivateListItem(Player.currentTrack);\n\n Player.isPlaying = false;\n audio.pause();\n};\n\nvar resume = function resume() {\n\n if (audio.src == \"\") return false;\n\n flip.classList.add('is-flipped');\n activateListItem(Player.currentTrack);\n\n Player.isPlaying = true;\n audio.play();\n};\n\nvar playPrev = function playPrev() {\n\n if (audio.src == \"\") return false;\n\n var prev = Player.currentTrack - 1;\n prev > -1 ? playMusic(prev) : playMusic(0);\n};\n\nvar playNext = function playNext() {\n\n if (audio.src == \"\") return false;\n\n var next = Player.currentTrack + 1;\n var lastMusic = Player.playList.length - 1;\n var random = Math.round(Math.random() * lastMusic);\n\n if (!Player.isRandomized) {\n next <= lastMusic ? playMusic(next) : playMusic(0);\n } else {\n playMusic(random);\n }\n};\n\nvar repeat = function repeat() {\n if (!Player.isRepeating) {\n btnRepeat.classList.add('is-on');\n audio.setAttribute(\"loop\", \"\");\n Player.isRepeating = true;\n } else {\n btnRepeat.classList.remove('is-on');\n audio.removeAttribute(\"loop\");\n Player.isRepeating = false;\n }\n};\n\nvar randomize = function randomize() {\n if (!Player.isRandomized) {\n btnRandom.classList.add('is-on');\n Player.isRandomized = true;\n } else {\n btnRandom.classList.remove('is-on');\n Player.isRandomized = false;\n }\n};\n\nvar changeVolume = function changeVolume() {\n audio.volume = volumeControl.value / 10;\n};\n\nvar changeTime = function changeTime() {\n if (audio.readyState != 0) audio.currentTime = timeLine.value;\n};\n\nvar timeLineUpdate = function timeLineUpdate() {\n timeLine.value = audio.currentTime;\n};\n\nvar setTimeLineMax = function setTimeLineMax(time) {\n timeLine.setAttribute(\"max\", Math.round(time));\n};\n\nvar setMusicTime = function setMusicTime(time) {\n musicTime.innerHTML = timeHelper.secondsToTime(Math.round(time));\n};\n\nvar musicCountUpdate = function musicCountUpdate(time) {\n musicTimeCount.innerHTML = timeHelper.secondsToTime(Math.round(time));\n};\n\nvar setMusicName = function setMusicName(name) {\n musicName.innerHTML = name.replace(\".mp3\", \"\");\n};\n\nvar createPlayList = function createPlayList() {\n\n var musicName,\n i,\n li,\n button,\n span,\n len = Player.playList.length;\n\n playListElement.innerHTML = \"\";\n\n for (i = 0; i < len; i += 1) {\n\n musicName = document.createTextNode(Player.playList[i].name.replace(\".mp3\", \"\"));\n\n li = document.createElement(\"li\");\n button = document.createElement(\"button\");\n span = document.createElement(\"span\");\n\n button.setAttribute(\"type\", \"button\");\n button.setAttribute(\"class\", \"btn btn-circle btn-small\");\n button.innerHTML = '';\n\n (function (id) {\n button.addEventListener('click', function () {\n playMusic(id);\n }, false);\n })(i);\n\n span.setAttribute(\"id\", \"list-icon-\" + i);\n span.setAttribute(\"class\", \"sound-wave\");\n span.innerHTML = \"\";\n\n li.setAttribute(\"id\", \"list-item-\" + i);\n li.setAttribute(\"class\", \"list-item\");\n li.appendChild(button);\n li.appendChild(musicName);\n li.appendChild(span);\n playListElement.appendChild(li);\n };\n};\n\n//botões\nbtnPlay.addEventListener(\"click\", resume, false);\nbtnPause.addEventListener(\"click\", pause, false);\nbtnPrev.addEventListener(\"click\", playPrev, false);\nbtnNext.addEventListener(\"click\", playNext, false);\nbtnRepeat.addEventListener(\"click\", repeat, false);\nbtnRandom.addEventListener(\"click\", randomize, false);\n\n//volume\nvolumeControl.addEventListener(\"change\", changeVolume, false);\n\n//timeLine\ntimeLine.addEventListener(\"change\", changeTime, false);\ntimeLine.addEventListener(\"mousedown\", function () {\n audio.removeEventListener(\"timeupdate\", timeLineUpdate);\n}, false);\ntimeLine.addEventListener(\"mouseup\", function () {\n audio.addEventListener(\"timeupdate\", timeLineUpdate, false);\n}, false);\n\n//player\naudio.addEventListener(\"ended\", playNext, false);\naudio.addEventListener(\"timeupdate\", timeLineUpdate, false);\naudio.addEventListener(\"timeupdate\", function () {\n musicCountUpdate(Math.floor(this.currentTime));\n}, false);\n\nmodule.exports = {\n setPlayList: setPlayList,\n clearPlayList: clearPlayList,\n playMusic: playMusic,\n createPlayList: createPlayList\n};\n\n},{\"../helpers/time\":3}],3:[function(require,module,exports){\n'use strict';\n\nfunction padLeft(n, width, z) {\n z = z || '0';\n n = n + '';\n return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;\n}\n\nvar secondsToTime = function secondsToTime(seconds) {\n\n if (isNaN(seconds) || seconds == \"\" || typeof seconds != 'number') return \"00:00\";\n\n var hours = parseInt(seconds / 3600) % 24,\n minutes = parseInt(seconds / 60) % 60,\n seconds = parseInt(seconds % 60);\n\n if (hours > 0) {\n var result = padLeft(hours, 2, 0) + ':' + padLeft(minutes, 2, 0) + ':' + padLeft(seconds, 2, 0);\n } else {\n var result = padLeft(minutes, 2, 0) + ':' + padLeft(seconds, 2, 0);\n }\n\n return result;\n};\n\nmodule.exports = {\n secondsToTime: secondsToTime\n};\n\n},{}],4:[function(require,module,exports){\n'use strict';\n\nrequire('./components/dropdown.js');\n\nvar Player = require('./components/player.js');\n\n(function () {\n\n var btnUpload = document.querySelector(\"#btn-upload\"),\n fileElement = document.querySelector(\"#file-element\"),\n themeLight = document.querySelector(\"#theme-light\"),\n themeDark = document.querySelector(\"#theme-dark\"),\n btnsTheme = document.querySelectorAll('.theme-item-btn'),\n btnsColor = document.querySelectorAll('.btn-color'),\n setLocalStorage = function setLocalStorage(item, value) {\n if (window.hasOwnProperty('localStorage')) {\n localStorage.setItem(item, value);\n }\n },\n getLocalStorage = function getLocalStorage(item) {\n if (window.hasOwnProperty('localStorage')) {\n return localStorage.getItem(item);\n }\n },\n setTheme = function setTheme(theme) {\n\n theme = theme || \"light\";\n document.body.classList.remove('dark', 'light');\n document.body.classList.add(theme);\n setLocalStorage(\"theme\", theme);\n },\n setColor = function setColor(color) {\n\n color = color || \"green\";\n document.body.className = document.body.className.replace(/(blue|red|green|pink|purple|cyan|teal|yellow|orange)/g, '');\n document.body.classList.add(color);\n setLocalStorage(\"color\", color);\n };\n\n if (window.hasOwnProperty('localStorage')) {\n setTheme(getLocalStorage('theme'));\n setColor(getLocalStorage('color'));\n }\n\n btnUpload.addEventListener(\"click\", function (e) {\n\n e.stopPropagation();\n e.preventDefault();\n\n if (fileElement) {\n fileElement.click();\n }\n }, false);\n\n fileElement.addEventListener(\"change\", function () {\n\n Player.clearPlayList();\n\n for (var i = 0, len = this.files.length; i < len; i += 1) {\n Player.setPlayList(this.files[i]);\n }\n\n Player.createPlayList();\n Player.playMusic(0);\n }, false);\n\n btnsTheme.forEach(function (btnTheme) {\n btnTheme.addEventListener('click', function () {\n var themeScheme = this.getAttribute('data-theme-scheme');\n setTheme(themeScheme);\n }, false);\n });\n\n btnsColor.forEach(function (btnColor) {\n btnColor.addEventListener('click', function () {\n var color = this.getAttribute('data-theme-color');\n setColor(color);\n }, false);\n });\n})();\n\n},{\"./components/dropdown.js\":1,\"./components/player.js\":2}],5:[function(require,module,exports){\n'use strict';\n\nrequire('./index.js');\n\n},{\"./index.js\":4}]},{},[5]);\n"],"file":"../bundle.js"} -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csilva2810/webmplayer/474163a178506b1a5e624e9b007340afc9b86d57/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 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 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csilva2810/webmplayer/474163a178506b1a5e624e9b007340afc9b86d57/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csilva2810/webmplayer/474163a178506b1a5e624e9b007340afc9b86d57/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var babelify = require('babelify'), 4 | browserify = require('browserify'), 5 | buffer = require('vinyl-buffer'), 6 | gulp = require('gulp'), 7 | gutil = require('gulp-util'), 8 | sass = require('gulp-sass'), 9 | livereload = require('gulp-livereload'), 10 | merge = require('merge'), 11 | rename = require('gulp-rename'), 12 | source = require('vinyl-source-stream'), 13 | sourceMaps = require('gulp-sourcemaps'), 14 | watchify = require('watchify'); 15 | 16 | var config = { 17 | js: { 18 | src: './src/js/main.js', 19 | outputDir: './dist/js/', 20 | mapDir: './maps/', 21 | outputFile: 'bundle.js' 22 | }, 23 | css: { 24 | src: './sass/**/*.scss', 25 | outputDir: './dist/css/', 26 | outputFile: 'main.css' 27 | } 28 | }; 29 | 30 | function bundle (bundler) { 31 | 32 | return bundler 33 | .bundle() // Start bundle 34 | .pipe(source(config.js.src)) // Entry point 35 | .pipe(buffer()) // Convert to gulp pipeline 36 | .pipe(rename(config.js.outputFile)) // Rename output from 'main.js' to 'bundle.js' 37 | .pipe(sourceMaps.init({ loadMaps : true })) // Strip inline source maps 38 | .pipe(sourceMaps.write(config.js.mapDir)) // Save source maps to their own directory 39 | .pipe(gulp.dest(config.js.outputDir)) // Save 'bundle' to build/ 40 | .pipe(livereload()); // Reload browser if relevant 41 | 42 | } 43 | 44 | gulp.task('bundle', function () { 45 | var bundler = browserify(config.js.src) // Pass browserify the entry point 46 | .transform(babelify, { presets : [ 'es2015' ] }); // Then, babelify, with ES2015 preset 47 | 48 | return bundle(bundler); // Chain other options -- sourcemaps, rename, etc. 49 | }); 50 | 51 | gulp.task('sass', function () { 52 | return gulp.src(config.css.src) 53 | .pipe(sass().on('error', sass.logError)) 54 | .pipe(gulp.dest(config.css.outputDir)); 55 | }); 56 | 57 | gulp.task('sass:watch', function () { 58 | gulp.watch('./sass/**/*.scss', ['sass']); 59 | }); -------------------------------------------------------------------------------- /img/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csilva2810/webmplayer/474163a178506b1a5e624e9b007340afc9b86d57/img/demo.png -------------------------------------------------------------------------------- /img/favicon-144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csilva2810/webmplayer/474163a178506b1a5e624e9b007340afc9b86d57/img/favicon-144.png -------------------------------------------------------------------------------- /img/favicon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csilva2810/webmplayer/474163a178506b1a5e624e9b007340afc9b86d57/img/favicon-192.png -------------------------------------------------------------------------------- /img/favicon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csilva2810/webmplayer/474163a178506b1a5e624e9b007340afc9b86d57/img/favicon-48.png -------------------------------------------------------------------------------- /img/favicon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csilva2810/webmplayer/474163a178506b1a5e624e9b007340afc9b86d57/img/favicon-512.png -------------------------------------------------------------------------------- /img/favicon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csilva2810/webmplayer/474163a178506b1a5e624e9b007340afc9b86d57/img/favicon-72.png -------------------------------------------------------------------------------- /img/favicon-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csilva2810/webmplayer/474163a178506b1a5e624e9b007340afc9b86d57/img/favicon-96.png -------------------------------------------------------------------------------- /img/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csilva2810/webmplayer/474163a178506b1a5e624e9b007340afc9b86d57/img/icon.ico -------------------------------------------------------------------------------- /img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csilva2810/webmplayer/474163a178506b1a5e624e9b007340afc9b86d57/img/icon.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Web Music Player 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 |
26 | 27 |
28 | 29 | 33 | 34 | 37 | 38 | 80 | 81 |
82 | 83 |
84 | 85 |
86 |
87 |
    88 |
    89 |
    90 | 91 |
    92 | 93 |
    94 | 95 | 96 | 97 |
    98 | 101 | 104 |
    105 |
    106 |
    107 | 110 |
    111 |
    112 | 115 |
    116 |
    117 |
    118 | 121 | 124 |
    125 | 126 |
    127 |
    Carregando...
    128 |
    129 | 130 |
    131 | 132 | 133 | 134 | 137 | 140 | 143 | 144 |
    135 | 136 | 138 | 139 | 141 | 142 |
    145 | 146 | 156 | 157 |
    158 | 159 |
    160 | 161 |
    162 | 163 |
    164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webmplayer", 3 | "version": "1.0.0", 4 | "description": "Web Player built with HTML5, Javascript and CSS", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "dev": "browserify src/js/main.js --debug | exorcist dist/js/bundle.map.js > dist/js/bundle.js", 9 | "dev:watch": "watchify -vd src/js/main.js -o 'exorcist dist/js/bundle.js.map > dist/js/bundle.js'" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/csilva2810/webmplayer.git" 14 | }, 15 | "keywords": [ 16 | "webplayer", 17 | "player" 18 | ], 19 | "author": "Carlos Silva", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/csilva2810/webmplayer/issues" 23 | }, 24 | "homepage": "https://github.com/csilva2810/webmplayer#readme", 25 | "dependencies": { 26 | "normalize.css": "^5.0.0" 27 | }, 28 | "devDependencies": { 29 | "babel-preset-es2015": "^6.16.0", 30 | "babelify": "^7.3.0", 31 | "browserify": "^13.1.0", 32 | "buffer": "^5.0.0", 33 | "exorcist": "^0.4.0", 34 | "gulp": "^3.9.1", 35 | "gulp-livereload": "^3.8.1", 36 | "gulp-rename": "^1.2.2", 37 | "gulp-sass": "^2.3.2", 38 | "gulp-sourcemaps": "^2.1.1", 39 | "gulp-uglify": "^2.0.0", 40 | "gulp-util": "^3.0.7", 41 | "merge": "^1.2.0", 42 | "vinyl-buffer": "^1.0.0", 43 | "vinyl-source-stream": "^1.1.0", 44 | "watchify": "^3.7.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /sass/abstracts/_mixins.scss: -------------------------------------------------------------------------------- 1 | /// Themify mixin 2 | /// @access private 3 | /// @author Hugo Giraudel 4 | /// @param {String} $property - Property to themify 5 | /// @param {String} $key - Key color to use from theme 6 | /// @param {Map} $themes [$themes] - Map of themes to use 7 | @mixin themify($property, $key, $themes: $themes, $colors: $colors) { 8 | // Iterate over the themes 9 | @each $theme, $t in $themes { 10 | // Create a selector (e.g. .theme-unicorn .media`) 11 | .#{$theme} & { 12 | // Output the declaration 13 | #{$property}: map-get($t, $key); 14 | } 15 | } 16 | 17 | @each $color, $c in $colors { 18 | // Create a selector (e.g. .theme-unicorn .media`) 19 | .#{$color} & { 20 | // Output the declaration 21 | #{$property}: map-get($c, $key); 22 | } 23 | } 24 | } 25 | 26 | /// Shorthand to themify color through `themify` mixin 27 | /// @access public 28 | /// @see {mixin} themify 29 | @mixin color($arguments...) { 30 | @include themify('color', $arguments...); 31 | } 32 | 33 | /// Shorthand to themify border-color through `themify` mixin 34 | /// @access public 35 | /// @see {mixin} themify 36 | @mixin border-color($arguments...) { 37 | @include themify('border-color', $arguments...); 38 | } 39 | 40 | /// Shorthand to themify background-color through `themify` mixin 41 | /// @access public 42 | /// @see {mixin} themify 43 | @mixin background-color($arguments...) { 44 | @include themify('background-color', $arguments...); 45 | } 46 | 47 | @mixin glow($arguments...) { 48 | @include themify('box-shadow', $arguments...); 49 | } -------------------------------------------------------------------------------- /sass/abstracts/_variables.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * TYPOGRAPH 3 | */ 4 | $mono-font-stack: ('Consolas', 'Courier New', 'Courier', 'Lucida Sans Typewriter', 'Lucida Typewriter', 'monaco', monospace); 5 | 6 | /** 7 | * COLORS FOR PAGES AND ELEMENTS 8 | */ 9 | $page-bg-color: #EAEDF1 !default; 10 | $text-color: #757575 !default; 11 | $border-color: #eeeeee !default; 12 | $el-bg-color: #fafafa !default; 13 | $el-bg-color-lighten: lighten($el-bg-color, 5%) !default; 14 | $el-bg-color-darken: darken($el-bg-color, 5%) !default; 15 | 16 | $dark-page-bg-color: #5A5D61 !default; 17 | $dark-text-color: #eceff1 !default; 18 | $dark-border-color: #444444 !default; 19 | $dark-el-bg-color: #3A3D41 !default; 20 | $dark-el-bg-color-lighten: lighten($dark-el-bg-color, 5%) !default; 21 | $dark-el-bg-color-darken: darken($dark-el-bg-color, 5%) !default; 22 | 23 | $btn-default-color: #eceff1 !default; 24 | $btn-default-color-darken: darken($btn-default-color, 5%) !default; 25 | 26 | /* 27 | * COLORS FOR USE IN THEMES 28 | */ 29 | $green: #66bb6a !default; 30 | $green-lighten: lighten($green, 5%) !default; 31 | $green-darken: darken($green, 5%) !default; 32 | $green-pastel: lighten($green, 30%) !default; 33 | 34 | $blue: #4fc3f7 !default; 35 | $blue-lighten: lighten($blue, 5%) !default; 36 | $blue-darken: darken($blue, 5%) !default; 37 | $blue-pastel: lighten($blue, 30%) !default; 38 | 39 | $red: #ff5555 !default; 40 | $red-lighten: lighten($red, 5%) !default; 41 | $red-darken: darken($red, 5%) !default; 42 | $red-pastel: lighten($red, 30%) !default; 43 | 44 | $pink: #f06292 !default; 45 | $pink-lighten: lighten($pink, 5%) !default; 46 | $pink-darken: darken($pink, 5%) !default; 47 | $pink-pastel: lighten($pink, 30%) !default; 48 | 49 | $purple: #ba68c8 !default; 50 | $purple-lighten: lighten($purple, 5%) !default; 51 | $purple-darken: darken($purple, 5%) !default; 52 | $purple-pastel: lighten($purple, 30%) !default; 53 | 54 | $cyan: #4dd0e1 !default; 55 | $cyan-lighten: lighten($cyan, 5%) !default; 56 | $cyan-darken: darken($cyan, 5%) !default; 57 | $cyan-pastel: lighten($cyan, 30%) !default; 58 | 59 | $teal: #00bfa5 !default; 60 | $teal-lighten: lighten($teal, 5%) !default; 61 | $teal-darken: darken($teal, 5%) !default; 62 | $teal-pastel: lighten($teal, 55%) !default; 63 | 64 | $yellow: #fbc02d !default; 65 | $yellow-lighten: lighten($yellow, 5%) !default; 66 | $yellow-darken: darken($yellow, 5%) !default; 67 | $yellow-pastel: lighten($yellow, 30%) !default; 68 | 69 | $orange: #ff7043 !default; 70 | $orange-lighten: lighten($orange, 5%) !default; 71 | $orange-darken: darken($orange, 5%) !default; 72 | $orange-pastel: lighten($orange, 30%) !default; 73 | 74 | $primary-color: $teal !default; 75 | $primary-color-lighten: lighten($primary-color, 5%) !default; 76 | $primary-color-darken: darken($primary-color, 5%) !default; 77 | $primary-color-pastel: lighten($primary-color, 30%) !default; 78 | 79 | $themes: ( 80 | 'light': ( 81 | 'bg-color': $page-bg-color, 82 | 'text-color': $text-color, 83 | 'border-color': $border-color, 84 | 'el-bg-color': $el-bg-color, 85 | 'el-bg-color-lighten': $el-bg-color-lighten, 86 | 'el-bg-color-darken': $el-bg-color-darken 87 | ), 88 | 'dark': ( 89 | 'bg-color': $dark-page-bg-color, 90 | 'text-color': $dark-text-color, 91 | 'border-color': $dark-border-color, 92 | 'el-bg-color': $dark-el-bg-color, 93 | 'el-bg-color-lighten': $dark-el-bg-color-lighten, 94 | 'el-bg-color-darken': $dark-el-bg-color-darken 95 | ) 96 | ) !default; 97 | 98 | $colors: ( 99 | 'green': ( 100 | 'primary': $green, 101 | 'lighten': $green-lighten, 102 | 'darken': $green-darken, 103 | 'glow': 0 0 5px $green, 104 | 'pastel': $green-pastel 105 | ), 106 | 'blue': ( 107 | 'primary': $blue, 108 | 'lighten': $blue-lighten, 109 | 'darken': $blue-darken, 110 | 'glow': 0 0 5px $blue, 111 | 'pastel': $blue-pastel 112 | ), 113 | 'red': ( 114 | 'primary': $red, 115 | 'lighten': $red-lighten, 116 | 'darken': $red-darken, 117 | 'glow': 0 0 5px $red, 118 | 'pastel': $red-pastel 119 | ), 120 | 'pink': ( 121 | 'primary': $pink, 122 | 'lighten': $pink-lighten, 123 | 'darken': $pink-darken, 124 | 'glow': 0 0 5px $pink, 125 | 'pastel': $pink-pastel 126 | ), 127 | 'purple': ( 128 | 'primary': $purple, 129 | 'lighten': $purple-lighten, 130 | 'darken': $purple-darken, 131 | 'glow': 0 0 5px $purple, 132 | 'pastel': $purple-pastel 133 | ), 134 | 'cyan': ( 135 | 'primary': $cyan, 136 | 'lighten': $cyan-lighten, 137 | 'darken': $cyan-darken, 138 | 'glow': 0 0 5px $cyan, 139 | 'pastel': $cyan-pastel 140 | ), 141 | 'teal': ( 142 | 'primary': $teal, 143 | 'lighten': $teal-lighten, 144 | 'darken': $teal-darken, 145 | 'glow': 0 0 5px $teal, 146 | 'pastel': $teal-pastel 147 | ), 148 | 'yellow': ( 149 | 'primary': $yellow, 150 | 'lighten': $yellow-lighten, 151 | 'darken': $yellow-darken, 152 | 'glow': 0 0 5px $yellow, 153 | 'pastel': $yellow-pastel 154 | ), 155 | 'orange': ( 156 | 'primary': $orange, 157 | 'lighten': $orange-lighten, 158 | 'darken': $orange-darken, 159 | 'glow': 0 0 5px $orange, 160 | 'pastel': $orange-pastel 161 | ) 162 | ) !default; -------------------------------------------------------------------------------- /sass/base/_base.scss: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | margin: 0; 4 | padding: 0; 5 | width: 100%; 6 | height: 100%; 7 | font-family: $font-stack; 8 | font-size: 100%; 9 | color: $text-color; 10 | } 11 | 12 | body { 13 | background-color: $page-bg-color; 14 | background-image: url('https://source.unsplash.com/daily?music'); 15 | background-size: cover; 16 | background-repeat: no-repeat; 17 | 18 | &.dark { 19 | color: $dark-text-color; 20 | background-color: $dark-page-bg-color; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /sass/base/_reset.scss: -------------------------------------------------------------------------------- 1 | *, 2 | *::before, 3 | *::after { 4 | box-sizing: border-box; 5 | } 6 | 7 | ::-webkit-scrollbar { 8 | width: 9px; 9 | height: 9px; 10 | } 11 | 12 | ::-webkit-scrollbar-track { 13 | background-color: transparent; 14 | } 15 | 16 | ::-webkit-scrollbar-thumb { 17 | background-color: #ddd; 18 | } 19 | 20 | ::-webkit-scrollbar-thumb:hover { 21 | background-color: #ccc; 22 | } 23 | 24 | ::-webkit-scrollbar-thumb:active { 25 | background-color: #bbb; 26 | } 27 | 28 | .dark { 29 | ::-webkit-scrollbar-thumb { 30 | background-color: #555; 31 | } 32 | 33 | ::-webkit-scrollbar-thumb:hover { 34 | background-color: #444; 35 | } 36 | 37 | ::-webkit-scrollbar-thumb:active { 38 | background-color: #333; 39 | } 40 | } -------------------------------------------------------------------------------- /sass/base/_typograph.scss: -------------------------------------------------------------------------------- 1 | $font-stack: ('Rubik', 'Helvetica', 'Segoe UI', sans-serif); 2 | -------------------------------------------------------------------------------- /sass/components/_buttons.scss: -------------------------------------------------------------------------------- 1 | /*--- buttons ---*/ 2 | .btn { 3 | 4 | @include background-color('el-bg-color-darken'); 5 | 6 | display: inline-block; 7 | padding: 8px 10px; 8 | border: 1px solid transparent; 9 | border-radius: 3px; 10 | outline: none; 11 | color: $text-color; 12 | // background-color: $btn-default-color; 13 | text-align: center; 14 | cursor: pointer; 15 | 16 | transition: .3s; 17 | will-change: box-shadow, background-color; 18 | 19 | @extend .shadow-1; 20 | 21 | &:hover, 22 | &:focus { 23 | // background-color: $btn-default-color-darken; 24 | @include background-color('el-bg-color-darken'); 25 | @extend .shadow-2; 26 | } 27 | 28 | &:active { 29 | @extend .shadow-3; 30 | } 31 | 32 | &.btn-primary { 33 | color: white; 34 | @include background-color('primary'); 35 | 36 | &:hover, 37 | &:focus { 38 | @include background-color('lighten'); 39 | } 40 | } 41 | 42 | &.btn-circle { 43 | padding: 0; 44 | width: 50px; 45 | height: 50px; 46 | line-height: 50px; 47 | border-radius: 50%; 48 | 49 | &.btn-large { 50 | font-size: 1.25em; 51 | width: 75px; 52 | height: 75px; 53 | line-height: 75px; 54 | } 55 | 56 | &.btn-small { 57 | font-size: 1em; 58 | width: 35px; 59 | height: 35px; 60 | line-height: 35px; 61 | } 62 | } 63 | 64 | &.btn-circle:hover { 65 | @include background-color('primary'); 66 | color: white; 67 | } 68 | 69 | &.is-on { 70 | // @include border-color('primary'); 71 | @include glow('glow'); 72 | @include color('primary'); 73 | } 74 | 75 | &.is-on:hover { 76 | color: white; 77 | } 78 | 79 | &.btn-color { 80 | display: inline-block; 81 | width: 24px; 82 | height: 24px; 83 | margin: 3px; 84 | box-shadow: none; 85 | 86 | &:hover, 87 | &:focus { 88 | box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.1); 89 | } 90 | } 91 | 92 | } -------------------------------------------------------------------------------- /sass/components/_card.scss: -------------------------------------------------------------------------------- 1 | .card { 2 | 3 | @include background-color('el-bg-color'); 4 | 5 | display: block; 6 | width: 100%; 7 | margin: 0 auto; 8 | border-radius: 3px; 9 | 10 | transition: .2s; 11 | will-change: box-shadow; 12 | 13 | @extend .shadow-2; 14 | 15 | &:hover { 16 | @extend .shadow-4; 17 | } 18 | 19 | & > .card-header { 20 | display: block; 21 | padding: 5px 10px; 22 | border-radius: 3px 3px 0 0; 23 | 24 | .btn-header { 25 | padding: 0; 26 | width: 32px; 27 | height: 32px; 28 | line-height: 32px; 29 | } 30 | } 31 | 32 | & > .card-content {} 33 | 34 | & > .card-footer {} 35 | 36 | } -------------------------------------------------------------------------------- /sass/components/_divider.scss: -------------------------------------------------------------------------------- 1 | .divider { 2 | @extend .no-margin; 3 | display: block; 4 | height: 1px; 5 | border: none; 6 | background-color: rgba(0, 0, 0, 0.04); 7 | border-bottom: 1px solid rgb(255, 255, 255); 8 | } 9 | 10 | .dark { 11 | .divider { 12 | background-color: rgba(0, 0, 0, 0.3); 13 | border-bottom: 1px solid rgba(255, 255, 255, 0.15); 14 | } 15 | } -------------------------------------------------------------------------------- /sass/components/_dropdown.scss: -------------------------------------------------------------------------------- 1 | .dropdown-wrapper { 2 | position: relative; 3 | } 4 | 5 | .dropdown-menu { 6 | z-index: 2; 7 | @extend .shadow-2; 8 | 9 | @include background-color('el-bg-color-lighten'); 10 | @include color('text-color'); 11 | 12 | position: absolute; 13 | right: 0; 14 | top: 120%; 15 | 16 | display: block; 17 | min-width: 50px; 18 | padding: 0; 19 | margin: 0; 20 | list-style: none; 21 | 22 | // background-color: #ffffff; 23 | border-radius: 3px; 24 | 25 | overflow: hidden; 26 | opacity: 0; 27 | visibility: hidden; 28 | 29 | transform-origin: top right; 30 | transform: translateY(-10px); 31 | 32 | transition: 0.4s ease; 33 | 34 | &:hover { 35 | @extend .shadow-3; 36 | } 37 | 38 | &.is-active { 39 | opacity: 1; 40 | visibility: visible; 41 | transform: translateY(0); 42 | } 43 | 44 | &.dropdown-up { 45 | top: -100%; 46 | transform: translateY(10px); 47 | } 48 | 49 | & > .item { 50 | display: block; 51 | width: 100%; 52 | line-height: normal; 53 | 54 | &.divider { 55 | display: block; 56 | height: 1px; 57 | margin: 0; 58 | border: none; 59 | background-color: #eee; 60 | background: linear-gradient(to right, transparent, #eee, transparent); 61 | } 62 | 63 | & > .link { 64 | display: block; 65 | width: 100%; 66 | padding: 12px 8px; 67 | color: #555; 68 | text-decoration: none; 69 | transition: .2s; 70 | 71 | &:hover, 72 | &:focus { 73 | background-color: #fafafa; 74 | } 75 | 76 | &:first-child { 77 | border-radius: 3px 3px 0 0; 78 | } 79 | 80 | &:last-child { 81 | border-radius: 0 0 3px 3px; 82 | } 83 | 84 | & > .icon { 85 | display: inline-block; 86 | margin-right: 5px; 87 | height: 22px; 88 | line-height: 22px; 89 | vertical-align: middle; 90 | } 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /sass/components/_flip-card.scss: -------------------------------------------------------------------------------- 1 | .flip-container { 2 | perspective: 1000; 3 | } 4 | 5 | .flip-container, 6 | .front, 7 | .back { 8 | display: inline-block; 9 | width: 80px; 10 | height: 75px; 11 | position: relative; 12 | top: 25px; 13 | z-index: 1; 14 | } 15 | 16 | .flipper { 17 | position: relative; 18 | transition: 0.6s; 19 | transform-style: preserve-3d; 20 | } 21 | 22 | .flip-container.is-flipped .flipper { 23 | transform: rotateY(180deg); 24 | } 25 | 26 | .front, 27 | .back { 28 | position: absolute; 29 | top: 0; 30 | left: 0; 31 | backface-visibility: hidden; 32 | } 33 | 34 | .front { 35 | z-index: 2; 36 | transform: rotateY(0deg); 37 | } 38 | 39 | .back { 40 | z-index: 1; 41 | transform: rotateY(180deg); 42 | } -------------------------------------------------------------------------------- /sass/components/_icons.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Glyphicons Halflings'; 3 | 4 | src: url('../../fonts/glyphicons-halflings-regular.eot'); 5 | src: url('../../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), 6 | url('../../fonts/glyphicons-halflings-regular.woff') format('woff'), 7 | url('../../fonts/glyphicons-halflings-regular.ttf') format('truetype'), 8 | url('../../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); 9 | } 10 | .icon { 11 | position: relative; 12 | top: 1px; 13 | display: inline-block; 14 | font-family: 'Glyphicons Halflings'; 15 | font-style: normal; 16 | font-weight: normal; 17 | line-height: 1; 18 | 19 | -webkit-font-smoothing: antialiased; 20 | -moz-osx-font-smoothing: grayscale; 21 | } 22 | .icon-headphones:before { 23 | content: "\e035"; 24 | } 25 | .icon-cog:before { 26 | content: "\e019"; 27 | } 28 | .icon-music:before { 29 | content: "\e002"; 30 | } 31 | .icon-repeat:before { 32 | content: "\e030"; 33 | } 34 | .icon-chevron-left:before { 35 | content: "\e079"; 36 | } 37 | .icon-chevron-right:before { 38 | content: "\e080"; 39 | } 40 | .icon-play:before { 41 | content: "\e072"; 42 | } 43 | .icon-pause:before { 44 | content: "\e073"; 45 | } 46 | .icon-random:before { 47 | content: "\e110"; 48 | } 49 | .icon-volume-down:before { 50 | content: "\e037"; 51 | } 52 | .icon-volume-up:before { 53 | content: "\e038"; 54 | } -------------------------------------------------------------------------------- /sass/components/_input-range.scss: -------------------------------------------------------------------------------- 1 | .range { 2 | @include background-color('el-bg-color-darken'); 3 | 4 | width: 100%; 5 | height: 6px; 6 | position: relative; 7 | top: -3px; 8 | border: none; 9 | outline: none; 10 | border-radius: 100px; 11 | box-shadow: inset 0 1px 1px 0 rgba(25, 25, 25, 0.1); 12 | transition: .2s; 13 | 14 | -webkit-appearance: none; 15 | -webkit-tap-highlight-color: rgba(255, 255, 255, 0); 16 | 17 | &:hover { 18 | // @include background-color('el-bg-color-lighten'); 19 | } 20 | 21 | &::-moz-range-track, 22 | &::-ms-fill-lower, 23 | &::-ms-fill-upper, 24 | &::-ms-track { 25 | border: none; 26 | color: transparent; 27 | background-color: transparent; 28 | } 29 | 30 | &::-ms-tooltip { 31 | display: none; 32 | } 33 | 34 | &::-webkit-slider-thumb { 35 | 36 | @include background-color('primary'); 37 | 38 | -webkit-appearance: none; 39 | width: 18px; 40 | height: 18px; 41 | border: none; 42 | border-radius: 50%; 43 | will-change: transform; 44 | transition: .2s; 45 | 46 | } 47 | 48 | &:active::-webkit-slider-thumb { 49 | transform: scale(1.2); 50 | box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.1); 51 | } 52 | 53 | &::-moz-range-thumb { 54 | 55 | @include background-color('primary'); 56 | 57 | width: 18px; 58 | height: 18px; 59 | border: none; 60 | border-radius: 50%; 61 | will-change: transform; 62 | transition: .3s; 63 | 64 | } 65 | 66 | &:active::-moz-range-thumb { 67 | transform: scale(1.2); 68 | } 69 | 70 | &::-ms-thumb { 71 | 72 | @include background-color('primary'); 73 | 74 | width: 18px; 75 | height: 18px; 76 | border: none; 77 | border-radius: 50%; 78 | will-change: transform; 79 | transition: .3s; 80 | 81 | } 82 | 83 | &:active::-ms-thumb { 84 | transform: scale(1.2); 85 | } 86 | 87 | } -------------------------------------------------------------------------------- /sass/components/_list.scss: -------------------------------------------------------------------------------- 1 | .play-list { 2 | list-style: none; 3 | width: 100%; 4 | margin: 0 auto; 5 | padding: 0; 6 | 7 | & > .list-item { 8 | padding: 8px; 9 | transition: background-color .2s; 10 | font-size: 0.8em; 11 | 12 | &:hover { 13 | background-color: rgba(0, 0, 0, 0.05); 14 | } 15 | 16 | &.is-active { 17 | background-color: rgba(0, 0, 0, 0.05); 18 | } 19 | 20 | & > .list-icon { 21 | 22 | } 23 | 24 | & > .btn { 25 | padding: 0; 26 | width: 30px; 27 | height: 30px; 28 | line-height: 30px; 29 | margin-right: 10px; 30 | } 31 | } 32 | } 33 | 34 | .dark { 35 | .play-list { 36 | & > .lit-item { 37 | &.is-active { 38 | background-color: rgba(0, 0, 0, 0.1); 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /sass/components/_loading.scss: -------------------------------------------------------------------------------- 1 | .loading { 2 | margin: 4px; 3 | display: none; 4 | } 5 | 6 | .loading.show { 7 | display: block; 8 | 9 | -webkit-animation: blink 1s ease-in-out 0s infinite alternate; 10 | -moz-animation: blink 1s ease-in-out 0s infinite alternate; 11 | animation: blink 1s ease-in-out 0s infinite alternate; 12 | } -------------------------------------------------------------------------------- /sass/components/_sound-waves.scss: -------------------------------------------------------------------------------- 1 | .sound-wave { 2 | display: inline-block; 3 | position: relative; 4 | margin-left: 10px; 5 | vertical-align: middle; 6 | } 7 | 8 | .sound-wave .bar { 9 | position: absolute; 10 | height: 2px; 11 | width: 6px; 12 | } 13 | 14 | .sound-wave.is-active .bar { 15 | -webkit-animation: sound 0.5s linear infinite alternate; 16 | -moz-animation: sound 0.5s linear infinite alternate; 17 | animation: sound 0.5s linear infinite alternate; 18 | } 19 | 20 | .sound-wave .bar:nth-child(1) { 21 | left: 0; 22 | -webkit-animation-delay: 0s; 23 | -moz-animation-delay: 0s; 24 | animation-delay: 0s; 25 | } 26 | 27 | .sound-wave .bar:nth-child(2) { 28 | left: 8px; 29 | -webkit-animation-delay: 0.5s; 30 | -moz-animation-delay: 0.5s; 31 | animation-delay: 0.5s; 32 | } 33 | 34 | .sound-wave .bar:nth-child(3) { 35 | left: 16px; 36 | -webkit-animation-delay: 0.75s; 37 | -moz-animation-delay: 0.75s; 38 | animation-delay: 0.75s; 39 | } 40 | 41 | @-webkit-keyframes sound { 42 | 0% { 43 | height: 4px; 44 | top: 0; 45 | background: #66CCFF; 46 | } 47 | 100% { 48 | height: 10px; 49 | top: -6px; 50 | background: #CC99FF; 51 | } 52 | } 53 | 54 | @keyframes sound { 55 | 0% { 56 | height: 2px; 57 | top: 0; 58 | background: #66CCFF; 59 | } 60 | 100% { 61 | height: 10px; 62 | top: -8px; 63 | background: #CC99FF; 64 | } 65 | } -------------------------------------------------------------------------------- /sass/components/_table.scss: -------------------------------------------------------------------------------- 1 | .table { 2 | width: 100%; 3 | border: none; 4 | background-color: transparent; 5 | border-collapse: collapse; 6 | } 7 | 8 | .table td { 9 | padding: 4px; 10 | } -------------------------------------------------------------------------------- /sass/layouts/_player.scss: -------------------------------------------------------------------------------- 1 | .container { 2 | position: fixed; 3 | top: 8%; 4 | right: 0; 5 | bottom: 0; 6 | left: 0; 7 | margin: auto; 8 | display: block; 9 | width: 80%; 10 | height: auto; 11 | } 12 | 13 | .logo { 14 | font-size: 1.5em; 15 | @include color('primary'); 16 | } 17 | 18 | .music-name { 19 | @include background-color('el-bg-color-darken'); 20 | 21 | display: block; 22 | padding: 8px; 23 | margin-top: 3px; 24 | border-radius: 3px; 25 | overflow: hidden; 26 | white-space: nowrap; 27 | text-overflow: ellipsis; 28 | // background-color: rgba(0, 0, 0, 0.04); 29 | box-shadow: inset 0 1px 2px 0 rgba(0, 0, 0, 0.1); 30 | } 31 | 32 | .play-list-wrap { 33 | width: 100%; 34 | height: 200px; 35 | max-height: 200px; 36 | overflow-y: auto; 37 | } 38 | 39 | .player-wrap { 40 | display: block; 41 | width: 100%; 42 | } -------------------------------------------------------------------------------- /sass/layouts/_user-settings.scss: -------------------------------------------------------------------------------- 1 | .dropdown-menu.user-settings { 2 | width: 120px; 3 | } 4 | 5 | .theme, 6 | .color { 7 | display: block; 8 | width: 100%; 9 | padding: 0; 10 | margin: 0; 11 | list-style: none; 12 | } 13 | 14 | .theme { 15 | 16 | .theme-item-btn { 17 | 18 | display: block; 19 | width: 100%; 20 | height: 40px; 21 | line-height: 40px; 22 | text-align: center; 23 | text-decoration: none; 24 | color: inherit; 25 | cursor: pointer; 26 | transition: .3s; 27 | 28 | &:hover { 29 | background: rgba(0, 0, 0, 0.05); 30 | } 31 | 32 | } 33 | 34 | } 35 | 36 | .color { 37 | 38 | & > .color-item { 39 | margin: 0; 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /sass/main.scss: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | 3 | /* 4 | IMPORT ORDER 5 | 1 - abstracts/ 6 | 2 - vendors/ 7 | 3 - utils/ 8 | 4 - base/ 9 | 5 - layout/ 10 | 6 - components/ 11 | 7 - pages/ 12 | 8 - themes/ 13 | */ 14 | 15 | @import 16 | 'abstracts/variables.scss', 17 | 'abstracts/mixins.scss'; 18 | 19 | @import 20 | 'vendors/normalize.scss'; 21 | 22 | @import 23 | 'utils/animations.scss', 24 | 'utils/colors.scss', 25 | 'utils/helpers.scss', 26 | 'utils/shadows.scss'; 27 | 28 | @import 29 | 'base/typograph.scss', 30 | 'base/reset.scss', 31 | 'base/base.scss'; 32 | 33 | @import 34 | 'layouts/player.scss', 35 | 'layouts/user-settings.scss'; 36 | 37 | @import 38 | 'components/buttons.scss', 39 | 'components/card.scss', 40 | 'components/dropdown.scss', 41 | 'components/flip-card.scss', 42 | 'components/icons.scss', 43 | 'components/input-range.scss', 44 | 'components/list.scss', 45 | 'components/loading.scss', 46 | 'components/sound-waves.scss', 47 | 'components/divider.scss', 48 | 'components/table.scss'; -------------------------------------------------------------------------------- /sass/utils/_animations.scss: -------------------------------------------------------------------------------- 1 | @-webkit-keyframes blink { 2 | 0% { opacity: 0; } 3 | 50% { opacity: 1; } 4 | 100% { opacity: 0; } 5 | } 6 | 7 | @keyframes blink { 8 | 0% { opacity: 0; } 9 | 50% { opacity: 1; } 10 | 100% { opacity: 0; } 11 | } -------------------------------------------------------------------------------- /sass/utils/_colors.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Generating classes to apply colors to elements 3 | E.G: .bg-blue, .text-blue 4 | */ 5 | @each $color, $c in $colors { 6 | 7 | .bg-#{$color} { 8 | background-color: map-get($c, 'primary') !important; 9 | } 10 | .text-#{$color} { 11 | color: map-get($c, 'primary') !important; 12 | } 13 | 14 | .bg-#{$color}-lighten { 15 | background-color: map-get($c, 'lighten') !important; 16 | } 17 | .text-#{$color}-lighten { 18 | color: map-get($c, 'lighten') !important; 19 | } 20 | 21 | .bg-#{$color}-darken { 22 | background-color: map-get($c, 'darken') !important; 23 | } 24 | .text-#{$color}-darken { 25 | color: map-get($c, 'darken') !important; 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /sass/utils/_helpers.scss: -------------------------------------------------------------------------------- 1 | .right { 2 | float: right !important; 3 | } 4 | 5 | .left { 6 | float: left !important; 7 | } 8 | 9 | .clearfix::after { 10 | content: ''; 11 | display: table; 12 | clear: both !important; 13 | } 14 | 15 | .inline { 16 | display: inline !important; 17 | } 18 | 19 | .inline-block { 20 | display: inline-block !important; 21 | } 22 | 23 | .block { 24 | display: block !important; 25 | } 26 | 27 | .half-width { 28 | width: 50% !important; 29 | } 30 | 31 | .one-third-width { 32 | width: 33.3333% !important; 33 | } 34 | 35 | .text-right { 36 | text-align: right !important; 37 | } 38 | 39 | .text-center { 40 | text-align: center !important; 41 | } 42 | 43 | .text-left { 44 | text-align: left !important; 45 | } 46 | 47 | .text-justify { 48 | text-align: justify !important; 49 | } 50 | 51 | .no-margin { 52 | margin: 0 !important; 53 | } 54 | 55 | .no-padding { 56 | padding: 0 !important; 57 | } 58 | 59 | .valign-middle { 60 | vertical-align: middle !important; 61 | } 62 | 63 | .valign-top { 64 | vertical-align: top !important; 65 | } 66 | 67 | .valign-bottom { 68 | vertical-align: bottom !important; 69 | } 70 | 71 | .valign-base { 72 | vertical-align: baseline !important; 73 | } 74 | 75 | .m-0 { 76 | margin: 0!important; 77 | } 78 | 79 | .m-t-0 { 80 | margin-top: 0!important; 81 | } 82 | 83 | .m-b-0 { 84 | margin-bottom: 0!important; 85 | } 86 | 87 | .m-l-0 { 88 | margin-left: 0!important; 89 | } 90 | 91 | .m-r-0 { 92 | margin-right: 0!important; 93 | } 94 | 95 | .m-5 { 96 | margin: 5px!important; 97 | } 98 | 99 | .m-t-5 { 100 | margin-top: 5px!important; 101 | } 102 | 103 | .m-b-5 { 104 | margin-bottom: 5px!important; 105 | } 106 | 107 | .m-l-5 { 108 | margin-left: 5px!important; 109 | } 110 | 111 | .m-r-5 { 112 | margin-right: 5px!important; 113 | } 114 | 115 | .m-10 { 116 | margin: 10px!important; 117 | } 118 | 119 | .m-t-10 { 120 | margin-top: 10px!important; 121 | } 122 | 123 | .m-b-10 { 124 | margin-bottom: 10px!important; 125 | } 126 | 127 | .m-l-10 { 128 | margin-left: 10px!important; 129 | } 130 | 131 | .m-r-10 { 132 | margin-right: 10px!important; 133 | } 134 | 135 | .m-15 { 136 | margin: 15px!important; 137 | } 138 | 139 | .m-t-15 { 140 | margin-top: 15px!important; 141 | } 142 | 143 | .m-b-15 { 144 | margin-bottom: 15px!important; 145 | } 146 | 147 | .m-l-15 { 148 | margin-left: 15px!important; 149 | } 150 | 151 | .m-r-15 { 152 | margin-right: 15px!important; 153 | } 154 | 155 | .m-20 { 156 | margin: 20px!important; 157 | } 158 | 159 | .m-t-20 { 160 | margin-top: 20px!important; 161 | } 162 | 163 | .m-b-20 { 164 | margin-bottom: 20px!important; 165 | } 166 | 167 | .m-l-20 { 168 | margin-left: 20px!important; 169 | } 170 | 171 | .m-r-20 { 172 | margin-right: 20px!important; 173 | } 174 | 175 | .m-25 { 176 | margin: 25px!important; 177 | } 178 | 179 | .m-t-25 { 180 | margin-top: 25px!important; 181 | } 182 | 183 | .m-b-25 { 184 | margin-bottom: 25px!important; 185 | } 186 | 187 | .m-l-25 { 188 | margin-left: 25px!important; 189 | } 190 | 191 | .m-r-25 { 192 | margin-right: 25px!important; 193 | } 194 | 195 | .m-30 { 196 | margin: 30px!important; 197 | } 198 | 199 | .m-t-30 { 200 | margin-top: 30px!important; 201 | } 202 | 203 | .m-b-30 { 204 | margin-bottom: 30px!important; 205 | } 206 | 207 | .m-l-30 { 208 | margin-left: 30px!important; 209 | } 210 | 211 | .m-r-30 { 212 | margin-right: 30px!important; 213 | } 214 | 215 | .p-0 { 216 | padding: 0!important; 217 | } 218 | 219 | .p-t-0 { 220 | padding-top: 0!important; 221 | } 222 | 223 | .p-b-0 { 224 | padding-bottom: 0!important; 225 | } 226 | 227 | .p-l-0 { 228 | padding-left: 0!important; 229 | } 230 | 231 | .p-r-0 { 232 | padding-right: 0!important; 233 | } 234 | 235 | .p-5 { 236 | padding: 5px!important; 237 | } 238 | 239 | .p-t-5 { 240 | padding-top: 5px!important; 241 | } 242 | 243 | .p-b-5 { 244 | padding-bottom: 5px!important; 245 | } 246 | 247 | .p-l-5 { 248 | padding-left: 5px!important; 249 | } 250 | 251 | .p-r-5 { 252 | padding-right: 5px!important; 253 | } 254 | 255 | .p-10 { 256 | padding: 10px!important; 257 | } 258 | 259 | .p-t-10 { 260 | padding-top: 10px!important; 261 | } 262 | 263 | .p-b-10 { 264 | padding-bottom: 10px!important; 265 | } 266 | 267 | .p-l-10 { 268 | padding-left: 10px!important; 269 | } 270 | 271 | .p-r-10 { 272 | padding-right: 10px!important; 273 | } 274 | 275 | .p-15 { 276 | padding: 15px!important; 277 | } 278 | 279 | .p-t-15 { 280 | padding-top: 15px!important; 281 | } 282 | 283 | .p-b-15 { 284 | padding-bottom: 15px!important; 285 | } 286 | 287 | .p-l-15 { 288 | padding-left: 15px!important; 289 | } 290 | 291 | .p-r-15 { 292 | padding-right: 15px!important; 293 | } 294 | 295 | .p-20 { 296 | padding: 20px!important; 297 | } 298 | 299 | .p-t-20 { 300 | padding-top: 20px!important; 301 | } 302 | 303 | .p-b-20 { 304 | padding-bottom: 20px!important; 305 | } 306 | 307 | .p-l-20 { 308 | padding-left: 20px!important; 309 | } 310 | 311 | .p-r-20 { 312 | padding-right: 20px!important; 313 | } 314 | 315 | .p-25 { 316 | padding: 25px!important; 317 | } 318 | 319 | .p-t-25 { 320 | padding-top: 25px!important; 321 | } 322 | 323 | .p-b-25 { 324 | padding-bottom: 25px!important; 325 | } 326 | 327 | .p-l-25 { 328 | padding-left: 25px!important; 329 | } 330 | 331 | .p-r-25 { 332 | padding-right: 25px!important; 333 | } 334 | 335 | .p-30 { 336 | padding: 30px!important; 337 | } 338 | 339 | .p-t-30 { 340 | padding-top: 30px!important; 341 | } 342 | 343 | .p-b-30 { 344 | padding-bottom: 30px!important; 345 | } 346 | 347 | .p-l-30 { 348 | padding-left: 30px!important; 349 | } 350 | 351 | .p-r-30 { 352 | padding-right: 30px!important; 353 | } 354 | 355 | .f-8 { 356 | font-size: 8px!important; 357 | } 358 | 359 | .f-9 { 360 | font-size: 9px!important; 361 | } 362 | 363 | .f-10 { 364 | font-size: 10px!important; 365 | } 366 | 367 | .f-11 { 368 | font-size: 11px!important; 369 | } 370 | 371 | .f-12 { 372 | font-size: 12px!important; 373 | } 374 | 375 | .f-13 { 376 | font-size: 13px!important; 377 | } 378 | 379 | .f-14 { 380 | font-size: 14px!important; 381 | } 382 | 383 | .f-15 { 384 | font-size: 15px!important; 385 | } 386 | 387 | .f-16 { 388 | font-size: 16px!important; 389 | } 390 | 391 | .f-17 { 392 | font-size: 17px!important; 393 | } 394 | 395 | .f-18 { 396 | font-size: 18px!important; 397 | } 398 | 399 | .f-19 { 400 | font-size: 19px!important; 401 | } 402 | 403 | .f-20 { 404 | font-size: 20px!important; 405 | } 406 | 407 | .f-300 { 408 | font-weight: 300!important; 409 | } 410 | 411 | .f-400 { 412 | font-weight: 400!important; 413 | } 414 | 415 | .f-500 { 416 | font-weight: 500!important; 417 | } 418 | 419 | .f-700 { 420 | font-weight: 700!important; 421 | } 422 | 423 | .close,body { 424 | font-weight: 400 425 | } 426 | 427 | .p-relative { 428 | position: relative!important; 429 | } 430 | 431 | .p-absolute { 432 | position: absolute!important; 433 | } 434 | 435 | .p-fixed { 436 | position: fixed!important; 437 | } 438 | 439 | .p-static { 440 | position: static!important; 441 | } 442 | 443 | #main,.h-inner,.hi-trigger,body { 444 | position: relative 445 | } 446 | 447 | .o-hidden { 448 | overflow: hidden!important; 449 | } 450 | 451 | .o-visible { 452 | overflow: visible!important; 453 | } 454 | 455 | .no-shadow { 456 | box-shadow: none !important; 457 | } 458 | 459 | .is-timer { 460 | font-family: $mono-font-stack; 461 | } -------------------------------------------------------------------------------- /sass/utils/_shadows.scss: -------------------------------------------------------------------------------- 1 | .shadow-1 { 2 | box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.075), 3 | 0 1px 3px 0 rgba(0, 0, 0, 0.1); 4 | } 5 | .shadow-2 { 6 | box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.075), 7 | 0 3px 4px 0 rgba(0, 0, 0, 0.1); 8 | } 9 | .shadow-3 { 10 | box-shadow: 0 1px 8px 0 rgba(0, 0, 0, 0.075), 11 | 0 3px 12px 0 rgba(0, 0, 0, 0.1); 12 | } 13 | .shadow-4 { 14 | box-shadow: 0 3px 14px 0 rgba(0, 0, 0, 0.075), 15 | 0 4px 20px 0 rgba(0, 0, 0, 0.1); 16 | } -------------------------------------------------------------------------------- /sass/vendors/_normalize.scss: -------------------------------------------------------------------------------- 1 | /*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /** 4 | * 1. Change the default font family in all browsers (opinionated). 5 | * 2. Correct the line height in all browsers. 6 | * 3. Prevent adjustments of font size after orientation changes in 7 | * IE on Windows Phone and in iOS. 8 | */ 9 | 10 | /* Document 11 | ========================================================================== */ 12 | 13 | html { 14 | font-family: sans-serif; /* 1 */ 15 | line-height: 1.15; /* 2 */ 16 | -ms-text-size-adjust: 100%; /* 3 */ 17 | -webkit-text-size-adjust: 100%; /* 3 */ 18 | } 19 | 20 | /* Sections 21 | ========================================================================== */ 22 | 23 | /** 24 | * Remove the margin in all browsers (opinionated). 25 | */ 26 | 27 | body { 28 | margin: 0; 29 | } 30 | 31 | /** 32 | * Add the correct display in IE 9-. 33 | */ 34 | 35 | article, 36 | aside, 37 | footer, 38 | header, 39 | nav, 40 | section { 41 | display: block; 42 | } 43 | 44 | /** 45 | * Correct the font size and margin on `h1` elements within `section` and 46 | * `article` contexts in Chrome, Firefox, and Safari. 47 | */ 48 | 49 | h1 { 50 | font-size: 2em; 51 | margin: 0.67em 0; 52 | } 53 | 54 | /* Grouping content 55 | ========================================================================== */ 56 | 57 | /** 58 | * Add the correct display in IE 9-. 59 | * 1. Add the correct display in IE. 60 | */ 61 | 62 | figcaption, 63 | figure, 64 | main { /* 1 */ 65 | display: block; 66 | } 67 | 68 | /** 69 | * Add the correct margin in IE 8. 70 | */ 71 | 72 | figure { 73 | margin: 1em 40px; 74 | } 75 | 76 | /** 77 | * 1. Add the correct box sizing in Firefox. 78 | * 2. Show the overflow in Edge and IE. 79 | */ 80 | 81 | hr { 82 | box-sizing: content-box; /* 1 */ 83 | height: 0; /* 1 */ 84 | overflow: visible; /* 2 */ 85 | } 86 | 87 | /** 88 | * 1. Correct the inheritance and scaling of font size in all browsers. 89 | * 2. Correct the odd `em` font sizing in all browsers. 90 | */ 91 | 92 | pre { 93 | font-family: monospace, monospace; /* 1 */ 94 | font-size: 1em; /* 2 */ 95 | } 96 | 97 | /* Text-level semantics 98 | ========================================================================== */ 99 | 100 | /** 101 | * 1. Remove the gray background on active links in IE 10. 102 | * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. 103 | */ 104 | 105 | a { 106 | background-color: transparent; /* 1 */ 107 | -webkit-text-decoration-skip: objects; /* 2 */ 108 | } 109 | 110 | /** 111 | * Remove the outline on focused links when they are also active or hovered 112 | * in all browsers (opinionated). 113 | */ 114 | 115 | a:active, 116 | a:hover { 117 | outline-width: 0; 118 | } 119 | 120 | /** 121 | * 1. Remove the bottom border in Firefox 39-. 122 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 123 | */ 124 | 125 | abbr[title] { 126 | border-bottom: none; /* 1 */ 127 | text-decoration: underline; /* 2 */ 128 | text-decoration: underline dotted; /* 2 */ 129 | } 130 | 131 | /** 132 | * Prevent the duplicate application of `bolder` by the next rule in Safari 6. 133 | */ 134 | 135 | b, 136 | strong { 137 | font-weight: inherit; 138 | } 139 | 140 | /** 141 | * Add the correct font weight in Chrome, Edge, and Safari. 142 | */ 143 | 144 | b, 145 | strong { 146 | font-weight: bolder; 147 | } 148 | 149 | /** 150 | * 1. Correct the inheritance and scaling of font size in all browsers. 151 | * 2. Correct the odd `em` font sizing in all browsers. 152 | */ 153 | 154 | code, 155 | kbd, 156 | samp { 157 | font-family: monospace, monospace; /* 1 */ 158 | font-size: 1em; /* 2 */ 159 | } 160 | 161 | /** 162 | * Add the correct font style in Android 4.3-. 163 | */ 164 | 165 | dfn { 166 | font-style: italic; 167 | } 168 | 169 | /** 170 | * Add the correct background and color in IE 9-. 171 | */ 172 | 173 | mark { 174 | background-color: #ff0; 175 | color: #000; 176 | } 177 | 178 | /** 179 | * Add the correct font size in all browsers. 180 | */ 181 | 182 | small { 183 | font-size: 80%; 184 | } 185 | 186 | /** 187 | * Prevent `sub` and `sup` elements from affecting the line height in 188 | * all browsers. 189 | */ 190 | 191 | sub, 192 | sup { 193 | font-size: 75%; 194 | line-height: 0; 195 | position: relative; 196 | vertical-align: baseline; 197 | } 198 | 199 | sub { 200 | bottom: -0.25em; 201 | } 202 | 203 | sup { 204 | top: -0.5em; 205 | } 206 | 207 | /* Embedded content 208 | ========================================================================== */ 209 | 210 | /** 211 | * Add the correct display in IE 9-. 212 | */ 213 | 214 | audio, 215 | video { 216 | display: inline-block; 217 | } 218 | 219 | /** 220 | * Add the correct display in iOS 4-7. 221 | */ 222 | 223 | audio:not([controls]) { 224 | display: none; 225 | height: 0; 226 | } 227 | 228 | /** 229 | * Remove the border on images inside links in IE 10-. 230 | */ 231 | 232 | img { 233 | border-style: none; 234 | } 235 | 236 | /** 237 | * Hide the overflow in IE. 238 | */ 239 | 240 | svg:not(:root) { 241 | overflow: hidden; 242 | } 243 | 244 | /* Forms 245 | ========================================================================== */ 246 | 247 | /** 248 | * 1. Change the font styles in all browsers (opinionated). 249 | * 2. Remove the margin in Firefox and Safari. 250 | */ 251 | 252 | button, 253 | input, 254 | optgroup, 255 | select, 256 | textarea { 257 | font-family: sans-serif; /* 1 */ 258 | font-size: 100%; /* 1 */ 259 | line-height: 1.15; /* 1 */ 260 | margin: 0; /* 2 */ 261 | } 262 | 263 | /** 264 | * Show the overflow in IE. 265 | * 1. Show the overflow in Edge. 266 | */ 267 | 268 | button, 269 | input { /* 1 */ 270 | overflow: visible; 271 | } 272 | 273 | /** 274 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 275 | * 1. Remove the inheritance of text transform in Firefox. 276 | */ 277 | 278 | button, 279 | select { /* 1 */ 280 | text-transform: none; 281 | } 282 | 283 | /** 284 | * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` 285 | * controls in Android 4. 286 | * 2. Correct the inability to style clickable types in iOS and Safari. 287 | */ 288 | 289 | button, 290 | html [type="button"], /* 1 */ 291 | [type="reset"], 292 | [type="submit"] { 293 | -webkit-appearance: button; /* 2 */ 294 | } 295 | 296 | /** 297 | * Remove the inner border and padding in Firefox. 298 | */ 299 | 300 | button::-moz-focus-inner, 301 | [type="button"]::-moz-focus-inner, 302 | [type="reset"]::-moz-focus-inner, 303 | [type="submit"]::-moz-focus-inner { 304 | border-style: none; 305 | padding: 0; 306 | } 307 | 308 | /** 309 | * Restore the focus styles unset by the previous rule. 310 | */ 311 | 312 | button:-moz-focusring, 313 | [type="button"]:-moz-focusring, 314 | [type="reset"]:-moz-focusring, 315 | [type="submit"]:-moz-focusring { 316 | outline: 1px dotted ButtonText; 317 | } 318 | 319 | /** 320 | * Change the border, margin, and padding in all browsers (opinionated). 321 | */ 322 | 323 | fieldset { 324 | border: 1px solid #c0c0c0; 325 | margin: 0 2px; 326 | padding: 0.35em 0.625em 0.75em; 327 | } 328 | 329 | /** 330 | * 1. Correct the text wrapping in Edge and IE. 331 | * 2. Correct the color inheritance from `fieldset` elements in IE. 332 | * 3. Remove the padding so developers are not caught out when they zero out 333 | * `fieldset` elements in all browsers. 334 | */ 335 | 336 | legend { 337 | box-sizing: border-box; /* 1 */ 338 | color: inherit; /* 2 */ 339 | display: table; /* 1 */ 340 | max-width: 100%; /* 1 */ 341 | padding: 0; /* 3 */ 342 | white-space: normal; /* 1 */ 343 | } 344 | 345 | /** 346 | * 1. Add the correct display in IE 9-. 347 | * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. 348 | */ 349 | 350 | progress { 351 | display: inline-block; /* 1 */ 352 | vertical-align: baseline; /* 2 */ 353 | } 354 | 355 | /** 356 | * Remove the default vertical scrollbar in IE. 357 | */ 358 | 359 | textarea { 360 | overflow: auto; 361 | } 362 | 363 | /** 364 | * 1. Add the correct box sizing in IE 10-. 365 | * 2. Remove the padding in IE 10-. 366 | */ 367 | 368 | [type="checkbox"], 369 | [type="radio"] { 370 | box-sizing: border-box; /* 1 */ 371 | padding: 0; /* 2 */ 372 | } 373 | 374 | /** 375 | * Correct the cursor style of increment and decrement buttons in Chrome. 376 | */ 377 | 378 | [type="number"]::-webkit-inner-spin-button, 379 | [type="number"]::-webkit-outer-spin-button { 380 | height: auto; 381 | } 382 | 383 | /** 384 | * 1. Correct the odd appearance in Chrome and Safari. 385 | * 2. Correct the outline style in Safari. 386 | */ 387 | 388 | [type="search"] { 389 | -webkit-appearance: textfield; /* 1 */ 390 | outline-offset: -2px; /* 2 */ 391 | } 392 | 393 | /** 394 | * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. 395 | */ 396 | 397 | [type="search"]::-webkit-search-cancel-button, 398 | [type="search"]::-webkit-search-decoration { 399 | -webkit-appearance: none; 400 | } 401 | 402 | /** 403 | * 1. Correct the inability to style clickable types in iOS and Safari. 404 | * 2. Change font properties to `inherit` in Safari. 405 | */ 406 | 407 | ::-webkit-file-upload-button { 408 | -webkit-appearance: button; /* 1 */ 409 | font: inherit; /* 2 */ 410 | } 411 | 412 | /* Interactive 413 | ========================================================================== */ 414 | 415 | /* 416 | * Add the correct display in IE 9-. 417 | * 1. Add the correct display in Edge, IE, and Firefox. 418 | */ 419 | 420 | details, /* 1 */ 421 | menu { 422 | display: block; 423 | } 424 | 425 | /* 426 | * Add the correct display in all browsers. 427 | */ 428 | 429 | summary { 430 | display: list-item; 431 | } 432 | 433 | /* Scripting 434 | ========================================================================== */ 435 | 436 | /** 437 | * Add the correct display in IE 9-. 438 | */ 439 | 440 | canvas { 441 | display: inline-block; 442 | } 443 | 444 | /** 445 | * Add the correct display in IE. 446 | */ 447 | 448 | template { 449 | display: none; 450 | } 451 | 452 | /* Hidden 453 | ========================================================================== */ 454 | 455 | /** 456 | * Add the correct display in IE 10-. 457 | */ 458 | 459 | [hidden] { 460 | display: none; 461 | } 462 | -------------------------------------------------------------------------------- /src/js/components/dropdown.js: -------------------------------------------------------------------------------- 1 | var toggles = document.querySelectorAll('.dropdown-toggle'); 2 | var dropdowns = []; 3 | 4 | var hasClass = function (el, cl) { 5 | return (el.classList.toString().indexOf(cl) > -1) ? true : false; 6 | } 7 | 8 | if (toggles) { 9 | toggles.forEach(function (toggle) { 10 | toggle.addEventListener('click', function (e) { 11 | 12 | e.stopPropagation(); 13 | 14 | var target = this.getAttribute('data-dropdown'); 15 | if (!target) return false; 16 | 17 | var dropdown = document.querySelector('#' + target); 18 | if (!dropdown) return false; 19 | 20 | if (hasClass(dropdown, 'is-active')) { 21 | dropdown.classList.remove('is-active'); 22 | } else { 23 | dropdown.classList.add('is-active'); 24 | dropdowns.push(dropdown); 25 | dropdown.addEventListener('click', function (e) { 26 | e.stopPropagation(); 27 | }, false); 28 | } 29 | 30 | }, false); 31 | }); 32 | 33 | document.body.addEventListener('click', function () { 34 | 35 | dropdowns.forEach(function (dropdown) { 36 | if (hasClass(dropdown, 'is-active')) { 37 | dropdown.classList.remove('is-active'); 38 | dropdowns.splice(dropdowns.indexOf(dropdown), 1); 39 | } 40 | }); 41 | 42 | }, false); 43 | 44 | } -------------------------------------------------------------------------------- /src/js/components/player.js: -------------------------------------------------------------------------------- 1 | var timeHelper = require('../helpers/time'); 2 | 3 | var audio = document.querySelector("#player"), 4 | btnPlay = document.querySelector("#btn-play"), 5 | btnPause = document.querySelector("#btn-pause"), 6 | btnPrev = document.querySelector("#prev"), 7 | btnNext = document.querySelector("#next"), 8 | btnRepeat = document.querySelector("#repeat"), 9 | btnRandom = document.querySelector("#random"), 10 | volumeControl = document.querySelector("#volume"), 11 | timeLine = document.querySelector("#timeline"), 12 | musicTimeCount = document.querySelector("#time-count"), 13 | musicTime = document.querySelector("#time"), 14 | musicName = document.querySelector("#music-name"), 15 | playListElement = document.querySelector("#play-list"), 16 | loading = document.querySelector("#loading-music"), 17 | flip = document.querySelector("#flip-container"), 18 | rd = new FileReader(); 19 | 20 | var Player = { 21 | currentTrack : 0, 22 | isPlaying : false, 23 | isRepeating : false, 24 | isRandomized : false, 25 | playList : [] 26 | }; 27 | 28 | var setPlayList = function (music) { 29 | Player.playList.push(music); 30 | } 31 | 32 | var activateListItem = function (id) { 33 | document.querySelector("#list-item-" + id).classList.add("is-active"); 34 | document.querySelector("#list-icon-" + id).classList.add("is-active"); 35 | } 36 | 37 | var inactivateListItem = function (id) { 38 | document.querySelector("#list-item-" + id).classList.remove("is-active"); 39 | document.querySelector("#list-icon-" + id).classList.remove("is-active"); 40 | } 41 | 42 | var clearPlayList = function () { 43 | Player.playList = []; 44 | } 45 | 46 | var showLoading = function () { 47 | loading.classList.add("show"); 48 | }; 49 | 50 | var hideLoading = function () { 51 | loading.classList.remove("show"); 52 | }; 53 | 54 | var playMusic = function (track) { 55 | 56 | rd.onloadstart = function () { 57 | showLoading(); 58 | }; 59 | 60 | rd.onload = function () { 61 | audio.src = this.result; 62 | }; 63 | 64 | rd.readAsDataURL(Player.playList[track]); 65 | 66 | audio.onloadeddata = function() { 67 | 68 | audio.play(); 69 | 70 | flip.classList.add('is-flipped'); 71 | if (Player.currentTrack > -1) { 72 | inactivateListItem(Player.currentTrack); 73 | } 74 | 75 | activateListItem(track); 76 | 77 | Player.isPlaying = true; 78 | Player.currentTrack = track; 79 | 80 | hideLoading(); 81 | setMusicName(Player.playList[track].name); 82 | setTimeLineMax(this.duration); 83 | setMusicTime(this.duration); 84 | }; 85 | 86 | }; 87 | 88 | var pause = function () { 89 | 90 | if (audio.src == "") return false; 91 | 92 | flip.classList.remove('is-flipped'); 93 | inactivateListItem(Player.currentTrack); 94 | 95 | Player.isPlaying = false; 96 | audio.pause(); 97 | 98 | }; 99 | 100 | var resume = function () { 101 | 102 | if (audio.src == "") return false; 103 | 104 | flip.classList.add('is-flipped'); 105 | activateListItem(Player.currentTrack); 106 | 107 | Player.isPlaying = true; 108 | audio.play(); 109 | 110 | } 111 | 112 | var playPrev = function () { 113 | 114 | if (audio.src == "") return false; 115 | 116 | var prev = Player.currentTrack - 1; 117 | (prev > -1) ? playMusic(prev) : playMusic(0); 118 | 119 | }; 120 | 121 | var playNext = function () { 122 | 123 | if (audio.src == "") return false; 124 | 125 | var next = Player.currentTrack + 1; 126 | var lastMusic = Player.playList.length - 1; 127 | var random = Math.round( Math.random() * lastMusic ); 128 | 129 | if (!Player.isRandomized) { 130 | (next <= lastMusic) ? playMusic(next) : playMusic(0); 131 | } else { 132 | playMusic(random); 133 | } 134 | 135 | }; 136 | 137 | var repeat = function () { 138 | if (!Player.isRepeating) { 139 | btnRepeat.classList.add('is-on'); 140 | audio.setAttribute("loop", ""); 141 | Player.isRepeating = true; 142 | } else { 143 | btnRepeat.classList.remove('is-on'); 144 | audio.removeAttribute("loop"); 145 | Player.isRepeating = false; 146 | } 147 | }; 148 | 149 | var randomize = function () { 150 | if (!Player.isRandomized) { 151 | btnRandom.classList.add('is-on'); 152 | Player.isRandomized = true; 153 | } else { 154 | btnRandom.classList.remove('is-on'); 155 | Player.isRandomized = false; 156 | } 157 | }; 158 | 159 | var changeVolume = function () { 160 | audio.volume = volumeControl.value / 10; 161 | }; 162 | 163 | var changeTime = function () { 164 | if (audio.readyState != 0) audio.currentTime = timeLine.value; 165 | }; 166 | 167 | var timeLineUpdate = function () { 168 | timeLine.value = audio.currentTime; 169 | }; 170 | 171 | var setTimeLineMax = function (time) { 172 | timeLine.setAttribute( "max", Math.round(time) ); 173 | }; 174 | 175 | var setMusicTime = function (time) { 176 | musicTime.innerHTML = timeHelper.secondsToTime( Math.round(time) ); 177 | }; 178 | 179 | var musicCountUpdate = function (time) { 180 | musicTimeCount.innerHTML = timeHelper.secondsToTime( Math.round(time) ); 181 | }; 182 | 183 | var setMusicName = function (name) { 184 | musicName.innerHTML = name.replace(".mp3", ""); 185 | }; 186 | 187 | var createPlayList = function () { 188 | 189 | var musicName, i, li, button, span, 190 | len = Player.playList.length; 191 | 192 | playListElement.innerHTML = ""; 193 | 194 | for (i = 0; i < len; i += 1) { 195 | 196 | musicName = document.createTextNode(Player.playList[i].name.replace(".mp3", "")); 197 | 198 | li = document.createElement("li"); 199 | button = document.createElement("button"); 200 | span = document.createElement("span"); 201 | 202 | button.setAttribute("type", "button"); 203 | button.setAttribute("class", "btn btn-circle btn-small"); 204 | button.innerHTML = ''; 205 | 206 | (function (id) { 207 | button.addEventListener('click', function () { 208 | playMusic(id); 209 | }, false); 210 | })(i); 211 | 212 | span.setAttribute("id", "list-icon-"+i); 213 | span.setAttribute("class", "sound-wave"); 214 | span.innerHTML = ""; 215 | 216 | li.setAttribute("id", "list-item-"+i); 217 | li.setAttribute("class", "list-item"); 218 | li.appendChild(button); 219 | li.appendChild(musicName); 220 | li.appendChild(span); 221 | playListElement.appendChild(li); 222 | 223 | }; 224 | }; 225 | 226 | //botões 227 | btnPlay.addEventListener("click", resume, false); 228 | btnPause.addEventListener("click", pause, false); 229 | btnPrev.addEventListener("click", playPrev, false); 230 | btnNext.addEventListener("click", playNext, false); 231 | btnRepeat.addEventListener("click", repeat, false); 232 | btnRandom.addEventListener("click", randomize, false); 233 | 234 | //volume 235 | volumeControl.addEventListener("change", changeVolume, false); 236 | 237 | //timeLine 238 | timeLine.addEventListener("change", changeTime, false); 239 | timeLine.addEventListener("mousedown", function() { 240 | audio.removeEventListener("timeupdate", timeLineUpdate); 241 | }, false); 242 | timeLine.addEventListener("mouseup", function() { 243 | audio.addEventListener("timeupdate", timeLineUpdate, false); 244 | }, false); 245 | 246 | //player 247 | audio.addEventListener("ended", playNext, false); 248 | audio.addEventListener("timeupdate", timeLineUpdate, false); 249 | audio.addEventListener("timeupdate", function() { 250 | musicCountUpdate( Math.floor(this.currentTime) ); 251 | }, false); 252 | 253 | module.exports = { 254 | setPlayList: setPlayList, 255 | clearPlayList: clearPlayList, 256 | playMusic: playMusic, 257 | createPlayList: createPlayList 258 | } -------------------------------------------------------------------------------- /src/js/helpers/time.js: -------------------------------------------------------------------------------- 1 | function padLeft(n, width, z) { 2 | z = z || '0'; 3 | n = n + ''; 4 | return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; 5 | } 6 | 7 | var secondsToTime = function (seconds) { 8 | 9 | if (isNaN(seconds) || seconds == "" || typeof seconds != 'number') return "00:00"; 10 | 11 | var hours = parseInt( seconds / 3600 ) % 24, 12 | minutes = parseInt( seconds / 60 ) % 60, 13 | seconds = parseInt( seconds % 60); 14 | 15 | if (hours > 0) { 16 | var result = padLeft(hours, 2, 0) + ':' + padLeft(minutes, 2, 0) + ':' + padLeft(seconds, 2, 0); 17 | } else { 18 | var result = padLeft(minutes, 2, 0) + ':' + padLeft(seconds, 2, 0); 19 | } 20 | 21 | return result; 22 | 23 | }; 24 | 25 | module.exports = { 26 | secondsToTime: secondsToTime 27 | } -------------------------------------------------------------------------------- /src/js/index.js: -------------------------------------------------------------------------------- 1 | require('./components/dropdown.js'); 2 | 3 | var Player = require('./components/player.js'); 4 | 5 | (function () { 6 | 7 | var btnUpload = document.querySelector("#btn-upload"), 8 | fileElement = document.querySelector("#file-element"), 9 | themeLight = document.querySelector("#theme-light"), 10 | themeDark = document.querySelector("#theme-dark"), 11 | btnsTheme = document.querySelectorAll('.theme-item-btn'), 12 | btnsColor = document.querySelectorAll('.btn-color'), 13 | 14 | setLocalStorage = function (item, value) { 15 | if (window.hasOwnProperty('localStorage')) { 16 | localStorage.setItem(item, value); 17 | } 18 | }, 19 | 20 | getLocalStorage = function (item) { 21 | if (window.hasOwnProperty('localStorage')) { 22 | return localStorage.getItem(item); 23 | } 24 | }, 25 | 26 | setTheme = function (theme) { 27 | 28 | theme = theme || "light"; 29 | document.body.classList.remove('dark', 'light'); 30 | document.body.classList.add(theme); 31 | setLocalStorage("theme", theme); 32 | 33 | }, 34 | 35 | setColor = function (color) { 36 | 37 | color = color || "green"; 38 | document.body.className = document.body.className.replace(/(blue|red|green|pink|purple|cyan|teal|yellow|orange)/g, ''); 39 | document.body.classList.add(color); 40 | setLocalStorage("color", color); 41 | 42 | }; 43 | 44 | if (window.hasOwnProperty('localStorage')) { 45 | setTheme(getLocalStorage('theme')); 46 | setColor(getLocalStorage('color')); 47 | } 48 | 49 | btnUpload.addEventListener("click", function (e) { 50 | 51 | e.stopPropagation(); 52 | e.preventDefault(); 53 | 54 | if (fileElement) { 55 | fileElement.click(); 56 | } 57 | 58 | }, false); 59 | 60 | fileElement.addEventListener("change", function () { 61 | 62 | Player.clearPlayList(); 63 | 64 | for (var i = 0, len = this.files.length; i < len; i += 1) { 65 | Player.setPlayList(this.files[i]); 66 | } 67 | 68 | Player.createPlayList(); 69 | Player.playMusic(0); 70 | 71 | }, false); 72 | 73 | btnsTheme.forEach(function (btnTheme) { 74 | btnTheme.addEventListener('click', function () { 75 | var themeScheme = this.getAttribute('data-theme-scheme'); 76 | setTheme(themeScheme); 77 | }, false); 78 | }); 79 | 80 | btnsColor.forEach(function (btnColor) { 81 | btnColor.addEventListener('click', function () { 82 | var color = this.getAttribute('data-theme-color'); 83 | setColor(color); 84 | }, false); 85 | }); 86 | 87 | }()); -------------------------------------------------------------------------------- /src/js/main.js: -------------------------------------------------------------------------------- 1 | require('./index.js'); --------------------------------------------------------------------------------