1if (!window.QPlayer) { 2 window.QPlayer = {}; 3} 4window.QPlayer.init = function () { 5 6 if (document.getElementById('QPlayer')) { 7 return; 8 } 9 10 $('body').append('<div id="QPlayer"><div id="QPlayer-body"><div id="QPlayer-panel"><div id="QPlayer-cover"><svg id="QPlayer-cover-default" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><circle cx="32" cy="32" r="32" style="fill:#222"/><circle cx="32" cy="32" r="16"/><circle cx="32" cy="32" r="12" style="fill:#e12"/><circle cx="32" cy="32" r="1.2" style="fill:#fff"/></svg></div><div id="QPlayer-control"><div id="QPlayer-title"><strong id="QPlayer-name"></strong> -<span id="QPlayer-artist"></span></div><div id="QPlayer-progress"><div id="QPlayer-progress-current" style="width: 0;"></div></div><div id="QPlayer-control-bar"><div id="QPlayer-time">00:00</div><div id="QPlayer-control-play"><svg id="QPlayer-btn-previous" xmlns="http://www.w3.org/2000/svg" viewBox="6 6 12 12"><path d="M6 6h2v12H6zm3.5 6l8.5 6V6z"/></svg><svg id="QPlayer-btn-next" xmlns="http://www.w3.org/2000/svg" viewBox="6 6 12 12"><path d="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z"/></svg><div id="QPlayer-btn-play"><svg id="QPlayer-play" xmlns="http://www.w3.org/2000/svg" viewBox="16 10 22 28"><path d="M16 10v28l22-14z"/></svg><svg id="QPlayer-pause" xmlns="http://www.w3.org/2000/svg" viewBox="12 10 24 28"><path d="M12 38h8V10h-8v28zm16-28v28h8V10h-8z"/></svg></div></div><div id="QPlayer-control-more"><div id="QPlayer-btn-mode"><svg id="QPlayer-btn-repeat" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4z"/></svg><svg id="QPlayer-btn-shuffle" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M10.59 9.17L5.41 4 4 5.41l5.17 5.17 1.42-1.41zM14.5 4l2.04 2.04L4 18.59 5.41 20 17.96 7.46 20 9.5V4h-5.5zm.33 9.41l-1.41 1.41 3.13 3.13L14.5 20H20v-5.5l-2.04 2.04-3.13-3.13z"/></svg></div><svg id="QPlayer-btn-list" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18"><path d="M7 10h9V8H7v2zm0-7v2h9V3H7zm0 12h9v-2H7v2zm-4-5h2V8H3v2zm0-7v2h2V3H3zm0 12h2v-2H3v2z"/></svg><svg id="QPlayer-btn-lyrics" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18"><path d="M4 14v2h10v-2H4zm0-8v2h10V6H4zm-2 6h14v-2H2v2zM2 2v2h14V2H2z"/></svg></div></div></div></div><div id="QPlayer-switch"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg></div></div><div id="QPlayer-more"><ol id="QPlayer-list"></ol><div id="QPlayer-lyrics"></div></div><audio id="QPlayer-audio"></audio></div>'); 11 12 var q = window.QPlayer; 13 var v = {}; 14 15 var 16 $q = $('#QPlayer'), 17 $audio = $('#QPlayer-audio'), 18 $cover = $('#QPlayer-cover'), 19 $list = $('#QPlayer-list'), 20 $title = $('#QPlayer-title'), 21 $more = $('#QPlayer-more'), 22 $time = $('#QPlayer-time'), 23 $progress = $('#QPlayer-progress'), 24 $progressCurrent = $('#QPlayer-progress-current'), 25 $lyrics = $('#QPlayer-lyrics'), 26 $mode = $('#QPlayer-btn-mode') 27 ; 28 29 var 30 audio = $audio[0], 31 coverTimeout = 500 32 ; 33 34 var $lyricsList, $listLi, isLoadPause, isPrevisionPlay, errorStartIndex, isAllError, setCoverTime; 35 36 q.version = '2.0.6'; 37 q.audio = audio; 38 q.defaultProvider = q.defaultProvider || 'default'; 39 q.provider = q.provider || {}; 40 q.provider.default = q.provider.default || { 41 dataType: '*', 42 lyrics: function (current, success) { 43 var url = current.lrc; 44 if (!url) { 45 return; 46 } 47 var dataType = this.dataType; 48 $.ajax({ 49 url: url, 50 dataType: dataType, 51 success: function (lrc) { 52 if (!lrc) { 53 return; 54 } 55 success(lrc); 56 } 57 }); 58 } 59 }; 60 61 function Shuffle(index) { 62 var _this = this; 63 if (index === undefined) { 64 this.index = -1; 65 this.list = []; 66 } else { 67 this.index = 0; 68 this.list = [index]; 69 } 70 this.next = function () { 71 if (this.index + 1 === this.list.length) { 72 if (this.list.length >= v.list.length) { 73 this.index = 0; 74 return _this.list[0]; 75 } 76 return push(); 77 } 78 return this.list[++this.index]; 79 }; 80 this.previous = function () { 81 if (this.index === 0) { 82 var length = v.list.length; 83 if (this.list.length === length) { 84 this.index = length - 1; 85 return this.list[this.index]; 86 } 87 var index = getIndex(); 88 this.list.unshift(index); 89 return index; 90 } 91 if (this.index === -1) { 92 return push(); 93 } 94 return this.list[--this.index]; 95 }; 96 function push() { 97 var index = getIndex(); 98 _this.list.push(index); 99 ++_this.index; 100 return index; 101 } 102 function getIndex() { 103 var length = v.list.length; 104 if (_this.index === -1) { 105 return random(length); 106 } 107 var list = []; 108 for (var i = 0; i < length; ++i) { 109 if (_this.list.includes(i)) { 110 continue; 111 } 112 list.push(i); 113 } 114 return list[random(list.length)]; 115 } 116 function random(max) { 117 return Math.floor(Math.random() * max); 118 } 119 } 120 121 function getNextIndex() { 122 if (v.list.length === 0) { 123 return false;
124 } 125 if (q.isShuffle) { 126 return q.shuffle.next(); 127 } 128 if (++q.index === q.list.length) { 129 q.index = 0; 130 } 131 return q.index; 132 } 133 134 function getPreviousIndex() { 135 if (v.list.length === 0) { 136 return false; 137 } 138 if (q.isShuffle) { 139 return q.shuffle.previous(); 140 } 141 if (--q.index < 0) { 142 q.index = q.list.length - 1; 143 } 144 return q.index; 145 } 146 147 function onPlay() { 148 $q.addClass('QPlayer-playing'); 149 // $title.marquee('resume'); 150 } 151 152 function onPause() { 153 if (isLoadPause) { 154 isLoadPause = false; 155 return; 156 } 157 $q.removeClass('QPlayer-playing'); 158 // $title.marquee('pause'); 159 } 160 161 function s2m(s) { 162 var m = Math.floor(s / 60); 163 s = Math.floor(s % 60); 164 if (m < 10) { 165 m = '0' + m; 166 } 167 if (s < 10) { 168 s = '0' + s; 169 } 170 return m + ':' + s; 171 } 172 173 function getListLi(index) { 174 return $listLi.eq(index); 175 } 176 177 function Provider(provider, current) { 178 var callbacks = new ProviderCallback(); 179 var isStop; 180 this.call = function (name, success, error) { 181 if (!error) { 182 error = function () {} 183 } 184 var data = current[name]; 185 if (data) { 186 success(data); 187 return; 188 } 189 var callback = provider[name]; 190 if (callback === true) { 191 callbacks.set(name, success, error); 192 return; 193 } 194 if (callback) { 195 callback(current, success, error); 196 return; 197 } 198 error(); 199 }; 200 this.stop = function () { 201 isStop = true; 202 }; 203 this.load = function () { 204 isStop = false; 205 var load = provider.load; 206 if (!load) { 207 return; 208 } 209 load(current, callbacks); 210 }; 211 212 function ProviderCallback() { 213 var callbacks = {}; 214 var caches = {}; 215 this.success = function (name, data, cache) { 216 var callback = callbacks[name]; 217 if (!callback) { 218 caches[name] = { 219 data: data, 220 cache: cache 221 }; 222 return; 223 } 224 callback.success(data, cache); 225 }; 226 this.error = function (name) { 227 var callback = callbacks[name]; 228 if (!callback) { 229 caches[name] = false; 230 return; 231 } 232 callback.error(); 233 }; 234 this.set = function (name, success, error) { 235 if (isStop) { 236 return; 237 } 238 var cache = caches[name]; 239 if (cache) { 240 success(cache.data, cache.cache); 241 return; 242 } 243 if (cache === false) { 244 error(); 245 return; 246 } 247 callbacks[name] = {success: success, error: error}; 248 }; 249 } 250 } 251 252 function getProvider(current) { 253 // noinspection JSUnresolvedVariable 254 var providerName = current.provider || q.defaultProvider; 255 if (typeof providerName === 'string') { 256 var provider = q.provider[providerName]; 257 if (!provider) { 258 console.warn('æ²¡ææ¾å°ç¸åºç Providerï¼' + providerName); 259 provider = {}; 260 } 261 provider = current.provider = new Provider(provider, current); 262 provider.name = providerName; 263 return provider; 264 } 265 return providerName instanceof Provider ? providerName : new Provider({}, current); 266 } 267 268 function Lyrics(lrc) { 269 this.time = []; 270 this.text = []; 271 this.index = -1; 272 this.nextTime = 0; 273 this.offset = 0; 274 this.has = false;
275 this.add = function (time, text) { 276 var length = this.time.length; 277 for (var i = 0; i < length; ++i) { 278 var t = this.time[i]; 279 if (t < time) { 280 continue; 281 } 282 if (t === time) { 283 this.text[i] += '<br>' + text; 284 return; 285 } 286 if (i !== length - 1) { 287 this.time.splice(i, 0, time); 288 this.text.splice(i, 0, text); 289 return; 290 } 291 } 292 this.time[length] = time; 293 this.text[length] = text; 294 }; 295 this.find = function (time) { 296 var length = this.time.length; 297 for (var i = 0; i < length; ++i) { 298 var t = this.time[i] + this.offset; 299 if (t < time) { 300 continue; 301 } 302 if (t === time) { 303 return i; 304 } 305 return i - 1; 306 } 307 return length - 1; 308 }; 309 this.goto = function (index) { 310 if (this.index !== -1) { 311 $($lyricsList[this.index]).removeClass('QPlayer-lyrics-current'); 312 } 313 this.nextTime = this.time[index + 1] + this.offset; 314 this.index = index; 315 if (index < 0) { 316 return; 317 } 318 var $current = $($lyricsList[index]).addClass('QPlayer-lyrics-current'); 319 $lyrics.stop(true).animate({ 320 scrollTop: $current.offset().top - $lyrics.offset().top + $lyrics.scrollTop() 321 - (162 - $current.height()) / 2 322 }); 323 }; 324 this.next = function (time) { 325 if (isNaN(this.nextTime) || this.nextTime > time) { 326 return; 327 } 328 this.goto(this.index + 1); 329 }; 330 this.show = function () { 331 var length = this.text.length; 332 if (length === 0) { 333 return; 334 } 335 var html = ''; 336 for (var i = 0; i < length; ++i) { 337 html += '<p>' + this.text[i] + '</p>'; 338 } 339 $lyrics.removeClass('QPlayer-lyrics-no'); 340 $lyrics.html(html); 341 $lyricsList = $lyrics.children(); 342 this.goto(-1); 343 }; 344 var linePattern = /^/mg; 345 var timePattern = /\t*\[([0-6]?\d):([0-6]?\d)(?:\.(\d{1,3}))?]/g; 346 var textPattern = /.*/mg; 347 var offsetPattern = /^\[offset:\t*([+-]?\d+)]/mg; 348 while ((linePattern.exec(lrc)) !== null) { 349 var lineIndex = linePattern.lastIndex; 350 var result; 351 offsetPattern.lastIndex = lineIndex; 352 if ((result = offsetPattern.exec(lrc)) != null) { 353 linePattern.lastIndex = offsetPattern.lastIndex; 354 this.offset = parseFloat(result[1]); 355 continue; 356 } 357 var index = timePattern.lastIndex = lineIndex; 358 var times = []; 359 function isTime() { 360 // noinspection JSReferencingMutableVariableFromClosure 361 return (result = timePattern.exec(lrc)) != null && result.index === index; 362 } 363 if (!isTime()) { 364 ++linePattern.lastIndex; 365 continue; 366 } 367 do { 368 linePattern.lastIndex = textPattern.lastIndex = timePattern.lastIndex; 369 var time = parseInt(result[1]) * 60000 + parseInt(result[2]) * 1000; 370 var f = result[3]; 371 if (f) { 372 var fLength = f.length; 373 time += parseInt(fLength < 3 ? f + '0'.repeat(3 - fLength) : f); 374 } 375 times.push(time); 376 index = timePattern.lastIndex; 377 } while (isTime()); 378 if (times.length === 0) { 379 continue; 380 } 381 var text = textPattern.exec(lrc)[0].trim(); 382 var length = times.length; 383 for (var i = 0; i < length; ++i) { 384 this.add(times[i], text); 385 } 386 } 387 this.has = this.time.length !== 0; 388 } 389 390 function errorWithIndex(index) { 391 if (errorStartIndex === index) { 392 isAllError = true; 393 init(); 394 q.pause(); 395 return true; 396 } 397 if (errorStartIndex === -1) { 398 errorStartIndex = index; 399 } 400 getListLi(index).addClass('QPlayer-list-error'); 401 return false;
402 } 403 404 function initCover() { 405 setTimeout(function () { 406 if (setCoverTime >= new Date().getTime() - coverTimeout) { 407 return; 408 } 409 $cover.css('background-image', ''); 410 $cover.addClass('QPlayer-cover-no'); 411 }, coverTimeout); 412 } 413 414 function initLoad() { 415 $lyrics.addClass('QPlayer-lyrics-no').html('<p>æ æè¯ï¼è¯·æ¬£èµã</p>'); 416 $title.html('<strong>æ²¡æææ²</strong>'); 417 $lyricsList = null; 418 $progressCurrent.width('0'); 419 audio.currentTime = 0; 420 initCover(); 421 // $title.marquee('destroy'); 422 } 423 424 function init() { 425 q.index= -1; 426 q.current = null; 427 initLoad(); 428 isLoadPause = false; 429 errorStartIndex = -1; 430 } 431 432 function initNoSongs() { 433 init(); 434 $listLi = null; 435 $list.html('<li class="QPlayer-list-current">æ²¡æææ²</li>'); 436 } 437 438 function isNeedMarquee() { 439 var width = 0; 440 // noinspection JSUnresolvedFunction 441 $title.children().each(function () { 442 width += $(this).width(); 443 }); 444 return width > $title.width(); 445 } 446 447 function preloadCover(url) { 448 var image = new Image(); 449 image.onload = function () { 450 setCoverTime = new Date().getTime(); 451 $cover.css('background-image', 'url("' + url + '")'); 452 $cover.removeClass('QPlayer-cover-no'); 453 }; 454 image.src = url; 455 } 456 457 function anchorSongList($li) { 458 $list.scrollTop($list.scrollTop() - $list.offset().top + $li.offset().top + 1); 459 } 460 461 function getArtist(artist) { 462 return Array.isArray(artist) ? artist.join(' / ') : artist; 463 } 464 465 /** 466 * å è½½ 467 * 468 * @param {Number} index 469 * @return {boolean} 470 */ 471 q.load = function(index) { 472 isAllError = false; 473 var current = q.current; 474 if (current) { 475 getProvider(current).stop(); 476 isLoadPause = true; 477 audio.pause(); 478 } 479 initLoad(); 480 var length = v.list.length; 481 if (length === 0) { 482 console.warn('list 为空ï¼'); 483 return false; 484 } 485 if (!(length > index || index > 0)) { 486 console.warn('è¶ åº listï¼length=' + length + 'ï¼index=' + index); 487 return false; 488 } 489 $list.children('.QPlayer-list-current').removeClass('QPlayer-list-current'); 490 var $li = getListLi(index).addClass('QPlayer-list-current'); 491 if (!current) { 492 anchorSongList($li) 493 } 494 current = v.list[index]; 495 var title = '<strong>' + current.name + '</strong>'; 496 var artist = getArtist(current.artist); 497 if (artist) { 498 title += '<span> - ' + artist + '</span>'; 499 } 500 $title.html(title); 501 if (isNeedMarquee()) { 502 // $title.marquee({ 503 // duration: 10000, 504 // gap: 40, 505 // delayBeforeStart: 1000, 506 // duplicated: true, 507 // startVisible: true 508 // }).marquee('pause'); 509 } 510 q.index = index; 511 q.current = current; 512 var provider = getProvider(current); 513 provider.call('cover', function (url, cache) { 514 if (isAllError || !url) { 515 return; 516 } 517 preloadCover(url); 518 if (cache) { 519 current.cover = url; 520 } 521 }); 522 provider.call('lyrics', function (lrc) { 523 if (isAllError || !lrc) { 524 return; 525 } 526 if (!(lrc instanceof Lyrics)) { 527 current.lyrics = new Lyrics(lrc); 528 } 529 current.lyrics.show(); 530 }); 531 provider.load(); 532 return true; 533 }; 534 535 /** 536 * ææ¾ 537 * 538 * @param index 539 * @param isPrevious 540 * @return {number} 541 * 0 é误 542 * 1 List 为空 543 * 2 ææ¾é³é¢ 544 * 3 å è½½å¹¶ææ¾é³é¢ 545 * 4 å ¨é¨éè¯¯æ æ³ææ¾ 546 */ 547 function play(index, isPrevious) { 548 isPrevisionPlay = isPrevious; 549 if (index === false) { 550 console.warn('list 为空ï¼'); 551 return 1; 552 } else if (typeof index === 'number') { 553 if (!q.load(index)) { 554 return errorWithIndex(index) ? 4 : 0; 555 } 556 } else { 557 index = q.index; 558 if (audio.readyState !== 0) { 559 onPlay(); 560 audioPlay(); 561 return 2; 562 } 563 } 564 if (index === -1) { 565 return 0; 566 } 567 568 onPlay(); 569 var current = q.current; 570 function getIndex() { 571 var list = v.list; 572 return list[index] === current ? index : list.indexOf(current); 573 } 574 function error() { 575 var _index = getIndex(); 576 if (_index === -1) { 577 console.warn('æªæ¾å°ç´¢å¼'); 578 return; 579 } 580 if (errorWithIndex(_index)) { 581 return; 582 } 583 if (isPrevious) { 584 q.previous(); 585 } else { 586 q.next(); 587 } 588 } 589 function audioPlay() { 590 function catchError(e) { 591 if (e.name === 'AbortError') { 592 return; 593 } 594 error = true; 595 console.error([e]); 596 } 597 var error = false;
598 var promise = null; 599 try { 600 promise = audio.play(); 601 if (typeof Promise === 'function' && promise instanceof Promise) { 602 promise 603 .then(function () { 604 getListLi(getIndex()).removeClass('QPlayer-list-error'); 605 }) 606 .catch(catchError); 607 } 608 } catch (e) { 609 catchError(e); 610 } 611 if (!error && !(typeof Promise === 'function' && promise instanceof Promise)) { 612 getListLi(getIndex()).removeClass('QPlayer-list-error'); 613 } 614 } 615 getProvider(current).call('audio', function (url, cache) { 616 if (isAllError) { 617 return; 618 } 619 if (!url) { 620 error(); 621 return; 622 } 623 if (cache) { 624 current.audio = cache; 625 } 626 audio.src = url; 627 audio.load(); 628 audioPlay(); 629 }, error); 630 return 3; 631 } 632 633 q.play = function (index, isPrevious) { 634 var bool = play(index, isPrevious); 635 if (bool) { 636 return bool; 637 } 638 return isPrevious ? q.previous() : q.next(); 639 }; 640 641 q.pause = function () { 642 onPause(); 643 audio.pause(); 644 }; 645 646 q.next = function () { 647 return q.play(getNextIndex()); 648 }; 649 650 q.previous = function () { 651 return q.play(getPreviousIndex(), true); 652 }; 653 654 q.reload = function () { 655 q.pause(); 656 return q.load(q.index); 657 } 658 659 /** 660 * @param {Object|String} options 661 */ 662 q.setColor = function(options) { 663 var jq = $('#QPlayer-theme'); 664 if (!jq.length) { 665 jq = $('<style id="QPlayer-theme"></style>'); 666 $q.append(jq); 667 } 668 // noinspection JSDeprecatedSymbols 669 var all = typeof options === 'string' ? options : options.all; 670 if (!all) { 671 jq.text(''); 672 return; 673 } 674 var color; 675 var style = ''; 676 function getColor(name) { 677 color = options[name]; 678 if (color === undefined) { 679 color = all; 680 } 681 } 682 getColor('switch'); 683 if (color) { 684 style += '#QPlayer-switch{background:' + color + ';}'; 685 } 686 getColor('progress'); 687 if (color) { 688 style += '#QPlayer-progress-current{background:' + color + ';}'; 689 } 690 getColor('list'); 691 if (color) { 692 style += '#QPlayer-list li:hover, #QPlayer-list li.QPlayer-list-current{border-left-color:' + color + ';}'; 693 } 694 getColor('lyrics'); 695 if (color) { 696 style += '#QPlayer-lyrics.QPlayer-lyrics-no p,#QPlayer-lyrics p.QPlayer-lyrics-current{color:' + color + ';}'; 697 } 698 jq.text(style); 699 }; 700 701 $('#QPlayer-switch').click(function () { 702 $q.toggleClass('QPlayer-show'); 703 }); 704 $('#QPlayer-btn-list').click(function () { 705 var name = 'QPlayer-list-show'; 706 if ($more.hasClass(name)) { 707 $more.removeClass(name); 708 } else { 709 var index = q.index; 710 if (index !== -1) { 711 anchorSongList(getListLi(index)) 712 } 713 $more.addClass(name); 714 } 715 }); 716 $('#QPlayer-btn-lyrics').click(function () { 717 $more.toggleClass('QPlayer-lyrics-show'); 718 }); 719 $('#QPlayer-btn-play').click(function () { 720 if ($q.hasClass('QPlayer-playing')) { 721 q.pause(); 722 } else { 723 q.play(); 724 } 725 }); 726 $('#QPlayer-btn-next').click(q.next); 727 $('#QPlayer-btn-previous').click(q.previous); 728 $cover.click(function () { 729 q.isRotate = !v.isRotate; 730 }); 731 $mode.click(function () { 732 q.isShuffle = !v.isShuffle 733 }); 734 $list.on('click', 'li:not(.QPlayer-list-current)', function () { 735 var index = $(this).index(); 736 if (v.isShuffle) { 737 q.shuffle = new Shuffle(index); 738 } 739 q.play(index); 740 }); 741 $audio 742 .on('playing', onPlay) 743 .on('pause', onPause) 744 .on('ended', q.next) 745 .on('timeupdate', function () { 746 var time = audio.currentTime; 747 $time.text(s2m(time)); 748 var lyrics = q.current.lyrics; 749 if (lyrics && lyrics.has) { 750 lyrics.next(time * 1000); 751 } 752 if (!isProgressClicked) { 753 $progressCurrent.width(100 * time / audio.duration + '%'); 754 } 755 }) 756 .on('error', function () { 757 console.log('error', arguments); 758 var index = v.list.indexOf(q.current); 759 if (index !== -1 && errorWithIndex(index)) { 760 return; 761 } 762 if (isPrevisionPlay) { 763 q.previous(); 764 } else { 765 q.next(); 766 } 767 }) 768 .on('canplay', function () { 769 errorStartIndex = -1; 770 }) 771 ; 772 773 // è¿åº¦æ¡æä½ 774 var isProgressClicked; 775 function getXFromEvent(e) { 776 var type = e.type; 777 switch (type) { 778 case 'mousedown': 779 case 'mouseup': 780 case 'mousemove': 781 return e.pageX; 782 case 'touchstart': 783 case 'touchmove': 784 case 'touchend': 785 return e.originalEvent.changedTouches[0].pageX; 786 } 787 return false;
788 } 789 function getProgressFromEvent(e) { 790 return getXFromEvent(e) - $progress.offset().left; 791 } 792 function moveProgress(e) { 793 if (!isProgressClicked) { 794 return; 795 } 796 e.preventDefault(); 797 var total = $progress.width(); 798 var current = getProgressFromEvent(e); 799 $progressCurrent.width(current < total ? current : total); 800 } 801 $progress.on('mousedown touchstart', function (e) { 802 isProgressClicked = true; 803 moveProgress(e); 804 }); 805 $(document) 806 .on('mouseup touchend', function (e) { 807 if (!isProgressClicked) { 808 return; 809 } 810 isProgressClicked = false; 811 var duration = audio.duration; 812 if (isNaN(duration)) { 813 $progressCurrent.width(0); 814 return; 815 } 816 var total = $progress.width(); 817 var current = getProgressFromEvent(e); 818 if (current >= total) { 819 q.next(); 820 return; 821 } 822 var time = current > 0 ? duration * current / total: 0; 823 audio.currentTime = time; 824 var lyrics = q.current.lyrics; 825 if (lyrics && lyrics.has) { 826 lyrics.goto(lyrics.find(time * 1000)); 827 } 828 }) 829 .on('mousemove touchmove', moveProgress); 830 831 initNoSongs(); 832 833 function getLocalStorageName(name) { 834 return 'QPlayer-' + name; 835 } 836 837 function getBoolFromLocalStorage(name) { 838 var value = localStorage.getItem(getLocalStorageName(name)); 839 return !!(value && value !== 'false'); 840 } 841 842 function setBoolFromLocalStorage(name, value) { 843 localStorage.setItem(getLocalStorageName(name), value); 844 } 845 846 function hasLocalStorageName(name) { 847 return localStorage.hasOwnProperty(getLocalStorageName(name)); 848 } 849 850 function defineProperties(obj, properties) { 851 var keys = Object.keys(properties); 852 var length = keys.length; 853 for (var i1 = 0; i1 < length; ++i1) { 854 var key1 = keys[i1]; 855 v[key1] = obj[key1]; 856 } 857 Object.defineProperties(obj, properties); 858 for (var i2 = 0; i2 < length; ++i2) { 859 var key2 = keys[i2]; 860 if (properties[key2].type === 'bool' && hasLocalStorageName(key2)) { 861 obj[key2] = getBoolFromLocalStorage(key2); 862 continue; 863 } 864 obj[key2] = v[key2] || properties[key2].default; 865 } 866 } 867 868 defineProperties(q,{ 869 isShuffle: { 870 get: function () { 871 return v.isShuffle; 872 }, 873 set: function (value) { 874 v.isShuffle = value; 875 setBoolFromLocalStorage('isShuffle', value); 876 if (value) { 877 $mode.addClass('QPlayer-shuffle'); 878 var index = q.index; 879 q.shuffle = new Shuffle(index === -1 ? undefined : index); 880 } else { 881 $mode.removeClass('QPlayer-shuffle'); 882 q.shuffle = null; 883 } 884 }, 885 type: 'bool', 886 default: false 887 }, 888 isRotate: { 889 get: function () { 890 return v.isRotate; 891 }, 892 set: function (value) { 893 v.isRotate = value; 894 setBoolFromLocalStorage('isRotate', value); 895 if (value) { 896 $cover.addClass('QPlayer-cover-rotate'); 897 } else { 898 $cover.removeClass('QPlayer-cover-rotate'); 899 } 900 }, 901 type: 'bool', 902 default: true 903 }, 904 list: { 905 get: function () { 906 return v.list; 907 }, 908 set: function (value) { 909 if (!Array.isArray(value)) { 910 console.warn('list åºè¯¥æ¯æ°ç»'); 911 return; 912 } 913 v.list = value; 914 var length = value.length; 915 if (length === 0) { 916 initNoSongs(); 917 return; 918 } 919 var html = ''; 920 for (var i = 0; i < length; ++i) { 921 var item = value[i]; 922 html += '<li><strong>' + item.name + '</strong>'; 923 var artist = getArtist(item.artist); 924 if (artist) { 925 html += '<span>' + artist + '</span>'; 926 } 927 html += '</li>'; 928 } 929 q.pause(); 930 $list.html(html); 931 $listLi = $list.children(); 932 if (q.index > -1 && q.current && length > q.index && value[q.index] === q.current) { // å·²å è½½ä¿æä¸å 933 return; 934 } 935 init(); 936 // noinspection JSCheckFunctionSignatures 937 q.load(getNextIndex()); 938 }, 939 type: 'list', 940 default: [] 941 } 942 }); 943}; 944 945$(window.QPlayer.init); 946
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.