|
1 /* |
|
2 * |
|
3 * Copyright 2010 Institut de recherche et d'innovation |
|
4 * contributor(s) : Samuel Huron |
|
5 * |
|
6 * contact@iri.centrepompidou.fr |
|
7 * http://www.iri.centrepompidou.fr |
|
8 * |
|
9 * This software is a computer program whose purpose is to show and add annotations on a video . |
|
10 * This software is governed by the CeCILL-C license under French law and |
|
11 * abiding by the rules of distribution of free software. You can use, |
|
12 * modify and/ or redistribute the software under the terms of the CeCILL-C |
|
13 * license as circulated by CEA, CNRS and INRIA at the following URL |
|
14 * "http://www.cecill.info". |
|
15 * |
|
16 * The fact that you are presently reading this means that you have had |
|
17 * knowledge of the CeCILL-C license and that you accept its terms. |
|
18 */ |
|
19 (function(global, document) { |
|
20 |
|
21 // Popcorn.js does not support archaic browsers |
|
22 if ( !document.addEventListener ) { |
|
23 global.Popcorn = { |
|
24 isSupported: false |
|
25 }; |
|
26 |
|
27 var methods = ( "forEach extend effects error guid sizeOf isArray nop position disable enable destroy " + |
|
28 "addTrackEvent removeTrackEvent getTrackEvents getTrackEvent getLastTrackEventId " + |
|
29 "timeUpdate plugin removePlugin compose effect parser xhr getJSONP getScript" ).split(/\s+/); |
|
30 |
|
31 while ( methods.length ) { |
|
32 global.Popcorn[ methods.shift() ] = function() {}; |
|
33 } |
|
34 return; |
|
35 } |
|
36 |
|
37 var |
|
38 |
|
39 AP = Array.prototype, |
|
40 OP = Object.prototype, |
|
41 |
|
42 forEach = AP.forEach, |
|
43 slice = AP.slice, |
|
44 hasOwn = OP.hasOwnProperty, |
|
45 toString = OP.toString, |
|
46 |
|
47 // Copy global Popcorn (may not exist) |
|
48 _Popcorn = global.Popcorn, |
|
49 |
|
50 // ID string matching |
|
51 rIdExp = /^(#([\w\-\_\.]+))$/, |
|
52 |
|
53 // Ready fn cache |
|
54 readyStack = [], |
|
55 readyBound = false, |
|
56 readyFired = false, |
|
57 |
|
58 // Non-public internal data object |
|
59 internal = { |
|
60 events: { |
|
61 hash: {}, |
|
62 apis: {} |
|
63 } |
|
64 }, |
|
65 |
|
66 // Non-public `requestAnimFrame` |
|
67 // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ |
|
68 requestAnimFrame = (function(){ |
|
69 return global.requestAnimationFrame || |
|
70 global.webkitRequestAnimationFrame || |
|
71 global.mozRequestAnimationFrame || |
|
72 global.oRequestAnimationFrame || |
|
73 global.msRequestAnimationFrame || |
|
74 function( callback, element ) { |
|
75 global.setTimeout( callback, 16 ); |
|
76 }; |
|
77 }()), |
|
78 |
|
79 refresh = function( obj ) { |
|
80 var currentTime = obj.media.currentTime, |
|
81 animation = obj.options.frameAnimation, |
|
82 disabled = obj.data.disabled, |
|
83 tracks = obj.data.trackEvents, |
|
84 animating = tracks.animating, |
|
85 start = tracks.startIndex, |
|
86 registryByName = Popcorn.registryByName, |
|
87 animIndex = 0, |
|
88 byStart, natives, type; |
|
89 |
|
90 start = Math.min( start + 1, tracks.byStart.length - 2 ); |
|
91 |
|
92 while ( start > 0 && tracks.byStart[ start ] ) { |
|
93 |
|
94 byStart = tracks.byStart[ start ]; |
|
95 natives = byStart._natives; |
|
96 type = natives && natives.type; |
|
97 |
|
98 if ( !natives || |
|
99 ( !!registryByName[ type ] || !!obj[ type ] ) ) { |
|
100 |
|
101 if ( ( byStart.start <= currentTime && byStart.end > currentTime ) && |
|
102 disabled.indexOf( type ) === -1 ) { |
|
103 |
|
104 if ( !byStart._running ) { |
|
105 byStart._running = true; |
|
106 natives.start.call( obj, null, byStart ); |
|
107 |
|
108 // if the 'frameAnimation' option is used, |
|
109 // push the current byStart object into the `animating` cue |
|
110 if ( animation && |
|
111 ( byStart && byStart._running && byStart.natives.frame ) ) { |
|
112 |
|
113 natives.frame.call( obj, null, byStart, currentTime ); |
|
114 } |
|
115 } |
|
116 } else if ( byStart._running === true ) { |
|
117 |
|
118 byStart._running = false; |
|
119 natives.end.call( obj, null, byStart ); |
|
120 |
|
121 if ( animation && byStart._natives.frame ) { |
|
122 animIndex = animating.indexOf( byStart ); |
|
123 if ( animIndex >= 0 ) { |
|
124 animating.splice( animIndex, 1 ); |
|
125 } |
|
126 } |
|
127 } |
|
128 } |
|
129 |
|
130 start--; |
|
131 } |
|
132 }, |
|
133 |
|
134 // Declare constructor |
|
135 // Returns an instance object. |
|
136 Popcorn = function( entity, options ) { |
|
137 // Return new Popcorn object |
|
138 return new Popcorn.p.init( entity, options || null ); |
|
139 }; |
|
140 |
|
141 // Popcorn API version, automatically inserted via build system. |
|
142 Popcorn.version = "@VERSION"; |
|
143 |
|
144 // Boolean flag allowing a client to determine if Popcorn can be supported |
|
145 Popcorn.isSupported = true; |
|
146 |
|
147 // Instance caching |
|
148 Popcorn.instances = []; |
|
149 |
|
150 // Declare a shortcut (Popcorn.p) to and a definition of |
|
151 // the new prototype for our Popcorn constructor |
|
152 Popcorn.p = Popcorn.prototype = { |
|
153 |
|
154 init: function( entity, options ) { |
|
155 |
|
156 var matches; |
|
157 |
|
158 // Supports Popcorn(function () { /../ }) |
|
159 // Originally proposed by Daniel Brooks |
|
160 |
|
161 if ( typeof entity === "function" ) { |
|
162 |
|
163 // If document ready has already fired |
|
164 if ( document.readyState === "interactive" || document.readyState === "complete" ) { |
|
165 |
|
166 entity( document, Popcorn ); |
|
167 |
|
168 return; |
|
169 } |
|
170 // Add `entity` fn to ready stack |
|
171 readyStack.push( entity ); |
|
172 |
|
173 // This process should happen once per page load |
|
174 if ( !readyBound ) { |
|
175 |
|
176 // set readyBound flag |
|
177 readyBound = true; |
|
178 |
|
179 var DOMContentLoaded = function() { |
|
180 |
|
181 readyFired = true; |
|
182 |
|
183 // Remove global DOM ready listener |
|
184 document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); |
|
185 |
|
186 // Execute all ready function in the stack |
|
187 for ( var i = 0, readyStackLength = readyStack.length; i < readyStackLength; i++ ) { |
|
188 |
|
189 readyStack[ i ].call( document, Popcorn ); |
|
190 |
|
191 } |
|
192 // GC readyStack |
|
193 readyStack = null; |
|
194 }; |
|
195 |
|
196 // Register global DOM ready listener |
|
197 document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); |
|
198 } |
|
199 |
|
200 return; |
|
201 } |
|
202 |
|
203 // Check if entity is a valid string id |
|
204 matches = rIdExp.exec( entity ); |
|
205 |
|
206 // Get media element by id or object reference |
|
207 this.media = matches && matches.length && matches[ 2 ] ? |
|
208 document.getElementById( matches[ 2 ] ) : |
|
209 entity; |
|
210 |
|
211 // Create an audio or video element property reference |
|
212 this[ ( this.media.nodeName && this.media.nodeName.toLowerCase() ) || "video" ] = this.media; |
|
213 |
|
214 // Register new instance |
|
215 Popcorn.instances.push( this ); |
|
216 |
|
217 this.options = options || {}; |
|
218 |
|
219 this.isDestroyed = false; |
|
220 |
|
221 this.data = { |
|
222 |
|
223 // Executed by either timeupdate event or in rAF loop |
|
224 timeUpdate: Popcorn.nop, |
|
225 |
|
226 // Allows disabling a plugin per instance |
|
227 disabled: [], |
|
228 |
|
229 // Stores DOM event queues by type |
|
230 events: {}, |
|
231 |
|
232 // Stores Special event hooks data |
|
233 hooks: {}, |
|
234 |
|
235 // Store track event history data |
|
236 history: [], |
|
237 |
|
238 // Stores ad-hoc state related data] |
|
239 state: { |
|
240 volume: this.media.volume |
|
241 }, |
|
242 |
|
243 // Store track event object references by trackId |
|
244 trackRefs: {}, |
|
245 |
|
246 // Playback track event queues |
|
247 trackEvents: { |
|
248 byStart: [{ |
|
249 |
|
250 start: -1, |
|
251 end: -1 |
|
252 }], |
|
253 byEnd: [{ |
|
254 start: -1, |
|
255 end: -1 |
|
256 }], |
|
257 animating: [], |
|
258 startIndex: 0, |
|
259 endIndex: 0, |
|
260 previousUpdateTime: -1 |
|
261 } |
|
262 }; |
|
263 |
|
264 // Wrap true ready check |
|
265 var isReady = function( that ) { |
|
266 |
|
267 var duration, videoDurationPlus; |
|
268 |
|
269 if ( that.media.readyState >= 2 ) { |
|
270 // Adding padding to the front and end of the arrays |
|
271 // this is so we do not fall off either end |
|
272 |
|
273 duration = that.media.duration; |
|
274 // Check for no duration info (NaN) |
|
275 videoDurationPlus = duration != duration ? Number.MAX_VALUE : duration + 1; |
|
276 |
|
277 Popcorn.addTrackEvent( that, { |
|
278 start: videoDurationPlus, |
|
279 end: videoDurationPlus |
|
280 }); |
|
281 |
|
282 if ( that.options.frameAnimation ) { |
|
283 // if Popcorn is created with frameAnimation option set to true, |
|
284 // requestAnimFrame is used instead of "timeupdate" media event. |
|
285 // This is for greater frame time accuracy, theoretically up to |
|
286 // 60 frames per second as opposed to ~4 ( ~every 15-250ms) |
|
287 that.data.timeUpdate = function () { |
|
288 |
|
289 Popcorn.timeUpdate( that, {} ); |
|
290 |
|
291 that.trigger( "timeupdate" ); |
|
292 |
|
293 !that.isDestroyed && requestAnimFrame( that.data.timeUpdate ); |
|
294 }; |
|
295 |
|
296 !that.isDestroyed && requestAnimFrame( that.data.timeUpdate ); |
|
297 |
|
298 } else { |
|
299 |
|
300 that.data.timeUpdate = function( event ) { |
|
301 Popcorn.timeUpdate( that, event ); |
|
302 }; |
|
303 |
|
304 if ( !that.isDestroyed ) { |
|
305 that.media.addEventListener( "timeupdate", that.data.timeUpdate, false ); |
|
306 } |
|
307 } |
|
308 } else { |
|
309 global.setTimeout(function() { |
|
310 isReady( that ); |
|
311 }, 1 ); |
|
312 } |
|
313 }; |
|
314 |
|
315 isReady( this ); |
|
316 |
|
317 return this; |
|
318 } |
|
319 }; |
|
320 |
|
321 // Extend constructor prototype to instance prototype |
|
322 // Allows chaining methods to instances |
|
323 Popcorn.p.init.prototype = Popcorn.p; |
|
324 |
|
325 Popcorn.forEach = function( obj, fn, context ) { |
|
326 |
|
327 if ( !obj || !fn ) { |
|
328 return {}; |
|
329 } |
|
330 |
|
331 context = context || this; |
|
332 |
|
333 var key, len; |
|
334 |
|
335 // Use native whenever possible |
|
336 if ( forEach && obj.forEach === forEach ) { |
|
337 return obj.forEach( fn, context ); |
|
338 } |
|
339 |
|
340 if ( toString.call( obj ) === "[object NodeList]" ) { |
|
341 for ( key = 0, len = obj.length; key < len; key++ ) { |
|
342 fn.call( context, obj[ key ], key, obj ); |
|
343 } |
|
344 return obj; |
|
345 } |
|
346 |
|
347 for ( key in obj ) { |
|
348 if ( hasOwn.call( obj, key ) ) { |
|
349 fn.call( context, obj[ key ], key, obj ); |
|
350 } |
|
351 } |
|
352 return obj; |
|
353 }; |
|
354 |
|
355 Popcorn.extend = function( obj ) { |
|
356 var dest = obj, src = slice.call( arguments, 1 ); |
|
357 |
|
358 Popcorn.forEach( src, function( copy ) { |
|
359 for ( var prop in copy ) { |
|
360 dest[ prop ] = copy[ prop ]; |
|
361 } |
|
362 }); |
|
363 |
|
364 return dest; |
|
365 }; |
|
366 |
|
367 |
|
368 // A Few reusable utils, memoized onto Popcorn |
|
369 Popcorn.extend( Popcorn, { |
|
370 noConflict: function( deep ) { |
|
371 |
|
372 if ( deep ) { |
|
373 global.Popcorn = _Popcorn; |
|
374 } |
|
375 |
|
376 return Popcorn; |
|
377 }, |
|
378 error: function( msg ) { |
|
379 throw new Error( msg ); |
|
380 }, |
|
381 guid: function( prefix ) { |
|
382 Popcorn.guid.counter++; |
|
383 return ( prefix ? prefix : "" ) + ( +new Date() + Popcorn.guid.counter ); |
|
384 }, |
|
385 sizeOf: function( obj ) { |
|
386 var size = 0; |
|
387 |
|
388 for ( var prop in obj ) { |
|
389 size++; |
|
390 } |
|
391 |
|
392 return size; |
|
393 }, |
|
394 isArray: Array.isArray || function( array ) { |
|
395 return toString.call( array ) === "[object Array]"; |
|
396 }, |
|
397 |
|
398 nop: function() {}, |
|
399 |
|
400 position: function( elem ) { |
|
401 |
|
402 var clientRect = elem.getBoundingClientRect(), |
|
403 bounds = {}, |
|
404 doc = elem.ownerDocument, |
|
405 docElem = document.documentElement, |
|
406 body = document.body, |
|
407 clientTop, clientLeft, scrollTop, scrollLeft, top, left; |
|
408 |
|
409 // Determine correct clientTop/Left |
|
410 clientTop = docElem.clientTop || body.clientTop || 0; |
|
411 clientLeft = docElem.clientLeft || body.clientLeft || 0; |
|
412 |
|
413 // Determine correct scrollTop/Left |
|
414 scrollTop = ( global.pageYOffset && docElem.scrollTop || body.scrollTop ); |
|
415 scrollLeft = ( global.pageXOffset && docElem.scrollLeft || body.scrollLeft ); |
|
416 |
|
417 // Temp top/left |
|
418 top = Math.ceil( clientRect.top + scrollTop - clientTop ); |
|
419 left = Math.ceil( clientRect.left + scrollLeft - clientLeft ); |
|
420 |
|
421 for ( var p in clientRect ) { |
|
422 bounds[ p ] = Math.round( clientRect[ p ] ); |
|
423 } |
|
424 |
|
425 return Popcorn.extend({}, bounds, { top: top, left: left }); |
|
426 }, |
|
427 |
|
428 disable: function( instance, plugin ) { |
|
429 |
|
430 var disabled = instance.data.disabled; |
|
431 |
|
432 if ( disabled.indexOf( plugin ) === -1 ) { |
|
433 disabled.push( plugin ); |
|
434 } |
|
435 |
|
436 refresh( instance ); |
|
437 |
|
438 return instance; |
|
439 }, |
|
440 enable: function( instance, plugin ) { |
|
441 |
|
442 var disabled = instance.data.disabled, |
|
443 index = disabled.indexOf( plugin ); |
|
444 |
|
445 if ( index > -1 ) { |
|
446 disabled.splice( index, 1 ); |
|
447 } |
|
448 |
|
449 refresh( instance ); |
|
450 |
|
451 return instance; |
|
452 }, |
|
453 destroy: function( instance ) { |
|
454 var events = instance.data.events, |
|
455 singleEvent, item, fn; |
|
456 |
|
457 // Iterate through all events and remove them |
|
458 for ( item in events ) { |
|
459 singleEvent = events[ item ]; |
|
460 for ( fn in singleEvent ) { |
|
461 delete singleEvent[ fn ]; |
|
462 } |
|
463 events[ item ] = null; |
|
464 } |
|
465 |
|
466 if ( !instance.isDestroyed ) { |
|
467 instance.data.timeUpdate && instance.media.removeEventListener( "timeupdate", instance.data.timeUpdate, false ); |
|
468 instance.isDestroyed = true; |
|
469 } |
|
470 } |
|
471 }); |
|
472 |
|
473 // Memoized GUID Counter |
|
474 Popcorn.guid.counter = 1; |
|
475 |
|
476 // Factory to implement getters, setters and controllers |
|
477 // as Popcorn instance methods. The IIFE will create and return |
|
478 // an object with defined methods |
|
479 Popcorn.extend(Popcorn.p, (function() { |
|
480 |
|
481 var methods = "load play pause currentTime playbackRate volume duration preload playbackRate " + |
|
482 "autoplay loop controls muted buffered readyState seeking paused played seekable ended", |
|
483 ret = {}; |
|
484 |
|
485 |
|
486 // Build methods, store in object that is returned and passed to extend |
|
487 Popcorn.forEach( methods.split( /\s+/g ), function( name ) { |
|
488 |
|
489 ret[ name ] = function( arg ) { |
|
490 |
|
491 if ( typeof this.media[ name ] === "function" ) { |
|
492 |
|
493 // Support for shorthanded play(n)/pause(n) jump to currentTime |
|
494 // If arg is not null or undefined and called by one of the |
|
495 // allowed shorthandable methods, then set the currentTime |
|
496 // Supports time as seconds or SMPTE |
|
497 if ( arg != null && /play|pause/.test( name ) ) { |
|
498 this.media.currentTime = Popcorn.util.toSeconds( arg ); |
|
499 } |
|
500 |
|
501 this.media[ name ](); |
|
502 |
|
503 return this; |
|
504 } |
|
505 |
|
506 |
|
507 if ( arg != null ) { |
|
508 |
|
509 this.media[ name ] = arg; |
|
510 |
|
511 return this; |
|
512 } |
|
513 |
|
514 return this.media[ name ]; |
|
515 }; |
|
516 }); |
|
517 |
|
518 return ret; |
|
519 |
|
520 })() |
|
521 ); |
|
522 |
|
523 Popcorn.forEach( "enable disable".split(" "), function( method ) { |
|
524 Popcorn.p[ method ] = function( plugin ) { |
|
525 return Popcorn[ method ]( this, plugin ); |
|
526 }; |
|
527 }); |
|
528 |
|
529 Popcorn.extend(Popcorn.p, { |
|
530 |
|
531 // Rounded currentTime |
|
532 roundTime: function() { |
|
533 return -~this.media.currentTime; |
|
534 }, |
|
535 |
|
536 // Attach an event to a single point in time |
|
537 exec: function( time, fn ) { |
|
538 |
|
539 // Creating a one second track event with an empty end |
|
540 Popcorn.addTrackEvent( this, { |
|
541 start: time, |
|
542 end: time + 1, |
|
543 _running: false, |
|
544 _natives: { |
|
545 start: fn || Popcorn.nop, |
|
546 end: Popcorn.nop, |
|
547 type: "exec" |
|
548 } |
|
549 }); |
|
550 |
|
551 return this; |
|
552 }, |
|
553 |
|
554 // Mute the calling media, optionally toggle |
|
555 mute: function( toggle ) { |
|
556 |
|
557 var event = toggle == null || toggle === true ? "muted" : "unmuted"; |
|
558 |
|
559 // If `toggle` is explicitly `false`, |
|
560 // unmute the media and restore the volume level |
|
561 if ( event === "unmuted" ) { |
|
562 this.media.muted = false; |
|
563 this.media.volume = this.data.state.volume; |
|
564 } |
|
565 |
|
566 // If `toggle` is either null or undefined, |
|
567 // save the current volume and mute the media element |
|
568 if ( event === "muted" ) { |
|
569 this.data.state.volume = this.media.volume; |
|
570 this.media.muted = true; |
|
571 } |
|
572 |
|
573 // Trigger either muted|unmuted event |
|
574 this.trigger( event ); |
|
575 |
|
576 return this; |
|
577 }, |
|
578 |
|
579 // Convenience method, unmute the calling media |
|
580 unmute: function( toggle ) { |
|
581 |
|
582 return this.mute( toggle == null ? false : !toggle ); |
|
583 }, |
|
584 |
|
585 // Get the client bounding box of an instance element |
|
586 position: function() { |
|
587 return Popcorn.position( this.media ); |
|
588 }, |
|
589 |
|
590 // Toggle a plugin's playback behaviour (on or off) per instance |
|
591 toggle: function( plugin ) { |
|
592 return Popcorn[ this.data.disabled.indexOf( plugin ) > -1 ? "enable" : "disable" ]( this, plugin ); |
|
593 }, |
|
594 |
|
595 // Set default values for plugin options objects per instance |
|
596 defaults: function( plugin, defaults ) { |
|
597 |
|
598 // If an array of default configurations is provided, |
|
599 // iterate and apply each to this instance |
|
600 if ( Popcorn.isArray( plugin ) ) { |
|
601 |
|
602 Popcorn.forEach( plugin, function( obj ) { |
|
603 for ( var name in obj ) { |
|
604 this.defaults( name, obj[ name ] ); |
|
605 } |
|
606 }, this ); |
|
607 |
|
608 return this; |
|
609 } |
|
610 |
|
611 if ( !this.options.defaults ) { |
|
612 this.options.defaults = {}; |
|
613 } |
|
614 |
|
615 if ( !this.options.defaults[ plugin ] ) { |
|
616 this.options.defaults[ plugin ] = {}; |
|
617 } |
|
618 |
|
619 Popcorn.extend( this.options.defaults[ plugin ], defaults ); |
|
620 |
|
621 return this; |
|
622 } |
|
623 }); |
|
624 |
|
625 Popcorn.Events = { |
|
626 UIEvents: "blur focus focusin focusout load resize scroll unload", |
|
627 MouseEvents: "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave click dblclick", |
|
628 Events: "loadstart progress suspend emptied stalled play pause " + |
|
629 "loadedmetadata loadeddata waiting playing canplay canplaythrough " + |
|
630 "seeking seeked timeupdate ended ratechange durationchange volumechange" |
|
631 }; |
|
632 |
|
633 Popcorn.Events.Natives = Popcorn.Events.UIEvents + " " + |
|
634 Popcorn.Events.MouseEvents + " " + |
|
635 Popcorn.Events.Events; |
|
636 |
|
637 internal.events.apiTypes = [ "UIEvents", "MouseEvents", "Events" ]; |
|
638 |
|
639 // Privately compile events table at load time |
|
640 (function( events, data ) { |
|
641 |
|
642 var apis = internal.events.apiTypes, |
|
643 eventsList = events.Natives.split( /\s+/g ), |
|
644 idx = 0, len = eventsList.length, prop; |
|
645 |
|
646 for( ; idx < len; idx++ ) { |
|
647 data.hash[ eventsList[idx] ] = true; |
|
648 } |
|
649 |
|
650 apis.forEach(function( val, idx ) { |
|
651 |
|
652 data.apis[ val ] = {}; |
|
653 |
|
654 var apiEvents = events[ val ].split( /\s+/g ), |
|
655 len = apiEvents.length, |
|
656 k = 0; |
|
657 |
|
658 for ( ; k < len; k++ ) { |
|
659 data.apis[ val ][ apiEvents[ k ] ] = true; |
|
660 } |
|
661 }); |
|
662 })( Popcorn.Events, internal.events ); |
|
663 |
|
664 Popcorn.events = { |
|
665 |
|
666 isNative: function( type ) { |
|
667 return !!internal.events.hash[ type ]; |
|
668 }, |
|
669 getInterface: function( type ) { |
|
670 |
|
671 if ( !Popcorn.events.isNative( type ) ) { |
|
672 return false; |
|
673 } |
|
674 |
|
675 var eventApi = internal.events, |
|
676 apis = eventApi.apiTypes, |
|
677 apihash = eventApi.apis, |
|
678 idx = 0, len = apis.length, api, tmp; |
|
679 |
|
680 for ( ; idx < len; idx++ ) { |
|
681 tmp = apis[ idx ]; |
|
682 |
|
683 if ( apihash[ tmp ][ type ] ) { |
|
684 api = tmp; |
|
685 break; |
|
686 } |
|
687 } |
|
688 return api; |
|
689 }, |
|
690 // Compile all native events to single array |
|
691 all: Popcorn.Events.Natives.split( /\s+/g ), |
|
692 // Defines all Event handling static functions |
|
693 fn: { |
|
694 trigger: function( type, data ) { |
|
695 |
|
696 var eventInterface, evt; |
|
697 // setup checks for custom event system |
|
698 if ( this.data.events[ type ] && Popcorn.sizeOf( this.data.events[ type ] ) ) { |
|
699 |
|
700 eventInterface = Popcorn.events.getInterface( type ); |
|
701 |
|
702 if ( eventInterface ) { |
|
703 |
|
704 evt = document.createEvent( eventInterface ); |
|
705 evt.initEvent( type, true, true, global, 1 ); |
|
706 |
|
707 this.media.dispatchEvent( evt ); |
|
708 |
|
709 return this; |
|
710 } |
|
711 |
|
712 // Custom events |
|
713 Popcorn.forEach( this.data.events[ type ], function( obj, key ) { |
|
714 |
|
715 obj.call( this, data ); |
|
716 |
|
717 }, this ); |
|
718 |
|
719 } |
|
720 |
|
721 return this; |
|
722 }, |
|
723 listen: function( type, fn ) { |
|
724 |
|
725 var self = this, |
|
726 hasEvents = true, |
|
727 eventHook = Popcorn.events.hooks[ type ], |
|
728 origType = type, |
|
729 tmp; |
|
730 |
|
731 if ( !this.data.events[ type ] ) { |
|
732 this.data.events[ type ] = {}; |
|
733 hasEvents = false; |
|
734 } |
|
735 |
|
736 // Check and setup event hooks |
|
737 if ( eventHook ) { |
|
738 |
|
739 // Execute hook add method if defined |
|
740 if ( eventHook.add ) { |
|
741 eventHook.add.call( this, {}, fn ); |
|
742 } |
|
743 |
|
744 // Reassign event type to our piggyback event type if defined |
|
745 if ( eventHook.bind ) { |
|
746 type = eventHook.bind; |
|
747 } |
|
748 |
|
749 // Reassign handler if defined |
|
750 if ( eventHook.handler ) { |
|
751 tmp = fn; |
|
752 |
|
753 fn = function wrapper( event ) { |
|
754 eventHook.handler.call( self, event, tmp ); |
|
755 }; |
|
756 } |
|
757 |
|
758 // assume the piggy back event is registered |
|
759 hasEvents = true; |
|
760 |
|
761 // Setup event registry entry |
|
762 if ( !this.data.events[ type ] ) { |
|
763 this.data.events[ type ] = {}; |
|
764 // Toggle if the previous assumption was untrue |
|
765 hasEvents = false; |
|
766 } |
|
767 } |
|
768 |
|
769 // Register event and handler |
|
770 this.data.events[ type ][ fn.name || ( fn.toString() + Popcorn.guid() ) ] = fn; |
|
771 |
|
772 // only attach one event of any type |
|
773 if ( !hasEvents && Popcorn.events.all.indexOf( type ) > -1 ) { |
|
774 |
|
775 this.media.addEventListener( type, function( event ) { |
|
776 |
|
777 Popcorn.forEach( self.data.events[ type ], function( obj, key ) { |
|
778 if ( typeof obj === "function" ) { |
|
779 obj.call( self, event ); |
|
780 } |
|
781 }); |
|
782 |
|
783 }, false); |
|
784 } |
|
785 return this; |
|
786 }, |
|
787 unlisten: function( type, fn ) { |
|
788 |
|
789 if ( this.data.events[ type ] && this.data.events[ type ][ fn ] ) { |
|
790 |
|
791 delete this.data.events[ type ][ fn ]; |
|
792 |
|
793 return this; |
|
794 } |
|
795 |
|
796 this.data.events[ type ] = null; |
|
797 |
|
798 return this; |
|
799 } |
|
800 }, |
|
801 hooks: { |
|
802 canplayall: { |
|
803 bind: "canplaythrough", |
|
804 add: function( event, callback ) { |
|
805 |
|
806 var state = false; |
|
807 |
|
808 if ( this.media.readyState ) { |
|
809 |
|
810 callback.call( this, event ); |
|
811 |
|
812 state = true; |
|
813 } |
|
814 |
|
815 this.data.hooks.canplayall = { |
|
816 fired: state |
|
817 }; |
|
818 }, |
|
819 // declare special handling instructions |
|
820 handler: function canplayall( event, callback ) { |
|
821 |
|
822 if ( !this.data.hooks.canplayall.fired ) { |
|
823 // trigger original user callback once |
|
824 callback.call( this, event ); |
|
825 |
|
826 this.data.hooks.canplayall.fired = true; |
|
827 } |
|
828 } |
|
829 } |
|
830 } |
|
831 }; |
|
832 |
|
833 // Extend Popcorn.events.fns (listen, unlisten, trigger) to all Popcorn instances |
|
834 Popcorn.forEach( [ "trigger", "listen", "unlisten" ], function( key ) { |
|
835 Popcorn.p[ key ] = Popcorn.events.fn[ key ]; |
|
836 }); |
|
837 |
|
838 // Internal Only - Adds track events to the instance object |
|
839 Popcorn.addTrackEvent = function( obj, track ) { |
|
840 |
|
841 // Determine if this track has default options set for it |
|
842 // If so, apply them to the track object |
|
843 if ( track && track._natives && track._natives.type && |
|
844 ( obj.options.defaults && obj.options.defaults[ track._natives.type ] ) ) { |
|
845 |
|
846 track = Popcorn.extend( {}, obj.options.defaults[ track._natives.type ], track ); |
|
847 } |
|
848 |
|
849 if ( track._natives ) { |
|
850 // Supports user defined track event id |
|
851 track._id = !track.id ? Popcorn.guid( track._natives.type ) : track.id; |
|
852 |
|
853 // Push track event ids into the history |
|
854 obj.data.history.push( track._id ); |
|
855 } |
|
856 |
|
857 track.start = Popcorn.util.toSeconds( track.start, obj.options.framerate ); |
|
858 track.end = Popcorn.util.toSeconds( track.end, obj.options.framerate ); |
|
859 |
|
860 // Store this definition in an array sorted by times |
|
861 var byStart = obj.data.trackEvents.byStart, |
|
862 byEnd = obj.data.trackEvents.byEnd, |
|
863 startIndex, endIndex, |
|
864 currentTime; |
|
865 |
|
866 for ( startIndex = byStart.length - 1; startIndex >= 0; startIndex-- ) { |
|
867 |
|
868 if ( track.start >= byStart[ startIndex ].start ) { |
|
869 byStart.splice( startIndex + 1, 0, track ); |
|
870 break; |
|
871 } |
|
872 } |
|
873 |
|
874 for ( endIndex = byEnd.length - 1; endIndex >= 0; endIndex-- ) { |
|
875 |
|
876 if ( track.end > byEnd[ endIndex ].end ) { |
|
877 byEnd.splice( endIndex + 1, 0, track ); |
|
878 break; |
|
879 } |
|
880 } |
|
881 |
|
882 // Display track event immediately if it's enabled and current |
|
883 if ( track._natives && |
|
884 ( !!Popcorn.registryByName[ track._natives.type ] || !!obj[ track._natives.type ] ) ) { |
|
885 |
|
886 currentTime = obj.media.currentTime; |
|
887 if ( track.end > currentTime && |
|
888 track.start <= currentTime && |
|
889 obj.data.disabled.indexOf( track._natives.type ) === -1 ) { |
|
890 |
|
891 track._running = true; |
|
892 track._natives.start.call( obj, null, track ); |
|
893 |
|
894 if ( obj.options.frameAnimation && |
|
895 track._natives.frame ) { |
|
896 |
|
897 obj.data.trackEvents.animating.push( track ); |
|
898 track._natives.frame.call( obj, null, track, currentTime ); |
|
899 } |
|
900 } |
|
901 } |
|
902 |
|
903 // update startIndex and endIndex |
|
904 if ( startIndex <= obj.data.trackEvents.startIndex && |
|
905 track.start <= obj.data.trackEvents.previousUpdateTime ) { |
|
906 |
|
907 obj.data.trackEvents.startIndex++; |
|
908 } |
|
909 |
|
910 if ( endIndex <= obj.data.trackEvents.endIndex && |
|
911 track.end < obj.data.trackEvents.previousUpdateTime ) { |
|
912 |
|
913 obj.data.trackEvents.endIndex++; |
|
914 } |
|
915 |
|
916 this.timeUpdate( obj, null, true ); |
|
917 |
|
918 // Store references to user added trackevents in ref table |
|
919 if ( track._id ) { |
|
920 Popcorn.addTrackEvent.ref( obj, track ); |
|
921 } |
|
922 }; |
|
923 |
|
924 // Internal Only - Adds track event references to the instance object's trackRefs hash table |
|
925 Popcorn.addTrackEvent.ref = function( obj, track ) { |
|
926 obj.data.trackRefs[ track._id ] = track; |
|
927 |
|
928 return obj; |
|
929 }; |
|
930 |
|
931 Popcorn.removeTrackEvent = function( obj, trackId ) { |
|
932 |
|
933 var historyLen = obj.data.history.length, |
|
934 indexWasAt = 0, |
|
935 byStart = [], |
|
936 byEnd = [], |
|
937 animating = [], |
|
938 history = []; |
|
939 |
|
940 Popcorn.forEach( obj.data.trackEvents.byStart, function( o, i, context ) { |
|
941 // Preserve the original start/end trackEvents |
|
942 if ( !o._id ) { |
|
943 byStart.push( obj.data.trackEvents.byStart[i] ); |
|
944 byEnd.push( obj.data.trackEvents.byEnd[i] ); |
|
945 } |
|
946 |
|
947 // Filter for user track events (vs system track events) |
|
948 if ( o._id ) { |
|
949 |
|
950 // Filter for the trackevent to remove |
|
951 if ( o._id !== trackId ) { |
|
952 byStart.push( obj.data.trackEvents.byStart[i] ); |
|
953 byEnd.push( obj.data.trackEvents.byEnd[i] ); |
|
954 } |
|
955 |
|
956 // Capture the position of the track being removed. |
|
957 if ( o._id === trackId ) { |
|
958 indexWasAt = i; |
|
959 o._natives._teardown && o._natives._teardown.call( obj, o ); |
|
960 } |
|
961 } |
|
962 |
|
963 }); |
|
964 |
|
965 if ( obj.data.trackEvents.animating.length ) { |
|
966 Popcorn.forEach( obj.data.trackEvents.animating, function( o, i, context ) { |
|
967 // Preserve the original start/end trackEvents |
|
968 if ( !o._id ) { |
|
969 animating.push( obj.data.trackEvents.animating[i] ); |
|
970 } |
|
971 |
|
972 // Filter for user track events (vs system track events) |
|
973 if ( o._id ) { |
|
974 // Filter for the trackevent to remove |
|
975 if ( o._id !== trackId ) { |
|
976 animating.push( obj.data.trackEvents.animating[i] ); |
|
977 } |
|
978 } |
|
979 }); |
|
980 } |
|
981 |
|
982 // Update |
|
983 if ( indexWasAt <= obj.data.trackEvents.startIndex ) { |
|
984 obj.data.trackEvents.startIndex--; |
|
985 } |
|
986 |
|
987 if ( indexWasAt <= obj.data.trackEvents.endIndex ) { |
|
988 obj.data.trackEvents.endIndex--; |
|
989 } |
|
990 |
|
991 obj.data.trackEvents.byStart = byStart; |
|
992 obj.data.trackEvents.byEnd = byEnd; |
|
993 obj.data.trackEvents.animating = animating; |
|
994 |
|
995 for ( var i = 0; i < historyLen; i++ ) { |
|
996 if ( obj.data.history[ i ] !== trackId ) { |
|
997 history.push( obj.data.history[ i ] ); |
|
998 } |
|
999 } |
|
1000 |
|
1001 // Update ordered history array |
|
1002 obj.data.history = history; |
|
1003 |
|
1004 // Update track event references |
|
1005 Popcorn.removeTrackEvent.ref( obj, trackId ); |
|
1006 }; |
|
1007 |
|
1008 // Internal Only - Removes track event references from instance object's trackRefs hash table |
|
1009 Popcorn.removeTrackEvent.ref = function( obj, trackId ) { |
|
1010 delete obj.data.trackRefs[ trackId ]; |
|
1011 |
|
1012 return obj; |
|
1013 }; |
|
1014 |
|
1015 // Return an array of track events bound to this instance object |
|
1016 Popcorn.getTrackEvents = function( obj ) { |
|
1017 |
|
1018 var trackevents = [], |
|
1019 refs = obj.data.trackEvents.byStart, |
|
1020 length = refs.length, |
|
1021 idx = 0, |
|
1022 ref; |
|
1023 |
|
1024 for ( ; idx < length; idx++ ) { |
|
1025 ref = refs[ idx ]; |
|
1026 // Return only user attributed track event references |
|
1027 if ( ref._id ) { |
|
1028 trackevents.push( ref ); |
|
1029 } |
|
1030 } |
|
1031 |
|
1032 return trackevents; |
|
1033 }; |
|
1034 |
|
1035 // Internal Only - Returns an instance object's trackRefs hash table |
|
1036 Popcorn.getTrackEvents.ref = function( obj ) { |
|
1037 return obj.data.trackRefs; |
|
1038 }; |
|
1039 |
|
1040 // Return a single track event bound to this instance object |
|
1041 Popcorn.getTrackEvent = function( obj, trackId ) { |
|
1042 return obj.data.trackRefs[ trackId ]; |
|
1043 }; |
|
1044 |
|
1045 // Internal Only - Returns an instance object's track reference by track id |
|
1046 Popcorn.getTrackEvent.ref = function( obj, trackId ) { |
|
1047 return obj.data.trackRefs[ trackId ]; |
|
1048 }; |
|
1049 |
|
1050 Popcorn.getLastTrackEventId = function( obj ) { |
|
1051 return obj.data.history[ obj.data.history.length - 1 ]; |
|
1052 }; |
|
1053 |
|
1054 Popcorn.timeUpdate = function( obj, event ) { |
|
1055 |
|
1056 var currentTime = obj.media.currentTime, |
|
1057 previousTime = obj.data.trackEvents.previousUpdateTime, |
|
1058 tracks = obj.data.trackEvents, |
|
1059 animating = tracks.animating, |
|
1060 end = tracks.endIndex, |
|
1061 start = tracks.startIndex, |
|
1062 animIndex = 0, |
|
1063 |
|
1064 registryByName = Popcorn.registryByName, |
|
1065 |
|
1066 byEnd, byStart, byAnimate, natives, type; |
|
1067 |
|
1068 // Playbar advancing |
|
1069 if ( previousTime <= currentTime ) { |
|
1070 |
|
1071 while ( tracks.byEnd[ end ] && tracks.byEnd[ end ].end <= currentTime ) { |
|
1072 |
|
1073 byEnd = tracks.byEnd[ end ]; |
|
1074 natives = byEnd._natives; |
|
1075 type = natives && natives.type; |
|
1076 |
|
1077 // If plugin does not exist on this instance, remove it |
|
1078 if ( !natives || |
|
1079 ( !!registryByName[ type ] || |
|
1080 !!obj[ type ] ) ) { |
|
1081 |
|
1082 if ( byEnd._running === true ) { |
|
1083 byEnd._running = false; |
|
1084 natives.end.call( obj, event, byEnd ); |
|
1085 } |
|
1086 |
|
1087 end++; |
|
1088 } else { |
|
1089 // remove track event |
|
1090 Popcorn.removeTrackEvent( obj, byEnd._id ); |
|
1091 return; |
|
1092 } |
|
1093 } |
|
1094 |
|
1095 while ( tracks.byStart[ start ] && tracks.byStart[ start ].start <= currentTime ) { |
|
1096 |
|
1097 byStart = tracks.byStart[ start ]; |
|
1098 natives = byStart._natives; |
|
1099 type = natives && natives.type; |
|
1100 |
|
1101 // If plugin does not exist on this instance, remove it |
|
1102 if ( !natives || |
|
1103 ( !!registryByName[ type ] || |
|
1104 !!obj[ type ] ) ) { |
|
1105 |
|
1106 if ( byStart.end > currentTime && |
|
1107 byStart._running === false && |
|
1108 obj.data.disabled.indexOf( type ) === -1 ) { |
|
1109 |
|
1110 byStart._running = true; |
|
1111 natives.start.call( obj, event, byStart ); |
|
1112 |
|
1113 // If the `frameAnimation` option is used, |
|
1114 // push the current byStart object into the `animating` cue |
|
1115 if ( obj.options.frameAnimation && |
|
1116 ( byStart && byStart._running && byStart._natives.frame ) ) { |
|
1117 |
|
1118 animating.push( byStart ); |
|
1119 } |
|
1120 } |
|
1121 start++; |
|
1122 } else { |
|
1123 // remove track event |
|
1124 Popcorn.removeTrackEvent( obj, byStart._id ); |
|
1125 return; |
|
1126 } |
|
1127 } |
|
1128 |
|
1129 // If the `frameAnimation` option is used, iterate the animating track |
|
1130 // and execute the `frame` callback |
|
1131 if ( obj.options.frameAnimation ) { |
|
1132 while ( animIndex < animating.length ) { |
|
1133 |
|
1134 byAnimate = animating[ animIndex ]; |
|
1135 |
|
1136 if ( !byAnimate._running ) { |
|
1137 animating.splice( animIndex, 1 ); |
|
1138 } else { |
|
1139 byAnimate._natives.frame.call( obj, event, byAnimate, currentTime ); |
|
1140 animIndex++; |
|
1141 } |
|
1142 } |
|
1143 } |
|
1144 |
|
1145 // Playbar receding |
|
1146 } else if ( previousTime > currentTime ) { |
|
1147 |
|
1148 while ( tracks.byStart[ start ] && tracks.byStart[ start ].start > currentTime ) { |
|
1149 |
|
1150 byStart = tracks.byStart[ start ]; |
|
1151 natives = byStart._natives; |
|
1152 type = natives && natives.type; |
|
1153 |
|
1154 // if plugin does not exist on this instance, remove it |
|
1155 if ( !natives || |
|
1156 ( !!registryByName[ type ] || |
|
1157 !!obj[ type ] ) ) { |
|
1158 |
|
1159 if ( byStart._running === true ) { |
|
1160 byStart._running = false; |
|
1161 natives.end.call( obj, event, byStart ); |
|
1162 } |
|
1163 start--; |
|
1164 } else { |
|
1165 // remove track event |
|
1166 Popcorn.removeTrackEvent( obj, byStart._id ); |
|
1167 return; |
|
1168 } |
|
1169 } |
|
1170 |
|
1171 while ( tracks.byEnd[ end ] && tracks.byEnd[ end ].end > currentTime ) { |
|
1172 |
|
1173 byEnd = tracks.byEnd[ end ]; |
|
1174 natives = byEnd._natives; |
|
1175 type = natives && natives.type; |
|
1176 |
|
1177 // if plugin does not exist on this instance, remove it |
|
1178 if ( !natives || |
|
1179 ( !!registryByName[ type ] || |
|
1180 !!obj[ type ] ) ) { |
|
1181 |
|
1182 if ( byEnd.start <= currentTime && |
|
1183 byEnd._running === false && |
|
1184 obj.data.disabled.indexOf( type ) === -1 ) { |
|
1185 |
|
1186 byEnd._running = true; |
|
1187 natives.start.call( obj, event, byEnd ); |
|
1188 |
|
1189 // If the `frameAnimation` option is used, |
|
1190 // push the current byEnd object into the `animating` cue |
|
1191 if ( obj.options.frameAnimation && |
|
1192 ( byEnd && byEnd._running && byEnd._natives.frame ) ) { |
|
1193 |
|
1194 animating.push( byEnd ); |
|
1195 } |
|
1196 } |
|
1197 end--; |
|
1198 } else { |
|
1199 // remove track event |
|
1200 Popcorn.removeTrackEvent( obj, byEnd._id ); |
|
1201 return; |
|
1202 } |
|
1203 } |
|
1204 |
|
1205 // If the `frameAnimation` option is used, iterate the animating track |
|
1206 // and execute the `frame` callback |
|
1207 if ( obj.options.frameAnimation ) { |
|
1208 while ( animIndex < animating.length ) { |
|
1209 |
|
1210 byAnimate = animating[ animIndex ]; |
|
1211 |
|
1212 if ( !byAnimate._running ) { |
|
1213 animating.splice( animIndex, 1 ); |
|
1214 } else { |
|
1215 byAnimate._natives.frame.call( obj, event, byAnimate, currentTime ); |
|
1216 animIndex++; |
|
1217 } |
|
1218 } |
|
1219 } |
|
1220 // time bar is not moving ( video is paused ) |
|
1221 } |
|
1222 |
|
1223 tracks.endIndex = end; |
|
1224 tracks.startIndex = start; |
|
1225 tracks.previousUpdateTime = currentTime; |
|
1226 }; |
|
1227 |
|
1228 // Map and Extend TrackEvent functions to all Popcorn instances |
|
1229 Popcorn.extend( Popcorn.p, { |
|
1230 |
|
1231 getTrackEvents: function() { |
|
1232 return Popcorn.getTrackEvents.call( null, this ); |
|
1233 }, |
|
1234 |
|
1235 getTrackEvent: function( id ) { |
|
1236 return Popcorn.getTrackEvent.call( null, this, id ); |
|
1237 }, |
|
1238 |
|
1239 getLastTrackEventId: function() { |
|
1240 return Popcorn.getLastTrackEventId.call( null, this ); |
|
1241 }, |
|
1242 |
|
1243 removeTrackEvent: function( id ) { |
|
1244 |
|
1245 Popcorn.removeTrackEvent.call( null, this, id ); |
|
1246 return this; |
|
1247 }, |
|
1248 |
|
1249 removePlugin: function( name ) { |
|
1250 Popcorn.removePlugin.call( null, this, name ); |
|
1251 return this; |
|
1252 }, |
|
1253 |
|
1254 timeUpdate: function( event ) { |
|
1255 Popcorn.timeUpdate.call( null, this, event ); |
|
1256 return this; |
|
1257 }, |
|
1258 |
|
1259 destroy: function() { |
|
1260 Popcorn.destroy.call( null, this ); |
|
1261 return this; |
|
1262 } |
|
1263 }); |
|
1264 |
|
1265 // Plugin manifests |
|
1266 Popcorn.manifest = {}; |
|
1267 // Plugins are registered |
|
1268 Popcorn.registry = []; |
|
1269 Popcorn.registryByName = {}; |
|
1270 // An interface for extending Popcorn |
|
1271 // with plugin functionality |
|
1272 Popcorn.plugin = function( name, definition, manifest ) { |
|
1273 |
|
1274 if ( Popcorn.protect.natives.indexOf( name.toLowerCase() ) >= 0 ) { |
|
1275 Popcorn.error( "'" + name + "' is a protected function name" ); |
|
1276 return; |
|
1277 } |
|
1278 |
|
1279 // Provides some sugar, but ultimately extends |
|
1280 // the definition into Popcorn.p |
|
1281 var reserved = [ "start", "end" ], |
|
1282 plugin = {}, |
|
1283 setup, |
|
1284 isfn = typeof definition === "function", |
|
1285 methods = [ "_setup", "_teardown", "start", "end", "frame" ]; |
|
1286 |
|
1287 // combines calls of two function calls into one |
|
1288 var combineFn = function( first, second ) { |
|
1289 |
|
1290 first = first || Popcorn.nop; |
|
1291 second = second || Popcorn.nop; |
|
1292 |
|
1293 return function() { |
|
1294 first.apply( this, arguments ); |
|
1295 second.apply( this, arguments ); |
|
1296 }; |
|
1297 }; |
|
1298 |
|
1299 // If `manifest` arg is undefined, check for manifest within the `definition` object |
|
1300 // If no `definition.manifest`, an empty object is a sufficient fallback |
|
1301 Popcorn.manifest[ name ] = manifest = manifest || definition.manifest || {}; |
|
1302 |
|
1303 // apply safe, and empty default functions |
|
1304 methods.forEach(function( method ) { |
|
1305 definition[ method ] = safeTry( definition[ method ] || Popcorn.nop, name ); |
|
1306 }); |
|
1307 |
|
1308 var pluginFn = function( setup, options ) { |
|
1309 |
|
1310 if ( !options ) { |
|
1311 return this; |
|
1312 } |
|
1313 |
|
1314 // Storing the plugin natives |
|
1315 var natives = options._natives = {}, |
|
1316 compose = "", |
|
1317 defaults, originalOpts, manifestOpts, mergedSetupOpts; |
|
1318 |
|
1319 Popcorn.extend( natives, setup ); |
|
1320 |
|
1321 options._natives.type = name; |
|
1322 options._running = false; |
|
1323 |
|
1324 natives.start = natives.start || natives[ "in" ]; |
|
1325 natives.end = natives.end || natives[ "out" ]; |
|
1326 |
|
1327 // extend teardown to always call end if running |
|
1328 natives._teardown = combineFn(function() { |
|
1329 |
|
1330 var args = slice.call( arguments ); |
|
1331 |
|
1332 // end function signature is not the same as teardown, |
|
1333 // put null on the front of arguments for the event parameter |
|
1334 args.unshift( null ); |
|
1335 |
|
1336 // only call end if event is running |
|
1337 args[ 1 ]._running && natives.end.apply( this, args ); |
|
1338 }, natives._teardown ); |
|
1339 |
|
1340 // Check for previously set default options |
|
1341 defaults = this.options.defaults && this.options.defaults[ options._natives && options._natives.type ]; |
|
1342 |
|
1343 // default to an empty string if no effect exists |
|
1344 // split string into an array of effects |
|
1345 options.compose = options.compose && options.compose.split( " " ) || []; |
|
1346 options.effect = options.effect && options.effect.split( " " ) || []; |
|
1347 |
|
1348 // join the two arrays together |
|
1349 options.compose = options.compose.concat( options.effect ); |
|
1350 |
|
1351 options.compose.forEach(function( composeOption ) { |
|
1352 |
|
1353 // if the requested compose is garbage, throw it away |
|
1354 compose = Popcorn.compositions[ composeOption ] || {}; |
|
1355 |
|
1356 // extends previous functions with compose function |
|
1357 methods.forEach(function( method ) { |
|
1358 natives[ method ] = combineFn( natives[ method ], compose[ method ] ); |
|
1359 }); |
|
1360 }); |
|
1361 |
|
1362 // Ensure a manifest object, an empty object is a sufficient fallback |
|
1363 options._natives.manifest = manifest; |
|
1364 |
|
1365 // Checks for expected properties |
|
1366 if ( !( "start" in options ) ) { |
|
1367 options.start = options[ "in" ] || 0; |
|
1368 } |
|
1369 |
|
1370 if ( !( "end" in options ) ) { |
|
1371 options.end = options[ "out" ] || this.duration() || Number.MAX_VALUE; |
|
1372 } |
|
1373 |
|
1374 // Merge with defaults if they exist, make sure per call is prioritized |
|
1375 mergedSetupOpts = defaults ? Popcorn.extend( {}, defaults, options ) : |
|
1376 options; |
|
1377 |
|
1378 // Resolves 239, 241, 242 |
|
1379 if ( !mergedSetupOpts.target ) { |
|
1380 |
|
1381 // Sometimes the manifest may be missing entirely |
|
1382 // or it has an options object that doesn't have a `target` property |
|
1383 manifestOpts = "options" in manifest && manifest.options; |
|
1384 |
|
1385 mergedSetupOpts.target = manifestOpts && "target" in manifestOpts && manifestOpts.target; |
|
1386 } |
|
1387 |
|
1388 // Trigger _setup method if exists |
|
1389 options._natives._setup && options._natives._setup.call( this, mergedSetupOpts ); |
|
1390 |
|
1391 // Create new track event for this instance |
|
1392 Popcorn.addTrackEvent( this, Popcorn.extend( mergedSetupOpts, options ) ); |
|
1393 |
|
1394 // Future support for plugin event definitions |
|
1395 // for all of the native events |
|
1396 Popcorn.forEach( setup, function( callback, type ) { |
|
1397 |
|
1398 if ( type !== "type" ) { |
|
1399 |
|
1400 if ( reserved.indexOf( type ) === -1 ) { |
|
1401 |
|
1402 this.listen( type, callback ); |
|
1403 } |
|
1404 } |
|
1405 |
|
1406 }, this ); |
|
1407 |
|
1408 return this; |
|
1409 }; |
|
1410 |
|
1411 // Assign new named definition |
|
1412 plugin[ name ] = function( options ) { |
|
1413 return pluginFn.call( this, isfn ? definition.call( this, options ) : definition, |
|
1414 options ); |
|
1415 }; |
|
1416 |
|
1417 // Extend Popcorn.p with new named definition |
|
1418 Popcorn.extend( Popcorn.p, plugin ); |
|
1419 |
|
1420 // Push into the registry |
|
1421 var entry = { |
|
1422 fn: plugin[ name ], |
|
1423 definition: definition, |
|
1424 base: definition, |
|
1425 parents: [], |
|
1426 name: name |
|
1427 }; |
|
1428 Popcorn.registry.push( |
|
1429 Popcorn.extend( plugin, entry, { |
|
1430 type: name |
|
1431 }) |
|
1432 ); |
|
1433 Popcorn.registryByName[ name ] = entry; |
|
1434 |
|
1435 return plugin; |
|
1436 }; |
|
1437 |
|
1438 // Storage for plugin function errors |
|
1439 Popcorn.plugin.errors = []; |
|
1440 |
|
1441 // Returns wrapped plugin function |
|
1442 function safeTry( fn, pluginName ) { |
|
1443 return function() { |
|
1444 |
|
1445 // When Popcorn.plugin.debug is true, do not suppress errors |
|
1446 if ( Popcorn.plugin.debug ) { |
|
1447 return fn.apply( this, arguments ); |
|
1448 } |
|
1449 |
|
1450 try { |
|
1451 return fn.apply( this, arguments ); |
|
1452 } catch ( ex ) { |
|
1453 |
|
1454 // Push plugin function errors into logging queue |
|
1455 Popcorn.plugin.errors.push({ |
|
1456 plugin: pluginName, |
|
1457 thrown: ex, |
|
1458 source: fn.toString() |
|
1459 }); |
|
1460 |
|
1461 // Trigger an error that the instance can listen for |
|
1462 // and react to |
|
1463 this.trigger( "error", Popcorn.plugin.errors ); |
|
1464 } |
|
1465 }; |
|
1466 } |
|
1467 |
|
1468 // Debug-mode flag for plugin development |
|
1469 Popcorn.plugin.debug = false; |
|
1470 |
|
1471 // removePlugin( type ) removes all tracks of that from all instances of popcorn |
|
1472 // removePlugin( obj, type ) removes all tracks of type from obj, where obj is a single instance of popcorn |
|
1473 Popcorn.removePlugin = function( obj, name ) { |
|
1474 |
|
1475 // Check if we are removing plugin from an instance or from all of Popcorn |
|
1476 if ( !name ) { |
|
1477 |
|
1478 // Fix the order |
|
1479 name = obj; |
|
1480 obj = Popcorn.p; |
|
1481 |
|
1482 if ( Popcorn.protect.natives.indexOf( name.toLowerCase() ) >= 0 ) { |
|
1483 Popcorn.error( "'" + name + "' is a protected function name" ); |
|
1484 return; |
|
1485 } |
|
1486 |
|
1487 var registryLen = Popcorn.registry.length, |
|
1488 registryIdx; |
|
1489 |
|
1490 // remove plugin reference from registry |
|
1491 for ( registryIdx = 0; registryIdx < registryLen; registryIdx++ ) { |
|
1492 if ( Popcorn.registry[ registryIdx ].name === name ) { |
|
1493 Popcorn.registry.splice( registryIdx, 1 ); |
|
1494 delete Popcorn.registryByName[ name ]; |
|
1495 delete Popcorn.manifest[ name ]; |
|
1496 |
|
1497 // delete the plugin |
|
1498 delete obj[ name ]; |
|
1499 |
|
1500 // plugin found and removed, stop checking, we are done |
|
1501 return; |
|
1502 } |
|
1503 } |
|
1504 |
|
1505 } |
|
1506 |
|
1507 var byStart = obj.data.trackEvents.byStart, |
|
1508 byEnd = obj.data.trackEvents.byEnd, |
|
1509 animating = obj.data.trackEvents.animating, |
|
1510 idx, sl; |
|
1511 |
|
1512 // remove all trackEvents |
|
1513 for ( idx = 0, sl = byStart.length; idx < sl; idx++ ) { |
|
1514 |
|
1515 if ( ( byStart[ idx ] && byStart[ idx ]._natives && byStart[ idx ]._natives.type === name ) && |
|
1516 ( byEnd[ idx ] && byEnd[ idx ]._natives && byEnd[ idx ]._natives.type === name ) ) { |
|
1517 |
|
1518 byStart[ idx ]._natives._teardown && byStart[ idx ]._natives._teardown.call( obj, byStart[ idx ] ); |
|
1519 |
|
1520 byStart.splice( idx, 1 ); |
|
1521 byEnd.splice( idx, 1 ); |
|
1522 |
|
1523 // update for loop if something removed, but keep checking |
|
1524 idx--; sl--; |
|
1525 if ( obj.data.trackEvents.startIndex <= idx ) { |
|
1526 obj.data.trackEvents.startIndex--; |
|
1527 obj.data.trackEvents.endIndex--; |
|
1528 } |
|
1529 } |
|
1530 } |
|
1531 |
|
1532 //remove all animating events |
|
1533 for ( idx = 0, sl = animating.length; idx < sl; idx++ ) { |
|
1534 |
|
1535 if ( animating[ idx ] && animating[ idx ]._natives && animating[ idx ]._natives.type === name ) { |
|
1536 |
|
1537 animating.splice( idx, 1 ); |
|
1538 |
|
1539 // update for loop if something removed, but keep checking |
|
1540 idx--; sl--; |
|
1541 } |
|
1542 } |
|
1543 |
|
1544 }; |
|
1545 |
|
1546 Popcorn.compositions = {}; |
|
1547 |
|
1548 // Plugin inheritance |
|
1549 Popcorn.compose = function( name, definition, manifest ) { |
|
1550 |
|
1551 // If `manifest` arg is undefined, check for manifest within the `definition` object |
|
1552 // If no `definition.manifest`, an empty object is a sufficient fallback |
|
1553 Popcorn.manifest[ name ] = manifest = manifest || definition.manifest || {}; |
|
1554 |
|
1555 // register the effect by name |
|
1556 Popcorn.compositions[ name ] = definition; |
|
1557 }; |
|
1558 |
|
1559 Popcorn.plugin.effect = Popcorn.effect = Popcorn.compose; |
|
1560 |
|
1561 // stores parsers keyed on filetype |
|
1562 Popcorn.parsers = {}; |
|
1563 |
|
1564 // An interface for extending Popcorn |
|
1565 // with parser functionality |
|
1566 Popcorn.parser = function( name, type, definition ) { |
|
1567 |
|
1568 if ( Popcorn.protect.natives.indexOf( name.toLowerCase() ) >= 0 ) { |
|
1569 Popcorn.error( "'" + name + "' is a protected function name" ); |
|
1570 return; |
|
1571 } |
|
1572 |
|
1573 // fixes parameters for overloaded function call |
|
1574 if ( typeof type === "function" && !definition ) { |
|
1575 definition = type; |
|
1576 type = ""; |
|
1577 } |
|
1578 |
|
1579 if ( typeof definition !== "function" || typeof type !== "string" ) { |
|
1580 return; |
|
1581 } |
|
1582 |
|
1583 // Provides some sugar, but ultimately extends |
|
1584 // the definition into Popcorn.p |
|
1585 |
|
1586 var natives = Popcorn.events.all, |
|
1587 parseFn, |
|
1588 parser = {}; |
|
1589 |
|
1590 parseFn = function( filename, callback ) { |
|
1591 |
|
1592 if ( !filename ) { |
|
1593 return this; |
|
1594 } |
|
1595 |
|
1596 var that = this; |
|
1597 |
|
1598 Popcorn.xhr({ |
|
1599 url: filename, |
|
1600 dataType: type, |
|
1601 success: function( data ) { |
|
1602 |
|
1603 var tracksObject = definition( data ), |
|
1604 tracksData, |
|
1605 tracksDataLen, |
|
1606 tracksDef, |
|
1607 idx = 0; |
|
1608 |
|
1609 tracksData = tracksObject.data || []; |
|
1610 tracksDataLen = tracksData.length; |
|
1611 tracksDef = null; |
|
1612 |
|
1613 // If no tracks to process, return immediately |
|
1614 if ( !tracksDataLen ) { |
|
1615 return; |
|
1616 } |
|
1617 |
|
1618 // Create tracks out of parsed object |
|
1619 for ( ; idx < tracksDataLen; idx++ ) { |
|
1620 |
|
1621 tracksDef = tracksData[ idx ]; |
|
1622 |
|
1623 for ( var key in tracksDef ) { |
|
1624 |
|
1625 if ( hasOwn.call( tracksDef, key ) && !!that[ key ] ) { |
|
1626 |
|
1627 that[ key ]( tracksDef[ key ] ); |
|
1628 } |
|
1629 } |
|
1630 } |
|
1631 if ( callback ) { |
|
1632 callback(); |
|
1633 } |
|
1634 } |
|
1635 }); |
|
1636 |
|
1637 return this; |
|
1638 }; |
|
1639 |
|
1640 // Assign new named definition |
|
1641 parser[ name ] = parseFn; |
|
1642 |
|
1643 // Extend Popcorn.p with new named definition |
|
1644 Popcorn.extend( Popcorn.p, parser ); |
|
1645 |
|
1646 // keys the function name by filetype extension |
|
1647 //Popcorn.parsers[ name ] = true; |
|
1648 |
|
1649 return parser; |
|
1650 }; |
|
1651 |
|
1652 Popcorn.player = function( name, player ) { |
|
1653 |
|
1654 player = player || {}; |
|
1655 |
|
1656 var playerFn = function( target, src, options ) { |
|
1657 |
|
1658 options = options || {}; |
|
1659 |
|
1660 // List of events |
|
1661 var date = new Date() / 1000, |
|
1662 baselineTime = date, |
|
1663 currentTime = 0, |
|
1664 volume = 1, |
|
1665 muted = false, |
|
1666 events = {}, |
|
1667 |
|
1668 // The container div of the resource |
|
1669 container = document.getElementById( rIdExp.exec( target ) && rIdExp.exec( target )[ 2 ] ) || |
|
1670 document.getElementById( target ) || |
|
1671 target, |
|
1672 basePlayer = {}, |
|
1673 timeout, |
|
1674 popcorn; |
|
1675 |
|
1676 // copies a div into the media object |
|
1677 for( var val in container ) { |
|
1678 |
|
1679 if ( typeof container[ val ] === "object" ) { |
|
1680 |
|
1681 basePlayer[ val ] = container[ val ]; |
|
1682 } else if ( typeof container[ val ] === "function" ) { |
|
1683 |
|
1684 basePlayer[ val ] = (function( value ) { |
|
1685 |
|
1686 // this is a stupid ugly kludgy hack in honour of Safari |
|
1687 // in Safari a NodeList is a function, not an object |
|
1688 if ( "length" in container[ value ] && !container[ value ].call ) { |
|
1689 |
|
1690 return container[ value ]; |
|
1691 } else { |
|
1692 |
|
1693 return function() { |
|
1694 |
|
1695 return container[ value ].apply( container, arguments ); |
|
1696 }; |
|
1697 } |
|
1698 }( val )); |
|
1699 } else { |
|
1700 |
|
1701 Popcorn.player.defineProperty( basePlayer, val, { |
|
1702 get: (function( value ) { |
|
1703 |
|
1704 return function() { |
|
1705 |
|
1706 return container[ value ]; |
|
1707 }; |
|
1708 }( val )), |
|
1709 set: Popcorn.nop, |
|
1710 configurable: true |
|
1711 }); |
|
1712 } |
|
1713 } |
|
1714 |
|
1715 var timeupdate = function() { |
|
1716 |
|
1717 date = new Date() / 1000; |
|
1718 |
|
1719 if ( !basePlayer.paused ) { |
|
1720 |
|
1721 basePlayer.currentTime = basePlayer.currentTime + ( date - baselineTime ); |
|
1722 basePlayer.dispatchEvent( "timeupdate" ); |
|
1723 timeout = setTimeout( timeupdate, 10 ); |
|
1724 } |
|
1725 |
|
1726 baselineTime = date; |
|
1727 }; |
|
1728 |
|
1729 basePlayer.play = function() { |
|
1730 |
|
1731 this.paused = false; |
|
1732 |
|
1733 if ( basePlayer.readyState >= 4 ) { |
|
1734 |
|
1735 baselineTime = new Date() / 1000; |
|
1736 basePlayer.dispatchEvent( "play" ); |
|
1737 timeupdate(); |
|
1738 } |
|
1739 }; |
|
1740 |
|
1741 basePlayer.pause = function() { |
|
1742 |
|
1743 this.paused = true; |
|
1744 basePlayer.dispatchEvent( "pause" ); |
|
1745 }; |
|
1746 |
|
1747 Popcorn.player.defineProperty( basePlayer, "currentTime", { |
|
1748 get: function() { |
|
1749 |
|
1750 return currentTime; |
|
1751 }, |
|
1752 set: function( val ) { |
|
1753 |
|
1754 // make sure val is a number |
|
1755 currentTime = +val; |
|
1756 basePlayer.dispatchEvent( "timeupdate" ); |
|
1757 return currentTime; |
|
1758 }, |
|
1759 configurable: true |
|
1760 }); |
|
1761 |
|
1762 Popcorn.player.defineProperty( basePlayer, "volume", { |
|
1763 get: function() { |
|
1764 |
|
1765 return volume; |
|
1766 }, |
|
1767 set: function( val ) { |
|
1768 |
|
1769 // make sure val is a number |
|
1770 volume = +val; |
|
1771 basePlayer.dispatchEvent( "volumechange" ); |
|
1772 return volume; |
|
1773 }, |
|
1774 configurable: true |
|
1775 }); |
|
1776 |
|
1777 Popcorn.player.defineProperty( basePlayer, "muted", { |
|
1778 get: function() { |
|
1779 |
|
1780 return muted; |
|
1781 }, |
|
1782 set: function( val ) { |
|
1783 |
|
1784 // make sure val is a number |
|
1785 muted = +val; |
|
1786 basePlayer.dispatchEvent( "volumechange" ); |
|
1787 return muted; |
|
1788 }, |
|
1789 configurable: true |
|
1790 }); |
|
1791 |
|
1792 // Adds an event listener to the object |
|
1793 basePlayer.addEventListener = function( evtName, fn ) { |
|
1794 |
|
1795 if ( !events[ evtName ] ) { |
|
1796 |
|
1797 events[ evtName ] = []; |
|
1798 } |
|
1799 |
|
1800 events[ evtName ].push( fn ); |
|
1801 return fn; |
|
1802 }; |
|
1803 |
|
1804 // Can take event object or simple string |
|
1805 basePlayer.dispatchEvent = function( oEvent ) { |
|
1806 |
|
1807 var evt, |
|
1808 self = this, |
|
1809 eventInterface, |
|
1810 eventName = oEvent.type; |
|
1811 |
|
1812 // A string was passed, create event object |
|
1813 if ( !eventName ) { |
|
1814 |
|
1815 eventName = oEvent; |
|
1816 eventInterface = Popcorn.events.getInterface( eventName ); |
|
1817 |
|
1818 if ( eventInterface ) { |
|
1819 |
|
1820 evt = document.createEvent( eventInterface ); |
|
1821 evt.initEvent( eventName, true, true, window, 1 ); |
|
1822 } |
|
1823 } |
|
1824 |
|
1825 Popcorn.forEach( events[ eventName ], function( val ) { |
|
1826 |
|
1827 val.call( self, evt, self ); |
|
1828 }); |
|
1829 }; |
|
1830 |
|
1831 // Attempt to get src from playerFn parameter |
|
1832 basePlayer.src = src || ""; |
|
1833 basePlayer.readyState = 0; |
|
1834 basePlayer.duration = 0; |
|
1835 basePlayer.paused = true; |
|
1836 basePlayer.ended = 0; |
|
1837 |
|
1838 if ( player._setup ) { |
|
1839 |
|
1840 player._setup.call( basePlayer, options ); |
|
1841 } else { |
|
1842 |
|
1843 // there is no setup, which means there is nothing to load |
|
1844 basePlayer.readyState = 4; |
|
1845 basePlayer.dispatchEvent( "load" ); |
|
1846 basePlayer.dispatchEvent( "loadeddata" ); |
|
1847 } |
|
1848 |
|
1849 // when a custom player is loaded, load basePlayer state into custom player |
|
1850 basePlayer.addEventListener( "load", function() { |
|
1851 |
|
1852 // if a player is not ready before currentTime is called, this will set it after it is ready |
|
1853 basePlayer.currentTime = currentTime; |
|
1854 |
|
1855 // same as above with volume and muted |
|
1856 basePlayer.volume = volume; |
|
1857 basePlayer.muted = muted; |
|
1858 }); |
|
1859 |
|
1860 basePlayer.addEventListener( "loadeddata", function() { |
|
1861 |
|
1862 // if play was called before player ready, start playing video |
|
1863 !basePlayer.paused && basePlayer.play(); |
|
1864 }); |
|
1865 |
|
1866 popcorn = new Popcorn.p.init( basePlayer, options ); |
|
1867 |
|
1868 return popcorn; |
|
1869 }; |
|
1870 |
|
1871 Popcorn[ name ] = Popcorn[ name ] || playerFn; |
|
1872 }; |
|
1873 |
|
1874 Popcorn.player.defineProperty = Object.defineProperty || function( object, description, options ) { |
|
1875 |
|
1876 object.__defineGetter__( description, options.get || Popcorn.nop ); |
|
1877 object.__defineSetter__( description, options.set || Popcorn.nop ); |
|
1878 }; |
|
1879 |
|
1880 // Cache references to reused RegExps |
|
1881 var rparams = /\?/, |
|
1882 // XHR Setup object |
|
1883 setup = { |
|
1884 url: "", |
|
1885 data: "", |
|
1886 dataType: "", |
|
1887 success: Popcorn.nop, |
|
1888 type: "GET", |
|
1889 async: true, |
|
1890 xhr: function() { |
|
1891 return new global.XMLHttpRequest(); |
|
1892 } |
|
1893 }; |
|
1894 |
|
1895 Popcorn.xhr = function( options ) { |
|
1896 |
|
1897 options.dataType = options.dataType && options.dataType.toLowerCase() || null; |
|
1898 |
|
1899 if ( options.dataType && |
|
1900 ( options.dataType === "jsonp" || options.dataType === "script" ) ) { |
|
1901 |
|
1902 Popcorn.xhr.getJSONP( |
|
1903 options.url, |
|
1904 options.success, |
|
1905 options.dataType === "script" |
|
1906 ); |
|
1907 return; |
|
1908 } |
|
1909 |
|
1910 var settings = Popcorn.extend( {}, setup, options ); |
|
1911 |
|
1912 // Create new XMLHttpRequest object |
|
1913 settings.ajax = settings.xhr(); |
|
1914 |
|
1915 if ( settings.ajax ) { |
|
1916 |
|
1917 if ( settings.type === "GET" && settings.data ) { |
|
1918 |
|
1919 // append query string |
|
1920 settings.url += ( rparams.test( settings.url ) ? "&" : "?" ) + settings.data; |
|
1921 |
|
1922 // Garbage collect and reset settings.data |
|
1923 settings.data = null; |
|
1924 } |
|
1925 |
|
1926 |
|
1927 settings.ajax.open( settings.type, settings.url, settings.async ); |
|
1928 settings.ajax.send( settings.data || null ); |
|
1929 |
|
1930 return Popcorn.xhr.httpData( settings ); |
|
1931 } |
|
1932 }; |
|
1933 |
|
1934 |
|
1935 Popcorn.xhr.httpData = function( settings ) { |
|
1936 |
|
1937 var data, json = null, |
|
1938 parser, xml = null; |
|
1939 |
|
1940 settings.ajax.onreadystatechange = function() { |
|
1941 |
|
1942 if ( settings.ajax.readyState === 4 ) { |
|
1943 |
|
1944 try { |
|
1945 json = JSON.parse( settings.ajax.responseText ); |
|
1946 } catch( e ) { |
|
1947 //suppress |
|
1948 } |
|
1949 |
|
1950 data = { |
|
1951 xml: settings.ajax.responseXML, |
|
1952 text: settings.ajax.responseText, |
|
1953 json: json |
|
1954 }; |
|
1955 |
|
1956 // Normalize: data.xml is non-null in IE9 regardless of if response is valid xml |
|
1957 if ( !data.xml || !data.xml.documentElement ) { |
|
1958 data.xml = null; |
|
1959 |
|
1960 try { |
|
1961 parser = new DOMParser(); |
|
1962 xml = parser.parseFromString( settings.ajax.responseText, "text/xml" ); |
|
1963 |
|
1964 if ( !xml.getElementsByTagName( "parsererror" ).length ) { |
|
1965 data.xml = xml; |
|
1966 } |
|
1967 } catch ( e ) { |
|
1968 // data.xml remains null |
|
1969 } |
|
1970 } |
|
1971 |
|
1972 // If a dataType was specified, return that type of data |
|
1973 if ( settings.dataType ) { |
|
1974 data = data[ settings.dataType ]; |
|
1975 } |
|
1976 |
|
1977 |
|
1978 settings.success.call( settings.ajax, data ); |
|
1979 |
|
1980 } |
|
1981 }; |
|
1982 return data; |
|
1983 }; |
|
1984 |
|
1985 Popcorn.xhr.getJSONP = function( url, success, isScript ) { |
|
1986 |
|
1987 var head = document.head || document.getElementsByTagName( "head" )[ 0 ] || document.documentElement, |
|
1988 script = document.createElement( "script" ), |
|
1989 paramStr = url.split( "?" )[ 1 ], |
|
1990 isFired = false, |
|
1991 params = [], |
|
1992 callback, parts, callparam; |
|
1993 |
|
1994 if ( paramStr && !isScript ) { |
|
1995 params = paramStr.split( "&" ); |
|
1996 } |
|
1997 |
|
1998 if ( params.length ) { |
|
1999 parts = params[ params.length - 1 ].split( "=" ); |
|
2000 } |
|
2001 |
|
2002 callback = params.length ? ( parts[ 1 ] ? parts[ 1 ] : parts[ 0 ] ) : "jsonp"; |
|
2003 |
|
2004 if ( !paramStr && !isScript ) { |
|
2005 url += "?callback=" + callback; |
|
2006 } |
|
2007 |
|
2008 if ( callback && !isScript ) { |
|
2009 |
|
2010 // If a callback name already exists |
|
2011 if ( !!window[ callback ] ) { |
|
2012 // Create a new unique callback name |
|
2013 callback = Popcorn.guid( callback ); |
|
2014 } |
|
2015 |
|
2016 // Define the JSONP success callback globally |
|
2017 window[ callback ] = function( data ) { |
|
2018 // Fire success callbacks |
|
2019 success && success( data ); |
|
2020 isFired = true; |
|
2021 }; |
|
2022 |
|
2023 // Replace callback param and callback name |
|
2024 url = url.replace( parts.join( "=" ), parts[ 0 ] + "=" + callback ); |
|
2025 } |
|
2026 |
|
2027 script.onload = function() { |
|
2028 |
|
2029 // Handling remote script loading callbacks |
|
2030 if ( isScript ) { |
|
2031 // getScript |
|
2032 success && success(); |
|
2033 } |
|
2034 |
|
2035 // Executing for JSONP requests |
|
2036 if ( isFired ) { |
|
2037 // Garbage collect the callback |
|
2038 delete window[ callback ]; |
|
2039 } |
|
2040 // Garbage collect the script resource |
|
2041 head.removeChild( script ); |
|
2042 }; |
|
2043 |
|
2044 script.src = url; |
|
2045 |
|
2046 head.insertBefore( script, head.firstChild ); |
|
2047 |
|
2048 return; |
|
2049 }; |
|
2050 |
|
2051 Popcorn.getJSONP = Popcorn.xhr.getJSONP; |
|
2052 |
|
2053 Popcorn.getScript = Popcorn.xhr.getScript = function( url, success ) { |
|
2054 |
|
2055 return Popcorn.xhr.getJSONP( url, success, true ); |
|
2056 }; |
|
2057 |
|
2058 Popcorn.util = { |
|
2059 // Simple function to parse a timestamp into seconds |
|
2060 // Acceptable formats are: |
|
2061 // HH:MM:SS.MMM |
|
2062 // HH:MM:SS;FF |
|
2063 // Hours and minutes are optional. They default to 0 |
|
2064 toSeconds: function( timeStr, framerate ) { |
|
2065 // Hours and minutes are optional |
|
2066 // Seconds must be specified |
|
2067 // Seconds can be followed by milliseconds OR by the frame information |
|
2068 var validTimeFormat = /^([0-9]+:){0,2}[0-9]+([.;][0-9]+)?$/, |
|
2069 errorMessage = "Invalid time format", |
|
2070 digitPairs, lastIndex, lastPair, firstPair, |
|
2071 frameInfo, frameTime; |
|
2072 |
|
2073 if ( typeof timeStr === "number" ) { |
|
2074 return timeStr; |
|
2075 } |
|
2076 |
|
2077 if ( typeof timeStr === "string" && |
|
2078 !validTimeFormat.test( timeStr ) ) { |
|
2079 Popcorn.error( errorMessage ); |
|
2080 } |
|
2081 |
|
2082 digitPairs = timeStr.split( ":" ); |
|
2083 lastIndex = digitPairs.length - 1; |
|
2084 lastPair = digitPairs[ lastIndex ]; |
|
2085 |
|
2086 // Fix last element: |
|
2087 if ( lastPair.indexOf( ";" ) > -1 ) { |
|
2088 |
|
2089 frameInfo = lastPair.split( ";" ); |
|
2090 frameTime = 0; |
|
2091 |
|
2092 if ( framerate && ( typeof framerate === "number" ) ) { |
|
2093 frameTime = parseFloat( frameInfo[ 1 ], 10 ) / framerate; |
|
2094 } |
|
2095 |
|
2096 digitPairs[ lastIndex ] = parseInt( frameInfo[ 0 ], 10 ) + frameTime; |
|
2097 } |
|
2098 |
|
2099 firstPair = digitPairs[ 0 ]; |
|
2100 |
|
2101 return { |
|
2102 |
|
2103 1: parseFloat( firstPair, 10 ), |
|
2104 |
|
2105 2: ( parseInt( firstPair, 10 ) * 60 ) + |
|
2106 parseFloat( digitPairs[ 1 ], 10 ), |
|
2107 |
|
2108 3: ( parseInt( firstPair, 10 ) * 3600 ) + |
|
2109 ( parseInt( digitPairs[ 1 ], 10 ) * 60 ) + |
|
2110 parseFloat( digitPairs[ 2 ], 10 ) |
|
2111 |
|
2112 }[ digitPairs.length || 1 ]; |
|
2113 } |
|
2114 }; |
|
2115 |
|
2116 |
|
2117 // Initialize locale data |
|
2118 // Based on http://en.wikipedia.org/wiki/Language_localisation#Language_tags_and_codes |
|
2119 function initLocale( arg ) { |
|
2120 |
|
2121 var locale = typeof arg === "string" ? arg : [ arg.language, arg.region ].join( "-" ), |
|
2122 parts = locale.split( "-" ); |
|
2123 |
|
2124 // Setup locale data table |
|
2125 return { |
|
2126 iso6391: locale, |
|
2127 language: parts[ 0 ] || "", |
|
2128 region: parts[ 1 ] || "" |
|
2129 }; |
|
2130 } |
|
2131 |
|
2132 // Declare locale data table |
|
2133 var localeData = initLocale( global.navigator.userLanguage || global.navigator.language ); |
|
2134 |
|
2135 Popcorn.locale = { |
|
2136 |
|
2137 // Popcorn.locale.get() |
|
2138 // returns reference to privately |
|
2139 // defined localeData |
|
2140 get: function() { |
|
2141 return localeData; |
|
2142 }, |
|
2143 |
|
2144 // Popcorn.locale.set( string|object ); |
|
2145 set: function( arg ) { |
|
2146 |
|
2147 localeData = initLocale( arg ); |
|
2148 |
|
2149 Popcorn.locale.broadcast(); |
|
2150 |
|
2151 return localeData; |
|
2152 }, |
|
2153 |
|
2154 // Popcorn.locale.broadcast( type ) |
|
2155 // Sends events to all popcorn media instances that are |
|
2156 // listening for locale events |
|
2157 broadcast: function( type ) { |
|
2158 |
|
2159 var instances = Popcorn.instances, |
|
2160 length = instances.length, |
|
2161 idx = 0, |
|
2162 instance; |
|
2163 |
|
2164 type = type || "locale:changed"; |
|
2165 |
|
2166 // Iterate all current instances |
|
2167 for ( ; idx < length; idx++ ) { |
|
2168 instance = instances[ idx ]; |
|
2169 |
|
2170 // For those instances with locale event listeners, |
|
2171 // trigger a locale change event |
|
2172 if ( type in instance.data.events ) { |
|
2173 instance.trigger( type ); |
|
2174 } |
|
2175 } |
|
2176 } |
|
2177 }; |
|
2178 |
|
2179 // alias for exec function |
|
2180 Popcorn.p.cue = Popcorn.p.exec; |
|
2181 |
|
2182 function getItems() { |
|
2183 |
|
2184 var item, |
|
2185 list = []; |
|
2186 |
|
2187 if ( Object.keys ) { |
|
2188 list = Object.keys( Popcorn.p ); |
|
2189 } else { |
|
2190 |
|
2191 for ( item in Popcorn.p ) { |
|
2192 if ( hasOwn.call( Popcorn.p, item ) ) { |
|
2193 list.push( item ); |
|
2194 } |
|
2195 } |
|
2196 } |
|
2197 |
|
2198 return list.join( "," ).toLowerCase().split( ","); |
|
2199 } |
|
2200 |
|
2201 // Protected API methods |
|
2202 Popcorn.protect = { |
|
2203 natives: getItems() |
|
2204 }; |
|
2205 |
|
2206 // Exposes Popcorn to global context |
|
2207 global.Popcorn = Popcorn; |
|
2208 |
|
2209 })(window, window.document); |
|
2210 // A global callback for youtube... that makes me angry |
|
2211 var onYouTubePlayerReady = function( containerId ) { |
|
2212 |
|
2213 onYouTubePlayerReady[ containerId ] && onYouTubePlayerReady[ containerId ](); |
|
2214 }; |
|
2215 onYouTubePlayerReady.stateChangeEventHandler = {}; |
|
2216 |
|
2217 Popcorn.player( "youtube", { |
|
2218 _setup: function( options ) { |
|
2219 |
|
2220 var media = this, |
|
2221 youtubeObject, |
|
2222 container = document.createElement( "div" ), |
|
2223 currentTime = 0, |
|
2224 seekTime = 0, |
|
2225 seeking = false, |
|
2226 |
|
2227 // state code for volume changed polling |
|
2228 volumeChanged = false, |
|
2229 lastMuted = false, |
|
2230 lastVolume = 0; |
|
2231 |
|
2232 container.id = media.id + Popcorn.guid(); |
|
2233 |
|
2234 media.appendChild( container ); |
|
2235 |
|
2236 var youtubeInit = function() { |
|
2237 |
|
2238 var flashvars, |
|
2239 params, |
|
2240 attributes, |
|
2241 src; |
|
2242 |
|
2243 // expose a callback to this scope, that is called from the global callback youtube calls |
|
2244 onYouTubePlayerReady[ container.id ] = function() { |
|
2245 |
|
2246 youtubeObject = document.getElementById( container.id ); |
|
2247 |
|
2248 // more youtube callback nonsense |
|
2249 onYouTubePlayerReady.stateChangeEventHandler[ container.id ] = function( state ) { |
|
2250 |
|
2251 // playing is state 1 |
|
2252 // paused is state 2 |
|
2253 if ( state === 1 ) { |
|
2254 |
|
2255 media.paused && media.play(); |
|
2256 // youtube fires paused events while seeking |
|
2257 // this is the only way to get seeking events |
|
2258 } else if ( state === 2 ) { |
|
2259 |
|
2260 // silly logic forced on me by the youtube API |
|
2261 // calling youtube.seekTo triggers multiple events |
|
2262 // with the second events getCurrentTime being the old time |
|
2263 if ( seeking && seekTime === currentTime && seekTime !== youtubeObject.getCurrentTime() ) { |
|
2264 |
|
2265 seeking = false; |
|
2266 youtubeObject.seekTo( currentTime ); |
|
2267 return; |
|
2268 } |
|
2269 |
|
2270 currentTime = youtubeObject.getCurrentTime(); |
|
2271 media.dispatchEvent( "timeupdate" ); |
|
2272 !media.paused && media.pause(); |
|
2273 } |
|
2274 }; |
|
2275 |
|
2276 // youtube requires callbacks to be a string to a function path from the global scope |
|
2277 youtubeObject.addEventListener( "onStateChange", "onYouTubePlayerReady.stateChangeEventHandler." + container.id ); |
|
2278 |
|
2279 var timeupdate = function() { |
|
2280 |
|
2281 if ( !media.paused ) { |
|
2282 |
|
2283 currentTime = youtubeObject.getCurrentTime(); |
|
2284 media.dispatchEvent( "timeupdate" ); |
|
2285 setTimeout( timeupdate, 10 ); |
|
2286 } |
|
2287 }; |
|
2288 |
|
2289 var volumeupdate = function() { |
|
2290 |
|
2291 if ( lastMuted !== youtubeObject.isMuted() ) { |
|
2292 |
|
2293 lastMuted = youtubeObject.isMuted(); |
|
2294 media.dispatchEvent( "volumechange" ); |
|
2295 } |
|
2296 |
|
2297 if ( lastVolume !== youtubeObject.getVolume() ) { |
|
2298 |
|
2299 lastVolume = youtubeObject.getVolume(); |
|
2300 media.dispatchEvent( "volumechange" ); |
|
2301 } |
|
2302 |
|
2303 setTimeout( volumeupdate, 250 ); |
|
2304 }; |
|
2305 |
|
2306 media.play = function() { |
|
2307 |
|
2308 media.paused = false; |
|
2309 media.dispatchEvent( "play" ); |
|
2310 |
|
2311 media.dispatchEvent( "playing" ); |
|
2312 timeupdate(); |
|
2313 youtubeObject.playVideo(); |
|
2314 }; |
|
2315 |
|
2316 media.pause = function() { |
|
2317 |
|
2318 if ( !media.paused ) { |
|
2319 |
|
2320 media.paused = true; |
|
2321 media.dispatchEvent( "pause" ); |
|
2322 youtubeObject.pauseVideo(); |
|
2323 } |
|
2324 }; |
|
2325 |
|
2326 Popcorn.player.defineProperty( media, "currentTime", { |
|
2327 set: function( val ) { |
|
2328 |
|
2329 // make sure val is a number |
|
2330 currentTime = seekTime = +val; |
|
2331 seeking = true; |
|
2332 media.dispatchEvent( "seeked" ); |
|
2333 media.dispatchEvent( "timeupdate" ); |
|
2334 youtubeObject.seekTo( currentTime ); |
|
2335 return currentTime; |
|
2336 }, |
|
2337 get: function() { |
|
2338 |
|
2339 return currentTime; |
|
2340 } |
|
2341 }); |
|
2342 |
|
2343 Popcorn.player.defineProperty( media, "muted", { |
|
2344 set: function( val ) { |
|
2345 |
|
2346 if ( youtubeObject.isMuted() !== val ) { |
|
2347 |
|
2348 if ( val ) { |
|
2349 |
|
2350 youtubeObject.mute(); |
|
2351 } else { |
|
2352 |
|
2353 youtubeObject.unMute(); |
|
2354 } |
|
2355 |
|
2356 lastMuted = youtubeObject.isMuted(); |
|
2357 media.dispatchEvent( "volumechange" ); |
|
2358 } |
|
2359 |
|
2360 return youtubeObject.isMuted(); |
|
2361 }, |
|
2362 get: function() { |
|
2363 |
|
2364 return youtubeObject.isMuted(); |
|
2365 } |
|
2366 }); |
|
2367 |
|
2368 Popcorn.player.defineProperty( media, "volume", { |
|
2369 set: function( val ) { |
|
2370 |
|
2371 if ( youtubeObject.getVolume() !== val ) { |
|
2372 |
|
2373 youtubeObject.setVolume( val ); |
|
2374 lastVolume = youtubeObject.getVolume(); |
|
2375 media.dispatchEvent( "volumechange" ); |
|
2376 } |
|
2377 |
|
2378 return youtubeObject.getVolume(); |
|
2379 }, |
|
2380 get: function() { |
|
2381 |
|
2382 return youtubeObject.getVolume(); |
|
2383 } |
|
2384 }); |
|
2385 |
|
2386 media.readyState = 4; |
|
2387 media.dispatchEvent( "load" ); |
|
2388 media.duration = youtubeObject.getDuration(); |
|
2389 media.dispatchEvent( "durationchange" ); |
|
2390 volumeupdate(); |
|
2391 |
|
2392 media.dispatchEvent( "loadeddata" ); |
|
2393 }; |
|
2394 |
|
2395 options.controls = +options.controls === 0 || +options.controls === 1 ? options.controls : 1; |
|
2396 options.annotations = +options.annotations === 1 || +options.annotations === 3 ? options.annotations : 1; |
|
2397 |
|
2398 flashvars = { |
|
2399 playerapiid: container.id, |
|
2400 controls: options.controls, |
|
2401 iv_load_policy: options.annotations |
|
2402 }; |
|
2403 |
|
2404 params = { |
|
2405 wmode: "transparent", |
|
2406 allowScriptAccess: "always" |
|
2407 }; |
|
2408 |
|
2409 attributes = { |
|
2410 id: container.id |
|
2411 }; |
|
2412 |
|
2413 src = /^.*[\/=](.{11})/.exec( media.src )[ 1 ]; |
|
2414 |
|
2415 swfobject.embedSWF( "http://www.youtube.com/e/" + src + "?enablejsapi=1&playerapiid=" + container.id + "&version=3", |
|
2416 container.id, media.offsetWidth, media.offsetHeight, "8", null, |
|
2417 flashvars, params, attributes ); |
|
2418 }; |
|
2419 |
|
2420 if ( !window.swfobject ) { |
|
2421 |
|
2422 Popcorn.getScript( "http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js", youtubeInit ); |
|
2423 } else { |
|
2424 |
|
2425 youtubeInit(); |
|
2426 } |
|
2427 } |
|
2428 }); |
|
2429 |
|
2430 // PLUGIN: Code |
|
2431 |
|
2432 (function ( Popcorn ) { |
|
2433 |
|
2434 /** |
|
2435 * Code Popcorn Plug-in |
|
2436 * |
|
2437 * Adds the ability to run arbitrary code (JavaScript functions) according to video timing. |
|
2438 * |
|
2439 * @param {Object} options |
|
2440 * |
|
2441 * Required parameters: start, end, template, data, and target. |
|
2442 * Optional parameter: static. |
|
2443 * |
|
2444 * start: the time in seconds when the mustache template should be rendered |
|
2445 * in the target div. |
|
2446 * |
|
2447 * end: the time in seconds when the rendered mustache template should be |
|
2448 * removed from the target div. |
|
2449 * |
|
2450 * onStart: the function to be run when the start time is reached. |
|
2451 * |
|
2452 * onFrame: [optional] a function to be run on each paint call |
|
2453 * (e.g., called ~60 times per second) between the start and end times. |
|
2454 * |
|
2455 * onEnd: [optional] a function to be run when the end time is reached. |
|
2456 * |
|
2457 * Example: |
|
2458 var p = Popcorn('#video') |
|
2459 |
|
2460 // onStart function only |
|
2461 .code({ |
|
2462 start: 1, |
|
2463 end: 4, |
|
2464 onStart: function( options ) { |
|
2465 // called on start |
|
2466 } |
|
2467 }) |
|
2468 |
|
2469 // onStart + onEnd only |
|
2470 .code({ |
|
2471 start: 6, |
|
2472 end: 8, |
|
2473 onStart: function( options ) { |
|
2474 // called on start |
|
2475 }, |
|
2476 onEnd: function ( options ) { |
|
2477 // called on end |
|
2478 } |
|
2479 }) |
|
2480 |
|
2481 // onStart, onEnd, onFrame |
|
2482 .code({ |
|
2483 start: 10, |
|
2484 end: 14, |
|
2485 onStart: function( options ) { |
|
2486 // called on start |
|
2487 }, |
|
2488 onFrame: function ( options ) { |
|
2489 // called on every paint frame between start and end. |
|
2490 // uses mozRequestAnimationFrame, webkitRequestAnimationFrame, |
|
2491 // or setTimeout with 16ms window. |
|
2492 }, |
|
2493 onEnd: function ( options ) { |
|
2494 // called on end |
|
2495 } |
|
2496 }); |
|
2497 * |
|
2498 */ |
|
2499 |
|
2500 Popcorn.plugin( "code" , function( options ) { |
|
2501 var running = false; |
|
2502 |
|
2503 // Setup a proper frame interval function (60fps), favouring paint events. |
|
2504 var step = (function() { |
|
2505 |
|
2506 var buildFrameRunner = function( runner ) { |
|
2507 return function( f, options ) { |
|
2508 |
|
2509 var _f = function() { |
|
2510 running && f(); |
|
2511 running && runner( _f ); |
|
2512 }; |
|
2513 |
|
2514 _f(); |
|
2515 }; |
|
2516 }; |
|
2517 |
|
2518 // Figure out which level of browser support we have for this |
|
2519 if ( window.webkitRequestAnimationFrame ) { |
|
2520 return buildFrameRunner( window.webkitRequestAnimationFrame ); |
|
2521 } else if ( window.mozRequestAnimationFrame ) { |
|
2522 return buildFrameRunner( window.mozRequestAnimationFrame ); |
|
2523 } else { |
|
2524 return buildFrameRunner( function( f ) { |
|
2525 window.setTimeout( f, 16 ); |
|
2526 }); |
|
2527 } |
|
2528 |
|
2529 })(); |
|
2530 |
|
2531 if ( !options.onStart || typeof options.onStart !== "function" ) { |
|
2532 |
|
2533 if ( Popcorn.plugin.debug ) { |
|
2534 throw new Error( "Popcorn Code Plugin Error: onStart must be a function." ); |
|
2535 } |
|
2536 options.onStart = Popcorn.nop; |
|
2537 } |
|
2538 |
|
2539 if ( options.onEnd && typeof options.onEnd !== "function" ) { |
|
2540 |
|
2541 if ( Popcorn.plugin.debug ) { |
|
2542 throw new Error( "Popcorn Code Plugin Error: onEnd must be a function." ); |
|
2543 } |
|
2544 options.onEnd = undefined; |
|
2545 } |
|
2546 |
|
2547 if ( options.onFrame && typeof options.onFrame !== "function" ) { |
|
2548 |
|
2549 if ( Popcorn.plugin.debug ) { |
|
2550 throw new Error( "Popcorn Code Plugin Error: onFrame must be a function." ); |
|
2551 } |
|
2552 options.onFrame = undefined; |
|
2553 } |
|
2554 |
|
2555 return { |
|
2556 start: function( event, options ) { |
|
2557 options.onStart( options ); |
|
2558 |
|
2559 if ( options.onFrame ) { |
|
2560 running = true; |
|
2561 step( options.onFrame, options ); |
|
2562 } |
|
2563 }, |
|
2564 |
|
2565 end: function( event, options ) { |
|
2566 if ( options.onFrame ) { |
|
2567 running = false; |
|
2568 } |
|
2569 |
|
2570 if ( options.onEnd ) { |
|
2571 options.onEnd( options ); |
|
2572 } |
|
2573 } |
|
2574 }; |
|
2575 }, |
|
2576 { |
|
2577 about: { |
|
2578 name: "Popcorn Code Plugin", |
|
2579 version: "0.1", |
|
2580 author: "David Humphrey (@humphd)", |
|
2581 website: "http://vocamus.net/dave" |
|
2582 }, |
|
2583 options: { |
|
2584 start: { |
|
2585 elem: "input", |
|
2586 type: "text", |
|
2587 label: "In" |
|
2588 }, |
|
2589 end: { |
|
2590 elem: "input", |
|
2591 type: "text", |
|
2592 label: "Out" |
|
2593 }, |
|
2594 onStart: { |
|
2595 elem: "input", |
|
2596 type: "function", |
|
2597 label: "onStart" |
|
2598 }, |
|
2599 onFrame: { |
|
2600 elem: "input", |
|
2601 type: "function", |
|
2602 label: "onFrame" |
|
2603 }, |
|
2604 onEnd: { |
|
2605 elem: "input", |
|
2606 type: "function", |
|
2607 label: "onEnd" |
|
2608 } |
|
2609 } |
|
2610 }); |
|
2611 })( Popcorn ); |
|
2612 var jwplayerObjects = {}; |
|
2613 |
|
2614 Popcorn.player( "jwplayer", { |
|
2615 _setup: function( options ) { |
|
2616 |
|
2617 var media = this, |
|
2618 player = {}, |
|
2619 container = document.createElement( "div" ), |
|
2620 currentTime = 0, |
|
2621 seekTime = 0, |
|
2622 seeking = false, |
|
2623 dataLoaded = false; |
|
2624 container.id = media.id + Popcorn.guid(); |
|
2625 |
|
2626 media.appendChild( container ); |
|
2627 |
|
2628 var initApi = function () { |
|
2629 jwplayer( container.id ).onTime(function() { |
|
2630 currentTime = jwplayer(container.id).getPosition(); |
|
2631 media.dispatchEvent( "timeupdate" ); |
|
2632 // timeout = setTimeout( timeupdate, 10 ); |
|
2633 }); |
|
2634 |
|
2635 media.play = function() { |
|
2636 media.paused = false; |
|
2637 media.dispatchEvent( "play" ); |
|
2638 |
|
2639 media.dispatchEvent( "playing" ); |
|
2640 jwplayer( container.id ).play(); |
|
2641 }; |
|
2642 |
|
2643 media.pause = function() { |
|
2644 |
|
2645 if ( !media.paused ) { |
|
2646 media.paused = true; |
|
2647 media.dispatchEvent( "pause" ); |
|
2648 jwplayer( container.id ).pause(); |
|
2649 } |
|
2650 }; |
|
2651 |
|
2652 Popcorn.player.defineProperty( media, "currentTime", { |
|
2653 set: function( val ) { |
|
2654 // make sure val is a number |
|
2655 currentTime = seekTime = +val; |
|
2656 seeking = true; |
|
2657 media.dispatchEvent( "seeked" ); |
|
2658 media.dispatchEvent( "timeupdate" ); |
|
2659 jwplayer( container.id ).seek( currentTime ); |
|
2660 return currentTime; |
|
2661 }, |
|
2662 get: function() { |
|
2663 return jwplayer( container.id ).getPosition(); |
|
2664 } |
|
2665 }); |
|
2666 |
|
2667 Popcorn.player.defineProperty( media, "muted", { |
|
2668 set: function( val ) { |
|
2669 if ( jwplayer( container.id ).getMute() !== val ) { |
|
2670 if ( val ) { |
|
2671 jwplayer( container.id ).setMute(true); |
|
2672 } else { |
|
2673 jwplayer( container.id ).setMute(false); |
|
2674 } |
|
2675 |
|
2676 media.dispatchEvent( "volumechange" ); |
|
2677 } |
|
2678 |
|
2679 return jwplayer( container.id ).getMute(); |
|
2680 }, |
|
2681 get: function() { |
|
2682 return jwplayer( container.id ).getMute(); |
|
2683 } |
|
2684 }); |
|
2685 |
|
2686 Popcorn.player.defineProperty( media, "volume", { |
|
2687 |
|
2688 set: function( val ) { |
|
2689 |
|
2690 if ( jwplayer( container.id ).getVolume() !== val *100 ) { |
|
2691 jwplayer( container.id ).setVolume( val * 100); |
|
2692 media.dispatchEvent( "volumechange" ); |
|
2693 } |
|
2694 |
|
2695 return (jwplayer( container.id ).getVolume()) / 100; |
|
2696 }, |
|
2697 |
|
2698 get: function() { |
|
2699 return jwplayer( container.id ).getVolume() / 100; |
|
2700 } |
|
2701 }); |
|
2702 |
|
2703 media.readyState = 4; |
|
2704 media.dispatchEvent( 'load' ); |
|
2705 dataLoaded = true; |
|
2706 |
|
2707 media.duration = options.duration; |
|
2708 media.dispatchEvent( 'durationchange' ); |
|
2709 |
|
2710 media.paused && media.dispatchEvent( 'loadeddata' ); |
|
2711 |
|
2712 }; |
|
2713 |
|
2714 options.events = { |
|
2715 onReady: initApi |
|
2716 }; |
|
2717 |
|
2718 jwplayer( container.id ).setup(options); |
|
2719 |
|
2720 } |
|
2721 }); |
|
2722 |
|
2723 // PLUGIN: Mediafragment |
|
2724 |
|
2725 (function ( Popcorn ) { |
|
2726 |
|
2727 /** |
|
2728 * Mediafragment popcorn plug-in |
|
2729 * Adds (limited) support for mediafragment requests |
|
2730 * to a popcorn video. |
|
2731 * @param {Object} options |
|
2732 * |
|
2733 **/ |
|
2734 Popcorn.plugin( "mediafragment" , { |
|
2735 |
|
2736 manifest: { |
|
2737 about: { |
|
2738 name: "Popcorn mediafragment plugin", |
|
2739 version: "0.1", |
|
2740 author: "Karim Hamidou", |
|
2741 website: "http://neyret.fr/~karim" |
|
2742 }, |
|
2743 options: { |
|
2744 } |
|
2745 }, |
|
2746 |
|
2747 _setup: function( options ) { |
|
2748 var advanceTime = function() { |
|
2749 var url = window.location.href; |
|
2750 |
|
2751 if ( url.split( "#" )[ 1 ] != null ) { |
|
2752 pageoffset = url.split( "#" )[1]; |
|
2753 |
|
2754 if ( pageoffset.substring( 2 ) != null ) { |
|
2755 var offsettime = pageoffset.substring( 2 ); |
|
2756 this.currentTime( parseFloat( offsettime ) ); |
|
2757 } |
|
2758 } |
|
2759 } |
|
2760 |
|
2761 var updateTime = function() { |
|
2762 var history = window.history; |
|
2763 if ( !history.pushState ) { |
|
2764 return false; |
|
2765 } |
|
2766 |
|
2767 splitArr = window.location.href.split( "#" ) |
|
2768 history.replaceState( {}, "", splitArr[0] + "#t=" + this.currentTime().toFixed( 2 ) ); |
|
2769 }; |
|
2770 |
|
2771 this.listen( "loadedmetadata", advanceTime ); |
|
2772 this.listen( "pause", updateTime ); |
|
2773 this.listen( "seeked", updateTime ); |
|
2774 }, |
|
2775 |
|
2776 _teardown: function( options ) { |
|
2777 // FIXME: anything to implement here ? |
|
2778 } |
|
2779 }); |
|
2780 })( Popcorn ); |
|
2781 if(typeof jwplayer=="undefined"){var jwplayer=function(a){if(jwplayer.api){return jwplayer.api.selectPlayer(a)}};var $jw=jwplayer;jwplayer.version="5.7.1896";jwplayer.vid=document.createElement("video");jwplayer.audio=document.createElement("audio");jwplayer.source=document.createElement("source");(function(b){b.utils=function(){};b.utils.typeOf=function(d){var c=typeof d;if(c==="object"){if(d){if(d instanceof Array){c="array"}}else{c="null"}}return c};b.utils.extend=function(){var c=b.utils.extend["arguments"];if(c.length>1){for(var e=1;e<c.length;e++){for(var d in c[e]){c[0][d]=c[e][d]}}return c[0]}return null};b.utils.clone=function(f){var c;var d=b.utils.clone["arguments"];if(d.length==1){switch(b.utils.typeOf(d[0])){case"object":c={};for(var e in d[0]){c[e]=b.utils.clone(d[0][e])}break;case"array":c=[];for(var e in d[0]){c[e]=b.utils.clone(d[0][e])}break;default:return d[0];break}}return c};b.utils.extension=function(c){if(!c){return""}c=c.substring(c.lastIndexOf("/")+1,c.length);c=c.split("?")[0];if(c.lastIndexOf(".")>-1){return c.substr(c.lastIndexOf(".")+1,c.length).toLowerCase()}return};b.utils.html=function(c,d){c.innerHTML=d};b.utils.wrap=function(c,d){if(c.parentNode){c.parentNode.replaceChild(d,c)}d.appendChild(c)};b.utils.ajax=function(g,f,c){var e;if(window.XMLHttpRequest){e=new XMLHttpRequest()}else{e=new ActiveXObject("Microsoft.XMLHTTP")}e.onreadystatechange=function(){if(e.readyState===4){if(e.status===200){if(f){f(e)}}else{if(c){c(g)}}}};try{e.open("GET",g,true);e.send(null)}catch(d){if(c){c(g)}}return e};b.utils.load=function(d,e,c){d.onreadystatechange=function(){if(d.readyState===4){if(d.status===200){if(e){e()}}else{if(c){c()}}}}};b.utils.find=function(d,c){return d.getElementsByTagName(c)};b.utils.append=function(c,d){c.appendChild(d)};b.utils.isIE=function(){return((!+"\v1")||(typeof window.ActiveXObject!="undefined"))};b.utils.isLegacyAndroid=function(){var c=navigator.userAgent.toLowerCase();return(c.match(/android 2.[012]/i)!==null)};b.utils.isIOS=function(d){if(typeof d=="undefined"){d=/iP(hone|ad|od)/i}var c=navigator.userAgent.toLowerCase();return(c.match(d)!==null)};b.utils.isIPad=function(){return b.utils.isIOS(/iPad/i)};b.utils.isIPod=function(){return b.utils.isIOS(/iP(hone|od)/i)};b.utils.getFirstPlaylistItemFromConfig=function(c){var d={};var e;if(c.playlist&&c.playlist.length){e=c.playlist[0]}else{e=c}d.file=e.file;d.levels=e.levels;d.streamer=e.streamer;d.playlistfile=e.playlistfile;d.provider=e.provider;if(!d.provider){if(d.file&&(d.file.toLowerCase().indexOf("youtube.com")>-1||d.file.toLowerCase().indexOf("youtu.be")>-1)){d.provider="youtube"}if(d.streamer&&d.streamer.toLowerCase().indexOf("rtmp://")==0){d.provider="rtmp"}if(e.type){d.provider=e.type.toLowerCase()}}if(d.provider=="audio"){d.provider="sound"}return d};b.utils.getOuterHTML=function(c){if(c.outerHTML){return c.outerHTML}else{try{return new XMLSerializer().serializeToString(c)}catch(d){return""}}};b.utils.setOuterHTML=function(f,e){if(f.outerHTML){f.outerHTML=e}else{var g=document.createElement("div");g.innerHTML=e;var c=document.createRange();c.selectNodeContents(g);var d=c.extractContents();f.parentNode.insertBefore(d,f);f.parentNode.removeChild(f)}};b.utils.hasFlash=function(){if(typeof navigator.plugins!="undefined"&&typeof navigator.plugins["Shockwave Flash"]!="undefined"){return true}if(typeof window.ActiveXObject!="undefined"){try{new ActiveXObject("ShockwaveFlash.ShockwaveFlash");return true}catch(c){}}return false};b.utils.getPluginName=function(c){if(c.lastIndexOf("/")>=0){c=c.substring(c.lastIndexOf("/")+1,c.length)}if(c.lastIndexOf("-")>=0){c=c.substring(0,c.lastIndexOf("-"))}if(c.lastIndexOf(".swf")>=0){c=c.substring(0,c.lastIndexOf(".swf"))}if(c.lastIndexOf(".js")>=0){c=c.substring(0,c.lastIndexOf(".js"))}return c};b.utils.getPluginVersion=function(c){if(c.lastIndexOf("-")>=0){if(c.lastIndexOf(".js")>=0){return c.substring(c.lastIndexOf("-")+1,c.lastIndexOf(".js"))}else{if(c.lastIndexOf(".swf")>=0){return c.substring(c.lastIndexOf("-")+1,c.lastIndexOf(".swf"))}else{return c.substring(c.lastIndexOf("-")+1)}}}return""};b.utils.getAbsolutePath=function(j,h){if(!b.utils.exists(h)){h=document.location.href}if(!b.utils.exists(j)){return undefined}if(a(j)){return j}var k=h.substring(0,h.indexOf("://")+3);var g=h.substring(k.length,h.indexOf("/",k.length+1));var d;if(j.indexOf("/")===0){d=j.split("/")}else{var e=h.split("?")[0];e=e.substring(k.length+g.length+1,e.lastIndexOf("/"));d=e.split("/").concat(j.split("/"))}var c=[];for(var f=0;f<d.length;f++){if(!d[f]||!b.utils.exists(d[f])||d[f]=="."){continue}else{if(d[f]==".."){c.pop()}else{c.push(d[f])}}}return k+g+"/"+c.join("/")};function a(d){if(!b.utils.exists(d)){return}var e=d.indexOf("://");var c=d.indexOf("?");return(e>0&&(c<0||(c>e)))}b.utils.pluginPathType={ABSOLUTE:"ABSOLUTE",RELATIVE:"RELATIVE",CDN:"CDN"};b.utils.getPluginPathType=function(d){if(typeof d!="string"){return}d=d.split("?")[0];var e=d.indexOf("://");if(e>0){return b.utils.pluginPathType.ABSOLUTE}var c=d.indexOf("/");var f=b.utils.extension(d);if(e<0&&c<0&&(!f||!isNaN(f))){return b.utils.pluginPathType.CDN}return b.utils.pluginPathType.RELATIVE};b.utils.mapEmpty=function(c){for(var d in c){return false}return true};b.utils.mapLength=function(d){var c=0;for(var e in d){c++}return c};b.utils.log=function(d,c){if(typeof console!="undefined"&&typeof console.log!="undefined"){if(c){console.log(d,c)}else{console.log(d)}}};b.utils.css=function(d,g,c){if(b.utils.exists(d)){for(var e in g){try{if(typeof g[e]==="undefined"){continue}else{if(typeof g[e]=="number"&&!(e=="zIndex"||e=="opacity")){if(isNaN(g[e])){continue}if(e.match(/color/i)){g[e]="#"+b.utils.strings.pad(g[e].toString(16),6)}else{g[e]=Math.ceil(g[e])+"px"}}}d.style[e]=g[e]}catch(f){}}}};b.utils.isYouTube=function(c){return(c.indexOf("youtube.com")>-1||c.indexOf("youtu.be")>-1)};b.utils.transform=function(c,d){c.style.webkitTransform=d;c.style.MozTransform=d;c.style.OTransform=d};b.utils.stretch=function(h,n,m,f,l,g){if(typeof m=="undefined"||typeof f=="undefined"||typeof l=="undefined"||typeof g=="undefined"){return}var d=m/l;var e=f/g;var k=0;var j=0;n.style.overflow="hidden";b.utils.transform(n,"");var c={};switch(h.toUpperCase()){case b.utils.stretching.NONE:c.width=l;c.height=g;break;case b.utils.stretching.UNIFORM:if(d>e){c.width=l*e;c.height=g*e}else{c.width=l*d;c.height=g*d}break;case b.utils.stretching.FILL:if(d>e){c.width=l*d;c.height=g*d}else{c.width=l*e;c.height=g*e}break;case b.utils.stretching.EXACTFIT:b.utils.transform(n,["scale(",d,",",e,")"," translate(0px,0px)"].join(""));c.width=l;c.height=g;break;default:break}c.top=(f-c.height)/2;c.left=(m-c.width)/2;b.utils.css(n,c)};b.utils.stretching={NONE:"NONE",FILL:"FILL",UNIFORM:"UNIFORM",EXACTFIT:"EXACTFIT"};b.utils.deepReplaceKeyName=function(h,e,c){switch(b.utils.typeOf(h)){case"array":for(var g=0;g<h.length;g++){h[g]=b.utils.deepReplaceKeyName(h[g],e,c)}break;case"object":for(var f in h){var d=f.replace(new RegExp(e,"g"),c);h[d]=b.utils.deepReplaceKeyName(h[f],e,c);if(f!=d){delete h[f]}}break}return h};b.utils.isInArray=function(e,d){if(!(e)||!(e instanceof Array)){return false}for(var c=0;c<e.length;c++){if(d===e[c]){return true}}return false};b.utils.exists=function(c){switch(typeof(c)){case"string":return(c.length>0);break;case"object":return(c!==null);case"undefined":return false}return true};b.utils.empty=function(c){if(typeof c.hasChildNodes=="function"){while(c.hasChildNodes()){c.removeChild(c.firstChild)}}};b.utils.parseDimension=function(c){if(typeof c=="string"){if(c===""){return 0}else{if(c.lastIndexOf("%")>-1){return c}else{return parseInt(c.replace("px",""),10)}}}return c};b.utils.getDimensions=function(c){if(c&&c.style){return{x:b.utils.parseDimension(c.style.left),y:b.utils.parseDimension(c.style.top),width:b.utils.parseDimension(c.style.width),height:b.utils.parseDimension(c.style.height)}}else{return{}}};b.utils.timeFormat=function(c){str="00:00";if(c>0){str=Math.floor(c/60)<10?"0"+Math.floor(c/60)+":":Math.floor(c/60)+":";str+=Math.floor(c%60)<10?"0"+Math.floor(c%60):Math.floor(c%60)}return str}})(jwplayer);(function(a){a.events=function(){};a.events.COMPLETE="COMPLETE";a.events.ERROR="ERROR"})(jwplayer);(function(jwplayer){jwplayer.events.eventdispatcher=function(debug){var _debug=debug;var _listeners;var _globallisteners;this.resetEventListeners=function(){_listeners={};_globallisteners=[]};this.resetEventListeners();this.addEventListener=function(type,listener,count){try{if(!jwplayer.utils.exists(_listeners[type])){_listeners[type]=[]}if(typeof(listener)=="string"){eval("listener = "+listener)}_listeners[type].push({listener:listener,count:count})}catch(err){jwplayer.utils.log("error",err)}return false};this.removeEventListener=function(type,listener){if(!_listeners[type]){return}try{for(var listenerIndex=0;listenerIndex<_listeners[type].length;listenerIndex++){if(_listeners[type][listenerIndex].listener.toString()==listener.toString()){_listeners[type].splice(listenerIndex,1);break}}}catch(err){jwplayer.utils.log("error",err)}return false};this.addGlobalListener=function(listener,count){try{if(typeof(listener)=="string"){eval("listener = "+listener)}_globallisteners.push({listener:listener,count:count})}catch(err){jwplayer.utils.log("error",err)}return false};this.removeGlobalListener=function(listener){if(!_globallisteners[type]){return}try{for(var globalListenerIndex=0;globalListenerIndex<_globallisteners.length;globalListenerIndex++){if(_globallisteners[globalListenerIndex].listener.toString()==listener.toString()){_globallisteners.splice(globalListenerIndex,1);break}}}catch(err){jwplayer.utils.log("error",err)}return false};this.sendEvent=function(type,data){if(!jwplayer.utils.exists(data)){data={}}if(_debug){jwplayer.utils.log(type,data)}if(typeof _listeners[type]!="undefined"){for(var listenerIndex=0;listenerIndex<_listeners[type].length;listenerIndex++){try{_listeners[type][listenerIndex].listener(data)}catch(err){jwplayer.utils.log("There was an error while handling a listener: "+err.toString(),_listeners[type][listenerIndex].listener)}if(_listeners[type][listenerIndex]){if(_listeners[type][listenerIndex].count===1){delete _listeners[type][listenerIndex]}else{if(_listeners[type][listenerIndex].count>0){_listeners[type][listenerIndex].count=_listeners[type][listenerIndex].count-1}}}}}for(var globalListenerIndex=0;globalListenerIndex<_globallisteners.length;globalListenerIndex++){try{_globallisteners[globalListenerIndex].listener(data)}catch(err){jwplayer.utils.log("There was an error while handling a listener: "+err.toString(),_globallisteners[globalListenerIndex].listener)}if(_globallisteners[globalListenerIndex]){if(_globallisteners[globalListenerIndex].count===1){delete _globallisteners[globalListenerIndex]}else{if(_globallisteners[globalListenerIndex].count>0){_globallisteners[globalListenerIndex].count=_globallisteners[globalListenerIndex].count-1}}}}}}})(jwplayer);(function(a){var b={};a.utils.animations=function(){};a.utils.animations.transform=function(c,d){c.style.webkitTransform=d;c.style.MozTransform=d;c.style.OTransform=d;c.style.msTransform=d};a.utils.animations.transformOrigin=function(c,d){c.style.webkitTransformOrigin=d;c.style.MozTransformOrigin=d;c.style.OTransformOrigin=d;c.style.msTransformOrigin=d};a.utils.animations.rotate=function(c,d){a.utils.animations.transform(c,["rotate(",d,"deg)"].join(""))};a.utils.cancelAnimation=function(c){delete b[c.id]};a.utils.fadeTo=function(m,f,e,j,h,d){if(b[m.id]!=d&&a.utils.exists(d)){return}if(m.style.opacity==f){return}var c=new Date().getTime();if(d>c){setTimeout(function(){a.utils.fadeTo(m,f,e,j,0,d)},d-c)}if(m.style.display=="none"){m.style.display="block"}if(!a.utils.exists(j)){j=m.style.opacity===""?1:m.style.opacity}if(m.style.opacity==f&&m.style.opacity!==""&&a.utils.exists(d)){if(f===0){m.style.display="none"}return}if(!a.utils.exists(d)){d=c;b[m.id]=d}if(!a.utils.exists(h)){h=0}var k=(e>0)?((c-d)/(e*1000)):0;k=k>1?1:k;var l=f-j;var g=j+(k*l);if(g>1){g=1}else{if(g<0){g=0}}m.style.opacity=g;if(h>0){b[m.id]=d+h*1000;a.utils.fadeTo(m,f,e,j,0,b[m.id]);return}setTimeout(function(){a.utils.fadeTo(m,f,e,j,0,d)},10)}})(jwplayer);(function(a){a.utils.arrays=function(){};a.utils.arrays.indexOf=function(c,d){for(var b=0;b<c.length;b++){if(c[b]==d){return b}}return -1};a.utils.arrays.remove=function(c,d){var b=a.utils.arrays.indexOf(c,d);if(b>-1){c.splice(b,1)}}})(jwplayer);(function(a){a.utils.extensionmap={"3gp":{html5:"video/3gpp",flash:"video"},"3gpp":{html5:"video/3gpp"},"3g2":{html5:"video/3gpp2",flash:"video"},"3gpp2":{html5:"video/3gpp2"},flv:{flash:"video"},f4a:{html5:"audio/mp4"},f4b:{html5:"audio/mp4",flash:"video"},f4v:{html5:"video/mp4",flash:"video"},mov:{html5:"video/quicktime",flash:"video"},m4a:{html5:"audio/mp4",flash:"video"},m4b:{html5:"audio/mp4"},m4p:{html5:"audio/mp4"},m4v:{html5:"video/mp4",flash:"video"},mp4:{html5:"video/mp4",flash:"video"},rbs:{flash:"sound"},aac:{html5:"audio/aac",flash:"video"},mp3:{html5:"audio/mp3",flash:"sound"},ogg:{html5:"audio/ogg"},oga:{html5:"audio/ogg"},ogv:{html5:"video/ogg"},webm:{html5:"video/webm"},m3u8:{html5:"audio/x-mpegurl"},gif:{flash:"image"},jpeg:{flash:"image"},jpg:{flash:"image"},swf:{flash:"image"},png:{flash:"image"},wav:{html5:"audio/x-wav"}}})(jwplayer);(function(e){e.utils.mediaparser=function(){};var g={element:{width:"width",height:"height",id:"id","class":"className",name:"name"},media:{src:"file",preload:"preload",autoplay:"autostart",loop:"repeat",controls:"controls"},source:{src:"file",type:"type",media:"media","data-jw-width":"width","data-jw-bitrate":"bitrate"},video:{poster:"image"}};var f={};e.utils.mediaparser.parseMedia=function(j){return d(j)};function c(k,j){if(!e.utils.exists(j)){j=g[k]}else{e.utils.extend(j,g[k])}return j}function d(n,j){if(f[n.tagName.toLowerCase()]&&!e.utils.exists(j)){return f[n.tagName.toLowerCase()](n)}else{j=c("element",j);var o={};for(var k in j){if(k!="length"){var m=n.getAttribute(k);if(e.utils.exists(m)){o[j[k]]=m}}}var l=n.style["#background-color"];if(l&&!(l=="transparent"||l=="rgba(0, 0, 0, 0)")){o.screencolor=l}return o}}function h(n,k){k=c("media",k);var l=[];var j=e.utils.selectors("source",n);for(var m in j){if(!isNaN(m)){l.push(a(j[m]))}}var o=d(n,k);if(e.utils.exists(o.file)){l[0]={file:o.file}}o.levels=l;return o}function a(l,k){k=c("source",k);var j=d(l,k);j.width=j.width?j.width:0;j.bitrate=j.bitrate?j.bitrate:0;return j}function b(l,k){k=c("video",k);var j=h(l,k);return j}f.media=h;f.audio=h;f.source=a;f.video=b})(jwplayer);(function(a){a.utils.loaderstatus={NEW:"NEW",LOADING:"LOADING",ERROR:"ERROR",COMPLETE:"COMPLETE"};a.utils.scriptloader=function(c){var d=a.utils.loaderstatus.NEW;var b=new a.events.eventdispatcher();a.utils.extend(this,b);this.load=function(){if(d==a.utils.loaderstatus.NEW){d=a.utils.loaderstatus.LOADING;var e=document.createElement("script");e.onload=function(f){d=a.utils.loaderstatus.COMPLETE;b.sendEvent(a.events.COMPLETE)};e.onerror=function(f){d=a.utils.loaderstatus.ERROR;b.sendEvent(a.events.ERROR)};e.onreadystatechange=function(){if(e.readyState=="loaded"||e.readyState=="complete"){d=a.utils.loaderstatus.COMPLETE;b.sendEvent(a.events.COMPLETE)}};document.getElementsByTagName("head")[0].appendChild(e);e.src=c}};this.getStatus=function(){return d}}})(jwplayer);(function(a){a.utils.selectors=function(b,e){if(!a.utils.exists(e)){e=document}b=a.utils.strings.trim(b);var c=b.charAt(0);if(c=="#"){return e.getElementById(b.substr(1))}else{if(c=="."){if(e.getElementsByClassName){return e.getElementsByClassName(b.substr(1))}else{return a.utils.selectors.getElementsByTagAndClass("*",b.substr(1))}}else{if(b.indexOf(".")>0){var d=b.split(".");return a.utils.selectors.getElementsByTagAndClass(d[0],d[1])}else{return e.getElementsByTagName(b)}}}return null};a.utils.selectors.getElementsByTagAndClass=function(e,h,g){var j=[];if(!a.utils.exists(g)){g=document}var f=g.getElementsByTagName(e);for(var d=0;d<f.length;d++){if(a.utils.exists(f[d].className)){var c=f[d].className.split(" ");for(var b=0;b<c.length;b++){if(c[b]==h){j.push(f[d])}}}}return j}})(jwplayer);(function(a){a.utils.strings=function(){};a.utils.strings.trim=function(b){return b.replace(/^\s*/,"").replace(/\s*$/,"")};a.utils.strings.pad=function(c,d,b){if(!b){b="0"}while(c.length<d){c=b+c}return c};a.utils.strings.serialize=function(b){if(b==null){return null}else{if(b=="true"){return true}else{if(b=="false"){return false}else{if(isNaN(Number(b))||b.length>5||b.length==0){return b}else{return Number(b)}}}}};a.utils.strings.seconds=function(d){d=d.replace(",",".");var b=d.split(":");var c=0;if(d.substr(-1)=="s"){c=Number(d.substr(0,d.length-1))}else{if(d.substr(-1)=="m"){c=Number(d.substr(0,d.length-1))*60}else{if(d.substr(-1)=="h"){c=Number(d.substr(0,d.length-1))*3600}else{if(b.length>1){c=Number(b[b.length-1]);c+=Number(b[b.length-2])*60;if(b.length==3){c+=Number(b[b.length-3])*3600}}else{c=Number(d)}}}}return c};a.utils.strings.xmlAttribute=function(b,c){for(var d=0;d<b.attributes.length;d++){if(b.attributes[d].name&&b.attributes[d].name.toLowerCase()==c.toLowerCase()){return b.attributes[d].value.toString()}}return""};a.utils.strings.jsonToString=function(f){var h=h||{};if(h&&h.stringify){return h.stringify(f)}var c=typeof(f);if(c!="object"||f===null){if(c=="string"){f='"'+f+'"'}else{return String(f)}}else{var g=[],b=(f&&f.constructor==Array);for(var d in f){var e=f[d];switch(typeof(e)){case"string":e='"'+e+'"';break;case"object":if(a.utils.exists(e)){e=a.utils.strings.jsonToString(e)}break}if(b){if(typeof(e)!="function"){g.push(String(e))}}else{if(typeof(e)!="function"){g.push('"'+d+'":'+String(e))}}}if(b){return"["+String(g)+"]"}else{return"{"+String(g)+"}"}}}})(jwplayer);(function(c){var d=new RegExp(/^(#|0x)[0-9a-fA-F]{3,6}/);c.utils.typechecker=function(g,f){f=!c.utils.exists(f)?b(g):f;return e(g,f)};function b(f){var g=["true","false","t","f"];if(g.toString().indexOf(f.toLowerCase().replace(" ",""))>=0){return"boolean"}else{if(d.test(f)){return"color"}else{if(!isNaN(parseInt(f,10))&&parseInt(f,10).toString().length==f.length){return"integer"}else{if(!isNaN(parseFloat(f))&&parseFloat(f).toString().length==f.length){return"float"}}}}return"string"}function e(g,f){if(!c.utils.exists(f)){return g}switch(f){case"color":if(g.length>0){return a(g)}return null;case"integer":return parseInt(g,10);case"float":return parseFloat(g);case"boolean":if(g.toLowerCase()=="true"){return true}else{if(g=="1"){return true}}return false}return g}function a(f){switch(f.toLowerCase()){case"blue":return parseInt("0000FF",16);case"green":return parseInt("00FF00",16);case"red":return parseInt("FF0000",16);case"cyan":return parseInt("00FFFF",16);case"magenta":return parseInt("FF00FF",16);case"yellow":return parseInt("FFFF00",16);case"black":return parseInt("000000",16);case"white":return parseInt("FFFFFF",16);default:f=f.replace(/(#|0x)?([0-9A-F]{3,6})$/gi,"$2");if(f.length==3){f=f.charAt(0)+f.charAt(0)+f.charAt(1)+f.charAt(1)+f.charAt(2)+f.charAt(2)}return parseInt(f,16)}return parseInt("000000",16)}})(jwplayer);(function(a){a.utils.parsers=function(){};a.utils.parsers.localName=function(b){if(!b){return""}else{if(b.localName){return b.localName}else{if(b.baseName){return b.baseName}else{return""}}}};a.utils.parsers.textContent=function(b){if(!b){return""}else{if(b.textContent){return b.textContent}else{if(b.text){return b.text}else{return""}}}}})(jwplayer);(function(a){a.utils.parsers.jwparser=function(){};a.utils.parsers.jwparser.PREFIX="jwplayer";a.utils.parsers.jwparser.parseEntry=function(c,d){for(var b=0;b<c.childNodes.length;b++){if(c.childNodes[b].prefix==a.utils.parsers.jwparser.PREFIX){d[a.utils.parsers.localName(c.childNodes[b])]=a.utils.strings.serialize(a.utils.parsers.textContent(c.childNodes[b]))}if(!d.file&&String(d.link).toLowerCase().indexOf("youtube")>-1){d.file=d.link}}return d};a.utils.parsers.jwparser.getProvider=function(c){if(c.type){return c.type}else{if(c.file.indexOf("youtube.com/w")>-1||c.file.indexOf("youtube.com/v")>-1||c.file.indexOf("youtu.be/")>-1){return"youtube"}else{if(c.streamer&&c.streamer.indexOf("rtmp")==0){return"rtmp"}else{if(c.streamer&&c.streamer.indexOf("http")==0){return"http"}else{var b=a.utils.strings.extension(c.file);if(extensions.hasOwnProperty(b)){return extensions[b]}}}}}return""}})(jwplayer);(function(a){a.utils.parsers.mediaparser=function(){};a.utils.parsers.mediaparser.PREFIX="media";a.utils.parsers.mediaparser.parseGroup=function(d,f){var e=false;for(var c=0;c<d.childNodes.length;c++){if(d.childNodes[c].prefix==a.utils.parsers.mediaparser.PREFIX){if(!a.utils.parsers.localName(d.childNodes[c])){continue}switch(a.utils.parsers.localName(d.childNodes[c]).toLowerCase()){case"content":if(!e){f.file=a.utils.strings.xmlAttribute(d.childNodes[c],"url")}if(a.utils.strings.xmlAttribute(d.childNodes[c],"duration")){f.duration=a.utils.strings.seconds(a.utils.strings.xmlAttribute(d.childNodes[c],"duration"))}if(a.utils.strings.xmlAttribute(d.childNodes[c],"start")){f.start=a.utils.strings.seconds(a.utils.strings.xmlAttribute(d.childNodes[c],"start"))}if(d.childNodes[c].childNodes&&d.childNodes[c].childNodes.length>0){f=a.utils.parsers.mediaparser.parseGroup(d.childNodes[c],f)}if(a.utils.strings.xmlAttribute(d.childNodes[c],"width")||a.utils.strings.xmlAttribute(d.childNodes[c],"bitrate")||a.utils.strings.xmlAttribute(d.childNodes[c],"url")){if(!f.levels){f.levels=[]}f.levels.push({width:a.utils.strings.xmlAttribute(d.childNodes[c],"width"),bitrate:a.utils.strings.xmlAttribute(d.childNodes[c],"bitrate"),file:a.utils.strings.xmlAttribute(d.childNodes[c],"url")})}break;case"title":f.title=a.utils.parsers.textContent(d.childNodes[c]);break;case"description":f.description=a.utils.parsers.textContent(d.childNodes[c]);break;case"keywords":f.tags=a.utils.parsers.textContent(d.childNodes[c]);break;case"thumbnail":f.image=a.utils.strings.xmlAttribute(d.childNodes[c],"url");break;case"credit":f.author=a.utils.parsers.textContent(d.childNodes[c]);break;case"player":var b=d.childNodes[c].url;if(b.indexOf("youtube.com")>=0||b.indexOf("youtu.be")>=0){e=true;f.file=a.utils.strings.xmlAttribute(d.childNodes[c],"url")}break;case"group":a.utils.parsers.mediaparser.parseGroup(d.childNodes[c],f);break}}}return f}})(jwplayer);(function(b){b.utils.parsers.rssparser=function(){};b.utils.parsers.rssparser.parse=function(f){var c=[];for(var e=0;e<f.childNodes.length;e++){if(b.utils.parsers.localName(f.childNodes[e]).toLowerCase()=="channel"){for(var d=0;d<f.childNodes[e].childNodes.length;d++){if(b.utils.parsers.localName(f.childNodes[e].childNodes[d]).toLowerCase()=="item"){c.push(a(f.childNodes[e].childNodes[d]))}}}}return c};function a(d){var e={};for(var c=0;c<d.childNodes.length;c++){if(!b.utils.parsers.localName(d.childNodes[c])){continue}switch(b.utils.parsers.localName(d.childNodes[c]).toLowerCase()){case"enclosure":e.file=b.utils.strings.xmlAttribute(d.childNodes[c],"url");break;case"title":e.title=b.utils.parsers.textContent(d.childNodes[c]);break;case"pubdate":e.date=b.utils.parsers.textContent(d.childNodes[c]);break;case"description":e.description=b.utils.parsers.textContent(d.childNodes[c]);break;case"link":e.link=b.utils.parsers.textContent(d.childNodes[c]);break;case"category":if(e.tags){e.tags+=b.utils.parsers.textContent(d.childNodes[c])}else{e.tags=b.utils.parsers.textContent(d.childNodes[c])}break}}e=b.utils.parsers.mediaparser.parseGroup(d,e);e=b.utils.parsers.jwparser.parseEntry(d,e);return new b.html5.playlistitem(e)}})(jwplayer);(function(a){var c={};var b={};a.plugins=function(){};a.plugins.loadPlugins=function(e,d){b[e]=new a.plugins.pluginloader(new a.plugins.model(c),d);return b[e]};a.plugins.registerPlugin=function(h,f,e){var d=a.utils.getPluginName(h);if(c[d]){c[d].registerPlugin(h,f,e)}else{a.utils.log("A plugin ("+h+") was registered with the player that was not loaded. Please check your configuration.");for(var g in b){b[g].pluginFailed()}}}})(jwplayer);(function(a){a.plugins.model=function(b){this.addPlugin=function(c){var d=a.utils.getPluginName(c);if(!b[d]){b[d]=new a.plugins.plugin(c)}return b[d]}}})(jwplayer);(function(a){a.plugins.pluginmodes={FLASH:"FLASH",JAVASCRIPT:"JAVASCRIPT",HYBRID:"HYBRID"};a.plugins.plugin=function(b){var d="http://plugins.longtailvideo.com";var j=a.utils.loaderstatus.NEW;var k;var h;var l;var c=new a.events.eventdispatcher();a.utils.extend(this,c);function e(){switch(a.utils.getPluginPathType(b)){case a.utils.pluginPathType.ABSOLUTE:return b;case a.utils.pluginPathType.RELATIVE:return a.utils.getAbsolutePath(b,window.location.href);case a.utils.pluginPathType.CDN:var n=a.utils.getPluginName(b);var m=a.utils.getPluginVersion(b);return d+"/"+a.version.split(".")[0]+"/"+n+"/"+n+(m!==""?("-"+m):"")+".js"}}function g(m){l=setTimeout(function(){j=a.utils.loaderstatus.COMPLETE;c.sendEvent(a.events.COMPLETE)},1000)}function f(m){j=a.utils.loaderstatus.ERROR;c.sendEvent(a.events.ERROR)}this.load=function(){if(j==a.utils.loaderstatus.NEW){if(b.lastIndexOf(".swf")>0){k=b;j=a.utils.loaderstatus.COMPLETE;c.sendEvent(a.events.COMPLETE);return}j=a.utils.loaderstatus.LOADING;var m=new a.utils.scriptloader(e());m.addEventListener(a.events.COMPLETE,g);m.addEventListener(a.events.ERROR,f);m.load()}};this.registerPlugin=function(o,n,m){if(l){clearTimeout(l);l=undefined}if(n&&m){k=m;h=n}else{if(typeof n=="string"){k=n}else{if(typeof n=="function"){h=n}else{if(!n&&!m){k=o}}}}j=a.utils.loaderstatus.COMPLETE;c.sendEvent(a.events.COMPLETE)};this.getStatus=function(){return j};this.getPluginName=function(){return a.utils.getPluginName(b)};this.getFlashPath=function(){if(k){switch(a.utils.getPluginPathType(k)){case a.utils.pluginPathType.ABSOLUTE:return k;case a.utils.pluginPathType.RELATIVE:if(b.lastIndexOf(".swf")>0){return a.utils.getAbsolutePath(k,window.location.href)}return a.utils.getAbsolutePath(k,e());case a.utils.pluginPathType.CDN:if(k.indexOf("-")>-1){return k+"h"}return k+"-h"}}return null};this.getJS=function(){return h};this.getPluginmode=function(){if(typeof k!="undefined"&&typeof h!="undefined"){return a.plugins.pluginmodes.HYBRID}else{if(typeof k!="undefined"){return a.plugins.pluginmodes.FLASH}else{if(typeof h!="undefined"){return a.plugins.pluginmodes.JAVASCRIPT}}}};this.getNewInstance=function(n,m,o){return new h(n,m,o)};this.getURL=function(){return b}}})(jwplayer);(function(a){a.plugins.pluginloader=function(h,e){var g={};var k=a.utils.loaderstatus.NEW;var d=false;var b=false;var c=new a.events.eventdispatcher();a.utils.extend(this,c);function f(){if(!b){b=true;k=a.utils.loaderstatus.COMPLETE;c.sendEvent(a.events.COMPLETE)}}function j(){if(!b){var m=0;for(plugin in g){var l=g[plugin].getStatus();if(l==a.utils.loaderstatus.LOADING||l==a.utils.loaderstatus.NEW){m++}}if(m==0){f()}}}this.setupPlugins=function(n,l,s){var m={length:0,plugins:{}};var p={length:0,plugins:{}};for(var o in g){var q=g[o].getPluginName();if(g[o].getFlashPath()){m.plugins[g[o].getFlashPath()]=l.plugins[o];m.plugins[g[o].getFlashPath()].pluginmode=g[o].getPluginmode();m.length++}if(g[o].getJS()){var r=document.createElement("div");r.id=n.id+"_"+q;r.style.position="absolute";r.style.zIndex=p.length+10;p.plugins[q]=g[o].getNewInstance(n,l.plugins[o],r);p.length++;if(typeof p.plugins[q].resize!="undefined"){n.onReady(s(p.plugins[q],r,true));n.onResize(s(p.plugins[q],r))}}}n.plugins=p.plugins;return m};this.load=function(){k=a.utils.loaderstatus.LOADING;d=true;for(var l in e){if(a.utils.exists(l)){g[l]=h.addPlugin(l);g[l].addEventListener(a.events.COMPLETE,j);g[l].addEventListener(a.events.ERROR,j)}}for(l in g){g[l].load()}d=false;j()};this.pluginFailed=function(){f()};this.getStatus=function(){return k}}})(jwplayer);(function(b){var a=[];b.api=function(d){this.container=d;this.id=d.id;var n={};var s={};var q={};var c=[];var h=undefined;var l=false;var j=[];var p=b.utils.getOuterHTML(d);var r={};var k={};this.getBuffer=function(){return this.callInternal("jwGetBuffer")};this.getContainer=function(){return this.container};function e(u,t){return function(z,v,w,x){if(u.renderingMode=="flash"||u.renderingMode=="html5"){var y;if(v){k[z]=v;y="jwplayer('"+u.id+"').callback('"+z+"')"}else{if(!v&&k[z]){delete k[z]}}h.jwDockSetButton(z,y,w,x)}return t}}this.getPlugin=function(t){var v=this;var u={};if(t=="dock"){return b.utils.extend(u,{setButton:e(v,u),show:function(){v.callInternal("jwDockShow");return u},hide:function(){v.callInternal("jwDockHide");return u},onShow:function(w){v.componentListener("dock",b.api.events.JWPLAYER_COMPONENT_SHOW,w);return u},onHide:function(w){v.componentListener("dock",b.api.events.JWPLAYER_COMPONENT_HIDE,w);return u}})}else{if(t=="controlbar"){return b.utils.extend(u,{show:function(){v.callInternal("jwControlbarShow");return u},hide:function(){v.callInternal("jwControlbarHide");return u},onShow:function(w){v.componentListener("controlbar",b.api.events.JWPLAYER_COMPONENT_SHOW,w);return u},onHide:function(w){v.componentListener("controlbar",b.api.events.JWPLAYER_COMPONENT_HIDE,w);return u}})}else{if(t=="display"){return b.utils.extend(u,{show:function(){v.callInternal("jwDisplayShow");return u},hide:function(){v.callInternal("jwDisplayHide");return u},onShow:function(w){v.componentListener("display",b.api.events.JWPLAYER_COMPONENT_SHOW,w);return u},onHide:function(w){v.componentListener("display",b.api.events.JWPLAYER_COMPONENT_HIDE,w);return u}})}else{return this.plugins[t]}}}};this.callback=function(t){if(k[t]){return k[t]()}};this.getDuration=function(){return this.callInternal("jwGetDuration")};this.getFullscreen=function(){return this.callInternal("jwGetFullscreen")};this.getHeight=function(){return this.callInternal("jwGetHeight")};this.getLockState=function(){return this.callInternal("jwGetLockState")};this.getMeta=function(){return this.getItemMeta()};this.getMute=function(){return this.callInternal("jwGetMute")};this.getPlaylist=function(){var u=this.callInternal("jwGetPlaylist");if(this.renderingMode=="flash"){b.utils.deepReplaceKeyName(u,"__dot__",".")}for(var t=0;t<u.length;t++){if(!b.utils.exists(u[t].index)){u[t].index=t}}return u};this.getPlaylistItem=function(t){if(!b.utils.exists(t)){t=this.getCurrentItem()}return this.getPlaylist()[t]};this.getPosition=function(){return this.callInternal("jwGetPosition")};this.getRenderingMode=function(){return this.renderingMode};this.getState=function(){return this.callInternal("jwGetState")};this.getVolume=function(){return this.callInternal("jwGetVolume")};this.getWidth=function(){return this.callInternal("jwGetWidth")};this.setFullscreen=function(t){if(!b.utils.exists(t)){this.callInternal("jwSetFullscreen",!this.callInternal("jwGetFullscreen"))}else{this.callInternal("jwSetFullscreen",t)}return this};this.setMute=function(t){if(!b.utils.exists(t)){this.callInternal("jwSetMute",!this.callInternal("jwGetMute"))}else{this.callInternal("jwSetMute",t)}return this};this.lock=function(){return this};this.unlock=function(){return this};this.load=function(t){this.callInternal("jwLoad",t);return this};this.playlistItem=function(t){this.callInternal("jwPlaylistItem",t);return this};this.playlistPrev=function(){this.callInternal("jwPlaylistPrev");return this};this.playlistNext=function(){this.callInternal("jwPlaylistNext");return this};this.resize=function(u,t){if(this.renderingMode=="html5"){h.jwResize(u,t)}else{this.container.width=u;this.container.height=t}return this};this.play=function(t){if(typeof t=="undefined"){t=this.getState();if(t==b.api.events.state.PLAYING||t==b.api.events.state.BUFFERING){this.callInternal("jwPause")}else{this.callInternal("jwPlay")}}else{this.callInternal("jwPlay",t)}return this};this.pause=function(t){if(typeof t=="undefined"){t=this.getState();if(t==b.api.events.state.PLAYING||t==b.api.events.state.BUFFERING){this.callInternal("jwPause")}else{this.callInternal("jwPlay")}}else{this.callInternal("jwPause",t)}return this};this.stop=function(){this.callInternal("jwStop");return this};this.seek=function(t){this.callInternal("jwSeek",t);return this};this.setVolume=function(t){this.callInternal("jwSetVolume",t);return this};this.onBufferChange=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_BUFFER,t)};this.onBufferFull=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_BUFFER_FULL,t)};this.onError=function(t){return this.eventListener(b.api.events.JWPLAYER_ERROR,t)};this.onFullscreen=function(t){return this.eventListener(b.api.events.JWPLAYER_FULLSCREEN,t)};this.onMeta=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_META,t)};this.onMute=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_MUTE,t)};this.onPlaylist=function(t){return this.eventListener(b.api.events.JWPLAYER_PLAYLIST_LOADED,t)};this.onPlaylistItem=function(t){return this.eventListener(b.api.events.JWPLAYER_PLAYLIST_ITEM,t)};this.onReady=function(t){return this.eventListener(b.api.events.API_READY,t)};this.onResize=function(t){return this.eventListener(b.api.events.JWPLAYER_RESIZE,t)};this.onComplete=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_COMPLETE,t)};this.onSeek=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_SEEK,t)};this.onTime=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_TIME,t)};this.onVolume=function(t){return this.eventListener(b.api.events.JWPLAYER_MEDIA_VOLUME,t)};this.onBuffer=function(t){return this.stateListener(b.api.events.state.BUFFERING,t)};this.onPause=function(t){return this.stateListener(b.api.events.state.PAUSED,t)};this.onPlay=function(t){return this.stateListener(b.api.events.state.PLAYING,t)};this.onIdle=function(t){return this.stateListener(b.api.events.state.IDLE,t)};this.remove=function(){n={};j=[];if(b.utils.getOuterHTML(this.container)!=p){b.api.destroyPlayer(this.id,p)}};this.setup=function(u){if(b.embed){var t=this.id;this.remove();var v=b(t);v.config=u;return new b.embed(v)}return this};this.registerPlugin=function(v,u,t){b.plugins.registerPlugin(v,u,t)};this.setPlayer=function(t,u){h=t;this.renderingMode=u};this.stateListener=function(t,u){if(!s[t]){s[t]=[];this.eventListener(b.api.events.JWPLAYER_PLAYER_STATE,g(t))}s[t].push(u);return this};function g(t){return function(v){var u=v.newstate,x=v.oldstate;if(u==t){var w=s[u];if(w){for(var y=0;y<w.length;y++){if(typeof w[y]=="function"){w[y].call(this,{oldstate:x,newstate:u})}}}}}}this.componentListener=function(t,u,v){if(!q[t]){q[t]={}}if(!q[t][u]){q[t][u]=[];this.eventListener(u,m(t,u))}q[t][u].push(v);return this};function m(t,u){return function(w){if(t==w.component){var v=q[t][u];if(v){for(var x=0;x<v.length;x++){if(typeof v[x]=="function"){v[x].call(this,w)}}}}}}this.addInternalListener=function(t,u){t.jwAddEventListener(u,'function(dat) { jwplayer("'+this.id+'").dispatchEvent("'+u+'", dat); }')};this.eventListener=function(t,u){if(!n[t]){n[t]=[];if(h&&l){this.addInternalListener(h,t)}}n[t].push(u);return this};this.dispatchEvent=function(v){if(n[v]){var u=f(v,arguments[1]);for(var t=0;t<n[v].length;t++){if(typeof n[v][t]=="function"){n[v][t].call(this,u)}}}};function f(v,t){var x=b.utils.extend({},t);if(v==b.api.events.JWPLAYER_FULLSCREEN&&!x.fullscreen){x.fullscreen=x.message=="true"?true:false;delete x.message}else{if(typeof x.data=="object"){x=b.utils.extend(x,x.data);delete x.data}}var u=["position","duration","offset"];for(var w in u){if(x[u[w]]){x[u[w]]=Math.round(x[u[w]]*1000)/1000}}return x}this.callInternal=function(u,t){if(l){if(typeof h!="undefined"&&typeof h[u]=="function"){if(b.utils.exists(t)){return(h[u])(t)}else{return(h[u])()}}return null}else{j.push({method:u,parameters:t})}};this.playerReady=function(v){l=true;if(!h){this.setPlayer(document.getElementById(v.id))}this.container=document.getElementById(this.id);for(var t in n){this.addInternalListener(h,t)}this.eventListener(b.api.events.JWPLAYER_PLAYLIST_ITEM,function(w){r={}});this.eventListener(b.api.events.JWPLAYER_MEDIA_META,function(w){b.utils.extend(r,w.metadata)});this.dispatchEvent(b.api.events.API_READY);while(j.length>0){var u=j.shift();this.callInternal(u.method,u.parameters)}};this.getItemMeta=function(){return r};this.getCurrentItem=function(){return this.callInternal("jwGetPlaylistIndex")};function o(v,x,w){var t=[];if(!x){x=0}if(!w){w=v.length-1}for(var u=x;u<=w;u++){t.push(v[u])}return t}return this};b.api.selectPlayer=function(d){var c;if(!b.utils.exists(d)){d=0}if(d.nodeType){c=d}else{if(typeof d=="string"){c=document.getElementById(d)}}if(c){var e=b.api.playerById(c.id);if(e){return e}else{return b.api.addPlayer(new b.api(c))}}else{if(typeof d=="number"){return b.getPlayers()[d]}}return null};b.api.events={API_READY:"jwplayerAPIReady",JWPLAYER_READY:"jwplayerReady",JWPLAYER_FULLSCREEN:"jwplayerFullscreen",JWPLAYER_RESIZE:"jwplayerResize",JWPLAYER_ERROR:"jwplayerError",JWPLAYER_COMPONENT_SHOW:"jwplayerComponentShow",JWPLAYER_COMPONENT_HIDE:"jwplayerComponentHide",JWPLAYER_MEDIA_BUFFER:"jwplayerMediaBuffer",JWPLAYER_MEDIA_BUFFER_FULL:"jwplayerMediaBufferFull",JWPLAYER_MEDIA_ERROR:"jwplayerMediaError",JWPLAYER_MEDIA_LOADED:"jwplayerMediaLoaded",JWPLAYER_MEDIA_COMPLETE:"jwplayerMediaComplete",JWPLAYER_MEDIA_SEEK:"jwplayerMediaSeek",JWPLAYER_MEDIA_TIME:"jwplayerMediaTime",JWPLAYER_MEDIA_VOLUME:"jwplayerMediaVolume",JWPLAYER_MEDIA_META:"jwplayerMediaMeta",JWPLAYER_MEDIA_MUTE:"jwplayerMediaMute",JWPLAYER_PLAYER_STATE:"jwplayerPlayerState",JWPLAYER_PLAYLIST_LOADED:"jwplayerPlaylistLoaded",JWPLAYER_PLAYLIST_ITEM:"jwplayerPlaylistItem"};b.api.events.state={BUFFERING:"BUFFERING",IDLE:"IDLE",PAUSED:"PAUSED",PLAYING:"PLAYING"};b.api.playerById=function(d){for(var c=0;c<a.length;c++){if(a[c].id==d){return a[c]}}return null};b.api.addPlayer=function(c){for(var d=0;d<a.length;d++){if(a[d]==c){return c}}a.push(c);return c};b.api.destroyPlayer=function(g,d){var f=-1;for(var j=0;j<a.length;j++){if(a[j].id==g){f=j;continue}}if(f>=0){var c=document.getElementById(a[f].id);if(document.getElementById(a[f].id+"_wrapper")){c=document.getElementById(a[f].id+"_wrapper")}if(c){if(d){b.utils.setOuterHTML(c,d)}else{var h=document.createElement("div");var e=c.id;if(c.id.indexOf("_wrapper")==c.id.length-8){newID=c.id.substring(0,c.id.length-8)}h.setAttribute("id",e);c.parentNode.replaceChild(h,c)}}a.splice(f,1)}return null};b.getPlayers=function(){return a.slice(0)}})(jwplayer);var _userPlayerReady=(typeof playerReady=="function")?playerReady:undefined;playerReady=function(b){var a=jwplayer.api.playerById(b.id);if(a){a.playerReady(b)}else{jwplayer.api.selectPlayer(b.id).playerReady(b)}if(_userPlayerReady){_userPlayerReady.call(this,b)}};(function(a){a.embed=function(g){var j={width:400,height:300,components:{controlbar:{position:"over"}}};var f=a.utils.mediaparser.parseMedia(g.container);var e=new a.embed.config(a.utils.extend(j,f,g.config),this);var h=a.plugins.loadPlugins(g.id,e.plugins);function c(m,l){for(var k in l){if(typeof m[k]=="function"){(m[k]).call(m,l[k])}}}function d(){if(h.getStatus()==a.utils.loaderstatus.COMPLETE){for(var m=0;m<e.modes.length;m++){if(e.modes[m].type&&a.embed[e.modes[m].type]){var k=e;if(e.modes[m].config){k=a.utils.extend(a.utils.clone(e),e.modes[m].config)}var l=new a.embed[e.modes[m].type](document.getElementById(g.id),e.modes[m],k,h,g);if(l.supportsConfig()){l.embed();c(g,e.events);return g}}}a.utils.log("No suitable players found");new a.embed.logo(a.utils.extend({hide:true},e.components.logo),"none",g.id)}}h.addEventListener(a.events.COMPLETE,d);h.addEventListener(a.events.ERROR,d);h.load();return g};function b(){if(!document.body){return setTimeout(b,15)}var c=a.utils.selectors.getElementsByTagAndClass("video","jwplayer");for(var d=0;d<c.length;d++){var e=c[d];a(e.id).setup({})}}b()})(jwplayer);(function(e){function h(){return[{type:"flash",src:"/jwplayer/player.swf"},{type:"html5"},{type:"download"}]}var a={players:"modes",autoplay:"autostart"};function b(n){var m=n.toLowerCase();var l=["left","right","top","bottom"];for(var k=0;k<l.length;k++){if(m==l[k]){return true}}return false}function c(l){var k=false;k=(l instanceof Array)||(typeof l=="object"&&!l.position&&!l.size);return k}function j(k){if(typeof k=="string"){if(parseInt(k).toString()==k||k.toLowerCase().indexOf("px")>-1){return parseInt(k)}}return k}var g=["playlist","dock","controlbar","logo","display"];function f(k){var n={};switch(e.utils.typeOf(k.plugins)){case"object":for(var m in k.plugins){n[e.utils.getPluginName(m)]=m}break;case"string":var o=k.plugins.split(",");for(var l=0;l<o.length;l++){n[e.utils.getPluginName(o[l])]=o[l]}break}return n}function d(o,n,m,k){if(e.utils.typeOf(o[n])!="object"){o[n]={}}var l=o[n][m];if(e.utils.typeOf(l)!="object"){o[n][m]=l={}}if(k){if(n=="plugins"){var p=e.utils.getPluginName(m);l[k]=o[p+"."+k];delete o[p+"."+k]}else{l[k]=o[m+"."+k];delete o[m+"."+k]}}}e.embed.deserialize=function(l){var m=f(l);for(var k in m){d(l,"plugins",m[k])}for(var p in l){if(p.indexOf(".")>-1){var o=p.split(".");var n=o[0];var p=o[1];if(e.utils.isInArray(g,n)){d(l,"components",n,p)}else{if(m[n]){d(l,"plugins",m[n],p)}}}}return l};e.embed.config=function(k,u){var t=e.utils.extend({},k);var r;if(c(t.playlist)){r=t.playlist;delete t.playlist}t=e.embed.deserialize(t);t.height=j(t.height);t.width=j(t.width);if(typeof t.plugins=="string"){var l=t.plugins.split(",");if(typeof t.plugins!="object"){t.plugins={}}for(var p=0;p<l.length;p++){var q=e.utils.getPluginName(l[p]);if(typeof t[q]=="object"){t.plugins[l[p]]=t[q];delete t[q]}else{t.plugins[l[p]]={}}}}for(var s=0;s<g.length;s++){var o=g[s];if(e.utils.exists(t[o])){if(typeof t[o]!="object"){if(!t.components[o]){t.components[o]={}}if(o=="logo"){t.components[o].file=t[o]}else{t.components[o].position=t[o]}delete t[o]}else{if(!t.components[o]){t.components[o]={}}e.utils.extend(t.components[o],t[o]);delete t[o]}}if(typeof t[o+"size"]!="undefined"){if(!t.components[o]){t.components[o]={}}t.components[o].size=t[o+"size"];delete t[o+"size"]}}if(typeof t.icons!="undefined"){if(!t.components.display){t.components.display={}}t.components.display.icons=t.icons;delete t.icons}for(var n in a){if(t[n]){if(!t[a[n]]){t[a[n]]=t[n]}delete t[n]}}var m;if(t.flashplayer&&!t.modes){m=h();m[0].src=t.flashplayer;delete t.flashplayer}else{if(t.modes){if(typeof t.modes=="string"){m=h();m[0].src=t.modes}else{if(t.modes instanceof Array){m=t.modes}else{if(typeof t.modes=="object"&&t.modes.type){m=[t.modes]}}}delete t.modes}else{m=h()}}t.modes=m;if(r){t.playlist=r}return t}})(jwplayer);(function(a){a.embed.download=function(c,g,b,d,f){this.embed=function(){var k=a.utils.extend({},b);var q={};var j=b.width?b.width:480;if(typeof j!="number"){j=parseInt(j,10)}var m=b.height?b.height:320;if(typeof m!="number"){m=parseInt(m,10)}var u,o,n;var s={};if(b.playlist&&b.playlist.length){s.file=b.playlist[0].file;o=b.playlist[0].image;s.levels=b.playlist[0].levels}else{s.file=b.file;o=b.image;s.levels=b.levels}if(s.file){u=s.file}else{if(s.levels&&s.levels.length){u=s.levels[0].file}}n=u?"pointer":"auto";var l={display:{style:{cursor:n,width:j,height:m,backgroundColor:"#000",position:"relative",textDecoration:"none",border:"none",display:"block"}},display_icon:{style:{cursor:n,position:"absolute",display:u?"block":"none",top:0,left:0,border:0,margin:0,padding:0,zIndex:3,width:50,height:50,backgroundImage:"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALdJREFUeNrs18ENgjAYhmFouDOCcQJGcARHgE10BDcgTOIosAGwQOuPwaQeuFRi2p/3Sb6EC5L3QCxZBgAAAOCorLW1zMn65TrlkH4NcV7QNcUQt7Gn7KIhxA+qNIR81spOGkL8oFJDyLJRdosqKDDkK+iX5+d7huzwM40xptMQMkjIOeRGo+VkEVvIPfTGIpKASfYIfT9iCHkHrBEzf4gcUQ56aEzuGK/mw0rHpy4AAACAf3kJMACBxjAQNRckhwAAAABJRU5ErkJggg==)"}},display_iconBackground:{style:{cursor:n,position:"absolute",display:u?"block":"none",top:((m-50)/2),left:((j-50)/2),border:0,width:50,height:50,margin:0,padding:0,zIndex:2,backgroundImage:"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEpJREFUeNrszwENADAIA7DhX8ENoBMZ5KR10EryckCJiIiIiIiIiIiIiIiIiIiIiIh8GmkRERERERERERERERERERERERGRHSPAAPlXH1phYpYaAAAAAElFTkSuQmCC)"}},display_image:{style:{width:j,height:m,display:o?"block":"none",position:"absolute",cursor:n,left:0,top:0,margin:0,padding:0,textDecoration:"none",zIndex:1,border:"none"}}};var h=function(v,x,y){var w=document.createElement(v);if(y){w.id=y}else{w.id=c.id+"_jwplayer_"+x}a.utils.css(w,l[x].style);return w};q.display=h("a","display",c.id);if(u){q.display.setAttribute("href",a.utils.getAbsolutePath(u))}q.display_image=h("img","display_image");q.display_image.setAttribute("alt","Click to download...");if(o){q.display_image.setAttribute("src",a.utils.getAbsolutePath(o))}if(true){q.display_icon=h("div","display_icon");q.display_iconBackground=h("div","display_iconBackground");q.display.appendChild(q.display_image);q.display_iconBackground.appendChild(q.display_icon);q.display.appendChild(q.display_iconBackground)}_css=a.utils.css;_hide=function(v){_css(v,{display:"none"})};function r(v){_imageWidth=q.display_image.naturalWidth;_imageHeight=q.display_image.naturalHeight;t()}function t(){a.utils.stretch(a.utils.stretching.UNIFORM,q.display_image,j,m,_imageWidth,_imageHeight)}q.display_image.onerror=function(v){_hide(q.display_image)};q.display_image.onload=r;c.parentNode.replaceChild(q.display,c);var p=(b.plugins&&b.plugins.logo)?b.plugins.logo:{};q.display.appendChild(new a.embed.logo(b.components.logo,"download",c.id));f.container=document.getElementById(f.id);f.setPlayer(q.display,"download")};this.supportsConfig=function(){if(b){var j=a.utils.getFirstPlaylistItemFromConfig(b);if(typeof j.file=="undefined"&&typeof j.levels=="undefined"){return true}else{if(j.file){return e(j.file,j.provider,j.playlistfile)}else{if(j.levels&&j.levels.length){for(var h=0;h<j.levels.length;h++){if(j.levels[h].file&&e(j.levels[h].file,j.provider,j.playlistfile)){return true}}}}}}else{return true}};function e(j,l,h){if(h){return false}var k=["image","sound","youtube","http"];if(l&&(k.toString().indexOf(l)>-1)){return true}if(!l||(l&&l=="video")){var m=a.utils.extension(j);if(m&&a.utils.extensionmap[m]){return true}}return false}}})(jwplayer);(function(a){a.embed.flash=function(f,g,l,e,j){function m(o,n,p){var q=document.createElement("param");q.setAttribute("name",n);q.setAttribute("value",p);o.appendChild(q)}function k(o,p,n){return function(q){if(n){document.getElementById(j.id+"_wrapper").appendChild(p)}var s=document.getElementById(j.id).getPluginConfig("display");o.resize(s.width,s.height);var r={left:s.x,top:s.y};a.utils.css(p,r)}}function d(p){if(!p){return{}}var r={};for(var o in p){var n=p[o];for(var q in n){r[o+"."+q]=n[q]}}return r}function h(q,p){if(q[p]){var s=q[p];for(var o in s){var n=s[o];if(typeof n=="string"){if(!q[o]){q[o]=n}}else{for(var r in n){if(!q[o+"."+r]){q[o+"."+r]=n[r]}}}}delete q[p]}}function b(q){if(!q){return{}}var t={},s=[];for(var n in q){var p=a.utils.getPluginName(n);var o=q[n];s.push(n);for(var r in o){t[p+"."+r]=o[r]}}t.plugins=s.join(",");return t}function c(p){var n=p.netstreambasepath?"":"netstreambasepath="+encodeURIComponent(window.location.href.split("#")[0])+"&";for(var o in p){if(typeof(p[o])=="object"){n+=o+"="+encodeURIComponent("[[JSON]]"+a.utils.strings.jsonToString(p[o]))+"&"}else{n+=o+"="+encodeURIComponent(p[o])+"&"}}return n.substring(0,n.length-1)}this.embed=function(){l.id=j.id;var y;var q=a.utils.extend({},l);var n=q.width;var w=q.height;if(f.id+"_wrapper"==f.parentNode.id){y=document.getElementById(f.id+"_wrapper")}else{y=document.createElement("div");y.id=f.id+"_wrapper";a.utils.wrap(f,y);a.utils.css(y,{position:"relative",width:n,height:w})}var o=e.setupPlugins(j,q,k);if(o.length>0){a.utils.extend(q,b(o.plugins))}else{delete q.plugins}var r=["height","width","modes","events"];for(var u=0;u<r.length;u++){delete q[r[u]]}var p="opaque";if(q.wmode){p=q.wmode}h(q,"components");h(q,"providers");if(typeof q["dock.position"]!="undefined"){if(q["dock.position"].toString().toLowerCase()=="false"){q.dock=q["dock.position"];delete q["dock.position"]}}var x="#000000";var t;if(a.utils.isIE()){var v='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" bgcolor="'+x+'" width="100%" height="100%" id="'+f.id+'" name="'+f.id+'" tabindex=0"">';v+='<param name="movie" value="'+g.src+'">';v+='<param name="allowfullscreen" value="true">';v+='<param name="allowscriptaccess" value="always">';v+='<param name="seamlesstabbing" value="true">';v+='<param name="wmode" value="'+p+'">';v+='<param name="flashvars" value="'+c(q)+'">';v+="</object>";a.utils.setOuterHTML(f,v);t=document.getElementById(f.id)}else{var s=document.createElement("object");s.setAttribute("type","application/x-shockwave-flash");s.setAttribute("data",g.src);s.setAttribute("width","100%");s.setAttribute("height","100%");s.setAttribute("bgcolor","#000000");s.setAttribute("id",f.id);s.setAttribute("name",f.id);s.setAttribute("tabindex",0);m(s,"allowfullscreen","true");m(s,"allowscriptaccess","always");m(s,"seamlesstabbing","true");m(s,"wmode",p);m(s,"flashvars",c(q));f.parentNode.replaceChild(s,f);t=s}j.container=t;j.setPlayer(t,"flash")};this.supportsConfig=function(){if(a.utils.hasFlash()){if(l){var o=a.utils.getFirstPlaylistItemFromConfig(l);if(typeof o.file=="undefined"&&typeof o.levels=="undefined"){return true}else{if(o.file){return flashCanPlay(o.file,o.provider)}else{if(o.levels&&o.levels.length){for(var n=0;n<o.levels.length;n++){if(o.levels[n].file&&flashCanPlay(o.levels[n].file,o.provider)){return true}}}}}}else{return true}}return false};flashCanPlay=function(n,p){var o=["video","http","sound","image"];if(p&&(o.toString().indexOf(p<0))){return true}var q=a.utils.extension(n);if(!q){return true}if(a.utils.exists(a.utils.extensionmap[q])&&!a.utils.exists(a.utils.extensionmap[q].flash)){return false}return true}}})(jwplayer);(function(a){a.embed.html5=function(c,g,b,d,f){function e(j,k,h){return function(l){var m=document.getElementById(c.id+"_displayarea");if(h){m.appendChild(k)}var n=m.style;j.resize(parseInt(n.width.replace("px","")),parseInt(n.height.replace("px","")));k.left=n.left;k.top=n.top}}this.embed=function(){if(a.html5){d.setupPlugins(f,b,e);c.innerHTML="";var j=a.utils.extend({screencolor:"0x000000"},b);var h=["plugins","modes","events"];for(var k=0;k<h.length;k++){delete j[h[k]]}if(j.levels&&!j.sources){j.sources=b.levels}if(j.skin&&j.skin.toLowerCase().indexOf(".zip")>0){j.skin=j.skin.replace(/\.zip/i,".xml")}var l=new (a.html5(c)).setup(j);f.container=document.getElementById(f.id);f.setPlayer(l,"html5")}else{return null}};this.supportsConfig=function(){if(!!a.vid.canPlayType){if(b){var j=a.utils.getFirstPlaylistItemFromConfig(b);if(typeof j.file=="undefined"&&typeof j.levels=="undefined"){return true}else{if(j.file){return html5CanPlay(a.vid,j.file,j.provider,j.playlistfile)}else{if(j.levels&&j.levels.length){for(var h=0;h<j.levels.length;h++){if(j.levels[h].file&&html5CanPlay(a.vid,j.levels[h].file,j.provider,j.playlistfile)){return true}}}}}}else{return true}}return false};html5CanPlay=function(k,j,l,h){if(h){return false}if(l&&l=="youtube"){return true}if(l&&l!="video"&&l!="http"&&l!="sound"){return false}var m=a.utils.extension(j);if(!a.utils.exists(m)||!a.utils.exists(a.utils.extensionmap[m])){return true}if(!a.utils.exists(a.utils.extensionmap[m].html5)){return false}if(a.utils.isLegacyAndroid()&&m.match(/m4v|mp4/)){return true}return browserCanPlay(k,a.utils.extensionmap[m].html5)};browserCanPlay=function(j,h){if(!h){return true}if(j.canPlayType(h)){return true}else{if(h=="audio/mp3"&&navigator.userAgent.match(/safari/i)){return j.canPlayType("audio/mpeg")}else{return false}}}}})(jwplayer);(function(a){a.embed.logo=function(m,l,d){var j={prefix:"http://l.longtailvideo.com/"+l+"/",file:"logo.png",link:"http://www.longtailvideo.com/players/jw-flv-player/",margin:8,out:0.5,over:1,timeout:5,hide:false,position:"bottom-left"};_css=a.utils.css;var b;var h;k();function k(){o();c();f()}function o(){if(j.prefix){var q=a.version.split(/\W/).splice(0,2).join("/");if(j.prefix.indexOf(q)<0){j.prefix+=q+"/"}}h=a.utils.extend({},j)}function p(){var s={border:"none",textDecoration:"none",position:"absolute",cursor:"pointer",zIndex:10};s.display=h.hide?"none":"block";var r=h.position.toLowerCase().split("-");for(var q in r){s[r[q]]=h.margin}return s}function c(){b=document.createElement("img");b.id=d+"_jwplayer_logo";b.style.display="none";b.onload=function(q){_css(b,p());e()};if(!h.file){return}if(h.file.indexOf("http://")===0){b.src=h.file}else{b.src=h.prefix+h.file}}if(!h.file){return}function f(){if(h.link){b.onmouseover=g;b.onmouseout=e;b.onclick=n}else{this.mouseEnabled=false}}function n(q){if(typeof q!="undefined"){q.preventDefault();q.stopPropagation()}if(h.link){window.open(h.link,"_blank")}return}function e(q){if(h.link){b.style.opacity=h.out}return}function g(q){if(h.hide){b.style.opacity=h.over}return}return b}})(jwplayer);(function(a){a.html5=function(b){var c=b;this.setup=function(d){a.utils.extend(this,new a.html5.api(c,d));return this};return this}})(jwplayer);(function(b){var d=b.utils;var c=d.css;b.html5.view=function(r,q,f){var u=r;var n=q;var x=f;var w;var g;var C;var s;var D;var p;var A;function z(){w=document.createElement("div");w.id=n.id;w.className=n.className;_videowrapper=document.createElement("div");_videowrapper.id=w.id+"_video_wrapper";n.id=w.id+"_video";c(w,{position:"relative",height:x.height,width:x.width,padding:0,backgroundColor:E(),zIndex:0});function E(){if(u.skin.getComponentSettings("display")&&u.skin.getComponentSettings("display").backgroundcolor){return u.skin.getComponentSettings("display").backgroundcolor}return parseInt("000000",16)}c(n,{width:x.width,height:x.height,top:0,left:0,zIndex:1,margin:"auto",display:"block"});c(_videowrapper,{overflow:"hidden",position:"absolute",top:0,left:0,bottom:0,right:0});d.wrap(n,w);d.wrap(n,_videowrapper);s=document.createElement("div");s.id=w.id+"_displayarea";w.appendChild(s)}function k(){for(var E=0;E<x.plugins.order.length;E++){var F=x.plugins.order[E];if(d.exists(x.plugins.object[F].getDisplayElement)){x.plugins.object[F].height=d.parseDimension(x.plugins.object[F].getDisplayElement().style.height);x.plugins.object[F].width=d.parseDimension(x.plugins.object[F].getDisplayElement().style.width);x.plugins.config[F].currentPosition=x.plugins.config[F].position}}v()}function m(E){c(s,{display:x.getMedia().hasChrome()?"none":"block"})}function v(F){var H=x.getMedia()?x.getMedia().getDisplayElement():null;if(d.exists(H)){if(A!=H){if(A&&A.parentNode){A.parentNode.replaceChild(H,A)}A=H}for(var E=0;E<x.plugins.order.length;E++){var G=x.plugins.order[E];if(d.exists(x.plugins.object[G].getDisplayElement)){x.plugins.config[G].currentPosition=x.plugins.config[G].position}}}j(x.width,x.height)}this.setup=function(){if(x&&x.getMedia()){n=x.getMedia().getDisplayElement()}z();k();u.jwAddEventListener(b.api.events.JWPLAYER_PLAYER_STATE,m);u.jwAddEventListener(b.api.events.JWPLAYER_MEDIA_LOADED,v);u.jwAddEventListener(b.api.events.JWPLAYER_MEDIA_META,function(){y()});var E;if(d.exists(window.onresize)){E=window.onresize}window.onresize=function(F){if(d.exists(E)){try{E(F)}catch(H){}}if(u.jwGetFullscreen()){var G=document.body.getBoundingClientRect();x.width=Math.abs(G.left)+Math.abs(G.right);x.height=window.innerHeight}j(x.width,x.height)}};function h(E){switch(E.keyCode){case 27:if(u.jwGetFullscreen()){u.jwSetFullscreen(false)}break;case 32:if(u.jwGetState()!=b.api.events.state.IDLE&&u.jwGetState()!=b.api.events.state.PAUSED){u.jwPause()}else{u.jwPlay()}break}}function j(H,E){if(w.style.display=="none"){return}var G=[].concat(x.plugins.order);G.reverse();D=G.length+2;if(!x.fullscreen){x.width=H;x.height=E;g=H;C=E;c(s,{top:0,bottom:0,left:0,right:0,width:H,height:E,position:"relative"});c(w,{height:C,width:g});var F=o(t,G);if(F.length>0){D+=F.length;var J=F.indexOf("playlist"),I=F.indexOf("controlbar");if(J>=0&&I>=0){F[J]=F.splice(I,1,F[J])[0]}o(l,F,true)}}else{if(!(navigator&&navigator.vendor&&navigator.vendor.indexOf("Apple")==0)){o(B,G,true)}}y()}function o(J,G,H){var F=[];for(var E=0;E<G.length;E++){var K=G[E];if(d.exists(x.plugins.object[K].getDisplayElement)){if(x.plugins.config[K].currentPosition!=b.html5.view.positions.NONE){var I=J(K,D--);if(!I){F.push(K)}else{x.plugins.object[K].resize(I.width,I.height);if(H){delete I.width;delete I.height}c(x.plugins.object[K].getDisplayElement(),I)}}else{c(x.plugins.object[K].getDisplayElement(),{display:"none"})}}}return F}function t(F,G){if(d.exists(x.plugins.object[F].getDisplayElement)){if(x.plugins.config[F].position&&a(x.plugins.config[F].position)){if(!d.exists(x.plugins.object[F].getDisplayElement().parentNode)){w.appendChild(x.plugins.object[F].getDisplayElement())}var E=e(F);E.zIndex=G;return E}}return false}function l(G,H){if(!d.exists(x.plugins.object[G].getDisplayElement().parentNode)){s.appendChild(x.plugins.object[G].getDisplayElement())}var E=x.width,F=x.height;if(typeof x.width=="string"&&x.width.lastIndexOf("%")>-1){percentage=parseFloat(x.width.substring(0,x.width.lastIndexOf("%")))/100;E=Math.round(window.innerWidth*percentage)}if(typeof x.height=="string"&&x.height.lastIndexOf("%")>-1){percentage=parseFloat(x.height.substring(0,x.height.lastIndexOf("%")))/100;F=Math.round(window.innerHeight*percentage)}return{position:"absolute",width:(E-d.parseDimension(s.style.left)-d.parseDimension(s.style.right)),height:(F-d.parseDimension(s.style.top)-d.parseDimension(s.style.bottom)),zIndex:H}}function B(E,F){return{position:"fixed",width:x.width,height:x.height,zIndex:F}}function y(){if(!d.exists(x.getMedia())){return}s.style.position="absolute";var H=x.getMedia().getDisplayElement();if(H&&H.tagName.toLowerCase()=="video"){H.style.position="absolute";var E,I;if(s.style.width.toString().lastIndexOf("%")>-1||s.style.width.toString().lastIndexOf("%")>-1){var F=s.getBoundingClientRect();E=Math.abs(F.left)+Math.abs(F.right);I=Math.abs(F.top)+Math.abs(F.bottom)}else{E=d.parseDimension(s.style.width);I=d.parseDimension(s.style.height)}if(H.parentNode){H.parentNode.style.left=s.style.left;H.parentNode.style.top=s.style.top}d.stretch(u.jwGetStretching(),H,E,I,H.videoWidth?H.videoWidth:400,H.videoHeight?H.videoHeight:300)}else{var G=x.plugins.object.display.getDisplayElement();if(G){x.getMedia().resize(d.parseDimension(G.style.width),d.parseDimension(G.style.height))}else{x.getMedia().resize(d.parseDimension(s.style.width),d.parseDimension(s.style.height))}}}function e(F){var G={position:"absolute",margin:0,padding:0,top:null};var E=x.plugins.config[F].currentPosition.toLowerCase();switch(E.toUpperCase()){case b.html5.view.positions.TOP:G.top=d.parseDimension(s.style.top);G.left=d.parseDimension(s.style.left);G.width=g-d.parseDimension(s.style.left)-d.parseDimension(s.style.right);G.height=x.plugins.object[F].height;s.style[E]=d.parseDimension(s.style[E])+x.plugins.object[F].height+"px";s.style.height=d.parseDimension(s.style.height)-G.height+"px";break;case b.html5.view.positions.RIGHT:G.top=d.parseDimension(s.style.top);G.right=d.parseDimension(s.style.right);G.width=x.plugins.object[F].width;G.height=C-d.parseDimension(s.style.top)-d.parseDimension(s.style.bottom);s.style[E]=d.parseDimension(s.style[E])+x.plugins.object[F].width+"px";s.style.width=d.parseDimension(s.style.width)-G.width+"px";break;case b.html5.view.positions.BOTTOM:G.bottom=d.parseDimension(s.style.bottom);G.left=d.parseDimension(s.style.left);G.width=g-d.parseDimension(s.style.left)-d.parseDimension(s.style.right);G.height=x.plugins.object[F].height;s.style[E]=d.parseDimension(s.style[E])+x.plugins.object[F].height+"px";s.style.height=d.parseDimension(s.style.height)-G.height+"px";break;case b.html5.view.positions.LEFT:G.top=d.parseDimension(s.style.top);G.left=d.parseDimension(s.style.left);G.width=x.plugins.object[F].width;G.height=C-d.parseDimension(s.style.top)-d.parseDimension(s.style.bottom);s.style[E]=d.parseDimension(s.style[E])+x.plugins.object[F].width+"px";s.style.width=d.parseDimension(s.style.width)-G.width+"px";break;default:break}return G}this.resize=j;this.fullscreen=function(H){if(navigator&&navigator.vendor&&navigator.vendor.indexOf("Apple")===0){if(x.getMedia().getDisplayElement().webkitSupportsFullscreen){if(H){try{x.getMedia().getDisplayElement().webkitEnterFullscreen()}catch(G){}}else{try{x.getMedia().getDisplayElement().webkitExitFullscreen()}catch(G){}}}}else{if(H){document.onkeydown=h;clearInterval(p);var F=document.body.getBoundingClientRect();x.width=Math.abs(F.left)+Math.abs(F.right);x.height=window.innerHeight;var E={position:"fixed",width:"100%",height:"100%",top:0,left:0,zIndex:2147483000};c(w,E);E.zIndex=1;if(x.getMedia()&&x.getMedia().getDisplayElement()){c(x.getMedia().getDisplayElement(),E)}E.zIndex=2;c(s,E)}else{document.onkeydown="";x.width=g;x.height=C;c(w,{position:"relative",height:x.height,width:x.width,zIndex:0})}j(x.width,x.height)}}};function a(e){return([b.html5.view.positions.TOP,b.html5.view.positions.RIGHT,b.html5.view.positions.BOTTOM,b.html5.view.positions.LEFT].toString().indexOf(e.toUpperCase())>-1)}b.html5.view.positions={TOP:"TOP",RIGHT:"RIGHT",BOTTOM:"BOTTOM",LEFT:"LEFT",OVER:"OVER",NONE:"NONE"}})(jwplayer);(function(a){var b={backgroundcolor:"",margin:10,font:"Arial,sans-serif",fontsize:10,fontcolor:parseInt("000000",16),fontstyle:"normal",fontweight:"bold",buttoncolor:parseInt("ffffff",16),position:a.html5.view.positions.BOTTOM,idlehide:false,layout:{left:{position:"left",elements:[{name:"play",type:"button"},{name:"divider",type:"divider"},{name:"prev",type:"button"},{name:"divider",type:"divider"},{name:"next",type:"button"},{name:"divider",type:"divider"},{name:"elapsed",type:"text"}]},center:{position:"center",elements:[{name:"time",type:"slider"}]},right:{position:"right",elements:[{name:"duration",type:"text"},{name:"blank",type:"button"},{name:"divider",type:"divider"},{name:"mute",type:"button"},{name:"volume",type:"slider"},{name:"divider",type:"divider"},{name:"fullscreen",type:"button"}]}}};_utils=a.utils;_css=_utils.css;_hide=function(c){_css(c,{display:"none"})};_show=function(c){_css(c,{display:"block"})};a.html5.controlbar=function(l,V){var k=l;var D=_utils.extend({},b,k.skin.getComponentSettings("controlbar"),V);if(D.position==a.html5.view.positions.NONE||typeof a.html5.view.positions[D.position]=="undefined"){return}if(_utils.mapLength(k.skin.getComponentLayout("controlbar"))>0){D.layout=k.skin.getComponentLayout("controlbar")}var ac;var P;var ab;var E;var v="none";var g;var j;var ad;var f;var e;var y;var Q={};var p=false;var c={};var Y;var h=false;var o;var d;var S=false;var G=false;var W=new a.html5.eventdispatcher();_utils.extend(this,W);function J(){if(!Y){Y=k.skin.getSkinElement("controlbar","background");if(!Y){Y={width:0,height:0,src:null}}}return Y}function N(){ab=0;E=0;P=0;if(!p){var ak={height:J().height,backgroundColor:D.backgroundcolor};ac=document.createElement("div");ac.id=k.id+"_jwplayer_controlbar";_css(ac,ak)}var aj=(k.skin.getSkinElement("controlbar","capLeft"));var ai=(k.skin.getSkinElement("controlbar","capRight"));if(aj){x("capLeft","left",false,ac)}var al={position:"absolute",height:J().height,left:(aj?aj.width:0),zIndex:0};Z("background",ac,al,"img");if(J().src){Q.background.src=J().src}al.zIndex=1;Z("elements",ac,al);if(ai){x("capRight","right",false,ac)}}this.getDisplayElement=function(){return ac};this.resize=function(ak,ai){_utils.cancelAnimation(ac);document.getElementById(k.id).onmousemove=A;e=ak;y=ai;if(G!=k.jwGetFullscreen()){G=k.jwGetFullscreen();d=undefined}var aj=w();A();I({id:k.id,duration:ad,position:j});u({id:k.id,bufferPercent:f});return aj};this.show=function(){if(h){h=false;_show(ac);T()}};this.hide=function(){if(!h){h=true;_hide(ac);aa()}};function q(){var aj=["timeSlider","volumeSlider","timeSliderRail","volumeSliderRail"];for(var ak in aj){var ai=aj[ak];if(typeof Q[ai]!="undefined"){c[ai]=Q[ai].getBoundingClientRect()}}}function A(ai){if(h){return}if(D.position==a.html5.view.positions.OVER||k.jwGetFullscreen()){clearTimeout(o);switch(k.jwGetState()){case a.api.events.state.PAUSED:case a.api.events.state.IDLE:if(!D.idlehide||_utils.exists(ai)){U()}if(D.idlehide){o=setTimeout(function(){z()},2000)}break;default:if(ai){U()}o=setTimeout(function(){z()},2000);break}}}function z(ai){aa();_utils.cancelAnimation(ac);_utils.fadeTo(ac,0,0.1,1,0)}function U(){T();_utils.cancelAnimation(ac);_utils.fadeTo(ac,1,0,1,0)}function H(ai){return function(){if(S&&d!=ai){d=ai;W.sendEvent(ai,{component:"controlbar",boundingRect:O()})}}}var T=H(a.api.events.JWPLAYER_COMPONENT_SHOW);var aa=H(a.api.events.JWPLAYER_COMPONENT_HIDE);function O(){if(D.position==a.html5.view.positions.OVER||k.jwGetFullscreen()){return _utils.getDimensions(ac)}else{return{x:0,y:0,width:0,height:0}}}function Z(am,al,ak,ai){var aj;if(!p){if(!ai){ai="div"}aj=document.createElement(ai);Q[am]=aj;aj.id=ac.id+"_"+am;al.appendChild(aj)}else{aj=document.getElementById(ac.id+"_"+am)}if(_utils.exists(ak)){_css(aj,ak)}return aj}function M(){ah(D.layout.left);ah(D.layout.right,-1);ah(D.layout.center)}function ah(al,ai){var am=al.position=="right"?"right":"left";var ak=_utils.extend([],al.elements);if(_utils.exists(ai)){ak.reverse()}for(var aj=0;aj<ak.length;aj++){C(ak[aj],am)}}function K(){return P++}function C(am,ao){var al,aj,ak,ai,aq;if(am.type=="divider"){x("divider"+K(),ao,true,undefined,undefined,am.width,am.element);return}switch(am.name){case"play":x("playButton",ao,false);x("pauseButton",ao,true);R("playButton","jwPlay");R("pauseButton","jwPause");break;case"prev":x("prevButton",ao,true);R("prevButton","jwPlaylistPrev");break;case"stop":x("stopButton",ao,true);R("stopButton","jwStop");break;case"next":x("nextButton",ao,true);R("nextButton","jwPlaylistNext");break;case"elapsed":x("elapsedText",ao,true);break;case"time":aj=!_utils.exists(k.skin.getSkinElement("controlbar","timeSliderCapLeft"))?0:k.skin.getSkinElement("controlbar","timeSliderCapLeft").width;ak=!_utils.exists(k.skin.getSkinElement("controlbar","timeSliderCapRight"))?0:k.skin.getSkinElement("controlbar","timeSliderCapRight").width;al=ao=="left"?aj:ak;ai=k.skin.getSkinElement("controlbar","timeSliderRail").width+aj+ak;aq={height:J().height,position:"absolute",top:0,width:ai};aq[ao]=ao=="left"?ab:E;var an=Z("timeSlider",Q.elements,aq);x("timeSliderCapLeft",ao,true,an,ao=="left"?0:al);x("timeSliderRail",ao,false,an,al);x("timeSliderBuffer",ao,false,an,al);x("timeSliderProgress",ao,false,an,al);x("timeSliderThumb",ao,false,an,al);x("timeSliderCapRight",ao,true,an,ao=="right"?0:al);X("time");break;case"fullscreen":x("fullscreenButton",ao,false);x("normalscreenButton",ao,true);R("fullscreenButton","jwSetFullscreen",true);R("normalscreenButton","jwSetFullscreen",false);break;case"volume":aj=!_utils.exists(k.skin.getSkinElement("controlbar","volumeSliderCapLeft"))?0:k.skin.getSkinElement("controlbar","volumeSliderCapLeft").width;ak=!_utils.exists(k.skin.getSkinElement("controlbar","volumeSliderCapRight"))?0:k.skin.getSkinElement("controlbar","volumeSliderCapRight").width;al=ao=="left"?aj:ak;ai=k.skin.getSkinElement("controlbar","volumeSliderRail").width+aj+ak;aq={height:J().height,position:"absolute",top:0,width:ai};aq[ao]=ao=="left"?ab:E;var ap=Z("volumeSlider",Q.elements,aq);x("volumeSliderCapLeft",ao,true,ap,ao=="left"?0:al);x("volumeSliderRail",ao,true,ap,al);x("volumeSliderProgress",ao,false,ap,al);x("volumeSliderCapRight",ao,true,ap,ao=="right"?0:al);X("volume");break;case"mute":x("muteButton",ao,false);x("unmuteButton",ao,true);R("muteButton","jwSetMute",true);R("unmuteButton","jwSetMute",false);break;case"duration":x("durationText",ao,true);break}}function x(al,ao,aj,ar,am,ai,ak){if(_utils.exists(k.skin.getSkinElement("controlbar",al))||al.indexOf("Text")>0||al.indexOf("divider")===0){var an={height:J().height,position:"absolute",display:"block",top:0};if((al.indexOf("next")===0||al.indexOf("prev")===0)&&k.jwGetPlaylist().length<2){aj=false;an.display="none"}var at;if(al.indexOf("Text")>0){al.innerhtml="00:00";an.font=D.fontsize+"px/"+(J().height+1)+"px "+D.font;an.color=D.fontcolor;an.textAlign="center";an.fontWeight=D.fontweight;an.fontStyle=D.fontstyle;an.cursor="default";at=14+3*D.fontsize}else{if(al.indexOf("divider")===0){if(ai){if(!isNaN(parseInt(ai))){at=parseInt(ai)}}else{if(ak){var ap=k.skin.getSkinElement("controlbar",ak);if(ap){an.background="url("+ap.src+") repeat-x center left";at=ap.width}}else{an.background="url("+k.skin.getSkinElement("controlbar","divider").src+") repeat-x center left";at=k.skin.getSkinElement("controlbar","divider").width}}}else{an.background="url("+k.skin.getSkinElement("controlbar",al).src+") repeat-x center left";at=k.skin.getSkinElement("controlbar",al).width}}if(ao=="left"){an.left=isNaN(am)?ab:am;if(aj){ab+=at}}else{if(ao=="right"){an.right=isNaN(am)?E:am;if(aj){E+=at}}}if(_utils.typeOf(ar)=="undefined"){ar=Q.elements}an.width=at;if(p){_css(Q[al],an)}else{var aq=Z(al,ar,an);if(_utils.exists(k.skin.getSkinElement("controlbar",al+"Over"))){aq.onmouseover=function(au){aq.style.backgroundImage=["url(",k.skin.getSkinElement("controlbar",al+"Over").src,")"].join("")};aq.onmouseout=function(au){aq.style.backgroundImage=["url(",k.skin.getSkinElement("controlbar",al).src,")"].join("")}}}}}function F(){k.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,B);k.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_ITEM,s);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_BUFFER,u);k.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,r);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_TIME,I);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_MUTE,ag);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_VOLUME,m);k.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_COMPLETE,L)}function B(){N();M();w();ae()}function s(ai){ad=k.jwGetPlaylist()[ai.index].duration;I({id:k.id,duration:ad,position:0});u({id:k.id,bufferProgress:0})}function ae(){I({id:k.id,duration:k.jwGetDuration(),position:0});u({id:k.id,bufferProgress:0});ag({id:k.id,mute:k.jwGetMute()});r({id:k.id,newstate:a.api.events.state.IDLE});m({id:k.id,volume:k.jwGetVolume()})}function R(ak,al,aj){if(p){return}if(_utils.exists(k.skin.getSkinElement("controlbar",ak))){var ai=Q[ak];if(_utils.exists(ai)){_css(ai,{cursor:"pointer"});if(al=="fullscreen"){ai.onmouseup=function(am){am.stopPropagation();k.jwSetFullscreen(!k.jwGetFullscreen())}}else{ai.onmouseup=function(am){am.stopPropagation();if(_utils.exists(aj)){k[al](aj)}else{k[al]()}}}}}}function X(ai){if(p){return}var aj=Q[ai+"Slider"];_css(Q.elements,{cursor:"pointer"});_css(aj,{cursor:"pointer"});aj.onmousedown=function(ak){v=ai};aj.onmouseup=function(ak){ak.stopPropagation();af(ak.pageX)};aj.onmousemove=function(ak){if(v=="time"){g=true;var al=ak.pageX-c[ai+"Slider"].left-window.pageXOffset;_css(Q.timeSliderThumb,{left:al})}}}function af(aj){g=false;var ai;if(v=="time"){ai=aj-c.timeSliderRail.left+window.pageXOffset;var al=ai/c.timeSliderRail.width*ad;if(al<0){al=0}else{if(al>ad){al=ad-3}}if(k.jwGetState()==a.api.events.state.PAUSED||k.jwGetState()==a.api.events.state.IDLE){k.jwPlay()}k.jwSeek(al)}else{if(v=="volume"){ai=aj-c.volumeSliderRail.left-window.pageXOffset;var ak=Math.round(ai/c.volumeSliderRail.width*100);if(ak<0){ak=0}else{if(ak>100){ak=100}}if(k.jwGetMute()){k.jwSetMute(false)}k.jwSetVolume(ak)}}v="none"}function u(aj){if(_utils.exists(aj.bufferPercent)){f=aj.bufferPercent}if(c.timeSliderRail){var ak=c.timeSliderRail.width;var ai=isNaN(Math.round(ak*f/100))?0:Math.round(ak*f/100);_css(Q.timeSliderBuffer,{width:ai})}}function ag(ai){if(ai.mute){_hide(Q.muteButton);_show(Q.unmuteButton);_hide(Q.volumeSliderProgress)}else{_show(Q.muteButton);_hide(Q.unmuteButton);_show(Q.volumeSliderProgress)}}function r(ai){if(ai.newstate==a.api.events.state.BUFFERING||ai.newstate==a.api.events.state.PLAYING){_show(Q.pauseButton);_hide(Q.playButton)}else{_hide(Q.pauseButton);_show(Q.playButton)}A();if(ai.newstate==a.api.events.state.IDLE){_hide(Q.timeSliderBuffer);_hide(Q.timeSliderProgress);_hide(Q.timeSliderThumb);I({id:k.id,duration:k.jwGetDuration(),position:0})}else{_show(Q.timeSliderBuffer);if(ai.newstate!=a.api.events.state.BUFFERING){_show(Q.timeSliderProgress);_show(Q.timeSliderThumb)}}}function L(ai){u({bufferPercent:0});I(_utils.extend(ai,{position:0,duration:ad}))}function I(al){if(_utils.exists(al.position)){j=al.position}if(_utils.exists(al.duration)){ad=al.duration}var aj=(j===ad===0)?0:j/ad;var am=c.timeSliderRail;if(am){var ai=isNaN(Math.round(am.width*aj))?0:Math.round(am.width*aj);var ak=ai;if(Q.timeSliderProgress){Q.timeSliderProgress.style.width=ai+"px";if(!g){if(Q.timeSliderThumb){Q.timeSliderThumb.style.left=ak+"px"}}}}if(Q.durationText){Q.durationText.innerHTML=_utils.timeFormat(ad)}if(Q.elapsedText){Q.elapsedText.innerHTML=_utils.timeFormat(j)}}function n(){var am,aj;var ak=document.getElementById(ac.id+"_elements");if(!ak){return}var al=ak.childNodes;for(var ai in ak.childNodes){if(isNaN(parseInt(ai,10))){continue}if(al[ai].id.indexOf(ac.id+"_divider")===0&&aj&&aj.id.indexOf(ac.id+"_divider")===0&&al[ai].style.backgroundImage==aj.style.backgroundImage){al[ai].style.display="none"}else{if(al[ai].id.indexOf(ac.id+"_divider")===0&&am&&am.style.display!="none"){al[ai].style.display="block"}}if(al[ai].style.display!="none"){aj=al[ai]}am=al[ai]}}function w(){n();if(k.jwGetFullscreen()){_show(Q.normalscreenButton);_hide(Q.fullscreenButton)}else{_hide(Q.normalscreenButton);_show(Q.fullscreenButton)}var aj={width:e};var ai={};if(D.position==a.html5.view.positions.OVER||k.jwGetFullscreen()){aj.left=D.margin;aj.width-=2*D.margin;aj.top=y-J().height-D.margin;aj.height=J().height}var al=k.skin.getSkinElement("controlbar","capLeft");var ak=k.skin.getSkinElement("controlbar","capRight");ai.left=al?al.width:0;ai.width=aj.width-ai.left-(ak?ak.width:0);var am=!_utils.exists(k.skin.getSkinElement("controlbar","timeSliderCapLeft"))?0:k.skin.getSkinElement("controlbar","timeSliderCapLeft").width;_css(Q.timeSliderRail,{width:(ai.width-ab-E),left:am});if(_utils.exists(Q.timeSliderCapRight)){_css(Q.timeSliderCapRight,{left:am+(ai.width-ab-E)})}_css(ac,aj);_css(Q.elements,ai);_css(Q.background,ai);q();return aj}function m(am){if(_utils.exists(Q.volumeSliderRail)){var ak=isNaN(am.volume/100)?1:am.volume/100;var al=_utils.parseDimension(Q.volumeSliderRail.style.width);var ai=isNaN(Math.round(al*ak))?0:Math.round(al*ak);var an=_utils.parseDimension(Q.volumeSliderRail.style.right);var aj=(!_utils.exists(k.skin.getSkinElement("controlbar","volumeSliderCapLeft")))?0:k.skin.getSkinElement("controlbar","volumeSliderCapLeft").width;_css(Q.volumeSliderProgress,{width:ai,left:aj});if(_utils.exists(Q.volumeSliderCapLeft)){_css(Q.volumeSliderCapLeft,{left:0})}}}function t(){N();M();q();p=true;F();D.idlehide=(D.idlehide.toString().toLowerCase()=="true");if(D.position==a.html5.view.positions.OVER&&D.idlehide){ac.style.opacity=0;S=true}else{setTimeout((function(){S=true;T()}),1)}ae()}t();return this}})(jwplayer);(function(b){var a=["width","height","state","playlist","item","position","buffer","duration","volume","mute","fullscreen"];var c=b.utils;b.html5.controller=function(z,w,h,v){var C=z;var G=h;var g=v;var o=w;var J=true;var e=-1;var A=c.exists(G.config.debug)&&(G.config.debug.toString().toLowerCase()=="console");var m=new b.html5.eventdispatcher(o.id,A);c.extend(this,m);var E=[];var d=false;function r(M){if(d){m.sendEvent(M.type,M)}else{E.push(M)}}function K(M){if(!d){m.sendEvent(b.api.events.JWPLAYER_READY,M);if(b.utils.exists(window.playerReady)){playerReady(M)}if(b.utils.exists(window[h.config.playerReady])){window[h.config.playerReady](M)}while(E.length>0){var O=E.shift();m.sendEvent(O.type,O)}if(h.config.autostart&&!b.utils.isIOS()){t(G.item)}while(p.length>0){var N=p.shift();x(N.method,N.arguments)}d=true}}G.addGlobalListener(r);G.addEventListener(b.api.events.JWPLAYER_MEDIA_BUFFER_FULL,function(){G.getMedia().play()});G.addEventListener(b.api.events.JWPLAYER_MEDIA_TIME,function(M){if(M.position>=G.playlist[G.item].start&&e>=0){G.playlist[G.item].start=e;e=-1}});G.addEventListener(b.api.events.JWPLAYER_MEDIA_COMPLETE,function(M){setTimeout(s,25)});function u(){try{f(G.item);if(G.playlist[G.item].levels[0].file.length>0){if(J||G.state==b.api.events.state.IDLE){G.getMedia().load(G.playlist[G.item]);J=false}else{if(G.state==b.api.events.state.PAUSED){G.getMedia().play()}}}return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function I(){try{if(G.playlist[G.item].levels[0].file.length>0){switch(G.state){case b.api.events.state.PLAYING:case b.api.events.state.BUFFERING:G.getMedia().pause();break}}return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function D(M){try{if(G.playlist[G.item].levels[0].file.length>0){if(typeof M!="number"){M=parseFloat(M)}switch(G.state){case b.api.events.state.IDLE:if(e<0){e=G.playlist[G.item].start;G.playlist[G.item].start=M}u();break;case b.api.events.state.PLAYING:case b.api.events.state.PAUSED:case b.api.events.state.BUFFERING:G.seek(M);break}}return true}catch(N){m.sendEvent(b.api.events.JWPLAYER_ERROR,N)}return false}function n(M){if(!c.exists(M)){M=true}try{G.getMedia().stop(M);return true}catch(N){m.sendEvent(b.api.events.JWPLAYER_ERROR,N)}return false}function k(){try{if(G.playlist[G.item].levels[0].file.length>0){if(G.config.shuffle){f(y())}else{if(G.item+1==G.playlist.length){f(0)}else{f(G.item+1)}}}if(G.state!=b.api.events.state.IDLE){var N=G.state;G.state=b.api.events.state.IDLE;m.sendEvent(b.api.events.JWPLAYER_PLAYER_STATE,{oldstate:N,newstate:b.api.events.state.IDLE})}u();return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function j(){try{if(G.playlist[G.item].levels[0].file.length>0){if(G.config.shuffle){f(y())}else{if(G.item===0){f(G.playlist.length-1)}else{f(G.item-1)}}}if(G.state!=b.api.events.state.IDLE){var N=G.state;G.state=b.api.events.state.IDLE;m.sendEvent(b.api.events.JWPLAYER_PLAYER_STATE,{oldstate:N,newstate:b.api.events.state.IDLE})}u();return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function y(){var M=null;if(G.playlist.length>1){while(!c.exists(M)){M=Math.floor(Math.random()*G.playlist.length);if(M==G.item){M=null}}}else{M=0}return M}function t(N){if(!G.playlist||!G.playlist[N]){return false}try{if(G.playlist[N].levels[0].file.length>0){var O=G.state;if(O!==b.api.events.state.IDLE){if(G.playlist[G.item].provider==G.playlist[N].provider){n(false)}else{n()}}f(N);u()}return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function f(M){if(!G.playlist[M]){return}G.setActiveMediaProvider(G.playlist[M]);if(G.item!=M){G.item=M;J=true;m.sendEvent(b.api.events.JWPLAYER_PLAYLIST_ITEM,{index:M})}}function H(N){try{f(G.item);var O=G.getMedia();switch(typeof(N)){case"number":O.volume(N);break;case"string":O.volume(parseInt(N,10));break}return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function q(N){try{f(G.item);var O=G.getMedia();if(typeof N=="undefined"){O.mute(!G.mute)}else{if(N.toString().toLowerCase()=="true"){O.mute(true)}else{O.mute(false)}}return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function l(N,M){try{G.width=N;G.height=M;g.resize(N,M);m.sendEvent(b.api.events.JWPLAYER_RESIZE,{width:G.width,height:G.height});return true}catch(O){m.sendEvent(b.api.events.JWPLAYER_ERROR,O)}return false}function B(N){try{if(typeof N=="undefined"){G.fullscreen=!G.fullscreen;g.fullscreen(!G.fullscreen)}else{if(N.toString().toLowerCase()=="true"){G.fullscreen=true;g.fullscreen(true)}else{G.fullscreen=false;g.fullscreen(false)}}m.sendEvent(b.api.events.JWPLAYER_RESIZE,{width:G.width,height:G.height});m.sendEvent(b.api.events.JWPLAYER_FULLSCREEN,{fullscreen:N});return true}catch(M){m.sendEvent(b.api.events.JWPLAYER_ERROR,M)}return false}function L(M){try{n();G.loadPlaylist(M);f(G.item);return true}catch(N){m.sendEvent(b.api.events.JWPLAYER_ERROR,N)}return false}b.html5.controller.repeatoptions={LIST:"LIST",ALWAYS:"ALWAYS",SINGLE:"SINGLE",NONE:"NONE"};function s(){switch(G.config.repeat.toUpperCase()){case b.html5.controller.repeatoptions.SINGLE:u();break;case b.html5.controller.repeatoptions.ALWAYS:if(G.item==G.playlist.length-1&&!G.config.shuffle){t(0)}else{k()}break;case b.html5.controller.repeatoptions.LIST:if(G.item==G.playlist.length-1&&!G.config.shuffle){n();f(0)}else{k()}break;default:n();break}}var p=[];function F(M){return function(){if(d){x(M,arguments)}else{p.push({method:M,arguments:arguments})}}}function x(O,N){var M=[];for(i=0;i<N.length;i++){M.push(N[i])}O.apply(this,M)}this.play=F(u);this.pause=F(I);this.seek=F(D);this.stop=F(n);this.next=F(k);this.prev=F(j);this.item=F(t);this.setVolume=F(H);this.setMute=F(q);this.resize=F(l);this.setFullscreen=F(B);this.load=F(L);this.playerReady=K}})(jwplayer);(function(a){a.html5.defaultSkin=function(){this.text='<?xml version="1.0" ?><skin author="LongTail Video" name="Five" version="1.0"><settings><setting name="backcolor" value="0xFFFFFF"/><setting name="frontcolor" value="0x000000"/><setting name="lightcolor" value="0x000000"/><setting name="screencolor" value="0x000000"/></settings><components><component name="controlbar"><settings><setting name="margin" value="20"/><setting name="fontsize" value="11"/></settings><elements><element name="background" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFJJREFUeNrslLENwAAIwxLU/09j5AiOgD5hVQzNAVY8JK4qEfHMIKBnd2+BQlBINaiRtL/aV2rdzYBsM6CIONbI1NZENTr3RwdB2PlnJgJ6BRgA4hwu5Qg5iswAAAAASUVORK5CYII="/><element name="capLeft" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAYCAIAAAC0rgCNAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD5JREFUeNosi8ENACAMAgnuv14H0Z8asI19XEjhOiKCMmibVgJTUt7V6fe9KXOtSQCfctJHu2q3/ot79hNgANc2OTz9uTCCAAAAAElFTkSuQmCC"/><element name="capRight" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAYCAIAAAC0rgCNAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD5JREFUeNosi8ENACAMAgnuv14H0Z8asI19XEjhOiKCMmibVgJTUt7V6fe9KXOtSQCfctJHu2q3/ot79hNgANc2OTz9uTCCAAAAAElFTkSuQmCC"/><element name="divider" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAYCAIAAAC0rgCNAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD5JREFUeNosi8ENACAMAgnuv14H0Z8asI19XEjhOiKCMmibVgJTUt7V6fe9KXOtSQCfctJHu2q3/ot79hNgANc2OTz9uTCCAAAAAElFTkSuQmCC"/><element name="playButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAYCAYAAAAVibZIAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEhJREFUeNpiYqABYBo1dNRQ+hr6H4jvA3E8NS39j4SpZvh/LJig4YxEGEqy3kET+w+AOGFQRhTJhrEQkGcczfujhg4CQwECDADpTRWU/B3wHQAAAABJRU5ErkJggg=="/><element name="pauseButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAYCAYAAAAVibZIAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAChJREFUeNpiYBgFo2DwA0YC8v/R1P4nRu+ooaOGUtnQUTAKhgIACDAAFCwQCfAJ4gwAAAAASUVORK5CYII="/><element name="prevButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAYCAYAAAAVibZIAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEtJREFUeNpiYBgFo2Dog/9QDAPyQHweTYwiQ/2B+D0Wi8g2tB+JTdBQRiIMJVkvEy0iglhDF9Aq9uOpHVEwoE+NJDUKRsFgAAABBgDe2hqZcNNL0AAAAABJRU5ErkJggg=="/><element name="nextButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAYCAYAAAAVibZIAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAElJREFUeNpiYBgFo2Dog/9AfB6I5dHE/lNqKAi/B2J/ahsKw/3EGMpIhKEk66WJoaR6fz61IyqemhEFSlL61ExSo2AUDAYAEGAAiG4hj+5t7M8AAAAASUVORK5CYII="/><element name="timeSliderRail" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADxJREFUeNpiYBgFo2AU0Bwwzluw+D8tLWARFhKiqQ9YuLg4aWsBGxs7bS1gZ6e5BWyjSX0UjIKhDgACDABlYQOGh5pYywAAAABJRU5ErkJggg=="/><element name="timeSliderBuffer" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD1JREFUeNpiYBgFo2AU0Bww1jc0/aelBSz8/Pw09QELOzs7bS1gY2OjrQWsrKy09gHraFIfBaNgqAOAAAMAvy0DChXHsZMAAAAASUVORK5CYII="/><element name="timeSliderProgress" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAClJREFUeNpiYBgFo2AU0BwwAvF/WlrARGsfjFow8BaMglEwCugAAAIMAOHfAQunR+XzAAAAAElFTkSuQmCC"/><element name="timeSliderThumb" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAICAYAAAA870V8AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABZJREFUeNpiZICA/yCCiQEJUJcDEGAAY0gBD1/m7Q0AAAAASUVORK5CYII="/><element name="muteButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAYCAYAAADKx8xXAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiYBgFIw3MB+L/5Gj8j6yRiRTFyICJXHfTXyMLAXlGati4YDRFDj8AEGAABk8GSqqS4CoAAAAASUVORK5CYII="/><element name="unmuteButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAYCAYAAADKx8xXAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD1JREFUeNpiYBgFgxz8p7bm+cQa+h8LHy7GhEcjIz4bmAjYykiun/8j0fakGPIfTfPgiSr6aB4FVAcAAQYAWdwR1G1Wd2gAAAAASUVORK5CYII="/><element name="volumeSliderRail" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAYCAYAAADkgu3FAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAGpJREFUeNpi/P//PwM9ABMDncCoRYPfIqqDZcuW1UPp/6AUDcNM1DQYKtRAlaAj1mCSLSLXYIIWUctgDItoZfDA5aOoqKhGEANIM9LVR7SymGDQUctikuOIXkFNdhHEOFrDjlpEd4sAAgwAriRMub95fu8AAAAASUVORK5CYII="/><element name="volumeSliderProgress" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAYCAYAAADkgu3FAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFtJREFUeNpi/P//PwM9ABMDncCoRYPfIlqAeij9H5SiYZiqBqPTlFqE02BKLSLaYFItIttgQhZRzWB8FjENiuRJ7aAbsMQwYMl7wDIsWUUQ42gNO2oR3S0CCDAAKhKq6MLLn8oAAAAASUVORK5CYII="/><element name="fullscreenButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAE5JREFUeNpiYBgFo2DQA0YC8v/xqP1PjDlMRDrEgUgxkgHIlfZoriVGjmzLsLFHAW2D6D8eA/9Tw7L/BAwgJE90PvhPpNgoGAVDEQAEGAAMdhTyXcPKcAAAAABJRU5ErkJggg=="/><element name="normalscreenButton" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEZJREFUeNpiYBgFo2DIg/9UUkOUAf8JiFFsyX88fJyAkcQgYMQjNkzBoAgiezyRbE+tFGSPxQJ7auYBmma0UTAKBhgABBgAJAEY6zON61sAAAAASUVORK5CYII="/></elements></component><component name="display"><elements><element name="background" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEpJREFUeNrszwENADAIA7DhX8ENoBMZ5KR10EryckCJiIiIiIiIiIiIiIiIiIiIiIh8GmkRERERERERERERERERERERERGRHSPAAPlXH1phYpYaAAAAAElFTkSuQmCC"/><element name="playIcon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALdJREFUeNrs18ENgjAYhmFouDOCcQJGcARHgE10BDcgTOIosAGwQOuPwaQeuFRi2p/3Sb6EC5L3QCxZBgAAAOCorLW1zMn65TrlkH4NcV7QNcUQt7Gn7KIhxA+qNIR81spOGkL8oFJDyLJRdosqKDDkK+iX5+d7huzwM40xptMQMkjIOeRGo+VkEVvIPfTGIpKASfYIfT9iCHkHrBEzf4gcUQ56aEzuGK/mw0rHpy4AAACAf3kJMACBxjAQNRckhwAAAABJRU5ErkJggg=="/><element name="muteIcon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHJJREFUeNrs1jEOgCAMBVAg7t5/8qaoIy4uoobyXsLCxA+0NCUAAADGUWvdQoQ41x4ixNBB2hBvBskdD3w5ZCkl3+33VqI0kjBBlh9rp+uTcyOP33TnolfsU85XX3yIRpQph8ZQY3wTZtU5AACASA4BBgDHoVuY1/fvOQAAAABJRU5ErkJggg=="/><element name="errorIcon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAWlJREFUeNrsl+1twjAQhsHq/7BBYQLYIBmBDcoGMAIjtBPQTcII2SDtBDBBwrU6pGsUO7YbO470PtKJkz9iH++d4ywWAAAAAABgljRNsyWr2bZzDuJG1rLdZhcMbTjrBCGDyUKsqQLFciJb9bSvuG/WagRVRUVUI6gqy5HVeKWfSgRyJruKIU//TrZTSn2nmlaXThrloi/v9F2STC1W4+Aw5cBzkquRc09bofFNc6YLxEON0VUZS5FPTftO49vMjRsIF3RhOGr7/D/pJw+FKU+q0vDyq8W42jCunDqI3LC5XxNj2wHLU1XjaRnb0Lhykhqhhd8MtSF5J9tbjCv4mXGvKJz/65FF/qJryyaaIvzP2QRxZTX2nTuXjvV/VPFSwyLnW7mpH99yTh1FEVro6JBSd40/pMrRdV8vPtcKl28T2pT8TnFZ4yNosct3Q0io6JfBiz1FlGdqVQH3VHnepAEAAAAAADDzEGAAcTwB10jWgxcAAAAASUVORK5CYII="/><element name="bufferIcon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAuhJREFUeNrsWr9rU1EUznuNGqvFQh1ULOhiBx0KDtIuioO4pJuik3FxFfUPaAV1FTdx0Q5d2g4FFxehTnEpZHFoBy20tCIWtGq0TZP4HfkeHB5N8m6Sl/sa74XDybvv3vvOd8/Pe4lXrVZT3dD8VJc0B8QBcUAcEAfESktHGeR5XtMfqFQq/f92zPe/NbtGlKTdCY30kuxrpMGO94BlQCXs+rbh3ONgA6BlzP1p20d80gEI5hmA2A92Qua1Q2PtAFISM+bvjMG8U+Q7oA3rQGASwrYCU6WpNdLGYbA+Pq5jjXIiwi8EEa2UDbQSaKOIuV+SlkcCrfjY8XTI9EpKGwP0C2kru2hLtHqa4zoXtZRWyvi4CLwv9Opr6Hkn6A9HKgEANsQ1iqC3Ub/vRUk2JgmRkatK36kVrnt0qObunwUdUUMXMWYpakJsO5Am8tAw2GBIgwWA+G2S2dMpiw0gDioQRQJoKhRb1QiDwlHZUABYbaXWsm5ae6loTE4ZDxN4CZar8foVzOJ2iyZ2kWF3t7YIevffaMT5yJ70kQb2fQ1sE5SHr2wazs2wgMxgbsEKEAgxAvZUJbQLBGTSBMgNrncJbA6AljtS/eKDJ0Ez+DmrQEzXS2h1Ck25kAg0IZcUOaydCy4sYnN2fOA+2AP16gNoHALlQ+fwH7XO4CxLenUpgj4xr6ugY2roPMbMx+Xs18m/E8CVEIhxsNeg83XWOAN6grG3lGbk8uE5fr4B/WH3cJw+co/l9nTYsSGYCJ/lY5/qv0thn6nrIWmjeJcPSnWOeY++AkF8tpJHIMAUs/MaBBpj3znZfQo5psY+ZrG4gv5HickjEOymKjEeRpgyST6IuZcTcWbnjcgdPi5ghxciRKsl1lDSsgwA1i8fssonJgzmTSqfGUkCENndNdAL7PS6QQ7ZYISTo+1qq0LEWjTWcvY4isa4z+yfQB+7ooyHVg5RI7/i1Ijn/vnggDggDogD4oC00P4KMACd/juEHOrS4AAAAABJRU5ErkJggg=="/></elements></component><component name="dock"><elements><element name="button" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFBJREFUeNrs0cEJACAQA8Eofu0fu/W6EM5ZSAFDRpKTBs00CQQEBAQEBAQEBAQEBAQEBATkK8iqbY+AgICAgICAgICAgICAgICAgIC86QowAG5PAQzEJ0lKAAAAAElFTkSuQmCC"/></elements></component><component name="playlist"><elements><element name="item" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAIAAAC1nk4lAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHhJREFUeNrs2NEJwCAMBcBYuv/CFuIE9VN47WWCR7iocXR3pdWdGPqqwIoMjYfQeAiNh9B4JHc6MHQVHnjggQceeOCBBx77TifyeOY0iHi8DqIdEY8dD5cL094eePzINB5CO/LwcOTptNB4CP25L4TIbZzpU7UEGAA5wz1uF5rF9AAAAABJRU5ErkJggg=="/><element name="sliderRail" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAA8CAIAAADpFA0BAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADhJREFUeNrsy6ENACAMAMHClp2wYxZLAg5Fcu9e3OjuOKqqfTMzbs14CIZhGIZhGIZhGP4VLwEGAK/BBnVFpB0oAAAAAElFTkSuQmCC"/><element name="sliderThumb" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAA8CAIAAADpFA0BAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNrsy7ENACAMBLE8++8caFFKKiRffU53112SGs3ttOohGIZhGIZhGIZh+Fe8BRgAiaUGde6NOSEAAAAASUVORK5CYII="/></elements></component></components></skin>';this.xml=null;if(window.DOMParser){parser=new DOMParser();this.xml=parser.parseFromString(this.text,"text/xml")}else{this.xml=new ActiveXObject("Microsoft.XMLDOM");this.xml.async="false";this.xml.loadXML(this.text)}return this}})(jwplayer);(function(a){_utils=a.utils;_css=_utils.css;_hide=function(b){_css(b,{display:"none"})};_show=function(b){_css(b,{display:"block"})};a.html5.display=function(k,G){var j={icons:true,showmute:false};var Q=_utils.extend({},j,G);var h=k;var P={};var e;var u;var w;var N;var s;var I;var A;var J=!_utils.exists(h.skin.getComponentSettings("display").bufferrotation)?15:parseInt(h.skin.getComponentSettings("display").bufferrotation,10);var q=!_utils.exists(h.skin.getComponentSettings("display").bufferinterval)?100:parseInt(h.skin.getComponentSettings("display").bufferinterval,10);var z=-1;var t="";var K=true;var d;var g=false;var n=false;var H=new a.html5.eventdispatcher();_utils.extend(this,H);var D={display:{style:{cursor:"pointer",top:0,left:0,overflow:"hidden"},click:m},display_icon:{style:{cursor:"pointer",position:"absolute",top:((h.skin.getSkinElement("display","background").height-h.skin.getSkinElement("display","playIcon").height)/2),left:((h.skin.getSkinElement("display","background").width-h.skin.getSkinElement("display","playIcon").width)/2),border:0,margin:0,padding:0,zIndex:3,display:"none"}},display_iconBackground:{style:{cursor:"pointer",position:"absolute",top:((u-h.skin.getSkinElement("display","background").height)/2),left:((e-h.skin.getSkinElement("display","background").width)/2),border:0,backgroundImage:(["url(",h.skin.getSkinElement("display","background").src,")"]).join(""),width:h.skin.getSkinElement("display","background").width,height:h.skin.getSkinElement("display","background").height,margin:0,padding:0,zIndex:2,display:"none"}},display_image:{style:{display:"none",width:e,height:u,position:"absolute",cursor:"pointer",left:0,top:0,margin:0,padding:0,textDecoration:"none",zIndex:1}},display_text:{style:{zIndex:4,position:"relative",opacity:0.8,backgroundColor:parseInt("000000",16),color:parseInt("ffffff",16),textAlign:"center",fontFamily:"Arial,sans-serif",padding:"0 5px",fontSize:14}}};h.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,p);h.jwAddEventListener(a.api.events.JWPLAYER_MEDIA_MUTE,p);h.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_ITEM,p);h.jwAddEventListener(a.api.events.JWPLAYER_ERROR,o);L();function L(){P.display=C("div","display");P.display_text=C("div","display_text");P.display.appendChild(P.display_text);P.display_image=C("img","display_image");P.display_image.onerror=function(R){_hide(P.display_image)};P.display_image.onload=y;P.display_icon=C("div","display_icon");P.display_iconBackground=C("div","display_iconBackground");P.display.appendChild(P.display_image);P.display_iconBackground.appendChild(P.display_icon);P.display.appendChild(P.display_iconBackground);f();setTimeout((function(){n=true;if(Q.icons.toString()=="true"){F()}}),1)}this.getDisplayElement=function(){return P.display};this.resize=function(S,R){_css(P.display,{width:S,height:R});_css(P.display_text,{width:(S-10),top:((R-P.display_text.getBoundingClientRect().height)/2)});_css(P.display_iconBackground,{top:((R-h.skin.getSkinElement("display","background").height)/2),left:((S-h.skin.getSkinElement("display","background").width)/2)});if(e!=S||u!=R){e=S;u=R;d=undefined;F()}c();p({})};this.show=function(){if(g){g=false;r(h.jwGetState())}};this.hide=function(){if(!g){B();g=true}};function y(R){w=P.display_image.naturalWidth;N=P.display_image.naturalHeight;c()}function c(){_utils.stretch(h.jwGetStretching(),P.display_image,e,u,w,N)}function C(R,T){var S=document.createElement(R);S.id=h.id+"_jwplayer_"+T;_css(S,D[T].style);return S}function f(){for(var R in P){if(_utils.exists(D[R].click)){P[R].onclick=D[R].click}}}function m(R){if(typeof R.preventDefault!="undefined"){R.preventDefault()}else{R.returnValue=false}if(h.jwGetState()!=a.api.events.state.PLAYING){h.jwPlay()}else{h.jwPause()}}function O(R){if(A){B();return}P.display_icon.style.backgroundImage=(["url(",h.skin.getSkinElement("display",R).src,")"]).join("");_css(P.display_icon,{width:h.skin.getSkinElement("display",R).width,height:h.skin.getSkinElement("display",R).height,top:(h.skin.getSkinElement("display","background").height-h.skin.getSkinElement("display",R).height)/2,left:(h.skin.getSkinElement("display","background").width-h.skin.getSkinElement("display",R).width)/2});b();if(_utils.exists(h.skin.getSkinElement("display",R+"Over"))){P.display_icon.onmouseover=function(S){P.display_icon.style.backgroundImage=["url(",h.skin.getSkinElement("display",R+"Over").src,")"].join("")};P.display_icon.onmouseout=function(S){P.display_icon.style.backgroundImage=["url(",h.skin.getSkinElement("display",R).src,")"].join("")}}else{P.display_icon.onmouseover=null;P.display_icon.onmouseout=null}}function B(){if(Q.icons.toString()=="true"){_hide(P.display_icon);_hide(P.display_iconBackground);M()}}function b(){if(!g&&Q.icons.toString()=="true"){_show(P.display_icon);_show(P.display_iconBackground);F()}}function o(R){A=true;B();P.display_text.innerHTML=R.error;_show(P.display_text);P.display_text.style.top=((u-P.display_text.getBoundingClientRect().height)/2)+"px"}function E(){P.display_image.style.display="none"}function p(R){if((R.type==a.api.events.JWPLAYER_PLAYER_STATE||R.type==a.api.events.JWPLAYER_PLAYLIST_ITEM)&&A){A=false;_hide(P.display_text)}var S=h.jwGetState();if(S==t){return}t=S;if(z>=0){clearTimeout(z)}if(K||h.jwGetState()==a.api.events.state.PLAYING||h.jwGetState()==a.api.events.state.PAUSED){r(h.jwGetState())}else{z=setTimeout(l(h.jwGetState()),500)}}function l(R){return(function(){r(R)})}function r(R){if(_utils.exists(I)){clearInterval(I);I=null;_utils.animations.rotate(P.display_icon,0)}switch(R){case a.api.events.state.BUFFERING:if(_utils.isIOS()){E();B()}else{if(h.jwGetPlaylist()[h.jwGetItem()].provider=="sound"){v()}s=0;I=setInterval(function(){s+=J;_utils.animations.rotate(P.display_icon,s%360)},q);O("bufferIcon");K=true}break;case a.api.events.state.PAUSED:if(!_utils.isIOS()){if(h.jwGetPlaylist()[h.jwGetItem()].provider!="sound"){_css(P.display_image,{background:"transparent no-repeat center center"})}O("playIcon");K=true}break;case a.api.events.state.IDLE:if(h.jwGetPlaylist()[h.jwGetItem()]&&h.jwGetPlaylist()[h.jwGetItem()].image){v()}else{E()}O("playIcon");K=true;break;default:if(h.jwGetPlaylist()[h.jwGetItem()]&&h.jwGetPlaylist()[h.jwGetItem()].provider=="sound"){if(_utils.isIOS()){E();K=false}else{v()}}else{E();K=false}if(h.jwGetMute()&&Q.showmute){O("muteIcon")}else{B()}break}z=-1}function v(){if(h.jwGetPlaylist()[h.jwGetItem()]&&h.jwGetPlaylist()[h.jwGetItem()].image){_css(P.display_image,{display:"block"});P.display_image.src=_utils.getAbsolutePath(h.jwGetPlaylist()[h.jwGetItem()].image)}}function x(R){return function(){if(!n){return}if(!g&&d!=R){d=R;H.sendEvent(R,{component:"display",boundingRect:_utils.getDimensions(P.display_iconBackground)})}}}var F=x(a.api.events.JWPLAYER_COMPONENT_SHOW);var M=x(a.api.events.JWPLAYER_COMPONENT_HIDE);return this}})(jwplayer);(function(a){_css=a.utils.css;a.html5.dock=function(p,u){function q(){return{align:a.html5.view.positions.RIGHT}}var k=a.utils.extend({},q(),u);if(k.align=="FALSE"){return}var f={};var s=[];var g;var v;var d=false;var t=false;var e={x:0,y:0,width:0,height:0};var r;var j=new a.html5.eventdispatcher();_utils.extend(this,j);var m=document.createElement("div");m.id=p.id+"_jwplayer_dock";p.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,l);this.getDisplayElement=function(){return m};this.setButton=function(A,x,y,z){if(!x&&f[A]){a.utils.arrays.remove(s,A);m.removeChild(f[A].div);delete f[A]}else{if(x){if(!f[A]){f[A]={}}f[A].handler=x;f[A].outGraphic=y;f[A].overGraphic=z;if(!f[A].div){s.push(A);f[A].div=document.createElement("div");f[A].div.style.position="relative";m.appendChild(f[A].div);f[A].div.appendChild(document.createElement("img"));f[A].div.childNodes[0].style.position="absolute";f[A].div.childNodes[0].style.left=0;f[A].div.childNodes[0].style.top=0;f[A].div.childNodes[0].style.zIndex=10;f[A].div.childNodes[0].style.cursor="pointer";f[A].div.appendChild(document.createElement("img"));f[A].div.childNodes[1].style.position="absolute";f[A].div.childNodes[1].style.left=0;f[A].div.childNodes[1].style.top=0;if(p.skin.getSkinElement("dock","button")){f[A].div.childNodes[1].src=p.skin.getSkinElement("dock","button").src}f[A].div.childNodes[1].style.zIndex=9;f[A].div.childNodes[1].style.cursor="pointer";f[A].div.onmouseover=function(){if(f[A].overGraphic){f[A].div.childNodes[0].src=f[A].overGraphic}if(p.skin.getSkinElement("dock","buttonOver")){f[A].div.childNodes[1].src=p.skin.getSkinElement("dock","buttonOver").src}};f[A].div.onmouseout=function(){if(f[A].outGraphic){f[A].div.childNodes[0].src=f[A].outGraphic}if(p.skin.getSkinElement("dock","button")){f[A].div.childNodes[1].src=p.skin.getSkinElement("dock","button").src}};if(f[A].overGraphic){f[A].div.childNodes[0].src=f[A].overGraphic}if(f[A].outGraphic){f[A].div.childNodes[0].src=f[A].outGraphic}if(p.skin.getSkinElement("dock","button")){f[A].div.childNodes[1].src=p.skin.getSkinElement("dock","button").src}}if(x){f[A].div.onclick=function(B){B.preventDefault();a(p.id).callback(A);if(f[A].overGraphic){f[A].div.childNodes[0].src=f[A].overGraphic}if(p.skin.getSkinElement("dock","button")){f[A].div.childNodes[1].src=p.skin.getSkinElement("dock","button").src}}}}}h(g,v)};function h(x,J){if(s.length>0){var y=10;var I=y;var F=-1;var G=p.skin.getSkinElement("dock","button").height;var E=p.skin.getSkinElement("dock","button").width;var C=x-E-y;var H,B;if(k.align==a.html5.view.positions.LEFT){F=1;C=y}for(var z=0;z<s.length;z++){var K=Math.floor(I/J);if((I+G+y)>((K+1)*J)){I=((K+1)*J)+y;K=Math.floor(I/J)}var A=f[s[z]].div;A.style.top=(I%J)+"px";A.style.left=(C+(p.skin.getSkinElement("dock","button").width+y)*K*F)+"px";var D={x:a.utils.parseDimension(A.style.left),y:a.utils.parseDimension(A.style.top),width:E,height:G};if(!H||(D.x<=H.x&&D.y<=H.y)){H=D}if(!B||(D.x>=B.x&&D.y>=B.y)){B=D}I+=p.skin.getSkinElement("dock","button").height+y}e={x:H.x,y:H.y,width:B.x-H.x+B.width,height:H.y-B.y+B.height}}if(t!=p.jwGetFullscreen()||g!=x||v!=J){g=x;v=J;t=p.jwGetFullscreen();r=undefined;setTimeout(n,1)}}function b(x){return function(){if(!d&&r!=x&&s.length>0){r=x;j.sendEvent(x,{component:"dock",boundingRect:e})}}}function l(x){if(a.utils.isIOS()){switch(x.newstate){case a.api.events.state.IDLE:o();break;default:c();break}}}var n=b(a.api.events.JWPLAYER_COMPONENT_SHOW);var w=b(a.api.events.JWPLAYER_COMPONENT_HIDE);this.resize=h;var o=function(){_css(m,{display:"block"});if(d){d=false;n()}};var c=function(){_css(m,{display:"none"});if(!d){w();d=true}};this.hide=c;this.show=o;return this}})(jwplayer);(function(a){a.html5.eventdispatcher=function(d,b){var c=new a.events.eventdispatcher(b);a.utils.extend(this,c);this.sendEvent=function(e,f){if(!a.utils.exists(f)){f={}}a.utils.extend(f,{id:d,version:a.version,type:e});c.sendEvent(e,f)}}})(jwplayer);(function(a){var b={prefix:"http://l.longtailvideo.com/html5/",file:"logo.png",link:"http://www.longtailvideo.com/players/jw-flv-player/",margin:8,out:0.5,over:1,timeout:5,hide:true,position:"bottom-left"};_css=a.utils.css;a.html5.logo=function(n,r){var q=n;var u;var d;var t;var h=false;g();function g(){o();c();l()}function o(){if(b.prefix){var v=n.version.split(/\W/).splice(0,2).join("/");if(b.prefix.indexOf(v)<0){b.prefix+=v+"/"}}if(r.position==a.html5.view.positions.OVER){r.position=b.position}d=a.utils.extend({},b)}function c(){t=document.createElement("img");t.id=q.id+"_jwplayer_logo";t.style.display="none";t.onload=function(v){_css(t,k());q.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,j);p()};if(!d.file){return}if(d.file.indexOf("http://")===0){t.src=d.file}else{t.src=d.prefix+d.file}}if(!d.file){return}this.resize=function(w,v){};this.getDisplayElement=function(){return t};function l(){if(d.link){t.onmouseover=f;t.onmouseout=p;t.onclick=s}else{this.mouseEnabled=false}}function s(v){if(typeof v!="undefined"){v.stopPropagation()}if(!h){return}q.jwPause();q.jwSetFullscreen(false);if(d.link){window.open(d.link,"_top")}return}function p(v){if(d.link&&h){t.style.opacity=d.out}return}function f(v){if(d.hide.toString()=="true"&&h){t.style.opacity=d.over}return}function k(){var x={textDecoration:"none",position:"absolute",cursor:"pointer"};x.display=(d.hide.toString()=="true")?"none":"block";var w=d.position.toLowerCase().split("-");for(var v in w){x[w[v]]=d.margin}return x}function m(){if(d.hide.toString()=="true"){t.style.display="block";t.style.opacity=0;a.utils.fadeTo(t,d.out,0.1,parseFloat(t.style.opacity));u=setTimeout(function(){e()},d.timeout*1000)}h=true}function e(){h=false;if(d.hide.toString()=="true"){a.utils.fadeTo(t,0,0.1,parseFloat(t.style.opacity))}}function j(v){if(v.newstate==a.api.events.state.BUFFERING){clearTimeout(u);m()}}return this}})(jwplayer);(function(a){var c={ended:a.api.events.state.IDLE,playing:a.api.events.state.PLAYING,pause:a.api.events.state.PAUSED,buffering:a.api.events.state.BUFFERING};var e=a.utils;var b=e.css;var d=e.isIOS();a.html5.mediavideo=function(h,s){var r={abort:n,canplay:k,canplaythrough:k,durationchange:G,emptied:n,ended:k,error:u,loadeddata:G,loadedmetadata:G,loadstart:k,pause:k,play:n,playing:k,progress:v,ratechange:n,seeked:k,seeking:k,stalled:k,suspend:k,timeupdate:D,volumechange:n,waiting:k,canshowcurrentframe:n,dataunavailable:n,empty:n,load:z,loadedfirstframe:n};var j=new a.html5.eventdispatcher();e.extend(this,j);var y=h,l=s,m,B,A,x,f,H=false,C,p,q;o();this.load=function(J,K){if(typeof K=="undefined"){K=true}x=J;e.empty(m);q=0;if(J.levels&&J.levels.length>0){if(J.levels.length==1){m.src=J.levels[0].file}else{if(m.src){m.removeAttribute("src")}for(var I=0;I<J.levels.length;I++){var L=m.ownerDocument.createElement("source");L.src=J.levels[I].file;m.appendChild(L);q++}}}else{m.src=J.file}if(d){if(J.image){m.poster=J.image}m.controls="controls";m.style.display="block"}C=p=A=false;y.buffer=0;if(!e.exists(J.start)){J.start=0}y.duration=J.duration;j.sendEvent(a.api.events.JWPLAYER_MEDIA_LOADED);if((!d&&J.levels.length==1)||!H){m.load()}H=false;if(K){E(a.api.events.state.BUFFERING);j.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER,{bufferPercent:0});this.play()}};this.play=function(){if(B!=a.api.events.state.PLAYING){t();if(p){E(a.api.events.state.PLAYING)}else{E(a.api.events.state.BUFFERING)}m.play()}};this.pause=function(){m.pause();E(a.api.events.state.PAUSED)};this.seek=function(I){if(!(y.duration<=0||isNaN(y.duration))&&!(y.position<=0||isNaN(y.position))){m.currentTime=I;m.play()}};_stop=this.stop=function(I){if(!e.exists(I)){I=true}g();if(I){m.style.display="none";p=false;var J=navigator.userAgent;if(J.match(/chrome/i)){m.src=undefined}else{if(J.match(/safari/i)){m.removeAttribute("src")}else{m.src=""}}m.removeAttribute("controls");m.removeAttribute("poster");e.empty(m);m.load();H=true;if(m.webkitSupportsFullscreen){try{m.webkitExitFullscreen()}catch(K){}}}E(a.api.events.state.IDLE)};this.fullscreen=function(I){if(I===true){this.resize("100%","100%")}else{this.resize(y.config.width,y.config.height)}};this.resize=function(J,I){if(false){b(l,{width:J,height:I})}j.sendEvent(a.api.events.JWPLAYER_MEDIA_RESIZE,{fullscreen:y.fullscreen,width:J,hieght:I})};this.volume=function(I){if(!d){m.volume=I/100;y.volume=I;j.sendEvent(a.api.events.JWPLAYER_MEDIA_VOLUME,{volume:Math.round(I)})}};this.mute=function(I){if(!d){m.muted=I;y.mute=I;j.sendEvent(a.api.events.JWPLAYER_MEDIA_MUTE,{mute:I})}};this.getDisplayElement=function(){return m};this.hasChrome=function(){return false};function o(){m=document.createElement("video");B=a.api.events.state.IDLE;for(var I in r){m.addEventListener(I,function(J){if(e.exists(J.target.parentNode)){r[J.type](J)}},true)}m.setAttribute("x-webkit-airplay","allow");if(l.parentNode){l.parentNode.replaceChild(m,l)}if(!m.id){m.id=l.id}}function E(I){if(I==a.api.events.state.PAUSED&&B==a.api.events.state.IDLE){return}if(B!=I){var J=B;y.state=B=I;j.sendEvent(a.api.events.JWPLAYER_PLAYER_STATE,{oldstate:J,newstate:I})}}function n(I){}function v(K){var J;if(e.exists(K)&&K.lengthComputable&&K.total){J=K.loaded/K.total*100}else{if(e.exists(m.buffered)&&(m.buffered.length>0)){var I=m.buffered.length-1;if(I>=0){J=m.buffered.end(I)/m.duration*100}}}if(p===false&&B==a.api.events.state.BUFFERING){j.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER_FULL);p=true}if(!C){if(J==100){C=true}if(e.exists(J)&&(J>y.buffer)){y.buffer=Math.round(J);j.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER,{bufferPercent:Math.round(J)})}}}function D(J){if(e.exists(J)&&e.exists(J.target)){if(!isNaN(J.target.duration)&&(isNaN(y.duration)||y.duration<1)){if(J.target.duration==Infinity){y.duration=0}else{y.duration=Math.round(J.target.duration*10)/10}}if(!A&&m.readyState>0){m.style.display="block";E(a.api.events.state.PLAYING)}if(B==a.api.events.state.PLAYING){if(!A&&m.readyState>0){A=true;try{if(m.currentTime<x.start){m.currentTime=x.start}}catch(I){}m.volume=y.volume/100;m.muted=y.mute}y.position=y.duration>0?(Math.round(J.target.currentTime*10)/10):0;j.sendEvent(a.api.events.JWPLAYER_MEDIA_TIME,{position:y.position,duration:y.duration});if(y.position>=y.duration&&(y.position>0||y.duration>0)){w()}}}v(J)}function z(I){}function k(I){if(c[I.type]){if(I.type=="ended"){w()}else{E(c[I.type])}}}function G(I){var J={height:I.target.videoHeight,width:I.target.videoWidth,duration:Math.round(I.target.duration*10)/10};if((y.duration===0||isNaN(y.duration))&&I.target.duration!=Infinity){y.duration=Math.round(I.target.duration*10)/10}j.sendEvent(a.api.events.JWPLAYER_MEDIA_META,{metadata:J})}function u(K){if(B==a.api.events.state.IDLE){return}var J="There was an error: ";if((K.target.error&&K.target.tagName.toLowerCase()=="video")||K.target.parentNode.error&&K.target.parentNode.tagName.toLowerCase()=="video"){var I=!e.exists(K.target.error)?K.target.parentNode.error:K.target.error;switch(I.code){case I.MEDIA_ERR_ABORTED:J="You aborted the video playback: ";break;case I.MEDIA_ERR_NETWORK:J="A network error caused the video download to fail part-way: ";break;case I.MEDIA_ERR_DECODE:J="The video playback was aborted due to a corruption problem or because the video used features your browser did not support: ";break;case I.MEDIA_ERR_SRC_NOT_SUPPORTED:J="The video could not be loaded, either because the server or network failed or because the format is not supported: ";break;default:J="An unknown error occurred: ";break}}else{if(K.target.tagName.toLowerCase()=="source"){q--;if(q>0){return}J="The video could not be loaded, either because the server or network failed or because the format is not supported: "}else{e.log("An unknown error occurred. Continuing...");return}}_stop(false);J+=F();_error=true;j.sendEvent(a.api.events.JWPLAYER_ERROR,{error:J});return}function F(){var K="";for(var J in x.levels){var I=x.levels[J];var L=l.ownerDocument.createElement("source");K+=a.utils.getAbsolutePath(I.file);if(J<(x.levels.length-1)){K+=", "}}return K}function t(){if(!e.exists(f)){f=setInterval(function(){v()},100)}}function g(){clearInterval(f);f=null}function w(){if(B!=a.api.events.state.IDLE){_stop(false);j.sendEvent(a.api.events.JWPLAYER_MEDIA_COMPLETE)}}}})(jwplayer);(function(a){var c={ended:a.api.events.state.IDLE,playing:a.api.events.state.PLAYING,pause:a.api.events.state.PAUSED,buffering:a.api.events.state.BUFFERING};var b=a.utils.css;a.html5.mediayoutube=function(j,e){var f=new a.html5.eventdispatcher();a.utils.extend(this,f);var l=j;var h=document.getElementById(e.id);var g=a.api.events.state.IDLE;var n,m;function k(p){if(g!=p){var q=g;l.state=p;g=p;f.sendEvent(a.api.events.JWPLAYER_PLAYER_STATE,{oldstate:q,newstate:p})}}this.getDisplayElement=function(){return h};this.play=function(){if(g==a.api.events.state.IDLE){f.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER,{bufferPercent:100});f.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER_FULL);k(a.api.events.state.PLAYING)}else{if(g==a.api.events.state.PAUSED){k(a.api.events.state.PLAYING)}}};this.pause=function(){k(a.api.events.state.PAUSED)};this.seek=function(p){};this.stop=function(p){if(!_utils.exists(p)){p=true}l.position=0;k(a.api.events.state.IDLE);if(p){b(h,{display:"none"})}};this.volume=function(p){l.volume=p;f.sendEvent(a.api.events.JWPLAYER_MEDIA_VOLUME,{volume:Math.round(p)})};this.mute=function(p){h.muted=p;l.mute=p;f.sendEvent(a.api.events.JWPLAYER_MEDIA_MUTE,{mute:p})};this.resize=function(q,p){if(q*p>0&&n){n.width=m.width=q;n.height=m.height=p}f.sendEvent(a.api.events.JWPLAYER_MEDIA_RESIZE,{fullscreen:l.fullscreen,width:q,height:p})};this.fullscreen=function(p){if(p===true){this.resize("100%","100%")}else{this.resize(l.config.width,l.config.height)}};this.load=function(p){o(p);b(n,{display:"block"});k(a.api.events.state.BUFFERING);f.sendEvent(a.api.events.JWPLAYER_MEDIA_BUFFER,{bufferPercent:0});f.sendEvent(a.api.events.JWPLAYER_MEDIA_LOADED);this.play()};this.hasChrome=function(){return(g!=a.api.events.state.IDLE)};function o(v){var s=v.levels[0].file;s=["http://www.youtube.com/v/",d(s),"&hl=en_US&fs=1&autoplay=1"].join("");n=document.createElement("object");n.id=h.id;n.style.position="absolute";var u={movie:s,allowfullscreen:"true",allowscriptaccess:"always"};for(var p in u){var t=document.createElement("param");t.name=p;t.value=u[p];n.appendChild(t)}m=document.createElement("embed");n.appendChild(m);var q={src:s,type:"application/x-shockwave-flash",allowfullscreen:"true",allowscriptaccess:"always",width:n.width,height:n.height};for(var r in q){m.setAttribute(r,q[r])}n.appendChild(m);n.style.zIndex=2147483000;if(h!=n&&h.parentNode){h.parentNode.replaceChild(n,h)}h=n}function d(q){var p=q.split(/\?|\#\!/);var s="";for(var r=0;r<p.length;r++){if(p[r].substr(0,2)=="v="){s=p[r].substr(2)}}if(s==""){if(q.indexOf("/v/")>=0){s=q.substr(q.indexOf("/v/")+3)}else{if(q.indexOf("youtu.be")>=0){s=q.substr(q.indexOf("youtu.be/")+9)}else{s=q}}}if(s.indexOf("?")>-1){s=s.substr(0,s.indexOf("?"))}if(s.indexOf("&")>-1){s=s.substr(0,s.indexOf("&"))}return s}this.embed=m;return this}})(jwplayer);(function(jwplayer){var _configurableStateVariables=["width","height","start","duration","volume","mute","fullscreen","item","plugins","stretching"];jwplayer.html5.model=function(api,container,options){var _api=api;var _container=container;var _model={id:_container.id,playlist:[],state:jwplayer.api.events.state.IDLE,position:0,buffer:0,config:{width:480,height:320,item:-1,skin:undefined,file:undefined,image:undefined,start:0,duration:0,bufferlength:5,volume:90,mute:false,fullscreen:false,repeat:"",stretching:jwplayer.utils.stretching.UNIFORM,autostart:false,debug:undefined,screencolor:undefined}};var _media;var _eventDispatcher=new jwplayer.html5.eventdispatcher();var _components=["display","logo","controlbar","playlist","dock"];jwplayer.utils.extend(_model,_eventDispatcher);for(var option in options){if(typeof options[option]=="string"){var type=/color$/.test(option)?"color":null;options[option]=jwplayer.utils.typechecker(options[option],type)}var config=_model.config;var path=option.split(".");for(var edge in path){if(edge==path.length-1){config[path[edge]]=options[option]}else{if(!jwplayer.utils.exists(config[path[edge]])){config[path[edge]]={}}config=config[path[edge]]}}}for(var index in _configurableStateVariables){var configurableStateVariable=_configurableStateVariables[index];_model[configurableStateVariable]=_model.config[configurableStateVariable]}var pluginorder=_components.concat([]);if(jwplayer.utils.exists(_model.plugins)){if(typeof _model.plugins=="string"){var userplugins=_model.plugins.split(",");for(var userplugin in userplugins){if(typeof userplugins[userplugin]=="string"){pluginorder.push(userplugins[userplugin].replace(/^\s+|\s+$/g,""))}}}}if(jwplayer.utils.isIOS()){pluginorder=["display","logo","dock","playlist"];if(!jwplayer.utils.exists(_model.config.repeat)){_model.config.repeat="list"}}else{if(_model.config.chromeless){pluginorder=["logo","dock","playlist"];if(!jwplayer.utils.exists(_model.config.repeat)){_model.config.repeat="list"}}}_model.plugins={order:pluginorder,config:{},object:{}};if(typeof _model.config.components!="undefined"){for(var component in _model.config.components){_model.plugins.config[component]=_model.config.components[component]}}for(var pluginIndex in _model.plugins.order){var pluginName=_model.plugins.order[pluginIndex];var pluginConfig=!jwplayer.utils.exists(_model.plugins.config[pluginName])?{}:_model.plugins.config[pluginName];_model.plugins.config[pluginName]=!jwplayer.utils.exists(_model.plugins.config[pluginName])?pluginConfig:jwplayer.utils.extend(_model.plugins.config[pluginName],pluginConfig);if(!jwplayer.utils.exists(_model.plugins.config[pluginName].position)){if(pluginName=="playlist"){_model.plugins.config[pluginName].position=jwplayer.html5.view.positions.NONE}else{_model.plugins.config[pluginName].position=jwplayer.html5.view.positions.OVER}}else{_model.plugins.config[pluginName].position=_model.plugins.config[pluginName].position.toString().toUpperCase()}}if(typeof _model.plugins.config.dock!="undefined"){if(typeof _model.plugins.config.dock!="object"){var position=_model.plugins.config.dock.toString().toUpperCase();_model.plugins.config.dock={position:position}}if(typeof _model.plugins.config.dock.position!="undefined"){_model.plugins.config.dock.align=_model.plugins.config.dock.position;_model.plugins.config.dock.position=jwplayer.html5.view.positions.OVER}}function _loadExternal(playlistfile){var loader=new jwplayer.html5.playlistloader();loader.addEventListener(jwplayer.api.events.JWPLAYER_PLAYLIST_LOADED,function(evt){_model.playlist=new jwplayer.html5.playlist(evt);_loadComplete(true)});loader.addEventListener(jwplayer.api.events.JWPLAYER_ERROR,function(evt){_model.playlist=new jwplayer.html5.playlist({playlist:[]});_loadComplete(false)});loader.load(playlistfile)}function _loadComplete(){if(_model.config.shuffle){_model.item=_getShuffleItem()}else{if(_model.config.item>=_model.playlist.length){_model.config.item=_model.playlist.length-1}else{if(_model.config.item<0){_model.config.item=0}}_model.item=_model.config.item}_eventDispatcher.sendEvent(jwplayer.api.events.JWPLAYER_PLAYLIST_LOADED,{playlist:_model.playlist});_eventDispatcher.sendEvent(jwplayer.api.events.JWPLAYER_PLAYLIST_ITEM,{index:_model.item})}_model.loadPlaylist=function(arg){var input;if(typeof arg=="string"){if(arg.indexOf("[")==0||arg.indexOf("{")=="0"){try{input=eval(arg)}catch(err){input=arg}}else{input=arg}}else{input=arg}var config;switch(jwplayer.utils.typeOf(input)){case"object":config=input;break;case"array":config={playlist:input};break;default:_loadExternal(input);return;break}_model.playlist=new jwplayer.html5.playlist(config);if(jwplayer.utils.extension(_model.playlist[0].file)=="xml"){_loadExternal(_model.playlist[0].file)}else{_loadComplete()}};function _getShuffleItem(){var result=null;if(_model.playlist.length>1){while(!jwplayer.utils.exists(result)){result=Math.floor(Math.random()*_model.playlist.length);if(result==_model.item){result=null}}}else{result=0}return result}function forward(evt){if(evt.type==jwplayer.api.events.JWPLAYER_MEDIA_LOADED){_container=_media.getDisplayElement()}_eventDispatcher.sendEvent(evt.type,evt)}var _mediaProviders={};_model.setActiveMediaProvider=function(playlistItem){if(playlistItem.provider=="audio"){playlistItem.provider="sound"}var provider=playlistItem.provider;var current=_media?_media.getDisplayElement():null;if(provider=="sound"||provider=="http"||provider==""){provider="video"}if(!jwplayer.utils.exists(_mediaProviders[provider])){switch(provider){case"video":_media=new jwplayer.html5.mediavideo(_model,current?current:_container);break;case"youtube":_media=new jwplayer.html5.mediayoutube(_model,current?current:_container);break}if(!jwplayer.utils.exists(_media)){return false}_media.addGlobalListener(forward);_mediaProviders[provider]=_media}else{if(_media!=_mediaProviders[provider]){if(_media){_media.stop()}_media=_mediaProviders[provider]}}return true};_model.getMedia=function(){return _media};_model.seek=function(pos){_eventDispatcher.sendEvent(jwplayer.api.events.JWPLAYER_MEDIA_SEEK,{position:_model.position,offset:pos});return _media.seek(pos)};_model.setupPlugins=function(){if(!jwplayer.utils.exists(_model.plugins)||!jwplayer.utils.exists(_model.plugins.order)||_model.plugins.order.length==0){jwplayer.utils.log("No plugins to set up");return _model}for(var i=0;i<_model.plugins.order.length;i++){try{var pluginName=_model.plugins.order[i];if(jwplayer.utils.exists(jwplayer.html5[pluginName])){if(pluginName=="playlist"){_model.plugins.object[pluginName]=new jwplayer.html5.playlistcomponent(_api,_model.plugins.config[pluginName])}else{_model.plugins.object[pluginName]=new jwplayer.html5[pluginName](_api,_model.plugins.config[pluginName])}}else{_model.plugins.order.splice(plugin,plugin+1)}if(typeof _model.plugins.object[pluginName].addGlobalListener=="function"){_model.plugins.object[pluginName].addGlobalListener(forward)}}catch(err){jwplayer.utils.log("Could not setup "+pluginName)}}};return _model}})(jwplayer);(function(a){a.html5.playlist=function(b){var d=[];if(b.playlist&&b.playlist instanceof Array&&b.playlist.length>0){for(var c in b.playlist){if(!isNaN(parseInt(c))){d.push(new a.html5.playlistitem(b.playlist[c]))}}}else{d.push(new a.html5.playlistitem(b))}return d}})(jwplayer);(function(a){var c={size:180,position:a.html5.view.positions.NONE,itemheight:60,thumbs:true,fontcolor:"#000000",overcolor:"",activecolor:"",backgroundcolor:"#f8f8f8",font:"_sans",fontsize:"",fontstyle:"",fontweight:""};var b={_sans:"Arial, Helvetica, sans-serif",_serif:"Times, Times New Roman, serif",_typewriter:"Courier New, Courier, monospace"};_utils=a.utils;_css=_utils.css;_hide=function(d){_css(d,{display:"none"})};_show=function(d){_css(d,{display:"block"})};a.html5.playlistcomponent=function(r,B){var w=r;var e=a.utils.extend({},c,w.skin.getComponentSettings("playlist"),B);if(e.position==a.html5.view.positions.NONE||typeof a.html5.view.positions[e.position]=="undefined"){return}var x;var l;var C;var d;var g;var f;var k=-1;var h={background:undefined,item:undefined,itemOver:undefined,itemImage:undefined,itemActive:undefined};this.getDisplayElement=function(){return x};this.resize=function(F,D){l=F;C=D;if(w.jwGetFullscreen()){_hide(x)}else{var E={display:"block",width:l,height:C};_css(x,E)}};this.show=function(){_show(x)};this.hide=function(){_hide(x)};function j(){x=document.createElement("div");x.id=w.id+"_jwplayer_playlistcomponent";switch(e.position){case a.html5.view.positions.RIGHT:case a.html5.view.positions.LEFT:x.style.width=e.size+"px";break;case a.html5.view.positions.TOP:case a.html5.view.positions.BOTTOM:x.style.height=e.size+"px";break}A();if(h.item){e.itemheight=h.item.height}x.style.backgroundColor="#C6C6C6";w.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,s);w.jwAddEventListener(a.api.events.JWPLAYER_PLAYLIST_ITEM,u);w.jwAddEventListener(a.api.events.JWPLAYER_PLAYER_STATE,m)}function p(){var D=document.createElement("ul");_css(D,{width:x.style.width,minWidth:x.style.width,height:x.style.height,backgroundColor:e.backgroundcolor,backgroundImage:h.background?"url("+h.background.src+")":"",color:e.fontcolor,listStyle:"none",margin:0,padding:0,fontFamily:b[e.font]?b[e.font]:b._sans,fontSize:(e.fontsize?e.fontsize:11)+"px",fontStyle:e.fontstyle,fontWeight:e.fontweight,overflowY:"auto"});return D}function y(D){return function(){var E=f.getElementsByClassName("item")[D];var F=e.fontcolor;var G=h.item?"url("+h.item.src+")":"";if(D==w.jwGetPlaylistIndex()){if(e.activecolor!==""){F=e.activecolor}if(h.itemActive){G="url("+h.itemActive.src+")"}}_css(E,{color:e.overcolor!==""?e.overcolor:F,backgroundImage:h.itemOver?"url("+h.itemOver.src+")":G})}}function o(D){return function(){var E=f.getElementsByClassName("item")[D];var F=e.fontcolor;var G=h.item?"url("+h.item.src+")":"";if(D==w.jwGetPlaylistIndex()){if(e.activecolor!==""){F=e.activecolor}if(h.itemActive){G="url("+h.itemActive.src+")"}}_css(E,{color:F,backgroundImage:G})}}function q(I){var P=d[I];var O=document.createElement("li");O.className="item";_css(O,{height:e.itemheight,display:"block",cursor:"pointer",backgroundImage:h.item?"url("+h.item.src+")":"",backgroundSize:"100% "+e.itemheight+"px"});O.onmouseover=y(I);O.onmouseout=o(I);var J=document.createElement("div");var F=new Image();var K=0;var L=0;var M=0;if(v()&&(P.image||P["playlist.image"]||h.itemImage)){F.className="image";if(h.itemImage){K=(e.itemheight-h.itemImage.height)/2;L=h.itemImage.width;M=h.itemImage.height}else{L=e.itemheight*4/3;M=e.itemheight}_css(J,{height:M,width:L,"float":"left",styleFloat:"left",cssFloat:"left",margin:"0 5px 0 0",background:"black",overflow:"hidden",margin:K+"px",position:"relative"});_css(F,{position:"relative"});J.appendChild(F);F.onload=function(){a.utils.stretch(a.utils.stretching.FILL,F,L,M,this.naturalWidth,this.naturalHeight)};if(P["playlist.image"]){F.src=P["playlist.image"]}else{if(P.image){F.src=P.image}else{if(h.itemImage){F.src=h.itemImage.src}}}O.appendChild(J)}var E=l-L-K*2;if(C<e.itemheight*d.length){E-=15}var D=document.createElement("div");_css(D,{position:"relative",height:"100%",overflow:"hidden"});var G=document.createElement("span");if(P.duration>0){G.className="duration";_css(G,{fontSize:(e.fontsize?e.fontsize:11)+"px",fontWeight:(e.fontweight?e.fontweight:"bold"),width:"40px",height:e.fontsize?e.fontsize+10:20,lineHeight:24,"float":"right",styleFloat:"right",cssFloat:"right"});G.innerHTML=_utils.timeFormat(P.duration);D.appendChild(G)}var N=document.createElement("span");N.className="title";_css(N,{padding:"5px 5px 0 "+(K?0:"5px"),height:e.fontsize?e.fontsize+10:20,lineHeight:e.fontsize?e.fontsize+10:20,overflow:"hidden","float":"left",styleFloat:"left",cssFloat:"left",width:((P.duration>0)?E-50:E)-10+"px",fontSize:(e.fontsize?e.fontsize:13)+"px",fontWeight:(e.fontweight?e.fontweight:"bold")});N.innerHTML=P?P.title:"";D.appendChild(N);if(P.description){var H=document.createElement("span");H.className="description";_css(H,{display:"block","float":"left",styleFloat:"left",cssFloat:"left",margin:0,paddingLeft:N.style.paddingLeft,paddingRight:N.style.paddingRight,lineHeight:(e.fontsize?e.fontsize+4:16)+"px",overflow:"hidden",position:"relative"});H.innerHTML=P.description;D.appendChild(H)}O.appendChild(D);return O}function s(E){x.innerHTML="";d=w.jwGetPlaylist();if(!d){return}items=[];f=p();for(var F=0;F<d.length;F++){var D=q(F);D.onclick=z(F);f.appendChild(D);items.push(D)}k=w.jwGetPlaylistIndex();o(k)();x.appendChild(f);if(_utils.isIOS()&&window.iScroll){f.style.height=e.itemheight*d.length+"px";var G=new iScroll(x.id)}}function z(D){return function(){w.jwPlaylistItem(D);w.jwPlay(true)}}function n(){f.scrollTop=w.jwGetPlaylistIndex()*e.itemheight}function v(){return e.thumbs.toString().toLowerCase()=="true"}function u(D){if(k>=0){o(k)();k=D.index}o(D.index)();n()}function m(){if(e.position==a.html5.view.positions.OVER){switch(w.jwGetState()){case a.api.events.state.IDLE:_show(x);break;default:_hide(x);break}}}function A(){for(var D in h){h[D]=t(D)}}function t(D){return w.skin.getSkinElement("playlist",D)}j();return this}})(jwplayer);(function(b){b.html5.playlistitem=function(d){var e={author:"",date:"",description:"",image:"",link:"",mediaid:"",tags:"",title:"",provider:"",file:"",streamer:"",duration:-1,start:0,currentLevel:-1,levels:[]};var c=b.utils.extend({},e,d);if(c.type){c.provider=c.type;delete c.type}if(c.levels.length===0){c.levels[0]=new b.html5.playlistitemlevel(c)}if(!c.provider){c.provider=a(c.levels[0])}else{c.provider=c.provider.toLowerCase()}return c};function a(e){if(b.utils.isYouTube(e.file)){return"youtube"}else{var f=b.utils.extension(e.file);var c;if(f&&b.utils.extensionmap[f]){if(f=="m3u8"){return"video"}c=b.utils.extensionmap[f].html5}else{if(e.type){c=e.type}}if(c){var d=c.split("/")[0];if(d=="audio"){return"sound"}else{if(d=="video"){return d}}}}return""}})(jwplayer);(function(a){a.html5.playlistitemlevel=function(b){var d={file:"",streamer:"",bitrate:0,width:0};for(var c in d){if(a.utils.exists(b[c])){d[c]=b[c]}}return d}})(jwplayer);(function(a){a.html5.playlistloader=function(){var c=new a.html5.eventdispatcher();a.utils.extend(this,c);this.load=function(e){a.utils.ajax(e,d,b)};function d(g){var f=[];try{var f=a.utils.parsers.rssparser.parse(g.responseXML.firstChild);c.sendEvent(a.api.events.JWPLAYER_PLAYLIST_LOADED,{playlist:new a.html5.playlist({playlist:f})})}catch(h){b("Could not parse the playlist")}}function b(e){c.sendEvent(a.api.events.JWPLAYER_ERROR,{error:e?e:"could not load playlist for whatever reason. too bad"})}}})(jwplayer);(function(a){a.html5.skin=function(){var b={};var c=false;this.load=function(d,e){new a.html5.skinloader(d,function(f){c=true;b=f;e()},function(){new a.html5.skinloader("",function(f){c=true;b=f;e()})})};this.getSkinElement=function(d,e){if(c){try{return b[d].elements[e]}catch(f){a.utils.log("No such skin component / element: ",[d,e])}}return null};this.getComponentSettings=function(d){if(c){return b[d].settings}return null};this.getComponentLayout=function(d){if(c){return b[d].layout}return null}}})(jwplayer);(function(a){a.html5.skinloader=function(f,p,k){var o={};var c=p;var l=k;var e=true;var j;var n=f;var s=false;function m(){if(typeof n!="string"||n===""){d(a.html5.defaultSkin().xml)}else{a.utils.ajax(a.utils.getAbsolutePath(n),function(t){try{if(a.utils.exists(t.responseXML)){d(t.responseXML);return}}catch(u){h()}d(a.html5.defaultSkin().xml)},function(t){d(a.html5.defaultSkin().xml)})}}function d(y){var E=y.getElementsByTagName("component");if(E.length===0){return}for(var H=0;H<E.length;H++){var C=E[H].getAttribute("name");var B={settings:{},elements:{},layout:{}};o[C]=B;var G=E[H].getElementsByTagName("elements")[0].getElementsByTagName("element");for(var F=0;F<G.length;F++){b(G[F],C)}var z=E[H].getElementsByTagName("settings")[0];if(z&&z.childNodes.length>0){var K=z.getElementsByTagName("setting");for(var P=0;P<K.length;P++){var Q=K[P].getAttribute("name");var I=K[P].getAttribute("value");var x=/color$/.test(Q)?"color":null;o[C].settings[Q]=a.utils.typechecker(I,x)}}var L=E[H].getElementsByTagName("layout")[0];if(L&&L.childNodes.length>0){var M=L.getElementsByTagName("group");for(var w=0;w<M.length;w++){var A=M[w];o[C].layout[A.getAttribute("position")]={elements:[]};for(var O=0;O<A.attributes.length;O++){var D=A.attributes[O];o[C].layout[A.getAttribute("position")][D.name]=D.value}var N=A.getElementsByTagName("*");for(var v=0;v<N.length;v++){var t=N[v];o[C].layout[A.getAttribute("position")].elements.push({type:t.tagName});for(var u=0;u<t.attributes.length;u++){var J=t.attributes[u];o[C].layout[A.getAttribute("position")].elements[v][J.name]=J.value}if(!a.utils.exists(o[C].layout[A.getAttribute("position")].elements[v].name)){o[C].layout[A.getAttribute("position")].elements[v].name=t.tagName}}}}e=false;r()}}function r(){clearInterval(j);if(!s){j=setInterval(function(){q()},100)}}function b(y,x){var w=new Image();var t=y.getAttribute("name");var v=y.getAttribute("src");var A;if(v.indexOf("data:image/png;base64,")===0){A=v}else{var u=a.utils.getAbsolutePath(n);var z=u.substr(0,u.lastIndexOf("/"));A=[z,x,v].join("/")}o[x].elements[t]={height:0,width:0,src:"",ready:false,image:w};w.onload=function(B){g(w,t,x)};w.onerror=function(B){s=true;r();l()};w.src=A}function h(){for(var u in o){var w=o[u];for(var t in w.elements){var x=w.elements[t];var v=x.image;v.onload=null;v.onerror=null;delete x.image;delete w.elements[t]}delete o[u]}}function q(){for(var t in o){if(t!="properties"){for(var u in o[t].elements){if(!o[t].elements[u].ready){return}}}}if(e===false){clearInterval(j);c(o)}}function g(t,v,u){if(o[u]&&o[u].elements[v]){o[u].elements[v].height=t.height;o[u].elements[v].width=t.width;o[u].elements[v].src=t.src;o[u].elements[v].ready=true;r()}else{a.utils.log("Loaded an image for a missing element: "+u+"."+v)}}m()}})(jwplayer);(function(a){a.html5.api=function(c,n){var m={};var f=document.createElement("div");c.parentNode.replaceChild(f,c);f.id=c.id;m.version=a.version;m.id=f.id;var l=new a.html5.model(m,f,n);var j=new a.html5.view(m,f,l);var k=new a.html5.controller(m,f,l,j);m.skin=new a.html5.skin();m.jwPlay=function(o){if(typeof o=="undefined"){e()}else{if(o.toString().toLowerCase()=="true"){k.play()}else{k.pause()}}};m.jwPause=function(o){if(typeof o=="undefined"){e()}else{if(o.toString().toLowerCase()=="true"){k.pause()}else{k.play()}}};function e(){if(l.state==a.api.events.state.PLAYING||l.state==a.api.events.state.BUFFERING){k.pause()}else{k.play()}}m.jwStop=k.stop;m.jwSeek=k.seek;m.jwPlaylistItem=k.item;m.jwPlaylistNext=k.next;m.jwPlaylistPrev=k.prev;m.jwResize=k.resize;m.jwLoad=k.load;function h(o){return function(){return l[o]}}function d(o,q,p){return function(){var r=l.plugins.object[o];if(r&&r[q]&&typeof r[q]=="function"){r[q].apply(r,p)}}}m.jwGetItem=h("item");m.jwGetPosition=h("position");m.jwGetDuration=h("duration");m.jwGetBuffer=h("buffer");m.jwGetWidth=h("width");m.jwGetHeight=h("height");m.jwGetFullscreen=h("fullscreen");m.jwSetFullscreen=k.setFullscreen;m.jwGetVolume=h("volume");m.jwSetVolume=k.setVolume;m.jwGetMute=h("mute");m.jwSetMute=k.setMute;m.jwGetStretching=h("stretching");m.jwGetState=h("state");m.jwGetVersion=function(){return m.version};m.jwGetPlaylist=function(){return l.playlist};m.jwGetPlaylistIndex=m.jwGetItem;m.jwAddEventListener=k.addEventListener;m.jwRemoveEventListener=k.removeEventListener;m.jwSendEvent=k.sendEvent;m.jwDockSetButton=function(r,o,p,q){if(l.plugins.object.dock&&l.plugins.object.dock.setButton){l.plugins.object.dock.setButton(r,o,p,q)}};m.jwControlbarShow=d("controlbar","show");m.jwControlbarHide=d("controlbar","hide");m.jwDockShow=d("dock","show");m.jwDockHide=d("dock","hide");m.jwDisplayShow=d("display","show");m.jwDisplayHide=d("display","hide");m.jwGetLevel=function(){};m.jwGetBandwidth=function(){};m.jwGetLockState=function(){};m.jwLock=function(){};m.jwUnlock=function(){};function b(){if(l.config.playlistfile){l.addEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,g);l.loadPlaylist(l.config.playlistfile)}else{if(typeof l.config.playlist=="string"){l.addEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,g);l.loadPlaylist(l.config.playlist)}else{l.loadPlaylist(l.config);setTimeout(g,25)}}}function g(o){l.removeEventListener(a.api.events.JWPLAYER_PLAYLIST_LOADED,g);l.setupPlugins();j.setup();var o={id:m.id,version:m.version};k.playerReady(o)}if(l.config.chromeless&&!a.utils.isIOS()){b()}else{m.skin.load(l.config.skin,b)}return m}})(jwplayer)};/* |
|
2782 mustache.js — Logic-less templates in JavaScript |
|
2783 |
|
2784 See http://mustache.github.com/ for more info. |
|
2785 */ |
|
2786 |
|
2787 var Mustache = function() { |
|
2788 var Renderer = function() {}; |
|
2789 |
|
2790 Renderer.prototype = { |
|
2791 otag: "{{", |
|
2792 ctag: "}}", |
|
2793 pragmas: {}, |
|
2794 buffer: [], |
|
2795 pragmas_implemented: { |
|
2796 "IMPLICIT-ITERATOR": true |
|
2797 }, |
|
2798 context: {}, |
|
2799 |
|
2800 render: function(template, context, partials, in_recursion) { |
|
2801 // reset buffer & set context |
|
2802 if(!in_recursion) { |
|
2803 this.context = context; |
|
2804 this.buffer = []; // TODO: make this non-lazy |
|
2805 } |
|
2806 |
|
2807 // fail fast |
|
2808 if(!this.includes("", template)) { |
|
2809 if(in_recursion) { |
|
2810 return template; |
|
2811 } else { |
|
2812 this.send(template); |
|
2813 return; |
|
2814 } |
|
2815 } |
|
2816 |
|
2817 template = this.render_pragmas(template); |
|
2818 var html = this.render_section(template, context, partials); |
|
2819 if(in_recursion) { |
|
2820 return this.render_tags(html, context, partials, in_recursion); |
|
2821 } |
|
2822 |
|
2823 this.render_tags(html, context, partials, in_recursion); |
|
2824 }, |
|
2825 |
|
2826 /* |
|
2827 Sends parsed lines |
|
2828 */ |
|
2829 send: function(line) { |
|
2830 if(line !== "") { |
|
2831 this.buffer.push(line); |
|
2832 } |
|
2833 }, |
|
2834 |
|
2835 /* |
|
2836 Looks for %PRAGMAS |
|
2837 */ |
|
2838 render_pragmas: function(template) { |
|
2839 // no pragmas |
|
2840 if(!this.includes("%", template)) { |
|
2841 return template; |
|
2842 } |
|
2843 |
|
2844 var that = this; |
|
2845 var regex = new RegExp(this.otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" + |
|
2846 this.ctag, "g"); |
|
2847 return template.replace(regex, function(match, pragma, options) { |
|
2848 if(!that.pragmas_implemented[pragma]) { |
|
2849 throw({message: |
|
2850 "This implementation of mustache doesn't understand the '" + |
|
2851 pragma + "' pragma"}); |
|
2852 } |
|
2853 that.pragmas[pragma] = {}; |
|
2854 if(options) { |
|
2855 var opts = options.split("="); |
|
2856 that.pragmas[pragma][opts[0]] = opts[1]; |
|
2857 } |
|
2858 return ""; |
|
2859 // ignore unknown pragmas silently |
|
2860 }); |
|
2861 }, |
|
2862 |
|
2863 /* |
|
2864 Tries to find a partial in the curent scope and render it |
|
2865 */ |
|
2866 render_partial: function(name, context, partials) { |
|
2867 name = this.trim(name); |
|
2868 if(!partials || partials[name] === undefined) { |
|
2869 throw({message: "unknown_partial '" + name + "'"}); |
|
2870 } |
|
2871 if(typeof(context[name]) != "object") { |
|
2872 return this.render(partials[name], context, partials, true); |
|
2873 } |
|
2874 return this.render(partials[name], context[name], partials, true); |
|
2875 }, |
|
2876 |
|
2877 /* |
|
2878 Renders inverted (^) and normal (#) sections |
|
2879 */ |
|
2880 render_section: function(template, context, partials) { |
|
2881 if(!this.includes("#", template) && !this.includes("^", template)) { |
|
2882 return template; |
|
2883 } |
|
2884 |
|
2885 var that = this; |
|
2886 // CSW - Added "+?" so it finds the tighest bound, not the widest |
|
2887 var regex = new RegExp(this.otag + "(\\^|\\#)\\s*(.+)\\s*" + this.ctag + |
|
2888 "\n*([\\s\\S]+?)" + this.otag + "\\/\\s*\\2\\s*" + this.ctag + |
|
2889 "\\s*", "mg"); |
|
2890 |
|
2891 // for each {{#foo}}{{/foo}} section do... |
|
2892 return template.replace(regex, function(match, type, name, content) { |
|
2893 var value = that.find(name, context); |
|
2894 if(type == "^") { // inverted section |
|
2895 if(!value || that.is_array(value) && value.length === 0) { |
|
2896 // false or empty list, render it |
|
2897 return that.render(content, context, partials, true); |
|
2898 } else { |
|
2899 return ""; |
|
2900 } |
|
2901 } else if(type == "#") { // normal section |
|
2902 if(that.is_array(value)) { // Enumerable, Let's loop! |
|
2903 return that.map(value, function(row) { |
|
2904 return that.render(content, that.create_context(row), |
|
2905 partials, true); |
|
2906 }).join(""); |
|
2907 } else if(that.is_object(value)) { // Object, Use it as subcontext! |
|
2908 return that.render(content, that.create_context(value), |
|
2909 partials, true); |
|
2910 } else if(typeof value === "function") { |
|
2911 // higher order section |
|
2912 return value.call(context, content, function(text) { |
|
2913 return that.render(text, context, partials, true); |
|
2914 }); |
|
2915 } else if(value) { // boolean section |
|
2916 return that.render(content, context, partials, true); |
|
2917 } else { |
|
2918 return ""; |
|
2919 } |
|
2920 } |
|
2921 }); |
|
2922 }, |
|
2923 |
|
2924 /* |
|
2925 Replace {{foo}} and friends with values from our view |
|
2926 */ |
|
2927 render_tags: function(template, context, partials, in_recursion) { |
|
2928 // tit for tat |
|
2929 var that = this; |
|
2930 |
|
2931 var new_regex = function() { |
|
2932 return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?" + |
|
2933 that.ctag + "+", "g"); |
|
2934 }; |
|
2935 |
|
2936 var regex = new_regex(); |
|
2937 var tag_replace_callback = function(match, operator, name) { |
|
2938 switch(operator) { |
|
2939 case "!": // ignore comments |
|
2940 return ""; |
|
2941 case "=": // set new delimiters, rebuild the replace regexp |
|
2942 that.set_delimiters(name); |
|
2943 regex = new_regex(); |
|
2944 return ""; |
|
2945 case ">": // render partial |
|
2946 return that.render_partial(name, context, partials); |
|
2947 case "{": // the triple mustache is unescaped |
|
2948 return that.find(name, context); |
|
2949 default: // escape the value |
|
2950 return that.escape(that.find(name, context)); |
|
2951 } |
|
2952 }; |
|
2953 var lines = template.split("\n"); |
|
2954 for(var i = 0; i < lines.length; i++) { |
|
2955 lines[i] = lines[i].replace(regex, tag_replace_callback, this); |
|
2956 if(!in_recursion) { |
|
2957 this.send(lines[i]); |
|
2958 } |
|
2959 } |
|
2960 |
|
2961 if(in_recursion) { |
|
2962 return lines.join("\n"); |
|
2963 } |
|
2964 }, |
|
2965 |
|
2966 set_delimiters: function(delimiters) { |
|
2967 var dels = delimiters.split(" "); |
|
2968 this.otag = this.escape_regex(dels[0]); |
|
2969 this.ctag = this.escape_regex(dels[1]); |
|
2970 }, |
|
2971 |
|
2972 escape_regex: function(text) { |
|
2973 // thank you Simon Willison |
|
2974 if(!arguments.callee.sRE) { |
|
2975 var specials = [ |
|
2976 '/', '.', '*', '+', '?', '|', |
|
2977 '(', ')', '[', ']', '{', '}', '\\' |
|
2978 ]; |
|
2979 arguments.callee.sRE = new RegExp( |
|
2980 '(\\' + specials.join('|\\') + ')', 'g' |
|
2981 ); |
|
2982 } |
|
2983 return text.replace(arguments.callee.sRE, '\\$1'); |
|
2984 }, |
|
2985 |
|
2986 /* |
|
2987 find `name` in current `context`. That is find me a value |
|
2988 from the view object |
|
2989 */ |
|
2990 find: function(name, context) { |
|
2991 name = this.trim(name); |
|
2992 |
|
2993 // Checks whether a value is thruthy or false or 0 |
|
2994 function is_kinda_truthy(bool) { |
|
2995 return bool === false || bool === 0 || bool; |
|
2996 } |
|
2997 |
|
2998 var value; |
|
2999 if(is_kinda_truthy(context[name])) { |
|
3000 value = context[name]; |
|
3001 } else if(is_kinda_truthy(this.context[name])) { |
|
3002 value = this.context[name]; |
|
3003 } |
|
3004 |
|
3005 if(typeof value === "function") { |
|
3006 return value.apply(context); |
|
3007 } |
|
3008 if(value !== undefined) { |
|
3009 return value; |
|
3010 } |
|
3011 // silently ignore unkown variables |
|
3012 return ""; |
|
3013 }, |
|
3014 |
|
3015 // Utility methods |
|
3016 |
|
3017 /* includes tag */ |
|
3018 includes: function(needle, haystack) { |
|
3019 return haystack.indexOf(this.otag + needle) != -1; |
|
3020 }, |
|
3021 |
|
3022 /* |
|
3023 Does away with nasty characters |
|
3024 */ |
|
3025 escape: function(s) { |
|
3026 s = String(s === null ? "" : s); |
|
3027 return s.replace(/&(?!\w+;)|["'<>\\]/g, function(s) { |
|
3028 switch(s) { |
|
3029 case "&": return "&"; |
|
3030 case "\\": return "\\\\"; |
|
3031 case '"': return '"'; |
|
3032 case "'": return '''; |
|
3033 case "<": return "<"; |
|
3034 case ">": return ">"; |
|
3035 default: return s; |
|
3036 } |
|
3037 }); |
|
3038 }, |
|
3039 |
|
3040 // by @langalex, support for arrays of strings |
|
3041 create_context: function(_context) { |
|
3042 if(this.is_object(_context)) { |
|
3043 return _context; |
|
3044 } else { |
|
3045 var iterator = "."; |
|
3046 if(this.pragmas["IMPLICIT-ITERATOR"]) { |
|
3047 iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator; |
|
3048 } |
|
3049 var ctx = {}; |
|
3050 ctx[iterator] = _context; |
|
3051 return ctx; |
|
3052 } |
|
3053 }, |
|
3054 |
|
3055 is_object: function(a) { |
|
3056 return a && typeof a == "object"; |
|
3057 }, |
|
3058 |
|
3059 is_array: function(a) { |
|
3060 return Object.prototype.toString.call(a) === '[object Array]'; |
|
3061 }, |
|
3062 |
|
3063 /* |
|
3064 Gets rid of leading and trailing whitespace |
|
3065 */ |
|
3066 trim: function(s) { |
|
3067 return s.replace(/^\s*|\s*$/g, ""); |
|
3068 }, |
|
3069 |
|
3070 /* |
|
3071 Why, why, why? Because IE. Cry, cry cry. |
|
3072 */ |
|
3073 map: function(array, fn) { |
|
3074 if (typeof array.map == "function") { |
|
3075 return array.map(fn); |
|
3076 } else { |
|
3077 var r = []; |
|
3078 var l = array.length; |
|
3079 for(var i = 0; i < l; i++) { |
|
3080 r.push(fn(array[i])); |
|
3081 } |
|
3082 return r; |
|
3083 } |
|
3084 } |
|
3085 }; |
|
3086 |
|
3087 return({ |
|
3088 name: "mustache.js", |
|
3089 version: "0.3.1-dev", |
|
3090 |
|
3091 /* |
|
3092 Turns a template and view into HTML |
|
3093 */ |
|
3094 to_html: function(template, view, partials, send_fun) { |
|
3095 var renderer = new Renderer(); |
|
3096 if(send_fun) { |
|
3097 renderer.send = send_fun; |
|
3098 } |
|
3099 renderer.render(template, view, partials); |
|
3100 if(!send_fun) { |
|
3101 return renderer.buffer.join("\n"); |
|
3102 } |
|
3103 } |
|
3104 }); |
|
3105 }(); |
|
3106 // ┌─────────────────────────────────────────────────────────────────────┐ \\ |
|
3107 // │ Raphaël 2.0 - JavaScript Vector Library │ \\ |
|
3108 // ├─────────────────────────────────────────────────────────────────────┤ \\ |
|
3109 // │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\ |
|
3110 // │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\ |
|
3111 // │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\ |
|
3112 // └─────────────────────────────────────────────────────────────────────┘ \\ |
|
3113 |
|
3114 // ┌──────────────────────────────────────────────────────────────────────────────────────┐ \\ |
|
3115 // │ Eve 0.3.2 - JavaScript Events Library │ \\ |
|
3116 // ├──────────────────────────────────────────────────────────────────────────────────────┤ \\ |
|
3117 // │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://dmitry.baranovskiy.com/) │ \\ |
|
3118 // │ Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. │ \\ |
|
3119 // └──────────────────────────────────────────────────────────────────────────────────────┘ \\ |
|
3120 |
|
3121 (function (glob) { |
|
3122 var version = "0.3.2", |
|
3123 has = "hasOwnProperty", |
|
3124 separator = /[\.\/]/, |
|
3125 wildcard = "*", |
|
3126 fun = function () {}, |
|
3127 numsort = function (a, b) { |
|
3128 return a - b; |
|
3129 }, |
|
3130 current_event, |
|
3131 stop, |
|
3132 events = {n: {}}, |
|
3133 |
|
3134 eve = function (name, scope) { |
|
3135 var e = events, |
|
3136 oldstop = stop, |
|
3137 args = Array.prototype.slice.call(arguments, 2), |
|
3138 listeners = eve.listeners(name), |
|
3139 z = 0, |
|
3140 f = false, |
|
3141 l, |
|
3142 indexed = [], |
|
3143 queue = {}, |
|
3144 out = [], |
|
3145 errors = []; |
|
3146 current_event = name; |
|
3147 stop = 0; |
|
3148 for (var i = 0, ii = listeners.length; i < ii; i++) if ("zIndex" in listeners[i]) { |
|
3149 indexed.push(listeners[i].zIndex); |
|
3150 if (listeners[i].zIndex < 0) { |
|
3151 queue[listeners[i].zIndex] = listeners[i]; |
|
3152 } |
|
3153 } |
|
3154 indexed.sort(numsort); |
|
3155 while (indexed[z] < 0) { |
|
3156 l = queue[indexed[z++]]; |
|
3157 out.push(l.apply(scope, args)); |
|
3158 if (stop) { |
|
3159 stop = oldstop; |
|
3160 return out; |
|
3161 } |
|
3162 } |
|
3163 for (i = 0; i < ii; i++) { |
|
3164 l = listeners[i]; |
|
3165 if ("zIndex" in l) { |
|
3166 if (l.zIndex == indexed[z]) { |
|
3167 out.push(l.apply(scope, args)); |
|
3168 if (stop) { |
|
3169 stop = oldstop; |
|
3170 return out; |
|
3171 } |
|
3172 do { |
|
3173 z++; |
|
3174 l = queue[indexed[z]]; |
|
3175 l && out.push(l.apply(scope, args)); |
|
3176 if (stop) { |
|
3177 stop = oldstop; |
|
3178 return out; |
|
3179 } |
|
3180 } while (l) |
|
3181 } else { |
|
3182 queue[l.zIndex] = l; |
|
3183 } |
|
3184 } else { |
|
3185 out.push(l.apply(scope, args)); |
|
3186 if (stop) { |
|
3187 stop = oldstop; |
|
3188 return out; |
|
3189 } |
|
3190 } |
|
3191 } |
|
3192 stop = oldstop; |
|
3193 return out.length ? out : null; |
|
3194 }; |
|
3195 |
|
3196 eve.listeners = function (name) { |
|
3197 var names = name.split(separator), |
|
3198 e = events, |
|
3199 item, |
|
3200 items, |
|
3201 k, |
|
3202 i, |
|
3203 ii, |
|
3204 j, |
|
3205 jj, |
|
3206 nes, |
|
3207 es = [e], |
|
3208 out = []; |
|
3209 for (i = 0, ii = names.length; i < ii; i++) { |
|
3210 nes = []; |
|
3211 for (j = 0, jj = es.length; j < jj; j++) { |
|
3212 e = es[j].n; |
|
3213 items = [e[names[i]], e[wildcard]]; |
|
3214 k = 2; |
|
3215 while (k--) { |
|
3216 item = items[k]; |
|
3217 if (item) { |
|
3218 nes.push(item); |
|
3219 out = out.concat(item.f || []); |
|
3220 } |
|
3221 } |
|
3222 } |
|
3223 es = nes; |
|
3224 } |
|
3225 return out; |
|
3226 }; |
|
3227 |
|
3228 |
|
3229 eve.on = function (name, f) { |
|
3230 var names = name.split(separator), |
|
3231 e = events; |
|
3232 for (var i = 0, ii = names.length; i < ii; i++) { |
|
3233 e = e.n; |
|
3234 !e[names[i]] && (e[names[i]] = {n: {}}); |
|
3235 e = e[names[i]]; |
|
3236 } |
|
3237 e.f = e.f || []; |
|
3238 for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) { |
|
3239 return fun; |
|
3240 } |
|
3241 e.f.push(f); |
|
3242 return function (zIndex) { |
|
3243 if (+zIndex == +zIndex) { |
|
3244 f.zIndex = +zIndex; |
|
3245 } |
|
3246 }; |
|
3247 }; |
|
3248 |
|
3249 eve.stop = function () { |
|
3250 stop = 1; |
|
3251 }; |
|
3252 |
|
3253 eve.nt = function (subname) { |
|
3254 if (subname) { |
|
3255 return new RegExp("(?:\\.|\\/|^)" + subname + "(?:\\.|\\/|$)").test(current_event); |
|
3256 } |
|
3257 return current_event; |
|
3258 }; |
|
3259 |
|
3260 eve.unbind = function (name, f) { |
|
3261 var names = name.split(separator), |
|
3262 e, |
|
3263 key, |
|
3264 splice, |
|
3265 cur = [events]; |
|
3266 for (var i = 0, ii = names.length; i < ii; i++) { |
|
3267 for (var j = 0; j < cur.length; j += splice.length - 2) { |
|
3268 splice = [j, 1]; |
|
3269 e = cur[j].n; |
|
3270 if (names[i] != wildcard) { |
|
3271 if (e[names[i]]) { |
|
3272 splice.push(e[names[i]]); |
|
3273 } |
|
3274 } else { |
|
3275 for (key in e) if (e[has](key)) { |
|
3276 splice.push(e[key]); |
|
3277 } |
|
3278 } |
|
3279 cur.splice.apply(cur, splice); |
|
3280 } |
|
3281 } |
|
3282 for (i = 0, ii = cur.length; i < ii; i++) { |
|
3283 e = cur[i]; |
|
3284 while (e.n) { |
|
3285 if (f) { |
|
3286 if (e.f) { |
|
3287 for (j = 0, jj = e.f.length; j < jj; j++) if (e.f[j] == f) { |
|
3288 e.f.splice(j, 1); |
|
3289 break; |
|
3290 } |
|
3291 !e.f.length && delete e.f; |
|
3292 } |
|
3293 for (key in e.n) if (e.n[has](key) && e.n[key].f) { |
|
3294 var funcs = e.n[key].f; |
|
3295 for (j = 0, jj = funcs.length; j < jj; j++) if (funcs[j] == f) { |
|
3296 funcs.splice(j, 1); |
|
3297 break; |
|
3298 } |
|
3299 !funcs.length && delete e.n[key].f; |
|
3300 } |
|
3301 } else { |
|
3302 delete e.f; |
|
3303 for (key in e.n) if (e.n[has](key) && e.n[key].f) { |
|
3304 delete e.n[key].f; |
|
3305 } |
|
3306 } |
|
3307 e = e.n; |
|
3308 } |
|
3309 } |
|
3310 }; |
|
3311 |
|
3312 eve.version = version; |
|
3313 eve.toString = function () { |
|
3314 return "You are running Eve " + version; |
|
3315 }; |
|
3316 (typeof module != "undefined" && module.exports) ? (module.exports = eve) : (glob.eve = eve); |
|
3317 })(this); |
|
3318 |
|
3319 // ┌─────────────────────────────────────────────────────────────────────┐ \\ |
|
3320 // │ "Raphaël 2.0" - JavaScript Vector Library │ \\ |
|
3321 // ├─────────────────────────────────────────────────────────────────────┤ \\ |
|
3322 // │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\ |
|
3323 // │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\ |
|
3324 // │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\ |
|
3325 // └─────────────────────────────────────────────────────────────────────┘ \\ |
|
3326 (function () { |
|
3327 |
|
3328 function R(first) { |
|
3329 if (R.is(first, "function")) { |
|
3330 return loaded ? first() : eve.on("DOMload", first); |
|
3331 } else if (R.is(first, array)) { |
|
3332 var a = first, |
|
3333 cnv = R._engine.create[apply](R, a.splice(0, 3 + R.is(a[0], nu))), |
|
3334 res = cnv.set(), |
|
3335 i = 0, |
|
3336 ii = a.length, |
|
3337 j; |
|
3338 for (; i < ii; i++) { |
|
3339 j = a[i] || {}; |
|
3340 elements[has](j.type) && res.push(cnv[j.type]().attr(j)); |
|
3341 } |
|
3342 return res; |
|
3343 } else { |
|
3344 var args = Array.prototype.slice.call(arguments, 0); |
|
3345 if (R.is(args[args.length - 1], "function")) { |
|
3346 var f = args.pop(); |
|
3347 return loaded ? f.call(R._engine.create[apply](R, args)) : eve.on("DOMload", function () { |
|
3348 f.call(R._engine.create[apply](R, args)); |
|
3349 }); |
|
3350 } else { |
|
3351 return R._engine.create[apply](R, arguments); |
|
3352 } |
|
3353 } |
|
3354 } |
|
3355 R.version = "2.0.0"; |
|
3356 R.eve = eve; |
|
3357 var loaded, |
|
3358 separator = /[, ]+/, |
|
3359 elements = {circle: 1, rect: 1, path: 1, ellipse: 1, text: 1, image: 1}, |
|
3360 formatrg = /\{(\d+)\}/g, |
|
3361 proto = "prototype", |
|
3362 has = "hasOwnProperty", |
|
3363 g = { |
|
3364 doc: document, |
|
3365 win: window |
|
3366 }, |
|
3367 oldRaphael = { |
|
3368 was: Object.prototype[has].call(g.win, "Raphael"), |
|
3369 is: g.win.Raphael |
|
3370 }, |
|
3371 Paper = function () { |
|
3372 |
|
3373 |
|
3374 this.ca = this.customAttributes = {}; |
|
3375 }, |
|
3376 paperproto, |
|
3377 appendChild = "appendChild", |
|
3378 apply = "apply", |
|
3379 concat = "concat", |
|
3380 supportsTouch = "createTouch" in g.doc, |
|
3381 E = "", |
|
3382 S = " ", |
|
3383 Str = String, |
|
3384 split = "split", |
|
3385 events = "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel"[split](S), |
|
3386 touchMap = { |
|
3387 mousedown: "touchstart", |
|
3388 mousemove: "touchmove", |
|
3389 mouseup: "touchend" |
|
3390 }, |
|
3391 lowerCase = Str.prototype.toLowerCase, |
|
3392 math = Math, |
|
3393 mmax = math.max, |
|
3394 mmin = math.min, |
|
3395 abs = math.abs, |
|
3396 pow = math.pow, |
|
3397 PI = math.PI, |
|
3398 nu = "number", |
|
3399 string = "string", |
|
3400 array = "array", |
|
3401 toString = "toString", |
|
3402 fillString = "fill", |
|
3403 objectToString = Object.prototype.toString, |
|
3404 paper = {}, |
|
3405 push = "push", |
|
3406 ISURL = R._ISURL = /^url\(['"]?([^\)]+?)['"]?\)$/i, |
|
3407 colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i, |
|
3408 isnan = {"NaN": 1, "Infinity": 1, "-Infinity": 1}, |
|
3409 bezierrg = /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/, |
|
3410 round = math.round, |
|
3411 setAttribute = "setAttribute", |
|
3412 toFloat = parseFloat, |
|
3413 toInt = parseInt, |
|
3414 upperCase = Str.prototype.toUpperCase, |
|
3415 availableAttrs = R._availableAttrs = { |
|
3416 "arrow-end": "none", |
|
3417 "arrow-start": "none", |
|
3418 blur: 0, |
|
3419 "clip-rect": "0 0 1e9 1e9", |
|
3420 cursor: "default", |
|
3421 cx: 0, |
|
3422 cy: 0, |
|
3423 fill: "#fff", |
|
3424 "fill-opacity": 1, |
|
3425 font: '10px "Arial"', |
|
3426 "font-family": '"Arial"', |
|
3427 "font-size": "10", |
|
3428 "font-style": "normal", |
|
3429 "font-weight": 400, |
|
3430 gradient: 0, |
|
3431 height: 0, |
|
3432 href: "http://raphaeljs.com/", |
|
3433 opacity: 1, |
|
3434 path: "M0,0", |
|
3435 r: 0, |
|
3436 rx: 0, |
|
3437 ry: 0, |
|
3438 src: "", |
|
3439 stroke: "#000", |
|
3440 "stroke-dasharray": "", |
|
3441 "stroke-linecap": "butt", |
|
3442 "stroke-linejoin": "butt", |
|
3443 "stroke-miterlimit": 0, |
|
3444 "stroke-opacity": 1, |
|
3445 "stroke-width": 1, |
|
3446 target: "_blank", |
|
3447 "text-anchor": "middle", |
|
3448 title: "Raphael", |
|
3449 transform: "", |
|
3450 width: 0, |
|
3451 x: 0, |
|
3452 y: 0 |
|
3453 }, |
|
3454 availableAnimAttrs = R._availableAnimAttrs = { |
|
3455 blur: nu, |
|
3456 "clip-rect": "csv", |
|
3457 cx: nu, |
|
3458 cy: nu, |
|
3459 fill: "colour", |
|
3460 "fill-opacity": nu, |
|
3461 "font-size": nu, |
|
3462 height: nu, |
|
3463 opacity: nu, |
|
3464 path: "path", |
|
3465 r: nu, |
|
3466 rx: nu, |
|
3467 ry: nu, |
|
3468 stroke: "colour", |
|
3469 "stroke-opacity": nu, |
|
3470 "stroke-width": nu, |
|
3471 transform: "transform", |
|
3472 width: nu, |
|
3473 x: nu, |
|
3474 y: nu |
|
3475 }, |
|
3476 commaSpaces = /\s*,\s*/, |
|
3477 hsrg = {hs: 1, rg: 1}, |
|
3478 p2s = /,?([achlmqrstvxz]),?/gi, |
|
3479 pathCommand = /([achlmrqstvz])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?\s*,?\s*)+)/ig, |
|
3480 tCommand = /([rstm])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?\s*,?\s*)+)/ig, |
|
3481 pathValues = /(-?\d*\.?\d*(?:e[\-+]?\d+)?)\s*,?\s*/ig, |
|
3482 radial_gradient = R._radial_gradient = /^r(?:\(([^,]+?)\s*,\s*([^\)]+?)\))?/, |
|
3483 eldata = {}, |
|
3484 sortByKey = function (a, b) { |
|
3485 return a.key - b.key; |
|
3486 }, |
|
3487 sortByNumber = function (a, b) { |
|
3488 return toFloat(a) - toFloat(b); |
|
3489 }, |
|
3490 fun = function () {}, |
|
3491 pipe = function (x) { |
|
3492 return x; |
|
3493 }, |
|
3494 rectPath = R._rectPath = function (x, y, w, h, r) { |
|
3495 if (r) { |
|
3496 return [["M", x + r, y], ["l", w - r * 2, 0], ["a", r, r, 0, 0, 1, r, r], ["l", 0, h - r * 2], ["a", r, r, 0, 0, 1, -r, r], ["l", r * 2 - w, 0], ["a", r, r, 0, 0, 1, -r, -r], ["l", 0, r * 2 - h], ["a", r, r, 0, 0, 1, r, -r], ["z"]]; |
|
3497 } |
|
3498 return [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]]; |
|
3499 }, |
|
3500 ellipsePath = function (x, y, rx, ry) { |
|
3501 if (ry == null) { |
|
3502 ry = rx; |
|
3503 } |
|
3504 return [["M", x, y], ["m", 0, -ry], ["a", rx, ry, 0, 1, 1, 0, 2 * ry], ["a", rx, ry, 0, 1, 1, 0, -2 * ry], ["z"]]; |
|
3505 }, |
|
3506 getPath = R._getPath = { |
|
3507 path: function (el) { |
|
3508 return el.attr("path"); |
|
3509 }, |
|
3510 circle: function (el) { |
|
3511 var a = el.attrs; |
|
3512 return ellipsePath(a.cx, a.cy, a.r); |
|
3513 }, |
|
3514 ellipse: function (el) { |
|
3515 var a = el.attrs; |
|
3516 return ellipsePath(a.cx, a.cy, a.rx, a.ry); |
|
3517 }, |
|
3518 rect: function (el) { |
|
3519 var a = el.attrs; |
|
3520 return rectPath(a.x, a.y, a.width, a.height, a.r); |
|
3521 }, |
|
3522 image: function (el) { |
|
3523 var a = el.attrs; |
|
3524 return rectPath(a.x, a.y, a.width, a.height); |
|
3525 }, |
|
3526 text: function (el) { |
|
3527 var bbox = el._getBBox(); |
|
3528 return rectPath(bbox.x, bbox.y, bbox.width, bbox.height); |
|
3529 } |
|
3530 }, |
|
3531 mapPath = R.mapPath = function (path, matrix) { |
|
3532 if (!matrix) { |
|
3533 return path; |
|
3534 } |
|
3535 var x, y, i, j, pathi; |
|
3536 path = path2curve(path); |
|
3537 for (i = 0, ii = path.length; i < ii; i++) { |
|
3538 pathi = path[i]; |
|
3539 for (j = 1, jj = pathi.length; j < jj; j += 2) { |
|
3540 x = matrix.x(pathi[j], pathi[j + 1]); |
|
3541 y = matrix.y(pathi[j], pathi[j + 1]); |
|
3542 pathi[j] = x; |
|
3543 pathi[j + 1] = y; |
|
3544 } |
|
3545 } |
|
3546 return path; |
|
3547 }; |
|
3548 |
|
3549 R._g = g; |
|
3550 |
|
3551 R.type = (g.win.SVGAngle || g.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML"); |
|
3552 if (R.type == "VML") { |
|
3553 var d = g.doc.createElement("div"), |
|
3554 b; |
|
3555 d.innerHTML = '<v:shape adj="1"/>'; |
|
3556 b = d.firstChild; |
|
3557 b.style.behavior = "url(#default#VML)"; |
|
3558 if (!(b && typeof b.adj == "object")) { |
|
3559 return (R.type = E); |
|
3560 } |
|
3561 d = null; |
|
3562 } |
|
3563 |
|
3564 |
|
3565 R.svg = !(R.vml = R.type == "VML"); |
|
3566 R._Paper = Paper; |
|
3567 |
|
3568 R.fn = paperproto = Paper.prototype = R.prototype; |
|
3569 R._id = 0; |
|
3570 R._oid = 0; |
|
3571 |
|
3572 R.is = function (o, type) { |
|
3573 type = lowerCase.call(type); |
|
3574 if (type == "finite") { |
|
3575 return !isnan[has](+o); |
|
3576 } |
|
3577 if (type == "array") { |
|
3578 return o instanceof Array; |
|
3579 } |
|
3580 return (type == "null" && o === null) || |
|
3581 (type == typeof o && o !== null) || |
|
3582 (type == "object" && o === Object(o)) || |
|
3583 (type == "array" && Array.isArray && Array.isArray(o)) || |
|
3584 objectToString.call(o).slice(8, -1).toLowerCase() == type; |
|
3585 }; |
|
3586 |
|
3587 R.angle = function (x1, y1, x2, y2, x3, y3) { |
|
3588 if (x3 == null) { |
|
3589 var x = x1 - x2, |
|
3590 y = y1 - y2; |
|
3591 if (!x && !y) { |
|
3592 return 0; |
|
3593 } |
|
3594 return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360; |
|
3595 } else { |
|
3596 return R.angle(x1, y1, x3, y3) - R.angle(x2, y2, x3, y3); |
|
3597 } |
|
3598 }; |
|
3599 |
|
3600 R.rad = function (deg) { |
|
3601 return deg % 360 * PI / 180; |
|
3602 }; |
|
3603 |
|
3604 R.deg = function (rad) { |
|
3605 return rad * 180 / PI % 360; |
|
3606 }; |
|
3607 |
|
3608 R.snapTo = function (values, value, tolerance) { |
|
3609 tolerance = R.is(tolerance, "finite") ? tolerance : 10; |
|
3610 if (R.is(values, array)) { |
|
3611 var i = values.length; |
|
3612 while (i--) if (abs(values[i] - value) <= tolerance) { |
|
3613 return values[i]; |
|
3614 } |
|
3615 } else { |
|
3616 values = +values; |
|
3617 var rem = value % values; |
|
3618 if (rem < tolerance) { |
|
3619 return value - rem; |
|
3620 } |
|
3621 if (rem > values - tolerance) { |
|
3622 return value - rem + values; |
|
3623 } |
|
3624 } |
|
3625 return value; |
|
3626 }; |
|
3627 |
|
3628 |
|
3629 var createUUID = R.createUUID = (function (uuidRegEx, uuidReplacer) { |
|
3630 return function () { |
|
3631 return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(uuidRegEx, uuidReplacer).toUpperCase(); |
|
3632 }; |
|
3633 })(/[xy]/g, function (c) { |
|
3634 var r = math.random() * 16 | 0, |
|
3635 v = c == "x" ? r : (r & 3 | 8); |
|
3636 return v.toString(16); |
|
3637 }); |
|
3638 |
|
3639 |
|
3640 R.setWindow = function (newwin) { |
|
3641 eve("setWindow", R, g.win, newwin); |
|
3642 g.win = newwin; |
|
3643 g.doc = g.win.document; |
|
3644 if (initWin) { |
|
3645 initWin(g.win); |
|
3646 } |
|
3647 }; |
|
3648 var toHex = function (color) { |
|
3649 if (R.vml) { |
|
3650 // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/ |
|
3651 var trim = /^\s+|\s+$/g; |
|
3652 var bod; |
|
3653 try { |
|
3654 var docum = new ActiveXObject("htmlfile"); |
|
3655 docum.write("<body>"); |
|
3656 docum.close(); |
|
3657 bod = docum.body; |
|
3658 } catch(e) { |
|
3659 bod = createPopup().document.body; |
|
3660 } |
|
3661 var range = bod.createTextRange(); |
|
3662 toHex = cacher(function (color) { |
|
3663 try { |
|
3664 bod.style.color = Str(color).replace(trim, E); |
|
3665 var value = range.queryCommandValue("ForeColor"); |
|
3666 value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16); |
|
3667 return "#" + ("000000" + value.toString(16)).slice(-6); |
|
3668 } catch(e) { |
|
3669 return "none"; |
|
3670 } |
|
3671 }); |
|
3672 } else { |
|
3673 var i = g.doc.createElement("i"); |
|
3674 i.title = "Rapha\xebl Colour Picker"; |
|
3675 i.style.display = "none"; |
|
3676 g.doc.body.appendChild(i); |
|
3677 toHex = cacher(function (color) { |
|
3678 i.style.color = color; |
|
3679 return g.doc.defaultView.getComputedStyle(i, E).getPropertyValue("color"); |
|
3680 }); |
|
3681 } |
|
3682 return toHex(color); |
|
3683 }, |
|
3684 hsbtoString = function () { |
|
3685 return "hsb(" + [this.h, this.s, this.b] + ")"; |
|
3686 }, |
|
3687 hsltoString = function () { |
|
3688 return "hsl(" + [this.h, this.s, this.l] + ")"; |
|
3689 }, |
|
3690 rgbtoString = function () { |
|
3691 return this.hex; |
|
3692 }, |
|
3693 prepareRGB = function (r, g, b) { |
|
3694 if (g == null && R.is(r, "object") && "r" in r && "g" in r && "b" in r) { |
|
3695 b = r.b; |
|
3696 g = r.g; |
|
3697 r = r.r; |
|
3698 } |
|
3699 if (g == null && R.is(r, string)) { |
|
3700 var clr = R.getRGB(r); |
|
3701 r = clr.r; |
|
3702 g = clr.g; |
|
3703 b = clr.b; |
|
3704 } |
|
3705 if (r > 1 || g > 1 || b > 1) { |
|
3706 r /= 255; |
|
3707 g /= 255; |
|
3708 b /= 255; |
|
3709 } |
|
3710 |
|
3711 return [r, g, b]; |
|
3712 }, |
|
3713 packageRGB = function (r, g, b, o) { |
|
3714 r *= 255; |
|
3715 g *= 255; |
|
3716 b *= 255; |
|
3717 var rgb = { |
|
3718 r: r, |
|
3719 g: g, |
|
3720 b: b, |
|
3721 hex: R.rgb(r, g, b), |
|
3722 toString: rgbtoString |
|
3723 }; |
|
3724 R.is(o, "finite") && (rgb.opacity = o); |
|
3725 return rgb; |
|
3726 }; |
|
3727 |
|
3728 |
|
3729 R.color = function (clr) { |
|
3730 var rgb; |
|
3731 if (R.is(clr, "object") && "h" in clr && "s" in clr && "b" in clr) { |
|
3732 rgb = R.hsb2rgb(clr); |
|
3733 clr.r = rgb.r; |
|
3734 clr.g = rgb.g; |
|
3735 clr.b = rgb.b; |
|
3736 clr.hex = rgb.hex; |
|
3737 } else if (R.is(clr, "object") && "h" in clr && "s" in clr && "l" in clr) { |
|
3738 rgb = R.hsl2rgb(clr); |
|
3739 clr.r = rgb.r; |
|
3740 clr.g = rgb.g; |
|
3741 clr.b = rgb.b; |
|
3742 clr.hex = rgb.hex; |
|
3743 } else { |
|
3744 if (R.is(clr, "string")) { |
|
3745 clr = R.getRGB(clr); |
|
3746 } |
|
3747 if (R.is(clr, "object") && "r" in clr && "g" in clr && "b" in clr) { |
|
3748 rgb = R.rgb2hsl(clr); |
|
3749 clr.h = rgb.h; |
|
3750 clr.s = rgb.s; |
|
3751 clr.l = rgb.l; |
|
3752 rgb = R.rgb2hsb(clr); |
|
3753 clr.v = rgb.b; |
|
3754 } else { |
|
3755 clr = {hex: "none"}; |
|
3756 crl.r = clr.g = clr.b = clr.h = clr.s = clr.v = clr.l = -1; |
|
3757 } |
|
3758 } |
|
3759 clr.toString = rgbtoString; |
|
3760 return clr; |
|
3761 }; |
|
3762 |
|
3763 R.hsb2rgb = function (h, s, v, o) { |
|
3764 if (this.is(h, "object") && "h" in h && "s" in h && "b" in h) { |
|
3765 v = h.b; |
|
3766 s = h.s; |
|
3767 h = h.h; |
|
3768 o = h.o; |
|
3769 } |
|
3770 h *= 360; |
|
3771 var R, G, B, X, C; |
|
3772 h = (h % 360) / 60; |
|
3773 C = v * s; |
|
3774 X = C * (1 - abs(h % 2 - 1)); |
|
3775 R = G = B = v - C; |
|
3776 |
|
3777 h = ~~h; |
|
3778 R += [C, X, 0, 0, X, C][h]; |
|
3779 G += [X, C, C, X, 0, 0][h]; |
|
3780 B += [0, 0, X, C, C, X][h]; |
|
3781 return packageRGB(R, G, B, o); |
|
3782 }; |
|
3783 |
|
3784 R.hsl2rgb = function (h, s, l, o) { |
|
3785 if (this.is(h, "object") && "h" in h && "s" in h && "l" in h) { |
|
3786 l = h.l; |
|
3787 s = h.s; |
|
3788 h = h.h; |
|
3789 } |
|
3790 if (h > 1 || s > 1 || l > 1) { |
|
3791 h /= 360; |
|
3792 s /= 100; |
|
3793 l /= 100; |
|
3794 } |
|
3795 h *= 360; |
|
3796 var R, G, B, X, C; |
|
3797 h = (h % 360) / 60; |
|
3798 C = 2 * s * (l < .5 ? l : 1 - l); |
|
3799 X = C * (1 - abs(h % 2 - 1)); |
|
3800 R = G = B = l - C / 2; |
|
3801 |
|
3802 h = ~~h; |
|
3803 R += [C, X, 0, 0, X, C][h]; |
|
3804 G += [X, C, C, X, 0, 0][h]; |
|
3805 B += [0, 0, X, C, C, X][h]; |
|
3806 return packageRGB(R, G, B, o); |
|
3807 }; |
|
3808 |
|
3809 R.rgb2hsb = function (r, g, b) { |
|
3810 b = prepareRGB(r, g, b); |
|
3811 r = b[0]; |
|
3812 g = b[1]; |
|
3813 b = b[2]; |
|
3814 |
|
3815 var H, S, V, C; |
|
3816 V = mmax(r, g, b); |
|
3817 C = V - mmin(r, g, b); |
|
3818 H = (C == 0 ? null : |
|
3819 V == r ? (g - b) / C : |
|
3820 V == g ? (b - r) / C + 2 : |
|
3821 (r - g) / C + 4 |
|
3822 ); |
|
3823 H = ((H + 360) % 6) * 60 / 360; |
|
3824 S = C == 0 ? 0 : C / V; |
|
3825 return {h: H, s: S, b: V, toString: hsbtoString}; |
|
3826 }; |
|
3827 |
|
3828 R.rgb2hsl = function (r, g, b) { |
|
3829 b = prepareRGB(r, g, b); |
|
3830 r = b[0]; |
|
3831 g = b[1]; |
|
3832 b = b[2]; |
|
3833 |
|
3834 var H, S, L, M, m, C; |
|
3835 M = mmax(r, g, b); |
|
3836 m = mmin(r, g, b); |
|
3837 C = M - m; |
|
3838 H = (C == 0 ? null : |
|
3839 M == r ? (g - b) / C : |
|
3840 M == g ? (b - r) / C + 2 : |
|
3841 (r - g) / C + 4); |
|
3842 H = ((H + 360) % 6) * 60 / 360; |
|
3843 L = (M + m) / 2; |
|
3844 S = (C == 0 ? 0 : |
|
3845 L < .5 ? C / (2 * L) : |
|
3846 C / (2 - 2 * L)); |
|
3847 return {h: H, s: S, l: L, toString: hsltoString}; |
|
3848 }; |
|
3849 R._path2string = function () { |
|
3850 return this.join(",").replace(p2s, "$1"); |
|
3851 }; |
|
3852 function repush(array, item) { |
|
3853 for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) { |
|
3854 return array.push(array.splice(i, 1)[0]); |
|
3855 } |
|
3856 } |
|
3857 function cacher(f, scope, postprocessor) { |
|
3858 function newf() { |
|
3859 var arg = Array.prototype.slice.call(arguments, 0), |
|
3860 args = arg.join("\u2400"), |
|
3861 cache = newf.cache = newf.cache || {}, |
|
3862 count = newf.count = newf.count || []; |
|
3863 if (cache[has](args)) { |
|
3864 repush(count, args); |
|
3865 return postprocessor ? postprocessor(cache[args]) : cache[args]; |
|
3866 } |
|
3867 count.length >= 1e3 && delete cache[count.shift()]; |
|
3868 count.push(args); |
|
3869 cache[args] = f[apply](scope, arg); |
|
3870 return postprocessor ? postprocessor(cache[args]) : cache[args]; |
|
3871 } |
|
3872 return newf; |
|
3873 } |
|
3874 |
|
3875 var preload = R._preload = function (src, f) { |
|
3876 var img = g.doc.createElement("img"); |
|
3877 img.style.cssText = "position:absolute;left:-9999em;top-9999em"; |
|
3878 img.onload = function () { |
|
3879 f.call(this); |
|
3880 this.onload = null; |
|
3881 g.doc.body.removeChild(this); |
|
3882 }; |
|
3883 img.onerror = function () { |
|
3884 g.doc.body.removeChild(this); |
|
3885 }; |
|
3886 g.doc.body.appendChild(img); |
|
3887 img.src = src; |
|
3888 }; |
|
3889 |
|
3890 function clrToString() { |
|
3891 return this.hex; |
|
3892 } |
|
3893 |
|
3894 |
|
3895 R.getRGB = cacher(function (colour) { |
|
3896 if (!colour || !!((colour = Str(colour)).indexOf("-") + 1)) { |
|
3897 return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString}; |
|
3898 } |
|
3899 if (colour == "none") { |
|
3900 return {r: -1, g: -1, b: -1, hex: "none", toString: clrToString}; |
|
3901 } |
|
3902 !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour)); |
|
3903 var res, |
|
3904 red, |
|
3905 green, |
|
3906 blue, |
|
3907 opacity, |
|
3908 t, |
|
3909 values, |
|
3910 rgb = colour.match(colourRegExp); |
|
3911 if (rgb) { |
|
3912 if (rgb[2]) { |
|
3913 blue = toInt(rgb[2].substring(5), 16); |
|
3914 green = toInt(rgb[2].substring(3, 5), 16); |
|
3915 red = toInt(rgb[2].substring(1, 3), 16); |
|
3916 } |
|
3917 if (rgb[3]) { |
|
3918 blue = toInt((t = rgb[3].charAt(3)) + t, 16); |
|
3919 green = toInt((t = rgb[3].charAt(2)) + t, 16); |
|
3920 red = toInt((t = rgb[3].charAt(1)) + t, 16); |
|
3921 } |
|
3922 if (rgb[4]) { |
|
3923 values = rgb[4][split](commaSpaces); |
|
3924 red = toFloat(values[0]); |
|
3925 values[0].slice(-1) == "%" && (red *= 2.55); |
|
3926 green = toFloat(values[1]); |
|
3927 values[1].slice(-1) == "%" && (green *= 2.55); |
|
3928 blue = toFloat(values[2]); |
|
3929 values[2].slice(-1) == "%" && (blue *= 2.55); |
|
3930 rgb[1].toLowerCase().slice(0, 4) == "rgba" && (opacity = toFloat(values[3])); |
|
3931 values[3] && values[3].slice(-1) == "%" && (opacity /= 100); |
|
3932 } |
|
3933 if (rgb[5]) { |
|
3934 values = rgb[5][split](commaSpaces); |
|
3935 red = toFloat(values[0]); |
|
3936 values[0].slice(-1) == "%" && (red *= 2.55); |
|
3937 green = toFloat(values[1]); |
|
3938 values[1].slice(-1) == "%" && (green *= 2.55); |
|
3939 blue = toFloat(values[2]); |
|
3940 values[2].slice(-1) == "%" && (blue *= 2.55); |
|
3941 (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360); |
|
3942 rgb[1].toLowerCase().slice(0, 4) == "hsba" && (opacity = toFloat(values[3])); |
|
3943 values[3] && values[3].slice(-1) == "%" && (opacity /= 100); |
|
3944 return R.hsb2rgb(red, green, blue, opacity); |
|
3945 } |
|
3946 if (rgb[6]) { |
|
3947 values = rgb[6][split](commaSpaces); |
|
3948 red = toFloat(values[0]); |
|
3949 values[0].slice(-1) == "%" && (red *= 2.55); |
|
3950 green = toFloat(values[1]); |
|
3951 values[1].slice(-1) == "%" && (green *= 2.55); |
|
3952 blue = toFloat(values[2]); |
|
3953 values[2].slice(-1) == "%" && (blue *= 2.55); |
|
3954 (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360); |
|
3955 rgb[1].toLowerCase().slice(0, 4) == "hsla" && (opacity = toFloat(values[3])); |
|
3956 values[3] && values[3].slice(-1) == "%" && (opacity /= 100); |
|
3957 return R.hsl2rgb(red, green, blue, opacity); |
|
3958 } |
|
3959 rgb = {r: red, g: green, b: blue, toString: clrToString}; |
|
3960 rgb.hex = "#" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1); |
|
3961 R.is(opacity, "finite") && (rgb.opacity = opacity); |
|
3962 return rgb; |
|
3963 } |
|
3964 return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString}; |
|
3965 }, R); |
|
3966 |
|
3967 R.hsb = cacher(function (h, s, b) { |
|
3968 return R.hsb2rgb(h, s, b).hex; |
|
3969 }); |
|
3970 |
|
3971 R.hsl = cacher(function (h, s, l) { |
|
3972 return R.hsl2rgb(h, s, l).hex; |
|
3973 }); |
|
3974 |
|
3975 R.rgb = cacher(function (r, g, b) { |
|
3976 return "#" + (16777216 | b | (g << 8) | (r << 16)).toString(16).slice(1); |
|
3977 }); |
|
3978 |
|
3979 R.getColor = function (value) { |
|
3980 var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75}, |
|
3981 rgb = this.hsb2rgb(start.h, start.s, start.b); |
|
3982 start.h += .075; |
|
3983 if (start.h > 1) { |
|
3984 start.h = 0; |
|
3985 start.s -= .2; |
|
3986 start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b}); |
|
3987 } |
|
3988 return rgb.hex; |
|
3989 }; |
|
3990 |
|
3991 R.getColor.reset = function () { |
|
3992 delete this.start; |
|
3993 }; |
|
3994 |
|
3995 // http://schepers.cc/getting-to-the-point |
|
3996 function catmullRom2bezier(crp) { |
|
3997 var d = []; |
|
3998 for (var i = 0, iLen = crp.length; iLen - 2 > i; i += 2) { |
|
3999 var p = [{x: +crp[i], y: +crp[i + 1]}, |
|
4000 {x: +crp[i], y: +crp[i + 1]}, |
|
4001 {x: +crp[i + 2], y: +crp[i + 3]}, |
|
4002 {x: +crp[i + 4], y: +crp[i + 5]}]; |
|
4003 if (iLen - 4 == i) { |
|
4004 p[0] = {x: +crp[i - 2], y: +crp[i - 1]}; |
|
4005 p[3] = p[2]; |
|
4006 } else if (i) { |
|
4007 p[0] = {x: +crp[i - 2], y: +crp[i - 1]}; |
|
4008 } |
|
4009 d.push(["C", |
|
4010 (-p[0].x + 6 * p[1].x + p[2].x) / 6, |
|
4011 (-p[0].y + 6 * p[1].y + p[2].y) / 6, |
|
4012 (p[1].x + 6 * p[2].x - p[3].x) / 6, |
|
4013 (p[1].y + 6*p[2].y - p[3].y) / 6, |
|
4014 p[2].x, |
|
4015 p[2].y |
|
4016 ]); |
|
4017 } |
|
4018 |
|
4019 return d; |
|
4020 } |
|
4021 |
|
4022 R.parsePathString = cacher(function (pathString) { |
|
4023 if (!pathString) { |
|
4024 return null; |
|
4025 } |
|
4026 var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, z: 0}, |
|
4027 data = []; |
|
4028 if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption |
|
4029 data = pathClone(pathString); |
|
4030 } |
|
4031 if (!data.length) { |
|
4032 Str(pathString).replace(pathCommand, function (a, b, c) { |
|
4033 var params = [], |
|
4034 name = b.toLowerCase(); |
|
4035 c.replace(pathValues, function (a, b) { |
|
4036 b && params.push(+b); |
|
4037 }); |
|
4038 if (name == "m" && params.length > 2) { |
|
4039 data.push([b][concat](params.splice(0, 2))); |
|
4040 name = "l"; |
|
4041 b = b == "m" ? "l" : "L"; |
|
4042 } |
|
4043 if (name == "r") { |
|
4044 data.push([b][concat](params)); |
|
4045 } else while (params.length >= paramCounts[name]) { |
|
4046 data.push([b][concat](params.splice(0, paramCounts[name]))); |
|
4047 if (!paramCounts[name]) { |
|
4048 break; |
|
4049 } |
|
4050 } |
|
4051 }); |
|
4052 } |
|
4053 data.toString = R._path2string; |
|
4054 return data; |
|
4055 }); |
|
4056 |
|
4057 R.parseTransformString = cacher(function (TString) { |
|
4058 if (!TString) { |
|
4059 return null; |
|
4060 } |
|
4061 var paramCounts = {r: 3, s: 4, t: 2, m: 6}, |
|
4062 data = []; |
|
4063 if (R.is(TString, array) && R.is(TString[0], array)) { // rough assumption |
|
4064 data = pathClone(TString); |
|
4065 } |
|
4066 if (!data.length) { |
|
4067 Str(TString).replace(tCommand, function (a, b, c) { |
|
4068 var params = [], |
|
4069 name = lowerCase.call(b); |
|
4070 c.replace(pathValues, function (a, b) { |
|
4071 b && params.push(+b); |
|
4072 }); |
|
4073 data.push([b][concat](params)); |
|
4074 }); |
|
4075 } |
|
4076 data.toString = R._path2string; |
|
4077 return data; |
|
4078 }); |
|
4079 |
|
4080 R.findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) { |
|
4081 var t1 = 1 - t, |
|
4082 t13 = pow(t1, 3), |
|
4083 t12 = pow(t1, 2), |
|
4084 t2 = t * t, |
|
4085 t3 = t2 * t, |
|
4086 x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x, |
|
4087 y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y, |
|
4088 mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x), |
|
4089 my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y), |
|
4090 nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x), |
|
4091 ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y), |
|
4092 ax = t1 * p1x + t * c1x, |
|
4093 ay = t1 * p1y + t * c1y, |
|
4094 cx = t1 * c2x + t * p2x, |
|
4095 cy = t1 * c2y + t * p2y, |
|
4096 alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI); |
|
4097 (mx > nx || my < ny) && (alpha += 180); |
|
4098 return { |
|
4099 x: x, |
|
4100 y: y, |
|
4101 m: {x: mx, y: my}, |
|
4102 n: {x: nx, y: ny}, |
|
4103 start: {x: ax, y: ay}, |
|
4104 end: {x: cx, y: cy}, |
|
4105 alpha: alpha |
|
4106 }; |
|
4107 }; |
|
4108 var pathDimensions = cacher(function (path) { |
|
4109 if (!path) { |
|
4110 return {x: 0, y: 0, width: 0, height: 0}; |
|
4111 } |
|
4112 path = path2curve(path); |
|
4113 var x = 0, |
|
4114 y = 0, |
|
4115 X = [], |
|
4116 Y = [], |
|
4117 p; |
|
4118 for (var i = 0, ii = path.length; i < ii; i++) { |
|
4119 p = path[i]; |
|
4120 if (p[0] == "M") { |
|
4121 x = p[1]; |
|
4122 y = p[2]; |
|
4123 X.push(x); |
|
4124 Y.push(y); |
|
4125 } else { |
|
4126 var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]); |
|
4127 X = X[concat](dim.min.x, dim.max.x); |
|
4128 Y = Y[concat](dim.min.y, dim.max.y); |
|
4129 x = p[5]; |
|
4130 y = p[6]; |
|
4131 } |
|
4132 } |
|
4133 var xmin = mmin[apply](0, X), |
|
4134 ymin = mmin[apply](0, Y); |
|
4135 return { |
|
4136 x: xmin, |
|
4137 y: ymin, |
|
4138 width: mmax[apply](0, X) - xmin, |
|
4139 height: mmax[apply](0, Y) - ymin |
|
4140 }; |
|
4141 }, null, function (o) { |
|
4142 return { |
|
4143 x: o.x, |
|
4144 y: o.y, |
|
4145 width: o.width, |
|
4146 height: o.height |
|
4147 }; |
|
4148 }), |
|
4149 pathClone = function (pathArray) { |
|
4150 var res = []; |
|
4151 if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption |
|
4152 pathArray = R.parsePathString(pathArray); |
|
4153 } |
|
4154 for (var i = 0, ii = pathArray.length; i < ii; i++) { |
|
4155 res[i] = []; |
|
4156 for (var j = 0, jj = pathArray[i].length; j < jj; j++) { |
|
4157 res[i][j] = pathArray[i][j]; |
|
4158 } |
|
4159 } |
|
4160 res.toString = R._path2string; |
|
4161 return res; |
|
4162 }, |
|
4163 pathToRelative = R._pathToRelative = cacher(function (pathArray) { |
|
4164 if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption |
|
4165 pathArray = R.parsePathString(pathArray); |
|
4166 } |
|
4167 var res = [], |
|
4168 x = 0, |
|
4169 y = 0, |
|
4170 mx = 0, |
|
4171 my = 0, |
|
4172 start = 0; |
|
4173 if (pathArray[0][0] == "M") { |
|
4174 x = pathArray[0][1]; |
|
4175 y = pathArray[0][2]; |
|
4176 mx = x; |
|
4177 my = y; |
|
4178 start++; |
|
4179 res.push(["M", x, y]); |
|
4180 } |
|
4181 for (var i = start, ii = pathArray.length; i < ii; i++) { |
|
4182 var r = res[i] = [], |
|
4183 pa = pathArray[i]; |
|
4184 if (pa[0] != lowerCase.call(pa[0])) { |
|
4185 r[0] = lowerCase.call(pa[0]); |
|
4186 switch (r[0]) { |
|
4187 case "a": |
|
4188 r[1] = pa[1]; |
|
4189 r[2] = pa[2]; |
|
4190 r[3] = pa[3]; |
|
4191 r[4] = pa[4]; |
|
4192 r[5] = pa[5]; |
|
4193 r[6] = +(pa[6] - x).toFixed(3); |
|
4194 r[7] = +(pa[7] - y).toFixed(3); |
|
4195 break; |
|
4196 case "v": |
|
4197 r[1] = +(pa[1] - y).toFixed(3); |
|
4198 break; |
|
4199 case "m": |
|
4200 mx = pa[1]; |
|
4201 my = pa[2]; |
|
4202 default: |
|
4203 for (var j = 1, jj = pa.length; j < jj; j++) { |
|
4204 r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3); |
|
4205 } |
|
4206 } |
|
4207 } else { |
|
4208 r = res[i] = []; |
|
4209 if (pa[0] == "m") { |
|
4210 mx = pa[1] + x; |
|
4211 my = pa[2] + y; |
|
4212 } |
|
4213 for (var k = 0, kk = pa.length; k < kk; k++) { |
|
4214 res[i][k] = pa[k]; |
|
4215 } |
|
4216 } |
|
4217 var len = res[i].length; |
|
4218 switch (res[i][0]) { |
|
4219 case "z": |
|
4220 x = mx; |
|
4221 y = my; |
|
4222 break; |
|
4223 case "h": |
|
4224 x += +res[i][len - 1]; |
|
4225 break; |
|
4226 case "v": |
|
4227 y += +res[i][len - 1]; |
|
4228 break; |
|
4229 default: |
|
4230 x += +res[i][len - 2]; |
|
4231 y += +res[i][len - 1]; |
|
4232 } |
|
4233 } |
|
4234 res.toString = R._path2string; |
|
4235 return res; |
|
4236 }, 0, pathClone), |
|
4237 pathToAbsolute = R._pathToAbsolute = cacher(function (pathArray) { |
|
4238 if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption |
|
4239 pathArray = R.parsePathString(pathArray); |
|
4240 } |
|
4241 if (!pathArray || !pathArray.length) { |
|
4242 return [["M", 0, 0]]; |
|
4243 } |
|
4244 var res = [], |
|
4245 x = 0, |
|
4246 y = 0, |
|
4247 mx = 0, |
|
4248 my = 0, |
|
4249 start = 0; |
|
4250 if (pathArray[0][0] == "M") { |
|
4251 x = +pathArray[0][1]; |
|
4252 y = +pathArray[0][2]; |
|
4253 mx = x; |
|
4254 my = y; |
|
4255 start++; |
|
4256 res[0] = ["M", x, y]; |
|
4257 } |
|
4258 for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) { |
|
4259 res.push(r = []); |
|
4260 pa = pathArray[i]; |
|
4261 if (pa[0] != upperCase.call(pa[0])) { |
|
4262 r[0] = upperCase.call(pa[0]); |
|
4263 switch (r[0]) { |
|
4264 case "A": |
|
4265 r[1] = pa[1]; |
|
4266 r[2] = pa[2]; |
|
4267 r[3] = pa[3]; |
|
4268 r[4] = pa[4]; |
|
4269 r[5] = pa[5]; |
|
4270 r[6] = +(pa[6] + x); |
|
4271 r[7] = +(pa[7] + y); |
|
4272 break; |
|
4273 case "V": |
|
4274 r[1] = +pa[1] + y; |
|
4275 break; |
|
4276 case "H": |
|
4277 r[1] = +pa[1] + x; |
|
4278 break; |
|
4279 case "R": |
|
4280 var dots = [x, y][concat](pa.slice(1)); |
|
4281 for (var j = 2, jj = dots.length; j < jj; j++) { |
|
4282 dots[j] = +dots[j] + x; |
|
4283 dots[++j] = +dots[j] + y; |
|
4284 } |
|
4285 res.pop(); |
|
4286 res = res[concat](catmullRom2bezier(dots)); |
|
4287 break; |
|
4288 case "M": |
|
4289 mx = +pa[1] + x; |
|
4290 my = +pa[2] + y; |
|
4291 default: |
|
4292 for (j = 1, jj = pa.length; j < jj; j++) { |
|
4293 r[j] = +pa[j] + ((j % 2) ? x : y); |
|
4294 } |
|
4295 } |
|
4296 } else if (pa[0] == "R") { |
|
4297 dots = [x, y][concat](pa.slice(1)); |
|
4298 res.pop(); |
|
4299 res = res[concat](catmullRom2bezier(dots)); |
|
4300 r = ["R"][concat](pa.slice(-2)); |
|
4301 } else { |
|
4302 for (var k = 0, kk = pa.length; k < kk; k++) { |
|
4303 r[k] = pa[k]; |
|
4304 } |
|
4305 } |
|
4306 switch (r[0]) { |
|
4307 case "Z": |
|
4308 x = mx; |
|
4309 y = my; |
|
4310 break; |
|
4311 case "H": |
|
4312 x = r[1]; |
|
4313 break; |
|
4314 case "V": |
|
4315 y = r[1]; |
|
4316 break; |
|
4317 case "M": |
|
4318 mx = r[r.length - 2]; |
|
4319 my = r[r.length - 1]; |
|
4320 default: |
|
4321 x = r[r.length - 2]; |
|
4322 y = r[r.length - 1]; |
|
4323 } |
|
4324 } |
|
4325 res.toString = R._path2string; |
|
4326 return res; |
|
4327 }, null, pathClone), |
|
4328 l2c = function (x1, y1, x2, y2) { |
|
4329 return [x1, y1, x2, y2, x2, y2]; |
|
4330 }, |
|
4331 q2c = function (x1, y1, ax, ay, x2, y2) { |
|
4332 var _13 = 1 / 3, |
|
4333 _23 = 2 / 3; |
|
4334 return [ |
|
4335 _13 * x1 + _23 * ax, |
|
4336 _13 * y1 + _23 * ay, |
|
4337 _13 * x2 + _23 * ax, |
|
4338 _13 * y2 + _23 * ay, |
|
4339 x2, |
|
4340 y2 |
|
4341 ]; |
|
4342 }, |
|
4343 a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) { |
|
4344 // for more information of where this math came from visit: |
|
4345 // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes |
|
4346 var _120 = PI * 120 / 180, |
|
4347 rad = PI / 180 * (+angle || 0), |
|
4348 res = [], |
|
4349 xy, |
|
4350 rotate = cacher(function (x, y, rad) { |
|
4351 var X = x * math.cos(rad) - y * math.sin(rad), |
|
4352 Y = x * math.sin(rad) + y * math.cos(rad); |
|
4353 return {x: X, y: Y}; |
|
4354 }); |
|
4355 if (!recursive) { |
|
4356 xy = rotate(x1, y1, -rad); |
|
4357 x1 = xy.x; |
|
4358 y1 = xy.y; |
|
4359 xy = rotate(x2, y2, -rad); |
|
4360 x2 = xy.x; |
|
4361 y2 = xy.y; |
|
4362 var cos = math.cos(PI / 180 * angle), |
|
4363 sin = math.sin(PI / 180 * angle), |
|
4364 x = (x1 - x2) / 2, |
|
4365 y = (y1 - y2) / 2; |
|
4366 var h = (x * x) / (rx * rx) + (y * y) / (ry * ry); |
|
4367 if (h > 1) { |
|
4368 h = math.sqrt(h); |
|
4369 rx = h * rx; |
|
4370 ry = h * ry; |
|
4371 } |
|
4372 var rx2 = rx * rx, |
|
4373 ry2 = ry * ry, |
|
4374 k = (large_arc_flag == sweep_flag ? -1 : 1) * |
|
4375 math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))), |
|
4376 cx = k * rx * y / ry + (x1 + x2) / 2, |
|
4377 cy = k * -ry * x / rx + (y1 + y2) / 2, |
|
4378 f1 = math.asin(((y1 - cy) / ry).toFixed(9)), |
|
4379 f2 = math.asin(((y2 - cy) / ry).toFixed(9)); |
|
4380 |
|
4381 f1 = x1 < cx ? PI - f1 : f1; |
|
4382 f2 = x2 < cx ? PI - f2 : f2; |
|
4383 f1 < 0 && (f1 = PI * 2 + f1); |
|
4384 f2 < 0 && (f2 = PI * 2 + f2); |
|
4385 if (sweep_flag && f1 > f2) { |
|
4386 f1 = f1 - PI * 2; |
|
4387 } |
|
4388 if (!sweep_flag && f2 > f1) { |
|
4389 f2 = f2 - PI * 2; |
|
4390 } |
|
4391 } else { |
|
4392 f1 = recursive[0]; |
|
4393 f2 = recursive[1]; |
|
4394 cx = recursive[2]; |
|
4395 cy = recursive[3]; |
|
4396 } |
|
4397 var df = f2 - f1; |
|
4398 if (abs(df) > _120) { |
|
4399 var f2old = f2, |
|
4400 x2old = x2, |
|
4401 y2old = y2; |
|
4402 f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1); |
|
4403 x2 = cx + rx * math.cos(f2); |
|
4404 y2 = cy + ry * math.sin(f2); |
|
4405 res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]); |
|
4406 } |
|
4407 df = f2 - f1; |
|
4408 var c1 = math.cos(f1), |
|
4409 s1 = math.sin(f1), |
|
4410 c2 = math.cos(f2), |
|
4411 s2 = math.sin(f2), |
|
4412 t = math.tan(df / 4), |
|
4413 hx = 4 / 3 * rx * t, |
|
4414 hy = 4 / 3 * ry * t, |
|
4415 m1 = [x1, y1], |
|
4416 m2 = [x1 + hx * s1, y1 - hy * c1], |
|
4417 m3 = [x2 + hx * s2, y2 - hy * c2], |
|
4418 m4 = [x2, y2]; |
|
4419 m2[0] = 2 * m1[0] - m2[0]; |
|
4420 m2[1] = 2 * m1[1] - m2[1]; |
|
4421 if (recursive) { |
|
4422 return [m2, m3, m4][concat](res); |
|
4423 } else { |
|
4424 res = [m2, m3, m4][concat](res).join()[split](","); |
|
4425 var newres = []; |
|
4426 for (var i = 0, ii = res.length; i < ii; i++) { |
|
4427 newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x; |
|
4428 } |
|
4429 return newres; |
|
4430 } |
|
4431 }, |
|
4432 findDotAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) { |
|
4433 var t1 = 1 - t; |
|
4434 return { |
|
4435 x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x, |
|
4436 y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y |
|
4437 }; |
|
4438 }, |
|
4439 curveDim = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) { |
|
4440 var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x), |
|
4441 b = 2 * (c1x - p1x) - 2 * (c2x - c1x), |
|
4442 c = p1x - c1x, |
|
4443 t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a, |
|
4444 t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a, |
|
4445 y = [p1y, p2y], |
|
4446 x = [p1x, p2x], |
|
4447 dot; |
|
4448 abs(t1) > "1e12" && (t1 = .5); |
|
4449 abs(t2) > "1e12" && (t2 = .5); |
|
4450 if (t1 > 0 && t1 < 1) { |
|
4451 dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1); |
|
4452 x.push(dot.x); |
|
4453 y.push(dot.y); |
|
4454 } |
|
4455 if (t2 > 0 && t2 < 1) { |
|
4456 dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2); |
|
4457 x.push(dot.x); |
|
4458 y.push(dot.y); |
|
4459 } |
|
4460 a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y); |
|
4461 b = 2 * (c1y - p1y) - 2 * (c2y - c1y); |
|
4462 c = p1y - c1y; |
|
4463 t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a; |
|
4464 t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a; |
|
4465 abs(t1) > "1e12" && (t1 = .5); |
|
4466 abs(t2) > "1e12" && (t2 = .5); |
|
4467 if (t1 > 0 && t1 < 1) { |
|
4468 dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1); |
|
4469 x.push(dot.x); |
|
4470 y.push(dot.y); |
|
4471 } |
|
4472 if (t2 > 0 && t2 < 1) { |
|
4473 dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2); |
|
4474 x.push(dot.x); |
|
4475 y.push(dot.y); |
|
4476 } |
|
4477 return { |
|
4478 min: {x: mmin[apply](0, x), y: mmin[apply](0, y)}, |
|
4479 max: {x: mmax[apply](0, x), y: mmax[apply](0, y)} |
|
4480 }; |
|
4481 }), |
|
4482 path2curve = R._path2curve = cacher(function (path, path2) { |
|
4483 var p = pathToAbsolute(path), |
|
4484 p2 = path2 && pathToAbsolute(path2), |
|
4485 attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null}, |
|
4486 attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null}, |
|
4487 processPath = function (path, d) { |
|
4488 var nx, ny; |
|
4489 if (!path) { |
|
4490 return ["C", d.x, d.y, d.x, d.y, d.x, d.y]; |
|
4491 } |
|
4492 !(path[0] in {T:1, Q:1}) && (d.qx = d.qy = null); |
|
4493 switch (path[0]) { |
|
4494 case "M": |
|
4495 d.X = path[1]; |
|
4496 d.Y = path[2]; |
|
4497 break; |
|
4498 case "A": |
|
4499 path = ["C"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1)))); |
|
4500 break; |
|
4501 case "S": |
|
4502 nx = d.x + (d.x - (d.bx || d.x)); |
|
4503 ny = d.y + (d.y - (d.by || d.y)); |
|
4504 path = ["C", nx, ny][concat](path.slice(1)); |
|
4505 break; |
|
4506 case "T": |
|
4507 d.qx = d.x + (d.x - (d.qx || d.x)); |
|
4508 d.qy = d.y + (d.y - (d.qy || d.y)); |
|
4509 path = ["C"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2])); |
|
4510 break; |
|
4511 case "Q": |
|
4512 d.qx = path[1]; |
|
4513 d.qy = path[2]; |
|
4514 path = ["C"][concat](q2c(d.x, d.y, path[1], path[2], path[3], path[4])); |
|
4515 break; |
|
4516 case "L": |
|
4517 path = ["C"][concat](l2c(d.x, d.y, path[1], path[2])); |
|
4518 break; |
|
4519 case "H": |
|
4520 path = ["C"][concat](l2c(d.x, d.y, path[1], d.y)); |
|
4521 break; |
|
4522 case "V": |
|
4523 path = ["C"][concat](l2c(d.x, d.y, d.x, path[1])); |
|
4524 break; |
|
4525 case "Z": |
|
4526 path = ["C"][concat](l2c(d.x, d.y, d.X, d.Y)); |
|
4527 break; |
|
4528 } |
|
4529 return path; |
|
4530 }, |
|
4531 fixArc = function (pp, i) { |
|
4532 if (pp[i].length > 7) { |
|
4533 pp[i].shift(); |
|
4534 var pi = pp[i]; |
|
4535 while (pi.length) { |
|
4536 pp.splice(i++, 0, ["C"][concat](pi.splice(0, 6))); |
|
4537 } |
|
4538 pp.splice(i, 1); |
|
4539 ii = mmax(p.length, p2 && p2.length || 0); |
|
4540 } |
|
4541 }, |
|
4542 fixM = function (path1, path2, a1, a2, i) { |
|
4543 if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") { |
|
4544 path2.splice(i, 0, ["M", a2.x, a2.y]); |
|
4545 a1.bx = 0; |
|
4546 a1.by = 0; |
|
4547 a1.x = path1[i][1]; |
|
4548 a1.y = path1[i][2]; |
|
4549 ii = mmax(p.length, p2 && p2.length || 0); |
|
4550 } |
|
4551 }; |
|
4552 for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii; i++) { |
|
4553 p[i] = processPath(p[i], attrs); |
|
4554 fixArc(p, i); |
|
4555 p2 && (p2[i] = processPath(p2[i], attrs2)); |
|
4556 p2 && fixArc(p2, i); |
|
4557 fixM(p, p2, attrs, attrs2, i); |
|
4558 fixM(p2, p, attrs2, attrs, i); |
|
4559 var seg = p[i], |
|
4560 seg2 = p2 && p2[i], |
|
4561 seglen = seg.length, |
|
4562 seg2len = p2 && seg2.length; |
|
4563 attrs.x = seg[seglen - 2]; |
|
4564 attrs.y = seg[seglen - 1]; |
|
4565 attrs.bx = toFloat(seg[seglen - 4]) || attrs.x; |
|
4566 attrs.by = toFloat(seg[seglen - 3]) || attrs.y; |
|
4567 attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x); |
|
4568 attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y); |
|
4569 attrs2.x = p2 && seg2[seg2len - 2]; |
|
4570 attrs2.y = p2 && seg2[seg2len - 1]; |
|
4571 } |
|
4572 return p2 ? [p, p2] : p; |
|
4573 }, null, pathClone), |
|
4574 parseDots = R._parseDots = cacher(function (gradient) { |
|
4575 var dots = []; |
|
4576 for (var i = 0, ii = gradient.length; i < ii; i++) { |
|
4577 var dot = {}, |
|
4578 par = gradient[i].match(/^([^:]*):?([\d\.]*)/); |
|
4579 dot.color = R.getRGB(par[1]); |
|
4580 if (dot.color.error) { |
|
4581 return null; |
|
4582 } |
|
4583 dot.color = dot.color.hex; |
|
4584 par[2] && (dot.offset = par[2] + "%"); |
|
4585 dots.push(dot); |
|
4586 } |
|
4587 for (i = 1, ii = dots.length - 1; i < ii; i++) { |
|
4588 if (!dots[i].offset) { |
|
4589 var start = toFloat(dots[i - 1].offset || 0), |
|
4590 end = 0; |
|
4591 for (var j = i + 1; j < ii; j++) { |
|
4592 if (dots[j].offset) { |
|
4593 end = dots[j].offset; |
|
4594 break; |
|
4595 } |
|
4596 } |
|
4597 if (!end) { |
|
4598 end = 100; |
|
4599 j = ii; |
|
4600 } |
|
4601 end = toFloat(end); |
|
4602 var d = (end - start) / (j - i + 1); |
|
4603 for (; i < j; i++) { |
|
4604 start += d; |
|
4605 dots[i].offset = start + "%"; |
|
4606 } |
|
4607 } |
|
4608 } |
|
4609 return dots; |
|
4610 }), |
|
4611 tear = R._tear = function (el, paper) { |
|
4612 el == paper.top && (paper.top = el.prev); |
|
4613 el == paper.bottom && (paper.bottom = el.next); |
|
4614 el.next && (el.next.prev = el.prev); |
|
4615 el.prev && (el.prev.next = el.next); |
|
4616 }, |
|
4617 tofront = R._tofront = function (el, paper) { |
|
4618 if (paper.top === el) { |
|
4619 return; |
|
4620 } |
|
4621 tear(el, paper); |
|
4622 el.next = null; |
|
4623 el.prev = paper.top; |
|
4624 paper.top.next = el; |
|
4625 paper.top = el; |
|
4626 }, |
|
4627 toback = R._toback = function (el, paper) { |
|
4628 if (paper.bottom === el) { |
|
4629 return; |
|
4630 } |
|
4631 tear(el, paper); |
|
4632 el.next = paper.bottom; |
|
4633 el.prev = null; |
|
4634 paper.bottom.prev = el; |
|
4635 paper.bottom = el; |
|
4636 }, |
|
4637 insertafter = R._insertafter = function (el, el2, paper) { |
|
4638 tear(el, paper); |
|
4639 el2 == paper.top && (paper.top = el); |
|
4640 el2.next && (el2.next.prev = el); |
|
4641 el.next = el2.next; |
|
4642 el.prev = el2; |
|
4643 el2.next = el; |
|
4644 }, |
|
4645 insertbefore = R._insertbefore = function (el, el2, paper) { |
|
4646 tear(el, paper); |
|
4647 el2 == paper.bottom && (paper.bottom = el); |
|
4648 el2.prev && (el2.prev.next = el); |
|
4649 el.prev = el2.prev; |
|
4650 el2.prev = el; |
|
4651 el.next = el2; |
|
4652 }, |
|
4653 removed = function (methodname) { |
|
4654 return function () { |
|
4655 throw new Error("Rapha\xebl: you are calling to method \u201c" + methodname + "\u201d of removed object"); |
|
4656 }; |
|
4657 }, |
|
4658 extractTransform = R._extractTransform = function (el, tstr) { |
|
4659 if (tstr == null) { |
|
4660 return el._.transform; |
|
4661 } |
|
4662 tstr = Str(tstr).replace(/\.{3}|\u2026/g, el._.transform || E); |
|
4663 var tdata = R.parseTransformString(tstr), |
|
4664 deg = 0, |
|
4665 dx = 0, |
|
4666 dy = 0, |
|
4667 sx = 1, |
|
4668 sy = 1, |
|
4669 _ = el._, |
|
4670 m = new Matrix; |
|
4671 _.transform = tdata || []; |
|
4672 if (tdata) { |
|
4673 for (var i = 0, ii = tdata.length; i < ii; i++) { |
|
4674 var t = tdata[i], |
|
4675 tlen = t.length, |
|
4676 command = Str(t[0]).toLowerCase(), |
|
4677 absolute = t[0] != command, |
|
4678 inver = absolute ? m.invert() : 0, |
|
4679 x1, |
|
4680 y1, |
|
4681 x2, |
|
4682 y2, |
|
4683 bb; |
|
4684 if (command == "t" && tlen == 3) { |
|
4685 if (absolute) { |
|
4686 x1 = inver.x(0, 0); |
|
4687 y1 = inver.y(0, 0); |
|
4688 x2 = inver.x(t[1], t[2]); |
|
4689 y2 = inver.y(t[1], t[2]); |
|
4690 m.translate(x2 - x1, y2 - y1); |
|
4691 } else { |
|
4692 m.translate(t[1], t[2]); |
|
4693 } |
|
4694 } else if (command == "r") { |
|
4695 if (tlen == 2) { |
|
4696 bb = bb || el.getBBox(1); |
|
4697 m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2); |
|
4698 deg += t[1]; |
|
4699 } else if (tlen == 4) { |
|
4700 if (absolute) { |
|
4701 x2 = inver.x(t[2], t[3]); |
|
4702 y2 = inver.y(t[2], t[3]); |
|
4703 m.rotate(t[1], x2, y2); |
|
4704 } else { |
|
4705 m.rotate(t[1], t[2], t[3]); |
|
4706 } |
|
4707 deg += t[1]; |
|
4708 } |
|
4709 } else if (command == "s") { |
|
4710 if (tlen == 2 || tlen == 3) { |
|
4711 bb = bb || el.getBBox(1); |
|
4712 m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2); |
|
4713 sx *= t[1]; |
|
4714 sy *= t[tlen - 1]; |
|
4715 } else if (tlen == 5) { |
|
4716 if (absolute) { |
|
4717 x2 = inver.x(t[3], t[4]); |
|
4718 y2 = inver.y(t[3], t[4]); |
|
4719 m.scale(t[1], t[2], x2, y2); |
|
4720 } else { |
|
4721 m.scale(t[1], t[2], t[3], t[4]); |
|
4722 } |
|
4723 sx *= t[1]; |
|
4724 sy *= t[2]; |
|
4725 } |
|
4726 } else if (command == "m" && tlen == 7) { |
|
4727 m.add(t[1], t[2], t[3], t[4], t[5], t[6]); |
|
4728 } |
|
4729 _.dirtyT = 1; |
|
4730 el.matrix = m; |
|
4731 } |
|
4732 } |
|
4733 |
|
4734 el.matrix = m; |
|
4735 |
|
4736 _.sx = sx; |
|
4737 _.sy = sy; |
|
4738 _.deg = deg; |
|
4739 _.dx = dx = m.e; |
|
4740 _.dy = dy = m.f; |
|
4741 |
|
4742 if (sx == 1 && sy == 1 && !deg && _.bbox) { |
|
4743 _.bbox.x += +dx; |
|
4744 _.bbox.y += +dy; |
|
4745 } else { |
|
4746 _.dirtyT = 1; |
|
4747 } |
|
4748 }, |
|
4749 getEmpty = function (item) { |
|
4750 var l = item[0]; |
|
4751 switch (l.toLowerCase()) { |
|
4752 case "t": return [l, 0, 0]; |
|
4753 case "m": return [l, 1, 0, 0, 1, 0, 0]; |
|
4754 case "r": if (item.length == 4) { |
|
4755 return [l, 0, item[2], item[3]]; |
|
4756 } else { |
|
4757 return [l, 0]; |
|
4758 } |
|
4759 case "s": if (item.length == 5) { |
|
4760 return [l, 1, 1, item[3], item[4]]; |
|
4761 } else if (item.length == 3) { |
|
4762 return [l, 1, 1]; |
|
4763 } else { |
|
4764 return [l, 1]; |
|
4765 } |
|
4766 } |
|
4767 }, |
|
4768 equaliseTransform = R._equaliseTransform = function (t1, t2) { |
|
4769 t2 = Str(t2).replace(/\.{3}|\u2026/g, t1); |
|
4770 t1 = R.parseTransformString(t1) || []; |
|
4771 t2 = R.parseTransformString(t2) || []; |
|
4772 var maxlength = mmax(t1.length, t2.length), |
|
4773 from = [], |
|
4774 to = [], |
|
4775 i = 0, j, jj, |
|
4776 tt1, tt2; |
|
4777 for (; i < maxlength; i++) { |
|
4778 tt1 = t1[i] || getEmpty(t2[i]); |
|
4779 tt2 = t2[i] || getEmpty(tt1); |
|
4780 if ((tt1[0] != tt2[0]) || |
|
4781 (tt1[0].toLowerCase() == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) || |
|
4782 (tt1[0].toLowerCase() == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4])) |
|
4783 ) { |
|
4784 return; |
|
4785 } |
|
4786 from[i] = []; |
|
4787 to[i] = []; |
|
4788 for (j = 0, jj = mmax(tt1.length, tt2.length); j < jj; j++) { |
|
4789 j in tt1 && (from[i][j] = tt1[j]); |
|
4790 j in tt2 && (to[i][j] = tt2[j]); |
|
4791 } |
|
4792 } |
|
4793 return { |
|
4794 from: from, |
|
4795 to: to |
|
4796 }; |
|
4797 }; |
|
4798 R._getContainer = function (x, y, w, h) { |
|
4799 var container; |
|
4800 container = h == null && !R.is(x, "object") ? g.doc.getElementById(x) : x; |
|
4801 if (container == null) { |
|
4802 return; |
|
4803 } |
|
4804 if (container.tagName) { |
|
4805 if (y == null) { |
|
4806 return { |
|
4807 container: container, |
|
4808 width: container.style.pixelWidth || container.offsetWidth, |
|
4809 height: container.style.pixelHeight || container.offsetHeight |
|
4810 }; |
|
4811 } else { |
|
4812 return { |
|
4813 container: container, |
|
4814 width: y, |
|
4815 height: w |
|
4816 }; |
|
4817 } |
|
4818 } |
|
4819 return { |
|
4820 container: 1, |
|
4821 x: x, |
|
4822 y: y, |
|
4823 width: w, |
|
4824 height: h |
|
4825 }; |
|
4826 }; |
|
4827 |
|
4828 R.pathToRelative = pathToRelative; |
|
4829 R._engine = {}; |
|
4830 |
|
4831 R.path2curve = path2curve; |
|
4832 |
|
4833 R.matrix = function (a, b, c, d, e, f) { |
|
4834 return new Matrix(a, b, c, d, e, f); |
|
4835 }; |
|
4836 function Matrix(a, b, c, d, e, f) { |
|
4837 if (a != null) { |
|
4838 this.a = +a; |
|
4839 this.b = +b; |
|
4840 this.c = +c; |
|
4841 this.d = +d; |
|
4842 this.e = +e; |
|
4843 this.f = +f; |
|
4844 } else { |
|
4845 this.a = 1; |
|
4846 this.b = 0; |
|
4847 this.c = 0; |
|
4848 this.d = 1; |
|
4849 this.e = 0; |
|
4850 this.f = 0; |
|
4851 } |
|
4852 } |
|
4853 (function (matrixproto) { |
|
4854 |
|
4855 matrixproto.add = function (a, b, c, d, e, f) { |
|
4856 var out = [[], [], []], |
|
4857 m = [[this.a, this.c, this.e], [this.b, this.d, this.f], [0, 0, 1]], |
|
4858 matrix = [[a, c, e], [b, d, f], [0, 0, 1]], |
|
4859 x, y, z, res; |
|
4860 |
|
4861 if (a && a instanceof Matrix) { |
|
4862 matrix = [[a.a, a.c, a.e], [a.b, a.d, a.f], [0, 0, 1]]; |
|
4863 } |
|
4864 |
|
4865 for (x = 0; x < 3; x++) { |
|
4866 for (y = 0; y < 3; y++) { |
|
4867 res = 0; |
|
4868 for (z = 0; z < 3; z++) { |
|
4869 res += m[x][z] * matrix[z][y]; |
|
4870 } |
|
4871 out[x][y] = res; |
|
4872 } |
|
4873 } |
|
4874 this.a = out[0][0]; |
|
4875 this.b = out[1][0]; |
|
4876 this.c = out[0][1]; |
|
4877 this.d = out[1][1]; |
|
4878 this.e = out[0][2]; |
|
4879 this.f = out[1][2]; |
|
4880 }; |
|
4881 |
|
4882 matrixproto.invert = function () { |
|
4883 var me = this, |
|
4884 x = me.a * me.d - me.b * me.c; |
|
4885 return new Matrix(me.d / x, -me.b / x, -me.c / x, me.a / x, (me.c * me.f - me.d * me.e) / x, (me.b * me.e - me.a * me.f) / x); |
|
4886 }; |
|
4887 |
|
4888 matrixproto.clone = function () { |
|
4889 return new Matrix(this.a, this.b, this.c, this.d, this.e, this.f); |
|
4890 }; |
|
4891 |
|
4892 matrixproto.translate = function (x, y) { |
|
4893 this.add(1, 0, 0, 1, x, y); |
|
4894 }; |
|
4895 |
|
4896 matrixproto.scale = function (x, y, cx, cy) { |
|
4897 y == null && (y = x); |
|
4898 (cx || cy) && this.add(1, 0, 0, 1, cx, cy); |
|
4899 this.add(x, 0, 0, y, 0, 0); |
|
4900 (cx || cy) && this.add(1, 0, 0, 1, -cx, -cy); |
|
4901 }; |
|
4902 |
|
4903 matrixproto.rotate = function (a, x, y) { |
|
4904 a = R.rad(a); |
|
4905 x = x || 0; |
|
4906 y = y || 0; |
|
4907 var cos = +math.cos(a).toFixed(9), |
|
4908 sin = +math.sin(a).toFixed(9); |
|
4909 this.add(cos, sin, -sin, cos, x, y); |
|
4910 this.add(1, 0, 0, 1, -x, -y); |
|
4911 }; |
|
4912 |
|
4913 matrixproto.x = function (x, y) { |
|
4914 return x * this.a + y * this.c + this.e; |
|
4915 }; |
|
4916 |
|
4917 matrixproto.y = function (x, y) { |
|
4918 return x * this.b + y * this.d + this.f; |
|
4919 }; |
|
4920 matrixproto.get = function (i) { |
|
4921 return +this[Str.fromCharCode(97 + i)].toFixed(4); |
|
4922 }; |
|
4923 matrixproto.toString = function () { |
|
4924 return R.svg ? |
|
4925 "matrix(" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)].join() + ")" : |
|
4926 [this.get(0), this.get(2), this.get(1), this.get(3), 0, 0].join(); |
|
4927 }; |
|
4928 matrixproto.toFilter = function () { |
|
4929 return "progid:DXImageTransform.Microsoft.Matrix(M11=" + this.get(0) + |
|
4930 ", M12=" + this.get(2) + ", M21=" + this.get(1) + ", M22=" + this.get(3) + |
|
4931 ", Dx=" + this.get(4) + ", Dy=" + this.get(5) + ", sizingmethod='auto expand')"; |
|
4932 }; |
|
4933 matrixproto.offset = function () { |
|
4934 return [this.e.toFixed(4), this.f.toFixed(4)]; |
|
4935 }; |
|
4936 function norm(a) { |
|
4937 return a[0] * a[0] + a[1] * a[1]; |
|
4938 } |
|
4939 function normalize(a) { |
|
4940 var mag = math.sqrt(norm(a)); |
|
4941 a[0] && (a[0] /= mag); |
|
4942 a[1] && (a[1] /= mag); |
|
4943 } |
|
4944 |
|
4945 matrixproto.split = function () { |
|
4946 var out = {}; |
|
4947 // translation |
|
4948 out.dx = this.e; |
|
4949 out.dy = this.f; |
|
4950 |
|
4951 // scale and shear |
|
4952 var row = [[this.a, this.c], [this.b, this.d]]; |
|
4953 out.scalex = math.sqrt(norm(row[0])); |
|
4954 normalize(row[0]); |
|
4955 |
|
4956 out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1]; |
|
4957 row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear]; |
|
4958 |
|
4959 out.scaley = math.sqrt(norm(row[1])); |
|
4960 normalize(row[1]); |
|
4961 out.shear /= out.scaley; |
|
4962 |
|
4963 // rotation |
|
4964 var sin = -row[0][1], |
|
4965 cos = row[1][1]; |
|
4966 if (cos < 0) { |
|
4967 out.rotate = R.deg(math.acos(cos)); |
|
4968 if (sin < 0) { |
|
4969 out.rotate = 360 - out.rotate; |
|
4970 } |
|
4971 } else { |
|
4972 out.rotate = R.deg(math.asin(sin)); |
|
4973 } |
|
4974 |
|
4975 out.isSimple = !+out.shear.toFixed(9) && (out.scalex.toFixed(9) == out.scaley.toFixed(9) || !out.rotate); |
|
4976 out.isSuperSimple = !+out.shear.toFixed(9) && out.scalex.toFixed(9) == out.scaley.toFixed(9) && !out.rotate; |
|
4977 out.noRotation = !+out.shear.toFixed(9) && !out.rotate; |
|
4978 return out; |
|
4979 }; |
|
4980 |
|
4981 matrixproto.toTransformString = function (shorter) { |
|
4982 var s = shorter || this[split](); |
|
4983 if (s.isSimple) { |
|
4984 return "t" + [s.dx, s.dy] + "s" + [s.scalex, s.scaley, 0, 0] + "r" + [s.rotate, 0, 0]; |
|
4985 } else { |
|
4986 return "m" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)]; |
|
4987 } |
|
4988 }; |
|
4989 })(Matrix.prototype); |
|
4990 |
|
4991 // WebKit rendering bug workaround method |
|
4992 var version = navigator.userAgent.match(/Version\/(.*?)\s/) || navigator.userAgent.match(/Chrome\/(\d+)/); |
|
4993 if ((navigator.vendor == "Apple Computer, Inc.") && (version && version[1] < 4 || navigator.platform.slice(0, 2) == "iP") || |
|
4994 (navigator.vendor == "Google Inc." && version && version[1] < 8)) { |
|
4995 |
|
4996 paperproto.safari = function () { |
|
4997 var rect = this.rect(-99, -99, this.width + 99, this.height + 99).attr({stroke: "none"}); |
|
4998 setTimeout(function () {rect.remove();}); |
|
4999 }; |
|
5000 } else { |
|
5001 paperproto.safari = fun; |
|
5002 } |
|
5003 |
|
5004 var preventDefault = function () { |
|
5005 this.returnValue = false; |
|
5006 }, |
|
5007 preventTouch = function () { |
|
5008 return this.originalEvent.preventDefault(); |
|
5009 }, |
|
5010 stopPropagation = function () { |
|
5011 this.cancelBubble = true; |
|
5012 }, |
|
5013 stopTouch = function () { |
|
5014 return this.originalEvent.stopPropagation(); |
|
5015 }, |
|
5016 addEvent = (function () { |
|
5017 if (g.doc.addEventListener) { |
|
5018 return function (obj, type, fn, element) { |
|
5019 var realName = supportsTouch && touchMap[type] ? touchMap[type] : type, |
|
5020 f = function (e) { |
|
5021 var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, |
|
5022 scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft, |
|
5023 x = e.clientX + scrollX, |
|
5024 y = e.clientY + scrollY; |
|
5025 if (supportsTouch && touchMap[has](type)) { |
|
5026 for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) { |
|
5027 if (e.targetTouches[i].target == obj) { |
|
5028 var olde = e; |
|
5029 e = e.targetTouches[i]; |
|
5030 e.originalEvent = olde; |
|
5031 e.preventDefault = preventTouch; |
|
5032 e.stopPropagation = stopTouch; |
|
5033 break; |
|
5034 } |
|
5035 } |
|
5036 } |
|
5037 return fn.call(element, e, x, y); |
|
5038 }; |
|
5039 obj.addEventListener(realName, f, false); |
|
5040 return function () { |
|
5041 obj.removeEventListener(realName, f, false); |
|
5042 return true; |
|
5043 }; |
|
5044 }; |
|
5045 } else if (g.doc.attachEvent) { |
|
5046 return function (obj, type, fn, element) { |
|
5047 var f = function (e) { |
|
5048 e = e || g.win.event; |
|
5049 var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, |
|
5050 scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft, |
|
5051 x = e.clientX + scrollX, |
|
5052 y = e.clientY + scrollY; |
|
5053 e.preventDefault = e.preventDefault || preventDefault; |
|
5054 e.stopPropagation = e.stopPropagation || stopPropagation; |
|
5055 return fn.call(element, e, x, y); |
|
5056 }; |
|
5057 obj.attachEvent("on" + type, f); |
|
5058 var detacher = function () { |
|
5059 obj.detachEvent("on" + type, f); |
|
5060 return true; |
|
5061 }; |
|
5062 return detacher; |
|
5063 }; |
|
5064 } |
|
5065 })(), |
|
5066 drag = [], |
|
5067 dragMove = function (e) { |
|
5068 var x = e.clientX, |
|
5069 y = e.clientY, |
|
5070 scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, |
|
5071 scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft, |
|
5072 dragi, |
|
5073 j = drag.length; |
|
5074 while (j--) { |
|
5075 dragi = drag[j]; |
|
5076 if (supportsTouch) { |
|
5077 var i = e.touches.length, |
|
5078 touch; |
|
5079 while (i--) { |
|
5080 touch = e.touches[i]; |
|
5081 if (touch.identifier == dragi.el._drag.id) { |
|
5082 x = touch.clientX; |
|
5083 y = touch.clientY; |
|
5084 (e.originalEvent ? e.originalEvent : e).preventDefault(); |
|
5085 break; |
|
5086 } |
|
5087 } |
|
5088 } else { |
|
5089 e.preventDefault(); |
|
5090 } |
|
5091 var node = dragi.el.node, |
|
5092 o, |
|
5093 next = node.nextSibling, |
|
5094 parent = node.parentNode, |
|
5095 display = node.style.display; |
|
5096 g.win.opera && parent.removeChild(node); |
|
5097 node.style.display = "none"; |
|
5098 o = dragi.el.paper.getElementByPoint(x, y); |
|
5099 node.style.display = display; |
|
5100 g.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node)); |
|
5101 o && eve("drag.over." + dragi.el.id, dragi.el, o); |
|
5102 x += scrollX; |
|
5103 y += scrollY; |
|
5104 eve("drag.move." + dragi.el.id, dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e); |
|
5105 } |
|
5106 }, |
|
5107 dragUp = function (e) { |
|
5108 R.unmousemove(dragMove).unmouseup(dragUp); |
|
5109 var i = drag.length, |
|
5110 dragi; |
|
5111 while (i--) { |
|
5112 dragi = drag[i]; |
|
5113 dragi.el._drag = {}; |
|
5114 eve("drag.end." + dragi.el.id, dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e); |
|
5115 } |
|
5116 drag = []; |
|
5117 }, |
|
5118 |
|
5119 elproto = R.el = {}; |
|
5120 |
|
5121 |
|
5122 |
|
5123 |
|
5124 |
|
5125 |
|
5126 |
|
5127 |
|
5128 |
|
5129 |
|
5130 |
|
5131 |
|
5132 |
|
5133 |
|
5134 |
|
5135 |
|
5136 |
|
5137 |
|
5138 |
|
5139 |
|
5140 |
|
5141 |
|
5142 |
|
5143 |
|
5144 |
|
5145 |
|
5146 |
|
5147 |
|
5148 |
|
5149 |
|
5150 |
|
5151 |
|
5152 for (var i = events.length; i--;) { |
|
5153 (function (eventName) { |
|
5154 R[eventName] = elproto[eventName] = function (fn, scope) { |
|
5155 if (R.is(fn, "function")) { |
|
5156 this.events = this.events || []; |
|
5157 this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || g.doc, eventName, fn, scope || this)}); |
|
5158 } |
|
5159 return this; |
|
5160 }; |
|
5161 R["un" + eventName] = elproto["un" + eventName] = function (fn) { |
|
5162 var events = this.events, |
|
5163 l = events.length; |
|
5164 while (l--) if (events[l].name == eventName && events[l].f == fn) { |
|
5165 events[l].unbind(); |
|
5166 events.splice(l, 1); |
|
5167 !events.length && delete this.events; |
|
5168 return this; |
|
5169 } |
|
5170 return this; |
|
5171 }; |
|
5172 })(events[i]); |
|
5173 } |
|
5174 |
|
5175 |
|
5176 elproto.data = function (key, value) { |
|
5177 var data = eldata[this.id] = eldata[this.id] || {}; |
|
5178 if (arguments.length == 1) { |
|
5179 if (R.is(key, "object")) { |
|
5180 for (var i in key) if (key[has](i)) { |
|
5181 this.data(i, key[i]); |
|
5182 } |
|
5183 return this; |
|
5184 } |
|
5185 eve("data.get." + this.id, this, data[key], key); |
|
5186 return data[key]; |
|
5187 } |
|
5188 data[key] = value; |
|
5189 eve("data.set." + this.id, this, value, key); |
|
5190 return this; |
|
5191 }; |
|
5192 |
|
5193 elproto.removeData = function (key) { |
|
5194 if (key == null) { |
|
5195 eldata[this.id] = {}; |
|
5196 } else { |
|
5197 eldata[this.id] && delete eldata[this.id][key]; |
|
5198 } |
|
5199 return this; |
|
5200 }; |
|
5201 |
|
5202 elproto.hover = function (f_in, f_out, scope_in, scope_out) { |
|
5203 return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in); |
|
5204 }; |
|
5205 |
|
5206 elproto.unhover = function (f_in, f_out) { |
|
5207 return this.unmouseover(f_in).unmouseout(f_out); |
|
5208 }; |
|
5209 |
|
5210 elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) { |
|
5211 function start(e) { |
|
5212 (e.originalEvent || e).preventDefault(); |
|
5213 var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop, |
|
5214 scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft; |
|
5215 this._drag.x = e.clientX + scrollX; |
|
5216 this._drag.y = e.clientY + scrollY; |
|
5217 this._drag.id = e.identifier; |
|
5218 !drag.length && R.mousemove(dragMove).mouseup(dragUp); |
|
5219 drag.push({el: this, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope}); |
|
5220 onstart && eve.on("drag.start." + this.id, onstart); |
|
5221 onmove && eve.on("drag.move." + this.id, onmove); |
|
5222 onend && eve.on("drag.end." + this.id, onend); |
|
5223 eve("drag.start." + this.id, start_scope || move_scope || this, e.clientX + scrollX, e.clientY + scrollY, e); |
|
5224 } |
|
5225 this._drag = {}; |
|
5226 this.mousedown(start); |
|
5227 return this; |
|
5228 }; |
|
5229 |
|
5230 elproto.onDragOver = function (f) { |
|
5231 f ? eve.on("drag.over." + this.id, f) : eve.unbind("drag.over." + this.id); |
|
5232 }; |
|
5233 |
|
5234 elproto.undrag = function () { |
|
5235 var i = drag.length; |
|
5236 while (i--) if (drag[i].el == this) { |
|
5237 R.unmousedown(drag[i].start); |
|
5238 drag.splice(i++, 1); |
|
5239 eve.unbind("drag.*." + this.id); |
|
5240 } |
|
5241 !drag.length && R.unmousemove(dragMove).unmouseup(dragUp); |
|
5242 }; |
|
5243 |
|
5244 paperproto.circle = function (x, y, r) { |
|
5245 var out = R._engine.circle(this, x || 0, y || 0, r || 0); |
|
5246 this.__set__ && this.__set__.push(out); |
|
5247 return out; |
|
5248 }; |
|
5249 |
|
5250 paperproto.rect = function (x, y, w, h, r) { |
|
5251 var out = R._engine.rect(this, x || 0, y || 0, w || 0, h || 0, r || 0); |
|
5252 this.__set__ && this.__set__.push(out); |
|
5253 return out; |
|
5254 }; |
|
5255 |
|
5256 paperproto.ellipse = function (x, y, rx, ry) { |
|
5257 var out = R._engine.ellipse(this, x || 0, y || 0, rx || 0, ry || 0); |
|
5258 this.__set__ && this.__set__.push(out); |
|
5259 return out; |
|
5260 }; |
|
5261 |
|
5262 paperproto.path = function (pathString) { |
|
5263 pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E); |
|
5264 var out = R._engine.path(R.format[apply](R, arguments), this); |
|
5265 this.__set__ && this.__set__.push(out); |
|
5266 return out; |
|
5267 }; |
|
5268 |
|
5269 paperproto.image = function (src, x, y, w, h) { |
|
5270 var out = R._engine.image(this, src || "about:blank", x || 0, y || 0, w || 0, h || 0); |
|
5271 this.__set__ && this.__set__.push(out); |
|
5272 return out; |
|
5273 }; |
|
5274 |
|
5275 paperproto.text = function (x, y, text) { |
|
5276 var out = R._engine.text(this, x || 0, y || 0, Str(text)); |
|
5277 this.__set__ && this.__set__.push(out); |
|
5278 return out; |
|
5279 }; |
|
5280 |
|
5281 paperproto.set = function (itemsArray) { |
|
5282 !R.is(itemsArray, "array") && (itemsArray = Array.prototype.splice.call(arguments, 0, arguments.length)); |
|
5283 var out = new Set(itemsArray); |
|
5284 this.__set__ && this.__set__.push(out); |
|
5285 return out; |
|
5286 }; |
|
5287 |
|
5288 paperproto.setStart = function (set) { |
|
5289 this.__set__ = set || this.set(); |
|
5290 }; |
|
5291 |
|
5292 paperproto.setFinish = function (set) { |
|
5293 var out = this.__set__; |
|
5294 delete this.__set__; |
|
5295 return out; |
|
5296 }; |
|
5297 |
|
5298 paperproto.setSize = function (width, height) { |
|
5299 return R._engine.setSize.call(this, width, height); |
|
5300 }; |
|
5301 |
|
5302 paperproto.setViewBox = function (x, y, w, h, fit) { |
|
5303 return R._engine.setViewBox.call(this, x, y, w, h, fit); |
|
5304 }; |
|
5305 |
|
5306 |
|
5307 paperproto.top = paperproto.bottom = null; |
|
5308 |
|
5309 paperproto.raphael = R; |
|
5310 var getOffset = function (elem) { |
|
5311 var box = elem.getBoundingClientRect(), |
|
5312 doc = elem.ownerDocument, |
|
5313 body = doc.body, |
|
5314 docElem = doc.documentElement, |
|
5315 clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0, |
|
5316 top = box.top + (g.win.pageYOffset || docElem.scrollTop || body.scrollTop ) - clientTop, |
|
5317 left = box.left + (g.win.pageXOffset || docElem.scrollLeft || body.scrollLeft) - clientLeft; |
|
5318 return { |
|
5319 y: top, |
|
5320 x: left |
|
5321 }; |
|
5322 }; |
|
5323 |
|
5324 paperproto.getElementByPoint = function (x, y) { |
|
5325 var paper = this, |
|
5326 svg = paper.canvas, |
|
5327 target = g.doc.elementFromPoint(x, y); |
|
5328 if (g.win.opera && target.tagName == "svg") { |
|
5329 var so = getOffset(svg), |
|
5330 sr = svg.createSVGRect(); |
|
5331 sr.x = x - so.x; |
|
5332 sr.y = y - so.y; |
|
5333 sr.width = sr.height = 1; |
|
5334 var hits = svg.getIntersectionList(sr, null); |
|
5335 if (hits.length) { |
|
5336 target = hits[hits.length - 1]; |
|
5337 } |
|
5338 } |
|
5339 if (!target) { |
|
5340 return null; |
|
5341 } |
|
5342 while (target.parentNode && target != svg.parentNode && !target.raphael) { |
|
5343 target = target.parentNode; |
|
5344 } |
|
5345 target == paper.canvas.parentNode && (target = svg); |
|
5346 target = target && target.raphael ? paper.getById(target.raphaelid) : null; |
|
5347 return target; |
|
5348 }; |
|
5349 |
|
5350 paperproto.getById = function (id) { |
|
5351 var bot = this.bottom; |
|
5352 while (bot) { |
|
5353 if (bot.id == id) { |
|
5354 return bot; |
|
5355 } |
|
5356 bot = bot.next; |
|
5357 } |
|
5358 return null; |
|
5359 }; |
|
5360 |
|
5361 paperproto.forEach = function (callback, thisArg) { |
|
5362 var bot = this.bottom; |
|
5363 while (bot) { |
|
5364 if (callback.call(thisArg, bot) === false) { |
|
5365 return this; |
|
5366 } |
|
5367 bot = bot.next; |
|
5368 } |
|
5369 return this; |
|
5370 }; |
|
5371 function x_y() { |
|
5372 return this.x + S + this.y; |
|
5373 } |
|
5374 function x_y_w_h() { |
|
5375 return this.x + S + this.y + S + this.width + " \xd7 " + this.height; |
|
5376 } |
|
5377 |
|
5378 elproto.getBBox = function (isWithoutTransform) { |
|
5379 if (this.removed) { |
|
5380 return {}; |
|
5381 } |
|
5382 var _ = this._; |
|
5383 if (isWithoutTransform) { |
|
5384 if (_.dirty || !_.bboxwt) { |
|
5385 this.realPath = getPath[this.type](this); |
|
5386 _.bboxwt = pathDimensions(this.realPath); |
|
5387 _.bboxwt.toString = x_y_w_h; |
|
5388 _.dirty = 0; |
|
5389 } |
|
5390 return _.bboxwt; |
|
5391 } |
|
5392 if (_.dirty || _.dirtyT || !_.bbox) { |
|
5393 if (_.dirty || !this.realPath) { |
|
5394 _.bboxwt = 0; |
|
5395 this.realPath = getPath[this.type](this); |
|
5396 } |
|
5397 _.bbox = pathDimensions(mapPath(this.realPath, this.matrix)); |
|
5398 _.bbox.toString = x_y_w_h; |
|
5399 _.dirty = _.dirtyT = 0; |
|
5400 } |
|
5401 return _.bbox; |
|
5402 }; |
|
5403 |
|
5404 elproto.clone = function () { |
|
5405 if (this.removed) { |
|
5406 return null; |
|
5407 } |
|
5408 var out = this.paper[this.type]().attr(this.attr()); |
|
5409 this.__set__ && this.__set__.push(out); |
|
5410 return out; |
|
5411 }; |
|
5412 |
|
5413 elproto.glow = function (glow) { |
|
5414 if (this.type == "text") { |
|
5415 return null; |
|
5416 } |
|
5417 glow = glow || {}; |
|
5418 var s = { |
|
5419 width: (glow.width || 10) + (+this.attr("stroke-width") || 1), |
|
5420 fill: glow.fill || false, |
|
5421 opacity: glow.opacity || .5, |
|
5422 offsetx: glow.offsetx || 0, |
|
5423 offsety: glow.offsety || 0, |
|
5424 color: glow.color || "#000" |
|
5425 }, |
|
5426 c = s.width / 2, |
|
5427 r = this.paper, |
|
5428 out = r.set(), |
|
5429 path = this.realPath || getPath[this.type](this); |
|
5430 path = this.matrix ? mapPath(path, this.matrix) : path; |
|
5431 for (var i = 1; i < c + 1; i++) { |
|
5432 out.push(r.path(path).attr({ |
|
5433 stroke: s.color, |
|
5434 fill: s.fill ? s.color : "none", |
|
5435 "stroke-linejoin": "round", |
|
5436 "stroke-linecap": "round", |
|
5437 "stroke-width": +(s.width / c * i).toFixed(3), |
|
5438 opacity: +(s.opacity / c).toFixed(3) |
|
5439 })); |
|
5440 } |
|
5441 return out.insertBefore(this).translate(s.offsetx, s.offsety); |
|
5442 }; |
|
5443 var curveslengths = {}, |
|
5444 getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) { |
|
5445 var len = 0, |
|
5446 precision = 100, |
|
5447 name = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y].join(), |
|
5448 cache = curveslengths[name], |
|
5449 old, dot; |
|
5450 !cache && (curveslengths[name] = cache = {data: []}); |
|
5451 cache.timer && clearTimeout(cache.timer); |
|
5452 cache.timer = setTimeout(function () {delete curveslengths[name];}, 2e3); |
|
5453 if (length != null && !cache.precision) { |
|
5454 var total = getPointAtSegmentLength(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y); |
|
5455 cache.precision = ~~total * 10; |
|
5456 cache.data = []; |
|
5457 } |
|
5458 precision = cache.precision || precision; |
|
5459 for (var i = 0; i < precision + 1; i++) { |
|
5460 if (cache.data[i * precision]) { |
|
5461 dot = cache.data[i * precision]; |
|
5462 } else { |
|
5463 dot = R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, i / precision); |
|
5464 cache.data[i * precision] = dot; |
|
5465 } |
|
5466 i && (len += pow(pow(old.x - dot.x, 2) + pow(old.y - dot.y, 2), .5)); |
|
5467 if (length != null && len >= length) { |
|
5468 return dot; |
|
5469 } |
|
5470 old = dot; |
|
5471 } |
|
5472 if (length == null) { |
|
5473 return len; |
|
5474 } |
|
5475 }, |
|
5476 getLengthFactory = function (istotal, subpath) { |
|
5477 return function (path, length, onlystart) { |
|
5478 path = path2curve(path); |
|
5479 var x, y, p, l, sp = "", subpaths = {}, point, |
|
5480 len = 0; |
|
5481 for (var i = 0, ii = path.length; i < ii; i++) { |
|
5482 p = path[i]; |
|
5483 if (p[0] == "M") { |
|
5484 x = +p[1]; |
|
5485 y = +p[2]; |
|
5486 } else { |
|
5487 l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]); |
|
5488 if (len + l > length) { |
|
5489 if (subpath && !subpaths.start) { |
|
5490 point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len); |
|
5491 sp += ["C" + point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y]; |
|
5492 if (onlystart) {return sp;} |
|
5493 subpaths.start = sp; |
|
5494 sp = ["M" + point.x, point.y + "C" + point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]].join(); |
|
5495 len += l; |
|
5496 x = +p[5]; |
|
5497 y = +p[6]; |
|
5498 continue; |
|
5499 } |
|
5500 if (!istotal && !subpath) { |
|
5501 point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len); |
|
5502 return {x: point.x, y: point.y, alpha: point.alpha}; |
|
5503 } |
|
5504 } |
|
5505 len += l; |
|
5506 x = +p[5]; |
|
5507 y = +p[6]; |
|
5508 } |
|
5509 sp += p.shift() + p; |
|
5510 } |
|
5511 subpaths.end = sp; |
|
5512 point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1); |
|
5513 point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha}); |
|
5514 return point; |
|
5515 }; |
|
5516 }; |
|
5517 var getTotalLength = getLengthFactory(1), |
|
5518 getPointAtLength = getLengthFactory(), |
|
5519 getSubpathsAtLength = getLengthFactory(0, 1); |
|
5520 |
|
5521 R.getTotalLength = getTotalLength; |
|
5522 |
|
5523 R.getPointAtLength = getPointAtLength; |
|
5524 |
|
5525 R.getSubpath = function (path, from, to) { |
|
5526 if (this.getTotalLength(path) - to < 1e-6) { |
|
5527 return getSubpathsAtLength(path, from).end; |
|
5528 } |
|
5529 var a = getSubpathsAtLength(path, to, 1); |
|
5530 return from ? getSubpathsAtLength(a, from).end : a; |
|
5531 }; |
|
5532 |
|
5533 elproto.getTotalLength = function () { |
|
5534 if (this.type != "path") {return;} |
|
5535 if (this.node.getTotalLength) { |
|
5536 return this.node.getTotalLength(); |
|
5537 } |
|
5538 return getTotalLength(this.attrs.path); |
|
5539 }; |
|
5540 |
|
5541 elproto.getPointAtLength = function (length) { |
|
5542 if (this.type != "path") {return;} |
|
5543 return getPointAtLength(this.attrs.path, length); |
|
5544 }; |
|
5545 |
|
5546 elproto.getSubpath = function (from, to) { |
|
5547 if (this.type != "path") {return;} |
|
5548 return R.getSubpath(this.attrs.path, from, to); |
|
5549 }; |
|
5550 |
|
5551 var ef = R.easing_formulas = { |
|
5552 linear: function (n) { |
|
5553 return n; |
|
5554 }, |
|
5555 "<": function (n) { |
|
5556 return pow(n, 1.7); |
|
5557 }, |
|
5558 ">": function (n) { |
|
5559 return pow(n, .48); |
|
5560 }, |
|
5561 "<>": function (n) { |
|
5562 var q = .48 - n / 1.04, |
|
5563 Q = math.sqrt(.1734 + q * q), |
|
5564 x = Q - q, |
|
5565 X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1), |
|
5566 y = -Q - q, |
|
5567 Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1), |
|
5568 t = X + Y + .5; |
|
5569 return (1 - t) * 3 * t * t + t * t * t; |
|
5570 }, |
|
5571 backIn: function (n) { |
|
5572 var s = 1.70158; |
|
5573 return n * n * ((s + 1) * n - s); |
|
5574 }, |
|
5575 backOut: function (n) { |
|
5576 n = n - 1; |
|
5577 var s = 1.70158; |
|
5578 return n * n * ((s + 1) * n + s) + 1; |
|
5579 }, |
|
5580 elastic: function (n) { |
|
5581 if (n == !!n) { |
|
5582 return n; |
|
5583 } |
|
5584 return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1; |
|
5585 }, |
|
5586 bounce: function (n) { |
|
5587 var s = 7.5625, |
|
5588 p = 2.75, |
|
5589 l; |
|
5590 if (n < (1 / p)) { |
|
5591 l = s * n * n; |
|
5592 } else { |
|
5593 if (n < (2 / p)) { |
|
5594 n -= (1.5 / p); |
|
5595 l = s * n * n + .75; |
|
5596 } else { |
|
5597 if (n < (2.5 / p)) { |
|
5598 n -= (2.25 / p); |
|
5599 l = s * n * n + .9375; |
|
5600 } else { |
|
5601 n -= (2.625 / p); |
|
5602 l = s * n * n + .984375; |
|
5603 } |
|
5604 } |
|
5605 } |
|
5606 return l; |
|
5607 } |
|
5608 }; |
|
5609 ef.easeIn = ef["ease-in"] = ef["<"]; |
|
5610 ef.easeOut = ef["ease-out"] = ef[">"]; |
|
5611 ef.easeInOut = ef["ease-in-out"] = ef["<>"]; |
|
5612 ef["back-in"] = ef.backIn; |
|
5613 ef["back-out"] = ef.backOut; |
|
5614 |
|
5615 var animationElements = [], |
|
5616 requestAnimFrame = window.requestAnimationFrame || |
|
5617 window.webkitRequestAnimationFrame || |
|
5618 window.mozRequestAnimationFrame || |
|
5619 window.oRequestAnimationFrame || |
|
5620 window.msRequestAnimationFrame || |
|
5621 function (callback) { |
|
5622 setTimeout(callback, 16); |
|
5623 }, |
|
5624 animation = function () { |
|
5625 var Now = +new Date, |
|
5626 l = 0; |
|
5627 for (; l < animationElements.length; l++) { |
|
5628 var e = animationElements[l]; |
|
5629 if (e.el.removed || e.paused) { |
|
5630 continue; |
|
5631 } |
|
5632 var time = Now - e.start, |
|
5633 ms = e.ms, |
|
5634 easing = e.easing, |
|
5635 from = e.from, |
|
5636 diff = e.diff, |
|
5637 to = e.to, |
|
5638 t = e.t, |
|
5639 that = e.el, |
|
5640 set = {}, |
|
5641 now, |
|
5642 init = {}, |
|
5643 key; |
|
5644 if (e.initstatus) { |
|
5645 time = (e.initstatus * e.anim.top - e.prev) / (e.percent - e.prev) * ms; |
|
5646 e.status = e.initstatus; |
|
5647 delete e.initstatus; |
|
5648 e.stop && animationElements.splice(l--, 1); |
|
5649 } else { |
|
5650 e.status = (e.prev + (e.percent - e.prev) * (time / ms)) / e.anim.top; |
|
5651 } |
|
5652 if (time < 0) { |
|
5653 continue; |
|
5654 } |
|
5655 if (time < ms) { |
|
5656 var pos = easing(time / ms); |
|
5657 for (var attr in from) if (from[has](attr)) { |
|
5658 switch (availableAnimAttrs[attr]) { |
|
5659 case nu: |
|
5660 now = +from[attr] + pos * ms * diff[attr]; |
|
5661 break; |
|
5662 case "colour": |
|
5663 now = "rgb(" + [ |
|
5664 upto255(round(from[attr].r + pos * ms * diff[attr].r)), |
|
5665 upto255(round(from[attr].g + pos * ms * diff[attr].g)), |
|
5666 upto255(round(from[attr].b + pos * ms * diff[attr].b)) |
|
5667 ].join(",") + ")"; |
|
5668 break; |
|
5669 case "path": |
|
5670 now = []; |
|
5671 for (var i = 0, ii = from[attr].length; i < ii; i++) { |
|
5672 now[i] = [from[attr][i][0]]; |
|
5673 for (var j = 1, jj = from[attr][i].length; j < jj; j++) { |
|
5674 now[i][j] = +from[attr][i][j] + pos * ms * diff[attr][i][j]; |
|
5675 } |
|
5676 now[i] = now[i].join(S); |
|
5677 } |
|
5678 now = now.join(S); |
|
5679 break; |
|
5680 case "transform": |
|
5681 if (diff[attr].real) { |
|
5682 now = []; |
|
5683 for (i = 0, ii = from[attr].length; i < ii; i++) { |
|
5684 now[i] = [from[attr][i][0]]; |
|
5685 for (j = 1, jj = from[attr][i].length; j < jj; j++) { |
|
5686 now[i][j] = from[attr][i][j] + pos * ms * diff[attr][i][j]; |
|
5687 } |
|
5688 } |
|
5689 } else { |
|
5690 var get = function (i) { |
|
5691 return +from[attr][i] + pos * ms * diff[attr][i]; |
|
5692 }; |
|
5693 // now = [["r", get(2), 0, 0], ["t", get(3), get(4)], ["s", get(0), get(1), 0, 0]]; |
|
5694 now = [["m", get(0), get(1), get(2), get(3), get(4), get(5)]]; |
|
5695 } |
|
5696 break; |
|
5697 case "csv": |
|
5698 if (attr == "clip-rect") { |
|
5699 now = []; |
|
5700 i = 4; |
|
5701 while (i--) { |
|
5702 now[i] = +from[attr][i] + pos * ms * diff[attr][i]; |
|
5703 } |
|
5704 } |
|
5705 break; |
|
5706 default: |
|
5707 var from2 = [][concat](from[attr]); |
|
5708 now = []; |
|
5709 i = that.paper.customAttributes[attr].length; |
|
5710 while (i--) { |
|
5711 now[i] = +from2[i] + pos * ms * diff[attr][i]; |
|
5712 } |
|
5713 break; |
|
5714 } |
|
5715 set[attr] = now; |
|
5716 } |
|
5717 that.attr(set); |
|
5718 (function (id, that, anim) { |
|
5719 setTimeout(function () { |
|
5720 eve("anim.frame." + id, that, anim); |
|
5721 }); |
|
5722 })(that.id, that, e.anim); |
|
5723 } else { |
|
5724 (function(f, el, a) { |
|
5725 setTimeout(function() { |
|
5726 eve("anim.frame." + el.id, el, a); |
|
5727 eve("anim.finish." + el.id, el, a); |
|
5728 R.is(f, "function") && f.call(el); |
|
5729 }); |
|
5730 })(e.callback, that, e.anim); |
|
5731 that.attr(to); |
|
5732 animationElements.splice(l--, 1); |
|
5733 if (e.repeat > 1 && !e.next) { |
|
5734 for (key in to) if (to[has](key)) { |
|
5735 init[key] = e.totalOrigin[key]; |
|
5736 } |
|
5737 e.el.attr(init); |
|
5738 runAnimation(e.anim, e.el, e.anim.percents[0], null, e.totalOrigin, e.repeat - 1); |
|
5739 } |
|
5740 if (e.next && !e.stop) { |
|
5741 runAnimation(e.anim, e.el, e.next, null, e.totalOrigin, e.repeat); |
|
5742 } |
|
5743 } |
|
5744 } |
|
5745 R.svg && that && that.paper && that.paper.safari(); |
|
5746 animationElements.length && requestAnimFrame(animation); |
|
5747 }, |
|
5748 upto255 = function (color) { |
|
5749 return color > 255 ? 255 : color < 0 ? 0 : color; |
|
5750 }; |
|
5751 |
|
5752 elproto.animateWith = function (element, anim, params, ms, easing, callback) { |
|
5753 var a = params ? R.animation(params, ms, easing, callback) : anim; |
|
5754 status = element.status(anim); |
|
5755 return this.animate(a).status(a, status * anim.ms / a.ms); |
|
5756 }; |
|
5757 function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) { |
|
5758 var cx = 3 * p1x, |
|
5759 bx = 3 * (p2x - p1x) - cx, |
|
5760 ax = 1 - cx - bx, |
|
5761 cy = 3 * p1y, |
|
5762 by = 3 * (p2y - p1y) - cy, |
|
5763 ay = 1 - cy - by; |
|
5764 function sampleCurveX(t) { |
|
5765 return ((ax * t + bx) * t + cx) * t; |
|
5766 } |
|
5767 function solve(x, epsilon) { |
|
5768 var t = solveCurveX(x, epsilon); |
|
5769 return ((ay * t + by) * t + cy) * t; |
|
5770 } |
|
5771 function solveCurveX(x, epsilon) { |
|
5772 var t0, t1, t2, x2, d2, i; |
|
5773 for(t2 = x, i = 0; i < 8; i++) { |
|
5774 x2 = sampleCurveX(t2) - x; |
|
5775 if (abs(x2) < epsilon) { |
|
5776 return t2; |
|
5777 } |
|
5778 d2 = (3 * ax * t2 + 2 * bx) * t2 + cx; |
|
5779 if (abs(d2) < 1e-6) { |
|
5780 break; |
|
5781 } |
|
5782 t2 = t2 - x2 / d2; |
|
5783 } |
|
5784 t0 = 0; |
|
5785 t1 = 1; |
|
5786 t2 = x; |
|
5787 if (t2 < t0) { |
|
5788 return t0; |
|
5789 } |
|
5790 if (t2 > t1) { |
|
5791 return t1; |
|
5792 } |
|
5793 while (t0 < t1) { |
|
5794 x2 = sampleCurveX(t2); |
|
5795 if (abs(x2 - x) < epsilon) { |
|
5796 return t2; |
|
5797 } |
|
5798 if (x > x2) { |
|
5799 t0 = t2; |
|
5800 } else { |
|
5801 t1 = t2; |
|
5802 } |
|
5803 t2 = (t1 - t0) / 2 + t0; |
|
5804 } |
|
5805 return t2; |
|
5806 } |
|
5807 return solve(t, 1 / (200 * duration)); |
|
5808 } |
|
5809 elproto.onAnimation = function (f) { |
|
5810 f ? eve.on("anim.frame." + this.id, f) : eve.unbind("anim.frame." + this.id); |
|
5811 return this; |
|
5812 }; |
|
5813 function Animation(anim, ms) { |
|
5814 var percents = [], |
|
5815 newAnim = {}; |
|
5816 this.ms = ms; |
|
5817 this.times = 1; |
|
5818 if (anim) { |
|
5819 for (var attr in anim) if (anim[has](attr)) { |
|
5820 newAnim[toFloat(attr)] = anim[attr]; |
|
5821 percents.push(toFloat(attr)); |
|
5822 } |
|
5823 percents.sort(sortByNumber); |
|
5824 } |
|
5825 this.anim = newAnim; |
|
5826 this.top = percents[percents.length - 1]; |
|
5827 this.percents = percents; |
|
5828 } |
|
5829 |
|
5830 Animation.prototype.delay = function (delay) { |
|
5831 var a = new Animation(this.anim, this.ms); |
|
5832 a.times = this.times; |
|
5833 a.del = +delay || 0; |
|
5834 return a; |
|
5835 }; |
|
5836 |
|
5837 Animation.prototype.repeat = function (times) { |
|
5838 var a = new Animation(this.anim, this.ms); |
|
5839 a.del = this.del; |
|
5840 a.times = math.floor(mmax(times, 0)) || 1; |
|
5841 return a; |
|
5842 }; |
|
5843 function runAnimation(anim, element, percent, status, totalOrigin, times) { |
|
5844 percent = toFloat(percent); |
|
5845 var params, |
|
5846 isInAnim, |
|
5847 isInAnimSet, |
|
5848 percents = [], |
|
5849 next, |
|
5850 prev, |
|
5851 timestamp, |
|
5852 ms = anim.ms, |
|
5853 from = {}, |
|
5854 to = {}, |
|
5855 diff = {}; |
|
5856 if (status) { |
|
5857 for (i = 0, ii = animationElements.length; i < ii; i++) { |
|
5858 var e = animationElements[i]; |
|
5859 if (e.el.id == element.id && e.anim == anim) { |
|
5860 if (e.percent != percent) { |
|
5861 animationElements.splice(i, 1); |
|
5862 isInAnimSet = 1; |
|
5863 } else { |
|
5864 isInAnim = e; |
|
5865 } |
|
5866 element.attr(e.totalOrigin); |
|
5867 break; |
|
5868 } |
|
5869 } |
|
5870 } else { |
|
5871 status = +to; // NaN |
|
5872 } |
|
5873 for (var i = 0, ii = anim.percents.length; i < ii; i++) { |
|
5874 if (anim.percents[i] == percent || anim.percents[i] > status * anim.top) { |
|
5875 percent = anim.percents[i]; |
|
5876 prev = anim.percents[i - 1] || 0; |
|
5877 ms = ms / anim.top * (percent - prev); |
|
5878 next = anim.percents[i + 1]; |
|
5879 params = anim.anim[percent]; |
|
5880 break; |
|
5881 } else if (status) { |
|
5882 element.attr(anim.anim[anim.percents[i]]); |
|
5883 } |
|
5884 } |
|
5885 if (!params) { |
|
5886 return; |
|
5887 } |
|
5888 if (!isInAnim) { |
|
5889 for (attr in params) if (params[has](attr)) { |
|
5890 if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) { |
|
5891 from[attr] = element.attr(attr); |
|
5892 (from[attr] == null) && (from[attr] = availableAttrs[attr]); |
|
5893 to[attr] = params[attr]; |
|
5894 switch (availableAnimAttrs[attr]) { |
|
5895 case nu: |
|
5896 diff[attr] = (to[attr] - from[attr]) / ms; |
|
5897 break; |
|
5898 case "colour": |
|
5899 from[attr] = R.getRGB(from[attr]); |
|
5900 var toColour = R.getRGB(to[attr]); |
|
5901 diff[attr] = { |
|
5902 r: (toColour.r - from[attr].r) / ms, |
|
5903 g: (toColour.g - from[attr].g) / ms, |
|
5904 b: (toColour.b - from[attr].b) / ms |
|
5905 }; |
|
5906 break; |
|
5907 case "path": |
|
5908 var pathes = path2curve(from[attr], to[attr]), |
|
5909 toPath = pathes[1]; |
|
5910 from[attr] = pathes[0]; |
|
5911 diff[attr] = []; |
|
5912 for (i = 0, ii = from[attr].length; i < ii; i++) { |
|
5913 diff[attr][i] = [0]; |
|
5914 for (var j = 1, jj = from[attr][i].length; j < jj; j++) { |
|
5915 diff[attr][i][j] = (toPath[i][j] - from[attr][i][j]) / ms; |
|
5916 } |
|
5917 } |
|
5918 break; |
|
5919 case "transform": |
|
5920 var _ = element._, |
|
5921 eq = equaliseTransform(_[attr], to[attr]); |
|
5922 if (eq) { |
|
5923 from[attr] = eq.from; |
|
5924 to[attr] = eq.to; |
|
5925 diff[attr] = []; |
|
5926 diff[attr].real = true; |
|
5927 for (i = 0, ii = from[attr].length; i < ii; i++) { |
|
5928 diff[attr][i] = [from[attr][i][0]]; |
|
5929 for (j = 1, jj = from[attr][i].length; j < jj; j++) { |
|
5930 diff[attr][i][j] = (to[attr][i][j] - from[attr][i][j]) / ms; |
|
5931 } |
|
5932 } |
|
5933 } else { |
|
5934 var m = (element.matrix || new Matrix), |
|
5935 to2 = { |
|
5936 _: {transform: _.transform}, |
|
5937 getBBox: function () { |
|
5938 return element.getBBox(1); |
|
5939 } |
|
5940 }; |
|
5941 from[attr] = [ |
|
5942 m.a, |
|
5943 m.b, |
|
5944 m.c, |
|
5945 m.d, |
|
5946 m.e, |
|
5947 m.f |
|
5948 ]; |
|
5949 extractTransform(to2, to[attr]); |
|
5950 to[attr] = to2._.transform; |
|
5951 diff[attr] = [ |
|
5952 (to2.matrix.a - m.a) / ms, |
|
5953 (to2.matrix.b - m.b) / ms, |
|
5954 (to2.matrix.c - m.c) / ms, |
|
5955 (to2.matrix.d - m.d) / ms, |
|
5956 (to2.matrix.e - m.e) / ms, |
|
5957 (to2.matrix.e - m.f) / ms |
|
5958 ]; |
|
5959 // from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy]; |
|
5960 // var to2 = {_:{}, getBBox: function () { return element.getBBox(); }}; |
|
5961 // extractTransform(to2, to[attr]); |
|
5962 // diff[attr] = [ |
|
5963 // (to2._.sx - _.sx) / ms, |
|
5964 // (to2._.sy - _.sy) / ms, |
|
5965 // (to2._.deg - _.deg) / ms, |
|
5966 // (to2._.dx - _.dx) / ms, |
|
5967 // (to2._.dy - _.dy) / ms |
|
5968 // ]; |
|
5969 } |
|
5970 break; |
|
5971 case "csv": |
|
5972 var values = Str(params[attr])[split](separator), |
|
5973 from2 = Str(from[attr])[split](separator); |
|
5974 if (attr == "clip-rect") { |
|
5975 from[attr] = from2; |
|
5976 diff[attr] = []; |
|
5977 i = from2.length; |
|
5978 while (i--) { |
|
5979 diff[attr][i] = (values[i] - from[attr][i]) / ms; |
|
5980 } |
|
5981 } |
|
5982 to[attr] = values; |
|
5983 break; |
|
5984 default: |
|
5985 values = [][concat](params[attr]); |
|
5986 from2 = [][concat](from[attr]); |
|
5987 diff[attr] = []; |
|
5988 i = element.paper.customAttributes[attr].length; |
|
5989 while (i--) { |
|
5990 diff[attr][i] = ((values[i] || 0) - (from2[i] || 0)) / ms; |
|
5991 } |
|
5992 break; |
|
5993 } |
|
5994 } |
|
5995 } |
|
5996 var easing = params.easing, |
|
5997 easyeasy = R.easing_formulas[easing]; |
|
5998 if (!easyeasy) { |
|
5999 easyeasy = Str(easing).match(bezierrg); |
|
6000 if (easyeasy && easyeasy.length == 5) { |
|
6001 var curve = easyeasy; |
|
6002 easyeasy = function (t) { |
|
6003 return CubicBezierAtTime(t, +curve[1], +curve[2], +curve[3], +curve[4], ms); |
|
6004 }; |
|
6005 } else { |
|
6006 easyeasy = pipe; |
|
6007 } |
|
6008 } |
|
6009 timestamp = params.start || anim.start || +new Date; |
|
6010 e = { |
|
6011 anim: anim, |
|
6012 percent: percent, |
|
6013 timestamp: timestamp, |
|
6014 start: timestamp + (anim.del || 0), |
|
6015 status: 0, |
|
6016 initstatus: status || 0, |
|
6017 stop: false, |
|
6018 ms: ms, |
|
6019 easing: easyeasy, |
|
6020 from: from, |
|
6021 diff: diff, |
|
6022 to: to, |
|
6023 el: element, |
|
6024 callback: params.callback, |
|
6025 prev: prev, |
|
6026 next: next, |
|
6027 repeat: times || anim.times, |
|
6028 origin: element.attr(), |
|
6029 totalOrigin: totalOrigin |
|
6030 }; |
|
6031 animationElements.push(e); |
|
6032 if (status && !isInAnim && !isInAnimSet) { |
|
6033 e.stop = true; |
|
6034 e.start = new Date - ms * status; |
|
6035 if (animationElements.length == 1) { |
|
6036 return animation(); |
|
6037 } |
|
6038 } |
|
6039 if (isInAnimSet) { |
|
6040 e.start = new Date - e.ms * status; |
|
6041 } |
|
6042 animationElements.length == 1 && requestAnimFrame(animation); |
|
6043 } else { |
|
6044 isInAnim.initstatus = status; |
|
6045 isInAnim.start = new Date - isInAnim.ms * status; |
|
6046 } |
|
6047 eve("anim.start." + element.id, element, anim); |
|
6048 } |
|
6049 |
|
6050 R.animation = function (params, ms, easing, callback) { |
|
6051 if (params instanceof Animation) { |
|
6052 return params; |
|
6053 } |
|
6054 if (R.is(easing, "function") || !easing) { |
|
6055 callback = callback || easing || null; |
|
6056 easing = null; |
|
6057 } |
|
6058 params = Object(params); |
|
6059 ms = +ms || 0; |
|
6060 var p = {}, |
|
6061 json, |
|
6062 attr; |
|
6063 for (attr in params) if (params[has](attr) && toFloat(attr) != attr && toFloat(attr) + "%" != attr) { |
|
6064 json = true; |
|
6065 p[attr] = params[attr]; |
|
6066 } |
|
6067 if (!json) { |
|
6068 return new Animation(params, ms); |
|
6069 } else { |
|
6070 easing && (p.easing = easing); |
|
6071 callback && (p.callback = callback); |
|
6072 return new Animation({100: p}, ms); |
|
6073 } |
|
6074 }; |
|
6075 |
|
6076 elproto.animate = function (params, ms, easing, callback) { |
|
6077 var element = this; |
|
6078 if (element.removed) { |
|
6079 callback && callback.call(element); |
|
6080 return element; |
|
6081 } |
|
6082 var anim = params instanceof Animation ? params : R.animation(params, ms, easing, callback); |
|
6083 runAnimation(anim, element, anim.percents[0], null, element.attr()); |
|
6084 return element; |
|
6085 }; |
|
6086 |
|
6087 elproto.setTime = function (anim, value) { |
|
6088 if (anim && value != null) { |
|
6089 this.status(anim, mmin(value, anim.ms) / anim.ms); |
|
6090 } |
|
6091 return this; |
|
6092 }; |
|
6093 |
|
6094 elproto.status = function (anim, value) { |
|
6095 var out = [], |
|
6096 i = 0, |
|
6097 len, |
|
6098 e; |
|
6099 if (value != null) { |
|
6100 runAnimation(anim, this, -1, mmin(value, 1)); |
|
6101 return this; |
|
6102 } else { |
|
6103 len = animationElements.length; |
|
6104 for (; i < len; i++) { |
|
6105 e = animationElements[i]; |
|
6106 if (e.el.id == this.id && (!anim || e.anim == anim)) { |
|
6107 if (anim) { |
|
6108 return e.status; |
|
6109 } |
|
6110 out.push({ |
|
6111 anim: e.anim, |
|
6112 status: e.status |
|
6113 }); |
|
6114 } |
|
6115 } |
|
6116 if (anim) { |
|
6117 return 0; |
|
6118 } |
|
6119 return out; |
|
6120 } |
|
6121 }; |
|
6122 |
|
6123 elproto.pause = function (anim) { |
|
6124 for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { |
|
6125 if (eve("anim.pause." + this.id, this, animationElements[i].anim) !== false) { |
|
6126 animationElements[i].paused = true; |
|
6127 } |
|
6128 } |
|
6129 return this; |
|
6130 }; |
|
6131 |
|
6132 elproto.resume = function (anim) { |
|
6133 for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { |
|
6134 var e = animationElements[i]; |
|
6135 if (eve("anim.resume." + this.id, this, e.anim) !== false) { |
|
6136 delete e.paused; |
|
6137 this.status(e.anim, e.status); |
|
6138 } |
|
6139 } |
|
6140 return this; |
|
6141 }; |
|
6142 |
|
6143 elproto.stop = function (anim) { |
|
6144 for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) { |
|
6145 if (eve("anim.stop." + this.id, this, animationElements[i].anim) !== false) { |
|
6146 animationElements.splice(i--, 1); |
|
6147 } |
|
6148 } |
|
6149 return this; |
|
6150 }; |
|
6151 elproto.toString = function () { |
|
6152 return "Rapha\xebl\u2019s object"; |
|
6153 }; |
|
6154 |
|
6155 // Set |
|
6156 var Set = function (items) { |
|
6157 this.items = []; |
|
6158 this.length = 0; |
|
6159 this.type = "set"; |
|
6160 if (items) { |
|
6161 for (var i = 0, ii = items.length; i < ii; i++) { |
|
6162 if (items[i] && (items[i].constructor == elproto.constructor || items[i].constructor == Set)) { |
|
6163 this[this.items.length] = this.items[this.items.length] = items[i]; |
|
6164 this.length++; |
|
6165 } |
|
6166 } |
|
6167 } |
|
6168 }, |
|
6169 setproto = Set.prototype; |
|
6170 |
|
6171 setproto.push = function () { |
|
6172 var item, |
|
6173 len; |
|
6174 for (var i = 0, ii = arguments.length; i < ii; i++) { |
|
6175 item = arguments[i]; |
|
6176 if (item && (item.constructor == elproto.constructor || item.constructor == Set)) { |
|
6177 len = this.items.length; |
|
6178 this[len] = this.items[len] = item; |
|
6179 this.length++; |
|
6180 } |
|
6181 } |
|
6182 return this; |
|
6183 }; |
|
6184 |
|
6185 setproto.pop = function () { |
|
6186 this.length && delete this[this.length--]; |
|
6187 return this.items.pop(); |
|
6188 }; |
|
6189 |
|
6190 setproto.forEach = function (callback, thisArg) { |
|
6191 for (var i = 0, ii = this.items.length; i < ii; i++) { |
|
6192 if (callback.call(thisArg, this.items[i], i) === false) { |
|
6193 return this; |
|
6194 } |
|
6195 } |
|
6196 return this; |
|
6197 }; |
|
6198 for (var method in elproto) if (elproto[has](method)) { |
|
6199 setproto[method] = (function (methodname) { |
|
6200 return function () { |
|
6201 var arg = arguments; |
|
6202 return this.forEach(function (el) { |
|
6203 el[methodname][apply](el, arg); |
|
6204 }); |
|
6205 }; |
|
6206 })(method); |
|
6207 } |
|
6208 setproto.attr = function (name, value) { |
|
6209 if (name && R.is(name, array) && R.is(name[0], "object")) { |
|
6210 for (var j = 0, jj = name.length; j < jj; j++) { |
|
6211 this.items[j].attr(name[j]); |
|
6212 } |
|
6213 } else { |
|
6214 for (var i = 0, ii = this.items.length; i < ii; i++) { |
|
6215 this.items[i].attr(name, value); |
|
6216 } |
|
6217 } |
|
6218 return this; |
|
6219 }; |
|
6220 |
|
6221 setproto.clear = function () { |
|
6222 while (this.length) { |
|
6223 this.pop(); |
|
6224 } |
|
6225 }; |
|
6226 |
|
6227 setproto.splice = function (index, count, insertion) { |
|
6228 index = index < 0 ? mmax(this.length + index, 0) : index; |
|
6229 count = mmax(0, mmin(this.length - index, count)); |
|
6230 var tail = [], |
|
6231 todel = [], |
|
6232 args = [], |
|
6233 i; |
|
6234 for (i = 2; i < arguments.length; i++) { |
|
6235 args.push(arguments[i]); |
|
6236 } |
|
6237 for (i = 0; i < count; i++) { |
|
6238 todel.push(this[index + i]); |
|
6239 } |
|
6240 for (; i < this.length - index; i++) { |
|
6241 tail.push(this[index + i]); |
|
6242 } |
|
6243 var arglen = args.length; |
|
6244 for (i = 0; i < arglen + tail.length; i++) { |
|
6245 this.items[index + i] = this[index + i] = i < arglen ? args[i] : tail[i - arglen]; |
|
6246 } |
|
6247 i = this.items.length = this.length -= count - arglen; |
|
6248 while (this[i]) { |
|
6249 delete this[i++]; |
|
6250 } |
|
6251 return new Set(todel); |
|
6252 }; |
|
6253 |
|
6254 setproto.exclude = function (el) { |
|
6255 for (var i = 0, ii = this.length; i < ii; i++) if (this[i] == el) { |
|
6256 this.splice(i, 1); |
|
6257 return true; |
|
6258 } |
|
6259 }; |
|
6260 setproto.animate = function (params, ms, easing, callback) { |
|
6261 (R.is(easing, "function") || !easing) && (callback = easing || null); |
|
6262 var len = this.items.length, |
|
6263 i = len, |
|
6264 item, |
|
6265 set = this, |
|
6266 collector; |
|
6267 if (!len) { |
|
6268 return this; |
|
6269 } |
|
6270 callback && (collector = function () { |
|
6271 !--len && callback.call(set); |
|
6272 }); |
|
6273 easing = R.is(easing, string) ? easing : collector; |
|
6274 var anim = R.animation(params, ms, easing, collector); |
|
6275 item = this.items[--i].animate(anim); |
|
6276 while (i--) { |
|
6277 this.items[i] && !this.items[i].removed && this.items[i].animateWith(item, anim); |
|
6278 } |
|
6279 return this; |
|
6280 }; |
|
6281 setproto.insertAfter = function (el) { |
|
6282 var i = this.items.length; |
|
6283 while (i--) { |
|
6284 this.items[i].insertAfter(el); |
|
6285 } |
|
6286 return this; |
|
6287 }; |
|
6288 setproto.getBBox = function () { |
|
6289 var x = [], |
|
6290 y = [], |
|
6291 w = [], |
|
6292 h = []; |
|
6293 for (var i = this.items.length; i--;) if (!this.items[i].removed) { |
|
6294 var box = this.items[i].getBBox(); |
|
6295 x.push(box.x); |
|
6296 y.push(box.y); |
|
6297 w.push(box.x + box.width); |
|
6298 h.push(box.y + box.height); |
|
6299 } |
|
6300 x = mmin[apply](0, x); |
|
6301 y = mmin[apply](0, y); |
|
6302 return { |
|
6303 x: x, |
|
6304 y: y, |
|
6305 width: mmax[apply](0, w) - x, |
|
6306 height: mmax[apply](0, h) - y |
|
6307 }; |
|
6308 }; |
|
6309 setproto.clone = function (s) { |
|
6310 s = new Set; |
|
6311 for (var i = 0, ii = this.items.length; i < ii; i++) { |
|
6312 s.push(this.items[i].clone()); |
|
6313 } |
|
6314 return s; |
|
6315 }; |
|
6316 setproto.toString = function () { |
|
6317 return "Rapha\xebl\u2018s set"; |
|
6318 }; |
|
6319 |
|
6320 |
|
6321 R.registerFont = function (font) { |
|
6322 if (!font.face) { |
|
6323 return font; |
|
6324 } |
|
6325 this.fonts = this.fonts || {}; |
|
6326 var fontcopy = { |
|
6327 w: font.w, |
|
6328 face: {}, |
|
6329 glyphs: {} |
|
6330 }, |
|
6331 family = font.face["font-family"]; |
|
6332 for (var prop in font.face) if (font.face[has](prop)) { |
|
6333 fontcopy.face[prop] = font.face[prop]; |
|
6334 } |
|
6335 if (this.fonts[family]) { |
|
6336 this.fonts[family].push(fontcopy); |
|
6337 } else { |
|
6338 this.fonts[family] = [fontcopy]; |
|
6339 } |
|
6340 if (!font.svg) { |
|
6341 fontcopy.face["units-per-em"] = toInt(font.face["units-per-em"], 10); |
|
6342 for (var glyph in font.glyphs) if (font.glyphs[has](glyph)) { |
|
6343 var path = font.glyphs[glyph]; |
|
6344 fontcopy.glyphs[glyph] = { |
|
6345 w: path.w, |
|
6346 k: {}, |
|
6347 d: path.d && "M" + path.d.replace(/[mlcxtrv]/g, function (command) { |
|
6348 return {l: "L", c: "C", x: "z", t: "m", r: "l", v: "c"}[command] || "M"; |
|
6349 }) + "z" |
|
6350 }; |
|
6351 if (path.k) { |
|
6352 for (var k in path.k) if (path[has](k)) { |
|
6353 fontcopy.glyphs[glyph].k[k] = path.k[k]; |
|
6354 } |
|
6355 } |
|
6356 } |
|
6357 } |
|
6358 return font; |
|
6359 }; |
|
6360 |
|
6361 paperproto.getFont = function (family, weight, style, stretch) { |
|
6362 stretch = stretch || "normal"; |
|
6363 style = style || "normal"; |
|
6364 weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400; |
|
6365 if (!R.fonts) { |
|
6366 return; |
|
6367 } |
|
6368 var font = R.fonts[family]; |
|
6369 if (!font) { |
|
6370 var name = new RegExp("(^|\\s)" + family.replace(/[^\w\d\s+!~.:_-]/g, E) + "(\\s|$)", "i"); |
|
6371 for (var fontName in R.fonts) if (R.fonts[has](fontName)) { |
|
6372 if (name.test(fontName)) { |
|
6373 font = R.fonts[fontName]; |
|
6374 break; |
|
6375 } |
|
6376 } |
|
6377 } |
|
6378 var thefont; |
|
6379 if (font) { |
|
6380 for (var i = 0, ii = font.length; i < ii; i++) { |
|
6381 thefont = font[i]; |
|
6382 if (thefont.face["font-weight"] == weight && (thefont.face["font-style"] == style || !thefont.face["font-style"]) && thefont.face["font-stretch"] == stretch) { |
|
6383 break; |
|
6384 } |
|
6385 } |
|
6386 } |
|
6387 return thefont; |
|
6388 }; |
|
6389 |
|
6390 paperproto.print = function (x, y, string, font, size, origin, letter_spacing) { |
|
6391 origin = origin || "middle"; // baseline|middle |
|
6392 letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1); |
|
6393 var out = this.set(), |
|
6394 letters = Str(string)[split](E), |
|
6395 shift = 0, |
|
6396 path = E, |
|
6397 scale; |
|
6398 R.is(font, string) && (font = this.getFont(font)); |
|
6399 if (font) { |
|
6400 scale = (size || 16) / font.face["units-per-em"]; |
|
6401 var bb = font.face.bbox[split](separator), |
|
6402 top = +bb[0], |
|
6403 height = +bb[1] + (origin == "baseline" ? bb[3] - bb[1] + (+font.face.descent) : (bb[3] - bb[1]) / 2); |
|
6404 for (var i = 0, ii = letters.length; i < ii; i++) { |
|
6405 var prev = i && font.glyphs[letters[i - 1]] || {}, |
|
6406 curr = font.glyphs[letters[i]]; |
|
6407 shift += i ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) + (font.w * letter_spacing) : 0; |
|
6408 curr && curr.d && out.push(this.path(curr.d).attr({ |
|
6409 fill: "#000", |
|
6410 stroke: "none", |
|
6411 transform: [["t", shift * scale, 0]] |
|
6412 })); |
|
6413 } |
|
6414 out.transform(["...s", scale, scale, top, height, "t", (x - top) / scale, (y - height) / scale]); |
|
6415 } |
|
6416 return out; |
|
6417 }; |
|
6418 |
|
6419 |
|
6420 R.format = function (token, params) { |
|
6421 var args = R.is(params, array) ? [0][concat](params) : arguments; |
|
6422 token && R.is(token, string) && args.length - 1 && (token = token.replace(formatrg, function (str, i) { |
|
6423 return args[++i] == null ? E : args[i]; |
|
6424 })); |
|
6425 return token || E; |
|
6426 }; |
|
6427 |
|
6428 R.fullfill = (function () { |
|
6429 var tokenRegex = /\{([^\}]+)\}/g, |
|
6430 objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g, // matches .xxxxx or ["xxxxx"] to run over object properties |
|
6431 replacer = function (all, key, obj) { |
|
6432 var res = obj; |
|
6433 key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) { |
|
6434 name = name || quotedName; |
|
6435 if (res) { |
|
6436 if (name in res) { |
|
6437 res = res[name]; |
|
6438 } |
|
6439 typeof res == "function" && isFunc && (res = res()); |
|
6440 } |
|
6441 }); |
|
6442 res = (res == null || res == obj ? all : res) + ""; |
|
6443 return res; |
|
6444 }; |
|
6445 return function (str, obj) { |
|
6446 return String(str).replace(tokenRegex, function (all, key) { |
|
6447 return replacer(all, key, obj); |
|
6448 }); |
|
6449 }; |
|
6450 })(); |
|
6451 |
|
6452 R.ninja = function () { |
|
6453 oldRaphael.was ? (g.win.Raphael = oldRaphael.is) : delete Raphael; |
|
6454 return R; |
|
6455 }; |
|
6456 |
|
6457 R.st = setproto; |
|
6458 // Firefox <3.6 fix: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html |
|
6459 (function (doc, loaded, f) { |
|
6460 if (doc.readyState == null && doc.addEventListener){ |
|
6461 doc.addEventListener(loaded, f = function () { |
|
6462 doc.removeEventListener(loaded, f, false); |
|
6463 doc.readyState = "complete"; |
|
6464 }, false); |
|
6465 doc.readyState = "loading"; |
|
6466 } |
|
6467 function isLoaded() { |
|
6468 (/in/).test(doc.readyState) ? setTimeout(isLoaded, 9) : R.eve("DOMload"); |
|
6469 } |
|
6470 isLoaded(); |
|
6471 })(document, "DOMContentLoaded"); |
|
6472 |
|
6473 oldRaphael.was ? (g.win.Raphael = R) : (Raphael = R); |
|
6474 |
|
6475 eve.on("DOMload", function () { |
|
6476 loaded = true; |
|
6477 }); |
|
6478 })(); |
|
6479 |
|
6480 // ┌─────────────────────────────────────────────────────────────────────┐ \\ |
|
6481 // │ Raphaël 2 - JavaScript Vector Library │ \\ |
|
6482 // ├─────────────────────────────────────────────────────────────────────┤ \\ |
|
6483 // │ SVG Module │ \\ |
|
6484 // ├─────────────────────────────────────────────────────────────────────┤ \\ |
|
6485 // │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\ |
|
6486 // │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\ |
|
6487 // │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\ |
|
6488 // └─────────────────────────────────────────────────────────────────────┘ \\ |
|
6489 window.Raphael.svg && function (R) { |
|
6490 var has = "hasOwnProperty", |
|
6491 Str = String, |
|
6492 toFloat = parseFloat, |
|
6493 toInt = parseInt, |
|
6494 math = Math, |
|
6495 mmax = math.max, |
|
6496 abs = math.abs, |
|
6497 pow = math.pow, |
|
6498 separator = /[, ]+/, |
|
6499 eve = R.eve, |
|
6500 E = "", |
|
6501 S = " "; |
|
6502 var xlink = "http://www.w3.org/1999/xlink", |
|
6503 markers = { |
|
6504 block: "M5,0 0,2.5 5,5z", |
|
6505 classic: "M5,0 0,2.5 5,5 3.5,3 3.5,2z", |
|
6506 diamond: "M2.5,0 5,2.5 2.5,5 0,2.5z", |
|
6507 open: "M6,1 1,3.5 6,6", |
|
6508 oval: "M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z" |
|
6509 }, |
|
6510 markerCounter = {}; |
|
6511 R.toString = function () { |
|
6512 return "Your browser supports SVG.\nYou are running Rapha\xebl " + this.version; |
|
6513 }; |
|
6514 var $ = function (el, attr) { |
|
6515 if (attr) { |
|
6516 if (typeof el == "string") { |
|
6517 el = $(el); |
|
6518 } |
|
6519 for (var key in attr) if (attr[has](key)) { |
|
6520 if (key.substring(0, 6) == "xlink:") { |
|
6521 el.setAttributeNS(xlink, key.substring(6), Str(attr[key])); |
|
6522 } else { |
|
6523 el.setAttribute(key, Str(attr[key])); |
|
6524 } |
|
6525 } |
|
6526 } else { |
|
6527 el = R._g.doc.createElementNS("http://www.w3.org/2000/svg", el); |
|
6528 el.style && (el.style.webkitTapHighlightColor = "rgba(0,0,0,0)"); |
|
6529 } |
|
6530 return el; |
|
6531 }, |
|
6532 gradients = {}, |
|
6533 rgGrad = /^url\(#(.*)\)$/, |
|
6534 removeGradientFill = function (node, paper) { |
|
6535 var oid = node.getAttribute("fill"); |
|
6536 oid = oid && oid.match(rgGrad); |
|
6537 if (oid && !--gradients[oid[1]]) { |
|
6538 delete gradients[oid[1]]; |
|
6539 paper.defs.removeChild(R._g.doc.getElementById(oid[1])); |
|
6540 } |
|
6541 }, |
|
6542 addGradientFill = function (element, gradient) { |
|
6543 var type = "linear", |
|
6544 id = element.id + gradient, |
|
6545 fx = .5, fy = .5, |
|
6546 o = element.node, |
|
6547 SVG = element.paper, |
|
6548 s = o.style, |
|
6549 el = R._g.doc.getElementById(id); |
|
6550 if (!el) { |
|
6551 gradient = Str(gradient).replace(R._radial_gradient, function (all, _fx, _fy) { |
|
6552 type = "radial"; |
|
6553 if (_fx && _fy) { |
|
6554 fx = toFloat(_fx); |
|
6555 fy = toFloat(_fy); |
|
6556 var dir = ((fy > .5) * 2 - 1); |
|
6557 pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && |
|
6558 (fy = math.sqrt(.25 - pow(fx - .5, 2)) * dir + .5) && |
|
6559 fy != .5 && |
|
6560 (fy = fy.toFixed(5) - 1e-5 * dir); |
|
6561 } |
|
6562 return E; |
|
6563 }); |
|
6564 gradient = gradient.split(/\s*\-\s*/); |
|
6565 if (type == "linear") { |
|
6566 var angle = gradient.shift(); |
|
6567 angle = -toFloat(angle); |
|
6568 if (isNaN(angle)) { |
|
6569 return null; |
|
6570 } |
|
6571 var vector = [0, 0, math.cos(R.rad(angle)), math.sin(R.rad(angle))], |
|
6572 max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1); |
|
6573 vector[2] *= max; |
|
6574 vector[3] *= max; |
|
6575 if (vector[2] < 0) { |
|
6576 vector[0] = -vector[2]; |
|
6577 vector[2] = 0; |
|
6578 } |
|
6579 if (vector[3] < 0) { |
|
6580 vector[1] = -vector[3]; |
|
6581 vector[3] = 0; |
|
6582 } |
|
6583 } |
|
6584 var dots = R._parseDots(gradient); |
|
6585 if (!dots) { |
|
6586 return null; |
|
6587 } |
|
6588 if (element.gradient) { |
|
6589 SVG.defs.removeChild(element.gradient); |
|
6590 delete element.gradient; |
|
6591 } |
|
6592 |
|
6593 id = id.replace(/[\(\)\s,\xb0#]/g, "-"); |
|
6594 el = $(type + "Gradient", {id: id}); |
|
6595 element.gradient = el; |
|
6596 $(el, type == "radial" ? { |
|
6597 fx: fx, |
|
6598 fy: fy |
|
6599 } : { |
|
6600 x1: vector[0], |
|
6601 y1: vector[1], |
|
6602 x2: vector[2], |
|
6603 y2: vector[3], |
|
6604 gradientTransform: element.matrix.invert() |
|
6605 }); |
|
6606 SVG.defs.appendChild(el); |
|
6607 for (var i = 0, ii = dots.length; i < ii; i++) { |
|
6608 el.appendChild($("stop", { |
|
6609 offset: dots[i].offset ? dots[i].offset : i ? "100%" : "0%", |
|
6610 "stop-color": dots[i].color || "#fff" |
|
6611 })); |
|
6612 } |
|
6613 } |
|
6614 $(o, { |
|
6615 fill: "url(#" + id + ")", |
|
6616 opacity: 1, |
|
6617 "fill-opacity": 1 |
|
6618 }); |
|
6619 s.fill = E; |
|
6620 s.opacity = 1; |
|
6621 s.fillOpacity = 1; |
|
6622 return 1; |
|
6623 }, |
|
6624 updatePosition = function (o) { |
|
6625 var bbox = o.getBBox(1); |
|
6626 $(o.pattern, {patternTransform: o.matrix.invert() + " translate(" + bbox.x + "," + bbox.y + ")"}); |
|
6627 }, |
|
6628 addArrow = function (o, value, isEnd) { |
|
6629 if (o.type == "path") { |
|
6630 var values = Str(value).toLowerCase().split("-"), |
|
6631 p = o.paper, |
|
6632 se = isEnd ? "end" : "start", |
|
6633 node = o.node, |
|
6634 attrs = o.attrs, |
|
6635 stroke = attrs["stroke-width"], |
|
6636 i = values.length, |
|
6637 type = "classic", |
|
6638 from, |
|
6639 to, |
|
6640 dx, |
|
6641 refX, |
|
6642 attr, |
|
6643 w = 3, |
|
6644 h = 3, |
|
6645 t = 5; |
|
6646 while (i--) { |
|
6647 switch (values[i]) { |
|
6648 case "block": |
|
6649 case "classic": |
|
6650 case "oval": |
|
6651 case "diamond": |
|
6652 case "open": |
|
6653 case "none": |
|
6654 type = values[i]; |
|
6655 break; |
|
6656 case "wide": h = 5; break; |
|
6657 case "narrow": h = 2; break; |
|
6658 case "long": w = 5; break; |
|
6659 case "short": w = 2; break; |
|
6660 } |
|
6661 } |
|
6662 if (type == "open") { |
|
6663 w += 2; |
|
6664 h += 2; |
|
6665 t += 2; |
|
6666 dx = 1; |
|
6667 refX = isEnd ? 4 : 1; |
|
6668 attr = { |
|
6669 fill: "none", |
|
6670 stroke: attrs.stroke |
|
6671 }; |
|
6672 } else { |
|
6673 refX = dx = w / 2; |
|
6674 attr = { |
|
6675 fill: attrs.stroke, |
|
6676 stroke: "none" |
|
6677 }; |
|
6678 } |
|
6679 if (o._.arrows) { |
|
6680 if (isEnd) { |
|
6681 o._.arrows.endPath && markerCounter[o._.arrows.endPath]--; |
|
6682 o._.arrows.endMarker && markerCounter[o._.arrows.endMarker]--; |
|
6683 } else { |
|
6684 o._.arrows.startPath && markerCounter[o._.arrows.startPath]--; |
|
6685 o._.arrows.startMarker && markerCounter[o._.arrows.startMarker]--; |
|
6686 } |
|
6687 } else { |
|
6688 o._.arrows = {}; |
|
6689 } |
|
6690 if (type != "none") { |
|
6691 var pathId = "raphael-marker-" + type, |
|
6692 markerId = "raphael-marker-" + se + type + w + h; |
|
6693 if (!R._g.doc.getElementById(pathId)) { |
|
6694 p.defs.appendChild($($("path"), { |
|
6695 "stroke-linecap": "round", |
|
6696 d: markers[type], |
|
6697 id: pathId |
|
6698 })); |
|
6699 markerCounter[pathId] = 1; |
|
6700 } else { |
|
6701 markerCounter[pathId]++; |
|
6702 } |
|
6703 var marker = R._g.doc.getElementById(markerId), |
|
6704 use; |
|
6705 if (!marker) { |
|
6706 marker = $($("marker"), { |
|
6707 id: markerId, |
|
6708 markerHeight: h, |
|
6709 markerWidth: w, |
|
6710 orient: "auto", |
|
6711 refX: refX, |
|
6712 refY: h / 2 |
|
6713 }); |
|
6714 use = $($("use"), { |
|
6715 "xlink:href": "#" + pathId, |
|
6716 transform: (isEnd ? " rotate(180 " + w / 2 + " " + h / 2 + ") " : S) + "scale(" + w / t + "," + h / t + ")", |
|
6717 "stroke-width": 1 / ((w / t + h / t) / 2) |
|
6718 }); |
|
6719 marker.appendChild(use); |
|
6720 p.defs.appendChild(marker); |
|
6721 markerCounter[markerId] = 1; |
|
6722 } else { |
|
6723 markerCounter[markerId]++; |
|
6724 use = marker.getElementsByTagName("use")[0]; |
|
6725 } |
|
6726 $(use, attr); |
|
6727 var delta = dx * (type != "diamond" && type != "oval"); |
|
6728 if (isEnd) { |
|
6729 from = o._.arrows.startdx * stroke || 0; |
|
6730 to = R.getTotalLength(attrs.path) - delta * stroke; |
|
6731 } else { |
|
6732 from = delta * stroke; |
|
6733 to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0); |
|
6734 } |
|
6735 attr = {}; |
|
6736 attr["marker-" + se] = "url(#" + markerId + ")"; |
|
6737 if (to || from) { |
|
6738 attr.d = Raphael.getSubpath(attrs.path, from, to); |
|
6739 } |
|
6740 $(node, attr); |
|
6741 o._.arrows[se + "Path"] = pathId; |
|
6742 o._.arrows[se + "Marker"] = markerId; |
|
6743 o._.arrows[se + "dx"] = delta; |
|
6744 o._.arrows[se + "Type"] = type; |
|
6745 o._.arrows[se + "String"] = value; |
|
6746 } else { |
|
6747 if (isEnd) { |
|
6748 from = o._.arrows.startdx * stroke || 0; |
|
6749 to = R.getTotalLength(attrs.path) - from; |
|
6750 } else { |
|
6751 from = 0; |
|
6752 to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0); |
|
6753 } |
|
6754 o._.arrows[se + "Path"] && $(node, {d: Raphael.getSubpath(attrs.path, from, to)}); |
|
6755 delete o._.arrows[se + "Path"]; |
|
6756 delete o._.arrows[se + "Marker"]; |
|
6757 delete o._.arrows[se + "dx"]; |
|
6758 delete o._.arrows[se + "Type"]; |
|
6759 delete o._.arrows[se + "String"]; |
|
6760 } |
|
6761 for (attr in markerCounter) if (markerCounter[has](attr) && !markerCounter[attr]) { |
|
6762 var item = R._g.doc.getElementById(attr); |
|
6763 item && item.parentNode.removeChild(item); |
|
6764 } |
|
6765 } |
|
6766 }, |
|
6767 dasharray = { |
|
6768 "": [0], |
|
6769 "none": [0], |
|
6770 "-": [3, 1], |
|
6771 ".": [1, 1], |
|
6772 "-.": [3, 1, 1, 1], |
|
6773 "-..": [3, 1, 1, 1, 1, 1], |
|
6774 ". ": [1, 3], |
|
6775 "- ": [4, 3], |
|
6776 "--": [8, 3], |
|
6777 "- .": [4, 3, 1, 3], |
|
6778 "--.": [8, 3, 1, 3], |
|
6779 "--..": [8, 3, 1, 3, 1, 3] |
|
6780 }, |
|
6781 addDashes = function (o, value, params) { |
|
6782 value = dasharray[Str(value).toLowerCase()]; |
|
6783 if (value) { |
|
6784 var width = o.attrs["stroke-width"] || "1", |
|
6785 butt = {round: width, square: width, butt: 0}[o.attrs["stroke-linecap"] || params["stroke-linecap"]] || 0, |
|
6786 dashes = [], |
|
6787 i = value.length; |
|
6788 while (i--) { |
|
6789 dashes[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt; |
|
6790 } |
|
6791 $(o.node, {"stroke-dasharray": dashes.join(",")}); |
|
6792 } |
|
6793 }, |
|
6794 setFillAndStroke = function (o, params) { |
|
6795 var node = o.node, |
|
6796 attrs = o.attrs, |
|
6797 vis = node.style.visibility; |
|
6798 node.style.visibility = "hidden"; |
|
6799 for (var att in params) { |
|
6800 if (params[has](att)) { |
|
6801 if (!R._availableAttrs[has](att)) { |
|
6802 continue; |
|
6803 } |
|
6804 var value = params[att]; |
|
6805 attrs[att] = value; |
|
6806 switch (att) { |
|
6807 case "blur": |
|
6808 o.blur(value); |
|
6809 break; |
|
6810 case "href": |
|
6811 case "title": |
|
6812 case "target": |
|
6813 var pn = node.parentNode; |
|
6814 if (pn.tagName.toLowerCase() != "a") { |
|
6815 var hl = $("a"); |
|
6816 pn.insertBefore(hl, node); |
|
6817 hl.appendChild(node); |
|
6818 pn = hl; |
|
6819 } |
|
6820 if (att == "target" && value == "blank") { |
|
6821 pn.setAttributeNS(xlink, "show", "new"); |
|
6822 } else { |
|
6823 pn.setAttributeNS(xlink, att, value); |
|
6824 } |
|
6825 break; |
|
6826 case "cursor": |
|
6827 node.style.cursor = value; |
|
6828 break; |
|
6829 case "transform": |
|
6830 o.transform(value); |
|
6831 break; |
|
6832 case "arrow-start": |
|
6833 addArrow(o, value); |
|
6834 break; |
|
6835 case "arrow-end": |
|
6836 addArrow(o, value, 1); |
|
6837 break; |
|
6838 case "clip-rect": |
|
6839 var rect = Str(value).split(separator); |
|
6840 if (rect.length == 4) { |
|
6841 o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode); |
|
6842 var el = $("clipPath"), |
|
6843 rc = $("rect"); |
|
6844 el.id = R.createUUID(); |
|
6845 $(rc, { |
|
6846 x: rect[0], |
|
6847 y: rect[1], |
|
6848 width: rect[2], |
|
6849 height: rect[3] |
|
6850 }); |
|
6851 el.appendChild(rc); |
|
6852 o.paper.defs.appendChild(el); |
|
6853 $(node, {"clip-path": "url(#" + el.id + ")"}); |
|
6854 o.clip = rc; |
|
6855 } |
|
6856 if (!value) { |
|
6857 var clip = R._g.doc.getElementById(node.getAttribute("clip-path").replace(/(^url\(#|\)$)/g, E)); |
|
6858 clip && clip.parentNode.removeChild(clip); |
|
6859 $(node, {"clip-path": E}); |
|
6860 delete o.clip; |
|
6861 } |
|
6862 break; |
|
6863 case "path": |
|
6864 if (o.type == "path") { |
|
6865 $(node, {d: value ? attrs.path = R._pathToAbsolute(value) : "M0,0"}); |
|
6866 o._.dirty = 1; |
|
6867 if (o._.arrows) { |
|
6868 "startString" in o._.arrows && addArrow(o, o._.arrows.startString); |
|
6869 "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1); |
|
6870 } |
|
6871 } |
|
6872 break; |
|
6873 case "width": |
|
6874 node.setAttribute(att, value); |
|
6875 o._.dirty = 1; |
|
6876 if (attrs.fx) { |
|
6877 att = "x"; |
|
6878 value = attrs.x; |
|
6879 } else { |
|
6880 break; |
|
6881 } |
|
6882 case "x": |
|
6883 if (attrs.fx) { |
|
6884 value = -attrs.x - (attrs.width || 0); |
|
6885 } |
|
6886 case "rx": |
|
6887 if (att == "rx" && o.type == "rect") { |
|
6888 break; |
|
6889 } |
|
6890 case "cx": |
|
6891 node.setAttribute(att, value); |
|
6892 o.pattern && updatePosition(o); |
|
6893 o._.dirty = 1; |
|
6894 break; |
|
6895 case "height": |
|
6896 node.setAttribute(att, value); |
|
6897 o._.dirty = 1; |
|
6898 if (attrs.fy) { |
|
6899 att = "y"; |
|
6900 value = attrs.y; |
|
6901 } else { |
|
6902 break; |
|
6903 } |
|
6904 case "y": |
|
6905 if (attrs.fy) { |
|
6906 value = -attrs.y - (attrs.height || 0); |
|
6907 } |
|
6908 case "ry": |
|
6909 if (att == "ry" && o.type == "rect") { |
|
6910 break; |
|
6911 } |
|
6912 case "cy": |
|
6913 node.setAttribute(att, value); |
|
6914 o.pattern && updatePosition(o); |
|
6915 o._.dirty = 1; |
|
6916 break; |
|
6917 case "r": |
|
6918 if (o.type == "rect") { |
|
6919 $(node, {rx: value, ry: value}); |
|
6920 } else { |
|
6921 node.setAttribute(att, value); |
|
6922 } |
|
6923 o._.dirty = 1; |
|
6924 break; |
|
6925 case "src": |
|
6926 if (o.type == "image") { |
|
6927 node.setAttributeNS(xlink, "href", value); |
|
6928 } |
|
6929 break; |
|
6930 case "stroke-width": |
|
6931 if (o._.sx != 1 || o._.sy != 1) { |
|
6932 value /= mmax(abs(o._.sx), abs(o._.sy)) || 1; |
|
6933 } |
|
6934 if (o.paper._vbSize) { |
|
6935 value *= o.paper._vbSize; |
|
6936 } |
|
6937 node.setAttribute(att, value); |
|
6938 if (attrs["stroke-dasharray"]) { |
|
6939 addDashes(o, attrs["stroke-dasharray"], params); |
|
6940 } |
|
6941 if (o._.arrows) { |
|
6942 "startString" in o._.arrows && addArrow(o, o._.arrows.startString); |
|
6943 "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1); |
|
6944 } |
|
6945 break; |
|
6946 case "stroke-dasharray": |
|
6947 addDashes(o, value, params); |
|
6948 break; |
|
6949 case "fill": |
|
6950 var isURL = Str(value).match(R._ISURL); |
|
6951 if (isURL) { |
|
6952 el = $("pattern"); |
|
6953 var ig = $("image"); |
|
6954 el.id = R.createUUID(); |
|
6955 $(el, {x: 0, y: 0, patternUnits: "userSpaceOnUse", height: 1, width: 1}); |
|
6956 $(ig, {x: 0, y: 0, "xlink:href": isURL[1]}); |
|
6957 el.appendChild(ig); |
|
6958 |
|
6959 (function (el) { |
|
6960 R._preload(isURL[1], function () { |
|
6961 var w = this.offsetWidth, |
|
6962 h = this.offsetHeight; |
|
6963 $(el, {width: w, height: h}); |
|
6964 $(ig, {width: w, height: h}); |
|
6965 o.paper.safari(); |
|
6966 }); |
|
6967 })(el); |
|
6968 o.paper.defs.appendChild(el); |
|
6969 node.style.fill = "url(#" + el.id + ")"; |
|
6970 $(node, {fill: "url(#" + el.id + ")"}); |
|
6971 o.pattern = el; |
|
6972 o.pattern && updatePosition(o); |
|
6973 break; |
|
6974 } |
|
6975 var clr = R.getRGB(value); |
|
6976 if (!clr.error) { |
|
6977 delete params.gradient; |
|
6978 delete attrs.gradient; |
|
6979 !R.is(attrs.opacity, "undefined") && |
|
6980 R.is(params.opacity, "undefined") && |
|
6981 $(node, {opacity: attrs.opacity}); |
|
6982 !R.is(attrs["fill-opacity"], "undefined") && |
|
6983 R.is(params["fill-opacity"], "undefined") && |
|
6984 $(node, {"fill-opacity": attrs["fill-opacity"]}); |
|
6985 } else if ((o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value)) { |
|
6986 if ("opacity" in attrs || "fill-opacity" in attrs) { |
|
6987 var gradient = R._g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E)); |
|
6988 if (gradient) { |
|
6989 var stops = gradient.getElementsByTagName("stop"); |
|
6990 $(stops[stops.length - 1], {"stop-opacity": ("opacity" in attrs ? attrs.opacity : 1) * ("fill-opacity" in attrs ? attrs["fill-opacity"] : 1)}); |
|
6991 } |
|
6992 } |
|
6993 attrs.gradient = value; |
|
6994 attrs.fill = "none"; |
|
6995 break; |
|
6996 } |
|
6997 clr[has]("opacity") && $(node, {"fill-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity}); |
|
6998 case "stroke": |
|
6999 clr = R.getRGB(value); |
|
7000 node.setAttribute(att, clr.hex); |
|
7001 att == "stroke" && clr[has]("opacity") && $(node, {"stroke-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity}); |
|
7002 if (att == "stroke" && o._.arrows) { |
|
7003 "startString" in o._.arrows && addArrow(o, o._.arrows.startString); |
|
7004 "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1); |
|
7005 } |
|
7006 break; |
|
7007 case "gradient": |
|
7008 (o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value); |
|
7009 break; |
|
7010 case "opacity": |
|
7011 if (attrs.gradient && !attrs[has]("stroke-opacity")) { |
|
7012 $(node, {"stroke-opacity": value > 1 ? value / 100 : value}); |
|
7013 } |
|
7014 // fall |
|
7015 case "fill-opacity": |
|
7016 if (attrs.gradient) { |
|
7017 gradient = R._g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E)); |
|
7018 if (gradient) { |
|
7019 stops = gradient.getElementsByTagName("stop"); |
|
7020 $(stops[stops.length - 1], {"stop-opacity": value}); |
|
7021 } |
|
7022 break; |
|
7023 } |
|
7024 default: |
|
7025 att == "font-size" && (value = toInt(value, 10) + "px"); |
|
7026 var cssrule = att.replace(/(\-.)/g, function (w) { |
|
7027 return w.substring(1).toUpperCase(); |
|
7028 }); |
|
7029 node.style[cssrule] = value; |
|
7030 o._.dirty = 1; |
|
7031 node.setAttribute(att, value); |
|
7032 break; |
|
7033 } |
|
7034 } |
|
7035 } |
|
7036 |
|
7037 tuneText(o, params); |
|
7038 node.style.visibility = vis; |
|
7039 }, |
|
7040 leading = 1.2, |
|
7041 tuneText = function (el, params) { |
|
7042 if (el.type != "text" || !(params[has]("text") || params[has]("font") || params[has]("font-size") || params[has]("x") || params[has]("y"))) { |
|
7043 return; |
|
7044 } |
|
7045 var a = el.attrs, |
|
7046 node = el.node, |
|
7047 fontSize = node.firstChild ? toInt(R._g.doc.defaultView.getComputedStyle(node.firstChild, E).getPropertyValue("font-size"), 10) : 10; |
|
7048 |
|
7049 if (params[has]("text")) { |
|
7050 a.text = params.text; |
|
7051 while (node.firstChild) { |
|
7052 node.removeChild(node.firstChild); |
|
7053 } |
|
7054 var texts = Str(params.text).split("\n"), |
|
7055 tspans = [], |
|
7056 tspan; |
|
7057 for (var i = 0, ii = texts.length; i < ii; i++) { |
|
7058 tspan = $("tspan"); |
|
7059 i && $(tspan, {dy: fontSize * leading, x: a.x}); |
|
7060 tspan.appendChild(R._g.doc.createTextNode(texts[i])); |
|
7061 node.appendChild(tspan); |
|
7062 tspans[i] = tspan; |
|
7063 } |
|
7064 } else { |
|
7065 tspans = node.getElementsByTagName("tspan"); |
|
7066 for (i = 0, ii = tspans.length; i < ii; i++) if (i) { |
|
7067 $(tspans[i], {dy: fontSize * leading, x: a.x}); |
|
7068 } else { |
|
7069 $(tspans[0], {dy: 0}); |
|
7070 } |
|
7071 } |
|
7072 $(node, {x: a.x, y: a.y}); |
|
7073 el._.dirty = 1; |
|
7074 var bb = el._getBBox(), |
|
7075 dif = a.y - (bb.y + bb.height / 2); |
|
7076 dif && R.is(dif, "finite") && $(tspans[0], {dy: dif}); |
|
7077 }, |
|
7078 Element = function (node, svg) { |
|
7079 var X = 0, |
|
7080 Y = 0; |
|
7081 |
|
7082 this[0] = this.node = node; |
|
7083 |
|
7084 node.raphael = true; |
|
7085 |
|
7086 this.id = R._oid++; |
|
7087 node.raphaelid = this.id; |
|
7088 this.matrix = R.matrix(); |
|
7089 this.realPath = null; |
|
7090 |
|
7091 this.paper = svg; |
|
7092 this.attrs = this.attrs || {}; |
|
7093 this._ = { |
|
7094 transform: [], |
|
7095 sx: 1, |
|
7096 sy: 1, |
|
7097 deg: 0, |
|
7098 dx: 0, |
|
7099 dy: 0, |
|
7100 dirty: 1 |
|
7101 }; |
|
7102 !svg.bottom && (svg.bottom = this); |
|
7103 |
|
7104 this.prev = svg.top; |
|
7105 svg.top && (svg.top.next = this); |
|
7106 svg.top = this; |
|
7107 |
|
7108 this.next = null; |
|
7109 }, |
|
7110 elproto = R.el; |
|
7111 |
|
7112 Element.prototype = elproto; |
|
7113 elproto.constructor = Element; |
|
7114 |
|
7115 R._engine.path = function (pathString, SVG) { |
|
7116 var el = $("path"); |
|
7117 SVG.canvas && SVG.canvas.appendChild(el); |
|
7118 var p = new Element(el, SVG); |
|
7119 p.type = "path"; |
|
7120 setFillAndStroke(p, { |
|
7121 fill: "none", |
|
7122 stroke: "#000", |
|
7123 path: pathString |
|
7124 }); |
|
7125 return p; |
|
7126 }; |
|
7127 |
|
7128 elproto.rotate = function (deg, cx, cy) { |
|
7129 if (this.removed) { |
|
7130 return this; |
|
7131 } |
|
7132 deg = Str(deg).split(separator); |
|
7133 if (deg.length - 1) { |
|
7134 cx = toFloat(deg[1]); |
|
7135 cy = toFloat(deg[2]); |
|
7136 } |
|
7137 deg = toFloat(deg[0]); |
|
7138 (cy == null) && (cx = cy); |
|
7139 if (cx == null || cy == null) { |
|
7140 var bbox = this.getBBox(1); |
|
7141 cx = bbox.x + bbox.width / 2; |
|
7142 cy = bbox.y + bbox.height / 2; |
|
7143 } |
|
7144 this.transform(this._.transform.concat([["r", deg, cx, cy]])); |
|
7145 return this; |
|
7146 }; |
|
7147 |
|
7148 elproto.scale = function (sx, sy, cx, cy) { |
|
7149 if (this.removed) { |
|
7150 return this; |
|
7151 } |
|
7152 sx = Str(sx).split(separator); |
|
7153 if (sx.length - 1) { |
|
7154 sy = toFloat(sx[1]); |
|
7155 cx = toFloat(sx[2]); |
|
7156 cy = toFloat(sx[3]); |
|
7157 } |
|
7158 sx = toFloat(sx[0]); |
|
7159 (sy == null) && (sy = sx); |
|
7160 (cy == null) && (cx = cy); |
|
7161 if (cx == null || cy == null) { |
|
7162 var bbox = this.getBBox(1); |
|
7163 } |
|
7164 cx = cx == null ? bbox.x + bbox.width / 2 : cx; |
|
7165 cy = cy == null ? bbox.y + bbox.height / 2 : cy; |
|
7166 this.transform(this._.transform.concat([["s", sx, sy, cx, cy]])); |
|
7167 return this; |
|
7168 }; |
|
7169 |
|
7170 elproto.translate = function (dx, dy) { |
|
7171 if (this.removed) { |
|
7172 return this; |
|
7173 } |
|
7174 dx = Str(dx).split(separator); |
|
7175 if (dx.length - 1) { |
|
7176 dy = toFloat(dx[1]); |
|
7177 } |
|
7178 dx = toFloat(dx[0]) || 0; |
|
7179 dy = +dy || 0; |
|
7180 this.transform(this._.transform.concat([["t", dx, dy]])); |
|
7181 return this; |
|
7182 }; |
|
7183 |
|
7184 elproto.transform = function (tstr) { |
|
7185 var _ = this._; |
|
7186 if (tstr == null) { |
|
7187 return _.transform; |
|
7188 } |
|
7189 R._extractTransform(this, tstr); |
|
7190 |
|
7191 this.clip && $(this.clip, {transform: this.matrix.invert()}); |
|
7192 this.pattern && updatePosition(this); |
|
7193 this.node && $(this.node, {transform: this.matrix}); |
|
7194 |
|
7195 if (_.sx != 1 || _.sy != 1) { |
|
7196 var sw = this.attrs[has]("stroke-width") ? this.attrs["stroke-width"] : 1; |
|
7197 this.attr({"stroke-width": sw}); |
|
7198 } |
|
7199 |
|
7200 return this; |
|
7201 }; |
|
7202 |
|
7203 elproto.hide = function () { |
|
7204 !this.removed && this.paper.safari(this.node.style.display = "none"); |
|
7205 return this; |
|
7206 }; |
|
7207 |
|
7208 elproto.show = function () { |
|
7209 !this.removed && this.paper.safari(this.node.style.display = ""); |
|
7210 return this; |
|
7211 }; |
|
7212 |
|
7213 elproto.remove = function () { |
|
7214 if (this.removed) { |
|
7215 return; |
|
7216 } |
|
7217 this.paper.__set__ && this.paper.__set__.exclude(this); |
|
7218 eve.unbind("*.*." + this.id); |
|
7219 R._tear(this, this.paper); |
|
7220 this.node.parentNode.removeChild(this.node); |
|
7221 for (var i in this) { |
|
7222 delete this[i]; |
|
7223 } |
|
7224 this.removed = true; |
|
7225 }; |
|
7226 elproto._getBBox = function () { |
|
7227 if (this.node.style.display == "none") { |
|
7228 this.show(); |
|
7229 var hide = true; |
|
7230 } |
|
7231 var bbox = {}; |
|
7232 try { |
|
7233 bbox = this.node.getBBox(); |
|
7234 } catch(e) { |
|
7235 // Firefox 3.0.x plays badly here |
|
7236 } finally { |
|
7237 bbox = bbox || {}; |
|
7238 } |
|
7239 hide && this.hide(); |
|
7240 return bbox; |
|
7241 }; |
|
7242 |
|
7243 elproto.attr = function (name, value) { |
|
7244 if (this.removed) { |
|
7245 return this; |
|
7246 } |
|
7247 if (name == null) { |
|
7248 var res = {}; |
|
7249 for (var a in this.attrs) if (this.attrs[has](a)) { |
|
7250 res[a] = this.attrs[a]; |
|
7251 } |
|
7252 res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient; |
|
7253 res.transform = this._.transform; |
|
7254 return res; |
|
7255 } |
|
7256 if (value == null && R.is(name, "string")) { |
|
7257 if (name == "fill" && this.attrs.fill == "none" && this.attrs.gradient) { |
|
7258 return this.attrs.gradient; |
|
7259 } |
|
7260 if (name == "transform") { |
|
7261 return this._.transform; |
|
7262 } |
|
7263 var names = name.split(separator), |
|
7264 out = {}; |
|
7265 for (var i = 0, ii = names.length; i < ii; i++) { |
|
7266 name = names[i]; |
|
7267 if (name in this.attrs) { |
|
7268 out[name] = this.attrs[name]; |
|
7269 } else if (R.is(this.paper.customAttributes[name], "function")) { |
|
7270 out[name] = this.paper.customAttributes[name].def; |
|
7271 } else { |
|
7272 out[name] = R._availableAttrs[name]; |
|
7273 } |
|
7274 } |
|
7275 return ii - 1 ? out : out[names[0]]; |
|
7276 } |
|
7277 if (value == null && R.is(name, "array")) { |
|
7278 out = {}; |
|
7279 for (i = 0, ii = name.length; i < ii; i++) { |
|
7280 out[name[i]] = this.attr(name[i]); |
|
7281 } |
|
7282 return out; |
|
7283 } |
|
7284 if (value != null) { |
|
7285 var params = {}; |
|
7286 params[name] = value; |
|
7287 } else if (name != null && R.is(name, "object")) { |
|
7288 params = name; |
|
7289 } |
|
7290 for (var key in params) { |
|
7291 eve("attr." + key + "." + this.id, this, params[key]); |
|
7292 } |
|
7293 for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) { |
|
7294 var par = this.paper.customAttributes[key].apply(this, [].concat(params[key])); |
|
7295 this.attrs[key] = params[key]; |
|
7296 for (var subkey in par) if (par[has](subkey)) { |
|
7297 params[subkey] = par[subkey]; |
|
7298 } |
|
7299 } |
|
7300 setFillAndStroke(this, params); |
|
7301 return this; |
|
7302 }; |
|
7303 |
|
7304 elproto.toFront = function () { |
|
7305 if (this.removed) { |
|
7306 return this; |
|
7307 } |
|
7308 this.node.parentNode.appendChild(this.node); |
|
7309 var svg = this.paper; |
|
7310 svg.top != this && R._tofront(this, svg); |
|
7311 return this; |
|
7312 }; |
|
7313 |
|
7314 elproto.toBack = function () { |
|
7315 if (this.removed) { |
|
7316 return this; |
|
7317 } |
|
7318 if (this.node.parentNode.firstChild != this.node) { |
|
7319 this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild); |
|
7320 R._toback(this, this.paper); |
|
7321 var svg = this.paper; |
|
7322 } |
|
7323 return this; |
|
7324 }; |
|
7325 |
|
7326 elproto.insertAfter = function (element) { |
|
7327 if (this.removed) { |
|
7328 return this; |
|
7329 } |
|
7330 var node = element.node || element[element.length - 1].node; |
|
7331 if (node.nextSibling) { |
|
7332 node.parentNode.insertBefore(this.node, node.nextSibling); |
|
7333 } else { |
|
7334 node.parentNode.appendChild(this.node); |
|
7335 } |
|
7336 R._insertafter(this, element, this.paper); |
|
7337 return this; |
|
7338 }; |
|
7339 |
|
7340 elproto.insertBefore = function (element) { |
|
7341 if (this.removed) { |
|
7342 return this; |
|
7343 } |
|
7344 var node = element.node || element[0].node; |
|
7345 node.parentNode.insertBefore(this.node, node); |
|
7346 R._insertbefore(this, element, this.paper); |
|
7347 return this; |
|
7348 }; |
|
7349 elproto.blur = function (size) { |
|
7350 // Experimental. No Safari support. Use it on your own risk. |
|
7351 var t = this; |
|
7352 if (+size !== 0) { |
|
7353 var fltr = $("filter"), |
|
7354 blur = $("feGaussianBlur"); |
|
7355 t.attrs.blur = size; |
|
7356 fltr.id = R.createUUID(); |
|
7357 $(blur, {stdDeviation: +size || 1.5}); |
|
7358 fltr.appendChild(blur); |
|
7359 t.paper.defs.appendChild(fltr); |
|
7360 t._blur = fltr; |
|
7361 $(t.node, {filter: "url(#" + fltr.id + ")"}); |
|
7362 } else { |
|
7363 if (t._blur) { |
|
7364 t._blur.parentNode.removeChild(t._blur); |
|
7365 delete t._blur; |
|
7366 delete t.attrs.blur; |
|
7367 } |
|
7368 t.node.removeAttribute("filter"); |
|
7369 } |
|
7370 }; |
|
7371 R._engine.circle = function (svg, x, y, r) { |
|
7372 var el = $("circle"); |
|
7373 svg.canvas && svg.canvas.appendChild(el); |
|
7374 var res = new Element(el, svg); |
|
7375 res.attrs = {cx: x, cy: y, r: r, fill: "none", stroke: "#000"}; |
|
7376 res.type = "circle"; |
|
7377 $(el, res.attrs); |
|
7378 return res; |
|
7379 }; |
|
7380 R._engine.rect = function (svg, x, y, w, h, r) { |
|
7381 var el = $("rect"); |
|
7382 svg.canvas && svg.canvas.appendChild(el); |
|
7383 var res = new Element(el, svg); |
|
7384 res.attrs = {x: x, y: y, width: w, height: h, r: r || 0, rx: r || 0, ry: r || 0, fill: "none", stroke: "#000"}; |
|
7385 res.type = "rect"; |
|
7386 $(el, res.attrs); |
|
7387 return res; |
|
7388 }; |
|
7389 R._engine.ellipse = function (svg, x, y, rx, ry) { |
|
7390 var el = $("ellipse"); |
|
7391 svg.canvas && svg.canvas.appendChild(el); |
|
7392 var res = new Element(el, svg); |
|
7393 res.attrs = {cx: x, cy: y, rx: rx, ry: ry, fill: "none", stroke: "#000"}; |
|
7394 res.type = "ellipse"; |
|
7395 $(el, res.attrs); |
|
7396 return res; |
|
7397 }; |
|
7398 R._engine.image = function (svg, src, x, y, w, h) { |
|
7399 var el = $("image"); |
|
7400 $(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: "none"}); |
|
7401 el.setAttributeNS(xlink, "href", src); |
|
7402 svg.canvas && svg.canvas.appendChild(el); |
|
7403 var res = new Element(el, svg); |
|
7404 res.attrs = {x: x, y: y, width: w, height: h, src: src}; |
|
7405 res.type = "image"; |
|
7406 return res; |
|
7407 }; |
|
7408 R._engine.text = function (svg, x, y, text) { |
|
7409 var el = $("text"); |
|
7410 // $(el, {x: x, y: y, "text-anchor": "middle"}); |
|
7411 svg.canvas && svg.canvas.appendChild(el); |
|
7412 var res = new Element(el, svg); |
|
7413 res.attrs = { |
|
7414 x: x, |
|
7415 y: y, |
|
7416 "text-anchor": "middle", |
|
7417 text: text, |
|
7418 font: R._availableAttrs.font, |
|
7419 stroke: "none", |
|
7420 fill: "#000" |
|
7421 }; |
|
7422 res.type = "text"; |
|
7423 setFillAndStroke(res, res.attrs); |
|
7424 return res; |
|
7425 }; |
|
7426 R._engine.setSize = function (width, height) { |
|
7427 this.width = width || this.width; |
|
7428 this.height = height || this.height; |
|
7429 this.canvas.setAttribute("width", this.width); |
|
7430 this.canvas.setAttribute("height", this.height); |
|
7431 if (this._viewBox) { |
|
7432 this.setViewBox.apply(this, this._viewBox); |
|
7433 } |
|
7434 return this; |
|
7435 }; |
|
7436 R._engine.create = function () { |
|
7437 var con = R._getContainer.apply(0, arguments), |
|
7438 container = con && con.container, |
|
7439 x = con.x, |
|
7440 y = con.y, |
|
7441 width = con.width, |
|
7442 height = con.height; |
|
7443 if (!container) { |
|
7444 throw new Error("SVG container not found."); |
|
7445 } |
|
7446 var cnvs = $("svg"), |
|
7447 css = "overflow:hidden;", |
|
7448 isFloating; |
|
7449 x = x || 0; |
|
7450 y = y || 0; |
|
7451 width = width || 512; |
|
7452 height = height || 342; |
|
7453 $(cnvs, { |
|
7454 height: height, |
|
7455 version: 1.1, |
|
7456 width: width, |
|
7457 xmlns: "http://www.w3.org/2000/svg" |
|
7458 }); |
|
7459 if (container == 1) { |
|
7460 cnvs.style.cssText = css + "position:absolute;left:" + x + "px;top:" + y + "px"; |
|
7461 R._g.doc.body.appendChild(cnvs); |
|
7462 isFloating = 1; |
|
7463 } else { |
|
7464 cnvs.style.cssText = css + "position:relative"; |
|
7465 if (container.firstChild) { |
|
7466 container.insertBefore(cnvs, container.firstChild); |
|
7467 } else { |
|
7468 container.appendChild(cnvs); |
|
7469 } |
|
7470 } |
|
7471 container = new R._Paper; |
|
7472 container.width = width; |
|
7473 container.height = height; |
|
7474 container.canvas = cnvs; |
|
7475 // plugins.call(container, container, R.fn); |
|
7476 container.clear(); |
|
7477 container._left = container._top = 0; |
|
7478 isFloating && (container.renderfix = function () {}); |
|
7479 container.renderfix(); |
|
7480 return container; |
|
7481 }; |
|
7482 R._engine.setViewBox = function (x, y, w, h, fit) { |
|
7483 eve("setViewBox", this, this._viewBox, [x, y, w, h, fit]); |
|
7484 var size = mmax(w / this.width, h / this.height), |
|
7485 top = this.top, |
|
7486 aspectRatio = fit ? "meet" : "xMinYMin", |
|
7487 vb, |
|
7488 sw; |
|
7489 if (x == null) { |
|
7490 if (this._vbSize) { |
|
7491 size = 1; |
|
7492 } |
|
7493 delete this._vbSize; |
|
7494 vb = "0 0 " + this.width + S + this.height; |
|
7495 } else { |
|
7496 this._vbSize = size; |
|
7497 vb = x + S + y + S + w + S + h; |
|
7498 } |
|
7499 $(this.canvas, { |
|
7500 viewBox: vb, |
|
7501 preserveAspectRatio: aspectRatio |
|
7502 }); |
|
7503 while (size && top) { |
|
7504 sw = "stroke-width" in top.attrs ? top.attrs["stroke-width"] : 1; |
|
7505 top.attr({"stroke-width": sw}); |
|
7506 top._.dirty = 1; |
|
7507 top._.dirtyT = 1; |
|
7508 top = top.prev; |
|
7509 } |
|
7510 this._viewBox = [x, y, w, h, !!fit]; |
|
7511 return this; |
|
7512 }; |
|
7513 |
|
7514 R.prototype.renderfix = function () { |
|
7515 var cnvs = this.canvas, |
|
7516 s = cnvs.style, |
|
7517 pos = cnvs.getScreenCTM() || cnvs.createSVGMatrix(), |
|
7518 left = -pos.e % 1, |
|
7519 top = -pos.f % 1; |
|
7520 if (left || top) { |
|
7521 if (left) { |
|
7522 this._left = (this._left + left) % 1; |
|
7523 s.left = this._left + "px"; |
|
7524 } |
|
7525 if (top) { |
|
7526 this._top = (this._top + top) % 1; |
|
7527 s.top = this._top + "px"; |
|
7528 } |
|
7529 } |
|
7530 }; |
|
7531 |
|
7532 R.prototype.clear = function () { |
|
7533 R.eve("clear", this); |
|
7534 var c = this.canvas; |
|
7535 while (c.firstChild) { |
|
7536 c.removeChild(c.firstChild); |
|
7537 } |
|
7538 this.bottom = this.top = null; |
|
7539 (this.desc = $("desc")).appendChild(R._g.doc.createTextNode("Created with Rapha\xebl " + R.version)); |
|
7540 c.appendChild(this.desc); |
|
7541 c.appendChild(this.defs = $("defs")); |
|
7542 }; |
|
7543 |
|
7544 R.prototype.remove = function () { |
|
7545 eve("remove", this); |
|
7546 this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas); |
|
7547 for (var i in this) { |
|
7548 this[i] = removed(i); |
|
7549 } |
|
7550 }; |
|
7551 var setproto = R.st; |
|
7552 for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) { |
|
7553 setproto[method] = (function (methodname) { |
|
7554 return function () { |
|
7555 var arg = arguments; |
|
7556 return this.forEach(function (el) { |
|
7557 el[methodname].apply(el, arg); |
|
7558 }); |
|
7559 }; |
|
7560 })(method); |
|
7561 } |
|
7562 }(window.Raphael); |
|
7563 |
|
7564 // ┌─────────────────────────────────────────────────────────────────────┐ \\ |
|
7565 // │ Raphaël 2 - JavaScript Vector Library │ \\ |
|
7566 // ├─────────────────────────────────────────────────────────────────────┤ \\ |
|
7567 // │ VML Module │ \\ |
|
7568 // ├─────────────────────────────────────────────────────────────────────┤ \\ |
|
7569 // │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\ |
|
7570 // │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\ |
|
7571 // │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\ |
|
7572 // └─────────────────────────────────────────────────────────────────────┘ \\ |
|
7573 window.Raphael.vml && function (R) { |
|
7574 var has = "hasOwnProperty", |
|
7575 Str = String, |
|
7576 toFloat = parseFloat, |
|
7577 math = Math, |
|
7578 round = math.round, |
|
7579 mmax = math.max, |
|
7580 mmin = math.min, |
|
7581 abs = math.abs, |
|
7582 fillString = "fill", |
|
7583 separator = /[, ]+/, |
|
7584 eve = R.eve, |
|
7585 ms = " progid:DXImageTransform.Microsoft", |
|
7586 S = " ", |
|
7587 E = "", |
|
7588 map = {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"}, |
|
7589 bites = /([clmz]),?([^clmz]*)/gi, |
|
7590 blurregexp = / progid:\S+Blur\([^\)]+\)/g, |
|
7591 val = /-?[^,\s-]+/g, |
|
7592 cssDot = "position:absolute;left:0;top:0;width:1px;height:1px", |
|
7593 zoom = 21600, |
|
7594 pathTypes = {path: 1, rect: 1, image: 1}, |
|
7595 ovalTypes = {circle: 1, ellipse: 1}, |
|
7596 path2vml = function (path) { |
|
7597 var total = /[ahqstv]/ig, |
|
7598 command = R._pathToAbsolute; |
|
7599 Str(path).match(total) && (command = R._path2curve); |
|
7600 total = /[clmz]/g; |
|
7601 if (command == R._pathToAbsolute && !Str(path).match(total)) { |
|
7602 var res = Str(path).replace(bites, function (all, command, args) { |
|
7603 var vals = [], |
|
7604 isMove = command.toLowerCase() == "m", |
|
7605 res = map[command]; |
|
7606 args.replace(val, function (value) { |
|
7607 if (isMove && vals.length == 2) { |
|
7608 res += vals + map[command == "m" ? "l" : "L"]; |
|
7609 vals = []; |
|
7610 } |
|
7611 vals.push(round(value * zoom)); |
|
7612 }); |
|
7613 return res + vals; |
|
7614 }); |
|
7615 return res; |
|
7616 } |
|
7617 var pa = command(path), p, r; |
|
7618 res = []; |
|
7619 for (var i = 0, ii = pa.length; i < ii; i++) { |
|
7620 p = pa[i]; |
|
7621 r = pa[i][0].toLowerCase(); |
|
7622 r == "z" && (r = "x"); |
|
7623 for (var j = 1, jj = p.length; j < jj; j++) { |
|
7624 r += round(p[j] * zoom) + (j != jj - 1 ? "," : E); |
|
7625 } |
|
7626 res.push(r); |
|
7627 } |
|
7628 return res.join(S); |
|
7629 }, |
|
7630 compensation = function (deg, dx, dy) { |
|
7631 var m = R.matrix(); |
|
7632 m.rotate(-deg, .5, .5); |
|
7633 return { |
|
7634 dx: m.x(dx, dy), |
|
7635 dy: m.y(dx, dy) |
|
7636 }; |
|
7637 }, |
|
7638 setCoords = function (p, sx, sy, dx, dy, deg) { |
|
7639 var _ = p._, |
|
7640 m = p.matrix, |
|
7641 fillpos = _.fillpos, |
|
7642 o = p.node, |
|
7643 s = o.style, |
|
7644 y = 1, |
|
7645 flip = "", |
|
7646 dxdy, |
|
7647 kx = zoom / sx, |
|
7648 ky = zoom / sy; |
|
7649 s.visibility = "hidden"; |
|
7650 if (!sx || !sy) { |
|
7651 return; |
|
7652 } |
|
7653 o.coordsize = abs(kx) + S + abs(ky); |
|
7654 s.rotation = deg * (sx * sy < 0 ? -1 : 1); |
|
7655 if (deg) { |
|
7656 var c = compensation(deg, dx, dy); |
|
7657 dx = c.dx; |
|
7658 dy = c.dy; |
|
7659 } |
|
7660 sx < 0 && (flip += "x"); |
|
7661 sy < 0 && (flip += " y") && (y = -1); |
|
7662 s.flip = flip; |
|
7663 o.coordorigin = (dx * -kx) + S + (dy * -ky); |
|
7664 if (fillpos || _.fillsize) { |
|
7665 var fill = o.getElementsByTagName(fillString); |
|
7666 fill = fill && fill[0]; |
|
7667 o.removeChild(fill); |
|
7668 if (fillpos) { |
|
7669 c = compensation(deg, m.x(fillpos[0], fillpos[1]), m.y(fillpos[0], fillpos[1])); |
|
7670 fill.position = c.dx * y + S + c.dy * y; |
|
7671 } |
|
7672 if (_.fillsize) { |
|
7673 fill.size = _.fillsize[0] * abs(sx) + S + _.fillsize[1] * abs(sy); |
|
7674 } |
|
7675 o.appendChild(fill); |
|
7676 } |
|
7677 s.visibility = "visible"; |
|
7678 }; |
|
7679 R.toString = function () { |
|
7680 return "Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl " + this.version; |
|
7681 }; |
|
7682 addArrow = function (o, value, isEnd) { |
|
7683 var values = Str(value).toLowerCase().split("-"), |
|
7684 se = isEnd ? "end" : "start", |
|
7685 i = values.length, |
|
7686 type = "classic", |
|
7687 w = "medium", |
|
7688 h = "medium"; |
|
7689 while (i--) { |
|
7690 switch (values[i]) { |
|
7691 case "block": |
|
7692 case "classic": |
|
7693 case "oval": |
|
7694 case "diamond": |
|
7695 case "open": |
|
7696 case "none": |
|
7697 type = values[i]; |
|
7698 break; |
|
7699 case "wide": |
|
7700 case "narrow": h = values[i]; break; |
|
7701 case "long": |
|
7702 case "short": w = values[i]; break; |
|
7703 } |
|
7704 } |
|
7705 var stroke = o.node.getElementsByTagName("stroke")[0]; |
|
7706 stroke[se + "arrow"] = type; |
|
7707 stroke[se + "arrowlength"] = w; |
|
7708 stroke[se + "arrowwidth"] = h; |
|
7709 }; |
|
7710 setFillAndStroke = function (o, params) { |
|
7711 // o.paper.canvas.style.display = "none"; |
|
7712 o.attrs = o.attrs || {}; |
|
7713 var node = o.node, |
|
7714 a = o.attrs, |
|
7715 s = node.style, |
|
7716 xy, |
|
7717 newpath = pathTypes[o.type] && (params.x != a.x || params.y != a.y || params.width != a.width || params.height != a.height || params.cx != a.cx || params.cy != a.cy || params.rx != a.rx || params.ry != a.ry || params.r != a.r), |
|
7718 isOval = ovalTypes[o.type] && (a.cx != params.cx || a.cy != params.cy || a.r != params.r || a.rx != params.rx || a.ry != params.ry), |
|
7719 res = o; |
|
7720 |
|
7721 |
|
7722 for (var par in params) if (params[has](par)) { |
|
7723 a[par] = params[par]; |
|
7724 } |
|
7725 if (newpath) { |
|
7726 a.path = R._getPath[o.type](o); |
|
7727 o._.dirty = 1; |
|
7728 } |
|
7729 params.href && (node.href = params.href); |
|
7730 params.title && (node.title = params.title); |
|
7731 params.target && (node.target = params.target); |
|
7732 params.cursor && (s.cursor = params.cursor); |
|
7733 "blur" in params && o.blur(params.blur); |
|
7734 if (params.path && o.type == "path" || newpath) { |
|
7735 node.path = path2vml(~Str(a.path).toLowerCase().indexOf("r") ? R._pathToAbsolute(a.path) : a.path); |
|
7736 if (o.type == "image") { |
|
7737 o._.fillpos = [a.x, a.y]; |
|
7738 o._.fillsize = [a.width, a.height]; |
|
7739 setCoords(o, 1, 1, 0, 0, 0); |
|
7740 } |
|
7741 } |
|
7742 "transform" in params && o.transform(params.transform); |
|
7743 if (isOval) { |
|
7744 var cx = +a.cx, |
|
7745 cy = +a.cy, |
|
7746 rx = +a.rx || +a.r || 0, |
|
7747 ry = +a.ry || +a.r || 0; |
|
7748 node.path = R.format("ar{0},{1},{2},{3},{4},{1},{4},{1}x", round((cx - rx) * zoom), round((cy - ry) * zoom), round((cx + rx) * zoom), round((cy + ry) * zoom), round(cx * zoom)); |
|
7749 } |
|
7750 if ("clip-rect" in params) { |
|
7751 var rect = Str(params["clip-rect"]).split(separator); |
|
7752 if (rect.length == 4) { |
|
7753 rect[2] = +rect[2] + (+rect[0]); |
|
7754 rect[3] = +rect[3] + (+rect[1]); |
|
7755 var div = node.clipRect || R._g.doc.createElement("div"), |
|
7756 dstyle = div.style; |
|
7757 dstyle.clip = R.format("rect({1}px {2}px {3}px {0}px)", rect); |
|
7758 if (!node.clipRect) { |
|
7759 dstyle.position = "absolute"; |
|
7760 dstyle.top = 0; |
|
7761 dstyle.left = 0; |
|
7762 dstyle.width = o.paper.width + "px"; |
|
7763 dstyle.height = o.paper.height + "px"; |
|
7764 node.parentNode.insertBefore(div, node); |
|
7765 div.appendChild(node); |
|
7766 node.clipRect = div; |
|
7767 } |
|
7768 } |
|
7769 if (!params["clip-rect"]) { |
|
7770 node.clipRect && (node.clipRect.style.clip = E); |
|
7771 } |
|
7772 } |
|
7773 if (o.textpath) { |
|
7774 var textpathStyle = o.textpath.style; |
|
7775 params.font && (textpathStyle.font = params.font); |
|
7776 params["font-family"] && (textpathStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g, E) + '"'); |
|
7777 params["font-size"] && (textpathStyle.fontSize = params["font-size"]); |
|
7778 params["font-weight"] && (textpathStyle.fontWeight = params["font-weight"]); |
|
7779 params["font-style"] && (textpathStyle.fontStyle = params["font-style"]); |
|
7780 } |
|
7781 if ("arrow-start" in params) { |
|
7782 addArrow(res, params["arrow-start"]); |
|
7783 } |
|
7784 if ("arrow-end" in params) { |
|
7785 addArrow(res, params["arrow-end"], 1); |
|
7786 } |
|
7787 if (params.opacity != null || |
|
7788 params["stroke-width"] != null || |
|
7789 params.fill != null || |
|
7790 params.src != null || |
|
7791 params.stroke != null || |
|
7792 params["stroke-width"] != null || |
|
7793 params["stroke-opacity"] != null || |
|
7794 params["fill-opacity"] != null || |
|
7795 params["stroke-dasharray"] != null || |
|
7796 params["stroke-miterlimit"] != null || |
|
7797 params["stroke-linejoin"] != null || |
|
7798 params["stroke-linecap"] != null) { |
|
7799 var fill = node.getElementsByTagName(fillString), |
|
7800 newfill = false; |
|
7801 fill = fill && fill[0]; |
|
7802 !fill && (newfill = fill = createNode(fillString)); |
|
7803 if (o.type == "image" && params.src) { |
|
7804 fill.src = params.src; |
|
7805 } |
|
7806 params.fill && (fill.on = true); |
|
7807 if (fill.on == null || params.fill == "none" || params.fill === null) { |
|
7808 fill.on = false; |
|
7809 } |
|
7810 if (fill.on && params.fill) { |
|
7811 var isURL = Str(params.fill).match(R._ISURL); |
|
7812 if (isURL) { |
|
7813 fill.parentNode == node && node.removeChild(fill); |
|
7814 fill.rotate = true; |
|
7815 fill.src = isURL[1]; |
|
7816 fill.type = "tile"; |
|
7817 var bbox = o.getBBox(1); |
|
7818 fill.position = bbox.x + S + bbox.y; |
|
7819 o._.fillpos = [bbox.x, bbox.y]; |
|
7820 |
|
7821 R._preload(isURL[1], function () { |
|
7822 o._.fillsize = [this.offsetWidth, this.offsetHeight]; |
|
7823 }); |
|
7824 } else { |
|
7825 fill.color = R.getRGB(params.fill).hex; |
|
7826 fill.src = E; |
|
7827 fill.type = "solid"; |
|
7828 if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != "r") && addGradientFill(res, params.fill, fill)) { |
|
7829 a.fill = "none"; |
|
7830 a.gradient = params.fill; |
|
7831 fill.rotate = false; |
|
7832 } |
|
7833 } |
|
7834 } |
|
7835 if ("fill-opacity" in params || "opacity" in params) { |
|
7836 var opacity = ((+a["fill-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1); |
|
7837 opacity = mmin(mmax(opacity, 0), 1); |
|
7838 fill.opacity = opacity; |
|
7839 if (fill.src) { |
|
7840 fill.color = "none"; |
|
7841 } |
|
7842 } |
|
7843 node.appendChild(fill); |
|
7844 var stroke = (node.getElementsByTagName("stroke") && node.getElementsByTagName("stroke")[0]), |
|
7845 newstroke = false; |
|
7846 !stroke && (newstroke = stroke = createNode("stroke")); |
|
7847 if ((params.stroke && params.stroke != "none") || |
|
7848 params["stroke-width"] || |
|
7849 params["stroke-opacity"] != null || |
|
7850 params["stroke-dasharray"] || |
|
7851 params["stroke-miterlimit"] || |
|
7852 params["stroke-linejoin"] || |
|
7853 params["stroke-linecap"]) { |
|
7854 stroke.on = true; |
|
7855 } |
|
7856 (params.stroke == "none" || params.stroke === null || stroke.on == null || params.stroke == 0 || params["stroke-width"] == 0) && (stroke.on = false); |
|
7857 var strokeColor = R.getRGB(params.stroke); |
|
7858 stroke.on && params.stroke && (stroke.color = strokeColor.hex); |
|
7859 opacity = ((+a["stroke-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1); |
|
7860 var width = (toFloat(params["stroke-width"]) || 1) * .75; |
|
7861 opacity = mmin(mmax(opacity, 0), 1); |
|
7862 params["stroke-width"] == null && (width = a["stroke-width"]); |
|
7863 params["stroke-width"] && (stroke.weight = width); |
|
7864 width && width < 1 && (opacity *= width) && (stroke.weight = 1); |
|
7865 stroke.opacity = opacity; |
|
7866 |
|
7867 params["stroke-linejoin"] && (stroke.joinstyle = params["stroke-linejoin"] || "miter"); |
|
7868 stroke.miterlimit = params["stroke-miterlimit"] || 8; |
|
7869 params["stroke-linecap"] && (stroke.endcap = params["stroke-linecap"] == "butt" ? "flat" : params["stroke-linecap"] == "square" ? "square" : "round"); |
|
7870 if (params["stroke-dasharray"]) { |
|
7871 var dasharray = { |
|
7872 "-": "shortdash", |
|
7873 ".": "shortdot", |
|
7874 "-.": "shortdashdot", |
|
7875 "-..": "shortdashdotdot", |
|
7876 ". ": "dot", |
|
7877 "- ": "dash", |
|
7878 "--": "longdash", |
|
7879 "- .": "dashdot", |
|
7880 "--.": "longdashdot", |
|
7881 "--..": "longdashdotdot" |
|
7882 }; |
|
7883 stroke.dashstyle = dasharray[has](params["stroke-dasharray"]) ? dasharray[params["stroke-dasharray"]] : E; |
|
7884 } |
|
7885 newstroke && node.appendChild(stroke); |
|
7886 } |
|
7887 if (res.type == "text") { |
|
7888 res.paper.canvas.style.display = E; |
|
7889 var span = res.paper.span, |
|
7890 m = 100, |
|
7891 fontSize = a.font && a.font.match(/\d+(?:\.\d*)?(?=px)/); |
|
7892 s = span.style; |
|
7893 a.font && (s.font = a.font); |
|
7894 a["font-family"] && (s.fontFamily = a["font-family"]); |
|
7895 a["font-weight"] && (s.fontWeight = a["font-weight"]); |
|
7896 a["font-style"] && (s.fontStyle = a["font-style"]); |
|
7897 fontSize = toFloat(fontSize ? fontSize[0] : a["font-size"]); |
|
7898 s.fontSize = fontSize * m + "px"; |
|
7899 res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/</g, "<").replace(/&/g, "&").replace(/\n/g, "<br>")); |
|
7900 var brect = span.getBoundingClientRect(); |
|
7901 res.W = a.w = (brect.right - brect.left) / m; |
|
7902 res.H = a.h = (brect.bottom - brect.top) / m; |
|
7903 // res.paper.canvas.style.display = "none"; |
|
7904 res.X = a.x; |
|
7905 res.Y = a.y + res.H / 2; |
|
7906 |
|
7907 ("x" in params || "y" in params) && (res.path.v = R.format("m{0},{1}l{2},{1}", round(a.x * zoom), round(a.y * zoom), round(a.x * zoom) + 1)); |
|
7908 var dirtyattrs = ["x", "y", "text", "font", "font-family", "font-weight", "font-style", "font-size"]; |
|
7909 for (var d = 0, dd = dirtyattrs.length; d < dd; d++) if (dirtyattrs[d] in params) { |
|
7910 res._.dirty = 1; |
|
7911 break; |
|
7912 } |
|
7913 |
|
7914 // text-anchor emulation |
|
7915 switch (a["text-anchor"]) { |
|
7916 case "start": |
|
7917 res.textpath.style["v-text-align"] = "left"; |
|
7918 res.bbx = res.W / 2; |
|
7919 break; |
|
7920 case "end": |
|
7921 res.textpath.style["v-text-align"] = "right"; |
|
7922 res.bbx = -res.W / 2; |
|
7923 break; |
|
7924 default: |
|
7925 res.textpath.style["v-text-align"] = "center"; |
|
7926 res.bbx = 0; |
|
7927 break; |
|
7928 } |
|
7929 res.textpath.style["v-text-kern"] = true; |
|
7930 } |
|
7931 // res.paper.canvas.style.display = E; |
|
7932 }; |
|
7933 addGradientFill = function (o, gradient, fill) { |
|
7934 o.attrs = o.attrs || {}; |
|
7935 var attrs = o.attrs, |
|
7936 pow = Math.pow, |
|
7937 opacity, |
|
7938 oindex, |
|
7939 type = "linear", |
|
7940 fxfy = ".5 .5"; |
|
7941 o.attrs.gradient = gradient; |
|
7942 gradient = Str(gradient).replace(R._radial_gradient, function (all, fx, fy) { |
|
7943 type = "radial"; |
|
7944 if (fx && fy) { |
|
7945 fx = toFloat(fx); |
|
7946 fy = toFloat(fy); |
|
7947 pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5); |
|
7948 fxfy = fx + S + fy; |
|
7949 } |
|
7950 return E; |
|
7951 }); |
|
7952 gradient = gradient.split(/\s*\-\s*/); |
|
7953 if (type == "linear") { |
|
7954 var angle = gradient.shift(); |
|
7955 angle = -toFloat(angle); |
|
7956 if (isNaN(angle)) { |
|
7957 return null; |
|
7958 } |
|
7959 } |
|
7960 var dots = R._parseDots(gradient); |
|
7961 if (!dots) { |
|
7962 return null; |
|
7963 } |
|
7964 o = o.shape || o.node; |
|
7965 if (dots.length) { |
|
7966 o.removeChild(fill); |
|
7967 fill.on = true; |
|
7968 fill.method = "none"; |
|
7969 fill.color = dots[0].color; |
|
7970 fill.color2 = dots[dots.length - 1].color; |
|
7971 var clrs = []; |
|
7972 for (var i = 0, ii = dots.length; i < ii; i++) { |
|
7973 dots[i].offset && clrs.push(dots[i].offset + S + dots[i].color); |
|
7974 } |
|
7975 fill.colors = clrs.length ? clrs.join() : "0% " + fill.color; |
|
7976 if (type == "radial") { |
|
7977 fill.type = "gradientTitle"; |
|
7978 fill.focus = "100%"; |
|
7979 fill.focussize = "0 0"; |
|
7980 fill.focusposition = fxfy; |
|
7981 fill.angle = 0; |
|
7982 } else { |
|
7983 // fill.rotate= true; |
|
7984 fill.type = "gradient"; |
|
7985 fill.angle = (270 - angle) % 360; |
|
7986 } |
|
7987 o.appendChild(fill); |
|
7988 } |
|
7989 return 1; |
|
7990 }; |
|
7991 Element = function (node, vml) { |
|
7992 this[0] = this.node = node; |
|
7993 node.raphael = true; |
|
7994 this.id = R._oid++; |
|
7995 node.raphaelid = this.id; |
|
7996 this.X = 0; |
|
7997 this.Y = 0; |
|
7998 this.attrs = {}; |
|
7999 this.paper = vml; |
|
8000 this.matrix = R.matrix(); |
|
8001 this._ = { |
|
8002 transform: [], |
|
8003 sx: 1, |
|
8004 sy: 1, |
|
8005 dx: 0, |
|
8006 dy: 0, |
|
8007 deg: 0, |
|
8008 dirty: 1, |
|
8009 dirtyT: 1 |
|
8010 }; |
|
8011 !vml.bottom && (vml.bottom = this); |
|
8012 this.prev = vml.top; |
|
8013 vml.top && (vml.top.next = this); |
|
8014 vml.top = this; |
|
8015 this.next = null; |
|
8016 }; |
|
8017 var elproto = R.el; |
|
8018 |
|
8019 Element.prototype = elproto; |
|
8020 elproto.constructor = Element; |
|
8021 elproto.transform = function (tstr) { |
|
8022 if (tstr == null) { |
|
8023 return this._.transform; |
|
8024 } |
|
8025 var vbs = this.paper._viewBoxShift, |
|
8026 vbt = vbs ? "s" + [vbs.scale, vbs.scale] + "-1-1t" + [vbs.dx, vbs.dy] : E, |
|
8027 oldt; |
|
8028 if (vbs) { |
|
8029 oldt = tstr = Str(tstr).replace(/\.{3}|\u2026/g, this._.transform || E); |
|
8030 } |
|
8031 R._extractTransform(this, vbt + tstr); |
|
8032 var matrix = this.matrix.clone(), |
|
8033 skew = this.skew, |
|
8034 o = this.node, |
|
8035 split, |
|
8036 isGrad = ~Str(this.attrs.fill).indexOf("-"), |
|
8037 isPatt = !Str(this.attrs.fill).indexOf("url("); |
|
8038 matrix.translate(-.5, -.5); |
|
8039 if (isPatt || isGrad || this.type == "image") { |
|
8040 skew.matrix = "1 0 0 1"; |
|
8041 skew.offset = "0 0"; |
|
8042 split = matrix.split(); |
|
8043 if ((isGrad && split.noRotation) || !split.isSimple) { |
|
8044 o.style.filter = matrix.toFilter(); |
|
8045 var bb = this.getBBox(), |
|
8046 bbt = this.getBBox(1), |
|
8047 dx = bb.x - bbt.x, |
|
8048 dy = bb.y - bbt.y; |
|
8049 o.coordorigin = (dx * -zoom) + S + (dy * -zoom); |
|
8050 setCoords(this, 1, 1, dx, dy, 0); |
|
8051 } else { |
|
8052 o.style.filter = E; |
|
8053 setCoords(this, split.scalex, split.scaley, split.dx, split.dy, split.rotate); |
|
8054 } |
|
8055 } else { |
|
8056 o.style.filter = E; |
|
8057 skew.matrix = Str(matrix); |
|
8058 skew.offset = matrix.offset(); |
|
8059 } |
|
8060 oldt && (this._.transform = oldt); |
|
8061 return this; |
|
8062 }; |
|
8063 elproto.rotate = function (deg, cx, cy) { |
|
8064 if (this.removed) { |
|
8065 return this; |
|
8066 } |
|
8067 if (deg == null) { |
|
8068 return; |
|
8069 } |
|
8070 deg = Str(deg).split(separator); |
|
8071 if (deg.length - 1) { |
|
8072 cx = toFloat(deg[1]); |
|
8073 cy = toFloat(deg[2]); |
|
8074 } |
|
8075 deg = toFloat(deg[0]); |
|
8076 (cy == null) && (cx = cy); |
|
8077 if (cx == null || cy == null) { |
|
8078 var bbox = this.getBBox(1); |
|
8079 cx = bbox.x + bbox.width / 2; |
|
8080 cy = bbox.y + bbox.height / 2; |
|
8081 } |
|
8082 this._.dirtyT = 1; |
|
8083 this.transform(this._.transform.concat([["r", deg, cx, cy]])); |
|
8084 return this; |
|
8085 }; |
|
8086 elproto.translate = function (dx, dy) { |
|
8087 if (this.removed) { |
|
8088 return this; |
|
8089 } |
|
8090 dx = Str(dx).split(separator); |
|
8091 if (dx.length - 1) { |
|
8092 dy = toFloat(dx[1]); |
|
8093 } |
|
8094 dx = toFloat(dx[0]) || 0; |
|
8095 dy = +dy || 0; |
|
8096 if (this._.bbox) { |
|
8097 this._.bbox.x += dx; |
|
8098 this._.bbox.y += dy; |
|
8099 } |
|
8100 this.transform(this._.transform.concat([["t", dx, dy]])); |
|
8101 return this; |
|
8102 }; |
|
8103 elproto.scale = function (sx, sy, cx, cy) { |
|
8104 if (this.removed) { |
|
8105 return this; |
|
8106 } |
|
8107 sx = Str(sx).split(separator); |
|
8108 if (sx.length - 1) { |
|
8109 sy = toFloat(sx[1]); |
|
8110 cx = toFloat(sx[2]); |
|
8111 cy = toFloat(sx[3]); |
|
8112 isNaN(cx) && (cx = null); |
|
8113 isNaN(cy) && (cy = null); |
|
8114 } |
|
8115 sx = toFloat(sx[0]); |
|
8116 (sy == null) && (sy = sx); |
|
8117 (cy == null) && (cx = cy); |
|
8118 if (cx == null || cy == null) { |
|
8119 var bbox = this.getBBox(1); |
|
8120 } |
|
8121 cx = cx == null ? bbox.x + bbox.width / 2 : cx; |
|
8122 cy = cy == null ? bbox.y + bbox.height / 2 : cy; |
|
8123 |
|
8124 this.transform(this._.transform.concat([["s", sx, sy, cx, cy]])); |
|
8125 this._.dirtyT = 1; |
|
8126 return this; |
|
8127 }; |
|
8128 elproto.hide = function () { |
|
8129 !this.removed && (this.node.style.display = "none"); |
|
8130 return this; |
|
8131 }; |
|
8132 elproto.show = function () { |
|
8133 !this.removed && (this.node.style.display = E); |
|
8134 return this; |
|
8135 }; |
|
8136 elproto._getBBox = function () { |
|
8137 if (this.removed) { |
|
8138 return {}; |
|
8139 } |
|
8140 if (this.type == "text") { |
|
8141 return { |
|
8142 x: this.X + (this.bbx || 0) - this.W / 2, |
|
8143 y: this.Y - this.H, |
|
8144 width: this.W, |
|
8145 height: this.H |
|
8146 }; |
|
8147 } else { |
|
8148 return pathDimensions(this.attrs.path); |
|
8149 } |
|
8150 }; |
|
8151 elproto.remove = function () { |
|
8152 if (this.removed) { |
|
8153 return; |
|
8154 } |
|
8155 this.paper.__set__ && this.paper.__set__.exclude(this); |
|
8156 R.eve.unbind("*.*." + this.id); |
|
8157 R._tear(this, this.paper); |
|
8158 this.node.parentNode.removeChild(this.node); |
|
8159 this.shape && this.shape.parentNode.removeChild(this.shape); |
|
8160 for (var i in this) { |
|
8161 delete this[i]; |
|
8162 } |
|
8163 this.removed = true; |
|
8164 }; |
|
8165 elproto.attr = function (name, value) { |
|
8166 if (this.removed) { |
|
8167 return this; |
|
8168 } |
|
8169 if (name == null) { |
|
8170 var res = {}; |
|
8171 for (var a in this.attrs) if (this.attrs[has](a)) { |
|
8172 res[a] = this.attrs[a]; |
|
8173 } |
|
8174 res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient; |
|
8175 res.transform = this._.transform; |
|
8176 return res; |
|
8177 } |
|
8178 if (value == null && R.is(name, "string")) { |
|
8179 if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) { |
|
8180 return this.attrs.gradient; |
|
8181 } |
|
8182 var names = name.split(separator), |
|
8183 out = {}; |
|
8184 for (var i = 0, ii = names.length; i < ii; i++) { |
|
8185 name = names[i]; |
|
8186 if (name in this.attrs) { |
|
8187 out[name] = this.attrs[name]; |
|
8188 } else if (R.is(this.paper.customAttributes[name], "function")) { |
|
8189 out[name] = this.paper.customAttributes[name].def; |
|
8190 } else { |
|
8191 out[name] = R._availableAttrs[name]; |
|
8192 } |
|
8193 } |
|
8194 return ii - 1 ? out : out[names[0]]; |
|
8195 } |
|
8196 if (this.attrs && value == null && R.is(name, "array")) { |
|
8197 out = {}; |
|
8198 for (i = 0, ii = name.length; i < ii; i++) { |
|
8199 out[name[i]] = this.attr(name[i]); |
|
8200 } |
|
8201 return out; |
|
8202 } |
|
8203 var params; |
|
8204 if (value != null) { |
|
8205 params = {}; |
|
8206 params[name] = value; |
|
8207 } |
|
8208 value == null && R.is(name, "object") && (params = name); |
|
8209 for (var key in params) { |
|
8210 eve("attr." + key + "." + this.id, this, params[key]); |
|
8211 } |
|
8212 if (params) { |
|
8213 for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) { |
|
8214 var par = this.paper.customAttributes[key].apply(this, [].concat(params[key])); |
|
8215 this.attrs[key] = params[key]; |
|
8216 for (var subkey in par) if (par[has](subkey)) { |
|
8217 params[subkey] = par[subkey]; |
|
8218 } |
|
8219 } |
|
8220 // this.paper.canvas.style.display = "none"; |
|
8221 if (params.text && this.type == "text") { |
|
8222 this.textpath.string = params.text; |
|
8223 } |
|
8224 setFillAndStroke(this, params); |
|
8225 // this.paper.canvas.style.display = E; |
|
8226 } |
|
8227 return this; |
|
8228 }; |
|
8229 elproto.toFront = function () { |
|
8230 !this.removed && this.node.parentNode.appendChild(this.node); |
|
8231 this.paper && this.paper.top != this && R._tofront(this, this.paper); |
|
8232 return this; |
|
8233 }; |
|
8234 elproto.toBack = function () { |
|
8235 if (this.removed) { |
|
8236 return this; |
|
8237 } |
|
8238 if (this.node.parentNode.firstChild != this.node) { |
|
8239 this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild); |
|
8240 R._toback(this, this.paper); |
|
8241 } |
|
8242 return this; |
|
8243 }; |
|
8244 elproto.insertAfter = function (element) { |
|
8245 if (this.removed) { |
|
8246 return this; |
|
8247 } |
|
8248 if (element.constructor == R.st.constructor) { |
|
8249 element = element[element.length - 1]; |
|
8250 } |
|
8251 if (element.node.nextSibling) { |
|
8252 element.node.parentNode.insertBefore(this.node, element.node.nextSibling); |
|
8253 } else { |
|
8254 element.node.parentNode.appendChild(this.node); |
|
8255 } |
|
8256 R._insertafter(this, element, this.paper); |
|
8257 return this; |
|
8258 }; |
|
8259 elproto.insertBefore = function (element) { |
|
8260 if (this.removed) { |
|
8261 return this; |
|
8262 } |
|
8263 if (element.constructor == R.st.constructor) { |
|
8264 element = element[0]; |
|
8265 } |
|
8266 element.node.parentNode.insertBefore(this.node, element.node); |
|
8267 R._insertbefore(this, element, this.paper); |
|
8268 return this; |
|
8269 }; |
|
8270 elproto.blur = function (size) { |
|
8271 var s = this.node.runtimeStyle, |
|
8272 f = s.filter; |
|
8273 f = f.replace(blurregexp, E); |
|
8274 if (+size !== 0) { |
|
8275 this.attrs.blur = size; |
|
8276 s.filter = f + S + ms + ".Blur(pixelradius=" + (+size || 1.5) + ")"; |
|
8277 s.margin = R.format("-{0}px 0 0 -{0}px", round(+size || 1.5)); |
|
8278 } else { |
|
8279 s.filter = f; |
|
8280 s.margin = 0; |
|
8281 delete this.attrs.blur; |
|
8282 } |
|
8283 }; |
|
8284 |
|
8285 R._engine.path = function (pathString, vml) { |
|
8286 var el = createNode("shape"); |
|
8287 el.style.cssText = cssDot; |
|
8288 el.coordsize = zoom + S + zoom; |
|
8289 el.coordorigin = vml.coordorigin; |
|
8290 var p = new Element(el, vml), |
|
8291 attr = {fill: "none", stroke: "#000"}; |
|
8292 pathString && (attr.path = pathString); |
|
8293 p.type = "path"; |
|
8294 p.path = []; |
|
8295 p.Path = E; |
|
8296 setFillAndStroke(p, attr); |
|
8297 vml.canvas.appendChild(el); |
|
8298 var skew = createNode("skew"); |
|
8299 skew.on = true; |
|
8300 el.appendChild(skew); |
|
8301 p.skew = skew; |
|
8302 p.transform(E); |
|
8303 return p; |
|
8304 }; |
|
8305 R._engine.rect = function (vml, x, y, w, h, r) { |
|
8306 var path = R._rectPath(x, y, w, h, r), |
|
8307 res = vml.path(path), |
|
8308 a = res.attrs; |
|
8309 res.X = a.x = x; |
|
8310 res.Y = a.y = y; |
|
8311 res.W = a.width = w; |
|
8312 res.H = a.height = h; |
|
8313 a.r = r; |
|
8314 a.path = path; |
|
8315 res.type = "rect"; |
|
8316 return res; |
|
8317 }; |
|
8318 R._engine.ellipse = function (vml, x, y, rx, ry) { |
|
8319 var res = vml.path(), |
|
8320 a = res.attrs; |
|
8321 res.X = x - rx; |
|
8322 res.Y = y - ry; |
|
8323 res.W = rx * 2; |
|
8324 res.H = ry * 2; |
|
8325 res.type = "ellipse"; |
|
8326 setFillAndStroke(res, { |
|
8327 cx: x, |
|
8328 cy: y, |
|
8329 rx: rx, |
|
8330 ry: ry |
|
8331 }); |
|
8332 return res; |
|
8333 }; |
|
8334 R._engine.circle = function (vml, x, y, r) { |
|
8335 var res = vml.path(), |
|
8336 a = res.attrs; |
|
8337 res.X = x - r; |
|
8338 res.Y = y - r; |
|
8339 res.W = res.H = r * 2; |
|
8340 res.type = "circle"; |
|
8341 setFillAndStroke(res, { |
|
8342 cx: x, |
|
8343 cy: y, |
|
8344 r: r |
|
8345 }); |
|
8346 return res; |
|
8347 }; |
|
8348 R._engine.image = function (vml, src, x, y, w, h) { |
|
8349 var path = R._rectPath(x, y, w, h), |
|
8350 res = vml.path(path).attr({stroke: "none"}), |
|
8351 a = res.attrs, |
|
8352 node = res.node, |
|
8353 fill = node.getElementsByTagName(fillString)[0]; |
|
8354 a.src = src; |
|
8355 res.X = a.x = x; |
|
8356 res.Y = a.y = y; |
|
8357 res.W = a.width = w; |
|
8358 res.H = a.height = h; |
|
8359 a.path = path; |
|
8360 res.type = "image"; |
|
8361 fill.parentNode == node && node.removeChild(fill); |
|
8362 fill.rotate = true; |
|
8363 fill.src = src; |
|
8364 fill.type = "tile"; |
|
8365 res._.fillpos = [x, y]; |
|
8366 res._.fillsize = [w, h]; |
|
8367 node.appendChild(fill); |
|
8368 setCoords(res, 1, 1, 0, 0, 0); |
|
8369 return res; |
|
8370 }; |
|
8371 R._engine.text = function (vml, x, y, text) { |
|
8372 var el = createNode("shape"), |
|
8373 path = createNode("path"), |
|
8374 o = createNode("textpath"); |
|
8375 x = x || 0; |
|
8376 y = y || 0; |
|
8377 text = text || ""; |
|
8378 path.v = R.format("m{0},{1}l{2},{1}", round(x * zoom), round(y * zoom), round(x * zoom) + 1); |
|
8379 path.textpathok = true; |
|
8380 o.string = Str(text); |
|
8381 o.on = true; |
|
8382 el.style.cssText = cssDot; |
|
8383 el.coordsize = zoom + S + zoom; |
|
8384 el.coordorigin = "0 0"; |
|
8385 var p = new Element(el, vml), |
|
8386 attr = { |
|
8387 fill: "#000", |
|
8388 stroke: "none", |
|
8389 font: R._availableAttrs.font, |
|
8390 text: text |
|
8391 }; |
|
8392 p.shape = el; |
|
8393 p.path = path; |
|
8394 p.textpath = o; |
|
8395 p.type = "text"; |
|
8396 p.attrs.text = Str(text); |
|
8397 p.attrs.x = x; |
|
8398 p.attrs.y = y; |
|
8399 p.attrs.w = 1; |
|
8400 p.attrs.h = 1; |
|
8401 setFillAndStroke(p, attr); |
|
8402 el.appendChild(o); |
|
8403 el.appendChild(path); |
|
8404 vml.canvas.appendChild(el); |
|
8405 var skew = createNode("skew"); |
|
8406 skew.on = true; |
|
8407 el.appendChild(skew); |
|
8408 p.skew = skew; |
|
8409 p.transform(E); |
|
8410 return p; |
|
8411 }; |
|
8412 R._engine.setSize = function (width, height) { |
|
8413 var cs = this.canvas.style; |
|
8414 this.width = width; |
|
8415 this.height = height; |
|
8416 width == +width && (width += "px"); |
|
8417 height == +height && (height += "px"); |
|
8418 cs.width = width; |
|
8419 cs.height = height; |
|
8420 cs.clip = "rect(0 " + width + " " + height + " 0)"; |
|
8421 if (this._viewBox) { |
|
8422 setViewBox.apply(this, this._viewBox); |
|
8423 } |
|
8424 return this; |
|
8425 }; |
|
8426 R._engine.setViewBox = function (x, y, w, h, fit) { |
|
8427 R.eve("setViewBox", this, this._viewBox, [x, y, w, h, fit]); |
|
8428 var width = this.width, |
|
8429 height = this.height, |
|
8430 size = 1 / mmax(w / width, h / height), |
|
8431 H, W; |
|
8432 if (fit) { |
|
8433 H = height / h; |
|
8434 W = width / w; |
|
8435 if (w * H < width) { |
|
8436 x -= (width - w * H) / 2 / H; |
|
8437 } |
|
8438 if (h * W < height) { |
|
8439 y -= (height - h * W) / 2 / W; |
|
8440 } |
|
8441 } |
|
8442 this._viewBox = [x, y, w, h, !!fit]; |
|
8443 this._viewBoxShift = { |
|
8444 dx: -x, |
|
8445 dy: -y, |
|
8446 scale: size |
|
8447 }; |
|
8448 this.forEach(function (el) { |
|
8449 el.transform("..."); |
|
8450 }); |
|
8451 return this; |
|
8452 }; |
|
8453 var createNode, |
|
8454 initWin = function (win) { |
|
8455 var doc = win.document; |
|
8456 doc.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)"); |
|
8457 try { |
|
8458 !doc.namespaces.rvml && doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml"); |
|
8459 createNode = function (tagName) { |
|
8460 return doc.createElement('<rvml:' + tagName + ' class="rvml">'); |
|
8461 }; |
|
8462 } catch (e) { |
|
8463 createNode = function (tagName) { |
|
8464 return doc.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">'); |
|
8465 }; |
|
8466 } |
|
8467 }; |
|
8468 initWin(R._g.win); |
|
8469 R._engine.create = function () { |
|
8470 var con = R._getContainer.apply(0, arguments), |
|
8471 container = con.container, |
|
8472 height = con.height, |
|
8473 s, |
|
8474 width = con.width, |
|
8475 x = con.x, |
|
8476 y = con.y; |
|
8477 if (!container) { |
|
8478 throw new Error("VML container not found."); |
|
8479 } |
|
8480 var res = new R._Paper, |
|
8481 c = res.canvas = R._g.doc.createElement("div"), |
|
8482 cs = c.style; |
|
8483 x = x || 0; |
|
8484 y = y || 0; |
|
8485 width = width || 512; |
|
8486 height = height || 342; |
|
8487 res.width = width; |
|
8488 res.height = height; |
|
8489 width == +width && (width += "px"); |
|
8490 height == +height && (height += "px"); |
|
8491 res.coordsize = zoom * 1e3 + S + zoom * 1e3; |
|
8492 res.coordorigin = "0 0"; |
|
8493 res.span = R._g.doc.createElement("span"); |
|
8494 res.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;"; |
|
8495 c.appendChild(res.span); |
|
8496 cs.cssText = R.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden", width, height); |
|
8497 if (container == 1) { |
|
8498 R._g.doc.body.appendChild(c); |
|
8499 cs.left = x + "px"; |
|
8500 cs.top = y + "px"; |
|
8501 cs.position = "absolute"; |
|
8502 } else { |
|
8503 if (container.firstChild) { |
|
8504 container.insertBefore(c, container.firstChild); |
|
8505 } else { |
|
8506 container.appendChild(c); |
|
8507 } |
|
8508 } |
|
8509 // plugins.call(res, res, R.fn); |
|
8510 res.renderfix = function () {}; |
|
8511 return res; |
|
8512 }; |
|
8513 R.prototype.clear = function () { |
|
8514 R.eve("clear", this); |
|
8515 this.canvas.innerHTML = E; |
|
8516 this.span = R._g.doc.createElement("span"); |
|
8517 this.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;"; |
|
8518 this.canvas.appendChild(this.span); |
|
8519 this.bottom = this.top = null; |
|
8520 }; |
|
8521 R.prototype.remove = function () { |
|
8522 R.eve("remove", this); |
|
8523 this.canvas.parentNode.removeChild(this.canvas); |
|
8524 for (var i in this) { |
|
8525 this[i] = removed(i); |
|
8526 } |
|
8527 return true; |
|
8528 }; |
|
8529 |
|
8530 var setproto = R.st; |
|
8531 for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) { |
|
8532 setproto[method] = (function (methodname) { |
|
8533 return function () { |
|
8534 var arg = arguments; |
|
8535 return this.forEach(function (el) { |
|
8536 el[methodname].apply(el, arg); |
|
8537 }); |
|
8538 }; |
|
8539 })(method); |
|
8540 } |
|
8541 }(window.Raphael);/* main file */ |
|
8542 |
|
8543 if ( window.IriSP === undefined && window.__IriSP === undefined ) { |
|
8544 var IriSP = {}; |
|
8545 var __IriSP = IriSP; /* for backward compatibility */ |
|
8546 } |
|
8547 |
|
8548 /* crap code will be the first against the wall when the |
|
8549 revolution comes */ |
|
8550 IriSP.loadLibs = function( libs, customCssPath, metadata_url, callback ) { |
|
8551 // Localize jQuery variable |
|
8552 IriSP.jQuery = null; |
|
8553 |
|
8554 /* FIXME : to refactor using popcorn.getscript ? */ |
|
8555 /******** Load jQuery if not present *********/ |
|
8556 if ( window.jQuery === undefined || window.jQuery.fn.jquery !== '1.4.2' ) { |
|
8557 |
|
8558 var script_tag = document.createElement( 'script' ); |
|
8559 script_tag.setAttribute( "type", "text/javascript" ); |
|
8560 script_tag.setAttribute( "src", libs.jQuery ); |
|
8561 |
|
8562 script_tag.onload = scriptLibHandler; |
|
8563 script_tag.onreadystatechange = function () { // Same thing but for IE |
|
8564 if ( this.readyState == 'complete' || this.readyState == 'loaded' ) { |
|
8565 scriptLibHandler(); |
|
8566 } |
|
8567 }; |
|
8568 |
|
8569 // Try to find the head, otherwise default to the documentElement |
|
8570 ( document.getElementsByTagName("head")[0] || document.documentElement ).appendChild( script_tag ); |
|
8571 } else { |
|
8572 // The jQuery version on the window is the one we want to use |
|
8573 IriSP.jQuery = window.jQuery; |
|
8574 scriptLibHandler(); |
|
8575 } |
|
8576 |
|
8577 /******** Called once jQuery has loaded ******/ |
|
8578 function scriptLibHandler() { |
|
8579 |
|
8580 var script_jqUi_tooltip = document.createElement( 'script' ); |
|
8581 script_jqUi_tooltip.setAttribute( "type", "text/javascript" ); |
|
8582 script_jqUi_tooltip.setAttribute( "src", libs.jQueryToolTip ); |
|
8583 script_jqUi_tooltip.onload = scriptLoadHandler; |
|
8584 script_jqUi_tooltip.onreadystatechange = function () { // Same thing but for IE |
|
8585 if ( this.readyState == 'complete' || this.readyState == 'loaded' ) { |
|
8586 scriptLoadHandler( "jquery.tools.min.js loded" ); |
|
8587 } |
|
8588 }; |
|
8589 |
|
8590 var script_swfObj = document.createElement('script'); |
|
8591 script_swfObj.setAttribute( "type","text/javascript" ); |
|
8592 script_swfObj.setAttribute( "src",libs.swfObject ); |
|
8593 script_swfObj.onload = scriptLoadHandler; |
|
8594 script_swfObj.onreadystatechange = function () { // Same thing but for IE |
|
8595 if ( this.readyState == 'complete' || this.readyState == 'loaded' ) { |
|
8596 scriptLoadHandler( "swfobject.js loded" ); |
|
8597 } |
|
8598 }; |
|
8599 |
|
8600 var script_jqUi = document.createElement( 'script' ); |
|
8601 script_jqUi.setAttribute( "type","text/javascript" ); |
|
8602 script_jqUi.setAttribute( "src",libs.jQueryUI ); |
|
8603 script_jqUi.onload = scriptLoadHandler; |
|
8604 script_jqUi.onreadystatechange = function () { // Same thing but for IE |
|
8605 if ( this.readyState == 'complete' || this.readyState == 'loaded' ) { |
|
8606 scriptLoadHandler( "jquery-ui.min.js loded" ); |
|
8607 } |
|
8608 }; |
|
8609 |
|
8610 |
|
8611 ( document.getElementsByTagName("head")[0] || document.documentElement ).appendChild( script_jqUi_tooltip); |
|
8612 ( document.getElementsByTagName("head")[0] || document.documentElement ).appendChild( script_jqUi ); |
|
8613 ( document.getElementsByTagName("head")[0] || document.documentElement ).appendChild( script_swfObj ); |
|
8614 |
|
8615 |
|
8616 }; |
|
8617 |
|
8618 /******** Called once all lib are loaded ******/ |
|
8619 var loadLib = 0; |
|
8620 /* FIXME : ugly */ |
|
8621 function scriptLoadHandler( Mylib ) { |
|
8622 //alert(Mylib); |
|
8623 loadLib +=1; |
|
8624 if( loadLib===3 ) { |
|
8625 main(); |
|
8626 } |
|
8627 }; |
|
8628 |
|
8629 /******** Our main function ********/ |
|
8630 function main() { |
|
8631 |
|
8632 |
|
8633 // Make our own IriSP.jQuery and restore window.jQuery if there was one. |
|
8634 IriSP.jQuery = window.jQuery.noConflict( true ); |
|
8635 // Call our Jquery |
|
8636 IriSP.jQuery( document ).ready( function($) { |
|
8637 |
|
8638 /******* Load CSS *******/ |
|
8639 var css_link_jquery = IriSP.jQuery( "<link>", { |
|
8640 rel: "stylesheet", |
|
8641 type: "text/css", |
|
8642 href: libs.cssjQueryUI, |
|
8643 'class': "dynamic_css" |
|
8644 } ); |
|
8645 var css_link_custom = IriSP.jQuery( "<link>", { |
|
8646 rel: "stylesheet", |
|
8647 type: "text/css", |
|
8648 href: customCssPath, |
|
8649 'class': "dynamic_css" |
|
8650 } ); |
|
8651 |
|
8652 css_link_jquery.appendTo( 'head' ); |
|
8653 css_link_custom.appendTo( 'head' ); |
|
8654 |
|
8655 // to see dynamicly loaded css on IE |
|
8656 if ( $.browser.msie ) { |
|
8657 $( '.dynamic_css' ).clone().appendTo( 'head' ); |
|
8658 } |
|
8659 |
|
8660 IriSP.setupDataLoader(); |
|
8661 IriSP.__dataloader.get(metadata_url, |
|
8662 function(data) { |
|
8663 /* save the data so that we could re-use it to |
|
8664 configure the video |
|
8665 */ |
|
8666 IriSP.__jsonMetadata = data; |
|
8667 callback.call(window) }); |
|
8668 }); |
|
8669 } |
|
8670 }; |
|
8671 |
|
8672 |
|
8673 IriSP.annotation_template = "{{! template for an annotation displayed in a segmentWidget }}<div title='{{divTitle}}' id='{{id}}' class='Ldt-iri-chapter' style='left: {{startPourcent}}%; width: {{endPourcent}}%; background:#{{hexa_color}};' ></div>"; |
|
8674 IriSP.annotationWidget_template = "{{! template for the annotation widget }}<div class='Ldt-AnnotationsWidget'> <!-- ugly div because we want to have a double border --> <div class='Ldt-Annotation-DoubleBorder'> <div class='Ldt-AnnotationContent'> <div class='Ldt-AnnotationShareIcons'> <a href=''><img src='{{img_dir}}/facebook.png' alt='share on facebook'></img></a> <a href=''><img src='{{img_dir}}/twitter.png' alt='share on twitter'></img></a> <a href=''><img src='{{img_dir}}/google.png' alt='share on google+'></img></a> </div> <div class='Ldt-SaTitle'></div> <div class='Ldt-SaDescription'></div> </div> </div></div>"; |
|
8675 IriSP.annotation_loading_template = "{{! template shown while the annotation widget is loading }}<div id='Ldt-load-container'><div id='Ldt-loader'> </div> Chargement... </div>"; |
|
8676 IriSP.arrowWidget_template = "<div class='Ldt-arrowWidget'></div>"; |
|
8677 IriSP.overlay_marker_template = "{{! the template for the small white bars which is z-indexed over our segment widget }}<div class='positionMarker'></div>"; |
|
8678 IriSP.player_template = "{{! template for the radio player }}<div class='Ldt-controler demo'> <div class='Ldt-LeftPlayerControls'> <div class='Ldt-button Ldt-CtrlPlay'></div> <div class='Ldt-button Ldt-CtrlAnnotate'></div> <div class='Ldt-button Ldt-CtrlSearch'></div> </div> <div class='Ldt-RightPlayerControls'> <div class='Ldt-Time'> <div class='Ldt-ElapsedTime'></div> <div class='Ldt-TimeSeparator'>/</div> <div class='Ldt-TotalTime'></div> </div> <div class='Ldt-button Ldt-CtrlSound'></div> </div></div>"; |
|
8679 IriSP.search_template = "{{! template for the search container }}<div class='LdtSearchContainer' style='margin-left: {{margin_left}}; position: absolute; margin-top: -60px;'> <div class='LdtSearch' style='display: none; background-color: #EEE; width: 165px; boder: 1px; border-color: #CFCFCF; position: absolute; text-align: center;'> <input class='LdtSearchInput' style='margin-top: 2px; margin-bottom: 2px;' /> </div></div><div class='cleaner'></div>"; |
|
8680 IriSP.share_template = "{{! social network sharing template }}<a onclick='__IriSP.MyApiPlayer.share(\'delicious\');' title='partager avec delicious'><span class='share shareDelicious'> </span></a> <a onclick='__IriSP.MyApiPlayer.share(\'facebook\');' title='partager avec facebook'> <span class='share shareFacebook'> </span></a><a onclick='__IriSP.MyApiPlayer.share(\'twitter\');' title='partager avec twitter'> <span class='share shareTwitter'> </span></a><a onclick='__IriSP.MyApiPlayer.share(\'myspace\');' title='partager avec Myspace'> <span class='share shareMySpace'> </span></a>"; |
|
8681 IriSP.sliderWidget_template = "{{! template for the slider widget - it's composed of two divs we one overlayed on top of the other }} <div class='Ldt-sliderBackground'></div><div class='Ldt-sliderForeground'></div><div class='Ldt-sliderPositionMarker'></div>"; |
|
8682 IriSP.tooltip_template = "{{! template used by the jquery ui tooltip }}<div class='Ldt-tooltip'> <div class='title'>{{title}}</div> <div class='time'>{{begin}} : {{end}} </div> <div class='description'>{{description}}</div></div>"; |
|
8683 IriSP.tooltipWidget_template = "{{! template for the tooltip widget }}<div class='tip'> <div class='tipcolor' style='height:10px;width:10px'></div> <div class='tiptext'></div>"; |
|
8684 IriSP.tweetWidget_template = "{{! template for the tweet widget }}<div class='Ldt-tweetWidget'> <div class='Ldt-tweet-DoubleBorder'> <img src='{{img_dir}}/minimize.png' class='Ldt-tweetWidgetKeepOpen' alt='dont minimize automatically'></img> <img src='{{img_dir}}/minimize.png' class='Ldt-tweetWidgetMinimize' alt='minimize window'></img> <div class='Ldt-tweetAvatar'></div> <img src='{{img_dir}}/profile_arrow.png' class='Ldt-tweetAvatar-profileArrow'></img> <div class='Ldt-tweetContents'></div> <a href='' target='_blank' class='Ldt-Retweet'><div class='Ldt-RetweetIcon'></div> - Retweet </a> <a href='' target='_blank' class='Ldt-TweetReply'><div class='Ldt-TweetReplyIcon'></div> - Reply</a> </div></div>";/* wrapper that simulates popcorn.js because |
|
8685 popcorn is a bit unstable at the time */ |
|
8686 |
|
8687 IriSP.PopcornReplacement = { |
|
8688 msgPump : {} /* used by jquery to receive and send messages */ |
|
8689 }; |
|
8690 |
|
8691 IriSP.PopcornReplacement.media = { |
|
8692 "paused": true, |
|
8693 "muted": false |
|
8694 }; |
|
8695 |
|
8696 IriSP.PopcornReplacement.listen = function(msg, callback) { |
|
8697 // IriSP.jQuery(IriSP.PopcornReplacement.msgPump).bind(msg, function(event, rest) { callback(rest); }); |
|
8698 if (!IriSP.PopcornReplacement.msgPump.hasOwnProperty(msg)) |
|
8699 IriSP.PopcornReplacement.msgPump[msg] = []; |
|
8700 |
|
8701 IriSP.PopcornReplacement.msgPump[msg].push(callback); |
|
8702 }; |
|
8703 |
|
8704 IriSP.PopcornReplacement.trigger = function(msg, params) { |
|
8705 // IriSP.jQuery(IriSP.PopcornReplacement.msgPump).trigger(msg, params); |
|
8706 |
|
8707 if (!IriSP.PopcornReplacement.msgPump.hasOwnProperty(msg)) |
|
8708 return; |
|
8709 |
|
8710 var d = IriSP.PopcornReplacement.msgPump[msg]; |
|
8711 for(var entry in d) { |
|
8712 d[entry].call(window, params); |
|
8713 } |
|
8714 |
|
8715 }; |
|
8716 |
|
8717 IriSP.PopcornReplacement.guid = function(prefix) { |
|
8718 var str = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { |
|
8719 var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); |
|
8720 return v.toString(16); |
|
8721 }); |
|
8722 |
|
8723 return prefix + str; |
|
8724 }; |
|
8725 |
|
8726 IriSP.PopcornReplacement.__initApi = function() { |
|
8727 IriSP.PopcornReplacement.trigger("loadedmetadata"); // we've done more than loading metadata of course, |
|
8728 // but popcorn doesn't need to know more. |
|
8729 IriSP.PopcornReplacement.media.muted = jwplayer(IriSP.PopcornReplacement._container).getMute(); |
|
8730 }; |
|
8731 |
|
8732 IriSP.PopcornReplacement.jwplayer = function(container, options) { |
|
8733 IriSP.PopcornReplacement._container = container.slice(1); //eschew the '#' |
|
8734 options.events = { |
|
8735 onReady: IriSP.PopcornReplacement.__initApi, |
|
8736 onTime: IriSP.PopcornReplacement.__timeHandler, |
|
8737 onPlay: IriSP.PopcornReplacement.__playHandler, |
|
8738 onPause: IriSP.PopcornReplacement.__pauseHandler, |
|
8739 onSeek: IriSP.PopcornReplacement.__seekHandler |
|
8740 } |
|
8741 |
|
8742 jwplayer(IriSP.PopcornReplacement._container).setup(options); |
|
8743 IriSP.PopcornReplacement.media.duration = options.duration; |
|
8744 return IriSP.PopcornReplacement; |
|
8745 }; |
|
8746 |
|
8747 IriSP.PopcornReplacement.currentTime = function(time) { |
|
8748 if (typeof(time) === "undefined") { |
|
8749 return jwplayer(IriSP.PopcornReplacement._container).getPosition(); |
|
8750 } else { |
|
8751 var currentTime = +time; |
|
8752 jwplayer( IriSP.PopcornReplacement._container ).seek( currentTime ); |
|
8753 IriSP.PopcornReplacement.trigger("seeked"); |
|
8754 return jwplayer(IriSP.PopcornReplacement._container).getPosition(); |
|
8755 } |
|
8756 }; |
|
8757 |
|
8758 IriSP.PopcornReplacement.play = function() { |
|
8759 IriSP.PopcornReplacement.media.paused = false; |
|
8760 IriSP.PopcornReplacement.trigger("play"); |
|
8761 // IriSP.PopcornReplacement.trigger("playing"); |
|
8762 jwplayer( IriSP.PopcornReplacement._container ).play(); |
|
8763 }; |
|
8764 |
|
8765 IriSP.PopcornReplacement.pause = function() { |
|
8766 if ( !IriSP.PopcornReplacement.media.paused ) { |
|
8767 IriSP.PopcornReplacement.media.paused = true; |
|
8768 IriSP.PopcornReplacement.trigger( "pause" ); |
|
8769 jwplayer( IriSP.PopcornReplacement._container ).pause(); |
|
8770 } |
|
8771 }; |
|
8772 |
|
8773 IriSP.PopcornReplacement.muted = function(val) { |
|
8774 if (typeof(val) !== "undefined") { |
|
8775 |
|
8776 if (jwplayer(IriSP.PopcornReplacement._container).getMute() !== val) { |
|
8777 if (val) { |
|
8778 jwplayer(IriSP.PopcornReplacement._container).setMute(true); |
|
8779 IriSP.PopcornReplacement.media.muted = true; |
|
8780 } else { |
|
8781 jwplayer( IriSP.PopcornReplacement._container ).setMute(false); |
|
8782 IriSP.PopcornReplacement.media.muted = false; |
|
8783 } |
|
8784 |
|
8785 IriSP.PopcornReplacement.trigger( "volumechange" ); |
|
8786 } |
|
8787 |
|
8788 return jwplayer( IriSP.PopcornReplacement._container ).getMute(); |
|
8789 } else { |
|
8790 return jwplayer( IriSP.PopcornReplacement._container ).getMute(); |
|
8791 } |
|
8792 }; |
|
8793 |
|
8794 IriSP.PopcornReplacement.mute = IriSP.PopcornReplacement.muted; |
|
8795 |
|
8796 IriSP.PopcornReplacement.__codes = []; |
|
8797 IriSP.PopcornReplacement.code = function(options) { |
|
8798 IriSP.PopcornReplacement.__codes.push(options); |
|
8799 return IriSP.PopcornReplacement; |
|
8800 }; |
|
8801 |
|
8802 IriSP.PopcornReplacement.__runCode = function() { |
|
8803 var currentTime = jwplayer(IriSP.PopcornReplacement._container).getPosition(); |
|
8804 var i = 0; |
|
8805 for(i = 0; i < IriSP.PopcornReplacement.__codes.length; i++) { |
|
8806 var c = IriSP.PopcornReplacement.__codes[i]; |
|
8807 if (currentTime == c.start) { |
|
8808 c.onStart(); |
|
8809 } |
|
8810 |
|
8811 if (currentTime == c.end) { |
|
8812 c.onEnd(); |
|
8813 } |
|
8814 |
|
8815 } |
|
8816 }; |
|
8817 |
|
8818 /* called everytime the player updates itself |
|
8819 (onTime event) |
|
8820 */ |
|
8821 |
|
8822 IriSP.PopcornReplacement.__timeHandler = function(event) { |
|
8823 var pos = event.position; |
|
8824 |
|
8825 var i = 0; |
|
8826 for(i = 0; i < IriSP.PopcornReplacement.__codes.length; i++) { |
|
8827 var c = IriSP.PopcornReplacement.__codes[i]; |
|
8828 |
|
8829 if (pos >= c.start && pos < c.end && |
|
8830 pos - 0.1 <= c.start) { |
|
8831 c.onStart(); |
|
8832 } |
|
8833 |
|
8834 if (pos >= c.start && pos >= c.end && |
|
8835 pos - 0.1 <= c.end) { |
|
8836 c.onEnd(); |
|
8837 } |
|
8838 |
|
8839 } |
|
8840 |
|
8841 IriSP.PopcornReplacement.trigger("timeupdate"); |
|
8842 }; |
|
8843 |
|
8844 IriSP.PopcornReplacement.__seekHandler = function(event) { |
|
8845 var i = 0; |
|
8846 for(i = 0; i < IriSP.PopcornReplacement.__codes.length; i++) { |
|
8847 var c = IriSP.PopcornReplacement.__codes[i]; |
|
8848 |
|
8849 if (event.position >= c.start && event.position < c.end) { |
|
8850 c.onEnd(); |
|
8851 } |
|
8852 |
|
8853 if (typeof(event.offset) === "undefined") |
|
8854 event.offset = 0; |
|
8855 if (event.offset >= c.start && event.offset < c.end) { |
|
8856 c.onStart(); |
|
8857 } |
|
8858 |
|
8859 } |
|
8860 |
|
8861 IriSP.PopcornReplacement.trigger("timeupdate"); |
|
8862 }; |
|
8863 |
|
8864 |
|
8865 IriSP.PopcornReplacement.__playHandler = function(event) { |
|
8866 IriSP.PopcornReplacement.media.paused = false; |
|
8867 IriSP.PopcornReplacement.trigger("play"); |
|
8868 }; |
|
8869 |
|
8870 IriSP.PopcornReplacement.__pauseHandler = function(event) { |
|
8871 IriSP.PopcornReplacement.media.paused = true; |
|
8872 IriSP.PopcornReplacement.trigger("pause"); |
|
8873 }; |
|
8874 |
|
8875 IriSP.PopcornReplacement.roundTime = function() { |
|
8876 var currentTime = IriSP.PopcornReplacement.currentTime(); |
|
8877 return Math.round(currentTime); |
|
8878 }; |
|
8879 /* utils.js - various utils that don't belong anywhere else */ |
|
8880 |
|
8881 /* trace function, for debugging */ |
|
8882 |
|
8883 IriSP.traceNum = 0; |
|
8884 IriSP.trace = function( msg, value ) { |
|
8885 /* |
|
8886 if( IriSP.config.gui.debug === true ) { |
|
8887 IriSP.traceNum += 1; |
|
8888 IriSP.jQuery( "<div>"+IriSP.traceNum+" - "+msg+" : "+value+"</div>" ).appendTo( "#Ldt-output" ); |
|
8889 } |
|
8890 */ |
|
8891 }; |
|
8892 |
|
8893 /* used in callbacks - because in callbacks we lose "this", |
|
8894 we need to have a special function which wraps "this" in |
|
8895 a closure. This way, the |
|
8896 */ |
|
8897 IriSP.wrap = function (obj, fn) { |
|
8898 return function() { |
|
8899 var args = Array.prototype.slice.call(arguments, 0); |
|
8900 return fn.apply(obj, args); |
|
8901 } |
|
8902 } |
|
8903 |
|
8904 /* convert a time to a percentage in the media */ |
|
8905 IriSP.timeToPourcent = function(time, timetotal){ |
|
8906 var time = Math.abs(time); |
|
8907 var timetotal = Math.abs(timetotal); |
|
8908 |
|
8909 return Math.floor((time/timetotal) * 100); |
|
8910 }; |
|
8911 |
|
8912 IriSP.padWithZeros = function(num) { |
|
8913 if (Math.abs(num) < 10) { |
|
8914 return "0" + num.toString(); |
|
8915 } else { |
|
8916 return num.toString(); |
|
8917 } |
|
8918 }; |
|
8919 /* convert a number of seconds to a tuple of the form |
|
8920 [hours, minutes, seconds] |
|
8921 */ |
|
8922 IriSP.secondsToTime = function(secs) { |
|
8923 var hours = Math.abs(parseInt( secs / 3600 ) % 24); |
|
8924 var minutes = Math.abs(parseInt( secs / 60 ) % 60); |
|
8925 var seconds = parseFloat(Math.abs(secs % 60).toFixed(0)); |
|
8926 |
|
8927 var toString_fn = function() { |
|
8928 var ret = ""; |
|
8929 if (hours > 0) |
|
8930 ret = IriSP.padWithZeros(this.hours) + ":"; |
|
8931 ret += IriSP.padWithZeros(this.minutes) + ":" + IriSP.padWithZeros(this.seconds); |
|
8932 |
|
8933 return ret; |
|
8934 } |
|
8935 return {"hours" : hours, "minutes" : minutes, "seconds" : seconds, toString: toString_fn}; |
|
8936 }; |
|
8937 |
|
8938 IriSP.secondsToString |
|
8939 |
|
8940 /* format a tweet - replaces @name by a link to the profile, #hashtag, etc. */ |
|
8941 IriSP.formatTweet = function(tweet) { |
|
8942 /* |
|
8943 an array of arrays which hold a regexp and its replacement. |
|
8944 */ |
|
8945 var regExps = [ |
|
8946 /* copied from http://codegolf.stackexchange.com/questions/464/shortest-url-regex-match-in-javascript/480#480 */ |
|
8947 [/((https?:\/\/)?[\w-]+(\.[\w-]+)+\.?(:\d+)?(\/\S*)?)/gi, "<a href='$1'>$1</a>"], |
|
8948 [/@(\w+)/gi, "<a href='http://twitter.com/$1'>@$1</a>"], // matches a @handle |
|
8949 [/#(\w+)/gi, "<a href='http://twitter.com/search?q=%23$1'>#$1</a>"],// matches a hashtag |
|
8950 [/(\+\+)/gi, "<span class='Ldt-PolemicPlusPlus'>$1</span>"], |
|
8951 [/(--)/gi, "<span class='Ldt-PolemicMinusMinus'>$1</span>"], |
|
8952 [/(==)/gi, "<span class='Ldt-PolemicEqualEqual'>$1</span>"], |
|
8953 [/(\?\?)/gi, "<span class='Ldt-PolemicQuestion'>$1</span>"] |
|
8954 ]; |
|
8955 |
|
8956 var i = 0; |
|
8957 for(i = 0; i < regExps.length; i++) { |
|
8958 tweet = tweet.replace(regExps[i][0], regExps[i][1]); |
|
8959 } |
|
8960 |
|
8961 return tweet; |
|
8962 }; |
|
8963 |
|
8964 IriSP.countProperties = function(obj) { |
|
8965 var count = 0; |
|
8966 |
|
8967 for(var prop in obj) { |
|
8968 if(obj.hasOwnProperty(prop)) |
|
8969 ++count; |
|
8970 } |
|
8971 |
|
8972 return count; |
|
8973 }; |
|
8974 |
|
8975 // conversion de couleur Decimal vers HexaDecimal || 000 si fff |
|
8976 IriSP.DEC_HEXA_COLOR = function (dec) { |
|
8977 var hexa='0123456789ABCDEF',hex=''; |
|
8978 var tmp; |
|
8979 while (dec>15){ |
|
8980 tmp = dec-(Math.floor(dec/16))*16; |
|
8981 hex = hexa.charAt(tmp)+hex; |
|
8982 dec = Math.floor(dec/16); |
|
8983 } |
|
8984 hex = hexa.charAt(dec)+hex; |
|
8985 if (hex == "FFCC00"){ hex="";/* by default color of Ldt annotation */ } |
|
8986 return(hex); |
|
8987 }; |
|
8988 |
|
8989 /* shortcut to have global variables in templates */ |
|
8990 IriSP.templToHTML = function(template, values) { |
|
8991 var params = IriSP.jQuery.extend(IriSP.default_templates_vars, values); |
|
8992 return Mustache.to_html(template, params); |
|
8993 }; |
|
8994 |
|
8995 /* we need to be stricter than encodeURIComponent, |
|
8996 because of twitter |
|
8997 */ |
|
8998 IriSP.encodeURI = function(str) { |
|
8999 return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28'). |
|
9000 replace(/\)/g, '%29').replace(/\*/g, '%2A'); |
|
9001 } |
|
9002 |
|
9003 |
|
9004 /* for ie compatibility |
|
9005 if (Object.prototype.__defineGetter__&&!Object.defineProperty) { |
|
9006 Object.defineProperty=function(obj,prop,desc) { |
|
9007 if ("get" in desc) obj.__defineGetter__(prop,desc.get); |
|
9008 if ("set" in desc) obj.__defineSetter__(prop,desc.set); |
|
9009 } |
|
9010 } |
|
9011 */ |
|
9012 /* data.js - this file deals with how the players gets and sends data */ |
|
9013 |
|
9014 IriSP.DataLoader = function() { |
|
9015 this._cache = {}; |
|
9016 |
|
9017 /* |
|
9018 A structure to hold callbacks for specific urls. We need it because |
|
9019 ajax calls are asynchronous, so it means that sometimes we ask |
|
9020 multiple times for a ressource because the first call hasn't been |
|
9021 received yet. |
|
9022 */ |
|
9023 this._callbacks = {}; |
|
9024 }; |
|
9025 |
|
9026 IriSP.DataLoader.prototype.get = function(url, callback) { |
|
9027 |
|
9028 var base_url = url.split("&")[0] |
|
9029 if (this._cache.hasOwnProperty(base_url)) { |
|
9030 callback(this._cache[base_url]); |
|
9031 } else { |
|
9032 if (!this._callbacks.hasOwnProperty(base_url)) { |
|
9033 this._callbacks[base_url] = []; |
|
9034 this._callbacks[base_url].push(callback); |
|
9035 /* we need a closure because this gets lost when it's called back */ |
|
9036 |
|
9037 // uncomment you don't want to use caching. |
|
9038 // IriSP.jQuery.get(url, callback); |
|
9039 |
|
9040 var func = function(data) { |
|
9041 this._cache[base_url] = data; |
|
9042 var i = 0; |
|
9043 |
|
9044 for (i = 0; i < this._callbacks[base_url].length; i++) { |
|
9045 this._callbacks[base_url][i](this._cache[base_url]); |
|
9046 } |
|
9047 }; |
|
9048 |
|
9049 /* automagically choose between json and jsonp */ |
|
9050 if (url.indexOf(document.location.hostname) === -1 && |
|
9051 url.indexOf("http://") !== -1 /* not a relative url */ ) { |
|
9052 // we contacting a foreign domain, use JSONP |
|
9053 |
|
9054 IriSP.jQuery.get(url, {}, IriSP.wrap(this, func), "jsonp"); |
|
9055 } else { |
|
9056 |
|
9057 // otherwise, hey, whatever rows your boat |
|
9058 IriSP.jQuery.get(url, IriSP.wrap(this, func)); |
|
9059 } |
|
9060 |
|
9061 } else { |
|
9062 /* simply push the callback - it'll get called when the ressource |
|
9063 has been received */ |
|
9064 |
|
9065 this._callbacks[base_url].push(callback); |
|
9066 |
|
9067 } |
|
9068 } |
|
9069 } |
|
9070 |
|
9071 /* the base abstract "class" */ |
|
9072 IriSP.Serializer = function(DataLoader, url) { |
|
9073 this._DataLoader = DataLoader; |
|
9074 this._url = url; |
|
9075 this._data = []; |
|
9076 }; |
|
9077 |
|
9078 IriSP.Serializer.prototype.serialize = function(data) { }; |
|
9079 IriSP.Serializer.prototype.deserialize = function(data) {}; |
|
9080 |
|
9081 IriSP.Serializer.prototype.currentMedia = function() { |
|
9082 }; |
|
9083 |
|
9084 IriSP.Serializer.prototype.sync = function(callback) { |
|
9085 callback.call(this, this._data); |
|
9086 }; |
|
9087 |
|
9088 IriSP.SerializerFactory = function(DataLoader) { |
|
9089 this._dataloader = DataLoader; |
|
9090 }; |
|
9091 |
|
9092 IriSP.SerializerFactory.prototype.getSerializer = function(metadataOptions) { |
|
9093 /* This function returns serializer set-up with the correct |
|
9094 configuration - takes a metadata struct describing the metadata source |
|
9095 */ |
|
9096 |
|
9097 if (metadataOptions === undefined) |
|
9098 /* return an empty serializer */ |
|
9099 return IriSP.Serializer("", ""); |
|
9100 |
|
9101 switch(metadataOptions.type) { |
|
9102 case "json": |
|
9103 return new IriSP.JSONSerializer(this._dataloader, metadataOptions.src); |
|
9104 break; |
|
9105 |
|
9106 case "dummy": /* only used for unit testing - not defined in production */ |
|
9107 return new IriSP.MockSerializer(this._dataloader, metadataOptions.src); |
|
9108 break; |
|
9109 |
|
9110 case "empty": |
|
9111 return new IriSP.Serializer("", "empty"); |
|
9112 break; |
|
9113 |
|
9114 default: |
|
9115 return undefined; |
|
9116 } |
|
9117 }; |
|
9118 /* site.js - all our site-dependent config : player chrome, cdn locations, etc...*/ |
|
9119 |
|
9120 IriSP.lib = { |
|
9121 jQuery : "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js", |
|
9122 jQueryUI : "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/jquery-ui.js", |
|
9123 jQueryToolTip : "http://cdn.jquerytools.org/1.2.4/all/jquery.tools.min.js", |
|
9124 swfObject : "http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js", |
|
9125 cssjQueryUI : "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/themes/base/jquery-ui.css", |
|
9126 popcorn : "src/js/libs/popcorn.js", |
|
9127 jwplayer : "src/js/libs/jwplayer.js", |
|
9128 "popcorn.mediafragment" : "src/js/libs/popcorn.mediafragment.js", |
|
9129 "popcorn.code" : "src/js/libs/popcorn.code.js", |
|
9130 "popcorn.jwplayer": "src/js/libs/popcorn.jwplayer.js", |
|
9131 "popcorn.youtube": "src/js/libs/popcorn.youtube.js", |
|
9132 raphael: "src/js/libs/raphael.js" |
|
9133 }; |
|
9134 |
|
9135 //Player Configuration |
|
9136 IriSP.config = undefined; |
|
9137 |
|
9138 IriSP.widgetsDefaults = { |
|
9139 "LayoutManager" : {spacer_div_height : "0px" }, |
|
9140 "PlayerWidget" : {}, |
|
9141 "AnnotationsWidget": {}, |
|
9142 "TweetsWidget" : { |
|
9143 default_profile_picture : "https://si0.twimg.com/sticky/default_profile_images/default_profile_1_normal.png", |
|
9144 tweet_display_period: 10000 // how long do we show a tweet ? |
|
9145 }, |
|
9146 "SliderWidget" : { |
|
9147 minimize_period: 850 // how long does the slider stays maximized after the user leaves the zone ? |
|
9148 } |
|
9149 }; |
|
9150 |
|
9151 IriSP.paths = { |
|
9152 // "imgs": "/tweetlive/res/metadataplayer/src/css/imgs" |
|
9153 "imgs": "/mdp/src/css/imgs" |
|
9154 }; |
|
9155 IriSP.default_templates_vars = { |
|
9156 "img_dir" : IriSP.paths.imgs |
|
9157 }; |
|
9158 |
|
9159 /* ui.js - ui related functions */ |
|
9160 |
|
9161 /* FIXME: use an sharing library */ |
|
9162 IriSP.LdtShareTool = IriSP.share_template; /* the contents come from share.html */ |
|
9163 |
|
9164 IriSP.createPlayerChrome = function(){ |
|
9165 var width = IriSP.config.gui.width; |
|
9166 var height = IriSP.config.gui.height; |
|
9167 var heightS = IriSP.config.gui.height-20; |
|
9168 |
|
9169 // AUDIO */ |
|
9170 // PB dans le html : ; |
|
9171 IriSP.trace( "__IriSP.createMyHtml",IriSP.config.gui.container ); |
|
9172 |
|
9173 |
|
9174 /* FIXME : factor this in another file */ |
|
9175 if( IriSP.config.gui.mode=="radio" ){ |
|
9176 |
|
9177 IriSP.jQuery( "#"+IriSP.config.gui.container ).before(IriSP.search_template); |
|
9178 var radioPlayer = Mustache.to_html(IriSP.radio_template, {"share_template" : IriSP.share_template}); |
|
9179 IriSP.jQuery(radioPlayer).appendTo("#"+IriSP.config.gui.container); |
|
9180 |
|
9181 // special tricks for IE 7 |
|
9182 if (IriSP.jQuery.browser.msie==true && IriSP.jQuery.browser.version=="7.0"){ |
|
9183 //LdtSearchContainer |
|
9184 //__IriSP.jQuery("#LdtPlayer").attr("margin-top","50px"); |
|
9185 IriSP.jQuery("#Ldt-Root").css("padding-top","25px"); |
|
9186 IriSP.trace("__IriSP.createHtml","IE7 SPECIAL "); |
|
9187 } |
|
9188 } else if(IriSP.config.gui.mode=="video") { |
|
9189 |
|
9190 var videoPlayer = Mustache.to_html(IriSP.video_template, {"share_template" : IriSP.share_template, "heightS" : heightS}); |
|
9191 IriSP.jQuery(videoPlayer).appendTo("#"+IriSP.config.gui.container); |
|
9192 } |
|
9193 |
|
9194 IriSP.jQuery("#Ldt-Annotations").width(width-(75*2)); |
|
9195 IriSP.jQuery("#Ldt-Show-Arrow-container").width(width-(75*2)); |
|
9196 IriSP.jQuery("#Ldt-ShowAnnotation-audio").width(width-10); |
|
9197 IriSP.jQuery("#Ldt-ShowAnnotation-video").width(width-10); |
|
9198 IriSP.jQuery("#Ldt-SaKeyword").width(width-10); |
|
9199 IriSP.jQuery("#Ldt-controler").width(width-10); |
|
9200 IriSP.jQuery("#Ldt-Control").attr("z-index","100"); |
|
9201 IriSP.jQuery("#Ldt-controler").hide(); |
|
9202 |
|
9203 IriSP.jQuery(IriSP.annotation_loading_template).appendTo("#Ldt-ShowAnnotation-audio"); |
|
9204 |
|
9205 if(IriSP.config.gui.mode=='radio'){ |
|
9206 IriSP.jQuery("#Ldt-load-container").attr("width",IriSP.config.gui.width); |
|
9207 } |
|
9208 // Show or not the output |
|
9209 if(IriSP.config.gui.debug===true){ |
|
9210 IriSP.jQuery("#Ldt-output").show(); |
|
9211 } else { |
|
9212 IriSP.jQuery("#Ldt-output").hide(); |
|
9213 } |
|
9214 |
|
9215 }; |
|
9216 |
|
9217 |
|
9218 /* create the buttons and the slider */ |
|
9219 IriSP.createInterface = function( width, height, duration ) { |
|
9220 |
|
9221 IriSP.jQuery( "#Ldt-controler" ).show(); |
|
9222 //__IriSP.jQuery("#Ldt-Root").css('display','visible'); |
|
9223 IriSP.trace( "__IriSP.createInterface" , width+","+height+","+duration+"," ); |
|
9224 |
|
9225 IriSP.jQuery( "#Ldt-ShowAnnotation").click( function () { |
|
9226 //__IriSP.jQuery(this).slideUp(); |
|
9227 } ); |
|
9228 |
|
9229 var LdtpPlayerY = IriSP.jQuery("#Ldt-PlaceHolder").attr("top"); |
|
9230 var LdtpPlayerX = IriSP.jQuery("#Ldt-PlaceHolder").attr("left"); |
|
9231 |
|
9232 IriSP.jQuery( "#slider-range-min" ).slider( { //range: "min", |
|
9233 value: 0, |
|
9234 min: 1, |
|
9235 max: duration/1000,//1:54:52.66 = 3600+3240+ |
|
9236 step: 0.1, |
|
9237 slide: function(event, ui) { |
|
9238 |
|
9239 //__IriSP.jQuery("#amount").val(ui.value+" s"); |
|
9240 //player.sendEvent('SEEK', ui.value) |
|
9241 IriSP.MyApiPlayer.seek(ui.value); |
|
9242 //changePageUrlOffset(ui.value); |
|
9243 //player.sendEvent('PAUSE') |
|
9244 } |
|
9245 } ); |
|
9246 |
|
9247 IriSP.trace("__IriSP.createInterface","ICI"); |
|
9248 IriSP.jQuery("#amount").val(IriSP.jQuery("#slider-range-min").slider("value")+" s"); |
|
9249 IriSP.jQuery(".Ldt-Control1 button:first").button({ |
|
9250 icons: { |
|
9251 primary: 'ui-icon-play' |
|
9252 }, |
|
9253 text: false |
|
9254 }).next().button({ |
|
9255 icons: { |
|
9256 primary: 'ui-icon-seek-next' |
|
9257 }, |
|
9258 text: false |
|
9259 }); |
|
9260 IriSP.jQuery(".Ldt-Control2 button:first").button({ |
|
9261 icons: { |
|
9262 primary: 'ui-icon-search'//, |
|
9263 //secondary: 'ui-icon-volume-off' |
|
9264 }, |
|
9265 text: false |
|
9266 }).next().button({ |
|
9267 icons: { |
|
9268 primary: 'ui-icon-volume-on' |
|
9269 }, |
|
9270 text: false |
|
9271 }); |
|
9272 |
|
9273 // /!\ PB A MODIFIER |
|
9274 //__IriSP.MyTags.draw(); |
|
9275 IriSP.trace("__IriSP.createInterface","ICI2"); |
|
9276 IriSP.jQuery( "#ldt-CtrlPlay" ).attr( "style", "background-color:#CD21C24;" ); |
|
9277 |
|
9278 IriSP.jQuery( "#Ldt-load-container" ).hide(); |
|
9279 |
|
9280 if( IriSP.config.gui.mode=="radio" & IriSP.jQuery.browser.msie != true ) { |
|
9281 IriSP.jQuery( "#Ldtplayer1" ).attr( "height", "0" ); |
|
9282 } |
|
9283 IriSP.trace( "__IriSP.createInterface" , "3" ); |
|
9284 |
|
9285 IriSP.trace( "__IriSP.createInterface", "END" ); |
|
9286 |
|
9287 }; |
|
9288 /* the widget classes and definitions */ |
|
9289 |
|
9290 IriSP.Widget = function(Popcorn, config, Serializer) { |
|
9291 |
|
9292 if (config === undefined || config === null) { |
|
9293 config = {} |
|
9294 } |
|
9295 |
|
9296 this._Popcorn = Popcorn; |
|
9297 this._config = config; |
|
9298 this._serializer = Serializer; |
|
9299 |
|
9300 if (config.hasOwnProperty("container")) { |
|
9301 this._id = config.container; |
|
9302 this.selector = IriSP.jQuery("#" + this._id); |
|
9303 } |
|
9304 |
|
9305 if (config.hasOwnProperty("spacer")) { |
|
9306 this._spacerId = config.spacer; |
|
9307 this.spacer = IriSP.jQuery("#" + this._spacerId); |
|
9308 } |
|
9309 |
|
9310 |
|
9311 if (config.hasOwnProperty("width")) { |
|
9312 // this.width and not this._width because we consider it public. |
|
9313 this.width = config.width; |
|
9314 } |
|
9315 |
|
9316 if (config.hasOwnProperty("height")) { |
|
9317 this.height = config.height; |
|
9318 } |
|
9319 |
|
9320 if (config.hasOwnProperty("heightmax")) { |
|
9321 this.heightmax = config.heightmax; |
|
9322 } |
|
9323 |
|
9324 if (config.hasOwnProperty("widthmax")) { |
|
9325 this.widthmax = config.widthmax; |
|
9326 } |
|
9327 |
|
9328 }; |
|
9329 |
|
9330 IriSP.Widget.prototype.draw = function() { |
|
9331 /* implemented by "sub-classes" */ |
|
9332 }; |
|
9333 |
|
9334 IriSP.Widget.prototype.redraw = function() { |
|
9335 /* implemented by "sub-classes" */ |
|
9336 }; |
|
9337 /* modules are non-graphical entities, similar to widgets */ |
|
9338 |
|
9339 IriSP.Module = function(Popcorn, config, Serializer) { |
|
9340 |
|
9341 if (config === undefined || config === null) { |
|
9342 config = {} |
|
9343 } |
|
9344 |
|
9345 this._Popcorn = Popcorn; |
|
9346 this._config = config; |
|
9347 this._serializer = Serializer; |
|
9348 }; |
|
9349 /* layout.js - very basic layout management */ |
|
9350 |
|
9351 /* |
|
9352 a layout manager manages a div and the layout of objects |
|
9353 inside it. |
|
9354 */ |
|
9355 |
|
9356 IriSP.LayoutManager = function(options) { |
|
9357 this._Popcorn = null; |
|
9358 this._widgets = []; |
|
9359 |
|
9360 this._div = "LdtPlayer"; |
|
9361 this._width = 640; |
|
9362 |
|
9363 if (options === undefined) { |
|
9364 options = {}; |
|
9365 }; |
|
9366 |
|
9367 if (options.hasOwnProperty('container')) { |
|
9368 this._div = options.container; |
|
9369 } |
|
9370 |
|
9371 if (options.hasOwnProperty('width')) { |
|
9372 this._width = options.width; |
|
9373 } |
|
9374 |
|
9375 if (options.hasOwnProperty('height')) { |
|
9376 this._height = options.height; |
|
9377 } |
|
9378 |
|
9379 /* this is a shortcut */ |
|
9380 this.selector = IriSP.jQuery("#" + this._div); |
|
9381 |
|
9382 this.selector.css("width", this._width); |
|
9383 |
|
9384 if (this._height !== undefined) |
|
9385 this.selector.css("height", this._height); |
|
9386 }; |
|
9387 |
|
9388 /* we need this special setter because of a chicken and egg problem : |
|
9389 we want the manager to use popcorn but the popcorn div will be managed |
|
9390 by the manager. So we need a way to set the instance the manager uses |
|
9391 */ |
|
9392 |
|
9393 IriSP.LayoutManager.prototype.setPopcornInstance = function(popcorn) { |
|
9394 this._Popcorn = popcorn; |
|
9395 } |
|
9396 |
|
9397 /* stem is a string to append to the id of the widget */ |
|
9398 IriSP.LayoutManager.prototype.createDiv = function(stem) { |
|
9399 if (typeof(stem) === "undefined") |
|
9400 stem = ""; |
|
9401 |
|
9402 var newDiv = Popcorn.guid(this._div + "_widget_" + stem + "_"); |
|
9403 var spacerDiv = Popcorn.guid("LdtPlayer_spacer_"); |
|
9404 this._widgets.push(newDiv); |
|
9405 |
|
9406 var divTempl = "<div id='{{id}}' style='width: {{width}}px; position: relative;'></div"; |
|
9407 var spacerTempl = "<div id='{{spacer_id}}' style='width: {{width}}px; position: relative; height: {{spacer_div_height}};'></div"; |
|
9408 |
|
9409 var divCode = Mustache.to_html(divTempl, {id: newDiv, width: this._width}); |
|
9410 var spacerCode = Mustache.to_html(spacerTempl, {spacer_id: spacerDiv, width: this._width, |
|
9411 spacer_div_height: IriSP.widgetsDefaults.LayoutManager.spacer_div_height }); |
|
9412 |
|
9413 this.selector.append(divCode); |
|
9414 this.selector.append(spacerCode); |
|
9415 |
|
9416 return [newDiv, spacerDiv]; |
|
9417 }; |
|
9418 /* init.js - initialization and configuration of Popcorn and the widgets |
|
9419 exemple json configuration: |
|
9420 |
|
9421 */ |
|
9422 |
|
9423 IriSP.setupDataLoader = function() { |
|
9424 /* we set it up separately because we need to |
|
9425 get data at the very beginning, for instance when |
|
9426 setting up the video */ |
|
9427 IriSP.__dataloader = new IriSP.DataLoader(); |
|
9428 }; |
|
9429 |
|
9430 IriSP.configurePopcorn = function (layoutManager, options) { |
|
9431 var pop; |
|
9432 var ret = layoutManager.createDiv(); |
|
9433 var containerDiv = ret[0]; |
|
9434 |
|
9435 switch(options.type) { |
|
9436 /* |
|
9437 todo : dynamically create the div/video tag which |
|
9438 will contain the video. |
|
9439 */ |
|
9440 case "html5": |
|
9441 var tmpId = Popcorn.guid("video"); |
|
9442 IriSP.jQuery("#" + containerDiv).append("<video src='" + options.file + "' id='" + tmpId + "'></video>"); |
|
9443 |
|
9444 if (options.hasOwnProperty("width")) |
|
9445 IriSP.jQuery("#" + containerDiv).css("width", options.width); |
|
9446 |
|
9447 if (options.hasOwnProperty("height")) |
|
9448 IriSP.jQuery("#" + containerDiv).css("height", options.height); |
|
9449 |
|
9450 pop = Popcorn("#" + tmpId).mediafragment({start : 0}); |
|
9451 break; |
|
9452 |
|
9453 case "jwplayer": |
|
9454 var opts = IriSP.jQuery.extend({}, options); |
|
9455 delete opts.container; |
|
9456 |
|
9457 if (options.provider === "rtmp") { |
|
9458 /* exit if we can't access the metadata */ |
|
9459 if (typeof(IriSP.__jsonMetadata) === "undefined") { |
|
9460 break; |
|
9461 }; |
|
9462 |
|
9463 |
|
9464 // the json format is totally illogical |
|
9465 opts.streamer = IriSP.__jsonMetadata["medias"][0]["meta"]["item"]["value"]; |
|
9466 var source = IriSP.__jsonMetadata["medias"][0]["href"]; |
|
9467 |
|
9468 // the source if a full url but jwplayer wants an url relative to the |
|
9469 // streamer url, so we've got to remove the common part. |
|
9470 opts.file = source.slice(opts.streamer.length); |
|
9471 } else { |
|
9472 /* other providers type, video for instance - |
|
9473 pass everything as is */ |
|
9474 } |
|
9475 |
|
9476 pop = IriSP.PopcornReplacement.jwplayer("#" + containerDiv, opts); |
|
9477 break; |
|
9478 |
|
9479 case "youtube": |
|
9480 var opts = IriSP.jQuery.extend({}, options); |
|
9481 delete opts.container; |
|
9482 opts.controls = 0; |
|
9483 opts.autostart = false; |
|
9484 templ = "width: {{width}}px; height: {{height}}px;"; |
|
9485 var str = Mustache.to_html(templ, {width: opts.width, height: opts.height}); |
|
9486 // Popcorn.youtube wants us to specify the size of the player in the style attribute of its container div. |
|
9487 IriSP.jQuery("#" + containerDiv).attr("style", str); |
|
9488 |
|
9489 pop = Popcorn.youtube("#" + containerDiv, opts.video, opts).mediafragment({start : 0}); |
|
9490 break; |
|
9491 |
|
9492 default: |
|
9493 pop = undefined; |
|
9494 }; |
|
9495 |
|
9496 return pop; |
|
9497 }; |
|
9498 |
|
9499 IriSP.configureWidgets = function (popcornInstance, layoutManager, guiOptions) { |
|
9500 |
|
9501 var serialFactory = new IriSP.SerializerFactory(IriSP.__dataloader); |
|
9502 var params = {width: guiOptions.width, height: guiOptions.height}; |
|
9503 |
|
9504 var ret_widgets = []; |
|
9505 var index; |
|
9506 |
|
9507 for (index = 0; index < guiOptions.widgets.length; index++) { |
|
9508 var widgetConfig = guiOptions.widgets[index]; |
|
9509 var widget = IriSP.instantiateWidget(popcornInstance, serialFactory, layoutManager, widgetConfig); |
|
9510 ret_widgets.push(widget); |
|
9511 |
|
9512 }; |
|
9513 |
|
9514 return ret_widgets; |
|
9515 }; |
|
9516 |
|
9517 IriSP.configureModules = function (popcornInstance, modulesList) { |
|
9518 |
|
9519 var serialFactory = new IriSP.SerializerFactory(IriSP.__dataloader); |
|
9520 var ret_modules = []; |
|
9521 var index; |
|
9522 |
|
9523 for (index = 0; index < modulesList.length; index++) { |
|
9524 var moduleConfig = modulesList[index]; |
|
9525 |
|
9526 var serializer = serialFactory.getSerializer(moduleConfig.metadata); |
|
9527 var module = new IriSP[moduleConfig.type](popcornInstance, moduleConfig, serializer); |
|
9528 ret_modules.push(module); |
|
9529 }; |
|
9530 |
|
9531 return ret_modules; |
|
9532 }; |
|
9533 |
|
9534 IriSP.instantiateWidget = function(popcornInstance, serialFactory, layoutManager, widgetConfig) { |
|
9535 /* create div returns us a container for the widget and a spacer */ |
|
9536 var ret = layoutManager.createDiv(widgetConfig.type); |
|
9537 var container = ret[0]; |
|
9538 var spacer = ret[1]; |
|
9539 |
|
9540 var arr = IriSP.jQuery.extend({}, widgetConfig); |
|
9541 arr.container = container; |
|
9542 arr.spacer = spacer; |
|
9543 |
|
9544 var serializer = serialFactory.getSerializer(widgetConfig.metadata); |
|
9545 |
|
9546 if (typeof serializer == "undefined") |
|
9547 debugger; |
|
9548 |
|
9549 // instantiate the object passed as a string |
|
9550 var widget = new IriSP[widgetConfig.type](popcornInstance, arr, serializer); |
|
9551 |
|
9552 if (widgetConfig.hasOwnProperty("requires")) { |
|
9553 // also create the widgets this one depends on. |
|
9554 // the dependency widget is available in the parent widget context as |
|
9555 // this.WidgetName (for instance, this.TipWidget); |
|
9556 |
|
9557 var i = 0; |
|
9558 for(i = 0; i < widgetConfig.requires.length; i++) { |
|
9559 var widgetName = widgetConfig.requires[i]["type"]; |
|
9560 widget[widgetName] = IriSP.instantiateWidget(popcornInstance, serialFactory, layoutManager, widgetConfig.requires[i]); |
|
9561 } |
|
9562 } |
|
9563 |
|
9564 serializer.sync(IriSP.wrap(widget, function() { this.draw(); })); |
|
9565 return widget; |
|
9566 }; |
|
9567 /* mediafragment module */ |
|
9568 |
|
9569 IriSP.MediaFragment = function(Popcorn, config, Serializer) { |
|
9570 IriSP.Module.call(this, Popcorn, config, Serializer); |
|
9571 |
|
9572 this.mutex = false; /* a mutex because we access the url from two different functions */ |
|
9573 |
|
9574 this._Popcorn.listen( "loadedmetadata", IriSP.wrap(this, IriSP.MediaFragment.advanceTime)); |
|
9575 this._Popcorn.listen( "pause", IriSP.wrap(this, IriSP.MediaFragment.updateTime)); |
|
9576 this._Popcorn.listen( "seeked", IriSP.wrap(this, IriSP.MediaFragment.updateTime)); |
|
9577 this._Popcorn.listen( "IriSP.PolemicTweet.click", IriSP.wrap(this, IriSP.MediaFragment.updateAnnotation)); |
|
9578 this._Popcorn.listen( "IriSP.SegmentsWidget.click", IriSP.wrap(this, IriSP.MediaFragment.updateAnnotation)); |
|
9579 }; |
|
9580 |
|
9581 IriSP.MediaFragment.advanceTime = function() { |
|
9582 var url = window.location.href; |
|
9583 |
|
9584 if ( url.split( "#" )[ 1 ] != null ) { |
|
9585 pageoffset = url.split( "#" )[1]; |
|
9586 |
|
9587 if ( pageoffset.substring(0, 2) === "t=") { |
|
9588 // timecode |
|
9589 if ( pageoffset.substring( 2 ) != null ) { |
|
9590 var offsettime = pageoffset.substring( 2 ); |
|
9591 this._Popcorn.currentTime( parseFloat( offsettime ) ); |
|
9592 } |
|
9593 } else if ( pageoffset.substring(0, 2) === "a=") { |
|
9594 // annotation |
|
9595 var annotationId = pageoffset.substring( 2 ); |
|
9596 |
|
9597 // there's no better way than that because |
|
9598 // of possible race conditions |
|
9599 this._serializer.sync(IriSP.wrap(this, function() { |
|
9600 IriSP.MediaFragment.lookupAnnotation.call(this, annotationId); |
|
9601 })); |
|
9602 } |
|
9603 } |
|
9604 }; |
|
9605 |
|
9606 IriSP.MediaFragment.updateTime = function() { |
|
9607 if (this.mutex === true) { |
|
9608 return; |
|
9609 } |
|
9610 |
|
9611 var history = window.history; |
|
9612 if ( !history.pushState ) { |
|
9613 return false; |
|
9614 } |
|
9615 |
|
9616 splitArr = window.location.href.split( "#" ) |
|
9617 history.replaceState( {}, "", splitArr[0] + "#t=" + this._Popcorn.currentTime().toFixed( 2 ) ); |
|
9618 }; |
|
9619 |
|
9620 |
|
9621 IriSP.MediaFragment.updateAnnotation = function(annotationId) { |
|
9622 var _this = this; |
|
9623 this.mutex = true; |
|
9624 |
|
9625 var history = window.history; |
|
9626 if ( !history.pushState ) { |
|
9627 return false; |
|
9628 } |
|
9629 |
|
9630 splitArr = window.location.href.split( "#" ) |
|
9631 history.replaceState( {}, "", splitArr[0] + "#a=" + annotationId); |
|
9632 |
|
9633 window.setTimeout(function() { _this.mutex = false }, 50); |
|
9634 }; |
|
9635 |
|
9636 // lookup and seek to the beginning of an annotation |
|
9637 IriSP.MediaFragment.lookupAnnotation = function(annotationId) { |
|
9638 var annotation = undefined; |
|
9639 var annotations = this._serializer._data.annotations; |
|
9640 |
|
9641 var i; |
|
9642 for (i = 0; i < annotations.length; i++) { |
|
9643 if (annotations[i].id === annotationId) { |
|
9644 annotation = annotations[i]; |
|
9645 break; |
|
9646 } |
|
9647 } |
|
9648 |
|
9649 if (typeof(annotation) !== "undefined") { |
|
9650 this._Popcorn.currentTime(annotation.begin / 1000); |
|
9651 } |
|
9652 }; |
|
9653 IriSP.AnnotationsWidget = function(Popcorn, config, Serializer) { |
|
9654 IriSP.Widget.call(this, Popcorn, config, Serializer); |
|
9655 |
|
9656 }; |
|
9657 |
|
9658 |
|
9659 IriSP.AnnotationsWidget.prototype = new IriSP.Widget(); |
|
9660 |
|
9661 IriSP.AnnotationsWidget.prototype.clear = function() { |
|
9662 this.selector.find(".Ldt-SaTitle").text(""); |
|
9663 this.selector.find(".Ldt-SaDescription").text(""); |
|
9664 this.selector.find(".Ldt-SaKeywordText").text(""); |
|
9665 }; |
|
9666 |
|
9667 IriSP.AnnotationsWidget.prototype.displayAnnotation = function(annotation) { |
|
9668 |
|
9669 var title = annotation.content.title; |
|
9670 var description = annotation.content.description; |
|
9671 var keywords = "" // FIXME; |
|
9672 var begin = +annotation.begin / 1000; |
|
9673 var end = +annotation.end / 1000; |
|
9674 var duration = +this._serializer.currentMedia().meta["dc:duration"]; |
|
9675 |
|
9676 var title_templ = "{{title}} - ( {{begin}} - {{end}} )"; |
|
9677 var endstr = Mustache.to_html(title_templ, {title: title, begin: IriSP.secondsToTime(begin), end: IriSP.secondsToTime(end)}); |
|
9678 |
|
9679 this.selector.find(".Ldt-SaTitle").text(endstr); |
|
9680 this.selector.find(".Ldt-SaDescription").text(description); |
|
9681 }; |
|
9682 |
|
9683 IriSP.AnnotationsWidget.prototype.clearWidget = function() { |
|
9684 |
|
9685 |
|
9686 /* retract the pane between two annotations */ |
|
9687 this.selector.find(".Ldt-SaTitle").text(""); |
|
9688 this.selector.find(".Ldt-SaDescription").text(""); |
|
9689 this.selector.find(".Ldt-SaKeywordText").html(""); |
|
9690 this.selector.find(".Ldt-ShowAnnotation").slideUp(); |
|
9691 }; |
|
9692 |
|
9693 IriSP.AnnotationsWidget.prototype.draw = function() { |
|
9694 var _this = this; |
|
9695 |
|
9696 var annotationMarkup = IriSP.templToHTML(IriSP.annotationWidget_template); |
|
9697 this.selector.append(annotationMarkup); |
|
9698 var view; |
|
9699 |
|
9700 if (typeof(this._serializer._data.views) !== "undefined" && this._serializer._data.views !== null) |
|
9701 view = this._serializer._data.views[0]; |
|
9702 |
|
9703 var view_type = ""; |
|
9704 |
|
9705 if(typeof(view) !== "undefined" && typeof(view.annotation_types) !== "undefined" && view.annotation_types.length > 1) { |
|
9706 view_type = view.annotation_types[0]; |
|
9707 } |
|
9708 |
|
9709 var annotations = this._serializer._data.annotations; |
|
9710 var i; |
|
9711 |
|
9712 for (i in annotations) { |
|
9713 var annotation = annotations[i]; |
|
9714 var begin = Math.round((+ annotation.begin) / 1000); |
|
9715 var end = Math.round((+ annotation.end) / 1000); |
|
9716 |
|
9717 if (view_type != "" && typeof(annotation.meta) !== "undefined" && typeof(annotation.meta["id-ref"]) !== "undefined" |
|
9718 && annotation.meta["id-ref"] != view_type) { |
|
9719 continue; |
|
9720 } |
|
9721 |
|
9722 |
|
9723 var conf = {start: begin, end: end, |
|
9724 onStart: |
|
9725 function(annotation) { |
|
9726 return function() { |
|
9727 _this.displayAnnotation(annotation); |
|
9728 |
|
9729 } }(annotation), |
|
9730 onEnd: |
|
9731 function() { _this.clearWidget.call(_this); }, |
|
9732 }; |
|
9733 this._Popcorn = this._Popcorn.code(conf); |
|
9734 } |
|
9735 |
|
9736 }; |
|
9737 IriSP.ArrowWidget = function(Popcorn, config, Serializer) { |
|
9738 IriSP.Widget.call(this, Popcorn, config, Serializer); |
|
9739 |
|
9740 this._oldAnnotation = null; |
|
9741 |
|
9742 }; |
|
9743 |
|
9744 |
|
9745 IriSP.ArrowWidget.prototype = new IriSP.Widget(); |
|
9746 |
|
9747 IriSP.ArrowWidget.prototype.clear = function() { |
|
9748 |
|
9749 }; |
|
9750 |
|
9751 IriSP.ArrowWidget.prototype.clearWidget = function() { |
|
9752 }; |
|
9753 |
|
9754 IriSP.ArrowWidget.prototype.draw = function() { |
|
9755 var templ = Mustache.to_html(IriSP.arrowWidget_template, {}); |
|
9756 this.selector.append(templ); |
|
9757 this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.timeUpdateHandler)); |
|
9758 }; |
|
9759 |
|
9760 IriSP.ArrowWidget.prototype.timeUpdateHandler = function(percents) { |
|
9761 var currentTime = this._Popcorn.currentTime(); |
|
9762 var currentAnnotation = this._serializer.currentAnnotations(currentTime)[0]; // FIXME : use the others ? |
|
9763 |
|
9764 /* move the arrow only if the current annotation changes */ |
|
9765 if (currentAnnotation != this._oldAnnotation) { |
|
9766 var begin = (+ currentAnnotation.begin) / 1000; |
|
9767 var end = (+ currentAnnotation.end) / 1000; |
|
9768 |
|
9769 var duration = +this._serializer.currentMedia().meta["dc:duration"] / 1000; |
|
9770 var middle_time = (begin + end) / 2; |
|
9771 var percents = Math.floor((middle_time / duration) * 100); |
|
9772 |
|
9773 // we need to apply a fix because the arrow has a certain length |
|
9774 // it's half the length of the arrow (27 / 2). We need to convert |
|
9775 // it in percents though. |
|
9776 var totalWidth = this.selector.width(); |
|
9777 var correction = ((27 / 2) / totalWidth) * 100; |
|
9778 var corrected_percents = percents - correction; |
|
9779 |
|
9780 /* don't move out of the screen */ |
|
9781 if (corrected_percents <= 0) |
|
9782 corrected_percents = 0; |
|
9783 |
|
9784 this.selector.children(".Ldt-arrowWidget").animate({"left" : corrected_percents + "%"}); |
|
9785 |
|
9786 this._oldAnnotation = currentAnnotation; |
|
9787 } |
|
9788 } |
|
9789 IriSP.PlayerWidget = function(Popcorn, config, Serializer) { |
|
9790 IriSP.Widget.call(this, Popcorn, config, Serializer); |
|
9791 |
|
9792 this._searchBlockOpen = false; |
|
9793 this._searchLastValue = ""; |
|
9794 }; |
|
9795 |
|
9796 IriSP.PlayerWidget.prototype = new IriSP.Widget(); |
|
9797 |
|
9798 IriSP.PlayerWidget.prototype.draw = function() { |
|
9799 var self = this; |
|
9800 var width = this.width; |
|
9801 var height = this.height; |
|
9802 var heightS = this.height-20; |
|
9803 |
|
9804 var Player_templ = Mustache.to_html(IriSP.player_template, {"share_template" : IriSP.share_template}); |
|
9805 this.selector.append(Player_templ); |
|
9806 |
|
9807 this.selector.children(".Ldt-controler").show(); |
|
9808 |
|
9809 // handle clicks by the user on the video. |
|
9810 this._Popcorn.listen("play", IriSP.wrap(this, this.playButtonUpdater)); |
|
9811 this._Popcorn.listen("pause", IriSP.wrap(this, this.playButtonUpdater)); |
|
9812 |
|
9813 this._Popcorn.listen("volumechange", IriSP.wrap(this, this.muteButtonUpdater)); |
|
9814 |
|
9815 this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.timeDisplayUpdater)); |
|
9816 this._Popcorn.listen("IriSP.search.matchFound", IriSP.wrap(this, this.searchMatch)); |
|
9817 this._Popcorn.listen("IriSP.search.noMatchFound", IriSP.wrap(this, this.searchNoMatch)); |
|
9818 |
|
9819 |
|
9820 this.selector.find(".Ldt-CtrlPlay").click(function() { self.playHandler.call(self); }); |
|
9821 this.selector.find(".Ldt-CtrlNext").click(function() { }); |
|
9822 this.selector.find(".Ldt-CtrlSearch").click(function() { self.searchButtonHandler.call(self); }); |
|
9823 |
|
9824 this.selector.find('.Ldt-CtrlSound').click(function() { self.muteHandler.call(self); } ); |
|
9825 |
|
9826 this.selector.find(".Ldt-CtrlPlay").attr( "style", "background-color:#CD21C24;" ); |
|
9827 |
|
9828 var searchButtonPos = this.selector.find(".Ldt-CtrlSearch").position(); |
|
9829 var searchBox = Mustache.to_html(IriSP.search_template, {margin_left : searchButtonPos.left + "px"}); |
|
9830 this.selector.append(searchBox); |
|
9831 |
|
9832 // trigger an IriSP.PlayerWidget.MouseOver to the widgets that are interested (i.e : sliderWidget) |
|
9833 this.selector.hover(function() { self._Popcorn.trigger("IriSP.PlayerWidget.MouseOver"); }, |
|
9834 function() { self._Popcorn.trigger("IriSP.PlayerWidget.MouseOut"); }); |
|
9835 |
|
9836 this.muteButtonUpdater(); /* some player - jwplayer notable - save the state of the mute button between sessions */ |
|
9837 }; |
|
9838 |
|
9839 /* Update the elasped time div */ |
|
9840 IriSP.PlayerWidget.prototype.timeDisplayUpdater = function() { |
|
9841 |
|
9842 if (this._previousSecond === undefined) |
|
9843 this._previousSecond = this._Popcorn.roundTime(); |
|
9844 |
|
9845 else { |
|
9846 /* we're still in the same second, so it's not necessary to update time */ |
|
9847 if (this._Popcorn.roundTime() == this._previousSecond) |
|
9848 return; |
|
9849 |
|
9850 } |
|
9851 |
|
9852 // we get it at each call because it may change. |
|
9853 var duration = +this._serializer.currentMedia().meta["dc:duration"] / 1000; |
|
9854 var totalTime = IriSP.secondsToTime(duration); |
|
9855 var elapsedTime = IriSP.secondsToTime(this._Popcorn.currentTime()); |
|
9856 |
|
9857 this.selector.find(".Ldt-ElapsedTime").html(elapsedTime.toString()); |
|
9858 this.selector.find(".Ldt-TotalTime").html(totalTime.toString()); |
|
9859 this._previousSecond = this._Popcorn.roundTime(); |
|
9860 }; |
|
9861 |
|
9862 /* update the icon of the button - separate function from playHandler |
|
9863 because in some cases (for instance, when the user directly clicks on |
|
9864 the jwplayer window) we have to change the icon without playing/pausing |
|
9865 */ |
|
9866 IriSP.PlayerWidget.prototype.playButtonUpdater = function() { |
|
9867 var status = this._Popcorn.media.paused; |
|
9868 |
|
9869 if ( status == true ){ |
|
9870 this.selector.find(".Ldt-CtrlPlay").attr("title", "Play"); |
|
9871 |
|
9872 // we use templToHTML because it has some predefined |
|
9873 // vars like where to get the images |
|
9874 var templ = IriSP.templToHTML("url({{img_dir}}/play_sprite.png)"); |
|
9875 this.selector.find(".Ldt-CtrlPlay").css("background-image", templ); |
|
9876 |
|
9877 } else { |
|
9878 this.selector.find(".Ldt-CtrlPlay").attr("title", "Pause"); |
|
9879 |
|
9880 // we use templToHTML because it has some predefined |
|
9881 // vars like where to get the images |
|
9882 var templ = IriSP.templToHTML("url({{img_dir}}/pause_sprite.png)"); |
|
9883 this.selector.find(".Ldt-CtrlPlay").css("background-image", templ); |
|
9884 } |
|
9885 |
|
9886 return; |
|
9887 }; |
|
9888 |
|
9889 |
|
9890 IriSP.PlayerWidget.prototype.playHandler = function() { |
|
9891 var status = this._Popcorn.media.paused; |
|
9892 |
|
9893 if ( status == true ){ |
|
9894 this._Popcorn.play(); |
|
9895 } else { |
|
9896 this._Popcorn.pause(); |
|
9897 } |
|
9898 }; |
|
9899 |
|
9900 IriSP.PlayerWidget.prototype.muteHandler = function() { |
|
9901 if (!this._Popcorn.muted()) { |
|
9902 this._Popcorn.mute(true); |
|
9903 } else { |
|
9904 this._Popcorn.mute(false); |
|
9905 } |
|
9906 }; |
|
9907 |
|
9908 IriSP.PlayerWidget.prototype.muteButtonUpdater = function() { |
|
9909 var status = this._Popcorn.media.muted; |
|
9910 |
|
9911 if ( status == true ){ |
|
9912 this.selector.find(".Ldt-CtrlSound").attr("title", "Unmute"); |
|
9913 |
|
9914 // we use templToHTML because it has some predefined |
|
9915 // vars like where to get the images |
|
9916 var templ = IriSP.templToHTML("url({{img_dir}}/sound_sprite.png)"); |
|
9917 this.selector.find(".Ldt-CtrlSound").css("background-image", templ); |
|
9918 |
|
9919 } else { |
|
9920 this.selector.find(".Ldt-CtrlSound").attr("title", "Mute"); |
|
9921 |
|
9922 // we use templToHTML because it has some predefined |
|
9923 // vars like where to get the images |
|
9924 var templ = IriSP.templToHTML("url({{img_dir}}/mute_sprite.png)"); |
|
9925 this.selector.find(".Ldt-CtrlSound").css("background-image", templ); |
|
9926 } |
|
9927 |
|
9928 return; |
|
9929 }; |
|
9930 |
|
9931 |
|
9932 IriSP.PlayerWidget.prototype.searchButtonHandler = function() { |
|
9933 var self = this; |
|
9934 |
|
9935 /* show the search field if it is not shown */ |
|
9936 if ( this._searchBlockOpen == false ) { |
|
9937 this.selector.find(".LdtSearch").show(100); |
|
9938 |
|
9939 this.selector.find(".LdtSearchInput").css('background-color','#fff'); |
|
9940 this.selector.find(".LdtSearchInput").focus(); |
|
9941 this.selector.find(".LdtSearchInput").attr('value', this._searchLastValue); |
|
9942 this._Popcorn.trigger("IriSP.search", this._searchLastValue); // trigger the search to make it more natural. |
|
9943 |
|
9944 this._searchBlockOpen = true; |
|
9945 this.selector.find(".LdtSearchInput").bind('keyup', null, function() { self.searchHandler.call(self); } ); |
|
9946 |
|
9947 // we need this variable because some widget can find a match in |
|
9948 // their data while at the same time other's don't. As we want the |
|
9949 // search field to become green when there's a match, we need a |
|
9950 // variable to remember that we had one. |
|
9951 this._positiveMatch = false; |
|
9952 |
|
9953 // tell the world the field is open |
|
9954 this._Popcorn.trigger("IriSP.search.open"); |
|
9955 |
|
9956 } else { |
|
9957 this._searchLastValue = this.selector.find(".LdtSearchInput").attr('value'); |
|
9958 this.selector.find(".LdtSearchInput").attr('value',''); |
|
9959 this.selector.find(".LdtSearch").hide(100); |
|
9960 |
|
9961 // unbind the watcher event. |
|
9962 this.selector.find(".LdtSearchInput").unbind('keypress set'); |
|
9963 this._searchBlockOpen = false; |
|
9964 |
|
9965 this._positiveMatch = false; |
|
9966 |
|
9967 this._Popcorn.trigger("IriSP.search.closed"); |
|
9968 } |
|
9969 }; |
|
9970 |
|
9971 /* this handler is called whenever the content of the search |
|
9972 field changes */ |
|
9973 IriSP.PlayerWidget.prototype.searchHandler = function() { |
|
9974 this._searchLastValue = this.selector.find(".LdtSearchInput").attr('value'); |
|
9975 this._positiveMatch = false; |
|
9976 |
|
9977 // do nothing if the search field is empty, instead of highlighting everything. |
|
9978 if (this._searchLastValue == "") { |
|
9979 this._Popcorn.trigger("IriSP.search.cleared"); |
|
9980 this.selector.find(".LdtSearchInput").css('background-color',''); |
|
9981 } else { |
|
9982 this._Popcorn.trigger("IriSP.search", this._searchLastValue); |
|
9983 } |
|
9984 }; |
|
9985 |
|
9986 /* |
|
9987 handler for the IriSP.search.found message, which is sent by some views when they |
|
9988 highlight a match. |
|
9989 */ |
|
9990 IriSP.PlayerWidget.prototype.searchMatch = function() { |
|
9991 this._positiveMatch = true; |
|
9992 this.selector.find(".LdtSearchInput").css('background-color','#e1ffe1'); |
|
9993 } |
|
9994 |
|
9995 /* the same, except that no value could be found */ |
|
9996 IriSP.PlayerWidget.prototype.searchNoMatch = function() { |
|
9997 if (this._positiveMatch !== true) |
|
9998 this.selector.find(".LdtSearchInput").css('background-color', "#d62e3a"); |
|
9999 } |
|
10000 |
|
10001 /* |
|
10002 * |
|
10003 * Copyright 2010 Institut de recherche et d'innovation |
|
10004 * contributor(s) : Samuel Huron |
|
10005 * |
|
10006 * contact@iri.centrepompidou.fr |
|
10007 * http://www.iri.centrepompidou.fr |
|
10008 * |
|
10009 * This software is a computer program whose purpose is to show and add annotations on a video . |
|
10010 * This software is governed by the CeCILL-C license under French law and |
|
10011 * abiding by the rules of distribution of free software. You can use, |
|
10012 * modify and/ or redistribute the software under the terms of the CeCILL-C |
|
10013 * license as circulated by CEA, CNRS and INRIA at the following URL |
|
10014 * "http://www.cecill.info". |
|
10015 * |
|
10016 * The fact that you are presently reading this means that you have had |
|
10017 * knowledge of the CeCILL-C license and that you accept its terms. |
|
10018 */ |
|
10019 // CHART TIMELINE / VERSION PROTOTYPE :: |
|
10020 |
|
10021 IriSP.PolemicWidget = function(Popcorn, config, Serializer) { |
|
10022 IriSP.Widget.call(this, Popcorn, config, Serializer); |
|
10023 |
|
10024 this.userPol = new Array(); |
|
10025 this.userNoPol = new Array(); |
|
10026 this.userst = new Array(); |
|
10027 this.numberOfTweet = 0; |
|
10028 this.Users; |
|
10029 this.TweetPolemic; |
|
10030 this.yMax = this.height; |
|
10031 this.PaperSlider; |
|
10032 this.heightOfChart; |
|
10033 this.tweets = new Array(); |
|
10034 this.svgElements = {}; |
|
10035 |
|
10036 // Make and define the Raphael area |
|
10037 this.paper = Raphael(document.getElementById(this._id), config.width, config.height); |
|
10038 |
|
10039 this.oldSearchMatches = []; |
|
10040 |
|
10041 // event handlers |
|
10042 this._Popcorn.listen("IriSP.search", IriSP.wrap(this, function(searchString) { this.searchHandler(searchString); })); |
|
10043 this._Popcorn.listen("IriSP.search.closed", IriSP.wrap(this, this.searchFieldClosedHandler)); |
|
10044 this._Popcorn.listen("IriSP.search.cleared", IriSP.wrap(this, this.searchFieldClearedHandler)); |
|
10045 |
|
10046 }; |
|
10047 |
|
10048 IriSP.PolemicWidget.prototype = new IriSP.Widget(); |
|
10049 |
|
10050 IriSP.PolemicWidget.prototype.draw = function() { |
|
10051 |
|
10052 // variable |
|
10053 // yMax |
|
10054 |
|
10055 var self = this; |
|
10056 var yCoef = 2; // coef for height of 1 tweet |
|
10057 var frameSize = 5; // frame size |
|
10058 var margin = 1; // marge between frame |
|
10059 var lineSize = this.width; // timeline pixel width |
|
10060 var nbrframes = lineSize/frameSize; // frame numbers |
|
10061 var numberOfTweet = 0; // number of tweet overide later |
|
10062 var duration = +this._serializer.currentMedia().meta["dc:duration"]; // timescale width |
|
10063 var frameLength = lineSize / frameSize; // frame timescale |
|
10064 var timeline; |
|
10065 var colors = new Array("","#1D973D","#C5A62D","#CE0A15","#036AAE","#585858"); |
|
10066 |
|
10067 // array |
|
10068 //var tweets = new Array(); |
|
10069 var element = new Array(); |
|
10070 var cluster = new Array(); |
|
10071 var frames = new Array(frameLength); |
|
10072 var slices = new Array(); |
|
10073 |
|
10074 |
|
10075 // Classes ======================================================================= |
|
10076 var Frames = function(){ |
|
10077 |
|
10078 var Myclusters; |
|
10079 var x; |
|
10080 var y; |
|
10081 var width; |
|
10082 var height; |
|
10083 }; |
|
10084 Frames = function(json){ |
|
10085 // make my clusters |
|
10086 // ou Frame vide |
|
10087 }; |
|
10088 Frames.prototype.draw = function(){ |
|
10089 }; |
|
10090 Frames.prototype.zoom = function(){ |
|
10091 }; |
|
10092 Frames.prototype.inside = function(){ |
|
10093 }; |
|
10094 var Clusters = function(){ |
|
10095 var Object; |
|
10096 var yDist; |
|
10097 var x; |
|
10098 var y; |
|
10099 var width; |
|
10100 var height; |
|
10101 }; |
|
10102 Clusters = function(json){ |
|
10103 // make my object |
|
10104 }; |
|
10105 var Tweet = function(){ |
|
10106 }; |
|
10107 // Classes ======================================================================= |
|
10108 |
|
10109 // Refactoring (parametere) ************************************************************ |
|
10110 // color translastion |
|
10111 var qTweet_0 =0; |
|
10112 var qTweet_Q =0; |
|
10113 var qTweet_REF=0; |
|
10114 var qTweet_OK =0; |
|
10115 var qTweet_KO =0; |
|
10116 function colorTranslation(value){ |
|
10117 if(value == "Q"){ |
|
10118 qTweet_Q+=1; |
|
10119 return 2; |
|
10120 }else if(value =="REF"){ |
|
10121 qTweet_REF+=1; |
|
10122 return 4; |
|
10123 }else if(value =="OK"){ |
|
10124 qTweet_OK+=1; |
|
10125 return 1; |
|
10126 }else if(value =="KO"){ |
|
10127 qTweet_KO+=1; |
|
10128 return 3; |
|
10129 }else if(value ==""){ |
|
10130 qTweet_0+=1; |
|
10131 return 5; |
|
10132 } |
|
10133 } |
|
10134 |
|
10135 |
|
10136 this._serializer.sync(function(data) { loaded_callback.call(self, data) }); |
|
10137 |
|
10138 function loaded_callback (json) { |
|
10139 |
|
10140 // get current view (the first ???) |
|
10141 view = json.views[0]; |
|
10142 |
|
10143 // the tweets are by definition of the second annotation type FIXME ? |
|
10144 tweet_annot_type = null; |
|
10145 if(typeof(view.annotation_types) !== "undefined" && view.annotation_types.length > 1) { |
|
10146 tweet_annot_type = view.annotation_types[1]; |
|
10147 } |
|
10148 |
|
10149 for(var i = 0; i < json.annotations.length; i++) { |
|
10150 var item = json.annotations[i]; |
|
10151 var MyTime = Math.floor(item.begin/duration*lineSize); |
|
10152 var Myframe = Math.floor(MyTime/lineSize*frameLength); |
|
10153 |
|
10154 if (typeof(item.meta) !== "undefined" |
|
10155 && typeof(item.meta["id-ref"]) !== "undefined" |
|
10156 && item.meta["id-ref"] === tweet_annot_type) { |
|
10157 |
|
10158 var MyTJson = JSON.parse(item.meta['dc:source']['content']); |
|
10159 |
|
10160 if (item.content['polemics'] != undefined |
|
10161 && item.content['polemics'][0] != null) { |
|
10162 |
|
10163 // a tweet can have many polemics at the same time. |
|
10164 for(var j=0; j<item.content['polemics'].length; j++){ |
|
10165 |
|
10166 this.tweets[numberOfTweet] = { |
|
10167 id:i, |
|
10168 qualification:colorTranslation(item.content['polemics'][j]), |
|
10169 yIndicator:MyTime, |
|
10170 yframe:Myframe, |
|
10171 title:item.content['title'], |
|
10172 timeframe:item.begin, |
|
10173 userId: MyTJson.id, |
|
10174 userScreenName: MyTJson.screen_name, |
|
10175 tsource:MyTJson, |
|
10176 cinecast_id: item.id |
|
10177 }; |
|
10178 numberOfTweet+=1; |
|
10179 |
|
10180 } |
|
10181 } |
|
10182 else { |
|
10183 this.tweets[numberOfTweet] = { |
|
10184 id:i, |
|
10185 qualification:colorTranslation(""), |
|
10186 yIndicator:MyTime, |
|
10187 yframe:Myframe, |
|
10188 title:item.content['title'], |
|
10189 timeframe:item.begin, |
|
10190 userId: MyTJson.id, |
|
10191 userScreenName: MyTJson.screen_name, |
|
10192 tsource:MyTJson, |
|
10193 cinecast_id: item.id |
|
10194 }; |
|
10195 numberOfTweet+=1; |
|
10196 } |
|
10197 |
|
10198 } |
|
10199 }; |
|
10200 |
|
10201 DrawTweets.call (this); // FIXME: ugly. |
|
10202 |
|
10203 }; |
|
10204 |
|
10205 // tweet Drawing (in raphael) |
|
10206 function DrawTweets (){ |
|
10207 // GROUPES TWEET ============================================ |
|
10208 // Count nbr of cluster and tweet in a frame an save int in "frames" |
|
10209 numberOfTweet = this.tweets.length; |
|
10210 for(var i=0; i<nbrframes; i++) { |
|
10211 for(var j=0; j<numberOfTweet; j++) { |
|
10212 |
|
10213 if (i==this.tweets[j].yframe){ |
|
10214 |
|
10215 var k = this.tweets[j].qualification; |
|
10216 |
|
10217 // make array for frame cluster |
|
10218 if(frames[i]==undefined){ |
|
10219 frames[i] = {id:i, |
|
10220 qualifVol:new Array(), |
|
10221 mytweetsID:new Array() |
|
10222 }; |
|
10223 } |
|
10224 // add my tweet to frame |
|
10225 frames[i].mytweetsID.push(this.tweets[j]); |
|
10226 |
|
10227 // count opinion by frame |
|
10228 if( frames[i].qualifVol[k] == undefined){ |
|
10229 frames[i].qualifVol[k] = 1; |
|
10230 }else{ |
|
10231 frames[i].qualifVol[k] += 1; |
|
10232 } |
|
10233 |
|
10234 } |
|
10235 } |
|
10236 } |
|
10237 |
|
10238 // GROUPES TWEET ============================================ |
|
10239 // max of tweet by Frame |
|
10240 var max = 0; |
|
10241 for(var i = 0; i < nbrframes; i++) { |
|
10242 var moy = 0; |
|
10243 for (var j = 0; j < 6; j++) { |
|
10244 if (frames[i] != undefined) { |
|
10245 if (frames[i].qualifVol[j] != undefined) { |
|
10246 moy += frames[i].qualifVol[j]; |
|
10247 } |
|
10248 } |
|
10249 } |
|
10250 |
|
10251 if (moy > max) { |
|
10252 max = moy; |
|
10253 } |
|
10254 } |
|
10255 |
|
10256 var tweetDrawed = new Array(); |
|
10257 var TweetHeight = 5; |
|
10258 |
|
10259 // DRAW TWEETS ============================================ |
|
10260 for(var i = 0; i < nbrframes; i++) { |
|
10261 var addEheight = 5; |
|
10262 if (frames[i] != undefined){ |
|
10263 // by type |
|
10264 |
|
10265 for (var j = 6; j > -1; j--) { |
|
10266 if (frames[i].qualifVol[j] != undefined) { |
|
10267 // show tweet by type |
|
10268 for (var k = 0; k < frames[i].mytweetsID.length; k++) { |
|
10269 |
|
10270 if (frames[i].mytweetsID[k].qualification == j) { |
|
10271 var x = i * frameSize; |
|
10272 var y = this.heightmax - addEheight; |
|
10273 |
|
10274 if (this.yMax > y) { |
|
10275 this.yMax = y; |
|
10276 } |
|
10277 |
|
10278 var e = this.paper.rect(x, y, frameSize - margin, TweetHeight /* height */) |
|
10279 .attr({stroke:"#00","stroke-width":0.1, fill: colors[j]}); |
|
10280 |
|
10281 addEheight += TweetHeight; |
|
10282 |
|
10283 e.color = colors[j]; |
|
10284 e.time = frames[i].mytweetsID[k].timeframe; |
|
10285 e.title = frames[i].mytweetsID[k].title; |
|
10286 e.id = frames[i].mytweetsID[k].cinecast_id; |
|
10287 |
|
10288 this.svgElements[e.id] = e; |
|
10289 |
|
10290 e.mouseover(function(element) { return function (event) { |
|
10291 // event.clientX and event.clientY are to raphael what event.pageX and pageY are to jquery. |
|
10292 self.TooltipWidget.show.call(self.TooltipWidget, element.title, element.attr("fill"), event.clientX - 106, event.clientY - 160); |
|
10293 element.displayed = true; |
|
10294 }}(e)).mouseout(function(element) { return function () { |
|
10295 self.TooltipWidget.hide.call(self.TooltipWidget); |
|
10296 }}(e)).mousedown(function () { |
|
10297 self._Popcorn.currentTime(this.time/1000); |
|
10298 self._Popcorn.trigger("IriSP.PolemicTweet.click", this.id); |
|
10299 }); |
|
10300 |
|
10301 IriSP.jQuery(e.node).attr('id', 't' + k + ''); |
|
10302 IriSP.jQuery(e.node).attr('title', frames[i].mytweetsID[k].title); |
|
10303 IriSP.jQuery(e.node).attr('begin', frames[i].mytweetsID[k].timeframe); |
|
10304 } |
|
10305 } |
|
10306 } |
|
10307 } |
|
10308 } |
|
10309 |
|
10310 } |
|
10311 // DRAW UI :: resize border and bgd |
|
10312 this.paperBackground = this.paper.rect(0, 0, this.width, this.heightmax).attr({fill:"#F8F8F8","stroke-width":0.1,opacity: 1}); |
|
10313 |
|
10314 // outer borders |
|
10315 this.outerBorders = []; |
|
10316 this.outerBorders.push(this.paper.rect(0, this.height - 1, this.width, 1).attr({fill:"#ababab",stroke: "none",opacity: 1})); |
|
10317 this.outerBorders.push(this.paper.rect(0, 0, this.width, 1).attr({fill:"#ababab",stroke: "none",opacity: 1})); |
|
10318 |
|
10319 // inner borders |
|
10320 this.innerBorders = []; |
|
10321 this.innerBorders.push(this.paper.rect(1, this.height - 2, this.width, 1).attr({fill:"#efefef",stroke: "none",opacity: 1})); |
|
10322 this.innerBorders.push(this.paper.rect(1, 1, this.width, 1).attr({fill:"#efefef",stroke: "none",opacity: 1})); |
|
10323 this.innerBorders.push(this.paper.rect(1, 1, 1, this.height - 2).attr({fill:"#d0d1d1",stroke: "none",opacity: 0.8})); |
|
10324 this.innerBorders.push(this.paper.rect(this.width - 2, 1, 1, this.height - 2).attr({fill:"#efefef",stroke: "none",opacity: 1})); |
|
10325 |
|
10326 |
|
10327 |
|
10328 this.paperSlider = this.paper.rect(0, 0, 0, this.heightmax).attr({fill:"#D4D5D5", stroke: "none", opacity: 1}); |
|
10329 |
|
10330 // the small white line displayed over the slider. |
|
10331 this.sliderTip = this.paper.rect(0, 0, 1, this.heightmax).attr({fill:"#fc00ff", stroke: "none", opacity: 1}); |
|
10332 // decalage |
|
10333 // tweetSelection = this.paper.rect(-100,-100,5,5).attr({fill:"#fff",stroke: "none",opacity: 1}); |
|
10334 |
|
10335 |
|
10336 this.paperSlider.toBack(); |
|
10337 this.paperBackground.toBack(); |
|
10338 this.sliderTip.toFront(); |
|
10339 } |
|
10340 |
|
10341 this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.sliderUpdater)); |
|
10342 } |
|
10343 |
|
10344 IriSP.PolemicWidget.prototype.sliderUpdater = function() { |
|
10345 |
|
10346 var time = +this._Popcorn.currentTime(); |
|
10347 var duration = +this._serializer.currentMedia().meta["dc:duration"]; |
|
10348 |
|
10349 this.paperSlider.attr("width", time * (this.width / (duration / 1000))); |
|
10350 |
|
10351 this.sliderTip.attr("x", time * (this.width / (duration / 1000))); |
|
10352 }; |
|
10353 |
|
10354 IriSP.PolemicWidget.prototype.searchHandler = function(searchString) { |
|
10355 if (searchString == "") |
|
10356 return; |
|
10357 |
|
10358 var matches = this._serializer.searchTweetsOccurences(searchString); |
|
10359 |
|
10360 if (IriSP.countProperties(matches) > 0) { |
|
10361 this._Popcorn.trigger("IriSP.search.matchFound"); |
|
10362 } else { |
|
10363 this._Popcorn.trigger("IriSP.search.noMatchFound"); |
|
10364 } |
|
10365 |
|
10366 for (var id in matches) { |
|
10367 if (this.svgElements.hasOwnProperty(id)) { |
|
10368 var e = this.svgElements[id]; |
|
10369 this.svgElements[id].attr({fill: "#fc00ff"}); |
|
10370 } |
|
10371 } |
|
10372 |
|
10373 // clean up the blocks that were in the previous search |
|
10374 // but who aren't in the current one. |
|
10375 for (var id in this.oldSearchMatches) { |
|
10376 if (!matches.hasOwnProperty(id)) { |
|
10377 var e = this.svgElements[id]; |
|
10378 e.attr({fill: e.color}); |
|
10379 } |
|
10380 } |
|
10381 |
|
10382 this.oldSearchMatches = matches; |
|
10383 }; |
|
10384 |
|
10385 IriSP.PolemicWidget.prototype.searchFieldClearedHandler = function() { |
|
10386 // clean up the blocks that were in the previous search |
|
10387 // but who aren't in the current one. |
|
10388 for (var id in this.oldSearchMatches) { |
|
10389 var e = this.svgElements[id]; |
|
10390 e.attr({fill: e.color}); |
|
10391 } |
|
10392 |
|
10393 }; |
|
10394 |
|
10395 IriSP.PolemicWidget.prototype.searchFieldClosedHandler = function() { |
|
10396 // clean up the blocks that were in the previous search |
|
10397 // but who aren't in the current one. |
|
10398 for (var id in this.oldSearchMatches) { |
|
10399 var e = this.svgElements[id]; |
|
10400 e.attr({fill: e.color}); |
|
10401 } |
|
10402 |
|
10403 }; |
|
10404 |
|
10405 IriSP.SegmentsWidget = function(Popcorn, config, Serializer) { |
|
10406 |
|
10407 var self = this; |
|
10408 IriSP.Widget.call(this, Popcorn, config, Serializer); |
|
10409 this.oldSearchMatches = []; |
|
10410 |
|
10411 // event handlers |
|
10412 this._Popcorn.listen("IriSP.search", function(searchString) { self.searchHandler.call(self, searchString); }); |
|
10413 this._Popcorn.listen("IriSP.search.closed", function() { self.searchFieldClosedHandler.call(self); }); |
|
10414 this._Popcorn.listen("IriSP.search.cleared", function() { self.searchFieldClearedHandler.call(self); }); |
|
10415 }; |
|
10416 |
|
10417 IriSP.SegmentsWidget.prototype = new IriSP.Widget(); |
|
10418 |
|
10419 IriSP.SegmentsWidget.prototype.draw = function() { |
|
10420 |
|
10421 var self = this; |
|
10422 var annotations = this._serializer._data.annotations; |
|
10423 |
|
10424 this.selector.addClass("Ldt-SegmentsWidget"); |
|
10425 |
|
10426 /* in case we have different types of annotations, we want to display only the first type */ |
|
10427 /* the next two lines are a bit verbose because for some test data, _serializer.data.view is either |
|
10428 null or undefined. |
|
10429 */ |
|
10430 var view; |
|
10431 |
|
10432 if (typeof(this._serializer._data.views) !== "undefined" && this._serializer._data.views !== null) |
|
10433 view = this._serializer._data.views[0]; |
|
10434 |
|
10435 var view_type = ""; |
|
10436 |
|
10437 if(typeof(view) !== "undefined" && typeof(view.annotation_types) !== "undefined" && view.annotation_types.length > 1) { |
|
10438 view_type = view.annotation_types[0]; |
|
10439 } |
|
10440 |
|
10441 this.selector.append(Mustache.to_html(IriSP.overlay_marker_template)); |
|
10442 |
|
10443 this.positionMarker = this.selector.children(":first"); |
|
10444 |
|
10445 this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.positionUpdater)); |
|
10446 |
|
10447 |
|
10448 var i = 0; |
|
10449 var totalWidth = this.selector.width(); |
|
10450 var onePxPercent = 100 / totalWidth; /* the value of a pixel, in percents */ |
|
10451 |
|
10452 for (i = 0; i < annotations.length; i++) { |
|
10453 var annotation = annotations[i]; |
|
10454 |
|
10455 /* filter the annotations whose type is not the one we want */ |
|
10456 if (view_type != "" && typeof(annotation.meta) !== "undefined" && typeof(annotation.meta["id-ref"]) !== "undefined" |
|
10457 && annotation.meta["id-ref"] != view_type) { |
|
10458 continue; |
|
10459 } |
|
10460 |
|
10461 var begin = Math.round((+ annotation.begin) / 1000); |
|
10462 var end = Math.round((+ annotation.end) / 1000); |
|
10463 var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000; |
|
10464 var id = annotation.id; |
|
10465 var startPourcent = IriSP.timeToPourcent(begin, duration); |
|
10466 |
|
10467 /* some sort of collapsing occurs, so we only have to substract one pixel to each box instead of |
|
10468 two |
|
10469 */ |
|
10470 var endPourcent = IriSP.timeToPourcent(end, duration) - startPourcent - onePxPercent * 1; |
|
10471 |
|
10472 /* on the other hand, we have to substract one pixel from the first box because it's the only |
|
10473 one to have to effective 1px margins */ |
|
10474 if (i == 0) { |
|
10475 |
|
10476 endPourcent -= onePxPercent; |
|
10477 } |
|
10478 |
|
10479 var divTitle = annotation.content.title.substr(0,55); |
|
10480 var color = annotation.content.color |
|
10481 |
|
10482 |
|
10483 var annotationTemplate = Mustache.to_html(IriSP.annotation_template, |
|
10484 {"divTitle" : divTitle, "id" : id, "startPourcent" : startPourcent, |
|
10485 "endPourcent" : endPourcent, "hexa_color" : IriSP.DEC_HEXA_COLOR(color), |
|
10486 "seekPlace" : Math.round(begin/1000)}); |
|
10487 |
|
10488 |
|
10489 this.selector.append(annotationTemplate); |
|
10490 |
|
10491 // IriSP.jQuery("#" + id).tooltip({ effect: 'slide'}); |
|
10492 |
|
10493 IriSP.jQuery("#" + id).fadeTo(0, 0.3); |
|
10494 |
|
10495 IriSP.jQuery("#" + id).mouseover( |
|
10496 /* we wrap the handler in another function because js's scoping |
|
10497 rules are function-based - otherwise, the internal vars like |
|
10498 divTitle are preserved but they are looked-up from the draw |
|
10499 method scope, so after that the loop is run, so they're not |
|
10500 preserved */ |
|
10501 (function(divTitle) { |
|
10502 return function(event) { |
|
10503 IriSP.jQuery(this).animate({opacity: 0.6}, 5); |
|
10504 var offset = IriSP.jQuery(this).offset(); |
|
10505 var correction = IriSP.jQuery(this).outerWidth() / 2; |
|
10506 |
|
10507 var offset_x = offset.left + correction - 106; |
|
10508 if (offset_x < 0) |
|
10509 offset_x = 0; |
|
10510 |
|
10511 self.TooltipWidget.show(divTitle, color, offset_x, event.pageY - 160); |
|
10512 } })(divTitle)).mouseout(function(){ |
|
10513 IriSP.jQuery(this).animate({opacity: 0.3}, 5); |
|
10514 self.TooltipWidget.hide(); |
|
10515 }); |
|
10516 |
|
10517 IriSP.jQuery("#" + id).click(function(_this, annotation) { |
|
10518 return function() { _this.clickHandler(annotation)}; |
|
10519 }(this, annotation)); |
|
10520 } |
|
10521 }; |
|
10522 |
|
10523 /* restores the view after a search */ |
|
10524 IriSP.SegmentsWidget.prototype.clear = function() { |
|
10525 this.selector.children(".Ldt-iri-chapter").css('border','none').animate({opacity:0.3}, 100); |
|
10526 }; |
|
10527 |
|
10528 IriSP.SegmentsWidget.prototype.clickHandler = function(annotation) { |
|
10529 this._Popcorn.trigger("IriSP.SegmentsWidget.click", annotation.id); |
|
10530 var begin = (+ annotation.begin) / 1000; |
|
10531 this._Popcorn.currentTime(Math.round(begin)); |
|
10532 }; |
|
10533 |
|
10534 IriSP.SegmentsWidget.prototype.searchHandler = function(searchString) { |
|
10535 |
|
10536 if (searchString == "") |
|
10537 return; |
|
10538 |
|
10539 var matches = this._serializer.searchOccurences(searchString); |
|
10540 |
|
10541 if (IriSP.countProperties(matches) > 0) { |
|
10542 this._Popcorn.trigger("IriSP.search.matchFound"); |
|
10543 } else { |
|
10544 this._Popcorn.trigger("IriSP.search.noMatchFound"); |
|
10545 } |
|
10546 |
|
10547 // un-highlight all the blocks |
|
10548 this.selector.children(".Ldt-iri-chapter").css("opacity", 0.1); |
|
10549 |
|
10550 // then highlight the ones with matches. |
|
10551 for (var id in matches) { |
|
10552 var factor = 0.5 + matches[id] * 0.2; |
|
10553 this.selector.find("#"+id).dequeue(); |
|
10554 this.selector.find("#"+id).css('border','1px red'); |
|
10555 this.selector.find("#"+id).animate({opacity:factor}, 200); |
|
10556 } |
|
10557 |
|
10558 |
|
10559 this.oldSearchMatches = matches; |
|
10560 }; |
|
10561 |
|
10562 IriSP.SegmentsWidget.prototype.searchFieldClearedHandler = function() { |
|
10563 this.clear(); |
|
10564 }; |
|
10565 |
|
10566 IriSP.SegmentsWidget.prototype.searchFieldClosedHandler = function() { |
|
10567 this.clear(); |
|
10568 }; |
|
10569 |
|
10570 IriSP.SegmentsWidget.prototype.positionUpdater = function() { |
|
10571 var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000; |
|
10572 var time = this._Popcorn.currentTime(); |
|
10573 var position = ((time / duration) * 100).toFixed(2); |
|
10574 |
|
10575 this.positionMarker.css("left", position + "%"); |
|
10576 }; |
|
10577 IriSP.SliderWidget = function(Popcorn, config, Serializer) { |
|
10578 IriSP.Widget.call(this, Popcorn, config, Serializer); |
|
10579 }; |
|
10580 |
|
10581 IriSP.SliderWidget.prototype = new IriSP.Widget(); |
|
10582 |
|
10583 IriSP.SliderWidget.prototype.draw = function() { |
|
10584 var self = this; |
|
10585 |
|
10586 this.selector.append(Mustache.to_html(IriSP.sliderWidget_template, {})); |
|
10587 this.selector.addClass("Ldt-SliderMinimized"); |
|
10588 |
|
10589 this.sliderBackground = this.selector.find(".Ldt-sliderBackground"); |
|
10590 this.sliderForeground = this.selector.find(".Ldt-sliderForeground"); |
|
10591 this.positionMarker = this.selector.find(".Ldt-sliderPositionMarker"); |
|
10592 |
|
10593 |
|
10594 // a special variable to stop methods from tinkering |
|
10595 // with the positionMarker when the user is dragging it |
|
10596 this.draggingOngoing = false; |
|
10597 |
|
10598 // another special variable used by the timeout handler to |
|
10599 // open or close the slider. |
|
10600 this.sliderMaximized = false; |
|
10601 this.timeOutId = null; |
|
10602 |
|
10603 this.positionMarker.draggable({axis: "x", |
|
10604 start: IriSP.wrap(this, this.positionMarkerDraggingStartedHandler), |
|
10605 stop: IriSP.wrap(this, this.positionMarkerDraggedHandler), |
|
10606 containment: "parent" |
|
10607 }); |
|
10608 |
|
10609 this.sliderBackground.click(function(event) { self.backgroundClickHandler.call(self, event); }); |
|
10610 this.sliderForeground.click(function(event) { self.foregroundClickHandler.call(self, event); }); |
|
10611 |
|
10612 this.selector.hover(IriSP.wrap(this, this.mouseOverHandler), IriSP.wrap(this, this.mouseOutHandler)); |
|
10613 |
|
10614 // update the positions |
|
10615 this._Popcorn.listen("timeupdate", IriSP.wrap(this, this.sliderUpdater)); |
|
10616 |
|
10617 // special messages : |
|
10618 this._Popcorn.listen("IriSP.PlayerWidget.MouseOver", IriSP.wrap(this, this.mouseOverHandler)); |
|
10619 this._Popcorn.listen("IriSP.PlayerWidget.MouseOut", IriSP.wrap(this, this.mouseOutHandler)); |
|
10620 }; |
|
10621 |
|
10622 /* update the slider and the position marker as time passes */ |
|
10623 IriSP.SliderWidget.prototype.sliderUpdater = function() { |
|
10624 if(this.draggingOngoing) |
|
10625 return; |
|
10626 |
|
10627 var time = this._Popcorn.currentTime(); |
|
10628 |
|
10629 var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000; |
|
10630 var percent = ((time / duration) * 100).toFixed(2); |
|
10631 this.sliderForeground.css("width", percent + "%"); |
|
10632 this.positionMarker.css("left", percent + "%"); |
|
10633 |
|
10634 }; |
|
10635 |
|
10636 IriSP.SliderWidget.prototype.backgroundClickHandler = function(event) { |
|
10637 /* this piece of code is a little bit convoluted - here's how it works : |
|
10638 we want to handle clicks on the progress bar and convert those to seeks in the media. |
|
10639 However, jquery only gives us a global position, and we want a number of pixels relative |
|
10640 to our container div, so we get the parent position, and compute an offset to this position, |
|
10641 and finally compute the progress ratio in the media. |
|
10642 Finally we multiply this ratio with the duration to get the correct time |
|
10643 */ |
|
10644 |
|
10645 var parentOffset = this.sliderBackground.parent().offset(); |
|
10646 var width = this.sliderBackground.width(); |
|
10647 var relX = event.pageX - parentOffset.left; |
|
10648 |
|
10649 var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000; |
|
10650 var newTime = ((relX / width) * duration).toFixed(2); |
|
10651 |
|
10652 this._Popcorn.currentTime(newTime); |
|
10653 }; |
|
10654 |
|
10655 /* same function as the previous one, except that it handles clicks |
|
10656 on the foreground element */ |
|
10657 IriSP.SliderWidget.prototype.foregroundClickHandler = function(event) { |
|
10658 var parentOffset = this.sliderForeground.parent().offset(); |
|
10659 var width = this.sliderBackground.width(); |
|
10660 var relX = event.pageX - parentOffset.left; |
|
10661 |
|
10662 var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000; |
|
10663 var newTime = ((relX / width) * duration).toFixed(2); |
|
10664 |
|
10665 this._Popcorn.currentTime(newTime); |
|
10666 }; |
|
10667 |
|
10668 /* handles mouse over the slider */ |
|
10669 IriSP.SliderWidget.prototype.mouseOverHandler = function(event) { |
|
10670 |
|
10671 if (this.timeOutId !== null) { |
|
10672 window.clearTimeout(this.timeOutId); |
|
10673 } |
|
10674 |
|
10675 this.sliderMaximized = true; |
|
10676 |
|
10677 this.sliderBackground.animate({"height": "9px"}, 100); |
|
10678 this.sliderForeground.animate({"height": "9px"}, 100); |
|
10679 |
|
10680 // this.selector.removeClass("Ldt-SliderMinimized"); |
|
10681 // this.selector.addClass("Ldt-SliderMaximized"); |
|
10682 }; |
|
10683 |
|
10684 /* handles when the mouse leaves the slider */ |
|
10685 IriSP.SliderWidget.prototype.mouseOutHandler = function(event) { |
|
10686 |
|
10687 this.timeOutId = window.setTimeout(IriSP.wrap(this, this.minimizeOnTimeout), |
|
10688 IriSP.widgetsDefaults.SliderWidget.minimize_period); |
|
10689 }; |
|
10690 |
|
10691 IriSP.SliderWidget.prototype.minimizeOnTimeout = function(event) { |
|
10692 this.sliderBackground.animate({"height": "5px"}, 100); |
|
10693 this.sliderForeground.animate({"height": "5px"}, 100); |
|
10694 this.sliderMinimized = true; |
|
10695 |
|
10696 // this.selector.removeClass("Ldt-SliderMaximized"); |
|
10697 // this.selector.addClass("Ldt-SliderMinimized"); |
|
10698 |
|
10699 }; |
|
10700 |
|
10701 // called when the user starts dragging the position indicator |
|
10702 IriSP.SliderWidget.prototype.positionMarkerDraggingStartedHandler = function(event, ui) { |
|
10703 this.draggingOngoing = true; |
|
10704 }; |
|
10705 |
|
10706 IriSP.SliderWidget.prototype.positionMarkerDraggedHandler = function(event, ui) { |
|
10707 var width = this.sliderBackground.width(); |
|
10708 var duration = this._serializer.currentMedia().meta["dc:duration"] / 1000; |
|
10709 var newTime = ((ui.offset.left / width) * duration).toFixed(2); |
|
10710 |
|
10711 this._Popcorn.currentTime(newTime); |
|
10712 |
|
10713 this.draggingOngoing = false; |
|
10714 }; |
|
10715 |
|
10716 /* this widget displays a small tooltip */ |
|
10717 IriSP.TooltipWidget = function(Popcorn, config, Serializer) { |
|
10718 IriSP.Widget.call(this, Popcorn, config, Serializer); |
|
10719 }; |
|
10720 |
|
10721 |
|
10722 IriSP.TooltipWidget.prototype = new IriSP.Widget(); |
|
10723 |
|
10724 IriSP.TooltipWidget.prototype.draw = function() { |
|
10725 var templ = Mustache.to_html(IriSP.tooltipWidget_template); |
|
10726 |
|
10727 this.selector.append(templ); |
|
10728 this.hide(); |
|
10729 |
|
10730 }; |
|
10731 |
|
10732 IriSP.TooltipWidget.prototype.clear = function() { |
|
10733 this.selector.find(".tiptext").text(""); |
|
10734 }; |
|
10735 |
|
10736 IriSP.TooltipWidget.prototype.show = function(text, color, x, y) { |
|
10737 if (this.selector.find(".tiptext").text() == text) |
|
10738 return; |
|
10739 |
|
10740 this.selector.find(".tipcolor").css("background-color", color); |
|
10741 this.selector.find(".tiptext").text(text); |
|
10742 this.selector.find(".tip").css("left", x).css("top", y); |
|
10743 }; |
|
10744 |
|
10745 IriSP.TooltipWidget.prototype.hide = function() { |
|
10746 this.clear(); |
|
10747 this.selector.find(".tip").css("left", -10000).css("top", -100000); |
|
10748 }; |
|
10749 /* a widget that displays tweet - used in conjunction with the polemicWidget */ |
|
10750 |
|
10751 IriSP.TweetsWidget = function(Popcorn, config, Serializer) { |
|
10752 IriSP.Widget.call(this, Popcorn, config, Serializer); |
|
10753 |
|
10754 this._displayingTweet = false; |
|
10755 this._timeoutId = undefined; |
|
10756 }; |
|
10757 |
|
10758 |
|
10759 IriSP.TweetsWidget.prototype = new IriSP.Widget(); |
|
10760 |
|
10761 |
|
10762 IriSP.TweetsWidget.prototype.drawTweet = function(annotation) { |
|
10763 |
|
10764 var title = IriSP.formatTweet(annotation.content.title); |
|
10765 var img = annotation.content.img.src; |
|
10766 if (typeof(img) === "undefined" || img === "" || img === "None") { |
|
10767 img = IriSP.widgetsDefaults.TweetsWidget.default_profile_picture; |
|
10768 } |
|
10769 |
|
10770 var imageMarkup = IriSP.templToHTML("<img src='{{src}}' alt='user image'></img>", |
|
10771 {src : img}); |
|
10772 |
|
10773 if (typeof(annotation.meta["dc:source"].content) !== "undefined") { |
|
10774 var tweetContents = JSON.parse(annotation.meta["dc:source"].content); |
|
10775 var creator = tweetContents.user.screen_name; |
|
10776 var real_name = tweetContents.user.name; |
|
10777 |
|
10778 imageMarkup = IriSP.templToHTML("<a href='http://twitter.com/{{creator}}'><img src='{{src}}' alt='user image'></img></a>", |
|
10779 {src : img, creator: creator}); |
|
10780 |
|
10781 var formatted_date = new Date(tweetContents.created_at).toLocaleDateString(); |
|
10782 title = IriSP.templToHTML("<a class='Ldt-tweet_userHandle' href='http://twitter.com/{{creator}}'>@{{creator}}</a> - " + |
|
10783 "<div class='Ldt-tweet_realName'>{{real_name}}</div>" + |
|
10784 "<div class='Ldt-tweet_tweetContents'>{{{ contents }}}</div>" + |
|
10785 "<div class='Ldt-tweet_date'>{{ date }}</div>", |
|
10786 {creator: creator, real_name: real_name, contents : title, date : formatted_date}); |
|
10787 |
|
10788 this.selector.find(".Ldt-TweetReply").attr("href", "http://twitter.com/home?status=@" + creator + ":%20"); |
|
10789 |
|
10790 |
|
10791 var rtText = Mustache.to_html("http://twitter.com/home?status=RT @{{creator}}: {{text}}", |
|
10792 {creator: creator, text: IriSP.encodeURI(annotation.content.title)}); |
|
10793 this.selector.find(".Ldt-Retweet").attr("href", rtText); |
|
10794 } |
|
10795 |
|
10796 this.selector.find(".Ldt-tweetContents").html(title); |
|
10797 this.selector.find(".Ldt-tweetAvatar").html(imageMarkup); |
|
10798 this.selector.show("blind", 250); |
|
10799 }; |
|
10800 |
|
10801 IriSP.TweetsWidget.prototype.displayTweet = function(annotation) { |
|
10802 if (this._displayingTweet === false) { |
|
10803 this._displayingTweet = true; |
|
10804 } else { |
|
10805 window.clearTimeout(this._timeoutId); |
|
10806 } |
|
10807 |
|
10808 this.drawTweet(annotation); |
|
10809 |
|
10810 var time = this._Popcorn.currentTime(); |
|
10811 this._timeoutId = window.setTimeout(IriSP.wrap(this, this.clearPanel), IriSP.widgetsDefaults.TweetsWidget.tweet_display_period); |
|
10812 }; |
|
10813 |
|
10814 |
|
10815 IriSP.TweetsWidget.prototype.clearPanel = function() { |
|
10816 this._displayingTweet = false; |
|
10817 this._timeoutId = undefined; |
|
10818 this.closePanel(); |
|
10819 |
|
10820 }; |
|
10821 |
|
10822 IriSP.TweetsWidget.prototype.closePanel = function() { |
|
10823 if (this._timeoutId != undefined) { |
|
10824 /* we're called from the "close window" link */ |
|
10825 /* cancel the timeout */ |
|
10826 window.clearTimeout(this._timeoutId); |
|
10827 this._timeoutId = null; |
|
10828 } |
|
10829 |
|
10830 this.selector.hide("blind", 400); |
|
10831 |
|
10832 }; |
|
10833 |
|
10834 /* cancel the timeout if the user clicks on the keep panel open button */ |
|
10835 IriSP.TweetsWidget.prototype.keepPanel = function() { |
|
10836 if (this._timeoutId != undefined) { |
|
10837 /* we're called from the "close window" link */ |
|
10838 /* cancel the timeout */ |
|
10839 window.clearTimeout(this._timeoutId); |
|
10840 this._timeoutId = null; |
|
10841 } |
|
10842 }; |
|
10843 |
|
10844 IriSP.TweetsWidget.prototype.draw = function() { |
|
10845 var _this = this; |
|
10846 |
|
10847 var tweetMarkup = IriSP.templToHTML(IriSP.tweetWidget_template, {"share_template" : IriSP.share_template}); |
|
10848 this.selector.append(tweetMarkup); |
|
10849 this.selector.hide(); |
|
10850 this.selector.find(".Ldt-tweetWidgetMinimize").click(IriSP.wrap(this, this.closePanel)); |
|
10851 this.selector.find(".Ldt-tweetWidgetKeepOpen").click(IriSP.wrap(this, this.keepPanel)); |
|
10852 |
|
10853 this._Popcorn.listen("IriSP.PolemicTweet.click", IriSP.wrap(this, this.PolemicTweetClickHandler)); |
|
10854 }; |
|
10855 |
|
10856 IriSP.TweetsWidget.prototype.PolemicTweetClickHandler = function(tweet_id) { |
|
10857 var index, annotation; |
|
10858 for (index in this._serializer._data.annotations) { |
|
10859 annotation = this._serializer._data.annotations[index]; |
|
10860 |
|
10861 if (annotation.id === tweet_id) |
|
10862 break; |
|
10863 } |
|
10864 |
|
10865 if (annotation.id !== tweet_id) |
|
10866 /* we haven't found it */ |
|
10867 return; |
|
10868 |
|
10869 this.displayTweet(annotation); |
|
10870 return; |
|
10871 }; |
|
10872 |
|
10873 IriSP.JSONSerializer = function(DataLoader, url) { |
|
10874 IriSP.Serializer.call(this, DataLoader, url); |
|
10875 }; |
|
10876 |
|
10877 IriSP.JSONSerializer.prototype = new IriSP.Serializer(); |
|
10878 |
|
10879 IriSP.JSONSerializer.prototype.serialize = function(data) { |
|
10880 return JSON.stringify(data); |
|
10881 }; |
|
10882 |
|
10883 IriSP.JSONSerializer.prototype.deserialize = function(data) { |
|
10884 return JSON.parse(data); |
|
10885 }; |
|
10886 |
|
10887 IriSP.JSONSerializer.prototype.sync = function(callback) { |
|
10888 /* we don't have to do much because jQuery handles json for us */ |
|
10889 |
|
10890 var self = this; |
|
10891 |
|
10892 var fn = function(data) { |
|
10893 self._data = data; |
|
10894 // sort the data too |
|
10895 self._data["annotations"].sort(function(a, b) |
|
10896 { var a_begin = +a.begin; |
|
10897 var b_begin = +b.begin; |
|
10898 return a_begin - b_begin; |
|
10899 }); |
|
10900 |
|
10901 callback(data); |
|
10902 }; |
|
10903 |
|
10904 this._DataLoader.get(this._url, fn); |
|
10905 }; |
|
10906 |
|
10907 IriSP.JSONSerializer.prototype.currentMedia = function() { |
|
10908 return this._data.medias[0]; /* FIXME: don't hardcode it */ |
|
10909 }; |
|
10910 |
|
10911 /* this function searches for an annotation which matches title, description and keyword |
|
10912 "" matches any field. |
|
10913 Note: it ignores tweets. |
|
10914 */ |
|
10915 IriSP.JSONSerializer.prototype.searchAnnotations = function(title, description, keyword) { |
|
10916 /* we can have many types of annotations. We want search to only look for regular segments */ |
|
10917 /* the next two lines are a bit verbose because for some test data, _serializer.data.view is either |
|
10918 null or undefined. |
|
10919 */ |
|
10920 var view; |
|
10921 |
|
10922 if (typeof(this._data.views) !== "undefined" && this._data.views !== null) |
|
10923 view = this._data.views[0]; |
|
10924 |
|
10925 var searchViewType = ""; |
|
10926 |
|
10927 if(typeof(view) !== "undefined" && typeof(view.annotation_types) !== "undefined" && view.annotation_types.length > 1) { |
|
10928 searchViewType = view.annotation_types[0]; |
|
10929 } |
|
10930 |
|
10931 var filterfn = function(annotation) { |
|
10932 if( searchViewType != "" && |
|
10933 typeof(annotation.meta) !== "undefined" && |
|
10934 typeof(annotation.meta["id-ref"]) !== "undefined" && |
|
10935 annotation.meta["id-ref"] !== searchViewType) { |
|
10936 return true; // don't pass |
|
10937 } else { |
|
10938 return false; |
|
10939 } |
|
10940 }; |
|
10941 |
|
10942 return this.searchAnnotationsFilter(title, description, keyword, filterfn); |
|
10943 |
|
10944 }; |
|
10945 |
|
10946 /* only look for tweets */ |
|
10947 IriSP.JSONSerializer.prototype.searchTweets = function(title, description, keyword) { |
|
10948 /* we can have many types of annotations. We want search to only look for regular segments */ |
|
10949 /* the next two lines are a bit verbose because for some test data, _serializer.data.view is either |
|
10950 null or undefined. |
|
10951 */ |
|
10952 var view; |
|
10953 |
|
10954 if (typeof(this._data.views) !== "undefined" && this._data.views !== null) |
|
10955 view = this._data.views[0]; |
|
10956 |
|
10957 var searchViewType = ""; |
|
10958 |
|
10959 if(typeof(view) !== "undefined" && typeof(view.annotation_types) !== "undefined" && view.annotation_types.length > 1) { |
|
10960 searchViewType = view.annotation_types[0]; |
|
10961 } |
|
10962 |
|
10963 var filterfn = function(annotation) { |
|
10964 if( searchViewType != "" && |
|
10965 typeof(annotation.meta) !== "undefined" && |
|
10966 typeof(annotation.meta["id-ref"]) !== "undefined" && |
|
10967 annotation.meta["id-ref"] !== searchViewType) { |
|
10968 return false; // pass |
|
10969 } else { |
|
10970 return true; |
|
10971 } |
|
10972 }; |
|
10973 |
|
10974 return this.searchAnnotationsFilter(title, description, keyword, filterfn); |
|
10975 |
|
10976 }; |
|
10977 |
|
10978 /* |
|
10979 the previous function call this one, which is more general: |
|
10980 */ |
|
10981 IriSP.JSONSerializer.prototype.searchAnnotationsFilter = function(title, description, keyword, filter) { |
|
10982 |
|
10983 var rTitle; |
|
10984 var rDescription; |
|
10985 var rKeyword; |
|
10986 /* match anything if given the empty string */ |
|
10987 if (title == "") |
|
10988 title = ".*"; |
|
10989 if (description == "") |
|
10990 description = ".*"; |
|
10991 if (keyword == "") |
|
10992 keyword = ".*"; |
|
10993 |
|
10994 rTitle = new RegExp(title, "i"); |
|
10995 rDescription = new RegExp(description, "i"); |
|
10996 rKeyword = new RegExp(keyword, "i"); |
|
10997 |
|
10998 var ret_array = []; |
|
10999 |
|
11000 var i; |
|
11001 for (i in this._data.annotations) { |
|
11002 var annotation = this._data.annotations[i]; |
|
11003 |
|
11004 /* filter the annotations whose type is not the one we want */ |
|
11005 if (filter(annotation)) { |
|
11006 continue; |
|
11007 } |
|
11008 |
|
11009 if (rTitle.test(annotation.content.title) && |
|
11010 rDescription.test(annotation.content.description)) { |
|
11011 /* FIXME : implement keyword support */ |
|
11012 ret_array.push(annotation); |
|
11013 } |
|
11014 } |
|
11015 |
|
11016 return ret_array; |
|
11017 }; |
|
11018 |
|
11019 /* breaks a string in words and searches each of these words. Returns an array |
|
11020 of objects with the id of the annotation and its number of occurences. |
|
11021 |
|
11022 FIXME: optimize ? seems to be n^2 in the worst case. |
|
11023 */ |
|
11024 IriSP.JSONSerializer.prototype.searchOccurences = function(searchString) { |
|
11025 var ret = { }; |
|
11026 var keywords = searchString.split(/\s+/); |
|
11027 |
|
11028 for (var i in keywords) { |
|
11029 var keyword = keywords[i]; |
|
11030 |
|
11031 // search this keyword in descriptions and title |
|
11032 var found_annotations = [] |
|
11033 found_annotations = found_annotations.concat(this.searchAnnotations(keyword, "", "")); |
|
11034 found_annotations = found_annotations.concat(this.searchAnnotations("", keyword, "")); |
|
11035 |
|
11036 for (var j in found_annotations) { |
|
11037 var current_annotation = found_annotations[j]; |
|
11038 |
|
11039 if (!ret.hasOwnProperty(current_annotation.id)) { |
|
11040 ret[current_annotation.id] = 1; |
|
11041 } else { |
|
11042 ret[current_annotation.id] += 1; |
|
11043 } |
|
11044 |
|
11045 } |
|
11046 |
|
11047 }; |
|
11048 |
|
11049 return ret; |
|
11050 }; |
|
11051 |
|
11052 /* breaks a string in words and searches each of these words. Returns an array |
|
11053 of objects with the id of the annotation and its number of occurences. |
|
11054 |
|
11055 FIXME: optimize ? seems to be n^2 in the worst case. |
|
11056 */ |
|
11057 IriSP.JSONSerializer.prototype.searchTweetsOccurences = function(searchString) { |
|
11058 var ret = { }; |
|
11059 var keywords = searchString.split(/\s+/); |
|
11060 |
|
11061 for (var i in keywords) { |
|
11062 var keyword = keywords[i]; |
|
11063 |
|
11064 // search this keyword in descriptions and title |
|
11065 var found_annotations = [] |
|
11066 found_annotations = found_annotations.concat(this.searchTweets(keyword, "", "")); |
|
11067 found_annotations = found_annotations.concat(this.searchTweets("", keyword, "")); |
|
11068 |
|
11069 for (var j in found_annotations) { |
|
11070 var current_annotation = found_annotations[j]; |
|
11071 |
|
11072 if (!ret.hasOwnProperty(current_annotation.id)) { |
|
11073 ret[current_annotation.id] = 1; |
|
11074 } else { |
|
11075 ret[current_annotation.id] += 1; |
|
11076 } |
|
11077 |
|
11078 } |
|
11079 |
|
11080 }; |
|
11081 |
|
11082 return ret; |
|
11083 }; |
|
11084 |
|
11085 /* takes the currentTime and returns all the annotations that are displayable at the moment |
|
11086 NB: only takes account the first type of annotations - ignores tweets |
|
11087 currentTime is in seconds. |
|
11088 */ |
|
11089 |
|
11090 IriSP.JSONSerializer.prototype.currentAnnotations = function(currentTime) { |
|
11091 var view; |
|
11092 var currentTimeMs = 1000 * currentTime; |
|
11093 |
|
11094 if (typeof(this._data.views) !== "undefined" && this._data.views !== null) |
|
11095 view = this._data.views[0]; |
|
11096 |
|
11097 var view_type = ""; |
|
11098 |
|
11099 if(typeof(view) !== "undefined" && typeof(view.annotation_types) !== "undefined" && view.annotation_types.length >= 1) { |
|
11100 view_type = view.annotation_types[0]; |
|
11101 } |
|
11102 |
|
11103 var ret_array = []; |
|
11104 |
|
11105 var i; |
|
11106 |
|
11107 for (i in this._data.annotations) { |
|
11108 var annotation = this._data.annotations[i]; |
|
11109 |
|
11110 if (annotation.meta["id-ref"] === view_type && annotation.begin <= currentTimeMs && annotation.end >= currentTimeMs) |
|
11111 ret_array.push(annotation); |
|
11112 } |
|
11113 |
|
11114 return ret_array; |
|
11115 }; |