Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. I am a failed stand-up comic, a cornrower, and a book author.About | Contact | Newsletter
[原文发表地址]Creating a Podcast Player with HTML5 for a IE9 Pinned Site on Windows 7
[原文发表时间]2011-08-22 23:53
我今天看了下HTML5Rocks 播客播放器示例,突然想到我好像从来没有写过关于我在4月份为这个开发者的生活所创建在IE9上的播客播放器。最近在TDL的每个页面上都有一个Flash播放器,而且总有一天有人会创建一个HTML5播客播放器来规范这些东西,但到目前为止,我还没看到。很多都只是单版或者示例,就好像我在这里小小的演示版一样。
HTML5Rocks播放器有很多聪明的设计,值得你查看下源代码来找出其中的妙处。在页面顶部有一个空的<audio/>标签,他们会问你“你能播放MP3吗?”,然后根据它的指示显示一个兼容性信息。你还可以在<audio/>元素中添加文本,如果不支持该元素,这些文本就会被显示出来。
1: $('#compatibilityMsg').html('Your browser <strong>' +
2: ($('#player').get(0).canPlayType('audio/mpeg') != '' ? 'can' : 'cannot') +
3: '</strong> play .mp3 files using HTML5 audio');
用<audio>标签播放音频再简单不过了。HTML5Rocks示例还有些其他功能像是设置音量和搜索,这些是你不常在示例中看到的功能。
我想给TDL创建一个小的播客播放器,能够通过一些自定义按钮将Site Pinning和Jump List功能结合起来,并用HTML5音频来播放。
所以功能就是:
· 可钉针固定(将Favlcon拖到任务栏)
· 右击Jumplist查看最近播放
· 在预览中通过任务按钮播放
· 前一个,下一个,播放,暂停
· 最小化代码
另外,我不擅长JavaScript。下面就是它的样子看起来像是在不断变化(像动画GIF一样,应为这些都是未来的风格,难道你没听说?)对于那些谁不想自己尝试一下。
以下是代码的总体思路。
在首页上有所有篇章的列表,是通过for 循环来遍历show的数据库所创建的。我只是在每个show的div旁添加了一个无预先加载的音频元素:
1: <audio id="audio-2-0-4-taste" preload="none" src="http://traffic.libsyn.com/devlife/204-Taste.mp3"></audio>
2: <div class="episode">
3: <a href='post/2-0-3-education' class="showlink">
4: <img src="Images//203-lead.png"
5: alt="2.0.3 Education" width="320" height="220"/>
6: <div class='title'>
7: <p>2.0.3 Education</p>
8: <div class='description'>
9: <p>Scott and Rob talk to two developers about the role education has played in their careers</p>
10: </div>
11: </div>
12: </a>
13: </div>
每个show都有一个“showlink”类的超文本引用。我把它们收集起来,放在了jQuery插件:
1: <script> 1: 2: 3: $(function(){ 4: 5: $(".showlink").IE9PodcastPlayer(); 6: 7: }); 8: </script>
1:
2:
3: $(function(){
4:
5: $(".showlink").IE9PodcastPlayer();
6:
7: });
8:
希望大家也可以给些评论,因为我对jQuery和JavaScript还不是很熟练。其实还可以再添加一些选项/设置,不过我为这个页站设置了一些默认项。
简单来说,我添加了一些按钮,设置点击事件,来选择show的列表中的前后项。
1: (function( $ ){
2: $.fn.IE9PodcastPlayer = function(options) {
3:
4: var settings = {
5: 'playerStatusDiv' : '#podcastStatus',
6: 'currentShowIndex' : 0
7: };
9: this.each(function() {
10: // If options exist, lets merge them
11: // with our default settings
12: if ( options ) {
13: $.extend( settings, options );
14: }
15: });
16:
17: function initButtons() {
18: try {
19: // Developer sample code
20: if(window.external.msIsSiteMode()) {
21: // Add buttons listener
22: document.addEventListener('msthumbnailclick', onButtonClicked, false);
23:
24: // Add buttons
25: btnPrev = window.external.msSiteModeAddThumbBarButton('/images/prev.ico', 'Previous');
26: btnPlayPause = window.external.msSiteModeAddThumbBarButton('/images/play.ico', 'Play');
27: btnNext = window.external.msSiteModeAddThumbBarButton('/images/next.ico', 'Next');
28:
29: // Add styles
30: stylePlay = window.external.msSiteModeAddButtonStyle(btnPlayPause, '/images/play.ico', "Play");
31: stylePause = window.external.msSiteModeAddButtonStyle(btnPlayPause, '/images/pause.ico', "Pause");
32:
33: // Show thumbar
34: window.external.msSiteModeShowThumbBar();
35: }
36: }
37: catch(e) {
38: // fail silently
39: }
40: }
41:
42: function onButtonClicked(e) {
43: var btnText = "",
44: lastIndex = 0;
45:
46: if (e.buttonID !== btnPlayPause) {
47:
48: switch (e.buttonID) {
49: case btnPrev:
50: btnText = "Previous";
51: settings.currentShowIndex--;
52: if (settings.currentShowIndex < 0) { settings.currentShowIndex = 0 };
53: break;
54: case btnNext:
55: btnText = "Next";
56: lastIndex = $('audio').length-1;
57: settings.currentShowIndex++;
58: if(settings.currentShowIndex >= lastIndex) { settings.currentShowIndex = lastIndex };
59: break;
60: }
61:
62: stopAll();
63: $(settings.playerStatusDiv).text(btnText).fadeIn('slow',
64: function(){playPause(settings.currentShowIndex)}
65: );
66: } else {
67:
68: playPause(settings.currentShowIndex);
69:
70: }
71: }
72:
73: function stopAll() {
74: $('audio').each(function(){
75: try {
76: $(this)[0].pause();
77: }
78: catch(e) {
79: // fail silently
80: };
81: });
82: $(settings.playerStatusDiv).hide();
83: }
84:
85: function playPause(podcastID) {
86: var player = $('audio')[podcastID];
87: if(player.paused)
88: {
89: player.play();
90: $(settings.playerStatusDiv).text("Playing...").fadeIn('slow');
91: }
92: else
93: {
94: player.pause();
95: $(settings.playerStatusDiv).text("Paused").fadeIn('slow');
96: }
97:
98: updatePlayPauseButton(podcastID);
99: }
100:
101: function updatePlayPauseButton(podcastID) {
102: var player = $('audio')[podcastID];
103: try {
104: if(window.external.msIsSiteMode()) {
105: if (player.paused)
106: window.external.msSiteModeShowButtonStyle(btnPlayPause, stylePlay);
107: else
108: window.external.msSiteModeShowButtonStyle(btnPlayPause, stylePause);
109: }
110: }
111: catch(e) {
112: // fail silently
113: }
114: }
115:
116: function addSite() {
117: try {
118: window.external.msAddSiteMode();
119: }
120: catch (e) {
121: alert("This feature is only available in Internet Explorer 9. Bummer.");
122: }
123: }
124:
125: initButtons();
126: updatePlayPauseButton(0);
127:
128: if(location.pathname == "/")
129: {
130: window.external.msSiteModeClearJumpList()
131: window.external.msSiteModeCreateJumplist('Episodes');
132:
133: //This is the stuff we selected and passed in!
134: this.filter(":lt(10)").each(function() {
135: window.external.msSiteModeAddJumpListItem($(this).text().substring(41,60), this.href, '/favicon.ico');
136: });
137:
138: window.external.msSiteModeShowJumplist();
139: }
140:
141: };
142: })( jQuery );
我必须解决而且还很纠结的一部分是最后的filter()和substring()。看到我是如何困难地处理截断的show标题的编码吗?我在传递整个<a/>和其子元素时弄了太多文本。我得找个更清晰的方式来让我的插件知道我的标题和音频文件。期待你们的评论。
如果你真想了解支持钉针固定和动态jumplist 功能的jQuery插件还有我还没写到的内容,请看Pinify the jQuery Site Pinning Plugin或者NuGet。