PageSourceSearch

https://saili.science/static/js/player.js

js saili.science collected 2026-09-25 22:37:42 UTC 14,658 bytes, 429 lines download raw bytes

1(function ($) {
2    // Settings
3    var isShowNotification = false,
4        isInitMarquee = true,
5        shuffleArray = [],
6        shuffleIndex,
7        autoClearTimer,
8        autoShowTimer,
9        isFirstPlay = localStorage.qplayer == undefined ? true : false,
10        isShuffle = localStorage.qplayer == undefined ? false : localStorage.qplayer === 'true' ? true : false;
11    first = true;
12    index = 0;
13    // Load playlist
14    for (var i = 0; i < playlist.length; i++) {
15        var item = playlist[i];
16        $('#playlist').append('<li class="lib" style="overflow:hidden;"><strong style="margin-left: 5px;">' + item.title + '</strong><span style="float: right;" class="artist">' + item.artist + '</span></li>');
17        if (item.mp3 == "") {
18            $('#playlist li').eq(i).css('color', '#ddd');
19        }
20    }
21
22    var currentTrack = localStorage.song, audio, timeout;
23    var shuffle_array = localStorage.qplayer_shuffle_array;
24
25    if (isShuffle && shuffle_array != undefined && playlist.length === (shuffleArray = JSON.parse(shuffle_array)).length) {
26        shuffleIndex = 0;
27        if (currentTrack == undefined) {
28            currentTrack = shuffleArray[0];
29            $('#QPlayer .cover').attr('title', '点击关闭随机播放');
30        }
31    } else {
32        isShuffle = false;
33        $('#QPlayer .cover').attr('title', '点击开启随机播放');
34    }
35    //判断是否显示滚动条
36    var totalHeight = 0;
37    for (var i = 0; i < playlist.length; i++) {
38        totalHeight += ($('#playlist li').eq(i).height() + 6);
39    }
40    if (totalHeight > 360) {
41        $('#playlist').css("overflow", "auto");
42        if (isShuffle) {
43            var temp = 0;
44            for (var j = 0; j < currentTrack; j++) {
45                temp += ($('#playlist li').eq(j).height() + 6);
46            }
47            $('#playlist').scrollTop(temp);
48        }
49    }
50
51    var play = function () {
52        sessionStorage.autoPlay = "true"
53        audio.play();
54        if (isRotate) {
55            $("#player .cover img").css("animation", "9.8s linear 0s normal none infinite rotate");
56            $("#player .cover img").css("animation-play-state", "running");
57        }
58        $('.playback').addClass('playing');
59        timeout = setInterval(updateProgress, 500);
60        //超过显示栏运行跑马灯
61        if (isExceedTag()) {
62            if (isInitMarquee) {
63                initMarquee();
64                isInitMarquee = false;
65            } else {
66                $('.marquee').marquee('resume');
67            }
68        }
69    }
70
71    var pause = function () {
72        audio.pause();
73        $("#player .cover img").css("animation-play-state", "paused");
74        $('.playback').removeClass('playing');
75        clearInterval(timeout);
76        if (isExceedTag()) {
77            $('.marquee').marquee('pause');
78        }
79        sessionStorage.autoPlay = ""
80    }
81
82    // Update progress
83    var setProgress = function (value) {
84        var currentSec = parseInt(value % 60) < 10 ? '0' + parseInt(value % 60) : parseInt(value % 60),
85            ratio = value / audio.duration * 100;
86
87        $('.timer').html(parseInt(value / 60) + ':' + currentSec);
88        localStorage.time = value
89        localStorage.song = currentTrack
90    }
91
92    var updateProgress = function () {
93        setProgress(audio.currentTime);
94    }
95
96    // Switch track
97    var switchTrack = function (i) {
98        if (i < 0) {
99            track = currentTrack = playlist.length - 1;
100        } else if (i >= playlist.length) {
101            track = currentTrack = 0;
102        } else {
103            track = i;
104        }
105        isInitMarquee = true;
106        $('audio').remove();
107        loadMusic(track);
108        play();
109    }
110
111    // Shuffle
112    var shufflePlay = function (i) {
113        if (i === 1) {
114            //下一首
115            if (++shuffleIndex === shuffleArray.length) {
116                shuffleIndex = 0;
117            }
118            currentTrack = shuffleArray[shuffleIndex];
119
120        } else if (i === 0) {
121            //上一首
122            if (--shuffleIndex < 0) {
123                shuffleIndex = shuffleArray.length - 1;
124            }
125            currentTrack = shuffleArray[shuffleIndex];
126        }
127        switchTrack(currentTrack);
128    }
129
130    // Fire when track ended
131    var ended = function () {
132        pause();
133        audio.currentTime = 0;
134        if (isShuffle) {
135            shufflePlay(1);
136        } else {
137            if (currentTrack < playlist.length) switchTrack(++currentTrack);
138        }
139
140    }
141
142    var beforeLoad = function () {
143        var endVal = this.seekable && this.seekable.length ? this.seekable.end(0) : 0;
144    }
145
146    // Fire when track loaded completely
147    var afterLoad = function () {
148        if (autoplay == true) play();
149    }
150
151    // Load track
152    var loadMusic = function (i) {
153        var item = playlist[i];
154        while (item.mp3 == "") {
155            showNotification('歌曲地址为空,已自动跳过');
156            if (isShuffle) {
157                if (++shuffleIndex === shuffleArray.length) {
158                    shuffleIndex = 0;
159                }
160                i = currentTrack = shuffleArray[shuffleIndex];
161            } else {
162                currentTrack = ++i;
163            }
164            item = playlist[i];
165        }
166        var newaudio = $('<audio>').html('<source src="' + item.mp3 + '"><source src="' + item.ogg + '">').appendTo('#player');
167        $('.cover').html('<img src="' + item.cover + '" alt="' + item.album + '">');
168        $('.musicTag').html('<strong>' + item.title + '</strong><span>
168 - </span><span class="artist">' + item.artist + '</span>');
169        $('#playlist li').removeClass('playing').eq(i).addClass('playing');
170        audio = newaudio[0];
171
172        audio.addEventListener('progress', beforeLoad, false);
173        audio.addEventListener('durationchange', beforeLoad, false);
174        audio.addEventListener('canplay', afterLoad, false);
175        audio.addEventListener('ended', ended, false);
176    }
177
178    var FirstLoad = function (i, time) {
179        if (i == undefined) {
180            i = 0
181            currentTrack = 0
182            shuffleIndex = 0
183        }
184        loadMusic(i)
185        if (time) {
186            audio.currentTime = time
187        }
188        if (sessionStorage.autoPlay == undefined) {
189            sessionStorage.autoPlay = "false"
190        }
191
192    }
193
194    FirstLoad(currentTrack, localStorage.time);
195    if (sessionStorage.autoPlay == "true") {
196        play()
197    }
198	$('.rewind').on('click', function(){
199		if (isShuffle){
200			shufflePlay(0);
201		} else {
202			switchTrack(--currentTrack);
203		}
204	});
205
206	$('.fastforward').on('click', function(){
207		if (isShuffle){
208			shufflePlay(1);
209		} else {
210			switchTrack(++currentTrack);
211		}
212	});
213	
214    $('.playback').on('click', function () {
215        if ($(this).hasClass('playing')) {
216            pause();
217        } else {
218            play();
219        }
220    });
221
222    $('#playlist li').each(function (i) {
223        $(this).on('click', function () {
224            if (isShuffle) {
225                for (var j = 0; j < shuffleArray.length; j++) {
226                    if (shuffleArray[j] === i) {
227                        shuffleIndex = j;
228                        break;
229                    }
230                }
231            } else {
232                currentTrack = i;
233            }
234            switchTrack(i);
235        });
236    });
237
238    $('#QPlayer .liebiao,#QPlayer .liebiao').on('click', function () {
239        var pl = $('#playlist');
240        if (pl.hasClass('go') === false) {
241            pl.css({"max-height": "360px", "transition": "max-height .5s ease"});
242            pl.css("border", "1px solid #dedede");
243            pl.addClass('go');
244        } else {
245            pl.css({"max-height": "0px", "transition": "max-height .5s ease"});
246            pl.css("border", "0");
247            pl.removeClass('go');
248        }
249    });
250
251	$("#QPlayer .ssBtn").on('click', function(){
252		var mA = $("#QPlayer");
253		if ($('.ssBtn .adf').hasClass('on') === false) {
254			if (isFirstPlay) {
255			    setTimeout("showTips('#player .cover','点击封面开启(关闭)随机播放', " + function(){setTimeout("showTips('#player .ctrl .musicTag','点击拖动标题栏快进(快退)')", 1000)} + ");", 500);
256			    isFirstPlay = !isFirstPlay;
257			    localStorage.qplayer = 'false';
258			}
259			mA.css("transform", "translateX(250px)");
260		    $('.ssBtn .adf').addClass('on');
261		} else {	
262			mA.css("transform", "translateX(0px)");
263            $('.ssBtn .adf').removeClass('on') 	
264		}
265	}); 
266	
267	//控制是否长期显示
268    //$("div.ssBtn").click()
269
270    $("#player .cover").on('click', function () {
271        isShuffle = !isShuffle;
272        if (isShuffle) {
273            $("#player .cover").attr("title", "点击关闭随机播放");
274            showNotification('已开启随机播放');
275
276            var temp = [];
277            for (var i = 0; i < playlist.length; i++) {
278                temp[i] = i;
279            }
280            shuffleArray = shuffle(temp);
281            for (var j = 0; j < shuffleArray.length; j++) {
282                if (shuffleArray[j] === currentTrack) {
283                    shuffleIndex = j;
284                    break;
285                }
286            }
287            localStorage.qplayer_shuffle_array = JSON.stringify(shuffleArray);
288        } else {
289            $("#player .cover").attr("title", "点击开启随机播放");
290            showNotification('已关闭随机播放');
291            localStorage.removeItem('qplayer_shuffle_array');
292        }
293        localStorage.qplayer = isShuffle;
294    });
295
296
297    var startX, endX;
298    $('#player .ctrl .musicTag').mousedown(function (event) {
299        startX = event.screenX;
300    }).mousemove(function (event) {
301        //鼠标左键
302        if (event.which === 1) {
303            endX = event.screenX;
304            var seekRange = Math.round((endX - startX) / 678 * 100);
305            audio.currentTime += seekRange;
306            setProgress(audio.currentTime);
307        }
308    });
309
310    $('#player .ctrl .musicTag').bind('touchstart', function (event) {
311        startX = event.originalEvent.targetTouches[0].screenX;
312    }).bind('touchmove', function (event) {
313        endX = event.originalEvent.targetTouches[0].screenX;
314        var seekRange = Math.round((endX - startX) / 678 * 100);
315        audio.currentTime += seekRange;
316        setProgress(audio.currentTime);
317    });
318
319})(jQuery);
320
321
322function initMarquee() {
323    $('.marquee').marquee({
324        //speed in milliseconds of the marquee
325        duration: 15000,
326        //gap in pixels between the tickers
327        gap: 50,
328        //time in milliseconds before the marquee will start animating
329        delayBeforeStart: 0,
330        //'left' or 'right'
331        direction: 'left',
332        //true or false - should the marquee be duplicated to show an effect of continues flow
333        duplicated: true
334    });
335}
336
337//检测标题和作者信息总宽度是否超出播放器,超过则返回true开启跑马灯
338function isExceedTag() {
339    var isExceedTag = false;
340    if ($('.musicTag strong').width() + $('.musicTag span').width() + $('.musicTag .artist').width() > $('.musicTag').width()) {
341        isExceedTag = true;
342    }
343    return isExceedTag;
344}
345
346
347function shuffle(array) {
348    var m = array.length,
349        t, i;
350    // 如果还剩有元素…
351    while (m) {
352        // 随机选取一个元素…
353        i = Math.floor(Math.random() * m--);
354        // 与当前元素进行交换
355        t = array[m];
356        array[m] = array[i];
357        array[i] = t;
358    }
359    return array;
360}
361
362function showNotification(info) {
363    isShowNotification = true;
364    //判断通知是否存在,存在就移除
365    if ($('.qplayer-notification').length > 0) {
366        $('.qplayer-notification').remove();
367        clearTimeout(autoClearTimer);
368        clearTimeout(autoShowTimer);
369    }
370    $('body').append('<div class="qplayer-notification animation-target"><span class="qplayer-notification-icon">i</span><span class="body" style="box-shadow: rgba(0, 0, 0, 0.0980392) 0px 0px 5px;"><span class="message"></span></span><a class="close" href="#" onclick="closeNotification();return false;">×</a><div style="clear: both"></div>');
371    $('.qplayer-notification .message').text(info);
372    //用width:auto来自动获取通知栏宽度
373    var width = $('.qplayer-notification').css({"opacity": "0", "width": "auto"}).width() + 20;
374    $('.qplayer-notification').css({"width": "50px", "opacity": "1"});
375
376    autoShowTimer = setTimeout(function () {
377        $('.qplayer-notification').css({"width": width, "transition": "all .7s ease"});
378        $('.qplayer-notification .close').delay(500).show(0);
379    }, 1500);
380    autoClearTimer = setTimeout("if ($('.qplayer-notification').length>0) {closeNotification()}", 8000);
381}
382
383
384function closeNotification() {
385    isShowNotification = false;
386    $('.qplayer-notification').css({"width": "50px", "transition": "all .7s ease"});
387    $('.qplayer-notification .close').delay(500).hide(0);
388    setTimeout(function () {
389        if (!isShowNotification) {
390            $('.qplayer-notification').css("opacity", "0");
391            $('.qplayer-notification-icon').css({"transform": "scale(0)", "transition": "transform .5s ease"});
392        }
393    }, 1000);
394    setTimeout(function () {
395        if (!isShowNotification) {
396            $('.qplayer-notification').remove();
397        }
398    }, 1500);
399    clearTimeout(autoClearTimer);
400    clearTimeout(autoShowTimer);
401}
402
403/*
404 *div: 要在其上面显示tip的div
405 *info: tip内容
406 *func: 不再提示按钮的click绑定函数
407 */
408function showTips(div, info, func) {
409    var box_height = 100;
410    $('body').append('<div class="qplayer_tips"><span class="tips_arrow"></span><span class="info" style="display:none">' + info + '</span><button class="tips_button" onclick="removeTips()">不再提示</button></div>');
411    $('.qplayer_tips').css({"top": $(div).offset().top - box_height - 30 - 15, "left": $(div).offset().left - 28});
412    $('.qplayer_tips').css({"height": box_height, "transition": "all .5s ease-in-out"});
413    $('.qplayer_tips .info').delay(500).fadeIn();
414    $('.tips_arrow').css({"border-width": "15px", "transition": "all .5s ease-in-out"});
415    $('.tips_button').css({"height": "30px", "transition": "all .5s ease-in-out"});
416    if (func != undefined) {
417        $('.tips_button').click(func);
418    }
419}
420
421function removeTips() {
422    $('.qplayer_tips .info').fadeOut();
423    $('.qplayer_tips').css({"height": "0", "transition": "all .5s ease-in-out"});
424    $('.tips_arrow').css({"border-width": "0", "transition": "all .5s ease-in-out"});
425    $('.tips_button').css({"opacity": "0", "transition": "all .2s ease-in-out"});
426    setTimeout(function () {
427        $('.qplayer_tips').remove()
428    }, 500);
429}

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.