diff --git a/spa/api/v1/MixResource.py b/spa/api/v1/MixResource.py index 9d62903..db7316b 100755 --- a/spa/api/v1/MixResource.py +++ b/spa/api/v1/MixResource.py @@ -22,7 +22,10 @@ from spa.models.mix import Mix class MixResource(BackboneCompatibleResource): comments = fields.ToManyField('spa.api.v1.CommentResource.CommentResource', 'comments', null=True) favourites = fields.ToManyField('spa.api.v1.UserResource.UserResource', 'favourites', - related_name='favourites', full=True, null=True) + related_name='favourites', full=False, null=True) + + likes = fields.ToManyField('spa.api.v1.UserResource.UserResource', 'likes', + related_name='likes', full=False, null=True) class Meta: queryset = Mix.objects.filter(is_active=True) @@ -33,7 +36,7 @@ class MixResource(BackboneCompatibleResource): filtering = { 'comments': ALL_WITH_RELATIONS, 'favourites': ALL_WITH_RELATIONS, - 'activity_likes': ALL_WITH_RELATIONS + 'likes': ALL_WITH_RELATIONS, } authorization = Authorization() diff --git a/spa/api/v1/UserResource.py b/spa/api/v1/UserResource.py index ee497b3..b5fbec1 100755 --- a/spa/api/v1/UserResource.py +++ b/spa/api/v1/UserResource.py @@ -1,9 +1,11 @@ +from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned from django.db.models import Count, Q from tastypie import fields -from tastypie.authentication import Authentication -from tastypie.authorization import DjangoAuthorization +from tastypie.authentication import Authentication, BasicAuthentication +from tastypie.authorization import DjangoAuthorization, Authorization from django.conf.urls import url from tastypie.constants import ALL +from tastypie.http import HttpGone, HttpMultipleChoices from tastypie.utils import trailing_slash from spa.api.v1.BackboneCompatibleResource import BackboneCompatibleResource @@ -13,9 +15,11 @@ from spa.models.mix import Mix class UserResource(BackboneCompatibleResource): + followers = fields.ToManyField(to='self', attribute='followers', + related_name='followers', null=True) + class Meta: - queryset = UserProfile.objects.all().annotate(mix_count=Count('mixes'))\ - .extra(select={'u':'user'}).order_by('-mix_count') + queryset = UserProfile.objects.all().annotate(mix_count=Count('mixes')).order_by('-mix_count') favourites = fields.ToManyField('spa.api.v1.MixResource.MixResource', 'favourites', null=True) resource_name = 'user' excludes = ['is_active', 'is_staff', 'is_superuser', 'password'] @@ -23,8 +27,8 @@ class UserResource(BackboneCompatibleResource): filtering = { 'slug': ALL, } - authorization = DjangoAuthorization() - authentication = Authentication() + authorization = Authorization() + authentication = BasicAuthentication() favourites = fields.ToManyField('spa.api.v1.MixResource', 'favourites') def _hydrateBitmapOption(self, source, comparator): @@ -39,15 +43,10 @@ class UserResource(BackboneCompatibleResource): self.wrap_view('dispatch_detail'), name="api_dispatch_detail"), url(r"^(?P%s)/(?P[\w\d_.-]+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"), + url(r"^(?P%s)/(?P\w[\w/-]*)/followers%s$" % (self._meta.resource_name, trailing_slash()), + self.wrap_view('get_followers'), name="api_get_followers"), ] - """ - Stub method, not actually needed just yet - but take heed of note below when implementing in the future - def apply_sorting(self, obj_list, options=None): - #apply the sort to the obj_list, not the super call - """ - def apply_filters(self, request, applicable_filters): semi_filtered = super(UserResource, self).apply_filters(request, applicable_filters) return semi_filtered @@ -77,6 +76,7 @@ class UserResource(BackboneCompatibleResource): bundle.obj.remove_follower(bundle.request.user.get_profile()) def obj_update(self, bundle, skip_errors=False, **kwargs): + """ This feels extremely hacky - but for some reason, deleting from the bundle in hydrate is not preventing the fields from being serialized at the ORM @@ -94,7 +94,6 @@ class UserResource(BackboneCompatibleResource): except: pass - return super(UserResource, self).obj_update(bundle, skip_errors, **kwargs) def dehydrate_description(self, bundle): @@ -123,7 +122,7 @@ class UserResource(BackboneCompatibleResource): self._hydrateBitmapOption(bundle.obj.activity_sharing_networks, UserProfile.ACTIVITY_SHARE_NETWORK_TWITTER) - bundle.data['like_count'] = Mix.objects.filter(activity_likes__user=bundle.obj).count() + bundle.data['like_count'] = Mix.objects.filter(likes__user=bundle.obj).count() bundle.data['favourite_count'] = Mix.objects.filter(favourites__user=bundle.obj).count() bundle.data['follower_count'] = bundle.obj.followers.count() bundle.data['following_count'] = bundle.obj.following.count() @@ -155,3 +154,15 @@ class UserResource(BackboneCompatibleResource): del bundle.data['activity_sharing_networks_twitter'] return bundle + + def get_followers(self, request, **kwargs): + try: + basic_bundle = self.build_bundle(request=request) + obj = self.cached_obj_get(bundle=basic_bundle, **self.remove_api_resource_names(kwargs)) + except ObjectDoesNotExist: + return HttpGone() + except MultipleObjectsReturned: + return HttpMultipleChoices("More than one resource is found at this URI.") + + child_resource = UserResource() + return child_resource.get_list(request, mix=obj) diff --git a/spa/api/v1/auth.py b/spa/api/v1/auth.py new file mode 100644 index 0000000..d1bf67c --- /dev/null +++ b/spa/api/v1/auth.py @@ -0,0 +1,16 @@ +from tastypie.authorization import Authorization + + +class UserOwnsRowAuthorisation(Authorization): + """ + If the user is already authenticated by a django session it will + allow the request (useful for ajax calls) . + In addition, we will check that the user owns the row being updated + or is an admin + """ + + def apply_limits(self, request, object_list): + if request and hasattr(request, 'user'): + return object_list.filter(author__username=request.user.username) + + return object_list.none() \ No newline at end of file diff --git a/spa/embedding/__init__.py b/spa/embedding/__init__.py new file mode 100644 index 0000000..6d4caf8 --- /dev/null +++ b/spa/embedding/__init__.py @@ -0,0 +1 @@ +__author__ = 'fergalm' diff --git a/spa/embedding/urls.py b/spa/embedding/urls.py new file mode 100644 index 0000000..10a3e67 --- /dev/null +++ b/spa/embedding/urls.py @@ -0,0 +1,7 @@ +from django.conf.urls import patterns, url + +urlpatterns = patterns( + '', + url(r'^mix/(?P\d+)/$', 'spa.embedding.views.mix', name='embed_mix'), + url(r'^mix/(?P[\w\d_.-]+)/$', 'spa.embedding.views.mix', name='embed_mix_slug'), +) \ No newline at end of file diff --git a/spa/embedding/views.py b/spa/embedding/views.py new file mode 100644 index 0000000..eb16419 --- /dev/null +++ b/spa/embedding/views.py @@ -0,0 +1,34 @@ +from django.contrib.sites.models import Site +from django.http import Http404 +from django.shortcuts import render_to_response +from django.template import RequestContext +from spa.models import Mix + + +def mix(request, **args): + try: + if 'mix_id' in args: + mix = Mix.objects.get(pk=args['mix_id']) + else: + mix = Mix.objects.get(slug=args['slug']) + except Mix.DoesNotExist: + raise Http404 + + image = mix.get_image_url('1500x1500') + audio_url = mix.get_stream_path() + mix_url = mix.get_absolute_url() + payload = { + "description": mix.description.replace('
', '\n'), + "title": mix.title, + "image_url": image, + "audio_url": audio_url, + "mix_url": 'http://%s%s' % (Site.objects.get_current().domain, mix_url) + } + response = render_to_response( + 'inc/embed/mix.html', + payload, + context_instance=RequestContext(request) + ) + response['X-XSS-Protection'] = 0 + response['X-Frame-Options'] = 'IGNORE' + return response diff --git a/spa/management/commands/debugRelations.py b/spa/management/commands/debugRelations.py index bf29653..f534eb0 100644 --- a/spa/management/commands/debugRelations.py +++ b/spa/management/commands/debugRelations.py @@ -5,8 +5,9 @@ from spa.models import Mix class Command(NoArgsCommand): def handle_noargs(self, **options): try: - list = Mix.objects.filter(slug='dss-on-deepvibes-radio-17th-july-jamie-o-sullivan')[0] - for fav in list.favourites.all(): + #l = Mix.objects.filter(slug='dss-on-deepvibes-radio-17th-july-jamie-o-sullivan')[0] + l = Mix.objects.filter(favourites__slug='fergalmoran')[0] + for fav in l.favourites.all(): print fav.slug pass except Exception, ex: diff --git a/spa/management/commands/import_favourites.py b/spa/management/commands/import_favourites.py new file mode 100644 index 0000000..2a8cd37 --- /dev/null +++ b/spa/management/commands/import_favourites.py @@ -0,0 +1,15 @@ +from django.core.management.base import NoArgsCommand +from spa.models.activity import ActivityFavourite + + +class Command(NoArgsCommand): + def handle_noargs(self, **options): + try: + l = ActivityFavourite.objects.all() + for item in l: + m = item.mix + m.favourites.add(item.user) + m.save() + + except Exception, ex: + print "Debug exception: %s" % ex.message \ No newline at end of file diff --git a/spa/management/commands/import_likes.py b/spa/management/commands/import_likes.py new file mode 100644 index 0000000..1438e59 --- /dev/null +++ b/spa/management/commands/import_likes.py @@ -0,0 +1,15 @@ +from django.core.management.base import NoArgsCommand +from spa.models.activity import ActivityFavourite, ActivityLike + + +class Command(NoArgsCommand): + def handle_noargs(self, **options): + try: + l = ActivityLike.objects.all() + for item in l: + m = item.mix + m.favourites.add(item.user) + m.save() + + except Exception, ex: + print "Debug exception: %s" % ex.message \ No newline at end of file diff --git a/spa/models/mix.py b/spa/models/mix.py index fa9d127..0e5e888 100755 --- a/spa/models/mix.py +++ b/spa/models/mix.py @@ -50,7 +50,8 @@ class Mix(_BaseModel): genres = models.ManyToManyField(Genre) #activity based stuff - favourites = models.ManyToManyField(UserProfile, blank=True, null=True) + favourites = models.ManyToManyField(UserProfile, related_name='favourites', blank=True, null=True) + likes = models.ManyToManyField(UserProfile, related_name='likes', blank=True, null=True) def __unicode__(self): return self.title @@ -168,14 +169,6 @@ class Mix(_BaseModel): except Exception, e: self.logger.exception("Unable to add mix play: %s" % e.message) - def is_liked(self, user): - if user is None: - return False - if user.is_authenticated(): - return self.activity_likes.filter(user=user).count() != 0 - - return False - def update_favourite(self, user, value): try: if user is None: @@ -198,10 +191,12 @@ class Mix(_BaseModel): return if user.is_authenticated(): if value: - if self.activity_likes.filter(user=user).count() == 0: - ActivityLike(user=user.get_profile(), mix=self).save() + if self.likes.filter(user=user).count() == 0: + self.likes.add(user.get_profile()) + self.save() else: - self.activity_likes.filter(user=user).delete() + self.likes.remove(user.get_profile()) + self.save() except Exception, ex: self.logger.error("Exception updating like: %s" % ex.message) @@ -212,3 +207,12 @@ class Mix(_BaseModel): return self.favourites.filter(user=user).count() != 0 else: return False + + def is_liked(self, user): + if user is None: + return False + if user.is_authenticated(): + return self.likes.filter(user=user).count() != 0 + + return False + diff --git a/spa/templates.py b/spa/templates.py index d0580af..b7d1688 100755 --- a/spa/templates.py +++ b/spa/templates.py @@ -1,9 +1,9 @@ +from django.contrib.sites.models import Site from django.shortcuts import render_to_response from django.template.context import RequestContext from htmlmin.decorators import not_minified_response from dss import localsettings from spa.forms import UserForm -from spa.models import UserProfile __author__ = 'fergalm' @@ -24,7 +24,18 @@ def get_template_ex(request, template_name): @not_minified_response -def get_dialog(request, dialog_name): +def get_embed_codes_dialog(request, slug): + payload = { + 'embed_code': 'http://%s/embed/%s' % (Site.objects.get_current().domain, slug) + } + return render_to_response( + 'views/dlg/EmbedCodes.html', + payload, + context_instance=RequestContext(request)) + + +@not_minified_response +def get_dialog(request, dialog_name, **kwargs): return render_to_response( 'views/dlg/%s.html' % dialog_name, context_instance=RequestContext(request)) diff --git a/spa/urls.py b/spa/urls.py index 697cd4e..6e1cabc 100755 --- a/spa/urls.py +++ b/spa/urls.py @@ -33,12 +33,15 @@ urlpatterns = patterns( url(r'^$', 'spa.views.app', name='home'), url(r'^tpl/(?P\w+)/$', 'spa.templates.get_template'), url(r'^dlg/(?P\w+)/$', 'spa.templates.get_dialog'), + url(r'^dlg/embed/(?P[\w\d_.-]+)/$', 'spa.templates.get_embed_codes_dialog'), + url(r'^js/(?P\w+)/$', 'spa.templates.get_javascript'), url(r'^tplex/(?P\w+)/$', 'spa.templates.get_template_ex'), url(r'^podcast\.xml', 'spa.podcast.get_default_podcast'), url(r'^podcast', 'spa.podcast.get_default_podcast'), url(r'^podcasts', 'spa.podcast.get_default_podcast'), url(r'^social/', include('spa.social.urls')), + url(r'^embed/', include('spa.embedding.urls')), url(r'^ajax/', include(ajax.urls)), url(r'^audio/', include(audio.urls)), url(r'^api/', include(v1_api.urls)), diff --git a/static/bin/flashmediaelement.swf b/static/bin/flashmediaelement.swf new file mode 100644 index 0000000..d8c66d2 Binary files /dev/null and b/static/bin/flashmediaelement.swf differ diff --git a/static/bin/silverlightmediaelement.xap b/static/bin/silverlightmediaelement.xap new file mode 100644 index 0000000..9d55c2e Binary files /dev/null and b/static/bin/silverlightmediaelement.xap differ diff --git a/static/css/controls.svg b/static/css/controls.svg new file mode 100644 index 0000000..af3bd41 --- /dev/null +++ b/static/css/controls.svg @@ -0,0 +1 @@ + cc \ No newline at end of file diff --git a/static/css/mediaelementplayer.css b/static/css/mediaelementplayer.css new file mode 100644 index 0000000..4d9472d --- /dev/null +++ b/static/css/mediaelementplayer.css @@ -0,0 +1,869 @@ +.mejs-container { + position: relative; + background: #000; + font-family: Helvetica, Arial; + text-align: left; + vertical-align: top; + text-indent: 0; +} + +.me-plugin { + position: absolute; +} + +.mejs-embed, .mejs-embed body { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + background: #000; + overflow: hidden; +} + +.mejs-fullscreen { + /* set it to not show scroll bars so 100% will work */ + overflow: hidden !important; +} + +.mejs-container-fullscreen { + position: fixed; + left: 0; + top: 0; + right: 0; + bottom: 0; + overflow: hidden; + z-index: 1000; +} +.mejs-container-fullscreen .mejs-mediaelement, +.mejs-container-fullscreen video { + width: 100%; + height: 100%; +} + +.mejs-clear { + clear: both; +} + +/* Start: LAYERS */ +.mejs-background { + position: absolute; + top: 0; + left: 0; +} + +.mejs-mediaelement { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.mejs-poster { + position: absolute; + top: 0; + left: 0; + background-size: contain ; + background-position: 50% 50% ; + background-repeat: no-repeat ; +} +:root .mejs-poster img { + display: none ; +} + +.mejs-poster img { + border: 0; + padding: 0; + border: 0; +} + +.mejs-overlay { + position: absolute; + top: 0; + left: 0; +} + +.mejs-overlay-play { + cursor: pointer; +} + +.mejs-overlay-button { + position: absolute; + top: 50%; + left: 50%; + width: 100px; + height: 100px; + margin: -50px 0 0 -50px; + background: url(bigplay.svg) no-repeat; +} + +.no-svg .mejs-overlay-button { + background-image: url(bigplay.png); +} + +.mejs-overlay:hover .mejs-overlay-button { + background-position: 0 -100px ; +} + +.mejs-overlay-loading { + position: absolute; + top: 50%; + left: 50%; + width: 80px; + height: 80px; + margin: -40px 0 0 -40px; + background: #333; + background: url(background.png); + background: rgba(0, 0, 0, 0.9); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(50,50,50,0.9)), to(rgba(0,0,0,0.9))); + background: -webkit-linear-gradient(top, rgba(50,50,50,0.9), rgba(0,0,0,0.9)); + background: -moz-linear-gradient(top, rgba(50,50,50,0.9), rgba(0,0,0,0.9)); + background: -o-linear-gradient(top, rgba(50,50,50,0.9), rgba(0,0,0,0.9)); + background: -ms-linear-gradient(top, rgba(50,50,50,0.9), rgba(0,0,0,0.9)); + background: linear-gradient(rgba(50,50,50,0.9), rgba(0,0,0,0.9)); +} + +.mejs-overlay-loading span { + display: block; + width: 80px; + height: 80px; + background: transparent url(loading.gif) 50% 50% no-repeat; +} + +/* End: LAYERS */ + +/* Start: CONTROL BAR */ +.mejs-container .mejs-controls { + position: absolute; + list-style-type: none; + margin: 0; + padding: 0; + bottom: 0; + left: 0; + background: url(background.png); + background: rgba(0, 0, 0, 0.7); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(50,50,50,0.7)), to(rgba(0,0,0,0.7))); + background: -webkit-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + background: -moz-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + background: -o-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + background: -ms-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + background: linear-gradient(rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + height: 30px; + width: 100%; +} +.mejs-container .mejs-controls div { + list-style-type: none; + background-image: none; + display: block; + float: left; + margin: 0; + padding: 0; + width: 26px; + height: 26px; + font-size: 11px; + line-height: 11px; + font-family: Helvetica, Arial; + border: 0; +} + +.mejs-controls .mejs-button button { + cursor: pointer; + display: block; + font-size: 0; + line-height: 0; + text-decoration: none; + margin: 7px 5px; + padding: 0; + position: absolute; + height: 16px; + width: 16px; + border: 0; + background: transparent url(controls.svg) no-repeat; +} + +.no-svg .mejs-controls .mejs-button button { + background-image: url(controls.png); +} + +/* :focus for accessibility */ +.mejs-controls .mejs-button button:focus { + outline: solid 1px yellow; +} + +/* End: CONTROL BAR */ + +/* Start: Time (Current / Duration) */ +.mejs-container .mejs-controls .mejs-time { + color: #fff; + display: block; + height: 17px; + width: auto; + padding: 8px 3px 0 3px ; + overflow: hidden; + text-align: center; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} + +.mejs-container .mejs-controls .mejs-time span { + color: #fff; + font-size: 11px; + line-height: 12px; + display: block; + float: left; + margin: 1px 2px 0 0; + width: auto; +} +/* End: Time (Current / Duration) */ + +/* Start: Play/Pause/Stop */ +.mejs-controls .mejs-play button { + background-position: 0 0; +} + +.mejs-controls .mejs-pause button { + background-position: 0 -16px; +} + +.mejs-controls .mejs-stop button { + background-position: -112px 0; +} +/* Start: Play/Pause/Stop */ + +/* Start: Progress Bar */ +.mejs-controls div.mejs-time-rail { + width: 200px; + padding-top: 5px; +} + +.mejs-controls .mejs-time-rail span { + display: block; + position: absolute; + width: 180px; + height: 10px; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; + cursor: pointer; +} + +.mejs-controls .mejs-time-rail .mejs-time-total { + margin: 5px; + background: #333; + background: rgba(50,50,50,0.8); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(30,30,30,0.8)), to(rgba(60,60,60,0.8))); + background: -webkit-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8)); + background: -moz-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8)); + background: -o-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8)); + background: -ms-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8)); + background: linear-gradient(rgba(30,30,30,0.8), rgba(60,60,60,0.8)); +} + +.mejs-controls .mejs-time-rail .mejs-time-buffering { + width: 100%; + background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + -webkit-background-size: 15px 15px; + -moz-background-size: 15px 15px; + -o-background-size: 15px 15px; + background-size: 15px 15px; + -webkit-animation: buffering-stripes 2s linear infinite; + -moz-animation: buffering-stripes 2s linear infinite; + -ms-animation: buffering-stripes 2s linear infinite; + -o-animation: buffering-stripes 2s linear infinite; + animation: buffering-stripes 2s linear infinite; +} + +@-webkit-keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} } +@-moz-keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} } +@-ms-keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} } +@-o-keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} } +@keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} } + +.mejs-controls .mejs-time-rail .mejs-time-loaded { + background: #3caac8; + background: rgba(60,170,200,0.8); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(44,124,145,0.8)), to(rgba(78,183,212,0.8))); + background: -webkit-linear-gradient(top, rgba(44,124,145,0.8), rgba(78,183,212,0.8)); + background: -moz-linear-gradient(top, rgba(44,124,145,0.8), rgba(78,183,212,0.8)); + background: -o-linear-gradient(top, rgba(44,124,145,0.8), rgba(78,183,212,0.8)); + background: -ms-linear-gradient(top, rgba(44,124,145,0.8), rgba(78,183,212,0.8)); + background: linear-gradient(rgba(44,124,145,0.8), rgba(78,183,212,0.8)); + width: 0; +} + +.mejs-controls .mejs-time-rail .mejs-time-current { + background: #fff; + background: rgba(255,255,255,0.8); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255,255,255,0.9)), to(rgba(200,200,200,0.8))); + background: -webkit-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + background: -moz-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + background: -o-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + background: -ms-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + background: linear-gradient(rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + width: 0; +} + +.mejs-controls .mejs-time-rail .mejs-time-handle { + display: none; + position: absolute; + margin: 0; + width: 10px; + background: #fff; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + cursor: pointer; + border: solid 2px #333; + top: -2px; + text-align: center; +} + +.mejs-controls .mejs-time-rail .mejs-time-float { + position: absolute; + display: none; + background: #eee; + width: 36px; + height: 17px; + border: solid 1px #333; + top: -26px; + margin-left: -18px; + text-align: center; + color: #111; +} + +.mejs-controls .mejs-time-rail .mejs-time-float-current { + margin: 2px; + width: 30px; + display: block; + text-align: center; + left: 0; +} + +.mejs-controls .mejs-time-rail .mejs-time-float-corner { + position: absolute; + display: block; + width: 0; + height: 0; + line-height: 0; + border: solid 5px #eee; + border-color: #eee transparent transparent transparent; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + top: 15px; + left: 13px; +} + +.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float { + width: 48px; +} + +.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float-current { + width: 44px; +} + +.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float-corner { + left: 18px; +} + +/* +.mejs-controls .mejs-time-rail:hover .mejs-time-handle { + visibility:visible; +} +*/ +/* End: Progress Bar */ + +/* Start: Fullscreen */ +.mejs-controls .mejs-fullscreen-button button { + background-position: -32px 0; +} + +.mejs-controls .mejs-unfullscreen button { + background-position: -32px -16px; +} +/* End: Fullscreen */ + + +/* Start: Mute/Volume */ +.mejs-controls .mejs-volume-button { +} + +.mejs-controls .mejs-mute button { + background-position: -16px -16px; +} + +.mejs-controls .mejs-unmute button { + background-position: -16px 0; +} + +.mejs-controls .mejs-volume-button { + position: relative; +} + +.mejs-controls .mejs-volume-button .mejs-volume-slider { + display: none; + height: 115px; + width: 25px; + background: url(background.png); + background: rgba(50, 50, 50, 0.7); + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + top: -115px; + left: 0; + z-index: 1; + position: absolute; + margin: 0; +} + +.mejs-controls .mejs-volume-button:hover { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +/* +.mejs-controls .mejs-volume-button:hover .mejs-volume-slider { + display: block; +} +*/ + +.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-total { + position: absolute; + left: 11px; + top: 8px; + width: 2px; + height: 100px; + background: #ddd; + background: rgba(255, 255, 255, 0.5); + margin: 0; +} + +.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-current { + position: absolute; + left: 11px; + top: 8px; + width: 2px; + height: 100px; + background: #ddd; + background: rgba(255, 255, 255, 0.9); + margin: 0; +} + +.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-handle { + position: absolute; + left: 4px; + top: -3px; + width: 16px; + height: 6px; + background: #ddd; + background: rgba(255, 255, 255, 0.9); + cursor: N-resize; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; + margin: 0; +} + +/* horizontal version */ +.mejs-controls div.mejs-horizontal-volume-slider { + height: 26px; + width: 60px; + position: relative; +} + +.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-total { + position: absolute; + left: 0; + top: 11px; + width: 50px; + height: 8px; + margin: 0; + padding: 0; + font-size: 1px; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; + background: #333; + background: rgba(50,50,50,0.8); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(30,30,30,0.8)), to(rgba(60,60,60,0.8))); + background: -webkit-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8)); + background: -moz-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8)); + background: -o-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8)); + background: -ms-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8)); + background: linear-gradient(rgba(30,30,30,0.8), rgba(60,60,60,0.8)); +} + +.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-current { + position: absolute; + left: 0; + top: 11px; + width: 50px; + height: 8px; + margin: 0; + padding: 0; + font-size: 1px; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; + background: #fff; + background: rgba(255,255,255,0.8); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255,255,255,0.9)), to(rgba(200,200,200,0.8))); + background: -webkit-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + background: -moz-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + background: -o-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + background: -ms-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + background: linear-gradient(rgba(255,255,255,0.9), rgba(200,200,200,0.8)); +} + +.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-handle { + display: none; +} + +/* End: Mute/Volume */ + +/* Start: Track (Captions and Chapters) */ +.mejs-controls .mejs-captions-button { + position: relative; +} + +.mejs-controls .mejs-captions-button button { + background-position: -48px 0; +} +.mejs-controls .mejs-captions-button .mejs-captions-selector { + visibility: hidden; + position: absolute; + bottom: 26px; + right: -10px; + width: 130px; + height: 100px; + background: url(background.png); + background: rgba(50,50,50,0.7); + border: solid 1px transparent; + padding: 10px; + overflow: hidden; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +/* +.mejs-controls .mejs-captions-button:hover .mejs-captions-selector { + visibility: visible; +} +*/ + +.mejs-controls .mejs-captions-button .mejs-captions-selector ul { + margin: 0; + padding: 0; + display: block; + list-style-type: none !important; + overflow: hidden; +} + +.mejs-controls .mejs-captions-button .mejs-captions-selector ul li { + margin: 0 0 6px 0; + padding: 0; + list-style-type: none !important; + display: block; + color: #fff; + overflow: hidden; +} + +.mejs-controls .mejs-captions-button .mejs-captions-selector ul li input { + clear: both; + float: left; + margin: 3px 3px 0 5px; +} + +.mejs-controls .mejs-captions-button .mejs-captions-selector ul li label { + width: 100px; + float: left; + padding: 4px 0 0 0; + line-height: 15px; + font-family: helvetica, arial; + font-size: 10px; +} + +.mejs-controls .mejs-captions-button .mejs-captions-translations { + font-size: 10px; + margin: 0 0 5px 0; +} + +.mejs-chapters { + position: absolute; + top: 0; + left: 0; + -xborder-right: solid 1px #fff; + width: 10000px; + z-index: 1; +} + +.mejs-chapters .mejs-chapter { + position: absolute; + float: left; + background: #222; + background: rgba(0, 0, 0, 0.7); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(50,50,50,0.7)), to(rgba(0,0,0,0.7))); + background: -webkit-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + background: -moz-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + background: -o-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + background: -ms-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + background: linear-gradient(rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, startColorstr=#323232,endColorstr=#000000); + overflow: hidden; + border: 0; +} + +.mejs-chapters .mejs-chapter .mejs-chapter-block { + font-size: 11px; + color: #fff; + padding: 5px; + display: block; + border-right: solid 1px #333; + border-bottom: solid 1px #333; + cursor: pointer; +} + +.mejs-chapters .mejs-chapter .mejs-chapter-block-last { + border-right: none; +} + +.mejs-chapters .mejs-chapter .mejs-chapter-block:hover { + background: #666; + background: rgba(102,102,102, 0.7); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(102,102,102,0.7)), to(rgba(50,50,50,0.6))); + background: -webkit-linear-gradient(top, rgba(102,102,102,0.7), rgba(50,50,50,0.6)); + background: -moz-linear-gradient(top, rgba(102,102,102,0.7), rgba(50,50,50,0.6)); + background: -o-linear-gradient(top, rgba(102,102,102,0.7), rgba(50,50,50,0.6)); + background: -ms-linear-gradient(top, rgba(102,102,102,0.7), rgba(50,50,50,0.6)); + background: linear-gradient(rgba(102,102,102,0.7), rgba(50,50,50,0.6)); + filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, startColorstr=#666666,endColorstr=#323232); +} + +.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-title { + font-size: 12px; + font-weight: bold; + display: block; + white-space: nowrap; + text-overflow: ellipsis; + margin: 0 0 3px 0; + line-height: 12px; +} + +.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-timespan { + font-size: 12px; + line-height: 12px; + margin: 3px 0 4px 0; + display: block; + white-space: nowrap; + text-overflow: ellipsis; +} + +.mejs-captions-layer { + position: absolute; + bottom: 0; + left: 0; + text-align:center; + line-height: 22px; + font-size: 12px; + color: #fff; +} + +.mejs-captions-layer a { + color: #fff; + text-decoration: underline; +} + +.mejs-captions-layer[lang=ar] { + font-size: 20px; + font-weight: normal; +} + +.mejs-captions-position { + position: absolute; + width: 100%; + bottom: 15px; + left: 0; +} + +.mejs-captions-position-hover { + bottom: 45px; +} + +.mejs-captions-text { + padding: 3px 5px; + background: url(background.png); + background: rgba(20, 20, 20, 0.8); + +} +/* End: Track (Captions and Chapters) */ + +/* Start: Error */ +.me-cannotplay { +} + +.me-cannotplay a { + color: #fff; + font-weight: bold; +} + +.me-cannotplay span { + padding: 15px; + display: block; +} +/* End: Error */ + + +/* Start: Loop */ +.mejs-controls .mejs-loop-off button { + background-position: -64px -16px; +} + +.mejs-controls .mejs-loop-on button { + background-position: -64px 0; +} + +/* End: Loop */ + +/* Start: backlight */ +.mejs-controls .mejs-backlight-off button { + background-position: -80px -16px; +} + +.mejs-controls .mejs-backlight-on button { + background-position: -80px 0; +} +/* End: backlight */ + +/* Start: Picture Controls */ +.mejs-controls .mejs-picturecontrols-button { + background-position: -96px 0; +} +/* End: Picture Controls */ + + +/* context menu */ +.mejs-contextmenu { + position: absolute; + width: 150px; + padding: 10px; + border-radius: 4px; + top: 0; + left: 0; + background: #fff; + border: solid 1px #999; + z-index: 1001; /* make sure it shows on fullscreen */ +} +.mejs-contextmenu .mejs-contextmenu-separator { + height: 1px; + font-size: 0; + margin: 5px 6px; + background: #333; +} + +.mejs-contextmenu .mejs-contextmenu-item { + font-family: Helvetica, Arial; + font-size: 12px; + padding: 4px 6px; + cursor: pointer; + color: #333; +} +.mejs-contextmenu .mejs-contextmenu-item:hover { + background: #2C7C91; + color: #fff; +} + +/* Start: Source Chooser */ +.mejs-controls .mejs-sourcechooser-button { + position: relative; +} + +.mejs-controls .mejs-sourcechooser-button button { + background-position: -128px 0; +} + +.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector { + visibility: hidden; + position: absolute; + bottom: 26px; + right: -10px; + width: 130px; + height: 100px; + background: url(background.png); + background: rgba(50,50,50,0.7); + border: solid 1px transparent; + padding: 10px; + overflow: hidden; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul { + margin: 0; + padding: 0; + display: block; + list-style-type: none !important; + overflow: hidden; +} + +.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li { + margin: 0 0 6px 0; + padding: 0; + list-style-type: none !important; + display: block; + color: #fff; + overflow: hidden; +} + +.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li input { + clear: both; + float: left; + margin: 3px 3px 0 5px; +} + +.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li label { + width: 100px; + float: left; + padding: 4px 0 0 0; + line-height: 15px; + font-family: helvetica, arial; + font-size: 10px; +} +/* End: Source Chooser */ + +/* Start: Postroll */ +.mejs-postroll-layer { + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + background: url(background.png); + background: rgba(50,50,50,0.7); + z-index: 1000; + overflow: hidden; +} +.mejs-postroll-layer-content { + width: 100%; + height: 100%; +} +.mejs-postroll-close { + position: absolute; + right: 0; + top: 0; + background: url(background.png); + background: rgba(50,50,50,0.7); + color: #fff; + padding: 4px; + z-index: 100; + cursor: pointer; +} +/* End: Postroll */ diff --git a/static/css/mejs-skins.css b/static/css/mejs-skins.css new file mode 100644 index 0000000..5c27cf1 --- /dev/null +++ b/static/css/mejs-skins.css @@ -0,0 +1,289 @@ +/* TED player */ +.mejs-container.mejs-ted { + +} +.mejs-ted .mejs-controls { + background: #eee; + height: 65px; +} + +.mejs-ted .mejs-button, +.mejs-ted .mejs-time { + position: absolute; + background: #ddd; +} +.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-total { + background-color: none; + background: url(controls-ted.png) repeat-x 0 -52px; + height: 6px; +} +.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-buffering { + height: 6px; +} +.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-loaded { + background-color: none; + background: url(controls-ted.png) repeat-x 0 -52px; + width: 0; + height: 6px; +} +.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-current { + width: 0; + height: 6px; + background-color: none; + background: url(controls-ted.png) repeat-x 0 -59px; +} +.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-handle { + display: block; + margin: 0; + width: 14px; + height: 21px; + top: -7px; + border: 0; + background: url(controls-ted.png) no-repeat 0 0; +} +.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-float { + display: none; +} +.mejs-ted .mejs-controls .mejs-playpause-button { + top: 29px; + left: 9px; + width: 49px; + height: 28px; +} +.mejs-ted .mejs-controls .mejs-playpause-button button { + width: 49px; + height: 28px; + background: url(controls-ted.png) no-repeat -50px -23px; + margin: 0; + padding: 0; +} +.mejs-ted .mejs-controls .mejs-pause button { + background-position: 0 -23px; +} + +.mejs-ted .mejs-controls .mejs-fullscreen-button { + top: 34px; + right: 9px; + width: 17px; + height: 15px; + background : none; +} +.mejs-ted .mejs-controls .mejs-fullscreen-button button { + width: 19px; + height: 17px; + background: transparent url(controls-ted.png) no-repeat 0 -66px; + margin: 0; + padding: 0; +} +.mejs-ted .mejs-controls .mejs-unfullscreen button { + background: transparent url(controls-ted.png) no-repeat -21px -66px; + margin: 0; + padding: 0; +} +.mejs-ted .mejs-controls .mejs-volume-button { + top: 30px; + right: 35px; + width: 24px; + height: 22px; +} +.mejs-ted .mejs-controls .mejs-mute button { + background: url(controls-ted.png) no-repeat -15px 0; + width: 24px; + height: 22px; + margin: 0; + padding: 0; +} +.mejs-ted .mejs-controls .mejs-unmute button { + background: url(controls-ted.png) no-repeat -40px 0; + width: 24px; + height: 22px; + margin: 0; + padding: 0; +} +.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-slider { + background: #fff; + border: solid 1px #aaa; + border-width: 1px 1px 0 1px; + width: 22px; + height: 65px; + top: -65px; +} +.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-total { + background: url(controls-ted.png) repeat-y -41px -66px; + left: 8px; + width: 6px; + height: 50px; +} +.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-current { + left: 8px; + width: 6px; + background: url(controls-ted.png) repeat-y -48px -66px; + height: 50px; +} + +.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-handle { + display: none; +} + +.mejs-ted .mejs-controls .mejs-time span { + color: #333; +} +.mejs-ted .mejs-controls .mejs-currenttime-container { + position: absolute; + top: 32px; + right: 100px; + border: solid 1px #999; + background: #fff; + color: #333; + padding-top: 2px; + border-radius: 3px; + color: #333; +} +.mejs-ted .mejs-controls .mejs-duration-container { + + position: absolute; + top: 32px; + right: 65px; + border: solid 1px #999; + background: #fff; + color: #333; + padding-top: 2px; + border-radius: 3px; + color: #333; +} + +.mejs-ted .mejs-controls .mejs-time button{ + color: #333; +} +.mejs-ted .mejs-controls .mejs-captions-button { + display: none; +} +/* END: TED player */ + + +/* WMP player */ +.mejs-container.mejs-wmp { + +} +.mejs-wmp .mejs-controls { + background: transparent url(controls-wmp-bg.png) center 16px no-repeat; + height: 65px; +} + +.mejs-wmp .mejs-button, +.mejs-wmp .mejs-time { + position: absolute; + background: transparent; +} +.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-total { + background-color: transparent; + border: solid 1px #ccc; + height: 3px; +} +.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-buffering { + height: 3px; +} +.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-loaded { + background-color: rgba(255,255,255,0.3); + width: 0; + height: 3px; +} +.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-current { + width: 0; + height: 1px; + background-color: #014CB6; + border: solid 1px #7FC9FA; + border-width: 1px 0; + border-color: #7FC9FA #fff #619FF2 #fff; +} +.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-handle { + display: block; + margin: 0; + width: 16px; + height: 9px; + top: -3px; + border: 0; + background: url(controls-wmp.png) no-repeat 0 -80px; +} +.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-float { + display: none; +} +.mejs-wmp .mejs-controls .mejs-playpause-button { + top: 10px; + left: 50%; + margin: 10px 0 0 -20px; + width: 40px; + height: 40px; + +} +.mejs-wmp .mejs-controls .mejs-playpause-button button { + width: 40px; + height: 40px; + background: url(controls-wmp.png) no-repeat 0 0; + margin: 0; + padding: 0; +} +.mejs-wmp .mejs-controls .mejs-pause button { + background-position: 0 -40px; +} + +.mejs-wmp .mejs-controls .mejs-currenttime-container { + position: absolute; + top: 25px; + left: 50%; + margin-left: -93px; +} +.mejs-wmp .mejs-controls .mejs-duration-container { + position: absolute; + top: 25px; + left: 50%; + margin-left: -58px; +} + + +.mejs-wmp .mejs-controls .mejs-volume-button { + top: 32px; + right: 50%; + margin-right: -55px; + width: 20px; + height: 15px; +} +.mejs-wmp .mejs-controls .mejs-volume-button button { + margin: 0; + padding: 0; + background: url(controls-wmp.png) no-repeat -42px -17px; + width: 20px; + height: 15px; +} +.mejs-wmp .mejs-controls .mejs-unmute button { + margin: 0; + padding: 0; + background: url(controls-wmp.png) no-repeat -42px 0; + width: 20px; + height: 15px; +} +.mejs-wmp .mejs-controls .mejs-volume-button .mejs-volume-slider { + background: rgba(102,102,102,0.6); +} + +.mejs-wmp .mejs-controls .mejs-fullscreen-button { + top: 32px; + right: 50%; + margin-right: -82px; + width: 15px; + height: 14px; +} +.mejs-wmp .mejs-controls .mejs-fullscreen-button button { + margin: 0; + padding: 0; + background: url(controls-wmp.png) no-repeat -63px 0; + width: 15px; + height: 14px; +} +.mejs-wmp .mejs-controls .mejs-captions-button { + display: none; +} +/* END: WMP player */ + + + diff --git a/static/js/app/appv2.coffee b/static/js/app/appv2.coffee index 5b3d801..0e85047 100755 --- a/static/js/app/appv2.coffee +++ b/static/js/app/appv2.coffee @@ -1,9 +1,7 @@ -define ['backbone', 'marionette', 'vent', 'utils' - 'app.lib/router', 'app.lib/panningRegion', 'app.lib/realtimeController', 'app.lib/audioController', +define ['backbone', 'marionette', 'vent', 'utils', + 'app.lib/social', 'app.lib/router', 'app.lib/panningRegion', 'app.lib/realtimeController', 'app.lib/audioController', 'views/widgets/headerView', 'views/sidebar/sidebarView', 'models/mix/mixCollection'], -(Backbone, Marionette, vent, utils, - DssRouter, PanningRegion, RealtimeController, AudioController, - HeaderView, SidebarView, MixCollection) -> +(Backbone, Marionette, vent, utils, social, DssRouter, PanningRegion, RealtimeController, AudioController, HeaderView, SidebarView, MixCollection) -> App = new Marionette.Application(); App.audioController = new AudioController(); App.realtimeController = new RealtimeController(); @@ -64,11 +62,14 @@ define ['backbone', 'marionette', 'vent', 'utils' true @listenTo vent, "mix:share", (mode, model) -> - console.log "App(vent): mix:share" + console.log "App(vent): mix:share (" + mode + ")" if (mode == "facebook") social.sharePageToFacebook(model); else if (mode == "twitter") social.sharePageToTwitter(model); + else if (mode == "embed") + social.generateEmbedCode(model) + true App.headerRegion.show(new HeaderView()); diff --git a/static/js/app/appv2.js b/static/js/app/appv2.js index 2577d7f..e76c371 100755 --- a/static/js/app/appv2.js +++ b/static/js/app/appv2.js @@ -1,6 +1,6 @@ // Generated by CoffeeScript 1.6.2 (function() { - define(['backbone', 'marionette', 'vent', 'utils', 'app.lib/router', 'app.lib/panningRegion', 'app.lib/realtimeController', 'app.lib/audioController', 'views/widgets/headerView', 'views/sidebar/sidebarView', 'models/mix/mixCollection'], function(Backbone, Marionette, vent, utils, DssRouter, PanningRegion, RealtimeController, AudioController, HeaderView, SidebarView, MixCollection) { + define(['backbone', 'marionette', 'vent', 'utils', 'app.lib/social', 'app.lib/router', 'app.lib/panningRegion', 'app.lib/realtimeController', 'app.lib/audioController', 'views/widgets/headerView', 'views/sidebar/sidebarView', 'models/mix/mixCollection'], function(Backbone, Marionette, vent, utils, social, DssRouter, PanningRegion, RealtimeController, AudioController, HeaderView, SidebarView, MixCollection) { var App, sidebarView; App = new Marionette.Application(); @@ -76,11 +76,13 @@ return true; }); return this.listenTo(vent, "mix:share", function(mode, model) { - console.log("App(vent): mix:share"); + console.log("App(vent): mix:share (" + mode + ")"); if (mode === "facebook") { social.sharePageToFacebook(model); } else if (mode === "twitter") { social.sharePageToTwitter(model); + } else if (mode === "embed") { + social.generateEmbedCode(model); } return true; }); diff --git a/static/js/app/lib/controller.coffee b/static/js/app/lib/controller.coffee index 66fb142..2254a35 100755 --- a/static/js/app/lib/controller.coffee +++ b/static/js/app/lib/controller.coffee @@ -71,12 +71,12 @@ define ['app', 'marionette', 'vent', showUserFavourites: (slug) -> console.log("Controller: showUserFavourites") @_showMixList() - vent.trigger("mix:showlist", {order_by: 'latest', type: 'favourites', user: slug}) + vent.trigger("mix:showlist", {order_by: 'latest', favourites__slug: slug}) showUserLikes: (slug) -> console.log("Controller: showUserLikes") @_showMixList() - vent.trigger("mix:showlist", {order_by: 'latest', type: 'likes', user: slug}) + vent.trigger("mix:showlist", {order_by: 'latest', likes__slug: slug}) showUserFollowing: (slug) -> console.log("Controller: showUserFollowing") diff --git a/static/js/app/lib/controller.js b/static/js/app/lib/controller.js index fec518b..dadf88c 100755 --- a/static/js/app/lib/controller.js +++ b/static/js/app/lib/controller.js @@ -120,8 +120,7 @@ this._showMixList(); return vent.trigger("mix:showlist", { order_by: 'latest', - type: 'favourites', - user: slug + favourites__slug: slug }); }; @@ -130,8 +129,7 @@ this._showMixList(); return vent.trigger("mix:showlist", { order_by: 'latest', - type: 'likes', - user: slug + likes__slug: slug }); }; diff --git a/static/js/app/lib/social.coffee b/static/js/app/lib/social.coffee new file mode 100644 index 0000000..e786c39 --- /dev/null +++ b/static/js/app/lib/social.coffee @@ -0,0 +1,39 @@ +define ['jquery', 'utils'], ($, utils) -> + postFacebookLike: (mixId) -> + + #first off, find if the current user has allowed facebook likes + $.getJSON "social/like/" + mixId + "/", (data) -> + com.podnoms.utils.showAlert "Posted your like to facebook, you can stop this in your settings page.", "Cheers feen" + + + generateEmbedCode: (model) -> + console.log("Generating embed code"); + utils.modal "/dlg/embed/" + model.get('slug') + + sharePageToTwitter: (model) -> + + #We get the URL of the link + loc = $(this).attr("href") + + #We get the title of the link + title = $(this).attr("title") + + #We trigger a new window with the Twitter dialog, in the middle of the page + window.open "http://twitter.com/share?url=" + "http://" + window.location.host + "/" + model.get("item_url") + "&text=" + model.get("title"), "twitterwindow", "height=450, width=550, top=" + ($(window).height() / 2 - 225) + ", left=" + $(window).width() / 2 + ", toolbar=0, location=0, menubar=0, directories=0, scrollbars=0" + + sharePageToFacebook: (model) -> + FB.ui + method: "feed" + name: "Check out this mix on Deep South Sounds" + display: "popup" + link: "http://" + window.location.host + "/" + model.get("item_url") + picture: model.get("mix_image") + caption: model.get("title") + description: model.get("description") + , (response) -> + if response and response.post_id + com.podnoms.utils.showAlert "Success", "Post shared to facebook" + else + com.podnoms.utils.showError "Error", "Failure sharing post" + + diff --git a/static/js/app/lib/utils.js b/static/js/app/lib/utils.js index e216899..7dbf1c1 100755 --- a/static/js/app/lib/utils.js +++ b/static/js/app/lib/utils.js @@ -1,8 +1,8 @@ -// Generated by CoffeeScript 1.3.3 +// Generated by CoffeeScript 1.6.2 (function() { - define(['jquery', 'bootstrap', 'toastr'], function($, bootstrap, toastr) { var _this = this; + return { modal: function(url) { if (url) { @@ -24,6 +24,7 @@ }, checkPlayCount: function() { var _this = this; + if (document.cookie.indexOf("sessionId")) { $.getJSON("/ajax/session_play_count", function(data) { console.log("utils: got playcount"); @@ -46,6 +47,7 @@ generateGuid: function() { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) { var r, v; + r = Math.random() * 16 | 0; v = (c === "x" ? r : r & 0x3 | 0x8); return v.toString(16); @@ -53,6 +55,7 @@ }, downloadURL: function(url) { var iframe; + iframe = document.getElementById("hiddenDownloader"); if (iframe === null) { iframe = document.createElement("iframe"); diff --git a/static/js/app/models/mix/mixCollection.coffee b/static/js/app/models/mix/mixCollection.coffee index 80495ac..0440d2c 100755 --- a/static/js/app/models/mix/mixCollection.coffee +++ b/static/js/app/models/mix/mixCollection.coffee @@ -8,4 +8,3 @@ define ['backbone', 'models/mix/mixItem', 'app.lib/backbone.dss.model.collection console.log("MixCollection: parse") MixCollection - diff --git a/static/js/app/models/mix/mixCollection.js b/static/js/app/models/mix/mixCollection.js index 68d2ad3..cbe2c86 100755 --- a/static/js/app/models/mix/mixCollection.js +++ b/static/js/app/models/mix/mixCollection.js @@ -1,16 +1,17 @@ -// Generated by CoffeeScript 1.3.3 +// Generated by CoffeeScript 1.6.2 (function() { var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; define(['backbone', 'models/mix/mixItem', 'app.lib/backbone.dss.model.collection'], function(Backbone, MixItem, DssCollection) { - var MixCollection; - MixCollection = (function(_super) { + var MixCollection, _ref; + MixCollection = (function(_super) { __extends(MixCollection, _super); function MixCollection() { - return MixCollection.__super__.constructor.apply(this, arguments); + _ref = MixCollection.__super__.constructor.apply(this, arguments); + return _ref; } MixCollection.prototype.model = MixItem; diff --git a/static/js/app/social.js b/static/js/app/social.js deleted file mode 100755 index f43f5dc..0000000 --- a/static/js/app/social.js +++ /dev/null @@ -1,60 +0,0 @@ -/** @license - - ---------------------------------------------- - - Copyright (c) 2012, Fergal Moran. All rights reserved. - Code provided under the BSD License: - - */ - -social = { - postFacebookLike: function (mixId) { - //first off, find if the current user has allowed facebook likes - $.getJSON( - 'social/like/' + mixId + '/', - function (data) { - com.podnoms.utils.showAlert("Posted your like to facebook, you can stop this in your settings page.", "Cheers feen"); - } - ); - }, - - postFacebookFavourite: function (mixId) { - - }, - - sharePageToTwitter: function (model) { - //We get the URL of the link - var loc = $(this).attr('href'); - - //We get the title of the link - var title = $(this).attr('title'); - - //We trigger a new window with the Twitter dialog, in the middle of the page - window.open( - 'http://twitter.com/share?url=' + 'http://' + window.location.host + "/" + model.get('item_url') + - '&text=' + model.get('title'), - 'twitterwindow', - 'height=450, width=550, top=' + ($(window).height() / 2 - 225) + - ', left=' + $(window).width() / 2 + - ', toolbar=0, location=0, menubar=0, directories=0, scrollbars=0'); - }, - sharePageToFacebook: function (model) { - FB.ui({ - method: 'feed', - name: 'Check out this mix on Deep South Sounds', - display: 'popup', - link: 'http://' + window.location.host + "/" + model.get('item_url'), - picture: model.get('mix_image'), - caption: model.get('title'), - description: model.get('description') - }, - function (response) { - if (response && response.post_id) { - com.podnoms.utils.showAlert("Success", "Post shared to facebook"); - } else { - com.podnoms.utils.showError("Error", "Failure sharing post"); - } - } - ); - } -}; \ No newline at end of file diff --git a/static/js/app/views/mix/mixItemView.coffee b/static/js/app/views/mix/mixItemView.coffee index 8840d66..f9f2926 100755 --- a/static/js/app/views/mix/mixItemView.coffee +++ b/static/js/app/views/mix/mixItemView.coffee @@ -31,7 +31,7 @@ define ['moment', 'app', 'vent', 'marionette', 'utils', 'models/comment/commentC id = @model.get('id') if @model.get('duration') totalDuration = moment.duration(this.model.get('duration'), "seconds") - totalDurationText = if totalDuration.hours() != 0 then moment(totalDuration).format("HH:mm:ss") else moment(totalDuration).format("mm:ss"); + totalDurationText = if totalDuration.hours() != 0 then moment(totalDuration).format("h:mm:ss") else moment(totalDuration).format("mm:ss"); $('#player-duration-' + id, this.el).text(totalDurationText) diff --git a/static/js/app/views/mix/mixItemView.js b/static/js/app/views/mix/mixItemView.js index 079ee1b..3389fad 100755 --- a/static/js/app/views/mix/mixItemView.js +++ b/static/js/app/views/mix/mixItemView.js @@ -1,26 +1,22 @@ -// Generated by CoffeeScript 1.3.3 +// Generated by CoffeeScript 1.6.2 (function() { var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; define(['moment', 'app', 'vent', 'marionette', 'utils', 'models/comment/commentCollection', 'views/comment/commentListView', 'text!/tpl/MixListItemView'], function(moment, App, vent, Marionette, utils, CommentsCollection, CommentsListView, Template) { - var MixItemView; - MixItemView = (function(_super) { + var MixItemView, _ref; + MixItemView = (function(_super) { __extends(MixItemView, _super); function MixItemView() { this.doStart = __bind(this.doStart, this); - this.renderComments = __bind(this.renderComments, this); - this.renderGenres = __bind(this.renderGenres, this); - this.onRender = __bind(this.onRender, this); - - this.initialize = __bind(this.initialize, this); - return MixItemView.__super__.constructor.apply(this, arguments); + this.initialize = __bind(this.initialize, this); _ref = MixItemView.__super__.constructor.apply(this, arguments); + return _ref; } MixItemView.prototype.template = _.template(Template); @@ -54,10 +50,11 @@ MixItemView.prototype.onRender = function() { var id, totalDuration, totalDurationText; + id = this.model.get('id'); if (this.model.get('duration')) { totalDuration = moment.duration(this.model.get('duration'), "seconds"); - totalDurationText = totalDuration.hours() !== 0 ? moment(totalDuration).format("HH:mm:ss") : moment(totalDuration).format("mm:ss"); + totalDurationText = totalDuration.hours() !== 0 ? moment(totalDuration).format("h:mm:ss") : moment(totalDuration).format("mm:ss"); $('#player-duration-' + id, this.el).text(totalDurationText); } this.renderGenres(); @@ -73,6 +70,7 @@ MixItemView.prototype.renderGenres = function() { var el; + el = this.el; $.each(this.model.get("genre-list"), function(data) { $("#genre-list", el).append('' + this.text + ''); @@ -83,6 +81,7 @@ MixItemView.prototype.renderComments = function() { var comments; + comments = new CommentsCollection(); comments.url = this.model.get("resource_uri") + "comments/"; comments.mix_id = this.model.id; @@ -90,6 +89,7 @@ comments.fetch({ success: function(data) { var content; + console.log(data); content = new CommentsListView({ collection: comments @@ -139,6 +139,7 @@ MixItemView.prototype.mixFavourite = function() { var app; + console.log("MixItemView: favouriteMix"); app = require('app'); vent.trigger("mix:favourite", this.model); @@ -153,6 +154,7 @@ MixItemView.prototype.mixShare = function(e) { var mode; + console.log("MixItemView: shareMix"); mode = $(e.currentTarget).data("mode"); console.log("MixItemView: " + mode); diff --git a/static/js/jwplayer.html5.js b/static/js/jwplayer.html5.js new file mode 100644 index 0000000..05c179e --- /dev/null +++ b/static/js/jwplayer.html5.js @@ -0,0 +1,196 @@ +(function(f){f.html5={};f.html5.version="6.5.3609"})(jwplayer); +(function(f){function h(a){return function(){a("Error loading file")}}function e(a,b,c,e){return function(){try{var g=a.responseXML;if(g&&g.firstChild)return c(a)}catch(d){}(g=f.parseXML(a.responseText))&&g.firstChild?(a=f.extend({},a,{responseXML:g}),c(a)):e&&e(a.responseText?"Invalid XML":b)}}var d=window;f.serialize=function(a){return null==a?null:"true"==a.toString().toLowerCase()?!0:"false"==a.toString().toLowerCase()?!1:isNaN(Number(a))||5c?"0":"")+c+":"+(10>a?"0":"")+a}return"00:00"};f.seconds=function(a){a=a.replace(",", +".");var b=a.split(":"),c=0;"s"==a.substr(-1)?c=Number(a.substr(0,a.length-1)):"m"==a.substr(-1)?c=60*Number(a.substr(0,a.length-1)):"h"==a.substr(-1)?c=3600*Number(a.substr(0,a.length-1)):1e.indexOf("url")?"url("+e+")":e+k;else switch(a){case "z-index":case "opacity":b=e+k;break a;default:b=a.match(/color/i)?"#"+f.pad(e.toString(16).replace(/^0x/i,""),6)+k:0===e?0+k:Math.ceil(e)+"px"+k}}}g(c[d][a])&&!g(b)?delete c[d][a]:g(b)&&(c[d][a]=b)}); +0r?(c*=g,k*=g):(c*=r,k*=r);case h.NONE:g=r=1;case h.EXACTFIT:j=!0;break;default:g>r?0.95=x.length||(x[D].data?y.populate(x[D].data):(E=a=x[D].file,h.ajax(a,q,m)),s(!1))}function A(){var a=[];a.push({label:"Off"});for(var b=0;b=q)){b=c;break}-1==b?a(""):b!=j&&(j=b,a(g[c].text))}function f(a,b){h(b, +function(b,c){a.style[b]=c})}var g,r,l,j,q,m="visible",p;this.hide=function(){f(r,{display:"none"});p&&(clearInterval(p),p=null)};this.populate=function(a){j=-1;g=a;c()};this.resize=function(){b()};r=document.createElement("div");l=document.createElement("span");r.appendChild(l);d.appendChild(r);f(r,{display:"block",height:"auto",position:"absolute",bottom:"20px",textAlign:"center",width:"100%"});f(l,{color:"#"+e.color.substr(-6),display:"inline-block",fontFamily:e.fontFamily,fontStyle:e.fontStyle, +fontWeight:e.fontWeight,height:"auto",margin:"auto",position:"relative",textAlign:"center",textDecoration:e.textDecoration,wordWrap:"break-word",width:"auto"});e.back?f(l,{background:"#000"}):f(l,{textShadow:"-2px 0px 1px #000,2px 0px 1px #000,0px -2px 1px #000,0px 2px 1px #000,-1px 1px 1px #000,1px 1px 1px #000,1px -1px 1px #000,1px 1px 1px #000"});this.show=function(){f(r,{display:"block"});p||(p=setInterval(b,250));b()};this.update=function(a){q=a;g&&c()}}})(jwplayer.html5); +(function(f){var h=f.html5,e=f.utils,d=f.events,a=d.state,b=e.css;f=e.transitionStyle;var c="button",k="text",g="divider",r="slider",l="100%",j={display:"none"},q={display:v},m=!1,p=!0,s=null,v=void 0,u=window,A=document;h.controlbar=function(f,B){function t(a,b,c){return{name:a,type:b,className:c}}function y(a){var b=m,c;K.elapsed&&(c=e.timeFormat(a.position),K.elapsed.innerHTML=c,b=c.length!=e.timeFormat(wa).length);K.duration&&(c=e.timeFormat(a.duration),K.duration.innerHTML=c,b=b||c.length!=e.timeFormat(ia).length); +0ka.right?a.offsetX(ka.right-b.right):b.lefta&&(a=0);0.9ca.maxwidth;c=ua?0:ca.margin;b(C(),{left:a?"50%":c,right:a?v:c,"margin-left":a?O.clientWidth/-2:v,width:a?l:v});ka=e.bounds(O);e.foreach(Ea,function(a,b){pa(b)})};ha.audioMode=function(a){a!=ua&&(ua=a,b(C(".jwfullscreen"),{display:a?"none":v}),b(C(".jwhd"),{display:a?"none":v}), +b(C(".jwcc"),{display:a?"none":v}),a&&(b(C(".fsdiv"),j),b(C(".hddiv"),j)),ya())};ha.element=function(){return O};ha.margin=function(){return parseInt(ca.margin)};ha.height=function(){return V};ha.show=function(){ha.visible||(clearTimeout(Ha),Ha=v,ha.visible=!0,O.style.display="inline-block",ya(),w(),Ha=setTimeout(function(){O.style.opacity=1},10))};ha.hide=function(){ha.visible&&(ha.visible=!1,O.style.opacity=0,clearTimeout(Ha),Ha=v,Ha=setTimeout(function(){O.style.display="none"},150))};K={};H=f; +$=H.id+"_controlbar";ia=wa=0;O=M();O.id=$;O.className="jwcontrolbar";R=H.skin;ga=R.getComponentLayout("controlbar");ga||(ga=W.layout);e.clearCss("#"+$);E();var Ia=G("capLeft"),U=G("capRight"),ab=G("background",{position:"absolute",left:Q("capLeft").width,right:Q("capRight").width,"background-repeat":"repeat-x"},p);ab&&O.appendChild(ab);Ia&&O.appendChild(Ia);Ga("left");Ga("center");Ga("right");O.appendChild(xa.left);O.appendChild(xa.center);O.appendChild(xa.right);K.hd&&(la=new h.menu("hd",$+"_hd", +R,Ta),aa(la,K.hd,oa,va),Ea.hd=la);K.cc&&(ma=new h.menu("cc",$+"_cc",R,Ua),aa(ma,K.cc,ea,P),Ea.cc=ma);K.mute&&(K.volume&&K.volume.vertical)&&(ra=new h.overlay($+"_volumeoverlay",R),ra.setContents(K.volume),aa(ra,K.mute,X),Ea.volume=ra);K.fullscreen&&(Ma=new h.overlay($+"_fullscreenoverlay",R),Ia=A.createElement("div"),Ia.className="jwoverlaytext",Ia.innerHTML="Fullscreen",Ma.setContents(Ia),aa(Ma,K.fullscreen,da),Ea.fullscreen=Ma);b(C(".jwright"),{right:Q("capRight").width});U&&O.appendChild(U);H.jwAddEventListener(d.JWPLAYER_MEDIA_TIME, +y);H.jwAddEventListener(d.JWPLAYER_PLAYER_STATE,function(c){switch(c.newstate){case a.BUFFERING:case a.PLAYING:b(C(".jwtimeSliderThumb"),{opacity:1});Z("play",p);break;case a.PAUSED:ta||Z("play",m);break;case a.IDLE:Z("play",m),b(C(".jwtimeSliderThumb"),{opacity:0}),K.timeRail&&(K.timeRail.className="jwrail",setTimeout(function(){K.timeRail.className+=" jwsmooth"},100)),Da(0),y({position:0,duration:0})}});H.jwAddEventListener(d.JWPLAYER_PLAYLIST_ITEM,function(a){a=H.jwGetPlaylist()[a.index].tracks; +if("array"==e.typeOf(a))for(var b=0;b=M)clearInterval(C);else{M--;var b=Math.max(I.width,h.bounds(t).width- +w.width-y.width);(h.isFF()||h.isIE())&&b++;h.isChrome()&&1==t.parentNode.clientWidth%2&&b++;e(j(),{"background-size":[y.width+a,b+a,w.width+a].join()},!0)}}function u(){N=(N+G)%360;h.rotate(z,N)}var A=g,n=A.skin,B=f,t,y,w,D,x,z,I,E=0,C,M;this.element=function(){return t};this.setText=function(b){var c=x.style;x.innerHTML=b?b.replace(":",":\x3cbr\x3e"):"";c.height="0";c.display="block";if(b)for(;2b.left&&a.offsetX(c.left-b.left+8);m.show();h.foreach(B,function(a,b){a!=g&&b.hide()})},!1);j.addEventListener("mouseout",function(){s=setTimeout(m.hide,100)},!1);t.appendChild(m.element());B[g]=m}A++;p()}};w.removeButton=function(a){n[a]&&(y.removeChild(n[a].element),y.removeChild(n[a].divider),delete n[a],A--,p())};w.numButtons=function(){return A};w.visible=!1;t=q("div","jwdock");y=q("div","jwdockbuttons");t.appendChild(y); +t.id=v;var D=m("button"),x=m("buttonOver"),z=m("buttonActive");D&&(e(j(),{height:D.height,padding:s.margin}),e(a,{height:D.height}),e(j("button"),{width:D.width,cursor:"pointer",border:c,background:D.src}),x.src&&e(j("button:hover"),{background:x.src}),z.src&&e(j("button:active"),{background:z.src}),e(j("button\x3ediv"),{opacity:s.iconalpha}),e(j("button:hover\x3ediv"),{opacity:s.iconalphaover}),e(j("button:active\x3ediv"),{opacity:s.iconalphaactive}),e(j(".jwoverlay"),{top:s.margin+D.height}),l("capLeft", +y),l("capRight",y),l("divider"));setTimeout(function(){d(t)})};e(".jwdock",{opacity:0,display:c});e(".jwdock \x3e *",{height:"100%","float":"left"});e(".jwdock \x3e .jwoverlay",{height:"auto","float":c,"z-index":99});e(a+" button",{position:"relative"});e(a+" \x3e *",{height:"100%","float":"left"});e(a+" .divider",{display:c});e(a+" button ~ .divider",{display:k});e(a+" .capLeft, "+a+" .capRight",{display:c});e(a+" .capRight",{"float":"right"});e(a+" button \x3e div",{left:0,right:0,top:0,bottom:0, +margin:5,position:"absolute","background-position":"center","background-repeat":"no-repeat"});h.transitionStyle(".jwdock","background .15s, opacity .15s");h.transitionStyle(".jwdock .jwoverlay","opacity .15s");h.transitionStyle(a+" button div","opacity .15s")})(jwplayer.html5); +(function(f){var h=jwplayer,e=h.utils,d=h.events,a=d.state,b=h.playlist;f.instream=function(c,h,g,r){function l(a){a.type==d.JWPLAYER_MEDIA_ERROR&&(a=e.extend({},a),a.type=d.JWPLAYER_ERROR);s(a.type,a);N=!0;G.jwInstreamDestroy(!1)}function j(a){E&&s(a.type,a)}function q(){E&&x.play()}function m(){E&&setTimeout(function(){G.jwInstreamDestroy(!0)},10)}function p(a){a.width&&a.height&&B.resizeMedia()}function s(a,b,c){(E||c)&&C.sendEvent(a,b)}function v(){z&&z.redraw();I&&I.redraw()}var u={controlbarseekable:"never", +controlbarpausable:!0,controlbarstoppable:!0,playlistclickable:!0},A,n,B=g,t,y,w,D,x,z,I,E=!1,C,M,F,G=this,N=!1,T=!0;this.load=function(g,C){e.isAndroid(2.3)?l({type:d.JWPLAYER_ERROR,message:"Error loading instream: Cannot play instream on Android 2.3"}):(E=!0,n=e.extend(u,C),A=new b.item(g),M=document.createElement("div"),M.id=G.id+"_instream_container",t=r.detachMedia(),x=new f.video(t),x.addGlobalListener(j),x.addEventListener(d.JWPLAYER_MEDIA_META,p),x.addEventListener(d.JWPLAYER_MEDIA_COMPLETE, +m),x.addEventListener(d.JWPLAYER_MEDIA_BUFFER_FULL,q),x.addEventListener(d.JWPLAYER_MEDIA_ERROR,l),x.attachMedia(),x.mute(h.mute),x.volume(h.volume),F=new f.model({},x),F.setVolume(h.volume),F.setMute(h.mute),F.addEventListener(d.JWPLAYER_ERROR,l),D=h.playlist[h.item],w=h.getVideo().checkComplete()?a.IDLE:c.jwGetState(),r.checkBeforePlay()&&(w=a.PLAYING,T=!1),y=t.currentTime,F.setPlaylist([g]),N||((w==a.BUFFERING||w==a.PLAYING)&&t.pause(),I=new f.display(G),I.setAlternateClickHandler(function(b){F.state== +a.PAUSED?G.jwInstreamPlay():(G.jwInstreamPause(),s(d.JWPLAYER_INSTREAM_CLICK,b))}),M.appendChild(I.element()),e.isMobile()||(z=new f.controlbar(G),M.appendChild(z.element()),z.show()),B.setupInstream(M,z,I,t),v(),x.load(F.playlist[0])))};this.jwInstreamDestroy=function(b){if(E){E=!1;w!=a.IDLE?x.load(D,!1):x.stop();C.resetEventListeners();N||I.revertAlternateClickHandler();x.detachMedia();B.destroyInstream();if(z)try{z.element().parentNode.removeChild(z.getDisplayElement())}catch(c){}s(d.JWPLAYER_INSTREAM_DESTROYED, +{reason:b?"complete":"destroyed"},!0);r.attachMedia();if(w==a.BUFFERING||w==a.PLAYING)t.play(),h.playlist[h.item]==D&&T&&h.getVideo().seek(y)}};this.jwInstreamAddEventListener=function(a,b){C.addEventListener(a,b)};this.jwInstreamRemoveEventListener=function(a,b){C.removeEventListener(a,b)};this.jwInstreamPlay=function(){E&&(x.play(!0),h.state=jwplayer.events.state.PLAYING,I.show())};this.jwInstreamPause=function(){E&&(x.pause(!0),h.state=jwplayer.events.state.PAUSED,I.show())};this.jwInstreamSeek= +function(a){E&&x.seek(a)};this.jwPlay=function(){"true"==n.controlbarpausable.toString().toLowerCase()&&this.jwInstreamPlay()};this.jwPause=function(){"true"==n.controlbarpausable.toString().toLowerCase()&&this.jwInstreamPause()};this.jwStop=function(){"true"==n.controlbarstoppable.toString().toLowerCase()&&(this.jwInstreamDestroy(),c.jwStop())};this.jwSeek=function(a){switch(n.controlbarseekable.toLowerCase()){case "always":this.jwInstreamSeek(a);break;case "backwards":F.position>a&&this.jwInstreamSeek(a)}}; +this.jwSeekDrag=function(a){F.seekDrag(a)};this.jwGetPosition=function(){};this.jwGetDuration=function(){};this.jwGetWidth=c.jwGetWidth;this.jwGetHeight=c.jwGetHeight;this.jwGetFullscreen=c.jwGetFullscreen;this.jwSetFullscreen=c.jwSetFullscreen;this.jwGetVolume=function(){return h.volume};this.jwSetVolume=function(a){F.setVolume(a);c.jwSetVolume(a)};this.jwGetMute=function(){return h.mute};this.jwSetMute=function(a){F.setMute(a);c.jwSetMute(a)};this.jwGetState=function(){return h.state};this.jwGetPlaylist= +function(){return[A]};this.jwGetPlaylistIndex=function(){return 0};this.jwGetStretching=function(){return h.config.stretching};this.jwAddEventListener=function(a,b){C.addEventListener(a,b)};this.jwRemoveEventListener=function(a,b){C.removeEventListener(a,b)};this.jwSetCurrentQuality=function(){};this.jwGetQualityLevels=function(){return[]};this.skin=c.skin;this.id=c.id+"_instream";C=new d.eventdispatcher;c.jwAddEventListener(d.JWPLAYER_RESIZE,v);c.jwAddEventListener(d.JWPLAYER_FULLSCREEN,function(a){j(a); +v()});return this}})(jwplayer.html5); +(function(f){var h=f.utils,e=h.css,d=f.events.state,a=f.html5.logo=function(b,c){function k(a){h.exists(a)&&a.stopPropagation();if(!m||!l.link)g.jwGetState()==d.IDLE||g.jwGetState()==d.PAUSED?g.jwPlay():g.jwPause();m&&l.link&&(g.jwPause(),g.jwSetFullscreen(!1),window.open(l.link,l.linktarget))}var g=b,r=g.id+"_logo",l,j,q=a.defaults,m=!1;this.resize=function(){};this.element=function(){return j};this.offset=function(a){e("#"+r+" ",{"margin-bottom":a})};this.position=function(){return l.position}; +this.margin=function(){return parseInt(l.margin)};this.hide=function(a){if(l.hide||a)m=!1,j.style.visibility="hidden",j.style.opacity=0};this.show=function(){m=!0;j.style.visibility="visible";j.style.opacity=1};var p="o";g.edition&&(p=g.edition(),p="pro"==p?"p":"premium"==p?"r":"ads"==p?"a":"free"==p?"f":"o");if("o"==p||"f"==p)q.link="http://www.longtailvideo.com/jwpabout/?a\x3dl\x26v\x3d"+f.version+"\x26m\x3dh\x26e\x3d"+p;l=h.extend({},q,c);l.hide="true"==l.hide.toString();j=document.createElement("img"); +j.className="jwlogo";j.id=r;if(l.file){var q=/(\w+)-(\w+)/.exec(l.position),p={},s=l.margin;3==q.length?(p[q[1]]=s,p[q[2]]=s):p.top=p.right=s;e("#"+r+" ",p);j.src=(l.prefix?l.prefix:"")+l.file;j.onclick=k}else j.style.display="none";return this};a.defaults={prefix:h.repo(),file:"logo.png",linktarget:"_top",margin:8,hide:!1,position:"top-right"};e(".jwlogo",{cursor:"pointer",position:"absolute","z-index":100,opacity:0});h.transitionStyle(".jwlogo","visibility .15s, opacity .15s")})(jwplayer); +(function(f){var h=f.html5,e=f.utils,d=e.css,a=void 0;h.menu=function(b,c,f,g){function r(a,b){return function(){v(a);q&&q(b)}}function l(a,b){var c=document.createElement("div");a&&(c.className=a);b&&b.appendChild(c);return c}function j(b){return(b=f.getSkinElement("tooltip",b))?b:{width:0,height:0,src:a}}var q=g,m=new h.overlay(c+"_overlay",f);g=e.extend({fontcase:a,fontcolor:"#cccccc",fontsize:11,fontweight:a,activecolor:"#ffffff",overcolor:"#ffffff"},f.getComponentSettings("tooltip"));var p,s= +[];this.element=function(){return m.element()};this.addOption=function(a,b){var d=l("jwoption",p);d.id=c+"_option_"+b;d.innerHTML=a;d.addEventListener("click",r(s.length,b));s.push(d)};this.clearOptions=function(){for(;0a?(a= +0,b=!0):a=-1==a||a>c.playlist.length?c.playlist.length-1:a;if(b||a!=c.item)c.item=a,c.sendEvent(e.JWPLAYER_PLAYLIST_ITEM,{index:c.item})};c.setVolume=function(a){c.mute&&0a&&(a=0);1parseFloat(jwplayer.version))&&s("Incompatible player version");if(0===a.length)p(m);else for(b=0;br[b].end;)b++;b==r.length&&b--;if(r[b].text)if(a=r[b].text,0>a.indexOf("://")&&(a=l?l+"/"+a:a),0D)&&Z(D);f()}},emptied:c,ended:function(){F&&z!=d.IDLE&&(N=-1,X=!0,b(e.JWPLAYER_MEDIA_BEFORECOMPLETE), +F&&(m(d.IDLE),X=!1,b(e.JWPLAYER_MEDIA_COMPLETE)))},error:function(){F&&(h.log("Error playing media: %o",n.error),M.sendEvent(e.JWPLAYER_MEDIA_ERROR,{message:"Error loading media: File could not be played"}),m(d.IDLE))},loadeddata:c,loadedmetadata:g,loadstart:c,pause:r,play:r,playing:r,progress:function(){y&&(0N&&(N=0);for(a=0;aa)&&(N=a,h.saveCookie("qualityLabel",G[a].label),b(e.JWPLAYER_MEDIA_LEVEL_CHANGED,{currentQuality:a, +levels:j(G)}),a=n.currentTime,q(),L.seek(a)))};L.getCurrentQuality=function(){return N};L.getQualityLevels=function(){return j(G)};n=a;h.foreach(v,function(a,b){n.addEventListener(a,b,!1)});n.controls=!0;n.controls=!1;n.setAttribute("x-webkit-airplay","allow");F=!0}})(jwplayer); +(function(f){var h=jwplayer.utils,e=jwplayer.events,d=e.state,a=h.css,b=h.isMobile(),c=h.isIPad(),k=h.isIPod(),g=h.isAndroid(),r=h.isIOS(),l=document,j="aspectMode",q="jwmain",m="jwvideo",p="jwplaylistcontainer",s=!0,v=!1,u="hidden",A="none",n="block";f.view=function(B,t){function y(a){a&&(a.element().addEventListener("mousemove",x,v),a.element().addEventListener("mouseout",z,v))}function w(a,b){var c=l.createElement(a);b&&(c.className=b);return c}function D(){clearTimeout(pa);if(S.jwGetState()== +d.PLAYING||S.jwGetState()==d.PAUSED)oa(),Aa||(pa=setTimeout(I,Da))}function x(){clearTimeout(pa);Aa=s}function z(){Aa=v}function I(){S.jwGetState()!=d.BUFFERING&&(H&&(!V&&!O)&&H.hide(),U&&(!ia&&!O)&&U.hide(),X());clearTimeout(pa);pa=0}function E(a){ba.sendEvent(a.type,a)}function C(b,c,d){h.exists(d)||(d=!0);h.exists(b)&&h.exists(c)&&(J.width=b,J.height=c);P.style.width=isNaN(b)?b:b+"px";-1==P.className.indexOf(j)&&(P.style.height=isNaN(c)?c:c+"px");R&&R.redraw();H&&H.redraw();W&&(W.offset(H&&0<= +W.position().indexOf("bottom")?H.height()+H.margin():0),setTimeout(function(){U&&U.offset("top-left"==W.position()?W.element().clientWidth+W.margin():0)},500));b=J.playlistsize;var f=J.playlistposition;M(c);if(K&&b&&("right"==f||"bottom"==f)){K.redraw();c={display:n};var g={};c[f]=0;g[f]=b;"right"==f?c.width=b:c.height=b;a(fa(p),c);a(fa(q),g)}F();d&&ba.sendEvent(e.JWPLAYER_RESIZE)}function M(a){V=b&&!O?v:0=a;H&&(V?(H.audioMode(s), +oa(),R.hidePreview(s),Z(),ea(v)):(H.audioMode(v),Pa(S.jwGetState())));W&&V&&X();P.style.backgroundColor=V?"transparent":"#000"}function F(){Y&&-1==P.className.indexOf(j)&&h.stretch(J.stretching,Y,ja.clientWidth,ja.clientHeight,Y.videoWidth,Y.videoHeight)}function G(a){if(J.fullscreen)switch(a.keyCode){case 27:Ba(v)}}function N(a){r||(a?(P.className+=" jwfullscreen",l.getElementsByTagName("body")[0].style["overflow-y"]=u):(P.className=P.className.replace(/\s+jwfullscreen/,""),l.getElementsByTagName("body")[0].style["overflow-y"]= +""))}function T(){var a;a:{a=[l.mozFullScreenElement,l.webkitCurrentFullScreenElement,Y.webkitDisplayingFullscreen];for(var b=0;bc||c>d)}else d=void 0;if(d)return h;d=a.substring(0,a.indexOf("://")+3);var c=a.substring(d.length,a.indexOf("/",d.length+1)),e;0===h.indexOf("/")?e=h.split("/"):(e=a.split("?")[0],e=e.substring(d.length+c.length+1,e.lastIndexOf("/")),e=e.split("/").concat(h.split("/"))); +for(var g=[],m=0;md&&0>c&&(!a||!isNaN(a))?n.CDN:n.RELATIVE}};b.getPluginName=function(a){return a.replace(/^(.*\/)?([^-]*)-?.*\.(swf|js)$/,"$2")};b.getPluginVersion=function(a){return a.replace(/[^-]*-?([^\.]*).*$/,"$1")}; +b.isYouTube=function(a){return-1=d.length&&(d[1]=0);for(var n=a.strToLongs(e.encode(b).slice(0,16)),h=d.length,f=d[h-1],p=d[0],q,j=Math.floor(6+52/h),g=0;0>>2&3;for(var m=0;m>>5^p<<2)+(p>>>3^f<<4)^(g^p)+(n[m&3^q]^f),f=d[m]+=f}d=a.longsToStr(d);return k.encode(d)};a.decrypt=function(c, +b){if(0==c.length)return"";for(var d=a.strToLongs(k.decode(c)),n=a.strToLongs(e.encode(b).slice(0,16)),h=d.length,f=d[h-1],p=d[0],q,j=2654435769*Math.floor(6+52/h);0!=j;){q=j>>>2&3;for(var g=h-1;0<=g;g--)f=d[0>>5^p<<2)+(p>>>3^f<<4)^(j^p)+(n[g&3^q]^f),p=d[g]-=f;j-=2654435769}d=a.longsToStr(d);d=d.replace(/\0+$/,"");return e.decode(d)};a.strToLongs=function(a){for(var b=Array(Math.ceil(a.length/4)),d=0;d>>8&255,a[d]>>>16&255,a[d]>>>24&255);return b.join("")};var k={code:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\x3d",encode:function(a,b){var d,n,h,f,p=[],q="",j,g,m=k.code;g=("undefined"==typeof b?0:b)?e.encode(a):a;j=g.length%3;if(0j++;)q+="\x3d",g+="\x00";for(j=0;j>18&63,n=f>>12&63,h=f>>6&63,f&=63,p[j/3]=m.charAt(d)+m.charAt(n)+m.charAt(h)+m.charAt(f);p=p.join("");return p=p.slice(0,p.length-q.length)+q},decode:function(a,b){b="undefined"==typeof b?!1:b;var d,f,h,r,p,q=[],j,g=k.code;j=b?e.decode(a):a;for(var m=0;m>>16&255,f=h>>>8&255,h&=255,q[m/4]=String.fromCharCode(d,f, +h),64==p&&(q[m/4]=String.fromCharCode(d,f)),64==r&&(q[m/4]=String.fromCharCode(d));r=q.join("");return b?e.decode(r):r}},e={encode:function(a){a=a.replace(/[\u0080-\u07ff]/g,function(a){a=a.charCodeAt(0);return String.fromCharCode(192|a>>6,128|a&63)});return a=a.replace(/[\u0800-\uffff]/g,function(a){a=a.charCodeAt(0);return String.fromCharCode(224|a>>12,128|a>>6&63,128|a&63)})},decode:function(a){a=a.replace(/[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g,function(a){a=(a.charCodeAt(0)&15)<<12| +(a.charCodeAt(1)&63)<<6|a.charCodeAt(2)&63;return String.fromCharCode(a)});return a=a.replace(/[\u00c0-\u00df][\u0080-\u00bf]/g,function(a){a=(a.charCodeAt(0)&31)<<6|a.charCodeAt(1)&63;return String.fromCharCode(a)})}}}(jwplayer.utils),function(f){f.events={COMPLETE:"COMPLETE",ERROR:"ERROR",API_READY:"jwplayerAPIReady",JWPLAYER_READY:"jwplayerReady",JWPLAYER_FULLSCREEN:"jwplayerFullscreen",JWPLAYER_RESIZE:"jwplayerResize",JWPLAYER_ERROR:"jwplayerError",JWPLAYER_SETUP_ERROR:"jwplayerSetupError",JWPLAYER_MEDIA_BEFOREPLAY:"jwplayerMediaBeforePlay", +JWPLAYER_MEDIA_BEFORECOMPLETE:"jwplayerMediaBeforeComplete",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_MEDIA_LEVELS:"jwplayerMediaLevels",JWPLAYER_MEDIA_LEVEL_CHANGED:"jwplayerMediaLevelChanged",JWPLAYER_CAPTIONS_CHANGED:"jwplayerCaptionsChanged",JWPLAYER_CAPTIONS_LIST:"jwplayerCaptionsList",JWPLAYER_PLAYER_STATE:"jwplayerPlayerState",state:{BUFFERING:"BUFFERING",IDLE:"IDLE",PAUSED:"PAUSED",PLAYING:"PLAYING"},JWPLAYER_PLAYLIST_LOADED:"jwplayerPlaylistLoaded",JWPLAYER_PLAYLIST_ITEM:"jwplayerPlaylistItem",JWPLAYER_PLAYLIST_COMPLETE:"jwplayerPlaylistComplete", +JWPLAYER_DISPLAY_CLICK:"jwplayerViewClick",JWPLAYER_CONTROLS:"jwplayerViewControls",JWPLAYER_INSTREAM_CLICK:"jwplayerInstreamClicked",JWPLAYER_INSTREAM_DESTROYED:"jwplayerInstreamDestroyed",JWPLAYER_AD_TIME:"jwplayerAdTime",JWPLAYER_AD_ERROR:"jwplayerAdError",JWPLAYER_AD_CLICK:"jwplayerAdClicked",JWPLAYER_AD_COMPLETE:"jwplayerAdComplete",JWPLAYER_AD_IMPRESSION:"jwplayerAdImpression",JWPLAYER_AD_COMPANIONS:"jwplayerAdCompanions"}}(jwplayer),function(f){var a=jwplayer.utils;f.eventdispatcher=function(f, +e){var c,b;this.resetEventListeners=function(){c={};b=[]};this.resetEventListeners();this.addEventListener=function(b,e,h){try{a.exists(c[b])||(c[b]=[]),"string"==a.typeOf(e)&&(e=(new Function("return "+e))()),c[b].push({listener:e,count:h})}catch(f){a.log("error",f)}return!1};this.removeEventListener=function(b,e){if(c[b]){try{for(var h=0;hparseFloat(f.version)))p=!0,q="Incompatible player version",d()}); +0==b&&d()}}var h=a.loaderstatus.NEW,r=!1,p=!1,q,j=b,g=new k.eventdispatcher;a.extend(this,g);this.setupPlugins=function(b,d,g){var h={length:0,plugins:{}},m=0,f={},j=c.getPlugins();e(d.plugins,function(c,e){var A=a.getPluginName(c),n=j[A],k=n.getFlashPath(),p=n.getJS(),q=n.getURL();k&&(h.plugins[k]=a.extend({},e),h.plugins[k].pluginmode=n.getPluginmode(),h.length++);try{if(p&&d.plugins&&d.plugins[q]){var r=document.createElement("div");r.id=b.id+"_"+A;r.style.position="absolute";r.style.top=0;r.style.zIndex= +m+10;f[A]=n.getNewInstance(b,a.extend({},d.plugins[q]),r);m++;b.onReady(g(f[A],r,!0));b.onResize(g(f[A],r))}}catch(E){a.log("ERROR: Failed to load "+A+".")}});b.plugins=f;return h};this.load=function(){if(!(a.exists(b)&&"object"!=a.typeOf(b))){h=a.loaderstatus.LOADING;e(b,function(b){a.exists(b)&&(b=c.addPlugin(b),b.addEventListener(k.COMPLETE,n),b.addEventListener(k.ERROR,m))});var d=c.getPlugins();e(d,function(a,b){b.load()})}n()};var m=this.pluginFailed=function(){p||(p=!0,q="File not found",d())}; +this.getStatus=function(){return h}}}(jwplayer),function(f){f.playlist=function(a){var k=[];if("array"==f.utils.typeOf(a))for(var e=0;em.playlist.length&&(0==m.playlist.length||!m.playlist[0].sources|| +0==m.playlist[0].sources.length))p();else if(y.getStatus()==a.loaderstatus.COMPLETE){for(var f=0;f=d||0>=c?0:100*(c/d)+"%")}-1==b.width.toString().indexOf("%")?delete b.aspectratio:d?b.aspectratio=d:delete b.aspectratio;return b}).addConfig=function(b,c){a(c);return e.extend(b,c)}}(jwplayer),function(f){var a=f.utils,k=document;f.embed.download=function(e,c,b){function d(b,c){for(var d=k.querySelectorAll(b),e=0;eg)return j.sendEvent(k.ERROR,{message:"Flash version must be 10.0 or greater"}), +!1;var f,l,t=h.config.listbar,u=a.extend({},d);if(c.id+"_wrapper"==c.parentNode.id)f=document.getElementById(c.id+"_wrapper");else{f=document.createElement("div");l=document.createElement("div");l.style.display="none";l.id=c.id+"_aspect";f.id=c.id+"_wrapper";f.style.position="relative";f.style.display="block";f.style.width=a.styleDimension(u.width);f.style.height=a.styleDimension(u.height);if(h.config.aspectratio){var w=parseFloat(h.config.aspectratio);l.style.display="block";l.style.marginTop=h.config.aspectratio; +f.style.height="auto";f.style.display="inline-block";t&&("bottom"==t.position?l.style.paddingBottom=t.size+"px":"right"==t.position&&(l.style.marginBottom=-1*t.size*(w/100)+"px"))}c.parentNode.replaceChild(f,c);f.appendChild(c);f.appendChild(l)}f=n.setupPlugins(h,u,p);0= +u.height?"transparent":"opaque";l="height width modes events primary base fallback volume".split(" ");for(t=0;t and