~mahara-contributors/mahara-adminlang/adminlang-master

« back to all changes in this revision

Viewing changes to htdocs/artefact/file/blocktype/internalmedia/flowplayer/flowplayer-3.2.4.js

  • Committer: Ruslan Kabalin
  • Date: 2011-08-03 14:54:09 UTC
  • Revision ID: git-v1:a3409b53a971ec3bad8b5d1329298046d9596381
Revert back to master brach.

The adminlang-master was mistakingly based on the mahara 1.3_STABLE. This is
required for easy merge with the master.

Command used:
for i in `git rev-list
f731cf9b2cf72b61ed6a317acab23a30b9046c8a..afb5850ba246f41b624c162e8d8e6e72c534f239`;
do git revert -n $i; done

Change-Id: I9db8553a66facfaca81492cd978f974c6e7b8892

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/** 
2
 
 * flowplayer.js 3.2.4. The Flowplayer API
3
 
 * 
4
 
 * Copyright 2009 Flowplayer Oy
5
 
 * 
6
 
 * This file is part of Flowplayer.
7
 
 * 
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.
12
 
 * 
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.
17
 
 * 
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/>.
20
 
 * 
21
 
 * Date: 2010-08-25 12:48:46 +0000 (Wed, 25 Aug 2010)
22
 
 * Revision: 551 
23
 
 */
24
 
(function() {
25
 
 
26
 
/* 
27
 
        FEATURES 
28
 
        --------
29
 
        - $f() and flowplayer() functions       
30
 
        - handling multiple instances 
31
 
        - Flowplayer programming API 
32
 
        - Flowplayer event model        
33
 
        - player loading / unloading    
34
 
        - jQuery support
35
 
*/ 
36
 
 
37
 
 
38
 
/*jslint glovar: true, browser: true */
39
 
/*global flowplayer, $f */
40
 
 
41
 
// {{{ private utility methods
42
 
        
43
 
        function log(args) {
44
 
                console.log("$f.fireEvent", [].slice.call(args));       
45
 
        }
46
 
 
47
 
                
48
 
        // thanks: http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
49
 
        function clone(obj) {   
50
 
                if (!obj || typeof obj != 'object') { return obj; }             
51
 
                var temp = new obj.constructor();       
52
 
                for (var key in obj) {  
53
 
                        if (obj.hasOwnProperty(key)) {
54
 
                                temp[key] = clone(obj[key]);
55
 
                        }
56
 
                }               
57
 
                return temp;
58
 
        }
59
 
 
60
 
        // stripped from jQuery, thanks John Resig 
61
 
        function each(obj, fn) {
62
 
                if (!obj) { return; }
63
 
                
64
 
                var name, i = 0, length = obj.length;
65
 
        
66
 
                // object
67
 
                if (length === undefined) {
68
 
                        for (name in obj) {
69
 
                                if (fn.call(obj[name], name, obj[name]) === false) { break; }
70
 
                        }
71
 
                        
72
 
                // array
73
 
                } else {
74
 
                        for (var value = obj[0];
75
 
                                i < length && fn.call( value, i, value ) !== false; value = obj[++i]) {                         
76
 
                        }
77
 
                }
78
 
        
79
 
                return obj;
80
 
        }
81
 
 
82
 
        
83
 
        // convenience
84
 
        function el(id) {
85
 
                return document.getElementById(id);     
86
 
        }       
87
 
 
88
 
        
89
 
        // used extensively. a very simple implementation. 
90
 
        function extend(to, from, skipFuncs) {
91
 
                if (typeof from != 'object') { return to; }
92
 
                
93
 
                if (to && from) {                       
94
 
                        each(from, function(name, value) {
95
 
                                if (!skipFuncs || typeof value != 'function') {
96
 
                                        to[name] = value;               
97
 
                                }
98
 
                        });
99
 
                }
100
 
                
101
 
                return to;
102
 
        }
103
 
        
104
 
        // var arr = select("elem.className"); 
105
 
        function select(query) {
106
 
                var index = query.indexOf("."); 
107
 
                if (index != -1) {
108
 
                        var tag = query.slice(0, index) || "*";
109
 
                        var klass = query.slice(index + 1, query.length);
110
 
                        var els = [];
111
 
                        each(document.getElementsByTagName(tag), function() {
112
 
                                if (this.className && this.className.indexOf(klass) != -1) {
113
 
                                        els.push(this);         
114
 
                                }
115
 
                        });
116
 
                        return els;
117
 
                }
118
 
        }
119
 
        
120
 
        // fix event inconsistencies across browsers
121
 
        function stopEvent(e) {
122
 
                e = e || window.event;
123
 
                
124
 
                if (e.preventDefault) {
125
 
                        e.stopPropagation();
126
 
                        e.preventDefault();
127
 
                        
128
 
                } else {
129
 
                        e.returnValue = false;  
130
 
                        e.cancelBubble = true;
131
 
                } 
132
 
                return false;
133
 
        }
134
 
 
135
 
        // push an event listener into existing array of listeners
136
 
        function bind(to, evt, fn) {
137
 
                to[evt] = to[evt] || [];
138
 
                to[evt].push(fn);               
139
 
        }
140
 
        
141
 
        
142
 
        // generates an unique id
143
 
   function makeId() {
144
 
      return "_" + ("" + Math.random()).slice(2, 10);   
145
 
   }
146
 
        
147
 
//}}}   
148
 
        
149
 
 
150
 
// {{{ Clip
151
 
 
152
 
        var Clip = function(json, index, player) {
153
 
                
154
 
                // private variables
155
 
                var self = this,
156
 
                         cuepoints = {},
157
 
                         listeners = {};
158
 
                         
159
 
                self.index = index;
160
 
                
161
 
                // instance variables
162
 
                if (typeof json == 'string') {
163
 
                        json = {url:json};      
164
 
                }
165
 
        
166
 
                extend(this, json, true);       
167
 
                
168
 
                // event handling 
169
 
                each(("Begin*,Start,Pause*,Resume*,Seek*,Stop*,Finish*,LastSecond,Update,BufferFull,BufferEmpty,BufferStop").split(","),
170
 
                        function() {
171
 
                        
172
 
                        var evt = "on" + this;
173
 
                                
174
 
                        // before event
175
 
                        if (evt.indexOf("*") != -1) {
176
 
                                evt = evt.slice(0, evt.length -1); 
177
 
                                var before = "onBefore" + evt.slice(2); 
178
 
                                
179
 
                                self[before] = function(fn) {
180
 
                                        bind(listeners, before, fn);
181
 
                                        return self;
182
 
                                };                              
183
 
                        }  
184
 
                        
185
 
                        self[evt] = function(fn) {
186
 
                                bind(listeners, evt, fn);
187
 
                                return self;
188
 
                        };
189
 
                        
190
 
                        
191
 
                        // set common clip event listeners to player level
192
 
                        if (index == -1) {
193
 
                                if (self[before]) {
194
 
                                        player[before] = self[before];          
195
 
                                }                               
196
 
                                if (self[evt])  {
197
 
                                        player[evt] = self[evt];                
198
 
                                }
199
 
                        }
200
 
                        
201
 
                });                       
202
 
                
203
 
                extend(this, { 
204
 
                         
205
 
                        onCuepoint: function(points, fn) {    
206
 
                                
207
 
                                // embedded cuepoints
208
 
                                if (arguments.length == 1) {
209
 
                                        cuepoints.embedded = [null, points];
210
 
                                        return self;
211
 
                                }
212
 
                                
213
 
                                if (typeof points == 'number') {
214
 
                                        points = [points];      
215
 
                                }
216
 
                                
217
 
                                var fnId = makeId();  
218
 
                                cuepoints[fnId] = [points, fn]; 
219
 
                                
220
 
                                if (player.isLoaded()) {
221
 
                                        player._api().fp_addCuepoints(points, index, fnId);     
222
 
                                }  
223
 
                                
224
 
                                return self;
225
 
                        },
226
 
                        
227
 
                        update: function(json) {
228
 
                                extend(self, json);
229
 
 
230
 
                                if (player.isLoaded()) {
231
 
                                        player._api().fp_updateClip(json, index);       
232
 
                                }
233
 
                                var conf = player.getConfig(); 
234
 
                                var clip = (index == -1) ? conf.clip : conf.playlist[index];
235
 
                                extend(clip, json, true);
236
 
                        },
237
 
                        
238
 
                        
239
 
                        // internal event for performing clip tasks. should be made private someday
240
 
                        _fireEvent: function(evt, arg1, arg2, target) { 
241
 
                                if (evt == 'onLoad') { 
242
 
                                        each(cuepoints, function(key, val) {
243
 
                                                if (val[0]) {
244
 
                                                        player._api().fp_addCuepoints(val[0], index, key);              
245
 
                                                }
246
 
                                        }); 
247
 
                                        return false;
248
 
                                }
249
 
                                
250
 
                                // target clip we are working against
251
 
                                target = target || self;        
252
 
                                
253
 
                                if (evt == 'onCuepoint') {
254
 
                                        var fn = cuepoints[arg1];
255
 
                                        if (fn) {
256
 
                                                return fn[1].call(player, target, arg2);
257
 
                                        }
258
 
                                }  
259
 
 
260
 
                                // 1. clip properties, 2-3. metadata, 4. updates, 5. resumes from nested clip
261
 
                                if (arg1 && "onBeforeBegin,onMetaData,onStart,onUpdate,onResume".indexOf(evt) != -1) {                                  
262
 
                                        // update clip properties
263
 
                                        extend(target, arg1);                                   
264
 
                                        
265
 
                                        if (arg1.metaData) {
266
 
                                                if (!target.duration) {
267
 
                                                        target.duration = arg1.metaData.duration;       
268
 
                                                } else {
269
 
                                                        target.fullDuration = arg1.metaData.duration;   
270
 
                                                }                                       
271
 
                                        }
272
 
                                }                               
273
 
                                
274
 
 
275
 
                                var ret = true;
276
 
                                each(listeners[evt], function() {
277
 
                                        ret = this.call(player, target, arg1, arg2);            
278
 
                                }); 
279
 
                                return ret;                             
280
 
                        }                       
281
 
                        
282
 
                });
283
 
                
284
 
                
285
 
                // get cuepoints from config
286
 
                if (json.onCuepoint) {
287
 
                        var arg = json.onCuepoint;
288
 
                        self.onCuepoint.apply(self, typeof arg == 'function' ? [arg] : arg);
289
 
                        delete json.onCuepoint;
290
 
                } 
291
 
                
292
 
                // get other events
293
 
                each(json, function(key, val) {
294
 
                        
295
 
                        if (typeof val == 'function') {
296
 
                                bind(listeners, key, val);
297
 
                                delete json[key];
298
 
                        }
299
 
                        
300
 
                });
301
 
 
302
 
                
303
 
                // setup common clip event callbacks for Player object too (shortcuts)
304
 
                if (index == -1) {
305
 
                        player.onCuepoint = this.onCuepoint;    
306
 
                }
307
 
 
308
 
        };
309
 
 
310
 
//}}}
311
 
 
312
 
 
313
 
// {{{ Plugin
314
 
                
315
 
        var Plugin = function(name, json, player, fn) {
316
 
        
317
 
                var self = this,
318
 
                         listeners = {},
319
 
                         hasMethods = false;
320
 
        
321
 
                if (fn) {
322
 
                        extend(listeners, fn);  
323
 
                }   
324
 
                
325
 
                // custom callback functions in configuration
326
 
                each(json, function(key, val) {
327
 
                        if (typeof val == 'function') {
328
 
                                listeners[key] = val;
329
 
                                delete json[key];       
330
 
                        }
331
 
                });  
332
 
                
333
 
                // core plugin methods          
334
 
                extend(this, {
335
 
  
336
 
                        // speed and fn are optional
337
 
                        animate: function(props, speed, fn) { 
338
 
                                if (!props) {
339
 
                                        return self;    
340
 
                                }
341
 
                                
342
 
                                if (typeof speed == 'function') { 
343
 
                                        fn = speed; 
344
 
                                        speed = 500;
345
 
                                }
346
 
                                
347
 
                                if (typeof props == 'string') {
348
 
                                        var key = props;
349
 
                                        props = {};
350
 
                                        props[key] = speed;
351
 
                                        speed = 500; 
352
 
                                }
353
 
                                
354
 
                                if (fn) {
355
 
                                        var fnId = makeId();
356
 
                                        listeners[fnId] = fn;
357
 
                                }
358
 
                
359
 
                                if (speed === undefined) { speed = 500; }
360
 
                                json = player._api().fp_animate(name, props, speed, fnId);      
361
 
                                return self;
362
 
                        },
363
 
                        
364
 
                        css: function(props, val) {
365
 
                                if (val !== undefined) {
366
 
                                        var css = {};
367
 
                                        css[props] = val;
368
 
                                        props = css;                                    
369
 
                                }
370
 
                                json = player._api().fp_css(name, props);
371
 
                                extend(self, json);
372
 
                                return self;
373
 
                        },
374
 
                        
375
 
                        show: function() {
376
 
                                this.display = 'block';
377
 
                                player._api().fp_showPlugin(name);
378
 
                                return self;
379
 
                        },
380
 
                        
381
 
                        hide: function() {
382
 
                                this.display = 'none';
383
 
                                player._api().fp_hidePlugin(name);
384
 
                                return self;
385
 
                        },
386
 
                        
387
 
                        // toggle between visible / hidden state
388
 
                        toggle: function() {
389
 
                                this.display = player._api().fp_togglePlugin(name);
390
 
                                return self;
391
 
                        },                      
392
 
                        
393
 
                        fadeTo: function(o, speed, fn) {
394
 
                                
395
 
                                if (typeof speed == 'function') { 
396
 
                                        fn = speed; 
397
 
                                        speed = 500;
398
 
                                }
399
 
                                
400
 
                                if (fn) {
401
 
                                        var fnId = makeId();
402
 
                                        listeners[fnId] = fn;
403
 
                                }                               
404
 
                                this.display = player._api().fp_fadeTo(name, o, speed, fnId);
405
 
                                this.opacity = o;
406
 
                                return self;
407
 
                        },
408
 
                        
409
 
                        fadeIn: function(speed, fn) { 
410
 
                                return self.fadeTo(1, speed, fn);                               
411
 
                        },
412
 
        
413
 
                        fadeOut: function(speed, fn) {
414
 
                                return self.fadeTo(0, speed, fn);       
415
 
                        },
416
 
                        
417
 
                        getName: function() {
418
 
                                return name;    
419
 
                        },
420
 
                        
421
 
                        getPlayer: function() {
422
 
                                return player;  
423
 
                        },
424
 
                        
425
 
                        // internal method. should be made private some day
426
 
         _fireEvent: function(evt, arg, arg2) {
427
 
                                
428
 
            // update plugins properties & methods
429
 
            if (evt == 'onUpdate') {
430
 
               var json = player._api().fp_getPlugin(name); 
431
 
                                        if (!json) { return;    }                                       
432
 
                                        
433
 
               extend(self, json);
434
 
               delete self.methods;
435
 
                                        
436
 
               if (!hasMethods) {
437
 
                  each(json.methods, function() {
438
 
                     var method = "" + this;       
439
 
                                                        
440
 
                     self[method] = function() {
441
 
                        var a = [].slice.call(arguments);
442
 
                        var ret = player._api().fp_invoke(name, method, a); 
443
 
                        return ret === 'undefined' || ret === undefined ? self : ret;
444
 
                     };
445
 
                  });
446
 
                  hasMethods = true;         
447
 
               }
448
 
            }
449
 
            
450
 
            // plugin callbacks
451
 
            var fn = listeners[evt];
452
 
 
453
 
                        if (fn) {
454
 
                                var ret = fn.apply(self, arg);
455
 
                                        
456
 
                                // "one-shot" callback
457
 
                                if (evt.slice(0, 1) == "_") {
458
 
                                        delete listeners[evt];  
459
 
                                } 
460
 
                                
461
 
                                return ret;
462
 
            }
463
 
            
464
 
            return self;
465
 
         }
466
 
                        
467
 
                });
468
 
 
469
 
        };
470
 
 
471
 
 
472
 
//}}}
473
 
 
474
 
 
475
 
function Player(wrapper, params, conf) {   
476
 
        
477
 
        // private variables (+ arguments)
478
 
        var self = this, 
479
 
                api = null, 
480
 
                isUnloading = false,
481
 
                html, 
482
 
                commonClip, 
483
 
                playlist = [], 
484
 
                plugins = {},
485
 
                listeners = {},
486
 
                playerId,
487
 
                apiId,
488
 
                
489
 
                // n'th player on the page
490
 
                playerIndex,
491
 
                
492
 
                // active clip's index number
493
 
                activeIndex,
494
 
                
495
 
                swfHeight,
496
 
                wrapperHeight;  
497
 
 
498
 
  
499
 
// {{{ public methods 
500
 
        
501
 
        extend(self, {
502
 
                        
503
 
                id: function() {
504
 
                        return playerId;        
505
 
                }, 
506
 
                
507
 
                isLoaded: function() {
508
 
                        return (api !== null && api.fp_play !== undefined && !isUnloading);     
509
 
                },
510
 
                
511
 
                getParent: function() {
512
 
                        return wrapper; 
513
 
                },
514
 
                
515
 
                hide: function(all) {
516
 
                        if (all) { wrapper.style.height = "0px"; }
517
 
                        if (self.isLoaded()) { api.style.height = "0px"; } 
518
 
                        return self;
519
 
                },
520
 
 
521
 
                show: function() {
522
 
                        wrapper.style.height = wrapperHeight + "px";
523
 
                        if (self.isLoaded()) { api.style.height = swfHeight + "px"; }
524
 
                        return self;
525
 
                }, 
526
 
                                        
527
 
                isHidden: function() {
528
 
                        return self.isLoaded() && parseInt(api.style.height, 10) === 0;
529
 
                },
530
 
                
531
 
                load: function(fn) { 
532
 
                        if (!self.isLoaded() && self._fireEvent("onBeforeLoad") !== false) {
533
 
                                var onPlayersUnloaded = function() {
534
 
                                        html = wrapper.innerHTML;                               
535
 
                                
536
 
                                        // do not use splash as alternate content for flashembed
537
 
                                        if (html && !flashembed.isSupported(params.version)) {
538
 
                                                wrapper.innerHTML = "";                                 
539
 
                                        }                                 
540
 
                                        
541
 
                                        // onLoad listener given as argument
542
 
                                        if (fn) {
543
 
                                                fn.cached = true;
544
 
                                                bind(listeners, "onLoad", fn);  
545
 
                                        }
546
 
                                        
547
 
                                        // install Flash object inside given container
548
 
                                        flashembed(wrapper, params, {config: conf});
549
 
                                };
550
 
                                
551
 
                                
552
 
                                // unload all instances
553
 
                                var unloadedPlayersNb = 0;
554
 
                                each(players, function()  {
555
 
                                        this.unload(function(wasUnloaded) {
556
 
                                                if ( ++unloadedPlayersNb == players.length ) {
557
 
                                                        onPlayersUnloaded();
558
 
                                                }
559
 
                                        });             
560
 
                                });
561
 
                        }
562
 
                        
563
 
                        return self;    
564
 
                },
565
 
                
566
 
                unload: function(fn) {
567
 
                        
568
 
                        
569
 
                        // if we are fullscreen on safari, we can't unload as it would crash the PluginHost, sorry
570
 
                        if (this.isFullscreen() && /WebKit/i.test(navigator.userAgent)) {
571
 
                                if ( fn ) { fn(false); }
572
 
                                return self;
573
 
                        }
574
 
                        
575
 
                        
576
 
                        // unload only if in splash state
577
 
                        if (html.replace(/\s/g,'') !== '') {
578
 
                                
579
 
                                if (self._fireEvent("onBeforeUnload") === false) {
580
 
                                        if ( fn ) { fn(false); }
581
 
                                        return self;
582
 
                                }       
583
 
                                
584
 
                                isUnloading = true;
585
 
                                // try closing
586
 
                                try {
587
 
                                        if (api) { 
588
 
                                                api.fp_close();
589
 
                                                
590
 
                                                // fire unload only when API is present
591
 
                                                self._fireEvent("onUnload");
592
 
                                        }                               
593
 
                                } catch (error) {}                              
594
 
                                
595
 
                                var clean = function() {
596
 
                                        api = null;                             
597
 
                                        wrapper.innerHTML = html;
598
 
                                        isUnloading = false;
599
 
                                        
600
 
                                        if ( fn ) { fn(true); }
601
 
                                };
602
 
                                
603
 
                                setTimeout(clean, 50);                  
604
 
                        } 
605
 
                        else if ( fn ) { fn(false); }
606
 
                        
607
 
                        return self;
608
 
                
609
 
                },
610
 
                
611
 
                getClip: function(index) {
612
 
                        if (index === undefined) {
613
 
                                index = activeIndex;    
614
 
                        }
615
 
                        return playlist[index];
616
 
                },
617
 
                
618
 
                
619
 
                getCommonClip: function() {
620
 
                        return commonClip;      
621
 
                },              
622
 
                
623
 
                getPlaylist: function() {
624
 
                        return playlist; 
625
 
                },
626
 
                
627
 
      getPlugin: function(name) {  
628
 
         var plugin = plugins[name];
629
 
         
630
 
                        // create plugin if nessessary
631
 
         if (!plugin && self.isLoaded()) {
632
 
                                var json = self._api().fp_getPlugin(name);
633
 
                                if (json) {
634
 
                                        plugin = new Plugin(name, json, self);
635
 
                                        plugins[name] = plugin;                                                 
636
 
                                } 
637
 
         }        
638
 
         return plugin; 
639
 
      },
640
 
                
641
 
                getScreen: function() { 
642
 
                        return self.getPlugin("screen");
643
 
                }, 
644
 
                
645
 
                getControls: function() { 
646
 
                        return self.getPlugin("controls")._fireEvent("onUpdate");
647
 
                }, 
648
 
                
649
 
                // 3.2
650
 
                getLogo: function() {
651
 
                        try {
652
 
                                return self.getPlugin("logo")._fireEvent("onUpdate");
653
 
                        } catch (ignored) {}
654
 
                },
655
 
                
656
 
                // 3.2
657
 
                getPlay: function() {
658
 
                        return self.getPlugin("play")._fireEvent("onUpdate");
659
 
                },
660
 
                
661
 
 
662
 
                getConfig: function(copy) { 
663
 
                        return copy ? clone(conf) : conf;
664
 
                },
665
 
                
666
 
                getFlashParams: function() { 
667
 
                        return params;
668
 
                },              
669
 
                
670
 
                loadPlugin: function(name, url, props, fn) { 
671
 
 
672
 
                        // properties not supplied                      
673
 
                        if (typeof props == 'function') { 
674
 
                                fn = props; 
675
 
                                props = {};
676
 
                        } 
677
 
                        
678
 
                        // if fn not given, make a fake id so that plugin's onUpdate get's fired
679
 
                        var fnId = fn ? makeId() : "_"; 
680
 
                        self._api().fp_loadPlugin(name, url, props, fnId); 
681
 
                        
682
 
                        // create new plugin
683
 
                        var arg = {};
684
 
                        arg[fnId] = fn;
685
 
                        var p = new Plugin(name, null, self, arg);
686
 
                        plugins[name] = p;
687
 
                        return p;                       
688
 
                },
689
 
                
690
 
                
691
 
                getState: function() {
692
 
                        return self.isLoaded() ? api.fp_getState() : -1;
693
 
                },
694
 
                
695
 
                // "lazy" play
696
 
                play: function(clip, instream) {
697
 
                        
698
 
                        var p = function() {
699
 
                                if (clip !== undefined) {
700
 
                                        self._api().fp_play(clip, instream);
701
 
                                } else {
702
 
                                        self._api().fp_play();  
703
 
                                }
704
 
                        };
705
 
                        
706
 
                        if (self.isLoaded()) {
707
 
                                p();    
708
 
                        } else if ( isUnloading ) {
709
 
                                setTimeout(function() { 
710
 
                                        self.play(clip, instream); 
711
 
                                }, 50);
712
 
                                
713
 
                        } else {
714
 
                                self.load(function() { 
715
 
                                        p();
716
 
                                });
717
 
                        }
718
 
                        
719
 
                        return self;
720
 
                },
721
 
                
722
 
                getVersion: function() {
723
 
                        var js = "flowplayer.js 3.2.4";
724
 
                        if (self.isLoaded()) {
725
 
                                var ver = api.fp_getVersion();
726
 
                                ver.push(js);
727
 
                                return ver;
728
 
                        }
729
 
                        return js; 
730
 
                },
731
 
                
732
 
                _api: function() {
733
 
                        if (!self.isLoaded()) {
734
 
                                throw "Flowplayer " +self.id()+ " not loaded when calling an API method";
735
 
                        }
736
 
                        return api;                             
737
 
                },
738
 
                
739
 
                setClip: function(clip) {
740
 
                        self.setPlaylist([clip]);
741
 
                        return self;
742
 
                },
743
 
                
744
 
                getIndex: function() {
745
 
                        return playerIndex;     
746
 
                },
747
 
                
748
 
                _swfHeight: function() {
749
 
                        return api.clientHeight;
750
 
                }
751
 
                
752
 
        }); 
753
 
        
754
 
        
755
 
        // event handlers
756
 
        each(("Click*,Load*,Unload*,Keypress*,Volume*,Mute*,Unmute*,PlaylistReplace,ClipAdd,Fullscreen*,FullscreenExit,Error,MouseOver,MouseOut").split(","),
757
 
                function() {             
758
 
                        var name = "on" + this;
759
 
                        
760
 
                        // before event
761
 
                        if (name.indexOf("*") != -1) {
762
 
                                name = name.slice(0, name.length -1); 
763
 
                                var name2 = "onBefore" + name.slice(2);
764
 
                                self[name2] = function(fn) {
765
 
                                        bind(listeners, name2, fn);     
766
 
                                        return self;
767
 
                                };                                              
768
 
                        }
769
 
                        
770
 
                        // normal event
771
 
                        self[name] = function(fn) {
772
 
                                bind(listeners, name, fn);      
773
 
                                return self;
774
 
                        };                       
775
 
                }
776
 
        ); 
777
 
        
778
 
        
779
 
        // core API methods
780
 
        each(("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(","),              
781
 
                function() {             
782
 
                        var name = this;
783
 
                        
784
 
                        self[name] = function(a1, a2) {
785
 
                                if (!self.isLoaded()) { return self; }
786
 
                                var ret = null;
787
 
                                
788
 
                                // two arguments
789
 
                                if (a1 !== undefined && a2 !== undefined) { 
790
 
                                        ret = api["fp_" + name](a1, a2);
791
 
                                        
792
 
                                } else { 
793
 
                                        ret = (a1 === undefined) ? api["fp_" + name]() : api["fp_" + name](a1);
794
 
                                        
795
 
                                }
796
 
                                                        
797
 
                                return ret === 'undefined' || ret === undefined ? self : ret;
798
 
                        };                       
799
 
                }
800
 
        );              
801
 
        
802
 
//}}}
803
 
 
804
 
 
805
 
// {{{ public method: _fireEvent
806
 
                
807
 
        self._fireEvent = function(a) {         
808
 
                
809
 
                if (typeof a == 'string') { a = [a]; }
810
 
                
811
 
                var evt = a[0], arg0 = a[1], arg1 = a[2], arg2 = a[3], i = 0;           
812
 
                if (conf.debug) { log(a); }                             
813
 
                
814
 
                // internal onLoad
815
 
                if (!self.isLoaded() && evt == 'onLoad' && arg0 == 'player') {                                          
816
 
                        
817
 
                        api = api || el(apiId); 
818
 
                        swfHeight = self._swfHeight();
819
 
                        
820
 
                        each(playlist, function() {
821
 
                                this._fireEvent("onLoad");              
822
 
                        });
823
 
                        
824
 
                        each(plugins, function(name, p) {
825
 
                                p._fireEvent("onUpdate");               
826
 
                        }); 
827
 
                        
828
 
                        commonClip._fireEvent("onLoad");  
829
 
                }
830
 
                
831
 
                // other onLoad events are skipped
832
 
                if (evt == 'onLoad' && arg0 != 'player') { return; }
833
 
                
834
 
                
835
 
                // "normalize" error handling
836
 
                if (evt == 'onError') { 
837
 
                        if (typeof arg0 == 'string' || (typeof arg0 == 'number' && typeof arg1 == 'number'))  {
838
 
                                arg0 = arg1;
839
 
                                arg1 = arg2;
840
 
                        }                        
841
 
                }
842
 
                
843
 
                
844
 
      if (evt == 'onContextMenu') {
845
 
         each(conf.contextMenu[arg0], function(key, fn)  {
846
 
            fn.call(self);
847
 
         });
848
 
         return;
849
 
      }
850
 
 
851
 
                if (evt == 'onPluginEvent' || evt == 'onBeforePluginEvent') { 
852
 
                        var name = arg0.name || arg0;
853
 
                        var p = plugins[name];
854
 
 
855
 
                        if (p) {
856
 
                                p._fireEvent("onUpdate", arg0);
857
 
                                return p._fireEvent(arg1, a.slice(3));          
858
 
                        }
859
 
                        return;
860
 
                }               
861
 
 
862
 
                // replace whole playlist
863
 
                if (evt == 'onPlaylistReplace') {
864
 
                        playlist = [];
865
 
                        var index = 0;
866
 
                        each(arg0, function() {
867
 
                                playlist.push(new Clip(this, index++, self));
868
 
                        });             
869
 
                }
870
 
                
871
 
                // insert new clip to the playlist. arg0 = clip, arg1 = index 
872
 
                if (evt == 'onClipAdd') {
873
 
                        
874
 
                        // instream clip additions are ignored at this point
875
 
                        if (arg0.isInStream) { return; }
876
 
                        
877
 
                        // add new clip into playlist                   
878
 
                        arg0 = new Clip(arg0, arg1, self);
879
 
                        playlist.splice(arg1, 0, arg0);
880
 
                        
881
 
                        // increment index variable for the rest of the clips on playlist 
882
 
                        for (i = arg1 + 1; i < playlist.length; i++) {
883
 
                                playlist[i].index++;    
884
 
                        }
885
 
                }
886
 
                
887
 
                
888
 
                var ret = true;
889
 
                
890
 
                // clip event
891
 
                if (typeof arg0 == 'number' && arg0 < playlist.length) {
892
 
                        
893
 
                        activeIndex = arg0;
894
 
                        var clip = playlist[arg0];                      
895
 
                        
896
 
                        if (clip) {
897
 
                                ret = clip._fireEvent(evt, arg1, arg2); 
898
 
                        } 
899
 
                        
900
 
                        if (!clip || ret !== false) {
901
 
                                // clip argument is given for common clip, because it behaves as the target
902
 
                                ret = commonClip._fireEvent(evt, arg1, arg2, clip);     
903
 
                        }  
904
 
                }
905
 
                
906
 
                
907
 
                // trigger player event
908
 
                each(listeners[evt], function() {
909
 
                        ret = this.call(self, arg0, arg1);              
910
 
                        
911
 
                        // remove cached entry
912
 
                        if (this.cached) {
913
 
                                listeners[evt].splice(i, 1);    
914
 
                        }
915
 
                        
916
 
                        // break loop
917
 
                        if (ret === false) { return false;       }
918
 
                        i++;
919
 
                        
920
 
                }); 
921
 
 
922
 
                return ret;
923
 
        };
924
 
 
925
 
//}}}
926
 
 
927
 
 
928
 
// {{{ init
929
 
        
930
 
   function init() {
931
 
                // replace previous installation 
932
 
                if ($f(wrapper)) {
933
 
                        $f(wrapper).getParent().innerHTML = ""; 
934
 
                        playerIndex = $f(wrapper).getIndex();
935
 
                        players[playerIndex] = self;
936
 
                        
937
 
                // register this player into global array of instances
938
 
                } else {
939
 
                        players.push(self);
940
 
                        playerIndex = players.length -1;
941
 
                }
942
 
                
943
 
                wrapperHeight = parseInt(wrapper.style.height, 10) || wrapper.clientHeight;     
944
 
                
945
 
                // playerId     
946
 
                playerId = wrapper.id || "fp" + makeId();
947
 
                apiId = params.id || playerId + "_api";
948
 
                params.id = apiId;
949
 
                conf.playerId = playerId;
950
 
                
951
 
 
952
 
                // plain url is given as config
953
 
                if (typeof conf == 'string') {
954
 
                        conf = {clip:{url:conf}};       
955
 
                } 
956
 
                
957
 
                if (typeof conf.clip == 'string') {
958
 
                        conf.clip = {url: conf.clip};   
959
 
                }
960
 
                
961
 
                // common clip is always there
962
 
                conf.clip = conf.clip || {};  
963
 
                
964
 
                
965
 
                // wrapper href as common clip's url
966
 
                if (wrapper.getAttribute("href", 2) && !conf.clip.url) { 
967
 
                        conf.clip.url = wrapper.getAttribute("href", 2);                        
968
 
                } 
969
 
                
970
 
                commonClip = new Clip(conf.clip, -1, self); 
971
 
                
972
 
                // playlist
973
 
                conf.playlist = conf.playlist || [conf.clip]; 
974
 
                
975
 
                var index = 0;
976
 
                
977
 
                each(conf.playlist, function() {
978
 
                        
979
 
                        var clip = this;                        
980
 
                        
981
 
                        /* sometimes clip is given as array. this is not accepted. */
982
 
                        if (typeof clip == 'object' && clip.length) {
983
 
                                clip = {url: "" + clip};        
984
 
                        }                       
985
 
                        
986
 
                        // populate common clip properties to each clip
987
 
                        each(conf.clip, function(key, val) {
988
 
                                if (val !== undefined && clip[key] === undefined && typeof val != 'function') {
989
 
                                        clip[key] = val;        
990
 
                                }
991
 
                        });     
992
 
                        
993
 
                        // modify playlist in configuration
994
 
                        conf.playlist[index] = clip;                    
995
 
                        
996
 
                        // populate playlist array
997
 
                        clip = new Clip(clip, index, self);
998
 
                        playlist.push(clip);                                            
999
 
                        index++;                        
1000
 
                });                             
1001
 
                
1002
 
                // event listeners
1003
 
                each(conf, function(key, val) {
1004
 
                        if (typeof val == 'function') {
1005
 
                                
1006
 
                                // common clip event
1007
 
                                if (commonClip[key]) {
1008
 
                                        commonClip[key](val);
1009
 
                                        
1010
 
                                // player event
1011
 
                                } else {
1012
 
                                        bind(listeners, key, val);      
1013
 
                                }                               
1014
 
                                
1015
 
                                // no need to supply for the Flash component
1016
 
                                delete conf[key];       
1017
 
                        }
1018
 
                });              
1019
 
                
1020
 
                
1021
 
                // plugins
1022
 
                each(conf.plugins, function(name, val) {
1023
 
                        if (val) {
1024
 
                                plugins[name] = new Plugin(name, val, self);
1025
 
                        }
1026
 
                });
1027
 
                
1028
 
                
1029
 
                // setup controlbar plugin if not explicitly defined
1030
 
                if (!conf.plugins || conf.plugins.controls === undefined) {
1031
 
                        plugins.controls = new Plugin("controls", null, self);  
1032
 
                }
1033
 
                
1034
 
                // setup canvas as plugin
1035
 
                plugins.canvas = new Plugin("canvas", null, self);              
1036
 
                
1037
 
                html = wrapper.innerHTML;
1038
 
                
1039
 
                // click function
1040
 
                function doClick(e) { 
1041
 
                        
1042
 
                        // ipad/iPhone --> follow the link if plugin not installed
1043
 
                        var hasiPadSupport = self.hasiPadSupport && self.hasiPadSupport();
1044
 
                        if (/iPad|iPhone|iPod/i.test(navigator.userAgent) && !/.flv$/i.test(playlist[0].url) && ! hasiPadSupport ) {
1045
 
                                return true;    
1046
 
                        }
1047
 
                        
1048
 
                        if (!self.isLoaded() && self._fireEvent("onBeforeClick") !== false) {
1049
 
                                self.load();            
1050
 
                        } 
1051
 
                        return stopEvent(e);                                    
1052
 
                }
1053
 
                
1054
 
                function installPlayer() {
1055
 
                        // defer loading upon click
1056
 
                        if (html.replace(/\s/g, '') !== '') {    
1057
 
 
1058
 
                                if (wrapper.addEventListener) {
1059
 
                                        wrapper.addEventListener("click", doClick, false);      
1060
 
 
1061
 
                                } else if (wrapper.attachEvent) {
1062
 
                                        wrapper.attachEvent("onclick", doClick);        
1063
 
                                }
1064
 
 
1065
 
                        // player is loaded upon page load 
1066
 
                        } else {
1067
 
 
1068
 
                                // prevent default action from wrapper. (fixes safari problems)
1069
 
                                if (wrapper.addEventListener) {
1070
 
                                        wrapper.addEventListener("click", stopEvent, false);    
1071
 
                                }
1072
 
                                // load player
1073
 
                                self.load();
1074
 
                        }
1075
 
                }
1076
 
                
1077
 
                // now that the player is initialized, wait for the plugin chain to finish
1078
 
                // before actually changing the dom
1079
 
                setTimeout(installPlayer, 0);
1080
 
        }
1081
 
 
1082
 
        // possibly defer initialization until DOM get's loaded
1083
 
        if (typeof wrapper == 'string') { 
1084
 
                var node = el(wrapper);                 
1085
 
                if (!node) { throw "Flowplayer cannot access element: " + wrapper; }
1086
 
                wrapper = node; 
1087
 
                init();
1088
 
                
1089
 
        // we have a DOM element so page is already loaded
1090
 
        } else {                
1091
 
                init();
1092
 
        }
1093
 
        
1094
 
        
1095
 
//}}}
1096
 
 
1097
 
 
1098
 
}
1099
 
 
1100
 
 
1101
 
// {{{ flowplayer() & statics 
1102
 
 
1103
 
// container for player instances
1104
 
var players = [];
1105
 
 
1106
 
 
1107
 
// this object is returned when multiple player's are requested 
1108
 
function Iterator(arr) {
1109
 
        
1110
 
        this.length = arr.length;
1111
 
        
1112
 
        this.each = function(fn)  {
1113
 
                each(arr, fn);  
1114
 
        };
1115
 
        
1116
 
        this.size = function() {
1117
 
                return arr.length;      
1118
 
        };      
1119
 
}
1120
 
 
1121
 
// these two variables are the only global variables
1122
 
window.flowplayer = window.$f = function() {
1123
 
        var instance = null;
1124
 
        var arg = arguments[0]; 
1125
 
        
1126
 
        // $f()
1127
 
        if (!arguments.length) {
1128
 
                each(players, function() {
1129
 
                        if (this.isLoaded())  {
1130
 
                                instance = this;        
1131
 
                                return false;
1132
 
                        }
1133
 
                });
1134
 
                
1135
 
                return instance || players[0];
1136
 
        } 
1137
 
        
1138
 
        if (arguments.length == 1) {
1139
 
                
1140
 
                // $f(index);
1141
 
                if (typeof arg == 'number') { 
1142
 
                        return players[arg];    
1143
 
        
1144
 
                        
1145
 
                // $f(wrapper || 'containerId' || '*');
1146
 
                } else {
1147
 
                        
1148
 
                        // $f("*");
1149
 
                        if (arg == '*') {
1150
 
                                return new Iterator(players);   
1151
 
                        }
1152
 
                        
1153
 
                        // $f(wrapper || 'containerId');
1154
 
                        each(players, function() {
1155
 
                                if (this.id() == arg.id || this.id() == arg || this.getParent() == arg)  {
1156
 
                                        instance = this;        
1157
 
                                        return false;
1158
 
                                }
1159
 
                        });
1160
 
                        
1161
 
                        return instance;                                        
1162
 
                }
1163
 
        }                       
1164
 
 
1165
 
        // instance builder 
1166
 
        if (arguments.length > 1) {             
1167
 
 
1168
 
                // flashembed parameters
1169
 
                var params = arguments[1],
1170
 
                         conf = (arguments.length == 3) ? arguments[2] : {};
1171
 
                                        
1172
 
                
1173
 
                if (typeof params == 'string') {
1174
 
                        params = {src: params}; 
1175
 
                } 
1176
 
                
1177
 
                params = extend({
1178
 
                        bgcolor: "#000000",
1179
 
                        version: [9, 0],
1180
 
                        expressInstall: "http://static.flowplayer.org/swf/expressinstall.swf",
1181
 
                        cachebusting: true
1182
 
                        
1183
 
                }, params);             
1184
 
                
1185
 
                if (typeof arg == 'string') {
1186
 
                        
1187
 
                        // select arg by classname
1188
 
                        if (arg.indexOf(".") != -1) {
1189
 
                                var instances = [];
1190
 
                                
1191
 
                                each(select(arg), function() { 
1192
 
                                        instances.push(new Player(this, clone(params), clone(conf)));           
1193
 
                                });     
1194
 
                                
1195
 
                                return new Iterator(instances);
1196
 
                                
1197
 
                        // select node by id
1198
 
                        } else {                
1199
 
                                var node = el(arg);
1200
 
                                return new Player(node !== null ? node : arg, params, conf);    
1201
 
                        } 
1202
 
                        
1203
 
                        
1204
 
                // arg is a DOM element
1205
 
                } else if (arg) {
1206
 
                        return new Player(arg, params, conf);                                           
1207
 
                }
1208
 
                
1209
 
        } 
1210
 
        
1211
 
        return null; 
1212
 
};
1213
 
        
1214
 
extend(window.$f, {
1215
 
 
1216
 
        // called by Flash External Interface           
1217
 
        fireEvent: function() {
1218
 
                var a = [].slice.call(arguments);
1219
 
                var p = $f(a[0]);               
1220
 
                return p ? p._fireEvent(a.slice(1)) : null;
1221
 
        },
1222
 
        
1223
 
        
1224
 
        // create plugins by modifying Player's prototype
1225
 
        addPlugin: function(name, fn) {
1226
 
                Player.prototype[name] = fn;
1227
 
                return $f;
1228
 
        },
1229
 
        
1230
 
        // utility methods for plugin developers
1231
 
        each: each,
1232
 
        
1233
 
        extend: extend
1234
 
});
1235
 
 
1236
 
        
1237
 
//}}}
1238
 
 
1239
 
 
1240
 
//{{{ jQuery support
1241
 
 
1242
 
if (typeof jQuery == 'function') {
1243
 
        
1244
 
        jQuery.fn.flowplayer = function(params, conf) {  
1245
 
                
1246
 
                // select instances
1247
 
                if (!arguments.length || typeof arguments[0] == 'number') {
1248
 
                        var arr = [];
1249
 
                        this.each(function()  {
1250
 
                                var p = $f(this);
1251
 
                                if (p) {
1252
 
                                        arr.push(p);    
1253
 
                                }
1254
 
                        });
1255
 
                        return arguments.length ? arr[arguments[0]] : new Iterator(arr);
1256
 
                }
1257
 
                
1258
 
                // create flowplayer instances
1259
 
                return this.each(function() { 
1260
 
                        $f(this, clone(params), conf ? clone(conf) : {});       
1261
 
                }); 
1262
 
                
1263
 
        };
1264
 
        
1265
 
}
1266
 
 
1267
 
//}}}
1268
 
 
1269
 
 
1270
 
})();
1271
 
/**
1272
 
 * @license 
1273
 
 * jQuery Tools 3.2.4 / Flashembed - New wave Flash embedding
1274
 
 * 
1275
 
 * NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
1276
 
 * 
1277
 
 * http://flowplayer.org/tools/toolbox/flashembed.html
1278
 
 *
1279
 
 * Since : March 2008
1280
 
 * Date  : @DATE 
1281
 
 */ 
1282
 
(function() {
1283
 
                
1284
 
        var IE = document.all,
1285
 
                 URL = 'http://www.adobe.com/go/getflashplayer',
1286
 
                 JQUERY = typeof jQuery == 'function', 
1287
 
                 RE = /(\d+)[^\d]+(\d+)[^\d]*(\d*)/,
1288
 
                 GLOBAL_OPTS = { 
1289
 
                        // very common opts
1290
 
                        width: '100%',
1291
 
                        height: '100%',         
1292
 
                        id: "_" + ("" + Math.random()).slice(9),
1293
 
                        
1294
 
                        // flashembed defaults
1295
 
                        allowfullscreen: true,
1296
 
                        allowscriptaccess: 'always',
1297
 
                        quality: 'high',        
1298
 
                        
1299
 
                        // flashembed specific options
1300
 
                        version: [3, 0],
1301
 
                        onFail: null,
1302
 
                        expressInstall: null, 
1303
 
                        w3c: false,
1304
 
                        cachebusting: false                              
1305
 
        };
1306
 
        
1307
 
        // version 9 bugfix: (http://blog.deconcept.com/2006/07/28/swfobject-143-released/)
1308
 
        if (window.attachEvent) {
1309
 
                window.attachEvent("onbeforeunload", function() {
1310
 
                        __flash_unloadHandler = function() {};
1311
 
                        __flash_savedUnloadHandler = function() {};
1312
 
                });
1313
 
        }
1314
 
        
1315
 
        // simple extend
1316
 
        function extend(to, from) {
1317
 
                if (from) {
1318
 
                        for (var key in from) {
1319
 
                                if (from.hasOwnProperty(key)) {
1320
 
                                        to[key] = from[key];
1321
 
                                }
1322
 
                        }
1323
 
                } 
1324
 
                return to;
1325
 
        }       
1326
 
 
1327
 
        // used by asString method      
1328
 
        function map(arr, func) {
1329
 
                var newArr = []; 
1330
 
                for (var i in arr) {
1331
 
                        if (arr.hasOwnProperty(i)) {
1332
 
                                newArr[i] = func(arr[i]);
1333
 
                        }
1334
 
                }
1335
 
                return newArr;
1336
 
        }
1337
 
 
1338
 
        window.flashembed = function(root, opts, conf) {
1339
 
        
1340
 
                // root must be found / loaded  
1341
 
                if (typeof root == 'string') {
1342
 
                        root = document.getElementById(root.replace("#", ""));
1343
 
                }
1344
 
                
1345
 
                // not found
1346
 
                if (!root) { return; }
1347
 
                
1348
 
                if (typeof opts == 'string') {
1349
 
                        opts = {src: opts};     
1350
 
                }
1351
 
 
1352
 
                return new Flash(root, extend(extend({}, GLOBAL_OPTS), opts), conf); 
1353
 
        };      
1354
 
        
1355
 
        // flashembed "static" API
1356
 
        var f = extend(window.flashembed, {
1357
 
                
1358
 
                conf: GLOBAL_OPTS,
1359
 
        
1360
 
                getVersion: function()  {
1361
 
                        var fo, ver;
1362
 
                        
1363
 
                        try {
1364
 
                                ver = navigator.plugins["Shockwave Flash"].description.slice(16); 
1365
 
                        } catch(e) {
1366
 
                                
1367
 
                                try  {
1368
 
                                        fo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
1369
 
                                        ver = fo && fo.GetVariable("$version");
1370
 
                                        
1371
 
                                } catch(err) {
1372
 
                try  {
1373
 
                    fo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
1374
 
                    ver = fo && fo.GetVariable("$version");  
1375
 
                } catch(err2) { }                                               
1376
 
                                } 
1377
 
                        }
1378
 
                        
1379
 
                        ver = RE.exec(ver);
1380
 
                        return ver ? [ver[1], ver[3]] : [0, 0];
1381
 
                },
1382
 
                
1383
 
                asString: function(obj) { 
1384
 
 
1385
 
                        if (obj === null || obj === undefined) { return null; }
1386
 
                        var type = typeof obj;
1387
 
                        if (type == 'object' && obj.push) { type = 'array'; }
1388
 
                        
1389
 
                        switch (type){  
1390
 
                                
1391
 
                                case 'string':
1392
 
                                        obj = obj.replace(new RegExp('(["\\\\])', 'g'), '\\$1');
1393
 
                                        
1394
 
                                        // flash does not handle %- characters well. transforms "50%" to "50pct" (a dirty hack, I admit)
1395
 
                                        obj = obj.replace(/^\s?(\d+\.?\d+)%/, "$1pct");
1396
 
                                        return '"' +obj+ '"';
1397
 
                                        
1398
 
                                case 'array':
1399
 
                                        return '['+ map(obj, function(el) {
1400
 
                                                return f.asString(el);
1401
 
                                        }).join(',') +']'; 
1402
 
                                        
1403
 
                                case 'function':
1404
 
                                        return '"function()"';
1405
 
                                        
1406
 
                                case 'object':
1407
 
                                        var str = [];
1408
 
                                        for (var prop in obj) {
1409
 
                                                if (obj.hasOwnProperty(prop)) {
1410
 
                                                        str.push('"'+prop+'":'+ f.asString(obj[prop]));
1411
 
                                                }
1412
 
                                        }
1413
 
                                        return '{'+str.join(',')+'}';
1414
 
                        }
1415
 
                        
1416
 
                        // replace ' --> "  and remove spaces
1417
 
                        return String(obj).replace(/\s/g, " ").replace(/\'/g, "\"");
1418
 
                },
1419
 
                
1420
 
                getHTML: function(opts, conf) {
1421
 
 
1422
 
                        opts = extend({}, opts);
1423
 
                        
1424
 
                        /******* OBJECT tag and it's attributes *******/
1425
 
                        var html = '<object width="' + opts.width + 
1426
 
                                '" height="' + opts.height + 
1427
 
                                '" id="' + opts.id + 
1428
 
                                '" name="' + opts.id + '"';
1429
 
                        
1430
 
                        if (opts.cachebusting) {
1431
 
                                opts.src += ((opts.src.indexOf("?") != -1 ? "&" : "?") + Math.random());                
1432
 
                        }                       
1433
 
                        
1434
 
                        if (opts.w3c || !IE) {
1435
 
                                html += ' data="' +opts.src+ '" type="application/x-shockwave-flash"';          
1436
 
                        } else {
1437
 
                                html += ' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';        
1438
 
                        }
1439
 
                        
1440
 
                        html += '>'; 
1441
 
                        
1442
 
                        /******* nested PARAM tags *******/
1443
 
                        if (opts.w3c || IE) {
1444
 
                                html += '<param name="movie" value="' +opts.src+ '" />';        
1445
 
                        } 
1446
 
                        
1447
 
                        // not allowed params
1448
 
                        opts.width = opts.height = opts.id = opts.w3c = opts.src = null;
1449
 
                        opts.onFail = opts.version = opts.expressInstall = null;
1450
 
                        
1451
 
                        for (var key in opts) {
1452
 
                                if (opts[key]) {
1453
 
                                        html += '<param name="'+ key +'" value="'+ opts[key] +'" />';
1454
 
                                }
1455
 
                        }       
1456
 
                
1457
 
                        /******* FLASHVARS *******/
1458
 
                        var vars = "";
1459
 
                        
1460
 
                        if (conf) {
1461
 
                                for (var k in conf) { 
1462
 
                                        if (conf[k]) {
1463
 
                                                var val = conf[k]; 
1464
 
                                                vars += k +'='+ (/function|object/.test(typeof val) ? f.asString(val) : val) + '&';
1465
 
                                        }
1466
 
                                }
1467
 
                                vars = vars.slice(0, -1);
1468
 
                                html += '<param name="flashvars" value=\'' + vars + '\' />';
1469
 
                        }
1470
 
                        
1471
 
                        html += "</object>";    
1472
 
                        
1473
 
                        return html;                            
1474
 
                },
1475
 
                
1476
 
                isSupported: function(ver) {
1477
 
                        return VERSION[0] > ver[0] || VERSION[0] == ver[0] && VERSION[1] >= ver[1];                     
1478
 
                }               
1479
 
                
1480
 
        });
1481
 
        
1482
 
        var VERSION = f.getVersion(); 
1483
 
        
1484
 
        function Flash(root, opts, conf) {  
1485
 
                                                        
1486
 
                // version is ok
1487
 
                if (f.isSupported(opts.version)) {
1488
 
                        root.innerHTML = f.getHTML(opts, conf);
1489
 
                        
1490
 
                // express install
1491
 
                } else if (opts.expressInstall && f.isSupported([6, 65])) {
1492
 
                        root.innerHTML = f.getHTML(extend(opts, {src: opts.expressInstall}), {
1493
 
                                MMredirectURL: location.href,
1494
 
                                MMplayerType: 'PlugIn',
1495
 
                                MMdoctitle: document.title
1496
 
                        });     
1497
 
                        
1498
 
                } else {
1499
 
                        
1500
 
                        // fail #2.1 custom content inside container
1501
 
                        if (!root.innerHTML.replace(/\s/g, '')) {
1502
 
                                root.innerHTML = 
1503
 
                                        "<h2>Flash version " + opts.version + " or greater is required</h2>" + 
1504
 
                                        "<h3>" + 
1505
 
                                                (VERSION[0] > 0 ? "Your version is " + VERSION : "You have no flash plugin installed") +
1506
 
                                        "</h3>" + 
1507
 
                                        
1508
 
                                        (root.tagName == 'A' ? "<p>Click here to download latest version</p>" : 
1509
 
                                                "<p>Download latest version from <a href='" + URL + "'>here</a></p>");
1510
 
                                        
1511
 
                                if (root.tagName == 'A') {      
1512
 
                                        root.onclick = function() {
1513
 
                                                location.href = URL;
1514
 
                                        };
1515
 
                                }                               
1516
 
                        }
1517
 
                        
1518
 
                        // onFail
1519
 
                        if (opts.onFail) {
1520
 
                                var ret = opts.onFail.call(this);
1521
 
                                if (typeof ret == 'string') { root.innerHTML = ret; }   
1522
 
                        }                       
1523
 
                }
1524
 
                
1525
 
                // http://flowplayer.org/forum/8/18186#post-18593
1526
 
                if (IE) {
1527
 
                        window[opts.id] = document.getElementById(opts.id);
1528
 
                } 
1529
 
                
1530
 
                // API methods for callback
1531
 
                extend(this, {
1532
 
                                
1533
 
                        getRoot: function() {
1534
 
                                return root;    
1535
 
                        },
1536
 
                        
1537
 
                        getOptions: function() {
1538
 
                                return opts;    
1539
 
                        },
1540
 
 
1541
 
                        
1542
 
                        getConf: function() {
1543
 
                                return conf;    
1544
 
                        }, 
1545
 
                        
1546
 
                        getApi: function() {
1547
 
                                return root.firstChild; 
1548
 
                        }
1549
 
                        
1550
 
                }); 
1551
 
        }
1552
 
        
1553
 
        // setup jquery support
1554
 
        if (JQUERY) {
1555
 
                
1556
 
                // tools version number
1557
 
                jQuery.tools = jQuery.tools || {version: '3.2.4'};
1558
 
                
1559
 
                jQuery.tools.flashembed = {  
1560
 
                        conf: GLOBAL_OPTS
1561
 
                };      
1562
 
                
1563
 
                jQuery.fn.flashembed = function(opts, conf) {           
1564
 
                        return this.each(function() { 
1565
 
                                $(this).data("flashembed", flashembed(this, opts, conf));
1566
 
                        });
1567
 
                }; 
1568
 
        } 
1569
 
        
1570
 
})();
1571