functions.js 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900
  1. /**************************************************
  2. * MKOnlinePlayer v2.4
  3. * 封装函数及UI交互模块
  4. * 编写:mengkun(https://mkblog.cn)
  5. * 时间:2018-3-11
  6. *************************************************/
  7. // 判断是否是移动设备
  8. var isMobile = {
  9. Android: function() {
  10. return navigator.userAgent.match(/Android/i) ? true : false;
  11. },
  12. BlackBerry: function() {
  13. return navigator.userAgent.match(/BlackBerry/i) ? true : false;
  14. },
  15. iOS: function() {
  16. return navigator.userAgent.match(/iPhone|iPad|iPod/i) ? true : false;
  17. },
  18. Windows: function() {
  19. return navigator.userAgent.match(/IEMobile/i) ? true : false;
  20. },
  21. any: function() {
  22. return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Windows());
  23. }
  24. };
  25. $(function(){
  26. if(mkPlayer.debug) {
  27. console.warn('播放器调试模式已开启,正常使用时请在 js/player.js 中按说明关闭调试模式');
  28. }
  29. rem.isMobile = isMobile.any(); // 判断是否是移动设备
  30. rem.webTitle = document.title; // 记录页面原本的标题
  31. rem.errCount = 0; // 连续播放失败的歌曲数归零
  32. initProgress(); // 初始化音量条、进度条(进度条初始化要在 Audio 前,别问我为什么……)
  33. initAudio(); // 初始化 audio 标签,事件绑定
  34. if(rem.isMobile) { // 加了滚动条插件和没加滚动条插件所操作的对象是不一样的
  35. rem.sheetList = $("#sheet");
  36. rem.mainList = $("#main-list");
  37. } else {
  38. // 滚动条初始化(只在非移动端启用滚动条控件)
  39. $("#main-list,#sheet").mCustomScrollbar({
  40. theme:"minimal",
  41. advanced:{
  42. updateOnContentResize: true // 数据更新后自动刷新滚动条
  43. }
  44. });
  45. rem.sheetList = $("#sheet .mCSB_container");
  46. rem.mainList = $("#main-list .mCSB_container");
  47. }
  48. addListhead(); // 列表头
  49. addListbar("loading"); // 列表加载中
  50. // 顶部按钮点击处理
  51. $(".btn").click(function(){
  52. switch($(this).data("action")) {
  53. case "player": // 播放器
  54. dataBox("player");
  55. break;
  56. case "search": // 搜索
  57. searchBox();
  58. break;
  59. case "playing": // 正在播放
  60. loadList(1); // 显示正在播放列表
  61. break;
  62. case "sheet": // 播放列表
  63. dataBox("sheet"); // 在主界面显示出音乐专辑
  64. break;
  65. }
  66. });
  67. // 列表项双击播放
  68. $(".music-list").on("dblclick",".list-item", function() {
  69. var num = parseInt($(this).data("no"));
  70. if(isNaN(num)) return false;
  71. listClick(num);
  72. });
  73. // 移动端列表项单击播放
  74. $(".music-list").on("click",".list-item", function() {
  75. if(rem.isMobile) {
  76. var num = parseInt($(this).data("no"));
  77. if(isNaN(num)) return false;
  78. listClick(num);
  79. }
  80. });
  81. // 小屏幕点击右侧小点查看歌曲详细信息
  82. $(".music-list").on("click",".list-mobile-menu", function() {
  83. var num = parseInt($(this).parent().data("no"));
  84. musicInfo(rem.dislist, num);
  85. return false;
  86. });
  87. // 列表鼠标移过显示对应的操作按钮
  88. $(".music-list").on("mousemove",".list-item", function() {
  89. var num = parseInt($(this).data("no"));
  90. if(isNaN(num)) return false;
  91. // 还没有追加菜单则加上菜单
  92. if(!$(this).data("loadmenu")) {
  93. var target = $(this).find(".music-name");
  94. var html = '<span class="music-name-cult">' +
  95. target.html() +
  96. '</span>' +
  97. '<div class="list-menu" data-no="' + num + '">' +
  98. '<span class="list-icon icon-play" data-function="play" title="点击播放这首歌"></span>' +
  99. '<span class="list-icon icon-download" data-function="download" title="点击下载这首歌"></span>' +
  100. '<span class="list-icon icon-share" data-function="share" title="点击分享这首歌"></span>' +
  101. '</div>';
  102. target.html(html);
  103. $(this).data("loadmenu", true);
  104. }
  105. });
  106. // 列表中的菜单点击
  107. $(".music-list").on("click",".icon-play,.icon-download,.icon-share", function() {
  108. var num = parseInt($(this).parent().data("no"));
  109. if(isNaN(num)) return false;
  110. switch($(this).data("function")) {
  111. case "play": // 播放
  112. listClick(num); // 调用列表点击处理函数
  113. break;
  114. case "download": // 下载
  115. ajaxUrl(musicList[rem.dislist].item[num], download);
  116. break;
  117. case "share": // 分享
  118. // ajax 请求数据
  119. ajaxUrl(musicList[rem.dislist].item[num], ajaxShare);
  120. break;
  121. }
  122. return true;
  123. });
  124. // 点击加载更多
  125. $(".music-list").on("click",".list-loadmore", function() {
  126. $(".list-loadmore").removeClass('list-loadmore');
  127. $(".list-loadmore").html('加载中...');
  128. ajaxSearch();
  129. });
  130. // 点击专辑显示专辑歌曲
  131. $("#sheet").on("click",".sheet-cover,.sheet-name", function() {
  132. var num = parseInt($(this).parent().data("no"));
  133. // 是用户列表,但是还没有加载数据
  134. if(musicList[num].item.length === 0 && musicList[num].creatorID) {
  135. layer.msg('列表读取中...', {icon: 16,shade: 0.01,time: 500}); // 0代表加载的风格,支持0-2
  136. // ajax加载数据
  137. ajaxPlayList(musicList[num].id, num, loadList);
  138. return true;
  139. }
  140. loadList(num);
  141. });
  142. // 点击同步云音乐
  143. $("#sheet").on("click",".login-in", function() {
  144. layer.prompt(
  145. {
  146. title: '请输入您的网易云 UID',
  147. closeBtn: false,
  148. // value: '', // 默认值
  149. btn: ['<span class="iconfont icon-edit" style="font-size:15px;font-weight:800;"></span> 确定', '<span class="iconfont icon-logout" style="font-size:15px;font-weight:800;"></span> 取消', '<span class="iconfont icon-profile" style="font-size:15px;font-weight:800;"></span> 帮助'],
  150. btn3: function(index, layero){
  151. layer.open({
  152. title: '如何获取您的网易云UID?'
  153. ,closeBtn: false
  154. ,btn: ['<span class="iconfont icon-logout" style="font-size:15px;font-weight:800;"></span> 知道啦']
  155. ,area: '280px;'
  156. ,shade: 0.6 //遮罩透明度
  157. ,anim: -1 //0-6的动画形式,-1不开启
  158. ,content:
  159. '1、首先<a href="http://music.163.com/" target="_blank" style="color:#fa8587">点我(http://music.163.com/)</a>打开网易云音乐官网<br>' +
  160. '2、然后点击页面右上角的“登录”,登录您的账号<br>' +
  161. '3、点击您的头像,进入个人中心<br>' +
  162. '4、此时浏览器地址栏 <span style="color:#fa8587">/user/home?id=</span> 后面的<span style="color:#fa8587">数字</span>就是您的网易云 UID'
  163. });
  164. }
  165. },
  166. function(val, index){ // 输入后的回调函数
  167. if(isNaN(val)) {
  168. layer.msg('uid 只能是数字',{anim: 6});
  169. return false;
  170. }
  171. layer.close(index); // 关闭输入框
  172. ajaxUserList(val);
  173. });
  174. });
  175. // 刷新用户列表
  176. $("#sheet").on("click",".login-refresh", function() {
  177. playerSavedata('ulist', '');
  178. layer.msg('刷新歌单');
  179. clearUserlist();
  180. });
  181. // 退出登录
  182. $("#sheet").on("click",".login-out", function() {
  183. playerSavedata('uid', '');
  184. playerSavedata('ulist', '');
  185. layer.msg('已退出');
  186. clearUserlist();
  187. });
  188. // 播放、暂停按钮的处理
  189. $("#music-info").click(function(){
  190. if(rem.playid === undefined) {
  191. layer.msg('请先播放歌曲');
  192. return false;
  193. }
  194. musicInfo(rem.playlist, rem.playid);
  195. });
  196. // 播放、暂停按钮的处理
  197. $(".btn-play").click(function(){
  198. pause();
  199. });
  200. // 循环顺序的处理
  201. $(".btn-order").click(function(){
  202. orderChange();
  203. });
  204. // 上一首歌
  205. $(".btn-prev").click(function(){
  206. prevMusic();
  207. });
  208. // 下一首
  209. $(".btn-next").click(function(){
  210. nextMusic();
  211. });
  212. // 静音按钮点击事件
  213. $(".btn-quiet").click(function(){
  214. var oldVol; // 之前的音量值
  215. if($(this).is('.btn-state-quiet')) {
  216. oldVol = $(this).data("volume");
  217. oldVol = oldVol? oldVol: (rem.isMobile? 1: mkPlayer.volume); // 没找到记录的音量,则重置为默认音量
  218. $(this).removeClass("btn-state-quiet"); // 取消静音
  219. } else {
  220. oldVol = volume_bar.percent;
  221. $(this).addClass("btn-state-quiet"); // 开启静音
  222. $(this).data("volume", oldVol); // 记录当前音量值
  223. oldVol = 0;
  224. }
  225. playerSavedata('volume', oldVol); // 存储音量信息
  226. volume_bar.goto(oldVol); // 刷新音量显示
  227. if(rem.audio[0] !== undefined) rem.audio[0].volume = oldVol; // 应用音量
  228. });
  229. if((mkPlayer.coverbg === true && !rem.isMobile) || (mkPlayer.mcoverbg === true && rem.isMobile)) { // 开启了封面背景
  230. if(rem.isMobile) { // 移动端采用另一种模糊方案
  231. $('#blur-img').html('<div class="blured-img" id="mobile-blur"></div><div class="blur-mask mobile-mask"></div>');
  232. } else {
  233. // 背景图片初始化
  234. $('#blur-img').backgroundBlur({
  235. // imageURL : '', // URL to the image that will be used for blurring
  236. blurAmount : 50, // 模糊度
  237. imageClass : 'blured-img', // 背景区应用样式
  238. overlayClass : 'blur-mask', // 覆盖背景区class,可用于遮罩或额外的效果
  239. // duration: 0, // 图片淡出时间
  240. endOpacity : 1 // 图像最终的不透明度
  241. });
  242. }
  243. $('.blur-mask').fadeIn(1000); // 遮罩层淡出
  244. }
  245. // 图片加载失败处理
  246. $('img').error(function(){
  247. $(this).attr('src', 'images/player_cover.png');
  248. });
  249. // 初始化播放列表
  250. initList();
  251. });
  252. // 展现系统列表中任意首歌的歌曲信息
  253. function musicInfo(list, index) {
  254. var music = musicList[list].item[index];
  255. var tempStr = '<div style="padding: 20px; line-height: 22px; background-color: #393D49; color: #fff; font-weight: 300;"><span class="info-title">歌名:</span>' + music.name +
  256. '<br><span class="info-title">歌手:</span>' + music.artist +
  257. '<br><span class="info-title">专辑:</span>' + music.album;
  258. if(list == rem.playlist && index == rem.playid) { // 当前正在播放这首歌,那么还可以顺便获取一下时长。。
  259. tempStr += '<br><span class="info-title">时长:</span>' + formatTime(rem.audio[0].duration);
  260. }
  261. tempStr += '<br><span class="info-title">操作:</span>' +
  262. '<span class="info-btn" onclick="thisDownload(this)" data-list="' + list + '" data-index="' + index + '">下载</span>' +
  263. '<span style="margin-left: 10px" class="info-btn" onclick="thisShare(this)" data-list="' + list + '" data-index="' + index + '">&nbsp;外链</span></div>';
  264. layer.open({
  265. type: 1,
  266. title: false, //不显示标题栏
  267. closeBtn: false,
  268. area: '240px;',
  269. shade: 0.8,
  270. id: 'LAY_layuipro',
  271. resize: false,
  272. btn: ['<span class="iconfont icon-logout" style="font-size:15px;font-weight:800;"></span> 关闭'],
  273. btnAlign: 'c',
  274. moveType: 1, //拖拽模式,0或者1
  275. content: tempStr,
  276. });
  277. if(mkPlayer.debug) {
  278. console.info('id: "' + music.id + '",\n' +
  279. 'name: "' + music.name + '",\n' +
  280. 'artist: "' + music.artist + '",\n' +
  281. 'album: "' + music.album + '",\n' +
  282. 'source: "' + music.source + '",\n' +
  283. 'url_id: "' + music.url_id + '",\n' +
  284. 'pic_id: "' + music.pic_id + '",\n' +
  285. 'lyric_id: "' + music.lyric_id + '",\n' +
  286. 'pic: "' + music.pic + '",\n' +
  287. 'url: ""');
  288. // 'url: "' + music.url + '"');
  289. }
  290. }
  291. // 展现搜索弹窗
  292. function searchBox() {
  293. var tmpHtml = '<form onSubmit="return searchSubmit()"><div id="search-area">' +
  294. ' <div class="search-group">' +
  295. ' <input type="text" name="wd" id="search-wd" placeholder="搜索歌手、歌名、专辑" autofocus >' +
  296. ' <button class="search-submit" type="submit"><span class="iconfont icon-search2"></span></button>' +
  297. ' </div>' +
  298. ' <div class="radio-group" id="music-source">' +
  299. ' <label class="leo-label"><input class="leo-radio" type="radio" name="source" value="netease" checked=""><span class="leo-radioInput"></span><img class="leo-img" src="images/s-netease.png"> </label>' +
  300. ' <label class="leo-label"><input class="leo-radio" type="radio" name="source" value="tencent"><span class="leo-radioInput"></span><img class="leo-img" src="images/s-qq.png"></label>' +
  301. ' <label class="leo-label"><input class="leo-radio" type="radio" name="source" value="xiami"><span class="leo-radioInput"></span><img class="leo-img" src="images/s-xiami.png"></label>' +
  302. ' <label class="leo-label"><input class="leo-radio" type="radio" name="source" value="kugou"><span class="leo-radioInput"></span><img class="leo-img" src="images/s-kugou.png"></label>' +
  303. ' <label class="leo-label"><input class="leo-radio" type="radio" name="source" value="baidu"><span class="leo-radioInput"></span><img class="leo-img" src="images/s-baidu.png"></label>' +
  304. ' </div>' +
  305. '</div></form>';
  306. layer.open({
  307. title: '搜一搜你最爱的歌'
  308. ,closeBtn: false
  309. ,area: '280px;'
  310. ,shade: 0.6 //遮罩透明度
  311. ,btn: ['<span class="iconfont icon-logout" style="font-size:15px;font-weight:800;"></span> 关闭']
  312. ,anim: -1 //0-6的动画形式,-1不开启
  313. ,content: tmpHtml,
  314. cancel: function(){
  315. }
  316. });
  317. // 恢复上一次的输入
  318. $("#search-wd").focus().val(rem.wd);
  319. $("#music-source input[name='source'][value='" + rem.source + "']").prop("checked", "checked");
  320. }
  321. // 搜索提交
  322. function searchSubmit() {
  323. var wd = $("#search-wd").val();
  324. if(!wd) {
  325. layer.msg('搜索内容不能为空');
  326. $("#search-wd").focus();
  327. return false;
  328. }
  329. rem.source = $("#music-source input[name='source']:checked").val();
  330. layer.closeAll('page'); // 关闭搜索框
  331. rem.loadPage = 1; // 已加载页数复位
  332. rem.wd = wd; // 搜索词
  333. ajaxSearch(); // 加载搜索结果
  334. return false;
  335. }
  336. // 下载正在播放的这首歌
  337. function thisDownload(obj) {
  338. ajaxUrl(musicList[$(obj).data("list")].item[$(obj).data("index")], download);
  339. }
  340. // 分享正在播放的这首歌
  341. function thisShare(obj) {
  342. ajaxUrl(musicList[$(obj).data("list")].item[$(obj).data("index")], ajaxShare);
  343. }
  344. // 下载歌曲
  345. // 参数:包含歌曲信息的数组
  346. function download(music) {
  347. if(music.url == 'err' || music.url == "" || music.url == null) {
  348. layer.msg('这首歌不支持下载');
  349. return;
  350. }
  351. openDownloadDialog(music.url, music.name + ' - ' + music.artist);
  352. }
  353. /**
  354. * 通用的打开下载对话框方法,没有测试过具体兼容性
  355. * @param url 下载地址,也可以是一个blob对象,必选
  356. * @param saveName 保存文件名,可选
  357. * http://www.cnblogs.com/liuxianan/p/js-download.html
  358. */
  359. function openDownloadDialog(url, saveName)
  360. {
  361. if(typeof url == 'object' && url instanceof Blob)
  362. {
  363. url = URL.createObjectURL(url); // 创建blob地址
  364. }
  365. var aLink = document.createElement('a');
  366. aLink.href = url;
  367. aLink.target = "_blank";
  368. aLink.download = saveName || ''; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
  369. var event;
  370. if(window.MouseEvent) event = new MouseEvent('click');
  371. else
  372. {
  373. event = document.createEvent('MouseEvents');
  374. event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
  375. }
  376. aLink.dispatchEvent(event);
  377. }
  378. // 获取外链的ajax回调函数
  379. // 参数:包含音乐信息的数组
  380. function ajaxShare(music) {
  381. if(music.url == 'err' || music.url == "" || music.url == null) {
  382. layer.msg('这首歌不支持外链获取');
  383. return;
  384. }
  385. var tmpHtml = '<p>' + music.artist + ' - ' + music.name + ' 的外链地址为:</p>' +
  386. '<input class="share-url" onmouseover="this.focus();this.select()" value="' + music.url + '">' +
  387. '<p class="share-tips">* 获取到的音乐外链有效期较短,请按需使用。</p>';
  388. layer.open({
  389. title: '歌曲外链分享'
  390. ,closeBtn: false
  391. ,btn: ['<span class="iconfont icon-logout" style="font-size:15px;font-weight:800;"></span> 关闭']
  392. ,content: tmpHtml
  393. });
  394. }
  395. // 改变右侧封面图像
  396. // 新的图像地址
  397. function changeCover(music) {
  398. var img = music.pic; // 获取歌曲封面
  399. var animate = false,imgload = false;
  400. if(!img) { // 封面为空
  401. ajaxPic(music, changeCover); // 获取歌曲封面图
  402. img == "err"; // 暂时用无图像占个位...
  403. }
  404. if(img == "err") {
  405. img = "images/player_cover.png";
  406. } else {
  407. if(mkPlayer.mcoverbg === true && rem.isMobile) // 移动端封面
  408. {
  409. $("#music-cover").load(function(){
  410. $("#mobile-blur").css('background-image', 'url("' + img + '")');
  411. });
  412. }
  413. else if(mkPlayer.coverbg === true && !rem.isMobile) // PC端封面
  414. {
  415. $("#music-cover").load(function(){
  416. if(animate) { // 渐变动画也已完成
  417. $("#blur-img").backgroundBlur(img); // 替换图像并淡出
  418. $("#blur-img").animate({opacity:"1"}, 2000); // 背景更换特效
  419. } else {
  420. imgload = true; // 告诉下面的函数,图片已准备好
  421. }
  422. });
  423. // 渐变动画
  424. $("#blur-img").animate({opacity: "0.2"}, 1000, function(){
  425. if(imgload) { // 如果图片已经加载好了
  426. $("#blur-img").backgroundBlur(img); // 替换图像并淡出
  427. $("#blur-img").animate({opacity:"1"}, 2000); // 背景更换特效
  428. } else {
  429. animate = true; // 等待图像加载完
  430. }
  431. });
  432. }
  433. }
  434. $("#music-cover").attr("src", img); // 改变右侧封面
  435. $(".sheet-item[data-no='1'] .sheet-cover").attr('src', img); // 改变正在播放列表的图像
  436. }
  437. // 向列表中载入某个播放列表
  438. function loadList(list) {
  439. if(musicList[list].isloading === true) {
  440. layer.msg('列表读取中...', {icon: 16,shade: 0.01,time: 500});
  441. return true;
  442. }
  443. rem.dislist = list; // 记录当前显示的列表
  444. dataBox("list"); // 在主界面显示出播放列表
  445. // 调试信息输出
  446. if(mkPlayer.debug) {
  447. if(musicList[list].id) {
  448. console.log('加载播放列表 ' + list + ' - ' + musicList[list].name + '\n' +
  449. 'id: ' + musicList[list].id + ',\n' +
  450. 'name: "' + musicList[list].name + '",\n' +
  451. 'cover: "' + musicList[list].cover + '",\n' +
  452. 'item: []');
  453. } else {
  454. console.log('加载播放列表 ' + list + ' - ' + musicList[list].name);
  455. }
  456. }
  457. rem.mainList.html(''); // 清空列表中原有的元素
  458. addListhead(); // 向列表中加入列表头
  459. if(musicList[list].item.length == 0) {
  460. addListbar("nodata"); // 列表中没有数据
  461. } else {
  462. // 逐项添加数据
  463. for(var i=0; i<musicList[list].item.length; i++) {
  464. var tmpMusic = musicList[list].item[i];
  465. addItem(i + 1, tmpMusic.name, tmpMusic.artist, tmpMusic.album);
  466. // 音乐链接均有有效期限制,重新显示列表时清空处理
  467. if(list == 1 || list == 2) tmpMusic.url = "";
  468. }
  469. // 列表加载完成后的处理
  470. if(list == 1 || list == 2) { // 历史记录和正在播放列表允许清空
  471. addListbar("clear"); // 清空列表
  472. }
  473. if(rem.playlist === undefined) { // 未曾播放过
  474. if(mkPlayer.autoplay == true) pause(); // 设置了自动播放,则自动播放
  475. } else {
  476. refreshList(); // 刷新列表,添加正在播放样式
  477. }
  478. listToTop(); // 播放列表滚动到顶部
  479. }
  480. }
  481. // 播放列表滚动到顶部
  482. function listToTop() {
  483. if(rem.isMobile) {
  484. $("#main-list").animate({scrollTop: 0}, 200);
  485. } else {
  486. $("#main-list").mCustomScrollbar("scrollTo", 0, "top");
  487. }
  488. }
  489. // 向列表中加入列表头
  490. function addListhead() {
  491. var html = '<div class="list-item list-head">' +
  492. ' <span class="music-album">' +
  493. ' 专辑' +
  494. ' </span>' +
  495. ' <span class="auth-name">' +
  496. ' 歌手' +
  497. ' </span>' +
  498. ' <span class="music-name">' +
  499. ' 歌曲' +
  500. ' </span>' +
  501. '</div>';
  502. rem.mainList.append(html);
  503. }
  504. // 列表中新增一项
  505. // 参数:编号、名字、歌手、专辑
  506. function addItem(no, name, auth, album) {
  507. var html = '<div class="list-item" data-no="' + (no - 1) + '">' +
  508. ' <span class="list-num">' + no + '</span>' +
  509. ' <span class="list-mobile-menu"></span>' +
  510. ' <span class="music-album">' + album + '</span>' +
  511. ' <span class="auth-name">' + auth + '</span>' +
  512. ' <span class="music-name">' + name + '</span>' +
  513. '</div>';
  514. rem.mainList.append(html);
  515. }
  516. // 加载列表中的提示条
  517. // 参数:类型(more、nomore、loading、nodata、clear)
  518. function addListbar(types) {
  519. var html
  520. switch(types) {
  521. case "more": // 还可以加载更多
  522. html = '<div class="list-item text-center list-loadmore list-clickable" title="点击加载更多数据" id="list-foot">点击加载更多...</div>';
  523. break;
  524. case "nomore": // 数据加载完了
  525. html = '<div class="list-item text-center" id="list-foot">全都加载完了</div>';
  526. break;
  527. case "loading": // 加载中
  528. html = '<div class="list-item text-center" id="list-foot">播放列表加载中...</div>';
  529. break;
  530. case "nodata": // 列表中没有内容
  531. html = '<div class="list-item text-center" id="list-foot">获取列表失败,请刷新重试...</div>';
  532. break;
  533. case "clear": // 清空列表
  534. html = '<div class="list-item text-center list-clickable" id="list-foot" onclick="clearDislist();">清空列表</div>';
  535. break;
  536. }
  537. rem.mainList.append(html);
  538. }
  539. // 将时间格式化为 00:00 的格式
  540. // 参数:原始时间
  541. function formatTime(time){
  542. var hour,minute,second;
  543. hour = String(parseInt(time/3600,10));
  544. if(hour.length == 1) hour='0' + hour;
  545. minute=String(parseInt((time%3600)/60,10));
  546. if(minute.length == 1) minute='0'+minute;
  547. second=String(parseInt(time%60,10));
  548. if(second.length == 1) second='0'+second;
  549. if(hour > 0) {
  550. return hour + ":" + minute + ":" + second;
  551. } else {
  552. return minute + ":" + second;
  553. }
  554. }
  555. // url编码
  556. // 输入参数:待编码的字符串
  557. function urlEncode(String) {
  558. return encodeURIComponent(String).replace(/'/g,"%27").replace(/"/g,"%22");
  559. }
  560. // 在 ajax 获取了音乐的信息后再进行更新
  561. // 参数:要进行更新的音乐
  562. function updateMinfo(music) {
  563. // 不含有 id 的歌曲无法更新
  564. if(!music.id) return false;
  565. // 循环查找播放列表并更新信息
  566. for(var i=0; i<musicList.length; i++) {
  567. for(var j=0; j<musicList[i].item.length; j++) {
  568. // ID 对上了,那就更新信息
  569. if(musicList[i].item[j].id == music.id && musicList[i].item[j].source == music.source) {
  570. musicList[i].item[j] == music; // 更新音乐信息
  571. j = musicList[i].item.length; // 一个列表中只找一首,找到了就跳出
  572. }
  573. }
  574. }
  575. }
  576. // 刷新当前显示的列表,如果有正在播放则添加样式
  577. function refreshList() {
  578. // 还没播放过,不用对比了
  579. if(rem.playlist === undefined) return true;
  580. $(".list-playing").removeClass("list-playing"); // 移除其它的正在播放
  581. if(rem.paused !== true) { // 没有暂停
  582. for(var i=0; i<musicList[rem.dislist].item.length; i++) {
  583. // 与正在播放的歌曲 id 相同
  584. if((musicList[rem.dislist].item[i].id !== undefined) &&
  585. (musicList[rem.dislist].item[i].id == musicList[1].item[rem.playid].id) &&
  586. (musicList[rem.dislist].item[i].source == musicList[1].item[rem.playid].source)) {
  587. $(".list-item[data-no='" + i + "']").addClass("list-playing"); // 添加正在播放样式
  588. return true; // 一般列表中只有一首,找到了赶紧跳出
  589. }
  590. }
  591. }
  592. }
  593. // 添加一个歌单
  594. // 参数:编号、歌单名字、歌单封面
  595. function addSheet(no, name, cover) {
  596. if(!cover) cover = "images/player_cover.png";
  597. if(!name) name = "读取中...";
  598. var html = '<div class="sheet-item" data-no="' + no + '">' +
  599. ' <img class="sheet-cover" src="' +cover+ '">' +
  600. ' <p class="sheet-name">' +name+ '</p>' +
  601. '</div>';
  602. rem.sheetList.append(html);
  603. }
  604. // 清空歌单显示
  605. function clearSheet() {
  606. rem.sheetList.html('');
  607. }
  608. // 歌单列表底部登陆条
  609. function sheetBar() {
  610. var barHtml;
  611. if(playerReaddata('uid')) {
  612. barHtml = '已同步 ' + rem.uname + ' 的歌单 <span class="login-btn login-refresh">[刷新]</span> <span class="login-btn login-out">[退出]</span>';
  613. } else {
  614. barHtml = '我的歌单 <span class="login-btn login-in">[点击同步]</span>';
  615. }
  616. barHtml = '<span id="sheet-bar"><div class="clear-fix"></div>' +
  617. '<div id="user-login" class="sheet-title-bar">' + barHtml +
  618. '</div></span>';
  619. rem.sheetList.append(barHtml);
  620. }
  621. // 选择要显示哪个数据区
  622. // 参数:要显示的数据区(list、sheet、player)
  623. function dataBox(choose) {
  624. $('.btn-box .active').removeClass('active');
  625. switch(choose) {
  626. case "list": // 显示播放列表
  627. if($(".btn[data-action='player']").css('display') !== 'none') {
  628. $("#player").hide();
  629. } else if ($("#player").css('display') == 'none') {
  630. $("#player").fadeIn();
  631. }
  632. $("#main-list").fadeIn();
  633. $("#sheet").fadeOut();
  634. if(rem.dislist == 1 || rem.dislist == rem.playlist) { // 正在播放
  635. $(".btn[data-action='playing']").addClass('active');
  636. } else if(rem.dislist == 0) { // 搜索
  637. $(".btn[data-action='search']").addClass('active');
  638. }
  639. break;
  640. case "sheet": // 显示专辑
  641. if($(".btn[data-action='player']").css('display') !== 'none') {
  642. $("#player").hide();
  643. } else if ($("#player").css('display') == 'none') {
  644. $("#player").fadeIn();
  645. }
  646. $("#sheet").fadeIn();
  647. $("#main-list").fadeOut();
  648. $(".btn[data-action='sheet']").addClass('active');
  649. break;
  650. case "player": // 显示播放器
  651. $("#player").fadeIn();
  652. $("#sheet").fadeOut();
  653. $("#main-list").fadeOut();
  654. $(".btn[data-action='player']").addClass('active');
  655. break;
  656. }
  657. }
  658. // 将当前歌曲加入播放历史
  659. // 参数:要添加的音乐
  660. function addHis(music) {
  661. if(rem.playlist == 2) return true; // 在播放“播放记录”列表则不作改变
  662. if(musicList[2].item.length > 300) musicList[2].item.length = 299; // 限定播放历史最多是 300 首
  663. if(music.id !== undefined && music.id !== '') {
  664. // 检查历史数据中是否有这首歌,如果有则提至前面
  665. for(var i=0; i<musicList[2].item.length; i++) {
  666. if(musicList[2].item[i].id == music.id && musicList[2].item[i].source == music.source) {
  667. musicList[2].item.splice(i, 1); // 先删除相同的
  668. i = musicList[2].item.length; // 找到了,跳出循环
  669. }
  670. }
  671. }
  672. // 再放到第一位
  673. musicList[2].item.unshift(music);
  674. playerSavedata('his', musicList[2].item); // 保存播放历史列表
  675. }
  676. // 初始化播放列表
  677. function initList() {
  678. // 登陆过,那就读取出用户的歌单,并追加到系统歌单的后面
  679. if(playerReaddata('uid')) {
  680. rem.uid = playerReaddata('uid');
  681. rem.uname = playerReaddata('uname');
  682. // musicList.push(playerReaddata('ulist'));
  683. var tmp_ulist = playerReaddata('ulist'); // 读取本地记录的用户歌单
  684. if(tmp_ulist) musicList.push.apply(musicList, tmp_ulist); // 追加到系统歌单的后面
  685. }
  686. // 显示所有的歌单
  687. for(var i=1; i<musicList.length; i++) {
  688. if(i == 1) { // 正在播放列表
  689. // 读取正在播放列表
  690. var tmp_item = playerReaddata('playing');
  691. if(tmp_item) { // 读取到了正在播放列表
  692. musicList[1].item = tmp_item;
  693. mkPlayer.defaultlist = 1; // 默认显示正在播放列表
  694. }
  695. } else if(i == 2) { // 历史记录列表
  696. // 读取历史记录
  697. var tmp_item = playerReaddata('his');
  698. if(tmp_item) {
  699. musicList[2].item = tmp_item;
  700. }
  701. // 列表不是用户列表,并且信息为空,需要ajax读取列表
  702. }else if(!musicList[i].creatorID && (musicList[i].item == undefined || (i>2 && musicList[i].item.length == 0))) {
  703. musicList[i].item = [];
  704. if(musicList[i].id) { // 列表ID已定义
  705. // ajax获取列表信息
  706. ajaxPlayList(musicList[i].id, i);
  707. } else { // 列表 ID 未定义
  708. if(!musicList[i].name) musicList[i].name = '未命名';
  709. }
  710. }
  711. // 在前端显示出来
  712. addSheet(i, musicList[i].name, musicList[i].cover);
  713. }
  714. // 登陆了,但歌单又没有,说明是在刷新歌单
  715. if(playerReaddata('uid') && !tmp_ulist) {
  716. ajaxUserList(rem.uid);
  717. return true;
  718. }
  719. // 首页显示默认列表
  720. if(mkPlayer.defaultlist >= musicList.length) mkPlayer.defaultlist = 1; // 超出范围,显示正在播放列表
  721. if(musicList[mkPlayer.defaultlist].isloading !== true) loadList(mkPlayer.defaultlist);
  722. // 显示最后一项登陆条
  723. sheetBar();
  724. }
  725. // 清空用户的同步列表
  726. function clearUserlist() {
  727. if(!rem.uid) return false;
  728. // 查找用户歌单起点
  729. for(var i=1; i<musicList.length; i++) {
  730. if(musicList[i].creatorID !== undefined && musicList[i].creatorID == rem.uid) break; // 找到了就退出
  731. }
  732. // 删除记忆数组
  733. musicList.splice(i, musicList.length - i); // 先删除相同的
  734. musicList.length = i;
  735. // 刷新列表显示
  736. clearSheet();
  737. initList();
  738. }
  739. // 清空当前显示的列表
  740. function clearDislist() {
  741. musicList[rem.dislist].item.length = 0; // 清空内容
  742. if(rem.dislist == 1) { // 正在播放列表
  743. playerSavedata('playing', ''); // 清空本地记录
  744. $(".sheet-item[data-no='1'] .sheet-cover").attr('src', 'images/player_cover.png'); // 恢复正在播放的封面
  745. } else if(rem.dislist == 2) { // 播放记录
  746. playerSavedata('his', ''); // 清空本地记录
  747. }
  748. layer.msg('列表已被清空');
  749. dataBox("sheet"); // 在主界面显示出音乐专辑
  750. }
  751. // 刷新播放列表,为正在播放的项添加正在播放中的标识
  752. function refreshSheet() {
  753. // 调试信息输出
  754. if(mkPlayer.debug) {
  755. console.log("开始播放列表 " + musicList[rem.playlist].name + " 中的歌曲");
  756. }
  757. $(".sheet-playing").removeClass("sheet-playing"); // 移除其它的正在播放
  758. $(".sheet-item[data-no='" + rem.playlist + "']").addClass("sheet-playing"); // 添加样式
  759. }
  760. // 播放器本地存储信息
  761. // 参数:键值、数据
  762. function playerSavedata(key, data) {
  763. key = 'mkPlayer2_' + key; // 添加前缀,防止串用
  764. data = JSON.stringify(data);
  765. // 存储,IE6~7 不支持HTML5本地存储
  766. if (window.localStorage) {
  767. localStorage.setItem(key, data);
  768. }
  769. }
  770. // 播放器读取本地存储信息
  771. // 参数:键值
  772. // 返回:数据
  773. function playerReaddata(key) {
  774. if(!window.localStorage) return '';
  775. key = 'mkPlayer2_' + key;
  776. return JSON.parse(localStorage.getItem(key));
  777. }