From: Guillaume Pellerin Date: Mon, 28 Apr 2014 23:00:30 +0000 (+0200) Subject: - server: components moved to server/ X-Git-Tag: 0.5.5~1^2~37^2~3 X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=619baa44c1b7c12dc3bf31427667cb39dc992697;p=timeside.git - server: components moved to server/ - server: sandbox moved to server/sandbox/ - player: static files moved to player/static/timeside/ - bugfixes, cleanup --- diff --git a/tests/sandbox/test_limsi_sad.py b/tests/sandbox/test_limsi_sad.py new file mode 100644 index 0000000..2c54070 --- /dev/null +++ b/tests/sandbox/test_limsi_sad.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- + +import timeside + +decoder = timeside.decoder.FileDecoder('/home/momo/music_local/test/sweep.wav') +analyzer = timeside.analyzer.LimsiSad('etape') +(decoder | analyzer).run() +print analyzer.results() diff --git a/tests/server/__init__.py b/tests/server/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/server/diag.sh b/tests/server/diag.sh deleted file mode 100755 index a76eca4..0000000 --- a/tests/server/diag.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh - -app="timeside" -dir="diagram" - -if [ ! -d $dir ]; then - mkdir $dir -fi - -./manage.py graph_models -a > $dir/$app-all.dot -./manage.py graph_models $app > $dir/$app.dot - -sed -i '/#\ /d' $dir/$app-all.dot -sed -i '/#\ /d' $dir/$app.dot - -dot $dir/$app-all.dot -Tpdf -o $dir/$app-all.pdf -dot $dir/$app.dot -Tpdf -o $dir/$app.pdf - -rsync -a $dir/ doc.parisson.com:/var/www/files/doc/$app/diagram/ diff --git a/tests/server/diagram/timeside.dot b/tests/server/diagram/timeside.dot deleted file mode 100644 index 2f04481..0000000 --- a/tests/server/diagram/timeside.dot +++ /dev/null @@ -1,541 +0,0 @@ -digraph model_graph { - - fontname = "Helvetica" - fontsize = 8 - splines = true - - node [ - fontname = "Helvetica" - fontsize = 8 - shape = "plaintext" - ] - - edge [ - fontname = "Helvetica" - fontsize = 8 - ] - - - - timeside_models_DocBaseResource [label=< - - - - - - - - - - - - - -
- - DocBaseResource
<BaseResource> -
- date_added - - DateTimeField -
- date_modified - - DateTimeField -
- description - - TextField -
- title - - CharField -
- uuid - - CharField -
- >] - - timeside_models_BaseResource [label=< - - - - - - - - - -
- - BaseResource -
- date_added - - DateTimeField -
- date_modified - - DateTimeField -
- uuid - - CharField -
- >] - - timeside_models_Selection [label=< - - - - - - - - - - - - - - - - - -
- - Selection
<DocBaseResource> -
- id - - AutoField -
- author - - ForeignKey (id) -
- date_added - - DateTimeField -
- date_modified - - DateTimeField -
- description - - TextField -
- title - - CharField -
- uuid - - CharField -
- >] - - timeside_models_Item [label=< - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Item
<DocBaseResource> -
- id - - AutoField -
- author - - ForeignKey (id) -
- date_added - - DateTimeField -
- date_modified - - DateTimeField -
- description - - TextField -
- file - - FileField -
- hdf5 - - FileField -
- lock - - BooleanField -
- mime_type - - CharField -
- sha1 - - CharField -
- title - - CharField -
- url - - URLField -
- uuid - - CharField -
- >] - - timeside_models_Experience [label=< - - - - - - - - - - - - - - - - - - - -
- - Experience
<DocBaseResource> -
- id - - AutoField -
- author - - ForeignKey (id) -
- date_added - - DateTimeField -
- date_modified - - DateTimeField -
- description - - TextField -
- is_public - - BooleanField -
- title - - CharField -
- uuid - - CharField -
- >] - - timeside_models_Processor [label=< - - - - - - - - - -
- - Processor -
- id - - AutoField -
- pid - - CharField -
- version - - CharField -
- >] - - timeside_models_Preset [label=< - - - - - - - - - - - -
- - Preset -
- id - - AutoField -
- processor - - ForeignKey (id) -
- is_public - - BooleanField -
- parameters - - TextField -
- >] - - timeside_models_Result [label=< - - - - - - - - - - - - - - - - - - - - - - - -
- - Result
<BaseResource> -
- id - - AutoField -
- item - - ForeignKey (id) -
- preset - - ForeignKey (id) -
- date_added - - DateTimeField -
- date_modified - - DateTimeField -
- file - - FileField -
- hdf5 - - FileField -
- mime_type - - CharField -
- status - - IntegerField -
- uuid - - CharField -
- >] - - timeside_models_Task [label=< - - - - - - - - - - - - - -
- - Task -
- id - - AutoField -
- author - - ForeignKey (id) -
- experience - - ForeignKey (id) -
- selection - - ForeignKey (id) -
- status - - IntegerField -
- >] - - - - - - timeside_models_DocBaseResource -> timeside_models_BaseResource - [label="abstract\ninheritance"] [arrowhead=empty, arrowtail=none, dir=both]; - django_contrib_auth_models_User [label=< - - -
- User -
- >] - timeside_models_Selection -> django_contrib_auth_models_User - [label="author (selections)"] [arrowhead=none, arrowtail=dot, dir=both]; - - timeside_models_Selection -> timeside_models_Item - [label="items (selections)"] [arrowhead=dot arrowtail=dot, dir=both]; - - timeside_models_Selection -> timeside_models_Selection - [label="selections (other_selections)"] [arrowhead=dot arrowtail=dot, dir=both]; - - timeside_models_Selection -> timeside_models_DocBaseResource - [label="abstract\ninheritance"] [arrowhead=empty, arrowtail=none, dir=both]; - django_contrib_auth_models_User [label=< - - -
- User -
- >] - timeside_models_Item -> django_contrib_auth_models_User - [label="author (items)"] [arrowhead=none, arrowtail=dot, dir=both]; - - timeside_models_Item -> timeside_models_DocBaseResource - [label="abstract\ninheritance"] [arrowhead=empty, arrowtail=none, dir=both]; - django_contrib_auth_models_User [label=< - - -
- User -
- >] - timeside_models_Experience -> django_contrib_auth_models_User - [label="author (experiences)"] [arrowhead=none, arrowtail=dot, dir=both]; - - timeside_models_Experience -> timeside_models_Preset - [label="presets (experiences)"] [arrowhead=dot arrowtail=dot, dir=both]; - - timeside_models_Experience -> timeside_models_Experience - [label="experiences (other_experiences)"] [arrowhead=dot arrowtail=dot, dir=both]; - - timeside_models_Experience -> timeside_models_DocBaseResource - [label="abstract\ninheritance"] [arrowhead=empty, arrowtail=none, dir=both]; - - timeside_models_Preset -> timeside_models_Processor - [label="processor (preset)"] [arrowhead=none, arrowtail=dot, dir=both]; - - timeside_models_Result -> timeside_models_Item - [label="item (results)"] [arrowhead=none, arrowtail=dot, dir=both]; - - timeside_models_Result -> timeside_models_Preset - [label="preset (results)"] [arrowhead=none, arrowtail=dot, dir=both]; - - timeside_models_Result -> timeside_models_BaseResource - [label="abstract\ninheritance"] [arrowhead=empty, arrowtail=none, dir=both]; - - timeside_models_Task -> timeside_models_Experience - [label="experience (task)"] [arrowhead=none, arrowtail=dot, dir=both]; - - timeside_models_Task -> timeside_models_Selection - [label="selection (task)"] [arrowhead=none, arrowtail=dot, dir=both]; - django_contrib_auth_models_User [label=< - - -
- User -
- >] - timeside_models_Task -> django_contrib_auth_models_User - [label="author (tasks)"] [arrowhead=none, arrowtail=dot, dir=both]; - -} - diff --git a/tests/server/diagram/timeside.pdf b/tests/server/diagram/timeside.pdf deleted file mode 100644 index 9f72bae..0000000 Binary files a/tests/server/diagram/timeside.pdf and /dev/null differ diff --git a/tests/server/manage.py b/tests/server/manage.py deleted file mode 100755 index f9726f9..0000000 --- a/tests/server/manage.py +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env python -import os -import sys - -if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") - - from django.core.management import execute_from_command_line - - execute_from_command_line(sys.argv) diff --git a/tests/server/settings.py b/tests/server/settings.py deleted file mode 100644 index 057b403..0000000 --- a/tests/server/settings.py +++ /dev/null @@ -1,168 +0,0 @@ -# Django settings for server project. - -DEBUG = True -TEMPLATE_DEBUG = DEBUG - -import os, sys -sys.dont_write_bytecode = True - -ADMINS = ( - # ('Your Name', 'your_email@example.com'), -) - -MANAGERS = ADMINS - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. - 'NAME': 'timeside.sql', # Or path to database file if using sqlite3. - 'USER': '', # Not used with sqlite3. - 'PASSWORD': '', # Not used with sqlite3. - 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. - 'PORT': '', # Set to empty string for default. Not used with sqlite3. - } -} - -# Hosts/domain names that are valid for this site; required if DEBUG is False -# See https://docs.djangoproject.com/en/1.4/ref/settings/#allowed-hosts -ALLOWED_HOSTS = [] - -# Local time zone for this installation. Choices can be found here: -# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name -# although not all choices may be available on all operating systems. -# In a Windows environment this must be set to your system time zone. -TIME_ZONE = 'America/Chicago' - -# Language code for this installation. All choices can be found here: -# http://www.i18nguy.com/unicode/language-identifiers.html -LANGUAGE_CODE = 'en-us' - -SITE_ID = 1 - -# If you set this to False, Django will make some optimizations so as not -# to load the internationalization machinery. -USE_I18N = True - -# If you set this to False, Django will not format dates, numbers and -# calendars according to the current locale. -USE_L10N = True - -# If you set this to False, Django will not use timezone-aware datetimes. -USE_TZ = True - -# Full filesystem path to the project. -PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) - -# Absolute filesystem path to the directory that will hold user-uploaded files. -# Example: "/home/media/media.lawrence.com/media/" -MEDIA_ROOT = PROJECT_ROOT + '/media/' - -# URL that handles the media served from MEDIA_ROOT. Make sure to use a -# trailing slash. -# Examples: "http://media.lawrence.com/media/", "http://example.com/media/" -MEDIA_URL = '' - -# Absolute path to the directory static files should be collected to. -# Don't put anything in this directory yourself; store your static files -# in apps' "static/" subdirectories and in STATICFILES_DIRS. -# Example: "/home/media/media.lawrence.com/static/" -STATIC_ROOT = '' - -# URL prefix for static files. -# Example: "http://media.lawrence.com/static/" -STATIC_URL = '/static/' - -# Additional locations of static files -STATICFILES_DIRS = ( - # Put strings here, like "/home/html/static" or "C:/www/django/static". - # Always use forward slashes, even on Windows. - # Don't forget to use absolute paths, not relative paths. -) - -# List of finder classes that know how to find static files in -# various locations. -STATICFILES_FINDERS = ( - 'django.contrib.staticfiles.finders.FileSystemFinder', - 'django.contrib.staticfiles.finders.AppDirectoriesFinder', -# 'django.contrib.staticfiles.finders.DefaultStorageFinder', -) - -# Make this unique, and don't share it with anybody. -SECRET_KEY = '5%z&a3r@t0=xr2eaio+400qf-32$b5zp897pr*wh5i^s4(-+3(' - -# List of callables that know how to import templates from various sources. -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', -# 'django.template.loaders.eggs.Loader', -) - -MIDDLEWARE_CLASSES = ( - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - # Uncomment the next line for simple clickjacking protection: - # 'django.middleware.clickjacking.XFrameOptionsMiddleware', -) - -ROOT_URLCONF = 'urls' - -# Python dotted path to the WSGI application used by Django's runserver. -WSGI_APPLICATION = 'wsgi.application' - -TEMPLATE_DIRS = ( - # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". - # Always use forward slashes, even on Windows. - # Don't forget to use absolute paths, not relative paths. -) - -INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.messages', - 'django.contrib.staticfiles', - # Uncomment the next line to enable the admin: - 'django.contrib.admin', - # Uncomment the next line to enable admin documentation: - # 'django.contrib.admindocs', - 'django_extensions', - 'south', - 'timeside', - 'rest_framework', -) - -# A sample logging configuration. The only tangible logging -# performed by this configuration is to send an email to -# the site admins on every HTTP 500 error when DEBUG=False. -# See http://docs.djangoproject.com/en/dev/topics/logging for -# more details on how to customize your logging configuration. -LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'filters': { - 'require_debug_false': { - '()': 'django.utils.log.RequireDebugFalse' - } - }, - 'handlers': { - 'mail_admins': { - 'level': 'ERROR', - 'filters': ['require_debug_false'], - 'class': 'django.utils.log.AdminEmailHandler' - } - }, - 'loggers': { - 'django.request': { - 'handlers': ['mail_admins'], - 'level': 'ERROR', - 'propagate': True, - }, - } -} - -REST_FRAMEWORK = { -} \ No newline at end of file diff --git a/tests/server/update_schema.sh b/tests/server/update_schema.sh deleted file mode 100755 index 82d28e9..0000000 --- a/tests/server/update_schema.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -./manage.py schemamigration timeside --auto -./manage.py migrate timeside - diff --git a/tests/server/urls.py b/tests/server/urls.py deleted file mode 100644 index 98374ec..0000000 --- a/tests/server/urls.py +++ /dev/null @@ -1,20 +0,0 @@ -from django.conf.urls import patterns, include, url - -# Uncomment the next two lines to enable the admin: -from django.contrib import admin -admin.autodiscover() - -urlpatterns = patterns('', - - url(r'^', include('timeside.urls')), - - # Examples: - # url(r'^$', 'server.views.home', name='home'), - # url(r'^server/', include('server.foo.urls')), - - # Uncomment the admin/doc line below to enable admin documentation: - # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), - - # Uncomment the next line to enable the admin: - url(r'^admin/', include(admin.site.urls)), -) diff --git a/tests/server/wsgi.py b/tests/server/wsgi.py deleted file mode 100644 index c4ec771..0000000 --- a/tests/server/wsgi.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -WSGI config for server project. - -This module contains the WSGI application used by Django's development server -and any production WSGI deployments. It should expose a module-level variable -named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover -this application via the ``WSGI_APPLICATION`` setting. - -Usually you will have the standard Django WSGI application here, but it also -might make sense to replace the whole Django WSGI application with a custom one -that later delegates to the Django one. For example, you could introduce WSGI -middleware here, or combine a Django application with an application of another -framework. - -""" -import os - -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "server.settings") - -# This application object is used by any WSGI server configured to use this -# file. This includes Django's development server, if the WSGI_APPLICATION -# setting points here. -from django.core.wsgi import get_wsgi_application -application = get_wsgi_application() - -# Apply WSGI middleware here. -# from helloworld.wsgi import HelloWorldApplication -# application = HelloWorldApplication(application) diff --git a/timeside/__init__.py b/timeside/__init__.py index 333a661..2bbc454 100644 --- a/timeside/__init__.py +++ b/timeside/__init__.py @@ -7,4 +7,5 @@ from . import analyzer from . import grapher from . import encoder + __version__ = '0.5.5' diff --git a/timeside/admin.py b/timeside/admin.py deleted file mode 100644 index 9ad18c1..0000000 --- a/timeside/admin.py +++ /dev/null @@ -1,12 +0,0 @@ - -from django.contrib import admin -from timeside.models import * - -admin.site.register(Selection) -admin.site.register(Item) -admin.site.register(Experience) -admin.site.register(Processor) -admin.site.register(Preset) -admin.site.register(Result) -admin.site.register(Task) - diff --git a/timeside/encoder/metadata.py b/timeside/encoder/metadata.py new file mode 100644 index 0000000..86abf87 --- /dev/null +++ b/timeside/encoder/metadata.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2007-2009 Parisson +# Copyright (c) 2007 Olivier Guilyardi +# Copyright (c) 2007-2009 Guillaume Pellerin +# +# This file is part of TimeSide. + +# TimeSide is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. + +# TimeSide is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with TimeSide. If not, see . + +class Metadata(object): + pass + + diff --git a/timeside/metadata.py b/timeside/metadata.py deleted file mode 100644 index 86abf87..0000000 --- a/timeside/metadata.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2007-2009 Parisson -# Copyright (c) 2007 Olivier Guilyardi -# Copyright (c) 2007-2009 Guillaume Pellerin -# -# This file is part of TimeSide. - -# TimeSide is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. - -# TimeSide is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with TimeSide. If not, see . - -class Metadata(object): - pass - - diff --git a/timeside/migrations/0001_initial.py b/timeside/migrations/0001_initial.py deleted file mode 100644 index bba562c..0000000 --- a/timeside/migrations/0001_initial.py +++ /dev/null @@ -1,284 +0,0 @@ -# -*- coding: utf-8 -*- -from south.utils import datetime_utils as datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - # Adding model 'Selection' - db.create_table('timeside_selections', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('date_added', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), - ('date_modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, null=True, blank=True)), - ('uuid', self.gf('django.db.models.fields.CharField')(unique=True, max_length=512, blank=True)), - ('title', self.gf('django.db.models.fields.CharField')(max_length=512, blank=True)), - ('description', self.gf('django.db.models.fields.TextField')(blank=True)), - ('author', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='selections', null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), - )) - db.send_create_signal('timeside', ['Selection']) - - # Adding M2M table for field items on 'Selection' - m2m_table_name = db.shorten_name('timeside_selections_items') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('selection', models.ForeignKey(orm['timeside.selection'], null=False)), - ('item', models.ForeignKey(orm['timeside.item'], null=False)) - )) - db.create_unique(m2m_table_name, ['selection_id', 'item_id']) - - # Adding M2M table for field selections on 'Selection' - m2m_table_name = db.shorten_name('timeside_selections_selections') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('from_selection', models.ForeignKey(orm['timeside.selection'], null=False)), - ('to_selection', models.ForeignKey(orm['timeside.selection'], null=False)) - )) - db.create_unique(m2m_table_name, ['from_selection_id', 'to_selection_id']) - - # Adding model 'Item' - db.create_table('timeside_items', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('date_added', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), - ('date_modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, null=True, blank=True)), - ('uuid', self.gf('django.db.models.fields.CharField')(unique=True, max_length=512, blank=True)), - ('title', self.gf('django.db.models.fields.CharField')(max_length=512, blank=True)), - ('description', self.gf('django.db.models.fields.TextField')(blank=True)), - ('file', self.gf('django.db.models.fields.files.FileField')(max_length=1024, blank=True)), - ('url', self.gf('django.db.models.fields.URLField')(max_length=1024, blank=True)), - ('sha1', self.gf('django.db.models.fields.CharField')(max_length=512, blank=True)), - ('mime_type', self.gf('django.db.models.fields.CharField')(max_length=256, blank=True)), - ('hdf5', self.gf('django.db.models.fields.files.FileField')(max_length=1024, blank=True)), - ('lock', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('author', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='items', null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), - )) - db.send_create_signal('timeside', ['Item']) - - # Adding model 'Experience' - db.create_table('timeside_experiences', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('date_added', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), - ('date_modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, null=True, blank=True)), - ('uuid', self.gf('django.db.models.fields.CharField')(unique=True, max_length=512, blank=True)), - ('title', self.gf('django.db.models.fields.CharField')(max_length=512, blank=True)), - ('description', self.gf('django.db.models.fields.TextField')(blank=True)), - ('author', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='experiences', null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), - ('is_preset', self.gf('django.db.models.fields.BooleanField')(default=False)), - )) - db.send_create_signal('timeside', ['Experience']) - - # Adding M2M table for field processors on 'Experience' - m2m_table_name = db.shorten_name('timeside_experiences_processors') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('experience', models.ForeignKey(orm['timeside.experience'], null=False)), - ('processor', models.ForeignKey(orm['timeside.processor'], null=False)) - )) - db.create_unique(m2m_table_name, ['experience_id', 'processor_id']) - - # Adding M2M table for field experiences on 'Experience' - m2m_table_name = db.shorten_name('timeside_experiences_experiences') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('from_experience', models.ForeignKey(orm['timeside.experience'], null=False)), - ('to_experience', models.ForeignKey(orm['timeside.experience'], null=False)) - )) - db.create_unique(m2m_table_name, ['from_experience_id', 'to_experience_id']) - - # Adding model 'Processor' - db.create_table('timeside_processors', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('pid', self.gf('django.db.models.fields.CharField')(max_length=256)), - ('type', self.gf('django.db.models.fields.CharField')(default='none', max_length=64)), - ('version', self.gf('django.db.models.fields.CharField')(max_length=64, blank=True)), - )) - db.send_create_signal('timeside', ['Processor']) - - # Adding model 'Result' - db.create_table('timeside_results', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('date_added', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), - ('date_modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, null=True, blank=True)), - ('uuid', self.gf('django.db.models.fields.CharField')(unique=True, max_length=512, blank=True)), - ('item', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='results', null=True, on_delete=models.SET_NULL, to=orm['timeside.Item'])), - ('processor', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='results', null=True, on_delete=models.SET_NULL, to=orm['timeside.Processor'])), - ('hdf5', self.gf('django.db.models.fields.files.FileField')(max_length=1024, blank=True)), - ('output', self.gf('django.db.models.fields.files.FileField')(max_length=1024, blank=True)), - ('output_mime_type', self.gf('django.db.models.fields.CharField')(max_length=256, blank=True)), - ('status', self.gf('django.db.models.fields.IntegerField')(default=1)), - )) - db.send_create_signal('timeside', ['Result']) - - # Adding model 'Parameters' - db.create_table('timeside_parameters', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('processor', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='parameters', null=True, to=orm['timeside.Experience'])), - ('parameters', self.gf('django.db.models.fields.TextField')(blank=True)), - ('is_preset', self.gf('django.db.models.fields.BooleanField')(default=False)), - )) - db.send_create_signal('timeside', ['Parameters']) - - # Adding model 'Task' - db.create_table('timeside_tasks', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('experience', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='task', null=True, to=orm['timeside.Experience'])), - ('selection', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='task', null=True, to=orm['timeside.Selection'])), - ('status', self.gf('django.db.models.fields.IntegerField')(default=1)), - ('author', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='tasks', null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), - )) - db.send_create_signal('timeside', ['Task']) - - - def backwards(self, orm): - # Deleting model 'Selection' - db.delete_table('timeside_selections') - - # Removing M2M table for field items on 'Selection' - db.delete_table(db.shorten_name('timeside_selections_items')) - - # Removing M2M table for field selections on 'Selection' - db.delete_table(db.shorten_name('timeside_selections_selections')) - - # Deleting model 'Item' - db.delete_table('timeside_items') - - # Deleting model 'Experience' - db.delete_table('timeside_experiences') - - # Removing M2M table for field processors on 'Experience' - db.delete_table(db.shorten_name('timeside_experiences_processors')) - - # Removing M2M table for field experiences on 'Experience' - db.delete_table(db.shorten_name('timeside_experiences_experiences')) - - # Deleting model 'Processor' - db.delete_table('timeside_processors') - - # Deleting model 'Result' - db.delete_table('timeside_results') - - # Deleting model 'Parameters' - db.delete_table('timeside_parameters') - - # Deleting model 'Task' - db.delete_table('timeside_tasks') - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'timeside.experience': { - 'Meta': {'object_name': 'Experience', 'db_table': "'timeside_experiences'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'experiences'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'experiences': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'other_experiences'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Experience']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_preset': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'processors': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'experiences'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Processor']"}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.item': { - 'Meta': {'ordering': "['title']", 'object_name': 'Item', 'db_table': "'timeside_items'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'items'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'hdf5': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'lock': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), - 'sha1': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.parameters': { - 'Meta': {'object_name': 'Parameters'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_preset': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'parameters': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'processor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parameters'", 'null': 'True', 'to': "orm['timeside.Experience']"}) - }, - 'timeside.processor': { - 'Meta': {'object_name': 'Processor', 'db_table': "'timeside_processors'"}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'pid': ('django.db.models.fields.CharField', [], {'max_length': '256'}), - 'type': ('django.db.models.fields.CharField', [], {'default': "'none'", 'max_length': '64'}), - 'version': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}) - }, - 'timeside.result': { - 'Meta': {'object_name': 'Result', 'db_table': "'timeside_results'"}, - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'hdf5': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'results'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['timeside.Item']"}), - 'output': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'output_mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), - 'processor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'results'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['timeside.Processor']"}), - 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.selection': { - 'Meta': {'object_name': 'Selection', 'db_table': "'timeside_selections'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'selections'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'items': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'selections'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Item']"}), - 'selections': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'other_selections'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Selection']"}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.task': { - 'Meta': {'object_name': 'Task', 'db_table': "'timeside_tasks'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tasks'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'experience': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'task'", 'null': 'True', 'to': "orm['timeside.Experience']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'selection': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'task'", 'null': 'True', 'to': "orm['timeside.Selection']"}), - 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}) - } - } - - complete_apps = ['timeside'] \ No newline at end of file diff --git a/timeside/migrations/0002_auto__chg_field_parameters_processor.py b/timeside/migrations/0002_auto__chg_field_parameters_processor.py deleted file mode 100644 index aea7f91..0000000 --- a/timeside/migrations/0002_auto__chg_field_parameters_processor.py +++ /dev/null @@ -1,135 +0,0 @@ -# -*- coding: utf-8 -*- -from south.utils import datetime_utils as datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - - # Changing field 'Parameters.processor' - db.alter_column('timeside_parameters', 'processor_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['timeside.Processor'])) - - def backwards(self, orm): - - # Changing field 'Parameters.processor' - db.alter_column('timeside_parameters', 'processor_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['timeside.Experience'])) - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'timeside.experience': { - 'Meta': {'object_name': 'Experience', 'db_table': "'timeside_experiences'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'experiences'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'experiences': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'other_experiences'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Experience']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_preset': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'processors': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'experiences'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Processor']"}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.item': { - 'Meta': {'ordering': "['title']", 'object_name': 'Item', 'db_table': "'timeside_items'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'items'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'hdf5': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'lock': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), - 'sha1': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.parameters': { - 'Meta': {'object_name': 'Parameters'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_preset': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'parameters': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'processor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parameters'", 'null': 'True', 'to': "orm['timeside.Processor']"}) - }, - 'timeside.processor': { - 'Meta': {'object_name': 'Processor', 'db_table': "'timeside_processors'"}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'pid': ('django.db.models.fields.CharField', [], {'max_length': '256'}), - 'type': ('django.db.models.fields.CharField', [], {'default': "'none'", 'max_length': '64'}), - 'version': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}) - }, - 'timeside.result': { - 'Meta': {'object_name': 'Result', 'db_table': "'timeside_results'"}, - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'hdf5': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'results'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['timeside.Item']"}), - 'output': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'output_mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), - 'processor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'results'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['timeside.Processor']"}), - 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.selection': { - 'Meta': {'object_name': 'Selection', 'db_table': "'timeside_selections'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'selections'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'items': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'selections'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Item']"}), - 'selections': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'other_selections'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Selection']"}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.task': { - 'Meta': {'object_name': 'Task', 'db_table': "'timeside_tasks'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tasks'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'experience': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'task'", 'null': 'True', 'to': "orm['timeside.Experience']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'selection': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'task'", 'null': 'True', 'to': "orm['timeside.Selection']"}), - 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}) - } - } - - complete_apps = ['timeside'] \ No newline at end of file diff --git a/timeside/migrations/0003_auto__del_field_processor_type.py b/timeside/migrations/0003_auto__del_field_processor_type.py deleted file mode 100644 index 1c5c6a2..0000000 --- a/timeside/migrations/0003_auto__del_field_processor_type.py +++ /dev/null @@ -1,136 +0,0 @@ -# -*- coding: utf-8 -*- -from south.utils import datetime_utils as datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - # Deleting field 'Processor.type' - db.delete_column('timeside_processors', 'type') - - - def backwards(self, orm): - # Adding field 'Processor.type' - db.add_column('timeside_processors', 'type', - self.gf('django.db.models.fields.CharField')(default='none', max_length=64), - keep_default=False) - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'timeside.experience': { - 'Meta': {'object_name': 'Experience', 'db_table': "'timeside_experiences'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'experiences'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'experiences': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'other_experiences'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Experience']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_preset': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'processors': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'experiences'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Processor']"}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.item': { - 'Meta': {'ordering': "['title']", 'object_name': 'Item', 'db_table': "'timeside_items'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'items'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'hdf5': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'lock': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), - 'sha1': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.parameters': { - 'Meta': {'object_name': 'Parameters'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_preset': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'parameters': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'processor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parameters'", 'null': 'True', 'to': "orm['timeside.Processor']"}) - }, - 'timeside.processor': { - 'Meta': {'object_name': 'Processor', 'db_table': "'timeside_processors'"}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'pid': ('django.db.models.fields.CharField', [], {'max_length': '256'}), - 'version': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}) - }, - 'timeside.result': { - 'Meta': {'object_name': 'Result', 'db_table': "'timeside_results'"}, - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'hdf5': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'results'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['timeside.Item']"}), - 'output': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'output_mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), - 'processor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'results'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['timeside.Processor']"}), - 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.selection': { - 'Meta': {'object_name': 'Selection', 'db_table': "'timeside_selections'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'selections'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'items': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'selections'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Item']"}), - 'selections': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'other_selections'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Selection']"}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.task': { - 'Meta': {'object_name': 'Task', 'db_table': "'timeside_tasks'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tasks'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'experience': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'task'", 'null': 'True', 'to': "orm['timeside.Experience']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'selection': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'task'", 'null': 'True', 'to': "orm['timeside.Selection']"}), - 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}) - } - } - - complete_apps = ['timeside'] \ No newline at end of file diff --git a/timeside/migrations/0004_auto__del_field_result_processor__add_field_result_parameters.py b/timeside/migrations/0004_auto__del_field_result_processor__add_field_result_parameters.py deleted file mode 100644 index 6b03bcf..0000000 --- a/timeside/migrations/0004_auto__del_field_result_processor__add_field_result_parameters.py +++ /dev/null @@ -1,144 +0,0 @@ -# -*- coding: utf-8 -*- -from south.utils import datetime_utils as datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - # Deleting field 'Result.processor' - db.delete_column('timeside_results', 'processor_id') - - # Adding field 'Result.parameters' - db.add_column('timeside_results', 'parameters', - self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='results', null=True, on_delete=models.SET_NULL, to=orm['timeside.Parameters']), - keep_default=False) - - - def backwards(self, orm): - # Adding field 'Result.processor' - db.add_column('timeside_results', 'processor', - self.gf('django.db.models.fields.related.ForeignKey')(related_name='results', null=True, to=orm['timeside.Processor'], on_delete=models.SET_NULL, blank=True), - keep_default=False) - - # Deleting field 'Result.parameters' - db.delete_column('timeside_results', 'parameters_id') - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'timeside.experience': { - 'Meta': {'object_name': 'Experience', 'db_table': "'timeside_experiences'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'experiences'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'experiences': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'other_experiences'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Experience']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_preset': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'processors': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'experiences'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Processor']"}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.item': { - 'Meta': {'ordering': "['title']", 'object_name': 'Item', 'db_table': "'timeside_items'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'items'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'hdf5': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'lock': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), - 'sha1': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.parameters': { - 'Meta': {'object_name': 'Parameters'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_preset': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'parameters': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'processor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parameters'", 'null': 'True', 'to': "orm['timeside.Processor']"}) - }, - 'timeside.processor': { - 'Meta': {'object_name': 'Processor', 'db_table': "'timeside_processors'"}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'pid': ('django.db.models.fields.CharField', [], {'max_length': '256'}), - 'version': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}) - }, - 'timeside.result': { - 'Meta': {'object_name': 'Result', 'db_table': "'timeside_results'"}, - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'hdf5': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'results'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['timeside.Item']"}), - 'output': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'output_mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), - 'parameters': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'results'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['timeside.Parameters']"}), - 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.selection': { - 'Meta': {'object_name': 'Selection', 'db_table': "'timeside_selections'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'selections'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'items': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'selections'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Item']"}), - 'selections': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'other_selections'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Selection']"}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.task': { - 'Meta': {'object_name': 'Task', 'db_table': "'timeside_tasks'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tasks'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'experience': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'task'", 'null': 'True', 'to': "orm['timeside.Experience']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'selection': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'task'", 'null': 'True', 'to': "orm['timeside.Selection']"}), - 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}) - } - } - - complete_apps = ['timeside'] \ No newline at end of file diff --git a/timeside/migrations/0005_auto__del_field_result_output_mime_type__del_field_result_output__add_.py b/timeside/migrations/0005_auto__del_field_result_output_mime_type__del_field_result_output__add_.py deleted file mode 100644 index 64dd868..0000000 --- a/timeside/migrations/0005_auto__del_field_result_output_mime_type__del_field_result_output__add_.py +++ /dev/null @@ -1,166 +0,0 @@ -# -*- coding: utf-8 -*- -from south.utils import datetime_utils as datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - # Deleting field 'Result.output_mime_type' - db.delete_column('timeside_results', 'output_mime_type') - - # Deleting field 'Result.output' - db.delete_column('timeside_results', 'output') - - # Adding field 'Result.file' - db.add_column('timeside_results', 'file', - self.gf('django.db.models.fields.files.FileField')(max_length=1024, null=True, blank=True), - keep_default=False) - - # Adding field 'Result.mime_type' - db.add_column('timeside_results', 'mime_type', - self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True), - keep_default=False) - - - # Changing field 'Result.hdf5' - db.alter_column('timeside_results', 'hdf5', self.gf('django.db.models.fields.files.FileField')(max_length=1024, null=True)) - - def backwards(self, orm): - # Adding field 'Result.output_mime_type' - db.add_column('timeside_results', 'output_mime_type', - self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True), - keep_default=False) - - # Adding field 'Result.output' - db.add_column('timeside_results', 'output', - self.gf('django.db.models.fields.files.FileField')(default='foo.bar', max_length=1024, blank=True), - keep_default=False) - - # Deleting field 'Result.file' - db.delete_column('timeside_results', 'file') - - # Deleting field 'Result.mime_type' - db.delete_column('timeside_results', 'mime_type') - - - # Changing field 'Result.hdf5' - db.alter_column('timeside_results', 'hdf5', self.gf('django.db.models.fields.files.FileField')(default='foo.bar', max_length=1024)) - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'timeside.experience': { - 'Meta': {'object_name': 'Experience', 'db_table': "'timeside_experiences'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'experiences'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'experiences': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'other_experiences'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Experience']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_preset': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'processors': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'experiences'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Processor']"}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.item': { - 'Meta': {'ordering': "['title']", 'object_name': 'Item', 'db_table': "'timeside_items'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'items'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'hdf5': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'lock': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), - 'sha1': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.parameters': { - 'Meta': {'object_name': 'Parameters'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_preset': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'parameters': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'processor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'parameters'", 'null': 'True', 'to': "orm['timeside.Processor']"}) - }, - 'timeside.processor': { - 'Meta': {'object_name': 'Processor', 'db_table': "'timeside_processors'"}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'pid': ('django.db.models.fields.CharField', [], {'max_length': '256'}), - 'version': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}) - }, - 'timeside.result': { - 'Meta': {'object_name': 'Result', 'db_table': "'timeside_results'"}, - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), - 'hdf5': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'results'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['timeside.Item']"}), - 'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), - 'parameters': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'results'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['timeside.Parameters']"}), - 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.selection': { - 'Meta': {'object_name': 'Selection', 'db_table': "'timeside_selections'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'selections'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'items': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'selections'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Item']"}), - 'selections': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'other_selections'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Selection']"}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.task': { - 'Meta': {'object_name': 'Task', 'db_table': "'timeside_tasks'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tasks'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'experience': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'task'", 'null': 'True', 'to': "orm['timeside.Experience']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'selection': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'task'", 'null': 'True', 'to': "orm['timeside.Selection']"}), - 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}) - } - } - - complete_apps = ['timeside'] \ No newline at end of file diff --git a/timeside/migrations/0006_auto__del_parameters__add_preset__del_field_result_parameters__add_fie.py b/timeside/migrations/0006_auto__del_parameters__add_preset__del_field_result_parameters__add_fie.py deleted file mode 100644 index 5f9d3fe..0000000 --- a/timeside/migrations/0006_auto__del_parameters__add_preset__del_field_result_parameters__add_fie.py +++ /dev/null @@ -1,220 +0,0 @@ -# -*- coding: utf-8 -*- -from south.utils import datetime_utils as datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - # Deleting model 'Parameters' - db.delete_table('timeside_parameters') - - # Adding model 'Preset' - db.create_table('timeside_presets', ( - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('processor', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='preset', null=True, to=orm['timeside.Processor'])), - ('parameters', self.gf('django.db.models.fields.TextField')(blank=True)), - ('is_public', self.gf('django.db.models.fields.BooleanField')(default=False)), - )) - db.send_create_signal('timeside', ['Preset']) - - # Deleting field 'Result.parameters' - db.delete_column('timeside_results', 'parameters_id') - - # Adding field 'Result.preset' - db.add_column('timeside_results', 'preset', - self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='results', null=True, on_delete=models.SET_NULL, to=orm['timeside.Preset']), - keep_default=False) - - - # Changing field 'Result.hdf5' - db.alter_column('timeside_results', 'hdf5', self.gf('django.db.models.fields.files.FileField')(default=0, max_length=1024)) - - # Changing field 'Result.file' - db.alter_column('timeside_results', 'file', self.gf('django.db.models.fields.files.FileField')(default=0, max_length=1024)) - # Deleting field 'Experience.is_preset' - db.delete_column('timeside_experiences', 'is_preset') - - # Adding field 'Experience.is_public' - db.add_column('timeside_experiences', 'is_public', - self.gf('django.db.models.fields.BooleanField')(default=False), - keep_default=False) - - # Removing M2M table for field processors on 'Experience' - db.delete_table(db.shorten_name('timeside_experiences_processors')) - - # Adding M2M table for field presets on 'Experience' - m2m_table_name = db.shorten_name('timeside_experiences_presets') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('experience', models.ForeignKey(orm['timeside.experience'], null=False)), - ('preset', models.ForeignKey(orm['timeside.preset'], null=False)) - )) - db.create_unique(m2m_table_name, ['experience_id', 'preset_id']) - - - def backwards(self, orm): - # Adding model 'Parameters' - db.create_table('timeside_parameters', ( - ('parameters', self.gf('django.db.models.fields.TextField')(blank=True)), - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('is_preset', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('processor', self.gf('django.db.models.fields.related.ForeignKey')(related_name='parameters', null=True, to=orm['timeside.Processor'], blank=True)), - )) - db.send_create_signal('timeside', ['Parameters']) - - # Deleting model 'Preset' - db.delete_table('timeside_presets') - - # Adding field 'Result.parameters' - db.add_column('timeside_results', 'parameters', - self.gf('django.db.models.fields.related.ForeignKey')(related_name='results', null=True, to=orm['timeside.Parameters'], on_delete=models.SET_NULL, blank=True), - keep_default=False) - - # Deleting field 'Result.preset' - db.delete_column('timeside_results', 'preset_id') - - - # Changing field 'Result.hdf5' - db.alter_column('timeside_results', 'hdf5', self.gf('django.db.models.fields.files.FileField')(max_length=1024, null=True)) - - # Changing field 'Result.file' - db.alter_column('timeside_results', 'file', self.gf('django.db.models.fields.files.FileField')(max_length=1024, null=True)) - # Adding field 'Experience.is_preset' - db.add_column('timeside_experiences', 'is_preset', - self.gf('django.db.models.fields.BooleanField')(default=False), - keep_default=False) - - # Deleting field 'Experience.is_public' - db.delete_column('timeside_experiences', 'is_public') - - # Adding M2M table for field processors on 'Experience' - m2m_table_name = db.shorten_name('timeside_experiences_processors') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('experience', models.ForeignKey(orm['timeside.experience'], null=False)), - ('processor', models.ForeignKey(orm['timeside.processor'], null=False)) - )) - db.create_unique(m2m_table_name, ['experience_id', 'processor_id']) - - # Removing M2M table for field presets on 'Experience' - db.delete_table(db.shorten_name('timeside_experiences_presets')) - - - models = { - 'auth.group': { - 'Meta': {'object_name': 'Group'}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'auth.permission': { - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - 'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'timeside.experience': { - 'Meta': {'object_name': 'Experience', 'db_table': "'timeside_experiences'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'experiences'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'experiences': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'other_experiences'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Experience']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'presets': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'experiences'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Preset']"}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.item': { - 'Meta': {'ordering': "['title']", 'object_name': 'Item', 'db_table': "'timeside_items'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'items'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'hdf5': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'lock': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), - 'sha1': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.preset': { - 'Meta': {'object_name': 'Preset', 'db_table': "'timeside_presets'"}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'parameters': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'processor': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'preset'", 'null': 'True', 'to': "orm['timeside.Processor']"}) - }, - 'timeside.processor': { - 'Meta': {'object_name': 'Processor', 'db_table': "'timeside_processors'"}, - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'pid': ('django.db.models.fields.CharField', [], {'max_length': '256'}), - 'version': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}) - }, - 'timeside.result': { - 'Meta': {'object_name': 'Result', 'db_table': "'timeside_results'"}, - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'hdf5': ('django.db.models.fields.files.FileField', [], {'max_length': '1024', 'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'item': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'results'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['timeside.Item']"}), - 'mime_type': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), - 'preset': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'results'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['timeside.Preset']"}), - 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.selection': { - 'Meta': {'object_name': 'Selection', 'db_table': "'timeside_selections'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'selections'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'date_added': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'date_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'null': 'True', 'blank': 'True'}), - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'items': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'selections'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Item']"}), - 'selections': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'other_selections'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['timeside.Selection']"}), - 'title': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), - 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512', 'blank': 'True'}) - }, - 'timeside.task': { - 'Meta': {'object_name': 'Task', 'db_table': "'timeside_tasks'"}, - 'author': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'tasks'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['auth.User']"}), - 'experience': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'task'", 'null': 'True', 'to': "orm['timeside.Experience']"}), - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'selection': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'task'", 'null': 'True', 'to': "orm['timeside.Selection']"}), - 'status': ('django.db.models.fields.IntegerField', [], {'default': '1'}) - } - } - - complete_apps = ['timeside'] \ No newline at end of file diff --git a/timeside/migrations/__init__.py b/timeside/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/timeside/models.py b/timeside/models.py deleted file mode 100644 index 67052b4..0000000 --- a/timeside/models.py +++ /dev/null @@ -1,263 +0,0 @@ -# -*- coding: utf-8 -*- - -import timeside, os, uuid, time, hashlib, mimetypes - -from timeside.analyzer.core import AnalyzerResultContainer, AnalyzerResult -from timeside.decoder.utils import sha1sum_file - -from django.db import models -from django.utils.translation import ugettext_lazy as _ -from django.contrib.auth.models import User -from django.db.models.signals import post_save -from django.conf import settings - -app = 'timeside' - -processors = timeside.core.processors(timeside.api.IProcessor) - -PROCESSOR_PIDS = [(processor.id(), processor.id()) for processor in processors] - -STATUS = ((0, _('failed')), (1, _('pending')), (2, _('running')), - (3, _('done')), (4, _('ready'))) - -def get_mime_type(path): - return mimetypes.guess_type(path)[0] - -def get_processor(pid): - for proc in processors: - if proc.id() == pid: - return proc() - raise ValueError('Processor %s does not exists' % pid) - -def set_mimetype(sender, **kwargs): - instance = kwargs['instance'] - if instance.file: - if not instance.mime_type: - instance.mime_type = get_mime_type(instance.file.path) - -def set_hash(sender, **kwargs): - instance = kwargs['instance'] - if instance.file: - if not instance.sha1: - instance.sha1 = sha1sum_file(instance.file.path) - -class MetaCore: - - app_label = app - - -class BaseResource(models.Model): - - date_added = models.DateTimeField(_('date added'), auto_now_add=True) - date_modified = models.DateTimeField(_('date modified'), auto_now=True, null=True) - uuid = models.CharField(_('uuid'), unique=True, blank=True, max_length=512, editable=False) - - class Meta(MetaCore): - abstract = True - - def save(self, **kwargs): - if not self.uuid: - self.uuid = uuid.uuid4() - super(BaseResource, self).save(**kwargs) - - -class DocBaseResource(BaseResource): - - title = models.CharField(_('title'), blank=True, max_length=512) - description = models.TextField(_('description'), blank=True) - - def __unicode__(self): - return self.title - - class Meta(MetaCore): - abstract = True - - -class Selection(DocBaseResource): - - items = models.ManyToManyField('Item', related_name="selections", verbose_name=_('items'), blank=True, null=True) - author = models.ForeignKey(User, related_name="selections", verbose_name=_('author'), blank=True, null=True, on_delete=models.SET_NULL) - selections = models.ManyToManyField('Selection', related_name="other_selections", verbose_name=_('other selections'), blank=True, null=True) - - class Meta(MetaCore): - db_table = app + '_selections' - verbose_name = _('selection') - - -class Item(DocBaseResource): - - file = models.FileField(_('file'), upload_to='items/%Y/%m/%d', blank=True, max_length=1024) - url = models.URLField(_('URL'), blank=True, max_length=1024) - sha1 = models.CharField(_('sha1'), blank=True, max_length=512) - mime_type = models.CharField(_('mime type'), blank=True, max_length=256) - hdf5 = models.FileField(_('HDF5 result file'), upload_to='results/%Y/%m/%d', blank=True, max_length=1024) - lock = models.BooleanField(default=False) - author = models.ForeignKey(User, related_name="items", verbose_name=_('author'), blank=True, null=True, on_delete=models.SET_NULL) - - class Meta(MetaCore): - db_table = app + '_items' - ordering = ['title'] - verbose_name = _('item') - - def results(self): - return [result for result in self.results.all()] - - def lock_setter(self, lock): - self.lock = lock - self.save() - - -class Experience(DocBaseResource): - - presets = models.ManyToManyField('Preset', related_name="experiences", verbose_name=_('presets'), blank=True, null=True) - author = models.ForeignKey(User, related_name="experiences", verbose_name=_('author'), blank=True, null=True, on_delete=models.SET_NULL) - experiences = models.ManyToManyField('Experience', related_name="other_experiences", verbose_name=_('other experiences'), blank=True, null=True) - is_public = models.BooleanField(default=False) - - class Meta(MetaCore): - db_table = app + '_experiences' - verbose_name = _('Experience') - - - -class Processor(models.Model): - - pid = models.CharField(_('pid'), choices=PROCESSOR_PIDS, max_length=256) - version = models.CharField(_('version'), max_length=64, blank=True) - - class Meta(MetaCore): - db_table = app + '_processors' - verbose_name = _('processor') - - def __unicode__(self): - return '_'.join([self.pid, str(self.id)]) - - def save(self, **kwargs): - if not self.version: - self.version = timeside.__version__ - super(Processor, self).save(**kwargs) - - -class Preset(models.Model): - - processor = models.ForeignKey('Processor', related_name="preset", verbose_name=_('processor'), blank=True, null=True) - parameters = models.TextField(_('Parameters'), blank=True) - is_public = models.BooleanField(default=False) - - class Meta: - db_table = app + '_presets' - verbose_name = _('Preset') - verbose_name_plural = _('Presets') - - def __unicode__(self): - return '_'.join([unicode(self.processor), str(self.id)]) - - -class Result(BaseResource): - - item = models.ForeignKey('Item', related_name="results", verbose_name=_('item'), blank=True, null=True, on_delete=models.SET_NULL) - preset = models.ForeignKey('Preset', related_name="results", verbose_name=_('preset'), blank=True, null=True, on_delete=models.SET_NULL) - hdf5 = models.FileField(_('HDF5 result file'), upload_to='results/%Y/%m/%d', blank=True, max_length=1024) - file = models.FileField(_('Output file'), upload_to='results/%Y/%m/%d', blank=True, max_length=1024) - mime_type = models.CharField(_('Output file MIME type'), blank=True, max_length=256) - status = models.IntegerField(_('status'), choices=STATUS, default=1) - - class Meta(MetaCore): - db_table = app + '_results' - verbose_name = _('Result') - verbose_name_plural = _('Results') - - def status_setter(self, status): - self.status = status - self.save() - - def __unicode__(self): - return '_'.join([self.item.title, unicode(self.parameters.processor)]) - - -class Task(models.Model): - - experience = models.ForeignKey('Experience', related_name="task", verbose_name=_('experience'), blank=True, null=True) - selection = models.ForeignKey('Selection', related_name="task", verbose_name=_('selection'), blank=True, null=True) - status = models.IntegerField(_('status'), choices=STATUS, default=1) - author = models.ForeignKey(User, related_name="tasks", verbose_name=_('author'), blank=True, null=True, on_delete=models.SET_NULL) - - class Meta(MetaCore): - db_table = app + '_tasks' - verbose_name = _('Task') - verbose_name_plural = _('Tasks') - - def __unicode__(self): - return '_'.join([unicode(self.experience), unicode(self.id)]) - - def status_setter(self, status): - self.status = status - self.save() - - def run(self): - results_root = 'results' - if not os.path.exists(settings.MEDIA_ROOT + results_root): - os.makedirs(settings.MEDIA_ROOT + results_root) - - self.status_setter(2) - - for item in self.selection.items.all(): - path = results_root + os.sep + item.uuid + os.sep - if not os.path.exists(settings.MEDIA_ROOT + os.sep + path): - os.makedirs(settings.MEDIA_ROOT + os.sep + path) - - # pipe = timeside.decoder.FileDecoder(item.file.path, sha1=item.sha1) - pipe = timeside.decoder.FileDecoder(item.file.path) - - proc_dict = {} - - for preset in self.experience.presets.all(): - proc = get_processor(preset.processor.pid) - proc_dict[preset.processor] = proc - #proc.set_parameters(preset.parameters) - pipe = pipe | proc - - # while item.lock: - # time.sleep(30) - - if not item.hdf5: - item.hdf5 = path + item.uuid + '.hdf5' - item.save() - - pipe.run() - item.lock_setter(True) - pipe.results.to_hdf5(item.hdf5.path) - item.lock_setter(False) - - for processor in proc_dict.keys(): - proc = proc_dict[processor] - - for processor_id in proc.results.keys(): - parameters = proc.results[processor_id].parameters - preset, c = Preset.objects.get_or_create(processor=processor, parameters=unicode(parameters)) - result, c = Result.objects.get_or_create(preset=preset, item=item) - - if proc.type == 'analyzer': - result.hdf5 = path + item.uuid + '_' + str(proc.UUID) + '.hdf5' - proc.results.to_hdf5(result.hdf5.path) - - if proc.type == 'grapher': - result.file = path + item.uuid + '_' + str(proc.UUID) + '.png' - proc.render(output=result.file) - - result.save() - - # except: - # self.status_setter(0) - # item.lock_setter(False) - # break - - self.status_setter(3) - del proc - del pipe - - -post_save.connect(set_mimetype, sender=Item) -post_save.connect(set_hash, sender=Item) -post_save.connect(set_mimetype, sender=Result) - diff --git a/timeside/player/__init__.py b/timeside/player/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/timeside/player/static/timeside/README.rst b/timeside/player/static/timeside/README.rst new file mode 100644 index 0000000..241b18b --- /dev/null +++ b/timeside/player/static/timeside/README.rst @@ -0,0 +1,30 @@ +=================== +TimeSide UI +=================== + +Please refer to http://code.google.com/p/timeside/wiki/UiGuide for an exhaustive guide. + +Provides +========= + +* SoundManager 2 >= 2.97 : http://www.schillmania.com/projects/soundmanager2 +* jQuery => 1.6 : http://www.jquery.com +* Raphael (ADDED AUTOMATICALLY, DO NOT ADD YOURSELF) => 1.52 http://raphaeljs.com/ + + +Licensing +========= + +Copyright (c) 2009-2011 Parisson SARL + +Copyright (c) 2008-2009 Samalyse + +Copyright (c) 2011 Riccardo Zaccarelli + +Authors: + + * Riccardo Zaccarelli + * Olivier Guilyardi + +TimeSide is released under the terms of the GNU General Public License +version 2. Please see the LICENSE file for details. diff --git a/timeside/player/static/timeside/js/libs/jquery-1.6.min.js b/timeside/player/static/timeside/js/libs/jquery-1.6.min.js new file mode 100644 index 0000000..c72011d --- /dev/null +++ b/timeside/player/static/timeside/js/libs/jquery-1.6.min.js @@ -0,0 +1,16 @@ +/*! + * jQuery JavaScript Library v1.6 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon May 2 13:50:00 2011 -0400 + */ +(function(a,b){function cw(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function ct(a){if(!ch[a]){var b=f("<"+a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d===""){ci||(ci=c.createElement("iframe"),ci.frameBorder=ci.width=ci.height=0),c.body.appendChild(ci);if(!cj||!ci.createElement)cj=(ci.contentWindow||ci.contentDocument).document,cj.write("");b=cj.createElement(a),cj.body.appendChild(b),d=f.css(b,"display"),c.body.removeChild(ci)}ch[a]=d}return ch[a]}function cs(a,b){var c={};f.each(cn.concat.apply([],cn.slice(0,b)),function(){c[this]=a});return c}function cr(){co=b}function cq(){setTimeout(cr,0);return co=f.now()}function cg(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function cf(){try{return new a.XMLHttpRequest}catch(b){}}function b_(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(a,b){return(a&&a!=="*"?a+".":"")+b.replace(z,"`").replace(A,"&")}function M(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;ic)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function K(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function E(){return!0}function D(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){name="data-"+c.replace(j,"$1-$2").toLowerCase(),d=a.getAttribute(name);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(e){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function H(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(H,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=d.userAgent,x,y,z,A=Object.prototype.toString,B=Object.prototype.hasOwnProperty,C=Array.prototype.push,D=Array.prototype.slice,E=String.prototype.trim,F=Array.prototype.indexOf,G={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?g=[null,a,null]:g=i.exec(a);if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6",length:0,size:function(){return this.length},toArray:function(){return D.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?C.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),y.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(D.apply(this,arguments),"slice",D.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:C,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;y.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!y){y=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",z,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",z),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&H()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):G[A.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!B.call(a,"constructor")&&!B.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||B.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c
a",b=a.getElementsByTagName("*"),d=a.getElementsByTagName("a")[0];if(!b||!b.length||!d)return{};e=c.createElement("select"),f=e.appendChild(c.createElement("option")),g=a.getElementsByTagName("input")[0],i={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.55$/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:g.value==="on",optSelected:f.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},g.checked=!0,i.noCloneChecked=g.cloneNode(!0).checked,e.disabled=!0,i.optDisabled=!f.disabled;try{delete a.test}catch(r){i.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function click(){i.noCloneEvent=!1,a.detachEvent("onclick",click)}),a.cloneNode(!0).fireEvent("onclick")),g=c.createElement("input"),g.value="t",g.setAttribute("type","radio"),i.radioValue=g.value==="t",g.setAttribute("checked","checked"),a.appendChild(g),j=c.createDocumentFragment(),j.appendChild(a.firstChild),i.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",k=c.createElement("body"),l={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"};for(p in l)k.style[p]=l[p];k.appendChild(a),c.documentElement.appendChild(k),i.appendChecked=g.checked,i.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,i.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
",i.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
t
",m=a.getElementsByTagName("td"),q=m[0].offsetHeight===0,m[0].style.display="",m[1].style.display="none",i.reliableHiddenOffsets=q&&m[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(h=c.createElement("div"),h.style.width="0",h.style.marginRight="0",a.appendChild(h),i.reliableMarginRight=(parseInt(c.defaultView.getComputedStyle(h,null).marginRight,10)||0)===0),k.innerHTML="",c.documentElement.removeChild(k);if(a.attachEvent)for(p in{submit:1,change:1,focusin:1})o="on"+p,q=o in a,q||(a.setAttribute(o,"return;"),q=typeof a[o]=="function"),i[p+"Bubbles"]=q;return i}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[c]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[c]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;return(e.value||"").replace(p,"")}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||"set"in c&&c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b=a.selectedIndex,c=[],d=a.options,e=a.type==="select-one";if(b<0)return null;for(var g=e?b:0,h=e?b+1:d.length;g=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex",readonly:"readOnly"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);var h,i,j=g!==1||!f.isXMLDoc(a);c=j&&f.attrFix[c]||c,i=f.attrHooks[c]||(v&&(f.nodeName(a,"form")||u.test(c))?v:b);if(d!==b){if(d===null||d===!1&&!t.test(c)){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;d===!0&&!t.test(c)&&(d=c),a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j)return i.get(a,c);h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.getAttribute("value");a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}}},propFix:{},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);c=i&&f.propFix[c]||c,h=f.propHooks[c];return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),f.support.getSetAttribute||(f.attrFix=f.extend(f.attrFix,{"for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder"}),v=f.attrHooks.name=f.attrHooks.value=f.valHooks.button={get:function(a,c){var d;if(c==="value"&&!f.nodeName(a,"button"))return a.getAttribute(c);d=a.getAttributeNode(c);return d&&d.specified?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var w=Object.prototype.hasOwnProperty,x=/\.(.*)$/,y=/^(?:textarea|input|select)$/i,z=/\./g,A=/ /g,B=/[^\w\s.|`]/g,C=function(a){return a.replace(B,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=D;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=D);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),C).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},J=function J(a){var c=a.target,d,e;if(!!y.test(c.nodeName)&&!c.readOnly){d=f._data(c,"_change_data"),e=I(c),(a.type!=="focusout"||c.type!=="radio")&&f._data(c,"_change_data",e);if(d===b||e===d)return;if(d!=null||e)a.type="change",a.liveFired=b,f.event.trigger(a,arguments[1],c)}};f.event.special.change={filters:{focusout:J,beforedeactivate:J,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&J.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&J.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",I(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in H)f.event.add(this,c+".specialChange",H[c]);return y.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return y.test(this.nodeName)}},H=f.event.special.change.filters,H.focus=H.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){return a.nodeName.toLowerCase()==="input"&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(h=g;h0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=T.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var X=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,Z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,$=/<([\w:]+)/,_=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};be.optgroup=be.option,be.tbody=be.tfoot=be.colgroup=be.caption=be.thead,be.th=be.td,f.support.htmlSerialize||(be._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(X,""):null;if(typeof a=="string"&&!bb.test(a)&&(f.support.leadingWhitespace||!Y.test(a))&&!be[($.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Z,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bh(a,d),e=bi(a),g=bi(d);for(h=0;e[h];++h)bh(e[h],g[h])}if(b){bg(a,d);if(c){e=bi(a),g=bi(d);for(h=0;e[h];++h)bg(e[h],g[h])}}return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[];for(var i=0,j;(j=a[i])!=null;i++){typeof j=="number"&&(j+="");if(!j)continue;if(typeof j=="string")if(!ba.test(j))j=b.createTextNode(j);else{j=j.replace(Z,"<$1>");var k=($.exec(j)||["",""])[1].toLowerCase(),l=be[k]||be._default,m=l[0],n=b.createElement("div");n.innerHTML=l[1]+j+l[2];while(m--)n=n.lastChild;if(!f.support.tbody){var o=_.test(j),p=k==="table"&&!o?n.firstChild&&n.firstChild.childNodes:l[1]===""&&!o?n.childNodes:[];for(var q=p.length-1;q>=0;--q)f.nodeName(p[q],"tbody")&&!p[q].childNodes.length&&p[q].parentNode.removeChild(p[q])}!f.support.leadingWhitespace&&Y.test(j)&&n.insertBefore(b.createTextNode(Y.exec(j)[0]),n.firstChild),j=n.childNodes}var r;if(!f.support.appendChecked)if(j[0]&&typeof (r=j.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bn.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bm.test(g)?g.replace(bm,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bx(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(by=function(a,c){var d,e,g;c=c.replace(bp,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bz=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bq.test(d)&&br.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bx=by||bz,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV;try{bU=e.href}catch(bW){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bX(bS),ajaxTransport:bX(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?b$(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=b_(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bY(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bY(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bZ(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var ca=f.now(),cb=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+ca++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cb.test(b.url)||e&&cb.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cb,l),b.url===j&&(e&&(k=k.replace(cb,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cc=a.ActiveXObject?function(){for(var a in ce)ce[a](0,1)}:!1,cd=0,ce;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cf()||cg()}:cf,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cc&&delete ce[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cd,cc&&(ce||(ce={},f(a).unload(cc)),ce[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ch={},ci,cj,ck=/^(?:toggle|show|hide)$/,cl=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cm,cn=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],co,cp=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cs("show",3),a,b,c);for(var g=0,h=this.length;g=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a=f.timers,b=a.length;while(b--)a[b]()||a.splice(b,1);a.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cm),cm=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cu=/^t(?:able|d|h)$/i,cv=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cw(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);f.offset.initialize();var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.offset.doesNotAddBorder&&(!f.offset.doesAddBorderForTableAndCells||!cu.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={initialize:function(){var a=c.body,b=c.createElement("div"),d,e,g,h,i=parseFloat(f.css(a,"marginTop"))||0,j="
";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cv.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cv.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cw(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cw(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){return this[0]?parseFloat(f.css(this[0],d,"padding")):null},f.fn["outer"+c]=function(a){return this[0]?parseFloat(f.css(this[0],d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window); \ No newline at end of file diff --git a/timeside/player/static/timeside/js/libs/raphael-min.js b/timeside/player/static/timeside/js/libs/raphael-min.js new file mode 100644 index 0000000..e5e7126 --- /dev/null +++ b/timeside/player/static/timeside/js/libs/raphael-min.js @@ -0,0 +1,7 @@ +/* + * Raphael 1.5.2 - JavaScript Vector Library + * + * Copyright (c) 2010 Dmitry Baranovskiy (http://raphaeljs.com) + * Licensed under the MIT (http://raphaeljs.com/license.html) license. + */ +(function(){function a(){if(a.is(arguments[0],G)){var b=arguments[0],d=bV[m](a,b.splice(0,3+a.is(b[0],E))),e=d.set();for(var g=0,h=b[w];g";bg=bf.firstChild;bg.style.behavior="url(#default#VML)";if(!(bg&&typeof bg.adj=="object"))return a.type=null;bf=null}a.svg=!(a.vml=a.type=="VML");j[e]=a[e];k=j[e];a._id=0;a._oid=0;a.fn={};a.is=function(a,b){b=x.call(b);if(b=="finite")return!O[f](+a);return b=="null"&&a===null||b==typeof a||b=="object"&&a===Object(a)||b=="array"&&Array.isArray&&Array.isArray(a)||J.call(a).slice(8,-1).toLowerCase()==b};a.angle=function(b,c,d,e,f,g){{if(f==null){var h=b-d,i=c-e;if(!h&&!i)return 0;return((h<0)*180+y.atan(-i/-h)*180/D+360)%360}return a.angle(b,c,f,g)-a.angle(d,e,f,g)}};a.rad=function(a){return a%360*D/180};a.deg=function(a){return a*180/D%360};a.snapTo=function(b,c,d){d=a.is(d,"finite")?d:10;if(a.is(b,G)){var e=b.length;while(e--)if(B(b[e]-c)<=d)return b[e]}else{b=+b;var f=c%b;if(fb-d)return c-f+b}return c};function bh(){var a=[],b=0;for(;b<32;b++)a[b]=(~(~(y.random()*16)))[H](16);a[12]=4;a[16]=(a[16]&3|8)[H](16);return"r-"+a[v]("")}a.setWindow=function(a){h=a;g=h.document};var bi=function(b){if(a.vml){var c=/^\s+|\s+$/g,d;try{var e=new ActiveXObject("htmlfile");e.write("");e.close();d=e.body}catch(a){d=createPopup().document.body}var f=d.createTextRange();bi=bm(function(a){try{d.style.color=r(a)[Y](c,p);var b=f.queryCommandValue("ForeColor");b=(b&255)<<16|b&65280|(b&16711680)>>>16;return"#"+("000000"+b[H](16)).slice(-6)}catch(a){return"none"}})}else{var h=g.createElement("i");h.title="Raphaël Colour Picker";h.style.display="none";g.body[l](h);bi=bm(function(a){h.style.color=a;return g.defaultView.getComputedStyle(h,p).getPropertyValue("color")})}return bi(b)},bj=function(){return"hsb("+[this.h,this.s,this.b]+")"},bk=function(){return"hsl("+[this.h,this.s,this.l]+")"},bl=function(){return this.hex};a.hsb2rgb=function(b,c,d,e){if(a.is(b,"object")&&"h"in b&&"s"in b&&"b"in b){d=b.b;c=b.s;b=b.h;e=b.o}return a.hsl2rgb(b,c,d/2,e)};a.hsl2rgb=function(b,c,d,e){if(a.is(b,"object")&&"h"in b&&"s"in b&&"l"in b){d=b.l;c=b.s;b=b.h}if(b>1||c>1||d>1){b/=360;c/=100;d/=100}var f={},g=["r","g","b"],h,i,j,k,l,m;if(c){d<0.5?h=d*(1+c):h=d+c-d*c;i=2*d-h;for(var n=0;n<3;n++){j=b+1/3*-(n-1);j<0&&j++;j>1&&j--;j*6<1?f[g[n]]=i+(h-i)*6*j:j*2<1?f[g[n]]=h:j*3<2?f[g[n]]=i+(h-i)*(2/3-j)*6:f[g[n]]=i}}else f={r:d,g:d,b:d};f.r*=255;f.g*=255;f.b*=255;f.hex="#"+(16777216|f.b|f.g<<8|f.r<<16).toString(16).slice(1);a.is(e,"finite")&&(f.opacity=e);f.toString=bl;return f};a.rgb2hsb=function(b,c,d){if(c==null&&a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b){d=b.b;c=b.g;b=b.r}if(c==null&&a.is(b,F)){var e=a.getRGB(b);b=e.r;c=e.g;d=e.b}if(b>1||c>1||d>1){b/=255;c/=255;d/=255}var f=z(b,c,d),g=A(b,c,d),h,i,j=f;{if(g==f)return{h:0,s:0,b:f,toString:bj};var k=f-g;i=k/f;b==f?h=(c-d)/k:c==f?h=2+(d-b)/k:h=4+(b-c)/k;h/=6;h<0&&h++;h>1&&h--}return{h:h,s:i,b:j,toString:bj}};a.rgb2hsl=function(b,c,d){if(c==null&&a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b){d=b.b;c=b.g;b=b.r}if(c==null&&a.is(b,F)){var e=a.getRGB(b);b=e.r;c=e.g;d=e.b}if(b>1||c>1||d>1){b/=255;c/=255;d/=255}var f=z(b,c,d),g=A(b,c,d),h,i,j=(f+g)/2,k;if(g==f)k={h:0,s:0,l:j};else{var l=f-g;i=j<0.5?l/(f+g):l/(2-f-g);b==f?h=(c-d)/l:c==f?h=2+(d-b)/l:h=4+(b-c)/l;h/=6;h<0&&h++;h>1&&h--;k={h:h,s:i,l:j}}k.toString=bk;return k};a._path2string=function(){return this.join(",")[Y](ba,"$1")};function bm(a,b,c){function d(){var g=Array[e].slice.call(arguments,0),h=g[v]("►"),i=d.cache=d.cache||{},j=d.count=d.count||[];if(i[f](h))return c?c(i[h]):i[h];j[w]>=1000&&delete i[j.shift()];j[L](h);i[h]=a[m](b,g);return c?c(i[h]):i[h]}return d}a.getRGB=bm(function(b){if(!b||!(!((b=r(b)).indexOf("-")+1)))return{r:-1,g:-1,b:-1,hex:"none",error:1};if(b=="none")return{r:-1,g:-1,b:-1,hex:"none"};!(_[f](b.toLowerCase().substring(0,2))||b.charAt()=="#")&&(b=bi(b));var c,d,e,g,h,i,j,k=b.match(N);if(k){if(k[2]){g=T(k[2].substring(5),16);e=T(k[2].substring(3,5),16);d=T(k[2].substring(1,3),16)}if(k[3]){g=T((i=k[3].charAt(3))+i,16);e=T((i=k[3].charAt(2))+i,16);d=T((i=k[3].charAt(1))+i,16)}if(k[4]){j=k[4][s]($);d=S(j[0]);j[0].slice(-1)=="%"&&(d*=2.55);e=S(j[1]);j[1].slice(-1)=="%"&&(e*=2.55);g=S(j[2]);j[2].slice(-1)=="%"&&(g*=2.55);k[1].toLowerCase().slice(0,4)=="rgba"&&(h=S(j[3]));j[3]&&j[3].slice(-1)=="%"&&(h/=100)}if(k[5]){j=k[5][s]($);d=S(j[0]);j[0].slice(-1)=="%"&&(d*=2.55);e=S(j[1]);j[1].slice(-1)=="%"&&(e*=2.55);g=S(j[2]);j[2].slice(-1)=="%"&&(g*=2.55);(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360);k[1].toLowerCase().slice(0,4)=="hsba"&&(h=S(j[3]));j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsb2rgb(d,e,g,h)}if(k[6]){j=k[6][s]($);d=S(j[0]);j[0].slice(-1)=="%"&&(d*=2.55);e=S(j[1]);j[1].slice(-1)=="%"&&(e*=2.55);g=S(j[2]);j[2].slice(-1)=="%"&&(g*=2.55);(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360);k[1].toLowerCase().slice(0,4)=="hsla"&&(h=S(j[3]));j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsl2rgb(d,e,g,h)}k={r:d,g:e,b:g};k.hex="#"+(16777216|g|e<<8|d<<16).toString(16).slice(1);a.is(h,"finite")&&(k.opacity=h);return k}return{r:-1,g:-1,b:-1,hex:"none",error:1}},a);a.getColor=function(a){var b=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||0.75},c=this.hsb2rgb(b.h,b.s,b.b);b.h+=0.075;if(b.h>1){b.h=0;b.s-=0.2;b.s<=0&&(this.getColor.start={h:0,s:1,b:b.b})}return c.hex};a.getColor.reset=function(){delete this.start};a.parsePathString=bm(function(b){if(!b)return null;var c={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},d=[];a.is(b,G)&&a.is(b[0],G)&&(d=bo(b));d[w]||r(b)[Y](bb,function(a,b,e){var f=[],g=x.call(b);e[Y](bc,function(a,b){b&&f[L](+b)});if(g=="m"&&f[w]>2){d[L]([b][n](f.splice(0,2)));g="l";b=b=="m"?"l":"L"}while(f[w]>=c[g]){d[L]([b][n](f.splice(0,c[g])));if(!c[g])break}});d[H]=a._path2string;return d});a.findDotsAtSegment=function(a,b,c,d,e,f,g,h,i){var j=1-i,k=C(j,3)*a+C(j,2)*3*i*c+j*3*i*i*e+C(i,3)*g,l=C(j,3)*b+C(j,2)*3*i*d+j*3*i*i*f+C(i,3)*h,m=a+2*i*(c-a)+i*i*(e-2*c+a),n=b+2*i*(d-b)+i*i*(f-2*d+b),o=c+2*i*(e-c)+i*i*(g-2*e+c),p=d+2*i*(f-d)+i*i*(h-2*f+d),q=(1-i)*a+i*c,r=(1-i)*b+i*d,s=(1-i)*e+i*g,t=(1-i)*f+i*h,u=90-y.atan((m-o)/(n-p))*180/D;(m>o||n1){x=y.sqrt(x);c=x*c;d=x*d}var z=c*c,A=d*d,C=(f==g?-1:1)*y.sqrt(B((z*A-z*u*u-A*t*t)/(z*u*u+A*t*t))),E=C*c*u/d+(a+h)/2,F=C*-d*t/c+(b+i)/2,G=y.asin(((b-F)/d).toFixed(9)),H=y.asin(((i-F)/d).toFixed(9));G=aH&&(G=G-D*2);!g&&H>G&&(H=H-D*2)}var I=H-G;if(B(I)>k){var J=H,K=h,L=i;H=G+k*(g&&H>G?1:-1);h=E+c*y.cos(H);i=F+d*y.sin(H);m=bt(h,i,c,d,e,0,g,K,L,[H,J,E,F])}I=H-G;var M=y.cos(G),N=y.sin(G),O=y.cos(H),P=y.sin(H),Q=y.tan(I/4),R=4/3*c*Q,S=4/3*d*Q,T=[a,b],U=[a+R*N,b-S*M],V=[h+R*P,i-S*O],W=[h,i];U[0]=2*T[0]-U[0];U[1]=2*T[1]-U[1];{if(j)return[U,V,W][n](m);m=[U,V,W][n](m)[v]()[s](",");var X=[];for(var Y=0,Z=m[w];Y"1e12"&&(l=0.5);B(n)>"1e12"&&(n=0.5);if(l>0&&l<1){q=bu(a,b,c,d,e,f,g,h,l);p[L](q.x);o[L](q.y)}if(n>0&&n<1){q=bu(a,b,c,d,e,f,g,h,n);p[L](q.x);o[L](q.y)}i=f-2*d+b-(h-2*f+d);j=2*(d-b)-2*(f-d);k=b-d;l=(-j+y.sqrt(j*j-4*i*k))/2/i;n=(-j-y.sqrt(j*j-4*i*k))/2/i;B(l)>"1e12"&&(l=0.5);B(n)>"1e12"&&(n=0.5);if(l>0&&l<1){q=bu(a,b,c,d,e,f,g,h,l);p[L](q.x);o[L](q.y)}if(n>0&&n<1){q=bu(a,b,c,d,e,f,g,h,n);p[L](q.x);o[L](q.y)}return{min:{x:A[m](0,p),y:A[m](0,o)},max:{x:z[m](0,p),y:z[m](0,o)}}}),bw=bm(function(a,b){var c=bq(a),d=b&&bq(b),e={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},f={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},g=function(a,b){var c,d;if(!a)return["C",b.x,b.y,b.x,b.y,b.x,b.y];!(a[0]in{T:1,Q:1})&&(b.qx=b.qy=null);switch(a[0]){case"M":b.X=a[1];b.Y=a[2];break;case"A":a=["C"][n](bt[m](0,[b.x,b.y][n](a.slice(1))));break;case"S":c=b.x+(b.x-(b.bx||b.x));d=b.y+(b.y-(b.by||b.y));a=["C",c,d][n](a.slice(1));break;case"T":b.qx=b.x+(b.x-(b.qx||b.x));b.qy=b.y+(b.y-(b.qy||b.y));a=["C"][n](bs(b.x,b.y,b.qx,b.qy,a[1],a[2]));break;case"Q":b.qx=a[1];b.qy=a[2];a=["C"][n](bs(b.x,b.y,a[1],a[2],a[3],a[4]));break;case"L":a=["C"][n](br(b.x,b.y,a[1],a[2]));break;case"H":a=["C"][n](br(b.x,b.y,a[1],b.y));break;case"V":a=["C"][n](br(b.x,b.y,b.x,a[1]));break;case"Z":a=["C"][n](br(b.x,b.y,b.X,b.Y));break}return a},h=function(a,b){if(a[b][w]>7){a[b].shift();var e=a[b];while(e[w])a.splice(b++,0,["C"][n](e.splice(0,6)));a.splice(b,1);k=z(c[w],d&&d[w]||0)}},i=function(a,b,e,f,g){if(a&&b&&a[g][0]=="M"&&b[g][0]!="M"){b.splice(g,0,["M",f.x,f.y]);e.bx=0;e.by=0;e.x=a[g][1];e.y=a[g][2];k=z(c[w],d&&d[w]||0)}};for(var j=0,k=z(c[w],d&&d[w]||0);j0.5)*2-1;C(e-0.5,2)+C(f-0.5,2)>0.25&&(f=y.sqrt(0.25-C(e-0.5,2))*g+0.5)&&f!=0.5&&(f=f.toFixed(5)-0.00001*g)}return p});b=b[s](/\s*\-\s*/);if(d=="linear"){var i=b.shift();i=-S(i);if(isNaN(i))return null;var j=[0,0,y.cos(i*D/180),y.sin(i*D/180)],k=1/(z(B(j[2]),B(j[3]))||1);j[2]*=k;j[3]*=k;if(j[2]<0){j[0]=-j[2];j[2]=0}if(j[3]<0){j[1]=-j[3];j[3]=0}}var m=bx(b);if(!m)return null;var n=a.getAttribute(I);n=n.match(/^url\(#(.*)\)$/);n&&c.defs.removeChild(g.getElementById(n[1]));var o=bG(d+"Gradient");o.id=bh();bG(o,d=="radial"?{fx:e,fy:f}:{x1:j[0],y1:j[1],x2:j[2],y2:j[3]});c.defs[l](o);for(var q=0,t=m[w];q1?G.opacity/100:G.opacity});case"stroke":G=a.getRGB(o);h[R](n,G.hex);n=="stroke"&&G[f]("opacity")&&bG(h,{"stroke-opacity":G.opacity>1?G.opacity/100:G.opacity});break;case"gradient":(({circle:1,ellipse:1})[f](c.type)||r(o).charAt()!="r")&&bI(h,o,c.paper);break;case"opacity":i.gradient&&!i[f]("stroke-opacity")&&bG(h,{"stroke-opacity":o>1?o/100:o});case"fill-opacity":if(i.gradient){var H=g.getElementById(h.getAttribute(I)[Y](/^url\(#|\)$/g,p));if(H){var J=H.getElementsByTagName("stop");J[J[w]-1][R]("stop-opacity",o)}break}default:n=="font-size"&&(o=T(o,10)+"px");var K=n[Y](/(\-.)/g,function(a){return V.call(a.substring(1))});h.style[K]=o;h[R](n,o);break}}}bM(c,d);m?c.rotate(m.join(q)):S(j)&&c.rotate(j,true)},bL=1.2,bM=function(b,c){if(b.type!="text"||!(c[f]("text")||c[f]("font")||c[f]("font-size")||c[f]("x")||c[f]("y")))return;var d=b.attrs,e=b.node,h=e.firstChild?T(g.defaultView.getComputedStyle(e.firstChild,p).getPropertyValue("font-size"),10):10;if(c[f]("text")){d.text=c.text;while(e.firstChild)e.removeChild(e.firstChild);var i=r(c.text)[s]("\n");for(var j=0,k=i[w];jb.height&&(b.height=e.y+e.height-b.y);e.x+e.width-b.x>b.width&&(b.width=e.x+e.width-b.x)}}a&&this.hide();return b};bN[e].attr=function(b,c){if(this.removed)return this;if(b==null){var d={};for(var e in this.attrs)this.attrs[f](e)&&(d[e]=this.attrs[e]);this._.rt.deg&&(d.rotation=this.rotate());(this._.sx!=1||this._.sy!=1)&&(d.scale=this.scale());d.gradient&&d.fill=="none"&&(d.fill=d.gradient)&&delete d.gradient;return d}if(c==null&&a.is(b,F)){if(b=="translation")return cz.call(this);if(b=="rotation")return this.rotate();if(b=="scale")return this.scale();if(b==I&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;return this.attrs[b]}if(c==null&&a.is(b,G)){var g={};for(var h=0,i=b.length;h"));m.W=h.w=m.paper.span.offsetWidth;m.H=h.h=m.paper.span.offsetHeight;m.X=h.x;m.Y=h.y+Q(m.H/2);switch(h["text-anchor"]){case"start":m.node.style["v-text-align"]="left";m.bbx=Q(m.W/2);break;case"end":m.node.style["v-text-align"]="right";m.bbx=-Q(m.W/2);break;default:m.node.style["v-text-align"]="center";break}}};bI=function(a,b){a.attrs=a.attrs||{};var c=a.attrs,d,e="linear",f=".5 .5";a.attrs.gradient=b;b=r(b)[Y](bd,function(a,b,c){e="radial";if(b&&c){b=S(b);c=S(c);C(b-0.5,2)+C(c-0.5,2)>0.25&&(c=y.sqrt(0.25-C(b-0.5,2))*((c>0.5)*2-1)+0.5);f=b+q+c}return p});b=b[s](/\s*\-\s*/);if(e=="linear"){var g=b.shift();g=-S(g);if(isNaN(g))return null}var h=bx(b);if(!h)return null;a=a.shape||a.node;d=a.getElementsByTagName(I)[0]||cd(I);!d.parentNode&&a.appendChild(d);if(h[w]){d.on=true;d.method="none";d.color=h[0].color;d.color2=h[h[w]-1].color;var i=[];for(var j=0,k=h[w];j")}}catch(a){cd=function(a){return g.createElement("<"+a+" xmlns=\"urn:schemas-microsoft.com:vml\" class=\"rvml\">")}}bV=function(){var b=by[m](0,arguments),c=b.container,d=b.height,e,f=b.width,h=b.x,i=b.y;if(!c)throw new Error("VML container not found.");var k=new j,n=k.canvas=g.createElement("div"),o=n.style;h=h||0;i=i||0;f=f||512;d=d||342;f==+f&&(f+="px");d==+d&&(d+="px");k.width=1000;k.height=1000;k.coordsize=b_*1000+q+b_*1000;k.coordorigin="0 0";k.span=g.createElement("span");k.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";n[l](k.span);o.cssText=a.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",f,d);if(c==1){g.body[l](n);o.left=h+"px";o.top=i+"px";o.position="absolute"}else c.firstChild?c.insertBefore(n,c.firstChild):c[l](n);bz.call(k,k,a.fn);return k};k.clear=function(){this.canvas.innerHTML=p;this.span=g.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas[l](this.span);this.bottom=this.top=null};k.remove=function(){this.canvas.parentNode.removeChild(this.canvas);for(var a in this)this[a]=bF(a);return true}}var ce=navigator.userAgent.match(/Version\\x2f(.*?)\s/);navigator.vendor=="Apple Computer, Inc."&&(ce&&ce[1]<4||navigator.platform.slice(0,2)=="iP")?k.safari=function(){var a=this.rect(-99,-99,this.width+99,this.height+99).attr({stroke:"none"});h.setTimeout(function(){a.remove()})}:k.safari=function(){};var cf=function(){this.returnValue=false},cg=function(){return this.originalEvent.preventDefault()},ch=function(){this.cancelBubble=true},ci=function(){return this.originalEvent.stopPropagation()},cj=(function(){{if(g.addEventListener)return function(a,b,c,d){var e=o&&u[b]?u[b]:b,g=function(e){if(o&&u[f](b))for(var g=0,h=e.targetTouches&&e.targetTouches.length;g1&&(a=Array[e].splice.call(arguments,0,arguments[w]));return new cC(a)};k.setSize=bU;k.top=k.bottom=null;k.raphael=a;function co(){return this.x+q+this.y}bO.resetScale=function(){if(this.removed)return this;this._.sx=1;this._.sy=1;this.attrs.scale="1 1"};bO.scale=function(a,b,c,d){if(this.removed)return this;if(a==null&&b==null)return{x:this._.sx,y:this._.sy,toString:co};b=b||a;!(+b)&&(b=a);var e,f,g,h,i=this.attrs;if(a!=0){var j=this.getBBox(),k=j.x+j.width/2,l=j.y+j.height/2,m=B(a/this._.sx),o=B(b/this._.sy);c=+c||c==0?c:k;d=+d||d==0?d:l;var r=this._.sx>0,s=this._.sy>0,t=~(~(a/B(a))),u=~(~(b/B(b))),x=m*t,y=o*u,z=this.node.style,A=c+B(k-c)*x*(k>c==r?1:-1),C=d+B(l-d)*y*(l>d==s?1:-1),D=a*t>b*u?o:m;switch(this.type){case"rect":case"image":var E=i.width*m,F=i.height*o;this.attr({height:F,r:i.r*D,width:E,x:A-E/2,y:C-F/2});break;case"circle":case"ellipse":this.attr({rx:i.rx*m,ry:i.ry*o,r:i.r*D,cx:A,cy:C});break;case"text":this.attr({x:A,y:C});break;case"path":var G=bp(i.path),H=true,I=r?x:m,J=s?y:o;for(var K=0,L=G[w];Kr)p=n.data[r*l];else{p=a.findDotsAtSegment(b,c,d,e,f,g,h,i,r/l);n.data[r]=p}r&&(k+=C(C(o.x-p.x,2)+C(o.y-p.y,2),0.5));if(j!=null&&k>=j)return p;o=p}if(j==null)return k},cr=function(b,c){return function(d,e,f){d=bw(d);var g,h,i,j,k="",l={},m,n=0;for(var o=0,p=d.length;oe){if(c&&!l.start){m=cq(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n);k+=["C",m.start.x,m.start.y,m.m.x,m.m.y,m.x,m.y];if(f)return k;l.start=k;k=["M",m.x,m.y+"C",m.n.x,m.n.y,m.end.x,m.end.y,i[5],i[6]][v]();n+=j;g=+i[5];h=+i[6];continue}if(!b&&!c){m=cq(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n);return{x:m.x,y:m.y,alpha:m.alpha}}}n+=j;g=+i[5];h=+i[6]}k+=i}l.end=k;m=b?n:c?l:a.findDotsAtSegment(g,h,i[1],i[2],i[3],i[4],i[5],i[6],1);m.alpha&&(m={x:m.x,y:m.y,alpha:m.alpha});return m}},cs=cr(1),ct=cr(),cu=cr(0,1);bO.getTotalLength=function(){if(this.type!="path")return;if(this.node.getTotalLength)return this.node.getTotalLength();return cs(this.attrs.path)};bO.getPointAtLength=function(a){if(this.type!="path")return;return ct(this.attrs.path,a)};bO.getSubpath=function(a,b){if(this.type!="path")return;if(B(this.getTotalLength()-b)<"1e-6")return cu(this.attrs.path,a).end;var c=cu(this.attrs.path,b,1);return a?cu(c,a).end:c};a.easing_formulas={linear:function(a){return a},"<":function(a){return C(a,3)},">":function(a){return C(a-1,3)+1},"<>":function(a){a=a*2;if(a<1)return C(a,3)/2;a-=2;return(C(a,3)+2)/2},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a=a-1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a==0||a==1)return a;var b=0.3,c=b/4;return C(2,-10*a)*y.sin((a-c)*(2*D)/b)+1},bounce:function(a){var b=7.5625,c=2.75,d;if(a<1/c)d=b*a*a;else if(a<2/c){a-=1.5/c;d=b*a*a+0.75}else if(a<2.5/c){a-=2.25/c;d=b*a*a+0.9375}else{a-=2.625/c;d=b*a*a+0.984375}return d}};var cv=[],cw=function(){var b=+(new Date);for(var c=0;cd)return d;while(cf?c=e:d=e;e=(d-c)/2+c}return e}return n(a,1/(200*f))}bO.onAnimation=function(a){this._run=a||0;return this};bO.animate=function(c,d,e,g){var h=this;h.timeouts=h.timeouts||[];if(a.is(e,"function")||!e)g=e||null;if(h.removed){g&&g.call(h);return h}var i={},j={},k=false,l={};for(var m in c)if(c[f](m)){if(X[f](m)||h.paper.customAttributes[f](m)){k=true;i[m]=h.attr(m);i[m]==null&&(i[m]=W[m]);j[m]=c[m];switch(X[m]){case"along":var n=cs(c[m]),o=ct(c[m],n*!(!c.back)),p=h.getBBox();l[m]=n/d;l.tx=p.x;l.ty=p.y;l.sx=o.x;l.sy=o.y;j.rot=c.rot;j.back=c.back;j.len=n;c.rot&&(l.r=S(h.rotate())||0);break;case E:l[m]=(j[m]-i[m])/d;break;case"colour":i[m]=a.getRGB(i[m]);var q=a.getRGB(j[m]);l[m]={r:(q.r-i[m].r)/d,g:(q.g-i[m].g)/d,b:(q.b-i[m].b)/d};break;case"path":var t=bw(i[m],j[m]);i[m]=t[0];var u=t[1];l[m]=[];for(var v=0,x=i[m][w];vopera.version()?new Audio(null):new Audio).canPlayType}catch(ib){pa= +!1}this.hasHTML5=pa;this.html5={usingFlash:null};this.flash={};this.ignoreFlash=this.html5Only=!1;var Ka,c=this,h=null,s="HTML5::",A,v=navigator.userAgent,k=Z,Q=k.location.href.toString(),i=document,ra,La,sa,j,D=[],ta=!0,x,R=!1,S=!1,m=!1,o=!1,ba=!1,n,eb=0,T,w,ua,H,va,I,J,K,Ma,wa,ca,da,ea,L,xa,U,fa,ga,M,Na,ya,fb=["log","info","warn","error"],Oa,ha,Pa,V=null,za=null,p,Aa,N,Qa,ia,ja,O,t,W=!1,Ba=!1,Ra,Sa,Ta,ka=0,X=null,la,B=null,Ua,ma,Y,E,Ca,Da,Va,u,Wa=Array.prototype.slice,G=!1,z,Ea,Xa,C,Ya,Fa=v.match(/(ipad|iphone|ipod)/i), +F=v.match(/msie/i),gb=v.match(/webkit/i),Ga=v.match(/safari/i)&&!v.match(/chrome/i),qa=v.match(/opera/i),Ha=v.match(/(mobile|pre\/|xoom)/i)||Fa,Ia=!Q.match(/usehtml5audio/i)&&!Q.match(/sm2\-ignorebadua/i)&&Ga&&!v.match(/silk/i)&&v.match(/OS X 10_6_([3-7])/i),Za="undefined"!==typeof console&&"undefined"!==typeof console.log,Ja="undefined"!==typeof i.hasFocus?i.hasFocus():null,na=Ga&&("undefined"===typeof i.hasFocus||!i.hasFocus()),$a=!na,ab=/(mp3|mp4|mpa|m4a|m4b)/i,P=i.location?i.location.protocol.match(/http/i): +null,bb=!P?"http://":"",cb=/^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,db="mpeg4,aac,flv,mov,mp4,m4v,f4v,m4a,m4b,mp4v,3gp,3g2".split(","),hb=RegExp("\\.("+db.join("|")+")(\\?.*)?$","i");this.mimePattern=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.useAltURL=!P;this._global_a=null;if(Ha&&(c.useHTML5Audio=!0,c.preferFlash=!1,Fa))G=c.ignoreFlash=!0;this.setup=function(a){var d=!c.url;"undefined"!==typeof a&&m&&B&&c.ok()&&("undefined"!==typeof a.flashVersion|| +"undefined"!==typeof a.url)&&O(p("setupLate"));ua(a);d&&U&&"undefined"!==typeof a.url&&c.beginDelayedInit();!U&&"undefined"!==typeof a.url&&"complete"===i.readyState&&setTimeout(L,1);return c};this.supported=this.ok=function(){return B?m&&!o:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(c){return A(c)||i[c]||k[c]};this.createSound=function(a,d){function e(){g=ia(g);c.sounds[f.id]=new Ka(f);c.soundIDs.push(f.id);return c.sounds[f.id]}var b,g=null,f=b=null;b="soundManager.createSound(): "+p(!m? +"notReady":"notOK");if(!m||!c.ok())return O(b),!1;"undefined"!==typeof d&&(a={id:a,url:d});g=w(a);g.url=la(g.url);f=g;f.id.toString().charAt(0).match(/^[0-9]$/)&&c._wD("soundManager.createSound(): "+p("badID",f.id),2);c._wD("soundManager.createSound(): "+f.id+" ("+f.url+")",1);if(t(f.id,!0))return c._wD("soundManager.createSound(): "+f.id+" exists",1),c.sounds[f.id];if(ma(f))b=e(),c._wD("Creating sound "+f.id+", using HTML5"),b._setup_html5(f);else{if(8=a)return!1;for(a-=1;0<=a;a--)if(c=y[a],!c.fired&&b.position>=c.position)c.fired=!0,q++,c.method.apply(c.scope,[c.position]);return!0};this._resetOnPosition=function(b){var a,c;a=y.length;if(!a)return!1;for(a-=1;0<=a;a--)if(c=y[a],c.fired&&b<=c.position)c.fired=!1,q--; +return!0};v=function(){var a=b._iO,d=a.from,e=a.to,f,g;g=function(){c._wD(b.id+': "to" time of '+e+" reached.");b.clearOnPosition(e,g);b.stop()};f=function(){c._wD(b.id+': playing "from" '+d);if(null!==e&&!isNaN(e))b.onPosition(e,g)};if(null!==d&&!isNaN(d))a.position=d,a.multiShot=!1,f();return a};k=function(){var a,c=b._iO.onposition;if(c)for(a in c)if(c.hasOwnProperty(a))b.onPosition(parseInt(a,10),c[a])};u=function(){var a,c=b._iO.onposition;if(c)for(a in c)c.hasOwnProperty(a)&&b.clearOnPosition(parseInt(a, +10))};i=function(){b.isHTML5&&Ra(b)};l=function(){b.isHTML5&&Sa(b)};g=function(a){a||(y=[],q=0);m=!1;b._hasTimer=null;b._a=null;b._html5_canplay=!1;b.bytesLoaded=null;b.bytesTotal=null;b.duration=b._iO&&b._iO.duration?b._iO.duration:null;b.durationEstimate=null;b.buffered=[];b.eqData=[];b.eqData.left=[];b.eqData.right=[];b.failures=0;b.isBuffering=!1;b.instanceOptions={};b.instanceCount=0;b.loaded=!1;b.metadata={};b.readyState=0;b.muted=!1;b.paused=!1;b.peakData={left:0,right:0};b.waveformData={left:[], +right:[]};b.playState=0;b.position=null;b.id3={}};g();this._onTimer=function(a){var c,f=!1,g={};if(b._hasTimer||a){if(b._a&&(a||(0opera.version()?new Audio(null):new Audio,e=b._a,e._called_load=!1,G)c._global_a=e;b.isHTML5=!0;b._a=e;e._t=b;f();b._apply_loop(e,a.loops);a.autoLoad||a.autoPlay?b.load():(e.autobuffer=!1,e.preload="auto");return e};f=function(){if(b._a._added_events)return!1;var a;b._a._added_events=!0;for(a in C)C.hasOwnProperty(a)&&b._a&&b._a.addEventListener(a,C[a],!1); +return!0};r=function(){var a;c._wD(s+"removing event listeners: "+b.id);b._a._added_events=!1;for(a in C)C.hasOwnProperty(a)&&b._a&&b._a.removeEventListener(a,C[a],!1)};this._onload=function(a){a=!!a||!b.isHTML5&&8===j&&b.duration;c._wD('SMSound._onload(): "'+b.id+'"'+(a?" loaded.":" failed to load? - "+b.url),a?1:2);!a&&!b.isHTML5&&(!0===c.sandbox.noRemote&&c._wD("SMSound._onload(): "+p("noNet"),1),!0===c.sandbox.noLocal&&c._wD("SMSound._onload(): "+p("noLocal"),1));b.loaded=a;b.readyState=a?3:2; +b._onbufferchange(0);b._iO.onload&&b._iO.onload.apply(b,[a]);return!0};this._onbufferchange=function(a){if(0===b.playState||a&&b.isBuffering||!a&&!b.isBuffering)return!1;b.isBuffering=1===a;b._iO.onbufferchange&&(c._wD("SMSound._onbufferchange(): "+a),b._iO.onbufferchange.apply(b));return!0};this._onsuspend=function(){b._iO.onsuspend&&(c._wD("SMSound._onsuspend()"),b._iO.onsuspend.apply(b));return!0};this._onfailure=function(a,d,e){b.failures++;c._wD('SMSound._onfailure(): "'+b.id+'" count '+b.failures); +if(b._iO.onfailure&&1===b.failures)b._iO.onfailure(b,a,d,e);else c._wD("SMSound._onfailure(): ignoring")};this._onfinish=function(){var a=b._iO.onfinish;b._onbufferchange(0);b._resetOnPosition(0);if(b.instanceCount){b.instanceCount--;if(!b.instanceCount&&(u(),b.playState=0,b.paused=!1,b.instanceCount=0,b.instanceOptions={},b._iO={},l(),b.isHTML5))b.position=0;if((!b.instanceCount||b._iO.multiShotEvents)&&a)c._wD('SMSound._onfinish(): "'+b.id+'"'),a.apply(b)}};this._whileloading=function(a,c,d,e){var f= +b._iO;b.bytesLoaded=a;b.bytesTotal=c;b.duration=Math.floor(d);b.bufferLength=e;b.durationEstimate=!b.isHTML5&&!f.isMovieStar?f.duration?b.duration>f.duration?b.duration:f.duration:parseInt(b.bytesTotal/b.bytesLoaded*b.duration,10):b.duration;if(!b.isHTML5)b.buffered=[{start:0,end:b.duration}];(3!==b.readyState||b.isHTML5)&&f.whileloading&&f.whileloading.apply(b)};this._whileplaying=function(a,c,d,e,f){var g=b._iO;if(isNaN(a)||null===a)return!1;b.position=Math.max(0,a);b._processOnPosition();if(!b.isHTML5&& +8opera.version()?new Audio(null): +new Audio:null,e,b,g={},f;f=c.audioFormats;for(e in f)if(f.hasOwnProperty(e)&&(b="audio/"+e,g[e]=a(f[e].type),g[b]=g[e],e.match(ab)?(c.flash[e]=!0,c.flash[b]=!0):(c.flash[e]=!1,c.flash[b]=!1),f[e]&&f[e].related))for(b=f[e].related.length-1;0<=b;b--)g["audio/"+f[e].related[b]]=g[e],c.html5[f[e].related[b]]=g[e],c.flash[f[e].related[b]]=g[e];g.canPlayType=d?a:null;c.html5=w(c.html5,g);return!0};da={notReady:"Not loaded yet - wait for soundManager.onready()",notOK:"Audio support is not available.",domError:"soundManager::createMovie(): appendChild/innerHTML call failed. DOM not ready or other error.", +spcWmode:"soundManager::createMovie(): Removing wmode, preventing known SWF loading issue(s)",swf404:"soundManager: Verify that %s is a valid path.",tryDebug:"Try soundManager.debugFlash = true for more security details (output goes to SWF.)",checkSWF:"See SWF output for more debug info.",localFail:"soundManager: Non-HTTP page ("+i.location.protocol+" URL?) Review Flash player security settings for this special case:\nhttp://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html\nMay need to add/allow path, eg. c:/sm2/ or /users/me/sm2/", +waitFocus:"soundManager: Special case: Waiting for SWF to load with window focus...",waitImpatient:"soundManager: Getting impatient, still waiting for Flash%s...",waitForever:"soundManager: Waiting indefinitely for Flash (will recover if unblocked)...",waitSWF:"soundManager: Retrying, waiting for 100% SWF load...",needFunction:"soundManager: Function object expected for %s",badID:'Warning: Sound ID "%s" should be a string, starting with a non-numeric character',currentObj:"--- soundManager._debug(): Current sound objects ---", +waitEI:"soundManager::initMovie(): Waiting for ExternalInterface call from Flash...",waitOnload:"soundManager: Waiting for window.onload()",docLoaded:"soundManager: Document already loaded",onload:"soundManager::initComplete(): calling soundManager.onload()",onloadOK:"soundManager.onload() complete",init:"soundManager::init()",didInit:"soundManager::init(): Already called?",flashJS:"soundManager: Attempting JS to Flash call...",secNote:"Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html", +badRemove:"Warning: Failed to remove flash movie.",shutdown:"soundManager.disable(): Shutting down",queue:"soundManager: Queueing %s handler",smFail:"soundManager: Failed to initialise.",smError:"SMSound.load(): Exception: JS-Flash communication failed, or JS error.",fbTimeout:"No flash response, applying .swf_timedout CSS...",fbLoaded:"Flash loaded",fbHandler:"soundManager::flashBlockHandler()",manURL:"SMSound.load(): Using manually-assigned URL",onURL:"soundManager.load(): current URL already assigned.", +badFV:'soundManager.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.',as2loop:"Note: Setting stream:false so looping can work (flash 8 limitation)",noNSLoop:"Note: Looping not implemented for MovieStar formats",needfl9:"Note: Switching to flash 9, required for MP4 formats.",mfTimeout:"Setting flashLoadTimeout = 0 (infinite) for off-screen, mobile flash case",needFlash:"soundManager: Fatal error: Flash is needed to play some required formats, but is not available.",gotFocus:"soundManager: Got window focus.", +mfOn:"mobileFlash::enabling on-screen flash repositioning",policy:"Enabling usePolicyFile for data access",setup:"soundManager.setup(): allowed parameters: %s",setupError:'soundManager.setup(): "%s" cannot be assigned with this method.',setupUndef:'soundManager.setup(): Could not find option "%s"',setupLate:"soundManager.setup(): url + flashVersion changes will not take effect until reboot().",h5a:"creating HTML5 Audio() object",noURL:"soundManager: Flash URL required. Call soundManager.setup({url:...}) to get started."}; +p=function(){var a=Wa.call(arguments),c=a.shift(),c=da&&da[c]?da[c]:"",e,b;if(c&&a&&a.length)for(e=0,b=a.length;ej)c._wD(p("needfl9")),c.flashVersion=j=9;c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":9===j?" (AS3/Flash 9)":" (AS2/Flash 8)");8'}if(R&&S)return!1;if(c.html5Only)return wa(),e(),c.oMC=A(c.movieID),sa(),S=R=!0,!1;var g=d||c.url,f=c.altURL||g,h=fa(),l=N(),k=null,k=i.getElementsByTagName("html")[0],j,o,m,k=k&&k.dir&&k.dir.match(/rtl/i),a="undefined"===typeof a?c.id:a;wa();c.url=Pa(P?g:f);d=c.url;c.wmode=!c.wmode&&c.useHighPerformance?"transparent":c.wmode;if(null!== +c.wmode&&(v.match(/msie 8/i)||!F&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i))n("spcWmode"),c.wmode=null;h={name:a,id:a,src:d,quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:bb+"www.macromedia.com/go/getflashplayer",title:"JS/Flash audio component (SoundManager 2)",type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};if(c.debugFlash)h.FlashVars="debug=1";c.wmode||delete h.wmode;if(F)g=i.createElement("div"),o=['',b("movie",d),b("AllowScriptAccess",c.allowScriptAccess),b("quality",h.quality),c.wmode?b("wmode",c.wmode):"",b("bgcolor",c.bgColor),b("hasPriority","true"),c.debugFlash?b("FlashVars",h.FlashVars):"",""].join("");else for(j in g=i.createElement("embed"),h)h.hasOwnProperty(j)&&g.setAttribute(j, +h[j]);ya();l=N();if(h=fa())if(c.oMC=A(c.movieID)||i.createElement("div"),c.oMC.id){m=c.oMC.className;c.oMC.className=(m?m+" ":"movieContainer")+(l?" "+l:"");c.oMC.appendChild(g);if(F)j=c.oMC.appendChild(i.createElement("div")),j.className="sm2-object-box",j.innerHTML=o;S=!0}else{c.oMC.id=c.movieID;c.oMC.className="movieContainer "+l;j=l=null;if(!c.useFlashBlock)if(c.useHighPerformance)l={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"};else if(l={position:"absolute", +width:"6px",height:"6px",top:"-9999px",left:"-9999px"},k)l.left=Math.abs(parseInt(l.left,10))+"px";if(gb)c.oMC.style.zIndex=1E4;if(!c.debugFlash)for(m in l)l.hasOwnProperty(m)&&(c.oMC.style[m]=l[m]);try{F||c.oMC.appendChild(g);h.appendChild(c.oMC);if(F)j=c.oMC.appendChild(i.createElement("div")),j.className="sm2-object-box",j.innerHTML=o;S=!0}catch(q){throw Error(p("domError")+" \n"+q.toString());}}R=!0;e();c._wD("soundManager::createMovie(): Trying to load "+d+(!P&&c.altURL?" (alternate URL)":""), +1);return!0};ea=function(){if(c.html5Only)return ga(),!1;if(h)return!1;if(!c.url)return n("noURL"),!1;h=c.getMovie(c.id);if(!h)V?(F?c.oMC.innerHTML=za:c.oMC.appendChild(V),V=null,R=!0):ga(c.id,c.url),h=c.getMovie(c.id);h&&n("waitEI");"function"===typeof c.oninitmovie&&setTimeout(c.oninitmovie,1);return!0};K=function(){setTimeout(Ma,1E3)};Ma=function(){var a,d=!1;if(!c.url||W)return!1;W=!0;u.remove(k,"load",K);if(na&&!Ja)return n("waitFocus"),!1;m||(a=c.getMoviePercent(),c._wD(p("waitImpatient",0< +a?" (SWF "+a+"% loaded)":"")),0a&&(d=!0));setTimeout(function(){a=c.getMoviePercent();if(d)return W=!1,c._wD(p("waitSWF")),k.setTimeout(K,1),!1;m||(c._wD("soundManager: No Flash response within expected time.\nLikely causes: "+(0===a?"Loading "+c.movieURL+" may have failed (and/or Flash "+j+"+ not present?), ":"")+"Flash blocked or JS-Flash security error."+(c.debugFlash?" "+p("checkSWF"):""),2),!P&&a&&(n("localFail",2),c.debugFlash||n("tryDebug",2)),0===a&&c._wD(p("swf404",c.url)),x("flashtojs", +!1,": Timed out"+P?" (Check flash security or flash blockers)":" (No plugin/missing SWF?)"));!m&&$a&&(null===a?c.useFlashBlock||0===c.flashLoadTimeout?(c.useFlashBlock&&Aa(),n("waitForever")):ha(!0):0===c.flashLoadTimeout?n("waitForever"):ha(!0))},c.flashLoadTimeout)};ca=function(){if(Ja||!na)return u.remove(k,"focus",ca),!0;Ja=$a=!0;n("gotFocus");W=!1;K();u.remove(k,"focus",ca);return!0};Ya=function(){var a,d=[];if(c.useHTML5Audio&&c.hasHTML5){for(a in c.audioFormats)c.audioFormats.hasOwnProperty(a)&& +d.push(a+": "+c.html5[a]+(!c.html5[a]&&z&&c.flash[a]?" (using flash)":c.preferFlash&&c.flash[a]&&z?" (preferring flash)":!c.html5[a]?" ("+(c.audioFormats[a].required?"required, ":"")+"and no flash support)":""));c._wD("-- SoundManager 2: HTML5 support tests ("+c.html5Test+"): "+d.join(", ")+" --",1)}};T=function(a){if(m)return!1;if(c.html5Only)return c._wD("-- SoundManager 2: loaded --"),m=!0,J(),x("onload",!0),!0;var d=!0,e;if(!c.useFlashBlock||!c.flashLoadTimeout||c.getMoviePercent())m=!0,o&&(e= +{type:!z&&B?"NO_FLASH":"INIT_TIMEOUT"});c._wD("-- SoundManager 2 "+(o?"failed to load":"loaded")+" ("+(o?"Flash security/load error":"OK")+") --",1);if(o||a){if(c.useFlashBlock&&c.oMC)c.oMC.className=N()+" "+(null===c.getMoviePercent()?"swf_timedout":"swf_error");I({type:"ontimeout",error:e,ignoreInit:!0});x("onload",!1);M(e);d=!1}else x("onload",!0);o||(c.waitForWindowLoad&&!ba?(n("waitOnload"),u.add(k,"load",J)):(c.waitForWindowLoad&&ba&&n("docLoaded"),J()));return d};La=function(){var a,d=c.setupOptions; +for(a in d)d.hasOwnProperty(a)&&("undefined"===typeof c[a]?c[a]=d[a]:c[a]!==d[a]&&(c.setupOptions[a]=c[a]))};sa=function(){n("init");if(m)return n("didInit"),!1;if(c.html5Only){if(!m)u.remove(k,"load",c.beginDelayedInit),c.enabled=!0,T();return!0}ea();try{n("flashJS"),h._externalInterfaceTest(!1),Na(!0,c.flashPollingInterval||(c.useHighPerformance?10:50)),c.debugMode||h._disableDebug(),c.enabled=!0,x("jstoflash",!0),c.html5Only||u.add(k,"unload",ra)}catch(a){return c._wD("js/flash exception: "+a.toString()), +x("jstoflash",!1),M({type:"JS_TO_FLASH_EXCEPTION",fatal:!0}),ha(!0),T(),!1}T();u.remove(k,"load",c.beginDelayedInit);return!0};L=function(){if(U)return!1;U=!0;La();ya();var a=null,a=null,d="undefined"!==typeof console&&"function"===typeof console.log,e=Q.toLowerCase();-1!==e.indexOf("sm2-usehtml5audio=")&&(a="1"===e.charAt(e.indexOf("sm2-usehtml5audio=")+18),d&&console.log((a?"Enabling ":"Disabling ")+"useHTML5Audio via URL parameter"),c.setup({useHTML5Audio:a}));-1!==e.indexOf("sm2-preferflash=")&& +(a="1"===e.charAt(e.indexOf("sm2-preferflash=")+16),d&&console.log((a?"Enabling ":"Disabling ")+"preferFlash via URL parameter"),c.setup({preferFlash:a}));!z&&c.hasHTML5&&(c._wD("SoundManager: No Flash detected"+(!c.useHTML5Audio?", enabling HTML5.":". Trying HTML5-only mode.")),c.setup({useHTML5Audio:!0,preferFlash:!1}));Va();c.html5.usingFlash=Ua();B=c.html5.usingFlash;Ya();!z&&B&&(n("needFlash"),c.setup({flashLoadTimeout:1}));i.removeEventListener&&i.removeEventListener("DOMContentLoaded",L,!1); +ea();return!0};Da=function(){"complete"===i.readyState&&(L(),i.detachEvent("onreadystatechange",Da));return!0};xa=function(){ba=!0;u.remove(k,"load",xa)};Ea();u.add(k,"focus",ca);u.add(k,"load",K);u.add(k,"load",xa);i.addEventListener?i.addEventListener("DOMContentLoaded",L,!1):i.attachEvent?i.attachEvent("onreadystatechange",Da):(x("onload",!1),M({type:"NO_DOM2_EVENTS",fatal:!0}))}var oa=null;if("undefined"===typeof SM2_DEFER||!SM2_DEFER)oa=new $;Z.SoundManager=$;Z.soundManager=oa})(window); \ No newline at end of file diff --git a/timeside/player/static/timeside/js/libs/soundmanager2-nodebug-jsmin.js b/timeside/player/static/timeside/js/libs/soundmanager2-nodebug-jsmin.js new file mode 100644 index 0000000..ca2fc0e --- /dev/null +++ b/timeside/player/static/timeside/js/libs/soundmanager2-nodebug-jsmin.js @@ -0,0 +1,80 @@ +/** @license + * + * SoundManager 2: JavaScript Sound for the Web + * ---------------------------------------------- + * http://schillmania.com/projects/soundmanager2/ + * + * Copyright (c) 2007, Scott Schiller. All rights reserved. + * Code provided under the BSD License: + * http://schillmania.com/projects/soundmanager2/license.txt + * + * V2.97a.20120916 + */ +(function(fa){function R(R,ea){function S(a){return c.preferFlash&&y&&!c.ignoreFlash&&"undefined"!==typeof c.flash[a]&&c.flash[a]}function l(a){return function(c){var d=this._t;return!d||!d._a?null:a.call(this,c)}}this.setupOptions={url:R||null,flashVersion:8,debugMode:!0,debugFlash:!1,useConsole:!0,consoleOnly:!0,waitForWindowLoad:!1,bgColor:"#ffffff",useHighPerformance:!1,flashPollingInterval:null,html5PollingInterval:null,flashLoadTimeout:1E3,wmode:null,allowScriptAccess:"always",useFlashBlock:!1, +useHTML5Audio:!0,html5Test:/^(probably|maybe)$/i,preferFlash:!0,noSWFCache:!1};this.defaultOptions={autoLoad:!1,autoPlay:!1,from:null,loops:1,onid3:null,onload:null,whileloading:null,onplay:null,onpause:null,onresume:null,whileplaying:null,onposition:null,onstop:null,onfailure:null,onfinish:null,multiShot:!0,multiShotEvents:!1,position:null,pan:0,stream:!0,to:null,type:null,usePolicyFile:!1,volume:100};this.flash9Options={isMovieStar:null,usePeakData:!1,useWaveformData:!1,useEQData:!1,onbufferchange:null, +ondataerror:null};this.movieStarOptions={bufferTime:3,serverURL:null,onconnect:null,duration:null};this.audioFormats={mp3:{type:['audio/mpeg; codecs="mp3"',"audio/mpeg","audio/mp3","audio/MPA","audio/mpa-robust"],required:!0},mp4:{related:["aac","m4a","m4b"],type:['audio/mp4; codecs="mp4a.40.2"',"audio/aac","audio/x-m4a","audio/MP4A-LATM","audio/mpeg4-generic"],required:!1},ogg:{type:["audio/ogg; codecs=vorbis"],required:!1},wav:{type:['audio/wav; codecs="1"',"audio/wav","audio/wave","audio/x-wav"], +required:!1}};this.movieID="sm2-container";this.id=ea||"sm2movie";this.debugID="soundmanager-debug";this.debugURLParam=/([#?&])debug=1/i;this.versionNumber="V2.97a.20120916";this.altURL=this.movieURL=this.version=null;this.enabled=this.swfLoaded=!1;this.oMC=null;this.sounds={};this.soundIDs=[];this.didFlashBlock=this.muted=!1;this.filePattern=null;this.filePatterns={flash8:/\.mp3(\?.*)?$/i,flash9:/\.mp3(\?.*)?$/i};this.features={buffering:!1,peakData:!1,waveformData:!1,eqData:!1,movieStar:!1};this.sandbox= +{};var ga;try{ga="undefined"!==typeof Audio&&"undefined"!==typeof(ha&&10>opera.version()?new Audio(null):new Audio).canPlayType}catch(Za){ga=!1}this.hasHTML5=ga;this.html5={usingFlash:null};this.flash={};this.ignoreFlash=this.html5Only=!1;var Da,c=this,i=null,T,q=navigator.userAgent,h=fa,ia=h.location.href.toString(),m=document,ja,Ea,ka,j,v=[],J=!1,K=!1,k=!1,s=!1,la=!1,L,r,ma,U,na,B,C,D,Fa,oa,V,W,E,pa,M,qa,X,F,Ga,ra,Ha,Y,Ia,N=null,sa=null,t,ta,G,Z,$,H,p,O=!1,ua=!1,Ja,Ka,La,aa=0,P=null,ba,n=null,Ma, +ca,Q,w,va,wa,Na,o,Wa=Array.prototype.slice,z=!1,y,xa,Oa,u,Pa,ya=q.match(/(ipad|iphone|ipod)/i),x=q.match(/msie/i),Xa=q.match(/webkit/i),za=q.match(/safari/i)&&!q.match(/chrome/i),ha=q.match(/opera/i),Aa=q.match(/(mobile|pre\/|xoom)/i)||ya,Qa=!ia.match(/usehtml5audio/i)&&!ia.match(/sm2\-ignorebadua/i)&&za&&!q.match(/silk/i)&&q.match(/OS X 10_6_([3-7])/i),Ba="undefined"!==typeof m.hasFocus?m.hasFocus():null,da=za&&("undefined"===typeof m.hasFocus||!m.hasFocus()),Ra=!da,Sa=/(mp3|mp4|mpa|m4a|m4b)/i,Ca= +m.location?m.location.protocol.match(/http/i):null,Ta=!Ca?"http://":"",Ua=/^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,Va="mpeg4,aac,flv,mov,mp4,m4v,f4v,m4a,m4b,mp4v,3gp,3g2".split(","),Ya=RegExp("\\.("+Va.join("|")+")(\\?.*)?$","i");this.mimePattern=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.useAltURL=!Ca;this._global_a=null;if(Aa&&(c.useHTML5Audio=!0,c.preferFlash=!1,ya))z=c.ignoreFlash=!0;this.setup=function(a){var e=!c.url;"undefined"!==typeof a&& +k&&n&&c.ok()&&("undefined"!==typeof a.flashVersion||"undefined"!==typeof a.url)&&H(t("setupLate"));ma(a);e&&M&&"undefined"!==typeof a.url&&c.beginDelayedInit();!M&&"undefined"!==typeof a.url&&"complete"===m.readyState&&setTimeout(E,1);return c};this.supported=this.ok=function(){return n?k&&!s:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(a){return T(a)||m[a]||h[a]};this.createSound=function(a,e){function d(){b=Z(b);c.sounds[f.id]=new Da(f);c.soundIDs.push(f.id);return c.sounds[f.id]}var b=null, +g=null,f=null;if(!k||!c.ok())return H(void 0),!1;"undefined"!==typeof e&&(a={id:a,url:e});b=r(a);b.url=ba(b.url);f=b;if(p(f.id,!0))return c.sounds[f.id];if(ca(f))g=d(),g._setup_html5(f);else{if(8=a)return!1;for(a-=1;0<=a;a--)if(c=k[a],!c.fired&&b.position>=c.position)c.fired=!0,o++,c.method.apply(c.scope,[c.position]);return!0};this._resetOnPosition=function(b){var a,c;a=k.length;if(!a)return!1;for(a-=1;0<=a;a--)if(c=k[a],c.fired&&b<=c.position)c.fired=!1,o--;return!0};s=function(){var a=b._iO,c=a.from,e=a.to,d,f;f=function(){b.clearOnPosition(e, +f);b.stop()};d=function(){if(null!==e&&!isNaN(e))b.onPosition(e,f)};if(null!==c&&!isNaN(c))a.position=c,a.multiShot=!1,d();return a};m=function(){var a,c=b._iO.onposition;if(c)for(a in c)if(c.hasOwnProperty(a))b.onPosition(parseInt(a,10),c[a])};q=function(){var a,c=b._iO.onposition;if(c)for(a in c)c.hasOwnProperty(a)&&b.clearOnPosition(parseInt(a,10))};h=function(){b.isHTML5&&Ja(b)};I=function(){b.isHTML5&&Ka(b)};g=function(a){a||(k=[],o=0);l=!1;b._hasTimer=null;b._a=null;b._html5_canplay=!1;b.bytesLoaded= +null;b.bytesTotal=null;b.duration=b._iO&&b._iO.duration?b._iO.duration:null;b.durationEstimate=null;b.buffered=[];b.eqData=[];b.eqData.left=[];b.eqData.right=[];b.failures=0;b.isBuffering=!1;b.instanceOptions={};b.instanceCount=0;b.loaded=!1;b.metadata={};b.readyState=0;b.muted=!1;b.paused=!1;b.peakData={left:0,right:0};b.waveformData={left:[],right:[]};b.playState=0;b.position=null;b.id3={}};g();this._onTimer=function(a){var c,f=!1,g={};if(b._hasTimer||a){if(b._a&&(a||(0opera.version()?new Audio(null):new Audio,d=b._a,d._called_load=!1,z)c._global_a=d;b.isHTML5=!0;b._a=d;d._t=b;f();b._apply_loop(d,a.loops);a.autoLoad||a.autoPlay? +b.load():(d.autobuffer=!1,d.preload="auto");return d};f=function(){if(b._a._added_events)return!1;var a;b._a._added_events=!0;for(a in u)u.hasOwnProperty(a)&&b._a&&b._a.addEventListener(a,u[a],!1);return!0};A=function(){var a;b._a._added_events=!1;for(a in u)u.hasOwnProperty(a)&&b._a&&b._a.removeEventListener(a,u[a],!1)};this._onload=function(a){a=!!a||!b.isHTML5&&8===j&&b.duration;b.loaded=a;b.readyState=a?3:2;b._onbufferchange(0);b._iO.onload&&b._iO.onload.apply(b,[a]);return!0};this._onbufferchange= +function(a){if(0===b.playState||a&&b.isBuffering||!a&&!b.isBuffering)return!1;b.isBuffering=1===a;b._iO.onbufferchange&&b._iO.onbufferchange.apply(b);return!0};this._onsuspend=function(){b._iO.onsuspend&&b._iO.onsuspend.apply(b);return!0};this._onfailure=function(a,c,e){b.failures++;if(b._iO.onfailure&&1===b.failures)b._iO.onfailure(b,a,c,e)};this._onfinish=function(){var a=b._iO.onfinish;b._onbufferchange(0);b._resetOnPosition(0);if(b.instanceCount){b.instanceCount--;if(!b.instanceCount&&(q(),b.playState= +0,b.paused=!1,b.instanceCount=0,b.instanceOptions={},b._iO={},I(),b.isHTML5))b.position=0;(!b.instanceCount||b._iO.multiShotEvents)&&a&&a.apply(b)}};this._whileloading=function(a,c,e,d){var f=b._iO;b.bytesLoaded=a;b.bytesTotal=c;b.duration=Math.floor(e);b.bufferLength=d;b.durationEstimate=!b.isHTML5&&!f.isMovieStar?f.duration?b.duration>f.duration?b.duration:f.duration:parseInt(b.bytesTotal/b.bytesLoaded*b.duration,10):b.duration;if(!b.isHTML5)b.buffered=[{start:0,end:b.duration}];(3!==b.readyState|| +b.isHTML5)&&f.whileloading&&f.whileloading.apply(b)};this._whileplaying=function(a,c,e,d,f){var g=b._iO;if(isNaN(a)||null===a)return!1;b.position=Math.max(0,a);b._processOnPosition();if(!b.isHTML5&&8opera.version()?new Audio(null):new Audio:null,d,b,g={},f;f=c.audioFormats;for(d in f)if(f.hasOwnProperty(d)&&(b="audio/"+d,g[d]=a(f[d].type),g[b]=g[d],d.match(Sa)?(c.flash[d]=!0,c.flash[b]=!0):(c.flash[d]=!1,c.flash[b]=!1),f[d]&&f[d].related))for(b=f[d].related.length- +1;0<=b;b--)g["audio/"+f[d].related[b]]=g[d],c.html5[f[d].related[b]]=g[d],c.flash[f[d].related[b]]=g[d];g.canPlayType=e?a:null;c.html5=r(c.html5,g);return!0};t=function(){};Z=function(a){if(8===j&&1j)c.flashVersion=j=9;c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":9===j?" (AS3/Flash 9)":" (AS2/Flash 8)");8'}if(J&&K)return!1;if(c.html5Only)return oa(),c.oMC=T(c.movieID),ka(),K=J=!0,!1;var b=e||c.url,g=c.altURL||b,f=qa(),h=G(),i=null,i=m.getElementsByTagName("html")[0],j,k,l,i=i&&i.dir&&i.dir.match(/rtl/i),a="undefined"===typeof a?c.id:a;oa();c.url=Ia(Ca?b:g);e=c.url;c.wmode=!c.wmode&&c.useHighPerformance?"transparent":c.wmode;if(null!==c.wmode&&(q.match(/msie 8/i)||!x&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i))c.wmode= +null;f={name:a,id:a,src:e,quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:Ta+"www.macromedia.com/go/getflashplayer",title:"JS/Flash audio component (SoundManager 2)",type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};if(c.debugFlash)f.FlashVars="debug=1";c.wmode||delete f.wmode;if(x)b=m.createElement("div"),k=['',d("movie",e),d("AllowScriptAccess",c.allowScriptAccess),d("quality",f.quality),c.wmode?d("wmode",c.wmode):"",d("bgcolor",c.bgColor),d("hasPriority","true"),c.debugFlash?d("FlashVars",f.FlashVars):"",""].join("");else for(j in b=m.createElement("embed"),f)f.hasOwnProperty(j)&&b.setAttribute(j,f[j]);ra();h=G();if(f=qa())if(c.oMC=T(c.movieID)||m.createElement("div"),c.oMC.id){l=c.oMC.className;c.oMC.className= +(l?l+" ":"movieContainer")+(h?" "+h:"");c.oMC.appendChild(b);if(x)j=c.oMC.appendChild(m.createElement("div")),j.className="sm2-object-box",j.innerHTML=k;K=!0}else{c.oMC.id=c.movieID;c.oMC.className="movieContainer "+h;j=h=null;if(!c.useFlashBlock)if(c.useHighPerformance)h={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"};else if(h={position:"absolute",width:"6px",height:"6px",top:"-9999px",left:"-9999px"},i)h.left=Math.abs(parseInt(h.left,10))+"px";if(Xa)c.oMC.style.zIndex= +1E4;if(!c.debugFlash)for(l in h)h.hasOwnProperty(l)&&(c.oMC.style[l]=h[l]);try{x||c.oMC.appendChild(b);f.appendChild(c.oMC);if(x)j=c.oMC.appendChild(m.createElement("div")),j.className="sm2-object-box",j.innerHTML=k;K=!0}catch(n){throw Error(t("domError")+" \n"+n.toString());}}return J=!0};W=function(){if(c.html5Only)return X(),!1;if(i||!c.url)return!1;i=c.getMovie(c.id);if(!i)N?(x?c.oMC.innerHTML=sa:c.oMC.appendChild(N),N=null,J=!0):X(c.id,c.url),i=c.getMovie(c.id);"function"===typeof c.oninitmovie&& +setTimeout(c.oninitmovie,1);return!0};D=function(){setTimeout(Fa,1E3)};Fa=function(){var a,e=!1;if(!c.url||O)return!1;O=!0;o.remove(h,"load",D);if(da&&!Ba)return!1;k||(a=c.getMoviePercent(),0a&&(e=!0));setTimeout(function(){a=c.getMoviePercent();if(e)return O=!1,h.setTimeout(D,1),!1;!k&&Ra&&(null===a?c.useFlashBlock||0===c.flashLoadTimeout?c.useFlashBlock&&ta():Y(!0):0!==c.flashLoadTimeout&&Y(!0))},c.flashLoadTimeout)};V=function(){if(Ba||!da)return o.remove(h,"focus",V),!0;Ba=Ra=!0;O=!1; +D();o.remove(h,"focus",V);return!0};Pa=function(){};L=function(a){if(k)return!1;if(c.html5Only)return k=!0,C(),!0;var e=!0,d;if(!c.useFlashBlock||!c.flashLoadTimeout||c.getMoviePercent())k=!0,s&&(d={type:!y&&n?"NO_FLASH":"INIT_TIMEOUT"});if(s||a){if(c.useFlashBlock&&c.oMC)c.oMC.className=G()+" "+(null===c.getMoviePercent()?"swf_timedout":"swf_error");B({type:"ontimeout",error:d,ignoreInit:!0});F(d);e=!1}s||(c.waitForWindowLoad&&!la?o.add(h,"load",C):C());return e};Ea=function(){var a,e=c.setupOptions; +for(a in e)e.hasOwnProperty(a)&&("undefined"===typeof c[a]?c[a]=e[a]:c[a]!==e[a]&&(c.setupOptions[a]=c[a]))};ka=function(){if(k)return!1;if(c.html5Only){if(!k)o.remove(h,"load",c.beginDelayedInit),c.enabled=!0,L();return!0}W();try{i._externalInterfaceTest(!1),Ga(!0,c.flashPollingInterval||(c.useHighPerformance?10:50)),c.debugMode||i._disableDebug(),c.enabled=!0,c.html5Only||o.add(h,"unload",ja)}catch(a){return F({type:"JS_TO_FLASH_EXCEPTION",fatal:!0}),Y(!0),L(),!1}L();o.remove(h,"load",c.beginDelayedInit); +return!0};E=function(){if(M)return!1;M=!0;Ea();ra();!y&&c.hasHTML5&&c.setup({useHTML5Audio:!0,preferFlash:!1});Na();c.html5.usingFlash=Ma();n=c.html5.usingFlash;Pa();!y&&n&&c.setup({flashLoadTimeout:1});m.removeEventListener&&m.removeEventListener("DOMContentLoaded",E,!1);W();return!0};wa=function(){"complete"===m.readyState&&(E(),m.detachEvent("onreadystatechange",wa));return!0};pa=function(){la=!0;o.remove(h,"load",pa)};xa();o.add(h,"focus",V);o.add(h,"load",D);o.add(h,"load",pa);m.addEventListener? +m.addEventListener("DOMContentLoaded",E,!1):m.attachEvent?m.attachEvent("onreadystatechange",wa):F({type:"NO_DOM2_EVENTS",fatal:!0})}var ea=null;if("undefined"===typeof SM2_DEFER||!SM2_DEFER)ea=new R;fa.SoundManager=R;fa.soundManager=ea})(window); \ No newline at end of file diff --git a/timeside/player/static/timeside/js/libs/soundmanager2-nodebug.js b/timeside/player/static/timeside/js/libs/soundmanager2-nodebug.js new file mode 100644 index 0000000..856175b --- /dev/null +++ b/timeside/player/static/timeside/js/libs/soundmanager2-nodebug.js @@ -0,0 +1,2511 @@ +/** @license + * + * SoundManager 2: JavaScript Sound for the Web + * ---------------------------------------------- + * http://schillmania.com/projects/soundmanager2/ + * + * Copyright (c) 2007, Scott Schiller. All rights reserved. + * Code provided under the BSD License: + * http://schillmania.com/projects/soundmanager2/license.txt + * + * V2.97a.20120916 + */ + +/*global window, SM2_DEFER, sm2Debugger, console, document, navigator, setTimeout, setInterval, clearInterval, Audio */ +/*jslint regexp: true, sloppy: true, white: true, nomen: true, plusplus: true */ + +(function(window) { +var soundManager = null; +function SoundManager(smURL, smID) { + this.setupOptions = { + 'url': (smURL || null), + 'flashVersion': 8, + 'debugMode': true, + 'debugFlash': false, + 'useConsole': true, + 'consoleOnly': true, + 'waitForWindowLoad': false, + 'bgColor': '#ffffff', + 'useHighPerformance': false, + 'flashPollingInterval': null, + 'html5PollingInterval': null, + 'flashLoadTimeout': 1000, + 'wmode': null, + 'allowScriptAccess': 'always', + 'useFlashBlock': false, + 'useHTML5Audio': true, + 'html5Test': /^(probably|maybe)$/i, + 'preferFlash': true, + 'noSWFCache': false + }; + this.defaultOptions = { + 'autoLoad': false, + 'autoPlay': false, + 'from': null, + 'loops': 1, + 'onid3': null, + 'onload': null, + 'whileloading': null, + 'onplay': null, + 'onpause': null, + 'onresume': null, + 'whileplaying': null, + 'onposition': null, + 'onstop': null, + 'onfailure': null, + 'onfinish': null, + 'multiShot': true, + 'multiShotEvents': false, + 'position': null, + 'pan': 0, + 'stream': true, + 'to': null, + 'type': null, + 'usePolicyFile': false, + 'volume': 100 + }; + this.flash9Options = { + 'isMovieStar': null, + 'usePeakData': false, + 'useWaveformData': false, + 'useEQData': false, + 'onbufferchange': null, + 'ondataerror': null + }; + this.movieStarOptions = { + 'bufferTime': 3, + 'serverURL': null, + 'onconnect': null, + 'duration': null + }; + this.audioFormats = { + 'mp3': { + 'type': ['audio/mpeg; codecs="mp3"', 'audio/mpeg', 'audio/mp3', 'audio/MPA', 'audio/mpa-robust'], + 'required': true + }, + 'mp4': { + 'related': ['aac','m4a','m4b'], + 'type': ['audio/mp4; codecs="mp4a.40.2"', 'audio/aac', 'audio/x-m4a', 'audio/MP4A-LATM', 'audio/mpeg4-generic'], + 'required': false + }, + 'ogg': { + 'type': ['audio/ogg; codecs=vorbis'], + 'required': false + }, + 'wav': { + 'type': ['audio/wav; codecs="1"', 'audio/wav', 'audio/wave', 'audio/x-wav'], + 'required': false + } + }; + this.movieID = 'sm2-container'; + this.id = (smID || 'sm2movie'); + this.debugID = 'soundmanager-debug'; + this.debugURLParam = /([#?&])debug=1/i; + this.versionNumber = 'V2.97a.20120916'; + this.version = null; + this.movieURL = null; + this.altURL = null; + this.swfLoaded = false; + this.enabled = false; + this.oMC = null; + this.sounds = {}; + this.soundIDs = []; + this.muted = false; + this.didFlashBlock = false; + this.filePattern = null; + this.filePatterns = { + 'flash8': /\.mp3(\?.*)?$/i, + 'flash9': /\.mp3(\?.*)?$/i + }; + this.features = { + 'buffering': false, + 'peakData': false, + 'waveformData': false, + 'eqData': false, + 'movieStar': false + }; + this.sandbox = { + }; + this.hasHTML5 = (function() { + try { + return (typeof Audio !== 'undefined' && typeof (_isOpera && opera.version() < 10 ? new Audio(null) : new Audio()).canPlayType !== 'undefined'); + } catch(e) { + return false; + } + }()); + this.html5 = { + 'usingFlash': null + }; + this.flash = {}; + this.html5Only = false; + this.ignoreFlash = false; + var SMSound, + _s = this, _flash = null, _sm = 'soundManager', _smc = _sm+'::', _h5 = 'HTML5::', _id, _ua = navigator.userAgent, _win = window, _wl = _win.location.href.toString(), _doc = document, _doNothing, _setProperties, _init, _fV, _on_queue = [], _debugOpen = true, _debugTS, _didAppend = false, _appendSuccess = false, _didInit = false, _disabled = false, _windowLoaded = false, _wDS, _wdCount = 0, _initComplete, _mixin, _assign, _extraOptions, _addOnEvent, _processOnEvents, _initUserOnload, _delayWaitForEI, _waitForEI, _setVersionInfo, _handleFocus, _strings, _initMovie, _domContentLoaded, _winOnLoad, _didDCLoaded, _getDocument, _createMovie, _catchError, _setPolling, _initDebug, _debugLevels = ['log', 'info', 'warn', 'error'], _defaultFlashVersion = 8, _disableObject, _failSafely, _normalizeMovieURL, _oRemoved = null, _oRemovedHTML = null, _str, _flashBlockHandler, _getSWFCSS, _swfCSS, _toggleDebug, _loopFix, _policyFix, _complain, _idCheck, _waitingForEI = false, _initPending = false, _startTimer, _stopTimer, _timerExecute, _h5TimerCount = 0, _h5IntervalTimer = null, _parseURL, + _needsFlash = null, _featureCheck, _html5OK, _html5CanPlay, _html5Ext, _html5Unload, _domContentLoadedIE, _testHTML5, _event, _slice = Array.prototype.slice, _useGlobalHTML5Audio = false, _hasFlash, _detectFlash, _badSafariFix, _html5_events, _showSupport, + _is_iDevice = _ua.match(/(ipad|iphone|ipod)/i), _isIE = _ua.match(/msie/i), _isWebkit = _ua.match(/webkit/i), _isSafari = (_ua.match(/safari/i) && !_ua.match(/chrome/i)), _isOpera = (_ua.match(/opera/i)), + _mobileHTML5 = (_ua.match(/(mobile|pre\/|xoom)/i) || _is_iDevice), + _isBadSafari = (!_wl.match(/usehtml5audio/i) && !_wl.match(/sm2\-ignorebadua/i) && _isSafari && !_ua.match(/silk/i) && _ua.match(/OS X 10_6_([3-7])/i)), + _hasConsole = (typeof console !== 'undefined' && typeof console.log !== 'undefined'), _isFocused = (typeof _doc.hasFocus !== 'undefined'?_doc.hasFocus():null), _tryInitOnFocus = (_isSafari && (typeof _doc.hasFocus === 'undefined' || !_doc.hasFocus())), _okToDisable = !_tryInitOnFocus, _flashMIME = /(mp3|mp4|mpa|m4a|m4b)/i, + _emptyURL = 'about:blank', + _overHTTP = (_doc.location?_doc.location.protocol.match(/http/i):null), + _http = (!_overHTTP ? 'http:/'+'/' : ''), + _netStreamMimeTypes = /^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i, + _netStreamTypes = ['mpeg4', 'aac', 'flv', 'mov', 'mp4', 'm4v', 'f4v', 'm4a', 'm4b', 'mp4v', '3gp', '3g2'], + _netStreamPattern = new RegExp('\\.(' + _netStreamTypes.join('|') + ')(\\?.*)?$', 'i'); + this.mimePattern = /^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i; + this.useAltURL = !_overHTTP; + this._global_a = null; + _swfCSS = { + 'swfBox': 'sm2-object-box', + 'swfDefault': 'movieContainer', + 'swfError': 'swf_error', + 'swfTimedout': 'swf_timedout', + 'swfLoaded': 'swf_loaded', + 'swfUnblocked': 'swf_unblocked', + 'sm2Debug': 'sm2_debug', + 'highPerf': 'high_performance', + 'flashDebug': 'flash_debug' + }; + if (_mobileHTML5) { + _s.useHTML5Audio = true; + _s.preferFlash = false; + if (_is_iDevice) { + _s.ignoreFlash = true; + _useGlobalHTML5Audio = true; + } + } + this.setup = function(options) { + var noURL = (!_s.url); + if (typeof options !== 'undefined' && _didInit && _needsFlash && _s.ok() && (typeof options.flashVersion !== 'undefined' || typeof options.url !== 'undefined')) { + _complain(_str('setupLate')); + } + _assign(options); + if (noURL && _didDCLoaded && typeof options.url !== 'undefined') { + _s.beginDelayedInit(); + } + if (!_didDCLoaded && typeof options.url !== 'undefined' && _doc.readyState === 'complete') { + setTimeout(_domContentLoaded, 1); + } + return _s; + }; + this.ok = function() { + return (_needsFlash?(_didInit && !_disabled):(_s.useHTML5Audio && _s.hasHTML5)); + }; + this.supported = this.ok; + this.getMovie = function(smID) { + return _id(smID) || _doc[smID] || _win[smID]; + }; + this.createSound = function(oOptions, _url) { + var _cs, _cs_string, thisOptions = null, oSound = null, _tO = null; + if (!_didInit || !_s.ok()) { + _complain(_cs_string); + return false; + } + if (typeof _url !== 'undefined') { + oOptions = { + 'id': oOptions, + 'url': _url + }; + } + thisOptions = _mixin(oOptions); + thisOptions.url = _parseURL(thisOptions.url); + _tO = thisOptions; + if (_idCheck(_tO.id, true)) { + return _s.sounds[_tO.id]; + } + function make() { + thisOptions = _loopFix(thisOptions); + _s.sounds[_tO.id] = new SMSound(_tO); + _s.soundIDs.push(_tO.id); + return _s.sounds[_tO.id]; + } + if (_html5OK(_tO)) { + oSound = make(); + oSound._setup_html5(_tO); + } else { + if (_fV > 8) { + if (_tO.isMovieStar === null) { + _tO.isMovieStar = !!(_tO.serverURL || (_tO.type ? _tO.type.match(_netStreamMimeTypes) : false) || _tO.url.match(_netStreamPattern)); + } + } + _tO = _policyFix(_tO, _cs); + oSound = make(); + if (_fV === 8) { + _flash._createSound(_tO.id, _tO.loops||1, _tO.usePolicyFile); + } else { + _flash._createSound(_tO.id, _tO.url, _tO.usePeakData, _tO.useWaveformData, _tO.useEQData, _tO.isMovieStar, (_tO.isMovieStar?_tO.bufferTime:false), _tO.loops||1, _tO.serverURL, _tO.duration||null, _tO.autoPlay, true, _tO.autoLoad, _tO.usePolicyFile); + if (!_tO.serverURL) { + oSound.connected = true; + if (_tO.onconnect) { + _tO.onconnect.apply(oSound); + } + } + } + if (!_tO.serverURL && (_tO.autoLoad || _tO.autoPlay)) { + oSound.load(_tO); + } + } + if (!_tO.serverURL && _tO.autoPlay) { + oSound.play(); + } + return oSound; + }; + this.destroySound = function(sID, _bFromSound) { + if (!_idCheck(sID)) { + return false; + } + var oS = _s.sounds[sID], i; + oS._iO = {}; + oS.stop(); + oS.unload(); + for (i = 0; i < _s.soundIDs.length; i++) { + if (_s.soundIDs[i] === sID) { + _s.soundIDs.splice(i, 1); + break; + } + } + if (!_bFromSound) { + oS.destruct(true); + } + oS = null; + delete _s.sounds[sID]; + return true; + }; + this.load = function(sID, oOptions) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].load(oOptions); + }; + this.unload = function(sID) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].unload(); + }; + this.onPosition = function(sID, nPosition, oMethod, oScope) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].onposition(nPosition, oMethod, oScope); + }; + this.onposition = this.onPosition; + this.clearOnPosition = function(sID, nPosition, oMethod) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].clearOnPosition(nPosition, oMethod); + }; + this.play = function(sID, oOptions) { + var result = false; + if (!_didInit || !_s.ok()) { + _complain(_sm+'.play(): ' + _str(!_didInit?'notReady':'notOK')); + return result; + } + if (!_idCheck(sID)) { + if (!(oOptions instanceof Object)) { + oOptions = { + url: oOptions + }; + } + if (oOptions && oOptions.url) { + oOptions.id = sID; + result = _s.createSound(oOptions).play(); + } + return result; + } + return _s.sounds[sID].play(oOptions); + }; + this.start = this.play; + this.setPosition = function(sID, nMsecOffset) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].setPosition(nMsecOffset); + }; + this.stop = function(sID) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].stop(); + }; + this.stopAll = function() { + var oSound; + for (oSound in _s.sounds) { + if (_s.sounds.hasOwnProperty(oSound)) { + _s.sounds[oSound].stop(); + } + } + }; + this.pause = function(sID) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].pause(); + }; + this.pauseAll = function() { + var i; + for (i = _s.soundIDs.length-1; i >= 0; i--) { + _s.sounds[_s.soundIDs[i]].pause(); + } + }; + this.resume = function(sID) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].resume(); + }; + this.resumeAll = function() { + var i; + for (i = _s.soundIDs.length-1; i >= 0; i--) { + _s.sounds[_s.soundIDs[i]].resume(); + } + }; + this.togglePause = function(sID) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].togglePause(); + }; + this.setPan = function(sID, nPan) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].setPan(nPan); + }; + this.setVolume = function(sID, nVol) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].setVolume(nVol); + }; + this.mute = function(sID) { + var i = 0; + if (typeof sID !== 'string') { + sID = null; + } + if (!sID) { + for (i = _s.soundIDs.length-1; i >= 0; i--) { + _s.sounds[_s.soundIDs[i]].mute(); + } + _s.muted = true; + } else { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].mute(); + } + return true; + }; + this.muteAll = function() { + _s.mute(); + }; + this.unmute = function(sID) { + var i; + if (typeof sID !== 'string') { + sID = null; + } + if (!sID) { + for (i = _s.soundIDs.length-1; i >= 0; i--) { + _s.sounds[_s.soundIDs[i]].unmute(); + } + _s.muted = false; + } else { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].unmute(); + } + return true; + }; + this.unmuteAll = function() { + _s.unmute(); + }; + this.toggleMute = function(sID) { + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].toggleMute(); + }; + this.getMemoryUse = function() { + var ram = 0; + if (_flash && _fV !== 8) { + ram = parseInt(_flash._getMemoryUse(), 10); + } + return ram; + }; + this.disable = function(bNoDisable) { + var i; + if (typeof bNoDisable === 'undefined') { + bNoDisable = false; + } + if (_disabled) { + return false; + } + _disabled = true; + for (i = _s.soundIDs.length-1; i >= 0; i--) { + _disableObject(_s.sounds[_s.soundIDs[i]]); + } + _initComplete(bNoDisable); + _event.remove(_win, 'load', _initUserOnload); + return true; + }; + this.canPlayMIME = function(sMIME) { + var result; + if (_s.hasHTML5) { + result = _html5CanPlay({type:sMIME}); + } + if (!result && _needsFlash) { + result = (sMIME && _s.ok() ? !!((_fV > 8 ? sMIME.match(_netStreamMimeTypes) : null) || sMIME.match(_s.mimePattern)) : null); + } + return result; + }; + this.canPlayURL = function(sURL) { + var result; + if (_s.hasHTML5) { + result = _html5CanPlay({url: sURL}); + } + if (!result && _needsFlash) { + result = (sURL && _s.ok() ? !!(sURL.match(_s.filePattern)) : null); + } + return result; + }; + this.canPlayLink = function(oLink) { + if (typeof oLink.type !== 'undefined' && oLink.type) { + if (_s.canPlayMIME(oLink.type)) { + return true; + } + } + return _s.canPlayURL(oLink.href); + }; + this.getSoundById = function(sID, _suppressDebug) { + if (!sID) { + throw new Error(_sm+'.getSoundById(): sID is null/undefined'); + } + var result = _s.sounds[sID]; + return result; + }; + this.onready = function(oMethod, oScope) { + var sType = 'onready', + result = false; + if (typeof oMethod === 'function') { + if (!oScope) { + oScope = _win; + } + _addOnEvent(sType, oMethod, oScope); + _processOnEvents(); + result = true; + } else { + throw _str('needFunction', sType); + } + return result; + }; + this.ontimeout = function(oMethod, oScope) { + var sType = 'ontimeout', + result = false; + if (typeof oMethod === 'function') { + if (!oScope) { + oScope = _win; + } + _addOnEvent(sType, oMethod, oScope); + _processOnEvents({type:sType}); + result = true; + } else { + throw _str('needFunction', sType); + } + return result; + }; + this._writeDebug = function(sText, sType, _bTimestamp) { + return true; + }; + this._wD = this._writeDebug; + this._debug = function() { + }; + this.reboot = function() { + var i, j; + for (i = _s.soundIDs.length-1; i >= 0; i--) { + _s.sounds[_s.soundIDs[i]].destruct(); + } + if (_flash) { + try { + if (_isIE) { + _oRemovedHTML = _flash.innerHTML; + } + _oRemoved = _flash.parentNode.removeChild(_flash); + } catch(e) { + } + } + _oRemovedHTML = _oRemoved = _needsFlash = null; + _s.enabled = _didDCLoaded = _didInit = _waitingForEI = _initPending = _didAppend = _appendSuccess = _disabled = _s.swfLoaded = false; + _s.soundIDs = []; + _s.sounds = {}; + _flash = null; + for (i in _on_queue) { + if (_on_queue.hasOwnProperty(i)) { + for (j = _on_queue[i].length-1; j >= 0; j--) { + _on_queue[i][j].fired = false; + } + } + } + _win.setTimeout(_s.beginDelayedInit, 20); + }; + this.getMoviePercent = function() { + return (_flash && typeof _flash.PercentLoaded !== 'undefined' ? _flash.PercentLoaded() : null); + }; + this.beginDelayedInit = function() { + _windowLoaded = true; + _domContentLoaded(); + setTimeout(function() { + if (_initPending) { + return false; + } + _createMovie(); + _initMovie(); + _initPending = true; + return true; + }, 20); + _delayWaitForEI(); + }; + this.destruct = function() { + _s.disable(true); + }; + SMSound = function(oOptions) { + var _t = this, _resetProperties, _add_html5_events, _remove_html5_events, _stop_html5_timer, _start_html5_timer, _attachOnPosition, _onplay_called = false, _onPositionItems = [], _onPositionFired = 0, _detachOnPosition, _applyFromTo, _lastURL = null, _lastHTML5State; + _lastHTML5State = { + duration: null, + time: null + }; + this.id = oOptions.id; + this.sID = this.id; + this.url = oOptions.url; + this.options = _mixin(oOptions); + this.instanceOptions = this.options; + this._iO = this.instanceOptions; + this.pan = this.options.pan; + this.volume = this.options.volume; + this.isHTML5 = false; + this._a = null; + this.id3 = {}; + this._debug = function() { + }; + this.load = function(oOptions) { + var oS = null, _iO; + if (typeof oOptions !== 'undefined') { + _t._iO = _mixin(oOptions, _t.options); + _t.instanceOptions = _t._iO; + } else { + oOptions = _t.options; + _t._iO = oOptions; + _t.instanceOptions = _t._iO; + if (_lastURL && _lastURL !== _t.url) { + _t._iO.url = _t.url; + _t.url = null; + } + } + if (!_t._iO.url) { + _t._iO.url = _t.url; + } + _t._iO.url = _parseURL(_t._iO.url); + if (_t._iO.url === _t.url && _t.readyState !== 0 && _t.readyState !== 2) { + if (_t.readyState === 3 && _t._iO.onload) { + _t._iO.onload.apply(_t, [(!!_t.duration)]); + } + return _t; + } + _iO = _t._iO; + _lastURL = (_t.url && _t.url.toString ? _t.url.toString() : null); + _t.loaded = false; + _t.readyState = 1; + _t.playState = 0; + _t.id3 = {}; + if (_html5OK(_iO)) { + oS = _t._setup_html5(_iO); + if (!oS._called_load) { + _t._html5_canplay = false; + if (_t._a.src !== _iO.url) { + _t._a.src = _iO.url; + _t.setPosition(0); + } + _t._a.autobuffer = 'auto'; + _t._a.preload = 'auto'; + oS._called_load = true; + if (_iO.autoPlay) { + _t.play(); + } + } else { + } + } else { + try { + _t.isHTML5 = false; + _t._iO = _policyFix(_loopFix(_iO)); + _iO = _t._iO; + if (_fV === 8) { + _flash._load(_t.id, _iO.url, _iO.stream, _iO.autoPlay, (_iO.whileloading?1:0), _iO.loops||1, _iO.usePolicyFile); + } else { + _flash._load(_t.id, _iO.url, !!(_iO.stream), !!(_iO.autoPlay), _iO.loops||1, !!(_iO.autoLoad), _iO.usePolicyFile); + } + } catch(e) { + _catchError({type:'SMSOUND_LOAD_JS_EXCEPTION', fatal:true}); + } + } + _t.url = _iO.url; + return _t; + }; + this.unload = function() { + if (_t.readyState !== 0) { + if (!_t.isHTML5) { + if (_fV === 8) { + _flash._unload(_t.id, _emptyURL); + } else { + _flash._unload(_t.id); + } + } else { + _stop_html5_timer(); + if (_t._a) { + _t._a.pause(); + _html5Unload(_t._a, _emptyURL); + _t.url = _emptyURL; + } + } + _resetProperties(); + } + return _t; + }; + this.destruct = function(_bFromSM) { + if (!_t.isHTML5) { + _t._iO.onfailure = null; + _flash._destroySound(_t.id); + } else { + _stop_html5_timer(); + if (_t._a) { + _t._a.pause(); + _html5Unload(_t._a); + if (!_useGlobalHTML5Audio) { + _remove_html5_events(); + } + _t._a._t = null; + _t._a = null; + } + } + if (!_bFromSM) { + _s.destroySound(_t.id, true); + } + }; + this.play = function(oOptions, _updatePlayState) { + var fN, allowMulti, a, onready, startOK = true, + exit = null; + _updatePlayState = (typeof _updatePlayState === 'undefined' ? true : _updatePlayState); + if (!oOptions) { + oOptions = {}; + } + if (_t.url) { + _t._iO.url = _t.url; + } + _t._iO = _mixin(_t._iO, _t.options); + _t._iO = _mixin(oOptions, _t._iO); + _t._iO.url = _parseURL(_t._iO.url); + _t.instanceOptions = _t._iO; + if (_t._iO.serverURL && !_t.connected) { + if (!_t.getAutoPlay()) { + _t.setAutoPlay(true); + } + return _t; + } + if (_html5OK(_t._iO)) { + _t._setup_html5(_t._iO); + _start_html5_timer(); + } + if (_t.playState === 1 && !_t.paused) { + allowMulti = _t._iO.multiShot; + if (!allowMulti) { + exit = _t; + } else { + } + } + if (exit !== null) { + return exit; + } + if (oOptions.url && oOptions.url !== _t.url) { + _t.load(_t._iO); + } + if (!_t.loaded) { + if (_t.readyState === 0) { + if (!_t.isHTML5) { + _t._iO.autoPlay = true; + _t.load(_t._iO); + } else { + _t.load(_t._iO); + } + } else if (_t.readyState === 2) { + exit = _t; + } else { + } + } else { + } + if (exit !== null) { + return exit; + } + if (!_t.isHTML5 && _fV === 9 && _t.position > 0 && _t.position === _t.duration) { + oOptions.position = 0; + } + if (_t.paused && _t.position >= 0 && (!_t._iO.serverURL || _t.position > 0)) { + _t.resume(); + } else { + _t._iO = _mixin(oOptions, _t._iO); + if (_t._iO.from !== null && _t._iO.to !== null && _t.instanceCount === 0 && _t.playState === 0 && !_t._iO.serverURL) { + onready = function() { + _t._iO = _mixin(oOptions, _t._iO); + _t.play(_t._iO); + }; + if (_t.isHTML5 && !_t._html5_canplay) { + _t.load({ + _oncanplay: onready + }); + exit = false; + } else if (!_t.isHTML5 && !_t.loaded && (!_t.readyState || _t.readyState !== 2)) { + _t.load({ + onload: onready + }); + exit = false; + } + if (exit !== null) { + return exit; + } + _t._iO = _applyFromTo(); + } + if (!_t.instanceCount || _t._iO.multiShotEvents || (!_t.isHTML5 && _fV > 8 && !_t.getAutoPlay())) { + _t.instanceCount++; + } + if (_t._iO.onposition && _t.playState === 0) { + _attachOnPosition(_t); + } + _t.playState = 1; + _t.paused = false; + _t.position = (typeof _t._iO.position !== 'undefined' && !isNaN(_t._iO.position) ? _t._iO.position : 0); + if (!_t.isHTML5) { + _t._iO = _policyFix(_loopFix(_t._iO)); + } + if (_t._iO.onplay && _updatePlayState) { + _t._iO.onplay.apply(_t); + _onplay_called = true; + } + _t.setVolume(_t._iO.volume, true); + _t.setPan(_t._iO.pan, true); + if (!_t.isHTML5) { + startOK = _flash._start(_t.id, _t._iO.loops || 1, (_fV === 9 ? _t._iO.position : _t._iO.position / 1000), _t._iO.multiShot); + if (_fV === 9 && !startOK) { + if (_t._iO.onplayerror) { + _t._iO.onplayerror.apply(_t); + } + } + } else { + _start_html5_timer(); + a = _t._setup_html5(); + _t.setPosition(_t._iO.position); + a.play(); + } + } + return _t; + }; + this.start = this.play; + this.stop = function(bAll) { + var _iO = _t._iO, _oP; + if (_t.playState === 1) { + _t._onbufferchange(0); + _t._resetOnPosition(0); + _t.paused = false; + if (!_t.isHTML5) { + _t.playState = 0; + } + _detachOnPosition(); + if (_iO.to) { + _t.clearOnPosition(_iO.to); + } + if (!_t.isHTML5) { + _flash._stop(_t.id, bAll); + if (_iO.serverURL) { + _t.unload(); + } + } else { + if (_t._a) { + _oP = _t.position; + _t.setPosition(0); + _t.position = _oP; + _t._a.pause(); + _t.playState = 0; + _t._onTimer(); + _stop_html5_timer(); + } + } + _t.instanceCount = 0; + _t._iO = {}; + if (_iO.onstop) { + _iO.onstop.apply(_t); + } + } + return _t; + }; + this.setAutoPlay = function(autoPlay) { + _t._iO.autoPlay = autoPlay; + if (!_t.isHTML5) { + _flash._setAutoPlay(_t.id, autoPlay); + if (autoPlay) { + if (!_t.instanceCount && _t.readyState === 1) { + _t.instanceCount++; + } + } + } + }; + this.getAutoPlay = function() { + return _t._iO.autoPlay; + }; + this.setPosition = function(nMsecOffset) { + if (typeof nMsecOffset === 'undefined') { + nMsecOffset = 0; + } + var original_pos, + position, position1K, + offset = (_t.isHTML5 ? Math.max(nMsecOffset, 0) : Math.min(_t.duration || _t._iO.duration, Math.max(nMsecOffset, 0))); + original_pos = _t.position; + _t.position = offset; + position1K = _t.position/1000; + _t._resetOnPosition(_t.position); + _t._iO.position = offset; + if (!_t.isHTML5) { + position = (_fV === 9 ? _t.position : position1K); + if (_t.readyState && _t.readyState !== 2) { + _flash._setPosition(_t.id, position, (_t.paused || !_t.playState), _t._iO.multiShot); + } + } else if (_t._a) { + if (_t._html5_canplay) { + if (_t._a.currentTime !== position1K) { + try { + _t._a.currentTime = position1K; + if (_t.playState === 0 || _t.paused) { + _t._a.pause(); + } + } catch(e) { + } + } + } else { + } + } + if (_t.isHTML5) { + if (_t.paused) { + _t._onTimer(true); + } + } + return _t; + }; + this.pause = function(_bCallFlash) { + if (_t.paused || (_t.playState === 0 && _t.readyState !== 1)) { + return _t; + } + _t.paused = true; + if (!_t.isHTML5) { + if (_bCallFlash || typeof _bCallFlash === 'undefined') { + _flash._pause(_t.id, _t._iO.multiShot); + } + } else { + _t._setup_html5().pause(); + _stop_html5_timer(); + } + if (_t._iO.onpause) { + _t._iO.onpause.apply(_t); + } + return _t; + }; + this.resume = function() { + var _iO = _t._iO; + if (!_t.paused) { + return _t; + } + _t.paused = false; + _t.playState = 1; + if (!_t.isHTML5) { + if (_iO.isMovieStar && !_iO.serverURL) { + _t.setPosition(_t.position); + } + _flash._pause(_t.id, _iO.multiShot); + } else { + _t._setup_html5().play(); + _start_html5_timer(); + } + if (!_onplay_called && _iO.onplay) { + _iO.onplay.apply(_t); + _onplay_called = true; + } else if (_iO.onresume) { + _iO.onresume.apply(_t); + } + return _t; + }; + this.togglePause = function() { + if (_t.playState === 0) { + _t.play({ + position: (_fV === 9 && !_t.isHTML5 ? _t.position : _t.position / 1000) + }); + return _t; + } + if (_t.paused) { + _t.resume(); + } else { + _t.pause(); + } + return _t; + }; + this.setPan = function(nPan, bInstanceOnly) { + if (typeof nPan === 'undefined') { + nPan = 0; + } + if (typeof bInstanceOnly === 'undefined') { + bInstanceOnly = false; + } + if (!_t.isHTML5) { + _flash._setPan(_t.id, nPan); + } + _t._iO.pan = nPan; + if (!bInstanceOnly) { + _t.pan = nPan; + _t.options.pan = nPan; + } + return _t; + }; + this.setVolume = function(nVol, _bInstanceOnly) { + if (typeof nVol === 'undefined') { + nVol = 100; + } + if (typeof _bInstanceOnly === 'undefined') { + _bInstanceOnly = false; + } + if (!_t.isHTML5) { + _flash._setVolume(_t.id, (_s.muted && !_t.muted) || _t.muted?0:nVol); + } else if (_t._a) { + _t._a.volume = Math.max(0, Math.min(1, nVol/100)); + } + _t._iO.volume = nVol; + if (!_bInstanceOnly) { + _t.volume = nVol; + _t.options.volume = nVol; + } + return _t; + }; + this.mute = function() { + _t.muted = true; + if (!_t.isHTML5) { + _flash._setVolume(_t.id, 0); + } else if (_t._a) { + _t._a.muted = true; + } + return _t; + }; + this.unmute = function() { + _t.muted = false; + var hasIO = (typeof _t._iO.volume !== 'undefined'); + if (!_t.isHTML5) { + _flash._setVolume(_t.id, hasIO?_t._iO.volume:_t.options.volume); + } else if (_t._a) { + _t._a.muted = false; + } + return _t; + }; + this.toggleMute = function() { + return (_t.muted?_t.unmute():_t.mute()); + }; + this.onPosition = function(nPosition, oMethod, oScope) { + _onPositionItems.push({ + position: parseInt(nPosition, 10), + method: oMethod, + scope: (typeof oScope !== 'undefined' ? oScope : _t), + fired: false + }); + return _t; + }; + this.onposition = this.onPosition; + this.clearOnPosition = function(nPosition, oMethod) { + var i; + nPosition = parseInt(nPosition, 10); + if (isNaN(nPosition)) { + return false; + } + for (i=0; i < _onPositionItems.length; i++) { + if (nPosition === _onPositionItems[i].position) { + if (!oMethod || (oMethod === _onPositionItems[i].method)) { + if (_onPositionItems[i].fired) { + _onPositionFired--; + } + _onPositionItems.splice(i, 1); + } + } + } + }; + this._processOnPosition = function() { + var i, item, j = _onPositionItems.length; + if (!j || !_t.playState || _onPositionFired >= j) { + return false; + } + for (i=j-1; i >= 0; i--) { + item = _onPositionItems[i]; + if (!item.fired && _t.position >= item.position) { + item.fired = true; + _onPositionFired++; + item.method.apply(item.scope, [item.position]); + } + } + return true; + }; + this._resetOnPosition = function(nPosition) { + var i, item, j = _onPositionItems.length; + if (!j) { + return false; + } + for (i=j-1; i >= 0; i--) { + item = _onPositionItems[i]; + if (item.fired && nPosition <= item.position) { + item.fired = false; + _onPositionFired--; + } + } + return true; + }; + _applyFromTo = function() { + var _iO = _t._iO, + f = _iO.from, + t = _iO.to, + start, end; + end = function() { + _t.clearOnPosition(t, end); + _t.stop(); + }; + start = function() { + if (t !== null && !isNaN(t)) { + _t.onPosition(t, end); + } + }; + if (f !== null && !isNaN(f)) { + _iO.position = f; + _iO.multiShot = false; + start(); + } + return _iO; + }; + _attachOnPosition = function() { + var item, + op = _t._iO.onposition; + if (op) { + for (item in op) { + if (op.hasOwnProperty(item)) { + _t.onPosition(parseInt(item, 10), op[item]); + } + } + } + }; + _detachOnPosition = function() { + var item, + op = _t._iO.onposition; + if (op) { + for (item in op) { + if (op.hasOwnProperty(item)) { + _t.clearOnPosition(parseInt(item, 10)); + } + } + } + }; + _start_html5_timer = function() { + if (_t.isHTML5) { + _startTimer(_t); + } + }; + _stop_html5_timer = function() { + if (_t.isHTML5) { + _stopTimer(_t); + } + }; + _resetProperties = function(retainPosition) { + if (!retainPosition) { + _onPositionItems = []; + _onPositionFired = 0; + } + _onplay_called = false; + _t._hasTimer = null; + _t._a = null; + _t._html5_canplay = false; + _t.bytesLoaded = null; + _t.bytesTotal = null; + _t.duration = (_t._iO && _t._iO.duration ? _t._iO.duration : null); + _t.durationEstimate = null; + _t.buffered = []; + _t.eqData = []; + _t.eqData.left = []; + _t.eqData.right = []; + _t.failures = 0; + _t.isBuffering = false; + _t.instanceOptions = {}; + _t.instanceCount = 0; + _t.loaded = false; + _t.metadata = {}; + _t.readyState = 0; + _t.muted = false; + _t.paused = false; + _t.peakData = { + left: 0, + right: 0 + }; + _t.waveformData = { + left: [], + right: [] + }; + _t.playState = 0; + _t.position = null; + _t.id3 = {}; + }; + _resetProperties(); + this._onTimer = function(bForce) { + var duration, isNew = false, time, x = {}; + if (_t._hasTimer || bForce) { + if (_t._a && (bForce || ((_t.playState > 0 || _t.readyState === 1) && !_t.paused))) { + duration = _t._get_html5_duration(); + if (duration !== _lastHTML5State.duration) { + _lastHTML5State.duration = duration; + _t.duration = duration; + isNew = true; + } + _t.durationEstimate = _t.duration; + time = (_t._a.currentTime * 1000 || 0); + if (time !== _lastHTML5State.time) { + _lastHTML5State.time = time; + isNew = true; + } + if (isNew || bForce) { + _t._whileplaying(time,x,x,x,x); + } + } + return isNew; + } + }; + this._get_html5_duration = function() { + var _iO = _t._iO, + d = (_t._a && _t._a.duration ? _t._a.duration*1000 : (_iO && _iO.duration ? _iO.duration : null)), + result = (d && !isNaN(d) && d !== Infinity ? d : null); + return result; + }; + this._apply_loop = function(a, nLoops) { + a.loop = (nLoops > 1 ? 'loop' : ''); + }; + this._setup_html5 = function(oOptions) { + var _iO = _mixin(_t._iO, oOptions), d = decodeURI, + _a = _useGlobalHTML5Audio ? _s._global_a : _t._a, + _dURL = d(_iO.url), + _oldIO = (_a && _a._t ? _a._t.instanceOptions : null), + result; + if (_a) { + if (_a._t) { + if (!_useGlobalHTML5Audio && _dURL === d(_lastURL)) { + result = _a; + } else if (_useGlobalHTML5Audio && _oldIO.url === _iO.url && (!_lastURL || (_lastURL === _oldIO.url))) { + result = _a; + } + if (result) { + _t._apply_loop(_a, _iO.loops); + return result; + } + } + if (_useGlobalHTML5Audio && _a._t && _a._t.playState && _iO.url !== _oldIO.url) { + _a._t.stop(); + } + _resetProperties((_oldIO && _oldIO.url ? _iO.url === _oldIO.url : (_lastURL ? _lastURL === _iO.url : false))); + _a.src = _iO.url; + _t.url = _iO.url; + _lastURL = _iO.url; + _a._called_load = false; + } else { + if (_iO.autoLoad || _iO.autoPlay) { + _t._a = new Audio(_iO.url); + } else { + _t._a = (_isOpera && opera.version() < 10 ? new Audio(null) : new Audio()); + } + _a = _t._a; + _a._called_load = false; + if (_useGlobalHTML5Audio) { + _s._global_a = _a; + } + } + _t.isHTML5 = true; + _t._a = _a; + _a._t = _t; + _add_html5_events(); + _t._apply_loop(_a, _iO.loops); + if (_iO.autoLoad || _iO.autoPlay) { + _t.load(); + } else { + _a.autobuffer = false; + _a.preload = 'auto'; + } + return _a; + }; + _add_html5_events = function() { + if (_t._a._added_events) { + return false; + } + var f; + function add(oEvt, oFn, bCapture) { + return _t._a ? _t._a.addEventListener(oEvt, oFn, bCapture||false) : null; + } + _t._a._added_events = true; + for (f in _html5_events) { + if (_html5_events.hasOwnProperty(f)) { + add(f, _html5_events[f]); + } + } + return true; + }; + _remove_html5_events = function() { + var f; + function remove(oEvt, oFn, bCapture) { + return (_t._a ? _t._a.removeEventListener(oEvt, oFn, bCapture||false) : null); + } + _t._a._added_events = false; + for (f in _html5_events) { + if (_html5_events.hasOwnProperty(f)) { + remove(f, _html5_events[f]); + } + } + }; + this._onload = function(nSuccess) { + var fN, + loadOK = (!!(nSuccess) || (!_t.isHTML5 && _fV === 8 && _t.duration)); + _t.loaded = loadOK; + _t.readyState = loadOK?3:2; + _t._onbufferchange(0); + if (_t._iO.onload) { + _t._iO.onload.apply(_t, [loadOK]); + } + return true; + }; + this._onbufferchange = function(nIsBuffering) { + if (_t.playState === 0) { + return false; + } + if ((nIsBuffering && _t.isBuffering) || (!nIsBuffering && !_t.isBuffering)) { + return false; + } + _t.isBuffering = (nIsBuffering === 1); + if (_t._iO.onbufferchange) { + _t._iO.onbufferchange.apply(_t); + } + return true; + }; + this._onsuspend = function() { + if (_t._iO.onsuspend) { + _t._iO.onsuspend.apply(_t); + } + return true; + }; + this._onfailure = function(msg, level, code) { + _t.failures++; + if (_t._iO.onfailure && _t.failures === 1) { + _t._iO.onfailure(_t, msg, level, code); + } else { + } + }; + this._onfinish = function() { + var _io_onfinish = _t._iO.onfinish; + _t._onbufferchange(0); + _t._resetOnPosition(0); + if (_t.instanceCount) { + _t.instanceCount--; + if (!_t.instanceCount) { + _detachOnPosition(); + _t.playState = 0; + _t.paused = false; + _t.instanceCount = 0; + _t.instanceOptions = {}; + _t._iO = {}; + _stop_html5_timer(); + if (_t.isHTML5) { + _t.position = 0; + } + } + if (!_t.instanceCount || _t._iO.multiShotEvents) { + if (_io_onfinish) { + _io_onfinish.apply(_t); + } + } + } + }; + this._whileloading = function(nBytesLoaded, nBytesTotal, nDuration, nBufferLength) { + var _iO = _t._iO; + _t.bytesLoaded = nBytesLoaded; + _t.bytesTotal = nBytesTotal; + _t.duration = Math.floor(nDuration); + _t.bufferLength = nBufferLength; + if (!_t.isHTML5 && !_iO.isMovieStar) { + if (_iO.duration) { + _t.durationEstimate = (_t.duration > _iO.duration) ? _t.duration : _iO.duration; + } else { + _t.durationEstimate = parseInt((_t.bytesTotal / _t.bytesLoaded) * _t.duration, 10); + } + } else { + _t.durationEstimate = _t.duration; + } + if (!_t.isHTML5) { + _t.buffered = [{ + 'start': 0, + 'end': _t.duration + }]; + } + if ((_t.readyState !== 3 || _t.isHTML5) && _iO.whileloading) { + _iO.whileloading.apply(_t); + } + }; + this._whileplaying = function(nPosition, oPeakData, oWaveformDataLeft, oWaveformDataRight, oEQData) { + var _iO = _t._iO, + eqLeft; + if (isNaN(nPosition) || nPosition === null) { + return false; + } + _t.position = Math.max(0, nPosition); + _t._processOnPosition(); + if (!_t.isHTML5 && _fV > 8) { + if (_iO.usePeakData && typeof oPeakData !== 'undefined' && oPeakData) { + _t.peakData = { + left: oPeakData.leftPeak, + right: oPeakData.rightPeak + }; + } + if (_iO.useWaveformData && typeof oWaveformDataLeft !== 'undefined' && oWaveformDataLeft) { + _t.waveformData = { + left: oWaveformDataLeft.split(','), + right: oWaveformDataRight.split(',') + }; + } + if (_iO.useEQData) { + if (typeof oEQData !== 'undefined' && oEQData && oEQData.leftEQ) { + eqLeft = oEQData.leftEQ.split(','); + _t.eqData = eqLeft; + _t.eqData.left = eqLeft; + if (typeof oEQData.rightEQ !== 'undefined' && oEQData.rightEQ) { + _t.eqData.right = oEQData.rightEQ.split(','); + } + } + } + } + if (_t.playState === 1) { + if (!_t.isHTML5 && _fV === 8 && !_t.position && _t.isBuffering) { + _t._onbufferchange(0); + } + if (_iO.whileplaying) { + _iO.whileplaying.apply(_t); + } + } + return true; + }; + this._oncaptiondata = function(oData) { + _t.captiondata = oData; + if (_t._iO.oncaptiondata) { + _t._iO.oncaptiondata.apply(_t, [oData]); + } + }; + this._onmetadata = function(oMDProps, oMDData) { + var oData = {}, i, j; + for (i = 0, j = oMDProps.length; i < j; i++) { + oData[oMDProps[i]] = oMDData[i]; + } + _t.metadata = oData; + if (_t._iO.onmetadata) { + _t._iO.onmetadata.apply(_t); + } + }; + this._onid3 = function(oID3Props, oID3Data) { + var oData = [], i, j; + for (i = 0, j = oID3Props.length; i < j; i++) { + oData[oID3Props[i]] = oID3Data[i]; + } + _t.id3 = _mixin(_t.id3, oData); + if (_t._iO.onid3) { + _t._iO.onid3.apply(_t); + } + }; + this._onconnect = function(bSuccess) { + bSuccess = (bSuccess === 1); + _t.connected = bSuccess; + if (bSuccess) { + _t.failures = 0; + if (_idCheck(_t.id)) { + if (_t.getAutoPlay()) { + _t.play(undefined, _t.getAutoPlay()); + } else if (_t._iO.autoLoad) { + _t.load(); + } + } + if (_t._iO.onconnect) { + _t._iO.onconnect.apply(_t, [bSuccess]); + } + } + }; + this._ondataerror = function(sError) { + if (_t.playState > 0) { + if (_t._iO.ondataerror) { + _t._iO.ondataerror.apply(_t); + } + } + }; + }; + _getDocument = function() { + return (_doc.body || _doc._docElement || _doc.getElementsByTagName('div')[0]); + }; + _id = function(sID) { + return _doc.getElementById(sID); + }; + _mixin = function(oMain, oAdd) { + var o1 = (oMain || {}), o2, o; + o2 = (typeof oAdd === 'undefined' ? _s.defaultOptions : oAdd); + for (o in o2) { + if (o2.hasOwnProperty(o) && typeof o1[o] === 'undefined') { + if (typeof o2[o] !== 'object' || o2[o] === null) { + o1[o] = o2[o]; + } else { + o1[o] = _mixin(o1[o], o2[o]); + } + } + } + return o1; + }; + _extraOptions = { + 'onready': 1, + 'ontimeout': 1, + 'defaultOptions': 1, + 'flash9Options': 1, + 'movieStarOptions': 1 + }; + _assign = function(o, oParent) { + var i, + result = true, + hasParent = (typeof oParent !== 'undefined'), + setupOptions = _s.setupOptions, + extraOptions = _extraOptions; + for (i in o) { + if (o.hasOwnProperty(i)) { + if (typeof o[i] !== 'object' || o[i] === null || o[i] instanceof Array) { + if (hasParent && typeof extraOptions[oParent] !== 'undefined') { + _s[oParent][i] = o[i]; + } else if (typeof setupOptions[i] !== 'undefined') { + _s.setupOptions[i] = o[i]; + _s[i] = o[i]; + } else if (typeof extraOptions[i] === 'undefined') { + _complain(_str((typeof _s[i] === 'undefined' ? 'setupUndef' : 'setupError'), i), 2); + result = false; + } else { + if (_s[i] instanceof Function) { + _s[i].apply(_s, (o[i] instanceof Array? o[i] : [o[i]])); + } else { + _s[i] = o[i]; + } + } + } else { + if (typeof extraOptions[i] === 'undefined') { + _complain(_str((typeof _s[i] === 'undefined' ? 'setupUndef' : 'setupError'), i), 2); + result = false; + } else { + return _assign(o[i], i); + } + } + } + } + return result; + }; + function _preferFlashCheck(kind) { + return (_s.preferFlash && _hasFlash && !_s.ignoreFlash && (typeof _s.flash[kind] !== 'undefined' && _s.flash[kind])); + } + _event = (function() { + var old = (_win.attachEvent), + evt = { + add: (old?'attachEvent':'addEventListener'), + remove: (old?'detachEvent':'removeEventListener') + }; + function getArgs(oArgs) { + var args = _slice.call(oArgs), + len = args.length; + if (old) { + args[1] = 'on' + args[1]; + if (len > 3) { + args.pop(); + } + } else if (len === 3) { + args.push(false); + } + return args; + } + function apply(args, sType) { + var element = args.shift(), + method = [evt[sType]]; + if (old) { + element[method](args[0], args[1]); + } else { + element[method].apply(element, args); + } + } + function add() { + apply(getArgs(arguments), 'add'); + } + function remove() { + apply(getArgs(arguments), 'remove'); + } + return { + 'add': add, + 'remove': remove + }; + }()); + function _html5_event(oFn) { + return function(e) { + var t = this._t, + result; + if (!t || !t._a) { + result = null; + } else { + result = oFn.call(this, e); + } + return result; + }; + } + _html5_events = { + abort: _html5_event(function() { + }), + canplay: _html5_event(function() { + var t = this._t, + position1K; + if (t._html5_canplay) { + return true; + } + t._html5_canplay = true; + t._onbufferchange(0); + position1K = (typeof t._iO.position !== 'undefined' && !isNaN(t._iO.position)?t._iO.position/1000:null); + if (t.position && this.currentTime !== position1K) { + try { + this.currentTime = position1K; + } catch(ee) { + } + } + if (t._iO._oncanplay) { + t._iO._oncanplay(); + } + }), + canplaythrough: _html5_event(function() { + var t = this._t; + if (!t.loaded) { + t._onbufferchange(0); + t._whileloading(t.bytesLoaded, t.bytesTotal, t._get_html5_duration()); + t._onload(true); + } + }), + ended: _html5_event(function() { + var t = this._t; + t._onfinish(); + }), + error: _html5_event(function() { + this._t._onload(false); + }), + loadeddata: _html5_event(function() { + var t = this._t; + if (!t._loaded && !_isSafari) { + t.duration = t._get_html5_duration(); + } + }), + loadedmetadata: _html5_event(function() { + }), + loadstart: _html5_event(function() { + this._t._onbufferchange(1); + }), + play: _html5_event(function() { + this._t._onbufferchange(0); + }), + playing: _html5_event(function() { + this._t._onbufferchange(0); + }), + progress: _html5_event(function(e) { + var t = this._t, + i, j, str, buffered = 0, + isProgress = (e.type === 'progress'), + ranges = e.target.buffered, + loaded = (e.loaded||0), + total = (e.total||1), + scale = 1000; + t.buffered = []; + if (ranges && ranges.length) { + for (i=0, j=ranges.length; i= 0; i--) { + support['audio/'+aF[item].related[i]] = support[item]; + _s.html5[aF[item].related[i]] = support[item]; + _s.flash[aF[item].related[i]] = support[item]; + } + } + } + } + support.canPlayType = (a?_cp:null); + _s.html5 = _mixin(_s.html5, support); + return true; + }; + _strings = { + }; + _str = function() { + }; + _loopFix = function(sOpt) { + if (_fV === 8 && sOpt.loops > 1 && sOpt.stream) { + sOpt.stream = false; + } + return sOpt; + }; + _policyFix = function(sOpt, sPre) { + if (sOpt && !sOpt.usePolicyFile && (sOpt.onid3 || sOpt.usePeakData || sOpt.useWaveformData || sOpt.useEQData)) { + sOpt.usePolicyFile = true; + } + return sOpt; + }; + _complain = function(sMsg) { + }; + _doNothing = function() { + return false; + }; + _disableObject = function(o) { + var oProp; + for (oProp in o) { + if (o.hasOwnProperty(oProp) && typeof o[oProp] === 'function') { + o[oProp] = _doNothing; + } + } + oProp = null; + }; + _failSafely = function(bNoDisable) { + if (typeof bNoDisable === 'undefined') { + bNoDisable = false; + } + if (_disabled || bNoDisable) { + _s.disable(bNoDisable); + } + }; + _normalizeMovieURL = function(smURL) { + var urlParams = null, url; + if (smURL) { + if (smURL.match(/\.swf(\?.*)?$/i)) { + urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf('.swf?') + 4); + if (urlParams) { + return smURL; + } + } else if (smURL.lastIndexOf('/') !== smURL.length - 1) { + smURL += '/'; + } + } + url = (smURL && smURL.lastIndexOf('/') !== - 1 ? smURL.substr(0, smURL.lastIndexOf('/') + 1) : './') + _s.movieURL; + if (_s.noSWFCache) { + url += ('?ts=' + new Date().getTime()); + } + return url; + }; + _setVersionInfo = function() { + _fV = parseInt(_s.flashVersion, 10); + if (_fV !== 8 && _fV !== 9) { + _s.flashVersion = _fV = _defaultFlashVersion; + } + var isDebug = (_s.debugMode || _s.debugFlash?'_debug.swf':'.swf'); + if (_s.useHTML5Audio && !_s.html5Only && _s.audioFormats.mp4.required && _fV < 9) { + _s.flashVersion = _fV = 9; + } + _s.version = _s.versionNumber + (_s.html5Only?' (HTML5-only mode)':(_fV === 9?' (AS3/Flash 9)':' (AS2/Flash 8)')); + if (_fV > 8) { + _s.defaultOptions = _mixin(_s.defaultOptions, _s.flash9Options); + _s.features.buffering = true; + _s.defaultOptions = _mixin(_s.defaultOptions, _s.movieStarOptions); + _s.filePatterns.flash9 = new RegExp('\\.(mp3|' + _netStreamTypes.join('|') + ')(\\?.*)?$', 'i'); + _s.features.movieStar = true; + } else { + _s.features.movieStar = false; + } + _s.filePattern = _s.filePatterns[(_fV !== 8?'flash9':'flash8')]; + _s.movieURL = (_fV === 8?'soundmanager2.swf':'soundmanager2_flash9.swf').replace('.swf', isDebug); + _s.features.peakData = _s.features.waveformData = _s.features.eqData = (_fV > 8); + }; + _setPolling = function(bPolling, bHighPerformance) { + if (!_flash) { + return false; + } + _flash._setPolling(bPolling, bHighPerformance); + }; + _initDebug = function() { + if (_s.debugURLParam.test(_wl)) { + _s.debugMode = true; + } + }; + _idCheck = this.getSoundById; + _getSWFCSS = function() { + var css = []; + if (_s.debugMode) { + css.push(_swfCSS.sm2Debug); + } + if (_s.debugFlash) { + css.push(_swfCSS.flashDebug); + } + if (_s.useHighPerformance) { + css.push(_swfCSS.highPerf); + } + return css.join(' '); + }; + _flashBlockHandler = function() { + var name = _str('fbHandler'), + p = _s.getMoviePercent(), + css = _swfCSS, + error = {type:'FLASHBLOCK'}; + if (_s.html5Only) { + return false; + } + if (!_s.ok()) { + if (_needsFlash) { + _s.oMC.className = _getSWFCSS() + ' ' + css.swfDefault + ' ' + (p === null?css.swfTimedout:css.swfError); + } + _s.didFlashBlock = true; + _processOnEvents({type:'ontimeout', ignoreInit:true, error:error}); + _catchError(error); + } else { + if (_s.oMC) { + _s.oMC.className = [_getSWFCSS(), css.swfDefault, css.swfLoaded + (_s.didFlashBlock?' '+css.swfUnblocked:'')].join(' '); + } + } + }; + _addOnEvent = function(sType, oMethod, oScope) { + if (typeof _on_queue[sType] === 'undefined') { + _on_queue[sType] = []; + } + _on_queue[sType].push({ + 'method': oMethod, + 'scope': (oScope || null), + 'fired': false + }); + }; + _processOnEvents = function(oOptions) { + if (!oOptions) { + oOptions = { + type: (_s.ok() ? 'onready' : 'ontimeout') + }; + } + if (!_didInit && oOptions && !oOptions.ignoreInit) { + return false; + } + if (oOptions.type === 'ontimeout' && (_s.ok() || (_disabled && !oOptions.ignoreInit))) { + return false; + } + var status = { + success: (oOptions && oOptions.ignoreInit?_s.ok():!_disabled) + }, + srcQueue = (oOptions && oOptions.type?_on_queue[oOptions.type]||[]:[]), + queue = [], i, j, + args = [status], + canRetry = (_needsFlash && _s.useFlashBlock && !_s.ok()); + if (oOptions.error) { + args[0].error = oOptions.error; + } + for (i = 0, j = srcQueue.length; i < j; i++) { + if (srcQueue[i].fired !== true) { + queue.push(srcQueue[i]); + } + } + if (queue.length) { + for (i = 0, j = queue.length; i < j; i++) { + if (queue[i].scope) { + queue[i].method.apply(queue[i].scope, args); + } else { + queue[i].method.apply(this, args); + } + if (!canRetry) { + queue[i].fired = true; + } + } + } + return true; + }; + _initUserOnload = function() { + _win.setTimeout(function() { + if (_s.useFlashBlock) { + _flashBlockHandler(); + } + _processOnEvents(); + if (typeof _s.onload === 'function') { + _s.onload.apply(_win); + } + if (_s.waitForWindowLoad) { + _event.add(_win, 'load', _initUserOnload); + } + },1); + }; + _detectFlash = function() { + if (typeof _hasFlash !== 'undefined') { + return _hasFlash; + } + var hasPlugin = false, n = navigator, nP = n.plugins, obj, type, types, AX = _win.ActiveXObject; + if (nP && nP.length) { + type = 'application/x-shockwave-flash'; + types = n.mimeTypes; + if (types && types[type] && types[type].enabledPlugin && types[type].enabledPlugin.description) { + hasPlugin = true; + } + } else if (typeof AX !== 'undefined') { + try { + obj = new AX('ShockwaveFlash.ShockwaveFlash'); + } catch(e) { + } + hasPlugin = (!!obj); + } + _hasFlash = hasPlugin; + return hasPlugin; + }; + _featureCheck = function() { + var needsFlash, + item, + result = true, + formats = _s.audioFormats, + isSpecial = (_is_iDevice && !!(_ua.match(/os (1|2|3_0|3_1)/i))); + if (isSpecial) { + _s.hasHTML5 = false; + _s.html5Only = true; + if (_s.oMC) { + _s.oMC.style.display = 'none'; + } + result = false; + } else { + if (_s.useHTML5Audio) { + if (!_s.html5 || !_s.html5.canPlayType) { + _s.hasHTML5 = false; + } + } + } + if (_s.useHTML5Audio && _s.hasHTML5) { + for (item in formats) { + if (formats.hasOwnProperty(item)) { + if ((formats[item].required && !_s.html5.canPlayType(formats[item].type)) || (_s.preferFlash && (_s.flash[item] || _s.flash[formats[item].type]))) { + needsFlash = true; + } + } + } + } + if (_s.ignoreFlash) { + needsFlash = false; + } + _s.html5Only = (_s.hasHTML5 && _s.useHTML5Audio && !needsFlash); + return (!_s.html5Only); + }; + _parseURL = function(url) { + var i, j, urlResult = 0, result; + if (url instanceof Array) { + for (i=0, j=url.length; i= 0; i--) { + if (_s.sounds[_s.soundIDs[i]].isHTML5 && _s.sounds[_s.soundIDs[i]]._hasTimer) { + _s.sounds[_s.soundIDs[i]]._onTimer(); + } + } + }; + _catchError = function(options) { + options = (typeof options !== 'undefined' ? options : {}); + if (typeof _s.onerror === 'function') { + _s.onerror.apply(_win, [{type:(typeof options.type !== 'undefined' ? options.type : null)}]); + } + if (typeof options.fatal !== 'undefined' && options.fatal) { + _s.disable(); + } + }; + _badSafariFix = function() { + if (!_isBadSafari || !_detectFlash()) { + return false; + } + var aF = _s.audioFormats, i, item; + for (item in aF) { + if (aF.hasOwnProperty(item)) { + if (item === 'mp3' || item === 'mp4') { + _s.html5[item] = false; + if (aF[item] && aF[item].related) { + for (i = aF[item].related.length-1; i >= 0; i--) { + _s.html5[aF[item].related[i]] = false; + } + } + } + } + } + }; + this._setSandboxType = function(sandboxType) { + }; + this._externalInterfaceOK = function(flashDate, swfVersion) { + if (_s.swfLoaded) { + return false; + } + var e, eiTime = new Date().getTime(); + _s.swfLoaded = true; + _tryInitOnFocus = false; + if (_isBadSafari) { + _badSafariFix(); + } + setTimeout(_init, _isIE ? 100 : 1); + }; + _createMovie = function(smID, smURL) { + if (_didAppend && _appendSuccess) { + return false; + } + function _initMsg() { + } + if (_s.html5Only) { + _setVersionInfo(); + _initMsg(); + _s.oMC = _id(_s.movieID); + _init(); + _didAppend = true; + _appendSuccess = true; + return false; + } + var remoteURL = (smURL || _s.url), + localURL = (_s.altURL || remoteURL), + swfTitle = 'JS/Flash audio component (SoundManager 2)', + oTarget = _getDocument(), + extraClass = _getSWFCSS(), + isRTL = null, + html = _doc.getElementsByTagName('html')[0], + oEmbed, oMovie, tmp, movieHTML, oEl, s, x, sClass; + isRTL = (html && html.dir && html.dir.match(/rtl/i)); + smID = (typeof smID === 'undefined'?_s.id:smID); + function param(name, value) { + return ''; + } + _setVersionInfo(); + _s.url = _normalizeMovieURL(_overHTTP?remoteURL:localURL); + smURL = _s.url; + _s.wmode = (!_s.wmode && _s.useHighPerformance ? 'transparent' : _s.wmode); + if (_s.wmode !== null && (_ua.match(/msie 8/i) || (!_isIE && !_s.useHighPerformance)) && navigator.platform.match(/win32|win64/i)) { + _s.wmode = null; + } + oEmbed = { + 'name': smID, + 'id': smID, + 'src': smURL, + 'quality': 'high', + 'allowScriptAccess': _s.allowScriptAccess, + 'bgcolor': _s.bgColor, + 'pluginspage': _http+'www.macromedia.com/go/getflashplayer', + 'title': swfTitle, + 'type': 'application/x-shockwave-flash', + 'wmode': _s.wmode, + 'hasPriority': 'true' + }; + if (_s.debugFlash) { + oEmbed.FlashVars = 'debug=1'; + } + if (!_s.wmode) { + delete oEmbed.wmode; + } + if (_isIE) { + oMovie = _doc.createElement('div'); + movieHTML = [ + '', + param('movie', smURL), + param('AllowScriptAccess', _s.allowScriptAccess), + param('quality', oEmbed.quality), + (_s.wmode? param('wmode', _s.wmode): ''), + param('bgcolor', _s.bgColor), + param('hasPriority', 'true'), + (_s.debugFlash ? param('FlashVars', oEmbed.FlashVars) : ''), + '' + ].join(''); + } else { + oMovie = _doc.createElement('embed'); + for (tmp in oEmbed) { + if (oEmbed.hasOwnProperty(tmp)) { + oMovie.setAttribute(tmp, oEmbed[tmp]); + } + } + } + _initDebug(); + extraClass = _getSWFCSS(); + oTarget = _getDocument(); + if (oTarget) { + _s.oMC = (_id(_s.movieID) || _doc.createElement('div')); + if (!_s.oMC.id) { + _s.oMC.id = _s.movieID; + _s.oMC.className = _swfCSS.swfDefault + ' ' + extraClass; + s = null; + oEl = null; + if (!_s.useFlashBlock) { + if (_s.useHighPerformance) { + s = { + 'position': 'fixed', + 'width': '8px', + 'height': '8px', + 'bottom': '0px', + 'left': '0px', + 'overflow': 'hidden' + }; + } else { + s = { + 'position': 'absolute', + 'width': '6px', + 'height': '6px', + 'top': '-9999px', + 'left': '-9999px' + }; + if (isRTL) { + s.left = Math.abs(parseInt(s.left,10))+'px'; + } + } + } + if (_isWebkit) { + _s.oMC.style.zIndex = 10000; + } + if (!_s.debugFlash) { + for (x in s) { + if (s.hasOwnProperty(x)) { + _s.oMC.style[x] = s[x]; + } + } + } + try { + if (!_isIE) { + _s.oMC.appendChild(oMovie); + } + oTarget.appendChild(_s.oMC); + if (_isIE) { + oEl = _s.oMC.appendChild(_doc.createElement('div')); + oEl.className = _swfCSS.swfBox; + oEl.innerHTML = movieHTML; + } + _appendSuccess = true; + } catch(e) { + throw new Error(_str('domError')+' \n'+e.toString()); + } + } else { + sClass = _s.oMC.className; + _s.oMC.className = (sClass?sClass+' ':_swfCSS.swfDefault) + (extraClass?' '+extraClass:''); + _s.oMC.appendChild(oMovie); + if (_isIE) { + oEl = _s.oMC.appendChild(_doc.createElement('div')); + oEl.className = _swfCSS.swfBox; + oEl.innerHTML = movieHTML; + } + _appendSuccess = true; + } + } + _didAppend = true; + _initMsg(); + return true; + }; + _initMovie = function() { + if (_s.html5Only) { + _createMovie(); + return false; + } + if (_flash) { + return false; + } + if (!_s.url) { + return false; + } + _flash = _s.getMovie(_s.id); + if (!_flash) { + if (!_oRemoved) { + _createMovie(_s.id, _s.url); + } else { + if (!_isIE) { + _s.oMC.appendChild(_oRemoved); + } else { + _s.oMC.innerHTML = _oRemovedHTML; + } + _oRemoved = null; + _didAppend = true; + } + _flash = _s.getMovie(_s.id); + } + if (typeof _s.oninitmovie === 'function') { + setTimeout(_s.oninitmovie, 1); + } + return true; + }; + _delayWaitForEI = function() { + setTimeout(_waitForEI, 1000); + }; + _waitForEI = function() { + var p, + loadIncomplete = false; + if (!_s.url) { + return false; + } + if (_waitingForEI) { + return false; + } + _waitingForEI = true; + _event.remove(_win, 'load', _delayWaitForEI); + if (_tryInitOnFocus && !_isFocused) { + return false; + } + if (!_didInit) { + p = _s.getMoviePercent(); + if (p > 0 && p < 100) { + loadIncomplete = true; + } + } + setTimeout(function() { + p = _s.getMoviePercent(); + if (loadIncomplete) { + _waitingForEI = false; + _win.setTimeout(_delayWaitForEI, 1); + return false; + } + if (!_didInit && _okToDisable) { + if (p === null) { + if (_s.useFlashBlock || _s.flashLoadTimeout === 0) { + if (_s.useFlashBlock) { + _flashBlockHandler(); + } + } else { + _failSafely(true); + } + } else { + if (_s.flashLoadTimeout === 0) { + } else { + _failSafely(true); + } + } + } + }, _s.flashLoadTimeout); + }; + _handleFocus = function() { + function cleanup() { + _event.remove(_win, 'focus', _handleFocus); + } + if (_isFocused || !_tryInitOnFocus) { + cleanup(); + return true; + } + _okToDisable = true; + _isFocused = true; + _waitingForEI = false; + _delayWaitForEI(); + cleanup(); + return true; + }; + _showSupport = function() { + }; + _initComplete = function(bNoDisable) { + if (_didInit) { + return false; + } + if (_s.html5Only) { + _didInit = true; + _initUserOnload(); + return true; + } + var wasTimeout = (_s.useFlashBlock && _s.flashLoadTimeout && !_s.getMoviePercent()), + result = true, + error; + if (!wasTimeout) { + _didInit = true; + if (_disabled) { + error = {type: (!_hasFlash && _needsFlash ? 'NO_FLASH' : 'INIT_TIMEOUT')}; + } + } + if (_disabled || bNoDisable) { + if (_s.useFlashBlock && _s.oMC) { + _s.oMC.className = _getSWFCSS() + ' ' + (_s.getMoviePercent() === null?_swfCSS.swfTimedout:_swfCSS.swfError); + } + _processOnEvents({type:'ontimeout', error:error, ignoreInit: true}); + _catchError(error); + result = false; + } else { + } + if (!_disabled) { + if (_s.waitForWindowLoad && !_windowLoaded) { + _event.add(_win, 'load', _initUserOnload); + } else { + _initUserOnload(); + } + } + return result; + }; + _setProperties = function() { + var i, + o = _s.setupOptions; + for (i in o) { + if (o.hasOwnProperty(i)) { + if (typeof _s[i] === 'undefined') { + _s[i] = o[i]; + } else if (_s[i] !== o[i]) { + _s.setupOptions[i] = _s[i]; + } + } + } + }; + _init = function() { + if (_didInit) { + return false; + } + function _cleanup() { + _event.remove(_win, 'load', _s.beginDelayedInit); + } + if (_s.html5Only) { + if (!_didInit) { + _cleanup(); + _s.enabled = true; + _initComplete(); + } + return true; + } + _initMovie(); + try { + _flash._externalInterfaceTest(false); + _setPolling(true, (_s.flashPollingInterval || (_s.useHighPerformance ? 10 : 50))); + if (!_s.debugMode) { + _flash._disableDebug(); + } + _s.enabled = true; + if (!_s.html5Only) { + _event.add(_win, 'unload', _doNothing); + } + } catch(e) { + _catchError({type:'JS_TO_FLASH_EXCEPTION', fatal:true}); + _failSafely(true); + _initComplete(); + return false; + } + _initComplete(); + _cleanup(); + return true; + }; + _domContentLoaded = function() { + if (_didDCLoaded) { + return false; + } + _didDCLoaded = true; + _setProperties(); + _initDebug(); + if (!_hasFlash && _s.hasHTML5) { + _s.setup({ + 'useHTML5Audio': true, + 'preferFlash': false + }); + } + _testHTML5(); + _s.html5.usingFlash = _featureCheck(); + _needsFlash = _s.html5.usingFlash; + _showSupport(); + if (!_hasFlash && _needsFlash) { + _s.setup({ + 'flashLoadTimeout': 1 + }); + } + if (_doc.removeEventListener) { + _doc.removeEventListener('DOMContentLoaded', _domContentLoaded, false); + } + _initMovie(); + return true; + }; + _domContentLoadedIE = function() { + if (_doc.readyState === 'complete') { + _domContentLoaded(); + _doc.detachEvent('onreadystatechange', _domContentLoadedIE); + } + return true; + }; + _winOnLoad = function() { + _windowLoaded = true; + _event.remove(_win, 'load', _winOnLoad); + }; + _detectFlash(); + _event.add(_win, 'focus', _handleFocus); + _event.add(_win, 'load', _delayWaitForEI); + _event.add(_win, 'load', _winOnLoad); + if (_doc.addEventListener) { + _doc.addEventListener('DOMContentLoaded', _domContentLoaded, false); + } else if (_doc.attachEvent) { + _doc.attachEvent('onreadystatechange', _domContentLoadedIE); + } else { + _catchError({type:'NO_DOM2_EVENTS', fatal:true}); + } +} +// SM2_DEFER details: http://www.schillmania.com/projects/soundmanager2/doc/getstarted/#lazy-loading +if (typeof SM2_DEFER === 'undefined' || !SM2_DEFER) { + soundManager = new SoundManager(); +} +window.SoundManager = SoundManager; +window.soundManager = soundManager; +}(window)); \ No newline at end of file diff --git a/timeside/player/static/timeside/js/libs/soundmanager2.js b/timeside/player/static/timeside/js/libs/soundmanager2.js new file mode 100644 index 0000000..d9d4422 --- /dev/null +++ b/timeside/player/static/timeside/js/libs/soundmanager2.js @@ -0,0 +1,5530 @@ +/** @license + * + * SoundManager 2: JavaScript Sound for the Web + * ---------------------------------------------- + * http://schillmania.com/projects/soundmanager2/ + * + * Copyright (c) 2007, Scott Schiller. All rights reserved. + * Code provided under the BSD License: + * http://schillmania.com/projects/soundmanager2/license.txt + * + * V2.97a.20120916 + */ + +/*global window, SM2_DEFER, sm2Debugger, console, document, navigator, setTimeout, setInterval, clearInterval, Audio */ +/*jslint regexp: true, sloppy: true, white: true, nomen: true, plusplus: true */ + +/** + * About this file + * --------------- + * This is the fully-commented source version of the SoundManager 2 API, + * recommended for use during development and testing. + * + * See soundmanager2-nodebug-jsmin.js for an optimized build (~11KB with gzip.) + * http://schillmania.com/projects/soundmanager2/doc/getstarted/#basic-inclusion + * Alternately, serve this file with gzip for 75% compression savings (~30KB over HTTP.) + * + * You may notice and comments in this source; these are delimiters for + * debug blocks which are removed in the -nodebug builds, further optimizing code size. + * + * Also, as you may note: Whoa, reliable cross-platform/device audio support is hard! ;) + */ + +(function(window) { + +var soundManager = null; + +/** + * The SoundManager constructor. + * + * @constructor + * @param {string} smURL Optional: Path to SWF files + * @param {string} smID Optional: The ID to use for the SWF container element + * @this {SoundManager} + * @return {SoundManager} The new SoundManager instance + */ + +function SoundManager(smURL, smID) { + + /** + * soundManager configuration options list + * defines top-level configuration properties to be applied to the soundManager instance (eg. soundManager.flashVersion) + * to set these properties, use the setup() method - eg., soundManager.setup({url: '/swf/', flashVersion: 9}) + */ + + this.setupOptions = { + + 'url': (smURL || null), // path (directory) where SoundManager 2 SWFs exist, eg., /path/to/swfs/ + 'flashVersion': 8, // flash build to use (8 or 9.) Some API features require 9. + 'debugMode': true, // enable debugging output (console.log() with HTML fallback) + 'debugFlash': false, // enable debugging output inside SWF, troubleshoot Flash/browser issues + 'useConsole': true, // use console.log() if available (otherwise, writes to #soundmanager-debug element) + 'consoleOnly': true, // if console is being used, do not create/write to #soundmanager-debug + 'waitForWindowLoad': false, // force SM2 to wait for window.onload() before trying to call soundManager.onload() + 'bgColor': '#ffffff', // SWF background color. N/A when wmode = 'transparent' + 'useHighPerformance': false, // position:fixed flash movie can help increase js/flash speed, minimize lag + 'flashPollingInterval': null, // msec affecting whileplaying/loading callback frequency. If null, default of 50 msec is used. + 'html5PollingInterval': null, // msec affecting whileplaying() for HTML5 audio, excluding mobile devices. If null, native HTML5 update events are used. + 'flashLoadTimeout': 1000, // msec to wait for flash movie to load before failing (0 = infinity) + 'wmode': null, // flash rendering mode - null, 'transparent', or 'opaque' (last two allow z-index to work) + 'allowScriptAccess': 'always', // for scripting the SWF (object/embed property), 'always' or 'sameDomain' + 'useFlashBlock': false, // *requires flashblock.css, see demos* - allow recovery from flash blockers. Wait indefinitely and apply timeout CSS to SWF, if applicable. + 'useHTML5Audio': true, // use HTML5 Audio() where API is supported (most Safari, Chrome versions), Firefox (no MP3/MP4.) Ideally, transparent vs. Flash API where possible. + 'html5Test': /^(probably|maybe)$/i, // HTML5 Audio() format support test. Use /^probably$/i; if you want to be more conservative. + 'preferFlash': true, // overrides useHTML5audio. if true and flash support present, will try to use flash for MP3/MP4 as needed since HTML5 audio support is still quirky in browsers. + 'noSWFCache': false // if true, appends ?ts={date} to break aggressive SWF caching. + + }; + + this.defaultOptions = { + + /** + * the default configuration for sound objects made with createSound() and related methods + * eg., volume, auto-load behaviour and so forth + */ + + 'autoLoad': false, // enable automatic loading (otherwise .load() will be called on demand with .play(), the latter being nicer on bandwidth - if you want to .load yourself, you also can) + 'autoPlay': false, // enable playing of file as soon as possible (much faster if "stream" is true) + 'from': null, // position to start playback within a sound (msec), default = beginning + 'loops': 1, // how many times to repeat the sound (position will wrap around to 0, setPosition() will break out of loop when >0) + 'onid3': null, // callback function for "ID3 data is added/available" + 'onload': null, // callback function for "load finished" + 'whileloading': null, // callback function for "download progress update" (X of Y bytes received) + 'onplay': null, // callback for "play" start + 'onpause': null, // callback for "pause" + 'onresume': null, // callback for "resume" (pause toggle) + 'whileplaying': null, // callback during play (position update) + 'onposition': null, // object containing times and function callbacks for positions of interest + 'onstop': null, // callback for "user stop" + 'onfailure': null, // callback function for when playing fails + 'onfinish': null, // callback function for "sound finished playing" + 'multiShot': true, // let sounds "restart" or layer on top of each other when played multiple times, rather than one-shot/one at a time + 'multiShotEvents': false, // fire multiple sound events (currently onfinish() only) when multiShot is enabled + 'position': null, // offset (milliseconds) to seek to within loaded sound data. + 'pan': 0, // "pan" settings, left-to-right, -100 to 100 + 'stream': true, // allows playing before entire file has loaded (recommended) + 'to': null, // position to end playback within a sound (msec), default = end + 'type': null, // MIME-like hint for file pattern / canPlay() tests, eg. audio/mp3 + 'usePolicyFile': false, // enable crossdomain.xml request for audio on remote domains (for ID3/waveform access) + 'volume': 100 // self-explanatory. 0-100, the latter being the max. + + }; + + this.flash9Options = { + + /** + * flash 9-only options, + * merged into defaultOptions if flash 9 is being used + */ + + 'isMovieStar': null, // "MovieStar" MPEG4 audio mode. Null (default) = auto detect MP4, AAC etc. based on URL. true = force on, ignore URL + 'usePeakData': false, // enable left/right channel peak (level) data + 'useWaveformData': false, // enable sound spectrum (raw waveform data) - NOTE: May increase CPU load. + 'useEQData': false, // enable sound EQ (frequency spectrum data) - NOTE: May increase CPU load. + 'onbufferchange': null, // callback for "isBuffering" property change + 'ondataerror': null // callback for waveform/eq data access error (flash playing audio in other tabs/domains) + + }; + + this.movieStarOptions = { + + /** + * flash 9.0r115+ MPEG4 audio options, + * merged into defaultOptions if flash 9+movieStar mode is enabled + */ + + 'bufferTime': 3, // seconds of data to buffer before playback begins (null = flash default of 0.1 seconds - if AAC playback is gappy, try increasing.) + 'serverURL': null, // rtmp: FMS or FMIS server to connect to, required when requesting media via RTMP or one of its variants + 'onconnect': null, // rtmp: callback for connection to flash media server + 'duration': null // rtmp: song duration (msec) + + }; + + this.audioFormats = { + + /** + * determines HTML5 support + flash requirements. + * if no support (via flash and/or HTML5) for a "required" format, SM2 will fail to start. + * flash fallback is used for MP3 or MP4 if HTML5 can't play it (or if preferFlash = true) + */ + + 'mp3': { + 'type': ['audio/mpeg; codecs="mp3"', 'audio/mpeg', 'audio/mp3', 'audio/MPA', 'audio/mpa-robust'], + 'required': true + }, + + 'mp4': { + 'related': ['aac','m4a','m4b'], // additional formats under the MP4 container + 'type': ['audio/mp4; codecs="mp4a.40.2"', 'audio/aac', 'audio/x-m4a', 'audio/MP4A-LATM', 'audio/mpeg4-generic'], + 'required': false + }, + + 'ogg': { + 'type': ['audio/ogg; codecs=vorbis'], + 'required': false + }, + + 'wav': { + 'type': ['audio/wav; codecs="1"', 'audio/wav', 'audio/wave', 'audio/x-wav'], + 'required': false + } + + }; + + // HTML attributes (id + class names) for the SWF container + + this.movieID = 'sm2-container'; + this.id = (smID || 'sm2movie'); + + this.debugID = 'soundmanager-debug'; + this.debugURLParam = /([#?&])debug=1/i; + + // dynamic attributes + + this.versionNumber = 'V2.97a.20120916'; + this.version = null; + this.movieURL = null; + this.altURL = null; + this.swfLoaded = false; + this.enabled = false; + this.oMC = null; + this.sounds = {}; + this.soundIDs = []; + this.muted = false; + this.didFlashBlock = false; + this.filePattern = null; + + this.filePatterns = { + + 'flash8': /\.mp3(\?.*)?$/i, + 'flash9': /\.mp3(\?.*)?$/i + + }; + + // support indicators, set at init + + this.features = { + + 'buffering': false, + 'peakData': false, + 'waveformData': false, + 'eqData': false, + 'movieStar': false + + }; + + // flash sandbox info, used primarily in troubleshooting + + this.sandbox = { + + // + 'type': null, + 'types': { + 'remote': 'remote (domain-based) rules', + 'localWithFile': 'local with file access (no internet access)', + 'localWithNetwork': 'local with network (internet access only, no local access)', + 'localTrusted': 'local, trusted (local+internet access)' + }, + 'description': null, + 'noRemote': null, + 'noLocal': null + // + + }; + + /** + * basic HTML5 Audio() support test + * try...catch because of IE 9 "not implemented" nonsense + * https://github.com/Modernizr/Modernizr/issues/224 + */ + + this.hasHTML5 = (function() { + try { + // new Audio(null) for stupid Opera 9.64 case, which throws not_enough_arguments exception otherwise. + return (typeof Audio !== 'undefined' && typeof (_isOpera && opera.version() < 10 ? new Audio(null) : new Audio()).canPlayType !== 'undefined'); + } catch(e) { + return false; + } + }()); + + /** + * format support (html5/flash) + * stores canPlayType() results based on audioFormats. + * eg. { mp3: boolean, mp4: boolean } + * treat as read-only. + */ + + this.html5 = { + 'usingFlash': null // set if/when flash fallback is needed + }; + + // file type support hash + this.flash = {}; + + // determined at init time + this.html5Only = false; + + // used for special cases (eg. iPad/iPhone/palm OS?) + this.ignoreFlash = false; + + /** + * a few private internals (OK, a lot. :D) + */ + + var SMSound, + _s = this, _flash = null, _sm = 'soundManager', _smc = _sm+'::', _h5 = 'HTML5::', _id, _ua = navigator.userAgent, _win = window, _wl = _win.location.href.toString(), _doc = document, _doNothing, _setProperties, _init, _fV, _on_queue = [], _debugOpen = true, _debugTS, _didAppend = false, _appendSuccess = false, _didInit = false, _disabled = false, _windowLoaded = false, _wDS, _wdCount = 0, _initComplete, _mixin, _assign, _extraOptions, _addOnEvent, _processOnEvents, _initUserOnload, _delayWaitForEI, _waitForEI, _setVersionInfo, _handleFocus, _strings, _initMovie, _domContentLoaded, _winOnLoad, _didDCLoaded, _getDocument, _createMovie, _catchError, _setPolling, _initDebug, _debugLevels = ['log', 'info', 'warn', 'error'], _defaultFlashVersion = 8, _disableObject, _failSafely, _normalizeMovieURL, _oRemoved = null, _oRemovedHTML = null, _str, _flashBlockHandler, _getSWFCSS, _swfCSS, _toggleDebug, _loopFix, _policyFix, _complain, _idCheck, _waitingForEI = false, _initPending = false, _startTimer, _stopTimer, _timerExecute, _h5TimerCount = 0, _h5IntervalTimer = null, _parseURL, + _needsFlash = null, _featureCheck, _html5OK, _html5CanPlay, _html5Ext, _html5Unload, _domContentLoadedIE, _testHTML5, _event, _slice = Array.prototype.slice, _useGlobalHTML5Audio = false, _hasFlash, _detectFlash, _badSafariFix, _html5_events, _showSupport, + _is_iDevice = _ua.match(/(ipad|iphone|ipod)/i), _isIE = _ua.match(/msie/i), _isWebkit = _ua.match(/webkit/i), _isSafari = (_ua.match(/safari/i) && !_ua.match(/chrome/i)), _isOpera = (_ua.match(/opera/i)), + _mobileHTML5 = (_ua.match(/(mobile|pre\/|xoom)/i) || _is_iDevice), + _isBadSafari = (!_wl.match(/usehtml5audio/i) && !_wl.match(/sm2\-ignorebadua/i) && _isSafari && !_ua.match(/silk/i) && _ua.match(/OS X 10_6_([3-7])/i)), // Safari 4 and 5 (excluding Kindle Fire, "Silk") occasionally fail to load/play HTML5 audio on Snow Leopard 10.6.3 through 10.6.7 due to bug(s) in QuickTime X and/or other underlying frameworks. :/ Confirmed bug. https://bugs.webkit.org/show_bug.cgi?id=32159 + _hasConsole = (typeof console !== 'undefined' && typeof console.log !== 'undefined'), _isFocused = (typeof _doc.hasFocus !== 'undefined'?_doc.hasFocus():null), _tryInitOnFocus = (_isSafari && (typeof _doc.hasFocus === 'undefined' || !_doc.hasFocus())), _okToDisable = !_tryInitOnFocus, _flashMIME = /(mp3|mp4|mpa|m4a|m4b)/i, + _emptyURL = 'about:blank', // safe URL to unload, or load nothing from (flash 8 + most HTML5 UAs) + _overHTTP = (_doc.location?_doc.location.protocol.match(/http/i):null), + _http = (!_overHTTP ? 'http:/'+'/' : ''), + // mp3, mp4, aac etc. + _netStreamMimeTypes = /^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i, + // Flash v9.0r115+ "moviestar" formats + _netStreamTypes = ['mpeg4', 'aac', 'flv', 'mov', 'mp4', 'm4v', 'f4v', 'm4a', 'm4b', 'mp4v', '3gp', '3g2'], + _netStreamPattern = new RegExp('\\.(' + _netStreamTypes.join('|') + ')(\\?.*)?$', 'i'); + + this.mimePattern = /^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i; // default mp3 set + + // use altURL if not "online" + this.useAltURL = !_overHTTP; + + this._global_a = null; + + _swfCSS = { + + 'swfBox': 'sm2-object-box', + 'swfDefault': 'movieContainer', + 'swfError': 'swf_error', // SWF loaded, but SM2 couldn't start (other error) + 'swfTimedout': 'swf_timedout', + 'swfLoaded': 'swf_loaded', + 'swfUnblocked': 'swf_unblocked', // or loaded OK + 'sm2Debug': 'sm2_debug', + 'highPerf': 'high_performance', + 'flashDebug': 'flash_debug' + + }; + + if (_mobileHTML5) { + + // prefer HTML5 for mobile + tablet-like devices, probably more reliable vs. flash at this point. + _s.useHTML5Audio = true; + _s.preferFlash = false; + + if (_is_iDevice) { + // by default, use global feature. iOS onfinish() -> next may fail otherwise. + _s.ignoreFlash = true; + _useGlobalHTML5Audio = true; + } + + } + + /** + * Public SoundManager API + * ----------------------- + */ + + /** + * Configures top-level soundManager properties. + * + * @param {object} options Option parameters, eg. { flashVersion: 9, url: '/path/to/swfs/' } + * onready and ontimeout are also accepted parameters. call soundManager.setup() to see the full list. + */ + + this.setup = function(options) { + + var noURL = (!_s.url); + + // warn if flash options have already been applied + + if (typeof options !== 'undefined' && _didInit && _needsFlash && _s.ok() && (typeof options.flashVersion !== 'undefined' || typeof options.url !== 'undefined')) { + _complain(_str('setupLate')); + } + + // TODO: defer: true? + + _assign(options); + + // special case 1: "Late setup". SM2 loaded normally, but user didn't assign flash URL eg., setup({url:...}) before SM2 init. Treat as delayed init. + + if (noURL && _didDCLoaded && typeof options.url !== 'undefined') { + _s.beginDelayedInit(); + } + + // special case 2: If lazy-loading SM2 (DOMContentLoaded has already happened) and user calls setup() with url: parameter, try to init ASAP. + + if (!_didDCLoaded && typeof options.url !== 'undefined' && _doc.readyState === 'complete') { + setTimeout(_domContentLoaded, 1); + } + + return _s; + + }; + + this.ok = function() { + + return (_needsFlash?(_didInit && !_disabled):(_s.useHTML5Audio && _s.hasHTML5)); + + }; + + this.supported = this.ok; // legacy + + this.getMovie = function(smID) { + + // safety net: some old browsers differ on SWF references, possibly related to ExternalInterface / flash version + return _id(smID) || _doc[smID] || _win[smID]; + + }; + + /** + * Creates a SMSound sound object instance. + * + * @param {object} oOptions Sound options (at minimum, id and url parameters are required.) + * @return {object} SMSound The new SMSound object. + */ + + this.createSound = function(oOptions, _url) { + + var _cs, _cs_string, thisOptions = null, oSound = null, _tO = null; + + // + _cs = _sm+'.createSound(): '; + _cs_string = _cs + _str(!_didInit?'notReady':'notOK'); + // + + if (!_didInit || !_s.ok()) { + _complain(_cs_string); + return false; + } + + if (typeof _url !== 'undefined') { + // function overloading in JS! :) ..assume simple createSound(id,url) use case + oOptions = { + 'id': oOptions, + 'url': _url + }; + } + + // inherit from defaultOptions + thisOptions = _mixin(oOptions); + + thisOptions.url = _parseURL(thisOptions.url); + + // local shortcut + _tO = thisOptions; + + // + if (_tO.id.toString().charAt(0).match(/^[0-9]$/)) { + _s._wD(_cs + _str('badID', _tO.id), 2); + } + + _s._wD(_cs + _tO.id + ' (' + _tO.url + ')', 1); + // + + if (_idCheck(_tO.id, true)) { + _s._wD(_cs + _tO.id + ' exists', 1); + return _s.sounds[_tO.id]; + } + + function make() { + + thisOptions = _loopFix(thisOptions); + _s.sounds[_tO.id] = new SMSound(_tO); + _s.soundIDs.push(_tO.id); + return _s.sounds[_tO.id]; + + } + + if (_html5OK(_tO)) { + + oSound = make(); + _s._wD('Creating sound '+_tO.id+', using HTML5'); + oSound._setup_html5(_tO); + + } else { + + if (_fV > 8) { + if (_tO.isMovieStar === null) { + // attempt to detect MPEG-4 formats + _tO.isMovieStar = !!(_tO.serverURL || (_tO.type ? _tO.type.match(_netStreamMimeTypes) : false) || _tO.url.match(_netStreamPattern)); + } + // + if (_tO.isMovieStar) { + _s._wD(_cs + 'using MovieStar handling'); + if (_tO.loops > 1) { + _wDS('noNSLoop'); + } + } + // + } + + _tO = _policyFix(_tO, _cs); + oSound = make(); + + if (_fV === 8) { + _flash._createSound(_tO.id, _tO.loops||1, _tO.usePolicyFile); + } else { + _flash._createSound(_tO.id, _tO.url, _tO.usePeakData, _tO.useWaveformData, _tO.useEQData, _tO.isMovieStar, (_tO.isMovieStar?_tO.bufferTime:false), _tO.loops||1, _tO.serverURL, _tO.duration||null, _tO.autoPlay, true, _tO.autoLoad, _tO.usePolicyFile); + if (!_tO.serverURL) { + // We are connected immediately + oSound.connected = true; + if (_tO.onconnect) { + _tO.onconnect.apply(oSound); + } + } + } + + if (!_tO.serverURL && (_tO.autoLoad || _tO.autoPlay)) { + // call load for non-rtmp streams + oSound.load(_tO); + } + + } + + // rtmp will play in onconnect + if (!_tO.serverURL && _tO.autoPlay) { + oSound.play(); + } + + return oSound; + + }; + + /** + * Destroys a SMSound sound object instance. + * + * @param {string} sID The ID of the sound to destroy + */ + + this.destroySound = function(sID, _bFromSound) { + + // explicitly destroy a sound before normal page unload, etc. + + if (!_idCheck(sID)) { + return false; + } + + var oS = _s.sounds[sID], i; + + // Disable all callbacks while the sound is being destroyed + oS._iO = {}; + + oS.stop(); + oS.unload(); + + for (i = 0; i < _s.soundIDs.length; i++) { + if (_s.soundIDs[i] === sID) { + _s.soundIDs.splice(i, 1); + break; + } + } + + if (!_bFromSound) { + // ignore if being called from SMSound instance + oS.destruct(true); + } + + oS = null; + delete _s.sounds[sID]; + + return true; + + }; + + /** + * Calls the load() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @param {object} oOptions Optional: Sound options + */ + + this.load = function(sID, oOptions) { + + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].load(oOptions); + + }; + + /** + * Calls the unload() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + */ + + this.unload = function(sID) { + + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].unload(); + + }; + + /** + * Calls the onPosition() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @param {number} nPosition The position to watch for + * @param {function} oMethod The relevant callback to fire + * @param {object} oScope Optional: The scope to apply the callback to + * @return {SMSound} The SMSound object + */ + + this.onPosition = function(sID, nPosition, oMethod, oScope) { + + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].onposition(nPosition, oMethod, oScope); + + }; + + // legacy/backwards-compability: lower-case method name + this.onposition = this.onPosition; + + /** + * Calls the clearOnPosition() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @param {number} nPosition The position to watch for + * @param {function} oMethod Optional: The relevant callback to fire + * @return {SMSound} The SMSound object + */ + + this.clearOnPosition = function(sID, nPosition, oMethod) { + + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].clearOnPosition(nPosition, oMethod); + + }; + + /** + * Calls the play() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @param {object} oOptions Optional: Sound options + * @return {SMSound} The SMSound object + */ + + this.play = function(sID, oOptions) { + + var result = false; + + if (!_didInit || !_s.ok()) { + _complain(_sm+'.play(): ' + _str(!_didInit?'notReady':'notOK')); + return result; + } + + if (!_idCheck(sID)) { + if (!(oOptions instanceof Object)) { + // overloading use case: play('mySound','/path/to/some.mp3'); + oOptions = { + url: oOptions + }; + } + if (oOptions && oOptions.url) { + // overloading use case, create+play: .play('someID',{url:'/path/to.mp3'}); + _s._wD(_sm+'.play(): attempting to create "' + sID + '"', 1); + oOptions.id = sID; + result = _s.createSound(oOptions).play(); + } + return result; + } + + return _s.sounds[sID].play(oOptions); + + }; + + this.start = this.play; // just for convenience + + /** + * Calls the setPosition() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @param {number} nMsecOffset Position (milliseconds) + * @return {SMSound} The SMSound object + */ + + this.setPosition = function(sID, nMsecOffset) { + + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].setPosition(nMsecOffset); + + }; + + /** + * Calls the stop() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @return {SMSound} The SMSound object + */ + + this.stop = function(sID) { + + if (!_idCheck(sID)) { + return false; + } + + _s._wD(_sm+'.stop(' + sID + ')', 1); + return _s.sounds[sID].stop(); + + }; + + /** + * Stops all currently-playing sounds. + */ + + this.stopAll = function() { + + var oSound; + _s._wD(_sm+'.stopAll()', 1); + + for (oSound in _s.sounds) { + if (_s.sounds.hasOwnProperty(oSound)) { + // apply only to sound objects + _s.sounds[oSound].stop(); + } + } + + }; + + /** + * Calls the pause() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @return {SMSound} The SMSound object + */ + + this.pause = function(sID) { + + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].pause(); + + }; + + /** + * Pauses all currently-playing sounds. + */ + + this.pauseAll = function() { + + var i; + for (i = _s.soundIDs.length-1; i >= 0; i--) { + _s.sounds[_s.soundIDs[i]].pause(); + } + + }; + + /** + * Calls the resume() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @return {SMSound} The SMSound object + */ + + this.resume = function(sID) { + + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].resume(); + + }; + + /** + * Resumes all currently-paused sounds. + */ + + this.resumeAll = function() { + + var i; + for (i = _s.soundIDs.length-1; i >= 0; i--) { + _s.sounds[_s.soundIDs[i]].resume(); + } + + }; + + /** + * Calls the togglePause() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @return {SMSound} The SMSound object + */ + + this.togglePause = function(sID) { + + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].togglePause(); + + }; + + /** + * Calls the setPan() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @param {number} nPan The pan value (-100 to 100) + * @return {SMSound} The SMSound object + */ + + this.setPan = function(sID, nPan) { + + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].setPan(nPan); + + }; + + /** + * Calls the setVolume() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @param {number} nVol The volume value (0 to 100) + * @return {SMSound} The SMSound object + */ + + this.setVolume = function(sID, nVol) { + + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].setVolume(nVol); + + }; + + /** + * Calls the mute() method of either a single SMSound object by ID, or all sound objects. + * + * @param {string} sID Optional: The ID of the sound (if omitted, all sounds will be used.) + */ + + this.mute = function(sID) { + + var i = 0; + + if (typeof sID !== 'string') { + sID = null; + } + + if (!sID) { + _s._wD(_sm+'.mute(): Muting all sounds'); + for (i = _s.soundIDs.length-1; i >= 0; i--) { + _s.sounds[_s.soundIDs[i]].mute(); + } + _s.muted = true; + } else { + if (!_idCheck(sID)) { + return false; + } + _s._wD(_sm+'.mute(): Muting "' + sID + '"'); + return _s.sounds[sID].mute(); + } + + return true; + + }; + + /** + * Mutes all sounds. + */ + + this.muteAll = function() { + + _s.mute(); + + }; + + /** + * Calls the unmute() method of either a single SMSound object by ID, or all sound objects. + * + * @param {string} sID Optional: The ID of the sound (if omitted, all sounds will be used.) + */ + + this.unmute = function(sID) { + + var i; + + if (typeof sID !== 'string') { + sID = null; + } + + if (!sID) { + + _s._wD(_sm+'.unmute(): Unmuting all sounds'); + for (i = _s.soundIDs.length-1; i >= 0; i--) { + _s.sounds[_s.soundIDs[i]].unmute(); + } + _s.muted = false; + + } else { + + if (!_idCheck(sID)) { + return false; + } + _s._wD(_sm+'.unmute(): Unmuting "' + sID + '"'); + return _s.sounds[sID].unmute(); + + } + + return true; + + }; + + /** + * Unmutes all sounds. + */ + + this.unmuteAll = function() { + + _s.unmute(); + + }; + + /** + * Calls the toggleMute() method of a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @return {SMSound} The SMSound object + */ + + this.toggleMute = function(sID) { + + if (!_idCheck(sID)) { + return false; + } + return _s.sounds[sID].toggleMute(); + + }; + + /** + * Retrieves the memory used by the flash plugin. + * + * @return {number} The amount of memory in use + */ + + this.getMemoryUse = function() { + + // flash-only + var ram = 0; + + if (_flash && _fV !== 8) { + ram = parseInt(_flash._getMemoryUse(), 10); + } + + return ram; + + }; + + /** + * Undocumented: NOPs soundManager and all SMSound objects. + */ + + this.disable = function(bNoDisable) { + + // destroy all functions + var i; + + if (typeof bNoDisable === 'undefined') { + bNoDisable = false; + } + + if (_disabled) { + return false; + } + + _disabled = true; + _wDS('shutdown', 1); + + for (i = _s.soundIDs.length-1; i >= 0; i--) { + _disableObject(_s.sounds[_s.soundIDs[i]]); + } + + // fire "complete", despite fail + _initComplete(bNoDisable); + _event.remove(_win, 'load', _initUserOnload); + + return true; + + }; + + /** + * Determines playability of a MIME type, eg. 'audio/mp3'. + */ + + this.canPlayMIME = function(sMIME) { + + var result; + + if (_s.hasHTML5) { + result = _html5CanPlay({type:sMIME}); + } + + if (!result && _needsFlash) { + // if flash 9, test netStream (movieStar) types as well. + result = (sMIME && _s.ok() ? !!((_fV > 8 ? sMIME.match(_netStreamMimeTypes) : null) || sMIME.match(_s.mimePattern)) : null); + } + + return result; + + }; + + /** + * Determines playability of a URL based on audio support. + * + * @param {string} sURL The URL to test + * @return {boolean} URL playability + */ + + this.canPlayURL = function(sURL) { + + var result; + + if (_s.hasHTML5) { + result = _html5CanPlay({url: sURL}); + } + + if (!result && _needsFlash) { + result = (sURL && _s.ok() ? !!(sURL.match(_s.filePattern)) : null); + } + + return result; + + }; + + /** + * Determines playability of an HTML DOM <a> object (or similar object literal) based on audio support. + * + * @param {object} oLink an HTML DOM <a> object or object literal including href and/or type attributes + * @return {boolean} URL playability + */ + + this.canPlayLink = function(oLink) { + + if (typeof oLink.type !== 'undefined' && oLink.type) { + if (_s.canPlayMIME(oLink.type)) { + return true; + } + } + + return _s.canPlayURL(oLink.href); + + }; + + /** + * Retrieves a SMSound object by ID. + * + * @param {string} sID The ID of the sound + * @return {SMSound} The SMSound object + */ + + this.getSoundById = function(sID, _suppressDebug) { + + if (!sID) { + throw new Error(_sm+'.getSoundById(): sID is null/undefined'); + } + + var result = _s.sounds[sID]; + + // + if (!result && !_suppressDebug) { + _s._wD('"' + sID + '" is an invalid sound ID.', 2); + } + // + + return result; + + }; + + /** + * Queues a callback for execution when SoundManager has successfully initialized. + * + * @param {function} oMethod The callback method to fire + * @param {object} oScope Optional: The scope to apply to the callback + */ + + this.onready = function(oMethod, oScope) { + + var sType = 'onready', + result = false; + + if (typeof oMethod === 'function') { + + // + if (_didInit) { + _s._wD(_str('queue', sType)); + } + // + + if (!oScope) { + oScope = _win; + } + + _addOnEvent(sType, oMethod, oScope); + _processOnEvents(); + + result = true; + + } else { + + throw _str('needFunction', sType); + + } + + return result; + + }; + + /** + * Queues a callback for execution when SoundManager has failed to initialize. + * + * @param {function} oMethod The callback method to fire + * @param {object} oScope Optional: The scope to apply to the callback + */ + + this.ontimeout = function(oMethod, oScope) { + + var sType = 'ontimeout', + result = false; + + if (typeof oMethod === 'function') { + + // + if (_didInit) { + _s._wD(_str('queue', sType)); + } + // + + if (!oScope) { + oScope = _win; + } + + _addOnEvent(sType, oMethod, oScope); + _processOnEvents({type:sType}); + + result = true; + + } else { + + throw _str('needFunction', sType); + + } + + return result; + + }; + + /** + * Writes console.log()-style debug output to a console or in-browser element. + * Applies when debugMode = true + * + * @param {string} sText The console message + * @param {string} sType Optional: Log type of 'info', 'warn' or 'error' + * @param {object} Optional: The scope to apply to the callback + */ + + this._writeDebug = function(sText, sType, _bTimestamp) { + + // pseudo-private console.log()-style output + // + + var sDID = 'soundmanager-debug', o, oItem, sMethod; + + if (!_s.debugMode) { + return false; + } + + if (typeof _bTimestamp !== 'undefined' && _bTimestamp) { + sText = sText + ' | ' + new Date().getTime(); + } + + if (_hasConsole && _s.useConsole) { + sMethod = _debugLevels[sType]; + if (typeof console[sMethod] !== 'undefined') { + console[sMethod](sText); + } else { + console.log(sText); + } + if (_s.consoleOnly) { + return true; + } + } + + try { + + o = _id(sDID); + + if (!o) { + return false; + } + + oItem = _doc.createElement('div'); + + if (++_wdCount % 2 === 0) { + oItem.className = 'sm2-alt'; + } + + if (typeof sType === 'undefined') { + sType = 0; + } else { + sType = parseInt(sType, 10); + } + + oItem.appendChild(_doc.createTextNode(sText)); + + if (sType) { + if (sType >= 2) { + oItem.style.fontWeight = 'bold'; + } + if (sType === 3) { + oItem.style.color = '#ff3333'; + } + } + + // top-to-bottom + // o.appendChild(oItem); + + // bottom-to-top + o.insertBefore(oItem, o.firstChild); + + } catch(e) { + // oh well + } + + o = null; + // + + return true; + + }; + + // alias + this._wD = this._writeDebug; + + /** + * Provides debug / state information on all SMSound objects. + */ + + this._debug = function() { + + // + var i, j; + _wDS('currentObj', 1); + + for (i = 0, j = _s.soundIDs.length; i < j; i++) { + _s.sounds[_s.soundIDs[i]]._debug(); + } + // + + }; + + /** + * Restarts and re-initializes the SoundManager instance. + */ + + this.reboot = function() { + + // attempt to reset and init SM2 + _s._wD(_sm+'.reboot()'); + + // + if (_s.soundIDs.length) { + _s._wD('Destroying ' + _s.soundIDs.length + ' SMSound objects...'); + } + // + + var i, j; + + for (i = _s.soundIDs.length-1; i >= 0; i--) { + _s.sounds[_s.soundIDs[i]].destruct(); + } + + // trash ze flash + + if (_flash) { + try { + if (_isIE) { + _oRemovedHTML = _flash.innerHTML; + } + _oRemoved = _flash.parentNode.removeChild(_flash); + _s._wD('Flash movie removed.'); + } catch(e) { + // uh-oh. + _wDS('badRemove', 2); + } + } + + // actually, force recreate of movie. + _oRemovedHTML = _oRemoved = _needsFlash = null; + + _s.enabled = _didDCLoaded = _didInit = _waitingForEI = _initPending = _didAppend = _appendSuccess = _disabled = _s.swfLoaded = false; + _s.soundIDs = []; + _s.sounds = {}; + _flash = null; + + for (i in _on_queue) { + if (_on_queue.hasOwnProperty(i)) { + for (j = _on_queue[i].length-1; j >= 0; j--) { + _on_queue[i][j].fired = false; + } + } + } + + _s._wD(_sm + ': Rebooting...'); + _win.setTimeout(_s.beginDelayedInit, 20); + + }; + + /** + * Undocumented: Determines the SM2 flash movie's load progress. + * + * @return {number or null} Percent loaded, or if invalid/unsupported, null. + */ + + this.getMoviePercent = function() { + + // interesting note: flash/ExternalInterface bridge methods are not typeof "function" nor instanceof Function, but are still valid. + return (_flash && typeof _flash.PercentLoaded !== 'undefined' ? _flash.PercentLoaded() : null); + + }; + + /** + * Additional helper for manually invoking SM2's init process after DOM Ready / window.onload(). + */ + + this.beginDelayedInit = function() { + + _windowLoaded = true; + _domContentLoaded(); + + setTimeout(function() { + + if (_initPending) { + return false; + } + + _createMovie(); + _initMovie(); + _initPending = true; + + return true; + + }, 20); + + _delayWaitForEI(); + + }; + + /** + * Destroys the SoundManager instance and all SMSound instances. + */ + + this.destruct = function() { + + _s._wD(_sm+'.destruct()'); + _s.disable(true); + + }; + + /** + * SMSound() (sound object) constructor + * ------------------------------------ + * + * @param {object} oOptions Sound options (id and url are required attributes) + * @return {SMSound} The new SMSound object + */ + + SMSound = function(oOptions) { + + var _t = this, _resetProperties, _add_html5_events, _remove_html5_events, _stop_html5_timer, _start_html5_timer, _attachOnPosition, _onplay_called = false, _onPositionItems = [], _onPositionFired = 0, _detachOnPosition, _applyFromTo, _lastURL = null, _lastHTML5State; + + _lastHTML5State = { + // tracks duration + position (time) + duration: null, + time: null + }; + + this.id = oOptions.id; + + // legacy + this.sID = this.id; + + this.url = oOptions.url; + this.options = _mixin(oOptions); + + // per-play-instance-specific options + this.instanceOptions = this.options; + + // short alias + this._iO = this.instanceOptions; + + // assign property defaults + this.pan = this.options.pan; + this.volume = this.options.volume; + + // whether or not this object is using HTML5 + this.isHTML5 = false; + + // internal HTML5 Audio() object reference + this._a = null; + + /** + * SMSound() public methods + * ------------------------ + */ + + this.id3 = {}; + + /** + * Writes SMSound object parameters to debug console + */ + + this._debug = function() { + + // + // pseudo-private console.log()-style output + + if (_s.debugMode) { + + var stuff = null, msg = [], sF, sfBracket, maxLength = 64; + + for (stuff in _t.options) { + if (_t.options[stuff] !== null) { + if (typeof _t.options[stuff] === 'function') { + // handle functions specially + sF = _t.options[stuff].toString(); + // normalize spaces + sF = sF.replace(/\s\s+/g, ' '); + sfBracket = sF.indexOf('{'); + msg.push(' ' + stuff + ': {' + sF.substr(sfBracket + 1, (Math.min(Math.max(sF.indexOf('\n') - 1, maxLength), maxLength))).replace(/\n/g, '') + '... }'); + } else { + msg.push(' ' + stuff + ': ' + _t.options[stuff]); + } + } + } + + _s._wD('SMSound() merged options: {\n' + msg.join(', \n') + '\n}'); + + } + // + + }; + + // + this._debug(); + // + + /** + * Begins loading a sound per its *url*. + * + * @param {object} oOptions Optional: Sound options + * @return {SMSound} The SMSound object + */ + + this.load = function(oOptions) { + + var oS = null, _iO; + + if (typeof oOptions !== 'undefined') { + _t._iO = _mixin(oOptions, _t.options); + _t.instanceOptions = _t._iO; + } else { + oOptions = _t.options; + _t._iO = oOptions; + _t.instanceOptions = _t._iO; + if (_lastURL && _lastURL !== _t.url) { + _wDS('manURL'); + _t._iO.url = _t.url; + _t.url = null; + } + } + + if (!_t._iO.url) { + _t._iO.url = _t.url; + } + + _t._iO.url = _parseURL(_t._iO.url); + + _s._wD('SMSound.load(): ' + _t._iO.url, 1); + + if (_t._iO.url === _t.url && _t.readyState !== 0 && _t.readyState !== 2) { + _wDS('onURL', 1); + // if loaded and an onload() exists, fire immediately. + if (_t.readyState === 3 && _t._iO.onload) { + // assume success based on truthy duration. + _t._iO.onload.apply(_t, [(!!_t.duration)]); + } + return _t; + } + + // local shortcut + _iO = _t._iO; + + // make a local copy of the old url before we re-assign it + _lastURL = (_t.url && _t.url.toString ? _t.url.toString() : null); + + // reset a few state properties + + _t.loaded = false; + _t.readyState = 1; + _t.playState = 0; + _t.id3 = {}; + + // TODO: If switching from HTML5 -> flash (or vice versa), stop currently-playing audio. + + if (_html5OK(_iO)) { + + oS = _t._setup_html5(_iO); + + if (!oS._called_load) { + + _s._wD(_h5+'load: '+_t.id); + + _t._html5_canplay = false; + + // TODO: review called_load / html5_canplay logic + + // if url provided directly to load(), assign it here. + + if (_t._a.src !== _iO.url) { + + _s._wD(_wDS('manURL') + ': ' + _iO.url); + + _t._a.src = _iO.url; + + // TODO: review / re-apply all relevant options (volume, loop, onposition etc.) + + // reset position for new URL + _t.setPosition(0); + + } + + // given explicit load call, try to preload. + + // early HTML5 implementation (non-standard) + _t._a.autobuffer = 'auto'; + + // standard + _t._a.preload = 'auto'; + + oS._called_load = true; + + if (_iO.autoPlay) { + _t.play(); + } + + } else { + + _s._wD(_h5+'ignoring request to load again: '+_t.id); + + } + + } else { + + try { + _t.isHTML5 = false; + _t._iO = _policyFix(_loopFix(_iO)); + // re-assign local shortcut + _iO = _t._iO; + if (_fV === 8) { + _flash._load(_t.id, _iO.url, _iO.stream, _iO.autoPlay, (_iO.whileloading?1:0), _iO.loops||1, _iO.usePolicyFile); + } else { + _flash._load(_t.id, _iO.url, !!(_iO.stream), !!(_iO.autoPlay), _iO.loops||1, !!(_iO.autoLoad), _iO.usePolicyFile); + } + } catch(e) { + _wDS('smError', 2); + _debugTS('onload', false); + _catchError({type:'SMSOUND_LOAD_JS_EXCEPTION', fatal:true}); + + } + + } + + // after all of this, ensure sound url is up to date. + _t.url = _iO.url; + + return _t; + + }; + + /** + * Unloads a sound, canceling any open HTTP requests. + * + * @return {SMSound} The SMSound object + */ + + this.unload = function() { + + // Flash 8/AS2 can't "close" a stream - fake it by loading an empty URL + // Flash 9/AS3: Close stream, preventing further load + // HTML5: Most UAs will use empty URL + + if (_t.readyState !== 0) { + + _s._wD('SMSound.unload(): "' + _t.id + '"'); + + if (!_t.isHTML5) { + + if (_fV === 8) { + _flash._unload(_t.id, _emptyURL); + } else { + _flash._unload(_t.id); + } + + } else { + + _stop_html5_timer(); + + if (_t._a) { + + _t._a.pause(); + _html5Unload(_t._a, _emptyURL); + + // reset local URL for next load / play call, too + _t.url = _emptyURL; + + } + + } + + // reset load/status flags + _resetProperties(); + + } + + return _t; + + }; + + /** + * Unloads and destroys a sound. + */ + + this.destruct = function(_bFromSM) { + + _s._wD('SMSound.destruct(): "' + _t.id + '"'); + + if (!_t.isHTML5) { + + // kill sound within Flash + // Disable the onfailure handler + _t._iO.onfailure = null; + _flash._destroySound(_t.id); + + } else { + + _stop_html5_timer(); + + if (_t._a) { + _t._a.pause(); + _html5Unload(_t._a); + if (!_useGlobalHTML5Audio) { + _remove_html5_events(); + } + // break obvious circular reference + _t._a._t = null; + _t._a = null; + } + + } + + if (!_bFromSM) { + // ensure deletion from controller + _s.destroySound(_t.id, true); + + } + + }; + + /** + * Begins playing a sound. + * + * @param {object} oOptions Optional: Sound options + * @return {SMSound} The SMSound object + */ + + this.play = function(oOptions, _updatePlayState) { + + var fN, allowMulti, a, onready, startOK = true, + exit = null; + + // + fN = 'SMSound.play(): '; + // + + // default to true + _updatePlayState = (typeof _updatePlayState === 'undefined' ? true : _updatePlayState); + + if (!oOptions) { + oOptions = {}; + } + + // first, use local URL (if specified) + if (_t.url) { + _t._iO.url = _t.url; + } + + // mix in any options defined at createSound() + _t._iO = _mixin(_t._iO, _t.options); + + // mix in any options specific to this method + _t._iO = _mixin(oOptions, _t._iO); + + _t._iO.url = _parseURL(_t._iO.url); + + _t.instanceOptions = _t._iO; + + // RTMP-only + if (_t._iO.serverURL && !_t.connected) { + if (!_t.getAutoPlay()) { + _s._wD(fN+' Netstream not connected yet - setting autoPlay'); + _t.setAutoPlay(true); + } + // play will be called in _onconnect() + return _t; + } + + if (_html5OK(_t._iO)) { + _t._setup_html5(_t._iO); + _start_html5_timer(); + } + + if (_t.playState === 1 && !_t.paused) { + allowMulti = _t._iO.multiShot; + if (!allowMulti) { + _s._wD(fN + '"' + _t.id + '" already playing (one-shot)', 1); + exit = _t; + } else { + _s._wD(fN + '"' + _t.id + '" already playing (multi-shot)', 1); + } + } + + if (exit !== null) { + return exit; + } + + // edge case: play() with explicit URL parameter + if (oOptions.url && oOptions.url !== _t.url) { + // load using merged options + _t.load(_t._iO); + } + + if (!_t.loaded) { + + if (_t.readyState === 0) { + + _s._wD(fN + 'Attempting to load "' + _t.id + '"', 1); + + // try to get this sound playing ASAP + if (!_t.isHTML5) { + // assign directly because setAutoPlay() increments the instanceCount + _t._iO.autoPlay = true; + _t.load(_t._iO); + } else { + // iOS needs this when recycling sounds, loading a new URL on an existing object. + _t.load(_t._iO); + } + + } else if (_t.readyState === 2) { + + _s._wD(fN + 'Could not load "' + _t.id + '" - exiting', 2); + exit = _t; + + } else { + + _s._wD(fN + '"' + _t.id + '" is loading - attempting to play..', 1); + + } + + } else { + + _s._wD(fN + '"' + _t.id + '"'); + + } + + if (exit !== null) { + return exit; + } + + if (!_t.isHTML5 && _fV === 9 && _t.position > 0 && _t.position === _t.duration) { + // flash 9 needs a position reset if play() is called while at the end of a sound. + _s._wD(fN + '"' + _t.id + '": Sound at end, resetting to position:0'); + oOptions.position = 0; + } + + /** + * Streams will pause when their buffer is full if they are being loaded. + * In this case paused is true, but the song hasn't started playing yet. + * If we just call resume() the onplay() callback will never be called. + * So only call resume() if the position is > 0. + * Another reason is because options like volume won't have been applied yet. + * For normal sounds, just resume. + */ + + if (_t.paused && _t.position >= 0 && (!_t._iO.serverURL || _t.position > 0)) { + + // https://gist.github.com/37b17df75cc4d7a90bf6 + _s._wD(fN + '"' + _t.id + '" is resuming from paused state',1); + _t.resume(); + + } else { + + _t._iO = _mixin(oOptions, _t._iO); + + // apply from/to parameters, if they exist (and not using RTMP) + if (_t._iO.from !== null && _t._iO.to !== null && _t.instanceCount === 0 && _t.playState === 0 && !_t._iO.serverURL) { + + onready = function() { + // sound "canplay" or onload() + // re-apply from/to to instance options, and start playback + _t._iO = _mixin(oOptions, _t._iO); + _t.play(_t._iO); + }; + + // HTML5 needs to at least have "canplay" fired before seeking. + if (_t.isHTML5 && !_t._html5_canplay) { + + // this hasn't been loaded yet. load it first, and then do this again. + _s._wD(fN+'Beginning load of "'+ _t.id+'" for from/to case'); + + _t.load({ + _oncanplay: onready + }); + + exit = false; + + } else if (!_t.isHTML5 && !_t.loaded && (!_t.readyState || _t.readyState !== 2)) { + + // to be safe, preload the whole thing in Flash. + + _s._wD(fN+'Preloading "'+ _t.id+'" for from/to case'); + + _t.load({ + onload: onready + }); + + exit = false; + + } + + if (exit !== null) { + return exit; + } + + // otherwise, we're ready to go. re-apply local options, and continue + + _t._iO = _applyFromTo(); + + } + + _s._wD(fN+'"'+ _t.id+'" is starting to play'); + + if (!_t.instanceCount || _t._iO.multiShotEvents || (!_t.isHTML5 && _fV > 8 && !_t.getAutoPlay())) { + _t.instanceCount++; + } + + // if first play and onposition parameters exist, apply them now + if (_t._iO.onposition && _t.playState === 0) { + _attachOnPosition(_t); + } + + _t.playState = 1; + _t.paused = false; + + _t.position = (typeof _t._iO.position !== 'undefined' && !isNaN(_t._iO.position) ? _t._iO.position : 0); + + if (!_t.isHTML5) { + _t._iO = _policyFix(_loopFix(_t._iO)); + } + + if (_t._iO.onplay && _updatePlayState) { + _t._iO.onplay.apply(_t); + _onplay_called = true; + } + + _t.setVolume(_t._iO.volume, true); + _t.setPan(_t._iO.pan, true); + + if (!_t.isHTML5) { + + startOK = _flash._start(_t.id, _t._iO.loops || 1, (_fV === 9 ? _t._iO.position : _t._iO.position / 1000), _t._iO.multiShot); + + if (_fV === 9 && !startOK) { + // edge case: no sound hardware, or 32-channel flash ceiling hit. + // applies only to Flash 9, non-NetStream/MovieStar sounds. + // http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Sound.html#play%28%29 + _s._wD(fN+ _t.id+': No sound hardware, or 32-sound ceiling hit'); + if (_t._iO.onplayerror) { + _t._iO.onplayerror.apply(_t); + } + + } + + } else { + + _start_html5_timer(); + + a = _t._setup_html5(); + + _t.setPosition(_t._iO.position); + + a.play(); + + } + + } + + return _t; + + }; + + // just for convenience + this.start = this.play; + + /** + * Stops playing a sound (and optionally, all sounds) + * + * @param {boolean} bAll Optional: Whether to stop all sounds + * @return {SMSound} The SMSound object + */ + + this.stop = function(bAll) { + + var _iO = _t._iO, _oP; + + if (_t.playState === 1) { + + _t._onbufferchange(0); + _t._resetOnPosition(0); + _t.paused = false; + + if (!_t.isHTML5) { + _t.playState = 0; + } + + // remove onPosition listeners, if any + _detachOnPosition(); + + // and "to" position, if set + if (_iO.to) { + _t.clearOnPosition(_iO.to); + } + + if (!_t.isHTML5) { + + _flash._stop(_t.id, bAll); + + // hack for netStream: just unload + if (_iO.serverURL) { + _t.unload(); + } + + } else { + + if (_t._a) { + + _oP = _t.position; + + // act like Flash, though + _t.setPosition(0); + + // hack: reflect old position for onstop() (also like Flash) + _t.position = _oP; + + // html5 has no stop() + // NOTE: pausing means iOS requires interaction to resume. + _t._a.pause(); + + _t.playState = 0; + + // and update UI + _t._onTimer(); + + _stop_html5_timer(); + + } + + } + + _t.instanceCount = 0; + _t._iO = {}; + + if (_iO.onstop) { + _iO.onstop.apply(_t); + } + + } + + return _t; + + }; + + /** + * Undocumented/internal: Sets autoPlay for RTMP. + * + * @param {boolean} autoPlay state + */ + + this.setAutoPlay = function(autoPlay) { + + _s._wD('sound '+_t.id+' turned autoplay ' + (autoPlay ? 'on' : 'off')); + _t._iO.autoPlay = autoPlay; + + if (!_t.isHTML5) { + _flash._setAutoPlay(_t.id, autoPlay); + if (autoPlay) { + // only increment the instanceCount if the sound isn't loaded (TODO: verify RTMP) + if (!_t.instanceCount && _t.readyState === 1) { + _t.instanceCount++; + _s._wD('sound '+_t.id+' incremented instance count to '+_t.instanceCount); + } + } + } + + }; + + /** + * Undocumented/internal: Returns the autoPlay boolean. + * + * @return {boolean} The current autoPlay value + */ + + this.getAutoPlay = function() { + + return _t._iO.autoPlay; + + }; + + /** + * Sets the position of a sound. + * + * @param {number} nMsecOffset Position (milliseconds) + * @return {SMSound} The SMSound object + */ + + this.setPosition = function(nMsecOffset) { + + if (typeof nMsecOffset === 'undefined') { + nMsecOffset = 0; + } + + var original_pos, + position, position1K, + // Use the duration from the instance options, if we don't have a track duration yet. + // position >= 0 and <= current available (loaded) duration + offset = (_t.isHTML5 ? Math.max(nMsecOffset, 0) : Math.min(_t.duration || _t._iO.duration, Math.max(nMsecOffset, 0))); + + original_pos = _t.position; + _t.position = offset; + position1K = _t.position/1000; + _t._resetOnPosition(_t.position); + _t._iO.position = offset; + + if (!_t.isHTML5) { + + position = (_fV === 9 ? _t.position : position1K); + if (_t.readyState && _t.readyState !== 2) { + // if paused or not playing, will not resume (by playing) + _flash._setPosition(_t.id, position, (_t.paused || !_t.playState), _t._iO.multiShot); + } + + } else if (_t._a) { + + // Set the position in the canplay handler if the sound is not ready yet + if (_t._html5_canplay) { + if (_t._a.currentTime !== position1K) { + /** + * DOM/JS errors/exceptions to watch out for: + * if seek is beyond (loaded?) position, "DOM exception 11" + * "INDEX_SIZE_ERR": DOM exception 1 + */ + _s._wD('setPosition('+position1K+'): setting position'); + try { + _t._a.currentTime = position1K; + if (_t.playState === 0 || _t.paused) { + // allow seek without auto-play/resume + _t._a.pause(); + } + } catch(e) { + _s._wD('setPosition('+position1K+'): setting position failed: '+e.message, 2); + } + } + } else { + _s._wD('setPosition('+position1K+'): delaying, sound not ready'); + } + + } + + if (_t.isHTML5) { + if (_t.paused) { + // if paused, refresh UI right away + // force update + _t._onTimer(true); + } + } + + return _t; + + }; + + /** + * Pauses sound playback. + * + * @return {SMSound} The SMSound object + */ + + this.pause = function(_bCallFlash) { + + if (_t.paused || (_t.playState === 0 && _t.readyState !== 1)) { + return _t; + } + + _s._wD('SMSound.pause()'); + _t.paused = true; + + if (!_t.isHTML5) { + if (_bCallFlash || typeof _bCallFlash === 'undefined') { + _flash._pause(_t.id, _t._iO.multiShot); + } + } else { + _t._setup_html5().pause(); + _stop_html5_timer(); + } + + if (_t._iO.onpause) { + _t._iO.onpause.apply(_t); + } + + return _t; + + }; + + /** + * Resumes sound playback. + * + * @return {SMSound} The SMSound object + */ + + /** + * When auto-loaded streams pause on buffer full they have a playState of 0. + * We need to make sure that the playState is set to 1 when these streams "resume". + * When a paused stream is resumed, we need to trigger the onplay() callback if it + * hasn't been called already. In this case since the sound is being played for the + * first time, I think it's more appropriate to call onplay() rather than onresume(). + */ + + this.resume = function() { + + var _iO = _t._iO; + + if (!_t.paused) { + return _t; + } + + _s._wD('SMSound.resume()'); + _t.paused = false; + _t.playState = 1; + + if (!_t.isHTML5) { + if (_iO.isMovieStar && !_iO.serverURL) { + // Bizarre Webkit bug (Chrome reported via 8tracks.com dudes): AAC content paused for 30+ seconds(?) will not resume without a reposition. + _t.setPosition(_t.position); + } + // flash method is toggle-based (pause/resume) + _flash._pause(_t.id, _iO.multiShot); + } else { + _t._setup_html5().play(); + _start_html5_timer(); + } + + if (!_onplay_called && _iO.onplay) { + _iO.onplay.apply(_t); + _onplay_called = true; + } else if (_iO.onresume) { + _iO.onresume.apply(_t); + } + + return _t; + + }; + + /** + * Toggles sound playback. + * + * @return {SMSound} The SMSound object + */ + + this.togglePause = function() { + + _s._wD('SMSound.togglePause()'); + + if (_t.playState === 0) { + _t.play({ + position: (_fV === 9 && !_t.isHTML5 ? _t.position : _t.position / 1000) + }); + return _t; + } + + if (_t.paused) { + _t.resume(); + } else { + _t.pause(); + } + + return _t; + + }; + + /** + * Sets the panning (L-R) effect. + * + * @param {number} nPan The pan value (-100 to 100) + * @return {SMSound} The SMSound object + */ + + this.setPan = function(nPan, bInstanceOnly) { + + if (typeof nPan === 'undefined') { + nPan = 0; + } + + if (typeof bInstanceOnly === 'undefined') { + bInstanceOnly = false; + } + + if (!_t.isHTML5) { + _flash._setPan(_t.id, nPan); + } // else { no HTML5 pan? } + + _t._iO.pan = nPan; + + if (!bInstanceOnly) { + _t.pan = nPan; + _t.options.pan = nPan; + } + + return _t; + + }; + + /** + * Sets the volume. + * + * @param {number} nVol The volume value (0 to 100) + * @return {SMSound} The SMSound object + */ + + this.setVolume = function(nVol, _bInstanceOnly) { + + /** + * Note: Setting volume has no effect on iOS "special snowflake" devices. + * Hardware volume control overrides software, and volume + * will always return 1 per Apple docs. (iOS 4 + 5.) + * http://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/AddingSoundtoCanvasAnimations/AddingSoundtoCanvasAnimations.html + */ + + if (typeof nVol === 'undefined') { + nVol = 100; + } + + if (typeof _bInstanceOnly === 'undefined') { + _bInstanceOnly = false; + } + + if (!_t.isHTML5) { + _flash._setVolume(_t.id, (_s.muted && !_t.muted) || _t.muted?0:nVol); + } else if (_t._a) { + // valid range: 0-1 + _t._a.volume = Math.max(0, Math.min(1, nVol/100)); + } + + _t._iO.volume = nVol; + + if (!_bInstanceOnly) { + _t.volume = nVol; + _t.options.volume = nVol; + } + + return _t; + + }; + + /** + * Mutes the sound. + * + * @return {SMSound} The SMSound object + */ + + this.mute = function() { + + _t.muted = true; + + if (!_t.isHTML5) { + _flash._setVolume(_t.id, 0); + } else if (_t._a) { + _t._a.muted = true; + } + + return _t; + + }; + + /** + * Unmutes the sound. + * + * @return {SMSound} The SMSound object + */ + + this.unmute = function() { + + _t.muted = false; + var hasIO = (typeof _t._iO.volume !== 'undefined'); + + if (!_t.isHTML5) { + _flash._setVolume(_t.id, hasIO?_t._iO.volume:_t.options.volume); + } else if (_t._a) { + _t._a.muted = false; + } + + return _t; + + }; + + /** + * Toggles the muted state of a sound. + * + * @return {SMSound} The SMSound object + */ + + this.toggleMute = function() { + + return (_t.muted?_t.unmute():_t.mute()); + + }; + + /** + * Registers a callback to be fired when a sound reaches a given position during playback. + * + * @param {number} nPosition The position to watch for + * @param {function} oMethod The relevant callback to fire + * @param {object} oScope Optional: The scope to apply the callback to + * @return {SMSound} The SMSound object + */ + + this.onPosition = function(nPosition, oMethod, oScope) { + + // TODO: basic dupe checking? + + _onPositionItems.push({ + position: parseInt(nPosition, 10), + method: oMethod, + scope: (typeof oScope !== 'undefined' ? oScope : _t), + fired: false + }); + + return _t; + + }; + + // legacy/backwards-compability: lower-case method name + this.onposition = this.onPosition; + + /** + * Removes registered callback(s) from a sound, by position and/or callback. + * + * @param {number} nPosition The position to clear callback(s) for + * @param {function} oMethod Optional: Identify one callback to be removed when multiple listeners exist for one position + * @return {SMSound} The SMSound object + */ + + this.clearOnPosition = function(nPosition, oMethod) { + + var i; + + nPosition = parseInt(nPosition, 10); + + if (isNaN(nPosition)) { + // safety check + return false; + } + + for (i=0; i < _onPositionItems.length; i++) { + + if (nPosition === _onPositionItems[i].position) { + // remove this item if no method was specified, or, if the method matches + if (!oMethod || (oMethod === _onPositionItems[i].method)) { + if (_onPositionItems[i].fired) { + // decrement "fired" counter, too + _onPositionFired--; + } + _onPositionItems.splice(i, 1); + } + } + + } + + }; + + this._processOnPosition = function() { + + var i, item, j = _onPositionItems.length; + + if (!j || !_t.playState || _onPositionFired >= j) { + return false; + } + + for (i=j-1; i >= 0; i--) { + item = _onPositionItems[i]; + if (!item.fired && _t.position >= item.position) { + item.fired = true; + _onPositionFired++; + item.method.apply(item.scope, [item.position]); + } + } + + return true; + + }; + + this._resetOnPosition = function(nPosition) { + + // reset "fired" for items interested in this position + var i, item, j = _onPositionItems.length; + + if (!j) { + return false; + } + + for (i=j-1; i >= 0; i--) { + item = _onPositionItems[i]; + if (item.fired && nPosition <= item.position) { + item.fired = false; + _onPositionFired--; + } + } + + return true; + + }; + + /** + * SMSound() private internals + * -------------------------------- + */ + + _applyFromTo = function() { + + var _iO = _t._iO, + f = _iO.from, + t = _iO.to, + start, end; + + end = function() { + + // end has been reached. + _s._wD(_t.id + ': "to" time of ' + t + ' reached.'); + + // detach listener + _t.clearOnPosition(t, end); + + // stop should clear this, too + _t.stop(); + + }; + + start = function() { + + _s._wD(_t.id + ': playing "from" ' + f); + + // add listener for end + if (t !== null && !isNaN(t)) { + _t.onPosition(t, end); + } + + }; + + if (f !== null && !isNaN(f)) { + + // apply to instance options, guaranteeing correct start position. + _iO.position = f; + + // multiShot timing can't be tracked, so prevent that. + _iO.multiShot = false; + + start(); + + } + + // return updated instanceOptions including starting position + return _iO; + + }; + + _attachOnPosition = function() { + + var item, + op = _t._iO.onposition; + + // attach onposition things, if any, now. + + if (op) { + + for (item in op) { + if (op.hasOwnProperty(item)) { + _t.onPosition(parseInt(item, 10), op[item]); + } + } + + } + + }; + + _detachOnPosition = function() { + + var item, + op = _t._iO.onposition; + + // detach any onposition()-style listeners. + + if (op) { + + for (item in op) { + if (op.hasOwnProperty(item)) { + _t.clearOnPosition(parseInt(item, 10)); + } + } + + } + + }; + + _start_html5_timer = function() { + + if (_t.isHTML5) { + _startTimer(_t); + } + + }; + + _stop_html5_timer = function() { + + if (_t.isHTML5) { + _stopTimer(_t); + } + + }; + + _resetProperties = function(retainPosition) { + + if (!retainPosition) { + _onPositionItems = []; + _onPositionFired = 0; + } + + _onplay_called = false; + + _t._hasTimer = null; + _t._a = null; + _t._html5_canplay = false; + _t.bytesLoaded = null; + _t.bytesTotal = null; + _t.duration = (_t._iO && _t._iO.duration ? _t._iO.duration : null); + _t.durationEstimate = null; + _t.buffered = []; + + // legacy: 1D array + _t.eqData = []; + + _t.eqData.left = []; + _t.eqData.right = []; + + _t.failures = 0; + _t.isBuffering = false; + _t.instanceOptions = {}; + _t.instanceCount = 0; + _t.loaded = false; + _t.metadata = {}; + + // 0 = uninitialised, 1 = loading, 2 = failed/error, 3 = loaded/success + _t.readyState = 0; + + _t.muted = false; + _t.paused = false; + + _t.peakData = { + left: 0, + right: 0 + }; + + _t.waveformData = { + left: [], + right: [] + }; + + _t.playState = 0; + _t.position = null; + + _t.id3 = {}; + + }; + + _resetProperties(); + + /** + * Pseudo-private SMSound internals + * -------------------------------- + */ + + this._onTimer = function(bForce) { + + /** + * HTML5-only _whileplaying() etc. + * called from both HTML5 native events, and polling/interval-based timers + * mimics flash and fires only when time/duration change, so as to be polling-friendly + */ + + var duration, isNew = false, time, x = {}; + + if (_t._hasTimer || bForce) { + + // TODO: May not need to track readyState (1 = loading) + + if (_t._a && (bForce || ((_t.playState > 0 || _t.readyState === 1) && !_t.paused))) { + + duration = _t._get_html5_duration(); + + if (duration !== _lastHTML5State.duration) { + + _lastHTML5State.duration = duration; + _t.duration = duration; + isNew = true; + + } + + // TODO: investigate why this goes wack if not set/re-set each time. + _t.durationEstimate = _t.duration; + + time = (_t._a.currentTime * 1000 || 0); + + if (time !== _lastHTML5State.time) { + + _lastHTML5State.time = time; + isNew = true; + + } + + if (isNew || bForce) { + + _t._whileplaying(time,x,x,x,x); + + } + + }/* else { + + // _s._wD('_onTimer: Warn for "'+_t.id+'": '+(!_t._a?'Could not find element. ':'')+(_t.playState === 0?'playState bad, 0?':'playState = '+_t.playState+', OK')); + + return false; + + }*/ + + return isNew; + + } + + }; + + this._get_html5_duration = function() { + + var _iO = _t._iO, + // if audio object exists, use its duration - else, instance option duration (if provided - it's a hack, really, and should be retired) OR null + d = (_t._a && _t._a.duration ? _t._a.duration*1000 : (_iO && _iO.duration ? _iO.duration : null)), + result = (d && !isNaN(d) && d !== Infinity ? d : null); + + return result; + + }; + + this._apply_loop = function(a, nLoops) { + + /** + * boolean instead of "loop", for webkit? - spec says string. http://www.w3.org/TR/html-markup/audio.html#audio.attrs.loop + * note that loop is either off or infinite under HTML5, unlike Flash which allows arbitrary loop counts to be specified. + */ + + // + if (!a.loop && nLoops > 1) { + _s._wD('Note: Native HTML5 looping is infinite.'); + } + // + + a.loop = (nLoops > 1 ? 'loop' : ''); + + }; + + this._setup_html5 = function(oOptions) { + + var _iO = _mixin(_t._iO, oOptions), d = decodeURI, + _a = _useGlobalHTML5Audio ? _s._global_a : _t._a, + _dURL = d(_iO.url), + _oldIO = (_a && _a._t ? _a._t.instanceOptions : null), + result; + + if (_a) { + + if (_a._t) { + + if (!_useGlobalHTML5Audio && _dURL === d(_lastURL)) { + + // same url, ignore request + result = _a; + + } else if (_useGlobalHTML5Audio && _oldIO.url === _iO.url && (!_lastURL || (_lastURL === _oldIO.url))) { + + // iOS-type reuse case + result = _a; + + } + + if (result) { + + _t._apply_loop(_a, _iO.loops); + return result; + + } + + } + + _s._wD('setting URL on existing object: ' + _dURL + (_lastURL ? ', old URL: ' + _lastURL : '')); + + /** + * "First things first, I, Poppa.." (reset the previous state of the old sound, if playing) + * Fixes case with devices that can only play one sound at a time + * Otherwise, other sounds in mid-play will be terminated without warning and in a stuck state + */ + + if (_useGlobalHTML5Audio && _a._t && _a._t.playState && _iO.url !== _oldIO.url) { + + _a._t.stop(); + + } + + // reset load/playstate, onPosition etc. if the URL is new. + // somewhat-tricky object re-use vs. new SMSound object, old vs. new URL comparisons + _resetProperties((_oldIO && _oldIO.url ? _iO.url === _oldIO.url : (_lastURL ? _lastURL === _iO.url : false))); + + _a.src = _iO.url; + _t.url = _iO.url; + _lastURL = _iO.url; + _a._called_load = false; + + } else { + + _wDS('h5a'); + + if (_iO.autoLoad || _iO.autoPlay) { + + _t._a = new Audio(_iO.url); + + } else { + + // null for stupid Opera 9.64 case + _t._a = (_isOpera && opera.version() < 10 ? new Audio(null) : new Audio()); + + } + + // assign local reference + _a = _t._a; + + _a._called_load = false; + + if (_useGlobalHTML5Audio) { + + _s._global_a = _a; + + } + + } + + _t.isHTML5 = true; + + // store a ref on the track + _t._a = _a; + + // store a ref on the audio + _a._t = _t; + + _add_html5_events(); + + _t._apply_loop(_a, _iO.loops); + + if (_iO.autoLoad || _iO.autoPlay) { + + _t.load(); + + } else { + + // early HTML5 implementation (non-standard) + _a.autobuffer = false; + + // standard ('none' is also an option.) + _a.preload = 'auto'; + + } + + return _a; + + }; + + _add_html5_events = function() { + + if (_t._a._added_events) { + return false; + } + + var f; + + function add(oEvt, oFn, bCapture) { + return _t._a ? _t._a.addEventListener(oEvt, oFn, bCapture||false) : null; + } + + _t._a._added_events = true; + + for (f in _html5_events) { + if (_html5_events.hasOwnProperty(f)) { + add(f, _html5_events[f]); + } + } + + return true; + + }; + + _remove_html5_events = function() { + + // Remove event listeners + + var f; + + function remove(oEvt, oFn, bCapture) { + return (_t._a ? _t._a.removeEventListener(oEvt, oFn, bCapture||false) : null); + } + + _s._wD(_h5+'removing event listeners: '+_t.id); + _t._a._added_events = false; + + for (f in _html5_events) { + if (_html5_events.hasOwnProperty(f)) { + remove(f, _html5_events[f]); + } + } + + }; + + /** + * Pseudo-private event internals + * ------------------------------ + */ + + this._onload = function(nSuccess) { + + + var fN, + // check for duration to prevent false positives from flash 8 when loading from cache. + loadOK = (!!(nSuccess) || (!_t.isHTML5 && _fV === 8 && _t.duration)); + + // + fN = 'SMSound._onload(): '; + _s._wD(fN + '"' + _t.id + '"' + (loadOK?' loaded.':' failed to load? - ' + _t.url), (loadOK?1:2)); + if (!loadOK && !_t.isHTML5) { + if (_s.sandbox.noRemote === true) { + _s._wD(fN + _str('noNet'), 1); + } + if (_s.sandbox.noLocal === true) { + _s._wD(fN + _str('noLocal'), 1); + } + } + // + + _t.loaded = loadOK; + _t.readyState = loadOK?3:2; + _t._onbufferchange(0); + + if (_t._iO.onload) { + _t._iO.onload.apply(_t, [loadOK]); + } + + return true; + + }; + + this._onbufferchange = function(nIsBuffering) { + + if (_t.playState === 0) { + // ignore if not playing + return false; + } + + if ((nIsBuffering && _t.isBuffering) || (!nIsBuffering && !_t.isBuffering)) { + return false; + } + + _t.isBuffering = (nIsBuffering === 1); + if (_t._iO.onbufferchange) { + _s._wD('SMSound._onbufferchange(): ' + nIsBuffering); + _t._iO.onbufferchange.apply(_t); + } + + return true; + + }; + + /** + * Notify Mobile Safari that user action is required + * to continue playing / loading the audio file. + */ + + this._onsuspend = function() { + + if (_t._iO.onsuspend) { + _s._wD('SMSound._onsuspend()'); + _t._iO.onsuspend.apply(_t); + } + + return true; + + }; + + /** + * flash 9/movieStar + RTMP-only method, should fire only once at most + * at this point we just recreate failed sounds rather than trying to reconnect + */ + + this._onfailure = function(msg, level, code) { + + _t.failures++; + _s._wD('SMSound._onfailure(): "'+_t.id+'" count '+_t.failures); + + if (_t._iO.onfailure && _t.failures === 1) { + _t._iO.onfailure(_t, msg, level, code); + } else { + _s._wD('SMSound._onfailure(): ignoring'); + } + + }; + + this._onfinish = function() { + + // store local copy before it gets trashed.. + var _io_onfinish = _t._iO.onfinish; + + _t._onbufferchange(0); + _t._resetOnPosition(0); + + // reset some state items + if (_t.instanceCount) { + + _t.instanceCount--; + + if (!_t.instanceCount) { + + // remove onPosition listeners, if any + _detachOnPosition(); + + // reset instance options + _t.playState = 0; + _t.paused = false; + _t.instanceCount = 0; + _t.instanceOptions = {}; + _t._iO = {}; + _stop_html5_timer(); + + // reset position, too + if (_t.isHTML5) { + _t.position = 0; + } + + } + + if (!_t.instanceCount || _t._iO.multiShotEvents) { + // fire onfinish for last, or every instance + if (_io_onfinish) { + _s._wD('SMSound._onfinish(): "' + _t.id + '"'); + _io_onfinish.apply(_t); + } + } + + } + + }; + + this._whileloading = function(nBytesLoaded, nBytesTotal, nDuration, nBufferLength) { + + var _iO = _t._iO; + + _t.bytesLoaded = nBytesLoaded; + _t.bytesTotal = nBytesTotal; + _t.duration = Math.floor(nDuration); + _t.bufferLength = nBufferLength; + + if (!_t.isHTML5 && !_iO.isMovieStar) { + + if (_iO.duration) { + // use duration from options, if specified and larger. nobody should be specifying duration in options, actually, and it should be retired. + _t.durationEstimate = (_t.duration > _iO.duration) ? _t.duration : _iO.duration; + } else { + _t.durationEstimate = parseInt((_t.bytesTotal / _t.bytesLoaded) * _t.duration, 10); + } + + } else { + + _t.durationEstimate = _t.duration; + + } + + // for flash, reflect sequential-load-style buffering + if (!_t.isHTML5) { + _t.buffered = [{ + 'start': 0, + 'end': _t.duration + }]; + } + + // allow whileloading to fire even if "load" fired under HTML5, due to HTTP range/partials + if ((_t.readyState !== 3 || _t.isHTML5) && _iO.whileloading) { + _iO.whileloading.apply(_t); + } + + }; + + this._whileplaying = function(nPosition, oPeakData, oWaveformDataLeft, oWaveformDataRight, oEQData) { + + var _iO = _t._iO, + eqLeft; + + if (isNaN(nPosition) || nPosition === null) { + // flash safety net + return false; + } + + // Safari HTML5 play() may return small -ve values when starting from position: 0, eg. -50.120396875. Unexpected/invalid per W3, I think. Normalize to 0. + _t.position = Math.max(0, nPosition); + + _t._processOnPosition(); + + if (!_t.isHTML5 && _fV > 8) { + + if (_iO.usePeakData && typeof oPeakData !== 'undefined' && oPeakData) { + _t.peakData = { + left: oPeakData.leftPeak, + right: oPeakData.rightPeak + }; + } + + if (_iO.useWaveformData && typeof oWaveformDataLeft !== 'undefined' && oWaveformDataLeft) { + _t.waveformData = { + left: oWaveformDataLeft.split(','), + right: oWaveformDataRight.split(',') + }; + } + + if (_iO.useEQData) { + if (typeof oEQData !== 'undefined' && oEQData && oEQData.leftEQ) { + eqLeft = oEQData.leftEQ.split(','); + _t.eqData = eqLeft; + _t.eqData.left = eqLeft; + if (typeof oEQData.rightEQ !== 'undefined' && oEQData.rightEQ) { + _t.eqData.right = oEQData.rightEQ.split(','); + } + } + } + + } + + if (_t.playState === 1) { + + // special case/hack: ensure buffering is false if loading from cache (and not yet started) + if (!_t.isHTML5 && _fV === 8 && !_t.position && _t.isBuffering) { + _t._onbufferchange(0); + } + + if (_iO.whileplaying) { + // flash may call after actual finish + _iO.whileplaying.apply(_t); + } + + } + + return true; + + }; + + this._oncaptiondata = function(oData) { + + /** + * internal: flash 9 + NetStream (MovieStar/RTMP-only) feature + * + * @param {object} oData + */ + + _s._wD('SMSound._oncaptiondata(): "' + this.id + '" caption data received.'); + + _t.captiondata = oData; + + if (_t._iO.oncaptiondata) { + _t._iO.oncaptiondata.apply(_t, [oData]); + } + + }; + + this._onmetadata = function(oMDProps, oMDData) { + + /** + * internal: flash 9 + NetStream (MovieStar/RTMP-only) feature + * RTMP may include song title, MovieStar content may include encoding info + * + * @param {array} oMDProps (names) + * @param {array} oMDData (values) + */ + + _s._wD('SMSound._onmetadata(): "' + this.id + '" metadata received.'); + + var oData = {}, i, j; + + for (i = 0, j = oMDProps.length; i < j; i++) { + oData[oMDProps[i]] = oMDData[i]; + } + _t.metadata = oData; + + if (_t._iO.onmetadata) { + _t._iO.onmetadata.apply(_t); + } + + }; + + this._onid3 = function(oID3Props, oID3Data) { + + /** + * internal: flash 8 + flash 9 ID3 feature + * may include artist, song title etc. + * + * @param {array} oID3Props (names) + * @param {array} oID3Data (values) + */ + + _s._wD('SMSound._onid3(): "' + this.id + '" ID3 data received.'); + + var oData = [], i, j; + + for (i = 0, j = oID3Props.length; i < j; i++) { + oData[oID3Props[i]] = oID3Data[i]; + } + _t.id3 = _mixin(_t.id3, oData); + + if (_t._iO.onid3) { + _t._iO.onid3.apply(_t); + } + + }; + + // flash/RTMP-only + + this._onconnect = function(bSuccess) { + + bSuccess = (bSuccess === 1); + _s._wD('SMSound._onconnect(): "'+_t.id+'"'+(bSuccess?' connected.':' failed to connect? - '+_t.url), (bSuccess?1:2)); + _t.connected = bSuccess; + + if (bSuccess) { + + _t.failures = 0; + + if (_idCheck(_t.id)) { + if (_t.getAutoPlay()) { + // only update the play state if auto playing + _t.play(undefined, _t.getAutoPlay()); + } else if (_t._iO.autoLoad) { + _t.load(); + } + } + + if (_t._iO.onconnect) { + _t._iO.onconnect.apply(_t, [bSuccess]); + } + + } + + }; + + this._ondataerror = function(sError) { + + // flash 9 wave/eq data handler + // hack: called at start, and end from flash at/after onfinish() + if (_t.playState > 0) { + _s._wD('SMSound._ondataerror(): ' + sError); + if (_t._iO.ondataerror) { + _t._iO.ondataerror.apply(_t); + } + } + + }; + + }; // SMSound() + + /** + * Private SoundManager internals + * ------------------------------ + */ + + _getDocument = function() { + + return (_doc.body || _doc._docElement || _doc.getElementsByTagName('div')[0]); + + }; + + _id = function(sID) { + + return _doc.getElementById(sID); + + }; + + _mixin = function(oMain, oAdd) { + + // non-destructive merge + var o1 = (oMain || {}), o2, o; + + // if unspecified, o2 is the default options object + o2 = (typeof oAdd === 'undefined' ? _s.defaultOptions : oAdd); + + for (o in o2) { + + if (o2.hasOwnProperty(o) && typeof o1[o] === 'undefined') { + + if (typeof o2[o] !== 'object' || o2[o] === null) { + + // assign directly + o1[o] = o2[o]; + + } else { + + // recurse through o2 + o1[o] = _mixin(o1[o], o2[o]); + + } + + } + + } + + return o1; + + }; + + // additional soundManager properties that soundManager.setup() will accept + + _extraOptions = { + 'onready': 1, + 'ontimeout': 1, + 'defaultOptions': 1, + 'flash9Options': 1, + 'movieStarOptions': 1 + }; + + _assign = function(o, oParent) { + + /** + * recursive assignment of properties, soundManager.setup() helper + * allows property assignment based on whitelist + */ + + var i, + result = true, + hasParent = (typeof oParent !== 'undefined'), + setupOptions = _s.setupOptions, + extraOptions = _extraOptions; + + // + + // if soundManager.setup() called, show accepted parameters. + + if (typeof o === 'undefined') { + + result = []; + + for (i in setupOptions) { + + if (setupOptions.hasOwnProperty(i)) { + result.push(i); + } + + } + + for (i in extraOptions) { + + if (extraOptions.hasOwnProperty(i)) { + + if (typeof _s[i] === 'object') { + + result.push(i+': {...}'); + + } else if (_s[i] instanceof Function) { + + result.push(i+': function() {...}'); + + } else { + + result.push(i); + + } + + } + + } + + _s._wD(_str('setup', result.join(', '))); + + return false; + + } + + // + + for (i in o) { + + if (o.hasOwnProperty(i)) { + + // if not an {object} we want to recurse through... + + if (typeof o[i] !== 'object' || o[i] === null || o[i] instanceof Array) { + + // check "allowed" options + + if (hasParent && typeof extraOptions[oParent] !== 'undefined') { + + // valid recursive / nested object option, eg., { defaultOptions: { volume: 50 } } + _s[oParent][i] = o[i]; + + } else if (typeof setupOptions[i] !== 'undefined') { + + // special case: assign to setupOptions object, which soundManager property references + _s.setupOptions[i] = o[i]; + + // assign directly to soundManager, too + _s[i] = o[i]; + + } else if (typeof extraOptions[i] === 'undefined') { + + // invalid or disallowed parameter. complain. + _complain(_str((typeof _s[i] === 'undefined' ? 'setupUndef' : 'setupError'), i), 2); + + result = false; + + } else { + + /** + * valid extraOptions parameter. + * is it a method, like onready/ontimeout? call it. + * multiple parameters should be in an array, eg. soundManager.setup({onready: [myHandler, myScope]}); + */ + + if (_s[i] instanceof Function) { + + _s[i].apply(_s, (o[i] instanceof Array? o[i] : [o[i]])); + + } else { + + // good old-fashioned direct assignment + _s[i] = o[i]; + + } + + } + + } else { + + // recursion case, eg., { defaultOptions: { ... } } + + if (typeof extraOptions[i] === 'undefined') { + + // invalid or disallowed parameter. complain. + _complain(_str((typeof _s[i] === 'undefined' ? 'setupUndef' : 'setupError'), i), 2); + + result = false; + + } else { + + // recurse through object + return _assign(o[i], i); + + } + + } + + } + + } + + return result; + + }; + + function _preferFlashCheck(kind) { + + // whether flash should play a given type + return (_s.preferFlash && _hasFlash && !_s.ignoreFlash && (typeof _s.flash[kind] !== 'undefined' && _s.flash[kind])); + + } + + /** + * Internal DOM2-level event helpers + * --------------------------------- + */ + + _event = (function() { + + var old = (_win.attachEvent), + evt = { + add: (old?'attachEvent':'addEventListener'), + remove: (old?'detachEvent':'removeEventListener') + }; + + function getArgs(oArgs) { + + var args = _slice.call(oArgs), + len = args.length; + + if (old) { + // prefix + args[1] = 'on' + args[1]; + if (len > 3) { + // no capture + args.pop(); + } + } else if (len === 3) { + args.push(false); + } + + return args; + + } + + function apply(args, sType) { + + var element = args.shift(), + method = [evt[sType]]; + + if (old) { + element[method](args[0], args[1]); + } else { + element[method].apply(element, args); + } + + } + + function add() { + + apply(getArgs(arguments), 'add'); + + } + + function remove() { + + apply(getArgs(arguments), 'remove'); + + } + + return { + 'add': add, + 'remove': remove + }; + + }()); + + /** + * Internal HTML5 event handling + * ----------------------------- + */ + + function _html5_event(oFn) { + + // wrap html5 event handlers so we don't call them on destroyed sounds + + return function(e) { + + var t = this._t, + result; + + if (!t || !t._a) { + // + if (t && t.id) { + _s._wD(_h5+'ignoring '+e.type+': '+t.id); + } else { + _s._wD(_h5+'ignoring '+e.type); + } + // + result = null; + } else { + result = oFn.call(this, e); + } + + return result; + + }; + + } + + _html5_events = { + + // HTML5 event-name-to-handler map + + abort: _html5_event(function() { + + _s._wD(_h5+'abort: '+this._t.id); + + }), + + // enough has loaded to play + + canplay: _html5_event(function() { + + var t = this._t, + position1K; + + if (t._html5_canplay) { + // this event has already fired. ignore. + return true; + } + + t._html5_canplay = true; + _s._wD(_h5+'canplay: '+t.id+', '+t.url); + t._onbufferchange(0); + + // position according to instance options + position1K = (typeof t._iO.position !== 'undefined' && !isNaN(t._iO.position)?t._iO.position/1000:null); + + // set the position if position was set before the sound loaded + if (t.position && this.currentTime !== position1K) { + _s._wD(_h5+'canplay: setting position to '+position1K); + try { + this.currentTime = position1K; + } catch(ee) { + _s._wD(_h5+'setting position of ' + position1K + ' failed: '+ee.message, 2); + } + } + + // hack for HTML5 from/to case + if (t._iO._oncanplay) { + t._iO._oncanplay(); + } + + }), + + canplaythrough: _html5_event(function() { + + var t = this._t; + + if (!t.loaded) { + t._onbufferchange(0); + t._whileloading(t.bytesLoaded, t.bytesTotal, t._get_html5_duration()); + t._onload(true); + } + + }), + + // TODO: Reserved for potential use + /* + emptied: _html5_event(function() { + + _s._wD(_h5+'emptied: '+this._t.id); + + }), + */ + + ended: _html5_event(function() { + + var t = this._t; + + _s._wD(_h5+'ended: '+t.id); + t._onfinish(); + + }), + + error: _html5_event(function() { + + _s._wD(_h5+'error: '+this.error.code); + // call load with error state? + this._t._onload(false); + + }), + + loadeddata: _html5_event(function() { + + var t = this._t; + + _s._wD(_h5+'loadeddata: '+this._t.id); + + // safari seems to nicely report progress events, eventually totalling 100% + if (!t._loaded && !_isSafari) { + t.duration = t._get_html5_duration(); + } + + }), + + loadedmetadata: _html5_event(function() { + + _s._wD(_h5+'loadedmetadata: '+this._t.id); + + }), + + loadstart: _html5_event(function() { + + _s._wD(_h5+'loadstart: '+this._t.id); + // assume buffering at first + this._t._onbufferchange(1); + + }), + + play: _html5_event(function() { + + _s._wD(_h5+'play: '+this._t.id+', '+this._t.url); + // once play starts, no buffering + this._t._onbufferchange(0); + + }), + + playing: _html5_event(function() { + + _s._wD(_h5+'playing: '+this._t.id); + + // once play starts, no buffering + this._t._onbufferchange(0); + + }), + + progress: _html5_event(function(e) { + + // note: can fire repeatedly after "loaded" event, due to use of HTTP range/partials + + var t = this._t, + i, j, str, buffered = 0, + isProgress = (e.type === 'progress'), + ranges = e.target.buffered, + // firefox 3.6 implements e.loaded/total (bytes) + loaded = (e.loaded||0), + total = (e.total||1), + // HTML5 returns msec. SM2 API uses seconds for setPosition() etc., whether Flash or HTML5. + scale = 1000; + + // reset the "buffered" (loaded byte ranges) array + t.buffered = []; + + if (ranges && ranges.length) { + + // if loaded is 0, try TimeRanges implementation as % of load + // https://developer.mozilla.org/en/DOM/TimeRanges + + // re-build "buffered" array + for (i=0, j=ranges.length; i + if (isProgress && ranges.length > 1) { + str = []; + j = ranges.length; + for (i=0; i + + } + + if (!isNaN(loaded)) { + + // if progress, likely not buffering + t._onbufferchange(0); + // TODO: prevent calls with duplicate values. + t._whileloading(loaded, total, t._get_html5_duration()); + if (loaded && total && loaded === total) { + // in case "onload" doesn't fire (eg. gecko 1.9.2) + _html5_events.canplaythrough.call(this, e); + } + + } + + }), + + ratechange: _html5_event(function() { + + _s._wD(_h5+'ratechange: '+this._t.id); + + }), + + suspend: _html5_event(function(e) { + + // download paused/stopped, may have finished (eg. onload) + var t = this._t; + + _s._wD(_h5+'suspend: '+t.id); + _html5_events.progress.call(this, e); + t._onsuspend(); + + }), + + stalled: _html5_event(function() { + + _s._wD(_h5+'stalled: '+this._t.id); + + }), + + timeupdate: _html5_event(function() { + + this._t._onTimer(); + + }), + + waiting: _html5_event(function() { + + var t = this._t; + + // see also: seeking + _s._wD(_h5+'waiting: '+t.id); + + // playback faster than download rate, etc. + t._onbufferchange(1); + + }) + + }; + + _html5OK = function(iO) { + + // playability test based on URL or MIME type + + var result; + + if (iO.serverURL || (iO.type && _preferFlashCheck(iO.type))) { + + // RTMP, or preferring flash + result = false; + + } else { + + // Use type, if specified. If HTML5-only mode, no other options, so just give 'er + result = ((iO.type ? _html5CanPlay({type:iO.type}) : _html5CanPlay({url:iO.url}) || _s.html5Only)); + + } + + return result; + + }; + + _html5Unload = function(oAudio, url) { + + /** + * Internal method: Unload media, and cancel any current/pending network requests. + * Firefox can load an empty URL, which allegedly destroys the decoder and stops the download. + * https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox#Stopping_the_download_of_media + * However, Firefox has been seen loading a relative URL from '' and thus requesting the hosting page on unload. + * Other UA behaviour is unclear, so everyone else gets an about:blank-style URL. + */ + + if (oAudio) { + // Firefox likes '' for unload (used to work?) - however, may request hosting page URL (bad.) Most other UAs dislike '' and fail to unload. + oAudio.src = url; + } + + }; + + _html5CanPlay = function(o) { + + /** + * Try to find MIME, test and return truthiness + * o = { + * url: '/path/to/an.mp3', + * type: 'audio/mp3' + * } + */ + + if (!_s.useHTML5Audio || !_s.hasHTML5) { + return false; + } + + var url = (o.url || null), + mime = (o.type || null), + aF = _s.audioFormats, + result, + offset, + fileExt, + item; + + // account for known cases like audio/mp3 + + if (mime && typeof _s.html5[mime] !== 'undefined') { + return (_s.html5[mime] && !_preferFlashCheck(mime)); + } + + if (!_html5Ext) { + _html5Ext = []; + for (item in aF) { + if (aF.hasOwnProperty(item)) { + _html5Ext.push(item); + if (aF[item].related) { + _html5Ext = _html5Ext.concat(aF[item].related); + } + } + } + _html5Ext = new RegExp('\\.('+_html5Ext.join('|')+')(\\?.*)?$','i'); + } + + // TODO: Strip URL queries, etc. + fileExt = (url ? url.toLowerCase().match(_html5Ext) : null); + + if (!fileExt || !fileExt.length) { + if (!mime) { + result = false; + } else { + // audio/mp3 -> mp3, result should be known + offset = mime.indexOf(';'); + // strip "audio/X; codecs.." + fileExt = (offset !== -1?mime.substr(0,offset):mime).substr(6); + } + } else { + // match the raw extension name - "mp3", for example + fileExt = fileExt[1]; + } + + if (fileExt && typeof _s.html5[fileExt] !== 'undefined') { + // result known + result = (_s.html5[fileExt] && !_preferFlashCheck(fileExt)); + } else { + mime = 'audio/'+fileExt; + result = _s.html5.canPlayType({type:mime}); + _s.html5[fileExt] = result; + // _s._wD('canPlayType, found result: '+result); + result = (result && _s.html5[mime] && !_preferFlashCheck(mime)); + } + + return result; + + }; + + _testHTML5 = function() { + + /** + * Internal: Iterates over audioFormats, determining support eg. audio/mp3, audio/mpeg and so on + * assigns results to html5[] and flash[]. + */ + + if (!_s.useHTML5Audio || !_s.hasHTML5) { + return false; + } + + // double-whammy: Opera 9.64 throws WRONG_ARGUMENTS_ERR if no parameter passed to Audio(), and Webkit + iOS happily tries to load "null" as a URL. :/ + var a = (typeof Audio !== 'undefined' ? (_isOpera && opera.version() < 10 ? new Audio(null) : new Audio()) : null), + item, lookup, support = {}, aF, i; + + function _cp(m) { + + var canPlay, i, j, + result = false, + isOK = false; + + if (!a || typeof a.canPlayType !== 'function') { + return result; + } + + if (m instanceof Array) { + // iterate through all mime types, return any successes + for (i=0, j=m.length; i= 0; i--) { + + // eg. audio/m4a + support['audio/'+aF[item].related[i]] = support[item]; + _s.html5[aF[item].related[i]] = support[item]; + _s.flash[aF[item].related[i]] = support[item]; + + } + + } + + } + + } + + support.canPlayType = (a?_cp:null); + _s.html5 = _mixin(_s.html5, support); + + return true; + + }; + + _strings = { + + // + notReady: 'Not loaded yet - wait for soundManager.onready()', + notOK: 'Audio support is not available.', + domError: _smc + 'createMovie(): appendChild/innerHTML call failed. DOM not ready or other error.', + spcWmode: _smc + 'createMovie(): Removing wmode, preventing known SWF loading issue(s)', + swf404: _sm + ': Verify that %s is a valid path.', + tryDebug: 'Try ' + _sm + '.debugFlash = true for more security details (output goes to SWF.)', + checkSWF: 'See SWF output for more debug info.', + localFail: _sm + ': Non-HTTP page (' + _doc.location.protocol + ' URL?) Review Flash player security settings for this special case:\nhttp://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html\nMay need to add/allow path, eg. c:/sm2/ or /users/me/sm2/', + waitFocus: _sm + ': Special case: Waiting for SWF to load with window focus...', + waitImpatient: _sm + ': Getting impatient, still waiting for Flash%s...', + waitForever: _sm + ': Waiting indefinitely for Flash (will recover if unblocked)...', + waitSWF: _sm + ': Retrying, waiting for 100% SWF load...', + needFunction: _sm + ': Function object expected for %s', + badID: 'Warning: Sound ID "%s" should be a string, starting with a non-numeric character', + currentObj: '--- ' + _sm + '._debug(): Current sound objects ---', + waitEI: _smc + 'initMovie(): Waiting for ExternalInterface call from Flash...', + waitOnload: _sm + ': Waiting for window.onload()', + docLoaded: _sm + ': Document already loaded', + onload: _smc + 'initComplete(): calling soundManager.onload()', + onloadOK: _sm + '.onload() complete', + init: _smc + 'init()', + didInit: _smc + 'init(): Already called?', + flashJS: _sm + ': Attempting JS to Flash call...', + secNote: 'Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html', + badRemove: 'Warning: Failed to remove flash movie.', + shutdown: _sm + '.disable(): Shutting down', + queue: _sm + ': Queueing %s handler', + smFail: _sm + ': Failed to initialise.', + smError: 'SMSound.load(): Exception: JS-Flash communication failed, or JS error.', + fbTimeout: 'No flash response, applying .'+_swfCSS.swfTimedout+' CSS...', + fbLoaded: 'Flash loaded', + fbHandler: _smc+'flashBlockHandler()', + manURL: 'SMSound.load(): Using manually-assigned URL', + onURL: _sm + '.load(): current URL already assigned.', + badFV: _sm + '.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.', + as2loop: 'Note: Setting stream:false so looping can work (flash 8 limitation)', + noNSLoop: 'Note: Looping not implemented for MovieStar formats', + needfl9: 'Note: Switching to flash 9, required for MP4 formats.', + mfTimeout: 'Setting flashLoadTimeout = 0 (infinite) for off-screen, mobile flash case', + needFlash: _sm + ': Fatal error: Flash is needed to play some required formats, but is not available.', + gotFocus: _sm + ': Got window focus.', + mfOn: 'mobileFlash::enabling on-screen flash repositioning', + policy: 'Enabling usePolicyFile for data access', + setup: _sm + '.setup(): allowed parameters: %s', + setupError: _sm + '.setup(): "%s" cannot be assigned with this method.', + setupUndef: _sm + '.setup(): Could not find option "%s"', + setupLate: _sm + '.setup(): url + flashVersion changes will not take effect until reboot().', + h5a: 'creating HTML5 Audio() object', + noURL: _sm + ': Flash URL required. Call soundManager.setup({url:...}) to get started.' + // + + }; + + _str = function() { + + // internal string replace helper. + // arguments: o [,items to replace] + // + + // real array, please + var args = _slice.call(arguments), + + // first arg + o = args.shift(), + + str = (_strings && _strings[o]?_strings[o]:''), i, j; + if (str && args && args.length) { + for (i = 0, j = args.length; i < j; i++) { + str = str.replace('%s', args[i]); + } + } + + return str; + // + + }; + + _loopFix = function(sOpt) { + + // flash 8 requires stream = false for looping to work + if (_fV === 8 && sOpt.loops > 1 && sOpt.stream) { + _wDS('as2loop'); + sOpt.stream = false; + } + + return sOpt; + + }; + + _policyFix = function(sOpt, sPre) { + + if (sOpt && !sOpt.usePolicyFile && (sOpt.onid3 || sOpt.usePeakData || sOpt.useWaveformData || sOpt.useEQData)) { + _s._wD((sPre || '') + _str('policy')); + sOpt.usePolicyFile = true; + } + + return sOpt; + + }; + + _complain = function(sMsg) { + + // + if (typeof console !== 'undefined' && typeof console.warn !== 'undefined') { + console.warn(sMsg); + } else { + _s._wD(sMsg); + } + // + + }; + + _doNothing = function() { + + return false; + + }; + + _disableObject = function(o) { + + var oProp; + + for (oProp in o) { + if (o.hasOwnProperty(oProp) && typeof o[oProp] === 'function') { + o[oProp] = _doNothing; + } + } + + oProp = null; + + }; + + _failSafely = function(bNoDisable) { + + // general failure exception handler + + if (typeof bNoDisable === 'undefined') { + bNoDisable = false; + } + + if (_disabled || bNoDisable) { + _wDS('smFail', 2); + _s.disable(bNoDisable); + } + + }; + + _normalizeMovieURL = function(smURL) { + + var urlParams = null, url; + + if (smURL) { + if (smURL.match(/\.swf(\?.*)?$/i)) { + urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf('.swf?') + 4); + if (urlParams) { + // assume user knows what they're doing + return smURL; + } + } else if (smURL.lastIndexOf('/') !== smURL.length - 1) { + // append trailing slash, if needed + smURL += '/'; + } + } + + url = (smURL && smURL.lastIndexOf('/') !== - 1 ? smURL.substr(0, smURL.lastIndexOf('/') + 1) : './') + _s.movieURL; + + if (_s.noSWFCache) { + url += ('?ts=' + new Date().getTime()); + } + + return url; + + }; + + _setVersionInfo = function() { + + // short-hand for internal use + + _fV = parseInt(_s.flashVersion, 10); + + if (_fV !== 8 && _fV !== 9) { + _s._wD(_str('badFV', _fV, _defaultFlashVersion)); + _s.flashVersion = _fV = _defaultFlashVersion; + } + + // debug flash movie, if applicable + + var isDebug = (_s.debugMode || _s.debugFlash?'_debug.swf':'.swf'); + + if (_s.useHTML5Audio && !_s.html5Only && _s.audioFormats.mp4.required && _fV < 9) { + _s._wD(_str('needfl9')); + _s.flashVersion = _fV = 9; + } + + _s.version = _s.versionNumber + (_s.html5Only?' (HTML5-only mode)':(_fV === 9?' (AS3/Flash 9)':' (AS2/Flash 8)')); + + // set up default options + if (_fV > 8) { + // +flash 9 base options + _s.defaultOptions = _mixin(_s.defaultOptions, _s.flash9Options); + _s.features.buffering = true; + // +moviestar support + _s.defaultOptions = _mixin(_s.defaultOptions, _s.movieStarOptions); + _s.filePatterns.flash9 = new RegExp('\\.(mp3|' + _netStreamTypes.join('|') + ')(\\?.*)?$', 'i'); + _s.features.movieStar = true; + } else { + _s.features.movieStar = false; + } + + // regExp for flash canPlay(), etc. + _s.filePattern = _s.filePatterns[(_fV !== 8?'flash9':'flash8')]; + + // if applicable, use _debug versions of SWFs + _s.movieURL = (_fV === 8?'soundmanager2.swf':'soundmanager2_flash9.swf').replace('.swf', isDebug); + + _s.features.peakData = _s.features.waveformData = _s.features.eqData = (_fV > 8); + + }; + + _setPolling = function(bPolling, bHighPerformance) { + + if (!_flash) { + return false; + } + + _flash._setPolling(bPolling, bHighPerformance); + + }; + + _initDebug = function() { + + // starts debug mode, creating output
for UAs without console object + + // allow force of debug mode via URL + if (_s.debugURLParam.test(_wl)) { + _s.debugMode = true; + } + + // + if (_id(_s.debugID)) { + return false; + } + + var oD, oDebug, oTarget, oToggle, tmp; + + if (_s.debugMode && !_id(_s.debugID) && (!_hasConsole || !_s.useConsole || !_s.consoleOnly)) { + + oD = _doc.createElement('div'); + oD.id = _s.debugID + '-toggle'; + + oToggle = { + 'position': 'fixed', + 'bottom': '0px', + 'right': '0px', + 'width': '1.2em', + 'height': '1.2em', + 'lineHeight': '1.2em', + 'margin': '2px', + 'textAlign': 'center', + 'border': '1px solid #999', + 'cursor': 'pointer', + 'background': '#fff', + 'color': '#333', + 'zIndex': 10001 + }; + + oD.appendChild(_doc.createTextNode('-')); + oD.onclick = _toggleDebug; + oD.title = 'Toggle SM2 debug console'; + + if (_ua.match(/msie 6/i)) { + oD.style.position = 'absolute'; + oD.style.cursor = 'hand'; + } + + for (tmp in oToggle) { + if (oToggle.hasOwnProperty(tmp)) { + oD.style[tmp] = oToggle[tmp]; + } + } + + oDebug = _doc.createElement('div'); + oDebug.id = _s.debugID; + oDebug.style.display = (_s.debugMode?'block':'none'); + + if (_s.debugMode && !_id(oD.id)) { + try { + oTarget = _getDocument(); + oTarget.appendChild(oD); + } catch(e2) { + throw new Error(_str('domError')+' \n'+e2.toString()); + } + oTarget.appendChild(oDebug); + } + + } + + oTarget = null; + // + + }; + + _idCheck = this.getSoundById; + + // + _wDS = function(o, errorLevel) { + + return (!o ? '' : _s._wD(_str(o), errorLevel)); + + }; + + // last-resort debugging option + + if (_wl.indexOf('sm2-debug=alert') + 1 && _s.debugMode) { + _s._wD = function(sText) {window.alert(sText);}; + } + + _toggleDebug = function() { + + var o = _id(_s.debugID), + oT = _id(_s.debugID + '-toggle'); + + if (!o) { + return false; + } + + if (_debugOpen) { + // minimize + oT.innerHTML = '+'; + o.style.display = 'none'; + } else { + oT.innerHTML = '-'; + o.style.display = 'block'; + } + + _debugOpen = !_debugOpen; + + }; + + _debugTS = function(sEventType, bSuccess, sMessage) { + + // troubleshooter debug hooks + + if (typeof sm2Debugger !== 'undefined') { + try { + sm2Debugger.handleEvent(sEventType, bSuccess, sMessage); + } catch(e) { + // oh well + } + } + + return true; + + }; + // + + _getSWFCSS = function() { + + var css = []; + + if (_s.debugMode) { + css.push(_swfCSS.sm2Debug); + } + + if (_s.debugFlash) { + css.push(_swfCSS.flashDebug); + } + + if (_s.useHighPerformance) { + css.push(_swfCSS.highPerf); + } + + return css.join(' '); + + }; + + _flashBlockHandler = function() { + + // *possible* flash block situation. + + var name = _str('fbHandler'), + p = _s.getMoviePercent(), + css = _swfCSS, + error = {type:'FLASHBLOCK'}; + + if (_s.html5Only) { + return false; + } + + if (!_s.ok()) { + + if (_needsFlash) { + // make the movie more visible, so user can fix + _s.oMC.className = _getSWFCSS() + ' ' + css.swfDefault + ' ' + (p === null?css.swfTimedout:css.swfError); + _s._wD(name+': '+_str('fbTimeout')+(p?' ('+_str('fbLoaded')+')':'')); + } + + _s.didFlashBlock = true; + + // fire onready(), complain lightly + _processOnEvents({type:'ontimeout', ignoreInit:true, error:error}); + _catchError(error); + + } else { + + // SM2 loaded OK (or recovered) + + // + if (_s.didFlashBlock) { + _s._wD(name+': Unblocked'); + } + // + + if (_s.oMC) { + _s.oMC.className = [_getSWFCSS(), css.swfDefault, css.swfLoaded + (_s.didFlashBlock?' '+css.swfUnblocked:'')].join(' '); + } + + } + + }; + + _addOnEvent = function(sType, oMethod, oScope) { + + if (typeof _on_queue[sType] === 'undefined') { + _on_queue[sType] = []; + } + + _on_queue[sType].push({ + 'method': oMethod, + 'scope': (oScope || null), + 'fired': false + }); + + }; + + _processOnEvents = function(oOptions) { + + // if unspecified, assume OK/error + + if (!oOptions) { + oOptions = { + type: (_s.ok() ? 'onready' : 'ontimeout') + }; + } + + if (!_didInit && oOptions && !oOptions.ignoreInit) { + // not ready yet. + return false; + } + + if (oOptions.type === 'ontimeout' && (_s.ok() || (_disabled && !oOptions.ignoreInit))) { + // invalid case + return false; + } + + var status = { + success: (oOptions && oOptions.ignoreInit?_s.ok():!_disabled) + }, + + // queue specified by type, or none + srcQueue = (oOptions && oOptions.type?_on_queue[oOptions.type]||[]:[]), + + queue = [], i, j, + args = [status], + canRetry = (_needsFlash && _s.useFlashBlock && !_s.ok()); + + if (oOptions.error) { + args[0].error = oOptions.error; + } + + for (i = 0, j = srcQueue.length; i < j; i++) { + if (srcQueue[i].fired !== true) { + queue.push(srcQueue[i]); + } + } + + if (queue.length) { + _s._wD(_sm + ': Firing ' + queue.length + ' '+oOptions.type+'() item' + (queue.length === 1?'':'s')); + for (i = 0, j = queue.length; i < j; i++) { + if (queue[i].scope) { + queue[i].method.apply(queue[i].scope, args); + } else { + queue[i].method.apply(this, args); + } + if (!canRetry) { + // flashblock case doesn't count here + queue[i].fired = true; + } + } + } + + return true; + + }; + + _initUserOnload = function() { + + _win.setTimeout(function() { + + if (_s.useFlashBlock) { + _flashBlockHandler(); + } + + _processOnEvents(); + + // call user-defined "onload", scoped to window + + if (typeof _s.onload === 'function') { + _wDS('onload', 1); + _s.onload.apply(_win); + _wDS('onloadOK', 1); + } + + if (_s.waitForWindowLoad) { + _event.add(_win, 'load', _initUserOnload); + } + + },1); + + }; + + _detectFlash = function() { + + // hat tip: Flash Detect library (BSD, (C) 2007) by Carl "DocYes" S. Yestrau - http://featureblend.com/javascript-flash-detection-library.html / http://featureblend.com/license.txt + + if (typeof _hasFlash !== 'undefined') { + // this work has already been done. + return _hasFlash; + } + + var hasPlugin = false, n = navigator, nP = n.plugins, obj, type, types, AX = _win.ActiveXObject; + + if (nP && nP.length) { + type = 'application/x-shockwave-flash'; + types = n.mimeTypes; + if (types && types[type] && types[type].enabledPlugin && types[type].enabledPlugin.description) { + hasPlugin = true; + } + } else if (typeof AX !== 'undefined') { + try { + obj = new AX('ShockwaveFlash.ShockwaveFlash'); + } catch(e) { + // oh well + } + hasPlugin = (!!obj); + } + + _hasFlash = hasPlugin; + + return hasPlugin; + + }; + + _featureCheck = function() { + + var needsFlash, + item, + result = true, + formats = _s.audioFormats, + // iPhone <= 3.1 has broken HTML5 audio(), but firmware 3.2 (original iPad) + iOS4 works. + isSpecial = (_is_iDevice && !!(_ua.match(/os (1|2|3_0|3_1)/i))); + + if (isSpecial) { + + // has Audio(), but is broken; let it load links directly. + _s.hasHTML5 = false; + + // ignore flash case, however + _s.html5Only = true; + + if (_s.oMC) { + _s.oMC.style.display = 'none'; + } + + result = false; + + } else { + + if (_s.useHTML5Audio) { + + if (!_s.html5 || !_s.html5.canPlayType) { + _s._wD('SoundManager: No HTML5 Audio() support detected.'); + _s.hasHTML5 = false; + } + + // + if (_isBadSafari) { + _s._wD(_smc+'Note: Buggy HTML5 Audio in Safari on this OS X release, see https://bugs.webkit.org/show_bug.cgi?id=32159 - '+(!_hasFlash?' would use flash fallback for MP3/MP4, but none detected.':'will use flash fallback for MP3/MP4, if available'),1); + } + // + + } + + } + + if (_s.useHTML5Audio && _s.hasHTML5) { + + for (item in formats) { + if (formats.hasOwnProperty(item)) { + if ((formats[item].required && !_s.html5.canPlayType(formats[item].type)) || (_s.preferFlash && (_s.flash[item] || _s.flash[formats[item].type]))) { + // flash may be required, or preferred for this format + needsFlash = true; + } + } + } + + } + + // sanity check... + if (_s.ignoreFlash) { + needsFlash = false; + } + + _s.html5Only = (_s.hasHTML5 && _s.useHTML5Audio && !needsFlash); + + return (!_s.html5Only); + + }; + + _parseURL = function(url) { + + /** + * Internal: Finds and returns the first playable URL (or failing that, the first URL.) + * @param {string or array} url A single URL string, OR, an array of URL strings or {url:'/path/to/resource', type:'audio/mp3'} objects. + */ + + var i, j, urlResult = 0, result; + + if (url instanceof Array) { + + // find the first good one + for (i=0, j=url.length; i= 0; i--) { + + if (_s.sounds[_s.soundIDs[i]].isHTML5 && _s.sounds[_s.soundIDs[i]]._hasTimer) { + + _s.sounds[_s.soundIDs[i]]._onTimer(); + + } + + } + + }; + + _catchError = function(options) { + + options = (typeof options !== 'undefined' ? options : {}); + + if (typeof _s.onerror === 'function') { + _s.onerror.apply(_win, [{type:(typeof options.type !== 'undefined' ? options.type : null)}]); + } + + if (typeof options.fatal !== 'undefined' && options.fatal) { + _s.disable(); + } + + }; + + _badSafariFix = function() { + + // special case: "bad" Safari (OS X 10.3 - 10.7) must fall back to flash for MP3/MP4 + if (!_isBadSafari || !_detectFlash()) { + // doesn't apply + return false; + } + + var aF = _s.audioFormats, i, item; + + for (item in aF) { + if (aF.hasOwnProperty(item)) { + if (item === 'mp3' || item === 'mp4') { + _s._wD(_sm+': Using flash fallback for '+item+' format'); + _s.html5[item] = false; + // assign result to related formats, too + if (aF[item] && aF[item].related) { + for (i = aF[item].related.length-1; i >= 0; i--) { + _s.html5[aF[item].related[i]] = false; + } + } + } + } + } + + }; + + /** + * Pseudo-private flash/ExternalInterface methods + * ---------------------------------------------- + */ + + this._setSandboxType = function(sandboxType) { + + // + var sb = _s.sandbox; + + sb.type = sandboxType; + sb.description = sb.types[(typeof sb.types[sandboxType] !== 'undefined'?sandboxType:'unknown')]; + + _s._wD('Flash security sandbox type: ' + sb.type); + + if (sb.type === 'localWithFile') { + + sb.noRemote = true; + sb.noLocal = false; + _wDS('secNote', 2); + + } else if (sb.type === 'localWithNetwork') { + + sb.noRemote = false; + sb.noLocal = true; + + } else if (sb.type === 'localTrusted') { + + sb.noRemote = false; + sb.noLocal = false; + + } + // + + }; + + this._externalInterfaceOK = function(flashDate, swfVersion) { + + // flash callback confirming flash loaded, EI working etc. + // flashDate = approx. timing/delay info for JS/flash bridge + // swfVersion: SWF build string + + if (_s.swfLoaded) { + return false; + } + + var e, eiTime = new Date().getTime(); + + _s._wD(_smc+'externalInterfaceOK()' + (flashDate?' (~' + (eiTime - flashDate) + ' ms)':'')); + _debugTS('swf', true); + _debugTS('flashtojs', true); + _s.swfLoaded = true; + _tryInitOnFocus = false; + + if (_isBadSafari) { + _badSafariFix(); + } + + // complain if JS + SWF build/version strings don't match, excluding +DEV builds + // + if (!swfVersion || swfVersion.replace(/\+dev/i,'') !== _s.versionNumber.replace(/\+dev/i, '')) { + + e = _sm + ': Fatal: JavaScript file build "' + _s.versionNumber + '" does not match Flash SWF build "' + swfVersion + '" at ' + _s.url + '. Ensure both are up-to-date.'; + + // escape flash -> JS stack so this error fires in window. + setTimeout(function versionMismatch() { + throw new Error(e); + }, 0); + + // exit, init will fail with timeout + return false; + + } + // + + // slight delay before init + setTimeout(_init, _isIE ? 100 : 1); + + }; + + /** + * Private initialization helpers + * ------------------------------ + */ + + _createMovie = function(smID, smURL) { + + if (_didAppend && _appendSuccess) { + // ignore if already succeeded + return false; + } + + function _initMsg() { + _s._wD('-- SoundManager 2 ' + _s.version + (!_s.html5Only && _s.useHTML5Audio?(_s.hasHTML5?' + HTML5 audio':', no HTML5 audio support'):'') + (!_s.html5Only ? (_s.useHighPerformance?', high performance mode, ':', ') + (( _s.flashPollingInterval ? 'custom (' + _s.flashPollingInterval + 'ms)' : 'normal') + ' polling') + (_s.wmode?', wmode: ' + _s.wmode:'') + (_s.debugFlash?', flash debug mode':'') + (_s.useFlashBlock?', flashBlock mode':'') : '') + ' --', 1); + } + + if (_s.html5Only) { + + // 100% HTML5 mode + _setVersionInfo(); + + _initMsg(); + _s.oMC = _id(_s.movieID); + _init(); + + // prevent multiple init attempts + _didAppend = true; + + _appendSuccess = true; + + return false; + + } + + // flash path + var remoteURL = (smURL || _s.url), + localURL = (_s.altURL || remoteURL), + swfTitle = 'JS/Flash audio component (SoundManager 2)', + oTarget = _getDocument(), + extraClass = _getSWFCSS(), + isRTL = null, + html = _doc.getElementsByTagName('html')[0], + oEmbed, oMovie, tmp, movieHTML, oEl, s, x, sClass; + + isRTL = (html && html.dir && html.dir.match(/rtl/i)); + smID = (typeof smID === 'undefined'?_s.id:smID); + + function param(name, value) { + return ''; + } + + // safety check for legacy (change to Flash 9 URL) + _setVersionInfo(); + _s.url = _normalizeMovieURL(_overHTTP?remoteURL:localURL); + smURL = _s.url; + + _s.wmode = (!_s.wmode && _s.useHighPerformance ? 'transparent' : _s.wmode); + + if (_s.wmode !== null && (_ua.match(/msie 8/i) || (!_isIE && !_s.useHighPerformance)) && navigator.platform.match(/win32|win64/i)) { + /** + * extra-special case: movie doesn't load until scrolled into view when using wmode = anything but 'window' here + * does not apply when using high performance (position:fixed means on-screen), OR infinite flash load timeout + * wmode breaks IE 8 on Vista + Win7 too in some cases, as of January 2011 (?) + */ + _wDS('spcWmode'); + _s.wmode = null; + } + + oEmbed = { + 'name': smID, + 'id': smID, + 'src': smURL, + 'quality': 'high', + 'allowScriptAccess': _s.allowScriptAccess, + 'bgcolor': _s.bgColor, + 'pluginspage': _http+'www.macromedia.com/go/getflashplayer', + 'title': swfTitle, + 'type': 'application/x-shockwave-flash', + 'wmode': _s.wmode, + // http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html + 'hasPriority': 'true' + }; + + if (_s.debugFlash) { + oEmbed.FlashVars = 'debug=1'; + } + + if (!_s.wmode) { + // don't write empty attribute + delete oEmbed.wmode; + } + + if (_isIE) { + + // IE is "special". + oMovie = _doc.createElement('div'); + movieHTML = [ + '', + param('movie', smURL), + param('AllowScriptAccess', _s.allowScriptAccess), + param('quality', oEmbed.quality), + (_s.wmode? param('wmode', _s.wmode): ''), + param('bgcolor', _s.bgColor), + param('hasPriority', 'true'), + (_s.debugFlash ? param('FlashVars', oEmbed.FlashVars) : ''), + '' + ].join(''); + + } else { + + oMovie = _doc.createElement('embed'); + for (tmp in oEmbed) { + if (oEmbed.hasOwnProperty(tmp)) { + oMovie.setAttribute(tmp, oEmbed[tmp]); + } + } + + } + + _initDebug(); + extraClass = _getSWFCSS(); + oTarget = _getDocument(); + + if (oTarget) { + + _s.oMC = (_id(_s.movieID) || _doc.createElement('div')); + + if (!_s.oMC.id) { + + _s.oMC.id = _s.movieID; + _s.oMC.className = _swfCSS.swfDefault + ' ' + extraClass; + s = null; + oEl = null; + + if (!_s.useFlashBlock) { + if (_s.useHighPerformance) { + // on-screen at all times + s = { + 'position': 'fixed', + 'width': '8px', + 'height': '8px', + // >= 6px for flash to run fast, >= 8px to start up under Firefox/win32 in some cases. odd? yes. + 'bottom': '0px', + 'left': '0px', + 'overflow': 'hidden' + }; + } else { + // hide off-screen, lower priority + s = { + 'position': 'absolute', + 'width': '6px', + 'height': '6px', + 'top': '-9999px', + 'left': '-9999px' + }; + if (isRTL) { + s.left = Math.abs(parseInt(s.left,10))+'px'; + } + } + } + + if (_isWebkit) { + // soundcloud-reported render/crash fix, safari 5 + _s.oMC.style.zIndex = 10000; + } + + if (!_s.debugFlash) { + for (x in s) { + if (s.hasOwnProperty(x)) { + _s.oMC.style[x] = s[x]; + } + } + } + + try { + if (!_isIE) { + _s.oMC.appendChild(oMovie); + } + oTarget.appendChild(_s.oMC); + if (_isIE) { + oEl = _s.oMC.appendChild(_doc.createElement('div')); + oEl.className = _swfCSS.swfBox; + oEl.innerHTML = movieHTML; + } + _appendSuccess = true; + } catch(e) { + throw new Error(_str('domError')+' \n'+e.toString()); + } + + } else { + + // SM2 container is already in the document (eg. flashblock use case) + sClass = _s.oMC.className; + _s.oMC.className = (sClass?sClass+' ':_swfCSS.swfDefault) + (extraClass?' '+extraClass:''); + _s.oMC.appendChild(oMovie); + if (_isIE) { + oEl = _s.oMC.appendChild(_doc.createElement('div')); + oEl.className = _swfCSS.swfBox; + oEl.innerHTML = movieHTML; + } + _appendSuccess = true; + + } + + } + + _didAppend = true; + _initMsg(); + _s._wD(_smc+'createMovie(): Trying to load ' + smURL + (!_overHTTP && _s.altURL?' (alternate URL)':''), 1); + + return true; + + }; + + _initMovie = function() { + + if (_s.html5Only) { + _createMovie(); + return false; + } + + // attempt to get, or create, movie (may already exist) + if (_flash) { + return false; + } + + if (!_s.url) { + + /** + * Something isn't right - we've reached init, but the soundManager url property has not been set. + * User has not called setup({url: ...}), or has not set soundManager.url (legacy use case) directly before init time. + * Notify and exit. If user calls setup() with a url: property, init will be restarted as in the deferred loading case. + */ + + _wDS('noURL'); + return false; + + } + + // inline markup case + _flash = _s.getMovie(_s.id); + + if (!_flash) { + if (!_oRemoved) { + // try to create + _createMovie(_s.id, _s.url); + } else { + // try to re-append removed movie after reboot() + if (!_isIE) { + _s.oMC.appendChild(_oRemoved); + } else { + _s.oMC.innerHTML = _oRemovedHTML; + } + _oRemoved = null; + _didAppend = true; + } + _flash = _s.getMovie(_s.id); + } + + // + if (_flash) { + _wDS('waitEI'); + } + // + + if (typeof _s.oninitmovie === 'function') { + setTimeout(_s.oninitmovie, 1); + } + + return true; + + }; + + _delayWaitForEI = function() { + + setTimeout(_waitForEI, 1000); + + }; + + _waitForEI = function() { + + var p, + loadIncomplete = false; + + if (!_s.url) { + // No SWF url to load (noURL case) - exit for now. Will be retried when url is set. + return false; + } + + if (_waitingForEI) { + return false; + } + + _waitingForEI = true; + _event.remove(_win, 'load', _delayWaitForEI); + + if (_tryInitOnFocus && !_isFocused) { + // Safari won't load flash in background tabs, only when focused. + _wDS('waitFocus'); + return false; + } + + if (!_didInit) { + p = _s.getMoviePercent(); + _s._wD(_str('waitImpatient', (p > 0 ? ' (SWF ' + p + '% loaded)' : ''))); + if (p > 0 && p < 100) { + loadIncomplete = true; + } + } + + setTimeout(function() { + + p = _s.getMoviePercent(); + + if (loadIncomplete) { + // special case: if movie *partially* loaded, retry until it's 100% before assuming failure. + _waitingForEI = false; + _s._wD(_str('waitSWF')); + _win.setTimeout(_delayWaitForEI, 1); + return false; + } + + // + if (!_didInit) { + _s._wD(_sm + ': No Flash response within expected time.\nLikely causes: ' + (p === 0?'Loading ' + _s.movieURL + ' may have failed (and/or Flash ' + _fV + '+ not present?), ':'') + 'Flash blocked or JS-Flash security error.' + (_s.debugFlash?' ' + _str('checkSWF'):''), 2); + if (!_overHTTP && p) { + _wDS('localFail', 2); + if (!_s.debugFlash) { + _wDS('tryDebug', 2); + } + } + if (p === 0) { + // if 0 (not null), probably a 404. + _s._wD(_str('swf404', _s.url)); + } + _debugTS('flashtojs', false, ': Timed out' + _overHTTP?' (Check flash security or flash blockers)':' (No plugin/missing SWF?)'); + } + // + + // give up / time-out, depending + + if (!_didInit && _okToDisable) { + if (p === null) { + // SWF failed. Maybe blocked. + if (_s.useFlashBlock || _s.flashLoadTimeout === 0) { + if (_s.useFlashBlock) { + _flashBlockHandler(); + } + _wDS('waitForever'); + } else { + // old SM2 behaviour, simply fail + _failSafely(true); + } + } else { + // flash loaded? Shouldn't be a blocking issue, then. + if (_s.flashLoadTimeout === 0) { + _wDS('waitForever'); + } else { + _failSafely(true); + } + } + } + + }, _s.flashLoadTimeout); + + }; + + _handleFocus = function() { + + function cleanup() { + _event.remove(_win, 'focus', _handleFocus); + } + + if (_isFocused || !_tryInitOnFocus) { + // already focused, or not special Safari background tab case + cleanup(); + return true; + } + + _okToDisable = true; + _isFocused = true; + _wDS('gotFocus'); + + // allow init to restart + _waitingForEI = false; + + // kick off ExternalInterface timeout, now that the SWF has started + _delayWaitForEI(); + + cleanup(); + return true; + + }; + + _showSupport = function() { + + // + + var item, tests = []; + + if (_s.useHTML5Audio && _s.hasHTML5) { + for (item in _s.audioFormats) { + if (_s.audioFormats.hasOwnProperty(item)) { + tests.push(item + ': ' + _s.html5[item] + (!_s.html5[item] && _hasFlash && _s.flash[item] ? ' (using flash)' : (_s.preferFlash && _s.flash[item] && _hasFlash ? ' (preferring flash)': (!_s.html5[item] ? ' (' + (_s.audioFormats[item].required ? 'required, ':'') + 'and no flash support)' : '')))); + } + } + _s._wD('-- SoundManager 2: HTML5 support tests ('+_s.html5Test+'): '+tests.join(', ')+' --',1); + } + + // + + }; + + _initComplete = function(bNoDisable) { + + if (_didInit) { + return false; + } + + if (_s.html5Only) { + // all good. + _s._wD('-- SoundManager 2: loaded --'); + _didInit = true; + _initUserOnload(); + _debugTS('onload', true); + return true; + } + + var wasTimeout = (_s.useFlashBlock && _s.flashLoadTimeout && !_s.getMoviePercent()), + result = true, + error; + + if (!wasTimeout) { + _didInit = true; + if (_disabled) { + error = {type: (!_hasFlash && _needsFlash ? 'NO_FLASH' : 'INIT_TIMEOUT')}; + } + } + + _s._wD('-- SoundManager 2 ' + (_disabled?'failed to load':'loaded') + ' (' + (_disabled?'Flash security/load error':'OK') + ') --', 1); + + if (_disabled || bNoDisable) { + if (_s.useFlashBlock && _s.oMC) { + _s.oMC.className = _getSWFCSS() + ' ' + (_s.getMoviePercent() === null?_swfCSS.swfTimedout:_swfCSS.swfError); + } + _processOnEvents({type:'ontimeout', error:error, ignoreInit: true}); + _debugTS('onload', false); + _catchError(error); + result = false; + } else { + _debugTS('onload', true); + } + + if (!_disabled) { + if (_s.waitForWindowLoad && !_windowLoaded) { + _wDS('waitOnload'); + _event.add(_win, 'load', _initUserOnload); + } else { + // + if (_s.waitForWindowLoad && _windowLoaded) { + _wDS('docLoaded'); + } + // + _initUserOnload(); + } + } + + return result; + + }; + + /** + * apply top-level setupOptions object as local properties, eg., this.setupOptions.flashVersion -> this.flashVersion (soundManager.flashVersion) + * this maintains backward compatibility, and allows properties to be defined separately for use by soundManager.setup(). + */ + + _setProperties = function() { + + var i, + o = _s.setupOptions; + + for (i in o) { + + if (o.hasOwnProperty(i)) { + + // assign local property if not already defined + + if (typeof _s[i] === 'undefined') { + + _s[i] = o[i]; + + } else if (_s[i] !== o[i]) { + + // legacy support: write manually-assigned property (eg., soundManager.url) back to setupOptions to keep things in sync + _s.setupOptions[i] = _s[i]; + + } + + } + + } + + }; + + + _init = function() { + + _wDS('init'); + + // called after onload() + + if (_didInit) { + _wDS('didInit'); + return false; + } + + function _cleanup() { + _event.remove(_win, 'load', _s.beginDelayedInit); + } + + if (_s.html5Only) { + if (!_didInit) { + // we don't need no steenking flash! + _cleanup(); + _s.enabled = true; + _initComplete(); + } + return true; + } + + // flash path + _initMovie(); + + try { + + _wDS('flashJS'); + + // attempt to talk to Flash + _flash._externalInterfaceTest(false); + + // apply user-specified polling interval, OR, if "high performance" set, faster vs. default polling + // (determines frequency of whileloading/whileplaying callbacks, effectively driving UI framerates) + _setPolling(true, (_s.flashPollingInterval || (_s.useHighPerformance ? 10 : 50))); + + if (!_s.debugMode) { + // stop the SWF from making debug output calls to JS + _flash._disableDebug(); + } + + _s.enabled = true; + _debugTS('jstoflash', true); + + if (!_s.html5Only) { + // prevent browser from showing cached page state (or rather, restoring "suspended" page state) via back button, because flash may be dead + // http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/ + _event.add(_win, 'unload', _doNothing); + } + + } catch(e) { + + _s._wD('js/flash exception: ' + e.toString()); + _debugTS('jstoflash', false); + _catchError({type:'JS_TO_FLASH_EXCEPTION', fatal:true}); + // don't disable, for reboot() + _failSafely(true); + _initComplete(); + + return false; + + } + + _initComplete(); + + // disconnect events + _cleanup(); + + return true; + + }; + + _domContentLoaded = function() { + + if (_didDCLoaded) { + return false; + } + + _didDCLoaded = true; + + // assign top-level soundManager properties eg. soundManager.url + _setProperties(); + + _initDebug(); + + /** + * Temporary feature: allow force of HTML5 via URL params: sm2-usehtml5audio=0 or 1 + * Ditto for sm2-preferFlash, too. + */ + // + (function(){ + + var a = 'sm2-usehtml5audio=', + a2 = 'sm2-preferflash=', + b = null, + b2 = null, + hasCon = (typeof console !== 'undefined' && typeof console.log === 'function'), + l = _wl.toLowerCase(); + + if (l.indexOf(a) !== -1) { + b = (l.charAt(l.indexOf(a)+a.length) === '1'); + if (hasCon) { + console.log((b?'Enabling ':'Disabling ')+'useHTML5Audio via URL parameter'); + } + _s.setup({ + 'useHTML5Audio': b + }); + } + + if (l.indexOf(a2) !== -1) { + b2 = (l.charAt(l.indexOf(a2)+a2.length) === '1'); + if (hasCon) { + console.log((b2?'Enabling ':'Disabling ')+'preferFlash via URL parameter'); + } + _s.setup({ + 'preferFlash': b2 + }); + } + + }()); + // + + if (!_hasFlash && _s.hasHTML5) { + _s._wD('SoundManager: No Flash detected'+(!_s.useHTML5Audio?', enabling HTML5.':'. Trying HTML5-only mode.')); + _s.setup({ + 'useHTML5Audio': true, + // make sure we aren't preferring flash, either + // TODO: preferFlash should not matter if flash is not installed. Currently, stuff breaks without the below tweak. + 'preferFlash': false + }); + } + + _testHTML5(); + _s.html5.usingFlash = _featureCheck(); + _needsFlash = _s.html5.usingFlash; + _showSupport(); + + if (!_hasFlash && _needsFlash) { + _wDS('needFlash'); + // TODO: Fatal here vs. timeout approach, etc. + // hack: fail sooner. + _s.setup({ + 'flashLoadTimeout': 1 + }); + } + + if (_doc.removeEventListener) { + _doc.removeEventListener('DOMContentLoaded', _domContentLoaded, false); + } + + _initMovie(); + return true; + + }; + + _domContentLoadedIE = function() { + + if (_doc.readyState === 'complete') { + _domContentLoaded(); + _doc.detachEvent('onreadystatechange', _domContentLoadedIE); + } + + return true; + + }; + + _winOnLoad = function() { + // catch edge case of _initComplete() firing after window.load() + _windowLoaded = true; + _event.remove(_win, 'load', _winOnLoad); + }; + + // sniff up-front + _detectFlash(); + + // focus and window load, init (primarily flash-driven) + _event.add(_win, 'focus', _handleFocus); + _event.add(_win, 'load', _delayWaitForEI); + _event.add(_win, 'load', _winOnLoad); + + if (_doc.addEventListener) { + + _doc.addEventListener('DOMContentLoaded', _domContentLoaded, false); + + } else if (_doc.attachEvent) { + + _doc.attachEvent('onreadystatechange', _domContentLoadedIE); + + } else { + + // no add/attachevent support - safe to assume no JS -> Flash either + _debugTS('onload', false); + _catchError({type:'NO_DOM2_EVENTS', fatal:true}); + + } + +} // SoundManager() + +// SM2_DEFER details: http://www.schillmania.com/projects/soundmanager2/doc/getstarted/#lazy-loading + +if (typeof SM2_DEFER === 'undefined' || !SM2_DEFER) { + soundManager = new SoundManager(); +} + +/** + * SoundManager public interfaces + * ------------------------------ + */ + +window.SoundManager = SoundManager; // constructor +window.soundManager = soundManager; // public API, flash callbacks etc. + +}(window)); \ No newline at end of file diff --git a/timeside/player/static/timeside/js/markermap.js b/timeside/player/static/timeside/js/markermap.js new file mode 100644 index 0000000..ad3ae8c --- /dev/null +++ b/timeside/player/static/timeside/js/markermap.js @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2007-2011 Parisson + * Copyright (c) 2011 Riccardo Zaccarelli + * + * This file is part of TimeSide. + * + * TimeSide is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * TimeSide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimeSide. If not, see . + * + * Author: Riccardo Zaccarelli + */ + +/** + * class fior managing markers in the player. This class extends TimesideArray (see timeside.js), and communicates with the other + * two TimesideArrays of the player which receive edit events (click, keys events etcetera): the ruler (ruler.js) and the markermapdiv (divmarker.js) + * All bindings between these three classes are set in in the player (See player.js , in particular loadMarkers method) + */ +Timeside.classes.MarkerMap = Timeside.classes.TimesideArray.extend({ + + init: function() { + this._super(); + }, + + pFloat: parseFloat, //reference to function parseFloat for faster lookup + //overridden + add: function(newMarker) { + if(!('offset' in newMarker)){ + return -1; + } + + if(typeof newMarker.offset != 'number'){ //check to be sure: + newMarker.offset = this.pFloat(newMarker.offset); + } + if(!('id' in newMarker)){ + newMarker.id = this.$TU.uniqid(); //Timeside.utils.uniqid(); + } + if(!('isEditable' in newMarker)){ + newMarker.isEditable = false; + } + var marker = newMarker; + var idx = this.insertionIndex(marker); + if(idx>=0){ //it exists? there is a problem.... + this.debug('markermap.add: adding an already existing marker!!'); //should not happen. however... + return -1; + } + + idx = -idx-1; + //we do not call the super add cause we want to insert at a specified index + this._super(marker,idx); + //notifies controller.onMarkerMapAdd + + this.fire('add', { + marker: marker, + index: idx + }); + + return idx; + }, + + //overridden method. Contrarily to super method, + //where the first argument is the index (integer), here the + //the first argument can also be a marker. Its index will be found and, if valid, the super method will be called + //RETURNS -1 IF SOMETHING HAS GONE WRONG, OTHERWISE THE + remove: function(markerOrMarkerIndex) { + var idx = -1; + if(typeof markerOrMarkerIndex == 'number'){ + idx = markerOrMarkerIndex; + }else if('id' in markerOrMarkerIndex && 'offset' in markerOrMarkerIndex){ + idx = this.insertionIndex(markerOrMarkerIndex); + //idx>=0 ONLY if marker has been found + } + if(idx<0 || idx>=this.length){ + this.debug('markermap.remove: index out of bounds or marker not found'); + return -1; + } + var marker = this._super(idx); + this.fire('remove',{ + 'index':idx, + 'marker':marker + }); + return idx; + }, + + //overridden method. Contrarily to super method, + //where the first argument is the 'from' index, here the + //the first argument can also be a marker + move: function(markerOrMarkerIndex, newOffset){ + var oldIndex = -1; + if(typeof markerOrMarkerIndex == 'number'){ + oldIndex = markerOrMarkerIndex; + }else if('id' in markerOrMarkerIndex && 'offset' in markerOrMarkerIndex){ + oldIndex = this.insertionIndex(markerOrMarkerIndex); + //oldIndex>=0 ONLY if marker has been found + } + if(oldIndex<0 || oldIndex>=this.length){ + this.debug('markermap.move: index out of bounds or marker not found'); + return -1; + } + + var newIndex = this.insertionIndex(newOffset); + //select the case: + if(newIndex<0){ //newindex should ALWAYS be lower than zero, as insertionIndex(number) should not match any marker + //we didn't move the marker on another marker (newOffset does not correspond to any marker) + //just return the real insertionIndex + newIndex = -newIndex-1; + } + + //now: if the isnertionIndex is greater than the marker index (oldIndex), + //we decrement newIndex cause super.move will first REMOVE the marker and then set it at newIndex + if(newIndex > oldIndex){ + newIndex--; + } + newIndex = this._super(oldIndex,newIndex); + + if(newIndex <0){ + this.debug('markermap.move: new index out of bounds'); + return -1; + } + + var markers = this.toArray(); + var marker = markers[newIndex]; + var oldOffset = marker.offset; + marker.offset = newOffset; + this.fire('move', { + marker: marker, + fromIndex: oldIndex, + toIndex: newIndex, + oldOffset: oldOffset + }); + return newIndex; + }, + + + //returns the insertion index of object in this sorted array by means of a binary search algorithm. + // A) If object is a marker and: + // a1) Is found (ie, there is a marker in this map + // with same offset and same id), returns the index of the marker found, in the range [0, this.length-1]. Otherwise, if + // a2) Is not found, then returns -(insertionIndex-1), where insertionIndex is the + // index at which object would be inserted preserving the array order. Note that this assures that a + // number lower than zero means that object is not present in the array, and viceversa + // B) If object is a number or a string number (eg, "12.567"), then a marker with offset = object is built and compared + // against the markers in the map. Note however that in this case that equality between marker's offset is sufficient, + // as object is not provided with an id. THEREFORE, IF THE MAP CONTAINS SEVERAL MARKERS AT INDICES i, i+1, ... i+n + // WITH SAME OFFSET == object, THERE IS NO WAY TO DETERMINE WHICH INDEX IN [i, i+1, ... i+n] WILL BE RETURNED. + // See player.forward and player.rewind for an example of the B) case. + //LAST NOTE: BE SURE object is either a number (float) or object.offset is a number (float). + //In case it is not known, If it is a string number such as + //"4.562" the comparison falis (eg, "2.567" > "10.544") but obviously, no error is thrown in javascript + // + insertionIndex: function(object){ + //default comparator function: + //returns 1 as the first argument is greater than the second + //returns -1 as the first argument is lower than the second + //returns 0 if the arguments are equal + var comparatorFunction = function(markerInMap,newMarker){ + var a = markerInMap.offset; + var b = newMarker.offset; + if(ab){ + return 1; + }else{ + var a1 = markerInMap.id; + var b1 = newMarker.id; + if(a1b1){ + return 1; + } + } + return 0; + }; + if(!(typeof object == 'object')){ + var offset; + if(typeof object == 'number'){ + offset = object; + }else{ //to be sure... + offset = parseFloat(object); + } + object = { + 'offset':offset + }; + //key will never be found, so return either 1 or -1: + comparatorFunction = function(markerInMap,newMarker){ + var a = markerInMap.offset; + var b = newMarker.offset; + return a < b ? -1 : (a>b ? 1 : 0); + }; + } + + var data = this.toArray(); + var low = 0; + var high = data.length-1; + + while (low <= high) { + var mid = (low + high) >>> 1; + //biwise operation is not as fast as in compiled languages such as C and java (see Jslint web page) + //However (tested on a PC in Chrome, IE and FF), it is faster than the equivalent: + //var mid = parseInt((low + high)/2); + //even if we reference parseInt before this loop and we call the variable assigned to it + var midVal = data[mid]; + var cmp = comparatorFunction(midVal,object); + if (cmp < 0){ + //the midvalue is lower than the searched index element + low = mid + 1; + }else if (cmp > 0){ + //the midvalue is greater than the searched index element + high = mid - 1; + }else{ + return mid; // key found + } + } + return -(low + 1); // key not found + }, + + //sets isEditable to value + setEditable: function(markerOrMarkerIndex, value) { + var idx = -1; + if(typeof markerOrMarkerIndex == 'number'){ + idx = markerOrMarkerIndex; + }else if('id' in markerOrMarkerIndex && 'offset' in markerOrMarkerIndex){ + idx = this.insertionIndex(markerOrMarkerIndex); + //idx>=0 ONLY if marker has been found + } + if(idx<0 || idx>=this.length){ + this.debug('markermap.setEditable: index out of bounds or marker not found'); + return -1; + } + var marker = this.toArray()[idx]; + var oldVal = marker.isEditable ? true : false; + marker.isEditable = value; + this.fire('markerEditStateChanged',{ + 'index':idx, + 'marker':marker, + 'oldValue':oldVal, + 'value':value + }); + return idx; + } + +} +); \ No newline at end of file diff --git a/timeside/player/static/timeside/js/player.js b/timeside/player/static/timeside/js/player.js new file mode 100644 index 0000000..d43e53c --- /dev/null +++ b/timeside/player/static/timeside/js/player.js @@ -0,0 +1,1067 @@ +/* + * Copyright (C) 2007-2011 Parisson + * Copyright (c) 2011 Riccardo Zaccarelli + * Copyright (c) 2010 Olivier Guilyardi + * + * This file is part of TimeSide. + * + * TimeSide is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * TimeSide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimeSide. If not, see . + * + * Authors: Riccardo Zaccarelli + * Olivier Guilyardi + */ + +/** + * The player class to instantiate a new player. Requires all necessary js (timeside, ruler, markermap etcetera...) and + * jQuery + */ + +//playerDiv, sound, durationInMsec, visualizers, markerMap); +Timeside.classes.Player = Timeside.classes.TimesideClass.extend({ + + //sound duration is in milliseconds because the soundmanager has that unit, + //player (according to timeside syntax) has durations in seconds + // newMarkerCallback must be either a string or a function, the necessary checks is done in Timeside.load + // (which calls this method) + //if markersArray is not an array, it defaults to [] + init: function(configObject) { + this._super(); + var $J = this.$J; + var me=this; + + var msgs = configObject.messages; + if(msgs){ + for(var k in msgs){ + if(msgs.hasOwnProperty(k)){ + var ms = msgs[k]; + if(typeof ms === 'string'){ + this.msgs[k] = ms; + } + } + } + } + + var onError = configObject.onError; + if(typeof onError !== 'function'){ + onError = function(msg){}; + } + + var onReady = configObject.onReady; + if(typeof onReady !== 'function'){ + onReady = function(player){}; + } + + var onReadyWithImage = configObject.onReadyWithImage; + + if(typeof onReadyWithImage === 'function'){ + var onReadyWithImageNamespace = 'imgRefreshed.temp_'+new Date().getTime(); //get an unique namespace + this.bind(onReadyWithImageNamespace,function(data){ + onReadyWithImage(me); + me.unbind(onReadyWithImageNamespace); + }); + } + + var container = configObject.container; + container = container instanceof $J ? container : $J(container); + container = container.length ? container.eq(0) : undefined; + if (!container || !container.length){ + onError('container not defined or invalid'); + return; + } + + var sMan = soundManager; + var sound = configObject.sound; + var createSound = false; + if(this.$TU.flashFailed){ + this.soundErrorMsg = 'soundManager error. If your browser does not support HTML5, Flash player (version '+sMan.flashVersion+'+) must be installed.\nIf flash is installed, try to:\n - Reload the page\n - Empty the cache (see browser preferences/options/tools) and reload the page\n - Restart the browser'; + }else{ + if(typeof sound !== 'string' && typeof sound !== 'object'){ + this.soundErrorMsg ='bad sound parameter: specify a a valid soundManager sound-object, an object with at least two properties, url and id, or URL as string'; + }else if(typeof sound === 'string'){ + createSound = true; + var soundURL = sound; + sound = { + id: 'ts-sound', + autoLoad: false, + url: soundURL, + multiShot: false + }; + //do a raw check to see if it is a soundmanager object + }else if(!sound.hasWonProperty('sID') || !sound.hasWonProperty('_iO') || !sound.hasWonProperty('url')){ + if(!sound.hasWonProperty('url') || !sound.hasWonProperty('id')){ //it is not a soundManager object, has at least an url??? + this.soundErrorMsg = 'bad sound parameter: object requires properties url and id at minimum'; + }else{ + createSound = true; + } + } + if(createSound){ + var soundOptions = sound; + if(sMan.canPlayURL(soundOptions.url)){ //this actually checks only if the url is well formed, not if the file is there + //check if we specified a valid sound duration, otherwise the sound must be loaded + + sound = sMan.createSound(soundOptions); + }else{ + this.soundErrorMsg = 'bad sound parameter (soundManager.canPlayURL returned false)'; + } + } + } + if(this.soundErrorMsg){ + this.getSound = function(){ + return undefined; + }; + }else{ + // sound.play = function(){ + // alert(this.readyState); + // }; + this.getSound = function(){ + return sound; + }; + } + var soundDurationInMsec = configObject.soundDuration; + if(typeof soundDurationInMsec !== 'number' || soundDurationInMsec<=0){ + onError('invalid soundDurationInMsec: NaN or not positive'); + return; + } + + + var soundImgFcn = configObject.soundImage; + + if(!(typeof soundImgFcn === 'string' || typeof soundImgFcn === 'function')){ + onError('invalid sound soundImgFcn. Provide a callback(width,height) or a string denoting a valid URL'); + return; + }else{ + if(typeof soundImgFcn === 'string'){ + var url = soundImgFcn; + this.imageCallback = new function(w,h){ + return url; + }; + }else{ //surely a function + this.imageCallback = soundImgFcn; + } + } + + var soundImgSize = configObject.imageSize; + var markersArray = configObject.markersArray; + var newMarker = configObject.newMarker; + + + + this.playState = 0; //0: not playing, 1: loading, 2:buffering, 3 playing (sound heard) + //container is the div #player + + this.getContainer = function(){ + return container; + }; + + + + var sd = this.toSec(soundDurationInMsec); + this.getSoundDuration = function(){ + return sd; + }; + + this.soundPosition = sound.position ? this.toSec(sound.position) : 0; + + + + // + + //initializing markermap and markerui + var map = new Timeside.classes.MarkerMap(); + this.getMarkerMap = function(){ + return map; + }; + + var canAddMarkers = false; + if(newMarker === true || (typeof newMarker === 'function')){ + canAddMarkers = true; + if(typeof newMarker === 'function'){ + this.newMarker = newMarker; + } + } + + //build the innerHTML as array, then join it. This is usually faster than string concatenation in some browsers. + //Note that the player image (see below) is not created now, however, if it was, it should be given a src + //as NOT specifying any src for image tags can be harmful, + //see http://www.nczonline.net/blog/2009/11/30/empty-image-src-can-destroy-your-site/ and + //http://geekswithblogs.net/bcaraway/archive/2007/08/24/114945.aspx for details + var html = [ + "
", + "
", + "
", + "
", + //lazily created: "", //not providing a src attribute is harmful. Dummy src attribute + "
", + "
", + "
", + "", + "", + "", + "", + "", + "", + "
", + "", + "", + "", + "
", + "
", + "
"]; + + container.html(html.join('')); + + var control = container.find('.ts-control'); + + //bind events to buttons: + var rewind = control.find('.ts-rewind'); + rewind.attr('href', '#').click(function(e){ + me.rewind.apply(me); + return false; + }); + + var forward = control.find('.ts-forward'); + forward.attr('href', '#').click(function(e){ + me.forward.apply(me); + return false; + }); + + var pause = control.find('.ts-pause'); + pause.attr('href', '#').bind('click', function(){ + me.pause.apply(me); + return false; + }); + + var play = control.find('.ts-play'); + play.attr('href', '#').bind('click', function(){ + me.play.apply(me); + return false; + }); + + var setMarkerButton = control.find('.ts-set-marker'); + + if(canAddMarkers){ + setMarkerButton.show().attr('href','#').unbind('click').bind('click', function(){ + me.addMarker(me.soundPosition); + return false; + }); + }else{ + setMarkerButton.hide().unbind('click'); + } + + + //volume: + var volumeSpeaker = control.find('.ts-volume-speaker'); + var volumeBarContainer = control.find('.ts-volume-bar-container'); + var volumeBar = volumeBarContainer.find('.ts-volume-bar'); + + var getVol = function(x){ + var vol = 100*x/volumeBarContainer.width(); + //allow click to easily set to zero or 100, ie set a margin to 5%: + var margin = 5; + if (vol < margin){ + vol=0; + }else if(vol >100-margin){ + vol = 100; + } + return vol; + }; + function setVolume(event,volumeElement){ + var x = event.pageX - volumeElement.offset().left; //using absolute coordinates allows us to + //avoid using layerX (not supported in all browsers) and clientX (which needs the window scrollLeft variable) + me.setSoundVolume(getVol(x)); + return false; + } + volumeBarContainer.attr('href', '#').click(function(event){ + return setVolume(event,volumeBar); + }); + volumeSpeaker.attr('href', '#').click(function(){ + me.setSoundVolume(me.getSoundVolume()>0 ? 0 : getVol(volumeBar.outerWidth())); + return false; + }); + this.setSoundVolume(this.getSoundVolume()); + + control.find('a').attr('href', '#') ; + + //SET NECESSARY CSS (THIS WILL OVERRIDE CSS SET IN STYLESHEETS): + //var viewer = container.find('.ts-viewer'); + var wave = container.find('.ts-wave'); + var ruler_ = container.find('.ts-ruler'); + wave.add(control).add(ruler_).css({ + 'position':'relative', + 'overflow':'hidden' + }); + //assigning display and title to all anchors + var subcontrolsToBeSetVisible = control.find('*'); + if(!canAddMarkers){ + subcontrolsToBeSetVisible = subcontrolsToBeSetVisible.filter(':not(a.ts-set-marker)'); + } + subcontrolsToBeSetVisible.css({ + 'display':'inline-block', + 'overflow':'hidden' + }); + + var waitImg = control.find('.ts-wait'); + waitImg.html('wait').css({ + 'position':'absolute' + }); + + var div = control.find('.ts-volume-wrapper-div'); + div.css({ + 'position':'absolute', + 'left':(volumeSpeaker.position().left+volumeSpeaker.outerWidth(true))+'px', + 'top':0, + 'width':'auto', + 'height':'100%' + }); + //END NECESSARY CSS + + //creating the ruler + var waveImage = container.find('.ts-image-canvas'); + var ruler = new Timeside.classes.Ruler(ruler_, waveImage, this.getSoundDuration()); + //var ruler = new Timeside.classes.Ruler(viewer, this.getSoundDuration()); + this.getRuler = function(){ + return ruler; + }; + //bind mouse events: + ruler.bind('rulermarkermouseevent', function(data){ + var idx = data.index; + data.marker = idx > -1 ? me.getMarker(idx) : undefined; + me.fire('markerMouseEvent',data); + }); + + //setting image size (if provided) and resize player. Note that _setImageSize (with underscore) is intended to be + //a private method (faster). setImageSize (without underscore) is the public method to use outside of player object + if(soundImgSize){ + this._setImageSize(soundImgSize.width,soundImgSize.height,container, wave,true); //calls this.resize which calls ruler.resize + }else{ + this._setImageSize('','',container, wave,true); //calls this.resize which calls ruler.resize + } + + //binds click for the pointer: + var v = wave; //.add(ruler); + v.unbind('click').click(function(evt){ + var w = v.width(); + var x = evt.pageX - v.offset().left; //using absolute coordinates allows us to + //avoid checking whether or not we are clicking on a vertical marker line, on a subdiv etcetera + var sd = me.getSoundDuration(); + me.setSoundPosition(sd*x/w); + }); + + + + //finally, load markers and bind events for markers (see method below): + //NOTE: loadMarkers ASYNCHRONOUSLY CALLS THE SERVER, SO METHODS WRITTEN AFTER IT MIGHT BE EXECUTED BEFORE + //loadMarkers has finished its job + //this.loadMarkers(callback); + if(!(markersArray) || !(markersArray.length)){ + markersArray = []; + } + this.loadMarkers(markersArray); + + + //IE7 BUG: the divs wave and control do not shift downwards after canvas is drawn and covers part of the rulrer. + //Weird enough (with IE it isn't actually), we have just to set the property we already set in the css: + //ie, top: auto. This is however useful even if somebody specified a top property on the divs + ruler_.add(wave).add(control).css('top','auto'); + onReady(this); + }, + + + + //functions for converting seconds (player unit) to milliseconds (sound manager unit) and viceversa: + toSec: function(milliseconds){ + return milliseconds/1000; + }, + toMsec : function(seconds){ //this function has less performances than toSec, as it calls Math.round + return Math.round(1000*seconds); //however, it is assumed that it is NOT called in loops + }, + isPlaying : function(){ + var sound = this.getSound(); + if(!sound){ + return false; + } + return this.playState; + /*Numeric value indicating the current playing state of the sound. + * 0 = stopped/uninitialised + * 1 = playing or buffering sound (play has been called, waiting for data etc.) + *Note that a 1 may not always guarantee that sound is being heard, given buffering and autoPlay status.*/ + //return sound && sound.playState==1; + }, + setSoundPosition: function(newPositionInSeconds){ + //if the player is playing and NOT yet fully loaded, simply calling: + //this.getSound().setPosition(this.toMsec(newPositionInSeconds)); + //resets the position to zero. So we use this workaround: + // this.getSound().stop(); //calling this.pause() hides the waiting bar, which is not the case here + // this.soundPosition = newPositionInSeconds; + // this.play(); + //however, that causes fast pointer move effect is undesiderable + //So: + var wasPlaying = this.isPlaying(); + if(wasPlaying){ + this.getSound().stop(); //dont call this.pause cause it hides the waitbar, if visible and resets the playState + } + //update pointer position. If this call is due to a pointer move (mouse release), + //ruler.isPointerMovingFromMouse=true and the following code has no effect (the pointer is already at the good position) + var ruler = this.getRuler(); + if(ruler){ + ruler.movePointer(newPositionInSeconds); + } + //set sound position: + var oldSoundPosition = this.soundPosition; + this.soundPosition = newPositionInSeconds; + + //resume playing if it was playing: + if(wasPlaying){ + var player = this; + + //delay a little bit the play resume, this might avoid fast pointer repositioning + //(it should not be the case, but it happens. why??) + setTimeout(function(){ + player.play.apply(player); + },100); + } + this.fire('soundPositionSet',{ + player:this, + oldSoundPosition:oldSoundPosition + }); + + }, + showSoundErroMessage: function(){ + alert(this.soundErrorMsg); + }, + //given a marker at index I, specifies that a marker corss event is fired whenever the sound position (pointer) + //is in the interval ]markerCrossedOffsetMargin-I,I+markerCrossedOffsetMargin[ + //the value is in seconds + //markerCrossedOffsetMargin : 0.5, + play : function(){ + + if(this.soundErrorMsg){ + alert(this.soundErrorMsg); + return false; + } + + var player = this; + var sound = player.getSound(); + + if(!player || !sound){ //just check. The cases here (especially, sound = undefined, should be + //together with this.soundErrorMsg != "", so we should have catch the case above + return false; + } + + + var fireOnMarkerPosition = function(seconds){}; //does nothing by default + var map = player.getMarkerMap(); + var markerCrossListeners = player.listenersMap['markerCrossed']; + //optimizing: if no listeners associated to markerCrossListeners, avoid creating a function + if(map && map.length && markerCrossListeners){ + var idx = 0; + if(player.soundPosition>0){ + idx = map.insertionIndex(player.soundPosition); + if(idx<0){ + idx=-idx-1; + } + } + var len = map.length; + if(idx>-1 && idx < len){ + var markers = map.toArray(); + var marker = markers[idx]; + var margin = 0.5; //1 second (0.5*2) of margin (before+after) + var offs = marker.offset; + var intervalUpperBound = offs+margin; + var intervalLowerBound = offs-margin; + var data = { //if you change data, change it also below + index:idx, + marker:marker, + currentSoundPosition: player.soundPosition, + nextMarkerTimeInterval: undefined + }; + fireOnMarkerPosition = function(seconds){ + if(marker){ + if(seconds>intervalLowerBound && seconds < intervalUpperBound){ + idx++; + marker = idx < len ? markers[idx] : undefined; + offs = marker ? marker.offset : undefined; + data.currentSoundPosition = seconds; + data.nextMarkerTimeInterval = marker ? [offs-margin, offs+margin] : undefined; + player.fire('markerCrossed',data); + + if(idx= this.getSoundDuration()){ + playOptions.onfinish(); + }else{ + sound.setVolume(sound.volume); //workaround. Just to be sure. Sometimes it fails when we re-play + sound.play(playOptions); + // soundManager.play(sound.sId,{ + // onload: function(success){ + // alert(success); + // } + // }); + } + + return false; + }, + + msgs : { + loading : 'loading', + buffering: 'buffering', + imgRefreshing : 'refreshing img' + }, + pause: function(){ + var sound = this.getSound(); + //we don't check if it's playing, as the stop must really stop anyway + //if(sound && this.isPlaying()){ + if(sound){ + var v = this.isPlaying(); + sound.stop(); + var data = { + player:this, + oldPlayState:this.playState, + endOfPlayback:false + }; + this.playState = 0; + this.fire('playStateChanged',data); + this.setWait(this.isImgRefreshing ? this.msgs.imgRefreshing : ''); + } + return false; + }, + + getWaitElement: function(){ + return this.getContainer().find('.ts-control').find('.ts-wait'); + }, + + setWait: function(msg){ + var wait = undefined; + + wait = this.getWaitElement(); + if(!wait || msg === undefined){ + return; + } + if(wait.html()!=msg){ + wait.html(msg); + } + + var visible = wait.css('display') != 'none'; + + if(msg && !visible){ + wait.show(); + this.fire('waitShown'); + }else if(!msg && visible){ + wait.hide(); + this.fire('waitHidden'); + } + }, + + /** + * sets whether or not window resize resizes also this player. When true, a variable _dynamicResize =setInterval(...) is attached to + * this class. When false, if _dynamicResize is in this class, clearInterval(_dynamicResize) is called and then the key is deleted + */ + setDynamicResize: function(value){ + var key = '_dynamicResize'; + if(!value && key in this){ + clearInterval(this[key]); + delete this[key]; + return; + } + var wdw = this.$J(window); + var w = wdw.width(); + //var h = wdw.height(); + var me = this; + this.dynamicResize = setInterval(function(){ + var newW = wdw.width(); + if(w!=newW){ + w = newW; + //still wait a second: are we still adjusting the window? (call resize just once): + setTimeout(function(){ + if(wdw.width()==newW){ + me.resize.apply(me); + } + },200); + } + },100); + }, + + resize: function() { + var height; + var container = this.getContainer(); + + var wave = container.find('.ts-wave'); + + height = wave.height(); + // if(!height){ + // height = this.minWaveHeight; + // wave.css('height',height+'px'); + // } + //if (height) { + //set image, imagecontainer and canvas (container on imagecontainer for lines and pointer triangles) css + var elements = wave.find('.ts-image-container').css('zIndex','0') + .add(wave.find('.ts-image-canvas').css('zIndex','1')); //the two children of ts-wave. Set also the zIndex + //in order to visualize the canvas OVER the wav image + var style = { + width: wave.width(), + height: height, + border: 0, + padding:0, + margin:0, + top:0, + left:0 + }; + elements.css(style); + elements.css('position','absolute'); + //} + + //refreshing images: + this.refreshImage(); + this.getRuler().resize(); + }, + getImageUrl : function(){ + var image = this.getContainer().find('.ts-image'); + if(image && image.length){ + return image.attr('src'); + } + return ''; + }, + refreshImage: function(){ + var container = this.getContainer(); + var imageC = container.find('.ts-image-container'); + var image = imageC.find('.ts-image'); + + + var size = this.getImageSize(); + + if(!size.width || !size.height){ + return; + } + var imgSrc = this.imageCallback(size.width,size.height); + var imageNotYetCreated = image.length == 0; + if(!imageNotYetCreated && image.attr('src')==imgSrc){ + return; + } + + var player= this; + + if(imageNotYetCreated){ + image = this.$J(''); + } + + //image inside ts-image-container: + image.css({ + 'width':'100%', + 'height':'100%' + }); // for IE7. Does not seem to hurt IE8, FF, Chrome + + var updateWait = function(){}; + var ir = player.msgs.imgRefreshing; + var we = player.getWaitElement(); + if(ir && we){ + updateWait = function(){ + if(!player.playState || player.playState==3){ + player.setWait(''); + } + } + } + image.load(function(){ + image.unbind('load'); + if(imageNotYetCreated){ + imageC.append(image.addClass('ts-image')); + } + updateWait(); + player.isImgRefreshing = false; + player.fire('imgRefreshed'); + }); + if(ir && we && (!this.playState || this.playState===3)){ //if loading (1) or buffering (2) do not update wait. + //If not playing (undefined or 0) playing (3) update wait + this.setWait(ir); + } + this.isImgRefreshing = true; + this.fire('imgRefreshing'); + image.attr('src', imgSrc); + + }, + getImageSize: function(){ + var wave = this.getContainer().find('.ts-wave'); + return { + width: wave.width(), + height:wave.height() + } + }, + + setImageSize: function(width,height){ + var container = this.getContainer(); + var wave = container.find('.ts-wave'); + this._setImageSize(width,height,container, wave,true); + }, + //this is intended to be a private method, use setImageSize from outside the player object) + _setImageSize: function(width,height,jQueryContainerElement, jQueryWaveElement, resize){ + if(width || height){ + var re = /(?:px|ex|em|%)$/; + if(width){ + width+=''; + width = re.exec(width) ? width : width+'px'; + jQueryContainerElement.css('width',width); + } + if(height){ + height+=''; + height = re.exec(height) ? height : height+'px'; + jQueryWaveElement.css('height',height); + } + } + if(resize){ + this.resize(); + } + }, + + getSoundVolume :function(){ + var s = this.getSound(); + return s ? s.volume : 0; + }, + //moves the pointer (and sound position) forward till the next marker or the end of sound + forward: function() { + var map = this.getMarkerMap(); + var markers = map.toArray(); + var len = markers.length; + var offset = this.getSoundDuration(); + var position = this.soundPosition; //parseFloat(this.getSoundPosition()); + var idx = map.insertionIndex(position); + if(idx<0){ + idx = -idx-1; //cursor is not on a a marker, get the insertion index + }else{ + //cursor is on a marker. As there might be several markers with the same offset + //(see MarkerMap.insertionIndex), move to the outmost right + while(idx0 && markers[idx-1].offset == position){ + idx--; + } + } + idx--; //move backward (rewind) + if(idx>=0){ + offset = markers[idx].offset; + } + this.setSoundPosition(offset); + return false; + }, + + setSoundVolume: function(volume){ + if(typeof volume != 'number'){ //note: typeof for primitive values, instanceof for the rest + //see topic http://stackoverflow.com/questions/472418/why-is-4-not-an-instance-of-number + volume = 100; + } + if(volume<0){ + volume = 0; + }else if(volume>100){ + volume = 100; + } + volume = Math.round(volume); + var sound = this.getSound(); + if(sound){ + sound.setVolume(volume); + } + var control = this.getContainer().find('.ts-control'); + var volumeSpeaker = control.find('.ts-volume-speaker'); + var volumeBarContainer = control.find('.ts-volume-bar-container'); + var volumeBar = volumeBarContainer.find('.ts-volume-bar'); + if(volume==0){ + volumeSpeaker.removeClass('ts-volume-speaker-on').addClass('ts-volume-speaker-off'); + volumeBar.css('visibility','hidden'); + }else{ + volumeSpeaker.removeClass('ts-volume-speaker-off').addClass('ts-volume-speaker-on'); + volumeBar.css('visibility','visible'); + volumeBar.css({ + 'height':'100%', + 'width':volume+'%' + }); + } + }, + + each: function(){ + var map = this.getMarkerMap(); + if(map){ + map.each.apply(map,arguments); + } + }, + + newMarker: function(offset){ + return { + offset:offset + }; + }, + addMarker: function(offset){ + var map = this.getMarkerMap(); + if(map){ + map.add(this.newMarker(offset)); + } + }, + + removeMarker: function(identifier){ //identifier can be an number (marker index) or a marker (the index will be aearched) + //see marlermap.remove + var map = this.getMarkerMap(); + if(map){ + map.remove(identifier); + } + }, + + moveMarker: function(identifier, newOffset){ //identifier can be an number (marker index) or a marker (the index will be aearched) + var map = this.getMarkerMap(); + if(map){ + map.move(identifier,newOffset); + } + }, + + getMarker: function(index){ + var map = this.getMarkerMap(); + if(map){ + return map.toArray()[index]; + } + return undefined; + }, + + setMarkerEditable: function(identifier, value){ + var map = this.getMarkerMap(); + if(map){ + return map.setEditable(identifier,value); + } + return undefined; + }, + + //markers is an array of objects with at least the field offset:sconds.milliseconds + loadMarkers: function(markers){ + //ruler.bind('markermoved',this.markerMoved,this); + //var $J = this.$J; //reference to jQuery + + var player = this; + //initialize the map. + var map = this.getMarkerMap(); + //var mapUI = this.getMarkersUI(); + var ruler = this.getRuler(); + + //TODO: think about if clearing or not: we assign some bindings in the constructor, too: + // map.clear(); + // ruler.clear(); + + var rulerAdd = ruler.add; + + if(markers){ + //add markers to the map. No listeners associated to it (for the moment) + for(var i =0; i< markers.length; i++){ + map.add.apply(map,[markers[i]]); + } + //add markers to ruler and div + map.each(function(i,marker){ + //isEditable and id are added if not present + rulerAdd.apply(ruler,[marker.offset, i, marker.isEditable]); + }); + } + + //the function above calls map.add: + //add bindings when adding a marker: + map.bind('add',function(data){ + //mapuiAdd.apply(mapUI,[data.marker, data.index,data.isNew]); + rulerAdd.apply(ruler,[data.marker.offset, data.index,data.marker.isEditable]); + player.fire('markerAdded',data); + }); + + //2) MOVE + + //add the binding when we move a marker on the ruler: + ruler.bind('markermoved',function(data){ + var soundPos = data.soundPosition; + var isPointer = data.isPointer; + if(isPointer){ + player.setSoundPosition(soundPos); + }else{ + map.move(data.markerElement.getIndex(), soundPos); + } + }); + + //and now add a binding to the map when we move a marker: + + map.bind('move', function(data){ + var from = data.fromIndex; + var to = data.toIndex; + ruler.move.apply(ruler,[from,to,data.marker.offset]); + player.fire('markerMoved',data); + }); + + //remove + map.bind('remove',function(data){ + ruler.remove.apply(ruler, [data.index]); + player.fire('markerRemoved',data); + }); + + //edit state changed + map.bind('markerEditStateChanged',function(data){ + ruler.setEditable.apply(ruler, [data.index, data.value]); + player.fire('markerEditStateChanged',data); + }); + } +}); diff --git a/timeside/player/static/timeside/js/ruler.js b/timeside/player/static/timeside/js/ruler.js new file mode 100644 index 0000000..259d7f3 --- /dev/null +++ b/timeside/player/static/timeside/js/ruler.js @@ -0,0 +1,475 @@ +/* + * Copyright (C) 2007-2011 Parisson + * Copyright (c) 2011 Riccardo Zaccarelli + * Copyright (c) 2010 Olivier Guilyardi + * + * This file is part of TimeSide. + * + * TimeSide is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * TimeSide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimeSide. If not, see . + * + * Authors: Riccardo Zaccarelli + * Olivier Guilyardi + */ + +/** + * Class representing the ruler (upper part) of the player. Requires jQuery + * and Raphael + */ +Timeside.classes.Ruler = Timeside.classes.TimesideArray.extend({ + //init constructor: soundDuration is IN SECONDS!!! (float) + init: function(rulerContainer, waveContainer, soundDuration){ + this._super(); + + this.getSoundDuration= function(){ + return soundDuration; + }; + + this.getWaveContainer =function(){ + return waveContainer; + }; + + this.getContainerWidth =function(){ + return waveContainer.width(); + }; + + this.getRulerContainer = function(){ + return rulerContainer; + } + }, + + resize : function(){ + var duration = this.getSoundDuration(); //in seconds + if (!duration) { + this.debug("ruler.resize: Can't draw ruler with a duration of 0"); + return; + } + + var $J = this.$J; + var rulerContainer = this.getRulerContainer(); + + //remove all elements not pointer or marker + rulerContainer.find(':not(a.ts-pointer,a.ts-marker,a.ts-pointer>*,a.ts-marker>*)').remove(); + + //calculate h with an artifice: create a span (that will be reused later) with the "standard" label + var firstSpan = $J('').css({ + 'display':'block', + 'position':'absolute' + }).html('00000'); //typical timelabel should be '00:00', with '00000' we assure a bit of extra safety space + //note also that display and position must be set as below to calculate the proper outerHeight + rulerContainer.append(firstSpan); //to calculate height, element must be in the document, append it + var verticalMargin = 1; + var h = 2*(verticalMargin+firstSpan.outerHeight()); + //h is the default height of the ruler svg (according to ruler font size) + //to accomodate the necessary space for the labels + //however, if we set a custom height on the ruler, ie h2 is nonzero: + var h2 = rulerContainer.height(); + //then, set the custom height as height for the canvas: + //note that, as markers and pointer have position: absolute, they do not affect div height + if(h2){ + h = h2; + } + var obj = this.calculateRulerElements(rulerContainer.width(),h,firstSpan.outerWidth()); + this.drawRuler(rulerContainer,h,obj.path); + + var labels = obj.labels; + if(labels && labels.length){ + for(var i=0; i ')); + span.html(labels[i][0]).css({ + 'display':'block', + 'position':'absolute', + 'width':'', + 'height':'', + 'right':'', + 'bottom':'', + 'top':'0', + 'left':labels[i][1]+'px' + }); + rulerContainer.append(span); + } + }else{ + firstSpan.html(this.makeTimeLabel(0)); + } + + var pointer = undefined; + if('getPointer' in this){ + pointer = this.getPointer(); + } + if(!pointer){ + pointer = this.add(0,-1); + this.getPointer = function(){ + return pointer; + }; + }else{ + pointer.refreshPosition(); + + } + this.each(function(i,rulermarker){ + rulermarker.refreshPosition(); + }); + + + }, + + drawRuler: function(rulerContainer,h,rulerLinesPath){ + var cssPref = this.cssPrefix; + var upperRectClass = cssPref + 'svg-' + 'ruler-upper-rect'; + var rulerLinesClass = cssPref + 'svg-' + 'ruler-lines'; + + var vml = this.$TU.vml; + if(vml){ + //we create each time a new Raphael object. This is not a big performance issue + var paper = Raphael(rulerContainer[0], rulerContainer.width(), h); + var rect = paper.rect(0,0, rulerContainer.width(), h/2); + var path = paper.path(rulerLinesPath); + var attr = vml.getVmlAttr; + rect.attr(attr(upperRectClass)); + path.attr(attr(rulerLinesClass)); + return; + } + //create svg. Note that elements must be created within a namespace (createElementNS) + //and attributes must be set via .setAttributeNS(null,name,value) + //in other words, jQuery does not work (maybe in future releases) + var $J = this.$J; + var svgNS = "http://www.w3.org/2000/svg"; + var d = document; + var svg = d.createElementNS(svgNS, "svg:svg"); + svg.setAttributeNS( null, "width", rulerContainer.width()); //TODO: optimize width is called also below + svg.setAttributeNS( null, "height", h); + rulerContainer.append($J(svg)); + + var rect = d.createElementNS(svgNS, "svg:rect"); + rect.setAttributeNS( null, "x", 0); + rect.setAttributeNS( null, "y", 0); + rect.setAttributeNS( null, "width", rulerContainer.width()); + rect.setAttributeNS( null, "height", (h/2)); + rect.setAttributeNS( null, "class", upperRectClass); + svg.appendChild(rect); + var lines = d.createElementNS(svgNS, "svg:path"); + lines.setAttributeNS( null, "d", rulerLinesPath); + lines.setAttributeNS( null, "class", rulerLinesClass); + svg.appendChild(lines); + }, + /** + * returns an object with the following properties: + * path: (string) the path of the ruler to be drawn + * labels (array) an array of arrays ['text',x,y] + */ + calculateRulerElements: function(w,h,timeLabelWidth){ + + var duration = this.getSoundDuration(); + + var fontLeftMargin = 2; //should be eual or greater to the ruler stroke width, so that + //the labels are not overlapping the vertical ruler lines + timeLabelWidth+=fontLeftMargin; + + var timeLabelDuration = timeLabelWidth*duration/w; + + //determine the ticks: + var sectionDurations = [1,2,5,10,30,60,120,300,1800,3600,7200,18000,36000]; + //sectionDurations in seconds. Note that 60=1 minute, 3600=1 hour (so the maximum sectionDuration is 36000=10hours) + var i=0; + var len = sectionDurations.length; + while(isectionDurations[i]){ + i++; + } + var sectionDuration = sectionDurations[i]; + var sectionNums = parseInt(0.5+(duration/sectionDurations[i])); //ceil + var sectionWidth = w*sectionDuration/duration; + + + var tickCounts = [10,5,2,1]; + i=0; + var tickCount = tickCounts[0]; + while(isectionWidth){ + i++; + } + var tickAtHalfSectionWidthHigher = i==0 || i==2; //draw tick at half section higher if ticks are even + tickCount = tickCounts[i]; + var tickWidth = sectionWidth/tickCount; + var makeTimeLabel = this.makeTimeLabel; + var h_1 = h-1; //TODO: use line tickness instead of 1 + var path = new Array(parseInt(0.5+(w/tickWidth))); + path[0] = ['M 0 '+h_1]; + len = path.length; + for(i=0; i < len; i+=tickCount){ + for(var j=1; j=0 && index < a.length){ + this._setEditable(a[index],value,false); + } + }, + //do not call, use setEditable(index,value) instead + _setEditable: function(pointerOrMarker, value, isPointer){ + var eventNamespace = this.eventNamespace; + var doc = this.$J(document); + var lbl = pointerOrMarker.getLabel(); + var me = this; + var mme = this.mouseEventType; + + + lbl.unbind('.'+eventNamespace); //this should delete all previous events + + lbl.bind('mouseenter.'+eventNamespace,function(evt){ + me.fire(mme,{ + eventName: 'mouseenter', + eventObj: evt, + index: isPointer ? -1 : pointerOrMarker.getIndex() + }); + return false; + }); + lbl.bind('mouseleave.'+eventNamespace,function(evt){ + me.fire(mme,{ + eventName: 'mouseleave', + eventObj: evt, + index: isPointer ? -1 : pointerOrMarker.getIndex() + }); + return false; + }); + + //to prevent page scrolling after mouseup, as click is also fired + lbl.bind('click.'+this.eventNamespace, function(evt){ + return false; + }); + + + lbl.bind('mousedown.'+eventNamespace,function(evt) { + if(evt.which===1){ + if(value){ + pointerOrMarker.isMovedByMouse = true; + } + + var launchDragStart = true; + + var startX = evt.pageX; + var startPos = lbl.position().left+lbl.width()/2; + + evt.stopPropagation(); //dont notify the ruler or other elements; + var newPos = startPos; + doc.bind('mousemove.'+eventNamespace, function(evt_){ + //preventClickFire=true; + if(value){ + var x = evt_.pageX; + newPos = startPos+(x-startX); + pointerOrMarker.move(newPos); + //update the text if pointer + if(isPointer){ + pointerOrMarker.setText(me.makeTimeLabel(me.toSoundPosition(newPos))); + } + } + if(launchDragStart){ + launchDragStart = false; + me.fire(mme,{ + eventName: 'dragstart', + eventObj: evt_, + index: isPointer ? -1 : pointerOrMarker.getIndex() + }); + } + return false; + + }); + //to avoid scrolling + ////TODO: check IE bug on mouseup on the ruler (pointer is moving too) + //TODO: what happens if the user releases the mouse OUTSIDE the browser???? check bug in IE (mouse release) + var mouseup = function(evt_){ + + doc.unbind('mousemove.'+eventNamespace); + doc.unbind('mouseup.'+eventNamespace); + evt_.stopPropagation(); + if(value){ + if(newPos !== startPos){ + + var data = { + 'markerElement':pointerOrMarker, + 'soundPosition': me.toSoundPosition.apply(me,[newPos]), + 'isPointer':isPointer + }; + me.fire('markermoved',data); + } + pointerOrMarker.isMovedByMouse = false; + } + if(evt_.pageX !== startX){ + me.fire(mme,{ + eventName: 'dragend', + eventObj: evt_, + index: isPointer ? -1 : pointerOrMarker.getIndex() + }); + }else{ + me.fire(mme,{ + eventName: 'click', + eventObj: evt_, + index: isPointer ? -1 : pointerOrMarker.getIndex() + }); + } + return false; + }; + doc.bind('mouseup.'+eventNamespace, mouseup); + } + + me.fire(mme,{ + eventName: 'mousedown', + eventObj: evt, + index: isPointer ? -1 : pointerOrMarker.getIndex() + }); + + + return false; + }); + }, + + //moves the pointer, does not notify any listener. + //soundPosition is in seconds (float) + movePointer : function(soundPosition) { + var pointer = this.getPointer(); + if (pointer && !pointer.isMovedByMouse) { + var pixelOffset = this.toPixelOffset(soundPosition); + //first set text, so the label width is set, then call move: + pointer.setText(this.makeTimeLabel(soundPosition)); + pointer.move(pixelOffset); //does NOT fire any move method + } + return soundPosition; + }, + + //soundPosition is in seconds (float) + toPixelOffset: function(soundPosition) { + var duration = this.getSoundDuration(); + if (soundPosition < 0){ + soundPosition = 0; + }else if (soundPosition > duration){ + soundPosition = duration; + } + var width = this.getContainerWidth(); + var pixelOffset = (soundPosition / duration) * width; + return pixelOffset; + }, + + //returns the soundPosition is in seconds (float) + toSoundPosition: function(pixelOffset) { + var width = this.getContainerWidth(); + + if (pixelOffset < 0){ + pixelOffset = 0; + }else if (pixelOffset > width){ + pixelOffset = width; + } + var duration = this.getSoundDuration(); + var soundPosition = (pixelOffset / width) *duration; + return soundPosition; + } +}); diff --git a/timeside/player/static/timeside/js/rulermarker.js b/timeside/player/static/timeside/js/rulermarker.js new file mode 100644 index 0000000..e98730c --- /dev/null +++ b/timeside/player/static/timeside/js/rulermarker.js @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2007-2011 Parisson + * Copyright (c) 2011 Riccardo Zaccarelli + * Copyright (c) 2010 Olivier Guilyardi + * + * This file is part of TimeSide. + * + * TimeSide is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * TimeSide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimeSide. If not, see . + * + * Authors: Riccardo Zaccarelli + * Olivier Guilyardi + */ + +/** + * Class representing a RulerMarker in TimesideUI + * Requires jQuery Raphael and all associated player classes. rulerDiv position MUST be relative + * (if this class is called from within player, it is) + */ + +Timeside.classes.RulerMarker = Timeside.classes.TimesideClass.extend({ + + + init: function(ruler, waveImgDiv, className) { + this._super(); + var rulerDiv = ruler.getRulerContainer(); + var $J = this.$J; + + var tooltip = ''; + + var cssPref = this.cssPrefix; + + var label = $J('') + .addClass(cssPref + className) + .css({ + display: 'block', + textAlign: 'center', + position: 'absolute', + zIndex: 1000 + }).append($J('')).attr('href', '#'); + + if (tooltip){ + label.attr('title', tooltip); + } + rulerDiv.append(label); + + //rulerDiv MUST HAVE POSITON relative or absolute (it is relative, see player.resize) + if(className != "pointer"){ + label.css('bottom','0'); + }else{ + label.css('top','0'); + } + + //set the index, + var index = -1; + this.setIndex = function(idx, optionalUpdateLabelWidth){ + index = idx; + this.setText(idx+1, optionalUpdateLabelWidth ? true : false); + }; + this.getIndex = function(){ + return index; + }; + + //end======================================================= + //creating public methods: + this.getLabel = function(){ + return label; + }; + + + this.getRulerWidth = function(){ + return rulerDiv.width(); + }; + this.getWaveHeight = function(){ + return waveImgDiv.height(); + }; + + this.positionInPixels = 0; + this.positionAsViewerRatio = 0; + + var arrowBaselineWidth = 9; + + var canvas = undefined; + var canvasClass = cssPref + 'svg-'+className+'-line'; + var vml = this.$TU.vml; //if vml, this class is populated with methods and NOT undefined + var round = Math.round; + if(!vml){ + canvas = this.createCanvasSvg(waveImgDiv, arrowBaselineWidth); + var path = canvas.childNodes[0]; //note that $J(canvas).find('path') does not work in FF at least 3.5 + path.setAttributeNS(null,'class',canvasClass); + this.moveCanvas = function(pixelOffset){ + pixelOffset = round(pixelOffset); + canvas.setAttributeNS( null, "transform", "translate("+pixelOffset+",0)"); + }; + this.jQueryCanvas = $J(canvas); + }else{ + canvas = this.createCanvasVml(waveImgDiv, arrowBaselineWidth); + this.jQueryCanvas = $J(canvas.node); + var attributes = vml.getVmlAttr(canvasClass); + canvas.attr(attributes); //Raphael method + this.moveCanvas = function(pixelOffset){ + pixelOffset = round(pixelOffset); + //for some reason, coordinates inside the VML object are stored by raphael with a zoom of 10: + this.jQueryCanvas.css('left',(10*pixelOffset)+'px'); + }; + //apparently, when resizing the markers loose their attributes. Therefore: + var r = this.refreshPosition; //reference to current refreshPosition + this.refreshPosition = function(){ + r.apply(this); + canvas.attr(attributes); + } + } + }, + + //sets the text of the marker, if the text changes the marker width and optionalUpdateLabelPosition=true, + //re-arranges the marker position to be center-aligned with its vertical line (the one lying on the wav image) + setText: function(text, optionalUpdateLabelPosition) { + var label = this.getLabel(); + if (label) { + var oldWidth = label.width(); + label.find('span').html(text); + var labelWidth = label.width(); + if(oldWidth != labelWidth && optionalUpdateLabelPosition){ + this.refreshLabelPosition(); + } + } + return this; + }, + + //these methods are executed only if marker is movable (see Ruler.js) + move : function(pixelOffset) { + var width = this.getRulerWidth(); + if (this.positionInPixels != pixelOffset) { + if (pixelOffset < 0) { + pixelOffset = 0; + } else if (pixelOffset >= width) { + pixelOffset = width - 1; + } + //defined in the init method (it depends on wehter the current browser supports SVG or not) + this.moveCanvas(pixelOffset); + + this.positionInPixels = pixelOffset; + this.refreshLabelPosition(width); + //store relative position (see refreshPosition below) + this.positionAsViewerRatio = pixelOffset == width-1 ? 1 : pixelOffset/width; + } + return this; + }, + + refreshLabelPosition : function(optionalContainerWidth){ + if(!(optionalContainerWidth)){ + optionalContainerWidth = this.getRulerWidth(); + } + var label = this.getLabel(); + var width = optionalContainerWidth; + var pixelOffset = this.positionInPixels; + var labelWidth = label.outerWidth(); //consider margins and padding + var labelPixelOffset = pixelOffset - labelWidth / 2; + if (labelPixelOffset < 0){ + labelPixelOffset = 0; + }else if (labelPixelOffset + labelWidth > width){ + labelPixelOffset = width - labelWidth; + } + label.css({ + left: this.mRound(labelPixelOffset) + 'px' + }); + + }, + + //function called on ruler.resize. Instead of recreating all markers, simply redraw them + refreshPosition : function(){ + var width = this.getRulerWidth(); + //store relativePosition: + var rp = this.positionAsViewerRatio; + this.move(this.mRound(this.positionAsViewerRatio*width)); + //reset relative position, which does not have to change + //but in move might have been rounded: + this.positionAsViewerRatio = rp; + }, + + + remove : function() { + var label = this.getLabel(); + label.remove(); + this.jQueryCanvas.remove(); //defined in the constructor + return this; + }, + + + createCanvasSvg: function(container, arrowBaseWidth){ + //create svg. Note that elements must be created within a namespace (createElementNS) + //and attributes must be set via .setAttributeNS(null,name,value) + //in other words, jQuery does not work (maybe in future releases) + var $J = this.$J; + var svgNS = "http://www.w3.org/2000/svg"; + var d = document; + var svg = undefined; + if(container.children().length>0){ + svg = container.children().get(0); + }else{ + svg = d.createElementNS(svgNS, "svg:svg"); + container.append($J(svg)); + } + var group = d.createElementNS(svgNS, "svg:g"); + group.setAttributeNS( null, "transform", "translate(0,0)"); + + var path = d.createElementNS(svgNS, "svg:path"); + path.setAttributeNS( null, "d", this.createCanvasPath(0,arrowBaseWidth)); + + group.appendChild(path); + svg.appendChild(group); + + return group; //return the group, not the path, as it is the group that will be translated when moving + }, + + createCanvasVml: function(container, arrowBaseWidth){ + var vml = this.$TU.vml; + var paper = vml.Raphael(container.get(0),container.width(),container.height()); + var shape = paper.path(this.createCanvasPath(0, arrowBaseWidth)); + return shape; + }, + + //w must be odd. Cause the central line must be centered. Example: + // + // xxxxx + // xxx + // x + // x + // x + // + createCanvasPath: function(x,w){ + var halfW = w >>> 1; + //in order to calculate the line height, we could simply set the wave height. However, due to potential + //resizing afterwards, the line could not stretch till the bottom (if it overflows it's fine, as the wave div container has + //overflow = hidden). As we do not want to rebuild the canvas on resize, + //we assess an height which will 99% overflow the wave height in any case. + //We use the wave height and the window height, and take 2 times + //the maximum of those heights: + var wdwH = this.$J(window).height(); + var waveH = this.getWaveHeight(); + var h = 2* (wdwH > waveH ? wdwH : waveH); + return 'M '+(x-halfW)+' 0 L '+(x)+' '+(halfW)+' L '+x+' '+h+ + ' L '+ (x+1)+' '+h+' L '+(x+1)+ ' '+(halfW)+' L '+(x+halfW+1)+' 0 z'; + }, + + //used for faster lookup + mRound: Math.round + +}); diff --git a/timeside/player/static/timeside/js/timeside.js b/timeside/player/static/timeside/js/timeside.js new file mode 100644 index 0000000..e274783 --- /dev/null +++ b/timeside/player/static/timeside/js/timeside.js @@ -0,0 +1,784 @@ +/* + * Copyright (C) 2007-2011 Parisson + * Copyright (c) 2011 Riccardo Zaccarelli + * Copyright (c) 2010 Olivier Guilyardi + * + * This file is part of TimeSide. + * + * TimeSide is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * TimeSide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimeSide. If not, see . + * + * Authors: Riccardo Zaccarelli + * Olivier Guilyardi + */ + +/** + * Root javascript file for TimesideUI, to be manually included in your web page (see online doc) + */ + +/** + *global variable housing all Timeside variables/mathods/classes: + */ +var Timeside = { + Class:undefined, + classes:{}, + player:undefined, + config: { + /** + *set to true to see debug messages on the console (only error or warning messages shown) + */ + debug: false, + /* + * timeside scripts to be loaded when Timeside.load is called. URL paths are relative to the timeside folder, which + * will be determined according to the src attribute of the timeside.js script path (to be included in the of the page) + */ + timesideScripts: ['rulermarker.js','markermap.js', 'player.js', 'ruler.js'], + //vml config variables. Used only if svg is NOT supported + vml : { + /* + * raphael script to be loaded when Timeside.load is called and svg is not supported. It will be prepended to the + * timesideScripts array defined above in config. URL paths are relative to the timeside folder, which + * will be determined according to the src attribute of the timeside.js script path (to be included in the of the page) + */ + raphaelScript : 'libs/raphael-min.js', + /* + * available attributes which can be converted from css-svg to Raphael attributes (see Raphael.js): + */ + raphaelAttributes : ["clip-rect", "cursor",'fill', "fill-opacity",'opacity', 'stroke', "stroke-dasharray", "stroke-linecap", "stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width", "text-anchor"] + } + }, + utils:{ + /** + * Returns an uniqid by creating the current local time in millisecond + a random number. + * Used for markers in markermap. The method is kind of public in order to be more accessible for other functions + * by calling Timeside.utils.uniqid(), in case it is needed + */ + uniqid : function() { + var d = new Date(); + return new String(d.getTime() + '' + Math.floor(Math.random() * 1000000)).substr(0, 18); + }, + /** + * vml object which will be populated by vml functions to interface timeside and raphael. See timeside.load. + * We could implement functions here for code readability, however, + * we delegate Timeside.load so that if svg is supported memory is free from unused vml methods. + * IN ANY CASE, svg support can be detected anywhere by calling, eg: + * var svg = !Timeside.utils.vml; + */ + vml: undefined, + + /** + * property that will be set to false if soundManager fails to initialize flash + */ + flashFailed : false + } +}; + + +/* Simple JavaScript Inheritance + * By John Resig http://ejohn.org/ + * MIT Licensed. + * (Inspired by base2 and Prototype) + */ + +/* + * In few words: the lightest and most-comprehensive way to implement inhertance and OOP in javascript. Usages can be found below. + * Basically, + * 1) a new Class is instantiated with Class.extend(). This function takes a dictionary + * of properties/methods which will be put IN THE PROTOTYPE of the class, so that each instance will share the same properties/methods + * and the latter don't have to be created for each instance separately. + * 2) If var A = Class.extend({...}) and var B = A.extend({..}), then methods which are found in B will override the same methods in A. + * In this case, the variable this._super inside the overridden methods will refers to the super-method and can thus be called safely. + * Consequently, if a _super property/method is implemented in the extend dictionary, it WILL NOT be accessible + * to the overriding methods of B. Basically, don't use _super as a key of the argument of extend. + * 3) AFTER the prototype has been populated, the init function, if exists, is called. The latter can be seen as a class constructor in java, + * with a substantial difference: when executing the init() method the class prototype has already been populated with all inherited methods. + * Private variable can be declared in the init function, as well as + * relative getters and setters, if needed. Downside is that the privileged getters and setters can’t be put in the prototype, + * i.e. they are created for each instance separately, and the _super keyword does not apply to them. Another issue is the overhead of closures in general (basically, write as less as possible + * in the init function, in particular if the class has to be declared several times) + * Of course, the this._super keyword of methods implemented in the init constructor does not work + * + * EXAMPLE: + * var MyClass = Class.extend({ + * init: function(optionalArray){ //constructor + * this._super(); //!!!ERROR: Class is the base class and does not have a super construcor + * var me = []; //private variable + * this.count = 6; //set the value of the public property defined below + * this.getMe = function(){ //public method + * this._super(); //!!!ERROR: methods defined in the init function don't have acces to _super + * } + * this.alert = function(){ //another public method, !!!WARNING: this will be put in the MyClass scope (NOT in the prototype) + * alert('ok'); + * } + * }, + * count:0, //public property + * alert: function(){ //public method. !!!WARNING: this method will be put in the prototype BEFORE the init is called, + * alert('no'); // so the alert defined above will be actually called + * } + * }); + * var MyClass2 = MyClass.extend({ + * init: function(){ + * this._super(); //call the super constructor + * } + * alert: function(){ //override a method + * this._super(); //call the super method, ie alerts 'no'. WARNING: However, as long as there is an alert written + * //in the init method of the superclass (see above), THAT method will be called + * } + * }); + * + */ + + +(function(parent){ + + var initializing = false, fnTest = /xyz/.test(function(){ + xyz; + }) ? /\b_super\b/ : /.*/; + + /*The xyz test above determines whether the browser can inspect the textual body of a function. + *If it can, you can perform an optimization by only wrapping an overridden method if it + *actually calls this._super() somewhere in its body. + *Since it requires an additional closure and function call overhead to support _super, + *it’s nice to skip that step if it isn’t needed. + */ + + //ADDED BY ME: + // before was: this.Class = function(){}, where this here is the DomWindow + // In order to chose where to attach the Class object, we added the argument parent (see above): + //if parent is undefined, attach Class to the DomWindow (same as before): + if(!parent){ + parent= window; + } + parent.Class = function(){}; + + //from here on, the code is untouched: + // + //We have the base Class implementation (does nothing) + //and we write here below the method extend which returns the Class with inhertance implemented: + // Create a new Class that inherits from this class + parent.Class.extend = function(prop) { + var _super = this.prototype; + + // Instantiate a base class (but only create the instance, + // don't run the init constructor) + initializing = true; + var prototype = new this(); + initializing = false; + + // Copy the properties over onto the new prototype + for (var name in prop) { + // Check if we're overwriting an existing function + prototype[name] = typeof prop[name] == "function" && + typeof _super[name] == "function" && fnTest.test(prop[name]) ? + (function(name, fn){ + return function() { + var tmp = this._super; + + // Add a new ._super() method that is the same method + // but on the super-class + this._super = _super[name]; + + // The method only need to be bound temporarily, so we + // remove it when we're done executing + var ret = fn.apply(this, arguments); + this._super = tmp; + + return ret; + }; + })(name, prop[name]) : + prop[name]; + } + + // The dummy class constructor + function Class() { + // All construction is actually done in the init method + if ( !initializing && this.init ){ + this.init.apply(this, arguments); + } + } + + // Populate our constructed prototype object + Class.prototype = prototype; + + // Enforce the constructor to be what we expect + Class.constructor = Class; + + // And make this class extendable + Class.extend = arguments.callee; + + return Class; + }; +})(Timeside); + + + +//Defining the base TimeClass class. Timeside.classes.[Player, Ruler, MarkerMap...] are typical implementations (see js files) +//Basically we store here static methods which must be accessible in several timside sub-classes +Timeside.classes.TimesideClass = Timeside.Class.extend({ + //init constructor. Define the 'bind' and 'fire' (TODO: rename as 'trigger'?) methods + //we do it in the init function so that we can set a private variable storing all + //listeners. This means we have to re-write all methods + init: function(){ + //the map for listeners. Must be declared in the init as it's private and NOT shared by all instances + //(ie, every instance has its own copy) + this.listenersMap={}; + }, + + cssPrefix : 'ts-', //actually almost uneuseful, still here for backward compatibility with old code (TODO: remove?) + $J : jQuery, //reference to jQuery for faster lookup inside methods + $TU : Timeside.utils, //reference to Timeside variable for faster lookup inside methods + debugging : false, + debug : Timeside.config.debug ? function(message) { + var C = console; + if (C && C.log) { + C.log(message); + } + } : function(message){}, + + /** + * 3 methods defining listeners, events fire and bind (aloing the lines of jQuery.bind, unbind and trigger. + * the only difference is that 'trigger' is 'fire' here). namespaces are allowed as in jQuery + */ + bind : function(eventType, callback, optionalThisArgInCallback){ + if(!callback || typeof callback !== 'function'){ + this.debug('TimesideClass.bind: cannot bind '+eventType+' to callback: the latter is null or not a function'); + return; + } + if(!eventType){ + this.debug('TimesideClass.bind: eventType is empty in bind'); + return; + } + var listenersMap = this.listenersMap; + if(optionalThisArgInCallback){ + var cb = callback; + callback = function(data){ + cb.apply(optionalThisArgInCallback,[data]); + }; + } + + if(listenersMap.hasOwnProperty(eventType)){ + listenersMap[eventType].push(callback); + }else{ + listenersMap[eventType] = [callback]; + } + + var idx = eventType.indexOf('.'); + if(idx <= 0 || idx >= eventType.length-1){ + return; + } + + eventType = eventType.substring(0,idx); + + + if(listenersMap.hasOwnProperty(eventType)){ + listenersMap[eventType].push(callback); + }else{ + listenersMap[eventType] = [callback]; + } + + }, + unbind : function(){ + var listenersMap = this.listenersMap; + var key,keyPlusDot; + if(arguments.length>0){ + key = arguments[0]; + if(listenersMap.hasOwnProperty(key)){ + var callbacks = listenersMap[key]; + var idx = key.indexOf('.'); + if(idx>0 && idx < key.length-1){ + //key is "eventtype.namespace", delete also functions stored in "eventType", if any + var baseKey = key.substring(0,idx); + var baseCallbacks = listenersMap[baseKey]; + if(baseCallbacks){ + for( var i = baseCallbacks.length; i>-1; i--){ + var bc = baseCallbacks[i]; + for( var j = callbacks.length; j>-1; j--){ + if(bc === callbacks[j]){ + baseCallbacks.splice(i,1); + } + } + } + } + }else if(idx<0){ + //key is "eventtype", delete also all functions stored in "eventType.namespace", if any + keyPlusDot = key+'.'; + for(var k in listenersMap){ + if(listenersMap.hasOwnProperty(k) && k.indexOf(keyPlusDot)==0 && k.length > keyPlusDot.length){ + delete listenersMap[k]; + } + } + } + delete listenersMap[key]; + } + }else{ + for(key in listenersMap){ + if(listenersMap.hasOwnProperty(key)){ + delete listenersMap[key]; + } + } + } + }, + fire : function(key, dataArgument){ + var listenersMap = this.listenersMap; + if(!(listenersMap.hasOwnProperty(key))){ + return; + } + if(arguments.length < 2 || !dataArgument){ + dataArgument = {}; + } + var callbacks = listenersMap[key]; + var len = callbacks && callbacks.length ? callbacks.length : 0; + for(var i=0; i0){ + ret[i] = separator+ret[i]; + } + } + return ret.join(""); + } +}); + +/** + * An Array-like implementation that suits the need of Marker mnanagement + * Ruler, MarkerMap and MarkerMapDiv implement this class + */ +Timeside.classes.TimesideArray = Timeside.classes.TimesideClass.extend({ + init: function(optionalArray){ + this._super(); + //here methods that CANNOT be overridden + var me= optionalArray ? optionalArray : []; + //note that this method written here OVERRIDES the same method written outside init in the children!!!! + this.toArray = function(returnACopy){ + if(returnACopy){ + var ret = []; + for(var i=0; i= l){ + return; + } + startInclusive = arg[0]=== undefined ? 0 : arg[0]; + endExclusive = l; + break; + default: + startInclusive = arg[0]=== undefined ? 0 : arg[0]; + endExclusive = arg[1]=== undefined ? l : arg[1]; + } + callback = arg[len-1]; + if(!(callback instanceof Function)){ + this.debug('TimesideClass.each: callback NOT a function!!!'); + return; + } + var me =this.toArray(); + for(var i = startInclusive; i=len)||(to<0 || to>=len)){ + return -1; + } + var elm = me.splice(from,1)[0]; + me.splice(to,0,elm); + + return to; + } +}); + + + +/** + *Main Timeside method to load player (see Timeside online doc) + */ + +Timeside.load =function(config){ + + var $J = jQuery; + var win = window; + var doc = document; + //function to be called onready or onerror: + var loadAll = function() { + + + //get the current script path (this file name is timeside.js, or timeside.js?..., or even timeside.js.pagespeed.blah.js) + var scripts = $J('script'); + var thisScriptPath = ''; + scripts.each(function(i,s){ + var src = $J(s).attr('src'); + if(src) { + var m = src.match(/^([^?]*\/)timeside.js/); + if (m) { + thisScriptPath = m[1]; + } + } + }); + + var ts = Timeside; + var ts_scripts = ts.config.timesideScripts; + //detect SVG support and load Raphael in case. Copied from Raphael code v 1.5.2: + var svg = (win.SVGAngle || doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); + if(!svg){ + //add the raphael path. Raphael will be loaded in Timeside.load (see below) + ts_scripts.splice(0,0,ts.config.vml.raphaelScript); + //populate the vml object with methods to be used in ruler and rulermarker: + + //global private variable: + //map to store each class name to the relative dictionary for raphael attr function (VML only) + var classToRaphaelAttr = {}; + //get the raphael attributes for which a conversion css -> raphael_attribute is possible: + var availableAttrs = ts.config.vml.raphaelAttributes; + //here below we store Raphael paper objects. var paper = Raphael(htmlElement) is the raphel method to build + //a new paper object. Internally, the method builds a div embedding vmls inside htmlElement, retriavable via the + //paper.node property. + //However, calling again var paper = Raphael(htmlElement) does not use the already created paper, + //but creates a new paper with a new paper.node (div). Too bad. The possibility to wrap existing paper node + //into a Raphael paper would be a nice and almost necessary feature, which however is not even + //planned to be implemented according to raphael developers (see raphael forums). + //In case of markers lines, we want to draw a new marker + //on the same raphael paper. Therefore, we store here raphael papers in a map htmlElement -> paper + var raphael_papers = {}; + ts.utils.vml = { + getVmlAttr: function(className){ + + if(classToRaphaelAttr.hasOwnProperty(className)){ + //if(className in classToRaphaelAttr){ + return classToRaphaelAttr[className]; + } + var d = document; + var dottedclassName = className.replace(/^\.*/,'.'); //add a dot if not present + var ssheets = d.styleSheets; + var len = ssheets.length-1; + + var attr = {}; + for(var i=0; i $dir/$app-all.dot +./manage.py graph_models $app > $dir/$app.dot + +sed -i '/#\ /d' $dir/$app-all.dot +sed -i '/#\ /d' $dir/$app.dot + +dot $dir/$app-all.dot -Tpdf -o $dir/$app-all.pdf +dot $dir/$app.dot -Tpdf -o $dir/$app.pdf + +rsync -a $dir/ doc.parisson.com:/var/www/files/doc/$app/diagram/ diff --git a/timeside/server/sandbox/diagram/timeside.dot b/timeside/server/sandbox/diagram/timeside.dot new file mode 100644 index 0000000..2f04481 --- /dev/null +++ b/timeside/server/sandbox/diagram/timeside.dot @@ -0,0 +1,541 @@ +digraph model_graph { + + fontname = "Helvetica" + fontsize = 8 + splines = true + + node [ + fontname = "Helvetica" + fontsize = 8 + shape = "plaintext" + ] + + edge [ + fontname = "Helvetica" + fontsize = 8 + ] + + + + timeside_models_DocBaseResource [label=< + + + + + + + + + + + + + +
+ + DocBaseResource
<BaseResource> +
+ date_added + + DateTimeField +
+ date_modified + + DateTimeField +
+ description + + TextField +
+ title + + CharField +
+ uuid + + CharField +
+ >] + + timeside_models_BaseResource [label=< + + + + + + + + + +
+ + BaseResource +
+ date_added + + DateTimeField +
+ date_modified + + DateTimeField +
+ uuid + + CharField +
+ >] + + timeside_models_Selection [label=< + + + + + + + + + + + + + + + + + +
+ + Selection
<DocBaseResource> +
+ id + + AutoField +
+ author + + ForeignKey (id) +
+ date_added + + DateTimeField +
+ date_modified + + DateTimeField +
+ description + + TextField +
+ title + + CharField +
+ uuid + + CharField +
+ >] + + timeside_models_Item [label=< + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + Item
<DocBaseResource> +
+ id + + AutoField +
+ author + + ForeignKey (id) +
+ date_added + + DateTimeField +
+ date_modified + + DateTimeField +
+ description + + TextField +
+ file + + FileField +
+ hdf5 + + FileField +
+ lock + + BooleanField +
+ mime_type + + CharField +
+ sha1 + + CharField +
+ title + + CharField +
+ url + + URLField +
+ uuid + + CharField +
+ >] + + timeside_models_Experience [label=< + + + + + + + + + + + + + + + + + + + +
+ + Experience
<DocBaseResource> +
+ id + + AutoField +
+ author + + ForeignKey (id) +
+ date_added + + DateTimeField +
+ date_modified + + DateTimeField +
+ description + + TextField +
+ is_public + + BooleanField +
+ title + + CharField +
+ uuid + + CharField +
+ >] + + timeside_models_Processor [label=< + + + + + + + + + +
+ + Processor +
+ id + + AutoField +
+ pid + + CharField +
+ version + + CharField +
+ >] + + timeside_models_Preset [label=< + + + + + + + + + + + +
+ + Preset +
+ id + + AutoField +
+ processor + + ForeignKey (id) +
+ is_public + + BooleanField +
+ parameters + + TextField +
+ >] + + timeside_models_Result [label=< + + + + + + + + + + + + + + + + + + + + + + + +
+ + Result
<BaseResource> +
+ id + + AutoField +
+ item + + ForeignKey (id) +
+ preset + + ForeignKey (id) +
+ date_added + + DateTimeField +
+ date_modified + + DateTimeField +
+ file + + FileField +
+ hdf5 + + FileField +
+ mime_type + + CharField +
+ status + + IntegerField +
+ uuid + + CharField +
+ >] + + timeside_models_Task [label=< + + + + + + + + + + + + + +
+ + Task +
+ id + + AutoField +
+ author + + ForeignKey (id) +
+ experience + + ForeignKey (id) +
+ selection + + ForeignKey (id) +
+ status + + IntegerField +
+ >] + + + + + + timeside_models_DocBaseResource -> timeside_models_BaseResource + [label="abstract\ninheritance"] [arrowhead=empty, arrowtail=none, dir=both]; + django_contrib_auth_models_User [label=< + + +
+ User +
+ >] + timeside_models_Selection -> django_contrib_auth_models_User + [label="author (selections)"] [arrowhead=none, arrowtail=dot, dir=both]; + + timeside_models_Selection -> timeside_models_Item + [label="items (selections)"] [arrowhead=dot arrowtail=dot, dir=both]; + + timeside_models_Selection -> timeside_models_Selection + [label="selections (other_selections)"] [arrowhead=dot arrowtail=dot, dir=both]; + + timeside_models_Selection -> timeside_models_DocBaseResource + [label="abstract\ninheritance"] [arrowhead=empty, arrowtail=none, dir=both]; + django_contrib_auth_models_User [label=< + + +
+ User +
+ >] + timeside_models_Item -> django_contrib_auth_models_User + [label="author (items)"] [arrowhead=none, arrowtail=dot, dir=both]; + + timeside_models_Item -> timeside_models_DocBaseResource + [label="abstract\ninheritance"] [arrowhead=empty, arrowtail=none, dir=both]; + django_contrib_auth_models_User [label=< + + +
+ User +
+ >] + timeside_models_Experience -> django_contrib_auth_models_User + [label="author (experiences)"] [arrowhead=none, arrowtail=dot, dir=both]; + + timeside_models_Experience -> timeside_models_Preset + [label="presets (experiences)"] [arrowhead=dot arrowtail=dot, dir=both]; + + timeside_models_Experience -> timeside_models_Experience + [label="experiences (other_experiences)"] [arrowhead=dot arrowtail=dot, dir=both]; + + timeside_models_Experience -> timeside_models_DocBaseResource + [label="abstract\ninheritance"] [arrowhead=empty, arrowtail=none, dir=both]; + + timeside_models_Preset -> timeside_models_Processor + [label="processor (preset)"] [arrowhead=none, arrowtail=dot, dir=both]; + + timeside_models_Result -> timeside_models_Item + [label="item (results)"] [arrowhead=none, arrowtail=dot, dir=both]; + + timeside_models_Result -> timeside_models_Preset + [label="preset (results)"] [arrowhead=none, arrowtail=dot, dir=both]; + + timeside_models_Result -> timeside_models_BaseResource + [label="abstract\ninheritance"] [arrowhead=empty, arrowtail=none, dir=both]; + + timeside_models_Task -> timeside_models_Experience + [label="experience (task)"] [arrowhead=none, arrowtail=dot, dir=both]; + + timeside_models_Task -> timeside_models_Selection + [label="selection (task)"] [arrowhead=none, arrowtail=dot, dir=both]; + django_contrib_auth_models_User [label=< + + +
+ User +
+ >] + timeside_models_Task -> django_contrib_auth_models_User + [label="author (tasks)"] [arrowhead=none, arrowtail=dot, dir=both]; + +} + diff --git a/timeside/server/sandbox/diagram/timeside.pdf b/timeside/server/sandbox/diagram/timeside.pdf new file mode 100644 index 0000000..9f72bae Binary files /dev/null and b/timeside/server/sandbox/diagram/timeside.pdf differ diff --git a/timeside/server/sandbox/manage.py b/timeside/server/sandbox/manage.py new file mode 100755 index 0000000..f9726f9 --- /dev/null +++ b/timeside/server/sandbox/manage.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/timeside/server/sandbox/settings.py b/timeside/server/sandbox/settings.py new file mode 100644 index 0000000..2318f5f --- /dev/null +++ b/timeside/server/sandbox/settings.py @@ -0,0 +1,170 @@ +# Django settings for server project. + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +import os, sys +sys.dont_write_bytecode = True + +ADMINS = ( + # ('Your Name', 'your_email@example.com'), +) + +MANAGERS = ADMINS + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. + 'NAME': 'timeside.sql', # Or path to database file if using sqlite3. + 'USER': '', # Not used with sqlite3. + 'PASSWORD': '', # Not used with sqlite3. + 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. + 'PORT': '', # Set to empty string for default. Not used with sqlite3. + } +} + +# Hosts/domain names that are valid for this site; required if DEBUG is False +# See https://docs.djangoproject.com/en/1.4/ref/settings/#allowed-hosts +ALLOWED_HOSTS = [] + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# In a Windows environment this must be set to your system time zone. +TIME_ZONE = 'America/Chicago' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# If you set this to False, Django will not format dates, numbers and +# calendars according to the current locale. +USE_L10N = True + +# If you set this to False, Django will not use timezone-aware datetimes. +USE_TZ = True + +# Full filesystem path to the project. +PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) + +# Absolute filesystem path to the directory that will hold user-uploaded files. +# Example: "/home/media/media.lawrence.com/media/" +MEDIA_ROOT = PROJECT_ROOT + '/media/' + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash. +# Examples: "http://media.lawrence.com/media/", "http://example.com/media/" +MEDIA_URL = '' + +# Absolute path to the directory static files should be collected to. +# Don't put anything in this directory yourself; store your static files +# in apps' "static/" subdirectories and in STATICFILES_DIRS. +# Example: "/home/media/media.lawrence.com/static/" +STATIC_ROOT = '' + +# URL prefix for static files. +# Example: "http://media.lawrence.com/static/" +STATIC_URL = '/static/' + +# Additional locations of static files +STATICFILES_DIRS = ( + # Put strings here, like "/home/html/static" or "C:/www/django/static". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. +) + +# List of finder classes that know how to find static files in +# various locations. +STATICFILES_FINDERS = ( + 'django.contrib.staticfiles.finders.FileSystemFinder', + 'django.contrib.staticfiles.finders.AppDirectoriesFinder', +# 'django.contrib.staticfiles.finders.DefaultStorageFinder', +) + +# Make this unique, and don't share it with anybody. +SECRET_KEY = '5%z&a3r@t0=xr2eaio+400qf-32$b5zp897pr*wh5i^s4(-+3(' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', +# 'django.template.loaders.eggs.Loader', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + # Uncomment the next line for simple clickjacking protection: + # 'django.middleware.clickjacking.XFrameOptionsMiddleware', +) + +ROOT_URLCONF = 'urls' + +# Python dotted path to the WSGI application used by Django's runserver. +WSGI_APPLICATION = 'wsgi.application' + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. +) + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.messages', + 'django.contrib.staticfiles', + # Uncomment the next line to enable the admin: + 'django.contrib.admin', + # Uncomment the next line to enable admin documentation: + # 'django.contrib.admindocs', + 'django_extensions', + 'south', + # 'timeside', + 'timeside.server', + 'timeside.player', + 'rest_framework', +) + +# A sample logging configuration. The only tangible logging +# performed by this configuration is to send an email to +# the site admins on every HTTP 500 error when DEBUG=False. +# See http://docs.djangoproject.com/en/dev/topics/logging for +# more details on how to customize your logging configuration. +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'filters': { + 'require_debug_false': { + '()': 'django.utils.log.RequireDebugFalse' + } + }, + 'handlers': { + 'mail_admins': { + 'level': 'ERROR', + 'filters': ['require_debug_false'], + 'class': 'django.utils.log.AdminEmailHandler' + } + }, + 'loggers': { + 'django.request': { + 'handlers': ['mail_admins'], + 'level': 'ERROR', + 'propagate': True, + }, + } +} + +REST_FRAMEWORK = { +} \ No newline at end of file diff --git a/timeside/server/sandbox/update_schema.sh b/timeside/server/sandbox/update_schema.sh new file mode 100755 index 0000000..82d28e9 --- /dev/null +++ b/timeside/server/sandbox/update_schema.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +./manage.py schemamigration timeside --auto +./manage.py migrate timeside + diff --git a/timeside/server/sandbox/urls.py b/timeside/server/sandbox/urls.py new file mode 100644 index 0000000..2224d24 --- /dev/null +++ b/timeside/server/sandbox/urls.py @@ -0,0 +1,20 @@ +from django.conf.urls import patterns, include, url + +# Uncomment the next two lines to enable the admin: +from django.contrib import admin +admin.autodiscover() + +urlpatterns = patterns('', + + url(r'^', include('timeside.server.urls')), + + # Examples: + # url(r'^$', 'server.views.home', name='home'), + # url(r'^server/', include('server.foo.urls')), + + # Uncomment the admin/doc line below to enable admin documentation: + # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), + + # Uncomment the next line to enable the admin: + url(r'^admin/', include(admin.site.urls)), +) diff --git a/timeside/server/sandbox/wsgi.py b/timeside/server/sandbox/wsgi.py new file mode 100644 index 0000000..c4d2c74 --- /dev/null +++ b/timeside/server/sandbox/wsgi.py @@ -0,0 +1,28 @@ +""" +WSGI config for server project. + +This module contains the WSGI application used by Django's development server +and any production WSGI deployments. It should expose a module-level variable +named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover +this application via the ``WSGI_APPLICATION`` setting. + +Usually you will have the standard Django WSGI application here, but it also +might make sense to replace the whole Django WSGI application with a custom one +that later delegates to the Django one. For example, you could introduce WSGI +middleware here, or combine a Django application with an application of another +framework. + +""" +import os + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sandbox.settings") + +# This application object is used by any WSGI server configured to use this +# file. This includes Django's development server, if the WSGI_APPLICATION +# setting points here. +from django.core.wsgi import get_wsgi_application +application = get_wsgi_application() + +# Apply WSGI middleware here. +# from helloworld.wsgi import HelloWorldApplication +# application = HelloWorldApplication(application) diff --git a/timeside/server/serializers.py b/timeside/server/serializers.py new file mode 100644 index 0000000..5814f11 --- /dev/null +++ b/timeside/server/serializers.py @@ -0,0 +1,61 @@ +from timeside.server.models import * +from rest_framework import serializers +import django.db.models +from django.contrib.auth.models import User + + +class SelectionSerializer(serializers.ModelSerializer): + + class Meta: + model = Selection + fields = ('id', 'items', 'selections', 'author') + + +class ItemSerializer(serializers.ModelSerializer): + + class Meta: + model = Item + fields = ('id', 'title', 'file', 'mime_type', 'author') + + +class ExperienceSerializer(serializers.ModelSerializer): + + class Meta: + model = Experience + fields = ('id', 'presets', 'experiences', 'is_public', 'author') + + +class ProcessorSerializer(serializers.ModelSerializer): + + class Meta: + model = Processor + fields = ('id', 'pid', 'version') + + +class ResultSerializer(serializers.ModelSerializer): + + class Meta: + model = Result + fields = ('id', 'item', 'preset', 'status', 'hdf5', 'file') + + +class PresetSerializer(serializers.ModelSerializer): + + class Meta: + model = Preset + fields = ('id', 'processor', 'parameters', 'is_public') + + +class TaskSerializer(serializers.ModelSerializer): + + class Meta: + model = Task + fields = ('id', 'experience', 'selection', 'status', 'author') + + +class UserSerializer(serializers.ModelSerializer): + + class Meta: + model = User + + diff --git a/timeside/server/templates/timeside/base.html b/timeside/server/templates/timeside/base.html new file mode 100644 index 0000000..372c79f --- /dev/null +++ b/timeside/server/templates/timeside/base.html @@ -0,0 +1,40 @@ + +{% load i18n %} +{% get_current_language as LANGUAGE_CODE %} +{% get_available_languages as LANGUAGES %} + + + + + + +{% block stylesheets %} +{% endblock %} + +{% block extra_stylesheets %}{% endblock %} + +{% block javascript %} + + + + +{% endblock %} + +{% block extra_javascript %}{% endblock %} + + + +{% block layout %} +
+ +{% block content %} +{% endblock content %} + +
+{% endblock layout %} + +{% block analytics %} +{% endblock analytics %} + + + diff --git a/timeside/server/templates/timeside/index.html b/timeside/server/templates/timeside/index.html new file mode 100644 index 0000000..9e67fd7 --- /dev/null +++ b/timeside/server/templates/timeside/index.html @@ -0,0 +1,12 @@ +{% extends "timeside/base.html" %} +{% load i18n %} + +{% block content %} + +
    + {% for item in object_list %} +
  • {{ item.title }}
  • + {% endfor %} +
+ +{% endblock content %} diff --git a/timeside/server/urls.py b/timeside/server/urls.py new file mode 100644 index 0000000..3c10efe --- /dev/null +++ b/timeside/server/urls.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +from django.conf.urls import patterns, include, url +from django.contrib import admin +from rest_framework import routers +from timeside.server import views + +admin.autodiscover() + +api_router = routers.DefaultRouter() +api_router.register(r'selections', views.SelectionViewSet) +api_router.register(r'items', views.ItemViewSet) +api_router.register(r'experiences', views.ExperienceViewSet) +api_router.register(r'processors', views.ProcessorViewSet) +api_router.register(r'results', views.ResultViewSet) +api_router.register(r'presets', views.PresetViewSet) +api_router.register(r'tasks', views.TaskViewSet) +api_router.register(r'users', views.UserViewSet) + +urlpatterns = patterns('', + url(r'^admin/', include(admin.site.urls)), + url(r'^api/', include(api_router.urls)), + url(r'^$', views.IndexView.as_view(), name="timeside-index"), + url(r'^results/(?P.*)/json/$', views.ResultAnalyzerView.as_view(), name="timeside-result-json"), +) diff --git a/timeside/server/views.py b/timeside/server/views.py new file mode 100644 index 0000000..d4cd7f7 --- /dev/null +++ b/timeside/server/views.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- + +from django.views.generic import * +from django.http import HttpResponse, HttpResponseRedirect + +from rest_framework import viewsets + +import timeside +from timeside.server.models import * +from timeside.server.serializers import * + + +class SelectionViewSet(viewsets.ModelViewSet): + + model = Selection + serializer_class = SelectionSerializer + + +class ItemViewSet(viewsets.ModelViewSet): + + model = Item + serializer_class = ItemSerializer + + +class ExperienceViewSet(viewsets.ModelViewSet): + + model = Experience + serializer_class = ExperienceSerializer + + +class ProcessorViewSet(viewsets.ModelViewSet): + + model = Processor + serializer_class = ProcessorSerializer + + +class ResultViewSet(viewsets.ModelViewSet): + + model = Result + serializer_class = ResultSerializer + + +class PresetViewSet(viewsets.ModelViewSet): + + model = Preset + serializer_class = PresetSerializer + + +class TaskViewSet(viewsets.ModelViewSet): + + model = Task + serializer_class = TaskSerializer + + +class UserViewSet(viewsets.ModelViewSet): + + model = User + serializer_class = UserSerializer + + +class IndexView(ListView): + + model = Item + template_name='timeside/index.html' + + def get_context_data(self, **kwargs): + context = super(IndexView, self).get_context_data(**kwargs) + return context + + def dispatch(self, *args, **kwargs): + return super(IndexView, self).dispatch(*args, **kwargs) + + +class ResultAnalyzerView(View): + + model = Result + + def get(self, request, *args, **kwargs): + result = Result.objects.get(pk=kwargs['pk']) + container = AnalyzerResultContainer() + return HttpResponse(container.from_hdf5(result.hdf5.path).to_json(), mimetype='application/json') + \ No newline at end of file diff --git a/timeside/static/timeside/README.rst b/timeside/static/timeside/README.rst deleted file mode 100644 index 241b18b..0000000 --- a/timeside/static/timeside/README.rst +++ /dev/null @@ -1,30 +0,0 @@ -=================== -TimeSide UI -=================== - -Please refer to http://code.google.com/p/timeside/wiki/UiGuide for an exhaustive guide. - -Provides -========= - -* SoundManager 2 >= 2.97 : http://www.schillmania.com/projects/soundmanager2 -* jQuery => 1.6 : http://www.jquery.com -* Raphael (ADDED AUTOMATICALLY, DO NOT ADD YOURSELF) => 1.52 http://raphaeljs.com/ - - -Licensing -========= - -Copyright (c) 2009-2011 Parisson SARL - -Copyright (c) 2008-2009 Samalyse - -Copyright (c) 2011 Riccardo Zaccarelli - -Authors: - - * Riccardo Zaccarelli - * Olivier Guilyardi - -TimeSide is released under the terms of the GNU General Public License -version 2. Please see the LICENSE file for details. diff --git a/timeside/static/timeside/js/libs/jquery-1.6.min.js b/timeside/static/timeside/js/libs/jquery-1.6.min.js deleted file mode 100644 index c72011d..0000000 --- a/timeside/static/timeside/js/libs/jquery-1.6.min.js +++ /dev/null @@ -1,16 +0,0 @@ -/*! - * jQuery JavaScript Library v1.6 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Mon May 2 13:50:00 2011 -0400 - */ -(function(a,b){function cw(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function ct(a){if(!ch[a]){var b=f("<"+a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d===""){ci||(ci=c.createElement("iframe"),ci.frameBorder=ci.width=ci.height=0),c.body.appendChild(ci);if(!cj||!ci.createElement)cj=(ci.contentWindow||ci.contentDocument).document,cj.write("");b=cj.createElement(a),cj.body.appendChild(b),d=f.css(b,"display"),c.body.removeChild(ci)}ch[a]=d}return ch[a]}function cs(a,b){var c={};f.each(cn.concat.apply([],cn.slice(0,b)),function(){c[this]=a});return c}function cr(){co=b}function cq(){setTimeout(cr,0);return co=f.now()}function cg(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function cf(){try{return new a.XMLHttpRequest}catch(b){}}function b_(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(a,b){return(a&&a!=="*"?a+".":"")+b.replace(z,"`").replace(A,"&")}function M(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;ic)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function K(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function E(){return!0}function D(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){name="data-"+c.replace(j,"$1-$2").toLowerCase(),d=a.getAttribute(name);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(e){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function H(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(H,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=d.userAgent,x,y,z,A=Object.prototype.toString,B=Object.prototype.hasOwnProperty,C=Array.prototype.push,D=Array.prototype.slice,E=String.prototype.trim,F=Array.prototype.indexOf,G={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?g=[null,a,null]:g=i.exec(a);if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6",length:0,size:function(){return this.length},toArray:function(){return D.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?C.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),y.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(D.apply(this,arguments),"slice",D.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:C,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;y.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!y){y=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",z,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",z),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&H()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):G[A.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!B.call(a,"constructor")&&!B.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||B.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c
a",b=a.getElementsByTagName("*"),d=a.getElementsByTagName("a")[0];if(!b||!b.length||!d)return{};e=c.createElement("select"),f=e.appendChild(c.createElement("option")),g=a.getElementsByTagName("input")[0],i={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.55$/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:g.value==="on",optSelected:f.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},g.checked=!0,i.noCloneChecked=g.cloneNode(!0).checked,e.disabled=!0,i.optDisabled=!f.disabled;try{delete a.test}catch(r){i.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function click(){i.noCloneEvent=!1,a.detachEvent("onclick",click)}),a.cloneNode(!0).fireEvent("onclick")),g=c.createElement("input"),g.value="t",g.setAttribute("type","radio"),i.radioValue=g.value==="t",g.setAttribute("checked","checked"),a.appendChild(g),j=c.createDocumentFragment(),j.appendChild(a.firstChild),i.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",k=c.createElement("body"),l={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"};for(p in l)k.style[p]=l[p];k.appendChild(a),c.documentElement.appendChild(k),i.appendChecked=g.checked,i.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,i.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
",i.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
t
",m=a.getElementsByTagName("td"),q=m[0].offsetHeight===0,m[0].style.display="",m[1].style.display="none",i.reliableHiddenOffsets=q&&m[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(h=c.createElement("div"),h.style.width="0",h.style.marginRight="0",a.appendChild(h),i.reliableMarginRight=(parseInt(c.defaultView.getComputedStyle(h,null).marginRight,10)||0)===0),k.innerHTML="",c.documentElement.removeChild(k);if(a.attachEvent)for(p in{submit:1,change:1,focusin:1})o="on"+p,q=o in a,q||(a.setAttribute(o,"return;"),q=typeof a[o]=="function"),i[p+"Bubbles"]=q;return i}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[c]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[c]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;return(e.value||"").replace(p,"")}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||"set"in c&&c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b=a.selectedIndex,c=[],d=a.options,e=a.type==="select-one";if(b<0)return null;for(var g=e?b:0,h=e?b+1:d.length;g=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex",readonly:"readOnly"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);var h,i,j=g!==1||!f.isXMLDoc(a);c=j&&f.attrFix[c]||c,i=f.attrHooks[c]||(v&&(f.nodeName(a,"form")||u.test(c))?v:b);if(d!==b){if(d===null||d===!1&&!t.test(c)){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;d===!0&&!t.test(c)&&(d=c),a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j)return i.get(a,c);h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.getAttribute("value");a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}}},propFix:{},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);c=i&&f.propFix[c]||c,h=f.propHooks[c];return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),f.support.getSetAttribute||(f.attrFix=f.extend(f.attrFix,{"for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder"}),v=f.attrHooks.name=f.attrHooks.value=f.valHooks.button={get:function(a,c){var d;if(c==="value"&&!f.nodeName(a,"button"))return a.getAttribute(c);d=a.getAttributeNode(c);return d&&d.specified?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var w=Object.prototype.hasOwnProperty,x=/\.(.*)$/,y=/^(?:textarea|input|select)$/i,z=/\./g,A=/ /g,B=/[^\w\s.|`]/g,C=function(a){return a.replace(B,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=D;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=D);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),C).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},J=function J(a){var c=a.target,d,e;if(!!y.test(c.nodeName)&&!c.readOnly){d=f._data(c,"_change_data"),e=I(c),(a.type!=="focusout"||c.type!=="radio")&&f._data(c,"_change_data",e);if(d===b||e===d)return;if(d!=null||e)a.type="change",a.liveFired=b,f.event.trigger(a,arguments[1],c)}};f.event.special.change={filters:{focusout:J,beforedeactivate:J,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&J.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&J.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",I(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in H)f.event.add(this,c+".specialChange",H[c]);return y.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return y.test(this.nodeName)}},H=f.event.special.change.filters,H.focus=H.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){return a.nodeName.toLowerCase()==="input"&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(h=g;h0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=T.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var X=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,Z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,$=/<([\w:]+)/,_=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};be.optgroup=be.option,be.tbody=be.tfoot=be.colgroup=be.caption=be.thead,be.th=be.td,f.support.htmlSerialize||(be._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(X,""):null;if(typeof a=="string"&&!bb.test(a)&&(f.support.leadingWhitespace||!Y.test(a))&&!be[($.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Z,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bh(a,d),e=bi(a),g=bi(d);for(h=0;e[h];++h)bh(e[h],g[h])}if(b){bg(a,d);if(c){e=bi(a),g=bi(d);for(h=0;e[h];++h)bg(e[h],g[h])}}return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[];for(var i=0,j;(j=a[i])!=null;i++){typeof j=="number"&&(j+="");if(!j)continue;if(typeof j=="string")if(!ba.test(j))j=b.createTextNode(j);else{j=j.replace(Z,"<$1>");var k=($.exec(j)||["",""])[1].toLowerCase(),l=be[k]||be._default,m=l[0],n=b.createElement("div");n.innerHTML=l[1]+j+l[2];while(m--)n=n.lastChild;if(!f.support.tbody){var o=_.test(j),p=k==="table"&&!o?n.firstChild&&n.firstChild.childNodes:l[1]===""&&!o?n.childNodes:[];for(var q=p.length-1;q>=0;--q)f.nodeName(p[q],"tbody")&&!p[q].childNodes.length&&p[q].parentNode.removeChild(p[q])}!f.support.leadingWhitespace&&Y.test(j)&&n.insertBefore(b.createTextNode(Y.exec(j)[0]),n.firstChild),j=n.childNodes}var r;if(!f.support.appendChecked)if(j[0]&&typeof (r=j.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bn.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bm.test(g)?g.replace(bm,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bx(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(by=function(a,c){var d,e,g;c=c.replace(bp,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bz=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bq.test(d)&&br.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bx=by||bz,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV;try{bU=e.href}catch(bW){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bX(bS),ajaxTransport:bX(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?b$(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=b_(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bY(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bY(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bZ(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var ca=f.now(),cb=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+ca++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cb.test(b.url)||e&&cb.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cb,l),b.url===j&&(e&&(k=k.replace(cb,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cc=a.ActiveXObject?function(){for(var a in ce)ce[a](0,1)}:!1,cd=0,ce;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cf()||cg()}:cf,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cc&&delete ce[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cd,cc&&(ce||(ce={},f(a).unload(cc)),ce[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ch={},ci,cj,ck=/^(?:toggle|show|hide)$/,cl=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cm,cn=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],co,cp=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cs("show",3),a,b,c);for(var g=0,h=this.length;g=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a=f.timers,b=a.length;while(b--)a[b]()||a.splice(b,1);a.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cm),cm=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cu=/^t(?:able|d|h)$/i,cv=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cw(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);f.offset.initialize();var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.offset.doesNotAddBorder&&(!f.offset.doesAddBorderForTableAndCells||!cu.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={initialize:function(){var a=c.body,b=c.createElement("div"),d,e,g,h,i=parseFloat(f.css(a,"marginTop"))||0,j="
";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cv.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cv.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cw(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cw(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){return this[0]?parseFloat(f.css(this[0],d,"padding")):null},f.fn["outer"+c]=function(a){return this[0]?parseFloat(f.css(this[0],d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window); \ No newline at end of file diff --git a/timeside/static/timeside/js/libs/raphael-min.js b/timeside/static/timeside/js/libs/raphael-min.js deleted file mode 100644 index e5e7126..0000000 --- a/timeside/static/timeside/js/libs/raphael-min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Raphael 1.5.2 - JavaScript Vector Library - * - * Copyright (c) 2010 Dmitry Baranovskiy (http://raphaeljs.com) - * Licensed under the MIT (http://raphaeljs.com/license.html) license. - */ -(function(){function a(){if(a.is(arguments[0],G)){var b=arguments[0],d=bV[m](a,b.splice(0,3+a.is(b[0],E))),e=d.set();for(var g=0,h=b[w];g";bg=bf.firstChild;bg.style.behavior="url(#default#VML)";if(!(bg&&typeof bg.adj=="object"))return a.type=null;bf=null}a.svg=!(a.vml=a.type=="VML");j[e]=a[e];k=j[e];a._id=0;a._oid=0;a.fn={};a.is=function(a,b){b=x.call(b);if(b=="finite")return!O[f](+a);return b=="null"&&a===null||b==typeof a||b=="object"&&a===Object(a)||b=="array"&&Array.isArray&&Array.isArray(a)||J.call(a).slice(8,-1).toLowerCase()==b};a.angle=function(b,c,d,e,f,g){{if(f==null){var h=b-d,i=c-e;if(!h&&!i)return 0;return((h<0)*180+y.atan(-i/-h)*180/D+360)%360}return a.angle(b,c,f,g)-a.angle(d,e,f,g)}};a.rad=function(a){return a%360*D/180};a.deg=function(a){return a*180/D%360};a.snapTo=function(b,c,d){d=a.is(d,"finite")?d:10;if(a.is(b,G)){var e=b.length;while(e--)if(B(b[e]-c)<=d)return b[e]}else{b=+b;var f=c%b;if(fb-d)return c-f+b}return c};function bh(){var a=[],b=0;for(;b<32;b++)a[b]=(~(~(y.random()*16)))[H](16);a[12]=4;a[16]=(a[16]&3|8)[H](16);return"r-"+a[v]("")}a.setWindow=function(a){h=a;g=h.document};var bi=function(b){if(a.vml){var c=/^\s+|\s+$/g,d;try{var e=new ActiveXObject("htmlfile");e.write("");e.close();d=e.body}catch(a){d=createPopup().document.body}var f=d.createTextRange();bi=bm(function(a){try{d.style.color=r(a)[Y](c,p);var b=f.queryCommandValue("ForeColor");b=(b&255)<<16|b&65280|(b&16711680)>>>16;return"#"+("000000"+b[H](16)).slice(-6)}catch(a){return"none"}})}else{var h=g.createElement("i");h.title="Raphaël Colour Picker";h.style.display="none";g.body[l](h);bi=bm(function(a){h.style.color=a;return g.defaultView.getComputedStyle(h,p).getPropertyValue("color")})}return bi(b)},bj=function(){return"hsb("+[this.h,this.s,this.b]+")"},bk=function(){return"hsl("+[this.h,this.s,this.l]+")"},bl=function(){return this.hex};a.hsb2rgb=function(b,c,d,e){if(a.is(b,"object")&&"h"in b&&"s"in b&&"b"in b){d=b.b;c=b.s;b=b.h;e=b.o}return a.hsl2rgb(b,c,d/2,e)};a.hsl2rgb=function(b,c,d,e){if(a.is(b,"object")&&"h"in b&&"s"in b&&"l"in b){d=b.l;c=b.s;b=b.h}if(b>1||c>1||d>1){b/=360;c/=100;d/=100}var f={},g=["r","g","b"],h,i,j,k,l,m;if(c){d<0.5?h=d*(1+c):h=d+c-d*c;i=2*d-h;for(var n=0;n<3;n++){j=b+1/3*-(n-1);j<0&&j++;j>1&&j--;j*6<1?f[g[n]]=i+(h-i)*6*j:j*2<1?f[g[n]]=h:j*3<2?f[g[n]]=i+(h-i)*(2/3-j)*6:f[g[n]]=i}}else f={r:d,g:d,b:d};f.r*=255;f.g*=255;f.b*=255;f.hex="#"+(16777216|f.b|f.g<<8|f.r<<16).toString(16).slice(1);a.is(e,"finite")&&(f.opacity=e);f.toString=bl;return f};a.rgb2hsb=function(b,c,d){if(c==null&&a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b){d=b.b;c=b.g;b=b.r}if(c==null&&a.is(b,F)){var e=a.getRGB(b);b=e.r;c=e.g;d=e.b}if(b>1||c>1||d>1){b/=255;c/=255;d/=255}var f=z(b,c,d),g=A(b,c,d),h,i,j=f;{if(g==f)return{h:0,s:0,b:f,toString:bj};var k=f-g;i=k/f;b==f?h=(c-d)/k:c==f?h=2+(d-b)/k:h=4+(b-c)/k;h/=6;h<0&&h++;h>1&&h--}return{h:h,s:i,b:j,toString:bj}};a.rgb2hsl=function(b,c,d){if(c==null&&a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b){d=b.b;c=b.g;b=b.r}if(c==null&&a.is(b,F)){var e=a.getRGB(b);b=e.r;c=e.g;d=e.b}if(b>1||c>1||d>1){b/=255;c/=255;d/=255}var f=z(b,c,d),g=A(b,c,d),h,i,j=(f+g)/2,k;if(g==f)k={h:0,s:0,l:j};else{var l=f-g;i=j<0.5?l/(f+g):l/(2-f-g);b==f?h=(c-d)/l:c==f?h=2+(d-b)/l:h=4+(b-c)/l;h/=6;h<0&&h++;h>1&&h--;k={h:h,s:i,l:j}}k.toString=bk;return k};a._path2string=function(){return this.join(",")[Y](ba,"$1")};function bm(a,b,c){function d(){var g=Array[e].slice.call(arguments,0),h=g[v]("►"),i=d.cache=d.cache||{},j=d.count=d.count||[];if(i[f](h))return c?c(i[h]):i[h];j[w]>=1000&&delete i[j.shift()];j[L](h);i[h]=a[m](b,g);return c?c(i[h]):i[h]}return d}a.getRGB=bm(function(b){if(!b||!(!((b=r(b)).indexOf("-")+1)))return{r:-1,g:-1,b:-1,hex:"none",error:1};if(b=="none")return{r:-1,g:-1,b:-1,hex:"none"};!(_[f](b.toLowerCase().substring(0,2))||b.charAt()=="#")&&(b=bi(b));var c,d,e,g,h,i,j,k=b.match(N);if(k){if(k[2]){g=T(k[2].substring(5),16);e=T(k[2].substring(3,5),16);d=T(k[2].substring(1,3),16)}if(k[3]){g=T((i=k[3].charAt(3))+i,16);e=T((i=k[3].charAt(2))+i,16);d=T((i=k[3].charAt(1))+i,16)}if(k[4]){j=k[4][s]($);d=S(j[0]);j[0].slice(-1)=="%"&&(d*=2.55);e=S(j[1]);j[1].slice(-1)=="%"&&(e*=2.55);g=S(j[2]);j[2].slice(-1)=="%"&&(g*=2.55);k[1].toLowerCase().slice(0,4)=="rgba"&&(h=S(j[3]));j[3]&&j[3].slice(-1)=="%"&&(h/=100)}if(k[5]){j=k[5][s]($);d=S(j[0]);j[0].slice(-1)=="%"&&(d*=2.55);e=S(j[1]);j[1].slice(-1)=="%"&&(e*=2.55);g=S(j[2]);j[2].slice(-1)=="%"&&(g*=2.55);(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360);k[1].toLowerCase().slice(0,4)=="hsba"&&(h=S(j[3]));j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsb2rgb(d,e,g,h)}if(k[6]){j=k[6][s]($);d=S(j[0]);j[0].slice(-1)=="%"&&(d*=2.55);e=S(j[1]);j[1].slice(-1)=="%"&&(e*=2.55);g=S(j[2]);j[2].slice(-1)=="%"&&(g*=2.55);(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360);k[1].toLowerCase().slice(0,4)=="hsla"&&(h=S(j[3]));j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsl2rgb(d,e,g,h)}k={r:d,g:e,b:g};k.hex="#"+(16777216|g|e<<8|d<<16).toString(16).slice(1);a.is(h,"finite")&&(k.opacity=h);return k}return{r:-1,g:-1,b:-1,hex:"none",error:1}},a);a.getColor=function(a){var b=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||0.75},c=this.hsb2rgb(b.h,b.s,b.b);b.h+=0.075;if(b.h>1){b.h=0;b.s-=0.2;b.s<=0&&(this.getColor.start={h:0,s:1,b:b.b})}return c.hex};a.getColor.reset=function(){delete this.start};a.parsePathString=bm(function(b){if(!b)return null;var c={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},d=[];a.is(b,G)&&a.is(b[0],G)&&(d=bo(b));d[w]||r(b)[Y](bb,function(a,b,e){var f=[],g=x.call(b);e[Y](bc,function(a,b){b&&f[L](+b)});if(g=="m"&&f[w]>2){d[L]([b][n](f.splice(0,2)));g="l";b=b=="m"?"l":"L"}while(f[w]>=c[g]){d[L]([b][n](f.splice(0,c[g])));if(!c[g])break}});d[H]=a._path2string;return d});a.findDotsAtSegment=function(a,b,c,d,e,f,g,h,i){var j=1-i,k=C(j,3)*a+C(j,2)*3*i*c+j*3*i*i*e+C(i,3)*g,l=C(j,3)*b+C(j,2)*3*i*d+j*3*i*i*f+C(i,3)*h,m=a+2*i*(c-a)+i*i*(e-2*c+a),n=b+2*i*(d-b)+i*i*(f-2*d+b),o=c+2*i*(e-c)+i*i*(g-2*e+c),p=d+2*i*(f-d)+i*i*(h-2*f+d),q=(1-i)*a+i*c,r=(1-i)*b+i*d,s=(1-i)*e+i*g,t=(1-i)*f+i*h,u=90-y.atan((m-o)/(n-p))*180/D;(m>o||n1){x=y.sqrt(x);c=x*c;d=x*d}var z=c*c,A=d*d,C=(f==g?-1:1)*y.sqrt(B((z*A-z*u*u-A*t*t)/(z*u*u+A*t*t))),E=C*c*u/d+(a+h)/2,F=C*-d*t/c+(b+i)/2,G=y.asin(((b-F)/d).toFixed(9)),H=y.asin(((i-F)/d).toFixed(9));G=aH&&(G=G-D*2);!g&&H>G&&(H=H-D*2)}var I=H-G;if(B(I)>k){var J=H,K=h,L=i;H=G+k*(g&&H>G?1:-1);h=E+c*y.cos(H);i=F+d*y.sin(H);m=bt(h,i,c,d,e,0,g,K,L,[H,J,E,F])}I=H-G;var M=y.cos(G),N=y.sin(G),O=y.cos(H),P=y.sin(H),Q=y.tan(I/4),R=4/3*c*Q,S=4/3*d*Q,T=[a,b],U=[a+R*N,b-S*M],V=[h+R*P,i-S*O],W=[h,i];U[0]=2*T[0]-U[0];U[1]=2*T[1]-U[1];{if(j)return[U,V,W][n](m);m=[U,V,W][n](m)[v]()[s](",");var X=[];for(var Y=0,Z=m[w];Y"1e12"&&(l=0.5);B(n)>"1e12"&&(n=0.5);if(l>0&&l<1){q=bu(a,b,c,d,e,f,g,h,l);p[L](q.x);o[L](q.y)}if(n>0&&n<1){q=bu(a,b,c,d,e,f,g,h,n);p[L](q.x);o[L](q.y)}i=f-2*d+b-(h-2*f+d);j=2*(d-b)-2*(f-d);k=b-d;l=(-j+y.sqrt(j*j-4*i*k))/2/i;n=(-j-y.sqrt(j*j-4*i*k))/2/i;B(l)>"1e12"&&(l=0.5);B(n)>"1e12"&&(n=0.5);if(l>0&&l<1){q=bu(a,b,c,d,e,f,g,h,l);p[L](q.x);o[L](q.y)}if(n>0&&n<1){q=bu(a,b,c,d,e,f,g,h,n);p[L](q.x);o[L](q.y)}return{min:{x:A[m](0,p),y:A[m](0,o)},max:{x:z[m](0,p),y:z[m](0,o)}}}),bw=bm(function(a,b){var c=bq(a),d=b&&bq(b),e={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},f={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},g=function(a,b){var c,d;if(!a)return["C",b.x,b.y,b.x,b.y,b.x,b.y];!(a[0]in{T:1,Q:1})&&(b.qx=b.qy=null);switch(a[0]){case"M":b.X=a[1];b.Y=a[2];break;case"A":a=["C"][n](bt[m](0,[b.x,b.y][n](a.slice(1))));break;case"S":c=b.x+(b.x-(b.bx||b.x));d=b.y+(b.y-(b.by||b.y));a=["C",c,d][n](a.slice(1));break;case"T":b.qx=b.x+(b.x-(b.qx||b.x));b.qy=b.y+(b.y-(b.qy||b.y));a=["C"][n](bs(b.x,b.y,b.qx,b.qy,a[1],a[2]));break;case"Q":b.qx=a[1];b.qy=a[2];a=["C"][n](bs(b.x,b.y,a[1],a[2],a[3],a[4]));break;case"L":a=["C"][n](br(b.x,b.y,a[1],a[2]));break;case"H":a=["C"][n](br(b.x,b.y,a[1],b.y));break;case"V":a=["C"][n](br(b.x,b.y,b.x,a[1]));break;case"Z":a=["C"][n](br(b.x,b.y,b.X,b.Y));break}return a},h=function(a,b){if(a[b][w]>7){a[b].shift();var e=a[b];while(e[w])a.splice(b++,0,["C"][n](e.splice(0,6)));a.splice(b,1);k=z(c[w],d&&d[w]||0)}},i=function(a,b,e,f,g){if(a&&b&&a[g][0]=="M"&&b[g][0]!="M"){b.splice(g,0,["M",f.x,f.y]);e.bx=0;e.by=0;e.x=a[g][1];e.y=a[g][2];k=z(c[w],d&&d[w]||0)}};for(var j=0,k=z(c[w],d&&d[w]||0);j0.5)*2-1;C(e-0.5,2)+C(f-0.5,2)>0.25&&(f=y.sqrt(0.25-C(e-0.5,2))*g+0.5)&&f!=0.5&&(f=f.toFixed(5)-0.00001*g)}return p});b=b[s](/\s*\-\s*/);if(d=="linear"){var i=b.shift();i=-S(i);if(isNaN(i))return null;var j=[0,0,y.cos(i*D/180),y.sin(i*D/180)],k=1/(z(B(j[2]),B(j[3]))||1);j[2]*=k;j[3]*=k;if(j[2]<0){j[0]=-j[2];j[2]=0}if(j[3]<0){j[1]=-j[3];j[3]=0}}var m=bx(b);if(!m)return null;var n=a.getAttribute(I);n=n.match(/^url\(#(.*)\)$/);n&&c.defs.removeChild(g.getElementById(n[1]));var o=bG(d+"Gradient");o.id=bh();bG(o,d=="radial"?{fx:e,fy:f}:{x1:j[0],y1:j[1],x2:j[2],y2:j[3]});c.defs[l](o);for(var q=0,t=m[w];q1?G.opacity/100:G.opacity});case"stroke":G=a.getRGB(o);h[R](n,G.hex);n=="stroke"&&G[f]("opacity")&&bG(h,{"stroke-opacity":G.opacity>1?G.opacity/100:G.opacity});break;case"gradient":(({circle:1,ellipse:1})[f](c.type)||r(o).charAt()!="r")&&bI(h,o,c.paper);break;case"opacity":i.gradient&&!i[f]("stroke-opacity")&&bG(h,{"stroke-opacity":o>1?o/100:o});case"fill-opacity":if(i.gradient){var H=g.getElementById(h.getAttribute(I)[Y](/^url\(#|\)$/g,p));if(H){var J=H.getElementsByTagName("stop");J[J[w]-1][R]("stop-opacity",o)}break}default:n=="font-size"&&(o=T(o,10)+"px");var K=n[Y](/(\-.)/g,function(a){return V.call(a.substring(1))});h.style[K]=o;h[R](n,o);break}}}bM(c,d);m?c.rotate(m.join(q)):S(j)&&c.rotate(j,true)},bL=1.2,bM=function(b,c){if(b.type!="text"||!(c[f]("text")||c[f]("font")||c[f]("font-size")||c[f]("x")||c[f]("y")))return;var d=b.attrs,e=b.node,h=e.firstChild?T(g.defaultView.getComputedStyle(e.firstChild,p).getPropertyValue("font-size"),10):10;if(c[f]("text")){d.text=c.text;while(e.firstChild)e.removeChild(e.firstChild);var i=r(c.text)[s]("\n");for(var j=0,k=i[w];jb.height&&(b.height=e.y+e.height-b.y);e.x+e.width-b.x>b.width&&(b.width=e.x+e.width-b.x)}}a&&this.hide();return b};bN[e].attr=function(b,c){if(this.removed)return this;if(b==null){var d={};for(var e in this.attrs)this.attrs[f](e)&&(d[e]=this.attrs[e]);this._.rt.deg&&(d.rotation=this.rotate());(this._.sx!=1||this._.sy!=1)&&(d.scale=this.scale());d.gradient&&d.fill=="none"&&(d.fill=d.gradient)&&delete d.gradient;return d}if(c==null&&a.is(b,F)){if(b=="translation")return cz.call(this);if(b=="rotation")return this.rotate();if(b=="scale")return this.scale();if(b==I&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;return this.attrs[b]}if(c==null&&a.is(b,G)){var g={};for(var h=0,i=b.length;h"));m.W=h.w=m.paper.span.offsetWidth;m.H=h.h=m.paper.span.offsetHeight;m.X=h.x;m.Y=h.y+Q(m.H/2);switch(h["text-anchor"]){case"start":m.node.style["v-text-align"]="left";m.bbx=Q(m.W/2);break;case"end":m.node.style["v-text-align"]="right";m.bbx=-Q(m.W/2);break;default:m.node.style["v-text-align"]="center";break}}};bI=function(a,b){a.attrs=a.attrs||{};var c=a.attrs,d,e="linear",f=".5 .5";a.attrs.gradient=b;b=r(b)[Y](bd,function(a,b,c){e="radial";if(b&&c){b=S(b);c=S(c);C(b-0.5,2)+C(c-0.5,2)>0.25&&(c=y.sqrt(0.25-C(b-0.5,2))*((c>0.5)*2-1)+0.5);f=b+q+c}return p});b=b[s](/\s*\-\s*/);if(e=="linear"){var g=b.shift();g=-S(g);if(isNaN(g))return null}var h=bx(b);if(!h)return null;a=a.shape||a.node;d=a.getElementsByTagName(I)[0]||cd(I);!d.parentNode&&a.appendChild(d);if(h[w]){d.on=true;d.method="none";d.color=h[0].color;d.color2=h[h[w]-1].color;var i=[];for(var j=0,k=h[w];j")}}catch(a){cd=function(a){return g.createElement("<"+a+" xmlns=\"urn:schemas-microsoft.com:vml\" class=\"rvml\">")}}bV=function(){var b=by[m](0,arguments),c=b.container,d=b.height,e,f=b.width,h=b.x,i=b.y;if(!c)throw new Error("VML container not found.");var k=new j,n=k.canvas=g.createElement("div"),o=n.style;h=h||0;i=i||0;f=f||512;d=d||342;f==+f&&(f+="px");d==+d&&(d+="px");k.width=1000;k.height=1000;k.coordsize=b_*1000+q+b_*1000;k.coordorigin="0 0";k.span=g.createElement("span");k.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";n[l](k.span);o.cssText=a.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",f,d);if(c==1){g.body[l](n);o.left=h+"px";o.top=i+"px";o.position="absolute"}else c.firstChild?c.insertBefore(n,c.firstChild):c[l](n);bz.call(k,k,a.fn);return k};k.clear=function(){this.canvas.innerHTML=p;this.span=g.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas[l](this.span);this.bottom=this.top=null};k.remove=function(){this.canvas.parentNode.removeChild(this.canvas);for(var a in this)this[a]=bF(a);return true}}var ce=navigator.userAgent.match(/Version\\x2f(.*?)\s/);navigator.vendor=="Apple Computer, Inc."&&(ce&&ce[1]<4||navigator.platform.slice(0,2)=="iP")?k.safari=function(){var a=this.rect(-99,-99,this.width+99,this.height+99).attr({stroke:"none"});h.setTimeout(function(){a.remove()})}:k.safari=function(){};var cf=function(){this.returnValue=false},cg=function(){return this.originalEvent.preventDefault()},ch=function(){this.cancelBubble=true},ci=function(){return this.originalEvent.stopPropagation()},cj=(function(){{if(g.addEventListener)return function(a,b,c,d){var e=o&&u[b]?u[b]:b,g=function(e){if(o&&u[f](b))for(var g=0,h=e.targetTouches&&e.targetTouches.length;g1&&(a=Array[e].splice.call(arguments,0,arguments[w]));return new cC(a)};k.setSize=bU;k.top=k.bottom=null;k.raphael=a;function co(){return this.x+q+this.y}bO.resetScale=function(){if(this.removed)return this;this._.sx=1;this._.sy=1;this.attrs.scale="1 1"};bO.scale=function(a,b,c,d){if(this.removed)return this;if(a==null&&b==null)return{x:this._.sx,y:this._.sy,toString:co};b=b||a;!(+b)&&(b=a);var e,f,g,h,i=this.attrs;if(a!=0){var j=this.getBBox(),k=j.x+j.width/2,l=j.y+j.height/2,m=B(a/this._.sx),o=B(b/this._.sy);c=+c||c==0?c:k;d=+d||d==0?d:l;var r=this._.sx>0,s=this._.sy>0,t=~(~(a/B(a))),u=~(~(b/B(b))),x=m*t,y=o*u,z=this.node.style,A=c+B(k-c)*x*(k>c==r?1:-1),C=d+B(l-d)*y*(l>d==s?1:-1),D=a*t>b*u?o:m;switch(this.type){case"rect":case"image":var E=i.width*m,F=i.height*o;this.attr({height:F,r:i.r*D,width:E,x:A-E/2,y:C-F/2});break;case"circle":case"ellipse":this.attr({rx:i.rx*m,ry:i.ry*o,r:i.r*D,cx:A,cy:C});break;case"text":this.attr({x:A,y:C});break;case"path":var G=bp(i.path),H=true,I=r?x:m,J=s?y:o;for(var K=0,L=G[w];Kr)p=n.data[r*l];else{p=a.findDotsAtSegment(b,c,d,e,f,g,h,i,r/l);n.data[r]=p}r&&(k+=C(C(o.x-p.x,2)+C(o.y-p.y,2),0.5));if(j!=null&&k>=j)return p;o=p}if(j==null)return k},cr=function(b,c){return function(d,e,f){d=bw(d);var g,h,i,j,k="",l={},m,n=0;for(var o=0,p=d.length;oe){if(c&&!l.start){m=cq(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n);k+=["C",m.start.x,m.start.y,m.m.x,m.m.y,m.x,m.y];if(f)return k;l.start=k;k=["M",m.x,m.y+"C",m.n.x,m.n.y,m.end.x,m.end.y,i[5],i[6]][v]();n+=j;g=+i[5];h=+i[6];continue}if(!b&&!c){m=cq(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n);return{x:m.x,y:m.y,alpha:m.alpha}}}n+=j;g=+i[5];h=+i[6]}k+=i}l.end=k;m=b?n:c?l:a.findDotsAtSegment(g,h,i[1],i[2],i[3],i[4],i[5],i[6],1);m.alpha&&(m={x:m.x,y:m.y,alpha:m.alpha});return m}},cs=cr(1),ct=cr(),cu=cr(0,1);bO.getTotalLength=function(){if(this.type!="path")return;if(this.node.getTotalLength)return this.node.getTotalLength();return cs(this.attrs.path)};bO.getPointAtLength=function(a){if(this.type!="path")return;return ct(this.attrs.path,a)};bO.getSubpath=function(a,b){if(this.type!="path")return;if(B(this.getTotalLength()-b)<"1e-6")return cu(this.attrs.path,a).end;var c=cu(this.attrs.path,b,1);return a?cu(c,a).end:c};a.easing_formulas={linear:function(a){return a},"<":function(a){return C(a,3)},">":function(a){return C(a-1,3)+1},"<>":function(a){a=a*2;if(a<1)return C(a,3)/2;a-=2;return(C(a,3)+2)/2},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a=a-1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a==0||a==1)return a;var b=0.3,c=b/4;return C(2,-10*a)*y.sin((a-c)*(2*D)/b)+1},bounce:function(a){var b=7.5625,c=2.75,d;if(a<1/c)d=b*a*a;else if(a<2/c){a-=1.5/c;d=b*a*a+0.75}else if(a<2.5/c){a-=2.25/c;d=b*a*a+0.9375}else{a-=2.625/c;d=b*a*a+0.984375}return d}};var cv=[],cw=function(){var b=+(new Date);for(var c=0;cd)return d;while(cf?c=e:d=e;e=(d-c)/2+c}return e}return n(a,1/(200*f))}bO.onAnimation=function(a){this._run=a||0;return this};bO.animate=function(c,d,e,g){var h=this;h.timeouts=h.timeouts||[];if(a.is(e,"function")||!e)g=e||null;if(h.removed){g&&g.call(h);return h}var i={},j={},k=false,l={};for(var m in c)if(c[f](m)){if(X[f](m)||h.paper.customAttributes[f](m)){k=true;i[m]=h.attr(m);i[m]==null&&(i[m]=W[m]);j[m]=c[m];switch(X[m]){case"along":var n=cs(c[m]),o=ct(c[m],n*!(!c.back)),p=h.getBBox();l[m]=n/d;l.tx=p.x;l.ty=p.y;l.sx=o.x;l.sy=o.y;j.rot=c.rot;j.back=c.back;j.len=n;c.rot&&(l.r=S(h.rotate())||0);break;case E:l[m]=(j[m]-i[m])/d;break;case"colour":i[m]=a.getRGB(i[m]);var q=a.getRGB(j[m]);l[m]={r:(q.r-i[m].r)/d,g:(q.g-i[m].g)/d,b:(q.b-i[m].b)/d};break;case"path":var t=bw(i[m],j[m]);i[m]=t[0];var u=t[1];l[m]=[];for(var v=0,x=i[m][w];vopera.version()?new Audio(null):new Audio).canPlayType}catch(ib){pa= -!1}this.hasHTML5=pa;this.html5={usingFlash:null};this.flash={};this.ignoreFlash=this.html5Only=!1;var Ka,c=this,h=null,s="HTML5::",A,v=navigator.userAgent,k=Z,Q=k.location.href.toString(),i=document,ra,La,sa,j,D=[],ta=!0,x,R=!1,S=!1,m=!1,o=!1,ba=!1,n,eb=0,T,w,ua,H,va,I,J,K,Ma,wa,ca,da,ea,L,xa,U,fa,ga,M,Na,ya,fb=["log","info","warn","error"],Oa,ha,Pa,V=null,za=null,p,Aa,N,Qa,ia,ja,O,t,W=!1,Ba=!1,Ra,Sa,Ta,ka=0,X=null,la,B=null,Ua,ma,Y,E,Ca,Da,Va,u,Wa=Array.prototype.slice,G=!1,z,Ea,Xa,C,Ya,Fa=v.match(/(ipad|iphone|ipod)/i), -F=v.match(/msie/i),gb=v.match(/webkit/i),Ga=v.match(/safari/i)&&!v.match(/chrome/i),qa=v.match(/opera/i),Ha=v.match(/(mobile|pre\/|xoom)/i)||Fa,Ia=!Q.match(/usehtml5audio/i)&&!Q.match(/sm2\-ignorebadua/i)&&Ga&&!v.match(/silk/i)&&v.match(/OS X 10_6_([3-7])/i),Za="undefined"!==typeof console&&"undefined"!==typeof console.log,Ja="undefined"!==typeof i.hasFocus?i.hasFocus():null,na=Ga&&("undefined"===typeof i.hasFocus||!i.hasFocus()),$a=!na,ab=/(mp3|mp4|mpa|m4a|m4b)/i,P=i.location?i.location.protocol.match(/http/i): -null,bb=!P?"http://":"",cb=/^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,db="mpeg4,aac,flv,mov,mp4,m4v,f4v,m4a,m4b,mp4v,3gp,3g2".split(","),hb=RegExp("\\.("+db.join("|")+")(\\?.*)?$","i");this.mimePattern=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.useAltURL=!P;this._global_a=null;if(Ha&&(c.useHTML5Audio=!0,c.preferFlash=!1,Fa))G=c.ignoreFlash=!0;this.setup=function(a){var d=!c.url;"undefined"!==typeof a&&m&&B&&c.ok()&&("undefined"!==typeof a.flashVersion|| -"undefined"!==typeof a.url)&&O(p("setupLate"));ua(a);d&&U&&"undefined"!==typeof a.url&&c.beginDelayedInit();!U&&"undefined"!==typeof a.url&&"complete"===i.readyState&&setTimeout(L,1);return c};this.supported=this.ok=function(){return B?m&&!o:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(c){return A(c)||i[c]||k[c]};this.createSound=function(a,d){function e(){g=ia(g);c.sounds[f.id]=new Ka(f);c.soundIDs.push(f.id);return c.sounds[f.id]}var b,g=null,f=b=null;b="soundManager.createSound(): "+p(!m? -"notReady":"notOK");if(!m||!c.ok())return O(b),!1;"undefined"!==typeof d&&(a={id:a,url:d});g=w(a);g.url=la(g.url);f=g;f.id.toString().charAt(0).match(/^[0-9]$/)&&c._wD("soundManager.createSound(): "+p("badID",f.id),2);c._wD("soundManager.createSound(): "+f.id+" ("+f.url+")",1);if(t(f.id,!0))return c._wD("soundManager.createSound(): "+f.id+" exists",1),c.sounds[f.id];if(ma(f))b=e(),c._wD("Creating sound "+f.id+", using HTML5"),b._setup_html5(f);else{if(8=a)return!1;for(a-=1;0<=a;a--)if(c=y[a],!c.fired&&b.position>=c.position)c.fired=!0,q++,c.method.apply(c.scope,[c.position]);return!0};this._resetOnPosition=function(b){var a,c;a=y.length;if(!a)return!1;for(a-=1;0<=a;a--)if(c=y[a],c.fired&&b<=c.position)c.fired=!1,q--; -return!0};v=function(){var a=b._iO,d=a.from,e=a.to,f,g;g=function(){c._wD(b.id+': "to" time of '+e+" reached.");b.clearOnPosition(e,g);b.stop()};f=function(){c._wD(b.id+': playing "from" '+d);if(null!==e&&!isNaN(e))b.onPosition(e,g)};if(null!==d&&!isNaN(d))a.position=d,a.multiShot=!1,f();return a};k=function(){var a,c=b._iO.onposition;if(c)for(a in c)if(c.hasOwnProperty(a))b.onPosition(parseInt(a,10),c[a])};u=function(){var a,c=b._iO.onposition;if(c)for(a in c)c.hasOwnProperty(a)&&b.clearOnPosition(parseInt(a, -10))};i=function(){b.isHTML5&&Ra(b)};l=function(){b.isHTML5&&Sa(b)};g=function(a){a||(y=[],q=0);m=!1;b._hasTimer=null;b._a=null;b._html5_canplay=!1;b.bytesLoaded=null;b.bytesTotal=null;b.duration=b._iO&&b._iO.duration?b._iO.duration:null;b.durationEstimate=null;b.buffered=[];b.eqData=[];b.eqData.left=[];b.eqData.right=[];b.failures=0;b.isBuffering=!1;b.instanceOptions={};b.instanceCount=0;b.loaded=!1;b.metadata={};b.readyState=0;b.muted=!1;b.paused=!1;b.peakData={left:0,right:0};b.waveformData={left:[], -right:[]};b.playState=0;b.position=null;b.id3={}};g();this._onTimer=function(a){var c,f=!1,g={};if(b._hasTimer||a){if(b._a&&(a||(0opera.version()?new Audio(null):new Audio,e=b._a,e._called_load=!1,G)c._global_a=e;b.isHTML5=!0;b._a=e;e._t=b;f();b._apply_loop(e,a.loops);a.autoLoad||a.autoPlay?b.load():(e.autobuffer=!1,e.preload="auto");return e};f=function(){if(b._a._added_events)return!1;var a;b._a._added_events=!0;for(a in C)C.hasOwnProperty(a)&&b._a&&b._a.addEventListener(a,C[a],!1); -return!0};r=function(){var a;c._wD(s+"removing event listeners: "+b.id);b._a._added_events=!1;for(a in C)C.hasOwnProperty(a)&&b._a&&b._a.removeEventListener(a,C[a],!1)};this._onload=function(a){a=!!a||!b.isHTML5&&8===j&&b.duration;c._wD('SMSound._onload(): "'+b.id+'"'+(a?" loaded.":" failed to load? - "+b.url),a?1:2);!a&&!b.isHTML5&&(!0===c.sandbox.noRemote&&c._wD("SMSound._onload(): "+p("noNet"),1),!0===c.sandbox.noLocal&&c._wD("SMSound._onload(): "+p("noLocal"),1));b.loaded=a;b.readyState=a?3:2; -b._onbufferchange(0);b._iO.onload&&b._iO.onload.apply(b,[a]);return!0};this._onbufferchange=function(a){if(0===b.playState||a&&b.isBuffering||!a&&!b.isBuffering)return!1;b.isBuffering=1===a;b._iO.onbufferchange&&(c._wD("SMSound._onbufferchange(): "+a),b._iO.onbufferchange.apply(b));return!0};this._onsuspend=function(){b._iO.onsuspend&&(c._wD("SMSound._onsuspend()"),b._iO.onsuspend.apply(b));return!0};this._onfailure=function(a,d,e){b.failures++;c._wD('SMSound._onfailure(): "'+b.id+'" count '+b.failures); -if(b._iO.onfailure&&1===b.failures)b._iO.onfailure(b,a,d,e);else c._wD("SMSound._onfailure(): ignoring")};this._onfinish=function(){var a=b._iO.onfinish;b._onbufferchange(0);b._resetOnPosition(0);if(b.instanceCount){b.instanceCount--;if(!b.instanceCount&&(u(),b.playState=0,b.paused=!1,b.instanceCount=0,b.instanceOptions={},b._iO={},l(),b.isHTML5))b.position=0;if((!b.instanceCount||b._iO.multiShotEvents)&&a)c._wD('SMSound._onfinish(): "'+b.id+'"'),a.apply(b)}};this._whileloading=function(a,c,d,e){var f= -b._iO;b.bytesLoaded=a;b.bytesTotal=c;b.duration=Math.floor(d);b.bufferLength=e;b.durationEstimate=!b.isHTML5&&!f.isMovieStar?f.duration?b.duration>f.duration?b.duration:f.duration:parseInt(b.bytesTotal/b.bytesLoaded*b.duration,10):b.duration;if(!b.isHTML5)b.buffered=[{start:0,end:b.duration}];(3!==b.readyState||b.isHTML5)&&f.whileloading&&f.whileloading.apply(b)};this._whileplaying=function(a,c,d,e,f){var g=b._iO;if(isNaN(a)||null===a)return!1;b.position=Math.max(0,a);b._processOnPosition();if(!b.isHTML5&& -8opera.version()?new Audio(null): -new Audio:null,e,b,g={},f;f=c.audioFormats;for(e in f)if(f.hasOwnProperty(e)&&(b="audio/"+e,g[e]=a(f[e].type),g[b]=g[e],e.match(ab)?(c.flash[e]=!0,c.flash[b]=!0):(c.flash[e]=!1,c.flash[b]=!1),f[e]&&f[e].related))for(b=f[e].related.length-1;0<=b;b--)g["audio/"+f[e].related[b]]=g[e],c.html5[f[e].related[b]]=g[e],c.flash[f[e].related[b]]=g[e];g.canPlayType=d?a:null;c.html5=w(c.html5,g);return!0};da={notReady:"Not loaded yet - wait for soundManager.onready()",notOK:"Audio support is not available.",domError:"soundManager::createMovie(): appendChild/innerHTML call failed. DOM not ready or other error.", -spcWmode:"soundManager::createMovie(): Removing wmode, preventing known SWF loading issue(s)",swf404:"soundManager: Verify that %s is a valid path.",tryDebug:"Try soundManager.debugFlash = true for more security details (output goes to SWF.)",checkSWF:"See SWF output for more debug info.",localFail:"soundManager: Non-HTTP page ("+i.location.protocol+" URL?) Review Flash player security settings for this special case:\nhttp://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html\nMay need to add/allow path, eg. c:/sm2/ or /users/me/sm2/", -waitFocus:"soundManager: Special case: Waiting for SWF to load with window focus...",waitImpatient:"soundManager: Getting impatient, still waiting for Flash%s...",waitForever:"soundManager: Waiting indefinitely for Flash (will recover if unblocked)...",waitSWF:"soundManager: Retrying, waiting for 100% SWF load...",needFunction:"soundManager: Function object expected for %s",badID:'Warning: Sound ID "%s" should be a string, starting with a non-numeric character',currentObj:"--- soundManager._debug(): Current sound objects ---", -waitEI:"soundManager::initMovie(): Waiting for ExternalInterface call from Flash...",waitOnload:"soundManager: Waiting for window.onload()",docLoaded:"soundManager: Document already loaded",onload:"soundManager::initComplete(): calling soundManager.onload()",onloadOK:"soundManager.onload() complete",init:"soundManager::init()",didInit:"soundManager::init(): Already called?",flashJS:"soundManager: Attempting JS to Flash call...",secNote:"Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html", -badRemove:"Warning: Failed to remove flash movie.",shutdown:"soundManager.disable(): Shutting down",queue:"soundManager: Queueing %s handler",smFail:"soundManager: Failed to initialise.",smError:"SMSound.load(): Exception: JS-Flash communication failed, or JS error.",fbTimeout:"No flash response, applying .swf_timedout CSS...",fbLoaded:"Flash loaded",fbHandler:"soundManager::flashBlockHandler()",manURL:"SMSound.load(): Using manually-assigned URL",onURL:"soundManager.load(): current URL already assigned.", -badFV:'soundManager.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.',as2loop:"Note: Setting stream:false so looping can work (flash 8 limitation)",noNSLoop:"Note: Looping not implemented for MovieStar formats",needfl9:"Note: Switching to flash 9, required for MP4 formats.",mfTimeout:"Setting flashLoadTimeout = 0 (infinite) for off-screen, mobile flash case",needFlash:"soundManager: Fatal error: Flash is needed to play some required formats, but is not available.",gotFocus:"soundManager: Got window focus.", -mfOn:"mobileFlash::enabling on-screen flash repositioning",policy:"Enabling usePolicyFile for data access",setup:"soundManager.setup(): allowed parameters: %s",setupError:'soundManager.setup(): "%s" cannot be assigned with this method.',setupUndef:'soundManager.setup(): Could not find option "%s"',setupLate:"soundManager.setup(): url + flashVersion changes will not take effect until reboot().",h5a:"creating HTML5 Audio() object",noURL:"soundManager: Flash URL required. Call soundManager.setup({url:...}) to get started."}; -p=function(){var a=Wa.call(arguments),c=a.shift(),c=da&&da[c]?da[c]:"",e,b;if(c&&a&&a.length)for(e=0,b=a.length;ej)c._wD(p("needfl9")),c.flashVersion=j=9;c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":9===j?" (AS3/Flash 9)":" (AS2/Flash 8)");8'}if(R&&S)return!1;if(c.html5Only)return wa(),e(),c.oMC=A(c.movieID),sa(),S=R=!0,!1;var g=d||c.url,f=c.altURL||g,h=fa(),l=N(),k=null,k=i.getElementsByTagName("html")[0],j,o,m,k=k&&k.dir&&k.dir.match(/rtl/i),a="undefined"===typeof a?c.id:a;wa();c.url=Pa(P?g:f);d=c.url;c.wmode=!c.wmode&&c.useHighPerformance?"transparent":c.wmode;if(null!== -c.wmode&&(v.match(/msie 8/i)||!F&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i))n("spcWmode"),c.wmode=null;h={name:a,id:a,src:d,quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:bb+"www.macromedia.com/go/getflashplayer",title:"JS/Flash audio component (SoundManager 2)",type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};if(c.debugFlash)h.FlashVars="debug=1";c.wmode||delete h.wmode;if(F)g=i.createElement("div"),o=['',b("movie",d),b("AllowScriptAccess",c.allowScriptAccess),b("quality",h.quality),c.wmode?b("wmode",c.wmode):"",b("bgcolor",c.bgColor),b("hasPriority","true"),c.debugFlash?b("FlashVars",h.FlashVars):"",""].join("");else for(j in g=i.createElement("embed"),h)h.hasOwnProperty(j)&&g.setAttribute(j, -h[j]);ya();l=N();if(h=fa())if(c.oMC=A(c.movieID)||i.createElement("div"),c.oMC.id){m=c.oMC.className;c.oMC.className=(m?m+" ":"movieContainer")+(l?" "+l:"");c.oMC.appendChild(g);if(F)j=c.oMC.appendChild(i.createElement("div")),j.className="sm2-object-box",j.innerHTML=o;S=!0}else{c.oMC.id=c.movieID;c.oMC.className="movieContainer "+l;j=l=null;if(!c.useFlashBlock)if(c.useHighPerformance)l={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"};else if(l={position:"absolute", -width:"6px",height:"6px",top:"-9999px",left:"-9999px"},k)l.left=Math.abs(parseInt(l.left,10))+"px";if(gb)c.oMC.style.zIndex=1E4;if(!c.debugFlash)for(m in l)l.hasOwnProperty(m)&&(c.oMC.style[m]=l[m]);try{F||c.oMC.appendChild(g);h.appendChild(c.oMC);if(F)j=c.oMC.appendChild(i.createElement("div")),j.className="sm2-object-box",j.innerHTML=o;S=!0}catch(q){throw Error(p("domError")+" \n"+q.toString());}}R=!0;e();c._wD("soundManager::createMovie(): Trying to load "+d+(!P&&c.altURL?" (alternate URL)":""), -1);return!0};ea=function(){if(c.html5Only)return ga(),!1;if(h)return!1;if(!c.url)return n("noURL"),!1;h=c.getMovie(c.id);if(!h)V?(F?c.oMC.innerHTML=za:c.oMC.appendChild(V),V=null,R=!0):ga(c.id,c.url),h=c.getMovie(c.id);h&&n("waitEI");"function"===typeof c.oninitmovie&&setTimeout(c.oninitmovie,1);return!0};K=function(){setTimeout(Ma,1E3)};Ma=function(){var a,d=!1;if(!c.url||W)return!1;W=!0;u.remove(k,"load",K);if(na&&!Ja)return n("waitFocus"),!1;m||(a=c.getMoviePercent(),c._wD(p("waitImpatient",0< -a?" (SWF "+a+"% loaded)":"")),0a&&(d=!0));setTimeout(function(){a=c.getMoviePercent();if(d)return W=!1,c._wD(p("waitSWF")),k.setTimeout(K,1),!1;m||(c._wD("soundManager: No Flash response within expected time.\nLikely causes: "+(0===a?"Loading "+c.movieURL+" may have failed (and/or Flash "+j+"+ not present?), ":"")+"Flash blocked or JS-Flash security error."+(c.debugFlash?" "+p("checkSWF"):""),2),!P&&a&&(n("localFail",2),c.debugFlash||n("tryDebug",2)),0===a&&c._wD(p("swf404",c.url)),x("flashtojs", -!1,": Timed out"+P?" (Check flash security or flash blockers)":" (No plugin/missing SWF?)"));!m&&$a&&(null===a?c.useFlashBlock||0===c.flashLoadTimeout?(c.useFlashBlock&&Aa(),n("waitForever")):ha(!0):0===c.flashLoadTimeout?n("waitForever"):ha(!0))},c.flashLoadTimeout)};ca=function(){if(Ja||!na)return u.remove(k,"focus",ca),!0;Ja=$a=!0;n("gotFocus");W=!1;K();u.remove(k,"focus",ca);return!0};Ya=function(){var a,d=[];if(c.useHTML5Audio&&c.hasHTML5){for(a in c.audioFormats)c.audioFormats.hasOwnProperty(a)&& -d.push(a+": "+c.html5[a]+(!c.html5[a]&&z&&c.flash[a]?" (using flash)":c.preferFlash&&c.flash[a]&&z?" (preferring flash)":!c.html5[a]?" ("+(c.audioFormats[a].required?"required, ":"")+"and no flash support)":""));c._wD("-- SoundManager 2: HTML5 support tests ("+c.html5Test+"): "+d.join(", ")+" --",1)}};T=function(a){if(m)return!1;if(c.html5Only)return c._wD("-- SoundManager 2: loaded --"),m=!0,J(),x("onload",!0),!0;var d=!0,e;if(!c.useFlashBlock||!c.flashLoadTimeout||c.getMoviePercent())m=!0,o&&(e= -{type:!z&&B?"NO_FLASH":"INIT_TIMEOUT"});c._wD("-- SoundManager 2 "+(o?"failed to load":"loaded")+" ("+(o?"Flash security/load error":"OK")+") --",1);if(o||a){if(c.useFlashBlock&&c.oMC)c.oMC.className=N()+" "+(null===c.getMoviePercent()?"swf_timedout":"swf_error");I({type:"ontimeout",error:e,ignoreInit:!0});x("onload",!1);M(e);d=!1}else x("onload",!0);o||(c.waitForWindowLoad&&!ba?(n("waitOnload"),u.add(k,"load",J)):(c.waitForWindowLoad&&ba&&n("docLoaded"),J()));return d};La=function(){var a,d=c.setupOptions; -for(a in d)d.hasOwnProperty(a)&&("undefined"===typeof c[a]?c[a]=d[a]:c[a]!==d[a]&&(c.setupOptions[a]=c[a]))};sa=function(){n("init");if(m)return n("didInit"),!1;if(c.html5Only){if(!m)u.remove(k,"load",c.beginDelayedInit),c.enabled=!0,T();return!0}ea();try{n("flashJS"),h._externalInterfaceTest(!1),Na(!0,c.flashPollingInterval||(c.useHighPerformance?10:50)),c.debugMode||h._disableDebug(),c.enabled=!0,x("jstoflash",!0),c.html5Only||u.add(k,"unload",ra)}catch(a){return c._wD("js/flash exception: "+a.toString()), -x("jstoflash",!1),M({type:"JS_TO_FLASH_EXCEPTION",fatal:!0}),ha(!0),T(),!1}T();u.remove(k,"load",c.beginDelayedInit);return!0};L=function(){if(U)return!1;U=!0;La();ya();var a=null,a=null,d="undefined"!==typeof console&&"function"===typeof console.log,e=Q.toLowerCase();-1!==e.indexOf("sm2-usehtml5audio=")&&(a="1"===e.charAt(e.indexOf("sm2-usehtml5audio=")+18),d&&console.log((a?"Enabling ":"Disabling ")+"useHTML5Audio via URL parameter"),c.setup({useHTML5Audio:a}));-1!==e.indexOf("sm2-preferflash=")&& -(a="1"===e.charAt(e.indexOf("sm2-preferflash=")+16),d&&console.log((a?"Enabling ":"Disabling ")+"preferFlash via URL parameter"),c.setup({preferFlash:a}));!z&&c.hasHTML5&&(c._wD("SoundManager: No Flash detected"+(!c.useHTML5Audio?", enabling HTML5.":". Trying HTML5-only mode.")),c.setup({useHTML5Audio:!0,preferFlash:!1}));Va();c.html5.usingFlash=Ua();B=c.html5.usingFlash;Ya();!z&&B&&(n("needFlash"),c.setup({flashLoadTimeout:1}));i.removeEventListener&&i.removeEventListener("DOMContentLoaded",L,!1); -ea();return!0};Da=function(){"complete"===i.readyState&&(L(),i.detachEvent("onreadystatechange",Da));return!0};xa=function(){ba=!0;u.remove(k,"load",xa)};Ea();u.add(k,"focus",ca);u.add(k,"load",K);u.add(k,"load",xa);i.addEventListener?i.addEventListener("DOMContentLoaded",L,!1):i.attachEvent?i.attachEvent("onreadystatechange",Da):(x("onload",!1),M({type:"NO_DOM2_EVENTS",fatal:!0}))}var oa=null;if("undefined"===typeof SM2_DEFER||!SM2_DEFER)oa=new $;Z.SoundManager=$;Z.soundManager=oa})(window); \ No newline at end of file diff --git a/timeside/static/timeside/js/libs/soundmanager2-nodebug-jsmin.js b/timeside/static/timeside/js/libs/soundmanager2-nodebug-jsmin.js deleted file mode 100644 index ca2fc0e..0000000 --- a/timeside/static/timeside/js/libs/soundmanager2-nodebug-jsmin.js +++ /dev/null @@ -1,80 +0,0 @@ -/** @license - * - * SoundManager 2: JavaScript Sound for the Web - * ---------------------------------------------- - * http://schillmania.com/projects/soundmanager2/ - * - * Copyright (c) 2007, Scott Schiller. All rights reserved. - * Code provided under the BSD License: - * http://schillmania.com/projects/soundmanager2/license.txt - * - * V2.97a.20120916 - */ -(function(fa){function R(R,ea){function S(a){return c.preferFlash&&y&&!c.ignoreFlash&&"undefined"!==typeof c.flash[a]&&c.flash[a]}function l(a){return function(c){var d=this._t;return!d||!d._a?null:a.call(this,c)}}this.setupOptions={url:R||null,flashVersion:8,debugMode:!0,debugFlash:!1,useConsole:!0,consoleOnly:!0,waitForWindowLoad:!1,bgColor:"#ffffff",useHighPerformance:!1,flashPollingInterval:null,html5PollingInterval:null,flashLoadTimeout:1E3,wmode:null,allowScriptAccess:"always",useFlashBlock:!1, -useHTML5Audio:!0,html5Test:/^(probably|maybe)$/i,preferFlash:!0,noSWFCache:!1};this.defaultOptions={autoLoad:!1,autoPlay:!1,from:null,loops:1,onid3:null,onload:null,whileloading:null,onplay:null,onpause:null,onresume:null,whileplaying:null,onposition:null,onstop:null,onfailure:null,onfinish:null,multiShot:!0,multiShotEvents:!1,position:null,pan:0,stream:!0,to:null,type:null,usePolicyFile:!1,volume:100};this.flash9Options={isMovieStar:null,usePeakData:!1,useWaveformData:!1,useEQData:!1,onbufferchange:null, -ondataerror:null};this.movieStarOptions={bufferTime:3,serverURL:null,onconnect:null,duration:null};this.audioFormats={mp3:{type:['audio/mpeg; codecs="mp3"',"audio/mpeg","audio/mp3","audio/MPA","audio/mpa-robust"],required:!0},mp4:{related:["aac","m4a","m4b"],type:['audio/mp4; codecs="mp4a.40.2"',"audio/aac","audio/x-m4a","audio/MP4A-LATM","audio/mpeg4-generic"],required:!1},ogg:{type:["audio/ogg; codecs=vorbis"],required:!1},wav:{type:['audio/wav; codecs="1"',"audio/wav","audio/wave","audio/x-wav"], -required:!1}};this.movieID="sm2-container";this.id=ea||"sm2movie";this.debugID="soundmanager-debug";this.debugURLParam=/([#?&])debug=1/i;this.versionNumber="V2.97a.20120916";this.altURL=this.movieURL=this.version=null;this.enabled=this.swfLoaded=!1;this.oMC=null;this.sounds={};this.soundIDs=[];this.didFlashBlock=this.muted=!1;this.filePattern=null;this.filePatterns={flash8:/\.mp3(\?.*)?$/i,flash9:/\.mp3(\?.*)?$/i};this.features={buffering:!1,peakData:!1,waveformData:!1,eqData:!1,movieStar:!1};this.sandbox= -{};var ga;try{ga="undefined"!==typeof Audio&&"undefined"!==typeof(ha&&10>opera.version()?new Audio(null):new Audio).canPlayType}catch(Za){ga=!1}this.hasHTML5=ga;this.html5={usingFlash:null};this.flash={};this.ignoreFlash=this.html5Only=!1;var Da,c=this,i=null,T,q=navigator.userAgent,h=fa,ia=h.location.href.toString(),m=document,ja,Ea,ka,j,v=[],J=!1,K=!1,k=!1,s=!1,la=!1,L,r,ma,U,na,B,C,D,Fa,oa,V,W,E,pa,M,qa,X,F,Ga,ra,Ha,Y,Ia,N=null,sa=null,t,ta,G,Z,$,H,p,O=!1,ua=!1,Ja,Ka,La,aa=0,P=null,ba,n=null,Ma, -ca,Q,w,va,wa,Na,o,Wa=Array.prototype.slice,z=!1,y,xa,Oa,u,Pa,ya=q.match(/(ipad|iphone|ipod)/i),x=q.match(/msie/i),Xa=q.match(/webkit/i),za=q.match(/safari/i)&&!q.match(/chrome/i),ha=q.match(/opera/i),Aa=q.match(/(mobile|pre\/|xoom)/i)||ya,Qa=!ia.match(/usehtml5audio/i)&&!ia.match(/sm2\-ignorebadua/i)&&za&&!q.match(/silk/i)&&q.match(/OS X 10_6_([3-7])/i),Ba="undefined"!==typeof m.hasFocus?m.hasFocus():null,da=za&&("undefined"===typeof m.hasFocus||!m.hasFocus()),Ra=!da,Sa=/(mp3|mp4|mpa|m4a|m4b)/i,Ca= -m.location?m.location.protocol.match(/http/i):null,Ta=!Ca?"http://":"",Ua=/^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,Va="mpeg4,aac,flv,mov,mp4,m4v,f4v,m4a,m4b,mp4v,3gp,3g2".split(","),Ya=RegExp("\\.("+Va.join("|")+")(\\?.*)?$","i");this.mimePattern=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.useAltURL=!Ca;this._global_a=null;if(Aa&&(c.useHTML5Audio=!0,c.preferFlash=!1,ya))z=c.ignoreFlash=!0;this.setup=function(a){var e=!c.url;"undefined"!==typeof a&& -k&&n&&c.ok()&&("undefined"!==typeof a.flashVersion||"undefined"!==typeof a.url)&&H(t("setupLate"));ma(a);e&&M&&"undefined"!==typeof a.url&&c.beginDelayedInit();!M&&"undefined"!==typeof a.url&&"complete"===m.readyState&&setTimeout(E,1);return c};this.supported=this.ok=function(){return n?k&&!s:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(a){return T(a)||m[a]||h[a]};this.createSound=function(a,e){function d(){b=Z(b);c.sounds[f.id]=new Da(f);c.soundIDs.push(f.id);return c.sounds[f.id]}var b=null, -g=null,f=null;if(!k||!c.ok())return H(void 0),!1;"undefined"!==typeof e&&(a={id:a,url:e});b=r(a);b.url=ba(b.url);f=b;if(p(f.id,!0))return c.sounds[f.id];if(ca(f))g=d(),g._setup_html5(f);else{if(8=a)return!1;for(a-=1;0<=a;a--)if(c=k[a],!c.fired&&b.position>=c.position)c.fired=!0,o++,c.method.apply(c.scope,[c.position]);return!0};this._resetOnPosition=function(b){var a,c;a=k.length;if(!a)return!1;for(a-=1;0<=a;a--)if(c=k[a],c.fired&&b<=c.position)c.fired=!1,o--;return!0};s=function(){var a=b._iO,c=a.from,e=a.to,d,f;f=function(){b.clearOnPosition(e, -f);b.stop()};d=function(){if(null!==e&&!isNaN(e))b.onPosition(e,f)};if(null!==c&&!isNaN(c))a.position=c,a.multiShot=!1,d();return a};m=function(){var a,c=b._iO.onposition;if(c)for(a in c)if(c.hasOwnProperty(a))b.onPosition(parseInt(a,10),c[a])};q=function(){var a,c=b._iO.onposition;if(c)for(a in c)c.hasOwnProperty(a)&&b.clearOnPosition(parseInt(a,10))};h=function(){b.isHTML5&&Ja(b)};I=function(){b.isHTML5&&Ka(b)};g=function(a){a||(k=[],o=0);l=!1;b._hasTimer=null;b._a=null;b._html5_canplay=!1;b.bytesLoaded= -null;b.bytesTotal=null;b.duration=b._iO&&b._iO.duration?b._iO.duration:null;b.durationEstimate=null;b.buffered=[];b.eqData=[];b.eqData.left=[];b.eqData.right=[];b.failures=0;b.isBuffering=!1;b.instanceOptions={};b.instanceCount=0;b.loaded=!1;b.metadata={};b.readyState=0;b.muted=!1;b.paused=!1;b.peakData={left:0,right:0};b.waveformData={left:[],right:[]};b.playState=0;b.position=null;b.id3={}};g();this._onTimer=function(a){var c,f=!1,g={};if(b._hasTimer||a){if(b._a&&(a||(0opera.version()?new Audio(null):new Audio,d=b._a,d._called_load=!1,z)c._global_a=d;b.isHTML5=!0;b._a=d;d._t=b;f();b._apply_loop(d,a.loops);a.autoLoad||a.autoPlay? -b.load():(d.autobuffer=!1,d.preload="auto");return d};f=function(){if(b._a._added_events)return!1;var a;b._a._added_events=!0;for(a in u)u.hasOwnProperty(a)&&b._a&&b._a.addEventListener(a,u[a],!1);return!0};A=function(){var a;b._a._added_events=!1;for(a in u)u.hasOwnProperty(a)&&b._a&&b._a.removeEventListener(a,u[a],!1)};this._onload=function(a){a=!!a||!b.isHTML5&&8===j&&b.duration;b.loaded=a;b.readyState=a?3:2;b._onbufferchange(0);b._iO.onload&&b._iO.onload.apply(b,[a]);return!0};this._onbufferchange= -function(a){if(0===b.playState||a&&b.isBuffering||!a&&!b.isBuffering)return!1;b.isBuffering=1===a;b._iO.onbufferchange&&b._iO.onbufferchange.apply(b);return!0};this._onsuspend=function(){b._iO.onsuspend&&b._iO.onsuspend.apply(b);return!0};this._onfailure=function(a,c,e){b.failures++;if(b._iO.onfailure&&1===b.failures)b._iO.onfailure(b,a,c,e)};this._onfinish=function(){var a=b._iO.onfinish;b._onbufferchange(0);b._resetOnPosition(0);if(b.instanceCount){b.instanceCount--;if(!b.instanceCount&&(q(),b.playState= -0,b.paused=!1,b.instanceCount=0,b.instanceOptions={},b._iO={},I(),b.isHTML5))b.position=0;(!b.instanceCount||b._iO.multiShotEvents)&&a&&a.apply(b)}};this._whileloading=function(a,c,e,d){var f=b._iO;b.bytesLoaded=a;b.bytesTotal=c;b.duration=Math.floor(e);b.bufferLength=d;b.durationEstimate=!b.isHTML5&&!f.isMovieStar?f.duration?b.duration>f.duration?b.duration:f.duration:parseInt(b.bytesTotal/b.bytesLoaded*b.duration,10):b.duration;if(!b.isHTML5)b.buffered=[{start:0,end:b.duration}];(3!==b.readyState|| -b.isHTML5)&&f.whileloading&&f.whileloading.apply(b)};this._whileplaying=function(a,c,e,d,f){var g=b._iO;if(isNaN(a)||null===a)return!1;b.position=Math.max(0,a);b._processOnPosition();if(!b.isHTML5&&8opera.version()?new Audio(null):new Audio:null,d,b,g={},f;f=c.audioFormats;for(d in f)if(f.hasOwnProperty(d)&&(b="audio/"+d,g[d]=a(f[d].type),g[b]=g[d],d.match(Sa)?(c.flash[d]=!0,c.flash[b]=!0):(c.flash[d]=!1,c.flash[b]=!1),f[d]&&f[d].related))for(b=f[d].related.length- -1;0<=b;b--)g["audio/"+f[d].related[b]]=g[d],c.html5[f[d].related[b]]=g[d],c.flash[f[d].related[b]]=g[d];g.canPlayType=e?a:null;c.html5=r(c.html5,g);return!0};t=function(){};Z=function(a){if(8===j&&1j)c.flashVersion=j=9;c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":9===j?" (AS3/Flash 9)":" (AS2/Flash 8)");8'}if(J&&K)return!1;if(c.html5Only)return oa(),c.oMC=T(c.movieID),ka(),K=J=!0,!1;var b=e||c.url,g=c.altURL||b,f=qa(),h=G(),i=null,i=m.getElementsByTagName("html")[0],j,k,l,i=i&&i.dir&&i.dir.match(/rtl/i),a="undefined"===typeof a?c.id:a;oa();c.url=Ia(Ca?b:g);e=c.url;c.wmode=!c.wmode&&c.useHighPerformance?"transparent":c.wmode;if(null!==c.wmode&&(q.match(/msie 8/i)||!x&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i))c.wmode= -null;f={name:a,id:a,src:e,quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:Ta+"www.macromedia.com/go/getflashplayer",title:"JS/Flash audio component (SoundManager 2)",type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};if(c.debugFlash)f.FlashVars="debug=1";c.wmode||delete f.wmode;if(x)b=m.createElement("div"),k=['',d("movie",e),d("AllowScriptAccess",c.allowScriptAccess),d("quality",f.quality),c.wmode?d("wmode",c.wmode):"",d("bgcolor",c.bgColor),d("hasPriority","true"),c.debugFlash?d("FlashVars",f.FlashVars):"",""].join("");else for(j in b=m.createElement("embed"),f)f.hasOwnProperty(j)&&b.setAttribute(j,f[j]);ra();h=G();if(f=qa())if(c.oMC=T(c.movieID)||m.createElement("div"),c.oMC.id){l=c.oMC.className;c.oMC.className= -(l?l+" ":"movieContainer")+(h?" "+h:"");c.oMC.appendChild(b);if(x)j=c.oMC.appendChild(m.createElement("div")),j.className="sm2-object-box",j.innerHTML=k;K=!0}else{c.oMC.id=c.movieID;c.oMC.className="movieContainer "+h;j=h=null;if(!c.useFlashBlock)if(c.useHighPerformance)h={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"};else if(h={position:"absolute",width:"6px",height:"6px",top:"-9999px",left:"-9999px"},i)h.left=Math.abs(parseInt(h.left,10))+"px";if(Xa)c.oMC.style.zIndex= -1E4;if(!c.debugFlash)for(l in h)h.hasOwnProperty(l)&&(c.oMC.style[l]=h[l]);try{x||c.oMC.appendChild(b);f.appendChild(c.oMC);if(x)j=c.oMC.appendChild(m.createElement("div")),j.className="sm2-object-box",j.innerHTML=k;K=!0}catch(n){throw Error(t("domError")+" \n"+n.toString());}}return J=!0};W=function(){if(c.html5Only)return X(),!1;if(i||!c.url)return!1;i=c.getMovie(c.id);if(!i)N?(x?c.oMC.innerHTML=sa:c.oMC.appendChild(N),N=null,J=!0):X(c.id,c.url),i=c.getMovie(c.id);"function"===typeof c.oninitmovie&& -setTimeout(c.oninitmovie,1);return!0};D=function(){setTimeout(Fa,1E3)};Fa=function(){var a,e=!1;if(!c.url||O)return!1;O=!0;o.remove(h,"load",D);if(da&&!Ba)return!1;k||(a=c.getMoviePercent(),0a&&(e=!0));setTimeout(function(){a=c.getMoviePercent();if(e)return O=!1,h.setTimeout(D,1),!1;!k&&Ra&&(null===a?c.useFlashBlock||0===c.flashLoadTimeout?c.useFlashBlock&&ta():Y(!0):0!==c.flashLoadTimeout&&Y(!0))},c.flashLoadTimeout)};V=function(){if(Ba||!da)return o.remove(h,"focus",V),!0;Ba=Ra=!0;O=!1; -D();o.remove(h,"focus",V);return!0};Pa=function(){};L=function(a){if(k)return!1;if(c.html5Only)return k=!0,C(),!0;var e=!0,d;if(!c.useFlashBlock||!c.flashLoadTimeout||c.getMoviePercent())k=!0,s&&(d={type:!y&&n?"NO_FLASH":"INIT_TIMEOUT"});if(s||a){if(c.useFlashBlock&&c.oMC)c.oMC.className=G()+" "+(null===c.getMoviePercent()?"swf_timedout":"swf_error");B({type:"ontimeout",error:d,ignoreInit:!0});F(d);e=!1}s||(c.waitForWindowLoad&&!la?o.add(h,"load",C):C());return e};Ea=function(){var a,e=c.setupOptions; -for(a in e)e.hasOwnProperty(a)&&("undefined"===typeof c[a]?c[a]=e[a]:c[a]!==e[a]&&(c.setupOptions[a]=c[a]))};ka=function(){if(k)return!1;if(c.html5Only){if(!k)o.remove(h,"load",c.beginDelayedInit),c.enabled=!0,L();return!0}W();try{i._externalInterfaceTest(!1),Ga(!0,c.flashPollingInterval||(c.useHighPerformance?10:50)),c.debugMode||i._disableDebug(),c.enabled=!0,c.html5Only||o.add(h,"unload",ja)}catch(a){return F({type:"JS_TO_FLASH_EXCEPTION",fatal:!0}),Y(!0),L(),!1}L();o.remove(h,"load",c.beginDelayedInit); -return!0};E=function(){if(M)return!1;M=!0;Ea();ra();!y&&c.hasHTML5&&c.setup({useHTML5Audio:!0,preferFlash:!1});Na();c.html5.usingFlash=Ma();n=c.html5.usingFlash;Pa();!y&&n&&c.setup({flashLoadTimeout:1});m.removeEventListener&&m.removeEventListener("DOMContentLoaded",E,!1);W();return!0};wa=function(){"complete"===m.readyState&&(E(),m.detachEvent("onreadystatechange",wa));return!0};pa=function(){la=!0;o.remove(h,"load",pa)};xa();o.add(h,"focus",V);o.add(h,"load",D);o.add(h,"load",pa);m.addEventListener? -m.addEventListener("DOMContentLoaded",E,!1):m.attachEvent?m.attachEvent("onreadystatechange",wa):F({type:"NO_DOM2_EVENTS",fatal:!0})}var ea=null;if("undefined"===typeof SM2_DEFER||!SM2_DEFER)ea=new R;fa.SoundManager=R;fa.soundManager=ea})(window); \ No newline at end of file diff --git a/timeside/static/timeside/js/libs/soundmanager2-nodebug.js b/timeside/static/timeside/js/libs/soundmanager2-nodebug.js deleted file mode 100644 index 856175b..0000000 --- a/timeside/static/timeside/js/libs/soundmanager2-nodebug.js +++ /dev/null @@ -1,2511 +0,0 @@ -/** @license - * - * SoundManager 2: JavaScript Sound for the Web - * ---------------------------------------------- - * http://schillmania.com/projects/soundmanager2/ - * - * Copyright (c) 2007, Scott Schiller. All rights reserved. - * Code provided under the BSD License: - * http://schillmania.com/projects/soundmanager2/license.txt - * - * V2.97a.20120916 - */ - -/*global window, SM2_DEFER, sm2Debugger, console, document, navigator, setTimeout, setInterval, clearInterval, Audio */ -/*jslint regexp: true, sloppy: true, white: true, nomen: true, plusplus: true */ - -(function(window) { -var soundManager = null; -function SoundManager(smURL, smID) { - this.setupOptions = { - 'url': (smURL || null), - 'flashVersion': 8, - 'debugMode': true, - 'debugFlash': false, - 'useConsole': true, - 'consoleOnly': true, - 'waitForWindowLoad': false, - 'bgColor': '#ffffff', - 'useHighPerformance': false, - 'flashPollingInterval': null, - 'html5PollingInterval': null, - 'flashLoadTimeout': 1000, - 'wmode': null, - 'allowScriptAccess': 'always', - 'useFlashBlock': false, - 'useHTML5Audio': true, - 'html5Test': /^(probably|maybe)$/i, - 'preferFlash': true, - 'noSWFCache': false - }; - this.defaultOptions = { - 'autoLoad': false, - 'autoPlay': false, - 'from': null, - 'loops': 1, - 'onid3': null, - 'onload': null, - 'whileloading': null, - 'onplay': null, - 'onpause': null, - 'onresume': null, - 'whileplaying': null, - 'onposition': null, - 'onstop': null, - 'onfailure': null, - 'onfinish': null, - 'multiShot': true, - 'multiShotEvents': false, - 'position': null, - 'pan': 0, - 'stream': true, - 'to': null, - 'type': null, - 'usePolicyFile': false, - 'volume': 100 - }; - this.flash9Options = { - 'isMovieStar': null, - 'usePeakData': false, - 'useWaveformData': false, - 'useEQData': false, - 'onbufferchange': null, - 'ondataerror': null - }; - this.movieStarOptions = { - 'bufferTime': 3, - 'serverURL': null, - 'onconnect': null, - 'duration': null - }; - this.audioFormats = { - 'mp3': { - 'type': ['audio/mpeg; codecs="mp3"', 'audio/mpeg', 'audio/mp3', 'audio/MPA', 'audio/mpa-robust'], - 'required': true - }, - 'mp4': { - 'related': ['aac','m4a','m4b'], - 'type': ['audio/mp4; codecs="mp4a.40.2"', 'audio/aac', 'audio/x-m4a', 'audio/MP4A-LATM', 'audio/mpeg4-generic'], - 'required': false - }, - 'ogg': { - 'type': ['audio/ogg; codecs=vorbis'], - 'required': false - }, - 'wav': { - 'type': ['audio/wav; codecs="1"', 'audio/wav', 'audio/wave', 'audio/x-wav'], - 'required': false - } - }; - this.movieID = 'sm2-container'; - this.id = (smID || 'sm2movie'); - this.debugID = 'soundmanager-debug'; - this.debugURLParam = /([#?&])debug=1/i; - this.versionNumber = 'V2.97a.20120916'; - this.version = null; - this.movieURL = null; - this.altURL = null; - this.swfLoaded = false; - this.enabled = false; - this.oMC = null; - this.sounds = {}; - this.soundIDs = []; - this.muted = false; - this.didFlashBlock = false; - this.filePattern = null; - this.filePatterns = { - 'flash8': /\.mp3(\?.*)?$/i, - 'flash9': /\.mp3(\?.*)?$/i - }; - this.features = { - 'buffering': false, - 'peakData': false, - 'waveformData': false, - 'eqData': false, - 'movieStar': false - }; - this.sandbox = { - }; - this.hasHTML5 = (function() { - try { - return (typeof Audio !== 'undefined' && typeof (_isOpera && opera.version() < 10 ? new Audio(null) : new Audio()).canPlayType !== 'undefined'); - } catch(e) { - return false; - } - }()); - this.html5 = { - 'usingFlash': null - }; - this.flash = {}; - this.html5Only = false; - this.ignoreFlash = false; - var SMSound, - _s = this, _flash = null, _sm = 'soundManager', _smc = _sm+'::', _h5 = 'HTML5::', _id, _ua = navigator.userAgent, _win = window, _wl = _win.location.href.toString(), _doc = document, _doNothing, _setProperties, _init, _fV, _on_queue = [], _debugOpen = true, _debugTS, _didAppend = false, _appendSuccess = false, _didInit = false, _disabled = false, _windowLoaded = false, _wDS, _wdCount = 0, _initComplete, _mixin, _assign, _extraOptions, _addOnEvent, _processOnEvents, _initUserOnload, _delayWaitForEI, _waitForEI, _setVersionInfo, _handleFocus, _strings, _initMovie, _domContentLoaded, _winOnLoad, _didDCLoaded, _getDocument, _createMovie, _catchError, _setPolling, _initDebug, _debugLevels = ['log', 'info', 'warn', 'error'], _defaultFlashVersion = 8, _disableObject, _failSafely, _normalizeMovieURL, _oRemoved = null, _oRemovedHTML = null, _str, _flashBlockHandler, _getSWFCSS, _swfCSS, _toggleDebug, _loopFix, _policyFix, _complain, _idCheck, _waitingForEI = false, _initPending = false, _startTimer, _stopTimer, _timerExecute, _h5TimerCount = 0, _h5IntervalTimer = null, _parseURL, - _needsFlash = null, _featureCheck, _html5OK, _html5CanPlay, _html5Ext, _html5Unload, _domContentLoadedIE, _testHTML5, _event, _slice = Array.prototype.slice, _useGlobalHTML5Audio = false, _hasFlash, _detectFlash, _badSafariFix, _html5_events, _showSupport, - _is_iDevice = _ua.match(/(ipad|iphone|ipod)/i), _isIE = _ua.match(/msie/i), _isWebkit = _ua.match(/webkit/i), _isSafari = (_ua.match(/safari/i) && !_ua.match(/chrome/i)), _isOpera = (_ua.match(/opera/i)), - _mobileHTML5 = (_ua.match(/(mobile|pre\/|xoom)/i) || _is_iDevice), - _isBadSafari = (!_wl.match(/usehtml5audio/i) && !_wl.match(/sm2\-ignorebadua/i) && _isSafari && !_ua.match(/silk/i) && _ua.match(/OS X 10_6_([3-7])/i)), - _hasConsole = (typeof console !== 'undefined' && typeof console.log !== 'undefined'), _isFocused = (typeof _doc.hasFocus !== 'undefined'?_doc.hasFocus():null), _tryInitOnFocus = (_isSafari && (typeof _doc.hasFocus === 'undefined' || !_doc.hasFocus())), _okToDisable = !_tryInitOnFocus, _flashMIME = /(mp3|mp4|mpa|m4a|m4b)/i, - _emptyURL = 'about:blank', - _overHTTP = (_doc.location?_doc.location.protocol.match(/http/i):null), - _http = (!_overHTTP ? 'http:/'+'/' : ''), - _netStreamMimeTypes = /^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i, - _netStreamTypes = ['mpeg4', 'aac', 'flv', 'mov', 'mp4', 'm4v', 'f4v', 'm4a', 'm4b', 'mp4v', '3gp', '3g2'], - _netStreamPattern = new RegExp('\\.(' + _netStreamTypes.join('|') + ')(\\?.*)?$', 'i'); - this.mimePattern = /^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i; - this.useAltURL = !_overHTTP; - this._global_a = null; - _swfCSS = { - 'swfBox': 'sm2-object-box', - 'swfDefault': 'movieContainer', - 'swfError': 'swf_error', - 'swfTimedout': 'swf_timedout', - 'swfLoaded': 'swf_loaded', - 'swfUnblocked': 'swf_unblocked', - 'sm2Debug': 'sm2_debug', - 'highPerf': 'high_performance', - 'flashDebug': 'flash_debug' - }; - if (_mobileHTML5) { - _s.useHTML5Audio = true; - _s.preferFlash = false; - if (_is_iDevice) { - _s.ignoreFlash = true; - _useGlobalHTML5Audio = true; - } - } - this.setup = function(options) { - var noURL = (!_s.url); - if (typeof options !== 'undefined' && _didInit && _needsFlash && _s.ok() && (typeof options.flashVersion !== 'undefined' || typeof options.url !== 'undefined')) { - _complain(_str('setupLate')); - } - _assign(options); - if (noURL && _didDCLoaded && typeof options.url !== 'undefined') { - _s.beginDelayedInit(); - } - if (!_didDCLoaded && typeof options.url !== 'undefined' && _doc.readyState === 'complete') { - setTimeout(_domContentLoaded, 1); - } - return _s; - }; - this.ok = function() { - return (_needsFlash?(_didInit && !_disabled):(_s.useHTML5Audio && _s.hasHTML5)); - }; - this.supported = this.ok; - this.getMovie = function(smID) { - return _id(smID) || _doc[smID] || _win[smID]; - }; - this.createSound = function(oOptions, _url) { - var _cs, _cs_string, thisOptions = null, oSound = null, _tO = null; - if (!_didInit || !_s.ok()) { - _complain(_cs_string); - return false; - } - if (typeof _url !== 'undefined') { - oOptions = { - 'id': oOptions, - 'url': _url - }; - } - thisOptions = _mixin(oOptions); - thisOptions.url = _parseURL(thisOptions.url); - _tO = thisOptions; - if (_idCheck(_tO.id, true)) { - return _s.sounds[_tO.id]; - } - function make() { - thisOptions = _loopFix(thisOptions); - _s.sounds[_tO.id] = new SMSound(_tO); - _s.soundIDs.push(_tO.id); - return _s.sounds[_tO.id]; - } - if (_html5OK(_tO)) { - oSound = make(); - oSound._setup_html5(_tO); - } else { - if (_fV > 8) { - if (_tO.isMovieStar === null) { - _tO.isMovieStar = !!(_tO.serverURL || (_tO.type ? _tO.type.match(_netStreamMimeTypes) : false) || _tO.url.match(_netStreamPattern)); - } - } - _tO = _policyFix(_tO, _cs); - oSound = make(); - if (_fV === 8) { - _flash._createSound(_tO.id, _tO.loops||1, _tO.usePolicyFile); - } else { - _flash._createSound(_tO.id, _tO.url, _tO.usePeakData, _tO.useWaveformData, _tO.useEQData, _tO.isMovieStar, (_tO.isMovieStar?_tO.bufferTime:false), _tO.loops||1, _tO.serverURL, _tO.duration||null, _tO.autoPlay, true, _tO.autoLoad, _tO.usePolicyFile); - if (!_tO.serverURL) { - oSound.connected = true; - if (_tO.onconnect) { - _tO.onconnect.apply(oSound); - } - } - } - if (!_tO.serverURL && (_tO.autoLoad || _tO.autoPlay)) { - oSound.load(_tO); - } - } - if (!_tO.serverURL && _tO.autoPlay) { - oSound.play(); - } - return oSound; - }; - this.destroySound = function(sID, _bFromSound) { - if (!_idCheck(sID)) { - return false; - } - var oS = _s.sounds[sID], i; - oS._iO = {}; - oS.stop(); - oS.unload(); - for (i = 0; i < _s.soundIDs.length; i++) { - if (_s.soundIDs[i] === sID) { - _s.soundIDs.splice(i, 1); - break; - } - } - if (!_bFromSound) { - oS.destruct(true); - } - oS = null; - delete _s.sounds[sID]; - return true; - }; - this.load = function(sID, oOptions) { - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].load(oOptions); - }; - this.unload = function(sID) { - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].unload(); - }; - this.onPosition = function(sID, nPosition, oMethod, oScope) { - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].onposition(nPosition, oMethod, oScope); - }; - this.onposition = this.onPosition; - this.clearOnPosition = function(sID, nPosition, oMethod) { - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].clearOnPosition(nPosition, oMethod); - }; - this.play = function(sID, oOptions) { - var result = false; - if (!_didInit || !_s.ok()) { - _complain(_sm+'.play(): ' + _str(!_didInit?'notReady':'notOK')); - return result; - } - if (!_idCheck(sID)) { - if (!(oOptions instanceof Object)) { - oOptions = { - url: oOptions - }; - } - if (oOptions && oOptions.url) { - oOptions.id = sID; - result = _s.createSound(oOptions).play(); - } - return result; - } - return _s.sounds[sID].play(oOptions); - }; - this.start = this.play; - this.setPosition = function(sID, nMsecOffset) { - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].setPosition(nMsecOffset); - }; - this.stop = function(sID) { - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].stop(); - }; - this.stopAll = function() { - var oSound; - for (oSound in _s.sounds) { - if (_s.sounds.hasOwnProperty(oSound)) { - _s.sounds[oSound].stop(); - } - } - }; - this.pause = function(sID) { - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].pause(); - }; - this.pauseAll = function() { - var i; - for (i = _s.soundIDs.length-1; i >= 0; i--) { - _s.sounds[_s.soundIDs[i]].pause(); - } - }; - this.resume = function(sID) { - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].resume(); - }; - this.resumeAll = function() { - var i; - for (i = _s.soundIDs.length-1; i >= 0; i--) { - _s.sounds[_s.soundIDs[i]].resume(); - } - }; - this.togglePause = function(sID) { - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].togglePause(); - }; - this.setPan = function(sID, nPan) { - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].setPan(nPan); - }; - this.setVolume = function(sID, nVol) { - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].setVolume(nVol); - }; - this.mute = function(sID) { - var i = 0; - if (typeof sID !== 'string') { - sID = null; - } - if (!sID) { - for (i = _s.soundIDs.length-1; i >= 0; i--) { - _s.sounds[_s.soundIDs[i]].mute(); - } - _s.muted = true; - } else { - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].mute(); - } - return true; - }; - this.muteAll = function() { - _s.mute(); - }; - this.unmute = function(sID) { - var i; - if (typeof sID !== 'string') { - sID = null; - } - if (!sID) { - for (i = _s.soundIDs.length-1; i >= 0; i--) { - _s.sounds[_s.soundIDs[i]].unmute(); - } - _s.muted = false; - } else { - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].unmute(); - } - return true; - }; - this.unmuteAll = function() { - _s.unmute(); - }; - this.toggleMute = function(sID) { - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].toggleMute(); - }; - this.getMemoryUse = function() { - var ram = 0; - if (_flash && _fV !== 8) { - ram = parseInt(_flash._getMemoryUse(), 10); - } - return ram; - }; - this.disable = function(bNoDisable) { - var i; - if (typeof bNoDisable === 'undefined') { - bNoDisable = false; - } - if (_disabled) { - return false; - } - _disabled = true; - for (i = _s.soundIDs.length-1; i >= 0; i--) { - _disableObject(_s.sounds[_s.soundIDs[i]]); - } - _initComplete(bNoDisable); - _event.remove(_win, 'load', _initUserOnload); - return true; - }; - this.canPlayMIME = function(sMIME) { - var result; - if (_s.hasHTML5) { - result = _html5CanPlay({type:sMIME}); - } - if (!result && _needsFlash) { - result = (sMIME && _s.ok() ? !!((_fV > 8 ? sMIME.match(_netStreamMimeTypes) : null) || sMIME.match(_s.mimePattern)) : null); - } - return result; - }; - this.canPlayURL = function(sURL) { - var result; - if (_s.hasHTML5) { - result = _html5CanPlay({url: sURL}); - } - if (!result && _needsFlash) { - result = (sURL && _s.ok() ? !!(sURL.match(_s.filePattern)) : null); - } - return result; - }; - this.canPlayLink = function(oLink) { - if (typeof oLink.type !== 'undefined' && oLink.type) { - if (_s.canPlayMIME(oLink.type)) { - return true; - } - } - return _s.canPlayURL(oLink.href); - }; - this.getSoundById = function(sID, _suppressDebug) { - if (!sID) { - throw new Error(_sm+'.getSoundById(): sID is null/undefined'); - } - var result = _s.sounds[sID]; - return result; - }; - this.onready = function(oMethod, oScope) { - var sType = 'onready', - result = false; - if (typeof oMethod === 'function') { - if (!oScope) { - oScope = _win; - } - _addOnEvent(sType, oMethod, oScope); - _processOnEvents(); - result = true; - } else { - throw _str('needFunction', sType); - } - return result; - }; - this.ontimeout = function(oMethod, oScope) { - var sType = 'ontimeout', - result = false; - if (typeof oMethod === 'function') { - if (!oScope) { - oScope = _win; - } - _addOnEvent(sType, oMethod, oScope); - _processOnEvents({type:sType}); - result = true; - } else { - throw _str('needFunction', sType); - } - return result; - }; - this._writeDebug = function(sText, sType, _bTimestamp) { - return true; - }; - this._wD = this._writeDebug; - this._debug = function() { - }; - this.reboot = function() { - var i, j; - for (i = _s.soundIDs.length-1; i >= 0; i--) { - _s.sounds[_s.soundIDs[i]].destruct(); - } - if (_flash) { - try { - if (_isIE) { - _oRemovedHTML = _flash.innerHTML; - } - _oRemoved = _flash.parentNode.removeChild(_flash); - } catch(e) { - } - } - _oRemovedHTML = _oRemoved = _needsFlash = null; - _s.enabled = _didDCLoaded = _didInit = _waitingForEI = _initPending = _didAppend = _appendSuccess = _disabled = _s.swfLoaded = false; - _s.soundIDs = []; - _s.sounds = {}; - _flash = null; - for (i in _on_queue) { - if (_on_queue.hasOwnProperty(i)) { - for (j = _on_queue[i].length-1; j >= 0; j--) { - _on_queue[i][j].fired = false; - } - } - } - _win.setTimeout(_s.beginDelayedInit, 20); - }; - this.getMoviePercent = function() { - return (_flash && typeof _flash.PercentLoaded !== 'undefined' ? _flash.PercentLoaded() : null); - }; - this.beginDelayedInit = function() { - _windowLoaded = true; - _domContentLoaded(); - setTimeout(function() { - if (_initPending) { - return false; - } - _createMovie(); - _initMovie(); - _initPending = true; - return true; - }, 20); - _delayWaitForEI(); - }; - this.destruct = function() { - _s.disable(true); - }; - SMSound = function(oOptions) { - var _t = this, _resetProperties, _add_html5_events, _remove_html5_events, _stop_html5_timer, _start_html5_timer, _attachOnPosition, _onplay_called = false, _onPositionItems = [], _onPositionFired = 0, _detachOnPosition, _applyFromTo, _lastURL = null, _lastHTML5State; - _lastHTML5State = { - duration: null, - time: null - }; - this.id = oOptions.id; - this.sID = this.id; - this.url = oOptions.url; - this.options = _mixin(oOptions); - this.instanceOptions = this.options; - this._iO = this.instanceOptions; - this.pan = this.options.pan; - this.volume = this.options.volume; - this.isHTML5 = false; - this._a = null; - this.id3 = {}; - this._debug = function() { - }; - this.load = function(oOptions) { - var oS = null, _iO; - if (typeof oOptions !== 'undefined') { - _t._iO = _mixin(oOptions, _t.options); - _t.instanceOptions = _t._iO; - } else { - oOptions = _t.options; - _t._iO = oOptions; - _t.instanceOptions = _t._iO; - if (_lastURL && _lastURL !== _t.url) { - _t._iO.url = _t.url; - _t.url = null; - } - } - if (!_t._iO.url) { - _t._iO.url = _t.url; - } - _t._iO.url = _parseURL(_t._iO.url); - if (_t._iO.url === _t.url && _t.readyState !== 0 && _t.readyState !== 2) { - if (_t.readyState === 3 && _t._iO.onload) { - _t._iO.onload.apply(_t, [(!!_t.duration)]); - } - return _t; - } - _iO = _t._iO; - _lastURL = (_t.url && _t.url.toString ? _t.url.toString() : null); - _t.loaded = false; - _t.readyState = 1; - _t.playState = 0; - _t.id3 = {}; - if (_html5OK(_iO)) { - oS = _t._setup_html5(_iO); - if (!oS._called_load) { - _t._html5_canplay = false; - if (_t._a.src !== _iO.url) { - _t._a.src = _iO.url; - _t.setPosition(0); - } - _t._a.autobuffer = 'auto'; - _t._a.preload = 'auto'; - oS._called_load = true; - if (_iO.autoPlay) { - _t.play(); - } - } else { - } - } else { - try { - _t.isHTML5 = false; - _t._iO = _policyFix(_loopFix(_iO)); - _iO = _t._iO; - if (_fV === 8) { - _flash._load(_t.id, _iO.url, _iO.stream, _iO.autoPlay, (_iO.whileloading?1:0), _iO.loops||1, _iO.usePolicyFile); - } else { - _flash._load(_t.id, _iO.url, !!(_iO.stream), !!(_iO.autoPlay), _iO.loops||1, !!(_iO.autoLoad), _iO.usePolicyFile); - } - } catch(e) { - _catchError({type:'SMSOUND_LOAD_JS_EXCEPTION', fatal:true}); - } - } - _t.url = _iO.url; - return _t; - }; - this.unload = function() { - if (_t.readyState !== 0) { - if (!_t.isHTML5) { - if (_fV === 8) { - _flash._unload(_t.id, _emptyURL); - } else { - _flash._unload(_t.id); - } - } else { - _stop_html5_timer(); - if (_t._a) { - _t._a.pause(); - _html5Unload(_t._a, _emptyURL); - _t.url = _emptyURL; - } - } - _resetProperties(); - } - return _t; - }; - this.destruct = function(_bFromSM) { - if (!_t.isHTML5) { - _t._iO.onfailure = null; - _flash._destroySound(_t.id); - } else { - _stop_html5_timer(); - if (_t._a) { - _t._a.pause(); - _html5Unload(_t._a); - if (!_useGlobalHTML5Audio) { - _remove_html5_events(); - } - _t._a._t = null; - _t._a = null; - } - } - if (!_bFromSM) { - _s.destroySound(_t.id, true); - } - }; - this.play = function(oOptions, _updatePlayState) { - var fN, allowMulti, a, onready, startOK = true, - exit = null; - _updatePlayState = (typeof _updatePlayState === 'undefined' ? true : _updatePlayState); - if (!oOptions) { - oOptions = {}; - } - if (_t.url) { - _t._iO.url = _t.url; - } - _t._iO = _mixin(_t._iO, _t.options); - _t._iO = _mixin(oOptions, _t._iO); - _t._iO.url = _parseURL(_t._iO.url); - _t.instanceOptions = _t._iO; - if (_t._iO.serverURL && !_t.connected) { - if (!_t.getAutoPlay()) { - _t.setAutoPlay(true); - } - return _t; - } - if (_html5OK(_t._iO)) { - _t._setup_html5(_t._iO); - _start_html5_timer(); - } - if (_t.playState === 1 && !_t.paused) { - allowMulti = _t._iO.multiShot; - if (!allowMulti) { - exit = _t; - } else { - } - } - if (exit !== null) { - return exit; - } - if (oOptions.url && oOptions.url !== _t.url) { - _t.load(_t._iO); - } - if (!_t.loaded) { - if (_t.readyState === 0) { - if (!_t.isHTML5) { - _t._iO.autoPlay = true; - _t.load(_t._iO); - } else { - _t.load(_t._iO); - } - } else if (_t.readyState === 2) { - exit = _t; - } else { - } - } else { - } - if (exit !== null) { - return exit; - } - if (!_t.isHTML5 && _fV === 9 && _t.position > 0 && _t.position === _t.duration) { - oOptions.position = 0; - } - if (_t.paused && _t.position >= 0 && (!_t._iO.serverURL || _t.position > 0)) { - _t.resume(); - } else { - _t._iO = _mixin(oOptions, _t._iO); - if (_t._iO.from !== null && _t._iO.to !== null && _t.instanceCount === 0 && _t.playState === 0 && !_t._iO.serverURL) { - onready = function() { - _t._iO = _mixin(oOptions, _t._iO); - _t.play(_t._iO); - }; - if (_t.isHTML5 && !_t._html5_canplay) { - _t.load({ - _oncanplay: onready - }); - exit = false; - } else if (!_t.isHTML5 && !_t.loaded && (!_t.readyState || _t.readyState !== 2)) { - _t.load({ - onload: onready - }); - exit = false; - } - if (exit !== null) { - return exit; - } - _t._iO = _applyFromTo(); - } - if (!_t.instanceCount || _t._iO.multiShotEvents || (!_t.isHTML5 && _fV > 8 && !_t.getAutoPlay())) { - _t.instanceCount++; - } - if (_t._iO.onposition && _t.playState === 0) { - _attachOnPosition(_t); - } - _t.playState = 1; - _t.paused = false; - _t.position = (typeof _t._iO.position !== 'undefined' && !isNaN(_t._iO.position) ? _t._iO.position : 0); - if (!_t.isHTML5) { - _t._iO = _policyFix(_loopFix(_t._iO)); - } - if (_t._iO.onplay && _updatePlayState) { - _t._iO.onplay.apply(_t); - _onplay_called = true; - } - _t.setVolume(_t._iO.volume, true); - _t.setPan(_t._iO.pan, true); - if (!_t.isHTML5) { - startOK = _flash._start(_t.id, _t._iO.loops || 1, (_fV === 9 ? _t._iO.position : _t._iO.position / 1000), _t._iO.multiShot); - if (_fV === 9 && !startOK) { - if (_t._iO.onplayerror) { - _t._iO.onplayerror.apply(_t); - } - } - } else { - _start_html5_timer(); - a = _t._setup_html5(); - _t.setPosition(_t._iO.position); - a.play(); - } - } - return _t; - }; - this.start = this.play; - this.stop = function(bAll) { - var _iO = _t._iO, _oP; - if (_t.playState === 1) { - _t._onbufferchange(0); - _t._resetOnPosition(0); - _t.paused = false; - if (!_t.isHTML5) { - _t.playState = 0; - } - _detachOnPosition(); - if (_iO.to) { - _t.clearOnPosition(_iO.to); - } - if (!_t.isHTML5) { - _flash._stop(_t.id, bAll); - if (_iO.serverURL) { - _t.unload(); - } - } else { - if (_t._a) { - _oP = _t.position; - _t.setPosition(0); - _t.position = _oP; - _t._a.pause(); - _t.playState = 0; - _t._onTimer(); - _stop_html5_timer(); - } - } - _t.instanceCount = 0; - _t._iO = {}; - if (_iO.onstop) { - _iO.onstop.apply(_t); - } - } - return _t; - }; - this.setAutoPlay = function(autoPlay) { - _t._iO.autoPlay = autoPlay; - if (!_t.isHTML5) { - _flash._setAutoPlay(_t.id, autoPlay); - if (autoPlay) { - if (!_t.instanceCount && _t.readyState === 1) { - _t.instanceCount++; - } - } - } - }; - this.getAutoPlay = function() { - return _t._iO.autoPlay; - }; - this.setPosition = function(nMsecOffset) { - if (typeof nMsecOffset === 'undefined') { - nMsecOffset = 0; - } - var original_pos, - position, position1K, - offset = (_t.isHTML5 ? Math.max(nMsecOffset, 0) : Math.min(_t.duration || _t._iO.duration, Math.max(nMsecOffset, 0))); - original_pos = _t.position; - _t.position = offset; - position1K = _t.position/1000; - _t._resetOnPosition(_t.position); - _t._iO.position = offset; - if (!_t.isHTML5) { - position = (_fV === 9 ? _t.position : position1K); - if (_t.readyState && _t.readyState !== 2) { - _flash._setPosition(_t.id, position, (_t.paused || !_t.playState), _t._iO.multiShot); - } - } else if (_t._a) { - if (_t._html5_canplay) { - if (_t._a.currentTime !== position1K) { - try { - _t._a.currentTime = position1K; - if (_t.playState === 0 || _t.paused) { - _t._a.pause(); - } - } catch(e) { - } - } - } else { - } - } - if (_t.isHTML5) { - if (_t.paused) { - _t._onTimer(true); - } - } - return _t; - }; - this.pause = function(_bCallFlash) { - if (_t.paused || (_t.playState === 0 && _t.readyState !== 1)) { - return _t; - } - _t.paused = true; - if (!_t.isHTML5) { - if (_bCallFlash || typeof _bCallFlash === 'undefined') { - _flash._pause(_t.id, _t._iO.multiShot); - } - } else { - _t._setup_html5().pause(); - _stop_html5_timer(); - } - if (_t._iO.onpause) { - _t._iO.onpause.apply(_t); - } - return _t; - }; - this.resume = function() { - var _iO = _t._iO; - if (!_t.paused) { - return _t; - } - _t.paused = false; - _t.playState = 1; - if (!_t.isHTML5) { - if (_iO.isMovieStar && !_iO.serverURL) { - _t.setPosition(_t.position); - } - _flash._pause(_t.id, _iO.multiShot); - } else { - _t._setup_html5().play(); - _start_html5_timer(); - } - if (!_onplay_called && _iO.onplay) { - _iO.onplay.apply(_t); - _onplay_called = true; - } else if (_iO.onresume) { - _iO.onresume.apply(_t); - } - return _t; - }; - this.togglePause = function() { - if (_t.playState === 0) { - _t.play({ - position: (_fV === 9 && !_t.isHTML5 ? _t.position : _t.position / 1000) - }); - return _t; - } - if (_t.paused) { - _t.resume(); - } else { - _t.pause(); - } - return _t; - }; - this.setPan = function(nPan, bInstanceOnly) { - if (typeof nPan === 'undefined') { - nPan = 0; - } - if (typeof bInstanceOnly === 'undefined') { - bInstanceOnly = false; - } - if (!_t.isHTML5) { - _flash._setPan(_t.id, nPan); - } - _t._iO.pan = nPan; - if (!bInstanceOnly) { - _t.pan = nPan; - _t.options.pan = nPan; - } - return _t; - }; - this.setVolume = function(nVol, _bInstanceOnly) { - if (typeof nVol === 'undefined') { - nVol = 100; - } - if (typeof _bInstanceOnly === 'undefined') { - _bInstanceOnly = false; - } - if (!_t.isHTML5) { - _flash._setVolume(_t.id, (_s.muted && !_t.muted) || _t.muted?0:nVol); - } else if (_t._a) { - _t._a.volume = Math.max(0, Math.min(1, nVol/100)); - } - _t._iO.volume = nVol; - if (!_bInstanceOnly) { - _t.volume = nVol; - _t.options.volume = nVol; - } - return _t; - }; - this.mute = function() { - _t.muted = true; - if (!_t.isHTML5) { - _flash._setVolume(_t.id, 0); - } else if (_t._a) { - _t._a.muted = true; - } - return _t; - }; - this.unmute = function() { - _t.muted = false; - var hasIO = (typeof _t._iO.volume !== 'undefined'); - if (!_t.isHTML5) { - _flash._setVolume(_t.id, hasIO?_t._iO.volume:_t.options.volume); - } else if (_t._a) { - _t._a.muted = false; - } - return _t; - }; - this.toggleMute = function() { - return (_t.muted?_t.unmute():_t.mute()); - }; - this.onPosition = function(nPosition, oMethod, oScope) { - _onPositionItems.push({ - position: parseInt(nPosition, 10), - method: oMethod, - scope: (typeof oScope !== 'undefined' ? oScope : _t), - fired: false - }); - return _t; - }; - this.onposition = this.onPosition; - this.clearOnPosition = function(nPosition, oMethod) { - var i; - nPosition = parseInt(nPosition, 10); - if (isNaN(nPosition)) { - return false; - } - for (i=0; i < _onPositionItems.length; i++) { - if (nPosition === _onPositionItems[i].position) { - if (!oMethod || (oMethod === _onPositionItems[i].method)) { - if (_onPositionItems[i].fired) { - _onPositionFired--; - } - _onPositionItems.splice(i, 1); - } - } - } - }; - this._processOnPosition = function() { - var i, item, j = _onPositionItems.length; - if (!j || !_t.playState || _onPositionFired >= j) { - return false; - } - for (i=j-1; i >= 0; i--) { - item = _onPositionItems[i]; - if (!item.fired && _t.position >= item.position) { - item.fired = true; - _onPositionFired++; - item.method.apply(item.scope, [item.position]); - } - } - return true; - }; - this._resetOnPosition = function(nPosition) { - var i, item, j = _onPositionItems.length; - if (!j) { - return false; - } - for (i=j-1; i >= 0; i--) { - item = _onPositionItems[i]; - if (item.fired && nPosition <= item.position) { - item.fired = false; - _onPositionFired--; - } - } - return true; - }; - _applyFromTo = function() { - var _iO = _t._iO, - f = _iO.from, - t = _iO.to, - start, end; - end = function() { - _t.clearOnPosition(t, end); - _t.stop(); - }; - start = function() { - if (t !== null && !isNaN(t)) { - _t.onPosition(t, end); - } - }; - if (f !== null && !isNaN(f)) { - _iO.position = f; - _iO.multiShot = false; - start(); - } - return _iO; - }; - _attachOnPosition = function() { - var item, - op = _t._iO.onposition; - if (op) { - for (item in op) { - if (op.hasOwnProperty(item)) { - _t.onPosition(parseInt(item, 10), op[item]); - } - } - } - }; - _detachOnPosition = function() { - var item, - op = _t._iO.onposition; - if (op) { - for (item in op) { - if (op.hasOwnProperty(item)) { - _t.clearOnPosition(parseInt(item, 10)); - } - } - } - }; - _start_html5_timer = function() { - if (_t.isHTML5) { - _startTimer(_t); - } - }; - _stop_html5_timer = function() { - if (_t.isHTML5) { - _stopTimer(_t); - } - }; - _resetProperties = function(retainPosition) { - if (!retainPosition) { - _onPositionItems = []; - _onPositionFired = 0; - } - _onplay_called = false; - _t._hasTimer = null; - _t._a = null; - _t._html5_canplay = false; - _t.bytesLoaded = null; - _t.bytesTotal = null; - _t.duration = (_t._iO && _t._iO.duration ? _t._iO.duration : null); - _t.durationEstimate = null; - _t.buffered = []; - _t.eqData = []; - _t.eqData.left = []; - _t.eqData.right = []; - _t.failures = 0; - _t.isBuffering = false; - _t.instanceOptions = {}; - _t.instanceCount = 0; - _t.loaded = false; - _t.metadata = {}; - _t.readyState = 0; - _t.muted = false; - _t.paused = false; - _t.peakData = { - left: 0, - right: 0 - }; - _t.waveformData = { - left: [], - right: [] - }; - _t.playState = 0; - _t.position = null; - _t.id3 = {}; - }; - _resetProperties(); - this._onTimer = function(bForce) { - var duration, isNew = false, time, x = {}; - if (_t._hasTimer || bForce) { - if (_t._a && (bForce || ((_t.playState > 0 || _t.readyState === 1) && !_t.paused))) { - duration = _t._get_html5_duration(); - if (duration !== _lastHTML5State.duration) { - _lastHTML5State.duration = duration; - _t.duration = duration; - isNew = true; - } - _t.durationEstimate = _t.duration; - time = (_t._a.currentTime * 1000 || 0); - if (time !== _lastHTML5State.time) { - _lastHTML5State.time = time; - isNew = true; - } - if (isNew || bForce) { - _t._whileplaying(time,x,x,x,x); - } - } - return isNew; - } - }; - this._get_html5_duration = function() { - var _iO = _t._iO, - d = (_t._a && _t._a.duration ? _t._a.duration*1000 : (_iO && _iO.duration ? _iO.duration : null)), - result = (d && !isNaN(d) && d !== Infinity ? d : null); - return result; - }; - this._apply_loop = function(a, nLoops) { - a.loop = (nLoops > 1 ? 'loop' : ''); - }; - this._setup_html5 = function(oOptions) { - var _iO = _mixin(_t._iO, oOptions), d = decodeURI, - _a = _useGlobalHTML5Audio ? _s._global_a : _t._a, - _dURL = d(_iO.url), - _oldIO = (_a && _a._t ? _a._t.instanceOptions : null), - result; - if (_a) { - if (_a._t) { - if (!_useGlobalHTML5Audio && _dURL === d(_lastURL)) { - result = _a; - } else if (_useGlobalHTML5Audio && _oldIO.url === _iO.url && (!_lastURL || (_lastURL === _oldIO.url))) { - result = _a; - } - if (result) { - _t._apply_loop(_a, _iO.loops); - return result; - } - } - if (_useGlobalHTML5Audio && _a._t && _a._t.playState && _iO.url !== _oldIO.url) { - _a._t.stop(); - } - _resetProperties((_oldIO && _oldIO.url ? _iO.url === _oldIO.url : (_lastURL ? _lastURL === _iO.url : false))); - _a.src = _iO.url; - _t.url = _iO.url; - _lastURL = _iO.url; - _a._called_load = false; - } else { - if (_iO.autoLoad || _iO.autoPlay) { - _t._a = new Audio(_iO.url); - } else { - _t._a = (_isOpera && opera.version() < 10 ? new Audio(null) : new Audio()); - } - _a = _t._a; - _a._called_load = false; - if (_useGlobalHTML5Audio) { - _s._global_a = _a; - } - } - _t.isHTML5 = true; - _t._a = _a; - _a._t = _t; - _add_html5_events(); - _t._apply_loop(_a, _iO.loops); - if (_iO.autoLoad || _iO.autoPlay) { - _t.load(); - } else { - _a.autobuffer = false; - _a.preload = 'auto'; - } - return _a; - }; - _add_html5_events = function() { - if (_t._a._added_events) { - return false; - } - var f; - function add(oEvt, oFn, bCapture) { - return _t._a ? _t._a.addEventListener(oEvt, oFn, bCapture||false) : null; - } - _t._a._added_events = true; - for (f in _html5_events) { - if (_html5_events.hasOwnProperty(f)) { - add(f, _html5_events[f]); - } - } - return true; - }; - _remove_html5_events = function() { - var f; - function remove(oEvt, oFn, bCapture) { - return (_t._a ? _t._a.removeEventListener(oEvt, oFn, bCapture||false) : null); - } - _t._a._added_events = false; - for (f in _html5_events) { - if (_html5_events.hasOwnProperty(f)) { - remove(f, _html5_events[f]); - } - } - }; - this._onload = function(nSuccess) { - var fN, - loadOK = (!!(nSuccess) || (!_t.isHTML5 && _fV === 8 && _t.duration)); - _t.loaded = loadOK; - _t.readyState = loadOK?3:2; - _t._onbufferchange(0); - if (_t._iO.onload) { - _t._iO.onload.apply(_t, [loadOK]); - } - return true; - }; - this._onbufferchange = function(nIsBuffering) { - if (_t.playState === 0) { - return false; - } - if ((nIsBuffering && _t.isBuffering) || (!nIsBuffering && !_t.isBuffering)) { - return false; - } - _t.isBuffering = (nIsBuffering === 1); - if (_t._iO.onbufferchange) { - _t._iO.onbufferchange.apply(_t); - } - return true; - }; - this._onsuspend = function() { - if (_t._iO.onsuspend) { - _t._iO.onsuspend.apply(_t); - } - return true; - }; - this._onfailure = function(msg, level, code) { - _t.failures++; - if (_t._iO.onfailure && _t.failures === 1) { - _t._iO.onfailure(_t, msg, level, code); - } else { - } - }; - this._onfinish = function() { - var _io_onfinish = _t._iO.onfinish; - _t._onbufferchange(0); - _t._resetOnPosition(0); - if (_t.instanceCount) { - _t.instanceCount--; - if (!_t.instanceCount) { - _detachOnPosition(); - _t.playState = 0; - _t.paused = false; - _t.instanceCount = 0; - _t.instanceOptions = {}; - _t._iO = {}; - _stop_html5_timer(); - if (_t.isHTML5) { - _t.position = 0; - } - } - if (!_t.instanceCount || _t._iO.multiShotEvents) { - if (_io_onfinish) { - _io_onfinish.apply(_t); - } - } - } - }; - this._whileloading = function(nBytesLoaded, nBytesTotal, nDuration, nBufferLength) { - var _iO = _t._iO; - _t.bytesLoaded = nBytesLoaded; - _t.bytesTotal = nBytesTotal; - _t.duration = Math.floor(nDuration); - _t.bufferLength = nBufferLength; - if (!_t.isHTML5 && !_iO.isMovieStar) { - if (_iO.duration) { - _t.durationEstimate = (_t.duration > _iO.duration) ? _t.duration : _iO.duration; - } else { - _t.durationEstimate = parseInt((_t.bytesTotal / _t.bytesLoaded) * _t.duration, 10); - } - } else { - _t.durationEstimate = _t.duration; - } - if (!_t.isHTML5) { - _t.buffered = [{ - 'start': 0, - 'end': _t.duration - }]; - } - if ((_t.readyState !== 3 || _t.isHTML5) && _iO.whileloading) { - _iO.whileloading.apply(_t); - } - }; - this._whileplaying = function(nPosition, oPeakData, oWaveformDataLeft, oWaveformDataRight, oEQData) { - var _iO = _t._iO, - eqLeft; - if (isNaN(nPosition) || nPosition === null) { - return false; - } - _t.position = Math.max(0, nPosition); - _t._processOnPosition(); - if (!_t.isHTML5 && _fV > 8) { - if (_iO.usePeakData && typeof oPeakData !== 'undefined' && oPeakData) { - _t.peakData = { - left: oPeakData.leftPeak, - right: oPeakData.rightPeak - }; - } - if (_iO.useWaveformData && typeof oWaveformDataLeft !== 'undefined' && oWaveformDataLeft) { - _t.waveformData = { - left: oWaveformDataLeft.split(','), - right: oWaveformDataRight.split(',') - }; - } - if (_iO.useEQData) { - if (typeof oEQData !== 'undefined' && oEQData && oEQData.leftEQ) { - eqLeft = oEQData.leftEQ.split(','); - _t.eqData = eqLeft; - _t.eqData.left = eqLeft; - if (typeof oEQData.rightEQ !== 'undefined' && oEQData.rightEQ) { - _t.eqData.right = oEQData.rightEQ.split(','); - } - } - } - } - if (_t.playState === 1) { - if (!_t.isHTML5 && _fV === 8 && !_t.position && _t.isBuffering) { - _t._onbufferchange(0); - } - if (_iO.whileplaying) { - _iO.whileplaying.apply(_t); - } - } - return true; - }; - this._oncaptiondata = function(oData) { - _t.captiondata = oData; - if (_t._iO.oncaptiondata) { - _t._iO.oncaptiondata.apply(_t, [oData]); - } - }; - this._onmetadata = function(oMDProps, oMDData) { - var oData = {}, i, j; - for (i = 0, j = oMDProps.length; i < j; i++) { - oData[oMDProps[i]] = oMDData[i]; - } - _t.metadata = oData; - if (_t._iO.onmetadata) { - _t._iO.onmetadata.apply(_t); - } - }; - this._onid3 = function(oID3Props, oID3Data) { - var oData = [], i, j; - for (i = 0, j = oID3Props.length; i < j; i++) { - oData[oID3Props[i]] = oID3Data[i]; - } - _t.id3 = _mixin(_t.id3, oData); - if (_t._iO.onid3) { - _t._iO.onid3.apply(_t); - } - }; - this._onconnect = function(bSuccess) { - bSuccess = (bSuccess === 1); - _t.connected = bSuccess; - if (bSuccess) { - _t.failures = 0; - if (_idCheck(_t.id)) { - if (_t.getAutoPlay()) { - _t.play(undefined, _t.getAutoPlay()); - } else if (_t._iO.autoLoad) { - _t.load(); - } - } - if (_t._iO.onconnect) { - _t._iO.onconnect.apply(_t, [bSuccess]); - } - } - }; - this._ondataerror = function(sError) { - if (_t.playState > 0) { - if (_t._iO.ondataerror) { - _t._iO.ondataerror.apply(_t); - } - } - }; - }; - _getDocument = function() { - return (_doc.body || _doc._docElement || _doc.getElementsByTagName('div')[0]); - }; - _id = function(sID) { - return _doc.getElementById(sID); - }; - _mixin = function(oMain, oAdd) { - var o1 = (oMain || {}), o2, o; - o2 = (typeof oAdd === 'undefined' ? _s.defaultOptions : oAdd); - for (o in o2) { - if (o2.hasOwnProperty(o) && typeof o1[o] === 'undefined') { - if (typeof o2[o] !== 'object' || o2[o] === null) { - o1[o] = o2[o]; - } else { - o1[o] = _mixin(o1[o], o2[o]); - } - } - } - return o1; - }; - _extraOptions = { - 'onready': 1, - 'ontimeout': 1, - 'defaultOptions': 1, - 'flash9Options': 1, - 'movieStarOptions': 1 - }; - _assign = function(o, oParent) { - var i, - result = true, - hasParent = (typeof oParent !== 'undefined'), - setupOptions = _s.setupOptions, - extraOptions = _extraOptions; - for (i in o) { - if (o.hasOwnProperty(i)) { - if (typeof o[i] !== 'object' || o[i] === null || o[i] instanceof Array) { - if (hasParent && typeof extraOptions[oParent] !== 'undefined') { - _s[oParent][i] = o[i]; - } else if (typeof setupOptions[i] !== 'undefined') { - _s.setupOptions[i] = o[i]; - _s[i] = o[i]; - } else if (typeof extraOptions[i] === 'undefined') { - _complain(_str((typeof _s[i] === 'undefined' ? 'setupUndef' : 'setupError'), i), 2); - result = false; - } else { - if (_s[i] instanceof Function) { - _s[i].apply(_s, (o[i] instanceof Array? o[i] : [o[i]])); - } else { - _s[i] = o[i]; - } - } - } else { - if (typeof extraOptions[i] === 'undefined') { - _complain(_str((typeof _s[i] === 'undefined' ? 'setupUndef' : 'setupError'), i), 2); - result = false; - } else { - return _assign(o[i], i); - } - } - } - } - return result; - }; - function _preferFlashCheck(kind) { - return (_s.preferFlash && _hasFlash && !_s.ignoreFlash && (typeof _s.flash[kind] !== 'undefined' && _s.flash[kind])); - } - _event = (function() { - var old = (_win.attachEvent), - evt = { - add: (old?'attachEvent':'addEventListener'), - remove: (old?'detachEvent':'removeEventListener') - }; - function getArgs(oArgs) { - var args = _slice.call(oArgs), - len = args.length; - if (old) { - args[1] = 'on' + args[1]; - if (len > 3) { - args.pop(); - } - } else if (len === 3) { - args.push(false); - } - return args; - } - function apply(args, sType) { - var element = args.shift(), - method = [evt[sType]]; - if (old) { - element[method](args[0], args[1]); - } else { - element[method].apply(element, args); - } - } - function add() { - apply(getArgs(arguments), 'add'); - } - function remove() { - apply(getArgs(arguments), 'remove'); - } - return { - 'add': add, - 'remove': remove - }; - }()); - function _html5_event(oFn) { - return function(e) { - var t = this._t, - result; - if (!t || !t._a) { - result = null; - } else { - result = oFn.call(this, e); - } - return result; - }; - } - _html5_events = { - abort: _html5_event(function() { - }), - canplay: _html5_event(function() { - var t = this._t, - position1K; - if (t._html5_canplay) { - return true; - } - t._html5_canplay = true; - t._onbufferchange(0); - position1K = (typeof t._iO.position !== 'undefined' && !isNaN(t._iO.position)?t._iO.position/1000:null); - if (t.position && this.currentTime !== position1K) { - try { - this.currentTime = position1K; - } catch(ee) { - } - } - if (t._iO._oncanplay) { - t._iO._oncanplay(); - } - }), - canplaythrough: _html5_event(function() { - var t = this._t; - if (!t.loaded) { - t._onbufferchange(0); - t._whileloading(t.bytesLoaded, t.bytesTotal, t._get_html5_duration()); - t._onload(true); - } - }), - ended: _html5_event(function() { - var t = this._t; - t._onfinish(); - }), - error: _html5_event(function() { - this._t._onload(false); - }), - loadeddata: _html5_event(function() { - var t = this._t; - if (!t._loaded && !_isSafari) { - t.duration = t._get_html5_duration(); - } - }), - loadedmetadata: _html5_event(function() { - }), - loadstart: _html5_event(function() { - this._t._onbufferchange(1); - }), - play: _html5_event(function() { - this._t._onbufferchange(0); - }), - playing: _html5_event(function() { - this._t._onbufferchange(0); - }), - progress: _html5_event(function(e) { - var t = this._t, - i, j, str, buffered = 0, - isProgress = (e.type === 'progress'), - ranges = e.target.buffered, - loaded = (e.loaded||0), - total = (e.total||1), - scale = 1000; - t.buffered = []; - if (ranges && ranges.length) { - for (i=0, j=ranges.length; i= 0; i--) { - support['audio/'+aF[item].related[i]] = support[item]; - _s.html5[aF[item].related[i]] = support[item]; - _s.flash[aF[item].related[i]] = support[item]; - } - } - } - } - support.canPlayType = (a?_cp:null); - _s.html5 = _mixin(_s.html5, support); - return true; - }; - _strings = { - }; - _str = function() { - }; - _loopFix = function(sOpt) { - if (_fV === 8 && sOpt.loops > 1 && sOpt.stream) { - sOpt.stream = false; - } - return sOpt; - }; - _policyFix = function(sOpt, sPre) { - if (sOpt && !sOpt.usePolicyFile && (sOpt.onid3 || sOpt.usePeakData || sOpt.useWaveformData || sOpt.useEQData)) { - sOpt.usePolicyFile = true; - } - return sOpt; - }; - _complain = function(sMsg) { - }; - _doNothing = function() { - return false; - }; - _disableObject = function(o) { - var oProp; - for (oProp in o) { - if (o.hasOwnProperty(oProp) && typeof o[oProp] === 'function') { - o[oProp] = _doNothing; - } - } - oProp = null; - }; - _failSafely = function(bNoDisable) { - if (typeof bNoDisable === 'undefined') { - bNoDisable = false; - } - if (_disabled || bNoDisable) { - _s.disable(bNoDisable); - } - }; - _normalizeMovieURL = function(smURL) { - var urlParams = null, url; - if (smURL) { - if (smURL.match(/\.swf(\?.*)?$/i)) { - urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf('.swf?') + 4); - if (urlParams) { - return smURL; - } - } else if (smURL.lastIndexOf('/') !== smURL.length - 1) { - smURL += '/'; - } - } - url = (smURL && smURL.lastIndexOf('/') !== - 1 ? smURL.substr(0, smURL.lastIndexOf('/') + 1) : './') + _s.movieURL; - if (_s.noSWFCache) { - url += ('?ts=' + new Date().getTime()); - } - return url; - }; - _setVersionInfo = function() { - _fV = parseInt(_s.flashVersion, 10); - if (_fV !== 8 && _fV !== 9) { - _s.flashVersion = _fV = _defaultFlashVersion; - } - var isDebug = (_s.debugMode || _s.debugFlash?'_debug.swf':'.swf'); - if (_s.useHTML5Audio && !_s.html5Only && _s.audioFormats.mp4.required && _fV < 9) { - _s.flashVersion = _fV = 9; - } - _s.version = _s.versionNumber + (_s.html5Only?' (HTML5-only mode)':(_fV === 9?' (AS3/Flash 9)':' (AS2/Flash 8)')); - if (_fV > 8) { - _s.defaultOptions = _mixin(_s.defaultOptions, _s.flash9Options); - _s.features.buffering = true; - _s.defaultOptions = _mixin(_s.defaultOptions, _s.movieStarOptions); - _s.filePatterns.flash9 = new RegExp('\\.(mp3|' + _netStreamTypes.join('|') + ')(\\?.*)?$', 'i'); - _s.features.movieStar = true; - } else { - _s.features.movieStar = false; - } - _s.filePattern = _s.filePatterns[(_fV !== 8?'flash9':'flash8')]; - _s.movieURL = (_fV === 8?'soundmanager2.swf':'soundmanager2_flash9.swf').replace('.swf', isDebug); - _s.features.peakData = _s.features.waveformData = _s.features.eqData = (_fV > 8); - }; - _setPolling = function(bPolling, bHighPerformance) { - if (!_flash) { - return false; - } - _flash._setPolling(bPolling, bHighPerformance); - }; - _initDebug = function() { - if (_s.debugURLParam.test(_wl)) { - _s.debugMode = true; - } - }; - _idCheck = this.getSoundById; - _getSWFCSS = function() { - var css = []; - if (_s.debugMode) { - css.push(_swfCSS.sm2Debug); - } - if (_s.debugFlash) { - css.push(_swfCSS.flashDebug); - } - if (_s.useHighPerformance) { - css.push(_swfCSS.highPerf); - } - return css.join(' '); - }; - _flashBlockHandler = function() { - var name = _str('fbHandler'), - p = _s.getMoviePercent(), - css = _swfCSS, - error = {type:'FLASHBLOCK'}; - if (_s.html5Only) { - return false; - } - if (!_s.ok()) { - if (_needsFlash) { - _s.oMC.className = _getSWFCSS() + ' ' + css.swfDefault + ' ' + (p === null?css.swfTimedout:css.swfError); - } - _s.didFlashBlock = true; - _processOnEvents({type:'ontimeout', ignoreInit:true, error:error}); - _catchError(error); - } else { - if (_s.oMC) { - _s.oMC.className = [_getSWFCSS(), css.swfDefault, css.swfLoaded + (_s.didFlashBlock?' '+css.swfUnblocked:'')].join(' '); - } - } - }; - _addOnEvent = function(sType, oMethod, oScope) { - if (typeof _on_queue[sType] === 'undefined') { - _on_queue[sType] = []; - } - _on_queue[sType].push({ - 'method': oMethod, - 'scope': (oScope || null), - 'fired': false - }); - }; - _processOnEvents = function(oOptions) { - if (!oOptions) { - oOptions = { - type: (_s.ok() ? 'onready' : 'ontimeout') - }; - } - if (!_didInit && oOptions && !oOptions.ignoreInit) { - return false; - } - if (oOptions.type === 'ontimeout' && (_s.ok() || (_disabled && !oOptions.ignoreInit))) { - return false; - } - var status = { - success: (oOptions && oOptions.ignoreInit?_s.ok():!_disabled) - }, - srcQueue = (oOptions && oOptions.type?_on_queue[oOptions.type]||[]:[]), - queue = [], i, j, - args = [status], - canRetry = (_needsFlash && _s.useFlashBlock && !_s.ok()); - if (oOptions.error) { - args[0].error = oOptions.error; - } - for (i = 0, j = srcQueue.length; i < j; i++) { - if (srcQueue[i].fired !== true) { - queue.push(srcQueue[i]); - } - } - if (queue.length) { - for (i = 0, j = queue.length; i < j; i++) { - if (queue[i].scope) { - queue[i].method.apply(queue[i].scope, args); - } else { - queue[i].method.apply(this, args); - } - if (!canRetry) { - queue[i].fired = true; - } - } - } - return true; - }; - _initUserOnload = function() { - _win.setTimeout(function() { - if (_s.useFlashBlock) { - _flashBlockHandler(); - } - _processOnEvents(); - if (typeof _s.onload === 'function') { - _s.onload.apply(_win); - } - if (_s.waitForWindowLoad) { - _event.add(_win, 'load', _initUserOnload); - } - },1); - }; - _detectFlash = function() { - if (typeof _hasFlash !== 'undefined') { - return _hasFlash; - } - var hasPlugin = false, n = navigator, nP = n.plugins, obj, type, types, AX = _win.ActiveXObject; - if (nP && nP.length) { - type = 'application/x-shockwave-flash'; - types = n.mimeTypes; - if (types && types[type] && types[type].enabledPlugin && types[type].enabledPlugin.description) { - hasPlugin = true; - } - } else if (typeof AX !== 'undefined') { - try { - obj = new AX('ShockwaveFlash.ShockwaveFlash'); - } catch(e) { - } - hasPlugin = (!!obj); - } - _hasFlash = hasPlugin; - return hasPlugin; - }; - _featureCheck = function() { - var needsFlash, - item, - result = true, - formats = _s.audioFormats, - isSpecial = (_is_iDevice && !!(_ua.match(/os (1|2|3_0|3_1)/i))); - if (isSpecial) { - _s.hasHTML5 = false; - _s.html5Only = true; - if (_s.oMC) { - _s.oMC.style.display = 'none'; - } - result = false; - } else { - if (_s.useHTML5Audio) { - if (!_s.html5 || !_s.html5.canPlayType) { - _s.hasHTML5 = false; - } - } - } - if (_s.useHTML5Audio && _s.hasHTML5) { - for (item in formats) { - if (formats.hasOwnProperty(item)) { - if ((formats[item].required && !_s.html5.canPlayType(formats[item].type)) || (_s.preferFlash && (_s.flash[item] || _s.flash[formats[item].type]))) { - needsFlash = true; - } - } - } - } - if (_s.ignoreFlash) { - needsFlash = false; - } - _s.html5Only = (_s.hasHTML5 && _s.useHTML5Audio && !needsFlash); - return (!_s.html5Only); - }; - _parseURL = function(url) { - var i, j, urlResult = 0, result; - if (url instanceof Array) { - for (i=0, j=url.length; i= 0; i--) { - if (_s.sounds[_s.soundIDs[i]].isHTML5 && _s.sounds[_s.soundIDs[i]]._hasTimer) { - _s.sounds[_s.soundIDs[i]]._onTimer(); - } - } - }; - _catchError = function(options) { - options = (typeof options !== 'undefined' ? options : {}); - if (typeof _s.onerror === 'function') { - _s.onerror.apply(_win, [{type:(typeof options.type !== 'undefined' ? options.type : null)}]); - } - if (typeof options.fatal !== 'undefined' && options.fatal) { - _s.disable(); - } - }; - _badSafariFix = function() { - if (!_isBadSafari || !_detectFlash()) { - return false; - } - var aF = _s.audioFormats, i, item; - for (item in aF) { - if (aF.hasOwnProperty(item)) { - if (item === 'mp3' || item === 'mp4') { - _s.html5[item] = false; - if (aF[item] && aF[item].related) { - for (i = aF[item].related.length-1; i >= 0; i--) { - _s.html5[aF[item].related[i]] = false; - } - } - } - } - } - }; - this._setSandboxType = function(sandboxType) { - }; - this._externalInterfaceOK = function(flashDate, swfVersion) { - if (_s.swfLoaded) { - return false; - } - var e, eiTime = new Date().getTime(); - _s.swfLoaded = true; - _tryInitOnFocus = false; - if (_isBadSafari) { - _badSafariFix(); - } - setTimeout(_init, _isIE ? 100 : 1); - }; - _createMovie = function(smID, smURL) { - if (_didAppend && _appendSuccess) { - return false; - } - function _initMsg() { - } - if (_s.html5Only) { - _setVersionInfo(); - _initMsg(); - _s.oMC = _id(_s.movieID); - _init(); - _didAppend = true; - _appendSuccess = true; - return false; - } - var remoteURL = (smURL || _s.url), - localURL = (_s.altURL || remoteURL), - swfTitle = 'JS/Flash audio component (SoundManager 2)', - oTarget = _getDocument(), - extraClass = _getSWFCSS(), - isRTL = null, - html = _doc.getElementsByTagName('html')[0], - oEmbed, oMovie, tmp, movieHTML, oEl, s, x, sClass; - isRTL = (html && html.dir && html.dir.match(/rtl/i)); - smID = (typeof smID === 'undefined'?_s.id:smID); - function param(name, value) { - return ''; - } - _setVersionInfo(); - _s.url = _normalizeMovieURL(_overHTTP?remoteURL:localURL); - smURL = _s.url; - _s.wmode = (!_s.wmode && _s.useHighPerformance ? 'transparent' : _s.wmode); - if (_s.wmode !== null && (_ua.match(/msie 8/i) || (!_isIE && !_s.useHighPerformance)) && navigator.platform.match(/win32|win64/i)) { - _s.wmode = null; - } - oEmbed = { - 'name': smID, - 'id': smID, - 'src': smURL, - 'quality': 'high', - 'allowScriptAccess': _s.allowScriptAccess, - 'bgcolor': _s.bgColor, - 'pluginspage': _http+'www.macromedia.com/go/getflashplayer', - 'title': swfTitle, - 'type': 'application/x-shockwave-flash', - 'wmode': _s.wmode, - 'hasPriority': 'true' - }; - if (_s.debugFlash) { - oEmbed.FlashVars = 'debug=1'; - } - if (!_s.wmode) { - delete oEmbed.wmode; - } - if (_isIE) { - oMovie = _doc.createElement('div'); - movieHTML = [ - '', - param('movie', smURL), - param('AllowScriptAccess', _s.allowScriptAccess), - param('quality', oEmbed.quality), - (_s.wmode? param('wmode', _s.wmode): ''), - param('bgcolor', _s.bgColor), - param('hasPriority', 'true'), - (_s.debugFlash ? param('FlashVars', oEmbed.FlashVars) : ''), - '' - ].join(''); - } else { - oMovie = _doc.createElement('embed'); - for (tmp in oEmbed) { - if (oEmbed.hasOwnProperty(tmp)) { - oMovie.setAttribute(tmp, oEmbed[tmp]); - } - } - } - _initDebug(); - extraClass = _getSWFCSS(); - oTarget = _getDocument(); - if (oTarget) { - _s.oMC = (_id(_s.movieID) || _doc.createElement('div')); - if (!_s.oMC.id) { - _s.oMC.id = _s.movieID; - _s.oMC.className = _swfCSS.swfDefault + ' ' + extraClass; - s = null; - oEl = null; - if (!_s.useFlashBlock) { - if (_s.useHighPerformance) { - s = { - 'position': 'fixed', - 'width': '8px', - 'height': '8px', - 'bottom': '0px', - 'left': '0px', - 'overflow': 'hidden' - }; - } else { - s = { - 'position': 'absolute', - 'width': '6px', - 'height': '6px', - 'top': '-9999px', - 'left': '-9999px' - }; - if (isRTL) { - s.left = Math.abs(parseInt(s.left,10))+'px'; - } - } - } - if (_isWebkit) { - _s.oMC.style.zIndex = 10000; - } - if (!_s.debugFlash) { - for (x in s) { - if (s.hasOwnProperty(x)) { - _s.oMC.style[x] = s[x]; - } - } - } - try { - if (!_isIE) { - _s.oMC.appendChild(oMovie); - } - oTarget.appendChild(_s.oMC); - if (_isIE) { - oEl = _s.oMC.appendChild(_doc.createElement('div')); - oEl.className = _swfCSS.swfBox; - oEl.innerHTML = movieHTML; - } - _appendSuccess = true; - } catch(e) { - throw new Error(_str('domError')+' \n'+e.toString()); - } - } else { - sClass = _s.oMC.className; - _s.oMC.className = (sClass?sClass+' ':_swfCSS.swfDefault) + (extraClass?' '+extraClass:''); - _s.oMC.appendChild(oMovie); - if (_isIE) { - oEl = _s.oMC.appendChild(_doc.createElement('div')); - oEl.className = _swfCSS.swfBox; - oEl.innerHTML = movieHTML; - } - _appendSuccess = true; - } - } - _didAppend = true; - _initMsg(); - return true; - }; - _initMovie = function() { - if (_s.html5Only) { - _createMovie(); - return false; - } - if (_flash) { - return false; - } - if (!_s.url) { - return false; - } - _flash = _s.getMovie(_s.id); - if (!_flash) { - if (!_oRemoved) { - _createMovie(_s.id, _s.url); - } else { - if (!_isIE) { - _s.oMC.appendChild(_oRemoved); - } else { - _s.oMC.innerHTML = _oRemovedHTML; - } - _oRemoved = null; - _didAppend = true; - } - _flash = _s.getMovie(_s.id); - } - if (typeof _s.oninitmovie === 'function') { - setTimeout(_s.oninitmovie, 1); - } - return true; - }; - _delayWaitForEI = function() { - setTimeout(_waitForEI, 1000); - }; - _waitForEI = function() { - var p, - loadIncomplete = false; - if (!_s.url) { - return false; - } - if (_waitingForEI) { - return false; - } - _waitingForEI = true; - _event.remove(_win, 'load', _delayWaitForEI); - if (_tryInitOnFocus && !_isFocused) { - return false; - } - if (!_didInit) { - p = _s.getMoviePercent(); - if (p > 0 && p < 100) { - loadIncomplete = true; - } - } - setTimeout(function() { - p = _s.getMoviePercent(); - if (loadIncomplete) { - _waitingForEI = false; - _win.setTimeout(_delayWaitForEI, 1); - return false; - } - if (!_didInit && _okToDisable) { - if (p === null) { - if (_s.useFlashBlock || _s.flashLoadTimeout === 0) { - if (_s.useFlashBlock) { - _flashBlockHandler(); - } - } else { - _failSafely(true); - } - } else { - if (_s.flashLoadTimeout === 0) { - } else { - _failSafely(true); - } - } - } - }, _s.flashLoadTimeout); - }; - _handleFocus = function() { - function cleanup() { - _event.remove(_win, 'focus', _handleFocus); - } - if (_isFocused || !_tryInitOnFocus) { - cleanup(); - return true; - } - _okToDisable = true; - _isFocused = true; - _waitingForEI = false; - _delayWaitForEI(); - cleanup(); - return true; - }; - _showSupport = function() { - }; - _initComplete = function(bNoDisable) { - if (_didInit) { - return false; - } - if (_s.html5Only) { - _didInit = true; - _initUserOnload(); - return true; - } - var wasTimeout = (_s.useFlashBlock && _s.flashLoadTimeout && !_s.getMoviePercent()), - result = true, - error; - if (!wasTimeout) { - _didInit = true; - if (_disabled) { - error = {type: (!_hasFlash && _needsFlash ? 'NO_FLASH' : 'INIT_TIMEOUT')}; - } - } - if (_disabled || bNoDisable) { - if (_s.useFlashBlock && _s.oMC) { - _s.oMC.className = _getSWFCSS() + ' ' + (_s.getMoviePercent() === null?_swfCSS.swfTimedout:_swfCSS.swfError); - } - _processOnEvents({type:'ontimeout', error:error, ignoreInit: true}); - _catchError(error); - result = false; - } else { - } - if (!_disabled) { - if (_s.waitForWindowLoad && !_windowLoaded) { - _event.add(_win, 'load', _initUserOnload); - } else { - _initUserOnload(); - } - } - return result; - }; - _setProperties = function() { - var i, - o = _s.setupOptions; - for (i in o) { - if (o.hasOwnProperty(i)) { - if (typeof _s[i] === 'undefined') { - _s[i] = o[i]; - } else if (_s[i] !== o[i]) { - _s.setupOptions[i] = _s[i]; - } - } - } - }; - _init = function() { - if (_didInit) { - return false; - } - function _cleanup() { - _event.remove(_win, 'load', _s.beginDelayedInit); - } - if (_s.html5Only) { - if (!_didInit) { - _cleanup(); - _s.enabled = true; - _initComplete(); - } - return true; - } - _initMovie(); - try { - _flash._externalInterfaceTest(false); - _setPolling(true, (_s.flashPollingInterval || (_s.useHighPerformance ? 10 : 50))); - if (!_s.debugMode) { - _flash._disableDebug(); - } - _s.enabled = true; - if (!_s.html5Only) { - _event.add(_win, 'unload', _doNothing); - } - } catch(e) { - _catchError({type:'JS_TO_FLASH_EXCEPTION', fatal:true}); - _failSafely(true); - _initComplete(); - return false; - } - _initComplete(); - _cleanup(); - return true; - }; - _domContentLoaded = function() { - if (_didDCLoaded) { - return false; - } - _didDCLoaded = true; - _setProperties(); - _initDebug(); - if (!_hasFlash && _s.hasHTML5) { - _s.setup({ - 'useHTML5Audio': true, - 'preferFlash': false - }); - } - _testHTML5(); - _s.html5.usingFlash = _featureCheck(); - _needsFlash = _s.html5.usingFlash; - _showSupport(); - if (!_hasFlash && _needsFlash) { - _s.setup({ - 'flashLoadTimeout': 1 - }); - } - if (_doc.removeEventListener) { - _doc.removeEventListener('DOMContentLoaded', _domContentLoaded, false); - } - _initMovie(); - return true; - }; - _domContentLoadedIE = function() { - if (_doc.readyState === 'complete') { - _domContentLoaded(); - _doc.detachEvent('onreadystatechange', _domContentLoadedIE); - } - return true; - }; - _winOnLoad = function() { - _windowLoaded = true; - _event.remove(_win, 'load', _winOnLoad); - }; - _detectFlash(); - _event.add(_win, 'focus', _handleFocus); - _event.add(_win, 'load', _delayWaitForEI); - _event.add(_win, 'load', _winOnLoad); - if (_doc.addEventListener) { - _doc.addEventListener('DOMContentLoaded', _domContentLoaded, false); - } else if (_doc.attachEvent) { - _doc.attachEvent('onreadystatechange', _domContentLoadedIE); - } else { - _catchError({type:'NO_DOM2_EVENTS', fatal:true}); - } -} -// SM2_DEFER details: http://www.schillmania.com/projects/soundmanager2/doc/getstarted/#lazy-loading -if (typeof SM2_DEFER === 'undefined' || !SM2_DEFER) { - soundManager = new SoundManager(); -} -window.SoundManager = SoundManager; -window.soundManager = soundManager; -}(window)); \ No newline at end of file diff --git a/timeside/static/timeside/js/libs/soundmanager2.js b/timeside/static/timeside/js/libs/soundmanager2.js deleted file mode 100644 index d9d4422..0000000 --- a/timeside/static/timeside/js/libs/soundmanager2.js +++ /dev/null @@ -1,5530 +0,0 @@ -/** @license - * - * SoundManager 2: JavaScript Sound for the Web - * ---------------------------------------------- - * http://schillmania.com/projects/soundmanager2/ - * - * Copyright (c) 2007, Scott Schiller. All rights reserved. - * Code provided under the BSD License: - * http://schillmania.com/projects/soundmanager2/license.txt - * - * V2.97a.20120916 - */ - -/*global window, SM2_DEFER, sm2Debugger, console, document, navigator, setTimeout, setInterval, clearInterval, Audio */ -/*jslint regexp: true, sloppy: true, white: true, nomen: true, plusplus: true */ - -/** - * About this file - * --------------- - * This is the fully-commented source version of the SoundManager 2 API, - * recommended for use during development and testing. - * - * See soundmanager2-nodebug-jsmin.js for an optimized build (~11KB with gzip.) - * http://schillmania.com/projects/soundmanager2/doc/getstarted/#basic-inclusion - * Alternately, serve this file with gzip for 75% compression savings (~30KB over HTTP.) - * - * You may notice and comments in this source; these are delimiters for - * debug blocks which are removed in the -nodebug builds, further optimizing code size. - * - * Also, as you may note: Whoa, reliable cross-platform/device audio support is hard! ;) - */ - -(function(window) { - -var soundManager = null; - -/** - * The SoundManager constructor. - * - * @constructor - * @param {string} smURL Optional: Path to SWF files - * @param {string} smID Optional: The ID to use for the SWF container element - * @this {SoundManager} - * @return {SoundManager} The new SoundManager instance - */ - -function SoundManager(smURL, smID) { - - /** - * soundManager configuration options list - * defines top-level configuration properties to be applied to the soundManager instance (eg. soundManager.flashVersion) - * to set these properties, use the setup() method - eg., soundManager.setup({url: '/swf/', flashVersion: 9}) - */ - - this.setupOptions = { - - 'url': (smURL || null), // path (directory) where SoundManager 2 SWFs exist, eg., /path/to/swfs/ - 'flashVersion': 8, // flash build to use (8 or 9.) Some API features require 9. - 'debugMode': true, // enable debugging output (console.log() with HTML fallback) - 'debugFlash': false, // enable debugging output inside SWF, troubleshoot Flash/browser issues - 'useConsole': true, // use console.log() if available (otherwise, writes to #soundmanager-debug element) - 'consoleOnly': true, // if console is being used, do not create/write to #soundmanager-debug - 'waitForWindowLoad': false, // force SM2 to wait for window.onload() before trying to call soundManager.onload() - 'bgColor': '#ffffff', // SWF background color. N/A when wmode = 'transparent' - 'useHighPerformance': false, // position:fixed flash movie can help increase js/flash speed, minimize lag - 'flashPollingInterval': null, // msec affecting whileplaying/loading callback frequency. If null, default of 50 msec is used. - 'html5PollingInterval': null, // msec affecting whileplaying() for HTML5 audio, excluding mobile devices. If null, native HTML5 update events are used. - 'flashLoadTimeout': 1000, // msec to wait for flash movie to load before failing (0 = infinity) - 'wmode': null, // flash rendering mode - null, 'transparent', or 'opaque' (last two allow z-index to work) - 'allowScriptAccess': 'always', // for scripting the SWF (object/embed property), 'always' or 'sameDomain' - 'useFlashBlock': false, // *requires flashblock.css, see demos* - allow recovery from flash blockers. Wait indefinitely and apply timeout CSS to SWF, if applicable. - 'useHTML5Audio': true, // use HTML5 Audio() where API is supported (most Safari, Chrome versions), Firefox (no MP3/MP4.) Ideally, transparent vs. Flash API where possible. - 'html5Test': /^(probably|maybe)$/i, // HTML5 Audio() format support test. Use /^probably$/i; if you want to be more conservative. - 'preferFlash': true, // overrides useHTML5audio. if true and flash support present, will try to use flash for MP3/MP4 as needed since HTML5 audio support is still quirky in browsers. - 'noSWFCache': false // if true, appends ?ts={date} to break aggressive SWF caching. - - }; - - this.defaultOptions = { - - /** - * the default configuration for sound objects made with createSound() and related methods - * eg., volume, auto-load behaviour and so forth - */ - - 'autoLoad': false, // enable automatic loading (otherwise .load() will be called on demand with .play(), the latter being nicer on bandwidth - if you want to .load yourself, you also can) - 'autoPlay': false, // enable playing of file as soon as possible (much faster if "stream" is true) - 'from': null, // position to start playback within a sound (msec), default = beginning - 'loops': 1, // how many times to repeat the sound (position will wrap around to 0, setPosition() will break out of loop when >0) - 'onid3': null, // callback function for "ID3 data is added/available" - 'onload': null, // callback function for "load finished" - 'whileloading': null, // callback function for "download progress update" (X of Y bytes received) - 'onplay': null, // callback for "play" start - 'onpause': null, // callback for "pause" - 'onresume': null, // callback for "resume" (pause toggle) - 'whileplaying': null, // callback during play (position update) - 'onposition': null, // object containing times and function callbacks for positions of interest - 'onstop': null, // callback for "user stop" - 'onfailure': null, // callback function for when playing fails - 'onfinish': null, // callback function for "sound finished playing" - 'multiShot': true, // let sounds "restart" or layer on top of each other when played multiple times, rather than one-shot/one at a time - 'multiShotEvents': false, // fire multiple sound events (currently onfinish() only) when multiShot is enabled - 'position': null, // offset (milliseconds) to seek to within loaded sound data. - 'pan': 0, // "pan" settings, left-to-right, -100 to 100 - 'stream': true, // allows playing before entire file has loaded (recommended) - 'to': null, // position to end playback within a sound (msec), default = end - 'type': null, // MIME-like hint for file pattern / canPlay() tests, eg. audio/mp3 - 'usePolicyFile': false, // enable crossdomain.xml request for audio on remote domains (for ID3/waveform access) - 'volume': 100 // self-explanatory. 0-100, the latter being the max. - - }; - - this.flash9Options = { - - /** - * flash 9-only options, - * merged into defaultOptions if flash 9 is being used - */ - - 'isMovieStar': null, // "MovieStar" MPEG4 audio mode. Null (default) = auto detect MP4, AAC etc. based on URL. true = force on, ignore URL - 'usePeakData': false, // enable left/right channel peak (level) data - 'useWaveformData': false, // enable sound spectrum (raw waveform data) - NOTE: May increase CPU load. - 'useEQData': false, // enable sound EQ (frequency spectrum data) - NOTE: May increase CPU load. - 'onbufferchange': null, // callback for "isBuffering" property change - 'ondataerror': null // callback for waveform/eq data access error (flash playing audio in other tabs/domains) - - }; - - this.movieStarOptions = { - - /** - * flash 9.0r115+ MPEG4 audio options, - * merged into defaultOptions if flash 9+movieStar mode is enabled - */ - - 'bufferTime': 3, // seconds of data to buffer before playback begins (null = flash default of 0.1 seconds - if AAC playback is gappy, try increasing.) - 'serverURL': null, // rtmp: FMS or FMIS server to connect to, required when requesting media via RTMP or one of its variants - 'onconnect': null, // rtmp: callback for connection to flash media server - 'duration': null // rtmp: song duration (msec) - - }; - - this.audioFormats = { - - /** - * determines HTML5 support + flash requirements. - * if no support (via flash and/or HTML5) for a "required" format, SM2 will fail to start. - * flash fallback is used for MP3 or MP4 if HTML5 can't play it (or if preferFlash = true) - */ - - 'mp3': { - 'type': ['audio/mpeg; codecs="mp3"', 'audio/mpeg', 'audio/mp3', 'audio/MPA', 'audio/mpa-robust'], - 'required': true - }, - - 'mp4': { - 'related': ['aac','m4a','m4b'], // additional formats under the MP4 container - 'type': ['audio/mp4; codecs="mp4a.40.2"', 'audio/aac', 'audio/x-m4a', 'audio/MP4A-LATM', 'audio/mpeg4-generic'], - 'required': false - }, - - 'ogg': { - 'type': ['audio/ogg; codecs=vorbis'], - 'required': false - }, - - 'wav': { - 'type': ['audio/wav; codecs="1"', 'audio/wav', 'audio/wave', 'audio/x-wav'], - 'required': false - } - - }; - - // HTML attributes (id + class names) for the SWF container - - this.movieID = 'sm2-container'; - this.id = (smID || 'sm2movie'); - - this.debugID = 'soundmanager-debug'; - this.debugURLParam = /([#?&])debug=1/i; - - // dynamic attributes - - this.versionNumber = 'V2.97a.20120916'; - this.version = null; - this.movieURL = null; - this.altURL = null; - this.swfLoaded = false; - this.enabled = false; - this.oMC = null; - this.sounds = {}; - this.soundIDs = []; - this.muted = false; - this.didFlashBlock = false; - this.filePattern = null; - - this.filePatterns = { - - 'flash8': /\.mp3(\?.*)?$/i, - 'flash9': /\.mp3(\?.*)?$/i - - }; - - // support indicators, set at init - - this.features = { - - 'buffering': false, - 'peakData': false, - 'waveformData': false, - 'eqData': false, - 'movieStar': false - - }; - - // flash sandbox info, used primarily in troubleshooting - - this.sandbox = { - - // - 'type': null, - 'types': { - 'remote': 'remote (domain-based) rules', - 'localWithFile': 'local with file access (no internet access)', - 'localWithNetwork': 'local with network (internet access only, no local access)', - 'localTrusted': 'local, trusted (local+internet access)' - }, - 'description': null, - 'noRemote': null, - 'noLocal': null - // - - }; - - /** - * basic HTML5 Audio() support test - * try...catch because of IE 9 "not implemented" nonsense - * https://github.com/Modernizr/Modernizr/issues/224 - */ - - this.hasHTML5 = (function() { - try { - // new Audio(null) for stupid Opera 9.64 case, which throws not_enough_arguments exception otherwise. - return (typeof Audio !== 'undefined' && typeof (_isOpera && opera.version() < 10 ? new Audio(null) : new Audio()).canPlayType !== 'undefined'); - } catch(e) { - return false; - } - }()); - - /** - * format support (html5/flash) - * stores canPlayType() results based on audioFormats. - * eg. { mp3: boolean, mp4: boolean } - * treat as read-only. - */ - - this.html5 = { - 'usingFlash': null // set if/when flash fallback is needed - }; - - // file type support hash - this.flash = {}; - - // determined at init time - this.html5Only = false; - - // used for special cases (eg. iPad/iPhone/palm OS?) - this.ignoreFlash = false; - - /** - * a few private internals (OK, a lot. :D) - */ - - var SMSound, - _s = this, _flash = null, _sm = 'soundManager', _smc = _sm+'::', _h5 = 'HTML5::', _id, _ua = navigator.userAgent, _win = window, _wl = _win.location.href.toString(), _doc = document, _doNothing, _setProperties, _init, _fV, _on_queue = [], _debugOpen = true, _debugTS, _didAppend = false, _appendSuccess = false, _didInit = false, _disabled = false, _windowLoaded = false, _wDS, _wdCount = 0, _initComplete, _mixin, _assign, _extraOptions, _addOnEvent, _processOnEvents, _initUserOnload, _delayWaitForEI, _waitForEI, _setVersionInfo, _handleFocus, _strings, _initMovie, _domContentLoaded, _winOnLoad, _didDCLoaded, _getDocument, _createMovie, _catchError, _setPolling, _initDebug, _debugLevels = ['log', 'info', 'warn', 'error'], _defaultFlashVersion = 8, _disableObject, _failSafely, _normalizeMovieURL, _oRemoved = null, _oRemovedHTML = null, _str, _flashBlockHandler, _getSWFCSS, _swfCSS, _toggleDebug, _loopFix, _policyFix, _complain, _idCheck, _waitingForEI = false, _initPending = false, _startTimer, _stopTimer, _timerExecute, _h5TimerCount = 0, _h5IntervalTimer = null, _parseURL, - _needsFlash = null, _featureCheck, _html5OK, _html5CanPlay, _html5Ext, _html5Unload, _domContentLoadedIE, _testHTML5, _event, _slice = Array.prototype.slice, _useGlobalHTML5Audio = false, _hasFlash, _detectFlash, _badSafariFix, _html5_events, _showSupport, - _is_iDevice = _ua.match(/(ipad|iphone|ipod)/i), _isIE = _ua.match(/msie/i), _isWebkit = _ua.match(/webkit/i), _isSafari = (_ua.match(/safari/i) && !_ua.match(/chrome/i)), _isOpera = (_ua.match(/opera/i)), - _mobileHTML5 = (_ua.match(/(mobile|pre\/|xoom)/i) || _is_iDevice), - _isBadSafari = (!_wl.match(/usehtml5audio/i) && !_wl.match(/sm2\-ignorebadua/i) && _isSafari && !_ua.match(/silk/i) && _ua.match(/OS X 10_6_([3-7])/i)), // Safari 4 and 5 (excluding Kindle Fire, "Silk") occasionally fail to load/play HTML5 audio on Snow Leopard 10.6.3 through 10.6.7 due to bug(s) in QuickTime X and/or other underlying frameworks. :/ Confirmed bug. https://bugs.webkit.org/show_bug.cgi?id=32159 - _hasConsole = (typeof console !== 'undefined' && typeof console.log !== 'undefined'), _isFocused = (typeof _doc.hasFocus !== 'undefined'?_doc.hasFocus():null), _tryInitOnFocus = (_isSafari && (typeof _doc.hasFocus === 'undefined' || !_doc.hasFocus())), _okToDisable = !_tryInitOnFocus, _flashMIME = /(mp3|mp4|mpa|m4a|m4b)/i, - _emptyURL = 'about:blank', // safe URL to unload, or load nothing from (flash 8 + most HTML5 UAs) - _overHTTP = (_doc.location?_doc.location.protocol.match(/http/i):null), - _http = (!_overHTTP ? 'http:/'+'/' : ''), - // mp3, mp4, aac etc. - _netStreamMimeTypes = /^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i, - // Flash v9.0r115+ "moviestar" formats - _netStreamTypes = ['mpeg4', 'aac', 'flv', 'mov', 'mp4', 'm4v', 'f4v', 'm4a', 'm4b', 'mp4v', '3gp', '3g2'], - _netStreamPattern = new RegExp('\\.(' + _netStreamTypes.join('|') + ')(\\?.*)?$', 'i'); - - this.mimePattern = /^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i; // default mp3 set - - // use altURL if not "online" - this.useAltURL = !_overHTTP; - - this._global_a = null; - - _swfCSS = { - - 'swfBox': 'sm2-object-box', - 'swfDefault': 'movieContainer', - 'swfError': 'swf_error', // SWF loaded, but SM2 couldn't start (other error) - 'swfTimedout': 'swf_timedout', - 'swfLoaded': 'swf_loaded', - 'swfUnblocked': 'swf_unblocked', // or loaded OK - 'sm2Debug': 'sm2_debug', - 'highPerf': 'high_performance', - 'flashDebug': 'flash_debug' - - }; - - if (_mobileHTML5) { - - // prefer HTML5 for mobile + tablet-like devices, probably more reliable vs. flash at this point. - _s.useHTML5Audio = true; - _s.preferFlash = false; - - if (_is_iDevice) { - // by default, use global feature. iOS onfinish() -> next may fail otherwise. - _s.ignoreFlash = true; - _useGlobalHTML5Audio = true; - } - - } - - /** - * Public SoundManager API - * ----------------------- - */ - - /** - * Configures top-level soundManager properties. - * - * @param {object} options Option parameters, eg. { flashVersion: 9, url: '/path/to/swfs/' } - * onready and ontimeout are also accepted parameters. call soundManager.setup() to see the full list. - */ - - this.setup = function(options) { - - var noURL = (!_s.url); - - // warn if flash options have already been applied - - if (typeof options !== 'undefined' && _didInit && _needsFlash && _s.ok() && (typeof options.flashVersion !== 'undefined' || typeof options.url !== 'undefined')) { - _complain(_str('setupLate')); - } - - // TODO: defer: true? - - _assign(options); - - // special case 1: "Late setup". SM2 loaded normally, but user didn't assign flash URL eg., setup({url:...}) before SM2 init. Treat as delayed init. - - if (noURL && _didDCLoaded && typeof options.url !== 'undefined') { - _s.beginDelayedInit(); - } - - // special case 2: If lazy-loading SM2 (DOMContentLoaded has already happened) and user calls setup() with url: parameter, try to init ASAP. - - if (!_didDCLoaded && typeof options.url !== 'undefined' && _doc.readyState === 'complete') { - setTimeout(_domContentLoaded, 1); - } - - return _s; - - }; - - this.ok = function() { - - return (_needsFlash?(_didInit && !_disabled):(_s.useHTML5Audio && _s.hasHTML5)); - - }; - - this.supported = this.ok; // legacy - - this.getMovie = function(smID) { - - // safety net: some old browsers differ on SWF references, possibly related to ExternalInterface / flash version - return _id(smID) || _doc[smID] || _win[smID]; - - }; - - /** - * Creates a SMSound sound object instance. - * - * @param {object} oOptions Sound options (at minimum, id and url parameters are required.) - * @return {object} SMSound The new SMSound object. - */ - - this.createSound = function(oOptions, _url) { - - var _cs, _cs_string, thisOptions = null, oSound = null, _tO = null; - - // - _cs = _sm+'.createSound(): '; - _cs_string = _cs + _str(!_didInit?'notReady':'notOK'); - // - - if (!_didInit || !_s.ok()) { - _complain(_cs_string); - return false; - } - - if (typeof _url !== 'undefined') { - // function overloading in JS! :) ..assume simple createSound(id,url) use case - oOptions = { - 'id': oOptions, - 'url': _url - }; - } - - // inherit from defaultOptions - thisOptions = _mixin(oOptions); - - thisOptions.url = _parseURL(thisOptions.url); - - // local shortcut - _tO = thisOptions; - - // - if (_tO.id.toString().charAt(0).match(/^[0-9]$/)) { - _s._wD(_cs + _str('badID', _tO.id), 2); - } - - _s._wD(_cs + _tO.id + ' (' + _tO.url + ')', 1); - // - - if (_idCheck(_tO.id, true)) { - _s._wD(_cs + _tO.id + ' exists', 1); - return _s.sounds[_tO.id]; - } - - function make() { - - thisOptions = _loopFix(thisOptions); - _s.sounds[_tO.id] = new SMSound(_tO); - _s.soundIDs.push(_tO.id); - return _s.sounds[_tO.id]; - - } - - if (_html5OK(_tO)) { - - oSound = make(); - _s._wD('Creating sound '+_tO.id+', using HTML5'); - oSound._setup_html5(_tO); - - } else { - - if (_fV > 8) { - if (_tO.isMovieStar === null) { - // attempt to detect MPEG-4 formats - _tO.isMovieStar = !!(_tO.serverURL || (_tO.type ? _tO.type.match(_netStreamMimeTypes) : false) || _tO.url.match(_netStreamPattern)); - } - // - if (_tO.isMovieStar) { - _s._wD(_cs + 'using MovieStar handling'); - if (_tO.loops > 1) { - _wDS('noNSLoop'); - } - } - // - } - - _tO = _policyFix(_tO, _cs); - oSound = make(); - - if (_fV === 8) { - _flash._createSound(_tO.id, _tO.loops||1, _tO.usePolicyFile); - } else { - _flash._createSound(_tO.id, _tO.url, _tO.usePeakData, _tO.useWaveformData, _tO.useEQData, _tO.isMovieStar, (_tO.isMovieStar?_tO.bufferTime:false), _tO.loops||1, _tO.serverURL, _tO.duration||null, _tO.autoPlay, true, _tO.autoLoad, _tO.usePolicyFile); - if (!_tO.serverURL) { - // We are connected immediately - oSound.connected = true; - if (_tO.onconnect) { - _tO.onconnect.apply(oSound); - } - } - } - - if (!_tO.serverURL && (_tO.autoLoad || _tO.autoPlay)) { - // call load for non-rtmp streams - oSound.load(_tO); - } - - } - - // rtmp will play in onconnect - if (!_tO.serverURL && _tO.autoPlay) { - oSound.play(); - } - - return oSound; - - }; - - /** - * Destroys a SMSound sound object instance. - * - * @param {string} sID The ID of the sound to destroy - */ - - this.destroySound = function(sID, _bFromSound) { - - // explicitly destroy a sound before normal page unload, etc. - - if (!_idCheck(sID)) { - return false; - } - - var oS = _s.sounds[sID], i; - - // Disable all callbacks while the sound is being destroyed - oS._iO = {}; - - oS.stop(); - oS.unload(); - - for (i = 0; i < _s.soundIDs.length; i++) { - if (_s.soundIDs[i] === sID) { - _s.soundIDs.splice(i, 1); - break; - } - } - - if (!_bFromSound) { - // ignore if being called from SMSound instance - oS.destruct(true); - } - - oS = null; - delete _s.sounds[sID]; - - return true; - - }; - - /** - * Calls the load() method of a SMSound object by ID. - * - * @param {string} sID The ID of the sound - * @param {object} oOptions Optional: Sound options - */ - - this.load = function(sID, oOptions) { - - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].load(oOptions); - - }; - - /** - * Calls the unload() method of a SMSound object by ID. - * - * @param {string} sID The ID of the sound - */ - - this.unload = function(sID) { - - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].unload(); - - }; - - /** - * Calls the onPosition() method of a SMSound object by ID. - * - * @param {string} sID The ID of the sound - * @param {number} nPosition The position to watch for - * @param {function} oMethod The relevant callback to fire - * @param {object} oScope Optional: The scope to apply the callback to - * @return {SMSound} The SMSound object - */ - - this.onPosition = function(sID, nPosition, oMethod, oScope) { - - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].onposition(nPosition, oMethod, oScope); - - }; - - // legacy/backwards-compability: lower-case method name - this.onposition = this.onPosition; - - /** - * Calls the clearOnPosition() method of a SMSound object by ID. - * - * @param {string} sID The ID of the sound - * @param {number} nPosition The position to watch for - * @param {function} oMethod Optional: The relevant callback to fire - * @return {SMSound} The SMSound object - */ - - this.clearOnPosition = function(sID, nPosition, oMethod) { - - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].clearOnPosition(nPosition, oMethod); - - }; - - /** - * Calls the play() method of a SMSound object by ID. - * - * @param {string} sID The ID of the sound - * @param {object} oOptions Optional: Sound options - * @return {SMSound} The SMSound object - */ - - this.play = function(sID, oOptions) { - - var result = false; - - if (!_didInit || !_s.ok()) { - _complain(_sm+'.play(): ' + _str(!_didInit?'notReady':'notOK')); - return result; - } - - if (!_idCheck(sID)) { - if (!(oOptions instanceof Object)) { - // overloading use case: play('mySound','/path/to/some.mp3'); - oOptions = { - url: oOptions - }; - } - if (oOptions && oOptions.url) { - // overloading use case, create+play: .play('someID',{url:'/path/to.mp3'}); - _s._wD(_sm+'.play(): attempting to create "' + sID + '"', 1); - oOptions.id = sID; - result = _s.createSound(oOptions).play(); - } - return result; - } - - return _s.sounds[sID].play(oOptions); - - }; - - this.start = this.play; // just for convenience - - /** - * Calls the setPosition() method of a SMSound object by ID. - * - * @param {string} sID The ID of the sound - * @param {number} nMsecOffset Position (milliseconds) - * @return {SMSound} The SMSound object - */ - - this.setPosition = function(sID, nMsecOffset) { - - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].setPosition(nMsecOffset); - - }; - - /** - * Calls the stop() method of a SMSound object by ID. - * - * @param {string} sID The ID of the sound - * @return {SMSound} The SMSound object - */ - - this.stop = function(sID) { - - if (!_idCheck(sID)) { - return false; - } - - _s._wD(_sm+'.stop(' + sID + ')', 1); - return _s.sounds[sID].stop(); - - }; - - /** - * Stops all currently-playing sounds. - */ - - this.stopAll = function() { - - var oSound; - _s._wD(_sm+'.stopAll()', 1); - - for (oSound in _s.sounds) { - if (_s.sounds.hasOwnProperty(oSound)) { - // apply only to sound objects - _s.sounds[oSound].stop(); - } - } - - }; - - /** - * Calls the pause() method of a SMSound object by ID. - * - * @param {string} sID The ID of the sound - * @return {SMSound} The SMSound object - */ - - this.pause = function(sID) { - - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].pause(); - - }; - - /** - * Pauses all currently-playing sounds. - */ - - this.pauseAll = function() { - - var i; - for (i = _s.soundIDs.length-1; i >= 0; i--) { - _s.sounds[_s.soundIDs[i]].pause(); - } - - }; - - /** - * Calls the resume() method of a SMSound object by ID. - * - * @param {string} sID The ID of the sound - * @return {SMSound} The SMSound object - */ - - this.resume = function(sID) { - - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].resume(); - - }; - - /** - * Resumes all currently-paused sounds. - */ - - this.resumeAll = function() { - - var i; - for (i = _s.soundIDs.length-1; i >= 0; i--) { - _s.sounds[_s.soundIDs[i]].resume(); - } - - }; - - /** - * Calls the togglePause() method of a SMSound object by ID. - * - * @param {string} sID The ID of the sound - * @return {SMSound} The SMSound object - */ - - this.togglePause = function(sID) { - - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].togglePause(); - - }; - - /** - * Calls the setPan() method of a SMSound object by ID. - * - * @param {string} sID The ID of the sound - * @param {number} nPan The pan value (-100 to 100) - * @return {SMSound} The SMSound object - */ - - this.setPan = function(sID, nPan) { - - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].setPan(nPan); - - }; - - /** - * Calls the setVolume() method of a SMSound object by ID. - * - * @param {string} sID The ID of the sound - * @param {number} nVol The volume value (0 to 100) - * @return {SMSound} The SMSound object - */ - - this.setVolume = function(sID, nVol) { - - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].setVolume(nVol); - - }; - - /** - * Calls the mute() method of either a single SMSound object by ID, or all sound objects. - * - * @param {string} sID Optional: The ID of the sound (if omitted, all sounds will be used.) - */ - - this.mute = function(sID) { - - var i = 0; - - if (typeof sID !== 'string') { - sID = null; - } - - if (!sID) { - _s._wD(_sm+'.mute(): Muting all sounds'); - for (i = _s.soundIDs.length-1; i >= 0; i--) { - _s.sounds[_s.soundIDs[i]].mute(); - } - _s.muted = true; - } else { - if (!_idCheck(sID)) { - return false; - } - _s._wD(_sm+'.mute(): Muting "' + sID + '"'); - return _s.sounds[sID].mute(); - } - - return true; - - }; - - /** - * Mutes all sounds. - */ - - this.muteAll = function() { - - _s.mute(); - - }; - - /** - * Calls the unmute() method of either a single SMSound object by ID, or all sound objects. - * - * @param {string} sID Optional: The ID of the sound (if omitted, all sounds will be used.) - */ - - this.unmute = function(sID) { - - var i; - - if (typeof sID !== 'string') { - sID = null; - } - - if (!sID) { - - _s._wD(_sm+'.unmute(): Unmuting all sounds'); - for (i = _s.soundIDs.length-1; i >= 0; i--) { - _s.sounds[_s.soundIDs[i]].unmute(); - } - _s.muted = false; - - } else { - - if (!_idCheck(sID)) { - return false; - } - _s._wD(_sm+'.unmute(): Unmuting "' + sID + '"'); - return _s.sounds[sID].unmute(); - - } - - return true; - - }; - - /** - * Unmutes all sounds. - */ - - this.unmuteAll = function() { - - _s.unmute(); - - }; - - /** - * Calls the toggleMute() method of a SMSound object by ID. - * - * @param {string} sID The ID of the sound - * @return {SMSound} The SMSound object - */ - - this.toggleMute = function(sID) { - - if (!_idCheck(sID)) { - return false; - } - return _s.sounds[sID].toggleMute(); - - }; - - /** - * Retrieves the memory used by the flash plugin. - * - * @return {number} The amount of memory in use - */ - - this.getMemoryUse = function() { - - // flash-only - var ram = 0; - - if (_flash && _fV !== 8) { - ram = parseInt(_flash._getMemoryUse(), 10); - } - - return ram; - - }; - - /** - * Undocumented: NOPs soundManager and all SMSound objects. - */ - - this.disable = function(bNoDisable) { - - // destroy all functions - var i; - - if (typeof bNoDisable === 'undefined') { - bNoDisable = false; - } - - if (_disabled) { - return false; - } - - _disabled = true; - _wDS('shutdown', 1); - - for (i = _s.soundIDs.length-1; i >= 0; i--) { - _disableObject(_s.sounds[_s.soundIDs[i]]); - } - - // fire "complete", despite fail - _initComplete(bNoDisable); - _event.remove(_win, 'load', _initUserOnload); - - return true; - - }; - - /** - * Determines playability of a MIME type, eg. 'audio/mp3'. - */ - - this.canPlayMIME = function(sMIME) { - - var result; - - if (_s.hasHTML5) { - result = _html5CanPlay({type:sMIME}); - } - - if (!result && _needsFlash) { - // if flash 9, test netStream (movieStar) types as well. - result = (sMIME && _s.ok() ? !!((_fV > 8 ? sMIME.match(_netStreamMimeTypes) : null) || sMIME.match(_s.mimePattern)) : null); - } - - return result; - - }; - - /** - * Determines playability of a URL based on audio support. - * - * @param {string} sURL The URL to test - * @return {boolean} URL playability - */ - - this.canPlayURL = function(sURL) { - - var result; - - if (_s.hasHTML5) { - result = _html5CanPlay({url: sURL}); - } - - if (!result && _needsFlash) { - result = (sURL && _s.ok() ? !!(sURL.match(_s.filePattern)) : null); - } - - return result; - - }; - - /** - * Determines playability of an HTML DOM <a> object (or similar object literal) based on audio support. - * - * @param {object} oLink an HTML DOM <a> object or object literal including href and/or type attributes - * @return {boolean} URL playability - */ - - this.canPlayLink = function(oLink) { - - if (typeof oLink.type !== 'undefined' && oLink.type) { - if (_s.canPlayMIME(oLink.type)) { - return true; - } - } - - return _s.canPlayURL(oLink.href); - - }; - - /** - * Retrieves a SMSound object by ID. - * - * @param {string} sID The ID of the sound - * @return {SMSound} The SMSound object - */ - - this.getSoundById = function(sID, _suppressDebug) { - - if (!sID) { - throw new Error(_sm+'.getSoundById(): sID is null/undefined'); - } - - var result = _s.sounds[sID]; - - // - if (!result && !_suppressDebug) { - _s._wD('"' + sID + '" is an invalid sound ID.', 2); - } - // - - return result; - - }; - - /** - * Queues a callback for execution when SoundManager has successfully initialized. - * - * @param {function} oMethod The callback method to fire - * @param {object} oScope Optional: The scope to apply to the callback - */ - - this.onready = function(oMethod, oScope) { - - var sType = 'onready', - result = false; - - if (typeof oMethod === 'function') { - - // - if (_didInit) { - _s._wD(_str('queue', sType)); - } - // - - if (!oScope) { - oScope = _win; - } - - _addOnEvent(sType, oMethod, oScope); - _processOnEvents(); - - result = true; - - } else { - - throw _str('needFunction', sType); - - } - - return result; - - }; - - /** - * Queues a callback for execution when SoundManager has failed to initialize. - * - * @param {function} oMethod The callback method to fire - * @param {object} oScope Optional: The scope to apply to the callback - */ - - this.ontimeout = function(oMethod, oScope) { - - var sType = 'ontimeout', - result = false; - - if (typeof oMethod === 'function') { - - // - if (_didInit) { - _s._wD(_str('queue', sType)); - } - // - - if (!oScope) { - oScope = _win; - } - - _addOnEvent(sType, oMethod, oScope); - _processOnEvents({type:sType}); - - result = true; - - } else { - - throw _str('needFunction', sType); - - } - - return result; - - }; - - /** - * Writes console.log()-style debug output to a console or in-browser element. - * Applies when debugMode = true - * - * @param {string} sText The console message - * @param {string} sType Optional: Log type of 'info', 'warn' or 'error' - * @param {object} Optional: The scope to apply to the callback - */ - - this._writeDebug = function(sText, sType, _bTimestamp) { - - // pseudo-private console.log()-style output - // - - var sDID = 'soundmanager-debug', o, oItem, sMethod; - - if (!_s.debugMode) { - return false; - } - - if (typeof _bTimestamp !== 'undefined' && _bTimestamp) { - sText = sText + ' | ' + new Date().getTime(); - } - - if (_hasConsole && _s.useConsole) { - sMethod = _debugLevels[sType]; - if (typeof console[sMethod] !== 'undefined') { - console[sMethod](sText); - } else { - console.log(sText); - } - if (_s.consoleOnly) { - return true; - } - } - - try { - - o = _id(sDID); - - if (!o) { - return false; - } - - oItem = _doc.createElement('div'); - - if (++_wdCount % 2 === 0) { - oItem.className = 'sm2-alt'; - } - - if (typeof sType === 'undefined') { - sType = 0; - } else { - sType = parseInt(sType, 10); - } - - oItem.appendChild(_doc.createTextNode(sText)); - - if (sType) { - if (sType >= 2) { - oItem.style.fontWeight = 'bold'; - } - if (sType === 3) { - oItem.style.color = '#ff3333'; - } - } - - // top-to-bottom - // o.appendChild(oItem); - - // bottom-to-top - o.insertBefore(oItem, o.firstChild); - - } catch(e) { - // oh well - } - - o = null; - // - - return true; - - }; - - // alias - this._wD = this._writeDebug; - - /** - * Provides debug / state information on all SMSound objects. - */ - - this._debug = function() { - - // - var i, j; - _wDS('currentObj', 1); - - for (i = 0, j = _s.soundIDs.length; i < j; i++) { - _s.sounds[_s.soundIDs[i]]._debug(); - } - // - - }; - - /** - * Restarts and re-initializes the SoundManager instance. - */ - - this.reboot = function() { - - // attempt to reset and init SM2 - _s._wD(_sm+'.reboot()'); - - // - if (_s.soundIDs.length) { - _s._wD('Destroying ' + _s.soundIDs.length + ' SMSound objects...'); - } - // - - var i, j; - - for (i = _s.soundIDs.length-1; i >= 0; i--) { - _s.sounds[_s.soundIDs[i]].destruct(); - } - - // trash ze flash - - if (_flash) { - try { - if (_isIE) { - _oRemovedHTML = _flash.innerHTML; - } - _oRemoved = _flash.parentNode.removeChild(_flash); - _s._wD('Flash movie removed.'); - } catch(e) { - // uh-oh. - _wDS('badRemove', 2); - } - } - - // actually, force recreate of movie. - _oRemovedHTML = _oRemoved = _needsFlash = null; - - _s.enabled = _didDCLoaded = _didInit = _waitingForEI = _initPending = _didAppend = _appendSuccess = _disabled = _s.swfLoaded = false; - _s.soundIDs = []; - _s.sounds = {}; - _flash = null; - - for (i in _on_queue) { - if (_on_queue.hasOwnProperty(i)) { - for (j = _on_queue[i].length-1; j >= 0; j--) { - _on_queue[i][j].fired = false; - } - } - } - - _s._wD(_sm + ': Rebooting...'); - _win.setTimeout(_s.beginDelayedInit, 20); - - }; - - /** - * Undocumented: Determines the SM2 flash movie's load progress. - * - * @return {number or null} Percent loaded, or if invalid/unsupported, null. - */ - - this.getMoviePercent = function() { - - // interesting note: flash/ExternalInterface bridge methods are not typeof "function" nor instanceof Function, but are still valid. - return (_flash && typeof _flash.PercentLoaded !== 'undefined' ? _flash.PercentLoaded() : null); - - }; - - /** - * Additional helper for manually invoking SM2's init process after DOM Ready / window.onload(). - */ - - this.beginDelayedInit = function() { - - _windowLoaded = true; - _domContentLoaded(); - - setTimeout(function() { - - if (_initPending) { - return false; - } - - _createMovie(); - _initMovie(); - _initPending = true; - - return true; - - }, 20); - - _delayWaitForEI(); - - }; - - /** - * Destroys the SoundManager instance and all SMSound instances. - */ - - this.destruct = function() { - - _s._wD(_sm+'.destruct()'); - _s.disable(true); - - }; - - /** - * SMSound() (sound object) constructor - * ------------------------------------ - * - * @param {object} oOptions Sound options (id and url are required attributes) - * @return {SMSound} The new SMSound object - */ - - SMSound = function(oOptions) { - - var _t = this, _resetProperties, _add_html5_events, _remove_html5_events, _stop_html5_timer, _start_html5_timer, _attachOnPosition, _onplay_called = false, _onPositionItems = [], _onPositionFired = 0, _detachOnPosition, _applyFromTo, _lastURL = null, _lastHTML5State; - - _lastHTML5State = { - // tracks duration + position (time) - duration: null, - time: null - }; - - this.id = oOptions.id; - - // legacy - this.sID = this.id; - - this.url = oOptions.url; - this.options = _mixin(oOptions); - - // per-play-instance-specific options - this.instanceOptions = this.options; - - // short alias - this._iO = this.instanceOptions; - - // assign property defaults - this.pan = this.options.pan; - this.volume = this.options.volume; - - // whether or not this object is using HTML5 - this.isHTML5 = false; - - // internal HTML5 Audio() object reference - this._a = null; - - /** - * SMSound() public methods - * ------------------------ - */ - - this.id3 = {}; - - /** - * Writes SMSound object parameters to debug console - */ - - this._debug = function() { - - // - // pseudo-private console.log()-style output - - if (_s.debugMode) { - - var stuff = null, msg = [], sF, sfBracket, maxLength = 64; - - for (stuff in _t.options) { - if (_t.options[stuff] !== null) { - if (typeof _t.options[stuff] === 'function') { - // handle functions specially - sF = _t.options[stuff].toString(); - // normalize spaces - sF = sF.replace(/\s\s+/g, ' '); - sfBracket = sF.indexOf('{'); - msg.push(' ' + stuff + ': {' + sF.substr(sfBracket + 1, (Math.min(Math.max(sF.indexOf('\n') - 1, maxLength), maxLength))).replace(/\n/g, '') + '... }'); - } else { - msg.push(' ' + stuff + ': ' + _t.options[stuff]); - } - } - } - - _s._wD('SMSound() merged options: {\n' + msg.join(', \n') + '\n}'); - - } - // - - }; - - // - this._debug(); - // - - /** - * Begins loading a sound per its *url*. - * - * @param {object} oOptions Optional: Sound options - * @return {SMSound} The SMSound object - */ - - this.load = function(oOptions) { - - var oS = null, _iO; - - if (typeof oOptions !== 'undefined') { - _t._iO = _mixin(oOptions, _t.options); - _t.instanceOptions = _t._iO; - } else { - oOptions = _t.options; - _t._iO = oOptions; - _t.instanceOptions = _t._iO; - if (_lastURL && _lastURL !== _t.url) { - _wDS('manURL'); - _t._iO.url = _t.url; - _t.url = null; - } - } - - if (!_t._iO.url) { - _t._iO.url = _t.url; - } - - _t._iO.url = _parseURL(_t._iO.url); - - _s._wD('SMSound.load(): ' + _t._iO.url, 1); - - if (_t._iO.url === _t.url && _t.readyState !== 0 && _t.readyState !== 2) { - _wDS('onURL', 1); - // if loaded and an onload() exists, fire immediately. - if (_t.readyState === 3 && _t._iO.onload) { - // assume success based on truthy duration. - _t._iO.onload.apply(_t, [(!!_t.duration)]); - } - return _t; - } - - // local shortcut - _iO = _t._iO; - - // make a local copy of the old url before we re-assign it - _lastURL = (_t.url && _t.url.toString ? _t.url.toString() : null); - - // reset a few state properties - - _t.loaded = false; - _t.readyState = 1; - _t.playState = 0; - _t.id3 = {}; - - // TODO: If switching from HTML5 -> flash (or vice versa), stop currently-playing audio. - - if (_html5OK(_iO)) { - - oS = _t._setup_html5(_iO); - - if (!oS._called_load) { - - _s._wD(_h5+'load: '+_t.id); - - _t._html5_canplay = false; - - // TODO: review called_load / html5_canplay logic - - // if url provided directly to load(), assign it here. - - if (_t._a.src !== _iO.url) { - - _s._wD(_wDS('manURL') + ': ' + _iO.url); - - _t._a.src = _iO.url; - - // TODO: review / re-apply all relevant options (volume, loop, onposition etc.) - - // reset position for new URL - _t.setPosition(0); - - } - - // given explicit load call, try to preload. - - // early HTML5 implementation (non-standard) - _t._a.autobuffer = 'auto'; - - // standard - _t._a.preload = 'auto'; - - oS._called_load = true; - - if (_iO.autoPlay) { - _t.play(); - } - - } else { - - _s._wD(_h5+'ignoring request to load again: '+_t.id); - - } - - } else { - - try { - _t.isHTML5 = false; - _t._iO = _policyFix(_loopFix(_iO)); - // re-assign local shortcut - _iO = _t._iO; - if (_fV === 8) { - _flash._load(_t.id, _iO.url, _iO.stream, _iO.autoPlay, (_iO.whileloading?1:0), _iO.loops||1, _iO.usePolicyFile); - } else { - _flash._load(_t.id, _iO.url, !!(_iO.stream), !!(_iO.autoPlay), _iO.loops||1, !!(_iO.autoLoad), _iO.usePolicyFile); - } - } catch(e) { - _wDS('smError', 2); - _debugTS('onload', false); - _catchError({type:'SMSOUND_LOAD_JS_EXCEPTION', fatal:true}); - - } - - } - - // after all of this, ensure sound url is up to date. - _t.url = _iO.url; - - return _t; - - }; - - /** - * Unloads a sound, canceling any open HTTP requests. - * - * @return {SMSound} The SMSound object - */ - - this.unload = function() { - - // Flash 8/AS2 can't "close" a stream - fake it by loading an empty URL - // Flash 9/AS3: Close stream, preventing further load - // HTML5: Most UAs will use empty URL - - if (_t.readyState !== 0) { - - _s._wD('SMSound.unload(): "' + _t.id + '"'); - - if (!_t.isHTML5) { - - if (_fV === 8) { - _flash._unload(_t.id, _emptyURL); - } else { - _flash._unload(_t.id); - } - - } else { - - _stop_html5_timer(); - - if (_t._a) { - - _t._a.pause(); - _html5Unload(_t._a, _emptyURL); - - // reset local URL for next load / play call, too - _t.url = _emptyURL; - - } - - } - - // reset load/status flags - _resetProperties(); - - } - - return _t; - - }; - - /** - * Unloads and destroys a sound. - */ - - this.destruct = function(_bFromSM) { - - _s._wD('SMSound.destruct(): "' + _t.id + '"'); - - if (!_t.isHTML5) { - - // kill sound within Flash - // Disable the onfailure handler - _t._iO.onfailure = null; - _flash._destroySound(_t.id); - - } else { - - _stop_html5_timer(); - - if (_t._a) { - _t._a.pause(); - _html5Unload(_t._a); - if (!_useGlobalHTML5Audio) { - _remove_html5_events(); - } - // break obvious circular reference - _t._a._t = null; - _t._a = null; - } - - } - - if (!_bFromSM) { - // ensure deletion from controller - _s.destroySound(_t.id, true); - - } - - }; - - /** - * Begins playing a sound. - * - * @param {object} oOptions Optional: Sound options - * @return {SMSound} The SMSound object - */ - - this.play = function(oOptions, _updatePlayState) { - - var fN, allowMulti, a, onready, startOK = true, - exit = null; - - // - fN = 'SMSound.play(): '; - // - - // default to true - _updatePlayState = (typeof _updatePlayState === 'undefined' ? true : _updatePlayState); - - if (!oOptions) { - oOptions = {}; - } - - // first, use local URL (if specified) - if (_t.url) { - _t._iO.url = _t.url; - } - - // mix in any options defined at createSound() - _t._iO = _mixin(_t._iO, _t.options); - - // mix in any options specific to this method - _t._iO = _mixin(oOptions, _t._iO); - - _t._iO.url = _parseURL(_t._iO.url); - - _t.instanceOptions = _t._iO; - - // RTMP-only - if (_t._iO.serverURL && !_t.connected) { - if (!_t.getAutoPlay()) { - _s._wD(fN+' Netstream not connected yet - setting autoPlay'); - _t.setAutoPlay(true); - } - // play will be called in _onconnect() - return _t; - } - - if (_html5OK(_t._iO)) { - _t._setup_html5(_t._iO); - _start_html5_timer(); - } - - if (_t.playState === 1 && !_t.paused) { - allowMulti = _t._iO.multiShot; - if (!allowMulti) { - _s._wD(fN + '"' + _t.id + '" already playing (one-shot)', 1); - exit = _t; - } else { - _s._wD(fN + '"' + _t.id + '" already playing (multi-shot)', 1); - } - } - - if (exit !== null) { - return exit; - } - - // edge case: play() with explicit URL parameter - if (oOptions.url && oOptions.url !== _t.url) { - // load using merged options - _t.load(_t._iO); - } - - if (!_t.loaded) { - - if (_t.readyState === 0) { - - _s._wD(fN + 'Attempting to load "' + _t.id + '"', 1); - - // try to get this sound playing ASAP - if (!_t.isHTML5) { - // assign directly because setAutoPlay() increments the instanceCount - _t._iO.autoPlay = true; - _t.load(_t._iO); - } else { - // iOS needs this when recycling sounds, loading a new URL on an existing object. - _t.load(_t._iO); - } - - } else if (_t.readyState === 2) { - - _s._wD(fN + 'Could not load "' + _t.id + '" - exiting', 2); - exit = _t; - - } else { - - _s._wD(fN + '"' + _t.id + '" is loading - attempting to play..', 1); - - } - - } else { - - _s._wD(fN + '"' + _t.id + '"'); - - } - - if (exit !== null) { - return exit; - } - - if (!_t.isHTML5 && _fV === 9 && _t.position > 0 && _t.position === _t.duration) { - // flash 9 needs a position reset if play() is called while at the end of a sound. - _s._wD(fN + '"' + _t.id + '": Sound at end, resetting to position:0'); - oOptions.position = 0; - } - - /** - * Streams will pause when their buffer is full if they are being loaded. - * In this case paused is true, but the song hasn't started playing yet. - * If we just call resume() the onplay() callback will never be called. - * So only call resume() if the position is > 0. - * Another reason is because options like volume won't have been applied yet. - * For normal sounds, just resume. - */ - - if (_t.paused && _t.position >= 0 && (!_t._iO.serverURL || _t.position > 0)) { - - // https://gist.github.com/37b17df75cc4d7a90bf6 - _s._wD(fN + '"' + _t.id + '" is resuming from paused state',1); - _t.resume(); - - } else { - - _t._iO = _mixin(oOptions, _t._iO); - - // apply from/to parameters, if they exist (and not using RTMP) - if (_t._iO.from !== null && _t._iO.to !== null && _t.instanceCount === 0 && _t.playState === 0 && !_t._iO.serverURL) { - - onready = function() { - // sound "canplay" or onload() - // re-apply from/to to instance options, and start playback - _t._iO = _mixin(oOptions, _t._iO); - _t.play(_t._iO); - }; - - // HTML5 needs to at least have "canplay" fired before seeking. - if (_t.isHTML5 && !_t._html5_canplay) { - - // this hasn't been loaded yet. load it first, and then do this again. - _s._wD(fN+'Beginning load of "'+ _t.id+'" for from/to case'); - - _t.load({ - _oncanplay: onready - }); - - exit = false; - - } else if (!_t.isHTML5 && !_t.loaded && (!_t.readyState || _t.readyState !== 2)) { - - // to be safe, preload the whole thing in Flash. - - _s._wD(fN+'Preloading "'+ _t.id+'" for from/to case'); - - _t.load({ - onload: onready - }); - - exit = false; - - } - - if (exit !== null) { - return exit; - } - - // otherwise, we're ready to go. re-apply local options, and continue - - _t._iO = _applyFromTo(); - - } - - _s._wD(fN+'"'+ _t.id+'" is starting to play'); - - if (!_t.instanceCount || _t._iO.multiShotEvents || (!_t.isHTML5 && _fV > 8 && !_t.getAutoPlay())) { - _t.instanceCount++; - } - - // if first play and onposition parameters exist, apply them now - if (_t._iO.onposition && _t.playState === 0) { - _attachOnPosition(_t); - } - - _t.playState = 1; - _t.paused = false; - - _t.position = (typeof _t._iO.position !== 'undefined' && !isNaN(_t._iO.position) ? _t._iO.position : 0); - - if (!_t.isHTML5) { - _t._iO = _policyFix(_loopFix(_t._iO)); - } - - if (_t._iO.onplay && _updatePlayState) { - _t._iO.onplay.apply(_t); - _onplay_called = true; - } - - _t.setVolume(_t._iO.volume, true); - _t.setPan(_t._iO.pan, true); - - if (!_t.isHTML5) { - - startOK = _flash._start(_t.id, _t._iO.loops || 1, (_fV === 9 ? _t._iO.position : _t._iO.position / 1000), _t._iO.multiShot); - - if (_fV === 9 && !startOK) { - // edge case: no sound hardware, or 32-channel flash ceiling hit. - // applies only to Flash 9, non-NetStream/MovieStar sounds. - // http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Sound.html#play%28%29 - _s._wD(fN+ _t.id+': No sound hardware, or 32-sound ceiling hit'); - if (_t._iO.onplayerror) { - _t._iO.onplayerror.apply(_t); - } - - } - - } else { - - _start_html5_timer(); - - a = _t._setup_html5(); - - _t.setPosition(_t._iO.position); - - a.play(); - - } - - } - - return _t; - - }; - - // just for convenience - this.start = this.play; - - /** - * Stops playing a sound (and optionally, all sounds) - * - * @param {boolean} bAll Optional: Whether to stop all sounds - * @return {SMSound} The SMSound object - */ - - this.stop = function(bAll) { - - var _iO = _t._iO, _oP; - - if (_t.playState === 1) { - - _t._onbufferchange(0); - _t._resetOnPosition(0); - _t.paused = false; - - if (!_t.isHTML5) { - _t.playState = 0; - } - - // remove onPosition listeners, if any - _detachOnPosition(); - - // and "to" position, if set - if (_iO.to) { - _t.clearOnPosition(_iO.to); - } - - if (!_t.isHTML5) { - - _flash._stop(_t.id, bAll); - - // hack for netStream: just unload - if (_iO.serverURL) { - _t.unload(); - } - - } else { - - if (_t._a) { - - _oP = _t.position; - - // act like Flash, though - _t.setPosition(0); - - // hack: reflect old position for onstop() (also like Flash) - _t.position = _oP; - - // html5 has no stop() - // NOTE: pausing means iOS requires interaction to resume. - _t._a.pause(); - - _t.playState = 0; - - // and update UI - _t._onTimer(); - - _stop_html5_timer(); - - } - - } - - _t.instanceCount = 0; - _t._iO = {}; - - if (_iO.onstop) { - _iO.onstop.apply(_t); - } - - } - - return _t; - - }; - - /** - * Undocumented/internal: Sets autoPlay for RTMP. - * - * @param {boolean} autoPlay state - */ - - this.setAutoPlay = function(autoPlay) { - - _s._wD('sound '+_t.id+' turned autoplay ' + (autoPlay ? 'on' : 'off')); - _t._iO.autoPlay = autoPlay; - - if (!_t.isHTML5) { - _flash._setAutoPlay(_t.id, autoPlay); - if (autoPlay) { - // only increment the instanceCount if the sound isn't loaded (TODO: verify RTMP) - if (!_t.instanceCount && _t.readyState === 1) { - _t.instanceCount++; - _s._wD('sound '+_t.id+' incremented instance count to '+_t.instanceCount); - } - } - } - - }; - - /** - * Undocumented/internal: Returns the autoPlay boolean. - * - * @return {boolean} The current autoPlay value - */ - - this.getAutoPlay = function() { - - return _t._iO.autoPlay; - - }; - - /** - * Sets the position of a sound. - * - * @param {number} nMsecOffset Position (milliseconds) - * @return {SMSound} The SMSound object - */ - - this.setPosition = function(nMsecOffset) { - - if (typeof nMsecOffset === 'undefined') { - nMsecOffset = 0; - } - - var original_pos, - position, position1K, - // Use the duration from the instance options, if we don't have a track duration yet. - // position >= 0 and <= current available (loaded) duration - offset = (_t.isHTML5 ? Math.max(nMsecOffset, 0) : Math.min(_t.duration || _t._iO.duration, Math.max(nMsecOffset, 0))); - - original_pos = _t.position; - _t.position = offset; - position1K = _t.position/1000; - _t._resetOnPosition(_t.position); - _t._iO.position = offset; - - if (!_t.isHTML5) { - - position = (_fV === 9 ? _t.position : position1K); - if (_t.readyState && _t.readyState !== 2) { - // if paused or not playing, will not resume (by playing) - _flash._setPosition(_t.id, position, (_t.paused || !_t.playState), _t._iO.multiShot); - } - - } else if (_t._a) { - - // Set the position in the canplay handler if the sound is not ready yet - if (_t._html5_canplay) { - if (_t._a.currentTime !== position1K) { - /** - * DOM/JS errors/exceptions to watch out for: - * if seek is beyond (loaded?) position, "DOM exception 11" - * "INDEX_SIZE_ERR": DOM exception 1 - */ - _s._wD('setPosition('+position1K+'): setting position'); - try { - _t._a.currentTime = position1K; - if (_t.playState === 0 || _t.paused) { - // allow seek without auto-play/resume - _t._a.pause(); - } - } catch(e) { - _s._wD('setPosition('+position1K+'): setting position failed: '+e.message, 2); - } - } - } else { - _s._wD('setPosition('+position1K+'): delaying, sound not ready'); - } - - } - - if (_t.isHTML5) { - if (_t.paused) { - // if paused, refresh UI right away - // force update - _t._onTimer(true); - } - } - - return _t; - - }; - - /** - * Pauses sound playback. - * - * @return {SMSound} The SMSound object - */ - - this.pause = function(_bCallFlash) { - - if (_t.paused || (_t.playState === 0 && _t.readyState !== 1)) { - return _t; - } - - _s._wD('SMSound.pause()'); - _t.paused = true; - - if (!_t.isHTML5) { - if (_bCallFlash || typeof _bCallFlash === 'undefined') { - _flash._pause(_t.id, _t._iO.multiShot); - } - } else { - _t._setup_html5().pause(); - _stop_html5_timer(); - } - - if (_t._iO.onpause) { - _t._iO.onpause.apply(_t); - } - - return _t; - - }; - - /** - * Resumes sound playback. - * - * @return {SMSound} The SMSound object - */ - - /** - * When auto-loaded streams pause on buffer full they have a playState of 0. - * We need to make sure that the playState is set to 1 when these streams "resume". - * When a paused stream is resumed, we need to trigger the onplay() callback if it - * hasn't been called already. In this case since the sound is being played for the - * first time, I think it's more appropriate to call onplay() rather than onresume(). - */ - - this.resume = function() { - - var _iO = _t._iO; - - if (!_t.paused) { - return _t; - } - - _s._wD('SMSound.resume()'); - _t.paused = false; - _t.playState = 1; - - if (!_t.isHTML5) { - if (_iO.isMovieStar && !_iO.serverURL) { - // Bizarre Webkit bug (Chrome reported via 8tracks.com dudes): AAC content paused for 30+ seconds(?) will not resume without a reposition. - _t.setPosition(_t.position); - } - // flash method is toggle-based (pause/resume) - _flash._pause(_t.id, _iO.multiShot); - } else { - _t._setup_html5().play(); - _start_html5_timer(); - } - - if (!_onplay_called && _iO.onplay) { - _iO.onplay.apply(_t); - _onplay_called = true; - } else if (_iO.onresume) { - _iO.onresume.apply(_t); - } - - return _t; - - }; - - /** - * Toggles sound playback. - * - * @return {SMSound} The SMSound object - */ - - this.togglePause = function() { - - _s._wD('SMSound.togglePause()'); - - if (_t.playState === 0) { - _t.play({ - position: (_fV === 9 && !_t.isHTML5 ? _t.position : _t.position / 1000) - }); - return _t; - } - - if (_t.paused) { - _t.resume(); - } else { - _t.pause(); - } - - return _t; - - }; - - /** - * Sets the panning (L-R) effect. - * - * @param {number} nPan The pan value (-100 to 100) - * @return {SMSound} The SMSound object - */ - - this.setPan = function(nPan, bInstanceOnly) { - - if (typeof nPan === 'undefined') { - nPan = 0; - } - - if (typeof bInstanceOnly === 'undefined') { - bInstanceOnly = false; - } - - if (!_t.isHTML5) { - _flash._setPan(_t.id, nPan); - } // else { no HTML5 pan? } - - _t._iO.pan = nPan; - - if (!bInstanceOnly) { - _t.pan = nPan; - _t.options.pan = nPan; - } - - return _t; - - }; - - /** - * Sets the volume. - * - * @param {number} nVol The volume value (0 to 100) - * @return {SMSound} The SMSound object - */ - - this.setVolume = function(nVol, _bInstanceOnly) { - - /** - * Note: Setting volume has no effect on iOS "special snowflake" devices. - * Hardware volume control overrides software, and volume - * will always return 1 per Apple docs. (iOS 4 + 5.) - * http://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/AddingSoundtoCanvasAnimations/AddingSoundtoCanvasAnimations.html - */ - - if (typeof nVol === 'undefined') { - nVol = 100; - } - - if (typeof _bInstanceOnly === 'undefined') { - _bInstanceOnly = false; - } - - if (!_t.isHTML5) { - _flash._setVolume(_t.id, (_s.muted && !_t.muted) || _t.muted?0:nVol); - } else if (_t._a) { - // valid range: 0-1 - _t._a.volume = Math.max(0, Math.min(1, nVol/100)); - } - - _t._iO.volume = nVol; - - if (!_bInstanceOnly) { - _t.volume = nVol; - _t.options.volume = nVol; - } - - return _t; - - }; - - /** - * Mutes the sound. - * - * @return {SMSound} The SMSound object - */ - - this.mute = function() { - - _t.muted = true; - - if (!_t.isHTML5) { - _flash._setVolume(_t.id, 0); - } else if (_t._a) { - _t._a.muted = true; - } - - return _t; - - }; - - /** - * Unmutes the sound. - * - * @return {SMSound} The SMSound object - */ - - this.unmute = function() { - - _t.muted = false; - var hasIO = (typeof _t._iO.volume !== 'undefined'); - - if (!_t.isHTML5) { - _flash._setVolume(_t.id, hasIO?_t._iO.volume:_t.options.volume); - } else if (_t._a) { - _t._a.muted = false; - } - - return _t; - - }; - - /** - * Toggles the muted state of a sound. - * - * @return {SMSound} The SMSound object - */ - - this.toggleMute = function() { - - return (_t.muted?_t.unmute():_t.mute()); - - }; - - /** - * Registers a callback to be fired when a sound reaches a given position during playback. - * - * @param {number} nPosition The position to watch for - * @param {function} oMethod The relevant callback to fire - * @param {object} oScope Optional: The scope to apply the callback to - * @return {SMSound} The SMSound object - */ - - this.onPosition = function(nPosition, oMethod, oScope) { - - // TODO: basic dupe checking? - - _onPositionItems.push({ - position: parseInt(nPosition, 10), - method: oMethod, - scope: (typeof oScope !== 'undefined' ? oScope : _t), - fired: false - }); - - return _t; - - }; - - // legacy/backwards-compability: lower-case method name - this.onposition = this.onPosition; - - /** - * Removes registered callback(s) from a sound, by position and/or callback. - * - * @param {number} nPosition The position to clear callback(s) for - * @param {function} oMethod Optional: Identify one callback to be removed when multiple listeners exist for one position - * @return {SMSound} The SMSound object - */ - - this.clearOnPosition = function(nPosition, oMethod) { - - var i; - - nPosition = parseInt(nPosition, 10); - - if (isNaN(nPosition)) { - // safety check - return false; - } - - for (i=0; i < _onPositionItems.length; i++) { - - if (nPosition === _onPositionItems[i].position) { - // remove this item if no method was specified, or, if the method matches - if (!oMethod || (oMethod === _onPositionItems[i].method)) { - if (_onPositionItems[i].fired) { - // decrement "fired" counter, too - _onPositionFired--; - } - _onPositionItems.splice(i, 1); - } - } - - } - - }; - - this._processOnPosition = function() { - - var i, item, j = _onPositionItems.length; - - if (!j || !_t.playState || _onPositionFired >= j) { - return false; - } - - for (i=j-1; i >= 0; i--) { - item = _onPositionItems[i]; - if (!item.fired && _t.position >= item.position) { - item.fired = true; - _onPositionFired++; - item.method.apply(item.scope, [item.position]); - } - } - - return true; - - }; - - this._resetOnPosition = function(nPosition) { - - // reset "fired" for items interested in this position - var i, item, j = _onPositionItems.length; - - if (!j) { - return false; - } - - for (i=j-1; i >= 0; i--) { - item = _onPositionItems[i]; - if (item.fired && nPosition <= item.position) { - item.fired = false; - _onPositionFired--; - } - } - - return true; - - }; - - /** - * SMSound() private internals - * -------------------------------- - */ - - _applyFromTo = function() { - - var _iO = _t._iO, - f = _iO.from, - t = _iO.to, - start, end; - - end = function() { - - // end has been reached. - _s._wD(_t.id + ': "to" time of ' + t + ' reached.'); - - // detach listener - _t.clearOnPosition(t, end); - - // stop should clear this, too - _t.stop(); - - }; - - start = function() { - - _s._wD(_t.id + ': playing "from" ' + f); - - // add listener for end - if (t !== null && !isNaN(t)) { - _t.onPosition(t, end); - } - - }; - - if (f !== null && !isNaN(f)) { - - // apply to instance options, guaranteeing correct start position. - _iO.position = f; - - // multiShot timing can't be tracked, so prevent that. - _iO.multiShot = false; - - start(); - - } - - // return updated instanceOptions including starting position - return _iO; - - }; - - _attachOnPosition = function() { - - var item, - op = _t._iO.onposition; - - // attach onposition things, if any, now. - - if (op) { - - for (item in op) { - if (op.hasOwnProperty(item)) { - _t.onPosition(parseInt(item, 10), op[item]); - } - } - - } - - }; - - _detachOnPosition = function() { - - var item, - op = _t._iO.onposition; - - // detach any onposition()-style listeners. - - if (op) { - - for (item in op) { - if (op.hasOwnProperty(item)) { - _t.clearOnPosition(parseInt(item, 10)); - } - } - - } - - }; - - _start_html5_timer = function() { - - if (_t.isHTML5) { - _startTimer(_t); - } - - }; - - _stop_html5_timer = function() { - - if (_t.isHTML5) { - _stopTimer(_t); - } - - }; - - _resetProperties = function(retainPosition) { - - if (!retainPosition) { - _onPositionItems = []; - _onPositionFired = 0; - } - - _onplay_called = false; - - _t._hasTimer = null; - _t._a = null; - _t._html5_canplay = false; - _t.bytesLoaded = null; - _t.bytesTotal = null; - _t.duration = (_t._iO && _t._iO.duration ? _t._iO.duration : null); - _t.durationEstimate = null; - _t.buffered = []; - - // legacy: 1D array - _t.eqData = []; - - _t.eqData.left = []; - _t.eqData.right = []; - - _t.failures = 0; - _t.isBuffering = false; - _t.instanceOptions = {}; - _t.instanceCount = 0; - _t.loaded = false; - _t.metadata = {}; - - // 0 = uninitialised, 1 = loading, 2 = failed/error, 3 = loaded/success - _t.readyState = 0; - - _t.muted = false; - _t.paused = false; - - _t.peakData = { - left: 0, - right: 0 - }; - - _t.waveformData = { - left: [], - right: [] - }; - - _t.playState = 0; - _t.position = null; - - _t.id3 = {}; - - }; - - _resetProperties(); - - /** - * Pseudo-private SMSound internals - * -------------------------------- - */ - - this._onTimer = function(bForce) { - - /** - * HTML5-only _whileplaying() etc. - * called from both HTML5 native events, and polling/interval-based timers - * mimics flash and fires only when time/duration change, so as to be polling-friendly - */ - - var duration, isNew = false, time, x = {}; - - if (_t._hasTimer || bForce) { - - // TODO: May not need to track readyState (1 = loading) - - if (_t._a && (bForce || ((_t.playState > 0 || _t.readyState === 1) && !_t.paused))) { - - duration = _t._get_html5_duration(); - - if (duration !== _lastHTML5State.duration) { - - _lastHTML5State.duration = duration; - _t.duration = duration; - isNew = true; - - } - - // TODO: investigate why this goes wack if not set/re-set each time. - _t.durationEstimate = _t.duration; - - time = (_t._a.currentTime * 1000 || 0); - - if (time !== _lastHTML5State.time) { - - _lastHTML5State.time = time; - isNew = true; - - } - - if (isNew || bForce) { - - _t._whileplaying(time,x,x,x,x); - - } - - }/* else { - - // _s._wD('_onTimer: Warn for "'+_t.id+'": '+(!_t._a?'Could not find element. ':'')+(_t.playState === 0?'playState bad, 0?':'playState = '+_t.playState+', OK')); - - return false; - - }*/ - - return isNew; - - } - - }; - - this._get_html5_duration = function() { - - var _iO = _t._iO, - // if audio object exists, use its duration - else, instance option duration (if provided - it's a hack, really, and should be retired) OR null - d = (_t._a && _t._a.duration ? _t._a.duration*1000 : (_iO && _iO.duration ? _iO.duration : null)), - result = (d && !isNaN(d) && d !== Infinity ? d : null); - - return result; - - }; - - this._apply_loop = function(a, nLoops) { - - /** - * boolean instead of "loop", for webkit? - spec says string. http://www.w3.org/TR/html-markup/audio.html#audio.attrs.loop - * note that loop is either off or infinite under HTML5, unlike Flash which allows arbitrary loop counts to be specified. - */ - - // - if (!a.loop && nLoops > 1) { - _s._wD('Note: Native HTML5 looping is infinite.'); - } - // - - a.loop = (nLoops > 1 ? 'loop' : ''); - - }; - - this._setup_html5 = function(oOptions) { - - var _iO = _mixin(_t._iO, oOptions), d = decodeURI, - _a = _useGlobalHTML5Audio ? _s._global_a : _t._a, - _dURL = d(_iO.url), - _oldIO = (_a && _a._t ? _a._t.instanceOptions : null), - result; - - if (_a) { - - if (_a._t) { - - if (!_useGlobalHTML5Audio && _dURL === d(_lastURL)) { - - // same url, ignore request - result = _a; - - } else if (_useGlobalHTML5Audio && _oldIO.url === _iO.url && (!_lastURL || (_lastURL === _oldIO.url))) { - - // iOS-type reuse case - result = _a; - - } - - if (result) { - - _t._apply_loop(_a, _iO.loops); - return result; - - } - - } - - _s._wD('setting URL on existing object: ' + _dURL + (_lastURL ? ', old URL: ' + _lastURL : '')); - - /** - * "First things first, I, Poppa.." (reset the previous state of the old sound, if playing) - * Fixes case with devices that can only play one sound at a time - * Otherwise, other sounds in mid-play will be terminated without warning and in a stuck state - */ - - if (_useGlobalHTML5Audio && _a._t && _a._t.playState && _iO.url !== _oldIO.url) { - - _a._t.stop(); - - } - - // reset load/playstate, onPosition etc. if the URL is new. - // somewhat-tricky object re-use vs. new SMSound object, old vs. new URL comparisons - _resetProperties((_oldIO && _oldIO.url ? _iO.url === _oldIO.url : (_lastURL ? _lastURL === _iO.url : false))); - - _a.src = _iO.url; - _t.url = _iO.url; - _lastURL = _iO.url; - _a._called_load = false; - - } else { - - _wDS('h5a'); - - if (_iO.autoLoad || _iO.autoPlay) { - - _t._a = new Audio(_iO.url); - - } else { - - // null for stupid Opera 9.64 case - _t._a = (_isOpera && opera.version() < 10 ? new Audio(null) : new Audio()); - - } - - // assign local reference - _a = _t._a; - - _a._called_load = false; - - if (_useGlobalHTML5Audio) { - - _s._global_a = _a; - - } - - } - - _t.isHTML5 = true; - - // store a ref on the track - _t._a = _a; - - // store a ref on the audio - _a._t = _t; - - _add_html5_events(); - - _t._apply_loop(_a, _iO.loops); - - if (_iO.autoLoad || _iO.autoPlay) { - - _t.load(); - - } else { - - // early HTML5 implementation (non-standard) - _a.autobuffer = false; - - // standard ('none' is also an option.) - _a.preload = 'auto'; - - } - - return _a; - - }; - - _add_html5_events = function() { - - if (_t._a._added_events) { - return false; - } - - var f; - - function add(oEvt, oFn, bCapture) { - return _t._a ? _t._a.addEventListener(oEvt, oFn, bCapture||false) : null; - } - - _t._a._added_events = true; - - for (f in _html5_events) { - if (_html5_events.hasOwnProperty(f)) { - add(f, _html5_events[f]); - } - } - - return true; - - }; - - _remove_html5_events = function() { - - // Remove event listeners - - var f; - - function remove(oEvt, oFn, bCapture) { - return (_t._a ? _t._a.removeEventListener(oEvt, oFn, bCapture||false) : null); - } - - _s._wD(_h5+'removing event listeners: '+_t.id); - _t._a._added_events = false; - - for (f in _html5_events) { - if (_html5_events.hasOwnProperty(f)) { - remove(f, _html5_events[f]); - } - } - - }; - - /** - * Pseudo-private event internals - * ------------------------------ - */ - - this._onload = function(nSuccess) { - - - var fN, - // check for duration to prevent false positives from flash 8 when loading from cache. - loadOK = (!!(nSuccess) || (!_t.isHTML5 && _fV === 8 && _t.duration)); - - // - fN = 'SMSound._onload(): '; - _s._wD(fN + '"' + _t.id + '"' + (loadOK?' loaded.':' failed to load? - ' + _t.url), (loadOK?1:2)); - if (!loadOK && !_t.isHTML5) { - if (_s.sandbox.noRemote === true) { - _s._wD(fN + _str('noNet'), 1); - } - if (_s.sandbox.noLocal === true) { - _s._wD(fN + _str('noLocal'), 1); - } - } - // - - _t.loaded = loadOK; - _t.readyState = loadOK?3:2; - _t._onbufferchange(0); - - if (_t._iO.onload) { - _t._iO.onload.apply(_t, [loadOK]); - } - - return true; - - }; - - this._onbufferchange = function(nIsBuffering) { - - if (_t.playState === 0) { - // ignore if not playing - return false; - } - - if ((nIsBuffering && _t.isBuffering) || (!nIsBuffering && !_t.isBuffering)) { - return false; - } - - _t.isBuffering = (nIsBuffering === 1); - if (_t._iO.onbufferchange) { - _s._wD('SMSound._onbufferchange(): ' + nIsBuffering); - _t._iO.onbufferchange.apply(_t); - } - - return true; - - }; - - /** - * Notify Mobile Safari that user action is required - * to continue playing / loading the audio file. - */ - - this._onsuspend = function() { - - if (_t._iO.onsuspend) { - _s._wD('SMSound._onsuspend()'); - _t._iO.onsuspend.apply(_t); - } - - return true; - - }; - - /** - * flash 9/movieStar + RTMP-only method, should fire only once at most - * at this point we just recreate failed sounds rather than trying to reconnect - */ - - this._onfailure = function(msg, level, code) { - - _t.failures++; - _s._wD('SMSound._onfailure(): "'+_t.id+'" count '+_t.failures); - - if (_t._iO.onfailure && _t.failures === 1) { - _t._iO.onfailure(_t, msg, level, code); - } else { - _s._wD('SMSound._onfailure(): ignoring'); - } - - }; - - this._onfinish = function() { - - // store local copy before it gets trashed.. - var _io_onfinish = _t._iO.onfinish; - - _t._onbufferchange(0); - _t._resetOnPosition(0); - - // reset some state items - if (_t.instanceCount) { - - _t.instanceCount--; - - if (!_t.instanceCount) { - - // remove onPosition listeners, if any - _detachOnPosition(); - - // reset instance options - _t.playState = 0; - _t.paused = false; - _t.instanceCount = 0; - _t.instanceOptions = {}; - _t._iO = {}; - _stop_html5_timer(); - - // reset position, too - if (_t.isHTML5) { - _t.position = 0; - } - - } - - if (!_t.instanceCount || _t._iO.multiShotEvents) { - // fire onfinish for last, or every instance - if (_io_onfinish) { - _s._wD('SMSound._onfinish(): "' + _t.id + '"'); - _io_onfinish.apply(_t); - } - } - - } - - }; - - this._whileloading = function(nBytesLoaded, nBytesTotal, nDuration, nBufferLength) { - - var _iO = _t._iO; - - _t.bytesLoaded = nBytesLoaded; - _t.bytesTotal = nBytesTotal; - _t.duration = Math.floor(nDuration); - _t.bufferLength = nBufferLength; - - if (!_t.isHTML5 && !_iO.isMovieStar) { - - if (_iO.duration) { - // use duration from options, if specified and larger. nobody should be specifying duration in options, actually, and it should be retired. - _t.durationEstimate = (_t.duration > _iO.duration) ? _t.duration : _iO.duration; - } else { - _t.durationEstimate = parseInt((_t.bytesTotal / _t.bytesLoaded) * _t.duration, 10); - } - - } else { - - _t.durationEstimate = _t.duration; - - } - - // for flash, reflect sequential-load-style buffering - if (!_t.isHTML5) { - _t.buffered = [{ - 'start': 0, - 'end': _t.duration - }]; - } - - // allow whileloading to fire even if "load" fired under HTML5, due to HTTP range/partials - if ((_t.readyState !== 3 || _t.isHTML5) && _iO.whileloading) { - _iO.whileloading.apply(_t); - } - - }; - - this._whileplaying = function(nPosition, oPeakData, oWaveformDataLeft, oWaveformDataRight, oEQData) { - - var _iO = _t._iO, - eqLeft; - - if (isNaN(nPosition) || nPosition === null) { - // flash safety net - return false; - } - - // Safari HTML5 play() may return small -ve values when starting from position: 0, eg. -50.120396875. Unexpected/invalid per W3, I think. Normalize to 0. - _t.position = Math.max(0, nPosition); - - _t._processOnPosition(); - - if (!_t.isHTML5 && _fV > 8) { - - if (_iO.usePeakData && typeof oPeakData !== 'undefined' && oPeakData) { - _t.peakData = { - left: oPeakData.leftPeak, - right: oPeakData.rightPeak - }; - } - - if (_iO.useWaveformData && typeof oWaveformDataLeft !== 'undefined' && oWaveformDataLeft) { - _t.waveformData = { - left: oWaveformDataLeft.split(','), - right: oWaveformDataRight.split(',') - }; - } - - if (_iO.useEQData) { - if (typeof oEQData !== 'undefined' && oEQData && oEQData.leftEQ) { - eqLeft = oEQData.leftEQ.split(','); - _t.eqData = eqLeft; - _t.eqData.left = eqLeft; - if (typeof oEQData.rightEQ !== 'undefined' && oEQData.rightEQ) { - _t.eqData.right = oEQData.rightEQ.split(','); - } - } - } - - } - - if (_t.playState === 1) { - - // special case/hack: ensure buffering is false if loading from cache (and not yet started) - if (!_t.isHTML5 && _fV === 8 && !_t.position && _t.isBuffering) { - _t._onbufferchange(0); - } - - if (_iO.whileplaying) { - // flash may call after actual finish - _iO.whileplaying.apply(_t); - } - - } - - return true; - - }; - - this._oncaptiondata = function(oData) { - - /** - * internal: flash 9 + NetStream (MovieStar/RTMP-only) feature - * - * @param {object} oData - */ - - _s._wD('SMSound._oncaptiondata(): "' + this.id + '" caption data received.'); - - _t.captiondata = oData; - - if (_t._iO.oncaptiondata) { - _t._iO.oncaptiondata.apply(_t, [oData]); - } - - }; - - this._onmetadata = function(oMDProps, oMDData) { - - /** - * internal: flash 9 + NetStream (MovieStar/RTMP-only) feature - * RTMP may include song title, MovieStar content may include encoding info - * - * @param {array} oMDProps (names) - * @param {array} oMDData (values) - */ - - _s._wD('SMSound._onmetadata(): "' + this.id + '" metadata received.'); - - var oData = {}, i, j; - - for (i = 0, j = oMDProps.length; i < j; i++) { - oData[oMDProps[i]] = oMDData[i]; - } - _t.metadata = oData; - - if (_t._iO.onmetadata) { - _t._iO.onmetadata.apply(_t); - } - - }; - - this._onid3 = function(oID3Props, oID3Data) { - - /** - * internal: flash 8 + flash 9 ID3 feature - * may include artist, song title etc. - * - * @param {array} oID3Props (names) - * @param {array} oID3Data (values) - */ - - _s._wD('SMSound._onid3(): "' + this.id + '" ID3 data received.'); - - var oData = [], i, j; - - for (i = 0, j = oID3Props.length; i < j; i++) { - oData[oID3Props[i]] = oID3Data[i]; - } - _t.id3 = _mixin(_t.id3, oData); - - if (_t._iO.onid3) { - _t._iO.onid3.apply(_t); - } - - }; - - // flash/RTMP-only - - this._onconnect = function(bSuccess) { - - bSuccess = (bSuccess === 1); - _s._wD('SMSound._onconnect(): "'+_t.id+'"'+(bSuccess?' connected.':' failed to connect? - '+_t.url), (bSuccess?1:2)); - _t.connected = bSuccess; - - if (bSuccess) { - - _t.failures = 0; - - if (_idCheck(_t.id)) { - if (_t.getAutoPlay()) { - // only update the play state if auto playing - _t.play(undefined, _t.getAutoPlay()); - } else if (_t._iO.autoLoad) { - _t.load(); - } - } - - if (_t._iO.onconnect) { - _t._iO.onconnect.apply(_t, [bSuccess]); - } - - } - - }; - - this._ondataerror = function(sError) { - - // flash 9 wave/eq data handler - // hack: called at start, and end from flash at/after onfinish() - if (_t.playState > 0) { - _s._wD('SMSound._ondataerror(): ' + sError); - if (_t._iO.ondataerror) { - _t._iO.ondataerror.apply(_t); - } - } - - }; - - }; // SMSound() - - /** - * Private SoundManager internals - * ------------------------------ - */ - - _getDocument = function() { - - return (_doc.body || _doc._docElement || _doc.getElementsByTagName('div')[0]); - - }; - - _id = function(sID) { - - return _doc.getElementById(sID); - - }; - - _mixin = function(oMain, oAdd) { - - // non-destructive merge - var o1 = (oMain || {}), o2, o; - - // if unspecified, o2 is the default options object - o2 = (typeof oAdd === 'undefined' ? _s.defaultOptions : oAdd); - - for (o in o2) { - - if (o2.hasOwnProperty(o) && typeof o1[o] === 'undefined') { - - if (typeof o2[o] !== 'object' || o2[o] === null) { - - // assign directly - o1[o] = o2[o]; - - } else { - - // recurse through o2 - o1[o] = _mixin(o1[o], o2[o]); - - } - - } - - } - - return o1; - - }; - - // additional soundManager properties that soundManager.setup() will accept - - _extraOptions = { - 'onready': 1, - 'ontimeout': 1, - 'defaultOptions': 1, - 'flash9Options': 1, - 'movieStarOptions': 1 - }; - - _assign = function(o, oParent) { - - /** - * recursive assignment of properties, soundManager.setup() helper - * allows property assignment based on whitelist - */ - - var i, - result = true, - hasParent = (typeof oParent !== 'undefined'), - setupOptions = _s.setupOptions, - extraOptions = _extraOptions; - - // - - // if soundManager.setup() called, show accepted parameters. - - if (typeof o === 'undefined') { - - result = []; - - for (i in setupOptions) { - - if (setupOptions.hasOwnProperty(i)) { - result.push(i); - } - - } - - for (i in extraOptions) { - - if (extraOptions.hasOwnProperty(i)) { - - if (typeof _s[i] === 'object') { - - result.push(i+': {...}'); - - } else if (_s[i] instanceof Function) { - - result.push(i+': function() {...}'); - - } else { - - result.push(i); - - } - - } - - } - - _s._wD(_str('setup', result.join(', '))); - - return false; - - } - - // - - for (i in o) { - - if (o.hasOwnProperty(i)) { - - // if not an {object} we want to recurse through... - - if (typeof o[i] !== 'object' || o[i] === null || o[i] instanceof Array) { - - // check "allowed" options - - if (hasParent && typeof extraOptions[oParent] !== 'undefined') { - - // valid recursive / nested object option, eg., { defaultOptions: { volume: 50 } } - _s[oParent][i] = o[i]; - - } else if (typeof setupOptions[i] !== 'undefined') { - - // special case: assign to setupOptions object, which soundManager property references - _s.setupOptions[i] = o[i]; - - // assign directly to soundManager, too - _s[i] = o[i]; - - } else if (typeof extraOptions[i] === 'undefined') { - - // invalid or disallowed parameter. complain. - _complain(_str((typeof _s[i] === 'undefined' ? 'setupUndef' : 'setupError'), i), 2); - - result = false; - - } else { - - /** - * valid extraOptions parameter. - * is it a method, like onready/ontimeout? call it. - * multiple parameters should be in an array, eg. soundManager.setup({onready: [myHandler, myScope]}); - */ - - if (_s[i] instanceof Function) { - - _s[i].apply(_s, (o[i] instanceof Array? o[i] : [o[i]])); - - } else { - - // good old-fashioned direct assignment - _s[i] = o[i]; - - } - - } - - } else { - - // recursion case, eg., { defaultOptions: { ... } } - - if (typeof extraOptions[i] === 'undefined') { - - // invalid or disallowed parameter. complain. - _complain(_str((typeof _s[i] === 'undefined' ? 'setupUndef' : 'setupError'), i), 2); - - result = false; - - } else { - - // recurse through object - return _assign(o[i], i); - - } - - } - - } - - } - - return result; - - }; - - function _preferFlashCheck(kind) { - - // whether flash should play a given type - return (_s.preferFlash && _hasFlash && !_s.ignoreFlash && (typeof _s.flash[kind] !== 'undefined' && _s.flash[kind])); - - } - - /** - * Internal DOM2-level event helpers - * --------------------------------- - */ - - _event = (function() { - - var old = (_win.attachEvent), - evt = { - add: (old?'attachEvent':'addEventListener'), - remove: (old?'detachEvent':'removeEventListener') - }; - - function getArgs(oArgs) { - - var args = _slice.call(oArgs), - len = args.length; - - if (old) { - // prefix - args[1] = 'on' + args[1]; - if (len > 3) { - // no capture - args.pop(); - } - } else if (len === 3) { - args.push(false); - } - - return args; - - } - - function apply(args, sType) { - - var element = args.shift(), - method = [evt[sType]]; - - if (old) { - element[method](args[0], args[1]); - } else { - element[method].apply(element, args); - } - - } - - function add() { - - apply(getArgs(arguments), 'add'); - - } - - function remove() { - - apply(getArgs(arguments), 'remove'); - - } - - return { - 'add': add, - 'remove': remove - }; - - }()); - - /** - * Internal HTML5 event handling - * ----------------------------- - */ - - function _html5_event(oFn) { - - // wrap html5 event handlers so we don't call them on destroyed sounds - - return function(e) { - - var t = this._t, - result; - - if (!t || !t._a) { - // - if (t && t.id) { - _s._wD(_h5+'ignoring '+e.type+': '+t.id); - } else { - _s._wD(_h5+'ignoring '+e.type); - } - // - result = null; - } else { - result = oFn.call(this, e); - } - - return result; - - }; - - } - - _html5_events = { - - // HTML5 event-name-to-handler map - - abort: _html5_event(function() { - - _s._wD(_h5+'abort: '+this._t.id); - - }), - - // enough has loaded to play - - canplay: _html5_event(function() { - - var t = this._t, - position1K; - - if (t._html5_canplay) { - // this event has already fired. ignore. - return true; - } - - t._html5_canplay = true; - _s._wD(_h5+'canplay: '+t.id+', '+t.url); - t._onbufferchange(0); - - // position according to instance options - position1K = (typeof t._iO.position !== 'undefined' && !isNaN(t._iO.position)?t._iO.position/1000:null); - - // set the position if position was set before the sound loaded - if (t.position && this.currentTime !== position1K) { - _s._wD(_h5+'canplay: setting position to '+position1K); - try { - this.currentTime = position1K; - } catch(ee) { - _s._wD(_h5+'setting position of ' + position1K + ' failed: '+ee.message, 2); - } - } - - // hack for HTML5 from/to case - if (t._iO._oncanplay) { - t._iO._oncanplay(); - } - - }), - - canplaythrough: _html5_event(function() { - - var t = this._t; - - if (!t.loaded) { - t._onbufferchange(0); - t._whileloading(t.bytesLoaded, t.bytesTotal, t._get_html5_duration()); - t._onload(true); - } - - }), - - // TODO: Reserved for potential use - /* - emptied: _html5_event(function() { - - _s._wD(_h5+'emptied: '+this._t.id); - - }), - */ - - ended: _html5_event(function() { - - var t = this._t; - - _s._wD(_h5+'ended: '+t.id); - t._onfinish(); - - }), - - error: _html5_event(function() { - - _s._wD(_h5+'error: '+this.error.code); - // call load with error state? - this._t._onload(false); - - }), - - loadeddata: _html5_event(function() { - - var t = this._t; - - _s._wD(_h5+'loadeddata: '+this._t.id); - - // safari seems to nicely report progress events, eventually totalling 100% - if (!t._loaded && !_isSafari) { - t.duration = t._get_html5_duration(); - } - - }), - - loadedmetadata: _html5_event(function() { - - _s._wD(_h5+'loadedmetadata: '+this._t.id); - - }), - - loadstart: _html5_event(function() { - - _s._wD(_h5+'loadstart: '+this._t.id); - // assume buffering at first - this._t._onbufferchange(1); - - }), - - play: _html5_event(function() { - - _s._wD(_h5+'play: '+this._t.id+', '+this._t.url); - // once play starts, no buffering - this._t._onbufferchange(0); - - }), - - playing: _html5_event(function() { - - _s._wD(_h5+'playing: '+this._t.id); - - // once play starts, no buffering - this._t._onbufferchange(0); - - }), - - progress: _html5_event(function(e) { - - // note: can fire repeatedly after "loaded" event, due to use of HTTP range/partials - - var t = this._t, - i, j, str, buffered = 0, - isProgress = (e.type === 'progress'), - ranges = e.target.buffered, - // firefox 3.6 implements e.loaded/total (bytes) - loaded = (e.loaded||0), - total = (e.total||1), - // HTML5 returns msec. SM2 API uses seconds for setPosition() etc., whether Flash or HTML5. - scale = 1000; - - // reset the "buffered" (loaded byte ranges) array - t.buffered = []; - - if (ranges && ranges.length) { - - // if loaded is 0, try TimeRanges implementation as % of load - // https://developer.mozilla.org/en/DOM/TimeRanges - - // re-build "buffered" array - for (i=0, j=ranges.length; i - if (isProgress && ranges.length > 1) { - str = []; - j = ranges.length; - for (i=0; i - - } - - if (!isNaN(loaded)) { - - // if progress, likely not buffering - t._onbufferchange(0); - // TODO: prevent calls with duplicate values. - t._whileloading(loaded, total, t._get_html5_duration()); - if (loaded && total && loaded === total) { - // in case "onload" doesn't fire (eg. gecko 1.9.2) - _html5_events.canplaythrough.call(this, e); - } - - } - - }), - - ratechange: _html5_event(function() { - - _s._wD(_h5+'ratechange: '+this._t.id); - - }), - - suspend: _html5_event(function(e) { - - // download paused/stopped, may have finished (eg. onload) - var t = this._t; - - _s._wD(_h5+'suspend: '+t.id); - _html5_events.progress.call(this, e); - t._onsuspend(); - - }), - - stalled: _html5_event(function() { - - _s._wD(_h5+'stalled: '+this._t.id); - - }), - - timeupdate: _html5_event(function() { - - this._t._onTimer(); - - }), - - waiting: _html5_event(function() { - - var t = this._t; - - // see also: seeking - _s._wD(_h5+'waiting: '+t.id); - - // playback faster than download rate, etc. - t._onbufferchange(1); - - }) - - }; - - _html5OK = function(iO) { - - // playability test based on URL or MIME type - - var result; - - if (iO.serverURL || (iO.type && _preferFlashCheck(iO.type))) { - - // RTMP, or preferring flash - result = false; - - } else { - - // Use type, if specified. If HTML5-only mode, no other options, so just give 'er - result = ((iO.type ? _html5CanPlay({type:iO.type}) : _html5CanPlay({url:iO.url}) || _s.html5Only)); - - } - - return result; - - }; - - _html5Unload = function(oAudio, url) { - - /** - * Internal method: Unload media, and cancel any current/pending network requests. - * Firefox can load an empty URL, which allegedly destroys the decoder and stops the download. - * https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox#Stopping_the_download_of_media - * However, Firefox has been seen loading a relative URL from '' and thus requesting the hosting page on unload. - * Other UA behaviour is unclear, so everyone else gets an about:blank-style URL. - */ - - if (oAudio) { - // Firefox likes '' for unload (used to work?) - however, may request hosting page URL (bad.) Most other UAs dislike '' and fail to unload. - oAudio.src = url; - } - - }; - - _html5CanPlay = function(o) { - - /** - * Try to find MIME, test and return truthiness - * o = { - * url: '/path/to/an.mp3', - * type: 'audio/mp3' - * } - */ - - if (!_s.useHTML5Audio || !_s.hasHTML5) { - return false; - } - - var url = (o.url || null), - mime = (o.type || null), - aF = _s.audioFormats, - result, - offset, - fileExt, - item; - - // account for known cases like audio/mp3 - - if (mime && typeof _s.html5[mime] !== 'undefined') { - return (_s.html5[mime] && !_preferFlashCheck(mime)); - } - - if (!_html5Ext) { - _html5Ext = []; - for (item in aF) { - if (aF.hasOwnProperty(item)) { - _html5Ext.push(item); - if (aF[item].related) { - _html5Ext = _html5Ext.concat(aF[item].related); - } - } - } - _html5Ext = new RegExp('\\.('+_html5Ext.join('|')+')(\\?.*)?$','i'); - } - - // TODO: Strip URL queries, etc. - fileExt = (url ? url.toLowerCase().match(_html5Ext) : null); - - if (!fileExt || !fileExt.length) { - if (!mime) { - result = false; - } else { - // audio/mp3 -> mp3, result should be known - offset = mime.indexOf(';'); - // strip "audio/X; codecs.." - fileExt = (offset !== -1?mime.substr(0,offset):mime).substr(6); - } - } else { - // match the raw extension name - "mp3", for example - fileExt = fileExt[1]; - } - - if (fileExt && typeof _s.html5[fileExt] !== 'undefined') { - // result known - result = (_s.html5[fileExt] && !_preferFlashCheck(fileExt)); - } else { - mime = 'audio/'+fileExt; - result = _s.html5.canPlayType({type:mime}); - _s.html5[fileExt] = result; - // _s._wD('canPlayType, found result: '+result); - result = (result && _s.html5[mime] && !_preferFlashCheck(mime)); - } - - return result; - - }; - - _testHTML5 = function() { - - /** - * Internal: Iterates over audioFormats, determining support eg. audio/mp3, audio/mpeg and so on - * assigns results to html5[] and flash[]. - */ - - if (!_s.useHTML5Audio || !_s.hasHTML5) { - return false; - } - - // double-whammy: Opera 9.64 throws WRONG_ARGUMENTS_ERR if no parameter passed to Audio(), and Webkit + iOS happily tries to load "null" as a URL. :/ - var a = (typeof Audio !== 'undefined' ? (_isOpera && opera.version() < 10 ? new Audio(null) : new Audio()) : null), - item, lookup, support = {}, aF, i; - - function _cp(m) { - - var canPlay, i, j, - result = false, - isOK = false; - - if (!a || typeof a.canPlayType !== 'function') { - return result; - } - - if (m instanceof Array) { - // iterate through all mime types, return any successes - for (i=0, j=m.length; i= 0; i--) { - - // eg. audio/m4a - support['audio/'+aF[item].related[i]] = support[item]; - _s.html5[aF[item].related[i]] = support[item]; - _s.flash[aF[item].related[i]] = support[item]; - - } - - } - - } - - } - - support.canPlayType = (a?_cp:null); - _s.html5 = _mixin(_s.html5, support); - - return true; - - }; - - _strings = { - - // - notReady: 'Not loaded yet - wait for soundManager.onready()', - notOK: 'Audio support is not available.', - domError: _smc + 'createMovie(): appendChild/innerHTML call failed. DOM not ready or other error.', - spcWmode: _smc + 'createMovie(): Removing wmode, preventing known SWF loading issue(s)', - swf404: _sm + ': Verify that %s is a valid path.', - tryDebug: 'Try ' + _sm + '.debugFlash = true for more security details (output goes to SWF.)', - checkSWF: 'See SWF output for more debug info.', - localFail: _sm + ': Non-HTTP page (' + _doc.location.protocol + ' URL?) Review Flash player security settings for this special case:\nhttp://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html\nMay need to add/allow path, eg. c:/sm2/ or /users/me/sm2/', - waitFocus: _sm + ': Special case: Waiting for SWF to load with window focus...', - waitImpatient: _sm + ': Getting impatient, still waiting for Flash%s...', - waitForever: _sm + ': Waiting indefinitely for Flash (will recover if unblocked)...', - waitSWF: _sm + ': Retrying, waiting for 100% SWF load...', - needFunction: _sm + ': Function object expected for %s', - badID: 'Warning: Sound ID "%s" should be a string, starting with a non-numeric character', - currentObj: '--- ' + _sm + '._debug(): Current sound objects ---', - waitEI: _smc + 'initMovie(): Waiting for ExternalInterface call from Flash...', - waitOnload: _sm + ': Waiting for window.onload()', - docLoaded: _sm + ': Document already loaded', - onload: _smc + 'initComplete(): calling soundManager.onload()', - onloadOK: _sm + '.onload() complete', - init: _smc + 'init()', - didInit: _smc + 'init(): Already called?', - flashJS: _sm + ': Attempting JS to Flash call...', - secNote: 'Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html', - badRemove: 'Warning: Failed to remove flash movie.', - shutdown: _sm + '.disable(): Shutting down', - queue: _sm + ': Queueing %s handler', - smFail: _sm + ': Failed to initialise.', - smError: 'SMSound.load(): Exception: JS-Flash communication failed, or JS error.', - fbTimeout: 'No flash response, applying .'+_swfCSS.swfTimedout+' CSS...', - fbLoaded: 'Flash loaded', - fbHandler: _smc+'flashBlockHandler()', - manURL: 'SMSound.load(): Using manually-assigned URL', - onURL: _sm + '.load(): current URL already assigned.', - badFV: _sm + '.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.', - as2loop: 'Note: Setting stream:false so looping can work (flash 8 limitation)', - noNSLoop: 'Note: Looping not implemented for MovieStar formats', - needfl9: 'Note: Switching to flash 9, required for MP4 formats.', - mfTimeout: 'Setting flashLoadTimeout = 0 (infinite) for off-screen, mobile flash case', - needFlash: _sm + ': Fatal error: Flash is needed to play some required formats, but is not available.', - gotFocus: _sm + ': Got window focus.', - mfOn: 'mobileFlash::enabling on-screen flash repositioning', - policy: 'Enabling usePolicyFile for data access', - setup: _sm + '.setup(): allowed parameters: %s', - setupError: _sm + '.setup(): "%s" cannot be assigned with this method.', - setupUndef: _sm + '.setup(): Could not find option "%s"', - setupLate: _sm + '.setup(): url + flashVersion changes will not take effect until reboot().', - h5a: 'creating HTML5 Audio() object', - noURL: _sm + ': Flash URL required. Call soundManager.setup({url:...}) to get started.' - // - - }; - - _str = function() { - - // internal string replace helper. - // arguments: o [,items to replace] - // - - // real array, please - var args = _slice.call(arguments), - - // first arg - o = args.shift(), - - str = (_strings && _strings[o]?_strings[o]:''), i, j; - if (str && args && args.length) { - for (i = 0, j = args.length; i < j; i++) { - str = str.replace('%s', args[i]); - } - } - - return str; - // - - }; - - _loopFix = function(sOpt) { - - // flash 8 requires stream = false for looping to work - if (_fV === 8 && sOpt.loops > 1 && sOpt.stream) { - _wDS('as2loop'); - sOpt.stream = false; - } - - return sOpt; - - }; - - _policyFix = function(sOpt, sPre) { - - if (sOpt && !sOpt.usePolicyFile && (sOpt.onid3 || sOpt.usePeakData || sOpt.useWaveformData || sOpt.useEQData)) { - _s._wD((sPre || '') + _str('policy')); - sOpt.usePolicyFile = true; - } - - return sOpt; - - }; - - _complain = function(sMsg) { - - // - if (typeof console !== 'undefined' && typeof console.warn !== 'undefined') { - console.warn(sMsg); - } else { - _s._wD(sMsg); - } - // - - }; - - _doNothing = function() { - - return false; - - }; - - _disableObject = function(o) { - - var oProp; - - for (oProp in o) { - if (o.hasOwnProperty(oProp) && typeof o[oProp] === 'function') { - o[oProp] = _doNothing; - } - } - - oProp = null; - - }; - - _failSafely = function(bNoDisable) { - - // general failure exception handler - - if (typeof bNoDisable === 'undefined') { - bNoDisable = false; - } - - if (_disabled || bNoDisable) { - _wDS('smFail', 2); - _s.disable(bNoDisable); - } - - }; - - _normalizeMovieURL = function(smURL) { - - var urlParams = null, url; - - if (smURL) { - if (smURL.match(/\.swf(\?.*)?$/i)) { - urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf('.swf?') + 4); - if (urlParams) { - // assume user knows what they're doing - return smURL; - } - } else if (smURL.lastIndexOf('/') !== smURL.length - 1) { - // append trailing slash, if needed - smURL += '/'; - } - } - - url = (smURL && smURL.lastIndexOf('/') !== - 1 ? smURL.substr(0, smURL.lastIndexOf('/') + 1) : './') + _s.movieURL; - - if (_s.noSWFCache) { - url += ('?ts=' + new Date().getTime()); - } - - return url; - - }; - - _setVersionInfo = function() { - - // short-hand for internal use - - _fV = parseInt(_s.flashVersion, 10); - - if (_fV !== 8 && _fV !== 9) { - _s._wD(_str('badFV', _fV, _defaultFlashVersion)); - _s.flashVersion = _fV = _defaultFlashVersion; - } - - // debug flash movie, if applicable - - var isDebug = (_s.debugMode || _s.debugFlash?'_debug.swf':'.swf'); - - if (_s.useHTML5Audio && !_s.html5Only && _s.audioFormats.mp4.required && _fV < 9) { - _s._wD(_str('needfl9')); - _s.flashVersion = _fV = 9; - } - - _s.version = _s.versionNumber + (_s.html5Only?' (HTML5-only mode)':(_fV === 9?' (AS3/Flash 9)':' (AS2/Flash 8)')); - - // set up default options - if (_fV > 8) { - // +flash 9 base options - _s.defaultOptions = _mixin(_s.defaultOptions, _s.flash9Options); - _s.features.buffering = true; - // +moviestar support - _s.defaultOptions = _mixin(_s.defaultOptions, _s.movieStarOptions); - _s.filePatterns.flash9 = new RegExp('\\.(mp3|' + _netStreamTypes.join('|') + ')(\\?.*)?$', 'i'); - _s.features.movieStar = true; - } else { - _s.features.movieStar = false; - } - - // regExp for flash canPlay(), etc. - _s.filePattern = _s.filePatterns[(_fV !== 8?'flash9':'flash8')]; - - // if applicable, use _debug versions of SWFs - _s.movieURL = (_fV === 8?'soundmanager2.swf':'soundmanager2_flash9.swf').replace('.swf', isDebug); - - _s.features.peakData = _s.features.waveformData = _s.features.eqData = (_fV > 8); - - }; - - _setPolling = function(bPolling, bHighPerformance) { - - if (!_flash) { - return false; - } - - _flash._setPolling(bPolling, bHighPerformance); - - }; - - _initDebug = function() { - - // starts debug mode, creating output
for UAs without console object - - // allow force of debug mode via URL - if (_s.debugURLParam.test(_wl)) { - _s.debugMode = true; - } - - // - if (_id(_s.debugID)) { - return false; - } - - var oD, oDebug, oTarget, oToggle, tmp; - - if (_s.debugMode && !_id(_s.debugID) && (!_hasConsole || !_s.useConsole || !_s.consoleOnly)) { - - oD = _doc.createElement('div'); - oD.id = _s.debugID + '-toggle'; - - oToggle = { - 'position': 'fixed', - 'bottom': '0px', - 'right': '0px', - 'width': '1.2em', - 'height': '1.2em', - 'lineHeight': '1.2em', - 'margin': '2px', - 'textAlign': 'center', - 'border': '1px solid #999', - 'cursor': 'pointer', - 'background': '#fff', - 'color': '#333', - 'zIndex': 10001 - }; - - oD.appendChild(_doc.createTextNode('-')); - oD.onclick = _toggleDebug; - oD.title = 'Toggle SM2 debug console'; - - if (_ua.match(/msie 6/i)) { - oD.style.position = 'absolute'; - oD.style.cursor = 'hand'; - } - - for (tmp in oToggle) { - if (oToggle.hasOwnProperty(tmp)) { - oD.style[tmp] = oToggle[tmp]; - } - } - - oDebug = _doc.createElement('div'); - oDebug.id = _s.debugID; - oDebug.style.display = (_s.debugMode?'block':'none'); - - if (_s.debugMode && !_id(oD.id)) { - try { - oTarget = _getDocument(); - oTarget.appendChild(oD); - } catch(e2) { - throw new Error(_str('domError')+' \n'+e2.toString()); - } - oTarget.appendChild(oDebug); - } - - } - - oTarget = null; - // - - }; - - _idCheck = this.getSoundById; - - // - _wDS = function(o, errorLevel) { - - return (!o ? '' : _s._wD(_str(o), errorLevel)); - - }; - - // last-resort debugging option - - if (_wl.indexOf('sm2-debug=alert') + 1 && _s.debugMode) { - _s._wD = function(sText) {window.alert(sText);}; - } - - _toggleDebug = function() { - - var o = _id(_s.debugID), - oT = _id(_s.debugID + '-toggle'); - - if (!o) { - return false; - } - - if (_debugOpen) { - // minimize - oT.innerHTML = '+'; - o.style.display = 'none'; - } else { - oT.innerHTML = '-'; - o.style.display = 'block'; - } - - _debugOpen = !_debugOpen; - - }; - - _debugTS = function(sEventType, bSuccess, sMessage) { - - // troubleshooter debug hooks - - if (typeof sm2Debugger !== 'undefined') { - try { - sm2Debugger.handleEvent(sEventType, bSuccess, sMessage); - } catch(e) { - // oh well - } - } - - return true; - - }; - // - - _getSWFCSS = function() { - - var css = []; - - if (_s.debugMode) { - css.push(_swfCSS.sm2Debug); - } - - if (_s.debugFlash) { - css.push(_swfCSS.flashDebug); - } - - if (_s.useHighPerformance) { - css.push(_swfCSS.highPerf); - } - - return css.join(' '); - - }; - - _flashBlockHandler = function() { - - // *possible* flash block situation. - - var name = _str('fbHandler'), - p = _s.getMoviePercent(), - css = _swfCSS, - error = {type:'FLASHBLOCK'}; - - if (_s.html5Only) { - return false; - } - - if (!_s.ok()) { - - if (_needsFlash) { - // make the movie more visible, so user can fix - _s.oMC.className = _getSWFCSS() + ' ' + css.swfDefault + ' ' + (p === null?css.swfTimedout:css.swfError); - _s._wD(name+': '+_str('fbTimeout')+(p?' ('+_str('fbLoaded')+')':'')); - } - - _s.didFlashBlock = true; - - // fire onready(), complain lightly - _processOnEvents({type:'ontimeout', ignoreInit:true, error:error}); - _catchError(error); - - } else { - - // SM2 loaded OK (or recovered) - - // - if (_s.didFlashBlock) { - _s._wD(name+': Unblocked'); - } - // - - if (_s.oMC) { - _s.oMC.className = [_getSWFCSS(), css.swfDefault, css.swfLoaded + (_s.didFlashBlock?' '+css.swfUnblocked:'')].join(' '); - } - - } - - }; - - _addOnEvent = function(sType, oMethod, oScope) { - - if (typeof _on_queue[sType] === 'undefined') { - _on_queue[sType] = []; - } - - _on_queue[sType].push({ - 'method': oMethod, - 'scope': (oScope || null), - 'fired': false - }); - - }; - - _processOnEvents = function(oOptions) { - - // if unspecified, assume OK/error - - if (!oOptions) { - oOptions = { - type: (_s.ok() ? 'onready' : 'ontimeout') - }; - } - - if (!_didInit && oOptions && !oOptions.ignoreInit) { - // not ready yet. - return false; - } - - if (oOptions.type === 'ontimeout' && (_s.ok() || (_disabled && !oOptions.ignoreInit))) { - // invalid case - return false; - } - - var status = { - success: (oOptions && oOptions.ignoreInit?_s.ok():!_disabled) - }, - - // queue specified by type, or none - srcQueue = (oOptions && oOptions.type?_on_queue[oOptions.type]||[]:[]), - - queue = [], i, j, - args = [status], - canRetry = (_needsFlash && _s.useFlashBlock && !_s.ok()); - - if (oOptions.error) { - args[0].error = oOptions.error; - } - - for (i = 0, j = srcQueue.length; i < j; i++) { - if (srcQueue[i].fired !== true) { - queue.push(srcQueue[i]); - } - } - - if (queue.length) { - _s._wD(_sm + ': Firing ' + queue.length + ' '+oOptions.type+'() item' + (queue.length === 1?'':'s')); - for (i = 0, j = queue.length; i < j; i++) { - if (queue[i].scope) { - queue[i].method.apply(queue[i].scope, args); - } else { - queue[i].method.apply(this, args); - } - if (!canRetry) { - // flashblock case doesn't count here - queue[i].fired = true; - } - } - } - - return true; - - }; - - _initUserOnload = function() { - - _win.setTimeout(function() { - - if (_s.useFlashBlock) { - _flashBlockHandler(); - } - - _processOnEvents(); - - // call user-defined "onload", scoped to window - - if (typeof _s.onload === 'function') { - _wDS('onload', 1); - _s.onload.apply(_win); - _wDS('onloadOK', 1); - } - - if (_s.waitForWindowLoad) { - _event.add(_win, 'load', _initUserOnload); - } - - },1); - - }; - - _detectFlash = function() { - - // hat tip: Flash Detect library (BSD, (C) 2007) by Carl "DocYes" S. Yestrau - http://featureblend.com/javascript-flash-detection-library.html / http://featureblend.com/license.txt - - if (typeof _hasFlash !== 'undefined') { - // this work has already been done. - return _hasFlash; - } - - var hasPlugin = false, n = navigator, nP = n.plugins, obj, type, types, AX = _win.ActiveXObject; - - if (nP && nP.length) { - type = 'application/x-shockwave-flash'; - types = n.mimeTypes; - if (types && types[type] && types[type].enabledPlugin && types[type].enabledPlugin.description) { - hasPlugin = true; - } - } else if (typeof AX !== 'undefined') { - try { - obj = new AX('ShockwaveFlash.ShockwaveFlash'); - } catch(e) { - // oh well - } - hasPlugin = (!!obj); - } - - _hasFlash = hasPlugin; - - return hasPlugin; - - }; - - _featureCheck = function() { - - var needsFlash, - item, - result = true, - formats = _s.audioFormats, - // iPhone <= 3.1 has broken HTML5 audio(), but firmware 3.2 (original iPad) + iOS4 works. - isSpecial = (_is_iDevice && !!(_ua.match(/os (1|2|3_0|3_1)/i))); - - if (isSpecial) { - - // has Audio(), but is broken; let it load links directly. - _s.hasHTML5 = false; - - // ignore flash case, however - _s.html5Only = true; - - if (_s.oMC) { - _s.oMC.style.display = 'none'; - } - - result = false; - - } else { - - if (_s.useHTML5Audio) { - - if (!_s.html5 || !_s.html5.canPlayType) { - _s._wD('SoundManager: No HTML5 Audio() support detected.'); - _s.hasHTML5 = false; - } - - // - if (_isBadSafari) { - _s._wD(_smc+'Note: Buggy HTML5 Audio in Safari on this OS X release, see https://bugs.webkit.org/show_bug.cgi?id=32159 - '+(!_hasFlash?' would use flash fallback for MP3/MP4, but none detected.':'will use flash fallback for MP3/MP4, if available'),1); - } - // - - } - - } - - if (_s.useHTML5Audio && _s.hasHTML5) { - - for (item in formats) { - if (formats.hasOwnProperty(item)) { - if ((formats[item].required && !_s.html5.canPlayType(formats[item].type)) || (_s.preferFlash && (_s.flash[item] || _s.flash[formats[item].type]))) { - // flash may be required, or preferred for this format - needsFlash = true; - } - } - } - - } - - // sanity check... - if (_s.ignoreFlash) { - needsFlash = false; - } - - _s.html5Only = (_s.hasHTML5 && _s.useHTML5Audio && !needsFlash); - - return (!_s.html5Only); - - }; - - _parseURL = function(url) { - - /** - * Internal: Finds and returns the first playable URL (or failing that, the first URL.) - * @param {string or array} url A single URL string, OR, an array of URL strings or {url:'/path/to/resource', type:'audio/mp3'} objects. - */ - - var i, j, urlResult = 0, result; - - if (url instanceof Array) { - - // find the first good one - for (i=0, j=url.length; i= 0; i--) { - - if (_s.sounds[_s.soundIDs[i]].isHTML5 && _s.sounds[_s.soundIDs[i]]._hasTimer) { - - _s.sounds[_s.soundIDs[i]]._onTimer(); - - } - - } - - }; - - _catchError = function(options) { - - options = (typeof options !== 'undefined' ? options : {}); - - if (typeof _s.onerror === 'function') { - _s.onerror.apply(_win, [{type:(typeof options.type !== 'undefined' ? options.type : null)}]); - } - - if (typeof options.fatal !== 'undefined' && options.fatal) { - _s.disable(); - } - - }; - - _badSafariFix = function() { - - // special case: "bad" Safari (OS X 10.3 - 10.7) must fall back to flash for MP3/MP4 - if (!_isBadSafari || !_detectFlash()) { - // doesn't apply - return false; - } - - var aF = _s.audioFormats, i, item; - - for (item in aF) { - if (aF.hasOwnProperty(item)) { - if (item === 'mp3' || item === 'mp4') { - _s._wD(_sm+': Using flash fallback for '+item+' format'); - _s.html5[item] = false; - // assign result to related formats, too - if (aF[item] && aF[item].related) { - for (i = aF[item].related.length-1; i >= 0; i--) { - _s.html5[aF[item].related[i]] = false; - } - } - } - } - } - - }; - - /** - * Pseudo-private flash/ExternalInterface methods - * ---------------------------------------------- - */ - - this._setSandboxType = function(sandboxType) { - - // - var sb = _s.sandbox; - - sb.type = sandboxType; - sb.description = sb.types[(typeof sb.types[sandboxType] !== 'undefined'?sandboxType:'unknown')]; - - _s._wD('Flash security sandbox type: ' + sb.type); - - if (sb.type === 'localWithFile') { - - sb.noRemote = true; - sb.noLocal = false; - _wDS('secNote', 2); - - } else if (sb.type === 'localWithNetwork') { - - sb.noRemote = false; - sb.noLocal = true; - - } else if (sb.type === 'localTrusted') { - - sb.noRemote = false; - sb.noLocal = false; - - } - // - - }; - - this._externalInterfaceOK = function(flashDate, swfVersion) { - - // flash callback confirming flash loaded, EI working etc. - // flashDate = approx. timing/delay info for JS/flash bridge - // swfVersion: SWF build string - - if (_s.swfLoaded) { - return false; - } - - var e, eiTime = new Date().getTime(); - - _s._wD(_smc+'externalInterfaceOK()' + (flashDate?' (~' + (eiTime - flashDate) + ' ms)':'')); - _debugTS('swf', true); - _debugTS('flashtojs', true); - _s.swfLoaded = true; - _tryInitOnFocus = false; - - if (_isBadSafari) { - _badSafariFix(); - } - - // complain if JS + SWF build/version strings don't match, excluding +DEV builds - // - if (!swfVersion || swfVersion.replace(/\+dev/i,'') !== _s.versionNumber.replace(/\+dev/i, '')) { - - e = _sm + ': Fatal: JavaScript file build "' + _s.versionNumber + '" does not match Flash SWF build "' + swfVersion + '" at ' + _s.url + '. Ensure both are up-to-date.'; - - // escape flash -> JS stack so this error fires in window. - setTimeout(function versionMismatch() { - throw new Error(e); - }, 0); - - // exit, init will fail with timeout - return false; - - } - // - - // slight delay before init - setTimeout(_init, _isIE ? 100 : 1); - - }; - - /** - * Private initialization helpers - * ------------------------------ - */ - - _createMovie = function(smID, smURL) { - - if (_didAppend && _appendSuccess) { - // ignore if already succeeded - return false; - } - - function _initMsg() { - _s._wD('-- SoundManager 2 ' + _s.version + (!_s.html5Only && _s.useHTML5Audio?(_s.hasHTML5?' + HTML5 audio':', no HTML5 audio support'):'') + (!_s.html5Only ? (_s.useHighPerformance?', high performance mode, ':', ') + (( _s.flashPollingInterval ? 'custom (' + _s.flashPollingInterval + 'ms)' : 'normal') + ' polling') + (_s.wmode?', wmode: ' + _s.wmode:'') + (_s.debugFlash?', flash debug mode':'') + (_s.useFlashBlock?', flashBlock mode':'') : '') + ' --', 1); - } - - if (_s.html5Only) { - - // 100% HTML5 mode - _setVersionInfo(); - - _initMsg(); - _s.oMC = _id(_s.movieID); - _init(); - - // prevent multiple init attempts - _didAppend = true; - - _appendSuccess = true; - - return false; - - } - - // flash path - var remoteURL = (smURL || _s.url), - localURL = (_s.altURL || remoteURL), - swfTitle = 'JS/Flash audio component (SoundManager 2)', - oTarget = _getDocument(), - extraClass = _getSWFCSS(), - isRTL = null, - html = _doc.getElementsByTagName('html')[0], - oEmbed, oMovie, tmp, movieHTML, oEl, s, x, sClass; - - isRTL = (html && html.dir && html.dir.match(/rtl/i)); - smID = (typeof smID === 'undefined'?_s.id:smID); - - function param(name, value) { - return ''; - } - - // safety check for legacy (change to Flash 9 URL) - _setVersionInfo(); - _s.url = _normalizeMovieURL(_overHTTP?remoteURL:localURL); - smURL = _s.url; - - _s.wmode = (!_s.wmode && _s.useHighPerformance ? 'transparent' : _s.wmode); - - if (_s.wmode !== null && (_ua.match(/msie 8/i) || (!_isIE && !_s.useHighPerformance)) && navigator.platform.match(/win32|win64/i)) { - /** - * extra-special case: movie doesn't load until scrolled into view when using wmode = anything but 'window' here - * does not apply when using high performance (position:fixed means on-screen), OR infinite flash load timeout - * wmode breaks IE 8 on Vista + Win7 too in some cases, as of January 2011 (?) - */ - _wDS('spcWmode'); - _s.wmode = null; - } - - oEmbed = { - 'name': smID, - 'id': smID, - 'src': smURL, - 'quality': 'high', - 'allowScriptAccess': _s.allowScriptAccess, - 'bgcolor': _s.bgColor, - 'pluginspage': _http+'www.macromedia.com/go/getflashplayer', - 'title': swfTitle, - 'type': 'application/x-shockwave-flash', - 'wmode': _s.wmode, - // http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html - 'hasPriority': 'true' - }; - - if (_s.debugFlash) { - oEmbed.FlashVars = 'debug=1'; - } - - if (!_s.wmode) { - // don't write empty attribute - delete oEmbed.wmode; - } - - if (_isIE) { - - // IE is "special". - oMovie = _doc.createElement('div'); - movieHTML = [ - '', - param('movie', smURL), - param('AllowScriptAccess', _s.allowScriptAccess), - param('quality', oEmbed.quality), - (_s.wmode? param('wmode', _s.wmode): ''), - param('bgcolor', _s.bgColor), - param('hasPriority', 'true'), - (_s.debugFlash ? param('FlashVars', oEmbed.FlashVars) : ''), - '' - ].join(''); - - } else { - - oMovie = _doc.createElement('embed'); - for (tmp in oEmbed) { - if (oEmbed.hasOwnProperty(tmp)) { - oMovie.setAttribute(tmp, oEmbed[tmp]); - } - } - - } - - _initDebug(); - extraClass = _getSWFCSS(); - oTarget = _getDocument(); - - if (oTarget) { - - _s.oMC = (_id(_s.movieID) || _doc.createElement('div')); - - if (!_s.oMC.id) { - - _s.oMC.id = _s.movieID; - _s.oMC.className = _swfCSS.swfDefault + ' ' + extraClass; - s = null; - oEl = null; - - if (!_s.useFlashBlock) { - if (_s.useHighPerformance) { - // on-screen at all times - s = { - 'position': 'fixed', - 'width': '8px', - 'height': '8px', - // >= 6px for flash to run fast, >= 8px to start up under Firefox/win32 in some cases. odd? yes. - 'bottom': '0px', - 'left': '0px', - 'overflow': 'hidden' - }; - } else { - // hide off-screen, lower priority - s = { - 'position': 'absolute', - 'width': '6px', - 'height': '6px', - 'top': '-9999px', - 'left': '-9999px' - }; - if (isRTL) { - s.left = Math.abs(parseInt(s.left,10))+'px'; - } - } - } - - if (_isWebkit) { - // soundcloud-reported render/crash fix, safari 5 - _s.oMC.style.zIndex = 10000; - } - - if (!_s.debugFlash) { - for (x in s) { - if (s.hasOwnProperty(x)) { - _s.oMC.style[x] = s[x]; - } - } - } - - try { - if (!_isIE) { - _s.oMC.appendChild(oMovie); - } - oTarget.appendChild(_s.oMC); - if (_isIE) { - oEl = _s.oMC.appendChild(_doc.createElement('div')); - oEl.className = _swfCSS.swfBox; - oEl.innerHTML = movieHTML; - } - _appendSuccess = true; - } catch(e) { - throw new Error(_str('domError')+' \n'+e.toString()); - } - - } else { - - // SM2 container is already in the document (eg. flashblock use case) - sClass = _s.oMC.className; - _s.oMC.className = (sClass?sClass+' ':_swfCSS.swfDefault) + (extraClass?' '+extraClass:''); - _s.oMC.appendChild(oMovie); - if (_isIE) { - oEl = _s.oMC.appendChild(_doc.createElement('div')); - oEl.className = _swfCSS.swfBox; - oEl.innerHTML = movieHTML; - } - _appendSuccess = true; - - } - - } - - _didAppend = true; - _initMsg(); - _s._wD(_smc+'createMovie(): Trying to load ' + smURL + (!_overHTTP && _s.altURL?' (alternate URL)':''), 1); - - return true; - - }; - - _initMovie = function() { - - if (_s.html5Only) { - _createMovie(); - return false; - } - - // attempt to get, or create, movie (may already exist) - if (_flash) { - return false; - } - - if (!_s.url) { - - /** - * Something isn't right - we've reached init, but the soundManager url property has not been set. - * User has not called setup({url: ...}), or has not set soundManager.url (legacy use case) directly before init time. - * Notify and exit. If user calls setup() with a url: property, init will be restarted as in the deferred loading case. - */ - - _wDS('noURL'); - return false; - - } - - // inline markup case - _flash = _s.getMovie(_s.id); - - if (!_flash) { - if (!_oRemoved) { - // try to create - _createMovie(_s.id, _s.url); - } else { - // try to re-append removed movie after reboot() - if (!_isIE) { - _s.oMC.appendChild(_oRemoved); - } else { - _s.oMC.innerHTML = _oRemovedHTML; - } - _oRemoved = null; - _didAppend = true; - } - _flash = _s.getMovie(_s.id); - } - - // - if (_flash) { - _wDS('waitEI'); - } - // - - if (typeof _s.oninitmovie === 'function') { - setTimeout(_s.oninitmovie, 1); - } - - return true; - - }; - - _delayWaitForEI = function() { - - setTimeout(_waitForEI, 1000); - - }; - - _waitForEI = function() { - - var p, - loadIncomplete = false; - - if (!_s.url) { - // No SWF url to load (noURL case) - exit for now. Will be retried when url is set. - return false; - } - - if (_waitingForEI) { - return false; - } - - _waitingForEI = true; - _event.remove(_win, 'load', _delayWaitForEI); - - if (_tryInitOnFocus && !_isFocused) { - // Safari won't load flash in background tabs, only when focused. - _wDS('waitFocus'); - return false; - } - - if (!_didInit) { - p = _s.getMoviePercent(); - _s._wD(_str('waitImpatient', (p > 0 ? ' (SWF ' + p + '% loaded)' : ''))); - if (p > 0 && p < 100) { - loadIncomplete = true; - } - } - - setTimeout(function() { - - p = _s.getMoviePercent(); - - if (loadIncomplete) { - // special case: if movie *partially* loaded, retry until it's 100% before assuming failure. - _waitingForEI = false; - _s._wD(_str('waitSWF')); - _win.setTimeout(_delayWaitForEI, 1); - return false; - } - - // - if (!_didInit) { - _s._wD(_sm + ': No Flash response within expected time.\nLikely causes: ' + (p === 0?'Loading ' + _s.movieURL + ' may have failed (and/or Flash ' + _fV + '+ not present?), ':'') + 'Flash blocked or JS-Flash security error.' + (_s.debugFlash?' ' + _str('checkSWF'):''), 2); - if (!_overHTTP && p) { - _wDS('localFail', 2); - if (!_s.debugFlash) { - _wDS('tryDebug', 2); - } - } - if (p === 0) { - // if 0 (not null), probably a 404. - _s._wD(_str('swf404', _s.url)); - } - _debugTS('flashtojs', false, ': Timed out' + _overHTTP?' (Check flash security or flash blockers)':' (No plugin/missing SWF?)'); - } - // - - // give up / time-out, depending - - if (!_didInit && _okToDisable) { - if (p === null) { - // SWF failed. Maybe blocked. - if (_s.useFlashBlock || _s.flashLoadTimeout === 0) { - if (_s.useFlashBlock) { - _flashBlockHandler(); - } - _wDS('waitForever'); - } else { - // old SM2 behaviour, simply fail - _failSafely(true); - } - } else { - // flash loaded? Shouldn't be a blocking issue, then. - if (_s.flashLoadTimeout === 0) { - _wDS('waitForever'); - } else { - _failSafely(true); - } - } - } - - }, _s.flashLoadTimeout); - - }; - - _handleFocus = function() { - - function cleanup() { - _event.remove(_win, 'focus', _handleFocus); - } - - if (_isFocused || !_tryInitOnFocus) { - // already focused, or not special Safari background tab case - cleanup(); - return true; - } - - _okToDisable = true; - _isFocused = true; - _wDS('gotFocus'); - - // allow init to restart - _waitingForEI = false; - - // kick off ExternalInterface timeout, now that the SWF has started - _delayWaitForEI(); - - cleanup(); - return true; - - }; - - _showSupport = function() { - - // - - var item, tests = []; - - if (_s.useHTML5Audio && _s.hasHTML5) { - for (item in _s.audioFormats) { - if (_s.audioFormats.hasOwnProperty(item)) { - tests.push(item + ': ' + _s.html5[item] + (!_s.html5[item] && _hasFlash && _s.flash[item] ? ' (using flash)' : (_s.preferFlash && _s.flash[item] && _hasFlash ? ' (preferring flash)': (!_s.html5[item] ? ' (' + (_s.audioFormats[item].required ? 'required, ':'') + 'and no flash support)' : '')))); - } - } - _s._wD('-- SoundManager 2: HTML5 support tests ('+_s.html5Test+'): '+tests.join(', ')+' --',1); - } - - // - - }; - - _initComplete = function(bNoDisable) { - - if (_didInit) { - return false; - } - - if (_s.html5Only) { - // all good. - _s._wD('-- SoundManager 2: loaded --'); - _didInit = true; - _initUserOnload(); - _debugTS('onload', true); - return true; - } - - var wasTimeout = (_s.useFlashBlock && _s.flashLoadTimeout && !_s.getMoviePercent()), - result = true, - error; - - if (!wasTimeout) { - _didInit = true; - if (_disabled) { - error = {type: (!_hasFlash && _needsFlash ? 'NO_FLASH' : 'INIT_TIMEOUT')}; - } - } - - _s._wD('-- SoundManager 2 ' + (_disabled?'failed to load':'loaded') + ' (' + (_disabled?'Flash security/load error':'OK') + ') --', 1); - - if (_disabled || bNoDisable) { - if (_s.useFlashBlock && _s.oMC) { - _s.oMC.className = _getSWFCSS() + ' ' + (_s.getMoviePercent() === null?_swfCSS.swfTimedout:_swfCSS.swfError); - } - _processOnEvents({type:'ontimeout', error:error, ignoreInit: true}); - _debugTS('onload', false); - _catchError(error); - result = false; - } else { - _debugTS('onload', true); - } - - if (!_disabled) { - if (_s.waitForWindowLoad && !_windowLoaded) { - _wDS('waitOnload'); - _event.add(_win, 'load', _initUserOnload); - } else { - // - if (_s.waitForWindowLoad && _windowLoaded) { - _wDS('docLoaded'); - } - // - _initUserOnload(); - } - } - - return result; - - }; - - /** - * apply top-level setupOptions object as local properties, eg., this.setupOptions.flashVersion -> this.flashVersion (soundManager.flashVersion) - * this maintains backward compatibility, and allows properties to be defined separately for use by soundManager.setup(). - */ - - _setProperties = function() { - - var i, - o = _s.setupOptions; - - for (i in o) { - - if (o.hasOwnProperty(i)) { - - // assign local property if not already defined - - if (typeof _s[i] === 'undefined') { - - _s[i] = o[i]; - - } else if (_s[i] !== o[i]) { - - // legacy support: write manually-assigned property (eg., soundManager.url) back to setupOptions to keep things in sync - _s.setupOptions[i] = _s[i]; - - } - - } - - } - - }; - - - _init = function() { - - _wDS('init'); - - // called after onload() - - if (_didInit) { - _wDS('didInit'); - return false; - } - - function _cleanup() { - _event.remove(_win, 'load', _s.beginDelayedInit); - } - - if (_s.html5Only) { - if (!_didInit) { - // we don't need no steenking flash! - _cleanup(); - _s.enabled = true; - _initComplete(); - } - return true; - } - - // flash path - _initMovie(); - - try { - - _wDS('flashJS'); - - // attempt to talk to Flash - _flash._externalInterfaceTest(false); - - // apply user-specified polling interval, OR, if "high performance" set, faster vs. default polling - // (determines frequency of whileloading/whileplaying callbacks, effectively driving UI framerates) - _setPolling(true, (_s.flashPollingInterval || (_s.useHighPerformance ? 10 : 50))); - - if (!_s.debugMode) { - // stop the SWF from making debug output calls to JS - _flash._disableDebug(); - } - - _s.enabled = true; - _debugTS('jstoflash', true); - - if (!_s.html5Only) { - // prevent browser from showing cached page state (or rather, restoring "suspended" page state) via back button, because flash may be dead - // http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/ - _event.add(_win, 'unload', _doNothing); - } - - } catch(e) { - - _s._wD('js/flash exception: ' + e.toString()); - _debugTS('jstoflash', false); - _catchError({type:'JS_TO_FLASH_EXCEPTION', fatal:true}); - // don't disable, for reboot() - _failSafely(true); - _initComplete(); - - return false; - - } - - _initComplete(); - - // disconnect events - _cleanup(); - - return true; - - }; - - _domContentLoaded = function() { - - if (_didDCLoaded) { - return false; - } - - _didDCLoaded = true; - - // assign top-level soundManager properties eg. soundManager.url - _setProperties(); - - _initDebug(); - - /** - * Temporary feature: allow force of HTML5 via URL params: sm2-usehtml5audio=0 or 1 - * Ditto for sm2-preferFlash, too. - */ - // - (function(){ - - var a = 'sm2-usehtml5audio=', - a2 = 'sm2-preferflash=', - b = null, - b2 = null, - hasCon = (typeof console !== 'undefined' && typeof console.log === 'function'), - l = _wl.toLowerCase(); - - if (l.indexOf(a) !== -1) { - b = (l.charAt(l.indexOf(a)+a.length) === '1'); - if (hasCon) { - console.log((b?'Enabling ':'Disabling ')+'useHTML5Audio via URL parameter'); - } - _s.setup({ - 'useHTML5Audio': b - }); - } - - if (l.indexOf(a2) !== -1) { - b2 = (l.charAt(l.indexOf(a2)+a2.length) === '1'); - if (hasCon) { - console.log((b2?'Enabling ':'Disabling ')+'preferFlash via URL parameter'); - } - _s.setup({ - 'preferFlash': b2 - }); - } - - }()); - // - - if (!_hasFlash && _s.hasHTML5) { - _s._wD('SoundManager: No Flash detected'+(!_s.useHTML5Audio?', enabling HTML5.':'. Trying HTML5-only mode.')); - _s.setup({ - 'useHTML5Audio': true, - // make sure we aren't preferring flash, either - // TODO: preferFlash should not matter if flash is not installed. Currently, stuff breaks without the below tweak. - 'preferFlash': false - }); - } - - _testHTML5(); - _s.html5.usingFlash = _featureCheck(); - _needsFlash = _s.html5.usingFlash; - _showSupport(); - - if (!_hasFlash && _needsFlash) { - _wDS('needFlash'); - // TODO: Fatal here vs. timeout approach, etc. - // hack: fail sooner. - _s.setup({ - 'flashLoadTimeout': 1 - }); - } - - if (_doc.removeEventListener) { - _doc.removeEventListener('DOMContentLoaded', _domContentLoaded, false); - } - - _initMovie(); - return true; - - }; - - _domContentLoadedIE = function() { - - if (_doc.readyState === 'complete') { - _domContentLoaded(); - _doc.detachEvent('onreadystatechange', _domContentLoadedIE); - } - - return true; - - }; - - _winOnLoad = function() { - // catch edge case of _initComplete() firing after window.load() - _windowLoaded = true; - _event.remove(_win, 'load', _winOnLoad); - }; - - // sniff up-front - _detectFlash(); - - // focus and window load, init (primarily flash-driven) - _event.add(_win, 'focus', _handleFocus); - _event.add(_win, 'load', _delayWaitForEI); - _event.add(_win, 'load', _winOnLoad); - - if (_doc.addEventListener) { - - _doc.addEventListener('DOMContentLoaded', _domContentLoaded, false); - - } else if (_doc.attachEvent) { - - _doc.attachEvent('onreadystatechange', _domContentLoadedIE); - - } else { - - // no add/attachevent support - safe to assume no JS -> Flash either - _debugTS('onload', false); - _catchError({type:'NO_DOM2_EVENTS', fatal:true}); - - } - -} // SoundManager() - -// SM2_DEFER details: http://www.schillmania.com/projects/soundmanager2/doc/getstarted/#lazy-loading - -if (typeof SM2_DEFER === 'undefined' || !SM2_DEFER) { - soundManager = new SoundManager(); -} - -/** - * SoundManager public interfaces - * ------------------------------ - */ - -window.SoundManager = SoundManager; // constructor -window.soundManager = soundManager; // public API, flash callbacks etc. - -}(window)); \ No newline at end of file diff --git a/timeside/static/timeside/js/markermap.js b/timeside/static/timeside/js/markermap.js deleted file mode 100644 index ad3ae8c..0000000 --- a/timeside/static/timeside/js/markermap.js +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (C) 2007-2011 Parisson - * Copyright (c) 2011 Riccardo Zaccarelli - * - * This file is part of TimeSide. - * - * TimeSide is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * TimeSide is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with TimeSide. If not, see . - * - * Author: Riccardo Zaccarelli - */ - -/** - * class fior managing markers in the player. This class extends TimesideArray (see timeside.js), and communicates with the other - * two TimesideArrays of the player which receive edit events (click, keys events etcetera): the ruler (ruler.js) and the markermapdiv (divmarker.js) - * All bindings between these three classes are set in in the player (See player.js , in particular loadMarkers method) - */ -Timeside.classes.MarkerMap = Timeside.classes.TimesideArray.extend({ - - init: function() { - this._super(); - }, - - pFloat: parseFloat, //reference to function parseFloat for faster lookup - //overridden - add: function(newMarker) { - if(!('offset' in newMarker)){ - return -1; - } - - if(typeof newMarker.offset != 'number'){ //check to be sure: - newMarker.offset = this.pFloat(newMarker.offset); - } - if(!('id' in newMarker)){ - newMarker.id = this.$TU.uniqid(); //Timeside.utils.uniqid(); - } - if(!('isEditable' in newMarker)){ - newMarker.isEditable = false; - } - var marker = newMarker; - var idx = this.insertionIndex(marker); - if(idx>=0){ //it exists? there is a problem.... - this.debug('markermap.add: adding an already existing marker!!'); //should not happen. however... - return -1; - } - - idx = -idx-1; - //we do not call the super add cause we want to insert at a specified index - this._super(marker,idx); - //notifies controller.onMarkerMapAdd - - this.fire('add', { - marker: marker, - index: idx - }); - - return idx; - }, - - //overridden method. Contrarily to super method, - //where the first argument is the index (integer), here the - //the first argument can also be a marker. Its index will be found and, if valid, the super method will be called - //RETURNS -1 IF SOMETHING HAS GONE WRONG, OTHERWISE THE - remove: function(markerOrMarkerIndex) { - var idx = -1; - if(typeof markerOrMarkerIndex == 'number'){ - idx = markerOrMarkerIndex; - }else if('id' in markerOrMarkerIndex && 'offset' in markerOrMarkerIndex){ - idx = this.insertionIndex(markerOrMarkerIndex); - //idx>=0 ONLY if marker has been found - } - if(idx<0 || idx>=this.length){ - this.debug('markermap.remove: index out of bounds or marker not found'); - return -1; - } - var marker = this._super(idx); - this.fire('remove',{ - 'index':idx, - 'marker':marker - }); - return idx; - }, - - //overridden method. Contrarily to super method, - //where the first argument is the 'from' index, here the - //the first argument can also be a marker - move: function(markerOrMarkerIndex, newOffset){ - var oldIndex = -1; - if(typeof markerOrMarkerIndex == 'number'){ - oldIndex = markerOrMarkerIndex; - }else if('id' in markerOrMarkerIndex && 'offset' in markerOrMarkerIndex){ - oldIndex = this.insertionIndex(markerOrMarkerIndex); - //oldIndex>=0 ONLY if marker has been found - } - if(oldIndex<0 || oldIndex>=this.length){ - this.debug('markermap.move: index out of bounds or marker not found'); - return -1; - } - - var newIndex = this.insertionIndex(newOffset); - //select the case: - if(newIndex<0){ //newindex should ALWAYS be lower than zero, as insertionIndex(number) should not match any marker - //we didn't move the marker on another marker (newOffset does not correspond to any marker) - //just return the real insertionIndex - newIndex = -newIndex-1; - } - - //now: if the isnertionIndex is greater than the marker index (oldIndex), - //we decrement newIndex cause super.move will first REMOVE the marker and then set it at newIndex - if(newIndex > oldIndex){ - newIndex--; - } - newIndex = this._super(oldIndex,newIndex); - - if(newIndex <0){ - this.debug('markermap.move: new index out of bounds'); - return -1; - } - - var markers = this.toArray(); - var marker = markers[newIndex]; - var oldOffset = marker.offset; - marker.offset = newOffset; - this.fire('move', { - marker: marker, - fromIndex: oldIndex, - toIndex: newIndex, - oldOffset: oldOffset - }); - return newIndex; - }, - - - //returns the insertion index of object in this sorted array by means of a binary search algorithm. - // A) If object is a marker and: - // a1) Is found (ie, there is a marker in this map - // with same offset and same id), returns the index of the marker found, in the range [0, this.length-1]. Otherwise, if - // a2) Is not found, then returns -(insertionIndex-1), where insertionIndex is the - // index at which object would be inserted preserving the array order. Note that this assures that a - // number lower than zero means that object is not present in the array, and viceversa - // B) If object is a number or a string number (eg, "12.567"), then a marker with offset = object is built and compared - // against the markers in the map. Note however that in this case that equality between marker's offset is sufficient, - // as object is not provided with an id. THEREFORE, IF THE MAP CONTAINS SEVERAL MARKERS AT INDICES i, i+1, ... i+n - // WITH SAME OFFSET == object, THERE IS NO WAY TO DETERMINE WHICH INDEX IN [i, i+1, ... i+n] WILL BE RETURNED. - // See player.forward and player.rewind for an example of the B) case. - //LAST NOTE: BE SURE object is either a number (float) or object.offset is a number (float). - //In case it is not known, If it is a string number such as - //"4.562" the comparison falis (eg, "2.567" > "10.544") but obviously, no error is thrown in javascript - // - insertionIndex: function(object){ - //default comparator function: - //returns 1 as the first argument is greater than the second - //returns -1 as the first argument is lower than the second - //returns 0 if the arguments are equal - var comparatorFunction = function(markerInMap,newMarker){ - var a = markerInMap.offset; - var b = newMarker.offset; - if(ab){ - return 1; - }else{ - var a1 = markerInMap.id; - var b1 = newMarker.id; - if(a1b1){ - return 1; - } - } - return 0; - }; - if(!(typeof object == 'object')){ - var offset; - if(typeof object == 'number'){ - offset = object; - }else{ //to be sure... - offset = parseFloat(object); - } - object = { - 'offset':offset - }; - //key will never be found, so return either 1 or -1: - comparatorFunction = function(markerInMap,newMarker){ - var a = markerInMap.offset; - var b = newMarker.offset; - return a < b ? -1 : (a>b ? 1 : 0); - }; - } - - var data = this.toArray(); - var low = 0; - var high = data.length-1; - - while (low <= high) { - var mid = (low + high) >>> 1; - //biwise operation is not as fast as in compiled languages such as C and java (see Jslint web page) - //However (tested on a PC in Chrome, IE and FF), it is faster than the equivalent: - //var mid = parseInt((low + high)/2); - //even if we reference parseInt before this loop and we call the variable assigned to it - var midVal = data[mid]; - var cmp = comparatorFunction(midVal,object); - if (cmp < 0){ - //the midvalue is lower than the searched index element - low = mid + 1; - }else if (cmp > 0){ - //the midvalue is greater than the searched index element - high = mid - 1; - }else{ - return mid; // key found - } - } - return -(low + 1); // key not found - }, - - //sets isEditable to value - setEditable: function(markerOrMarkerIndex, value) { - var idx = -1; - if(typeof markerOrMarkerIndex == 'number'){ - idx = markerOrMarkerIndex; - }else if('id' in markerOrMarkerIndex && 'offset' in markerOrMarkerIndex){ - idx = this.insertionIndex(markerOrMarkerIndex); - //idx>=0 ONLY if marker has been found - } - if(idx<0 || idx>=this.length){ - this.debug('markermap.setEditable: index out of bounds or marker not found'); - return -1; - } - var marker = this.toArray()[idx]; - var oldVal = marker.isEditable ? true : false; - marker.isEditable = value; - this.fire('markerEditStateChanged',{ - 'index':idx, - 'marker':marker, - 'oldValue':oldVal, - 'value':value - }); - return idx; - } - -} -); \ No newline at end of file diff --git a/timeside/static/timeside/js/player.js b/timeside/static/timeside/js/player.js deleted file mode 100644 index d43e53c..0000000 --- a/timeside/static/timeside/js/player.js +++ /dev/null @@ -1,1067 +0,0 @@ -/* - * Copyright (C) 2007-2011 Parisson - * Copyright (c) 2011 Riccardo Zaccarelli - * Copyright (c) 2010 Olivier Guilyardi - * - * This file is part of TimeSide. - * - * TimeSide is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * TimeSide is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with TimeSide. If not, see . - * - * Authors: Riccardo Zaccarelli - * Olivier Guilyardi - */ - -/** - * The player class to instantiate a new player. Requires all necessary js (timeside, ruler, markermap etcetera...) and - * jQuery - */ - -//playerDiv, sound, durationInMsec, visualizers, markerMap); -Timeside.classes.Player = Timeside.classes.TimesideClass.extend({ - - //sound duration is in milliseconds because the soundmanager has that unit, - //player (according to timeside syntax) has durations in seconds - // newMarkerCallback must be either a string or a function, the necessary checks is done in Timeside.load - // (which calls this method) - //if markersArray is not an array, it defaults to [] - init: function(configObject) { - this._super(); - var $J = this.$J; - var me=this; - - var msgs = configObject.messages; - if(msgs){ - for(var k in msgs){ - if(msgs.hasOwnProperty(k)){ - var ms = msgs[k]; - if(typeof ms === 'string'){ - this.msgs[k] = ms; - } - } - } - } - - var onError = configObject.onError; - if(typeof onError !== 'function'){ - onError = function(msg){}; - } - - var onReady = configObject.onReady; - if(typeof onReady !== 'function'){ - onReady = function(player){}; - } - - var onReadyWithImage = configObject.onReadyWithImage; - - if(typeof onReadyWithImage === 'function'){ - var onReadyWithImageNamespace = 'imgRefreshed.temp_'+new Date().getTime(); //get an unique namespace - this.bind(onReadyWithImageNamespace,function(data){ - onReadyWithImage(me); - me.unbind(onReadyWithImageNamespace); - }); - } - - var container = configObject.container; - container = container instanceof $J ? container : $J(container); - container = container.length ? container.eq(0) : undefined; - if (!container || !container.length){ - onError('container not defined or invalid'); - return; - } - - var sMan = soundManager; - var sound = configObject.sound; - var createSound = false; - if(this.$TU.flashFailed){ - this.soundErrorMsg = 'soundManager error. If your browser does not support HTML5, Flash player (version '+sMan.flashVersion+'+) must be installed.\nIf flash is installed, try to:\n - Reload the page\n - Empty the cache (see browser preferences/options/tools) and reload the page\n - Restart the browser'; - }else{ - if(typeof sound !== 'string' && typeof sound !== 'object'){ - this.soundErrorMsg ='bad sound parameter: specify a a valid soundManager sound-object, an object with at least two properties, url and id, or URL as string'; - }else if(typeof sound === 'string'){ - createSound = true; - var soundURL = sound; - sound = { - id: 'ts-sound', - autoLoad: false, - url: soundURL, - multiShot: false - }; - //do a raw check to see if it is a soundmanager object - }else if(!sound.hasWonProperty('sID') || !sound.hasWonProperty('_iO') || !sound.hasWonProperty('url')){ - if(!sound.hasWonProperty('url') || !sound.hasWonProperty('id')){ //it is not a soundManager object, has at least an url??? - this.soundErrorMsg = 'bad sound parameter: object requires properties url and id at minimum'; - }else{ - createSound = true; - } - } - if(createSound){ - var soundOptions = sound; - if(sMan.canPlayURL(soundOptions.url)){ //this actually checks only if the url is well formed, not if the file is there - //check if we specified a valid sound duration, otherwise the sound must be loaded - - sound = sMan.createSound(soundOptions); - }else{ - this.soundErrorMsg = 'bad sound parameter (soundManager.canPlayURL returned false)'; - } - } - } - if(this.soundErrorMsg){ - this.getSound = function(){ - return undefined; - }; - }else{ - // sound.play = function(){ - // alert(this.readyState); - // }; - this.getSound = function(){ - return sound; - }; - } - var soundDurationInMsec = configObject.soundDuration; - if(typeof soundDurationInMsec !== 'number' || soundDurationInMsec<=0){ - onError('invalid soundDurationInMsec: NaN or not positive'); - return; - } - - - var soundImgFcn = configObject.soundImage; - - if(!(typeof soundImgFcn === 'string' || typeof soundImgFcn === 'function')){ - onError('invalid sound soundImgFcn. Provide a callback(width,height) or a string denoting a valid URL'); - return; - }else{ - if(typeof soundImgFcn === 'string'){ - var url = soundImgFcn; - this.imageCallback = new function(w,h){ - return url; - }; - }else{ //surely a function - this.imageCallback = soundImgFcn; - } - } - - var soundImgSize = configObject.imageSize; - var markersArray = configObject.markersArray; - var newMarker = configObject.newMarker; - - - - this.playState = 0; //0: not playing, 1: loading, 2:buffering, 3 playing (sound heard) - //container is the div #player - - this.getContainer = function(){ - return container; - }; - - - - var sd = this.toSec(soundDurationInMsec); - this.getSoundDuration = function(){ - return sd; - }; - - this.soundPosition = sound.position ? this.toSec(sound.position) : 0; - - - - // - - //initializing markermap and markerui - var map = new Timeside.classes.MarkerMap(); - this.getMarkerMap = function(){ - return map; - }; - - var canAddMarkers = false; - if(newMarker === true || (typeof newMarker === 'function')){ - canAddMarkers = true; - if(typeof newMarker === 'function'){ - this.newMarker = newMarker; - } - } - - //build the innerHTML as array, then join it. This is usually faster than string concatenation in some browsers. - //Note that the player image (see below) is not created now, however, if it was, it should be given a src - //as NOT specifying any src for image tags can be harmful, - //see http://www.nczonline.net/blog/2009/11/30/empty-image-src-can-destroy-your-site/ and - //http://geekswithblogs.net/bcaraway/archive/2007/08/24/114945.aspx for details - var html = [ - "
", - "
", - "
", - "
", - //lazily created: "", //not providing a src attribute is harmful. Dummy src attribute - "
", - "
", - "
", - "", - "", - "", - "", - "", - "", - "
", - "", - "", - "", - "
", - "
", - "
"]; - - container.html(html.join('')); - - var control = container.find('.ts-control'); - - //bind events to buttons: - var rewind = control.find('.ts-rewind'); - rewind.attr('href', '#').click(function(e){ - me.rewind.apply(me); - return false; - }); - - var forward = control.find('.ts-forward'); - forward.attr('href', '#').click(function(e){ - me.forward.apply(me); - return false; - }); - - var pause = control.find('.ts-pause'); - pause.attr('href', '#').bind('click', function(){ - me.pause.apply(me); - return false; - }); - - var play = control.find('.ts-play'); - play.attr('href', '#').bind('click', function(){ - me.play.apply(me); - return false; - }); - - var setMarkerButton = control.find('.ts-set-marker'); - - if(canAddMarkers){ - setMarkerButton.show().attr('href','#').unbind('click').bind('click', function(){ - me.addMarker(me.soundPosition); - return false; - }); - }else{ - setMarkerButton.hide().unbind('click'); - } - - - //volume: - var volumeSpeaker = control.find('.ts-volume-speaker'); - var volumeBarContainer = control.find('.ts-volume-bar-container'); - var volumeBar = volumeBarContainer.find('.ts-volume-bar'); - - var getVol = function(x){ - var vol = 100*x/volumeBarContainer.width(); - //allow click to easily set to zero or 100, ie set a margin to 5%: - var margin = 5; - if (vol < margin){ - vol=0; - }else if(vol >100-margin){ - vol = 100; - } - return vol; - }; - function setVolume(event,volumeElement){ - var x = event.pageX - volumeElement.offset().left; //using absolute coordinates allows us to - //avoid using layerX (not supported in all browsers) and clientX (which needs the window scrollLeft variable) - me.setSoundVolume(getVol(x)); - return false; - } - volumeBarContainer.attr('href', '#').click(function(event){ - return setVolume(event,volumeBar); - }); - volumeSpeaker.attr('href', '#').click(function(){ - me.setSoundVolume(me.getSoundVolume()>0 ? 0 : getVol(volumeBar.outerWidth())); - return false; - }); - this.setSoundVolume(this.getSoundVolume()); - - control.find('a').attr('href', '#') ; - - //SET NECESSARY CSS (THIS WILL OVERRIDE CSS SET IN STYLESHEETS): - //var viewer = container.find('.ts-viewer'); - var wave = container.find('.ts-wave'); - var ruler_ = container.find('.ts-ruler'); - wave.add(control).add(ruler_).css({ - 'position':'relative', - 'overflow':'hidden' - }); - //assigning display and title to all anchors - var subcontrolsToBeSetVisible = control.find('*'); - if(!canAddMarkers){ - subcontrolsToBeSetVisible = subcontrolsToBeSetVisible.filter(':not(a.ts-set-marker)'); - } - subcontrolsToBeSetVisible.css({ - 'display':'inline-block', - 'overflow':'hidden' - }); - - var waitImg = control.find('.ts-wait'); - waitImg.html('wait').css({ - 'position':'absolute' - }); - - var div = control.find('.ts-volume-wrapper-div'); - div.css({ - 'position':'absolute', - 'left':(volumeSpeaker.position().left+volumeSpeaker.outerWidth(true))+'px', - 'top':0, - 'width':'auto', - 'height':'100%' - }); - //END NECESSARY CSS - - //creating the ruler - var waveImage = container.find('.ts-image-canvas'); - var ruler = new Timeside.classes.Ruler(ruler_, waveImage, this.getSoundDuration()); - //var ruler = new Timeside.classes.Ruler(viewer, this.getSoundDuration()); - this.getRuler = function(){ - return ruler; - }; - //bind mouse events: - ruler.bind('rulermarkermouseevent', function(data){ - var idx = data.index; - data.marker = idx > -1 ? me.getMarker(idx) : undefined; - me.fire('markerMouseEvent',data); - }); - - //setting image size (if provided) and resize player. Note that _setImageSize (with underscore) is intended to be - //a private method (faster). setImageSize (without underscore) is the public method to use outside of player object - if(soundImgSize){ - this._setImageSize(soundImgSize.width,soundImgSize.height,container, wave,true); //calls this.resize which calls ruler.resize - }else{ - this._setImageSize('','',container, wave,true); //calls this.resize which calls ruler.resize - } - - //binds click for the pointer: - var v = wave; //.add(ruler); - v.unbind('click').click(function(evt){ - var w = v.width(); - var x = evt.pageX - v.offset().left; //using absolute coordinates allows us to - //avoid checking whether or not we are clicking on a vertical marker line, on a subdiv etcetera - var sd = me.getSoundDuration(); - me.setSoundPosition(sd*x/w); - }); - - - - //finally, load markers and bind events for markers (see method below): - //NOTE: loadMarkers ASYNCHRONOUSLY CALLS THE SERVER, SO METHODS WRITTEN AFTER IT MIGHT BE EXECUTED BEFORE - //loadMarkers has finished its job - //this.loadMarkers(callback); - if(!(markersArray) || !(markersArray.length)){ - markersArray = []; - } - this.loadMarkers(markersArray); - - - //IE7 BUG: the divs wave and control do not shift downwards after canvas is drawn and covers part of the rulrer. - //Weird enough (with IE it isn't actually), we have just to set the property we already set in the css: - //ie, top: auto. This is however useful even if somebody specified a top property on the divs - ruler_.add(wave).add(control).css('top','auto'); - onReady(this); - }, - - - - //functions for converting seconds (player unit) to milliseconds (sound manager unit) and viceversa: - toSec: function(milliseconds){ - return milliseconds/1000; - }, - toMsec : function(seconds){ //this function has less performances than toSec, as it calls Math.round - return Math.round(1000*seconds); //however, it is assumed that it is NOT called in loops - }, - isPlaying : function(){ - var sound = this.getSound(); - if(!sound){ - return false; - } - return this.playState; - /*Numeric value indicating the current playing state of the sound. - * 0 = stopped/uninitialised - * 1 = playing or buffering sound (play has been called, waiting for data etc.) - *Note that a 1 may not always guarantee that sound is being heard, given buffering and autoPlay status.*/ - //return sound && sound.playState==1; - }, - setSoundPosition: function(newPositionInSeconds){ - //if the player is playing and NOT yet fully loaded, simply calling: - //this.getSound().setPosition(this.toMsec(newPositionInSeconds)); - //resets the position to zero. So we use this workaround: - // this.getSound().stop(); //calling this.pause() hides the waiting bar, which is not the case here - // this.soundPosition = newPositionInSeconds; - // this.play(); - //however, that causes fast pointer move effect is undesiderable - //So: - var wasPlaying = this.isPlaying(); - if(wasPlaying){ - this.getSound().stop(); //dont call this.pause cause it hides the waitbar, if visible and resets the playState - } - //update pointer position. If this call is due to a pointer move (mouse release), - //ruler.isPointerMovingFromMouse=true and the following code has no effect (the pointer is already at the good position) - var ruler = this.getRuler(); - if(ruler){ - ruler.movePointer(newPositionInSeconds); - } - //set sound position: - var oldSoundPosition = this.soundPosition; - this.soundPosition = newPositionInSeconds; - - //resume playing if it was playing: - if(wasPlaying){ - var player = this; - - //delay a little bit the play resume, this might avoid fast pointer repositioning - //(it should not be the case, but it happens. why??) - setTimeout(function(){ - player.play.apply(player); - },100); - } - this.fire('soundPositionSet',{ - player:this, - oldSoundPosition:oldSoundPosition - }); - - }, - showSoundErroMessage: function(){ - alert(this.soundErrorMsg); - }, - //given a marker at index I, specifies that a marker corss event is fired whenever the sound position (pointer) - //is in the interval ]markerCrossedOffsetMargin-I,I+markerCrossedOffsetMargin[ - //the value is in seconds - //markerCrossedOffsetMargin : 0.5, - play : function(){ - - if(this.soundErrorMsg){ - alert(this.soundErrorMsg); - return false; - } - - var player = this; - var sound = player.getSound(); - - if(!player || !sound){ //just check. The cases here (especially, sound = undefined, should be - //together with this.soundErrorMsg != "", so we should have catch the case above - return false; - } - - - var fireOnMarkerPosition = function(seconds){}; //does nothing by default - var map = player.getMarkerMap(); - var markerCrossListeners = player.listenersMap['markerCrossed']; - //optimizing: if no listeners associated to markerCrossListeners, avoid creating a function - if(map && map.length && markerCrossListeners){ - var idx = 0; - if(player.soundPosition>0){ - idx = map.insertionIndex(player.soundPosition); - if(idx<0){ - idx=-idx-1; - } - } - var len = map.length; - if(idx>-1 && idx < len){ - var markers = map.toArray(); - var marker = markers[idx]; - var margin = 0.5; //1 second (0.5*2) of margin (before+after) - var offs = marker.offset; - var intervalUpperBound = offs+margin; - var intervalLowerBound = offs-margin; - var data = { //if you change data, change it also below - index:idx, - marker:marker, - currentSoundPosition: player.soundPosition, - nextMarkerTimeInterval: undefined - }; - fireOnMarkerPosition = function(seconds){ - if(marker){ - if(seconds>intervalLowerBound && seconds < intervalUpperBound){ - idx++; - marker = idx < len ? markers[idx] : undefined; - offs = marker ? marker.offset : undefined; - data.currentSoundPosition = seconds; - data.nextMarkerTimeInterval = marker ? [offs-margin, offs+margin] : undefined; - player.fire('markerCrossed',data); - - if(idx= this.getSoundDuration()){ - playOptions.onfinish(); - }else{ - sound.setVolume(sound.volume); //workaround. Just to be sure. Sometimes it fails when we re-play - sound.play(playOptions); - // soundManager.play(sound.sId,{ - // onload: function(success){ - // alert(success); - // } - // }); - } - - return false; - }, - - msgs : { - loading : 'loading', - buffering: 'buffering', - imgRefreshing : 'refreshing img' - }, - pause: function(){ - var sound = this.getSound(); - //we don't check if it's playing, as the stop must really stop anyway - //if(sound && this.isPlaying()){ - if(sound){ - var v = this.isPlaying(); - sound.stop(); - var data = { - player:this, - oldPlayState:this.playState, - endOfPlayback:false - }; - this.playState = 0; - this.fire('playStateChanged',data); - this.setWait(this.isImgRefreshing ? this.msgs.imgRefreshing : ''); - } - return false; - }, - - getWaitElement: function(){ - return this.getContainer().find('.ts-control').find('.ts-wait'); - }, - - setWait: function(msg){ - var wait = undefined; - - wait = this.getWaitElement(); - if(!wait || msg === undefined){ - return; - } - if(wait.html()!=msg){ - wait.html(msg); - } - - var visible = wait.css('display') != 'none'; - - if(msg && !visible){ - wait.show(); - this.fire('waitShown'); - }else if(!msg && visible){ - wait.hide(); - this.fire('waitHidden'); - } - }, - - /** - * sets whether or not window resize resizes also this player. When true, a variable _dynamicResize =setInterval(...) is attached to - * this class. When false, if _dynamicResize is in this class, clearInterval(_dynamicResize) is called and then the key is deleted - */ - setDynamicResize: function(value){ - var key = '_dynamicResize'; - if(!value && key in this){ - clearInterval(this[key]); - delete this[key]; - return; - } - var wdw = this.$J(window); - var w = wdw.width(); - //var h = wdw.height(); - var me = this; - this.dynamicResize = setInterval(function(){ - var newW = wdw.width(); - if(w!=newW){ - w = newW; - //still wait a second: are we still adjusting the window? (call resize just once): - setTimeout(function(){ - if(wdw.width()==newW){ - me.resize.apply(me); - } - },200); - } - },100); - }, - - resize: function() { - var height; - var container = this.getContainer(); - - var wave = container.find('.ts-wave'); - - height = wave.height(); - // if(!height){ - // height = this.minWaveHeight; - // wave.css('height',height+'px'); - // } - //if (height) { - //set image, imagecontainer and canvas (container on imagecontainer for lines and pointer triangles) css - var elements = wave.find('.ts-image-container').css('zIndex','0') - .add(wave.find('.ts-image-canvas').css('zIndex','1')); //the two children of ts-wave. Set also the zIndex - //in order to visualize the canvas OVER the wav image - var style = { - width: wave.width(), - height: height, - border: 0, - padding:0, - margin:0, - top:0, - left:0 - }; - elements.css(style); - elements.css('position','absolute'); - //} - - //refreshing images: - this.refreshImage(); - this.getRuler().resize(); - }, - getImageUrl : function(){ - var image = this.getContainer().find('.ts-image'); - if(image && image.length){ - return image.attr('src'); - } - return ''; - }, - refreshImage: function(){ - var container = this.getContainer(); - var imageC = container.find('.ts-image-container'); - var image = imageC.find('.ts-image'); - - - var size = this.getImageSize(); - - if(!size.width || !size.height){ - return; - } - var imgSrc = this.imageCallback(size.width,size.height); - var imageNotYetCreated = image.length == 0; - if(!imageNotYetCreated && image.attr('src')==imgSrc){ - return; - } - - var player= this; - - if(imageNotYetCreated){ - image = this.$J(''); - } - - //image inside ts-image-container: - image.css({ - 'width':'100%', - 'height':'100%' - }); // for IE7. Does not seem to hurt IE8, FF, Chrome - - var updateWait = function(){}; - var ir = player.msgs.imgRefreshing; - var we = player.getWaitElement(); - if(ir && we){ - updateWait = function(){ - if(!player.playState || player.playState==3){ - player.setWait(''); - } - } - } - image.load(function(){ - image.unbind('load'); - if(imageNotYetCreated){ - imageC.append(image.addClass('ts-image')); - } - updateWait(); - player.isImgRefreshing = false; - player.fire('imgRefreshed'); - }); - if(ir && we && (!this.playState || this.playState===3)){ //if loading (1) or buffering (2) do not update wait. - //If not playing (undefined or 0) playing (3) update wait - this.setWait(ir); - } - this.isImgRefreshing = true; - this.fire('imgRefreshing'); - image.attr('src', imgSrc); - - }, - getImageSize: function(){ - var wave = this.getContainer().find('.ts-wave'); - return { - width: wave.width(), - height:wave.height() - } - }, - - setImageSize: function(width,height){ - var container = this.getContainer(); - var wave = container.find('.ts-wave'); - this._setImageSize(width,height,container, wave,true); - }, - //this is intended to be a private method, use setImageSize from outside the player object) - _setImageSize: function(width,height,jQueryContainerElement, jQueryWaveElement, resize){ - if(width || height){ - var re = /(?:px|ex|em|%)$/; - if(width){ - width+=''; - width = re.exec(width) ? width : width+'px'; - jQueryContainerElement.css('width',width); - } - if(height){ - height+=''; - height = re.exec(height) ? height : height+'px'; - jQueryWaveElement.css('height',height); - } - } - if(resize){ - this.resize(); - } - }, - - getSoundVolume :function(){ - var s = this.getSound(); - return s ? s.volume : 0; - }, - //moves the pointer (and sound position) forward till the next marker or the end of sound - forward: function() { - var map = this.getMarkerMap(); - var markers = map.toArray(); - var len = markers.length; - var offset = this.getSoundDuration(); - var position = this.soundPosition; //parseFloat(this.getSoundPosition()); - var idx = map.insertionIndex(position); - if(idx<0){ - idx = -idx-1; //cursor is not on a a marker, get the insertion index - }else{ - //cursor is on a marker. As there might be several markers with the same offset - //(see MarkerMap.insertionIndex), move to the outmost right - while(idx0 && markers[idx-1].offset == position){ - idx--; - } - } - idx--; //move backward (rewind) - if(idx>=0){ - offset = markers[idx].offset; - } - this.setSoundPosition(offset); - return false; - }, - - setSoundVolume: function(volume){ - if(typeof volume != 'number'){ //note: typeof for primitive values, instanceof for the rest - //see topic http://stackoverflow.com/questions/472418/why-is-4-not-an-instance-of-number - volume = 100; - } - if(volume<0){ - volume = 0; - }else if(volume>100){ - volume = 100; - } - volume = Math.round(volume); - var sound = this.getSound(); - if(sound){ - sound.setVolume(volume); - } - var control = this.getContainer().find('.ts-control'); - var volumeSpeaker = control.find('.ts-volume-speaker'); - var volumeBarContainer = control.find('.ts-volume-bar-container'); - var volumeBar = volumeBarContainer.find('.ts-volume-bar'); - if(volume==0){ - volumeSpeaker.removeClass('ts-volume-speaker-on').addClass('ts-volume-speaker-off'); - volumeBar.css('visibility','hidden'); - }else{ - volumeSpeaker.removeClass('ts-volume-speaker-off').addClass('ts-volume-speaker-on'); - volumeBar.css('visibility','visible'); - volumeBar.css({ - 'height':'100%', - 'width':volume+'%' - }); - } - }, - - each: function(){ - var map = this.getMarkerMap(); - if(map){ - map.each.apply(map,arguments); - } - }, - - newMarker: function(offset){ - return { - offset:offset - }; - }, - addMarker: function(offset){ - var map = this.getMarkerMap(); - if(map){ - map.add(this.newMarker(offset)); - } - }, - - removeMarker: function(identifier){ //identifier can be an number (marker index) or a marker (the index will be aearched) - //see marlermap.remove - var map = this.getMarkerMap(); - if(map){ - map.remove(identifier); - } - }, - - moveMarker: function(identifier, newOffset){ //identifier can be an number (marker index) or a marker (the index will be aearched) - var map = this.getMarkerMap(); - if(map){ - map.move(identifier,newOffset); - } - }, - - getMarker: function(index){ - var map = this.getMarkerMap(); - if(map){ - return map.toArray()[index]; - } - return undefined; - }, - - setMarkerEditable: function(identifier, value){ - var map = this.getMarkerMap(); - if(map){ - return map.setEditable(identifier,value); - } - return undefined; - }, - - //markers is an array of objects with at least the field offset:sconds.milliseconds - loadMarkers: function(markers){ - //ruler.bind('markermoved',this.markerMoved,this); - //var $J = this.$J; //reference to jQuery - - var player = this; - //initialize the map. - var map = this.getMarkerMap(); - //var mapUI = this.getMarkersUI(); - var ruler = this.getRuler(); - - //TODO: think about if clearing or not: we assign some bindings in the constructor, too: - // map.clear(); - // ruler.clear(); - - var rulerAdd = ruler.add; - - if(markers){ - //add markers to the map. No listeners associated to it (for the moment) - for(var i =0; i< markers.length; i++){ - map.add.apply(map,[markers[i]]); - } - //add markers to ruler and div - map.each(function(i,marker){ - //isEditable and id are added if not present - rulerAdd.apply(ruler,[marker.offset, i, marker.isEditable]); - }); - } - - //the function above calls map.add: - //add bindings when adding a marker: - map.bind('add',function(data){ - //mapuiAdd.apply(mapUI,[data.marker, data.index,data.isNew]); - rulerAdd.apply(ruler,[data.marker.offset, data.index,data.marker.isEditable]); - player.fire('markerAdded',data); - }); - - //2) MOVE - - //add the binding when we move a marker on the ruler: - ruler.bind('markermoved',function(data){ - var soundPos = data.soundPosition; - var isPointer = data.isPointer; - if(isPointer){ - player.setSoundPosition(soundPos); - }else{ - map.move(data.markerElement.getIndex(), soundPos); - } - }); - - //and now add a binding to the map when we move a marker: - - map.bind('move', function(data){ - var from = data.fromIndex; - var to = data.toIndex; - ruler.move.apply(ruler,[from,to,data.marker.offset]); - player.fire('markerMoved',data); - }); - - //remove - map.bind('remove',function(data){ - ruler.remove.apply(ruler, [data.index]); - player.fire('markerRemoved',data); - }); - - //edit state changed - map.bind('markerEditStateChanged',function(data){ - ruler.setEditable.apply(ruler, [data.index, data.value]); - player.fire('markerEditStateChanged',data); - }); - } -}); diff --git a/timeside/static/timeside/js/ruler.js b/timeside/static/timeside/js/ruler.js deleted file mode 100644 index 259d7f3..0000000 --- a/timeside/static/timeside/js/ruler.js +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Copyright (C) 2007-2011 Parisson - * Copyright (c) 2011 Riccardo Zaccarelli - * Copyright (c) 2010 Olivier Guilyardi - * - * This file is part of TimeSide. - * - * TimeSide is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * TimeSide is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with TimeSide. If not, see . - * - * Authors: Riccardo Zaccarelli - * Olivier Guilyardi - */ - -/** - * Class representing the ruler (upper part) of the player. Requires jQuery - * and Raphael - */ -Timeside.classes.Ruler = Timeside.classes.TimesideArray.extend({ - //init constructor: soundDuration is IN SECONDS!!! (float) - init: function(rulerContainer, waveContainer, soundDuration){ - this._super(); - - this.getSoundDuration= function(){ - return soundDuration; - }; - - this.getWaveContainer =function(){ - return waveContainer; - }; - - this.getContainerWidth =function(){ - return waveContainer.width(); - }; - - this.getRulerContainer = function(){ - return rulerContainer; - } - }, - - resize : function(){ - var duration = this.getSoundDuration(); //in seconds - if (!duration) { - this.debug("ruler.resize: Can't draw ruler with a duration of 0"); - return; - } - - var $J = this.$J; - var rulerContainer = this.getRulerContainer(); - - //remove all elements not pointer or marker - rulerContainer.find(':not(a.ts-pointer,a.ts-marker,a.ts-pointer>*,a.ts-marker>*)').remove(); - - //calculate h with an artifice: create a span (that will be reused later) with the "standard" label - var firstSpan = $J('').css({ - 'display':'block', - 'position':'absolute' - }).html('00000'); //typical timelabel should be '00:00', with '00000' we assure a bit of extra safety space - //note also that display and position must be set as below to calculate the proper outerHeight - rulerContainer.append(firstSpan); //to calculate height, element must be in the document, append it - var verticalMargin = 1; - var h = 2*(verticalMargin+firstSpan.outerHeight()); - //h is the default height of the ruler svg (according to ruler font size) - //to accomodate the necessary space for the labels - //however, if we set a custom height on the ruler, ie h2 is nonzero: - var h2 = rulerContainer.height(); - //then, set the custom height as height for the canvas: - //note that, as markers and pointer have position: absolute, they do not affect div height - if(h2){ - h = h2; - } - var obj = this.calculateRulerElements(rulerContainer.width(),h,firstSpan.outerWidth()); - this.drawRuler(rulerContainer,h,obj.path); - - var labels = obj.labels; - if(labels && labels.length){ - for(var i=0; i ')); - span.html(labels[i][0]).css({ - 'display':'block', - 'position':'absolute', - 'width':'', - 'height':'', - 'right':'', - 'bottom':'', - 'top':'0', - 'left':labels[i][1]+'px' - }); - rulerContainer.append(span); - } - }else{ - firstSpan.html(this.makeTimeLabel(0)); - } - - var pointer = undefined; - if('getPointer' in this){ - pointer = this.getPointer(); - } - if(!pointer){ - pointer = this.add(0,-1); - this.getPointer = function(){ - return pointer; - }; - }else{ - pointer.refreshPosition(); - - } - this.each(function(i,rulermarker){ - rulermarker.refreshPosition(); - }); - - - }, - - drawRuler: function(rulerContainer,h,rulerLinesPath){ - var cssPref = this.cssPrefix; - var upperRectClass = cssPref + 'svg-' + 'ruler-upper-rect'; - var rulerLinesClass = cssPref + 'svg-' + 'ruler-lines'; - - var vml = this.$TU.vml; - if(vml){ - //we create each time a new Raphael object. This is not a big performance issue - var paper = Raphael(rulerContainer[0], rulerContainer.width(), h); - var rect = paper.rect(0,0, rulerContainer.width(), h/2); - var path = paper.path(rulerLinesPath); - var attr = vml.getVmlAttr; - rect.attr(attr(upperRectClass)); - path.attr(attr(rulerLinesClass)); - return; - } - //create svg. Note that elements must be created within a namespace (createElementNS) - //and attributes must be set via .setAttributeNS(null,name,value) - //in other words, jQuery does not work (maybe in future releases) - var $J = this.$J; - var svgNS = "http://www.w3.org/2000/svg"; - var d = document; - var svg = d.createElementNS(svgNS, "svg:svg"); - svg.setAttributeNS( null, "width", rulerContainer.width()); //TODO: optimize width is called also below - svg.setAttributeNS( null, "height", h); - rulerContainer.append($J(svg)); - - var rect = d.createElementNS(svgNS, "svg:rect"); - rect.setAttributeNS( null, "x", 0); - rect.setAttributeNS( null, "y", 0); - rect.setAttributeNS( null, "width", rulerContainer.width()); - rect.setAttributeNS( null, "height", (h/2)); - rect.setAttributeNS( null, "class", upperRectClass); - svg.appendChild(rect); - var lines = d.createElementNS(svgNS, "svg:path"); - lines.setAttributeNS( null, "d", rulerLinesPath); - lines.setAttributeNS( null, "class", rulerLinesClass); - svg.appendChild(lines); - }, - /** - * returns an object with the following properties: - * path: (string) the path of the ruler to be drawn - * labels (array) an array of arrays ['text',x,y] - */ - calculateRulerElements: function(w,h,timeLabelWidth){ - - var duration = this.getSoundDuration(); - - var fontLeftMargin = 2; //should be eual or greater to the ruler stroke width, so that - //the labels are not overlapping the vertical ruler lines - timeLabelWidth+=fontLeftMargin; - - var timeLabelDuration = timeLabelWidth*duration/w; - - //determine the ticks: - var sectionDurations = [1,2,5,10,30,60,120,300,1800,3600,7200,18000,36000]; - //sectionDurations in seconds. Note that 60=1 minute, 3600=1 hour (so the maximum sectionDuration is 36000=10hours) - var i=0; - var len = sectionDurations.length; - while(isectionDurations[i]){ - i++; - } - var sectionDuration = sectionDurations[i]; - var sectionNums = parseInt(0.5+(duration/sectionDurations[i])); //ceil - var sectionWidth = w*sectionDuration/duration; - - - var tickCounts = [10,5,2,1]; - i=0; - var tickCount = tickCounts[0]; - while(isectionWidth){ - i++; - } - var tickAtHalfSectionWidthHigher = i==0 || i==2; //draw tick at half section higher if ticks are even - tickCount = tickCounts[i]; - var tickWidth = sectionWidth/tickCount; - var makeTimeLabel = this.makeTimeLabel; - var h_1 = h-1; //TODO: use line tickness instead of 1 - var path = new Array(parseInt(0.5+(w/tickWidth))); - path[0] = ['M 0 '+h_1]; - len = path.length; - for(i=0; i < len; i+=tickCount){ - for(var j=1; j=0 && index < a.length){ - this._setEditable(a[index],value,false); - } - }, - //do not call, use setEditable(index,value) instead - _setEditable: function(pointerOrMarker, value, isPointer){ - var eventNamespace = this.eventNamespace; - var doc = this.$J(document); - var lbl = pointerOrMarker.getLabel(); - var me = this; - var mme = this.mouseEventType; - - - lbl.unbind('.'+eventNamespace); //this should delete all previous events - - lbl.bind('mouseenter.'+eventNamespace,function(evt){ - me.fire(mme,{ - eventName: 'mouseenter', - eventObj: evt, - index: isPointer ? -1 : pointerOrMarker.getIndex() - }); - return false; - }); - lbl.bind('mouseleave.'+eventNamespace,function(evt){ - me.fire(mme,{ - eventName: 'mouseleave', - eventObj: evt, - index: isPointer ? -1 : pointerOrMarker.getIndex() - }); - return false; - }); - - //to prevent page scrolling after mouseup, as click is also fired - lbl.bind('click.'+this.eventNamespace, function(evt){ - return false; - }); - - - lbl.bind('mousedown.'+eventNamespace,function(evt) { - if(evt.which===1){ - if(value){ - pointerOrMarker.isMovedByMouse = true; - } - - var launchDragStart = true; - - var startX = evt.pageX; - var startPos = lbl.position().left+lbl.width()/2; - - evt.stopPropagation(); //dont notify the ruler or other elements; - var newPos = startPos; - doc.bind('mousemove.'+eventNamespace, function(evt_){ - //preventClickFire=true; - if(value){ - var x = evt_.pageX; - newPos = startPos+(x-startX); - pointerOrMarker.move(newPos); - //update the text if pointer - if(isPointer){ - pointerOrMarker.setText(me.makeTimeLabel(me.toSoundPosition(newPos))); - } - } - if(launchDragStart){ - launchDragStart = false; - me.fire(mme,{ - eventName: 'dragstart', - eventObj: evt_, - index: isPointer ? -1 : pointerOrMarker.getIndex() - }); - } - return false; - - }); - //to avoid scrolling - ////TODO: check IE bug on mouseup on the ruler (pointer is moving too) - //TODO: what happens if the user releases the mouse OUTSIDE the browser???? check bug in IE (mouse release) - var mouseup = function(evt_){ - - doc.unbind('mousemove.'+eventNamespace); - doc.unbind('mouseup.'+eventNamespace); - evt_.stopPropagation(); - if(value){ - if(newPos !== startPos){ - - var data = { - 'markerElement':pointerOrMarker, - 'soundPosition': me.toSoundPosition.apply(me,[newPos]), - 'isPointer':isPointer - }; - me.fire('markermoved',data); - } - pointerOrMarker.isMovedByMouse = false; - } - if(evt_.pageX !== startX){ - me.fire(mme,{ - eventName: 'dragend', - eventObj: evt_, - index: isPointer ? -1 : pointerOrMarker.getIndex() - }); - }else{ - me.fire(mme,{ - eventName: 'click', - eventObj: evt_, - index: isPointer ? -1 : pointerOrMarker.getIndex() - }); - } - return false; - }; - doc.bind('mouseup.'+eventNamespace, mouseup); - } - - me.fire(mme,{ - eventName: 'mousedown', - eventObj: evt, - index: isPointer ? -1 : pointerOrMarker.getIndex() - }); - - - return false; - }); - }, - - //moves the pointer, does not notify any listener. - //soundPosition is in seconds (float) - movePointer : function(soundPosition) { - var pointer = this.getPointer(); - if (pointer && !pointer.isMovedByMouse) { - var pixelOffset = this.toPixelOffset(soundPosition); - //first set text, so the label width is set, then call move: - pointer.setText(this.makeTimeLabel(soundPosition)); - pointer.move(pixelOffset); //does NOT fire any move method - } - return soundPosition; - }, - - //soundPosition is in seconds (float) - toPixelOffset: function(soundPosition) { - var duration = this.getSoundDuration(); - if (soundPosition < 0){ - soundPosition = 0; - }else if (soundPosition > duration){ - soundPosition = duration; - } - var width = this.getContainerWidth(); - var pixelOffset = (soundPosition / duration) * width; - return pixelOffset; - }, - - //returns the soundPosition is in seconds (float) - toSoundPosition: function(pixelOffset) { - var width = this.getContainerWidth(); - - if (pixelOffset < 0){ - pixelOffset = 0; - }else if (pixelOffset > width){ - pixelOffset = width; - } - var duration = this.getSoundDuration(); - var soundPosition = (pixelOffset / width) *duration; - return soundPosition; - } -}); diff --git a/timeside/static/timeside/js/rulermarker.js b/timeside/static/timeside/js/rulermarker.js deleted file mode 100644 index e98730c..0000000 --- a/timeside/static/timeside/js/rulermarker.js +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (C) 2007-2011 Parisson - * Copyright (c) 2011 Riccardo Zaccarelli - * Copyright (c) 2010 Olivier Guilyardi - * - * This file is part of TimeSide. - * - * TimeSide is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * TimeSide is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with TimeSide. If not, see . - * - * Authors: Riccardo Zaccarelli - * Olivier Guilyardi - */ - -/** - * Class representing a RulerMarker in TimesideUI - * Requires jQuery Raphael and all associated player classes. rulerDiv position MUST be relative - * (if this class is called from within player, it is) - */ - -Timeside.classes.RulerMarker = Timeside.classes.TimesideClass.extend({ - - - init: function(ruler, waveImgDiv, className) { - this._super(); - var rulerDiv = ruler.getRulerContainer(); - var $J = this.$J; - - var tooltip = ''; - - var cssPref = this.cssPrefix; - - var label = $J('') - .addClass(cssPref + className) - .css({ - display: 'block', - textAlign: 'center', - position: 'absolute', - zIndex: 1000 - }).append($J('')).attr('href', '#'); - - if (tooltip){ - label.attr('title', tooltip); - } - rulerDiv.append(label); - - //rulerDiv MUST HAVE POSITON relative or absolute (it is relative, see player.resize) - if(className != "pointer"){ - label.css('bottom','0'); - }else{ - label.css('top','0'); - } - - //set the index, - var index = -1; - this.setIndex = function(idx, optionalUpdateLabelWidth){ - index = idx; - this.setText(idx+1, optionalUpdateLabelWidth ? true : false); - }; - this.getIndex = function(){ - return index; - }; - - //end======================================================= - //creating public methods: - this.getLabel = function(){ - return label; - }; - - - this.getRulerWidth = function(){ - return rulerDiv.width(); - }; - this.getWaveHeight = function(){ - return waveImgDiv.height(); - }; - - this.positionInPixels = 0; - this.positionAsViewerRatio = 0; - - var arrowBaselineWidth = 9; - - var canvas = undefined; - var canvasClass = cssPref + 'svg-'+className+'-line'; - var vml = this.$TU.vml; //if vml, this class is populated with methods and NOT undefined - var round = Math.round; - if(!vml){ - canvas = this.createCanvasSvg(waveImgDiv, arrowBaselineWidth); - var path = canvas.childNodes[0]; //note that $J(canvas).find('path') does not work in FF at least 3.5 - path.setAttributeNS(null,'class',canvasClass); - this.moveCanvas = function(pixelOffset){ - pixelOffset = round(pixelOffset); - canvas.setAttributeNS( null, "transform", "translate("+pixelOffset+",0)"); - }; - this.jQueryCanvas = $J(canvas); - }else{ - canvas = this.createCanvasVml(waveImgDiv, arrowBaselineWidth); - this.jQueryCanvas = $J(canvas.node); - var attributes = vml.getVmlAttr(canvasClass); - canvas.attr(attributes); //Raphael method - this.moveCanvas = function(pixelOffset){ - pixelOffset = round(pixelOffset); - //for some reason, coordinates inside the VML object are stored by raphael with a zoom of 10: - this.jQueryCanvas.css('left',(10*pixelOffset)+'px'); - }; - //apparently, when resizing the markers loose their attributes. Therefore: - var r = this.refreshPosition; //reference to current refreshPosition - this.refreshPosition = function(){ - r.apply(this); - canvas.attr(attributes); - } - } - }, - - //sets the text of the marker, if the text changes the marker width and optionalUpdateLabelPosition=true, - //re-arranges the marker position to be center-aligned with its vertical line (the one lying on the wav image) - setText: function(text, optionalUpdateLabelPosition) { - var label = this.getLabel(); - if (label) { - var oldWidth = label.width(); - label.find('span').html(text); - var labelWidth = label.width(); - if(oldWidth != labelWidth && optionalUpdateLabelPosition){ - this.refreshLabelPosition(); - } - } - return this; - }, - - //these methods are executed only if marker is movable (see Ruler.js) - move : function(pixelOffset) { - var width = this.getRulerWidth(); - if (this.positionInPixels != pixelOffset) { - if (pixelOffset < 0) { - pixelOffset = 0; - } else if (pixelOffset >= width) { - pixelOffset = width - 1; - } - //defined in the init method (it depends on wehter the current browser supports SVG or not) - this.moveCanvas(pixelOffset); - - this.positionInPixels = pixelOffset; - this.refreshLabelPosition(width); - //store relative position (see refreshPosition below) - this.positionAsViewerRatio = pixelOffset == width-1 ? 1 : pixelOffset/width; - } - return this; - }, - - refreshLabelPosition : function(optionalContainerWidth){ - if(!(optionalContainerWidth)){ - optionalContainerWidth = this.getRulerWidth(); - } - var label = this.getLabel(); - var width = optionalContainerWidth; - var pixelOffset = this.positionInPixels; - var labelWidth = label.outerWidth(); //consider margins and padding - var labelPixelOffset = pixelOffset - labelWidth / 2; - if (labelPixelOffset < 0){ - labelPixelOffset = 0; - }else if (labelPixelOffset + labelWidth > width){ - labelPixelOffset = width - labelWidth; - } - label.css({ - left: this.mRound(labelPixelOffset) + 'px' - }); - - }, - - //function called on ruler.resize. Instead of recreating all markers, simply redraw them - refreshPosition : function(){ - var width = this.getRulerWidth(); - //store relativePosition: - var rp = this.positionAsViewerRatio; - this.move(this.mRound(this.positionAsViewerRatio*width)); - //reset relative position, which does not have to change - //but in move might have been rounded: - this.positionAsViewerRatio = rp; - }, - - - remove : function() { - var label = this.getLabel(); - label.remove(); - this.jQueryCanvas.remove(); //defined in the constructor - return this; - }, - - - createCanvasSvg: function(container, arrowBaseWidth){ - //create svg. Note that elements must be created within a namespace (createElementNS) - //and attributes must be set via .setAttributeNS(null,name,value) - //in other words, jQuery does not work (maybe in future releases) - var $J = this.$J; - var svgNS = "http://www.w3.org/2000/svg"; - var d = document; - var svg = undefined; - if(container.children().length>0){ - svg = container.children().get(0); - }else{ - svg = d.createElementNS(svgNS, "svg:svg"); - container.append($J(svg)); - } - var group = d.createElementNS(svgNS, "svg:g"); - group.setAttributeNS( null, "transform", "translate(0,0)"); - - var path = d.createElementNS(svgNS, "svg:path"); - path.setAttributeNS( null, "d", this.createCanvasPath(0,arrowBaseWidth)); - - group.appendChild(path); - svg.appendChild(group); - - return group; //return the group, not the path, as it is the group that will be translated when moving - }, - - createCanvasVml: function(container, arrowBaseWidth){ - var vml = this.$TU.vml; - var paper = vml.Raphael(container.get(0),container.width(),container.height()); - var shape = paper.path(this.createCanvasPath(0, arrowBaseWidth)); - return shape; - }, - - //w must be odd. Cause the central line must be centered. Example: - // - // xxxxx - // xxx - // x - // x - // x - // - createCanvasPath: function(x,w){ - var halfW = w >>> 1; - //in order to calculate the line height, we could simply set the wave height. However, due to potential - //resizing afterwards, the line could not stretch till the bottom (if it overflows it's fine, as the wave div container has - //overflow = hidden). As we do not want to rebuild the canvas on resize, - //we assess an height which will 99% overflow the wave height in any case. - //We use the wave height and the window height, and take 2 times - //the maximum of those heights: - var wdwH = this.$J(window).height(); - var waveH = this.getWaveHeight(); - var h = 2* (wdwH > waveH ? wdwH : waveH); - return 'M '+(x-halfW)+' 0 L '+(x)+' '+(halfW)+' L '+x+' '+h+ - ' L '+ (x+1)+' '+h+' L '+(x+1)+ ' '+(halfW)+' L '+(x+halfW+1)+' 0 z'; - }, - - //used for faster lookup - mRound: Math.round - -}); diff --git a/timeside/static/timeside/js/timeside.js b/timeside/static/timeside/js/timeside.js deleted file mode 100644 index e274783..0000000 --- a/timeside/static/timeside/js/timeside.js +++ /dev/null @@ -1,784 +0,0 @@ -/* - * Copyright (C) 2007-2011 Parisson - * Copyright (c) 2011 Riccardo Zaccarelli - * Copyright (c) 2010 Olivier Guilyardi - * - * This file is part of TimeSide. - * - * TimeSide is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * TimeSide is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with TimeSide. If not, see . - * - * Authors: Riccardo Zaccarelli - * Olivier Guilyardi - */ - -/** - * Root javascript file for TimesideUI, to be manually included in your web page (see online doc) - */ - -/** - *global variable housing all Timeside variables/mathods/classes: - */ -var Timeside = { - Class:undefined, - classes:{}, - player:undefined, - config: { - /** - *set to true to see debug messages on the console (only error or warning messages shown) - */ - debug: false, - /* - * timeside scripts to be loaded when Timeside.load is called. URL paths are relative to the timeside folder, which - * will be determined according to the src attribute of the timeside.js script path (to be included in the of the page) - */ - timesideScripts: ['rulermarker.js','markermap.js', 'player.js', 'ruler.js'], - //vml config variables. Used only if svg is NOT supported - vml : { - /* - * raphael script to be loaded when Timeside.load is called and svg is not supported. It will be prepended to the - * timesideScripts array defined above in config. URL paths are relative to the timeside folder, which - * will be determined according to the src attribute of the timeside.js script path (to be included in the of the page) - */ - raphaelScript : 'libs/raphael-min.js', - /* - * available attributes which can be converted from css-svg to Raphael attributes (see Raphael.js): - */ - raphaelAttributes : ["clip-rect", "cursor",'fill', "fill-opacity",'opacity', 'stroke', "stroke-dasharray", "stroke-linecap", "stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width", "text-anchor"] - } - }, - utils:{ - /** - * Returns an uniqid by creating the current local time in millisecond + a random number. - * Used for markers in markermap. The method is kind of public in order to be more accessible for other functions - * by calling Timeside.utils.uniqid(), in case it is needed - */ - uniqid : function() { - var d = new Date(); - return new String(d.getTime() + '' + Math.floor(Math.random() * 1000000)).substr(0, 18); - }, - /** - * vml object which will be populated by vml functions to interface timeside and raphael. See timeside.load. - * We could implement functions here for code readability, however, - * we delegate Timeside.load so that if svg is supported memory is free from unused vml methods. - * IN ANY CASE, svg support can be detected anywhere by calling, eg: - * var svg = !Timeside.utils.vml; - */ - vml: undefined, - - /** - * property that will be set to false if soundManager fails to initialize flash - */ - flashFailed : false - } -}; - - -/* Simple JavaScript Inheritance - * By John Resig http://ejohn.org/ - * MIT Licensed. - * (Inspired by base2 and Prototype) - */ - -/* - * In few words: the lightest and most-comprehensive way to implement inhertance and OOP in javascript. Usages can be found below. - * Basically, - * 1) a new Class is instantiated with Class.extend(). This function takes a dictionary - * of properties/methods which will be put IN THE PROTOTYPE of the class, so that each instance will share the same properties/methods - * and the latter don't have to be created for each instance separately. - * 2) If var A = Class.extend({...}) and var B = A.extend({..}), then methods which are found in B will override the same methods in A. - * In this case, the variable this._super inside the overridden methods will refers to the super-method and can thus be called safely. - * Consequently, if a _super property/method is implemented in the extend dictionary, it WILL NOT be accessible - * to the overriding methods of B. Basically, don't use _super as a key of the argument of extend. - * 3) AFTER the prototype has been populated, the init function, if exists, is called. The latter can be seen as a class constructor in java, - * with a substantial difference: when executing the init() method the class prototype has already been populated with all inherited methods. - * Private variable can be declared in the init function, as well as - * relative getters and setters, if needed. Downside is that the privileged getters and setters can’t be put in the prototype, - * i.e. they are created for each instance separately, and the _super keyword does not apply to them. Another issue is the overhead of closures in general (basically, write as less as possible - * in the init function, in particular if the class has to be declared several times) - * Of course, the this._super keyword of methods implemented in the init constructor does not work - * - * EXAMPLE: - * var MyClass = Class.extend({ - * init: function(optionalArray){ //constructor - * this._super(); //!!!ERROR: Class is the base class and does not have a super construcor - * var me = []; //private variable - * this.count = 6; //set the value of the public property defined below - * this.getMe = function(){ //public method - * this._super(); //!!!ERROR: methods defined in the init function don't have acces to _super - * } - * this.alert = function(){ //another public method, !!!WARNING: this will be put in the MyClass scope (NOT in the prototype) - * alert('ok'); - * } - * }, - * count:0, //public property - * alert: function(){ //public method. !!!WARNING: this method will be put in the prototype BEFORE the init is called, - * alert('no'); // so the alert defined above will be actually called - * } - * }); - * var MyClass2 = MyClass.extend({ - * init: function(){ - * this._super(); //call the super constructor - * } - * alert: function(){ //override a method - * this._super(); //call the super method, ie alerts 'no'. WARNING: However, as long as there is an alert written - * //in the init method of the superclass (see above), THAT method will be called - * } - * }); - * - */ - - -(function(parent){ - - var initializing = false, fnTest = /xyz/.test(function(){ - xyz; - }) ? /\b_super\b/ : /.*/; - - /*The xyz test above determines whether the browser can inspect the textual body of a function. - *If it can, you can perform an optimization by only wrapping an overridden method if it - *actually calls this._super() somewhere in its body. - *Since it requires an additional closure and function call overhead to support _super, - *it’s nice to skip that step if it isn’t needed. - */ - - //ADDED BY ME: - // before was: this.Class = function(){}, where this here is the DomWindow - // In order to chose where to attach the Class object, we added the argument parent (see above): - //if parent is undefined, attach Class to the DomWindow (same as before): - if(!parent){ - parent= window; - } - parent.Class = function(){}; - - //from here on, the code is untouched: - // - //We have the base Class implementation (does nothing) - //and we write here below the method extend which returns the Class with inhertance implemented: - // Create a new Class that inherits from this class - parent.Class.extend = function(prop) { - var _super = this.prototype; - - // Instantiate a base class (but only create the instance, - // don't run the init constructor) - initializing = true; - var prototype = new this(); - initializing = false; - - // Copy the properties over onto the new prototype - for (var name in prop) { - // Check if we're overwriting an existing function - prototype[name] = typeof prop[name] == "function" && - typeof _super[name] == "function" && fnTest.test(prop[name]) ? - (function(name, fn){ - return function() { - var tmp = this._super; - - // Add a new ._super() method that is the same method - // but on the super-class - this._super = _super[name]; - - // The method only need to be bound temporarily, so we - // remove it when we're done executing - var ret = fn.apply(this, arguments); - this._super = tmp; - - return ret; - }; - })(name, prop[name]) : - prop[name]; - } - - // The dummy class constructor - function Class() { - // All construction is actually done in the init method - if ( !initializing && this.init ){ - this.init.apply(this, arguments); - } - } - - // Populate our constructed prototype object - Class.prototype = prototype; - - // Enforce the constructor to be what we expect - Class.constructor = Class; - - // And make this class extendable - Class.extend = arguments.callee; - - return Class; - }; -})(Timeside); - - - -//Defining the base TimeClass class. Timeside.classes.[Player, Ruler, MarkerMap...] are typical implementations (see js files) -//Basically we store here static methods which must be accessible in several timside sub-classes -Timeside.classes.TimesideClass = Timeside.Class.extend({ - //init constructor. Define the 'bind' and 'fire' (TODO: rename as 'trigger'?) methods - //we do it in the init function so that we can set a private variable storing all - //listeners. This means we have to re-write all methods - init: function(){ - //the map for listeners. Must be declared in the init as it's private and NOT shared by all instances - //(ie, every instance has its own copy) - this.listenersMap={}; - }, - - cssPrefix : 'ts-', //actually almost uneuseful, still here for backward compatibility with old code (TODO: remove?) - $J : jQuery, //reference to jQuery for faster lookup inside methods - $TU : Timeside.utils, //reference to Timeside variable for faster lookup inside methods - debugging : false, - debug : Timeside.config.debug ? function(message) { - var C = console; - if (C && C.log) { - C.log(message); - } - } : function(message){}, - - /** - * 3 methods defining listeners, events fire and bind (aloing the lines of jQuery.bind, unbind and trigger. - * the only difference is that 'trigger' is 'fire' here). namespaces are allowed as in jQuery - */ - bind : function(eventType, callback, optionalThisArgInCallback){ - if(!callback || typeof callback !== 'function'){ - this.debug('TimesideClass.bind: cannot bind '+eventType+' to callback: the latter is null or not a function'); - return; - } - if(!eventType){ - this.debug('TimesideClass.bind: eventType is empty in bind'); - return; - } - var listenersMap = this.listenersMap; - if(optionalThisArgInCallback){ - var cb = callback; - callback = function(data){ - cb.apply(optionalThisArgInCallback,[data]); - }; - } - - if(listenersMap.hasOwnProperty(eventType)){ - listenersMap[eventType].push(callback); - }else{ - listenersMap[eventType] = [callback]; - } - - var idx = eventType.indexOf('.'); - if(idx <= 0 || idx >= eventType.length-1){ - return; - } - - eventType = eventType.substring(0,idx); - - - if(listenersMap.hasOwnProperty(eventType)){ - listenersMap[eventType].push(callback); - }else{ - listenersMap[eventType] = [callback]; - } - - }, - unbind : function(){ - var listenersMap = this.listenersMap; - var key,keyPlusDot; - if(arguments.length>0){ - key = arguments[0]; - if(listenersMap.hasOwnProperty(key)){ - var callbacks = listenersMap[key]; - var idx = key.indexOf('.'); - if(idx>0 && idx < key.length-1){ - //key is "eventtype.namespace", delete also functions stored in "eventType", if any - var baseKey = key.substring(0,idx); - var baseCallbacks = listenersMap[baseKey]; - if(baseCallbacks){ - for( var i = baseCallbacks.length; i>-1; i--){ - var bc = baseCallbacks[i]; - for( var j = callbacks.length; j>-1; j--){ - if(bc === callbacks[j]){ - baseCallbacks.splice(i,1); - } - } - } - } - }else if(idx<0){ - //key is "eventtype", delete also all functions stored in "eventType.namespace", if any - keyPlusDot = key+'.'; - for(var k in listenersMap){ - if(listenersMap.hasOwnProperty(k) && k.indexOf(keyPlusDot)==0 && k.length > keyPlusDot.length){ - delete listenersMap[k]; - } - } - } - delete listenersMap[key]; - } - }else{ - for(key in listenersMap){ - if(listenersMap.hasOwnProperty(key)){ - delete listenersMap[key]; - } - } - } - }, - fire : function(key, dataArgument){ - var listenersMap = this.listenersMap; - if(!(listenersMap.hasOwnProperty(key))){ - return; - } - if(arguments.length < 2 || !dataArgument){ - dataArgument = {}; - } - var callbacks = listenersMap[key]; - var len = callbacks && callbacks.length ? callbacks.length : 0; - for(var i=0; i0){ - ret[i] = separator+ret[i]; - } - } - return ret.join(""); - } -}); - -/** - * An Array-like implementation that suits the need of Marker mnanagement - * Ruler, MarkerMap and MarkerMapDiv implement this class - */ -Timeside.classes.TimesideArray = Timeside.classes.TimesideClass.extend({ - init: function(optionalArray){ - this._super(); - //here methods that CANNOT be overridden - var me= optionalArray ? optionalArray : []; - //note that this method written here OVERRIDES the same method written outside init in the children!!!! - this.toArray = function(returnACopy){ - if(returnACopy){ - var ret = []; - for(var i=0; i= l){ - return; - } - startInclusive = arg[0]=== undefined ? 0 : arg[0]; - endExclusive = l; - break; - default: - startInclusive = arg[0]=== undefined ? 0 : arg[0]; - endExclusive = arg[1]=== undefined ? l : arg[1]; - } - callback = arg[len-1]; - if(!(callback instanceof Function)){ - this.debug('TimesideClass.each: callback NOT a function!!!'); - return; - } - var me =this.toArray(); - for(var i = startInclusive; i=len)||(to<0 || to>=len)){ - return -1; - } - var elm = me.splice(from,1)[0]; - me.splice(to,0,elm); - - return to; - } -}); - - - -/** - *Main Timeside method to load player (see Timeside online doc) - */ - -Timeside.load =function(config){ - - var $J = jQuery; - var win = window; - var doc = document; - //function to be called onready or onerror: - var loadAll = function() { - - - //get the current script path (this file name is timeside.js, or timeside.js?..., or even timeside.js.pagespeed.blah.js) - var scripts = $J('script'); - var thisScriptPath = ''; - scripts.each(function(i,s){ - var src = $J(s).attr('src'); - if(src) { - var m = src.match(/^([^?]*\/)timeside.js/); - if (m) { - thisScriptPath = m[1]; - } - } - }); - - var ts = Timeside; - var ts_scripts = ts.config.timesideScripts; - //detect SVG support and load Raphael in case. Copied from Raphael code v 1.5.2: - var svg = (win.SVGAngle || doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1")); - if(!svg){ - //add the raphael path. Raphael will be loaded in Timeside.load (see below) - ts_scripts.splice(0,0,ts.config.vml.raphaelScript); - //populate the vml object with methods to be used in ruler and rulermarker: - - //global private variable: - //map to store each class name to the relative dictionary for raphael attr function (VML only) - var classToRaphaelAttr = {}; - //get the raphael attributes for which a conversion css -> raphael_attribute is possible: - var availableAttrs = ts.config.vml.raphaelAttributes; - //here below we store Raphael paper objects. var paper = Raphael(htmlElement) is the raphel method to build - //a new paper object. Internally, the method builds a div embedding vmls inside htmlElement, retriavable via the - //paper.node property. - //However, calling again var paper = Raphael(htmlElement) does not use the already created paper, - //but creates a new paper with a new paper.node (div). Too bad. The possibility to wrap existing paper node - //into a Raphael paper would be a nice and almost necessary feature, which however is not even - //planned to be implemented according to raphael developers (see raphael forums). - //In case of markers lines, we want to draw a new marker - //on the same raphael paper. Therefore, we store here raphael papers in a map htmlElement -> paper - var raphael_papers = {}; - ts.utils.vml = { - getVmlAttr: function(className){ - - if(classToRaphaelAttr.hasOwnProperty(className)){ - //if(className in classToRaphaelAttr){ - return classToRaphaelAttr[className]; - } - var d = document; - var dottedclassName = className.replace(/^\.*/,'.'); //add a dot if not present - var ssheets = d.styleSheets; - var len = ssheets.length-1; - - var attr = {}; - for(var i=0; i -{% load i18n %} -{% get_current_language as LANGUAGE_CODE %} -{% get_available_languages as LANGUAGES %} - - - - - - -{% block stylesheets %} -{% endblock %} - -{% block extra_stylesheets %}{% endblock %} - -{% block javascript %} - - - - -{% endblock %} - -{% block extra_javascript %}{% endblock %} - - - -{% block layout %} -
- -{% block content %} -{% endblock content %} - -
-{% endblock layout %} - -{% block analytics %} -{% endblock analytics %} - - - diff --git a/timeside/templates/timeside/index.html b/timeside/templates/timeside/index.html deleted file mode 100644 index 9e67fd7..0000000 --- a/timeside/templates/timeside/index.html +++ /dev/null @@ -1,12 +0,0 @@ -{% extends "timeside/base.html" %} -{% load i18n %} - -{% block content %} - -
    - {% for item in object_list %} -
  • {{ item.title }}
  • - {% endfor %} -
- -{% endblock content %} diff --git a/timeside/urls.py b/timeside/urls.py deleted file mode 100644 index 3f76c35..0000000 --- a/timeside/urls.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- - -from django.conf.urls import patterns, include, url -from django.contrib import admin -from rest_framework import routers -from timeside import views - -admin.autodiscover() - -api_router = routers.DefaultRouter() -api_router.register(r'selections', views.SelectionViewSet) -api_router.register(r'items', views.ItemViewSet) -api_router.register(r'experiences', views.ExperienceViewSet) -api_router.register(r'processors', views.ProcessorViewSet) -api_router.register(r'results', views.ResultViewSet) -api_router.register(r'presets', views.PresetViewSet) -api_router.register(r'tasks', views.TaskViewSet) -api_router.register(r'users', views.UserViewSet) - -urlpatterns = patterns('', - url(r'^admin/', include(admin.site.urls)), - url(r'^api/', include(api_router.urls)), - url(r'^$', views.IndexView.as_view(), name="timeside-index"), - url(r'^results/(?P.*)/json/$', views.ResultAnalyzerView.as_view(), name="timeside-result-json"), -) diff --git a/timeside/views.py b/timeside/views.py deleted file mode 100644 index cc4653d..0000000 --- a/timeside/views.py +++ /dev/null @@ -1,82 +0,0 @@ -# -*- coding: utf-8 -*- - -from django.views.generic import * -from django.http import HttpResponse, HttpResponseRedirect - -from rest_framework import viewsets - -import timeside -from timeside.models import * -from timeside.serializers import * - - -class SelectionViewSet(viewsets.ModelViewSet): - - model = Selection - serializer_class = SelectionSerializer - - -class ItemViewSet(viewsets.ModelViewSet): - - model = Item - serializer_class = ItemSerializer - - -class ExperienceViewSet(viewsets.ModelViewSet): - - model = Experience - serializer_class = ExperienceSerializer - - -class ProcessorViewSet(viewsets.ModelViewSet): - - model = Processor - serializer_class = ProcessorSerializer - - -class ResultViewSet(viewsets.ModelViewSet): - - model = Result - serializer_class = ResultSerializer - - -class PresetViewSet(viewsets.ModelViewSet): - - model = Preset - serializer_class = PresetSerializer - - -class TaskViewSet(viewsets.ModelViewSet): - - model = Task - serializer_class = TaskSerializer - - -class UserViewSet(viewsets.ModelViewSet): - - model = User - serializer_class = UserSerializer - - -class IndexView(ListView): - - model = Item - template_name='timeside/index.html' - - def get_context_data(self, **kwargs): - context = super(IndexView, self).get_context_data(**kwargs) - return context - - def dispatch(self, *args, **kwargs): - return super(IndexView, self).dispatch(*args, **kwargs) - - -class ResultAnalyzerView(View): - - model = Result - - def get(self, request, *args, **kwargs): - result = Result.objects.get(pk=kwargs['pk']) - container = AnalyzerResultContainer() - return HttpResponse(container.from_hdf5(result.hdf5.path).to_json(), mimetype='application/json') - \ No newline at end of file