function Music() { this.init(); } // 定义一个名为 'Music' 的构造函数,当创建 'Music' 类的实例时,会自动调用 'init' 方法,用于初始化音乐相关的一些设置和绑定事件等操作,这是面向对象编程中构造函数的常见用法,用于创建具有特定功能和属性的对象实例。 (function () { var pages = [], panels = [], selectedItem = null; // 创建三个私有变量,'pages' 数组用于存储分页相关的元素标识(可能是页面上分页按钮等元素的 ID 之类),'panels' 数组用于存储页面面板相关的元素标识(可能是用于展示不同页面内容的面板元素 ID),'selectedItem' 初始化为 null,用于记录用户选择的音乐相关信息(比如歌曲对象等),这几个变量在函数内部使用,外部无法直接访问,起到了数据封装的作用。 Music.prototype = { total: 70, pageSize: 10, dataUrl: "http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.search.common", playerUrl: "http://box.baidu.com/widget/flash/bdspacesong.swf", // 在 'Music' 类的原型对象上定义了四个属性。'total' 表示总的数据量(可能是搜索结果的总数之类),初始值为 70;'pageSize' 表示每页显示的数据条数,初始值为 10,用于分页功能相关计算;'dataUrl' 定义了获取音乐数据的 API 地址,指向百度音乐的一个搜索接口,通过向这个接口发送请求来获取音乐相关信息;'playerUrl' 定义了音乐播放器对应的 Flash 文件的 URL 地址,用于后续创建音乐播放相关的 HTML 元素嵌入到页面中实现音乐播放功能。 init: function () { var me = this; // 在 'init' 方法内部,首先将当前对象(this)赋值给变量'me',方便在内部函数中引用外部对象的属性和方法,这是一种常见的解决 JavaScript 中 this 指针指向问题的技巧,尤其是在事件回调函数中使用时。 domUtils.on($G("J_searchName"), "keyup", function (event) { var e = window.event || event; if (e.keyCode == 13) { me.dosearch(); } }); // 使用 'domUtils'(可能是自定义的 DOM 操作工具对象,包含处理 DOM 事件绑定等功能的函数)的 'on' 方法,为页面中 id 为 'J_searchName' 的元素(可能是一个输入框,用于输入搜索关键词)绑定 'keyup' 键盘按键抬起事件监听器。在事件回调函数中,先处理浏览器兼容性问题(获取正确的事件对象,因为不同浏览器获取事件对象的方式略有不同,IE 使用 'window.event',其他标准浏览器使用传入的参数 'event'),然后判断按下的键码(keyCode)是否为 13(回车键的键码),如果是回车键按下,则调用当前对象(通过'me' 引用)的 'dosearch' 方法,实现用户在输入框中输入关键词后按回车键触发搜索的功能。 domUtils.on($G("J_searchName"), "click", function () { me.dosearch(); }); // 同样使用 'domUtils' 的 'on' 方法,为 id 为 'J_searchName' 的元素绑定 'click' 点击事件监听器,当用户点击该元素时,直接调用 'dosearch' 方法,不过通常输入框点击事件的使用场景较少,这里可能是一种额外的触发搜索方式或者是代码冗余(具体看实际需求),正常更常见的是通过回车键触发搜索。 domUtils.on($G("J_searchBtn"), "click", function () { me.dosearch(); }); // 使用 'domUtils' 为页面中 id 为 'J_searchBtn' 的元素(可能是一个按钮,用于触发音乐搜索操作)绑定 'click' 点击事件监听器,当用户点击这个按钮时,调用 'dosearch' 方法,触发音乐搜索逻辑,这是比较常见的通过按钮点击来执行搜索功能的实现方式。 }, callback: function (data) { var me = this; me.data = data.song_list; setTimeout(function () { $G('J_resultBar').innerHTML = me._renderTemplate(data.song_list); }, 300); // 定义 'callback' 方法,用于接收从服务器获取音乐数据后的回调处理。首先将传入的 'data' 参数中的'song_list' 属性值(可能是包含歌曲信息的数组)赋值给当前对象(通过'me' 引用)的 'data' 属性,以便后续在其他方法中可以访问这些歌曲数据。然后使用'setTimeout' 函数,延迟 300 毫秒后执行一个匿名函数,在匿名函数内通过 '$G' 函数(可能是自定义的获取 DOM 元素的函数)获取页面中 id 为 'J_resultBar' 的元素,并将其 'innerHTML' 属性设置为调用 '_renderTemplate' 方法(后续定义)处理后的歌曲列表数据(data.song_list),实现将获取到的音乐数据渲染并展示到页面相应区域的功能,延迟执行可能是为了等待页面其他相关元素加载或准备好,避免出现数据渲染的错误或不一致情况。 }, dosearch: function () { var me = this; selectedItem = null; var key = $G('J_searchName').value; if (utils.trim(key) == "") return false; key = encodeURIComponent(key); me._sent(key); // 定义 'dosearch' 方法,用于执行音乐搜索操作。首先将'selectedItem' 重置为 null,表示当前没有选中的歌曲。然后通过 '$G' 函数获取页面中 id 为 'J_searchName' 的输入框元素的值(用户输入的搜索关键词),并使用 'utils.trim' 函数(可能是自定义的去除字符串两端空白字符的函数)去除关键词两端的空白字符,如果处理后的关键词为空字符串,则直接返回 false,阻止搜索操作执行(因为没有有效的搜索内容)。如果关键词不为空,则使用 'encodeURIComponent' 函数对关键词进行 URL 编码,使其符合 URL 传参的格式要求,最后调用当前对象(通过'me' 引用)的 '_sent' 方法(后续定义),传入编码后的关键词,发起向服务器获取音乐数据的请求。 }, doselect: function (i) { var me = this; if (typeof i == 'object') { selectedItem = i; } else if (typeof i == 'number') { selectedItem = me.data[i]; } // 定义 'doselect' 方法,用于处理用户选择音乐的操作。根据传入参数 'i' 的数据类型进行不同的处理,如果 'i' 是一个对象(可能是代表歌曲信息的对象),则直接将其赋值给'selectedItem',表示选中了这个歌曲对象;如果 'i' 是一个数字,则将当前对象(通过'me' 引用)的 'data' 属性(之前存储的歌曲列表数据)中对应索引的歌曲对象赋值给'selectedItem',这样就记录了用户选择的歌曲信息,方便后续进行播放、插入等相关操作。 }, onpageclick: function (id) { var me = this; for (var i = 0; i < pages.length; i++) { $G(pages[i]).className = 'pageoff'; $G(panels[i]).className = 'paneloff'; } $G('page' + id).className = 'pageon'; $G('panel' + id).className = 'panelon'; // 定义 'onpageclick' 方法,用于处理分页点击事件。首先遍历 'pages' 和 'panels' 数组(之前存储了分页和面板相关元素的标识),通过 '$G' 函数获取对应的元素,并将它们的 'className' 属性分别设置为 'pageoff' 和 'paneloff',也就是将所有分页按钮和对应面板设置为未选中状态(关闭状态)。然后通过 '$G' 函数获取当前点击的分页按钮(根据传入的 'id' 参数拼接出对应的元素 ID,如 'page' + id),将其 'className' 属性设置为 'pageon'(选中状态),同时将对应的面板('panel' + id)的 'className' 设置为 'panelon'(显示状态),实现分页切换时相应页面内容显示和分页按钮状态切换的功能。 }, listenTest: function (elem) { var me = this, view = $G('J_preview'), is_play_action = (elem.className == 'm-try'), old_trying = me._getTryingElem(); if (old_trying) { old_trying.className = 'm-try'; view.innerHTML = ''; } if (is_play_action) { elem.className = 'm-trying'; view.innerHTML = me._buildMusicHtml(me._getUrl(true)); } // 定义 'listenTest' 方法,用于处理音乐试听相关操作。首先获取当前对象(通过'me' 引用)、页面中 id 为 'J_preview' 的元素(可能是用于音乐预览展示的区域),判断传入的元素(elem)的 'className' 是否为'm-try',如果是则将 'is_play_action' 设置为 true,表示是播放操作(从类名推测'm-try' 可能代表播放相关的样式类)。接着调用 '_getTryingElem' 方法(后续定义)获取之前正在试听的元素(如果存在的话),如果存在,则将其 'className' 恢复为'm-try'(表示停止播放状态),并清空 'J_preview' 元素的 'innerHTML'(清除之前的试听内容)。如果是播放操作('is_play_action' 为 true),则将传入元素(elem)的 'className' 修改为'm-trying'(可能代表正在播放的样式类),并通过调用 '_buildMusicHtml' 方法(后续定义)传入获取到的音乐播放 URL(通过 '_getUrl' 方法获取,且传入参数 true 表示是试听情况),将生成的包含音乐播放器的 HTML 代码设置为 'J_preview' 元素的 'innerHTML',实现在预览区域播放音乐的功能。 }, _sent: function (param) { var me = this; $G('J_resultBar').innerHTML = '
'; utils.loadFile(document, { src: me.dataUrl + '&query=' + param + '&page_size=' + me.total + '&callback=music.callback&.r=' + Math.random(), tag: "script", type: "text/javascript", defer: "defer" }); // 定义 '_sent' 方法,用于向服务器发送获取音乐数据的请求。首先通过 '$G' 函数获取页面中 id 为 'J_resultBar' 的元素,并将其 'innerHTML' 属性设置为一个包含 'loading' 类名的 div 元素(从类名推测用于展示加载提示信息,样式可能在外部 CSS 文件中定义),用于提示用户正在加载数据。然后使用 'utils.loadFile' 函数(可能是自定义的加载文件的函数,这里用于加载 JavaScript 脚本文件),向 'document' 对象(页面的文档对象)添加一个 script 标签,设置其'src' 属性为拼接好的请求 URL,包含了之前定义的 'dataUrl'(基础 API 地址)、搜索关键词参数(param)、每页显示数量(page_size)、回调函数名称(callback=music.callback,表示数据获取成功后调用 'Music' 类的 'callback' 方法)以及一个随机数(用于避免缓存,确保每次请求都是新的,.r= + Math.random()),同时设置标签的 'tag' 为 "script"(表示是脚本标签),'type' 为 "text/javascript"(脚本类型),'defer' 属性为 "defer"(表示延迟加载,即页面解析完后再执行脚本,避免阻塞页面渲染),通过这种方式向服务器发起获取音乐数据的请求,并在获取成功后通过指定的回调函数处理数据。 }, _removeHtml: function (str) { var reg = /<\s*\/?\s*[^>]*\s*>/gi; return str.replace(reg, ""); // 定义 '_removeHtml' 方法,用于去除字符串中的 HTML 标签。通过创建一个正则表达式对象(reg),匹配以 '<' 开头,中间包含任意字符(除了 '>'),以 '>' 结尾的 HTML 标签(包括自闭和标签以及成对标签),不区分大小写(gi 修饰符),然后使用字符串的'replace' 方法将匹配到的 HTML 标签替换为空字符串,返回处理后的字符串,可用于清理歌曲信息等文本中的 HTML 标签,获取纯文本内容,比如歌曲标题、歌手名等文本信息的提取和清理。 }, _getUrl: function (isTryListen) { var me = this; var param = 'from=tiebasongwidget&url=&name=' + encodeURIComponent(me._removeHtml(selectedItem.title)) + '&artist=' + encodeURIComponent(me._removeHtml(selectedItem.author)) + '&extra=' + encodeURIComponent(me._removeHtml(selectedItem.album_title)) + '&autoPlay=' + isTryListen + '' + '&loop=true'; return me.playerUrl + "?" + param; // 定义 '_getUrl' 方法,用于获取音乐播放的 URL 参数。根据传入的 'isTryListen' 参数(布尔值,用于区分是试听还是正式插入播放等情况)构建请求参数 'param',参数中包含了来源信息(from=tiebasongwidget)、歌曲名称(通过获取'selectedItem' 的 'title' 属性,去除其中的 HTML 标签后进行 URL 编码)、歌手信息(同理处理 'author' 属性)、额外信息(可能是专辑相关,处理 'album_title' 属性)以及自动播放(autoPlay 根据 'isTryListen' 设置为 true 或 false)和循环播放(loop=true)等设置,最后将构建好的参数拼接在 'playerUrl'(音乐播放器的 Flash 文件 URL)后面,返回完整的音乐播放 URL,用于后续创建音乐播放相关的 HTML 元素或者发起播放请求等操作。 }, _getTryingElem: function () { var s = $G('J_listPanel').getElementsByTagName('span'); for (var i = 0; i < s.length; i++) { if (s[i].className == 'm-trying') return s[i]; } return null; // 定义 '_getTryingElem' 方法,用于查找页面中正在试听的元素(通过样式类'm-trying' 判断)。首先通过 '$G' 函数获取页面中 id 为 'J_listPanel' 的元素,并获取其内部所有的'span' 标签元素,存储在's' 数组中。然后循环遍历这个数组,判断每个'span' 元素的 'className' 是否为'm-trying',如果找到符合条件的元素,则返回该元素,表示找到了正在试听的元素;如果循环结束都没有找到,则返回 null,说明当前没有正在试听的元素。 }, _buildMusicHtml: function (playerUrl) { var html = '