2 * flowplayer.js The Flowplayer API
4 * Copyright 2009-2011 Flowplayer Oy
6 * This file is part of Flowplayer.
8 * Flowplayer is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * Flowplayer is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Flowplayer. If not, see <http://www.gnu.org/licenses/>.
24 console.log("$f.fireEvent", [].slice.call(p))
28 if (!r || typeof r != "object") {
31 var p = new r.constructor();
33 if (r.hasOwnProperty(q)) {
44 var p, q = 0, s = u.length;
45 if (s === undefined) {
47 if (r.call(u[p], p, u[p]) === false) {
52 for (var t = u[0]; q < s && r.call(t, q, t) !== false; t = u[++q]) {
59 return document.getElementById(p)
63 if (typeof q != "object") {
67 n(q, function (s, t) {
68 if (!p || typeof t != "function") {
77 var r = t.indexOf(".");
79 var q = t.slice(0, r) || "*";
80 var p = t.slice(r + 1, t.length);
82 n(document.getElementsByTagName(q), function () {
83 if (this.className && this.className.indexOf(p) != -1) {
92 p = p || window.event;
93 if (p.preventDefault) {
97 p.returnValue = false;
103 function k(r, p, q) {
109 return p.replace(/&/g, "%26").replace(/&/g, "%26").replace(/=/g, "%3D")
113 return"_" + ("" + Math.random()).slice(2, 10)
116 var i = function (u, s, t) {
117 var r = this, q = {}, v = {};
119 if (typeof u == "string") {
123 n(("Begin*,Start,Pause*,Resume*,Seek*,Stop*,Finish*,LastSecond,Update,BufferFull,BufferEmpty,BufferStop").split(","), function () {
125 if (w.indexOf("*") != -1) {
126 w = w.slice(0, w.length - 1);
127 var x = "onBefore" + w.slice(2);
128 r[x] = function (y) {
133 r[w] = function (y) {
146 j(this, {onCuepoint: function (y, x) {
147 if (arguments.length == 1) {
148 q.embedded = [null, y];
151 if (typeof y == "number") {
157 t._api().fp_addCuepoints(y, s, w)
160 }, update: function (x) {
163 t._api().fp_updateClip(x, s)
165 var w = t.getConfig();
166 var y = (s == -1) ? w.clip : w.playlist[s];
168 }, _fireEvent: function (w, z, x, B) {
170 n(q, function (C, D) {
172 t._api().fp_addCuepoints(D[0], s, C)
178 if (w == "onCuepoint") {
181 return A[1].call(t, B, x)
184 if (z && "onBeforeBegin,onMetaData,onMetaDataChange,onStart,onUpdate,onResume".indexOf(w) != -1) {
188 B.duration = z.metaData.duration
190 B.fullDuration = z.metaData.duration
195 n(v[w], function () {
196 y = this.call(t, B, z, x)
201 var p = u.onCuepoint;
202 r.onCuepoint.apply(r, typeof p == "function" ? [p] : p);
205 n(u, function (w, x) {
206 if (typeof x == "function") {
212 t.onCuepoint = this.onCuepoint
215 var m = function (q, s, r, u) {
216 var p = this, t = {}, v = false;
220 n(s, function (w, x) {
221 if (typeof x == "function") {
226 j(this, {animate: function (z, A, y) {
230 if (typeof A == "function") {
234 if (typeof z == "string") {
244 if (A === undefined) {
247 s = r._api().fp_animate(q, z, A, w);
249 }, css: function (x, y) {
250 if (y !== undefined) {
255 s = r._api().fp_css(q, x);
258 }, show: function () {
259 this.display = "block";
260 r._api().fp_showPlugin(q);
262 }, hide: function () {
263 this.display = "none";
264 r._api().fp_hidePlugin(q);
266 }, toggle: function () {
267 this.display = r._api().fp_togglePlugin(q);
269 }, fadeTo: function (z, y, x) {
270 if (typeof y == "function") {
278 this.display = r._api().fp_fadeTo(q, z, y, w);
281 }, fadeIn: function (x, w) {
282 return p.fadeTo(1, x, w)
283 }, fadeOut: function (x, w) {
284 return p.fadeTo(0, x, w)
285 }, getName: function () {
287 }, getPlayer: function () {
289 }, _fireEvent: function (x, w, y) {
290 if (x == "onUpdate") {
291 var A = r._api().fp_getPlugin(q);
298 n(A.methods, function () {
301 var D = [].slice.call(arguments);
302 var E = r._api().fp_invoke(q, C, D);
303 return E === "undefined" || E === undefined ? p : E
311 var z = B.apply(p, w);
312 if (x.slice(0, 1) == "_") {
321 function b(r, H, u) {
322 var x = this, w = null, E = false, v, t, G = [], z = {}, y = {}, F, s, q, D, p, B;
323 j(x, {id: function () {
325 }, isLoaded: function () {
326 return(w !== null && w.fp_play !== undefined && !E)
327 }, getParent: function () {
329 }, hide: function (I) {
331 r.style.height = "0px"
334 w.style.height = "0px"
337 }, show: function () {
338 r.style.height = B + "px";
340 w.style.height = p + "px"
343 }, isHidden: function () {
344 return x.isLoaded() && parseInt(w.style.height, 10) === 0
345 }, load: function (K) {
346 if (!x.isLoaded() && x._fireEvent("onBeforeLoad") !== false) {
347 var I = function () {
348 if (v && !flashembed.isSupported(H.version)) {
355 flashembed(r, H, {config: u})
359 this.unload(function (L) {
360 if (++J == a.length) {
367 }, unload: function (K) {
368 if (v.replace(/\s/g, "") !== "") {
369 if (x._fireEvent("onBeforeUnload") === false) {
378 if (w.fp_isFullscreen()) {
379 w.fp_toggleFullscreen()
382 x._fireEvent("onUnload")
386 var J = function () {
394 if (/WebKit/i.test(navigator.userAgent) && !/Chrome/i.test(navigator.userAgent)) {
405 }, getClip: function (I) {
406 if (I === undefined) {
410 }, getCommonClip: function () {
412 }, getPlaylist: function () {
414 }, getPlugin: function (I) {
416 if (!K && x.isLoaded()) {
417 var J = x._api().fp_getPlugin(I);
424 }, getScreen: function () {
425 return x.getPlugin("screen")
426 }, getControls: function () {
427 return x.getPlugin("controls")._fireEvent("onUpdate")
428 }, getLogo: function () {
430 return x.getPlugin("logo")._fireEvent("onUpdate")
433 }, getPlay: function () {
434 return x.getPlugin("play")._fireEvent("onUpdate")
435 }, getConfig: function (I) {
437 }, getFlashParams: function () {
439 }, loadPlugin: function (L, K, N, M) {
440 if (typeof N == "function") {
444 var J = M ? f() : "_";
445 x._api().fp_loadPlugin(L, K, N, J);
448 var O = new m(L, null, x, I);
451 }, getState: function () {
452 return x.isLoaded() ? w.fp_getState() : -1
453 }, play: function (J, I) {
454 var K = function () {
455 if (J !== undefined) {
456 x._api().fp_play(J, I)
465 setTimeout(function () {
475 }, getVersion: function () {
476 var J = "flowplayer.js @VERSION";
478 var I = w.fp_getVersion();
483 }, _api: function () {
485 throw"Flowplayer " + x.id() + " not loaded when calling an API method"
488 }, setClip: function (I) {
489 n(I, function (J, K) {
490 if (typeof K == "function") {
494 if (J == "onCuepoint") {
495 $f(r).getCommonClip().onCuepoint(I[J][0], I[J][1])
501 }, getIndex: function () {
503 }, bufferAnimate: function (I) {
504 w.fp_bufferAnimate(I === undefined || I);
506 }, _swfHeight: function () {
507 return w.clientHeight
509 n(("Click*,Load*,Unload*,Keypress*,Volume*,Mute*,Unmute*,PlaylistReplace,ClipAdd,Fullscreen*,FullscreenExit,Error,MouseOver,MouseOut").split(","), function () {
511 if (I.indexOf("*") != -1) {
512 I = I.slice(0, I.length - 1);
513 var J = "onBefore" + I.slice(2);
514 x[J] = function (K) {
519 x[I] = function (K) {
524 n(("pause,resume,mute,unmute,stop,toggle,seek,getStatus,getVolume,setVolume,getTime,isPaused,isPlaying,startBuffering,stopBuffering,isFullscreen,toggleFullscreen,reset,close,setPlaylist,addClip,playFeed,setKeyboardShortcutsEnabled,isKeyboardShortcutsEnabled").split(","), function () {
526 x[I] = function (K, J) {
531 if (K !== undefined && J !== undefined) {
532 L = w["fp_" + I](K, J)
534 L = (K === undefined) ? w["fp_" + I]() : w["fp_" + I](K)
536 return L === "undefined" || L === undefined ? x : L
539 x._fireEvent = function (R) {
540 if (typeof R == "string") {
543 var S = R[0], P = R[1], N = R[2], M = R[3], L = 0;
547 if (!x.isLoaded() && S == "onLoad" && P == "player") {
551 this._fireEvent("onLoad")
553 n(z, function (T, U) {
554 U._fireEvent("onUpdate")
556 t._fireEvent("onLoad")
558 if (S == "onLoad" && P != "player") {
561 if (S == "onError") {
562 if (typeof P == "string" || (typeof P == "number" && typeof N == "number")) {
567 if (S == "onContextMenu") {
568 n(u.contextMenu[P], function (T, U) {
573 if (S == "onPluginEvent" || S == "onBeforePluginEvent") {
577 J._fireEvent("onUpdate", P);
578 return J._fireEvent(N, R.slice(3))
582 if (S == "onPlaylistReplace") {
586 G.push(new i(this, O++, x))
589 if (S == "onClipAdd") {
595 for (L = N + 1; L < G.length; L++) {
600 if (typeof P == "number" && P < G.length) {
604 Q = K._fireEvent(S, N, M)
606 if (!K || Q !== false) {
607 Q = t._fireEvent(S, N, M, K)
610 n(y[S], function () {
611 Q = this.call(x, P, N);
623 r.innerHTML=''; // Moodle hack - we do not want splashscreens, unfortunately there is not switch to disable them
625 $f(r).getParent().innerHTML = "";
626 q = $f(r).getIndex();
632 B = parseInt(r.style.height, 10) || r.clientHeight;
633 F = r.id || "fp" + f();
634 s = H.id || F + "_api";
637 if (typeof u == "string") {
641 u.clip = u.clip || {};
642 if (r.getAttribute("href", 2) && !u.clip.url) {
643 u.clip.url = r.getAttribute("href", 2)
646 u.clip.url = e(u.clip.url)
648 t = new i(u.clip, -1, x);
649 u.playlist = u.playlist || [u.clip];
651 n(u.playlist, function () {
653 if (typeof M == "object" && M.length) {
659 n(u.clip, function (N, O) {
660 if (O !== undefined && M[N] === undefined && typeof O != "function") {
669 n(u, function (M, N) {
670 if (typeof N == "function") {
679 n(u.plugins, function (M, N) {
681 z[M] = new m(M, N, x)
684 if (!u.plugins || u.plugins.controls === undefined) {
685 z.controls = new m("controls", null, x)
687 z.canvas = new m("canvas", null, x);
690 if (/iPad|iPhone|iPod/i.test(navigator.userAgent) && !/.flv$/i.test(G[0].url) && !K()) {
693 if (!x.isLoaded() && x._fireEvent("onBeforeClick") !== false) {
700 return x.hasiPadSupport && x.hasiPadSupport()
704 if (v.replace(/\s/g, "") !== "") {
705 if (r.addEventListener) {
706 r.addEventListener("click", L, false)
709 r.attachEvent("onclick", L)
713 if (r.addEventListener && !K()) {
714 r.addEventListener("click", g, false)
723 if (typeof r == "string") {
726 throw"Flowplayer cannot access element: " + r
738 this.length = p.length;
739 this.each = function (r) {
742 this.size = function () {
746 for (name in b.prototype) {
747 q[name] = function () {
750 this[name].apply(this, r)
756 window.flowplayer = window.$f = function () {
758 var p = arguments[0];
759 if(!flashembed.isSupported([6, 65])){return null;} // Moodle hack - we do not want the missing flash hints - we need the original links for accessibility and incompatible browsers
760 if (!arguments.length) {
762 if (this.isLoaded()) {
769 if (arguments.length == 1) {
770 if (typeof p == "number") {
777 if (this.id() == p.id || this.id() == p || this.getParent() == p) {
785 if (arguments.length > 1) {
786 var u = arguments[1], r = (arguments.length == 3) ? arguments[2] : {};
787 if (typeof u == "string") {
790 u = j({bgcolor: "#000000", version: [10, 1], expressInstall: "http://releases.flowplayer.org/swf/expressinstall.swf", cachebusting: false}, u);
791 if (typeof p == "string") {
792 if (p.indexOf(".") != -1) {
794 n(o(p), function () {
795 t.push(new b(this, l(u), l(r)))
800 return new b(s !== null ? s : l(p), l(u), l(r))
804 return new b(p, l(u), l(r))
810 j(window.$f, {fireEvent: function () {
811 var q = [].slice.call(arguments);
813 return r ? r._fireEvent(q.slice(1)) : null
814 }, addPlugin: function (p, q) {
817 }, each: n, extend: j});
818 if (typeof jQuery == "function") {
819 jQuery.fn.flowplayer = function (r, q) {
820 if (!arguments.length || typeof arguments[0] == "number") {
822 this.each(function () {
828 return arguments.length ? p[arguments[0]] : new d(p)
830 return this.each(function () {
831 $f(this, l(r), q ? l(q) : {})
837 var h = document.all, j = "http://get.adobe.com/flashplayer", c = typeof jQuery == "function", e = /(\d+)[^\d]+(\d+)[^\d]*(\d*)/, b = {width: "100%", height: "100%", id: "_" + ("" + Math.random()).slice(9), allowfullscreen: true, allowscriptaccess: "always", quality: "high", version: [3, 0], onFail: null, expressInstall: null, w3c: false, cachebusting: false};
838 if (window.attachEvent) {
839 window.attachEvent("onbeforeunload", function () {
840 __flash_unloadHandler = function () {
842 __flash_savedUnloadHandler = function () {
849 if (l.hasOwnProperty(f)) {
860 if (f.hasOwnProperty(l)) {
867 window.flashembed = function (f, m, l) {
868 if (typeof f == "string") {
869 f = document.getElementById(f.replace("#", ""))
874 if (typeof m == "string") {
877 return new d(f, i(i({}, b), m), l)
879 var g = i(window.flashembed, {conf: b, getVersion: function () {
882 o = navigator.plugins["Shockwave Flash"];
883 if (o[0].enabledPlugin != null) {
884 f = o.description.slice(16)
888 m = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
889 f = m && m.GetVariable("$version")
892 m = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
893 f = m && m.GetVariable("$version")
899 return f ? [1 * f[1], 1 * f[(f[1] * 1 > 9 ? 2 : 3)] * 1] : [0, 0]
900 }, asString: function (l) {
901 if (l === null || l === undefined) {
905 if (f == "object" && l.push) {
910 l = l.replace(new RegExp('(["\\\\])', "g"), "\\$1");
911 l = l.replace(/^\s?(\d+\.?\d*)%/, "$1pct");
914 return"[" + a(l,function (o) {
918 return'"function()"';
922 if (l.hasOwnProperty(n)) {
923 m.push('"' + n + '":' + g.asString(l[n]))
926 return"{" + m.join(",") + "}"
928 return String(l).replace(/\s/g, " ").replace(/\'/g, '"')
929 }, getHTML: function (o, l) {
931 var n = '<object width="' + o.width + '" height="' + o.height + '" id="' + o.id + '" name="' + o.id + '"';
932 if (o.cachebusting) {
933 o.src += ((o.src.indexOf("?") != -1 ? "&" : "?") + Math.random())
936 n += ' data="' + o.src + '" type="application/x-shockwave-flash"'
938 n += ' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'
942 n += '<param name="movie" value="' + o.src + '" />'
944 o.width = o.height = o.id = o.w3c = o.src = null;
945 o.onFail = o.version = o.expressInstall = null;
948 n += '<param name="' + m + '" value="' + o[m] + '" />'
956 p += f + "=" + (/function|object/.test(typeof q) ? g.asString(q) : q) + "&"
960 n += '<param name="flashvars" value=\'' + p + "' />"
964 }, isSupported: function (f) {
965 return k[0] > f[0] || k[0] == f[0] && k[1] >= f[1]
967 var k = g.getVersion();
969 function d(f, n, m) {
970 if (g.isSupported(n.version)) {
971 f.innerHTML = g.getHTML(n, m)
973 if (n.expressInstall && g.isSupported([6, 65])) {
974 f.innerHTML = g.getHTML(i(n, {src: n.expressInstall}), {MMredirectURL: encodeURIComponent(location.href), MMplayerType: "PlugIn", MMdoctitle: document.title})
976 if (!f.innerHTML.replace(/\s/g, "")) {
977 f.innerHTML = "<h2>Flash version " + n.version + " or greater is required</h2><h3>" + (k[0] > 0 ? "Your version is " + k : "You have no flash plugin installed") + "</h3>" + (f.tagName == "A" ? "<p>Click here to download latest version</p>" : "<p>Download latest version from <a href='" + j + "'>here</a></p>");
978 if (f.tagName == "A" || f.tagName == "DIV") {
979 f.onclick = function () {
985 var l = n.onFail.call(this);
986 if (typeof l == "string") {
993 window[n.id] = document.getElementById(n.id)
995 i(this, {getRoot: function () {
997 }, getOptions: function () {
999 }, getConf: function () {
1001 }, getApi: function () {
1007 jQuery.tools = jQuery.tools || {version: "@VERSION"};
1008 jQuery.tools.flashembed = {conf: b};
1009 jQuery.fn.flashembed = function (l, f) {
1010 return this.each(function () {
1011 $(this).data("flashembed", flashembed(this, l, f))