mp3_player 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mp3_player.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2009 Gavin Morrice
2
+ Copyright (c) 2010-2013 Alexander Zubkov
3
+
4
+ MIT License
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,55 @@
1
+ = Mp3Player
2
+
3
+ Here's a WordPress Audio Player plugin wrapper for Rails 3.x with asset pipeline support.
4
+
5
+ == Installation
6
+
7
+ Simply add to your application's Gemfile:
8
+ gem 'mp3_player'
9
+
10
+ In your layout add:
11
+ <%= mp3_player_headers %>
12
+
13
+ or:
14
+ <%= javascript_include_tag 'http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js' %>
15
+ <%= mp3_player_headers without_swfobject: true %>
16
+
17
+ == Usage
18
+
19
+ To check the player is working simply add:
20
+ <%= mp3_player("http://github.com/sekrett/mp3_player/raw/master/test.mp3") %>
21
+ to your view.
22
+
23
+ If you're using paperclip or carrierwave:
24
+ <%= mp3_player @my_model.mp3.url %>
25
+
26
+ Additionally you can just use google's MP3 player with the following helper:
27
+ <%= google_mp3_player @my_model.mp3.url %>
28
+
29
+ == Customization
30
+
31
+ You may specify extra options (all colors should be expressed as hexadecimal values minus the '#'. eg.:
32
+ <%= mp3_player @my_model.mp3.url, { bg: "99FFFF", text: 'FF0000') %>
33
+
34
+ Also you may create a configuration yml file and set global options there:
35
+ rails generate mp3_player:yml
36
+
37
+ For a complete list of options see documentation at http://wpaudioplayer.com/standalone.
38
+
39
+ == Contributing
40
+
41
+ 1. Fork it
42
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
43
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
44
+ 4. Push to the branch (`git push origin my-new-feature`)
45
+ 5. Create new Pull Request
46
+
47
+ == Copyright
48
+
49
+ This plugin is based on the Audio Player 2.0 by Martin Laine (http://wpaudioplayer.com/standalone)
50
+
51
+ Thanks to Matt Ittigson (http://github.com/mattenat) for inspiring changes to help support paperclip.
52
+
53
+ Copyright © 2009 Gavin Morrice (http://handyrailstips.com), released under the MIT license
54
+
55
+ Copyright © 2010-2013 Alexander Zubkov (http://github.com/sekrett), released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,36 @@
1
+ ## Options
2
+
3
+ #:autostart: 'no' # if yes, player starts automatically
4
+ #:loop: 'no' # if yes, player loops
5
+ #:animation: 'yes' # if no, player is always open
6
+ #:remaining: 'no' # if yes, shows remaining track time rather than elapsed time
7
+ #:noinfo: 'no' # if yes, disables the track information display
8
+ #:initialvolume: '60' # initial volume level (from 0 to 100)
9
+ #:buffer: '5' # buffering time in seconds
10
+ #:encode: 'no' # indicates that the mp3 file urls are encoded
11
+ #:checkpolicy: 'no' # tells Flash to look for a policy file when loading mp3 files (this allows Flash to read ID3 tags from files hosted on a different domain)
12
+ #:rtl: 'no' # switches the layout to RTL (right to left) for Hebrew and Arabic languages
13
+
14
+ ## Flash player options
15
+
16
+ #:width: '290' # width of the player. e.g. 290 (290 pixels) or 100%
17
+ #:transparentpagebg: 'no' # if yes, the player background is transparent (matches the page background)
18
+ #:pagebg: '' # player background color (set it to your page background when transparentbg is set to ‘no’)
19
+
20
+ ## Colour scheme options
21
+
22
+ #:bg: 'E5E5E5' # Background
23
+ #:leftbg: 'CCCCCC' # Speaker icon/Volume control background
24
+ #:lefticon: '333333' # Speaker icon
25
+ #:voltrack: 'F2F2F2' # Volume track
26
+ #:volslider: '666666' # Volume slider
27
+ #:rightbg: 'B4B4B4' # Play/Pause button background
28
+ #:rightbghover: '999999' # Play/Pause button background (hover state)
29
+ #:righticon: '333333' # Play/Pause icon
30
+ #:righticonhover: 'FFFFFF' # Play/Pause icon (hover state)
31
+ #:loader: '009900' # Loading bar
32
+ #:track: 'FFFFFF' # Loading/Progress bar track backgrounds
33
+ #:tracker: 'DDDDDD' # Progress track
34
+ #:border: 'CCCCCC' # Progress bar border
35
+ #:skip: '666666' # Previous/Next skip buttons
36
+ #:text: '333333' # Text
@@ -0,0 +1,12 @@
1
+ module Mp3Player
2
+ module Generators
3
+ class YmlGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+ desc 'Creates a config/mp3_player.yml file for setting global options.'
6
+
7
+ def copy_yml
8
+ copy_file 'mp3_player.yml', 'config/mp3_player.yml'
9
+ end
10
+ end
11
+ end
12
+ end
data/lib/mp3_player.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'mp3_player/version'
2
+
3
+ require 'mp3_player/view_helper'
4
+ require 'mp3_player/layout_helper'
5
+ require 'mp3_player/engine'
6
+ # includes the view and layout helpers to ActionView::Base
7
+ ActionView::Base.send(:include, Mp3Player::ViewHelper)
8
+ ActionView::Base.send(:include, Mp3Player::LayoutHelper)
9
+
@@ -0,0 +1,6 @@
1
+ module Mp3Player
2
+ # Required for assets to be discoverable in the asset pipeline
3
+ # @private
4
+ class Engine < ::Rails::Engine
5
+ end
6
+ end
@@ -0,0 +1,41 @@
1
+ module Mp3Player
2
+ module LayoutHelper
3
+ if Rails.env.production?
4
+ load_config_options
5
+ else
6
+ @@default_options = nil
7
+ end
8
+
9
+ def mp3_player_headers options = {}
10
+ ViewHelper.reset_player_count
11
+
12
+ # Don't reload configuration options in production env
13
+ load_config_options if !Rails.env.production?
14
+
15
+ options.reverse_merge! @@default_options if @@default_options
16
+ options.reverse_merge!({ width: 290 })
17
+
18
+ audio_player_path = if options[:with_swfobject] == false
19
+ 'audio-player-noswfobject.js'
20
+ else
21
+ 'audio-player.js'
22
+ end
23
+
24
+ javascript_include_tag(audio_player_path) +
25
+ %Q[
26
+ <script type="text/javascript">
27
+ AudioPlayer.setup("#{asset_path('player.swf')}/", #{options.to_json} );
28
+ </script>].html_safe
29
+ end
30
+
31
+ private
32
+ def load_config_options
33
+ config_file_path = Rails.root.join('config', 'mp3_player.yml')
34
+ @@default_options = if File.exists? config_file_path
35
+ YAML::load(File.open(config_file_path))
36
+ else
37
+ nil
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,3 @@
1
+ module Mp3Player
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,36 @@
1
+ module Mp3Player
2
+ # This module contains the view helper <tt>mp3_player</tt> and <tt>google_mp3_player</tt>
3
+ module ViewHelper
4
+ # This counter is used to generated unique IDs
5
+ @@player_count = 0
6
+
7
+ # This is the helper method you'll call in the view. <tt><%= mp3_player @song.mp3.url %></tt>
8
+ # See the options at http://wpaudioplayer.com/standalone for more info on customising the player to match your site
9
+ def mp3_player path, options = {}
10
+ increment_player_count
11
+
12
+ options.merge!({soundFile: path})
13
+
14
+ %Q[
15
+ <p id="audioplayer_#{@@player_count}">Alternative content</p>
16
+ <script type="text/javascript">
17
+ AudioPlayer.embed("audioplayer_#{@@player_count}", #{options.to_json});
18
+ </script>
19
+ ].html_safe
20
+ end
21
+
22
+ def google_mp3_player path
23
+ %Q[
24
+ <embed type="application/x-shockwave-flash" wmode="transparent" src="http://www.google.com/reader/ui/3523697345-audio-player.swf?audioUrl=#{path}" height="27" width="320"></embed>
25
+ ].html_safe
26
+ end
27
+
28
+ def increment_player_count
29
+ @@player_count += 1
30
+ end
31
+
32
+ def self.reset_player_count
33
+ @@player_count = 0
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mp3_player/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'mp3_player'
8
+ spec.version = Mp3Player::VERSION
9
+ spec.authors = ['Gavin Morrice', 'Alexander Zubkov']
10
+ spec.email = ['info@zubkov.info']
11
+ spec.description = %q{WordPress Audio Player plugin wrapper for Rails 3.x with asset pipeline support}
12
+ spec.summary = %q{WordPress Audio Player plugin wrapper for Rails 3.x with asset pipeline support}
13
+ spec.homepage = ''
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.3'
22
+ spec.add_development_dependency 'rake'
23
+ end
data/test.mp3 ADDED
Binary file
Binary file
@@ -0,0 +1,143 @@
1
+ var AudioPlayer = function () {
2
+ var instances = [];
3
+ var groups = {};
4
+ var activePlayers = {};
5
+ var playerURL = "";
6
+ var defaultOptions = {};
7
+ var currentVolume = -1;
8
+ var requiredFlashVersion = "9";
9
+
10
+ function getPlayer(playerID) {
11
+ if (document.all && !window[playerID]) {
12
+ for (var i = 0; i < document.forms.length; i++) {
13
+ if (document.forms[i][playerID]) {
14
+ return document.forms[i][playerID];
15
+ break;
16
+ }
17
+ }
18
+ }
19
+ return document.all ? window[playerID] : document[playerID];
20
+ }
21
+
22
+ function addListener (playerID, type, func) {
23
+ getPlayer(playerID).addListener(type, func);
24
+ }
25
+
26
+ return {
27
+ setup: function (url, options) {
28
+ playerURL = url;
29
+ defaultOptions = options;
30
+ if (swfobject.hasFlashPlayerVersion(requiredFlashVersion)) {
31
+ swfobject.switchOffAutoHideShow();
32
+ swfobject.createCSS("p.audioplayer_container span", "visibility:hidden;height:24px;overflow:hidden;padding:0;border:none;");
33
+ }
34
+ },
35
+
36
+ getPlayer: function (playerID) {
37
+ return getPlayer(playerID);
38
+ },
39
+
40
+ addListener: function (playerID, type, func) {
41
+ addListener(playerID, type, func);
42
+ },
43
+
44
+ embed: function (elementID, options) {
45
+ var instanceOptions = {};
46
+ var key;
47
+
48
+ var flashParams = {};
49
+ var flashVars = {};
50
+ var flashAttributes = {};
51
+
52
+ // Merge default options and instance options
53
+ for (key in defaultOptions) {
54
+ instanceOptions[key] = defaultOptions[key];
55
+ }
56
+ for (key in options) {
57
+ instanceOptions[key] = options[key];
58
+ }
59
+
60
+ if (instanceOptions.transparentpagebg == "yes") {
61
+ flashParams.bgcolor = "#FFFFFF";
62
+ flashParams.wmode = "transparent";
63
+ } else {
64
+ if (instanceOptions.pagebg) {
65
+ flashParams.bgcolor = "#" + instanceOptions.pagebg;
66
+ }
67
+ flashParams.wmode = "opaque";
68
+ }
69
+
70
+ flashParams.menu = "false";
71
+
72
+ for (key in instanceOptions) {
73
+ if (key == "pagebg" || key == "width" || key == "transparentpagebg") {
74
+ continue;
75
+ }
76
+ flashVars[key] = instanceOptions[key];
77
+ }
78
+
79
+ flashAttributes.name = elementID;
80
+ flashAttributes.style = "outline: none";
81
+
82
+ flashVars.playerID = elementID;
83
+
84
+ swfobject.embedSWF(playerURL, elementID, instanceOptions.width.toString(), "24", requiredFlashVersion, false, flashVars, flashParams, flashAttributes);
85
+
86
+ instances.push(elementID);
87
+
88
+ if (options.group) {
89
+ groups[elementID] = options.group;
90
+ }
91
+ },
92
+
93
+ syncVolumes: function (playerID, volume) {
94
+ if (groups[playerID]) return;
95
+ currentVolume = volume;
96
+ for (var i = 0; i < instances.length; i++) {
97
+ if (!groups[instances[i]] && instances[i] != playerID) {
98
+ getPlayer(instances[i]).setVolume(currentVolume);
99
+ }
100
+ }
101
+ },
102
+
103
+ activate: function (playerID, info) {
104
+ for (var activePlayerID in activePlayers) {
105
+ if (activePlayerID == playerID) {
106
+ continue;
107
+ }
108
+ if (groups[playerID] != groups[activePlayerID]) {
109
+ this.close(activePlayerID);
110
+ continue;
111
+ }
112
+ if (!(groups[playerID] || groups[activePlayerID])) {
113
+ this.close(activePlayerID);
114
+ }
115
+ }
116
+ activePlayers[playerID] = 1;
117
+ },
118
+
119
+ load: function (playerID, soundFile, titles, artists) {
120
+ getPlayer(playerID).load(soundFile, titles, artists);
121
+ },
122
+
123
+ close: function (playerID) {
124
+ getPlayer(playerID).close();
125
+ if (playerID in activePlayers) {
126
+ delete activePlayers[playerID];
127
+ }
128
+ },
129
+
130
+ open: function (playerID, index) {
131
+ if (index == undefined) {
132
+ index = 1;
133
+ }
134
+ getPlayer(playerID).open(index == undefined ? 0 : index-1);
135
+ },
136
+
137
+ getVolume: function (playerID) {
138
+ return currentVolume;
139
+ }
140
+
141
+ }
142
+
143
+ }();
@@ -0,0 +1,920 @@
1
+ /*! SWFObject v2.2 <http://code.google.com/p/swfobject/>
2
+ is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
3
+ */
4
+
5
+ var audioplayer_swfobject = function() {
6
+
7
+ var UNDEF = "undefined",
8
+ OBJECT = "object",
9
+ SHOCKWAVE_FLASH = "Shockwave Flash",
10
+ SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
11
+ FLASH_MIME_TYPE = "application/x-shockwave-flash",
12
+ EXPRESS_INSTALL_ID = "SWFObjectExprInst",
13
+ ON_READY_STATE_CHANGE = "onreadystatechange",
14
+
15
+ win = window,
16
+ doc = document,
17
+ nav = navigator,
18
+
19
+ plugin = false,
20
+ domLoadFnArr = [main],
21
+ regObjArr = [],
22
+ objIdArr = [],
23
+ listenersArr = [],
24
+ storedAltContent,
25
+ storedAltContentId,
26
+ storedCallbackFn,
27
+ storedCallbackObj,
28
+ isDomLoaded = false,
29
+ isExpressInstallActive = false,
30
+ dynamicStylesheet,
31
+ dynamicStylesheetMedia,
32
+ autoHideShow = true,
33
+
34
+ /* Centralized function for browser feature detection
35
+ - User agent string detection is only used when no good alternative is possible
36
+ - Is executed directly for optimal performance
37
+ */
38
+ ua = function() {
39
+ var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
40
+ u = nav.userAgent.toLowerCase(),
41
+ p = nav.platform.toLowerCase(),
42
+ windows = p ? /win/.test(p) : /win/.test(u),
43
+ mac = p ? /mac/.test(p) : /mac/.test(u),
44
+ webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit
45
+ ie = !+"\v1", // feature detection based on Andrea Giammarchi's solution: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html
46
+ playerVersion = [0,0,0],
47
+ d = null;
48
+ if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
49
+ d = nav.plugins[SHOCKWAVE_FLASH].description;
50
+ if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+
51
+ plugin = true;
52
+ ie = false; // cascaded feature detection for Internet Explorer
53
+ d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
54
+ playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
55
+ playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
56
+ playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
57
+ }
58
+ }
59
+ else if (typeof win.ActiveXObject != UNDEF) {
60
+ try {
61
+ var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
62
+ if (a) { // a will return null when ActiveX is disabled
63
+ d = a.GetVariable("$version");
64
+ if (d) {
65
+ ie = true; // cascaded feature detection for Internet Explorer
66
+ d = d.split(" ")[1].split(",");
67
+ playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
68
+ }
69
+ }
70
+ }
71
+ catch(e) {}
72
+ }
73
+ return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
74
+ }(),
75
+
76
+ /* Cross-browser onDomLoad
77
+ - Will fire an event as soon as the DOM of a web page is loaded
78
+ - Internet Explorer workaround based on Diego Perini's solution: http://javascript.nwbox.com/IEContentLoaded/
79
+ - Regular onload serves as fallback
80
+ */
81
+ onDomLoad = function() {
82
+ if (!ua.w3) { return; }
83
+ if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { // function is fired after onload, e.g. when script is inserted dynamically
84
+ callDomLoadFunctions();
85
+ }
86
+ if (!isDomLoaded) {
87
+ if (typeof doc.addEventListener != UNDEF) {
88
+ doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
89
+ }
90
+ if (ua.ie && ua.win) {
91
+ doc.attachEvent(ON_READY_STATE_CHANGE, function() {
92
+ if (doc.readyState == "complete") {
93
+ doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
94
+ callDomLoadFunctions();
95
+ }
96
+ });
97
+ if (win == top) { // if not inside an iframe
98
+ (function(){
99
+ if (isDomLoaded) { return; }
100
+ try {
101
+ doc.documentElement.doScroll("left");
102
+ }
103
+ catch(e) {
104
+ setTimeout(arguments.callee, 0);
105
+ return;
106
+ }
107
+ callDomLoadFunctions();
108
+ })();
109
+ }
110
+ }
111
+ if (ua.wk) {
112
+ (function(){
113
+ if (isDomLoaded) { return; }
114
+ if (!/loaded|complete/.test(doc.readyState)) {
115
+ setTimeout(arguments.callee, 0);
116
+ return;
117
+ }
118
+ callDomLoadFunctions();
119
+ })();
120
+ }
121
+ addLoadEvent(callDomLoadFunctions);
122
+ }
123
+ }();
124
+
125
+ function callDomLoadFunctions() {
126
+ if (isDomLoaded) { return; }
127
+ try { // test if we can really add/remove elements to/from the DOM; we don't want to fire it too early
128
+ var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
129
+ t.parentNode.removeChild(t);
130
+ }
131
+ catch (e) { return; }
132
+ isDomLoaded = true;
133
+ var dl = domLoadFnArr.length;
134
+ for (var i = 0; i < dl; i++) {
135
+ domLoadFnArr[i]();
136
+ }
137
+ }
138
+
139
+ function addDomLoadEvent(fn) {
140
+ if (isDomLoaded) {
141
+ fn();
142
+ }
143
+ else {
144
+ domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+
145
+ }
146
+ }
147
+
148
+ /* Cross-browser onload
149
+ - Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/
150
+ - Will fire an event as soon as a web page including all of its assets are loaded
151
+ */
152
+ function addLoadEvent(fn) {
153
+ if (typeof win.addEventListener != UNDEF) {
154
+ win.addEventListener("load", fn, false);
155
+ }
156
+ else if (typeof doc.addEventListener != UNDEF) {
157
+ doc.addEventListener("load", fn, false);
158
+ }
159
+ else if (typeof win.attachEvent != UNDEF) {
160
+ addListener(win, "onload", fn);
161
+ }
162
+ else if (typeof win.onload == "function") {
163
+ var fnOld = win.onload;
164
+ win.onload = function() {
165
+ fnOld();
166
+ fn();
167
+ };
168
+ }
169
+ else {
170
+ win.onload = fn;
171
+ }
172
+ }
173
+
174
+ /* Main function
175
+ - Will preferably execute onDomLoad, otherwise onload (as a fallback)
176
+ */
177
+ function main() {
178
+ if (plugin) {
179
+ testPlayerVersion();
180
+ }
181
+ else {
182
+ matchVersions();
183
+ }
184
+ }
185
+
186
+ /* Detect the Flash Player version for non-Internet Explorer browsers
187
+ - Detecting the plug-in version via the object element is more precise than using the plugins collection item's description:
188
+ a. Both release and build numbers can be detected
189
+ b. Avoid wrong descriptions by corrupt installers provided by Adobe
190
+ c. Avoid wrong descriptions by multiple Flash Player entries in the plugin Array, caused by incorrect browser imports
191
+ - Disadvantage of this method is that it depends on the availability of the DOM, while the plugins collection is immediately available
192
+ */
193
+ function testPlayerVersion() {
194
+ var b = doc.getElementsByTagName("body")[0];
195
+ var o = createElement(OBJECT);
196
+ o.setAttribute("type", FLASH_MIME_TYPE);
197
+ var t = b.appendChild(o);
198
+ if (t) {
199
+ var counter = 0;
200
+ (function(){
201
+ if (typeof t.GetVariable != UNDEF) {
202
+ var d = t.GetVariable("$version");
203
+ if (d) {
204
+ d = d.split(" ")[1].split(",");
205
+ ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
206
+ }
207
+ }
208
+ else if (counter < 10) {
209
+ counter++;
210
+ setTimeout(arguments.callee, 10);
211
+ return;
212
+ }
213
+ b.removeChild(o);
214
+ t = null;
215
+ matchVersions();
216
+ })();
217
+ }
218
+ else {
219
+ matchVersions();
220
+ }
221
+ }
222
+
223
+ /* Perform Flash Player and SWF version matching; static publishing only
224
+ */
225
+ function matchVersions() {
226
+ var rl = regObjArr.length;
227
+ if (rl > 0) {
228
+ for (var i = 0; i < rl; i++) { // for each registered object element
229
+ var id = regObjArr[i].id;
230
+ var cb = regObjArr[i].callbackFn;
231
+ var cbObj = {success:false, id:id};
232
+ if (ua.pv[0] > 0) {
233
+ var obj = getElementById(id);
234
+ if (obj) {
235
+ if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { // Flash Player version >= published SWF version: Houston, we have a match!
236
+ setVisibility(id, true);
237
+ if (cb) {
238
+ cbObj.success = true;
239
+ cbObj.ref = getObjectById(id);
240
+ cb(cbObj);
241
+ }
242
+ }
243
+ else if (regObjArr[i].expressInstall && canExpressInstall()) { // show the Adobe Express Install dialog if set by the web page author and if supported
244
+ var att = {};
245
+ att.data = regObjArr[i].expressInstall;
246
+ att.width = obj.getAttribute("width") || "0";
247
+ att.height = obj.getAttribute("height") || "0";
248
+ if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
249
+ if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }
250
+ // parse HTML object param element's name-value pairs
251
+ var par = {};
252
+ var p = obj.getElementsByTagName("param");
253
+ var pl = p.length;
254
+ for (var j = 0; j < pl; j++) {
255
+ if (p[j].getAttribute("name").toLowerCase() != "movie") {
256
+ par[p[j].getAttribute("name")] = p[j].getAttribute("value");
257
+ }
258
+ }
259
+ showExpressInstall(att, par, id, cb);
260
+ }
261
+ else { // Flash Player and SWF version mismatch or an older Webkit engine that ignores the HTML object element's nested param elements: display alternative content instead of SWF
262
+ displayAltContent(obj);
263
+ if (cb) { cb(cbObj); }
264
+ }
265
+ }
266
+ }
267
+ else { // if no Flash Player is installed or the fp version cannot be detected we let the HTML object element do its job (either show a SWF or alternative content)
268
+ setVisibility(id, true);
269
+ if (cb) {
270
+ var o = getObjectById(id); // test whether there is an HTML object element or not
271
+ if (o && typeof o.SetVariable != UNDEF) {
272
+ cbObj.success = true;
273
+ cbObj.ref = o;
274
+ }
275
+ cb(cbObj);
276
+ }
277
+ }
278
+ }
279
+ }
280
+ }
281
+
282
+ function getObjectById(objectIdStr) {
283
+ var r = null;
284
+ var o = getElementById(objectIdStr);
285
+ if (o && o.nodeName == "OBJECT") {
286
+ if (typeof o.SetVariable != UNDEF) {
287
+ r = o;
288
+ }
289
+ else {
290
+ var n = o.getElementsByTagName(OBJECT)[0];
291
+ if (n) {
292
+ r = n;
293
+ }
294
+ }
295
+ }
296
+ return r;
297
+ }
298
+
299
+ /* Requirements for Adobe Express Install
300
+ - only one instance can be active at a time
301
+ - fp 6.0.65 or higher
302
+ - Win/Mac OS only
303
+ - no Webkit engines older than version 312
304
+ */
305
+ function canExpressInstall() {
306
+ return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
307
+ }
308
+
309
+ /* Show the Adobe Express Install dialog
310
+ - Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75
311
+ */
312
+ function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
313
+ isExpressInstallActive = true;
314
+ storedCallbackFn = callbackFn || null;
315
+ storedCallbackObj = {success:false, id:replaceElemIdStr};
316
+ var obj = getElementById(replaceElemIdStr);
317
+ if (obj) {
318
+ if (obj.nodeName == "OBJECT") { // static publishing
319
+ storedAltContent = abstractAltContent(obj);
320
+ storedAltContentId = null;
321
+ }
322
+ else { // dynamic publishing
323
+ storedAltContent = obj;
324
+ storedAltContentId = replaceElemIdStr;
325
+ }
326
+ att.id = EXPRESS_INSTALL_ID;
327
+ if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; }
328
+ if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; }
329
+ doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
330
+ var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
331
+ fv = "MMredirectURL=" + win.location.toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;
332
+ if (typeof par.flashvars != UNDEF) {
333
+ par.flashvars += "&" + fv;
334
+ }
335
+ else {
336
+ par.flashvars = fv;
337
+ }
338
+ // IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,
339
+ // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
340
+ if (ua.ie && ua.win && obj.readyState != 4) {
341
+ var newObj = createElement("div");
342
+ replaceElemIdStr += "SWFObjectNew";
343
+ newObj.setAttribute("id", replaceElemIdStr);
344
+ obj.parentNode.insertBefore(newObj, obj); // insert placeholder div that will be replaced by the object element that loads expressinstall.swf
345
+ obj.style.display = "none";
346
+ (function(){
347
+ if (obj.readyState == 4) {
348
+ obj.parentNode.removeChild(obj);
349
+ }
350
+ else {
351
+ setTimeout(arguments.callee, 10);
352
+ }
353
+ })();
354
+ }
355
+ createSWF(att, par, replaceElemIdStr);
356
+ }
357
+ }
358
+
359
+ /* Functions to abstract and display alternative content
360
+ */
361
+ function displayAltContent(obj) {
362
+ if (ua.ie && ua.win && obj.readyState != 4) {
363
+ // IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,
364
+ // because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
365
+ var el = createElement("div");
366
+ obj.parentNode.insertBefore(el, obj); // insert placeholder div that will be replaced by the alternative content
367
+ el.parentNode.replaceChild(abstractAltContent(obj), el);
368
+ obj.style.display = "none";
369
+ (function(){
370
+ if (obj.readyState == 4) {
371
+ obj.parentNode.removeChild(obj);
372
+ }
373
+ else {
374
+ setTimeout(arguments.callee, 10);
375
+ }
376
+ })();
377
+ }
378
+ else {
379
+ obj.parentNode.replaceChild(abstractAltContent(obj), obj);
380
+ }
381
+ }
382
+
383
+ function abstractAltContent(obj) {
384
+ var ac = createElement("div");
385
+ if (ua.win && ua.ie) {
386
+ ac.innerHTML = obj.innerHTML;
387
+ }
388
+ else {
389
+ var nestedObj = obj.getElementsByTagName(OBJECT)[0];
390
+ if (nestedObj) {
391
+ var c = nestedObj.childNodes;
392
+ if (c) {
393
+ var cl = c.length;
394
+ for (var i = 0; i < cl; i++) {
395
+ if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
396
+ ac.appendChild(c[i].cloneNode(true));
397
+ }
398
+ }
399
+ }
400
+ }
401
+ }
402
+ return ac;
403
+ }
404
+
405
+ /* Cross-browser dynamic SWF creation
406
+ */
407
+ function createSWF(attObj, parObj, id) {
408
+ var r, el = getElementById(id);
409
+ if (ua.wk && ua.wk < 312) { return r; }
410
+ if (el) {
411
+ if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content
412
+ attObj.id = id;
413
+ }
414
+ if (ua.ie && ua.win) { // Internet Explorer + the HTML object element + W3C DOM methods do not combine: fall back to outerHTML
415
+ var att = "";
416
+ for (var i in attObj) {
417
+ if (attObj[i] != Object.prototype[i]) { // filter out prototype additions from other potential libraries
418
+ if (i.toLowerCase() == "data") {
419
+ parObj.movie = attObj[i];
420
+ }
421
+ else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
422
+ att += ' class="' + attObj[i] + '"';
423
+ }
424
+ else if (i.toLowerCase() != "classid") {
425
+ att += ' ' + i + '="' + attObj[i] + '"';
426
+ }
427
+ }
428
+ }
429
+ var par = "";
430
+ for (var j in parObj) {
431
+ if (parObj[j] != Object.prototype[j]) { // filter out prototype additions from other potential libraries
432
+ par += '<param name="' + j + '" value="' + parObj[j] + '" />';
433
+ }
434
+ }
435
+ el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
436
+ objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only)
437
+ r = getElementById(attObj.id);
438
+ }
439
+ else { // well-behaving browsers
440
+ var o = createElement(OBJECT);
441
+ o.setAttribute("type", FLASH_MIME_TYPE);
442
+ for (var m in attObj) {
443
+ if (attObj[m] != Object.prototype[m]) { // filter out prototype additions from other potential libraries
444
+ if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
445
+ o.setAttribute("class", attObj[m]);
446
+ }
447
+ else if (m.toLowerCase() != "classid") { // filter out IE specific attribute
448
+ o.setAttribute(m, attObj[m]);
449
+ }
450
+ }
451
+ }
452
+ for (var n in parObj) {
453
+ if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // filter out prototype additions from other potential libraries and IE specific param element
454
+ createObjParam(o, n, parObj[n]);
455
+ }
456
+ }
457
+ el.parentNode.replaceChild(o, el);
458
+ r = o;
459
+ }
460
+ }
461
+ return r;
462
+ }
463
+
464
+ function createObjParam(el, pName, pValue) {
465
+ var p = createElement("param");
466
+ p.setAttribute("name", pName);
467
+ p.setAttribute("value", pValue);
468
+ el.appendChild(p);
469
+ }
470
+
471
+ /* Cross-browser SWF removal
472
+ - Especially needed to safely and completely remove a SWF in Internet Explorer
473
+ */
474
+ function removeSWF(id) {
475
+ var obj = getElementById(id);
476
+ if (obj && obj.nodeName == "OBJECT") {
477
+ if (ua.ie && ua.win) {
478
+ obj.style.display = "none";
479
+ (function(){
480
+ if (obj.readyState == 4) {
481
+ removeObjectInIE(id);
482
+ }
483
+ else {
484
+ setTimeout(arguments.callee, 10);
485
+ }
486
+ })();
487
+ }
488
+ else {
489
+ obj.parentNode.removeChild(obj);
490
+ }
491
+ }
492
+ }
493
+
494
+ function removeObjectInIE(id) {
495
+ var obj = getElementById(id);
496
+ if (obj) {
497
+ for (var i in obj) {
498
+ if (typeof obj[i] == "function") {
499
+ obj[i] = null;
500
+ }
501
+ }
502
+ obj.parentNode.removeChild(obj);
503
+ }
504
+ }
505
+
506
+ /* Functions to optimize JavaScript compression
507
+ */
508
+ function getElementById(id) {
509
+ var el = null;
510
+ try {
511
+ el = doc.getElementById(id);
512
+ }
513
+ catch (e) {}
514
+ return el;
515
+ }
516
+
517
+ function createElement(el) {
518
+ return doc.createElement(el);
519
+ }
520
+
521
+ /* Updated attachEvent function for Internet Explorer
522
+ - Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks
523
+ */
524
+ function addListener(target, eventType, fn) {
525
+ target.attachEvent(eventType, fn);
526
+ listenersArr[listenersArr.length] = [target, eventType, fn];
527
+ }
528
+
529
+ /* Flash Player and SWF content version matching
530
+ */
531
+ function hasPlayerVersion(rv) {
532
+ var pv = ua.pv, v = rv.split(".");
533
+ v[0] = parseInt(v[0], 10);
534
+ v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0"
535
+ v[2] = parseInt(v[2], 10) || 0;
536
+ return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
537
+ }
538
+
539
+ /* Cross-browser dynamic CSS creation
540
+ - Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php
541
+ */
542
+ function createCSS(sel, decl, media, newStyle) {
543
+ if (ua.ie && ua.mac) { return; }
544
+ var h = doc.getElementsByTagName("head")[0];
545
+ if (!h) { return; } // to also support badly authored HTML pages that lack a head element
546
+ var m = (media && typeof media == "string") ? media : "screen";
547
+ if (newStyle) {
548
+ dynamicStylesheet = null;
549
+ dynamicStylesheetMedia = null;
550
+ }
551
+ if (!dynamicStylesheet || dynamicStylesheetMedia != m) {
552
+ // create dynamic stylesheet + get a global reference to it
553
+ var s = createElement("style");
554
+ s.setAttribute("type", "text/css");
555
+ s.setAttribute("media", m);
556
+ dynamicStylesheet = h.appendChild(s);
557
+ if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
558
+ dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
559
+ }
560
+ dynamicStylesheetMedia = m;
561
+ }
562
+ // add style rule
563
+ if (ua.ie && ua.win) {
564
+ if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {
565
+ dynamicStylesheet.addRule(sel, decl);
566
+ }
567
+ }
568
+ else {
569
+ if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {
570
+ dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
571
+ }
572
+ }
573
+ }
574
+
575
+ function setVisibility(id, isVisible) {
576
+ if (!autoHideShow) { return; }
577
+ var v = isVisible ? "visible" : "hidden";
578
+ if (isDomLoaded && getElementById(id)) {
579
+ getElementById(id).style.visibility = v;
580
+ }
581
+ else {
582
+ createCSS("#" + id, "visibility:" + v);
583
+ }
584
+ }
585
+
586
+ /* Filter to avoid XSS attacks
587
+ */
588
+ function urlEncodeIfNecessary(s) {
589
+ var regex = /[\\\"<>\.;]/;
590
+ var hasBadChars = regex.exec(s) != null;
591
+ return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
592
+ }
593
+
594
+ /* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only)
595
+ */
596
+ var cleanup = function() {
597
+ if (ua.ie && ua.win) {
598
+ window.attachEvent("onunload", function() {
599
+ // remove listeners to avoid memory leaks
600
+ var ll = listenersArr.length;
601
+ for (var i = 0; i < ll; i++) {
602
+ listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
603
+ }
604
+ // cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect
605
+ var il = objIdArr.length;
606
+ for (var j = 0; j < il; j++) {
607
+ removeSWF(objIdArr[j]);
608
+ }
609
+ // cleanup library's main closures to avoid memory leaks
610
+ for (var k in ua) {
611
+ ua[k] = null;
612
+ }
613
+ ua = null;
614
+ for (var l in audioplayer_swfobject) {
615
+ audioplayer_swfobject[l] = null;
616
+ }
617
+ audioplayer_swfobject = null;
618
+ });
619
+ }
620
+ }();
621
+
622
+ return {
623
+ /* Public API
624
+ - Reference: http://code.google.com/p/swfobject/wiki/documentation
625
+ */
626
+ registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
627
+ if (ua.w3 && objectIdStr && swfVersionStr) {
628
+ var regObj = {};
629
+ regObj.id = objectIdStr;
630
+ regObj.swfVersion = swfVersionStr;
631
+ regObj.expressInstall = xiSwfUrlStr;
632
+ regObj.callbackFn = callbackFn;
633
+ regObjArr[regObjArr.length] = regObj;
634
+ setVisibility(objectIdStr, false);
635
+ }
636
+ else if (callbackFn) {
637
+ callbackFn({success:false, id:objectIdStr});
638
+ }
639
+ },
640
+
641
+ getObjectById: function(objectIdStr) {
642
+ if (ua.w3) {
643
+ return getObjectById(objectIdStr);
644
+ }
645
+ },
646
+
647
+ embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
648
+ var callbackObj = {success:false, id:replaceElemIdStr};
649
+ if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
650
+ setVisibility(replaceElemIdStr, false);
651
+ addDomLoadEvent(function() {
652
+ widthStr += ""; // auto-convert to string
653
+ heightStr += "";
654
+ var att = {};
655
+ if (attObj && typeof attObj === OBJECT) {
656
+ for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs
657
+ att[i] = attObj[i];
658
+ }
659
+ }
660
+ att.data = swfUrlStr;
661
+ att.width = widthStr;
662
+ att.height = heightStr;
663
+ var par = {};
664
+ if (parObj && typeof parObj === OBJECT) {
665
+ for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs
666
+ par[j] = parObj[j];
667
+ }
668
+ }
669
+ if (flashvarsObj && typeof flashvarsObj === OBJECT) {
670
+ for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs
671
+ if (typeof par.flashvars != UNDEF) {
672
+ par.flashvars += "&" + k + "=" + flashvarsObj[k];
673
+ }
674
+ else {
675
+ par.flashvars = k + "=" + flashvarsObj[k];
676
+ }
677
+ }
678
+ }
679
+ if (hasPlayerVersion(swfVersionStr)) { // create SWF
680
+ var obj = createSWF(att, par, replaceElemIdStr);
681
+ if (att.id == replaceElemIdStr) {
682
+ setVisibility(replaceElemIdStr, true);
683
+ }
684
+ callbackObj.success = true;
685
+ callbackObj.ref = obj;
686
+ }
687
+ else if (xiSwfUrlStr && canExpressInstall()) { // show Adobe Express Install
688
+ att.data = xiSwfUrlStr;
689
+ showExpressInstall(att, par, replaceElemIdStr, callbackFn);
690
+ return;
691
+ }
692
+ else { // show alternative content
693
+ setVisibility(replaceElemIdStr, true);
694
+ }
695
+ if (callbackFn) { callbackFn(callbackObj); }
696
+ });
697
+ }
698
+ else if (callbackFn) { callbackFn(callbackObj); }
699
+ },
700
+
701
+ switchOffAutoHideShow: function() {
702
+ autoHideShow = false;
703
+ },
704
+
705
+ ua: ua,
706
+
707
+ getFlashPlayerVersion: function() {
708
+ return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
709
+ },
710
+
711
+ hasFlashPlayerVersion: hasPlayerVersion,
712
+
713
+ createSWF: function(attObj, parObj, replaceElemIdStr) {
714
+ if (ua.w3) {
715
+ return createSWF(attObj, parObj, replaceElemIdStr);
716
+ }
717
+ else {
718
+ return undefined;
719
+ }
720
+ },
721
+
722
+ showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) {
723
+ if (ua.w3 && canExpressInstall()) {
724
+ showExpressInstall(att, par, replaceElemIdStr, callbackFn);
725
+ }
726
+ },
727
+
728
+ removeSWF: function(objElemIdStr) {
729
+ if (ua.w3) {
730
+ removeSWF(objElemIdStr);
731
+ }
732
+ },
733
+
734
+ createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) {
735
+ if (ua.w3) {
736
+ createCSS(selStr, declStr, mediaStr, newStyleBoolean);
737
+ }
738
+ },
739
+
740
+ addDomLoadEvent: addDomLoadEvent,
741
+
742
+ addLoadEvent: addLoadEvent,
743
+
744
+ getQueryParamValue: function(param) {
745
+ var q = doc.location.search || doc.location.hash;
746
+ if (q) {
747
+ if (/\?/.test(q)) { q = q.split("?")[1]; } // strip question mark
748
+ if (param == null) {
749
+ return urlEncodeIfNecessary(q);
750
+ }
751
+ var pairs = q.split("&");
752
+ for (var i = 0; i < pairs.length; i++) {
753
+ if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
754
+ return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
755
+ }
756
+ }
757
+ }
758
+ return "";
759
+ },
760
+
761
+ // For internal usage only
762
+ expressInstallCallback: function() {
763
+ if (isExpressInstallActive) {
764
+ var obj = getElementById(EXPRESS_INSTALL_ID);
765
+ if (obj && storedAltContent) {
766
+ obj.parentNode.replaceChild(storedAltContent, obj);
767
+ if (storedAltContentId) {
768
+ setVisibility(storedAltContentId, true);
769
+ if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }
770
+ }
771
+ if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }
772
+ }
773
+ isExpressInstallActive = false;
774
+ }
775
+ }
776
+ };
777
+ }();
778
+ var AudioPlayer = function () {
779
+ var instances = [];
780
+ var groups = {};
781
+ var activePlayers = {};
782
+ var playerURL = "";
783
+ var defaultOptions = {};
784
+ var currentVolume = -1;
785
+ var requiredFlashVersion = "9";
786
+
787
+ function getPlayer(playerID) {
788
+ if (document.all && !window[playerID]) {
789
+ for (var i = 0; i < document.forms.length; i++) {
790
+ if (document.forms[i][playerID]) {
791
+ return document.forms[i][playerID];
792
+ break;
793
+ }
794
+ }
795
+ }
796
+ return document.all ? window[playerID] : document[playerID];
797
+ }
798
+
799
+ function addListener (playerID, type, func) {
800
+ getPlayer(playerID).addListener(type, func);
801
+ }
802
+
803
+ return {
804
+ setup: function (url, options) {
805
+ playerURL = url;
806
+ defaultOptions = options;
807
+ if (audioplayer_swfobject.hasFlashPlayerVersion(requiredFlashVersion)) {
808
+ audioplayer_swfobject.switchOffAutoHideShow();
809
+ audioplayer_swfobject.createCSS("p.audioplayer_container span", "visibility:hidden;height:24px;overflow:hidden;padding:0;border:none;");
810
+ }
811
+ },
812
+
813
+ getPlayer: function (playerID) {
814
+ return getPlayer(playerID);
815
+ },
816
+
817
+ addListener: function (playerID, type, func) {
818
+ addListener(playerID, type, func);
819
+ },
820
+
821
+ embed: function (elementID, options) {
822
+ var instanceOptions = {};
823
+ var key;
824
+
825
+ var flashParams = {};
826
+ var flashVars = {};
827
+ var flashAttributes = {};
828
+
829
+ // Merge default options and instance options
830
+ for (key in defaultOptions) {
831
+ instanceOptions[key] = defaultOptions[key];
832
+ }
833
+ for (key in options) {
834
+ instanceOptions[key] = options[key];
835
+ }
836
+
837
+ if (instanceOptions.transparentpagebg == "yes") {
838
+ flashParams.bgcolor = "#FFFFFF";
839
+ flashParams.wmode = "transparent";
840
+ } else {
841
+ if (instanceOptions.pagebg) {
842
+ flashParams.bgcolor = "#" + instanceOptions.pagebg;
843
+ }
844
+ flashParams.wmode = "opaque";
845
+ }
846
+
847
+ flashParams.menu = "false";
848
+
849
+ for (key in instanceOptions) {
850
+ if (key == "pagebg" || key == "width" || key == "transparentpagebg") {
851
+ continue;
852
+ }
853
+ flashVars[key] = instanceOptions[key];
854
+ }
855
+
856
+ flashAttributes.name = elementID;
857
+ flashAttributes.style = "outline: none";
858
+
859
+ flashVars.playerID = elementID;
860
+
861
+ audioplayer_swfobject.embedSWF(playerURL, elementID, instanceOptions.width.toString(), "24", requiredFlashVersion, false, flashVars, flashParams, flashAttributes);
862
+
863
+ instances.push(elementID);
864
+
865
+ if (options.group) {
866
+ groups[elementID] = options.group;
867
+ }
868
+ },
869
+
870
+ syncVolumes: function (playerID, volume) {
871
+ if (groups[playerID]) return;
872
+ currentVolume = volume;
873
+ for (var i = 0; i < instances.length; i++) {
874
+ if (!groups[instances[i]] && instances[i] != playerID) {
875
+ getPlayer(instances[i]).setVolume(currentVolume);
876
+ }
877
+ }
878
+ },
879
+
880
+ activate: function (playerID, info) {
881
+ for (var activePlayerID in activePlayers) {
882
+ if (activePlayerID == playerID) {
883
+ continue;
884
+ }
885
+ if (groups[playerID] != groups[activePlayerID]) {
886
+ this.close(activePlayerID);
887
+ continue;
888
+ }
889
+ if (!(groups[playerID] || groups[activePlayerID])) {
890
+ this.close(activePlayerID);
891
+ }
892
+ }
893
+ activePlayers[playerID] = 1;
894
+ },
895
+
896
+ load: function (playerID, soundFile, titles, artists) {
897
+ getPlayer(playerID).load(soundFile, titles, artists);
898
+ },
899
+
900
+ close: function (playerID) {
901
+ getPlayer(playerID).close();
902
+ if (playerID in activePlayers) {
903
+ delete activePlayers[playerID];
904
+ }
905
+ },
906
+
907
+ open: function (playerID, index) {
908
+ if (index == undefined) {
909
+ index = 1;
910
+ }
911
+ getPlayer(playerID).open(index == undefined ? 0 : index-1);
912
+ },
913
+
914
+ getVolume: function (playerID) {
915
+ return currentVolume;
916
+ }
917
+
918
+ }
919
+
920
+ }();